Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCampbell Barton <ideasman42@gmail.com>2019-04-17 07:17:24 +0300
committerCampbell Barton <ideasman42@gmail.com>2019-04-17 07:21:24 +0300
commite12c08e8d170b7ca40f204a5b0423c23a9fbc2c1 (patch)
tree8cf3453d12edb177a218ef8009357518ec6cab6a /intern/cycles
parentb3dabc200a4b0399ec6b81f2ff2730d07b44fcaa (diff)
ClangFormat: apply to source, most of intern
Apply clang format as proposed in T53211. For details on usage and instructions for migrating branches without conflicts, see: https://wiki.blender.org/wiki/Tools/ClangFormat
Diffstat (limited to 'intern/cycles')
-rw-r--r--intern/cycles/CMakeLists.txt494
-rw-r--r--intern/cycles/app/CMakeLists.txt202
-rw-r--r--intern/cycles/app/cycles_cubin_cc.cpp478
-rw-r--r--intern/cycles/app/cycles_server.cpp158
-rw-r--r--intern/cycles/app/cycles_standalone.cpp794
-rw-r--r--intern/cycles/app/cycles_xml.cpp1012
-rw-r--r--intern/cycles/app/cycles_xml.h2
-rw-r--r--intern/cycles/blender/CCL_api.h2
-rw-r--r--intern/cycles/blender/CMakeLists.txt98
-rw-r--r--intern/cycles/blender/blender_camera.cpp1541
-rw-r--r--intern/cycles/blender/blender_curves.cpp1961
-rw-r--r--intern/cycles/blender/blender_device.cpp140
-rw-r--r--intern/cycles/blender/blender_device.h8
-rw-r--r--intern/cycles/blender/blender_logging.cpp6
-rw-r--r--intern/cycles/blender/blender_mesh.cpp2173
-rw-r--r--intern/cycles/blender/blender_object.cpp1169
-rw-r--r--intern/cycles/blender/blender_object_cull.cpp193
-rw-r--r--intern/cycles/blender/blender_object_cull.h37
-rw-r--r--intern/cycles/blender/blender_particles.cpp116
-rw-r--r--intern/cycles/blender/blender_python.cpp1594
-rw-r--r--intern/cycles/blender/blender_session.cpp2538
-rw-r--r--intern/cycles/blender/blender_session.h298
-rw-r--r--intern/cycles/blender/blender_shader.cpp2589
-rw-r--r--intern/cycles/blender/blender_sync.cpp1463
-rw-r--r--intern/cycles/blender/blender_sync.h330
-rw-r--r--intern/cycles/blender/blender_texture.cpp50
-rw-r--r--intern/cycles/blender/blender_texture.h10
-rw-r--r--intern/cycles/blender/blender_util.h1078
-rw-r--r--intern/cycles/bvh/CMakeLists.txt50
-rw-r--r--intern/cycles/bvh/bvh.cpp946
-rw-r--r--intern/cycles/bvh/bvh.h128
-rw-r--r--intern/cycles/bvh/bvh2.cpp458
-rw-r--r--intern/cycles/bvh/bvh2.h75
-rw-r--r--intern/cycles/bvh/bvh4.cpp688
-rw-r--r--intern/cycles/bvh/bvh4.h70
-rw-r--r--intern/cycles/bvh/bvh8.cpp852
-rw-r--r--intern/cycles/bvh/bvh8.h70
-rw-r--r--intern/cycles/bvh/bvh_binning.cpp446
-rw-r--r--intern/cycles/bvh/bvh_binning.h149
-rw-r--r--intern/cycles/bvh/bvh_build.cpp2101
-rw-r--r--intern/cycles/bvh/bvh_build.h193
-rw-r--r--intern/cycles/bvh/bvh_embree.cpp1646
-rw-r--r--intern/cycles/bvh/bvh_embree.h103
-rw-r--r--intern/cycles/bvh/bvh_node.cpp290
-rw-r--r--intern/cycles/bvh/bvh_node.h429
-rw-r--r--intern/cycles/bvh/bvh_params.h448
-rw-r--r--intern/cycles/bvh/bvh_sort.cpp287
-rw-r--r--intern/cycles/bvh/bvh_sort.h2
-rw-r--r--intern/cycles/bvh/bvh_split.cpp872
-rw-r--r--intern/cycles/bvh/bvh_split.h416
-rw-r--r--intern/cycles/bvh/bvh_unaligned.cpp231
-rw-r--r--intern/cycles/bvh/bvh_unaligned.h71
-rw-r--r--intern/cycles/cmake/external_libs.cmake230
-rw-r--r--intern/cycles/cmake/macros.cmake20
-rw-r--r--intern/cycles/device/CMakeLists.txt92
-rw-r--r--intern/cycles/device/device.cpp921
-rw-r--r--intern/cycles/device/device.h744
-rw-r--r--intern/cycles/device/device_cpu.cpp2094
-rw-r--r--intern/cycles/device/device_cuda.cpp5137
-rw-r--r--intern/cycles/device/device_denoising.cpp537
-rw-r--r--intern/cycles/device/device_denoising.h320
-rw-r--r--intern/cycles/device/device_intern.h27
-rw-r--r--intern/cycles/device/device_memory.cpp113
-rw-r--r--intern/cycles/device/device_memory.h678
-rw-r--r--intern/cycles/device/device_multi.cpp769
-rw-r--r--intern/cycles/device/device_network.cpp1453
-rw-r--r--intern/cycles/device/device_network.h843
-rw-r--r--intern/cycles/device/device_opencl.cpp373
-rw-r--r--intern/cycles/device/device_split_kernel.cpp517
-rw-r--r--intern/cycles/device/device_split_kernel.h185
-rw-r--r--intern/cycles/device/device_task.cpp175
-rw-r--r--intern/cycles/device/device_task.h155
-rw-r--r--intern/cycles/device/opencl/memory_manager.cpp361
-rw-r--r--intern/cycles/device/opencl/memory_manager.h97
-rw-r--r--intern/cycles/device/opencl/opencl.h1222
-rw-r--r--intern/cycles/device/opencl/opencl_split.cpp3506
-rw-r--r--intern/cycles/device/opencl/opencl_util.cpp1948
-rw-r--r--intern/cycles/doc/license/CMakeLists.txt12
-rw-r--r--intern/cycles/graph/CMakeLists.txt16
-rw-r--r--intern/cycles/graph/node.cpp817
-rw-r--r--intern/cycles/graph/node.h131
-rw-r--r--intern/cycles/graph/node_enum.h55
-rw-r--r--intern/cycles/graph/node_type.cpp265
-rw-r--r--intern/cycles/graph/node_type.h425
-rw-r--r--intern/cycles/graph/node_xml.cpp768
-rw-r--r--intern/cycles/graph/node_xml.h4
-rw-r--r--intern/cycles/kernel/CMakeLists.txt898
-rw-r--r--intern/cycles/kernel/bvh/bvh.h577
-rw-r--r--intern/cycles/kernel/bvh/bvh_embree.h173
-rw-r--r--intern/cycles/kernel/bvh/bvh_local.h358
-rw-r--r--intern/cycles/kernel/bvh/bvh_nodes.h899
-rw-r--r--intern/cycles/kernel/bvh/bvh_shadow_all.h563
-rw-r--r--intern/cycles/kernel/bvh/bvh_traversal.h632
-rw-r--r--intern/cycles/kernel/bvh/bvh_types.h46
-rw-r--r--intern/cycles/kernel/bvh/bvh_volume.h438
-rw-r--r--intern/cycles/kernel/bvh/bvh_volume_all.h557
-rw-r--r--intern/cycles/kernel/bvh/obvh_local.h641
-rw-r--r--intern/cycles/kernel/bvh/obvh_nodes.h817
-rw-r--r--intern/cycles/kernel/bvh/obvh_shadow_all.h1060
-rw-r--r--intern/cycles/kernel/bvh/obvh_traversal.h1013
-rw-r--r--intern/cycles/kernel/bvh/obvh_volume.h760
-rw-r--r--intern/cycles/kernel/bvh/obvh_volume_all.h866
-rw-r--r--intern/cycles/kernel/bvh/qbvh_local.h427
-rw-r--r--intern/cycles/kernel/bvh/qbvh_nodes.h700
-rw-r--r--intern/cycles/kernel/bvh/qbvh_shadow_all.h685
-rw-r--r--intern/cycles/kernel/bvh/qbvh_traversal.h731
-rw-r--r--intern/cycles/kernel/bvh/qbvh_volume.h538
-rw-r--r--intern/cycles/kernel/bvh/qbvh_volume_all.h650
-rw-r--r--intern/cycles/kernel/closure/alloc.h85
-rw-r--r--intern/cycles/kernel/closure/bsdf.h1015
-rw-r--r--intern/cycles/kernel/closure/bsdf_ashikhmin_shirley.h353
-rw-r--r--intern/cycles/kernel/closure/bsdf_ashikhmin_velvet.h168
-rw-r--r--intern/cycles/kernel/closure/bsdf_diffuse.h146
-rw-r--r--intern/cycles/kernel/closure/bsdf_diffuse_ramp.h101
-rw-r--r--intern/cycles/kernel/closure/bsdf_hair.h365
-rw-r--r--intern/cycles/kernel/closure/bsdf_hair_principled.h679
-rw-r--r--intern/cycles/kernel/closure/bsdf_microfacet.h1847
-rw-r--r--intern/cycles/kernel/closure/bsdf_microfacet_multi.h972
-rw-r--r--intern/cycles/kernel/closure/bsdf_microfacet_multi_impl.h398
-rw-r--r--intern/cycles/kernel/closure/bsdf_oren_nayar.h124
-rw-r--r--intern/cycles/kernel/closure/bsdf_phong_ramp.h171
-rw-r--r--intern/cycles/kernel/closure/bsdf_principled_diffuse.h130
-rw-r--r--intern/cycles/kernel/closure/bsdf_principled_sheen.h116
-rw-r--r--intern/cycles/kernel/closure/bsdf_reflection.h63
-rw-r--r--intern/cycles/kernel/closure/bsdf_refraction.h80
-rw-r--r--intern/cycles/kernel/closure/bsdf_toon.h242
-rw-r--r--intern/cycles/kernel/closure/bsdf_transparent.h116
-rw-r--r--intern/cycles/kernel/closure/bsdf_util.h183
-rw-r--r--intern/cycles/kernel/closure/bssrdf.h637
-rw-r--r--intern/cycles/kernel/closure/emissive.h42
-rw-r--r--intern/cycles/kernel/closure/volume.h209
-rw-r--r--intern/cycles/kernel/filter/filter.h6
-rw-r--r--intern/cycles/kernel/filter/filter_defines.h75
-rw-r--r--intern/cycles/kernel/filter/filter_features.h168
-rw-r--r--intern/cycles/kernel/filter/filter_features_sse.h129
-rw-r--r--intern/cycles/kernel/filter/filter_nlm_cpu.h334
-rw-r--r--intern/cycles/kernel/filter/filter_nlm_gpu.h365
-rw-r--r--intern/cycles/kernel/filter/filter_prefilter.h325
-rw-r--r--intern/cycles/kernel/filter/filter_reconstruction.h142
-rw-r--r--intern/cycles/kernel/filter/filter_transform.h177
-rw-r--r--intern/cycles/kernel/filter/filter_transform_gpu.h186
-rw-r--r--intern/cycles/kernel/filter/filter_transform_sse.h192
-rw-r--r--intern/cycles/kernel/geom/geom_attribute.h110
-rw-r--r--intern/cycles/kernel/geom/geom_curve.h441
-rw-r--r--intern/cycles/kernel/geom/geom_curve_intersect.h1770
-rw-r--r--intern/cycles/kernel/geom/geom_motion_curve.h306
-rw-r--r--intern/cycles/kernel/geom/geom_motion_triangle.h228
-rw-r--r--intern/cycles/kernel/geom/geom_motion_triangle_intersect.h418
-rw-r--r--intern/cycles/kernel/geom/geom_motion_triangle_shader.h151
-rw-r--r--intern/cycles/kernel/geom/geom_object.h503
-rw-r--r--intern/cycles/kernel/geom/geom_patch.h554
-rw-r--r--intern/cycles/kernel/geom/geom_primitive.h484
-rw-r--r--intern/cycles/kernel/geom/geom_subd_triangle.h765
-rw-r--r--intern/cycles/kernel/geom/geom_triangle.h353
-rw-r--r--intern/cycles/kernel/geom/geom_triangle_intersect.h1229
-rw-r--r--intern/cycles/kernel/geom/geom_volume.h56
-rw-r--r--intern/cycles/kernel/kernel.h11
-rw-r--r--intern/cycles/kernel/kernel_accumulate.h1093
-rw-r--r--intern/cycles/kernel/kernel_bake.h944
-rw-r--r--intern/cycles/kernel/kernel_camera.h696
-rw-r--r--intern/cycles/kernel/kernel_color.h10
-rw-r--r--intern/cycles/kernel/kernel_compat_cpu.h94
-rw-r--r--intern/cycles/kernel/kernel_compat_cuda.h87
-rw-r--r--intern/cycles/kernel/kernel_compat_opencl.h11
-rw-r--r--intern/cycles/kernel/kernel_differential.h132
-rw-r--r--intern/cycles/kernel/kernel_emission.h455
-rw-r--r--intern/cycles/kernel/kernel_film.h92
-rw-r--r--intern/cycles/kernel/kernel_globals.h165
-rw-r--r--intern/cycles/kernel/kernel_id_passes.h123
-rw-r--r--intern/cycles/kernel/kernel_jitter.h258
-rw-r--r--intern/cycles/kernel/kernel_light.h1946
-rw-r--r--intern/cycles/kernel/kernel_math.h2
-rw-r--r--intern/cycles/kernel/kernel_montecarlo.h349
-rw-r--r--intern/cycles/kernel/kernel_passes.h647
-rw-r--r--intern/cycles/kernel/kernel_path.h1210
-rw-r--r--intern/cycles/kernel/kernel_path_branched.h1032
-rw-r--r--intern/cycles/kernel/kernel_path_common.h31
-rw-r--r--intern/cycles/kernel/kernel_path_state.h367
-rw-r--r--intern/cycles/kernel/kernel_path_subsurface.h213
-rw-r--r--intern/cycles/kernel/kernel_path_surface.h603
-rw-r--r--intern/cycles/kernel/kernel_path_volume.h544
-rw-r--r--intern/cycles/kernel/kernel_profiling.h14
-rw-r--r--intern/cycles/kernel/kernel_projection.h272
-rw-r--r--intern/cycles/kernel/kernel_queues.h145
-rw-r--r--intern/cycles/kernel/kernel_random.h294
-rw-r--r--intern/cycles/kernel/kernel_shader.h1749
-rw-r--r--intern/cycles/kernel/kernel_shadow.h637
-rw-r--r--intern/cycles/kernel/kernel_subsurface.h822
-rw-r--r--intern/cycles/kernel/kernel_types.h2105
-rw-r--r--intern/cycles/kernel/kernel_volume.h2244
-rw-r--r--intern/cycles/kernel/kernel_work_stealing.h59
-rw-r--r--intern/cycles/kernel/kernels/cpu/filter.cpp2
-rw-r--r--intern/cycles/kernel/kernels/cpu/filter_avx.cpp2
-rw-r--r--intern/cycles/kernel/kernels/cpu/filter_avx2.cpp2
-rw-r--r--intern/cycles/kernel/kernels/cpu/filter_cpu.h42
-rw-r--r--intern/cycles/kernel/kernels/cpu/filter_cpu_impl.h229
-rw-r--r--intern/cycles/kernel/kernels/cpu/filter_sse2.cpp2
-rw-r--r--intern/cycles/kernel/kernels/cpu/filter_sse3.cpp2
-rw-r--r--intern/cycles/kernel/kernels/cpu/filter_sse41.cpp2
-rw-r--r--intern/cycles/kernel/kernels/cpu/kernel.cpp34
-rw-r--r--intern/cycles/kernel/kernels/cpu/kernel_avx.cpp2
-rw-r--r--intern/cycles/kernel/kernels/cpu/kernel_avx2.cpp2
-rw-r--r--intern/cycles/kernel/kernels/cpu/kernel_cpu.h53
-rw-r--r--intern/cycles/kernel/kernels/cpu/kernel_cpu_image.h965
-rw-r--r--intern/cycles/kernel/kernels/cpu/kernel_cpu_impl.h182
-rw-r--r--intern/cycles/kernel/kernels/cpu/kernel_split.cpp2
-rw-r--r--intern/cycles/kernel/kernels/cpu/kernel_split_avx.cpp2
-rw-r--r--intern/cycles/kernel/kernels/cpu/kernel_split_avx2.cpp2
-rw-r--r--intern/cycles/kernel/kernels/cpu/kernel_split_sse2.cpp2
-rw-r--r--intern/cycles/kernel/kernels/cpu/kernel_split_sse3.cpp2
-rw-r--r--intern/cycles/kernel/kernels/cpu/kernel_split_sse41.cpp2
-rw-r--r--intern/cycles/kernel/kernels/cpu/kernel_sse2.cpp2
-rw-r--r--intern/cycles/kernel/kernels/cpu/kernel_sse3.cpp2
-rw-r--r--intern/cycles/kernel/kernels/cpu/kernel_sse41.cpp2
-rw-r--r--intern/cycles/kernel/kernels/cuda/kernel_config.h14
-rw-r--r--intern/cycles/kernel/kernels/cuda/kernel_cuda_image.h237
-rw-r--r--intern/cycles/kernel/kernels/opencl/kernel_opencl_image.h425
-rw-r--r--intern/cycles/kernel/kernels/opencl/kernel_split_function.h59
-rw-r--r--intern/cycles/kernel/osl/CMakeLists.txt28
-rw-r--r--intern/cycles/kernel/osl/background.cpp37
-rw-r--r--intern/cycles/kernel/osl/bsdf_diffuse_ramp.cpp43
-rw-r--r--intern/cycles/kernel/osl/bsdf_phong_ramp.cpp45
-rw-r--r--intern/cycles/kernel/osl/emissive.cpp18
-rw-r--r--intern/cycles/kernel/osl/osl_bssrdf.cpp133
-rw-r--r--intern/cycles/kernel/osl/osl_closures.cpp1300
-rw-r--r--intern/cycles/kernel/osl/osl_closures.h86
-rw-r--r--intern/cycles/kernel/osl/osl_globals.h106
-rw-r--r--intern/cycles/kernel/osl/osl_services.cpp2064
-rw-r--r--intern/cycles/kernel/osl/osl_services.h388
-rw-r--r--intern/cycles/kernel/osl/osl_shader.cpp580
-rw-r--r--intern/cycles/kernel/osl/osl_shader.h35
-rw-r--r--intern/cycles/kernel/shaders/CMakeLists.txt212
-rw-r--r--intern/cycles/kernel/shaders/node_absorption_volume.osl10
-rw-r--r--intern/cycles/kernel/shaders/node_add_closure.osl10
-rw-r--r--intern/cycles/kernel/shaders/node_ambient_occlusion.osl36
-rw-r--r--intern/cycles/kernel/shaders/node_anisotropic_bsdf.osl70
-rw-r--r--intern/cycles/kernel/shaders/node_attribute.osl38
-rw-r--r--intern/cycles/kernel/shaders/node_background.osl10
-rw-r--r--intern/cycles/kernel/shaders/node_bevel.osl18
-rw-r--r--intern/cycles/kernel/shaders/node_blackbody.osl19
-rw-r--r--intern/cycles/kernel/shaders/node_brick_texture.osl165
-rw-r--r--intern/cycles/kernel/shaders/node_brightness.osl20
-rw-r--r--intern/cycles/kernel/shaders/node_bump.osl74
-rw-r--r--intern/cycles/kernel/shaders/node_camera.osl16
-rw-r--r--intern/cycles/kernel/shaders/node_checker_texture.osl71
-rw-r--r--intern/cycles/kernel/shaders/node_color.h197
-rw-r--r--intern/cycles/kernel/shaders/node_combine_hsv.osl9
-rw-r--r--intern/cycles/kernel/shaders/node_combine_rgb.osl9
-rw-r--r--intern/cycles/kernel/shaders/node_combine_xyz.osl9
-rw-r--r--intern/cycles/kernel/shaders/node_convert_from_color.osl26
-rw-r--r--intern/cycles/kernel/shaders/node_convert_from_float.osl26
-rw-r--r--intern/cycles/kernel/shaders/node_convert_from_int.osl28
-rw-r--r--intern/cycles/kernel/shaders/node_convert_from_normal.osl26
-rw-r--r--intern/cycles/kernel/shaders/node_convert_from_point.osl26
-rw-r--r--intern/cycles/kernel/shaders/node_convert_from_string.osl16
-rw-r--r--intern/cycles/kernel/shaders/node_convert_from_vector.osl26
-rw-r--r--intern/cycles/kernel/shaders/node_diffuse_bsdf.osl18
-rw-r--r--intern/cycles/kernel/shaders/node_displacement.osl30
-rw-r--r--intern/cycles/kernel/shaders/node_emission.osl8
-rw-r--r--intern/cycles/kernel/shaders/node_environment_texture.osl82
-rw-r--r--intern/cycles/kernel/shaders/node_fresnel.h44
-rw-r--r--intern/cycles/kernel/shaders/node_fresnel.osl14
-rw-r--r--intern/cycles/kernel/shaders/node_gamma.osl7
-rw-r--r--intern/cycles/kernel/shaders/node_geometry.osl88
-rw-r--r--intern/cycles/kernel/shaders/node_glass_bsdf.osl44
-rw-r--r--intern/cycles/kernel/shaders/node_glossy_bsdf.osl35
-rw-r--r--intern/cycles/kernel/shaders/node_gradient_texture.osl89
-rw-r--r--intern/cycles/kernel/shaders/node_hair_bsdf.osl65
-rw-r--r--intern/cycles/kernel/shaders/node_hair_info.osl22
-rw-r--r--intern/cycles/kernel/shaders/node_holdout.osl5
-rw-r--r--intern/cycles/kernel/shaders/node_hsv.osl36
-rw-r--r--intern/cycles/kernel/shaders/node_ies_light.osl29
-rw-r--r--intern/cycles/kernel/shaders/node_image_texture.osl378
-rw-r--r--intern/cycles/kernel/shaders/node_invert.osl10
-rw-r--r--intern/cycles/kernel/shaders/node_layer_weight.osl37
-rw-r--r--intern/cycles/kernel/shaders/node_light_falloff.osl40
-rw-r--r--intern/cycles/kernel/shaders/node_light_path.osl78
-rw-r--r--intern/cycles/kernel/shaders/node_magic_texture.osl162
-rw-r--r--intern/cycles/kernel/shaders/node_mapping.osl23
-rw-r--r--intern/cycles/kernel/shaders/node_math.osl162
-rw-r--r--intern/cycles/kernel/shaders/node_mix.osl421
-rw-r--r--intern/cycles/kernel/shaders/node_mix_closure.osl14
-rw-r--r--intern/cycles/kernel/shaders/node_musgrave_texture.osl302
-rw-r--r--intern/cycles/kernel/shaders/node_noise_texture.osl63
-rw-r--r--intern/cycles/kernel/shaders/node_normal.osl14
-rw-r--r--intern/cycles/kernel/shaders/node_normal_map.osl128
-rw-r--r--intern/cycles/kernel/shaders/node_object_info.osl18
-rw-r--r--intern/cycles/kernel/shaders/node_output_displacement.osl3
-rw-r--r--intern/cycles/kernel/shaders/node_output_surface.osl3
-rw-r--r--intern/cycles/kernel/shaders/node_output_volume.osl3
-rw-r--r--intern/cycles/kernel/shaders/node_particle_info.osl34
-rw-r--r--intern/cycles/kernel/shaders/node_principled_bsdf.osl245
-rw-r--r--intern/cycles/kernel/shaders/node_principled_hair_bsdf.osl128
-rw-r--r--intern/cycles/kernel/shaders/node_principled_volume.osl126
-rw-r--r--intern/cycles/kernel/shaders/node_ramp_util.h108
-rw-r--r--intern/cycles/kernel/shaders/node_refraction_bsdf.osl32
-rw-r--r--intern/cycles/kernel/shaders/node_rgb_curves.osl30
-rw-r--r--intern/cycles/kernel/shaders/node_rgb_ramp.osl18
-rw-r--r--intern/cycles/kernel/shaders/node_rgb_to_bw.osl7
-rw-r--r--intern/cycles/kernel/shaders/node_scatter_volume.osl12
-rw-r--r--intern/cycles/kernel/shaders/node_separate_hsv.osl19
-rw-r--r--intern/cycles/kernel/shaders/node_separate_rgb.osl15
-rw-r--r--intern/cycles/kernel/shaders/node_separate_xyz.osl15
-rw-r--r--intern/cycles/kernel/shaders/node_set_normal.osl9
-rw-r--r--intern/cycles/kernel/shaders/node_sky_texture.osl157
-rw-r--r--intern/cycles/kernel/shaders/node_subsurface_scattering.osl43
-rw-r--r--intern/cycles/kernel/shaders/node_tangent.osl46
-rw-r--r--intern/cycles/kernel/shaders/node_texture.h210
-rw-r--r--intern/cycles/kernel/shaders/node_texture_coordinate.osl141
-rw-r--r--intern/cycles/kernel/shaders/node_toon_bsdf.osl22
-rw-r--r--intern/cycles/kernel/shaders/node_translucent_bsdf.osl8
-rw-r--r--intern/cycles/kernel/shaders/node_transparent_bsdf.osl8
-rw-r--r--intern/cycles/kernel/shaders/node_uv_map.osl47
-rw-r--r--intern/cycles/kernel/shaders/node_value.osl20
-rw-r--r--intern/cycles/kernel/shaders/node_vector_curves.osl30
-rw-r--r--intern/cycles/kernel/shaders/node_vector_displacement.osl78
-rw-r--r--intern/cycles/kernel/shaders/node_vector_math.osl60
-rw-r--r--intern/cycles/kernel/shaders/node_vector_transform.osl30
-rw-r--r--intern/cycles/kernel/shaders/node_velvet_bsdf.osl14
-rw-r--r--intern/cycles/kernel/shaders/node_voronoi_texture.osl273
-rw-r--r--intern/cycles/kernel/shaders/node_voxel_texture.osl52
-rw-r--r--intern/cycles/kernel/shaders/node_wave_texture.osl72
-rw-r--r--intern/cycles/kernel/shaders/node_wavelength.osl7
-rw-r--r--intern/cycles/kernel/shaders/node_wireframe.osl39
-rw-r--r--intern/cycles/kernel/shaders/oslutil.h100
-rw-r--r--intern/cycles/kernel/shaders/stdosl.h1160
-rw-r--r--intern/cycles/kernel/split/kernel_branched.h350
-rw-r--r--intern/cycles/kernel/split/kernel_buffer_update.h227
-rw-r--r--intern/cycles/kernel/split/kernel_data_init.h122
-rw-r--r--intern/cycles/kernel/split/kernel_direct_lighting.h195
-rw-r--r--intern/cycles/kernel/split/kernel_do_volume.h325
-rw-r--r--intern/cycles/kernel/split/kernel_enqueue_inactive.h36
-rw-r--r--intern/cycles/kernel/split/kernel_holdout_emission_blurring_pathtermination_ao.h186
-rw-r--r--intern/cycles/kernel/split/kernel_indirect_background.h72
-rw-r--r--intern/cycles/kernel/split/kernel_indirect_subsurface.h79
-rw-r--r--intern/cycles/kernel/split/kernel_lamp_emission.h62
-rw-r--r--intern/cycles/kernel/split/kernel_next_iteration_setup.h350
-rw-r--r--intern/cycles/kernel/split/kernel_path_init.h88
-rw-r--r--intern/cycles/kernel/split/kernel_queue_enqueue.h85
-rw-r--r--intern/cycles/kernel/split/kernel_scene_intersect.h83
-rw-r--r--intern/cycles/kernel/split/kernel_shader_eval.h57
-rw-r--r--intern/cycles/kernel/split/kernel_shader_setup.h78
-rw-r--r--intern/cycles/kernel/split/kernel_shader_sort.h134
-rw-r--r--intern/cycles/kernel/split/kernel_shadow_blocked_ao.h49
-rw-r--r--intern/cycles/kernel/split/kernel_shadow_blocked_dl.h135
-rw-r--r--intern/cycles/kernel/split/kernel_split_common.h75
-rw-r--r--intern/cycles/kernel/split/kernel_split_data.h39
-rw-r--r--intern/cycles/kernel/split/kernel_split_data_types.h170
-rw-r--r--intern/cycles/kernel/split/kernel_subsurface_scatter.h475
-rw-r--r--intern/cycles/kernel/svm/svm.h624
-rw-r--r--intern/cycles/kernel/svm/svm_ao.h151
-rw-r--r--intern/cycles/kernel/svm/svm_attribute.h248
-rw-r--r--intern/cycles/kernel/svm/svm_bevel.h379
-rw-r--r--intern/cycles/kernel/svm/svm_blackbody.h11
-rw-r--r--intern/cycles/kernel/svm/svm_brick.h196
-rw-r--r--intern/cycles/kernel/svm/svm_brightness.h19
-rw-r--r--intern/cycles/kernel/svm/svm_bump.h58
-rw-r--r--intern/cycles/kernel/svm/svm_camera.h33
-rw-r--r--intern/cycles/kernel/svm/svm_checker.h42
-rw-r--r--intern/cycles/kernel/svm/svm_closure.h2147
-rw-r--r--intern/cycles/kernel/svm/svm_color_util.h366
-rw-r--r--intern/cycles/kernel/svm/svm_convert.h95
-rw-r--r--intern/cycles/kernel/svm/svm_displace.h225
-rw-r--r--intern/cycles/kernel/svm/svm_fresnel.h66
-rw-r--r--intern/cycles/kernel/svm/svm_gamma.h13
-rw-r--r--intern/cycles/kernel/svm/svm_geometry.h325
-rw-r--r--intern/cycles/kernel/svm/svm_gradient.h84
-rw-r--r--intern/cycles/kernel/svm/svm_hsv.h55
-rw-r--r--intern/cycles/kernel/svm/svm_ies.h149
-rw-r--r--intern/cycles/kernel/svm/svm_image.h324
-rw-r--r--intern/cycles/kernel/svm/svm_invert.h19
-rw-r--r--intern/cycles/kernel/svm/svm_light_path.h116
-rw-r--r--intern/cycles/kernel/svm/svm_magic.h159
-rw-r--r--intern/cycles/kernel/svm/svm_mapping.h30
-rw-r--r--intern/cycles/kernel/svm/svm_math.h48
-rw-r--r--intern/cycles/kernel/svm/svm_math_util.h269
-rw-r--r--intern/cycles/kernel/svm/svm_mix.h22
-rw-r--r--intern/cycles/kernel/svm/svm_musgrave.h319
-rw-r--r--intern/cycles/kernel/svm/svm_noise.h330
-rw-r--r--intern/cycles/kernel/svm/svm_noisetex.h55
-rw-r--r--intern/cycles/kernel/svm/svm_normal.h32
-rw-r--r--intern/cycles/kernel/svm/svm_ramp.h125
-rw-r--r--intern/cycles/kernel/svm/svm_ramp_util.h126
-rw-r--r--intern/cycles/kernel/svm/svm_sepcomb_hsv.h56
-rw-r--r--intern/cycles/kernel/svm/svm_sepcomb_vector.h30
-rw-r--r--intern/cycles/kernel/svm/svm_sky.h283
-rw-r--r--intern/cycles/kernel/svm/svm_tex_coord.h709
-rw-r--r--intern/cycles/kernel/svm/svm_texture.h56
-rw-r--r--intern/cycles/kernel/svm/svm_types.h745
-rw-r--r--intern/cycles/kernel/svm/svm_value.h17
-rw-r--r--intern/cycles/kernel/svm/svm_vector_transform.h141
-rw-r--r--intern/cycles/kernel/svm/svm_voronoi.h290
-rw-r--r--intern/cycles/kernel/svm/svm_voxel.h49
-rw-r--r--intern/cycles/kernel/svm/svm_wave.h70
-rw-r--r--intern/cycles/kernel/svm/svm_wavelength.h112
-rw-r--r--intern/cycles/kernel/svm/svm_wireframe.h150
-rw-r--r--intern/cycles/render/CMakeLists.txt132
-rw-r--r--intern/cycles/render/attribute.cpp969
-rw-r--r--intern/cycles/render/attribute.h300
-rw-r--r--intern/cycles/render/background.cpp150
-rw-r--r--intern/cycles/render/background.h38
-rw-r--r--intern/cycles/render/bake.cpp374
-rw-r--r--intern/cycles/render/bake.h91
-rw-r--r--intern/cycles/render/buffers.cpp709
-rw-r--r--intern/cycles/render/buffers.h180
-rw-r--r--intern/cycles/render/camera.cpp1297
-rw-r--r--intern/cycles/render/camera.h344
-rw-r--r--intern/cycles/render/constant_fold.cpp575
-rw-r--r--intern/cycles/render/constant_fold.h58
-rw-r--r--intern/cycles/render/coverage.cpp187
-rw-r--r--intern/cycles/render/coverage.h36
-rw-r--r--intern/cycles/render/curves.cpp222
-rw-r--r--intern/cycles/render/curves.h122
-rw-r--r--intern/cycles/render/denoising.cpp1370
-rw-r--r--intern/cycles/render/denoising.h238
-rw-r--r--intern/cycles/render/film.cpp856
-rw-r--r--intern/cycles/render/film.h92
-rw-r--r--intern/cycles/render/graph.cpp1906
-rw-r--r--intern/cycles/render/graph.h450
-rw-r--r--intern/cycles/render/image.cpp1741
-rw-r--r--intern/cycles/render/image.h259
-rw-r--r--intern/cycles/render/integrator.cpp363
-rw-r--r--intern/cycles/render/integrator.h96
-rw-r--r--intern/cycles/render/light.cpp1792
-rw-r--r--intern/cycles/render/light.h167
-rw-r--r--intern/cycles/render/merge.cpp824
-rw-r--r--intern/cycles/render/merge.h18
-rw-r--r--intern/cycles/render/mesh.cpp3754
-rw-r--r--intern/cycles/render/mesh.h642
-rw-r--r--intern/cycles/render/mesh_displace.cpp571
-rw-r--r--intern/cycles/render/mesh_subdivision.cpp1044
-rw-r--r--intern/cycles/render/mesh_volume.cpp728
-rw-r--r--intern/cycles/render/nodes.cpp8204
-rw-r--r--intern/cycles/render/nodes.h1834
-rw-r--r--intern/cycles/render/object.cpp1423
-rw-r--r--intern/cycles/render/object.h182
-rw-r--r--intern/cycles/render/osl.cpp1911
-rw-r--r--intern/cycles/render/osl.h223
-rw-r--r--intern/cycles/render/particles.cpp109
-rw-r--r--intern/cycles/render/particles.h47
-rw-r--r--intern/cycles/render/scene.cpp513
-rw-r--r--intern/cycles/render/scene.h396
-rw-r--r--intern/cycles/render/session.cpp1901
-rw-r--r--intern/cycles/render/session.h314
-rw-r--r--intern/cycles/render/shader.cpp1067
-rw-r--r--intern/cycles/render/shader.h248
-rw-r--r--intern/cycles/render/sobol.h2
-rw-r--r--intern/cycles/render/stats.cpp397
-rw-r--r--intern/cycles/render/stats.h134
-rw-r--r--intern/cycles/render/svm.cpp1398
-rw-r--r--intern/cycles/render/svm.h350
-rw-r--r--intern/cycles/render/tables.cpp98
-rw-r--r--intern/cycles/render/tables.h28
-rw-r--r--intern/cycles/render/tile.cpp854
-rw-r--r--intern/cycles/render/tile.h239
-rw-r--r--intern/cycles/subd/CMakeLists.txt18
-rw-r--r--intern/cycles/subd/subd_dice.cpp454
-rw-r--r--intern/cycles/subd/subd_dice.h157
-rw-r--r--intern/cycles/subd/subd_patch.cpp106
-rw-r--r--intern/cycles/subd/subd_patch.h41
-rw-r--r--intern/cycles/subd/subd_patch_table.cpp424
-rw-r--r--intern/cycles/subd/subd_patch_table.h32
-rw-r--r--intern/cycles/subd/subd_split.cpp351
-rw-r--r--intern/cycles/subd/subd_split.h26
-rw-r--r--intern/cycles/test/CMakeLists.txt110
-rw-r--r--intern/cycles/test/render_graph_finalize_test.cpp1883
-rw-r--r--intern/cycles/test/util_aligned_malloc_test.cpp14
-rw-r--r--intern/cycles/test/util_path_test.cpp250
-rw-r--r--intern/cycles/test/util_string_test.cpp191
-rw-r--r--intern/cycles/test/util_task_test.cpp49
-rw-r--r--intern/cycles/test/util_time_test.cpp61
-rw-r--r--intern/cycles/util/CMakeLists.txt246
-rw-r--r--intern/cycles/util/util_algorithm.h6
-rw-r--r--intern/cycles/util/util_aligned_malloc.cpp46
-rw-r--r--intern/cycles/util/util_aligned_malloc.h2
-rw-r--r--intern/cycles/util/util_args.h2
-rw-r--r--intern/cycles/util/util_array.h492
-rw-r--r--intern/cycles/util/util_atomic.h125
-rw-r--r--intern/cycles/util/util_avxb.h246
-rw-r--r--intern/cycles/util/util_avxf.h389
-rw-r--r--intern/cycles/util/util_boundbox.h457
-rw-r--r--intern/cycles/util/util_color.h286
-rw-r--r--intern/cycles/util/util_debug.cpp228
-rw-r--r--intern/cycles/util/util_debug.h285
-rw-r--r--intern/cycles/util/util_defines.h189
-rw-r--r--intern/cycles/util/util_foreach.h4
-rw-r--r--intern/cycles/util/util_function.h2
-rw-r--r--intern/cycles/util/util_guarded_allocator.cpp9
-rw-r--r--intern/cycles/util/util_guarded_allocator.h238
-rw-r--r--intern/cycles/util/util_half.h177
-rw-r--r--intern/cycles/util/util_hash.h55
-rw-r--r--intern/cycles/util/util_ies.cpp668
-rw-r--r--intern/cycles/util/util_ies.h62
-rw-r--r--intern/cycles/util/util_image.h80
-rw-r--r--intern/cycles/util/util_image_impl.h198
-rw-r--r--intern/cycles/util/util_list.h2
-rw-r--r--intern/cycles/util/util_logging.cpp60
-rw-r--r--intern/cycles/util/util_logging.h34
-rw-r--r--intern/cycles/util/util_map.h2
-rw-r--r--intern/cycles/util/util_math.h490
-rw-r--r--intern/cycles/util/util_math_cdf.cpp73
-rw-r--r--intern/cycles/util/util_math_cdf.h55
-rw-r--r--intern/cycles/util/util_math_fast.h860
-rw-r--r--intern/cycles/util/util_math_float2.h202
-rw-r--r--intern/cycles/util/util_math_float3.h395
-rw-r--r--intern/cycles/util/util_math_float4.h515
-rw-r--r--intern/cycles/util/util_math_int2.h18
-rw-r--r--intern/cycles/util/util_math_int3.h82
-rw-r--r--intern/cycles/util/util_math_int4.h157
-rw-r--r--intern/cycles/util/util_math_intersect.h359
-rw-r--r--intern/cycles/util/util_math_matrix.h527
-rw-r--r--intern/cycles/util/util_md5.cpp509
-rw-r--r--intern/cycles/util/util_md5.h36
-rw-r--r--intern/cycles/util/util_murmurhash.cpp134
-rw-r--r--intern/cycles/util/util_murmurhash.h3
-rw-r--r--intern/cycles/util/util_opengl.h2
-rw-r--r--intern/cycles/util/util_optimization.h50
-rw-r--r--intern/cycles/util/util_param.h2
-rw-r--r--intern/cycles/util/util_path.cpp1432
-rw-r--r--intern/cycles/util/util_path.h50
-rw-r--r--intern/cycles/util/util_profiling.cpp216
-rw-r--r--intern/cycles/util/util_profiling.h220
-rw-r--r--intern/cycles/util/util_progress.h706
-rw-r--r--intern/cycles/util/util_projection.h216
-rw-r--r--intern/cycles/util/util_queue.h2
-rw-r--r--intern/cycles/util/util_rect.h24
-rw-r--r--intern/cycles/util/util_set.h2
-rw-r--r--intern/cycles/util/util_simd.cpp42
-rw-r--r--intern/cycles/util/util_simd.h613
-rw-r--r--intern/cycles/util/util_sky_model.cpp402
-rw-r--r--intern/cycles/util/util_sky_model.h71
-rw-r--r--intern/cycles/util/util_sky_model_data.h7470
-rw-r--r--intern/cycles/util/util_sseb.h317
-rw-r--r--intern/cycles/util/util_ssef.h1128
-rw-r--r--intern/cycles/util/util_ssei.h664
-rw-r--r--intern/cycles/util/util_stack_allocator.h262
-rw-r--r--intern/cycles/util/util_static_assert.h16
-rw-r--r--intern/cycles/util/util_stats.h44
-rw-r--r--intern/cycles/util/util_string.cpp348
-rw-r--r--intern/cycles/util/util_string.h34
-rw-r--r--intern/cycles/util/util_system.cpp391
-rw-r--r--intern/cycles/util/util_system.h4
-rw-r--r--intern/cycles/util/util_task.cpp711
-rw-r--r--intern/cycles/util/util_task.h216
-rw-r--r--intern/cycles/util/util_texture.h62
-rw-r--r--intern/cycles/util/util_thread.cpp57
-rw-r--r--intern/cycles/util/util_thread.h156
-rw-r--r--intern/cycles/util/util_time.cpp146
-rw-r--r--intern/cycles/util/util_time.h54
-rw-r--r--intern/cycles/util/util_transform.cpp370
-rw-r--r--intern/cycles/util/util_transform.h578
-rw-r--r--intern/cycles/util/util_types.h22
-rw-r--r--intern/cycles/util/util_types_float2.h12
-rw-r--r--intern/cycles/util/util_types_float2_impl.h26
-rw-r--r--intern/cycles/util/util_types_float3.h51
-rw-r--r--intern/cycles/util/util_types_float3_impl.h70
-rw-r--r--intern/cycles/util/util_types_float4.h53
-rw-r--r--intern/cycles/util/util_types_float4_impl.h83
-rw-r--r--intern/cycles/util/util_types_float8.h45
-rw-r--r--intern/cycles/util/util_types_float8_impl.h70
-rw-r--r--intern/cycles/util/util_types_int2.h10
-rw-r--r--intern/cycles/util/util_types_int2_impl.h22
-rw-r--r--intern/cycles/util/util_types_int3.h51
-rw-r--r--intern/cycles/util/util_types_int3_impl.h70
-rw-r--r--intern/cycles/util/util_types_int4.h55
-rw-r--r--intern/cycles/util/util_types_int4_impl.h98
-rw-r--r--intern/cycles/util/util_types_uchar2.h10
-rw-r--r--intern/cycles/util/util_types_uchar2_impl.h22
-rw-r--r--intern/cycles/util/util_types_uchar3.h10
-rw-r--r--intern/cycles/util/util_types_uchar3_impl.h22
-rw-r--r--intern/cycles/util/util_types_uchar4.h10
-rw-r--r--intern/cycles/util/util_types_uchar4_impl.h22
-rw-r--r--intern/cycles/util/util_types_uint2.h10
-rw-r--r--intern/cycles/util/util_types_uint2_impl.h18
-rw-r--r--intern/cycles/util/util_types_uint3.h10
-rw-r--r--intern/cycles/util/util_types_uint3_impl.h18
-rw-r--r--intern/cycles/util/util_types_uint4.h10
-rw-r--r--intern/cycles/util/util_types_uint4_impl.h18
-rw-r--r--intern/cycles/util/util_types_ushort4.h4
-rw-r--r--intern/cycles/util/util_types_vector3.h18
-rw-r--r--intern/cycles/util/util_types_vector3_impl.h14
-rw-r--r--intern/cycles/util/util_unique_ptr.h2
-rw-r--r--intern/cycles/util/util_vector.h44
-rw-r--r--intern/cycles/util/util_version.h16
-rw-r--r--intern/cycles/util/util_view.cpp328
-rw-r--r--intern/cycles/util/util_view.h15
-rw-r--r--intern/cycles/util/util_windows.h24
-rw-r--r--intern/cycles/util/util_xml.h2
588 files changed, 107316 insertions, 104279 deletions
diff --git a/intern/cycles/CMakeLists.txt b/intern/cycles/CMakeLists.txt
index d4a613a78c7..87f88f7ed34 100644
--- a/intern/cycles/CMakeLists.txt
+++ b/intern/cycles/CMakeLists.txt
@@ -1,16 +1,16 @@
# Standalone or with Blender
if(NOT WITH_BLENDER AND WITH_CYCLES_STANDALONE)
- set(CYCLES_INSTALL_PATH "")
+ set(CYCLES_INSTALL_PATH "")
else()
- set(WITH_CYCLES_BLENDER ON)
- # WINDOWS_PYTHON_DEBUG needs to write into the user addons folder since it will
- # be started with --env-system-scripts pointing to the release folder, which will
- # lack the cycles addon, and we don't want to write into it.
- if(NOT WINDOWS_PYTHON_DEBUG)
- set(CYCLES_INSTALL_PATH "scripts/addons/cycles")
- else()
- set(CYCLES_INSTALL_PATH "$ENV{appdata}/blender foundation/blender/${BLENDER_VERSION}/scripts/addons/cycles")
- endif()
+ set(WITH_CYCLES_BLENDER ON)
+ # WINDOWS_PYTHON_DEBUG needs to write into the user addons folder since it will
+ # be started with --env-system-scripts pointing to the release folder, which will
+ # lack the cycles addon, and we don't want to write into it.
+ if(NOT WINDOWS_PYTHON_DEBUG)
+ set(CYCLES_INSTALL_PATH "scripts/addons/cycles")
+ else()
+ set(CYCLES_INSTALL_PATH "$ENV{appdata}/blender foundation/blender/${BLENDER_VERSION}/scripts/addons/cycles")
+ endif()
endif()
# External Libraries
@@ -23,329 +23,329 @@ include(cmake/macros.cmake)
# note: CXX_HAS_SSE is needed in case passing SSE flags fails altogether (gcc-arm)
if(WITH_CYCLES_NATIVE_ONLY)
- set(CXX_HAS_SSE FALSE)
- set(CXX_HAS_AVX FALSE)
- set(CXX_HAS_AVX2 FALSE)
- add_definitions(
- -DWITH_KERNEL_NATIVE
- )
-
- if(NOT MSVC)
- set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=native")
- set(CYCLES_KERNEL_FLAGS "-march=native")
- endif()
+ set(CXX_HAS_SSE FALSE)
+ set(CXX_HAS_AVX FALSE)
+ set(CXX_HAS_AVX2 FALSE)
+ add_definitions(
+ -DWITH_KERNEL_NATIVE
+ )
+
+ if(NOT MSVC)
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=native")
+ set(CYCLES_KERNEL_FLAGS "-march=native")
+ endif()
elseif(NOT WITH_CPU_SSE)
- set(CXX_HAS_SSE FALSE)
- set(CXX_HAS_AVX FALSE)
- set(CXX_HAS_AVX2 FALSE)
+ set(CXX_HAS_SSE FALSE)
+ set(CXX_HAS_AVX FALSE)
+ set(CXX_HAS_AVX2 FALSE)
elseif(WIN32 AND MSVC AND NOT CMAKE_CXX_COMPILER_ID MATCHES "Clang")
- set(CXX_HAS_SSE TRUE)
- set(CXX_HAS_AVX TRUE)
- set(CXX_HAS_AVX2 TRUE)
-
- # /arch:AVX for VC2012 and above
- if(NOT MSVC_VERSION LESS 1700)
- set(CYCLES_AVX_ARCH_FLAGS "/arch:AVX")
- set(CYCLES_AVX2_ARCH_FLAGS "/arch:AVX /arch:AVX2")
- elseif(NOT CMAKE_CL_64)
- set(CYCLES_AVX_ARCH_FLAGS "/arch:SSE2")
- set(CYCLES_AVX2_ARCH_FLAGS "/arch:SSE2")
- endif()
-
- # Unlike GCC/clang we still use fast math, because there is no fine
- # grained control and the speedup we get here is too big to ignore.
- set(CYCLES_KERNEL_FLAGS "/fp:fast -D_CRT_SECURE_NO_WARNINGS /GS-")
-
- # there is no /arch:SSE3, but intrinsics are available anyway
- if(CMAKE_CL_64)
- set(CYCLES_SSE2_KERNEL_FLAGS "${CYCLES_KERNEL_FLAGS}")
- set(CYCLES_SSE3_KERNEL_FLAGS "${CYCLES_KERNEL_FLAGS}")
- set(CYCLES_SSE41_KERNEL_FLAGS "${CYCLES_KERNEL_FLAGS}")
- set(CYCLES_AVX_KERNEL_FLAGS "${CYCLES_AVX_ARCH_FLAGS} ${CYCLES_KERNEL_FLAGS}")
- set(CYCLES_AVX2_KERNEL_FLAGS "${CYCLES_AVX2_ARCH_FLAGS} ${CYCLES_KERNEL_FLAGS}")
- else()
- set(CYCLES_SSE2_KERNEL_FLAGS "/arch:SSE2 ${CYCLES_KERNEL_FLAGS}")
- set(CYCLES_SSE3_KERNEL_FLAGS "/arch:SSE2 ${CYCLES_KERNEL_FLAGS}")
- set(CYCLES_SSE41_KERNEL_FLAGS "/arch:SSE2 ${CYCLES_KERNEL_FLAGS}")
- set(CYCLES_AVX_KERNEL_FLAGS "${CYCLES_AVX_ARCH_FLAGS} ${CYCLES_KERNEL_FLAGS}")
- set(CYCLES_AVX2_KERNEL_FLAGS "${CYCLES_AVX2_ARCH_FLAGS} ${CYCLES_KERNEL_FLAGS}")
- endif()
-
- set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CYCLES_KERNEL_FLAGS}")
- set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /Ox")
- set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} /Ox")
- set(CMAKE_CXX_FLAGS_MINSIZEREL "${CMAKE_CXX_FLAGS_MINSIZEREL} /Ox")
+ set(CXX_HAS_SSE TRUE)
+ set(CXX_HAS_AVX TRUE)
+ set(CXX_HAS_AVX2 TRUE)
+
+ # /arch:AVX for VC2012 and above
+ if(NOT MSVC_VERSION LESS 1700)
+ set(CYCLES_AVX_ARCH_FLAGS "/arch:AVX")
+ set(CYCLES_AVX2_ARCH_FLAGS "/arch:AVX /arch:AVX2")
+ elseif(NOT CMAKE_CL_64)
+ set(CYCLES_AVX_ARCH_FLAGS "/arch:SSE2")
+ set(CYCLES_AVX2_ARCH_FLAGS "/arch:SSE2")
+ endif()
+
+ # Unlike GCC/clang we still use fast math, because there is no fine
+ # grained control and the speedup we get here is too big to ignore.
+ set(CYCLES_KERNEL_FLAGS "/fp:fast -D_CRT_SECURE_NO_WARNINGS /GS-")
+
+ # there is no /arch:SSE3, but intrinsics are available anyway
+ if(CMAKE_CL_64)
+ set(CYCLES_SSE2_KERNEL_FLAGS "${CYCLES_KERNEL_FLAGS}")
+ set(CYCLES_SSE3_KERNEL_FLAGS "${CYCLES_KERNEL_FLAGS}")
+ set(CYCLES_SSE41_KERNEL_FLAGS "${CYCLES_KERNEL_FLAGS}")
+ set(CYCLES_AVX_KERNEL_FLAGS "${CYCLES_AVX_ARCH_FLAGS} ${CYCLES_KERNEL_FLAGS}")
+ set(CYCLES_AVX2_KERNEL_FLAGS "${CYCLES_AVX2_ARCH_FLAGS} ${CYCLES_KERNEL_FLAGS}")
+ else()
+ set(CYCLES_SSE2_KERNEL_FLAGS "/arch:SSE2 ${CYCLES_KERNEL_FLAGS}")
+ set(CYCLES_SSE3_KERNEL_FLAGS "/arch:SSE2 ${CYCLES_KERNEL_FLAGS}")
+ set(CYCLES_SSE41_KERNEL_FLAGS "/arch:SSE2 ${CYCLES_KERNEL_FLAGS}")
+ set(CYCLES_AVX_KERNEL_FLAGS "${CYCLES_AVX_ARCH_FLAGS} ${CYCLES_KERNEL_FLAGS}")
+ set(CYCLES_AVX2_KERNEL_FLAGS "${CYCLES_AVX2_ARCH_FLAGS} ${CYCLES_KERNEL_FLAGS}")
+ endif()
+
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CYCLES_KERNEL_FLAGS}")
+ set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /Ox")
+ set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} /Ox")
+ set(CMAKE_CXX_FLAGS_MINSIZEREL "${CMAKE_CXX_FLAGS_MINSIZEREL} /Ox")
elseif(CMAKE_COMPILER_IS_GNUCC OR (CMAKE_CXX_COMPILER_ID MATCHES "Clang"))
- check_cxx_compiler_flag(-msse CXX_HAS_SSE)
- check_cxx_compiler_flag(-mavx CXX_HAS_AVX)
- check_cxx_compiler_flag(-mavx2 CXX_HAS_AVX2)
-
- # Assume no signal trapping for better code generation.
- set(CYCLES_KERNEL_FLAGS "-fno-trapping-math")
- # Avoid overhead of setting errno for NaNs.
- set(CYCLES_KERNEL_FLAGS "${CYCLES_KERNEL_FLAGS} -fno-math-errno")
- # Let compiler optimize 0.0 - x without worrying about signed zeros.
- set(CYCLES_KERNEL_FLAGS "${CYCLES_KERNEL_FLAGS} -fno-signed-zeros")
-
- if(CMAKE_COMPILER_IS_GNUCC)
- # Assume no signal trapping for better code generation.
- set(CYCLES_KERNEL_FLAGS "${CYCLES_KERNEL_FLAGS} -fno-signaling-nans")
- # Assume a fixed rounding mode for better constant folding.
- set(CYCLES_KERNEL_FLAGS "${CYCLES_KERNEL_FLAGS} -fno-rounding-math")
- endif()
-
- if(CXX_HAS_SSE)
- if(CMAKE_COMPILER_IS_GNUCC)
- set(CYCLES_KERNEL_FLAGS "${CYCLES_KERNEL_FLAGS} -mfpmath=sse")
- endif()
-
- set(CYCLES_SSE2_KERNEL_FLAGS "${CYCLES_KERNEL_FLAGS} -msse -msse2")
- set(CYCLES_SSE3_KERNEL_FLAGS "${CYCLES_SSE2_KERNEL_FLAGS} -msse3 -mssse3")
- set(CYCLES_SSE41_KERNEL_FLAGS "${CYCLES_SSE3_KERNEL_FLAGS} -msse4.1")
- if(CXX_HAS_AVX)
- set(CYCLES_AVX_KERNEL_FLAGS "${CYCLES_SSE41_KERNEL_FLAGS} -mavx")
- endif()
- if(CXX_HAS_AVX2)
- set(CYCLES_AVX2_KERNEL_FLAGS "${CYCLES_SSE41_KERNEL_FLAGS} -mavx -mavx2 -mfma -mlzcnt -mbmi -mbmi2 -mf16c")
- endif()
- endif()
-
- set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CYCLES_KERNEL_FLAGS}")
+ check_cxx_compiler_flag(-msse CXX_HAS_SSE)
+ check_cxx_compiler_flag(-mavx CXX_HAS_AVX)
+ check_cxx_compiler_flag(-mavx2 CXX_HAS_AVX2)
+
+ # Assume no signal trapping for better code generation.
+ set(CYCLES_KERNEL_FLAGS "-fno-trapping-math")
+ # Avoid overhead of setting errno for NaNs.
+ set(CYCLES_KERNEL_FLAGS "${CYCLES_KERNEL_FLAGS} -fno-math-errno")
+ # Let compiler optimize 0.0 - x without worrying about signed zeros.
+ set(CYCLES_KERNEL_FLAGS "${CYCLES_KERNEL_FLAGS} -fno-signed-zeros")
+
+ if(CMAKE_COMPILER_IS_GNUCC)
+ # Assume no signal trapping for better code generation.
+ set(CYCLES_KERNEL_FLAGS "${CYCLES_KERNEL_FLAGS} -fno-signaling-nans")
+ # Assume a fixed rounding mode for better constant folding.
+ set(CYCLES_KERNEL_FLAGS "${CYCLES_KERNEL_FLAGS} -fno-rounding-math")
+ endif()
+
+ if(CXX_HAS_SSE)
+ if(CMAKE_COMPILER_IS_GNUCC)
+ set(CYCLES_KERNEL_FLAGS "${CYCLES_KERNEL_FLAGS} -mfpmath=sse")
+ endif()
+
+ set(CYCLES_SSE2_KERNEL_FLAGS "${CYCLES_KERNEL_FLAGS} -msse -msse2")
+ set(CYCLES_SSE3_KERNEL_FLAGS "${CYCLES_SSE2_KERNEL_FLAGS} -msse3 -mssse3")
+ set(CYCLES_SSE41_KERNEL_FLAGS "${CYCLES_SSE3_KERNEL_FLAGS} -msse4.1")
+ if(CXX_HAS_AVX)
+ set(CYCLES_AVX_KERNEL_FLAGS "${CYCLES_SSE41_KERNEL_FLAGS} -mavx")
+ endif()
+ if(CXX_HAS_AVX2)
+ set(CYCLES_AVX2_KERNEL_FLAGS "${CYCLES_SSE41_KERNEL_FLAGS} -mavx -mavx2 -mfma -mlzcnt -mbmi -mbmi2 -mf16c")
+ endif()
+ endif()
+
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CYCLES_KERNEL_FLAGS}")
elseif(WIN32 AND CMAKE_CXX_COMPILER_ID MATCHES "Intel")
- check_cxx_compiler_flag(/QxSSE2 CXX_HAS_SSE)
- check_cxx_compiler_flag(/arch:AVX CXX_HAS_AVX)
- check_cxx_compiler_flag(/QxCORE-AVX2 CXX_HAS_AVX2)
-
- if(CXX_HAS_SSE)
- set(CYCLES_SSE2_KERNEL_FLAGS "/QxSSE2")
- set(CYCLES_SSE3_KERNEL_FLAGS "/QxSSSE3")
- set(CYCLES_SSE41_KERNEL_FLAGS "/QxSSE4.1")
-
- if(CXX_HAS_AVX)
- set(CYCLES_AVX_KERNEL_FLAGS "/arch:AVX")
- endif()
-
- if(CXX_HAS_AVX2)
- set(CYCLES_AVX2_KERNEL_FLAGS "/QxCORE-AVX2")
- endif()
- endif()
+ check_cxx_compiler_flag(/QxSSE2 CXX_HAS_SSE)
+ check_cxx_compiler_flag(/arch:AVX CXX_HAS_AVX)
+ check_cxx_compiler_flag(/QxCORE-AVX2 CXX_HAS_AVX2)
+
+ if(CXX_HAS_SSE)
+ set(CYCLES_SSE2_KERNEL_FLAGS "/QxSSE2")
+ set(CYCLES_SSE3_KERNEL_FLAGS "/QxSSSE3")
+ set(CYCLES_SSE41_KERNEL_FLAGS "/QxSSE4.1")
+
+ if(CXX_HAS_AVX)
+ set(CYCLES_AVX_KERNEL_FLAGS "/arch:AVX")
+ endif()
+
+ if(CXX_HAS_AVX2)
+ set(CYCLES_AVX2_KERNEL_FLAGS "/QxCORE-AVX2")
+ endif()
+ endif()
elseif(CMAKE_CXX_COMPILER_ID MATCHES "Intel")
- if(APPLE)
- # ICC does not support SSE2 flag on MacOSX
- check_cxx_compiler_flag(-xssse3 CXX_HAS_SSE)
- else()
- check_cxx_compiler_flag(-xsse2 CXX_HAS_SSE)
- endif()
-
- check_cxx_compiler_flag(-xavx CXX_HAS_AVX)
- check_cxx_compiler_flag(-xcore-avx2 CXX_HAS_AVX2)
-
- if(CXX_HAS_SSE)
- if(APPLE)
- # ICC does not support SSE2 flag on MacOSX
- set(CYCLES_SSE2_KERNEL_FLAGS "-xssse3")
- else()
- set(CYCLES_SSE2_KERNEL_FLAGS "-xsse2")
- endif()
-
- set(CYCLES_SSE3_KERNEL_FLAGS "-xssse3")
- set(CYCLES_SSE41_KERNEL_FLAGS "-xsse4.1")
-
- if(CXX_HAS_AVX)
- set(CYCLES_AVX_KERNEL_FLAGS "-xavx")
- endif()
-
- if(CXX_HAS_AVX2)
- set(CYCLES_AVX2_KERNEL_FLAGS "-xcore-avx2")
- endif()
- endif()
+ if(APPLE)
+ # ICC does not support SSE2 flag on MacOSX
+ check_cxx_compiler_flag(-xssse3 CXX_HAS_SSE)
+ else()
+ check_cxx_compiler_flag(-xsse2 CXX_HAS_SSE)
+ endif()
+
+ check_cxx_compiler_flag(-xavx CXX_HAS_AVX)
+ check_cxx_compiler_flag(-xcore-avx2 CXX_HAS_AVX2)
+
+ if(CXX_HAS_SSE)
+ if(APPLE)
+ # ICC does not support SSE2 flag on MacOSX
+ set(CYCLES_SSE2_KERNEL_FLAGS "-xssse3")
+ else()
+ set(CYCLES_SSE2_KERNEL_FLAGS "-xsse2")
+ endif()
+
+ set(CYCLES_SSE3_KERNEL_FLAGS "-xssse3")
+ set(CYCLES_SSE41_KERNEL_FLAGS "-xsse4.1")
+
+ if(CXX_HAS_AVX)
+ set(CYCLES_AVX_KERNEL_FLAGS "-xavx")
+ endif()
+
+ if(CXX_HAS_AVX2)
+ set(CYCLES_AVX2_KERNEL_FLAGS "-xcore-avx2")
+ endif()
+ endif()
endif()
if(CXX_HAS_SSE)
- add_definitions(
- -DWITH_KERNEL_SSE2
- -DWITH_KERNEL_SSE3
- -DWITH_KERNEL_SSE41
- )
+ add_definitions(
+ -DWITH_KERNEL_SSE2
+ -DWITH_KERNEL_SSE3
+ -DWITH_KERNEL_SSE41
+ )
endif()
if(CXX_HAS_AVX)
- add_definitions(-DWITH_KERNEL_AVX)
+ add_definitions(-DWITH_KERNEL_AVX)
endif()
if(CXX_HAS_AVX2)
- add_definitions(-DWITH_KERNEL_AVX2)
+ add_definitions(-DWITH_KERNEL_AVX2)
endif()
if(WITH_CYCLES_OSL)
- if(WIN32 AND MSVC)
- set(RTTI_DISABLE_FLAGS "/GR- -DBOOST_NO_RTTI -DBOOST_NO_TYPEID")
- elseif(CMAKE_COMPILER_IS_GNUCC OR (CMAKE_C_COMPILER_ID MATCHES "Clang"))
- set(RTTI_DISABLE_FLAGS "-fno-rtti -DBOOST_NO_RTTI -DBOOST_NO_TYPEID")
- endif()
+ if(WIN32 AND MSVC)
+ set(RTTI_DISABLE_FLAGS "/GR- -DBOOST_NO_RTTI -DBOOST_NO_TYPEID")
+ elseif(CMAKE_COMPILER_IS_GNUCC OR (CMAKE_C_COMPILER_ID MATCHES "Clang"))
+ set(RTTI_DISABLE_FLAGS "-fno-rtti -DBOOST_NO_RTTI -DBOOST_NO_TYPEID")
+ endif()
endif()
# Definitions and Includes
add_definitions(
- ${BOOST_DEFINITIONS}
- ${OPENIMAGEIO_DEFINITIONS}
+ ${BOOST_DEFINITIONS}
+ ${OPENIMAGEIO_DEFINITIONS}
)
add_definitions(
- -DCCL_NAMESPACE_BEGIN=namespace\ ccl\ {
- -DCCL_NAMESPACE_END=}
+ -DCCL_NAMESPACE_BEGIN=namespace\ ccl\ {
+ -DCCL_NAMESPACE_END=}
)
if(WITH_CYCLES_STANDALONE_GUI)
- add_definitions(-DWITH_CYCLES_STANDALONE_GUI)
+ add_definitions(-DWITH_CYCLES_STANDALONE_GUI)
endif()
if(WITH_CYCLES_PTEX)
- add_definitions(-DWITH_PTEX)
+ add_definitions(-DWITH_PTEX)
endif()
if(WITH_CYCLES_OSL)
- add_definitions(-DWITH_OSL)
- #osl 1.9.x
- add_definitions(-DOSL_STATIC_BUILD)
- #pre 1.9
- add_definitions(-DOSL_STATIC_LIBRARY)
- include_directories(
- SYSTEM
- ${OSL_INCLUDE_DIR}
- )
+ add_definitions(-DWITH_OSL)
+ #osl 1.9.x
+ add_definitions(-DOSL_STATIC_BUILD)
+ #pre 1.9
+ add_definitions(-DOSL_STATIC_LIBRARY)
+ include_directories(
+ SYSTEM
+ ${OSL_INCLUDE_DIR}
+ )
endif()
if(WITH_CYCLES_EMBREE)
- add_definitions(-DWITH_EMBREE)
- add_definitions(-DEMBREE_STATIC_LIB)
- include_directories(
- SYSTEM
- ${EMBREE_INCLUDE_DIRS}
- )
+ add_definitions(-DWITH_EMBREE)
+ add_definitions(-DEMBREE_STATIC_LIB)
+ include_directories(
+ SYSTEM
+ ${EMBREE_INCLUDE_DIRS}
+ )
endif()
if(WITH_OPENSUBDIV)
- add_definitions(-DWITH_OPENSUBDIV)
- include_directories(
- SYSTEM
- ${OPENSUBDIV_INCLUDE_DIR}
- )
+ add_definitions(-DWITH_OPENSUBDIV)
+ include_directories(
+ SYSTEM
+ ${OPENSUBDIV_INCLUDE_DIR}
+ )
endif()
if(WITH_CYCLES_STANDALONE)
- set(WITH_CYCLES_DEVICE_OPENCL TRUE)
- set(WITH_CYCLES_DEVICE_CUDA TRUE)
- # Experimental and unfinished.
- set(WITH_CYCLES_NETWORK FALSE)
+ set(WITH_CYCLES_DEVICE_OPENCL TRUE)
+ set(WITH_CYCLES_DEVICE_CUDA TRUE)
+ # Experimental and unfinished.
+ set(WITH_CYCLES_NETWORK FALSE)
endif()
# TODO(sergey): Consider removing it, only causes confusion in interface.
set(WITH_CYCLES_DEVICE_MULTI TRUE)
# Logging capabilities using GLog library.
if(WITH_CYCLES_LOGGING)
- add_definitions(-DWITH_CYCLES_LOGGING)
- add_definitions(${GLOG_DEFINES})
- add_definitions(-DCYCLES_GFLAGS_NAMESPACE=${GFLAGS_NAMESPACE})
- include_directories(
- SYSTEM
- ${GLOG_INCLUDE_DIRS}
- ${GFLAGS_INCLUDE_DIRS}
- )
+ add_definitions(-DWITH_CYCLES_LOGGING)
+ add_definitions(${GLOG_DEFINES})
+ add_definitions(-DCYCLES_GFLAGS_NAMESPACE=${GFLAGS_NAMESPACE})
+ include_directories(
+ SYSTEM
+ ${GLOG_INCLUDE_DIRS}
+ ${GFLAGS_INCLUDE_DIRS}
+ )
endif()
# Debugging capabilities (debug passes etc).
if(WITH_CYCLES_DEBUG)
- add_definitions(-DWITH_CYCLES_DEBUG)
+ add_definitions(-DWITH_CYCLES_DEBUG)
endif()
if(NOT OPENIMAGEIO_PUGIXML_FOUND)
- add_definitions(-DWITH_SYSTEM_PUGIXML)
+ add_definitions(-DWITH_SYSTEM_PUGIXML)
endif()
include_directories(
- SYSTEM
- ${BOOST_INCLUDE_DIR}
- ${OPENIMAGEIO_INCLUDE_DIRS}
- ${OPENIMAGEIO_INCLUDE_DIRS}/OpenImageIO
- ${OPENEXR_INCLUDE_DIR}
- ${OPENEXR_INCLUDE_DIRS}
- ${PUGIXML_INCLUDE_DIR}
+ SYSTEM
+ ${BOOST_INCLUDE_DIR}
+ ${OPENIMAGEIO_INCLUDE_DIRS}
+ ${OPENIMAGEIO_INCLUDE_DIRS}/OpenImageIO
+ ${OPENEXR_INCLUDE_DIR}
+ ${OPENEXR_INCLUDE_DIRS}
+ ${PUGIXML_INCLUDE_DIR}
)
if(CYCLES_STANDALONE_REPOSITORY)
- include_directories(../third_party/atomic)
+ include_directories(../third_party/atomic)
else()
- include_directories(../atomic)
+ include_directories(../atomic)
endif()
# Warnings
if(CMAKE_COMPILER_IS_GNUCXX)
- ADD_CHECK_CXX_COMPILER_FLAG(CMAKE_CXX_FLAGS _has_cxxflag_float_conversion "-Werror=float-conversion")
- ADD_CHECK_CXX_COMPILER_FLAG(CMAKE_CXX_FLAGS _has_cxxflag_double_promotion "-Werror=double-promotion")
- ADD_CHECK_CXX_COMPILER_FLAG(CMAKE_CXX_FLAGS _has_no_error_unused_macros "-Wno-error=unused-macros")
- unset(_has_cxxflag_float_conversion)
- unset(_has_cxxflag_double_promotion)
- unset(_has_no_error_unused_macros)
+ ADD_CHECK_CXX_COMPILER_FLAG(CMAKE_CXX_FLAGS _has_cxxflag_float_conversion "-Werror=float-conversion")
+ ADD_CHECK_CXX_COMPILER_FLAG(CMAKE_CXX_FLAGS _has_cxxflag_double_promotion "-Werror=double-promotion")
+ ADD_CHECK_CXX_COMPILER_FLAG(CMAKE_CXX_FLAGS _has_no_error_unused_macros "-Wno-error=unused-macros")
+ unset(_has_cxxflag_float_conversion)
+ unset(_has_cxxflag_double_promotion)
+ unset(_has_no_error_unused_macros)
endif()
if(WITH_CYCLES_CUDA_BINARIES AND (NOT WITH_CYCLES_CUBIN_COMPILER))
- if(MSVC)
- set(MAX_MSVC 1800)
- if(${CUDA_VERSION} EQUAL "8.0")
- set(MAX_MSVC 1900)
- elseif(${CUDA_VERSION} EQUAL "9.0")
- set(MAX_MSVC 1910)
- elseif(${CUDA_VERSION} EQUAL "9.1")
- set(MAX_MSVC 1911)
- elseif(${CUDA_VERSION} EQUAL "10.0")
- set(MAX_MSVC 1999)
- elseif(${CUDA_VERSION} EQUAL "10.1")
- set(MAX_MSVC 1999)
- endif()
- if(NOT MSVC_VERSION LESS ${MAX_MSVC} OR CMAKE_C_COMPILER_ID MATCHES "Clang")
- message(STATUS "nvcc not supported for this compiler version, using cycles_cubin_cc instead.")
- set(WITH_CYCLES_CUBIN_COMPILER ON)
- endif()
- unset(MAX_MSVC)
- elseif(APPLE)
- if(NOT (${XCODE_VERSION} VERSION_LESS 10.0))
- message(STATUS "nvcc not supported for this compiler version, using cycles_cubin_cc instead.")
- set(WITH_CYCLES_CUBIN_COMPILER ON)
- endif()
- endif()
+ if(MSVC)
+ set(MAX_MSVC 1800)
+ if(${CUDA_VERSION} EQUAL "8.0")
+ set(MAX_MSVC 1900)
+ elseif(${CUDA_VERSION} EQUAL "9.0")
+ set(MAX_MSVC 1910)
+ elseif(${CUDA_VERSION} EQUAL "9.1")
+ set(MAX_MSVC 1911)
+ elseif(${CUDA_VERSION} EQUAL "10.0")
+ set(MAX_MSVC 1999)
+ elseif(${CUDA_VERSION} EQUAL "10.1")
+ set(MAX_MSVC 1999)
+ endif()
+ if(NOT MSVC_VERSION LESS ${MAX_MSVC} OR CMAKE_C_COMPILER_ID MATCHES "Clang")
+ message(STATUS "nvcc not supported for this compiler version, using cycles_cubin_cc instead.")
+ set(WITH_CYCLES_CUBIN_COMPILER ON)
+ endif()
+ unset(MAX_MSVC)
+ elseif(APPLE)
+ if(NOT (${XCODE_VERSION} VERSION_LESS 10.0))
+ message(STATUS "nvcc not supported for this compiler version, using cycles_cubin_cc instead.")
+ set(WITH_CYCLES_CUBIN_COMPILER ON)
+ endif()
+ endif()
endif()
# NVRTC gives wrong rendering result in CUDA 10.0, so we must use NVCC.
if(WITH_CYCLES_CUDA_BINARIES AND WITH_CYCLES_CUBIN_COMPILER)
- if(NOT (${CUDA_VERSION} VERSION_LESS 10.0))
- message(STATUS "cycles_cubin_cc not supported for CUDA 10.0+, using nvcc instead.")
- set(WITH_CYCLES_CUBIN_COMPILER OFF)
- endif()
+ if(NOT (${CUDA_VERSION} VERSION_LESS 10.0))
+ message(STATUS "cycles_cubin_cc not supported for CUDA 10.0+, using nvcc instead.")
+ set(WITH_CYCLES_CUBIN_COMPILER OFF)
+ endif()
endif()
# Subdirectories
if(WITH_CYCLES_BLENDER)
- add_definitions(-DWITH_BLENDER_GUARDEDALLOC)
- add_subdirectory(blender)
+ add_definitions(-DWITH_BLENDER_GUARDEDALLOC)
+ add_subdirectory(blender)
endif()
if(WITH_CYCLES_NETWORK)
- add_definitions(-DWITH_NETWORK)
+ add_definitions(-DWITH_NETWORK)
endif()
if(WITH_OPENCOLORIO)
- add_definitions(-DWITH_OCIO)
- include_directories(
- SYSTEM
- ${OPENCOLORIO_INCLUDE_DIRS}
- )
+ add_definitions(-DWITH_OCIO)
+ include_directories(
+ SYSTEM
+ ${OPENCOLORIO_INCLUDE_DIRS}
+ )
endif()
if(WITH_CYCLES_STANDALONE OR WITH_CYCLES_NETWORK OR WITH_CYCLES_CUBIN_COMPILER)
- add_subdirectory(app)
+ add_subdirectory(app)
endif()
add_subdirectory(bvh)
@@ -359,9 +359,9 @@ add_subdirectory(util)
# TODO(sergey): Make this to work with standalone repository.
if(WITH_GTESTS)
- add_subdirectory(test)
+ add_subdirectory(test)
endif()
if(NOT WITH_BLENDER AND WITH_CYCLES_STANDALONE)
- delayed_do_install(${CMAKE_BINARY_DIR}/bin)
+ delayed_do_install(${CMAKE_BINARY_DIR}/bin)
endif()
diff --git a/intern/cycles/app/CMakeLists.txt b/intern/cycles/app/CMakeLists.txt
index 2d7db860b09..36e3e179be5 100644
--- a/intern/cycles/app/CMakeLists.txt
+++ b/intern/cycles/app/CMakeLists.txt
@@ -1,6 +1,6 @@
set(INC
- ..
+ ..
)
set(INC_SYS
)
@@ -8,46 +8,46 @@ set(INC_SYS
# NOTE: LIBRARIES contains all the libraries which are common
# across release and debug build types, stored in a linking order.
set(LIBRARIES
- cycles_device
- cycles_kernel
- cycles_render
- cycles_bvh
- cycles_subd
- cycles_graph
- cycles_util
- ${BLENDER_GL_LIBRARIES}
- ${CYCLES_APP_GLEW_LIBRARY}
- ${PNG_LIBRARIES}
- ${JPEG_LIBRARIES}
- ${ZLIB_LIBRARIES}
- ${TIFF_LIBRARY}
- ${PTHREADS_LIBRARIES}
- extern_clew
+ cycles_device
+ cycles_kernel
+ cycles_render
+ cycles_bvh
+ cycles_subd
+ cycles_graph
+ cycles_util
+ ${BLENDER_GL_LIBRARIES}
+ ${CYCLES_APP_GLEW_LIBRARY}
+ ${PNG_LIBRARIES}
+ ${JPEG_LIBRARIES}
+ ${ZLIB_LIBRARIES}
+ ${TIFF_LIBRARY}
+ ${PTHREADS_LIBRARIES}
+ extern_clew
)
if(WITH_CUDA_DYNLOAD)
- list(APPEND LIBRARIES extern_cuew)
+ list(APPEND LIBRARIES extern_cuew)
else()
- list(APPEND LIBRARIES ${CUDA_CUDA_LIBRARY})
+ list(APPEND LIBRARIES ${CUDA_CUDA_LIBRARY})
endif()
if(WITH_CYCLES_OSL)
- list(APPEND LIBRARIES cycles_kernel_osl)
+ list(APPEND LIBRARIES cycles_kernel_osl)
endif()
if(NOT CYCLES_STANDALONE_REPOSITORY)
- list(APPEND LIBRARIES bf_intern_glew_mx bf_intern_guardedalloc bf_intern_numaapi)
+ list(APPEND LIBRARIES bf_intern_glew_mx bf_intern_guardedalloc bf_intern_numaapi)
endif()
if(WITH_CYCLES_LOGGING)
- list(APPEND LIBRARIES
- ${GLOG_LIBRARIES}
- ${GFLAGS_LIBRARIES}
- )
+ list(APPEND LIBRARIES
+ ${GLOG_LIBRARIES}
+ ${GFLAGS_LIBRARIES}
+ )
endif()
if(WITH_CYCLES_STANDALONE AND WITH_CYCLES_STANDALONE_GUI)
- list(APPEND LIBRARIES ${GLUT_LIBRARIES})
+ list(APPEND LIBRARIES ${GLUT_LIBRARIES})
endif()
# Common configuration.
@@ -62,7 +62,7 @@ link_directories(${OPENIMAGEIO_LIBPATH}
${OPENJPEG_LIBPATH})
if(WITH_OPENCOLORIO)
- link_directories(${OPENCOLORIO_LIBPATH})
+ link_directories(${OPENCOLORIO_LIBPATH})
endif()
add_definitions(${GL_DEFINITIONS})
@@ -78,90 +78,90 @@ include_directories(SYSTEM ${INC_SYS})
#
# TODO(sergey): Think of a better place for this?
macro(cycles_target_link_libraries target)
- target_link_libraries(${target} ${LIBRARIES})
- if(WITH_CYCLES_OSL)
- target_link_libraries(${target} ${OSL_LIBRARIES} ${LLVM_LIBRARIES})
- endif()
- if(WITH_CYCLES_EMBREE)
- target_link_libraries(${target} ${EMBREE_LIBRARIES})
- endif()
- if(WITH_OPENSUBDIV)
- target_link_libraries(${target} ${OPENSUBDIV_LIBRARIES})
- endif()
- if(WITH_OPENCOLORIO)
- target_link_libraries(${target} ${OPENCOLORIO_LIBRARIES})
- endif()
- target_link_libraries(
- ${target}
- ${OPENIMAGEIO_LIBRARIES}
- ${OPENEXR_LIBRARIES}
- ${OPENJPEG_LIBRARIES}
- ${PUGIXML_LIBRARIES}
- ${BOOST_LIBRARIES}
- ${CMAKE_DL_LIBS}
- ${PLATFORM_LINKLIBS}
- )
+ target_link_libraries(${target} ${LIBRARIES})
+ if(WITH_CYCLES_OSL)
+ target_link_libraries(${target} ${OSL_LIBRARIES} ${LLVM_LIBRARIES})
+ endif()
+ if(WITH_CYCLES_EMBREE)
+ target_link_libraries(${target} ${EMBREE_LIBRARIES})
+ endif()
+ if(WITH_OPENSUBDIV)
+ target_link_libraries(${target} ${OPENSUBDIV_LIBRARIES})
+ endif()
+ if(WITH_OPENCOLORIO)
+ target_link_libraries(${target} ${OPENCOLORIO_LIBRARIES})
+ endif()
+ target_link_libraries(
+ ${target}
+ ${OPENIMAGEIO_LIBRARIES}
+ ${OPENEXR_LIBRARIES}
+ ${OPENJPEG_LIBRARIES}
+ ${PUGIXML_LIBRARIES}
+ ${BOOST_LIBRARIES}
+ ${CMAKE_DL_LIBS}
+ ${PLATFORM_LINKLIBS}
+ )
endmacro()
# Application build targets
if(WITH_CYCLES_STANDALONE)
- set(SRC
- cycles_standalone.cpp
- cycles_xml.cpp
- cycles_xml.h
- )
- add_executable(cycles ${SRC})
- cycles_target_link_libraries(cycles)
-
- if(UNIX AND NOT APPLE)
- set_target_properties(cycles PROPERTIES INSTALL_RPATH $ORIGIN/lib)
- endif()
- unset(SRC)
+ set(SRC
+ cycles_standalone.cpp
+ cycles_xml.cpp
+ cycles_xml.h
+ )
+ add_executable(cycles ${SRC})
+ cycles_target_link_libraries(cycles)
+
+ if(UNIX AND NOT APPLE)
+ set_target_properties(cycles PROPERTIES INSTALL_RPATH $ORIGIN/lib)
+ endif()
+ unset(SRC)
endif()
if(WITH_CYCLES_NETWORK)
- set(SRC
- cycles_server.cpp
- )
- add_executable(cycles_server ${SRC})
- cycles_target_link_libraries(cycles_server)
-
- if(UNIX AND NOT APPLE)
- set_target_properties(cycles_server PROPERTIES INSTALL_RPATH $ORIGIN/lib)
- endif()
- unset(SRC)
+ set(SRC
+ cycles_server.cpp
+ )
+ add_executable(cycles_server ${SRC})
+ cycles_target_link_libraries(cycles_server)
+
+ if(UNIX AND NOT APPLE)
+ set_target_properties(cycles_server PROPERTIES INSTALL_RPATH $ORIGIN/lib)
+ endif()
+ unset(SRC)
endif()
if(WITH_CYCLES_CUBIN_COMPILER)
- # 32 bit windows is special, nvrtc is not supported on x86, so even
- # though we are building 32 bit blender a 64 bit cubin_cc will have
- # to be build to compile the cubins.
- if(MSVC AND NOT CMAKE_CL_64)
- message("Building with CUDA not supported on 32 bit, skipped")
- set(WITH_CYCLES_CUDA_BINARIES OFF CACHE BOOL "" FORCE)
- else()
- set(SRC
- cycles_cubin_cc.cpp
- )
- set(INC
- ../../../extern/cuew/include
- )
- add_executable(cycles_cubin_cc ${SRC})
- include_directories(${INC})
- target_link_libraries(cycles_cubin_cc
- extern_cuew
- ${OPENIMAGEIO_LIBRARIES}
- ${OPENEXR_LIBRARIES}
- ${OPENJPEG_LIBRARIES}
- ${PUGIXML_LIBRARIES}
- ${BOOST_LIBRARIES}
- ${PLATFORM_LINKLIBS}
- )
- if(NOT CYCLES_STANDALONE_REPOSITORY)
- target_link_libraries(cycles_cubin_cc bf_intern_guardedalloc)
- endif()
- unset(SRC)
- unset(INC)
- endif()
+ # 32 bit windows is special, nvrtc is not supported on x86, so even
+ # though we are building 32 bit blender a 64 bit cubin_cc will have
+ # to be build to compile the cubins.
+ if(MSVC AND NOT CMAKE_CL_64)
+ message("Building with CUDA not supported on 32 bit, skipped")
+ set(WITH_CYCLES_CUDA_BINARIES OFF CACHE BOOL "" FORCE)
+ else()
+ set(SRC
+ cycles_cubin_cc.cpp
+ )
+ set(INC
+ ../../../extern/cuew/include
+ )
+ add_executable(cycles_cubin_cc ${SRC})
+ include_directories(${INC})
+ target_link_libraries(cycles_cubin_cc
+ extern_cuew
+ ${OPENIMAGEIO_LIBRARIES}
+ ${OPENEXR_LIBRARIES}
+ ${OPENJPEG_LIBRARIES}
+ ${PUGIXML_LIBRARIES}
+ ${BOOST_LIBRARIES}
+ ${PLATFORM_LINKLIBS}
+ )
+ if(NOT CYCLES_STANDALONE_REPOSITORY)
+ target_link_libraries(cycles_cubin_cc bf_intern_guardedalloc)
+ endif()
+ unset(SRC)
+ unset(INC)
+ endif()
endif()
diff --git a/intern/cycles/app/cycles_cubin_cc.cpp b/intern/cycles/app/cycles_cubin_cc.cpp
index e6eb0be0d91..774c18f4219 100644
--- a/intern/cycles/app/cycles_cubin_cc.cpp
+++ b/intern/cycles/app/cycles_cubin_cc.cpp
@@ -26,272 +26,286 @@
#include "cuew.h"
#ifdef _MSC_VER
-# include <Windows.h>
+# include <Windows.h>
#endif
using std::string;
using std::vector;
namespace std {
- template<typename T>
- std::string to_string(const T &n) {
- std::ostringstream s;
- s << n;
- return s.str();
- }
-}
-
-class CompilationSettings
+template<typename T> std::string to_string(const T &n)
{
-public:
- CompilationSettings()
- : target_arch(0),
- bits(64),
- verbose(false),
- fast_math(false)
- {}
-
- string cuda_toolkit_dir;
- string input_file;
- string output_file;
- string ptx_file;
- vector<string> defines;
- vector<string> includes;
- int target_arch;
- int bits;
- bool verbose;
- bool fast_math;
+ std::ostringstream s;
+ s << n;
+ return s.str();
+}
+} // namespace std
+
+class CompilationSettings {
+ public:
+ CompilationSettings() : target_arch(0), bits(64), verbose(false), fast_math(false)
+ {
+ }
+
+ string cuda_toolkit_dir;
+ string input_file;
+ string output_file;
+ string ptx_file;
+ vector<string> defines;
+ vector<string> includes;
+ int target_arch;
+ int bits;
+ bool verbose;
+ bool fast_math;
};
static bool compile_cuda(CompilationSettings &settings)
{
- const char* headers[] = {"stdlib.h" , "float.h", "math.h", "stdio.h"};
- const char* header_content[] = {"\n", "\n", "\n", "\n"};
-
- printf("Building %s\n", settings.input_file.c_str());
-
- string code;
- if(!OIIO::Filesystem::read_text_file(settings.input_file, code)) {
- fprintf(stderr, "Error: unable to read %s\n", settings.input_file.c_str());
- return false;
- }
-
- vector<string> options;
- for(size_t i = 0; i < settings.includes.size(); i++) {
- options.push_back("-I" + settings.includes[i]);
- }
-
- for(size_t i = 0; i < settings.defines.size(); i++) {
- options.push_back("-D" + settings.defines[i]);
- }
- options.push_back("-D__KERNEL_CUDA_VERSION__=" + std::to_string(cuewNvrtcVersion()));
- options.push_back("-arch=compute_" + std::to_string(settings.target_arch));
- options.push_back("--device-as-default-execution-space");
- if(settings.fast_math)
- options.push_back("--use_fast_math");
-
- nvrtcProgram prog;
- nvrtcResult result = nvrtcCreateProgram(&prog,
- code.c_str(), // buffer
- NULL, // name
- sizeof(headers) / sizeof(void*), // numHeaders
- header_content, // headers
- headers); // includeNames
-
- if(result != NVRTC_SUCCESS) {
- fprintf(stderr, "Error: nvrtcCreateProgram failed (%d)\n\n", (int)result);
- return false;
- }
-
- /* Tranfer options to a classic C array. */
- vector<const char*> opts(options.size());
- for(size_t i = 0; i < options.size(); i++) {
- opts[i] = options[i].c_str();
- }
-
- result = nvrtcCompileProgram(prog, options.size(), &opts[0]);
-
- if(result != NVRTC_SUCCESS) {
- fprintf(stderr, "Error: nvrtcCompileProgram failed (%d)\n\n", (int)result);
-
- size_t log_size;
- nvrtcGetProgramLogSize(prog, &log_size);
-
- vector<char> log(log_size);
- nvrtcGetProgramLog(prog, &log[0]);
- fprintf(stderr, "%s\n", &log[0]);
-
- return false;
- }
-
- /* Retrieve the ptx code. */
- size_t ptx_size;
- result = nvrtcGetPTXSize(prog, &ptx_size);
- if(result != NVRTC_SUCCESS) {
- fprintf(stderr, "Error: nvrtcGetPTXSize failed (%d)\n\n", (int)result);
- return false;
- }
-
- vector<char> ptx_code(ptx_size);
- result = nvrtcGetPTX(prog, &ptx_code[0]);
- if(result != NVRTC_SUCCESS) {
- fprintf(stderr, "Error: nvrtcGetPTX failed (%d)\n\n", (int)result);
- return false;
- }
-
- /* Write a file in the temp folder with the ptx code. */
- settings.ptx_file = OIIO::Filesystem::temp_directory_path() + "/" + OIIO::Filesystem::unique_path();
- FILE * f= fopen(settings.ptx_file.c_str(), "wb");
- fwrite(&ptx_code[0], 1, ptx_size, f);
- fclose(f);
-
- return true;
+ const char *headers[] = {"stdlib.h", "float.h", "math.h", "stdio.h"};
+ const char *header_content[] = {"\n", "\n", "\n", "\n"};
+
+ printf("Building %s\n", settings.input_file.c_str());
+
+ string code;
+ if (!OIIO::Filesystem::read_text_file(settings.input_file, code)) {
+ fprintf(stderr, "Error: unable to read %s\n", settings.input_file.c_str());
+ return false;
+ }
+
+ vector<string> options;
+ for (size_t i = 0; i < settings.includes.size(); i++) {
+ options.push_back("-I" + settings.includes[i]);
+ }
+
+ for (size_t i = 0; i < settings.defines.size(); i++) {
+ options.push_back("-D" + settings.defines[i]);
+ }
+ options.push_back("-D__KERNEL_CUDA_VERSION__=" + std::to_string(cuewNvrtcVersion()));
+ options.push_back("-arch=compute_" + std::to_string(settings.target_arch));
+ options.push_back("--device-as-default-execution-space");
+ if (settings.fast_math)
+ options.push_back("--use_fast_math");
+
+ nvrtcProgram prog;
+ nvrtcResult result = nvrtcCreateProgram(&prog,
+ code.c_str(), // buffer
+ NULL, // name
+ sizeof(headers) / sizeof(void *), // numHeaders
+ header_content, // headers
+ headers); // includeNames
+
+ if (result != NVRTC_SUCCESS) {
+ fprintf(stderr, "Error: nvrtcCreateProgram failed (%d)\n\n", (int)result);
+ return false;
+ }
+
+ /* Tranfer options to a classic C array. */
+ vector<const char *> opts(options.size());
+ for (size_t i = 0; i < options.size(); i++) {
+ opts[i] = options[i].c_str();
+ }
+
+ result = nvrtcCompileProgram(prog, options.size(), &opts[0]);
+
+ if (result != NVRTC_SUCCESS) {
+ fprintf(stderr, "Error: nvrtcCompileProgram failed (%d)\n\n", (int)result);
+
+ size_t log_size;
+ nvrtcGetProgramLogSize(prog, &log_size);
+
+ vector<char> log(log_size);
+ nvrtcGetProgramLog(prog, &log[0]);
+ fprintf(stderr, "%s\n", &log[0]);
+
+ return false;
+ }
+
+ /* Retrieve the ptx code. */
+ size_t ptx_size;
+ result = nvrtcGetPTXSize(prog, &ptx_size);
+ if (result != NVRTC_SUCCESS) {
+ fprintf(stderr, "Error: nvrtcGetPTXSize failed (%d)\n\n", (int)result);
+ return false;
+ }
+
+ vector<char> ptx_code(ptx_size);
+ result = nvrtcGetPTX(prog, &ptx_code[0]);
+ if (result != NVRTC_SUCCESS) {
+ fprintf(stderr, "Error: nvrtcGetPTX failed (%d)\n\n", (int)result);
+ return false;
+ }
+
+ /* Write a file in the temp folder with the ptx code. */
+ settings.ptx_file = OIIO::Filesystem::temp_directory_path() + "/" +
+ OIIO::Filesystem::unique_path();
+ FILE *f = fopen(settings.ptx_file.c_str(), "wb");
+ fwrite(&ptx_code[0], 1, ptx_size, f);
+ fclose(f);
+
+ return true;
}
static bool link_ptxas(CompilationSettings &settings)
{
- string cudapath = "";
- if(settings.cuda_toolkit_dir.size())
- cudapath = settings.cuda_toolkit_dir + "/bin/";
-
- string ptx = "\"" +cudapath + "ptxas\" " + settings.ptx_file +
- " -o " + settings.output_file +
- " --gpu-name sm_" + std::to_string(settings.target_arch) +
- " -m" + std::to_string(settings.bits);
-
- if(settings.verbose) {
- ptx += " --verbose";
- printf("%s\n", ptx.c_str());
- }
-
- int pxresult = system(ptx.c_str());
- if(pxresult) {
- fprintf(stderr, "Error: ptxas failed (%d)\n\n", pxresult);
- return false;
- }
-
- if(!OIIO::Filesystem::remove(settings.ptx_file)) {
- fprintf(stderr, "Error: removing %s\n\n", settings.ptx_file.c_str());
- }
-
- return true;
+ string cudapath = "";
+ if (settings.cuda_toolkit_dir.size())
+ cudapath = settings.cuda_toolkit_dir + "/bin/";
+
+ string ptx = "\"" + cudapath + "ptxas\" " + settings.ptx_file + " -o " + settings.output_file +
+ " --gpu-name sm_" + std::to_string(settings.target_arch) + " -m" +
+ std::to_string(settings.bits);
+
+ if (settings.verbose) {
+ ptx += " --verbose";
+ printf("%s\n", ptx.c_str());
+ }
+
+ int pxresult = system(ptx.c_str());
+ if (pxresult) {
+ fprintf(stderr, "Error: ptxas failed (%d)\n\n", pxresult);
+ return false;
+ }
+
+ if (!OIIO::Filesystem::remove(settings.ptx_file)) {
+ fprintf(stderr, "Error: removing %s\n\n", settings.ptx_file.c_str());
+ }
+
+ return true;
}
static bool init(CompilationSettings &settings)
{
#ifdef _MSC_VER
- if(settings.cuda_toolkit_dir.size()) {
- SetDllDirectory((settings.cuda_toolkit_dir + "/bin").c_str());
- }
+ if (settings.cuda_toolkit_dir.size()) {
+ SetDllDirectory((settings.cuda_toolkit_dir + "/bin").c_str());
+ }
#else
- (void)settings;
+ (void)settings;
#endif
- int cuewresult = cuewInit(CUEW_INIT_NVRTC);
- if(cuewresult != CUEW_SUCCESS) {
- fprintf(stderr, "Error: cuew init fialed (0x%d)\n\n", cuewresult);
- return false;
- }
-
- if(cuewNvrtcVersion() < 80) {
- fprintf(stderr, "Error: only cuda 8 and higher is supported, %d\n\n", cuewCompilerVersion());
- return false;
- }
-
- if(!nvrtcCreateProgram) {
- fprintf(stderr, "Error: nvrtcCreateProgram not resolved\n");
- return false;
- }
-
- if(!nvrtcCompileProgram) {
- fprintf(stderr, "Error: nvrtcCompileProgram not resolved\n");
- return false;
- }
-
- if(!nvrtcGetProgramLogSize) {
- fprintf(stderr, "Error: nvrtcGetProgramLogSize not resolved\n");
- return false;
- }
-
- if(!nvrtcGetProgramLog) {
- fprintf(stderr, "Error: nvrtcGetProgramLog not resolved\n");
- return false;
- }
-
- if(!nvrtcGetPTXSize) {
- fprintf(stderr, "Error: nvrtcGetPTXSize not resolved\n");
- return false;
- }
-
- if(!nvrtcGetPTX) {
- fprintf(stderr, "Error: nvrtcGetPTX not resolved\n");
- return false;
- }
-
- return true;
+ int cuewresult = cuewInit(CUEW_INIT_NVRTC);
+ if (cuewresult != CUEW_SUCCESS) {
+ fprintf(stderr, "Error: cuew init fialed (0x%d)\n\n", cuewresult);
+ return false;
+ }
+
+ if (cuewNvrtcVersion() < 80) {
+ fprintf(stderr, "Error: only cuda 8 and higher is supported, %d\n\n", cuewCompilerVersion());
+ return false;
+ }
+
+ if (!nvrtcCreateProgram) {
+ fprintf(stderr, "Error: nvrtcCreateProgram not resolved\n");
+ return false;
+ }
+
+ if (!nvrtcCompileProgram) {
+ fprintf(stderr, "Error: nvrtcCompileProgram not resolved\n");
+ return false;
+ }
+
+ if (!nvrtcGetProgramLogSize) {
+ fprintf(stderr, "Error: nvrtcGetProgramLogSize not resolved\n");
+ return false;
+ }
+
+ if (!nvrtcGetProgramLog) {
+ fprintf(stderr, "Error: nvrtcGetProgramLog not resolved\n");
+ return false;
+ }
+
+ if (!nvrtcGetPTXSize) {
+ fprintf(stderr, "Error: nvrtcGetPTXSize not resolved\n");
+ return false;
+ }
+
+ if (!nvrtcGetPTX) {
+ fprintf(stderr, "Error: nvrtcGetPTX not resolved\n");
+ return false;
+ }
+
+ return true;
}
static bool parse_parameters(int argc, const char **argv, CompilationSettings &settings)
{
- OIIO::ArgParse ap;
- ap.options("Usage: cycles_cubin_cc [options]",
- "-target %d", &settings.target_arch, "target shader model",
- "-m %d", &settings.bits, "Cuda architecture bits",
- "-i %s", &settings.input_file, "Input source filename",
- "-o %s", &settings.output_file, "Output cubin filename",
- "-I %L", &settings.includes, "Add additional includepath",
- "-D %L", &settings.defines, "Add additional defines",
- "-v", &settings.verbose, "Use verbose logging",
- "--use_fast_math", &settings.fast_math, "Use fast math",
- "-cuda-toolkit-dir %s", &settings.cuda_toolkit_dir, "path to the cuda toolkit binary directory",
- NULL);
-
- if(ap.parse(argc, argv) < 0) {
- fprintf(stderr, "%s\n", ap.geterror().c_str());
- ap.usage();
- return false;
- }
-
- if(!settings.output_file.size()) {
- fprintf(stderr, "Error: Output file not set(-o), required\n\n");
- return false;
- }
-
- if(!settings.input_file.size()) {
- fprintf(stderr, "Error: Input file not set(-i, required\n\n");
- return false;
- }
-
- if(!settings.target_arch) {
- fprintf(stderr, "Error: target shader model not set (-target), required\n\n");
- return false;
- }
-
- return true;
+ OIIO::ArgParse ap;
+ ap.options("Usage: cycles_cubin_cc [options]",
+ "-target %d",
+ &settings.target_arch,
+ "target shader model",
+ "-m %d",
+ &settings.bits,
+ "Cuda architecture bits",
+ "-i %s",
+ &settings.input_file,
+ "Input source filename",
+ "-o %s",
+ &settings.output_file,
+ "Output cubin filename",
+ "-I %L",
+ &settings.includes,
+ "Add additional includepath",
+ "-D %L",
+ &settings.defines,
+ "Add additional defines",
+ "-v",
+ &settings.verbose,
+ "Use verbose logging",
+ "--use_fast_math",
+ &settings.fast_math,
+ "Use fast math",
+ "-cuda-toolkit-dir %s",
+ &settings.cuda_toolkit_dir,
+ "path to the cuda toolkit binary directory",
+ NULL);
+
+ if (ap.parse(argc, argv) < 0) {
+ fprintf(stderr, "%s\n", ap.geterror().c_str());
+ ap.usage();
+ return false;
+ }
+
+ if (!settings.output_file.size()) {
+ fprintf(stderr, "Error: Output file not set(-o), required\n\n");
+ return false;
+ }
+
+ if (!settings.input_file.size()) {
+ fprintf(stderr, "Error: Input file not set(-i, required\n\n");
+ return false;
+ }
+
+ if (!settings.target_arch) {
+ fprintf(stderr, "Error: target shader model not set (-target), required\n\n");
+ return false;
+ }
+
+ return true;
}
int main(int argc, const char **argv)
{
- CompilationSettings settings;
+ CompilationSettings settings;
- if(!parse_parameters(argc, argv, settings)) {
- fprintf(stderr, "Error: invalid parameters, exiting\n");
- exit(EXIT_FAILURE);
- }
+ if (!parse_parameters(argc, argv, settings)) {
+ fprintf(stderr, "Error: invalid parameters, exiting\n");
+ exit(EXIT_FAILURE);
+ }
- if(!init(settings)) {
- fprintf(stderr, "Error: initialization error, exiting\n");
- exit(EXIT_FAILURE);
- }
+ if (!init(settings)) {
+ fprintf(stderr, "Error: initialization error, exiting\n");
+ exit(EXIT_FAILURE);
+ }
- if(!compile_cuda(settings)) {
- fprintf(stderr, "Error: compilation error, exiting\n");
- exit(EXIT_FAILURE);
- }
+ if (!compile_cuda(settings)) {
+ fprintf(stderr, "Error: compilation error, exiting\n");
+ exit(EXIT_FAILURE);
+ }
- if(!link_ptxas(settings)) {
- exit(EXIT_FAILURE);
- }
+ if (!link_ptxas(settings)) {
+ exit(EXIT_FAILURE);
+ }
- return 0;
+ return 0;
}
diff --git a/intern/cycles/app/cycles_server.cpp b/intern/cycles/app/cycles_server.cpp
index e2166473aa3..c5a4c9b375b 100644
--- a/intern/cycles/app/cycles_server.cpp
+++ b/intern/cycles/app/cycles_server.cpp
@@ -30,85 +30,93 @@ using namespace ccl;
int main(int argc, const char **argv)
{
- util_logging_init(argv[0]);
- path_init();
+ util_logging_init(argv[0]);
+ path_init();
+
+ /* device types */
+ string devicelist = "";
+ string devicename = "cpu";
+ bool list = false, debug = false;
+ int threads = 0, verbosity = 1;
+
+ vector<DeviceType> &types = Device::available_types();
+
+ foreach (DeviceType type, types) {
+ if (devicelist != "")
+ devicelist += ", ";
+
+ devicelist += Device::string_from_type(type);
+ }
+
+ /* parse options */
+ ArgParse ap;
+
+ ap.options("Usage: cycles_server [options]",
+ "--device %s",
+ &devicename,
+ ("Devices to use: " + devicelist).c_str(),
+ "--list-devices",
+ &list,
+ "List information about all available devices",
+ "--threads %d",
+ &threads,
+ "Number of threads to use for CPU device",
+#ifdef WITH_CYCLES_LOGGING
+ "--debug",
+ &debug,
+ "Enable debug logging",
+ "--verbose %d",
+ &verbosity,
+ "Set verbosity of the logger",
+#endif
+ NULL);
- /* device types */
- string devicelist = "";
- string devicename = "cpu";
- bool list = false, debug = false;
- int threads = 0, verbosity = 1;
+ if (ap.parse(argc, argv) < 0) {
+ fprintf(stderr, "%s\n", ap.geterror().c_str());
+ ap.usage();
+ exit(EXIT_FAILURE);
+ }
- vector<DeviceType>& types = Device::available_types();
+ if (debug) {
+ util_logging_start();
+ util_logging_verbosity_set(verbosity);
+ }
- foreach(DeviceType type, types) {
- if(devicelist != "")
- devicelist += ", ";
+ if (list) {
+ vector<DeviceInfo> &devices = Device::available_devices();
- devicelist += Device::string_from_type(type);
- }
+ printf("Devices:\n");
- /* parse options */
- ArgParse ap;
+ foreach (DeviceInfo &info, devices) {
+ printf(" %s%s\n", info.description.c_str(), (info.display_device) ? " (display)" : "");
+ }
- ap.options ("Usage: cycles_server [options]",
- "--device %s", &devicename, ("Devices to use: " + devicelist).c_str(),
- "--list-devices", &list, "List information about all available devices",
- "--threads %d", &threads, "Number of threads to use for CPU device",
-#ifdef WITH_CYCLES_LOGGING
- "--debug", &debug, "Enable debug logging",
- "--verbose %d", &verbosity, "Set verbosity of the logger",
-#endif
- NULL);
-
- if(ap.parse(argc, argv) < 0) {
- fprintf(stderr, "%s\n", ap.geterror().c_str());
- ap.usage();
- exit(EXIT_FAILURE);
- }
-
- if(debug) {
- util_logging_start();
- util_logging_verbosity_set(verbosity);
- }
-
- if(list) {
- vector<DeviceInfo>& devices = Device::available_devices();
-
- printf("Devices:\n");
-
- foreach(DeviceInfo& info, devices) {
- printf(" %s%s\n",
- info.description.c_str(),
- (info.display_device)? " (display)": "");
- }
-
- exit(EXIT_SUCCESS);
- }
-
- /* find matching device */
- DeviceType device_type = Device::type_from_string(devicename.c_str());
- vector<DeviceInfo>& devices = Device::available_devices();
- DeviceInfo device_info;
-
- foreach(DeviceInfo& device, devices) {
- if(device_type == device.type) {
- device_info = device;
- break;
- }
- }
-
- TaskScheduler::init(threads);
-
- while(1) {
- Stats stats;
- Device *device = Device::create(device_info, stats, true);
- printf("Cycles Server with device: %s\n", device->info.description.c_str());
- device->server_run();
- delete device;
- }
-
- TaskScheduler::exit();
-
- return 0;
+ exit(EXIT_SUCCESS);
+ }
+
+ /* find matching device */
+ DeviceType device_type = Device::type_from_string(devicename.c_str());
+ vector<DeviceInfo> &devices = Device::available_devices();
+ DeviceInfo device_info;
+
+ foreach (DeviceInfo &device, devices) {
+ if (device_type == device.type) {
+ device_info = device;
+ break;
+ }
+ }
+
+ TaskScheduler::init(threads);
+
+ while (1) {
+ Stats stats;
+ Device *device = Device::create(device_info, stats, true);
+ printf("Cycles Server with device: %s\n", device->info.description.c_str());
+ device->server_run();
+ delete device;
+ }
+
+ TaskScheduler::exit();
+
+ return 0;
}
diff --git a/intern/cycles/app/cycles_standalone.cpp b/intern/cycles/app/cycles_standalone.cpp
index 9c899a38e7b..d2d112e8d7e 100644
--- a/intern/cycles/app/cycles_standalone.cpp
+++ b/intern/cycles/app/cycles_standalone.cpp
@@ -36,7 +36,7 @@
#include "util/util_version.h"
#ifdef WITH_CYCLES_STANDALONE_GUI
-#include "util/util_view.h"
+# include "util/util_view.h"
#endif
#include "app/cycles_xml.h"
@@ -44,447 +44,494 @@
CCL_NAMESPACE_BEGIN
struct Options {
- Session *session;
- Scene *scene;
- string filepath;
- int width, height;
- SceneParams scene_params;
- SessionParams session_params;
- bool quiet;
- bool show_help, interactive, pause;
- string output_path;
+ Session *session;
+ Scene *scene;
+ string filepath;
+ int width, height;
+ SceneParams scene_params;
+ SessionParams session_params;
+ bool quiet;
+ bool show_help, interactive, pause;
+ string output_path;
} options;
-static void session_print(const string& str)
+static void session_print(const string &str)
{
- /* print with carriage return to overwrite previous */
- printf("\r%s", str.c_str());
+ /* print with carriage return to overwrite previous */
+ printf("\r%s", str.c_str());
- /* add spaces to overwrite longer previous print */
- static int maxlen = 0;
- int len = str.size();
- maxlen = max(len, maxlen);
+ /* add spaces to overwrite longer previous print */
+ static int maxlen = 0;
+ int len = str.size();
+ maxlen = max(len, maxlen);
- for(int i = len; i < maxlen; i++)
- printf(" ");
+ for (int i = len; i < maxlen; i++)
+ printf(" ");
- /* flush because we don't write an end of line */
- fflush(stdout);
+ /* flush because we don't write an end of line */
+ fflush(stdout);
}
static void session_print_status()
{
- string status, substatus;
+ string status, substatus;
- /* get status */
- float progress = options.session->progress.get_progress();
- options.session->progress.get_status(status, substatus);
+ /* get status */
+ float progress = options.session->progress.get_progress();
+ options.session->progress.get_status(status, substatus);
- if(substatus != "")
- status += ": " + substatus;
+ if (substatus != "")
+ status += ": " + substatus;
- /* print status */
- status = string_printf("Progress %05.2f %s", (double) progress*100, status.c_str());
- session_print(status);
+ /* print status */
+ status = string_printf("Progress %05.2f %s", (double)progress * 100, status.c_str());
+ session_print(status);
}
static bool write_render(const uchar *pixels, int w, int h, int channels)
{
- string msg = string_printf("Writing image %s", options.output_path.c_str());
- session_print(msg);
+ string msg = string_printf("Writing image %s", options.output_path.c_str());
+ session_print(msg);
- unique_ptr<ImageOutput> out = unique_ptr<ImageOutput>(ImageOutput::create(options.output_path));
- if(!out) {
- return false;
- }
+ unique_ptr<ImageOutput> out = unique_ptr<ImageOutput>(ImageOutput::create(options.output_path));
+ if (!out) {
+ return false;
+ }
- ImageSpec spec(w, h, channels, TypeDesc::UINT8);
- if(!out->open(options.output_path, spec)) {
- return false;
- }
+ ImageSpec spec(w, h, channels, TypeDesc::UINT8);
+ if (!out->open(options.output_path, spec)) {
+ return false;
+ }
- /* conversion for different top/bottom convention */
- out->write_image(TypeDesc::UINT8,
- pixels + (h - 1) * w * channels,
- AutoStride,
- -w * channels,
- AutoStride);
+ /* conversion for different top/bottom convention */
+ out->write_image(
+ TypeDesc::UINT8, pixels + (h - 1) * w * channels, AutoStride, -w * channels, AutoStride);
- out->close();
+ out->close();
- return true;
+ return true;
}
-static BufferParams& session_buffer_params()
+static BufferParams &session_buffer_params()
{
- static BufferParams buffer_params;
- buffer_params.width = options.width;
- buffer_params.height = options.height;
- buffer_params.full_width = options.width;
- buffer_params.full_height = options.height;
+ static BufferParams buffer_params;
+ buffer_params.width = options.width;
+ buffer_params.height = options.height;
+ buffer_params.full_width = options.width;
+ buffer_params.full_height = options.height;
- return buffer_params;
+ return buffer_params;
}
static void scene_init()
{
- options.scene = new Scene(options.scene_params, options.session->device);
-
- /* Read XML */
- xml_read_file(options.scene, options.filepath.c_str());
-
- /* Camera width/height override? */
- if(!(options.width == 0 || options.height == 0)) {
- options.scene->camera->width = options.width;
- options.scene->camera->height = options.height;
- }
- else {
- options.width = options.scene->camera->width;
- options.height = options.scene->camera->height;
- }
-
- /* Calculate Viewplane */
- options.scene->camera->compute_auto_viewplane();
+ options.scene = new Scene(options.scene_params, options.session->device);
+
+ /* Read XML */
+ xml_read_file(options.scene, options.filepath.c_str());
+
+ /* Camera width/height override? */
+ if (!(options.width == 0 || options.height == 0)) {
+ options.scene->camera->width = options.width;
+ options.scene->camera->height = options.height;
+ }
+ else {
+ options.width = options.scene->camera->width;
+ options.height = options.scene->camera->height;
+ }
+
+ /* Calculate Viewplane */
+ options.scene->camera->compute_auto_viewplane();
}
static void session_init()
{
- options.session_params.write_render_cb = write_render;
- options.session = new Session(options.session_params);
+ options.session_params.write_render_cb = write_render;
+ options.session = new Session(options.session_params);
- if(options.session_params.background && !options.quiet)
- options.session->progress.set_update_callback(function_bind(&session_print_status));
+ if (options.session_params.background && !options.quiet)
+ options.session->progress.set_update_callback(function_bind(&session_print_status));
#ifdef WITH_CYCLES_STANDALONE_GUI
- else
- options.session->progress.set_update_callback(function_bind(&view_redraw));
+ else
+ options.session->progress.set_update_callback(function_bind(&view_redraw));
#endif
- /* load scene */
- scene_init();
- options.session->scene = options.scene;
+ /* load scene */
+ scene_init();
+ options.session->scene = options.scene;
- options.session->reset(session_buffer_params(), options.session_params.samples);
- options.session->start();
+ options.session->reset(session_buffer_params(), options.session_params.samples);
+ options.session->start();
}
static void session_exit()
{
- if(options.session) {
- delete options.session;
- options.session = NULL;
- }
-
- if(options.session_params.background && !options.quiet) {
- session_print("Finished Rendering.");
- printf("\n");
- }
+ if (options.session) {
+ delete options.session;
+ options.session = NULL;
+ }
+
+ if (options.session_params.background && !options.quiet) {
+ session_print("Finished Rendering.");
+ printf("\n");
+ }
}
#ifdef WITH_CYCLES_STANDALONE_GUI
-static void display_info(Progress& progress)
+static void display_info(Progress &progress)
{
- static double latency = 0.0;
- static double last = 0;
- double elapsed = time_dt();
- string str, interactive;
-
- latency = (elapsed - last);
- last = elapsed;
-
- double total_time, sample_time;
- string status, substatus;
-
- progress.get_time(total_time, sample_time);
- progress.get_status(status, substatus);
- float progress_val = progress.get_progress();
-
- if(substatus != "")
- status += ": " + substatus;
-
- interactive = options.interactive? "On":"Off";
-
- str = string_printf(
- "%s"
- " Time: %.2f"
- " Latency: %.4f"
- " Progress: %05.2f"
- " Average: %.4f"
- " Interactive: %s",
- status.c_str(), total_time, latency, (double) progress_val*100, sample_time, interactive.c_str());
-
- view_display_info(str.c_str());
-
- if(options.show_help)
- view_display_help();
+ static double latency = 0.0;
+ static double last = 0;
+ double elapsed = time_dt();
+ string str, interactive;
+
+ latency = (elapsed - last);
+ last = elapsed;
+
+ double total_time, sample_time;
+ string status, substatus;
+
+ progress.get_time(total_time, sample_time);
+ progress.get_status(status, substatus);
+ float progress_val = progress.get_progress();
+
+ if (substatus != "")
+ status += ": " + substatus;
+
+ interactive = options.interactive ? "On" : "Off";
+
+ str = string_printf(
+ "%s"
+ " Time: %.2f"
+ " Latency: %.4f"
+ " Progress: %05.2f"
+ " Average: %.4f"
+ " Interactive: %s",
+ status.c_str(),
+ total_time,
+ latency,
+ (double)progress_val * 100,
+ sample_time,
+ interactive.c_str());
+
+ view_display_info(str.c_str());
+
+ if (options.show_help)
+ view_display_help();
}
static void display()
{
- static DeviceDrawParams draw_params = DeviceDrawParams();
+ static DeviceDrawParams draw_params = DeviceDrawParams();
- options.session->draw(session_buffer_params(), draw_params);
+ options.session->draw(session_buffer_params(), draw_params);
- display_info(options.session->progress);
+ display_info(options.session->progress);
}
static void motion(int x, int y, int button)
{
- if(options.interactive) {
- Transform matrix = options.session->scene->camera->matrix;
-
- /* Translate */
- if(button == 0) {
- float3 translate = make_float3(x * 0.01f, -(y * 0.01f), 0.0f);
- matrix = matrix * transform_translate(translate);
- }
-
- /* Rotate */
- else if(button == 2) {
- float4 r1 = make_float4((float)x * 0.1f, 0.0f, 1.0f, 0.0f);
- matrix = matrix * transform_rotate(DEG2RADF(r1.x), make_float3(r1.y, r1.z, r1.w));
-
- float4 r2 = make_float4(y * 0.1f, 1.0f, 0.0f, 0.0f);
- matrix = matrix * transform_rotate(DEG2RADF(r2.x), make_float3(r2.y, r2.z, r2.w));
- }
-
- /* Update and Reset */
- options.session->scene->camera->matrix = matrix;
- options.session->scene->camera->need_update = true;
- options.session->scene->camera->need_device_update = true;
-
- options.session->reset(session_buffer_params(), options.session_params.samples);
- }
+ if (options.interactive) {
+ Transform matrix = options.session->scene->camera->matrix;
+
+ /* Translate */
+ if (button == 0) {
+ float3 translate = make_float3(x * 0.01f, -(y * 0.01f), 0.0f);
+ matrix = matrix * transform_translate(translate);
+ }
+
+ /* Rotate */
+ else if (button == 2) {
+ float4 r1 = make_float4((float)x * 0.1f, 0.0f, 1.0f, 0.0f);
+ matrix = matrix * transform_rotate(DEG2RADF(r1.x), make_float3(r1.y, r1.z, r1.w));
+
+ float4 r2 = make_float4(y * 0.1f, 1.0f, 0.0f, 0.0f);
+ matrix = matrix * transform_rotate(DEG2RADF(r2.x), make_float3(r2.y, r2.z, r2.w));
+ }
+
+ /* Update and Reset */
+ options.session->scene->camera->matrix = matrix;
+ options.session->scene->camera->need_update = true;
+ options.session->scene->camera->need_device_update = true;
+
+ options.session->reset(session_buffer_params(), options.session_params.samples);
+ }
}
static void resize(int width, int height)
{
- options.width = width;
- options.height = height;
-
- if(options.session) {
- /* Update camera */
- options.session->scene->camera->width = width;
- options.session->scene->camera->height = height;
- options.session->scene->camera->compute_auto_viewplane();
- options.session->scene->camera->need_update = true;
- options.session->scene->camera->need_device_update = true;
-
- options.session->reset(session_buffer_params(), options.session_params.samples);
- }
+ options.width = width;
+ options.height = height;
+
+ if (options.session) {
+ /* Update camera */
+ options.session->scene->camera->width = width;
+ options.session->scene->camera->height = height;
+ options.session->scene->camera->compute_auto_viewplane();
+ options.session->scene->camera->need_update = true;
+ options.session->scene->camera->need_device_update = true;
+
+ options.session->reset(session_buffer_params(), options.session_params.samples);
+ }
}
static void keyboard(unsigned char key)
{
- /* Toggle help */
- if(key == 'h')
- options.show_help = !(options.show_help);
-
- /* Reset */
- else if(key == 'r')
- options.session->reset(session_buffer_params(), options.session_params.samples);
-
- /* Cancel */
- else if(key == 27) // escape
- options.session->progress.set_cancel("Canceled");
-
- /* Pause */
- else if(key == 'p') {
- options.pause = !options.pause;
- options.session->set_pause(options.pause);
- }
-
- /* Interactive Mode */
- else if(key == 'i')
- options.interactive = !(options.interactive);
-
- /* Navigation */
- else if(options.interactive && (key == 'w' || key == 'a' || key == 's' || key == 'd')) {
- Transform matrix = options.session->scene->camera->matrix;
- float3 translate;
-
- if(key == 'w')
- translate = make_float3(0.0f, 0.0f, 0.1f);
- else if(key == 's')
- translate = make_float3(0.0f, 0.0f, -0.1f);
- else if(key == 'a')
- translate = make_float3(-0.1f, 0.0f, 0.0f);
- else if(key == 'd')
- translate = make_float3(0.1f, 0.0f, 0.0f);
-
- matrix = matrix * transform_translate(translate);
-
- /* Update and Reset */
- options.session->scene->camera->matrix = matrix;
- options.session->scene->camera->need_update = true;
- options.session->scene->camera->need_device_update = true;
-
- options.session->reset(session_buffer_params(), options.session_params.samples);
- }
-
- /* Set Max Bounces */
- else if(options.interactive && (key == '0' || key == '1' || key == '2' || key == '3')) {
- int bounce;
- switch(key) {
- case '0': bounce = 0; break;
- case '1': bounce = 1; break;
- case '2': bounce = 2; break;
- case '3': bounce = 3; break;
- default: bounce = 0; break;
- }
-
- options.session->scene->integrator->max_bounce = bounce;
-
- /* Update and Reset */
- options.session->scene->integrator->need_update = true;
-
- options.session->reset(session_buffer_params(), options.session_params.samples);
- }
+ /* Toggle help */
+ if (key == 'h')
+ options.show_help = !(options.show_help);
+
+ /* Reset */
+ else if (key == 'r')
+ options.session->reset(session_buffer_params(), options.session_params.samples);
+
+ /* Cancel */
+ else if (key == 27) // escape
+ options.session->progress.set_cancel("Canceled");
+
+ /* Pause */
+ else if (key == 'p') {
+ options.pause = !options.pause;
+ options.session->set_pause(options.pause);
+ }
+
+ /* Interactive Mode */
+ else if (key == 'i')
+ options.interactive = !(options.interactive);
+
+ /* Navigation */
+ else if (options.interactive && (key == 'w' || key == 'a' || key == 's' || key == 'd')) {
+ Transform matrix = options.session->scene->camera->matrix;
+ float3 translate;
+
+ if (key == 'w')
+ translate = make_float3(0.0f, 0.0f, 0.1f);
+ else if (key == 's')
+ translate = make_float3(0.0f, 0.0f, -0.1f);
+ else if (key == 'a')
+ translate = make_float3(-0.1f, 0.0f, 0.0f);
+ else if (key == 'd')
+ translate = make_float3(0.1f, 0.0f, 0.0f);
+
+ matrix = matrix * transform_translate(translate);
+
+ /* Update and Reset */
+ options.session->scene->camera->matrix = matrix;
+ options.session->scene->camera->need_update = true;
+ options.session->scene->camera->need_device_update = true;
+
+ options.session->reset(session_buffer_params(), options.session_params.samples);
+ }
+
+ /* Set Max Bounces */
+ else if (options.interactive && (key == '0' || key == '1' || key == '2' || key == '3')) {
+ int bounce;
+ switch (key) {
+ case '0':
+ bounce = 0;
+ break;
+ case '1':
+ bounce = 1;
+ break;
+ case '2':
+ bounce = 2;
+ break;
+ case '3':
+ bounce = 3;
+ break;
+ default:
+ bounce = 0;
+ break;
+ }
+
+ options.session->scene->integrator->max_bounce = bounce;
+
+ /* Update and Reset */
+ options.session->scene->integrator->need_update = true;
+
+ options.session->reset(session_buffer_params(), options.session_params.samples);
+ }
}
#endif
static int files_parse(int argc, const char *argv[])
{
- if(argc > 0)
- options.filepath = argv[0];
+ if (argc > 0)
+ options.filepath = argv[0];
- return 0;
+ return 0;
}
static void options_parse(int argc, const char **argv)
{
- options.width = 0;
- options.height = 0;
- options.filepath = "";
- options.session = NULL;
- options.quiet = false;
-
- /* device names */
- string device_names = "";
- string devicename = "CPU";
- bool list = false;
-
- /* List devices for which support is compiled in. */
- vector<DeviceType> types = Device::available_types();
- foreach(DeviceType type, types) {
- if(device_names != "")
- device_names += ", ";
-
- device_names += Device::string_from_type(type);
- }
-
- /* shading system */
- string ssname = "svm";
-
- /* parse options */
- ArgParse ap;
- bool help = false, debug = false, version = false;
- int verbosity = 1;
-
- ap.options ("Usage: cycles [options] file.xml",
- "%*", files_parse, "",
- "--device %s", &devicename, ("Devices to use: " + device_names).c_str(),
+ options.width = 0;
+ options.height = 0;
+ options.filepath = "";
+ options.session = NULL;
+ options.quiet = false;
+
+ /* device names */
+ string device_names = "";
+ string devicename = "CPU";
+ bool list = false;
+
+ /* List devices for which support is compiled in. */
+ vector<DeviceType> types = Device::available_types();
+ foreach (DeviceType type, types) {
+ if (device_names != "")
+ device_names += ", ";
+
+ device_names += Device::string_from_type(type);
+ }
+
+ /* shading system */
+ string ssname = "svm";
+
+ /* parse options */
+ ArgParse ap;
+ bool help = false, debug = false, version = false;
+ int verbosity = 1;
+
+ ap.options("Usage: cycles [options] file.xml",
+ "%*",
+ files_parse,
+ "",
+ "--device %s",
+ &devicename,
+ ("Devices to use: " + device_names).c_str(),
#ifdef WITH_OSL
- "--shadingsys %s", &ssname, "Shading system to use: svm, osl",
+ "--shadingsys %s",
+ &ssname,
+ "Shading system to use: svm, osl",
#endif
- "--background", &options.session_params.background, "Render in background, without user interface",
- "--quiet", &options.quiet, "In background mode, don't print progress messages",
- "--samples %d", &options.session_params.samples, "Number of samples to render",
- "--output %s", &options.output_path, "File path to write output image",
- "--threads %d", &options.session_params.threads, "CPU Rendering Threads",
- "--width %d", &options.width, "Window width in pixel",
- "--height %d", &options.height, "Window height in pixel",
- "--tile-width %d", &options.session_params.tile_size.x, "Tile width in pixels",
- "--tile-height %d", &options.session_params.tile_size.y, "Tile height in pixels",
- "--list-devices", &list, "List information about all available devices",
+ "--background",
+ &options.session_params.background,
+ "Render in background, without user interface",
+ "--quiet",
+ &options.quiet,
+ "In background mode, don't print progress messages",
+ "--samples %d",
+ &options.session_params.samples,
+ "Number of samples to render",
+ "--output %s",
+ &options.output_path,
+ "File path to write output image",
+ "--threads %d",
+ &options.session_params.threads,
+ "CPU Rendering Threads",
+ "--width %d",
+ &options.width,
+ "Window width in pixel",
+ "--height %d",
+ &options.height,
+ "Window height in pixel",
+ "--tile-width %d",
+ &options.session_params.tile_size.x,
+ "Tile width in pixels",
+ "--tile-height %d",
+ &options.session_params.tile_size.y,
+ "Tile height in pixels",
+ "--list-devices",
+ &list,
+ "List information about all available devices",
#ifdef WITH_CYCLES_LOGGING
- "--debug", &debug, "Enable debug logging",
- "--verbose %d", &verbosity, "Set verbosity of the logger",
+ "--debug",
+ &debug,
+ "Enable debug logging",
+ "--verbose %d",
+ &verbosity,
+ "Set verbosity of the logger",
#endif
- "--help", &help, "Print help message",
- "--version", &version, "Print version number",
- NULL);
-
- if(ap.parse(argc, argv) < 0) {
- fprintf(stderr, "%s\n", ap.geterror().c_str());
- ap.usage();
- exit(EXIT_FAILURE);
- }
-
- if(debug) {
- util_logging_start();
- util_logging_verbosity_set(verbosity);
- }
-
- if(list) {
- vector<DeviceInfo> devices = Device::available_devices();
- printf("Devices:\n");
-
- foreach(DeviceInfo& info, devices) {
- printf(" %-10s%s%s\n",
- Device::string_from_type(info.type).c_str(),
- info.description.c_str(),
- (info.display_device)? " (display)": "");
- }
-
- exit(EXIT_SUCCESS);
- }
- else if(version) {
- printf("%s\n", CYCLES_VERSION_STRING);
- exit(EXIT_SUCCESS);
- }
- else if(help || options.filepath == "") {
- ap.usage();
- exit(EXIT_SUCCESS);
- }
-
- if(ssname == "osl")
- options.scene_params.shadingsystem = SHADINGSYSTEM_OSL;
- else if(ssname == "svm")
- options.scene_params.shadingsystem = SHADINGSYSTEM_SVM;
+ "--help",
+ &help,
+ "Print help message",
+ "--version",
+ &version,
+ "Print version number",
+ NULL);
+
+ if (ap.parse(argc, argv) < 0) {
+ fprintf(stderr, "%s\n", ap.geterror().c_str());
+ ap.usage();
+ exit(EXIT_FAILURE);
+ }
+
+ if (debug) {
+ util_logging_start();
+ util_logging_verbosity_set(verbosity);
+ }
+
+ if (list) {
+ vector<DeviceInfo> devices = Device::available_devices();
+ printf("Devices:\n");
+
+ foreach (DeviceInfo &info, devices) {
+ printf(" %-10s%s%s\n",
+ Device::string_from_type(info.type).c_str(),
+ info.description.c_str(),
+ (info.display_device) ? " (display)" : "");
+ }
+
+ exit(EXIT_SUCCESS);
+ }
+ else if (version) {
+ printf("%s\n", CYCLES_VERSION_STRING);
+ exit(EXIT_SUCCESS);
+ }
+ else if (help || options.filepath == "") {
+ ap.usage();
+ exit(EXIT_SUCCESS);
+ }
+
+ if (ssname == "osl")
+ options.scene_params.shadingsystem = SHADINGSYSTEM_OSL;
+ else if (ssname == "svm")
+ options.scene_params.shadingsystem = SHADINGSYSTEM_SVM;
#ifndef WITH_CYCLES_STANDALONE_GUI
- options.session_params.background = true;
+ options.session_params.background = true;
#endif
- /* Use progressive rendering */
- options.session_params.progressive = true;
+ /* Use progressive rendering */
+ options.session_params.progressive = true;
- /* find matching device */
- DeviceType device_type = Device::type_from_string(devicename.c_str());
- vector<DeviceInfo> devices = Device::available_devices(DEVICE_MASK(device_type));
+ /* find matching device */
+ DeviceType device_type = Device::type_from_string(devicename.c_str());
+ vector<DeviceInfo> devices = Device::available_devices(DEVICE_MASK(device_type));
- bool device_available = false;
- if (!devices.empty()) {
- options.session_params.device = devices.front();
- device_available = true;
- }
+ bool device_available = false;
+ if (!devices.empty()) {
+ options.session_params.device = devices.front();
+ device_available = true;
+ }
- /* handle invalid configurations */
- if(options.session_params.device.type == DEVICE_NONE || !device_available) {
- fprintf(stderr, "Unknown device: %s\n", devicename.c_str());
- exit(EXIT_FAILURE);
- }
+ /* handle invalid configurations */
+ if (options.session_params.device.type == DEVICE_NONE || !device_available) {
+ fprintf(stderr, "Unknown device: %s\n", devicename.c_str());
+ exit(EXIT_FAILURE);
+ }
#ifdef WITH_OSL
- else if(!(ssname == "osl" || ssname == "svm")) {
- fprintf(stderr, "Unknown shading system: %s\n", ssname.c_str());
- exit(EXIT_FAILURE);
- }
- else if(options.scene_params.shadingsystem == SHADINGSYSTEM_OSL && options.session_params.device.type != DEVICE_CPU) {
- fprintf(stderr, "OSL shading system only works with CPU device\n");
- exit(EXIT_FAILURE);
- }
+ else if (!(ssname == "osl" || ssname == "svm")) {
+ fprintf(stderr, "Unknown shading system: %s\n", ssname.c_str());
+ exit(EXIT_FAILURE);
+ }
+ else if (options.scene_params.shadingsystem == SHADINGSYSTEM_OSL &&
+ options.session_params.device.type != DEVICE_CPU) {
+ fprintf(stderr, "OSL shading system only works with CPU device\n");
+ exit(EXIT_FAILURE);
+ }
#endif
- else if(options.session_params.samples < 0) {
- fprintf(stderr, "Invalid number of samples: %d\n", options.session_params.samples);
- exit(EXIT_FAILURE);
- }
- else if(options.filepath == "") {
- fprintf(stderr, "No file path specified\n");
- exit(EXIT_FAILURE);
- }
-
- /* For smoother Viewport */
- options.session_params.start_resolution = 64;
+ else if (options.session_params.samples < 0) {
+ fprintf(stderr, "Invalid number of samples: %d\n", options.session_params.samples);
+ exit(EXIT_FAILURE);
+ }
+ else if (options.filepath == "") {
+ fprintf(stderr, "No file path specified\n");
+ exit(EXIT_FAILURE);
+ }
+
+ /* For smoother Viewport */
+ options.session_params.start_resolution = 64;
}
CCL_NAMESPACE_END
@@ -493,26 +540,33 @@ using namespace ccl;
int main(int argc, const char **argv)
{
- util_logging_init(argv[0]);
- path_init();
- options_parse(argc, argv);
+ util_logging_init(argv[0]);
+ path_init();
+ options_parse(argc, argv);
#ifdef WITH_CYCLES_STANDALONE_GUI
- if(options.session_params.background) {
+ if (options.session_params.background) {
#endif
- session_init();
- options.session->wait();
- session_exit();
+ session_init();
+ options.session->wait();
+ session_exit();
#ifdef WITH_CYCLES_STANDALONE_GUI
- }
- else {
- string title = "Cycles: " + path_filename(options.filepath);
-
- /* init/exit are callback so they run while GL is initialized */
- view_main_loop(title.c_str(), options.width, options.height,
- session_init, session_exit, resize, display, keyboard, motion);
- }
+ }
+ else {
+ string title = "Cycles: " + path_filename(options.filepath);
+
+ /* init/exit are callback so they run while GL is initialized */
+ view_main_loop(title.c_str(),
+ options.width,
+ options.height,
+ session_init,
+ session_exit,
+ resize,
+ display,
+ keyboard,
+ motion);
+ }
#endif
- return 0;
+ return 0;
}
diff --git a/intern/cycles/app/cycles_xml.cpp b/intern/cycles/app/cycles_xml.cpp
index 86491adb3a4..9caf7068d3d 100644
--- a/intern/cycles/app/cycles_xml.cpp
+++ b/intern/cycles/app/cycles_xml.cpp
@@ -51,647 +51,649 @@ CCL_NAMESPACE_BEGIN
/* XML reading state */
struct XMLReadState : public XMLReader {
- Scene *scene; /* scene pointer */
- Transform tfm; /* current transform state */
- bool smooth; /* smooth normal state */
- Shader *shader; /* current shader */
- string base; /* base path to current file*/
- float dicing_rate; /* current dicing rate */
-
- XMLReadState()
- : scene(NULL),
- smooth(false),
- shader(NULL),
- dicing_rate(1.0f)
- {
- tfm = transform_identity();
- }
+ Scene *scene; /* scene pointer */
+ Transform tfm; /* current transform state */
+ bool smooth; /* smooth normal state */
+ Shader *shader; /* current shader */
+ string base; /* base path to current file*/
+ float dicing_rate; /* current dicing rate */
+
+ XMLReadState() : scene(NULL), smooth(false), shader(NULL), dicing_rate(1.0f)
+ {
+ tfm = transform_identity();
+ }
};
/* Attribute Reading */
static bool xml_read_int(int *value, xml_node node, const char *name)
{
- xml_attribute attr = node.attribute(name);
+ xml_attribute attr = node.attribute(name);
- if(attr) {
- *value = atoi(attr.value());
- return true;
- }
+ if (attr) {
+ *value = atoi(attr.value());
+ return true;
+ }
- return false;
+ return false;
}
-static bool xml_read_int_array(vector<int>& value, xml_node node, const char *name)
+static bool xml_read_int_array(vector<int> &value, xml_node node, const char *name)
{
- xml_attribute attr = node.attribute(name);
+ xml_attribute attr = node.attribute(name);
- if(attr) {
- vector<string> tokens;
- string_split(tokens, attr.value());
+ if (attr) {
+ vector<string> tokens;
+ string_split(tokens, attr.value());
- foreach(const string& token, tokens)
- value.push_back(atoi(token.c_str()));
+ foreach (const string &token, tokens)
+ value.push_back(atoi(token.c_str()));
- return true;
- }
+ return true;
+ }
- return false;
+ return false;
}
static bool xml_read_float(float *value, xml_node node, const char *name)
{
- xml_attribute attr = node.attribute(name);
+ xml_attribute attr = node.attribute(name);
- if(attr) {
- *value = (float)atof(attr.value());
- return true;
- }
+ if (attr) {
+ *value = (float)atof(attr.value());
+ return true;
+ }
- return false;
+ return false;
}
-static bool xml_read_float_array(vector<float>& value, xml_node node, const char *name)
+static bool xml_read_float_array(vector<float> &value, xml_node node, const char *name)
{
- xml_attribute attr = node.attribute(name);
+ xml_attribute attr = node.attribute(name);
- if(attr) {
- vector<string> tokens;
- string_split(tokens, attr.value());
+ if (attr) {
+ vector<string> tokens;
+ string_split(tokens, attr.value());
- foreach(const string& token, tokens)
- value.push_back((float)atof(token.c_str()));
+ foreach (const string &token, tokens)
+ value.push_back((float)atof(token.c_str()));
- return true;
- }
+ return true;
+ }
- return false;
+ return false;
}
static bool xml_read_float3(float3 *value, xml_node node, const char *name)
{
- vector<float> array;
+ vector<float> array;
- if(xml_read_float_array(array, node, name) && array.size() == 3) {
- *value = make_float3(array[0], array[1], array[2]);
- return true;
- }
+ if (xml_read_float_array(array, node, name) && array.size() == 3) {
+ *value = make_float3(array[0], array[1], array[2]);
+ return true;
+ }
- return false;
+ return false;
}
-static bool xml_read_float3_array(vector<float3>& value, xml_node node, const char *name)
+static bool xml_read_float3_array(vector<float3> &value, xml_node node, const char *name)
{
- vector<float> array;
+ vector<float> array;
- if(xml_read_float_array(array, node, name)) {
- for(size_t i = 0; i < array.size(); i += 3)
- value.push_back(make_float3(array[i+0], array[i+1], array[i+2]));
+ if (xml_read_float_array(array, node, name)) {
+ for (size_t i = 0; i < array.size(); i += 3)
+ value.push_back(make_float3(array[i + 0], array[i + 1], array[i + 2]));
- return true;
- }
+ return true;
+ }
- return false;
+ return false;
}
static bool xml_read_float4(float4 *value, xml_node node, const char *name)
{
- vector<float> array;
+ vector<float> array;
- if(xml_read_float_array(array, node, name) && array.size() == 4) {
- *value = make_float4(array[0], array[1], array[2], array[3]);
- return true;
- }
+ if (xml_read_float_array(array, node, name) && array.size() == 4) {
+ *value = make_float4(array[0], array[1], array[2], array[3]);
+ return true;
+ }
- return false;
+ return false;
}
static bool xml_read_string(string *str, xml_node node, const char *name)
{
- xml_attribute attr = node.attribute(name);
+ xml_attribute attr = node.attribute(name);
- if(attr) {
- *str = attr.value();
- return true;
- }
+ if (attr) {
+ *str = attr.value();
+ return true;
+ }
- return false;
+ return false;
}
static bool xml_equal_string(xml_node node, const char *name, const char *value)
{
- xml_attribute attr = node.attribute(name);
+ xml_attribute attr = node.attribute(name);
- if(attr)
- return string_iequals(attr.value(), value);
+ if (attr)
+ return string_iequals(attr.value(), value);
- return false;
+ return false;
}
/* Camera */
-static void xml_read_camera(XMLReadState& state, xml_node node)
+static void xml_read_camera(XMLReadState &state, xml_node node)
{
- Camera *cam = state.scene->camera;
+ Camera *cam = state.scene->camera;
- xml_read_int(&cam->width, node, "width");
- xml_read_int(&cam->height, node, "height");
+ xml_read_int(&cam->width, node, "width");
+ xml_read_int(&cam->height, node, "height");
- cam->full_width = cam->width;
- cam->full_height = cam->height;
+ cam->full_width = cam->width;
+ cam->full_height = cam->height;
- xml_read_node(state, cam, node);
+ xml_read_node(state, cam, node);
- cam->matrix = state.tfm;
+ cam->matrix = state.tfm;
- cam->need_update = true;
- cam->update(state.scene);
+ cam->need_update = true;
+ cam->update(state.scene);
}
/* Shader */
-static void xml_read_shader_graph(XMLReadState& state, Shader *shader, xml_node graph_node)
+static void xml_read_shader_graph(XMLReadState &state, Shader *shader, xml_node graph_node)
{
- xml_read_node(state, shader, graph_node);
-
- ShaderGraph *graph = new ShaderGraph();
-
- /* local state, shader nodes can't link to nodes outside the shader graph */
- XMLReader graph_reader;
- graph_reader.node_map[ustring("output")] = graph->output();
-
- for(xml_node node = graph_node.first_child(); node; node = node.next_sibling()) {
- ustring node_name(node.name());
-
- if(node_name == "connect") {
- /* connect nodes */
- vector<string> from_tokens, to_tokens;
-
- string_split(from_tokens, node.attribute("from").value());
- string_split(to_tokens, node.attribute("to").value());
-
- if(from_tokens.size() == 2 && to_tokens.size() == 2) {
- ustring from_node_name(from_tokens[0]);
- ustring from_socket_name(from_tokens[1]);
- ustring to_node_name(to_tokens[0]);
- ustring to_socket_name(to_tokens[1]);
-
- /* find nodes and sockets */
- ShaderOutput *output = NULL;
- ShaderInput *input = NULL;
-
- if(graph_reader.node_map.find(from_node_name) != graph_reader.node_map.end()) {
- ShaderNode *fromnode = (ShaderNode*)graph_reader.node_map[from_node_name];
-
- foreach(ShaderOutput *out, fromnode->outputs)
- if(string_iequals(out->socket_type.name.string(), from_socket_name.string()))
- output = out;
-
- if(!output)
- fprintf(stderr, "Unknown output socket name \"%s\" on \"%s\".\n", from_node_name.c_str(), from_socket_name.c_str());
- }
- else
- fprintf(stderr, "Unknown shader node name \"%s\".\n", from_node_name.c_str());
-
- if(graph_reader.node_map.find(to_node_name) != graph_reader.node_map.end()) {
- ShaderNode *tonode = (ShaderNode*)graph_reader.node_map[to_node_name];
-
- foreach(ShaderInput *in, tonode->inputs)
- if(string_iequals(in->socket_type.name.string(), to_socket_name.string()))
- input = in;
-
- if(!input)
- fprintf(stderr, "Unknown input socket name \"%s\" on \"%s\".\n", to_socket_name.c_str(), to_node_name.c_str());
- }
- else
- fprintf(stderr, "Unknown shader node name \"%s\".\n", to_node_name.c_str());
-
- /* connect */
- if(output && input)
- graph->connect(output, input);
- }
- else
- fprintf(stderr, "Invalid from or to value for connect node.\n");
-
- continue;
- }
-
- ShaderNode *snode = NULL;
+ xml_read_node(state, shader, graph_node);
+
+ ShaderGraph *graph = new ShaderGraph();
+
+ /* local state, shader nodes can't link to nodes outside the shader graph */
+ XMLReader graph_reader;
+ graph_reader.node_map[ustring("output")] = graph->output();
+
+ for (xml_node node = graph_node.first_child(); node; node = node.next_sibling()) {
+ ustring node_name(node.name());
+
+ if (node_name == "connect") {
+ /* connect nodes */
+ vector<string> from_tokens, to_tokens;
+
+ string_split(from_tokens, node.attribute("from").value());
+ string_split(to_tokens, node.attribute("to").value());
+
+ if (from_tokens.size() == 2 && to_tokens.size() == 2) {
+ ustring from_node_name(from_tokens[0]);
+ ustring from_socket_name(from_tokens[1]);
+ ustring to_node_name(to_tokens[0]);
+ ustring to_socket_name(to_tokens[1]);
+
+ /* find nodes and sockets */
+ ShaderOutput *output = NULL;
+ ShaderInput *input = NULL;
+
+ if (graph_reader.node_map.find(from_node_name) != graph_reader.node_map.end()) {
+ ShaderNode *fromnode = (ShaderNode *)graph_reader.node_map[from_node_name];
+
+ foreach (ShaderOutput *out, fromnode->outputs)
+ if (string_iequals(out->socket_type.name.string(), from_socket_name.string()))
+ output = out;
+
+ if (!output)
+ fprintf(stderr,
+ "Unknown output socket name \"%s\" on \"%s\".\n",
+ from_node_name.c_str(),
+ from_socket_name.c_str());
+ }
+ else
+ fprintf(stderr, "Unknown shader node name \"%s\".\n", from_node_name.c_str());
+
+ if (graph_reader.node_map.find(to_node_name) != graph_reader.node_map.end()) {
+ ShaderNode *tonode = (ShaderNode *)graph_reader.node_map[to_node_name];
+
+ foreach (ShaderInput *in, tonode->inputs)
+ if (string_iequals(in->socket_type.name.string(), to_socket_name.string()))
+ input = in;
+
+ if (!input)
+ fprintf(stderr,
+ "Unknown input socket name \"%s\" on \"%s\".\n",
+ to_socket_name.c_str(),
+ to_node_name.c_str());
+ }
+ else
+ fprintf(stderr, "Unknown shader node name \"%s\".\n", to_node_name.c_str());
+
+ /* connect */
+ if (output && input)
+ graph->connect(output, input);
+ }
+ else
+ fprintf(stderr, "Invalid from or to value for connect node.\n");
+
+ continue;
+ }
+
+ ShaderNode *snode = NULL;
#ifdef WITH_OSL
- if(node_name == "osl_shader") {
- ShaderManager *manager = state.scene->shader_manager;
-
- if(manager->use_osl()) {
- std::string filepath;
-
- if(xml_read_string(&filepath, node, "src")) {
- if(path_is_relative(filepath)) {
- filepath = path_join(state.base, filepath);
- }
-
- snode = ((OSLShaderManager*)manager)->osl_node(filepath);
-
- if(!snode) {
- fprintf(stderr, "Failed to create OSL node from \"%s\".\n", filepath.c_str());
- continue;
- }
- }
- else {
- fprintf(stderr, "OSL node missing \"src\" attribute.\n");
- continue;
- }
- }
- else {
- fprintf(stderr, "OSL node without using --shadingsys osl.\n");
- continue;
- }
- }
- else
+ if (node_name == "osl_shader") {
+ ShaderManager *manager = state.scene->shader_manager;
+
+ if (manager->use_osl()) {
+ std::string filepath;
+
+ if (xml_read_string(&filepath, node, "src")) {
+ if (path_is_relative(filepath)) {
+ filepath = path_join(state.base, filepath);
+ }
+
+ snode = ((OSLShaderManager *)manager)->osl_node(filepath);
+
+ if (!snode) {
+ fprintf(stderr, "Failed to create OSL node from \"%s\".\n", filepath.c_str());
+ continue;
+ }
+ }
+ else {
+ fprintf(stderr, "OSL node missing \"src\" attribute.\n");
+ continue;
+ }
+ }
+ else {
+ fprintf(stderr, "OSL node without using --shadingsys osl.\n");
+ continue;
+ }
+ }
+ else
#endif
- {
- /* exception for name collision */
- if(node_name == "background")
- node_name = "background_shader";
-
- const NodeType *node_type = NodeType::find(node_name);
-
- if(!node_type) {
- fprintf(stderr, "Unknown shader node \"%s\".\n", node.name());
- continue;
- }
- else if(node_type->type != NodeType::SHADER) {
- fprintf(stderr, "Node type \"%s\" is not a shader node.\n", node_type->name.c_str());
- continue;
- }
-
- snode = (ShaderNode*) node_type->create(node_type);
- }
-
- xml_read_node(graph_reader, snode, node);
-
- if(node_name == "image_texture") {
- ImageTextureNode *img = (ImageTextureNode*) snode;
- img->filename = path_join(state.base, img->filename.string());
- }
- else if(node_name == "environment_texture") {
- EnvironmentTextureNode *env = (EnvironmentTextureNode*) snode;
- env->filename = path_join(state.base, env->filename.string());
- }
-
- if(snode) {
- /* add to graph */
- graph->add(snode);
- }
- }
-
- shader->set_graph(graph);
- shader->tag_update(state.scene);
+ {
+ /* exception for name collision */
+ if (node_name == "background")
+ node_name = "background_shader";
+
+ const NodeType *node_type = NodeType::find(node_name);
+
+ if (!node_type) {
+ fprintf(stderr, "Unknown shader node \"%s\".\n", node.name());
+ continue;
+ }
+ else if (node_type->type != NodeType::SHADER) {
+ fprintf(stderr, "Node type \"%s\" is not a shader node.\n", node_type->name.c_str());
+ continue;
+ }
+
+ snode = (ShaderNode *)node_type->create(node_type);
+ }
+
+ xml_read_node(graph_reader, snode, node);
+
+ if (node_name == "image_texture") {
+ ImageTextureNode *img = (ImageTextureNode *)snode;
+ img->filename = path_join(state.base, img->filename.string());
+ }
+ else if (node_name == "environment_texture") {
+ EnvironmentTextureNode *env = (EnvironmentTextureNode *)snode;
+ env->filename = path_join(state.base, env->filename.string());
+ }
+
+ if (snode) {
+ /* add to graph */
+ graph->add(snode);
+ }
+ }
+
+ shader->set_graph(graph);
+ shader->tag_update(state.scene);
}
-static void xml_read_shader(XMLReadState& state, xml_node node)
+static void xml_read_shader(XMLReadState &state, xml_node node)
{
- Shader *shader = new Shader();
- xml_read_shader_graph(state, shader, node);
- state.scene->shaders.push_back(shader);
+ Shader *shader = new Shader();
+ xml_read_shader_graph(state, shader, node);
+ state.scene->shaders.push_back(shader);
}
/* Background */
-static void xml_read_background(XMLReadState& state, xml_node node)
+static void xml_read_background(XMLReadState &state, xml_node node)
{
- /* Background Settings */
- xml_read_node(state, state.scene->background, node);
+ /* Background Settings */
+ xml_read_node(state, state.scene->background, node);
- /* Background Shader */
- Shader *shader = state.scene->default_background;
- xml_read_shader_graph(state, shader, node);
+ /* Background Shader */
+ Shader *shader = state.scene->default_background;
+ xml_read_shader_graph(state, shader, node);
}
/* Mesh */
-static Mesh *xml_add_mesh(Scene *scene, const Transform& tfm)
+static Mesh *xml_add_mesh(Scene *scene, const Transform &tfm)
{
- /* create mesh */
- Mesh *mesh = new Mesh();
- scene->meshes.push_back(mesh);
+ /* create mesh */
+ Mesh *mesh = new Mesh();
+ scene->meshes.push_back(mesh);
- /* create object*/
- Object *object = new Object();
- object->mesh = mesh;
- object->tfm = tfm;
- scene->objects.push_back(object);
+ /* create object*/
+ Object *object = new Object();
+ object->mesh = mesh;
+ object->tfm = tfm;
+ scene->objects.push_back(object);
- return mesh;
+ return mesh;
}
-static void xml_read_mesh(const XMLReadState& state, xml_node node)
+static void xml_read_mesh(const XMLReadState &state, xml_node node)
{
- /* add mesh */
- Mesh *mesh = xml_add_mesh(state.scene, state.tfm);
- mesh->used_shaders.push_back(state.shader);
-
- /* read state */
- int shader = 0;
- bool smooth = state.smooth;
-
- /* read vertices and polygons */
- vector<float3> P;
- vector<float> UV;
- vector<int> verts, nverts;
-
- xml_read_float3_array(P, node, "P");
- xml_read_int_array(verts, node, "verts");
- xml_read_int_array(nverts, node, "nverts");
-
- if(xml_equal_string(node, "subdivision", "catmull-clark")) {
- mesh->subdivision_type = Mesh::SUBDIVISION_CATMULL_CLARK;
- }
- else if(xml_equal_string(node, "subdivision", "linear")) {
- mesh->subdivision_type = Mesh::SUBDIVISION_LINEAR;
- }
-
- if(mesh->subdivision_type == Mesh::SUBDIVISION_NONE) {
- /* create vertices */
- mesh->verts = P;
-
- size_t num_triangles = 0;
- for(size_t i = 0; i < nverts.size(); i++)
- num_triangles += nverts[i]-2;
- mesh->reserve_mesh(mesh->verts.size(), num_triangles);
-
- /* create triangles */
- int index_offset = 0;
-
- for(size_t i = 0; i < nverts.size(); i++) {
- for(int j = 0; j < nverts[i]-2; j++) {
- int v0 = verts[index_offset];
- int v1 = verts[index_offset + j + 1];
- int v2 = verts[index_offset + j + 2];
-
- assert(v0 < (int)P.size());
- assert(v1 < (int)P.size());
- assert(v2 < (int)P.size());
-
- mesh->add_triangle(v0, v1, v2, shader, smooth);
- }
-
- index_offset += nverts[i];
- }
-
- if(xml_read_float_array(UV, node, "UV")) {
- ustring name = ustring("UVMap");
- Attribute *attr = mesh->attributes.add(ATTR_STD_UV, name);
- float2 *fdata = attr->data_float2();
-
- /* loop over the triangles */
- index_offset = 0;
- for(size_t i = 0; i < nverts.size(); i++) {
- for(int j = 0; j < nverts[i]-2; j++) {
- int v0 = index_offset;
- int v1 = index_offset + j + 1;
- int v2 = index_offset + j + 2;
-
- assert(v0*2+1 < (int)UV.size());
- assert(v1*2+1 < (int)UV.size());
- assert(v2*2+1 < (int)UV.size());
-
- fdata[0] = make_float2(UV[v0*2], UV[v0*2+1]);
- fdata[1] = make_float2(UV[v1*2], UV[v1*2+1]);
- fdata[2] = make_float2(UV[v2*2], UV[v2*2+1]);
- fdata += 3;
- }
-
- index_offset += nverts[i];
- }
- }
- }
- else {
- /* create vertices */
- mesh->verts = P;
-
- size_t num_ngons = 0;
- size_t num_corners = 0;
- for(size_t i = 0; i < nverts.size(); i++) {
- num_ngons += (nverts[i] == 4) ? 0 : 1;
- num_corners += nverts[i];
- }
- mesh->reserve_subd_faces(nverts.size(), num_ngons, num_corners);
-
- /* create subd_faces */
- int index_offset = 0;
-
- for(size_t i = 0; i < nverts.size(); i++) {
- mesh->add_subd_face(&verts[index_offset], nverts[i], shader, smooth);
- index_offset += nverts[i];
- }
-
- /* uv map */
- if(xml_read_float_array(UV, node, "UV")) {
- ustring name = ustring("UVMap");
- Attribute *attr = mesh->subd_attributes.add(ATTR_STD_UV, name);
- float3 *fdata = attr->data_float3();
+ /* add mesh */
+ Mesh *mesh = xml_add_mesh(state.scene, state.tfm);
+ mesh->used_shaders.push_back(state.shader);
+
+ /* read state */
+ int shader = 0;
+ bool smooth = state.smooth;
+
+ /* read vertices and polygons */
+ vector<float3> P;
+ vector<float> UV;
+ vector<int> verts, nverts;
+
+ xml_read_float3_array(P, node, "P");
+ xml_read_int_array(verts, node, "verts");
+ xml_read_int_array(nverts, node, "nverts");
+
+ if (xml_equal_string(node, "subdivision", "catmull-clark")) {
+ mesh->subdivision_type = Mesh::SUBDIVISION_CATMULL_CLARK;
+ }
+ else if (xml_equal_string(node, "subdivision", "linear")) {
+ mesh->subdivision_type = Mesh::SUBDIVISION_LINEAR;
+ }
+
+ if (mesh->subdivision_type == Mesh::SUBDIVISION_NONE) {
+ /* create vertices */
+ mesh->verts = P;
+
+ size_t num_triangles = 0;
+ for (size_t i = 0; i < nverts.size(); i++)
+ num_triangles += nverts[i] - 2;
+ mesh->reserve_mesh(mesh->verts.size(), num_triangles);
+
+ /* create triangles */
+ int index_offset = 0;
+
+ for (size_t i = 0; i < nverts.size(); i++) {
+ for (int j = 0; j < nverts[i] - 2; j++) {
+ int v0 = verts[index_offset];
+ int v1 = verts[index_offset + j + 1];
+ int v2 = verts[index_offset + j + 2];
+
+ assert(v0 < (int)P.size());
+ assert(v1 < (int)P.size());
+ assert(v2 < (int)P.size());
+
+ mesh->add_triangle(v0, v1, v2, shader, smooth);
+ }
+
+ index_offset += nverts[i];
+ }
+
+ if (xml_read_float_array(UV, node, "UV")) {
+ ustring name = ustring("UVMap");
+ Attribute *attr = mesh->attributes.add(ATTR_STD_UV, name);
+ float2 *fdata = attr->data_float2();
+
+ /* loop over the triangles */
+ index_offset = 0;
+ for (size_t i = 0; i < nverts.size(); i++) {
+ for (int j = 0; j < nverts[i] - 2; j++) {
+ int v0 = index_offset;
+ int v1 = index_offset + j + 1;
+ int v2 = index_offset + j + 2;
+
+ assert(v0 * 2 + 1 < (int)UV.size());
+ assert(v1 * 2 + 1 < (int)UV.size());
+ assert(v2 * 2 + 1 < (int)UV.size());
+
+ fdata[0] = make_float2(UV[v0 * 2], UV[v0 * 2 + 1]);
+ fdata[1] = make_float2(UV[v1 * 2], UV[v1 * 2 + 1]);
+ fdata[2] = make_float2(UV[v2 * 2], UV[v2 * 2 + 1]);
+ fdata += 3;
+ }
+
+ index_offset += nverts[i];
+ }
+ }
+ }
+ else {
+ /* create vertices */
+ mesh->verts = P;
+
+ size_t num_ngons = 0;
+ size_t num_corners = 0;
+ for (size_t i = 0; i < nverts.size(); i++) {
+ num_ngons += (nverts[i] == 4) ? 0 : 1;
+ num_corners += nverts[i];
+ }
+ mesh->reserve_subd_faces(nverts.size(), num_ngons, num_corners);
+
+ /* create subd_faces */
+ int index_offset = 0;
+
+ for (size_t i = 0; i < nverts.size(); i++) {
+ mesh->add_subd_face(&verts[index_offset], nverts[i], shader, smooth);
+ index_offset += nverts[i];
+ }
+
+ /* uv map */
+ if (xml_read_float_array(UV, node, "UV")) {
+ ustring name = ustring("UVMap");
+ Attribute *attr = mesh->subd_attributes.add(ATTR_STD_UV, name);
+ float3 *fdata = attr->data_float3();
#if 0
- if(subdivide_uvs) {
- attr->flags |= ATTR_SUBDIVIDED;
- }
+ if(subdivide_uvs) {
+ attr->flags |= ATTR_SUBDIVIDED;
+ }
#endif
- index_offset = 0;
- for(size_t i = 0; i < nverts.size(); i++) {
- for(int j = 0; j < nverts[i]; j++) {
- *(fdata++) = make_float3(UV[index_offset++]);
- }
- }
- }
-
- /* setup subd params */
- if(!mesh->subd_params) {
- mesh->subd_params = new SubdParams(mesh);
- }
- SubdParams& sdparams = *mesh->subd_params;
-
- sdparams.dicing_rate = state.dicing_rate;
- xml_read_float(&sdparams.dicing_rate, node, "dicing_rate");
- sdparams.dicing_rate = std::max(0.1f, sdparams.dicing_rate);
-
- sdparams.objecttoworld = state.tfm;
- }
-
- /* we don't yet support arbitrary attributes, for now add vertex
- * coordinates as generated coordinates if requested */
- if(mesh->need_attribute(state.scene, ATTR_STD_GENERATED)) {
- Attribute *attr = mesh->attributes.add(ATTR_STD_GENERATED);
- memcpy(attr->data_float3(), mesh->verts.data(), sizeof(float3)*mesh->verts.size());
- }
+ index_offset = 0;
+ for (size_t i = 0; i < nverts.size(); i++) {
+ for (int j = 0; j < nverts[i]; j++) {
+ *(fdata++) = make_float3(UV[index_offset++]);
+ }
+ }
+ }
+
+ /* setup subd params */
+ if (!mesh->subd_params) {
+ mesh->subd_params = new SubdParams(mesh);
+ }
+ SubdParams &sdparams = *mesh->subd_params;
+
+ sdparams.dicing_rate = state.dicing_rate;
+ xml_read_float(&sdparams.dicing_rate, node, "dicing_rate");
+ sdparams.dicing_rate = std::max(0.1f, sdparams.dicing_rate);
+
+ sdparams.objecttoworld = state.tfm;
+ }
+
+ /* we don't yet support arbitrary attributes, for now add vertex
+ * coordinates as generated coordinates if requested */
+ if (mesh->need_attribute(state.scene, ATTR_STD_GENERATED)) {
+ Attribute *attr = mesh->attributes.add(ATTR_STD_GENERATED);
+ memcpy(attr->data_float3(), mesh->verts.data(), sizeof(float3) * mesh->verts.size());
+ }
}
/* Light */
-static void xml_read_light(XMLReadState& state, xml_node node)
+static void xml_read_light(XMLReadState &state, xml_node node)
{
- Light *light = new Light();
+ Light *light = new Light();
- light->shader = state.shader;
- xml_read_node(state, light, node);
+ light->shader = state.shader;
+ xml_read_node(state, light, node);
- state.scene->lights.push_back(light);
+ state.scene->lights.push_back(light);
}
/* Transform */
-static void xml_read_transform(xml_node node, Transform& tfm)
+static void xml_read_transform(xml_node node, Transform &tfm)
{
- if(node.attribute("matrix")) {
- vector<float> matrix;
- if(xml_read_float_array(matrix, node, "matrix") && matrix.size() == 16) {
- ProjectionTransform projection = *(ProjectionTransform*)&matrix[0];
- tfm = tfm * projection_to_transform(projection_transpose(projection));
- }
- }
-
- if(node.attribute("translate")) {
- float3 translate = make_float3(0.0f, 0.0f, 0.0f);
- xml_read_float3(&translate, node, "translate");
- tfm = tfm * transform_translate(translate);
- }
-
- if(node.attribute("rotate")) {
- float4 rotate = make_float4(0.0f, 0.0f, 0.0f, 0.0f);
- xml_read_float4(&rotate, node, "rotate");
- tfm = tfm * transform_rotate(DEG2RADF(rotate.x), make_float3(rotate.y, rotate.z, rotate.w));
- }
-
- if(node.attribute("scale")) {
- float3 scale = make_float3(0.0f, 0.0f, 0.0f);
- xml_read_float3(&scale, node, "scale");
- tfm = tfm * transform_scale(scale);
- }
+ if (node.attribute("matrix")) {
+ vector<float> matrix;
+ if (xml_read_float_array(matrix, node, "matrix") && matrix.size() == 16) {
+ ProjectionTransform projection = *(ProjectionTransform *)&matrix[0];
+ tfm = tfm * projection_to_transform(projection_transpose(projection));
+ }
+ }
+
+ if (node.attribute("translate")) {
+ float3 translate = make_float3(0.0f, 0.0f, 0.0f);
+ xml_read_float3(&translate, node, "translate");
+ tfm = tfm * transform_translate(translate);
+ }
+
+ if (node.attribute("rotate")) {
+ float4 rotate = make_float4(0.0f, 0.0f, 0.0f, 0.0f);
+ xml_read_float4(&rotate, node, "rotate");
+ tfm = tfm * transform_rotate(DEG2RADF(rotate.x), make_float3(rotate.y, rotate.z, rotate.w));
+ }
+
+ if (node.attribute("scale")) {
+ float3 scale = make_float3(0.0f, 0.0f, 0.0f);
+ xml_read_float3(&scale, node, "scale");
+ tfm = tfm * transform_scale(scale);
+ }
}
/* State */
-static void xml_read_state(XMLReadState& state, xml_node node)
+static void xml_read_state(XMLReadState &state, xml_node node)
{
- /* read shader */
- string shadername;
-
- if(xml_read_string(&shadername, node, "shader")) {
- bool found = false;
-
- foreach(Shader *shader, state.scene->shaders) {
- if(shader->name == shadername) {
- state.shader = shader;
- found = true;
- break;
- }
- }
-
- if(!found)
- fprintf(stderr, "Unknown shader \"%s\".\n", shadername.c_str());
- }
-
- xml_read_float(&state.dicing_rate, node, "dicing_rate");
-
- /* read smooth/flat */
- if(xml_equal_string(node, "interpolation", "smooth"))
- state.smooth = true;
- else if(xml_equal_string(node, "interpolation", "flat"))
- state.smooth = false;
+ /* read shader */
+ string shadername;
+
+ if (xml_read_string(&shadername, node, "shader")) {
+ bool found = false;
+
+ foreach (Shader *shader, state.scene->shaders) {
+ if (shader->name == shadername) {
+ state.shader = shader;
+ found = true;
+ break;
+ }
+ }
+
+ if (!found)
+ fprintf(stderr, "Unknown shader \"%s\".\n", shadername.c_str());
+ }
+
+ xml_read_float(&state.dicing_rate, node, "dicing_rate");
+
+ /* read smooth/flat */
+ if (xml_equal_string(node, "interpolation", "smooth"))
+ state.smooth = true;
+ else if (xml_equal_string(node, "interpolation", "flat"))
+ state.smooth = false;
}
/* Scene */
-static void xml_read_include(XMLReadState& state, const string& src);
+static void xml_read_include(XMLReadState &state, const string &src);
-static void xml_read_scene(XMLReadState& state, xml_node scene_node)
+static void xml_read_scene(XMLReadState &state, xml_node scene_node)
{
- for(xml_node node = scene_node.first_child(); node; node = node.next_sibling()) {
- if(string_iequals(node.name(), "film")) {
- xml_read_node(state, state.scene->film, node);
- }
- else if(string_iequals(node.name(), "integrator")) {
- xml_read_node(state, state.scene->integrator, node);
- }
- else if(string_iequals(node.name(), "camera")) {
- xml_read_camera(state, node);
- }
- else if(string_iequals(node.name(), "shader")) {
- xml_read_shader(state, node);
- }
- else if(string_iequals(node.name(), "background")) {
- xml_read_background(state, node);
- }
- else if(string_iequals(node.name(), "mesh")) {
- xml_read_mesh(state, node);
- }
- else if(string_iequals(node.name(), "light")) {
- xml_read_light(state, node);
- }
- else if(string_iequals(node.name(), "transform")) {
- XMLReadState substate = state;
-
- xml_read_transform(node, substate.tfm);
- xml_read_scene(substate, node);
- }
- else if(string_iequals(node.name(), "state")) {
- XMLReadState substate = state;
-
- xml_read_state(substate, node);
- xml_read_scene(substate, node);
- }
- else if(string_iequals(node.name(), "include")) {
- string src;
-
- if(xml_read_string(&src, node, "src"))
- xml_read_include(state, src);
- }
- else
- fprintf(stderr, "Unknown node \"%s\".\n", node.name());
- }
+ for (xml_node node = scene_node.first_child(); node; node = node.next_sibling()) {
+ if (string_iequals(node.name(), "film")) {
+ xml_read_node(state, state.scene->film, node);
+ }
+ else if (string_iequals(node.name(), "integrator")) {
+ xml_read_node(state, state.scene->integrator, node);
+ }
+ else if (string_iequals(node.name(), "camera")) {
+ xml_read_camera(state, node);
+ }
+ else if (string_iequals(node.name(), "shader")) {
+ xml_read_shader(state, node);
+ }
+ else if (string_iequals(node.name(), "background")) {
+ xml_read_background(state, node);
+ }
+ else if (string_iequals(node.name(), "mesh")) {
+ xml_read_mesh(state, node);
+ }
+ else if (string_iequals(node.name(), "light")) {
+ xml_read_light(state, node);
+ }
+ else if (string_iequals(node.name(), "transform")) {
+ XMLReadState substate = state;
+
+ xml_read_transform(node, substate.tfm);
+ xml_read_scene(substate, node);
+ }
+ else if (string_iequals(node.name(), "state")) {
+ XMLReadState substate = state;
+
+ xml_read_state(substate, node);
+ xml_read_scene(substate, node);
+ }
+ else if (string_iequals(node.name(), "include")) {
+ string src;
+
+ if (xml_read_string(&src, node, "src"))
+ xml_read_include(state, src);
+ }
+ else
+ fprintf(stderr, "Unknown node \"%s\".\n", node.name());
+ }
}
/* Include */
-static void xml_read_include(XMLReadState& state, const string& src)
+static void xml_read_include(XMLReadState &state, const string &src)
{
- /* open XML document */
- xml_document doc;
- xml_parse_result parse_result;
-
- string path = path_join(state.base, src);
- parse_result = doc.load_file(path.c_str());
-
- if(parse_result) {
- XMLReadState substate = state;
- substate.base = path_dirname(path);
-
- xml_node cycles = doc.child("cycles");
- xml_read_scene(substate, cycles);
- }
- else {
- fprintf(stderr, "%s read error: %s\n", src.c_str(), parse_result.description());
- exit(EXIT_FAILURE);
- }
+ /* open XML document */
+ xml_document doc;
+ xml_parse_result parse_result;
+
+ string path = path_join(state.base, src);
+ parse_result = doc.load_file(path.c_str());
+
+ if (parse_result) {
+ XMLReadState substate = state;
+ substate.base = path_dirname(path);
+
+ xml_node cycles = doc.child("cycles");
+ xml_read_scene(substate, cycles);
+ }
+ else {
+ fprintf(stderr, "%s read error: %s\n", src.c_str(), parse_result.description());
+ exit(EXIT_FAILURE);
+ }
}
/* File */
void xml_read_file(Scene *scene, const char *filepath)
{
- XMLReadState state;
+ XMLReadState state;
- state.scene = scene;
- state.tfm = transform_identity();
- state.shader = scene->default_surface;
- state.smooth = false;
- state.dicing_rate = 1.0f;
- state.base = path_dirname(filepath);
+ state.scene = scene;
+ state.tfm = transform_identity();
+ state.shader = scene->default_surface;
+ state.smooth = false;
+ state.dicing_rate = 1.0f;
+ state.base = path_dirname(filepath);
- xml_read_include(state, path_filename(filepath));
+ xml_read_include(state, path_filename(filepath));
- scene->params.bvh_type = SceneParams::BVH_STATIC;
+ scene->params.bvh_type = SceneParams::BVH_STATIC;
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/app/cycles_xml.h b/intern/cycles/app/cycles_xml.h
index a7bc1895d4e..6a48980d8ea 100644
--- a/intern/cycles/app/cycles_xml.h
+++ b/intern/cycles/app/cycles_xml.h
@@ -29,4 +29,4 @@ void xml_read_file(Scene *scene, const char *filepath);
CCL_NAMESPACE_END
-#endif /* __CYCLES_XML_H__ */
+#endif /* __CYCLES_XML_H__ */
diff --git a/intern/cycles/blender/CCL_api.h b/intern/cycles/blender/CCL_api.h
index b9750ad0c53..233ffc8802c 100644
--- a/intern/cycles/blender/CCL_api.h
+++ b/intern/cycles/blender/CCL_api.h
@@ -33,4 +33,4 @@ void CCL_logging_verbosity_set(int verbosity);
}
#endif
-#endif /* __CCL_API_H__ */
+#endif /* __CCL_API_H__ */
diff --git a/intern/cycles/blender/CMakeLists.txt b/intern/cycles/blender/CMakeLists.txt
index fc265a47a01..7354b1e615e 100644
--- a/intern/cycles/blender/CMakeLists.txt
+++ b/intern/cycles/blender/CMakeLists.txt
@@ -1,68 +1,68 @@
set(INC
- ..
- ../../glew-mx
- ../../guardedalloc
- ../../mikktspace
- ../../../source/blender/makesdna
- ../../../source/blender/makesrna
- ../../../source/blender/blenlib
- ${CMAKE_BINARY_DIR}/source/blender/makesrna/intern
+ ..
+ ../../glew-mx
+ ../../guardedalloc
+ ../../mikktspace
+ ../../../source/blender/makesdna
+ ../../../source/blender/makesrna
+ ../../../source/blender/blenlib
+ ${CMAKE_BINARY_DIR}/source/blender/makesrna/intern
)
set(INC_SYS
- ${PYTHON_INCLUDE_DIRS}
- ${GLEW_INCLUDE_DIR}
+ ${PYTHON_INCLUDE_DIRS}
+ ${GLEW_INCLUDE_DIR}
)
set(SRC
- blender_camera.cpp
- blender_device.cpp
- blender_mesh.cpp
- blender_object.cpp
- blender_object_cull.cpp
- blender_particles.cpp
- blender_curves.cpp
- blender_logging.cpp
- blender_python.cpp
- blender_session.cpp
- blender_shader.cpp
- blender_sync.cpp
- blender_texture.cpp
+ blender_camera.cpp
+ blender_device.cpp
+ blender_mesh.cpp
+ blender_object.cpp
+ blender_object_cull.cpp
+ blender_particles.cpp
+ blender_curves.cpp
+ blender_logging.cpp
+ blender_python.cpp
+ blender_session.cpp
+ blender_shader.cpp
+ blender_sync.cpp
+ blender_texture.cpp
- CCL_api.h
- blender_object_cull.h
- blender_sync.h
- blender_session.h
- blender_texture.h
- blender_util.h
+ CCL_api.h
+ blender_object_cull.h
+ blender_sync.h
+ blender_session.h
+ blender_texture.h
+ blender_util.h
)
set(LIB
- cycles_bvh
- cycles_device
- cycles_graph
- cycles_kernel
- cycles_render
- cycles_subd
- cycles_util
+ cycles_bvh
+ cycles_device
+ cycles_graph
+ cycles_kernel
+ cycles_render
+ cycles_subd
+ cycles_util
)
if(WITH_CYCLES_LOGGING)
- list(APPEND LIB
- extern_glog
- )
+ list(APPEND LIB
+ extern_glog
+ )
endif()
set(ADDON_FILES
- addon/__init__.py
- addon/engine.py
- addon/operators.py
- addon/osl.py
- addon/presets.py
- addon/properties.py
- addon/ui.py
- addon/version_update.py
+ addon/__init__.py
+ addon/engine.py
+ addon/operators.py
+ addon/osl.py
+ addon/presets.py
+ addon/properties.py
+ addon/ui.py
+ addon/version_update.py
)
add_definitions(${GL_DEFINITIONS})
@@ -72,14 +72,14 @@ if(WITH_CYCLES_DEVICE_OPENCL)
endif()
if(WITH_CYCLES_NETWORK)
- add_definitions(-DWITH_NETWORK)
+ add_definitions(-DWITH_NETWORK)
endif()
blender_add_lib(bf_intern_cycles "${SRC}" "${INC}" "${INC_SYS}" "${LIB}")
# avoid link failure with clang 3.4 debug
if(CMAKE_C_COMPILER_ID MATCHES "Clang" AND NOT ${CMAKE_C_COMPILER_VERSION} VERSION_LESS '3.4')
- set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -gline-tables-only")
+ set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -gline-tables-only")
endif()
add_dependencies(bf_intern_cycles bf_rna)
diff --git a/intern/cycles/blender/blender_camera.cpp b/intern/cycles/blender/blender_camera.cpp
index 21efba4cdf0..b3bfaa992a9 100644
--- a/intern/cycles/blender/blender_camera.cpp
+++ b/intern/cycles/blender/blender_camera.cpp
@@ -28,875 +28,858 @@ CCL_NAMESPACE_BEGIN
* render camera to this, and from there convert to our native camera format. */
struct BlenderCamera {
- float nearclip;
- float farclip;
+ float nearclip;
+ float farclip;
- CameraType type;
- float ortho_scale;
+ CameraType type;
+ float ortho_scale;
- float lens;
- float shuttertime;
- Camera::MotionPosition motion_position;
- array<float> shutter_curve;
+ float lens;
+ float shuttertime;
+ Camera::MotionPosition motion_position;
+ array<float> shutter_curve;
- Camera::RollingShutterType rolling_shutter_type;
- float rolling_shutter_duration;
+ Camera::RollingShutterType rolling_shutter_type;
+ float rolling_shutter_duration;
- float aperturesize;
- uint apertureblades;
- float aperturerotation;
- float focaldistance;
+ float aperturesize;
+ uint apertureblades;
+ float aperturerotation;
+ float focaldistance;
- float2 shift;
- float2 offset;
- float zoom;
+ float2 shift;
+ float2 offset;
+ float zoom;
- float2 pixelaspect;
+ float2 pixelaspect;
- float aperture_ratio;
+ float aperture_ratio;
- PanoramaType panorama_type;
- float fisheye_fov;
- float fisheye_lens;
- float latitude_min;
- float latitude_max;
- float longitude_min;
- float longitude_max;
- bool use_spherical_stereo;
- float interocular_distance;
- float convergence_distance;
- bool use_pole_merge;
- float pole_merge_angle_from;
- float pole_merge_angle_to;
+ PanoramaType panorama_type;
+ float fisheye_fov;
+ float fisheye_lens;
+ float latitude_min;
+ float latitude_max;
+ float longitude_min;
+ float longitude_max;
+ bool use_spherical_stereo;
+ float interocular_distance;
+ float convergence_distance;
+ bool use_pole_merge;
+ float pole_merge_angle_from;
+ float pole_merge_angle_to;
- enum { AUTO, HORIZONTAL, VERTICAL } sensor_fit;
- float sensor_width;
- float sensor_height;
+ enum { AUTO, HORIZONTAL, VERTICAL } sensor_fit;
+ float sensor_width;
+ float sensor_height;
- int full_width;
- int full_height;
+ int full_width;
+ int full_height;
- BoundBox2D border;
- BoundBox2D pano_viewplane;
- BoundBox2D viewport_camera_border;
+ BoundBox2D border;
+ BoundBox2D pano_viewplane;
+ BoundBox2D viewport_camera_border;
- Transform matrix;
+ Transform matrix;
- float offscreen_dicing_scale;
+ float offscreen_dicing_scale;
- int motion_steps;
+ int motion_steps;
};
-static void blender_camera_init(BlenderCamera *bcam,
- BL::RenderSettings& b_render)
+static void blender_camera_init(BlenderCamera *bcam, BL::RenderSettings &b_render)
{
- memset((void *)bcam, 0, sizeof(BlenderCamera));
-
- bcam->type = CAMERA_PERSPECTIVE;
- bcam->zoom = 1.0f;
- bcam->pixelaspect = make_float2(1.0f, 1.0f);
- bcam->sensor_width = 36.0f;
- bcam->sensor_height = 24.0f;
- bcam->sensor_fit = BlenderCamera::AUTO;
- bcam->shuttertime = 1.0f;
- bcam->motion_position = Camera::MOTION_POSITION_CENTER;
- bcam->rolling_shutter_type = Camera::ROLLING_SHUTTER_NONE;
- bcam->rolling_shutter_duration = 0.1f;
- bcam->border.right = 1.0f;
- bcam->border.top = 1.0f;
- bcam->pano_viewplane.right = 1.0f;
- bcam->pano_viewplane.top = 1.0f;
- bcam->viewport_camera_border.right = 1.0f;
- bcam->viewport_camera_border.top = 1.0f;
- bcam->offscreen_dicing_scale = 1.0f;
-
- /* render resolution */
- bcam->full_width = render_resolution_x(b_render);
- bcam->full_height = render_resolution_y(b_render);
+ memset((void *)bcam, 0, sizeof(BlenderCamera));
+
+ bcam->type = CAMERA_PERSPECTIVE;
+ bcam->zoom = 1.0f;
+ bcam->pixelaspect = make_float2(1.0f, 1.0f);
+ bcam->sensor_width = 36.0f;
+ bcam->sensor_height = 24.0f;
+ bcam->sensor_fit = BlenderCamera::AUTO;
+ bcam->shuttertime = 1.0f;
+ bcam->motion_position = Camera::MOTION_POSITION_CENTER;
+ bcam->rolling_shutter_type = Camera::ROLLING_SHUTTER_NONE;
+ bcam->rolling_shutter_duration = 0.1f;
+ bcam->border.right = 1.0f;
+ bcam->border.top = 1.0f;
+ bcam->pano_viewplane.right = 1.0f;
+ bcam->pano_viewplane.top = 1.0f;
+ bcam->viewport_camera_border.right = 1.0f;
+ bcam->viewport_camera_border.top = 1.0f;
+ bcam->offscreen_dicing_scale = 1.0f;
+
+ /* render resolution */
+ bcam->full_width = render_resolution_x(b_render);
+ bcam->full_height = render_resolution_y(b_render);
}
-static float blender_camera_focal_distance(BL::RenderEngine& b_engine,
- BL::Object& b_ob,
- BL::Camera& b_camera,
+static float blender_camera_focal_distance(BL::RenderEngine &b_engine,
+ BL::Object &b_ob,
+ BL::Camera &b_camera,
BlenderCamera *bcam)
{
- BL::Object b_dof_object = b_camera.dof_object();
-
- if(!b_dof_object)
- return b_camera.dof_distance();
-
- /* for dof object, return distance along camera Z direction */
- BL::Array<float, 16> b_ob_matrix;
- b_engine.camera_model_matrix(b_ob, bcam->use_spherical_stereo, b_ob_matrix);
- Transform obmat = transform_clear_scale(get_transform(b_ob_matrix));
- Transform dofmat = get_transform(b_dof_object.matrix_world());
- float3 view_dir = normalize(transform_get_column(&obmat, 2));
- float3 dof_dir = transform_get_column(&obmat, 3) - transform_get_column(&dofmat, 3);
- return fabsf(dot(view_dir, dof_dir));
+ BL::Object b_dof_object = b_camera.dof_object();
+
+ if (!b_dof_object)
+ return b_camera.dof_distance();
+
+ /* for dof object, return distance along camera Z direction */
+ BL::Array<float, 16> b_ob_matrix;
+ b_engine.camera_model_matrix(b_ob, bcam->use_spherical_stereo, b_ob_matrix);
+ Transform obmat = transform_clear_scale(get_transform(b_ob_matrix));
+ Transform dofmat = get_transform(b_dof_object.matrix_world());
+ float3 view_dir = normalize(transform_get_column(&obmat, 2));
+ float3 dof_dir = transform_get_column(&obmat, 3) - transform_get_column(&dofmat, 3);
+ return fabsf(dot(view_dir, dof_dir));
}
static void blender_camera_from_object(BlenderCamera *bcam,
- BL::RenderEngine& b_engine,
- BL::Object& b_ob,
+ BL::RenderEngine &b_engine,
+ BL::Object &b_ob,
bool skip_panorama = false)
{
- BL::ID b_ob_data = b_ob.data();
-
- if(b_ob_data.is_a(&RNA_Camera)) {
- BL::Camera b_camera(b_ob_data);
- PointerRNA ccamera = RNA_pointer_get(&b_camera.ptr, "cycles");
-
- bcam->nearclip = b_camera.clip_start();
- bcam->farclip = b_camera.clip_end();
-
- switch(b_camera.type())
- {
- case BL::Camera::type_ORTHO:
- bcam->type = CAMERA_ORTHOGRAPHIC;
- break;
- case BL::Camera::type_PANO:
- if(!skip_panorama)
- bcam->type = CAMERA_PANORAMA;
- else
- bcam->type = CAMERA_PERSPECTIVE;
- break;
- case BL::Camera::type_PERSP:
- default:
- bcam->type = CAMERA_PERSPECTIVE;
- break;
- }
-
- bcam->panorama_type = (PanoramaType)get_enum(ccamera,
- "panorama_type",
- PANORAMA_NUM_TYPES,
- PANORAMA_EQUIRECTANGULAR);
-
- bcam->fisheye_fov = RNA_float_get(&ccamera, "fisheye_fov");
- bcam->fisheye_lens = RNA_float_get(&ccamera, "fisheye_lens");
- bcam->latitude_min = RNA_float_get(&ccamera, "latitude_min");
- bcam->latitude_max = RNA_float_get(&ccamera, "latitude_max");
- bcam->longitude_min = RNA_float_get(&ccamera, "longitude_min");
- bcam->longitude_max = RNA_float_get(&ccamera, "longitude_max");
-
- bcam->interocular_distance = b_camera.stereo().interocular_distance();
- if(b_camera.stereo().convergence_mode() == BL::CameraStereoData::convergence_mode_PARALLEL) {
- bcam->convergence_distance = FLT_MAX;
- }
- else {
- bcam->convergence_distance = b_camera.stereo().convergence_distance();
- }
- bcam->use_spherical_stereo = b_engine.use_spherical_stereo(b_ob);
-
- bcam->use_pole_merge = b_camera.stereo().use_pole_merge();
- bcam->pole_merge_angle_from = b_camera.stereo().pole_merge_angle_from();
- bcam->pole_merge_angle_to = b_camera.stereo().pole_merge_angle_to();
-
- bcam->ortho_scale = b_camera.ortho_scale();
-
- bcam->lens = b_camera.lens();
-
- /* allow f/stop number to change aperture_size but still
- * give manual control over aperture radius */
- int aperture_type = get_enum(ccamera, "aperture_type");
-
- if(aperture_type == 1) {
- float fstop = RNA_float_get(&ccamera, "aperture_fstop");
- fstop = max(fstop, 1e-5f);
-
- if(bcam->type == CAMERA_ORTHOGRAPHIC)
- bcam->aperturesize = 1.0f/(2.0f*fstop);
- else
- bcam->aperturesize = (bcam->lens*1e-3f)/(2.0f*fstop);
- }
- else
- bcam->aperturesize = RNA_float_get(&ccamera, "aperture_size");
-
- bcam->apertureblades = RNA_int_get(&ccamera, "aperture_blades");
- bcam->aperturerotation = RNA_float_get(&ccamera, "aperture_rotation");
- bcam->focaldistance = blender_camera_focal_distance(b_engine, b_ob, b_camera, bcam);
- bcam->aperture_ratio = RNA_float_get(&ccamera, "aperture_ratio");
-
- bcam->shift.x = b_engine.camera_shift_x(b_ob, bcam->use_spherical_stereo);
- bcam->shift.y = b_camera.shift_y();
-
- bcam->sensor_width = b_camera.sensor_width();
- bcam->sensor_height = b_camera.sensor_height();
-
- if(b_camera.sensor_fit() == BL::Camera::sensor_fit_AUTO)
- bcam->sensor_fit = BlenderCamera::AUTO;
- else if(b_camera.sensor_fit() == BL::Camera::sensor_fit_HORIZONTAL)
- bcam->sensor_fit = BlenderCamera::HORIZONTAL;
- else
- bcam->sensor_fit = BlenderCamera::VERTICAL;
- }
- else if(b_ob_data.is_a(&RNA_Light)) {
- /* Can also look through spot light. */
- BL::SpotLight b_light(b_ob_data);
- float lens = 16.0f / tanf(b_light.spot_size() * 0.5f);
- if (lens > 0.0f) {
- bcam->lens = lens;
- }
- }
-
- bcam->motion_steps = object_motion_steps(b_ob, b_ob);
+ BL::ID b_ob_data = b_ob.data();
+
+ if (b_ob_data.is_a(&RNA_Camera)) {
+ BL::Camera b_camera(b_ob_data);
+ PointerRNA ccamera = RNA_pointer_get(&b_camera.ptr, "cycles");
+
+ bcam->nearclip = b_camera.clip_start();
+ bcam->farclip = b_camera.clip_end();
+
+ switch (b_camera.type()) {
+ case BL::Camera::type_ORTHO:
+ bcam->type = CAMERA_ORTHOGRAPHIC;
+ break;
+ case BL::Camera::type_PANO:
+ if (!skip_panorama)
+ bcam->type = CAMERA_PANORAMA;
+ else
+ bcam->type = CAMERA_PERSPECTIVE;
+ break;
+ case BL::Camera::type_PERSP:
+ default:
+ bcam->type = CAMERA_PERSPECTIVE;
+ break;
+ }
+
+ bcam->panorama_type = (PanoramaType)get_enum(
+ ccamera, "panorama_type", PANORAMA_NUM_TYPES, PANORAMA_EQUIRECTANGULAR);
+
+ bcam->fisheye_fov = RNA_float_get(&ccamera, "fisheye_fov");
+ bcam->fisheye_lens = RNA_float_get(&ccamera, "fisheye_lens");
+ bcam->latitude_min = RNA_float_get(&ccamera, "latitude_min");
+ bcam->latitude_max = RNA_float_get(&ccamera, "latitude_max");
+ bcam->longitude_min = RNA_float_get(&ccamera, "longitude_min");
+ bcam->longitude_max = RNA_float_get(&ccamera, "longitude_max");
+
+ bcam->interocular_distance = b_camera.stereo().interocular_distance();
+ if (b_camera.stereo().convergence_mode() == BL::CameraStereoData::convergence_mode_PARALLEL) {
+ bcam->convergence_distance = FLT_MAX;
+ }
+ else {
+ bcam->convergence_distance = b_camera.stereo().convergence_distance();
+ }
+ bcam->use_spherical_stereo = b_engine.use_spherical_stereo(b_ob);
+
+ bcam->use_pole_merge = b_camera.stereo().use_pole_merge();
+ bcam->pole_merge_angle_from = b_camera.stereo().pole_merge_angle_from();
+ bcam->pole_merge_angle_to = b_camera.stereo().pole_merge_angle_to();
+
+ bcam->ortho_scale = b_camera.ortho_scale();
+
+ bcam->lens = b_camera.lens();
+
+ /* allow f/stop number to change aperture_size but still
+ * give manual control over aperture radius */
+ int aperture_type = get_enum(ccamera, "aperture_type");
+
+ if (aperture_type == 1) {
+ float fstop = RNA_float_get(&ccamera, "aperture_fstop");
+ fstop = max(fstop, 1e-5f);
+
+ if (bcam->type == CAMERA_ORTHOGRAPHIC)
+ bcam->aperturesize = 1.0f / (2.0f * fstop);
+ else
+ bcam->aperturesize = (bcam->lens * 1e-3f) / (2.0f * fstop);
+ }
+ else
+ bcam->aperturesize = RNA_float_get(&ccamera, "aperture_size");
+
+ bcam->apertureblades = RNA_int_get(&ccamera, "aperture_blades");
+ bcam->aperturerotation = RNA_float_get(&ccamera, "aperture_rotation");
+ bcam->focaldistance = blender_camera_focal_distance(b_engine, b_ob, b_camera, bcam);
+ bcam->aperture_ratio = RNA_float_get(&ccamera, "aperture_ratio");
+
+ bcam->shift.x = b_engine.camera_shift_x(b_ob, bcam->use_spherical_stereo);
+ bcam->shift.y = b_camera.shift_y();
+
+ bcam->sensor_width = b_camera.sensor_width();
+ bcam->sensor_height = b_camera.sensor_height();
+
+ if (b_camera.sensor_fit() == BL::Camera::sensor_fit_AUTO)
+ bcam->sensor_fit = BlenderCamera::AUTO;
+ else if (b_camera.sensor_fit() == BL::Camera::sensor_fit_HORIZONTAL)
+ bcam->sensor_fit = BlenderCamera::HORIZONTAL;
+ else
+ bcam->sensor_fit = BlenderCamera::VERTICAL;
+ }
+ else if (b_ob_data.is_a(&RNA_Light)) {
+ /* Can also look through spot light. */
+ BL::SpotLight b_light(b_ob_data);
+ float lens = 16.0f / tanf(b_light.spot_size() * 0.5f);
+ if (lens > 0.0f) {
+ bcam->lens = lens;
+ }
+ }
+
+ bcam->motion_steps = object_motion_steps(b_ob, b_ob);
}
-static Transform blender_camera_matrix(const Transform& tfm,
+static Transform blender_camera_matrix(const Transform &tfm,
const CameraType type,
const PanoramaType panorama_type)
{
- Transform result;
-
- if(type == CAMERA_PANORAMA) {
- if(panorama_type == PANORAMA_MIRRORBALL) {
- /* Mirror ball camera is looking into the negative Y direction
- * which matches texture mirror ball mapping.
- */
- result = tfm *
- make_transform(1.0f, 0.0f, 0.0f, 0.0f,
- 0.0f, 0.0f, 1.0f, 0.0f,
- 0.0f, 1.0f, 0.0f, 0.0f);
- }
- else {
- /* Make it so environment camera needs to be pointed in the direction
- * of the positive x-axis to match an environment texture, this way
- * it is looking at the center of the texture
- */
- result = tfm *
- make_transform( 0.0f, -1.0f, 0.0f, 0.0f,
- 0.0f, 0.0f, 1.0f, 0.0f,
- -1.0f, 0.0f, 0.0f, 0.0f);
- }
- }
- else {
- /* note the blender camera points along the negative z-axis */
- result = tfm * transform_scale(1.0f, 1.0f, -1.0f);
- }
-
- return transform_clear_scale(result);
+ Transform result;
+
+ if (type == CAMERA_PANORAMA) {
+ if (panorama_type == PANORAMA_MIRRORBALL) {
+ /* Mirror ball camera is looking into the negative Y direction
+ * which matches texture mirror ball mapping.
+ */
+ result = tfm * make_transform(
+ 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f);
+ }
+ else {
+ /* Make it so environment camera needs to be pointed in the direction
+ * of the positive x-axis to match an environment texture, this way
+ * it is looking at the center of the texture
+ */
+ result = tfm * make_transform(
+ 0.0f, -1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, -1.0f, 0.0f, 0.0f, 0.0f);
+ }
+ }
+ else {
+ /* note the blender camera points along the negative z-axis */
+ result = tfm * transform_scale(1.0f, 1.0f, -1.0f);
+ }
+
+ return transform_clear_scale(result);
}
static void blender_camera_viewplane(BlenderCamera *bcam,
- int width, int height,
+ int width,
+ int height,
BoundBox2D *viewplane,
float *aspectratio,
float *sensor_size)
{
- /* dimensions */
- float xratio = (float)width*bcam->pixelaspect.x;
- float yratio = (float)height*bcam->pixelaspect.y;
-
- /* compute x/y aspect and ratio */
- float xaspect, yaspect;
- bool horizontal_fit;
-
- /* sensor fitting */
- if(bcam->sensor_fit == BlenderCamera::AUTO) {
- horizontal_fit = (xratio > yratio);
- if(sensor_size != NULL) {
- *sensor_size = bcam->sensor_width;
- }
- }
- else if(bcam->sensor_fit == BlenderCamera::HORIZONTAL) {
- horizontal_fit = true;
- if(sensor_size != NULL) {
- *sensor_size = bcam->sensor_width;
- }
- }
- else {
- horizontal_fit = false;
- if(sensor_size != NULL) {
- *sensor_size = bcam->sensor_height;
- }
- }
-
- if(horizontal_fit) {
- if(aspectratio != NULL) {
- *aspectratio = xratio/yratio;
- }
- xaspect = *aspectratio;
- yaspect = 1.0f;
- }
- else {
- if(aspectratio != NULL) {
- *aspectratio = yratio/xratio;
- }
- xaspect = 1.0f;
- yaspect = *aspectratio;
- }
-
- /* modify aspect for orthographic scale */
- if(bcam->type == CAMERA_ORTHOGRAPHIC) {
- xaspect = xaspect*bcam->ortho_scale/(*aspectratio*2.0f);
- yaspect = yaspect*bcam->ortho_scale/(*aspectratio*2.0f);
- if(aspectratio != NULL) {
- *aspectratio = bcam->ortho_scale/2.0f;
- }
- }
-
- if(bcam->type == CAMERA_PANORAMA) {
- /* set viewplane */
- if(viewplane != NULL) {
- *viewplane = bcam->pano_viewplane;
- }
- }
- else {
- /* set viewplane */
- if(viewplane != NULL) {
- viewplane->left = -xaspect;
- viewplane->right = xaspect;
- viewplane->bottom = -yaspect;
- viewplane->top = yaspect;
-
- /* zoom for 3d camera view */
- *viewplane = (*viewplane) * bcam->zoom;
-
- /* modify viewplane with camera shift and 3d camera view offset */
- float dx = 2.0f*(*aspectratio*bcam->shift.x + bcam->offset.x*xaspect*2.0f);
- float dy = 2.0f*(*aspectratio*bcam->shift.y + bcam->offset.y*yaspect*2.0f);
-
- viewplane->left += dx;
- viewplane->right += dx;
- viewplane->bottom += dy;
- viewplane->top += dy;
- }
- }
+ /* dimensions */
+ float xratio = (float)width * bcam->pixelaspect.x;
+ float yratio = (float)height * bcam->pixelaspect.y;
+
+ /* compute x/y aspect and ratio */
+ float xaspect, yaspect;
+ bool horizontal_fit;
+
+ /* sensor fitting */
+ if (bcam->sensor_fit == BlenderCamera::AUTO) {
+ horizontal_fit = (xratio > yratio);
+ if (sensor_size != NULL) {
+ *sensor_size = bcam->sensor_width;
+ }
+ }
+ else if (bcam->sensor_fit == BlenderCamera::HORIZONTAL) {
+ horizontal_fit = true;
+ if (sensor_size != NULL) {
+ *sensor_size = bcam->sensor_width;
+ }
+ }
+ else {
+ horizontal_fit = false;
+ if (sensor_size != NULL) {
+ *sensor_size = bcam->sensor_height;
+ }
+ }
+
+ if (horizontal_fit) {
+ if (aspectratio != NULL) {
+ *aspectratio = xratio / yratio;
+ }
+ xaspect = *aspectratio;
+ yaspect = 1.0f;
+ }
+ else {
+ if (aspectratio != NULL) {
+ *aspectratio = yratio / xratio;
+ }
+ xaspect = 1.0f;
+ yaspect = *aspectratio;
+ }
+
+ /* modify aspect for orthographic scale */
+ if (bcam->type == CAMERA_ORTHOGRAPHIC) {
+ xaspect = xaspect * bcam->ortho_scale / (*aspectratio * 2.0f);
+ yaspect = yaspect * bcam->ortho_scale / (*aspectratio * 2.0f);
+ if (aspectratio != NULL) {
+ *aspectratio = bcam->ortho_scale / 2.0f;
+ }
+ }
+
+ if (bcam->type == CAMERA_PANORAMA) {
+ /* set viewplane */
+ if (viewplane != NULL) {
+ *viewplane = bcam->pano_viewplane;
+ }
+ }
+ else {
+ /* set viewplane */
+ if (viewplane != NULL) {
+ viewplane->left = -xaspect;
+ viewplane->right = xaspect;
+ viewplane->bottom = -yaspect;
+ viewplane->top = yaspect;
+
+ /* zoom for 3d camera view */
+ *viewplane = (*viewplane) * bcam->zoom;
+
+ /* modify viewplane with camera shift and 3d camera view offset */
+ float dx = 2.0f * (*aspectratio * bcam->shift.x + bcam->offset.x * xaspect * 2.0f);
+ float dy = 2.0f * (*aspectratio * bcam->shift.y + bcam->offset.y * yaspect * 2.0f);
+
+ viewplane->left += dx;
+ viewplane->right += dx;
+ viewplane->bottom += dy;
+ viewplane->top += dy;
+ }
+ }
}
static void blender_camera_sync(Camera *cam,
BlenderCamera *bcam,
- int width, int height,
+ int width,
+ int height,
const char *viewname,
PointerRNA *cscene)
{
- /* copy camera to compare later */
- Camera prevcam = *cam;
- float aspectratio, sensor_size;
-
- /* viewplane */
- blender_camera_viewplane(bcam, width, height,
- &cam->viewplane, &aspectratio, &sensor_size);
-
- cam->width = bcam->full_width;
- cam->height = bcam->full_height;
-
- cam->full_width = width;
- cam->full_height = height;
-
- /* panorama sensor */
- if(bcam->type == CAMERA_PANORAMA && bcam->panorama_type == PANORAMA_FISHEYE_EQUISOLID) {
- float fit_xratio = (float)bcam->full_width*bcam->pixelaspect.x;
- float fit_yratio = (float)bcam->full_height*bcam->pixelaspect.y;
- bool horizontal_fit;
- float sensor_size;
-
- if(bcam->sensor_fit == BlenderCamera::AUTO) {
- horizontal_fit = (fit_xratio > fit_yratio);
- sensor_size = bcam->sensor_width;
- }
- else if(bcam->sensor_fit == BlenderCamera::HORIZONTAL) {
- horizontal_fit = true;
- sensor_size = bcam->sensor_width;
- }
- else { /* vertical */
- horizontal_fit = false;
- sensor_size = bcam->sensor_height;
- }
-
- if(horizontal_fit) {
- cam->sensorwidth = sensor_size;
- cam->sensorheight = sensor_size * fit_yratio / fit_xratio;
- }
- else {
- cam->sensorwidth = sensor_size * fit_xratio / fit_yratio;
- cam->sensorheight = sensor_size;
- }
- }
-
- /* clipping distances */
- cam->nearclip = bcam->nearclip;
- cam->farclip = bcam->farclip;
-
- /* type */
- cam->type = bcam->type;
-
- /* panorama */
- cam->panorama_type = bcam->panorama_type;
- cam->fisheye_fov = bcam->fisheye_fov;
- cam->fisheye_lens = bcam->fisheye_lens;
- cam->latitude_min = bcam->latitude_min;
- cam->latitude_max = bcam->latitude_max;
-
- cam->longitude_min = bcam->longitude_min;
- cam->longitude_max = bcam->longitude_max;
-
- /* panorama stereo */
- cam->interocular_distance = bcam->interocular_distance;
- cam->convergence_distance = bcam->convergence_distance;
- cam->use_spherical_stereo = bcam->use_spherical_stereo;
-
- if(cam->use_spherical_stereo) {
- if(strcmp(viewname, "left") == 0)
- cam->stereo_eye = Camera::STEREO_LEFT;
- else if(strcmp(viewname, "right") == 0)
- cam->stereo_eye = Camera::STEREO_RIGHT;
- else
- cam->stereo_eye = Camera::STEREO_NONE;
- }
-
- cam->use_pole_merge = bcam->use_pole_merge;
- cam->pole_merge_angle_from = bcam->pole_merge_angle_from;
- cam->pole_merge_angle_to = bcam->pole_merge_angle_to;
-
- /* anamorphic lens bokeh */
- cam->aperture_ratio = bcam->aperture_ratio;
-
- /* perspective */
- cam->fov = 2.0f * atanf((0.5f * sensor_size) / bcam->lens / aspectratio);
- cam->focaldistance = bcam->focaldistance;
- cam->aperturesize = bcam->aperturesize;
- cam->blades = bcam->apertureblades;
- cam->bladesrotation = bcam->aperturerotation;
-
- /* transform */
- cam->matrix = blender_camera_matrix(bcam->matrix,
- bcam->type,
- bcam->panorama_type);
- cam->motion.clear();
- cam->motion.resize(bcam->motion_steps, cam->matrix);
- cam->use_perspective_motion = false;
- cam->shuttertime = bcam->shuttertime;
- cam->fov_pre = cam->fov;
- cam->fov_post = cam->fov;
- cam->motion_position = bcam->motion_position;
-
- cam->rolling_shutter_type = bcam->rolling_shutter_type;
- cam->rolling_shutter_duration = bcam->rolling_shutter_duration;
-
- cam->shutter_curve = bcam->shutter_curve;
-
- /* border */
- cam->border = bcam->border;
- cam->viewport_camera_border = bcam->viewport_camera_border;
-
- bcam->offscreen_dicing_scale = RNA_float_get(cscene, "offscreen_dicing_scale");
- cam->offscreen_dicing_scale = bcam->offscreen_dicing_scale;
-
- /* set update flag */
- if(cam->modified(prevcam))
- cam->tag_update();
+ /* copy camera to compare later */
+ Camera prevcam = *cam;
+ float aspectratio, sensor_size;
+
+ /* viewplane */
+ blender_camera_viewplane(bcam, width, height, &cam->viewplane, &aspectratio, &sensor_size);
+
+ cam->width = bcam->full_width;
+ cam->height = bcam->full_height;
+
+ cam->full_width = width;
+ cam->full_height = height;
+
+ /* panorama sensor */
+ if (bcam->type == CAMERA_PANORAMA && bcam->panorama_type == PANORAMA_FISHEYE_EQUISOLID) {
+ float fit_xratio = (float)bcam->full_width * bcam->pixelaspect.x;
+ float fit_yratio = (float)bcam->full_height * bcam->pixelaspect.y;
+ bool horizontal_fit;
+ float sensor_size;
+
+ if (bcam->sensor_fit == BlenderCamera::AUTO) {
+ horizontal_fit = (fit_xratio > fit_yratio);
+ sensor_size = bcam->sensor_width;
+ }
+ else if (bcam->sensor_fit == BlenderCamera::HORIZONTAL) {
+ horizontal_fit = true;
+ sensor_size = bcam->sensor_width;
+ }
+ else { /* vertical */
+ horizontal_fit = false;
+ sensor_size = bcam->sensor_height;
+ }
+
+ if (horizontal_fit) {
+ cam->sensorwidth = sensor_size;
+ cam->sensorheight = sensor_size * fit_yratio / fit_xratio;
+ }
+ else {
+ cam->sensorwidth = sensor_size * fit_xratio / fit_yratio;
+ cam->sensorheight = sensor_size;
+ }
+ }
+
+ /* clipping distances */
+ cam->nearclip = bcam->nearclip;
+ cam->farclip = bcam->farclip;
+
+ /* type */
+ cam->type = bcam->type;
+
+ /* panorama */
+ cam->panorama_type = bcam->panorama_type;
+ cam->fisheye_fov = bcam->fisheye_fov;
+ cam->fisheye_lens = bcam->fisheye_lens;
+ cam->latitude_min = bcam->latitude_min;
+ cam->latitude_max = bcam->latitude_max;
+
+ cam->longitude_min = bcam->longitude_min;
+ cam->longitude_max = bcam->longitude_max;
+
+ /* panorama stereo */
+ cam->interocular_distance = bcam->interocular_distance;
+ cam->convergence_distance = bcam->convergence_distance;
+ cam->use_spherical_stereo = bcam->use_spherical_stereo;
+
+ if (cam->use_spherical_stereo) {
+ if (strcmp(viewname, "left") == 0)
+ cam->stereo_eye = Camera::STEREO_LEFT;
+ else if (strcmp(viewname, "right") == 0)
+ cam->stereo_eye = Camera::STEREO_RIGHT;
+ else
+ cam->stereo_eye = Camera::STEREO_NONE;
+ }
+
+ cam->use_pole_merge = bcam->use_pole_merge;
+ cam->pole_merge_angle_from = bcam->pole_merge_angle_from;
+ cam->pole_merge_angle_to = bcam->pole_merge_angle_to;
+
+ /* anamorphic lens bokeh */
+ cam->aperture_ratio = bcam->aperture_ratio;
+
+ /* perspective */
+ cam->fov = 2.0f * atanf((0.5f * sensor_size) / bcam->lens / aspectratio);
+ cam->focaldistance = bcam->focaldistance;
+ cam->aperturesize = bcam->aperturesize;
+ cam->blades = bcam->apertureblades;
+ cam->bladesrotation = bcam->aperturerotation;
+
+ /* transform */
+ cam->matrix = blender_camera_matrix(bcam->matrix, bcam->type, bcam->panorama_type);
+ cam->motion.clear();
+ cam->motion.resize(bcam->motion_steps, cam->matrix);
+ cam->use_perspective_motion = false;
+ cam->shuttertime = bcam->shuttertime;
+ cam->fov_pre = cam->fov;
+ cam->fov_post = cam->fov;
+ cam->motion_position = bcam->motion_position;
+
+ cam->rolling_shutter_type = bcam->rolling_shutter_type;
+ cam->rolling_shutter_duration = bcam->rolling_shutter_duration;
+
+ cam->shutter_curve = bcam->shutter_curve;
+
+ /* border */
+ cam->border = bcam->border;
+ cam->viewport_camera_border = bcam->viewport_camera_border;
+
+ bcam->offscreen_dicing_scale = RNA_float_get(cscene, "offscreen_dicing_scale");
+ cam->offscreen_dicing_scale = bcam->offscreen_dicing_scale;
+
+ /* set update flag */
+ if (cam->modified(prevcam))
+ cam->tag_update();
}
/* Sync Render Camera */
-void BlenderSync::sync_camera(BL::RenderSettings& b_render,
- BL::Object& b_override,
- int width, int height,
+void BlenderSync::sync_camera(BL::RenderSettings &b_render,
+ BL::Object &b_override,
+ int width,
+ int height,
const char *viewname)
{
- BlenderCamera bcam;
- blender_camera_init(&bcam, b_render);
-
- /* pixel aspect */
- bcam.pixelaspect.x = b_render.pixel_aspect_x();
- bcam.pixelaspect.y = b_render.pixel_aspect_y();
- bcam.shuttertime = b_render.motion_blur_shutter();
-
- BL::CurveMapping b_shutter_curve(b_render.motion_blur_shutter_curve());
- curvemapping_to_array(b_shutter_curve, bcam.shutter_curve, RAMP_TABLE_SIZE);
-
- PointerRNA cscene = RNA_pointer_get(&b_scene.ptr, "cycles");
- bcam.motion_position =
- (Camera::MotionPosition)get_enum(cscene,
- "motion_blur_position",
- Camera::MOTION_NUM_POSITIONS,
- Camera::MOTION_POSITION_CENTER);
- bcam.rolling_shutter_type =
- (Camera::RollingShutterType)get_enum(cscene,
- "rolling_shutter_type",
- Camera::ROLLING_SHUTTER_NUM_TYPES,
- Camera::ROLLING_SHUTTER_NONE);
- bcam.rolling_shutter_duration = RNA_float_get(&cscene, "rolling_shutter_duration");
-
- /* border */
- if(b_render.use_border()) {
- bcam.border.left = b_render.border_min_x();
- bcam.border.right = b_render.border_max_x();
- bcam.border.bottom = b_render.border_min_y();
- bcam.border.top = b_render.border_max_y();
- }
-
- /* camera object */
- BL::Object b_ob = b_scene.camera();
-
- if(b_override)
- b_ob = b_override;
-
- if(b_ob) {
- BL::Array<float, 16> b_ob_matrix;
- blender_camera_from_object(&bcam, b_engine, b_ob);
- b_engine.camera_model_matrix(b_ob, bcam.use_spherical_stereo, b_ob_matrix);
- bcam.matrix = get_transform(b_ob_matrix);
- }
-
- /* sync */
- Camera *cam = scene->camera;
- blender_camera_sync(cam, &bcam, width, height, viewname, &cscene);
-
- /* dicing camera */
- b_ob = BL::Object(RNA_pointer_get(&cscene, "dicing_camera"));
- if(b_ob) {
- BL::Array<float, 16> b_ob_matrix;
- blender_camera_from_object(&bcam, b_engine, b_ob);
- b_engine.camera_model_matrix(b_ob, bcam.use_spherical_stereo, b_ob_matrix);
- bcam.matrix = get_transform(b_ob_matrix);
-
- blender_camera_sync(scene->dicing_camera, &bcam, width, height, viewname, &cscene);
- }
- else {
- *scene->dicing_camera = *cam;
- }
+ BlenderCamera bcam;
+ blender_camera_init(&bcam, b_render);
+
+ /* pixel aspect */
+ bcam.pixelaspect.x = b_render.pixel_aspect_x();
+ bcam.pixelaspect.y = b_render.pixel_aspect_y();
+ bcam.shuttertime = b_render.motion_blur_shutter();
+
+ BL::CurveMapping b_shutter_curve(b_render.motion_blur_shutter_curve());
+ curvemapping_to_array(b_shutter_curve, bcam.shutter_curve, RAMP_TABLE_SIZE);
+
+ PointerRNA cscene = RNA_pointer_get(&b_scene.ptr, "cycles");
+ bcam.motion_position = (Camera::MotionPosition)get_enum(cscene,
+ "motion_blur_position",
+ Camera::MOTION_NUM_POSITIONS,
+ Camera::MOTION_POSITION_CENTER);
+ bcam.rolling_shutter_type = (Camera::RollingShutterType)get_enum(
+ cscene,
+ "rolling_shutter_type",
+ Camera::ROLLING_SHUTTER_NUM_TYPES,
+ Camera::ROLLING_SHUTTER_NONE);
+ bcam.rolling_shutter_duration = RNA_float_get(&cscene, "rolling_shutter_duration");
+
+ /* border */
+ if (b_render.use_border()) {
+ bcam.border.left = b_render.border_min_x();
+ bcam.border.right = b_render.border_max_x();
+ bcam.border.bottom = b_render.border_min_y();
+ bcam.border.top = b_render.border_max_y();
+ }
+
+ /* camera object */
+ BL::Object b_ob = b_scene.camera();
+
+ if (b_override)
+ b_ob = b_override;
+
+ if (b_ob) {
+ BL::Array<float, 16> b_ob_matrix;
+ blender_camera_from_object(&bcam, b_engine, b_ob);
+ b_engine.camera_model_matrix(b_ob, bcam.use_spherical_stereo, b_ob_matrix);
+ bcam.matrix = get_transform(b_ob_matrix);
+ }
+
+ /* sync */
+ Camera *cam = scene->camera;
+ blender_camera_sync(cam, &bcam, width, height, viewname, &cscene);
+
+ /* dicing camera */
+ b_ob = BL::Object(RNA_pointer_get(&cscene, "dicing_camera"));
+ if (b_ob) {
+ BL::Array<float, 16> b_ob_matrix;
+ blender_camera_from_object(&bcam, b_engine, b_ob);
+ b_engine.camera_model_matrix(b_ob, bcam.use_spherical_stereo, b_ob_matrix);
+ bcam.matrix = get_transform(b_ob_matrix);
+
+ blender_camera_sync(scene->dicing_camera, &bcam, width, height, viewname, &cscene);
+ }
+ else {
+ *scene->dicing_camera = *cam;
+ }
}
-void BlenderSync::sync_camera_motion(BL::RenderSettings& b_render,
- BL::Object& b_ob,
- int width, int height,
- float motion_time)
+void BlenderSync::sync_camera_motion(
+ BL::RenderSettings &b_render, BL::Object &b_ob, int width, int height, float motion_time)
{
- if(!b_ob)
- return;
-
- Camera *cam = scene->camera;
- BL::Array<float, 16> b_ob_matrix;
- b_engine.camera_model_matrix(b_ob, cam->use_spherical_stereo, b_ob_matrix);
- Transform tfm = get_transform(b_ob_matrix);
- tfm = blender_camera_matrix(tfm, cam->type, cam->panorama_type);
-
- if(motion_time == 0.0f) {
- /* When motion blur is not centered in frame, cam->matrix gets reset. */
- cam->matrix = tfm;
- }
-
- /* Set transform in motion array. */
- int motion_step = cam->motion_step(motion_time);
- if(motion_step >= 0) {
- cam->motion[motion_step] = tfm;
- }
-
- if(cam->type == CAMERA_PERSPECTIVE) {
- BlenderCamera bcam;
- float aspectratio, sensor_size;
- blender_camera_init(&bcam, b_render);
-
- /* TODO(sergey): Consider making it a part of blender_camera_init(). */
- bcam.pixelaspect.x = b_render.pixel_aspect_x();
- bcam.pixelaspect.y = b_render.pixel_aspect_y();
-
- blender_camera_from_object(&bcam, b_engine, b_ob);
- blender_camera_viewplane(&bcam,
- width, height,
- NULL,
- &aspectratio,
- &sensor_size);
- /* TODO(sergey): De-duplicate calculation with camera sync. */
- float fov = 2.0f * atanf((0.5f * sensor_size) / bcam.lens / aspectratio);
- if(fov != cam->fov) {
- VLOG(1) << "Camera " << b_ob.name() << " FOV change detected.";
- if(motion_time == 0.0f) {
- cam->fov = fov;
- }
- else if(motion_time == -1.0f) {
- cam->fov_pre = fov;
- cam->use_perspective_motion = true;
- }
- else if(motion_time == 1.0f) {
- cam->fov_post = fov;
- cam->use_perspective_motion = true;
- }
- }
- }
+ if (!b_ob)
+ return;
+
+ Camera *cam = scene->camera;
+ BL::Array<float, 16> b_ob_matrix;
+ b_engine.camera_model_matrix(b_ob, cam->use_spherical_stereo, b_ob_matrix);
+ Transform tfm = get_transform(b_ob_matrix);
+ tfm = blender_camera_matrix(tfm, cam->type, cam->panorama_type);
+
+ if (motion_time == 0.0f) {
+ /* When motion blur is not centered in frame, cam->matrix gets reset. */
+ cam->matrix = tfm;
+ }
+
+ /* Set transform in motion array. */
+ int motion_step = cam->motion_step(motion_time);
+ if (motion_step >= 0) {
+ cam->motion[motion_step] = tfm;
+ }
+
+ if (cam->type == CAMERA_PERSPECTIVE) {
+ BlenderCamera bcam;
+ float aspectratio, sensor_size;
+ blender_camera_init(&bcam, b_render);
+
+ /* TODO(sergey): Consider making it a part of blender_camera_init(). */
+ bcam.pixelaspect.x = b_render.pixel_aspect_x();
+ bcam.pixelaspect.y = b_render.pixel_aspect_y();
+
+ blender_camera_from_object(&bcam, b_engine, b_ob);
+ blender_camera_viewplane(&bcam, width, height, NULL, &aspectratio, &sensor_size);
+ /* TODO(sergey): De-duplicate calculation with camera sync. */
+ float fov = 2.0f * atanf((0.5f * sensor_size) / bcam.lens / aspectratio);
+ if (fov != cam->fov) {
+ VLOG(1) << "Camera " << b_ob.name() << " FOV change detected.";
+ if (motion_time == 0.0f) {
+ cam->fov = fov;
+ }
+ else if (motion_time == -1.0f) {
+ cam->fov_pre = fov;
+ cam->use_perspective_motion = true;
+ }
+ else if (motion_time == 1.0f) {
+ cam->fov_post = fov;
+ cam->use_perspective_motion = true;
+ }
+ }
+ }
}
/* Sync 3D View Camera */
-static void blender_camera_view_subset(BL::RenderEngine& b_engine,
- BL::RenderSettings& b_render,
- BL::Scene& b_scene,
- BL::Object& b_ob,
- BL::SpaceView3D& b_v3d,
- BL::RegionView3D& b_rv3d,
- int width, int height,
+static void blender_camera_view_subset(BL::RenderEngine &b_engine,
+ BL::RenderSettings &b_render,
+ BL::Scene &b_scene,
+ BL::Object &b_ob,
+ BL::SpaceView3D &b_v3d,
+ BL::RegionView3D &b_rv3d,
+ int width,
+ int height,
BoundBox2D *view_box,
BoundBox2D *cam_box);
static void blender_camera_from_view(BlenderCamera *bcam,
- BL::RenderEngine& b_engine,
- BL::Scene& b_scene,
- BL::SpaceView3D& b_v3d,
- BL::RegionView3D& b_rv3d,
- int width, int height,
+ BL::RenderEngine &b_engine,
+ BL::Scene &b_scene,
+ BL::SpaceView3D &b_v3d,
+ BL::RegionView3D &b_rv3d,
+ int width,
+ int height,
bool skip_panorama = false)
{
- /* 3d view parameters */
- bcam->nearclip = b_v3d.clip_start();
- bcam->farclip = b_v3d.clip_end();
- bcam->lens = b_v3d.lens();
- bcam->shuttertime = b_scene.render().motion_blur_shutter();
-
- BL::CurveMapping b_shutter_curve(b_scene.render().motion_blur_shutter_curve());
- curvemapping_to_array(b_shutter_curve, bcam->shutter_curve, RAMP_TABLE_SIZE);
-
- if(b_rv3d.view_perspective() == BL::RegionView3D::view_perspective_CAMERA) {
- /* camera view */
- BL::Object b_ob = (b_v3d.use_local_camera())? b_v3d.camera(): b_scene.camera();
-
- if(b_ob) {
- blender_camera_from_object(bcam, b_engine, b_ob, skip_panorama);
-
- if(!skip_panorama && bcam->type == CAMERA_PANORAMA) {
- /* in panorama camera view, we map viewplane to camera border */
- BoundBox2D view_box, cam_box;
-
- BL::RenderSettings b_render_settings(b_scene.render());
- blender_camera_view_subset(b_engine,
- b_render_settings,
- b_scene,
- b_ob,
- b_v3d,
- b_rv3d,
- width, height,
- &view_box,
- &cam_box);
-
- bcam->pano_viewplane = view_box.make_relative_to(cam_box);
- }
- else {
- /* magic zoom formula */
- bcam->zoom = (float)b_rv3d.view_camera_zoom();
- bcam->zoom = (1.41421f + bcam->zoom/50.0f);
- bcam->zoom *= bcam->zoom;
- bcam->zoom = 2.0f/bcam->zoom;
-
- /* offset */
- bcam->offset = get_float2(b_rv3d.view_camera_offset());
- }
- }
- }
- else if(b_rv3d.view_perspective() == BL::RegionView3D::view_perspective_ORTHO) {
- /* orthographic view */
- bcam->farclip *= 0.5f;
- bcam->nearclip = -bcam->farclip;
-
- float sensor_size;
- if(bcam->sensor_fit == BlenderCamera::VERTICAL)
- sensor_size = bcam->sensor_height;
- else
- sensor_size = bcam->sensor_width;
-
- bcam->type = CAMERA_ORTHOGRAPHIC;
- bcam->ortho_scale = b_rv3d.view_distance() * sensor_size / b_v3d.lens();
- }
-
- bcam->zoom *= 2.0f;
-
- /* 3d view transform */
- bcam->matrix = transform_inverse(get_transform(b_rv3d.view_matrix()));
+ /* 3d view parameters */
+ bcam->nearclip = b_v3d.clip_start();
+ bcam->farclip = b_v3d.clip_end();
+ bcam->lens = b_v3d.lens();
+ bcam->shuttertime = b_scene.render().motion_blur_shutter();
+
+ BL::CurveMapping b_shutter_curve(b_scene.render().motion_blur_shutter_curve());
+ curvemapping_to_array(b_shutter_curve, bcam->shutter_curve, RAMP_TABLE_SIZE);
+
+ if (b_rv3d.view_perspective() == BL::RegionView3D::view_perspective_CAMERA) {
+ /* camera view */
+ BL::Object b_ob = (b_v3d.use_local_camera()) ? b_v3d.camera() : b_scene.camera();
+
+ if (b_ob) {
+ blender_camera_from_object(bcam, b_engine, b_ob, skip_panorama);
+
+ if (!skip_panorama && bcam->type == CAMERA_PANORAMA) {
+ /* in panorama camera view, we map viewplane to camera border */
+ BoundBox2D view_box, cam_box;
+
+ BL::RenderSettings b_render_settings(b_scene.render());
+ blender_camera_view_subset(b_engine,
+ b_render_settings,
+ b_scene,
+ b_ob,
+ b_v3d,
+ b_rv3d,
+ width,
+ height,
+ &view_box,
+ &cam_box);
+
+ bcam->pano_viewplane = view_box.make_relative_to(cam_box);
+ }
+ else {
+ /* magic zoom formula */
+ bcam->zoom = (float)b_rv3d.view_camera_zoom();
+ bcam->zoom = (1.41421f + bcam->zoom / 50.0f);
+ bcam->zoom *= bcam->zoom;
+ bcam->zoom = 2.0f / bcam->zoom;
+
+ /* offset */
+ bcam->offset = get_float2(b_rv3d.view_camera_offset());
+ }
+ }
+ }
+ else if (b_rv3d.view_perspective() == BL::RegionView3D::view_perspective_ORTHO) {
+ /* orthographic view */
+ bcam->farclip *= 0.5f;
+ bcam->nearclip = -bcam->farclip;
+
+ float sensor_size;
+ if (bcam->sensor_fit == BlenderCamera::VERTICAL)
+ sensor_size = bcam->sensor_height;
+ else
+ sensor_size = bcam->sensor_width;
+
+ bcam->type = CAMERA_ORTHOGRAPHIC;
+ bcam->ortho_scale = b_rv3d.view_distance() * sensor_size / b_v3d.lens();
+ }
+
+ bcam->zoom *= 2.0f;
+
+ /* 3d view transform */
+ bcam->matrix = transform_inverse(get_transform(b_rv3d.view_matrix()));
}
-static void blender_camera_view_subset(BL::RenderEngine& b_engine,
- BL::RenderSettings& b_render,
- BL::Scene& b_scene,
- BL::Object& b_ob,
- BL::SpaceView3D& b_v3d,
- BL::RegionView3D& b_rv3d,
- int width, int height,
+static void blender_camera_view_subset(BL::RenderEngine &b_engine,
+ BL::RenderSettings &b_render,
+ BL::Scene &b_scene,
+ BL::Object &b_ob,
+ BL::SpaceView3D &b_v3d,
+ BL::RegionView3D &b_rv3d,
+ int width,
+ int height,
BoundBox2D *view_box,
BoundBox2D *cam_box)
{
- BoundBox2D cam, view;
- float view_aspect, cam_aspect, sensor_size;
+ BoundBox2D cam, view;
+ float view_aspect, cam_aspect, sensor_size;
- /* get viewport viewplane */
- BlenderCamera view_bcam;
- blender_camera_init(&view_bcam, b_render);
- blender_camera_from_view(&view_bcam, b_engine, b_scene, b_v3d, b_rv3d, width, height, true);
+ /* get viewport viewplane */
+ BlenderCamera view_bcam;
+ blender_camera_init(&view_bcam, b_render);
+ blender_camera_from_view(&view_bcam, b_engine, b_scene, b_v3d, b_rv3d, width, height, true);
- blender_camera_viewplane(&view_bcam, width, height,
- &view, &view_aspect, &sensor_size);
+ blender_camera_viewplane(&view_bcam, width, height, &view, &view_aspect, &sensor_size);
- /* get camera viewplane */
- BlenderCamera cam_bcam;
- blender_camera_init(&cam_bcam, b_render);
- blender_camera_from_object(&cam_bcam, b_engine, b_ob, true);
+ /* get camera viewplane */
+ BlenderCamera cam_bcam;
+ blender_camera_init(&cam_bcam, b_render);
+ blender_camera_from_object(&cam_bcam, b_engine, b_ob, true);
- blender_camera_viewplane(&cam_bcam, cam_bcam.full_width, cam_bcam.full_height,
- &cam, &cam_aspect, &sensor_size);
+ blender_camera_viewplane(
+ &cam_bcam, cam_bcam.full_width, cam_bcam.full_height, &cam, &cam_aspect, &sensor_size);
- /* return */
- *view_box = view * (1.0f/view_aspect);
- *cam_box = cam * (1.0f/cam_aspect);
+ /* return */
+ *view_box = view * (1.0f / view_aspect);
+ *cam_box = cam * (1.0f / cam_aspect);
}
-static void blender_camera_border_subset(BL::RenderEngine& b_engine,
- BL::RenderSettings& b_render,
- BL::Scene& b_scene,
- BL::SpaceView3D& b_v3d,
- BL::RegionView3D& b_rv3d,
- BL::Object& b_ob,
- int width, int height,
+static void blender_camera_border_subset(BL::RenderEngine &b_engine,
+ BL::RenderSettings &b_render,
+ BL::Scene &b_scene,
+ BL::SpaceView3D &b_v3d,
+ BL::RegionView3D &b_rv3d,
+ BL::Object &b_ob,
+ int width,
+ int height,
const BoundBox2D &border,
BoundBox2D *result)
{
- /* Determine camera viewport subset. */
- BoundBox2D view_box, cam_box;
- blender_camera_view_subset(b_engine, b_render, b_scene, b_ob, b_v3d, b_rv3d, width, height,
- &view_box, &cam_box);
-
- /* Determine viewport subset matching given border. */
- cam_box = cam_box.make_relative_to(view_box);
- *result = cam_box.subset(border);
+ /* Determine camera viewport subset. */
+ BoundBox2D view_box, cam_box;
+ blender_camera_view_subset(
+ b_engine, b_render, b_scene, b_ob, b_v3d, b_rv3d, width, height, &view_box, &cam_box);
+
+ /* Determine viewport subset matching given border. */
+ cam_box = cam_box.make_relative_to(view_box);
+ *result = cam_box.subset(border);
}
static void blender_camera_border(BlenderCamera *bcam,
- BL::RenderEngine& b_engine,
- BL::RenderSettings& b_render,
- BL::Scene& b_scene,
- BL::SpaceView3D& b_v3d,
- BL::RegionView3D& b_rv3d,
- int width, int height)
+ BL::RenderEngine &b_engine,
+ BL::RenderSettings &b_render,
+ BL::Scene &b_scene,
+ BL::SpaceView3D &b_v3d,
+ BL::RegionView3D &b_rv3d,
+ int width,
+ int height)
{
- bool is_camera_view;
-
- /* camera view? */
- is_camera_view = b_rv3d.view_perspective() == BL::RegionView3D::view_perspective_CAMERA;
-
- if(!is_camera_view) {
- /* for non-camera view check whether render border is enabled for viewport
- * and if so use border from 3d viewport
- * assume viewport has got correctly clamped border already
- */
- if(b_v3d.use_render_border()) {
- bcam->border.left = b_v3d.render_border_min_x();
- bcam->border.right = b_v3d.render_border_max_x();
- bcam->border.bottom = b_v3d.render_border_min_y();
- bcam->border.top = b_v3d.render_border_max_y();
- }
- return;
- }
-
- BL::Object b_ob = (b_v3d.use_local_camera())? b_v3d.camera(): b_scene.camera();
-
- if(!b_ob)
- return;
-
- /* Determine camera border inside the viewport. */
- BoundBox2D full_border;
- blender_camera_border_subset(b_engine,
- b_render,
- b_scene,
- b_v3d,
- b_rv3d,
- b_ob,
- width, height,
- full_border,
- &bcam->viewport_camera_border);
-
- if(!b_render.use_border()) {
- return;
- }
-
- bcam->border.left = b_render.border_min_x();
- bcam->border.right = b_render.border_max_x();
- bcam->border.bottom = b_render.border_min_y();
- bcam->border.top = b_render.border_max_y();
-
- /* Determine viewport subset matching camera border. */
- blender_camera_border_subset(b_engine,
- b_render,
- b_scene,
- b_v3d,
- b_rv3d,
- b_ob,
- width, height,
- bcam->border,
- &bcam->border);
- bcam->border = bcam->border.clamp();
+ bool is_camera_view;
+
+ /* camera view? */
+ is_camera_view = b_rv3d.view_perspective() == BL::RegionView3D::view_perspective_CAMERA;
+
+ if (!is_camera_view) {
+ /* for non-camera view check whether render border is enabled for viewport
+ * and if so use border from 3d viewport
+ * assume viewport has got correctly clamped border already
+ */
+ if (b_v3d.use_render_border()) {
+ bcam->border.left = b_v3d.render_border_min_x();
+ bcam->border.right = b_v3d.render_border_max_x();
+ bcam->border.bottom = b_v3d.render_border_min_y();
+ bcam->border.top = b_v3d.render_border_max_y();
+ }
+ return;
+ }
+
+ BL::Object b_ob = (b_v3d.use_local_camera()) ? b_v3d.camera() : b_scene.camera();
+
+ if (!b_ob)
+ return;
+
+ /* Determine camera border inside the viewport. */
+ BoundBox2D full_border;
+ blender_camera_border_subset(b_engine,
+ b_render,
+ b_scene,
+ b_v3d,
+ b_rv3d,
+ b_ob,
+ width,
+ height,
+ full_border,
+ &bcam->viewport_camera_border);
+
+ if (!b_render.use_border()) {
+ return;
+ }
+
+ bcam->border.left = b_render.border_min_x();
+ bcam->border.right = b_render.border_max_x();
+ bcam->border.bottom = b_render.border_min_y();
+ bcam->border.top = b_render.border_max_y();
+
+ /* Determine viewport subset matching camera border. */
+ blender_camera_border_subset(b_engine,
+ b_render,
+ b_scene,
+ b_v3d,
+ b_rv3d,
+ b_ob,
+ width,
+ height,
+ bcam->border,
+ &bcam->border);
+ bcam->border = bcam->border.clamp();
}
-void BlenderSync::sync_view(BL::SpaceView3D& b_v3d,
- BL::RegionView3D& b_rv3d,
- int width, int height)
+void BlenderSync::sync_view(BL::SpaceView3D &b_v3d,
+ BL::RegionView3D &b_rv3d,
+ int width,
+ int height)
{
- BlenderCamera bcam;
- BL::RenderSettings b_render_settings(b_scene.render());
- blender_camera_init(&bcam, b_render_settings);
- blender_camera_from_view(&bcam,
- b_engine,
- b_scene,
- b_v3d,
- b_rv3d,
- width, height);
- blender_camera_border(&bcam,
- b_engine,
- b_render_settings,
- b_scene,
- b_v3d,
- b_rv3d,
- width, height);
- PointerRNA cscene = RNA_pointer_get(&b_scene.ptr, "cycles");
- blender_camera_sync(scene->camera, &bcam, width, height, "", &cscene);
-
- /* dicing camera */
- BL::Object b_ob = BL::Object(RNA_pointer_get(&cscene, "dicing_camera"));
- if(b_ob) {
- BL::Array<float, 16> b_ob_matrix;
- blender_camera_from_object(&bcam, b_engine, b_ob);
- b_engine.camera_model_matrix(b_ob, bcam.use_spherical_stereo, b_ob_matrix);
- bcam.matrix = get_transform(b_ob_matrix);
-
- blender_camera_sync(scene->dicing_camera, &bcam, width, height, "", &cscene);
- }
- else {
- *scene->dicing_camera = *scene->camera;
- }
+ BlenderCamera bcam;
+ BL::RenderSettings b_render_settings(b_scene.render());
+ blender_camera_init(&bcam, b_render_settings);
+ blender_camera_from_view(&bcam, b_engine, b_scene, b_v3d, b_rv3d, width, height);
+ blender_camera_border(&bcam, b_engine, b_render_settings, b_scene, b_v3d, b_rv3d, width, height);
+ PointerRNA cscene = RNA_pointer_get(&b_scene.ptr, "cycles");
+ blender_camera_sync(scene->camera, &bcam, width, height, "", &cscene);
+
+ /* dicing camera */
+ BL::Object b_ob = BL::Object(RNA_pointer_get(&cscene, "dicing_camera"));
+ if (b_ob) {
+ BL::Array<float, 16> b_ob_matrix;
+ blender_camera_from_object(&bcam, b_engine, b_ob);
+ b_engine.camera_model_matrix(b_ob, bcam.use_spherical_stereo, b_ob_matrix);
+ bcam.matrix = get_transform(b_ob_matrix);
+
+ blender_camera_sync(scene->dicing_camera, &bcam, width, height, "", &cscene);
+ }
+ else {
+ *scene->dicing_camera = *scene->camera;
+ }
}
-BufferParams BlenderSync::get_buffer_params(BL::RenderSettings& b_render,
- BL::SpaceView3D& b_v3d,
- BL::RegionView3D& b_rv3d,
+BufferParams BlenderSync::get_buffer_params(BL::RenderSettings &b_render,
+ BL::SpaceView3D &b_v3d,
+ BL::RegionView3D &b_rv3d,
Camera *cam,
- int width, int height)
+ int width,
+ int height)
{
- BufferParams params;
- bool use_border = false;
-
- params.full_width = width;
- params.full_height = height;
-
- if(b_v3d && b_rv3d && b_rv3d.view_perspective() != BL::RegionView3D::view_perspective_CAMERA)
- use_border = b_v3d.use_render_border();
- else
- use_border = b_render.use_border();
-
- if(use_border) {
- /* border render */
- /* the viewport may offset the border outside the view */
- BoundBox2D border = cam->border.clamp();
- params.full_x = (int)(border.left * (float)width);
- params.full_y = (int)(border.bottom * (float)height);
- params.width = (int)(border.right * (float)width) - params.full_x;
- params.height = (int)(border.top * (float)height) - params.full_y;
-
- /* survive in case border goes out of view or becomes too small */
- params.width = max(params.width, 1);
- params.height = max(params.height, 1);
- }
- else {
- params.width = width;
- params.height = height;
- }
-
- return params;
+ BufferParams params;
+ bool use_border = false;
+
+ params.full_width = width;
+ params.full_height = height;
+
+ if (b_v3d && b_rv3d && b_rv3d.view_perspective() != BL::RegionView3D::view_perspective_CAMERA)
+ use_border = b_v3d.use_render_border();
+ else
+ use_border = b_render.use_border();
+
+ if (use_border) {
+ /* border render */
+ /* the viewport may offset the border outside the view */
+ BoundBox2D border = cam->border.clamp();
+ params.full_x = (int)(border.left * (float)width);
+ params.full_y = (int)(border.bottom * (float)height);
+ params.width = (int)(border.right * (float)width) - params.full_x;
+ params.height = (int)(border.top * (float)height) - params.full_y;
+
+ /* survive in case border goes out of view or becomes too small */
+ params.width = max(params.width, 1);
+ params.height = max(params.height, 1);
+ }
+ else {
+ params.width = width;
+ params.height = height;
+ }
+
+ return params;
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/blender/blender_curves.cpp b/intern/cycles/blender/blender_curves.cpp
index 602e63a3e47..d0375ceb79c 100644
--- a/intern/cycles/blender/blender_curves.cpp
+++ b/intern/cycles/blender/blender_curves.cpp
@@ -40,170 +40,165 @@ ParticleCurveData::~ParticleCurveData()
static void interp_weights(float t, float data[4])
{
- /* Cardinal curve interpolation */
- float t2 = t * t;
- float t3 = t2 * t;
- float fc = 0.71f;
-
- data[0] = -fc * t3 + 2.0f * fc * t2 - fc * t;
- data[1] = (2.0f - fc) * t3 + (fc - 3.0f) * t2 + 1.0f;
- data[2] = (fc - 2.0f) * t3 + (3.0f - 2.0f * fc) * t2 + fc * t;
- data[3] = fc * t3 - fc * t2;
+ /* Cardinal curve interpolation */
+ float t2 = t * t;
+ float t3 = t2 * t;
+ float fc = 0.71f;
+
+ data[0] = -fc * t3 + 2.0f * fc * t2 - fc * t;
+ data[1] = (2.0f - fc) * t3 + (fc - 3.0f) * t2 + 1.0f;
+ data[2] = (fc - 2.0f) * t3 + (3.0f - 2.0f * fc) * t2 + fc * t;
+ data[3] = fc * t3 - fc * t2;
}
-static void curveinterp_v3_v3v3v3v3(float3 *p,
- float3 *v1, float3 *v2, float3 *v3, float3 *v4,
- const float w[4])
+static void curveinterp_v3_v3v3v3v3(
+ float3 *p, float3 *v1, float3 *v2, float3 *v3, float3 *v4, const float w[4])
{
- p->x = v1->x * w[0] + v2->x * w[1] + v3->x * w[2] + v4->x * w[3];
- p->y = v1->y * w[0] + v2->y * w[1] + v3->y * w[2] + v4->y * w[3];
- p->z = v1->z * w[0] + v2->z * w[1] + v3->z * w[2] + v4->z * w[3];
+ p->x = v1->x * w[0] + v2->x * w[1] + v3->x * w[2] + v4->x * w[3];
+ p->y = v1->y * w[0] + v2->y * w[1] + v3->y * w[2] + v4->y * w[3];
+ p->z = v1->z * w[0] + v2->z * w[1] + v3->z * w[2] + v4->z * w[3];
}
static float shaperadius(float shape, float root, float tip, float time)
{
- assert(time >= 0.0f);
- assert(time <= 1.0f);
- float radius = 1.0f - time;
-
- if(shape != 0.0f) {
- if(shape < 0.0f)
- radius = powf(radius, 1.0f + shape);
- else
- radius = powf(radius, 1.0f / (1.0f - shape));
- }
- return (radius * (root - tip)) + tip;
+ assert(time >= 0.0f);
+ assert(time <= 1.0f);
+ float radius = 1.0f - time;
+
+ if (shape != 0.0f) {
+ if (shape < 0.0f)
+ radius = powf(radius, 1.0f + shape);
+ else
+ radius = powf(radius, 1.0f / (1.0f - shape));
+ }
+ return (radius * (root - tip)) + tip;
}
/* curve functions */
-static void InterpolateKeySegments(int seg,
- int segno,
- int key,
- int curve,
- float3 *keyloc,
- float *time,
- ParticleCurveData *CData)
+static void InterpolateKeySegments(
+ int seg, int segno, int key, int curve, float3 *keyloc, float *time, ParticleCurveData *CData)
{
- float3 ckey_loc1 = CData->curvekey_co[key];
- float3 ckey_loc2 = ckey_loc1;
- float3 ckey_loc3 = CData->curvekey_co[key+1];
- float3 ckey_loc4 = ckey_loc3;
+ float3 ckey_loc1 = CData->curvekey_co[key];
+ float3 ckey_loc2 = ckey_loc1;
+ float3 ckey_loc3 = CData->curvekey_co[key + 1];
+ float3 ckey_loc4 = ckey_loc3;
- if(key > CData->curve_firstkey[curve])
- ckey_loc1 = CData->curvekey_co[key - 1];
+ if (key > CData->curve_firstkey[curve])
+ ckey_loc1 = CData->curvekey_co[key - 1];
- if(key < CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 2)
- ckey_loc4 = CData->curvekey_co[key + 2];
+ if (key < CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 2)
+ ckey_loc4 = CData->curvekey_co[key + 2];
- float time1 = CData->curvekey_time[key]/CData->curve_length[curve];
- float time2 = CData->curvekey_time[key + 1]/CData->curve_length[curve];
+ float time1 = CData->curvekey_time[key] / CData->curve_length[curve];
+ float time2 = CData->curvekey_time[key + 1] / CData->curve_length[curve];
- float dfra = (time2 - time1) / (float)segno;
+ float dfra = (time2 - time1) / (float)segno;
- if(time)
- *time = (dfra * seg) + time1;
+ if (time)
+ *time = (dfra * seg) + time1;
- float t[4];
+ float t[4];
- interp_weights((float)seg / (float)segno, t);
+ interp_weights((float)seg / (float)segno, t);
- if(keyloc)
- curveinterp_v3_v3v3v3v3(keyloc, &ckey_loc1, &ckey_loc2, &ckey_loc3, &ckey_loc4, t);
+ if (keyloc)
+ curveinterp_v3_v3v3v3v3(keyloc, &ckey_loc1, &ckey_loc2, &ckey_loc3, &ckey_loc4, t);
}
-static bool ObtainCacheParticleData(Mesh *mesh,
- BL::Mesh *b_mesh,
- BL::Object *b_ob,
- ParticleCurveData *CData,
- bool background)
+static bool ObtainCacheParticleData(
+ Mesh *mesh, BL::Mesh *b_mesh, BL::Object *b_ob, ParticleCurveData *CData, bool background)
{
- int curvenum = 0;
- int keyno = 0;
-
- if(!(mesh && b_mesh && b_ob && CData))
- return false;
-
- Transform tfm = get_transform(b_ob->matrix_world());
- Transform itfm = transform_quick_inverse(tfm);
-
- BL::Object::modifiers_iterator b_mod;
- for(b_ob->modifiers.begin(b_mod); b_mod != b_ob->modifiers.end(); ++b_mod) {
- if((b_mod->type() == b_mod->type_PARTICLE_SYSTEM) && (background ? b_mod->show_render() : b_mod->show_viewport())) {
- BL::ParticleSystemModifier psmd((const PointerRNA)b_mod->ptr);
- BL::ParticleSystem b_psys((const PointerRNA)psmd.particle_system().ptr);
- BL::ParticleSettings b_part((const PointerRNA)b_psys.settings().ptr);
-
- if((b_part.render_type() == BL::ParticleSettings::render_type_PATH) && (b_part.type() == BL::ParticleSettings::type_HAIR)) {
- int shader = clamp(b_part.material()-1, 0, mesh->used_shaders.size()-1);
- int display_step = background ? b_part.render_step() : b_part.display_step();
- int totparts = b_psys.particles.length();
- int totchild = background ? b_psys.child_particles.length() : (int)((float)b_psys.child_particles.length() * (float)b_part.display_percentage() / 100.0f);
- int totcurves = totchild;
-
- if(b_part.child_type() == 0 || totchild == 0)
- totcurves += totparts;
-
- if(totcurves == 0)
- continue;
-
- int ren_step = (1 << display_step) + 1;
- if(b_part.kink() == BL::ParticleSettings::kink_SPIRAL)
- ren_step += b_part.kink_extra_steps();
-
- CData->psys_firstcurve.push_back_slow(curvenum);
- CData->psys_curvenum.push_back_slow(totcurves);
- CData->psys_shader.push_back_slow(shader);
-
- float radius = b_part.radius_scale() * 0.5f;
-
- CData->psys_rootradius.push_back_slow(radius * b_part.root_radius());
- CData->psys_tipradius.push_back_slow(radius * b_part.tip_radius());
- CData->psys_shape.push_back_slow(b_part.shape());
- CData->psys_closetip.push_back_slow(b_part.use_close_tip());
-
- int pa_no = 0;
- if(!(b_part.child_type() == 0) && totchild != 0)
- pa_no = totparts;
-
- int num_add = (totparts+totchild - pa_no);
- CData->curve_firstkey.reserve(CData->curve_firstkey.size() + num_add);
- CData->curve_keynum.reserve(CData->curve_keynum.size() + num_add);
- CData->curve_length.reserve(CData->curve_length.size() + num_add);
- CData->curvekey_co.reserve(CData->curvekey_co.size() + num_add*ren_step);
- CData->curvekey_time.reserve(CData->curvekey_time.size() + num_add*ren_step);
-
- for(; pa_no < totparts+totchild; pa_no++) {
- int keynum = 0;
- CData->curve_firstkey.push_back_slow(keyno);
-
- float curve_length = 0.0f;
- float3 pcKey;
- for(int step_no = 0; step_no < ren_step; step_no++) {
- float nco[3];
- b_psys.co_hair(*b_ob, pa_no, step_no, nco);
- float3 cKey = make_float3(nco[0], nco[1], nco[2]);
- cKey = transform_point(&itfm, cKey);
- if(step_no > 0) {
- const float step_length = len(cKey - pcKey);
- curve_length += step_length;
- }
- CData->curvekey_co.push_back_slow(cKey);
- CData->curvekey_time.push_back_slow(curve_length);
- pcKey = cKey;
- keynum++;
- }
- keyno += keynum;
-
- CData->curve_keynum.push_back_slow(keynum);
- CData->curve_length.push_back_slow(curve_length);
- curvenum++;
- }
- }
- }
- }
-
- return true;
+ int curvenum = 0;
+ int keyno = 0;
+
+ if (!(mesh && b_mesh && b_ob && CData))
+ return false;
+
+ Transform tfm = get_transform(b_ob->matrix_world());
+ Transform itfm = transform_quick_inverse(tfm);
+
+ BL::Object::modifiers_iterator b_mod;
+ for (b_ob->modifiers.begin(b_mod); b_mod != b_ob->modifiers.end(); ++b_mod) {
+ if ((b_mod->type() == b_mod->type_PARTICLE_SYSTEM) &&
+ (background ? b_mod->show_render() : b_mod->show_viewport())) {
+ BL::ParticleSystemModifier psmd((const PointerRNA)b_mod->ptr);
+ BL::ParticleSystem b_psys((const PointerRNA)psmd.particle_system().ptr);
+ BL::ParticleSettings b_part((const PointerRNA)b_psys.settings().ptr);
+
+ if ((b_part.render_type() == BL::ParticleSettings::render_type_PATH) &&
+ (b_part.type() == BL::ParticleSettings::type_HAIR)) {
+ int shader = clamp(b_part.material() - 1, 0, mesh->used_shaders.size() - 1);
+ int display_step = background ? b_part.render_step() : b_part.display_step();
+ int totparts = b_psys.particles.length();
+ int totchild = background ? b_psys.child_particles.length() :
+ (int)((float)b_psys.child_particles.length() *
+ (float)b_part.display_percentage() / 100.0f);
+ int totcurves = totchild;
+
+ if (b_part.child_type() == 0 || totchild == 0)
+ totcurves += totparts;
+
+ if (totcurves == 0)
+ continue;
+
+ int ren_step = (1 << display_step) + 1;
+ if (b_part.kink() == BL::ParticleSettings::kink_SPIRAL)
+ ren_step += b_part.kink_extra_steps();
+
+ CData->psys_firstcurve.push_back_slow(curvenum);
+ CData->psys_curvenum.push_back_slow(totcurves);
+ CData->psys_shader.push_back_slow(shader);
+
+ float radius = b_part.radius_scale() * 0.5f;
+
+ CData->psys_rootradius.push_back_slow(radius * b_part.root_radius());
+ CData->psys_tipradius.push_back_slow(radius * b_part.tip_radius());
+ CData->psys_shape.push_back_slow(b_part.shape());
+ CData->psys_closetip.push_back_slow(b_part.use_close_tip());
+
+ int pa_no = 0;
+ if (!(b_part.child_type() == 0) && totchild != 0)
+ pa_no = totparts;
+
+ int num_add = (totparts + totchild - pa_no);
+ CData->curve_firstkey.reserve(CData->curve_firstkey.size() + num_add);
+ CData->curve_keynum.reserve(CData->curve_keynum.size() + num_add);
+ CData->curve_length.reserve(CData->curve_length.size() + num_add);
+ CData->curvekey_co.reserve(CData->curvekey_co.size() + num_add * ren_step);
+ CData->curvekey_time.reserve(CData->curvekey_time.size() + num_add * ren_step);
+
+ for (; pa_no < totparts + totchild; pa_no++) {
+ int keynum = 0;
+ CData->curve_firstkey.push_back_slow(keyno);
+
+ float curve_length = 0.0f;
+ float3 pcKey;
+ for (int step_no = 0; step_no < ren_step; step_no++) {
+ float nco[3];
+ b_psys.co_hair(*b_ob, pa_no, step_no, nco);
+ float3 cKey = make_float3(nco[0], nco[1], nco[2]);
+ cKey = transform_point(&itfm, cKey);
+ if (step_no > 0) {
+ const float step_length = len(cKey - pcKey);
+ curve_length += step_length;
+ }
+ CData->curvekey_co.push_back_slow(cKey);
+ CData->curvekey_time.push_back_slow(curve_length);
+ pcKey = cKey;
+ keynum++;
+ }
+ keyno += keynum;
+
+ CData->curve_keynum.push_back_slow(keynum);
+ CData->curve_length.push_back_slow(curve_length);
+ curvenum++;
+ }
+ }
+ }
+ }
+
+ return true;
}
static bool ObtainCacheParticleUV(Mesh *mesh,
@@ -213,56 +208,60 @@ static bool ObtainCacheParticleUV(Mesh *mesh,
bool background,
int uv_num)
{
- if(!(mesh && b_mesh && b_ob && CData))
- return false;
-
- CData->curve_uv.clear();
-
- BL::Object::modifiers_iterator b_mod;
- for(b_ob->modifiers.begin(b_mod); b_mod != b_ob->modifiers.end(); ++b_mod) {
- if((b_mod->type() == b_mod->type_PARTICLE_SYSTEM) && (background ? b_mod->show_render() : b_mod->show_viewport())) {
- BL::ParticleSystemModifier psmd((const PointerRNA)b_mod->ptr);
- BL::ParticleSystem b_psys((const PointerRNA)psmd.particle_system().ptr);
- BL::ParticleSettings b_part((const PointerRNA)b_psys.settings().ptr);
-
- if((b_part.render_type() == BL::ParticleSettings::render_type_PATH) && (b_part.type() == BL::ParticleSettings::type_HAIR)) {
- int totparts = b_psys.particles.length();
- int totchild = background ? b_psys.child_particles.length() : (int)((float)b_psys.child_particles.length() * (float)b_part.display_percentage() / 100.0f);
- int totcurves = totchild;
-
- if(b_part.child_type() == 0 || totchild == 0)
- totcurves += totparts;
-
- if(totcurves == 0)
- continue;
-
- int pa_no = 0;
- if(!(b_part.child_type() == 0) && totchild != 0)
- pa_no = totparts;
-
- int num_add = (totparts+totchild - pa_no);
- CData->curve_uv.reserve(CData->curve_uv.size() + num_add);
-
- BL::ParticleSystem::particles_iterator b_pa;
- b_psys.particles.begin(b_pa);
- for(; pa_no < totparts+totchild; pa_no++) {
- /* Add UVs */
- BL::Mesh::uv_layers_iterator l;
- b_mesh->uv_layers.begin(l);
-
- float2 uv = make_float2(0.0f, 0.0f);
- if(b_mesh->uv_layers.length())
- b_psys.uv_on_emitter(psmd, *b_pa, pa_no, uv_num, &uv.x);
- CData->curve_uv.push_back_slow(uv);
-
- if(pa_no < totparts && b_pa != b_psys.particles.end())
- ++b_pa;
- }
- }
- }
- }
-
- return true;
+ if (!(mesh && b_mesh && b_ob && CData))
+ return false;
+
+ CData->curve_uv.clear();
+
+ BL::Object::modifiers_iterator b_mod;
+ for (b_ob->modifiers.begin(b_mod); b_mod != b_ob->modifiers.end(); ++b_mod) {
+ if ((b_mod->type() == b_mod->type_PARTICLE_SYSTEM) &&
+ (background ? b_mod->show_render() : b_mod->show_viewport())) {
+ BL::ParticleSystemModifier psmd((const PointerRNA)b_mod->ptr);
+ BL::ParticleSystem b_psys((const PointerRNA)psmd.particle_system().ptr);
+ BL::ParticleSettings b_part((const PointerRNA)b_psys.settings().ptr);
+
+ if ((b_part.render_type() == BL::ParticleSettings::render_type_PATH) &&
+ (b_part.type() == BL::ParticleSettings::type_HAIR)) {
+ int totparts = b_psys.particles.length();
+ int totchild = background ? b_psys.child_particles.length() :
+ (int)((float)b_psys.child_particles.length() *
+ (float)b_part.display_percentage() / 100.0f);
+ int totcurves = totchild;
+
+ if (b_part.child_type() == 0 || totchild == 0)
+ totcurves += totparts;
+
+ if (totcurves == 0)
+ continue;
+
+ int pa_no = 0;
+ if (!(b_part.child_type() == 0) && totchild != 0)
+ pa_no = totparts;
+
+ int num_add = (totparts + totchild - pa_no);
+ CData->curve_uv.reserve(CData->curve_uv.size() + num_add);
+
+ BL::ParticleSystem::particles_iterator b_pa;
+ b_psys.particles.begin(b_pa);
+ for (; pa_no < totparts + totchild; pa_no++) {
+ /* Add UVs */
+ BL::Mesh::uv_layers_iterator l;
+ b_mesh->uv_layers.begin(l);
+
+ float2 uv = make_float2(0.0f, 0.0f);
+ if (b_mesh->uv_layers.length())
+ b_psys.uv_on_emitter(psmd, *b_pa, pa_no, uv_num, &uv.x);
+ CData->curve_uv.push_back_slow(uv);
+
+ if (pa_no < totparts && b_pa != b_psys.particles.end())
+ ++b_pa;
+ }
+ }
+ }
+ }
+
+ return true;
}
static bool ObtainCacheParticleVcol(Mesh *mesh,
@@ -272,481 +271,542 @@ static bool ObtainCacheParticleVcol(Mesh *mesh,
bool background,
int vcol_num)
{
- if(!(mesh && b_mesh && b_ob && CData))
- return false;
-
- CData->curve_vcol.clear();
-
- BL::Object::modifiers_iterator b_mod;
- for(b_ob->modifiers.begin(b_mod); b_mod != b_ob->modifiers.end(); ++b_mod) {
- if((b_mod->type() == b_mod->type_PARTICLE_SYSTEM) && (background ? b_mod->show_render() : b_mod->show_viewport())) {
- BL::ParticleSystemModifier psmd((const PointerRNA)b_mod->ptr);
- BL::ParticleSystem b_psys((const PointerRNA)psmd.particle_system().ptr);
- BL::ParticleSettings b_part((const PointerRNA)b_psys.settings().ptr);
-
- if((b_part.render_type() == BL::ParticleSettings::render_type_PATH) && (b_part.type() == BL::ParticleSettings::type_HAIR)) {
- int totparts = b_psys.particles.length();
- int totchild = background ? b_psys.child_particles.length() : (int)((float)b_psys.child_particles.length() * (float)b_part.display_percentage() / 100.0f);
- int totcurves = totchild;
-
- if(b_part.child_type() == 0 || totchild == 0)
- totcurves += totparts;
-
- if(totcurves == 0)
- continue;
-
- int pa_no = 0;
- if(!(b_part.child_type() == 0) && totchild != 0)
- pa_no = totparts;
-
- int num_add = (totparts+totchild - pa_no);
- CData->curve_vcol.reserve(CData->curve_vcol.size() + num_add);
-
- BL::ParticleSystem::particles_iterator b_pa;
- b_psys.particles.begin(b_pa);
- for(; pa_no < totparts+totchild; pa_no++) {
- /* Add vertex colors */
- BL::Mesh::vertex_colors_iterator l;
- b_mesh->vertex_colors.begin(l);
-
- float3 vcol = make_float3(0.0f, 0.0f, 0.0f);
- if(b_mesh->vertex_colors.length())
- b_psys.mcol_on_emitter(psmd, *b_pa, pa_no, vcol_num, &vcol.x);
- CData->curve_vcol.push_back_slow(vcol);
-
- if(pa_no < totparts && b_pa != b_psys.particles.end())
- ++b_pa;
- }
- }
- }
- }
-
- return true;
+ if (!(mesh && b_mesh && b_ob && CData))
+ return false;
+
+ CData->curve_vcol.clear();
+
+ BL::Object::modifiers_iterator b_mod;
+ for (b_ob->modifiers.begin(b_mod); b_mod != b_ob->modifiers.end(); ++b_mod) {
+ if ((b_mod->type() == b_mod->type_PARTICLE_SYSTEM) &&
+ (background ? b_mod->show_render() : b_mod->show_viewport())) {
+ BL::ParticleSystemModifier psmd((const PointerRNA)b_mod->ptr);
+ BL::ParticleSystem b_psys((const PointerRNA)psmd.particle_system().ptr);
+ BL::ParticleSettings b_part((const PointerRNA)b_psys.settings().ptr);
+
+ if ((b_part.render_type() == BL::ParticleSettings::render_type_PATH) &&
+ (b_part.type() == BL::ParticleSettings::type_HAIR)) {
+ int totparts = b_psys.particles.length();
+ int totchild = background ? b_psys.child_particles.length() :
+ (int)((float)b_psys.child_particles.length() *
+ (float)b_part.display_percentage() / 100.0f);
+ int totcurves = totchild;
+
+ if (b_part.child_type() == 0 || totchild == 0)
+ totcurves += totparts;
+
+ if (totcurves == 0)
+ continue;
+
+ int pa_no = 0;
+ if (!(b_part.child_type() == 0) && totchild != 0)
+ pa_no = totparts;
+
+ int num_add = (totparts + totchild - pa_no);
+ CData->curve_vcol.reserve(CData->curve_vcol.size() + num_add);
+
+ BL::ParticleSystem::particles_iterator b_pa;
+ b_psys.particles.begin(b_pa);
+ for (; pa_no < totparts + totchild; pa_no++) {
+ /* Add vertex colors */
+ BL::Mesh::vertex_colors_iterator l;
+ b_mesh->vertex_colors.begin(l);
+
+ float3 vcol = make_float3(0.0f, 0.0f, 0.0f);
+ if (b_mesh->vertex_colors.length())
+ b_psys.mcol_on_emitter(psmd, *b_pa, pa_no, vcol_num, &vcol.x);
+ CData->curve_vcol.push_back_slow(vcol);
+
+ if (pa_no < totparts && b_pa != b_psys.particles.end())
+ ++b_pa;
+ }
+ }
+ }
+ }
+
+ return true;
}
-static void ExportCurveTrianglePlanes(Mesh *mesh, ParticleCurveData *CData,
- float3 RotCam, bool is_ortho)
+static void ExportCurveTrianglePlanes(Mesh *mesh,
+ ParticleCurveData *CData,
+ float3 RotCam,
+ bool is_ortho)
{
- int vertexno = mesh->verts.size();
- int vertexindex = vertexno;
- int numverts = 0, numtris = 0;
-
- /* compute and reserve size of arrays */
- for(int sys = 0; sys < CData->psys_firstcurve.size(); sys++) {
- for(int curve = CData->psys_firstcurve[sys]; curve < CData->psys_firstcurve[sys] + CData->psys_curvenum[sys]; curve++) {
- numverts += 2 + (CData->curve_keynum[curve] - 1)*2;
- numtris += (CData->curve_keynum[curve] - 1)*2;
- }
- }
-
- mesh->reserve_mesh(mesh->verts.size() + numverts, mesh->num_triangles() + numtris);
-
- /* actually export */
- for(int sys = 0; sys < CData->psys_firstcurve.size(); sys++) {
- for(int curve = CData->psys_firstcurve[sys]; curve < CData->psys_firstcurve[sys] + CData->psys_curvenum[sys]; curve++) {
- float3 xbasis;
- float3 v1;
- float time = 0.0f;
- float3 ickey_loc = CData->curvekey_co[CData->curve_firstkey[curve]];
- float radius = shaperadius(CData->psys_shape[sys], CData->psys_rootradius[sys], CData->psys_tipradius[sys], 0.0f);
- v1 = CData->curvekey_co[CData->curve_firstkey[curve] + 1] - CData->curvekey_co[CData->curve_firstkey[curve]];
- if(is_ortho)
- xbasis = normalize(cross(RotCam, v1));
- else
- xbasis = normalize(cross(RotCam - ickey_loc, v1));
- float3 ickey_loc_shfl = ickey_loc - radius * xbasis;
- float3 ickey_loc_shfr = ickey_loc + radius * xbasis;
- mesh->add_vertex(ickey_loc_shfl);
- mesh->add_vertex(ickey_loc_shfr);
- vertexindex += 2;
-
- for(int curvekey = CData->curve_firstkey[curve] + 1; curvekey < CData->curve_firstkey[curve] + CData->curve_keynum[curve]; curvekey++) {
- ickey_loc = CData->curvekey_co[curvekey];
-
- if(curvekey == CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 1)
- v1 = CData->curvekey_co[curvekey] - CData->curvekey_co[max(curvekey - 1, CData->curve_firstkey[curve])];
- else
- v1 = CData->curvekey_co[curvekey + 1] - CData->curvekey_co[curvekey - 1];
-
- time = CData->curvekey_time[curvekey]/CData->curve_length[curve];
- radius = shaperadius(CData->psys_shape[sys], CData->psys_rootradius[sys], CData->psys_tipradius[sys], time);
-
- if(curvekey == CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 1)
- radius = shaperadius(CData->psys_shape[sys], CData->psys_rootradius[sys], CData->psys_tipradius[sys], 0.95f);
-
- if(CData->psys_closetip[sys] && (curvekey == CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 1))
- radius = shaperadius(CData->psys_shape[sys], CData->psys_rootradius[sys], 0.0f, 0.95f);
-
- if(is_ortho)
- xbasis = normalize(cross(RotCam, v1));
- else
- xbasis = normalize(cross(RotCam - ickey_loc, v1));
- float3 ickey_loc_shfl = ickey_loc - radius * xbasis;
- float3 ickey_loc_shfr = ickey_loc + radius * xbasis;
- mesh->add_vertex(ickey_loc_shfl);
- mesh->add_vertex(ickey_loc_shfr);
- mesh->add_triangle(vertexindex-2, vertexindex, vertexindex-1, CData->psys_shader[sys], true);
- mesh->add_triangle(vertexindex+1, vertexindex-1, vertexindex, CData->psys_shader[sys], true);
- vertexindex += 2;
- }
- }
- }
-
- mesh->resize_mesh(mesh->verts.size(), mesh->num_triangles());
- mesh->attributes.remove(ATTR_STD_VERTEX_NORMAL);
- mesh->attributes.remove(ATTR_STD_FACE_NORMAL);
- mesh->add_face_normals();
- mesh->add_vertex_normals();
- mesh->attributes.remove(ATTR_STD_FACE_NORMAL);
-
- /* texture coords still needed */
+ int vertexno = mesh->verts.size();
+ int vertexindex = vertexno;
+ int numverts = 0, numtris = 0;
+
+ /* compute and reserve size of arrays */
+ for (int sys = 0; sys < CData->psys_firstcurve.size(); sys++) {
+ for (int curve = CData->psys_firstcurve[sys];
+ curve < CData->psys_firstcurve[sys] + CData->psys_curvenum[sys];
+ curve++) {
+ numverts += 2 + (CData->curve_keynum[curve] - 1) * 2;
+ numtris += (CData->curve_keynum[curve] - 1) * 2;
+ }
+ }
+
+ mesh->reserve_mesh(mesh->verts.size() + numverts, mesh->num_triangles() + numtris);
+
+ /* actually export */
+ for (int sys = 0; sys < CData->psys_firstcurve.size(); sys++) {
+ for (int curve = CData->psys_firstcurve[sys];
+ curve < CData->psys_firstcurve[sys] + CData->psys_curvenum[sys];
+ curve++) {
+ float3 xbasis;
+ float3 v1;
+ float time = 0.0f;
+ float3 ickey_loc = CData->curvekey_co[CData->curve_firstkey[curve]];
+ float radius = shaperadius(
+ CData->psys_shape[sys], CData->psys_rootradius[sys], CData->psys_tipradius[sys], 0.0f);
+ v1 = CData->curvekey_co[CData->curve_firstkey[curve] + 1] -
+ CData->curvekey_co[CData->curve_firstkey[curve]];
+ if (is_ortho)
+ xbasis = normalize(cross(RotCam, v1));
+ else
+ xbasis = normalize(cross(RotCam - ickey_loc, v1));
+ float3 ickey_loc_shfl = ickey_loc - radius * xbasis;
+ float3 ickey_loc_shfr = ickey_loc + radius * xbasis;
+ mesh->add_vertex(ickey_loc_shfl);
+ mesh->add_vertex(ickey_loc_shfr);
+ vertexindex += 2;
+
+ for (int curvekey = CData->curve_firstkey[curve] + 1;
+ curvekey < CData->curve_firstkey[curve] + CData->curve_keynum[curve];
+ curvekey++) {
+ ickey_loc = CData->curvekey_co[curvekey];
+
+ if (curvekey == CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 1)
+ v1 = CData->curvekey_co[curvekey] -
+ CData->curvekey_co[max(curvekey - 1, CData->curve_firstkey[curve])];
+ else
+ v1 = CData->curvekey_co[curvekey + 1] - CData->curvekey_co[curvekey - 1];
+
+ time = CData->curvekey_time[curvekey] / CData->curve_length[curve];
+ radius = shaperadius(
+ CData->psys_shape[sys], CData->psys_rootradius[sys], CData->psys_tipradius[sys], time);
+
+ if (curvekey == CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 1)
+ radius = shaperadius(CData->psys_shape[sys],
+ CData->psys_rootradius[sys],
+ CData->psys_tipradius[sys],
+ 0.95f);
+
+ if (CData->psys_closetip[sys] &&
+ (curvekey == CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 1))
+ radius = shaperadius(CData->psys_shape[sys], CData->psys_rootradius[sys], 0.0f, 0.95f);
+
+ if (is_ortho)
+ xbasis = normalize(cross(RotCam, v1));
+ else
+ xbasis = normalize(cross(RotCam - ickey_loc, v1));
+ float3 ickey_loc_shfl = ickey_loc - radius * xbasis;
+ float3 ickey_loc_shfr = ickey_loc + radius * xbasis;
+ mesh->add_vertex(ickey_loc_shfl);
+ mesh->add_vertex(ickey_loc_shfr);
+ mesh->add_triangle(
+ vertexindex - 2, vertexindex, vertexindex - 1, CData->psys_shader[sys], true);
+ mesh->add_triangle(
+ vertexindex + 1, vertexindex - 1, vertexindex, CData->psys_shader[sys], true);
+ vertexindex += 2;
+ }
+ }
+ }
+
+ mesh->resize_mesh(mesh->verts.size(), mesh->num_triangles());
+ mesh->attributes.remove(ATTR_STD_VERTEX_NORMAL);
+ mesh->attributes.remove(ATTR_STD_FACE_NORMAL);
+ mesh->add_face_normals();
+ mesh->add_vertex_normals();
+ mesh->attributes.remove(ATTR_STD_FACE_NORMAL);
+
+ /* texture coords still needed */
}
-static void ExportCurveTriangleGeometry(Mesh *mesh,
- ParticleCurveData *CData,
- int resolution)
+static void ExportCurveTriangleGeometry(Mesh *mesh, ParticleCurveData *CData, int resolution)
{
- int vertexno = mesh->verts.size();
- int vertexindex = vertexno;
- int numverts = 0, numtris = 0;
-
- /* compute and reserve size of arrays */
- for(int sys = 0; sys < CData->psys_firstcurve.size(); sys++) {
- for(int curve = CData->psys_firstcurve[sys]; curve < CData->psys_firstcurve[sys] + CData->psys_curvenum[sys]; curve++) {
- numverts += (CData->curve_keynum[curve] - 1)*resolution + resolution;
- numtris += (CData->curve_keynum[curve] - 1)*2*resolution;
- }
- }
-
- mesh->reserve_mesh(mesh->verts.size() + numverts, mesh->num_triangles() + numtris);
-
- /* actually export */
- for(int sys = 0; sys < CData->psys_firstcurve.size(); sys++) {
- for(int curve = CData->psys_firstcurve[sys]; curve < CData->psys_firstcurve[sys] + CData->psys_curvenum[sys]; curve++) {
- float3 firstxbasis = cross(make_float3(1.0f,0.0f,0.0f),CData->curvekey_co[CData->curve_firstkey[curve]+1] - CData->curvekey_co[CData->curve_firstkey[curve]]);
- if(!is_zero(firstxbasis))
- firstxbasis = normalize(firstxbasis);
- else
- firstxbasis = normalize(cross(make_float3(0.0f,1.0f,0.0f),CData->curvekey_co[CData->curve_firstkey[curve]+1] - CData->curvekey_co[CData->curve_firstkey[curve]]));
-
- for(int curvekey = CData->curve_firstkey[curve]; curvekey < CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 1; curvekey++) {
- float3 xbasis = firstxbasis;
- float3 v1;
- float3 v2;
-
- if(curvekey == CData->curve_firstkey[curve]) {
- v1 = CData->curvekey_co[min(curvekey+2,CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 1)] - CData->curvekey_co[curvekey+1];
- v2 = CData->curvekey_co[curvekey+1] - CData->curvekey_co[curvekey];
- }
- else if(curvekey == CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 1) {
- v1 = CData->curvekey_co[curvekey] - CData->curvekey_co[curvekey-1];
- v2 = CData->curvekey_co[curvekey-1] - CData->curvekey_co[max(curvekey-2,CData->curve_firstkey[curve])];
- }
- else {
- v1 = CData->curvekey_co[curvekey+1] - CData->curvekey_co[curvekey];
- v2 = CData->curvekey_co[curvekey] - CData->curvekey_co[curvekey-1];
- }
-
- xbasis = cross(v1, v2);
-
- if(len_squared(xbasis) >= 0.05f * len_squared(v1) * len_squared(v2)) {
- firstxbasis = normalize(xbasis);
- break;
- }
- }
-
- for(int curvekey = CData->curve_firstkey[curve]; curvekey < CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 1; curvekey++) {
- int subv = 1;
- float3 xbasis;
- float3 ybasis;
- float3 v1;
- float3 v2;
-
- if(curvekey == CData->curve_firstkey[curve]) {
- subv = 0;
- v1 = CData->curvekey_co[min(curvekey+2,CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 1)] - CData->curvekey_co[curvekey+1];
- v2 = CData->curvekey_co[curvekey+1] - CData->curvekey_co[curvekey];
- }
- else if(curvekey == CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 1) {
- v1 = CData->curvekey_co[curvekey] - CData->curvekey_co[curvekey-1];
- v2 = CData->curvekey_co[curvekey-1] - CData->curvekey_co[max(curvekey-2,CData->curve_firstkey[curve])];
- }
- else {
- v1 = CData->curvekey_co[curvekey+1] - CData->curvekey_co[curvekey];
- v2 = CData->curvekey_co[curvekey] - CData->curvekey_co[curvekey-1];
- }
-
- xbasis = cross(v1, v2);
-
- if(len_squared(xbasis) >= 0.05f * len_squared(v1) * len_squared(v2)) {
- xbasis = normalize(xbasis);
- firstxbasis = xbasis;
- }
- else
- xbasis = firstxbasis;
-
- ybasis = normalize(cross(xbasis, v2));
-
- for(; subv <= 1; subv++) {
- float3 ickey_loc = make_float3(0.0f,0.0f,0.0f);
- float time = 0.0f;
-
- InterpolateKeySegments(subv, 1, curvekey, curve, &ickey_loc, &time, CData);
-
- float radius = shaperadius(CData->psys_shape[sys], CData->psys_rootradius[sys], CData->psys_tipradius[sys], time);
-
- if((curvekey == CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 2) && (subv == 1))
- radius = shaperadius(CData->psys_shape[sys], CData->psys_rootradius[sys], CData->psys_tipradius[sys], 0.95f);
-
- if(CData->psys_closetip[sys] && (subv == 1) && (curvekey == CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 2))
- radius = shaperadius(CData->psys_shape[sys], CData->psys_rootradius[sys], 0.0f, 0.95f);
-
- float angle = M_2PI_F / (float)resolution;
- for(int section = 0; section < resolution; section++) {
- float3 ickey_loc_shf = ickey_loc + radius * (cosf(angle * section) * xbasis + sinf(angle * section) * ybasis);
- mesh->add_vertex(ickey_loc_shf);
- }
-
- if(subv != 0) {
- for(int section = 0; section < resolution - 1; section++) {
- mesh->add_triangle(vertexindex - resolution + section, vertexindex + section, vertexindex - resolution + section + 1, CData->psys_shader[sys], true);
- mesh->add_triangle(vertexindex + section + 1, vertexindex - resolution + section + 1, vertexindex + section, CData->psys_shader[sys], true);
- }
- mesh->add_triangle(vertexindex-1, vertexindex + resolution - 1, vertexindex - resolution, CData->psys_shader[sys], true);
- mesh->add_triangle(vertexindex, vertexindex - resolution , vertexindex + resolution - 1, CData->psys_shader[sys], true);
- }
- vertexindex += resolution;
- }
- }
- }
- }
-
- mesh->resize_mesh(mesh->verts.size(), mesh->num_triangles());
- mesh->attributes.remove(ATTR_STD_VERTEX_NORMAL);
- mesh->attributes.remove(ATTR_STD_FACE_NORMAL);
- mesh->add_face_normals();
- mesh->add_vertex_normals();
- mesh->attributes.remove(ATTR_STD_FACE_NORMAL);
-
- /* texture coords still needed */
+ int vertexno = mesh->verts.size();
+ int vertexindex = vertexno;
+ int numverts = 0, numtris = 0;
+
+ /* compute and reserve size of arrays */
+ for (int sys = 0; sys < CData->psys_firstcurve.size(); sys++) {
+ for (int curve = CData->psys_firstcurve[sys];
+ curve < CData->psys_firstcurve[sys] + CData->psys_curvenum[sys];
+ curve++) {
+ numverts += (CData->curve_keynum[curve] - 1) * resolution + resolution;
+ numtris += (CData->curve_keynum[curve] - 1) * 2 * resolution;
+ }
+ }
+
+ mesh->reserve_mesh(mesh->verts.size() + numverts, mesh->num_triangles() + numtris);
+
+ /* actually export */
+ for (int sys = 0; sys < CData->psys_firstcurve.size(); sys++) {
+ for (int curve = CData->psys_firstcurve[sys];
+ curve < CData->psys_firstcurve[sys] + CData->psys_curvenum[sys];
+ curve++) {
+ float3 firstxbasis = cross(make_float3(1.0f, 0.0f, 0.0f),
+ CData->curvekey_co[CData->curve_firstkey[curve] + 1] -
+ CData->curvekey_co[CData->curve_firstkey[curve]]);
+ if (!is_zero(firstxbasis))
+ firstxbasis = normalize(firstxbasis);
+ else
+ firstxbasis = normalize(cross(make_float3(0.0f, 1.0f, 0.0f),
+ CData->curvekey_co[CData->curve_firstkey[curve] + 1] -
+ CData->curvekey_co[CData->curve_firstkey[curve]]));
+
+ for (int curvekey = CData->curve_firstkey[curve];
+ curvekey < CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 1;
+ curvekey++) {
+ float3 xbasis = firstxbasis;
+ float3 v1;
+ float3 v2;
+
+ if (curvekey == CData->curve_firstkey[curve]) {
+ v1 = CData->curvekey_co[min(
+ curvekey + 2, CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 1)] -
+ CData->curvekey_co[curvekey + 1];
+ v2 = CData->curvekey_co[curvekey + 1] - CData->curvekey_co[curvekey];
+ }
+ else if (curvekey == CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 1) {
+ v1 = CData->curvekey_co[curvekey] - CData->curvekey_co[curvekey - 1];
+ v2 = CData->curvekey_co[curvekey - 1] -
+ CData->curvekey_co[max(curvekey - 2, CData->curve_firstkey[curve])];
+ }
+ else {
+ v1 = CData->curvekey_co[curvekey + 1] - CData->curvekey_co[curvekey];
+ v2 = CData->curvekey_co[curvekey] - CData->curvekey_co[curvekey - 1];
+ }
+
+ xbasis = cross(v1, v2);
+
+ if (len_squared(xbasis) >= 0.05f * len_squared(v1) * len_squared(v2)) {
+ firstxbasis = normalize(xbasis);
+ break;
+ }
+ }
+
+ for (int curvekey = CData->curve_firstkey[curve];
+ curvekey < CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 1;
+ curvekey++) {
+ int subv = 1;
+ float3 xbasis;
+ float3 ybasis;
+ float3 v1;
+ float3 v2;
+
+ if (curvekey == CData->curve_firstkey[curve]) {
+ subv = 0;
+ v1 = CData->curvekey_co[min(
+ curvekey + 2, CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 1)] -
+ CData->curvekey_co[curvekey + 1];
+ v2 = CData->curvekey_co[curvekey + 1] - CData->curvekey_co[curvekey];
+ }
+ else if (curvekey == CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 1) {
+ v1 = CData->curvekey_co[curvekey] - CData->curvekey_co[curvekey - 1];
+ v2 = CData->curvekey_co[curvekey - 1] -
+ CData->curvekey_co[max(curvekey - 2, CData->curve_firstkey[curve])];
+ }
+ else {
+ v1 = CData->curvekey_co[curvekey + 1] - CData->curvekey_co[curvekey];
+ v2 = CData->curvekey_co[curvekey] - CData->curvekey_co[curvekey - 1];
+ }
+
+ xbasis = cross(v1, v2);
+
+ if (len_squared(xbasis) >= 0.05f * len_squared(v1) * len_squared(v2)) {
+ xbasis = normalize(xbasis);
+ firstxbasis = xbasis;
+ }
+ else
+ xbasis = firstxbasis;
+
+ ybasis = normalize(cross(xbasis, v2));
+
+ for (; subv <= 1; subv++) {
+ float3 ickey_loc = make_float3(0.0f, 0.0f, 0.0f);
+ float time = 0.0f;
+
+ InterpolateKeySegments(subv, 1, curvekey, curve, &ickey_loc, &time, CData);
+
+ float radius = shaperadius(CData->psys_shape[sys],
+ CData->psys_rootradius[sys],
+ CData->psys_tipradius[sys],
+ time);
+
+ if ((curvekey == CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 2) &&
+ (subv == 1))
+ radius = shaperadius(CData->psys_shape[sys],
+ CData->psys_rootradius[sys],
+ CData->psys_tipradius[sys],
+ 0.95f);
+
+ if (CData->psys_closetip[sys] && (subv == 1) &&
+ (curvekey == CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 2))
+ radius = shaperadius(CData->psys_shape[sys], CData->psys_rootradius[sys], 0.0f, 0.95f);
+
+ float angle = M_2PI_F / (float)resolution;
+ for (int section = 0; section < resolution; section++) {
+ float3 ickey_loc_shf = ickey_loc + radius * (cosf(angle * section) * xbasis +
+ sinf(angle * section) * ybasis);
+ mesh->add_vertex(ickey_loc_shf);
+ }
+
+ if (subv != 0) {
+ for (int section = 0; section < resolution - 1; section++) {
+ mesh->add_triangle(vertexindex - resolution + section,
+ vertexindex + section,
+ vertexindex - resolution + section + 1,
+ CData->psys_shader[sys],
+ true);
+ mesh->add_triangle(vertexindex + section + 1,
+ vertexindex - resolution + section + 1,
+ vertexindex + section,
+ CData->psys_shader[sys],
+ true);
+ }
+ mesh->add_triangle(vertexindex - 1,
+ vertexindex + resolution - 1,
+ vertexindex - resolution,
+ CData->psys_shader[sys],
+ true);
+ mesh->add_triangle(vertexindex,
+ vertexindex - resolution,
+ vertexindex + resolution - 1,
+ CData->psys_shader[sys],
+ true);
+ }
+ vertexindex += resolution;
+ }
+ }
+ }
+ }
+
+ mesh->resize_mesh(mesh->verts.size(), mesh->num_triangles());
+ mesh->attributes.remove(ATTR_STD_VERTEX_NORMAL);
+ mesh->attributes.remove(ATTR_STD_FACE_NORMAL);
+ mesh->add_face_normals();
+ mesh->add_vertex_normals();
+ mesh->attributes.remove(ATTR_STD_FACE_NORMAL);
+
+ /* texture coords still needed */
}
static void ExportCurveSegments(Scene *scene, Mesh *mesh, ParticleCurveData *CData)
{
- int num_keys = 0;
- int num_curves = 0;
-
- if(mesh->num_curves())
- return;
-
- Attribute *attr_intercept = NULL;
- Attribute *attr_random = NULL;
-
- if(mesh->need_attribute(scene, ATTR_STD_CURVE_INTERCEPT))
- attr_intercept = mesh->curve_attributes.add(ATTR_STD_CURVE_INTERCEPT);
- if(mesh->need_attribute(scene, ATTR_STD_CURVE_RANDOM))
- attr_random = mesh->curve_attributes.add(ATTR_STD_CURVE_RANDOM);
-
- /* compute and reserve size of arrays */
- for(int sys = 0; sys < CData->psys_firstcurve.size(); sys++) {
- for(int curve = CData->psys_firstcurve[sys]; curve < CData->psys_firstcurve[sys] + CData->psys_curvenum[sys]; curve++) {
- num_keys += CData->curve_keynum[curve];
- num_curves++;
- }
- }
-
- if(num_curves > 0) {
- VLOG(1) << "Exporting curve segments for mesh " << mesh->name;
- }
-
- mesh->reserve_curves(mesh->num_curves() + num_curves, mesh->curve_keys.size() + num_keys);
-
- num_keys = 0;
- num_curves = 0;
-
- /* actually export */
- for(int sys = 0; sys < CData->psys_firstcurve.size(); sys++) {
- for(int curve = CData->psys_firstcurve[sys]; curve < CData->psys_firstcurve[sys] + CData->psys_curvenum[sys]; curve++) {
- size_t num_curve_keys = 0;
-
- for(int curvekey = CData->curve_firstkey[curve];
- curvekey < CData->curve_firstkey[curve] + CData->curve_keynum[curve];
- curvekey++)
- {
- const float3 ickey_loc = CData->curvekey_co[curvekey];
- const float curve_time = CData->curvekey_time[curvekey];
- const float curve_length = CData->curve_length[curve];
- const float time = (curve_length > 0.0f)
- ? curve_time / curve_length
- : 0.0f;
- float radius = shaperadius(CData->psys_shape[sys],
- CData->psys_rootradius[sys],
- CData->psys_tipradius[sys],
- time);
- if(CData->psys_closetip[sys] &&
- (curvekey == CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 1))
- {
- radius = 0.0f;
- }
- mesh->add_curve_key(ickey_loc, radius);
- if(attr_intercept)
- attr_intercept->add(time);
-
- num_curve_keys++;
- }
-
- if(attr_random != NULL) {
- attr_random->add(hash_int_01(num_curves));
- }
-
- mesh->add_curve(num_keys, CData->psys_shader[sys]);
- num_keys += num_curve_keys;
- num_curves++;
- }
- }
-
- /* check allocation */
- if((mesh->curve_keys.size() != num_keys) || (mesh->num_curves() != num_curves)) {
- VLOG(1) << "Allocation failed, clearing data";
- mesh->clear();
- }
+ int num_keys = 0;
+ int num_curves = 0;
+
+ if (mesh->num_curves())
+ return;
+
+ Attribute *attr_intercept = NULL;
+ Attribute *attr_random = NULL;
+
+ if (mesh->need_attribute(scene, ATTR_STD_CURVE_INTERCEPT))
+ attr_intercept = mesh->curve_attributes.add(ATTR_STD_CURVE_INTERCEPT);
+ if (mesh->need_attribute(scene, ATTR_STD_CURVE_RANDOM))
+ attr_random = mesh->curve_attributes.add(ATTR_STD_CURVE_RANDOM);
+
+ /* compute and reserve size of arrays */
+ for (int sys = 0; sys < CData->psys_firstcurve.size(); sys++) {
+ for (int curve = CData->psys_firstcurve[sys];
+ curve < CData->psys_firstcurve[sys] + CData->psys_curvenum[sys];
+ curve++) {
+ num_keys += CData->curve_keynum[curve];
+ num_curves++;
+ }
+ }
+
+ if (num_curves > 0) {
+ VLOG(1) << "Exporting curve segments for mesh " << mesh->name;
+ }
+
+ mesh->reserve_curves(mesh->num_curves() + num_curves, mesh->curve_keys.size() + num_keys);
+
+ num_keys = 0;
+ num_curves = 0;
+
+ /* actually export */
+ for (int sys = 0; sys < CData->psys_firstcurve.size(); sys++) {
+ for (int curve = CData->psys_firstcurve[sys];
+ curve < CData->psys_firstcurve[sys] + CData->psys_curvenum[sys];
+ curve++) {
+ size_t num_curve_keys = 0;
+
+ for (int curvekey = CData->curve_firstkey[curve];
+ curvekey < CData->curve_firstkey[curve] + CData->curve_keynum[curve];
+ curvekey++) {
+ const float3 ickey_loc = CData->curvekey_co[curvekey];
+ const float curve_time = CData->curvekey_time[curvekey];
+ const float curve_length = CData->curve_length[curve];
+ const float time = (curve_length > 0.0f) ? curve_time / curve_length : 0.0f;
+ float radius = shaperadius(
+ CData->psys_shape[sys], CData->psys_rootradius[sys], CData->psys_tipradius[sys], time);
+ if (CData->psys_closetip[sys] &&
+ (curvekey == CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 1)) {
+ radius = 0.0f;
+ }
+ mesh->add_curve_key(ickey_loc, radius);
+ if (attr_intercept)
+ attr_intercept->add(time);
+
+ num_curve_keys++;
+ }
+
+ if (attr_random != NULL) {
+ attr_random->add(hash_int_01(num_curves));
+ }
+
+ mesh->add_curve(num_keys, CData->psys_shader[sys]);
+ num_keys += num_curve_keys;
+ num_curves++;
+ }
+ }
+
+ /* check allocation */
+ if ((mesh->curve_keys.size() != num_keys) || (mesh->num_curves() != num_curves)) {
+ VLOG(1) << "Allocation failed, clearing data";
+ mesh->clear();
+ }
}
static float4 CurveSegmentMotionCV(ParticleCurveData *CData, int sys, int curve, int curvekey)
{
- const float3 ickey_loc = CData->curvekey_co[curvekey];
- const float curve_time = CData->curvekey_time[curvekey];
- const float curve_length = CData->curve_length[curve];
- float time = (curve_length > 0.0f) ? curve_time / curve_length : 0.0f;
- float radius = shaperadius(CData->psys_shape[sys], CData->psys_rootradius[sys], CData->psys_tipradius[sys], time);
-
- if(CData->psys_closetip[sys] && (curvekey == CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 1))
- radius = 0.0f;
-
- /* curve motion keys store both position and radius in float4 */
- float4 mP = float3_to_float4(ickey_loc);
- mP.w = radius;
- return mP;
+ const float3 ickey_loc = CData->curvekey_co[curvekey];
+ const float curve_time = CData->curvekey_time[curvekey];
+ const float curve_length = CData->curve_length[curve];
+ float time = (curve_length > 0.0f) ? curve_time / curve_length : 0.0f;
+ float radius = shaperadius(
+ CData->psys_shape[sys], CData->psys_rootradius[sys], CData->psys_tipradius[sys], time);
+
+ if (CData->psys_closetip[sys] &&
+ (curvekey == CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 1))
+ radius = 0.0f;
+
+ /* curve motion keys store both position and radius in float4 */
+ float4 mP = float3_to_float4(ickey_loc);
+ mP.w = radius;
+ return mP;
}
static float4 LerpCurveSegmentMotionCV(ParticleCurveData *CData, int sys, int curve, float step)
{
- assert(step >= 0.0f);
- assert(step <= 1.0f);
- const int first_curve_key = CData->curve_firstkey[curve];
- const float curve_key_f = step * (CData->curve_keynum[curve] - 1);
- int curvekey = (int)floorf(curve_key_f);
- const float remainder = curve_key_f - curvekey;
- if(remainder == 0.0f) {
- return CurveSegmentMotionCV(CData, sys, curve, first_curve_key + curvekey);
- }
- int curvekey2 = curvekey + 1;
- if(curvekey2 >= (CData->curve_keynum[curve] - 1)) {
- curvekey2 = (CData->curve_keynum[curve] - 1);
- curvekey = curvekey2 - 1;
- }
- const float4 mP = CurveSegmentMotionCV(
- CData, sys, curve, first_curve_key + curvekey);
- const float4 mP2 = CurveSegmentMotionCV(
- CData, sys, curve, first_curve_key + curvekey2);
- return lerp(mP, mP2, remainder);
+ assert(step >= 0.0f);
+ assert(step <= 1.0f);
+ const int first_curve_key = CData->curve_firstkey[curve];
+ const float curve_key_f = step * (CData->curve_keynum[curve] - 1);
+ int curvekey = (int)floorf(curve_key_f);
+ const float remainder = curve_key_f - curvekey;
+ if (remainder == 0.0f) {
+ return CurveSegmentMotionCV(CData, sys, curve, first_curve_key + curvekey);
+ }
+ int curvekey2 = curvekey + 1;
+ if (curvekey2 >= (CData->curve_keynum[curve] - 1)) {
+ curvekey2 = (CData->curve_keynum[curve] - 1);
+ curvekey = curvekey2 - 1;
+ }
+ const float4 mP = CurveSegmentMotionCV(CData, sys, curve, first_curve_key + curvekey);
+ const float4 mP2 = CurveSegmentMotionCV(CData, sys, curve, first_curve_key + curvekey2);
+ return lerp(mP, mP2, remainder);
}
static void ExportCurveSegmentsMotion(Mesh *mesh, ParticleCurveData *CData, int motion_step)
{
- VLOG(1) << "Exporting curve motion segments for mesh " << mesh->name
- << ", motion step " << motion_step;
-
- /* find attribute */
- Attribute *attr_mP = mesh->curve_attributes.find(ATTR_STD_MOTION_VERTEX_POSITION);
- bool new_attribute = false;
-
- /* add new attribute if it doesn't exist already */
- if(!attr_mP) {
- VLOG(1) << "Creating new motion vertex position attribute";
- attr_mP = mesh->curve_attributes.add(ATTR_STD_MOTION_VERTEX_POSITION);
- new_attribute = true;
- }
-
- /* export motion vectors for curve keys */
- size_t numkeys = mesh->curve_keys.size();
- float4 *mP = attr_mP->data_float4() + motion_step*numkeys;
- bool have_motion = false;
- int i = 0;
- int num_curves = 0;
-
- for(int sys = 0; sys < CData->psys_firstcurve.size(); sys++) {
- for(int curve = CData->psys_firstcurve[sys]; curve < CData->psys_firstcurve[sys] + CData->psys_curvenum[sys]; curve++) {
- /* Curve lengths may not match! Curves can be clipped. */
- int curve_key_end = (num_curves+1 < (int)mesh->curve_first_key.size() ? mesh->curve_first_key[num_curves+1] : (int)mesh->curve_keys.size());
- const int num_center_curve_keys = curve_key_end - mesh->curve_first_key[num_curves];
- const int is_num_keys_different = CData->curve_keynum[curve] - num_center_curve_keys;
-
- if(!is_num_keys_different) {
- for(int curvekey = CData->curve_firstkey[curve]; curvekey < CData->curve_firstkey[curve] + CData->curve_keynum[curve]; curvekey++) {
- if(i < mesh->curve_keys.size()) {
- mP[i] = CurveSegmentMotionCV(CData, sys, curve, curvekey);
- if(!have_motion) {
- /* unlike mesh coordinates, these tend to be slightly different
- * between frames due to particle transforms into/out of object
- * space, so we use an epsilon to detect actual changes */
- float4 curve_key = float3_to_float4(mesh->curve_keys[i]);
- curve_key.w = mesh->curve_radius[i];
- if(len_squared(mP[i] - curve_key) > 1e-5f*1e-5f)
- have_motion = true;
- }
- }
- i++;
- }
- }
- else {
- /* Number of keys has changed. Genereate an interpolated version
- * to preserve motion blur. */
- const float step_size =
- num_center_curve_keys > 1
- ? 1.0f / (num_center_curve_keys - 1)
- : 0.0f;
- for(int step_index = 0;
- step_index < num_center_curve_keys;
- ++step_index)
- {
- const float step = step_index * step_size;
- mP[i] = LerpCurveSegmentMotionCV(CData, sys, curve, step);
- i++;
- }
- have_motion = true;
- }
- num_curves++;
- }
- }
-
- /* in case of new attribute, we verify if there really was any motion */
- if(new_attribute) {
- if(i != numkeys || !have_motion) {
- /* No motion or hair "topology" changed, remove attributes again. */
- if(i != numkeys) {
- VLOG(1) << "Hair topology changed, removing attribute.";
- }
- else {
- VLOG(1) << "No motion, removing attribute.";
- }
- mesh->curve_attributes.remove(ATTR_STD_MOTION_VERTEX_POSITION);
- }
- else if(motion_step > 0) {
- VLOG(1) << "Filling in new motion vertex position for motion_step "
- << motion_step;
- /* motion, fill up previous steps that we might have skipped because
- * they had no motion, but we need them anyway now */
- for(int step = 0; step < motion_step; step++) {
- float4 *mP = attr_mP->data_float4() + step*numkeys;
-
- for(int key = 0; key < numkeys; key++) {
- mP[key] = float3_to_float4(mesh->curve_keys[key]);
- mP[key].w = mesh->curve_radius[key];
- }
- }
- }
- }
+ VLOG(1) << "Exporting curve motion segments for mesh " << mesh->name << ", motion step "
+ << motion_step;
+
+ /* find attribute */
+ Attribute *attr_mP = mesh->curve_attributes.find(ATTR_STD_MOTION_VERTEX_POSITION);
+ bool new_attribute = false;
+
+ /* add new attribute if it doesn't exist already */
+ if (!attr_mP) {
+ VLOG(1) << "Creating new motion vertex position attribute";
+ attr_mP = mesh->curve_attributes.add(ATTR_STD_MOTION_VERTEX_POSITION);
+ new_attribute = true;
+ }
+
+ /* export motion vectors for curve keys */
+ size_t numkeys = mesh->curve_keys.size();
+ float4 *mP = attr_mP->data_float4() + motion_step * numkeys;
+ bool have_motion = false;
+ int i = 0;
+ int num_curves = 0;
+
+ for (int sys = 0; sys < CData->psys_firstcurve.size(); sys++) {
+ for (int curve = CData->psys_firstcurve[sys];
+ curve < CData->psys_firstcurve[sys] + CData->psys_curvenum[sys];
+ curve++) {
+ /* Curve lengths may not match! Curves can be clipped. */
+ int curve_key_end = (num_curves + 1 < (int)mesh->curve_first_key.size() ?
+ mesh->curve_first_key[num_curves + 1] :
+ (int)mesh->curve_keys.size());
+ const int num_center_curve_keys = curve_key_end - mesh->curve_first_key[num_curves];
+ const int is_num_keys_different = CData->curve_keynum[curve] - num_center_curve_keys;
+
+ if (!is_num_keys_different) {
+ for (int curvekey = CData->curve_firstkey[curve];
+ curvekey < CData->curve_firstkey[curve] + CData->curve_keynum[curve];
+ curvekey++) {
+ if (i < mesh->curve_keys.size()) {
+ mP[i] = CurveSegmentMotionCV(CData, sys, curve, curvekey);
+ if (!have_motion) {
+ /* unlike mesh coordinates, these tend to be slightly different
+ * between frames due to particle transforms into/out of object
+ * space, so we use an epsilon to detect actual changes */
+ float4 curve_key = float3_to_float4(mesh->curve_keys[i]);
+ curve_key.w = mesh->curve_radius[i];
+ if (len_squared(mP[i] - curve_key) > 1e-5f * 1e-5f)
+ have_motion = true;
+ }
+ }
+ i++;
+ }
+ }
+ else {
+ /* Number of keys has changed. Genereate an interpolated version
+ * to preserve motion blur. */
+ const float step_size = num_center_curve_keys > 1 ? 1.0f / (num_center_curve_keys - 1) :
+ 0.0f;
+ for (int step_index = 0; step_index < num_center_curve_keys; ++step_index) {
+ const float step = step_index * step_size;
+ mP[i] = LerpCurveSegmentMotionCV(CData, sys, curve, step);
+ i++;
+ }
+ have_motion = true;
+ }
+ num_curves++;
+ }
+ }
+
+ /* in case of new attribute, we verify if there really was any motion */
+ if (new_attribute) {
+ if (i != numkeys || !have_motion) {
+ /* No motion or hair "topology" changed, remove attributes again. */
+ if (i != numkeys) {
+ VLOG(1) << "Hair topology changed, removing attribute.";
+ }
+ else {
+ VLOG(1) << "No motion, removing attribute.";
+ }
+ mesh->curve_attributes.remove(ATTR_STD_MOTION_VERTEX_POSITION);
+ }
+ else if (motion_step > 0) {
+ VLOG(1) << "Filling in new motion vertex position for motion_step " << motion_step;
+ /* motion, fill up previous steps that we might have skipped because
+ * they had no motion, but we need them anyway now */
+ for (int step = 0; step < motion_step; step++) {
+ float4 *mP = attr_mP->data_float4() + step * numkeys;
+
+ for (int key = 0; key < numkeys; key++) {
+ mP[key] = float3_to_float4(mesh->curve_keys[key]);
+ mP[key].w = mesh->curve_radius[key];
+ }
+ }
+ }
+ }
}
static void ExportCurveTriangleUV(ParticleCurveData *CData,
@@ -754,30 +814,34 @@ static void ExportCurveTriangleUV(ParticleCurveData *CData,
int resol,
float2 *uvdata)
{
- if(uvdata == NULL)
- return;
- int vertexindex = vert_offset;
-
- for(int sys = 0; sys < CData->psys_firstcurve.size(); sys++) {
- for(int curve = CData->psys_firstcurve[sys]; curve < CData->psys_firstcurve[sys] + CData->psys_curvenum[sys]; curve++) {
- 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++) {
- uvdata[vertexindex] = CData->curve_uv[curve];
- vertexindex++;
- uvdata[vertexindex] = CData->curve_uv[curve];
- vertexindex++;
- uvdata[vertexindex] = CData->curve_uv[curve];
- vertexindex++;
- uvdata[vertexindex] = CData->curve_uv[curve];
- vertexindex++;
- uvdata[vertexindex] = CData->curve_uv[curve];
- vertexindex++;
- uvdata[vertexindex] = CData->curve_uv[curve];
- vertexindex++;
- }
- }
- }
- }
+ if (uvdata == NULL)
+ return;
+ int vertexindex = vert_offset;
+
+ for (int sys = 0; sys < CData->psys_firstcurve.size(); sys++) {
+ for (int curve = CData->psys_firstcurve[sys];
+ curve < CData->psys_firstcurve[sys] + CData->psys_curvenum[sys];
+ curve++) {
+ 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++) {
+ uvdata[vertexindex] = CData->curve_uv[curve];
+ vertexindex++;
+ uvdata[vertexindex] = CData->curve_uv[curve];
+ vertexindex++;
+ uvdata[vertexindex] = CData->curve_uv[curve];
+ vertexindex++;
+ uvdata[vertexindex] = CData->curve_uv[curve];
+ vertexindex++;
+ uvdata[vertexindex] = CData->curve_uv[curve];
+ vertexindex++;
+ uvdata[vertexindex] = CData->curve_uv[curve];
+ vertexindex++;
+ }
+ }
+ }
+ }
}
static void ExportCurveTriangleVcol(ParticleCurveData *CData,
@@ -785,295 +849,296 @@ static void ExportCurveTriangleVcol(ParticleCurveData *CData,
int resol,
uchar4 *cdata)
{
- if(cdata == NULL)
- return;
-
- int vertexindex = vert_offset;
-
- for(int sys = 0; sys < CData->psys_firstcurve.size(); sys++) {
- for(int curve = CData->psys_firstcurve[sys]; curve < CData->psys_firstcurve[sys] + CData->psys_curvenum[sys]; curve++) {
- 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++) {
- /* Encode vertex color using the sRGB curve. */
- cdata[vertexindex] = color_float_to_byte(color_srgb_to_linear_v3(CData->curve_vcol[curve]));
- vertexindex++;
- cdata[vertexindex] = color_float_to_byte(color_srgb_to_linear_v3(CData->curve_vcol[curve]));
- vertexindex++;
- cdata[vertexindex] = color_float_to_byte(color_srgb_to_linear_v3(CData->curve_vcol[curve]));
- vertexindex++;
- cdata[vertexindex] = color_float_to_byte(color_srgb_to_linear_v3(CData->curve_vcol[curve]));
- vertexindex++;
- cdata[vertexindex] = color_float_to_byte(color_srgb_to_linear_v3(CData->curve_vcol[curve]));
- vertexindex++;
- cdata[vertexindex] = color_float_to_byte(color_srgb_to_linear_v3(CData->curve_vcol[curve]));
- vertexindex++;
- }
- }
- }
- }
+ if (cdata == NULL)
+ return;
+
+ int vertexindex = vert_offset;
+
+ for (int sys = 0; sys < CData->psys_firstcurve.size(); sys++) {
+ for (int curve = CData->psys_firstcurve[sys];
+ curve < CData->psys_firstcurve[sys] + CData->psys_curvenum[sys];
+ curve++) {
+ 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++) {
+ /* Encode vertex color using the sRGB curve. */
+ cdata[vertexindex] = color_float_to_byte(
+ color_srgb_to_linear_v3(CData->curve_vcol[curve]));
+ vertexindex++;
+ cdata[vertexindex] = color_float_to_byte(
+ color_srgb_to_linear_v3(CData->curve_vcol[curve]));
+ vertexindex++;
+ cdata[vertexindex] = color_float_to_byte(
+ color_srgb_to_linear_v3(CData->curve_vcol[curve]));
+ vertexindex++;
+ cdata[vertexindex] = color_float_to_byte(
+ color_srgb_to_linear_v3(CData->curve_vcol[curve]));
+ vertexindex++;
+ cdata[vertexindex] = color_float_to_byte(
+ color_srgb_to_linear_v3(CData->curve_vcol[curve]));
+ vertexindex++;
+ cdata[vertexindex] = color_float_to_byte(
+ color_srgb_to_linear_v3(CData->curve_vcol[curve]));
+ vertexindex++;
+ }
+ }
+ }
+ }
}
/* Hair Curve Sync */
void BlenderSync::sync_curve_settings()
{
- PointerRNA csscene = RNA_pointer_get(&b_scene.ptr, "cycles_curves");
-
- CurveSystemManager *curve_system_manager = scene->curve_system_manager;
- CurveSystemManager prev_curve_system_manager = *curve_system_manager;
-
- curve_system_manager->use_curves = get_boolean(csscene, "use_curves");
- curve_system_manager->minimum_width = get_float(csscene, "minimum_width");
- curve_system_manager->maximum_width = get_float(csscene, "maximum_width");
-
- curve_system_manager->primitive =
- (CurvePrimitiveType)get_enum(csscene,
- "primitive",
- CURVE_NUM_PRIMITIVE_TYPES,
- CURVE_LINE_SEGMENTS);
- curve_system_manager->curve_shape =
- (CurveShapeType)get_enum(csscene,
- "shape",
- CURVE_NUM_SHAPE_TYPES,
- CURVE_THICK);
- curve_system_manager->resolution = get_int(csscene, "resolution");
- curve_system_manager->subdivisions = get_int(csscene, "subdivisions");
- curve_system_manager->use_backfacing = !get_boolean(csscene, "cull_backfacing");
-
- /* Triangles */
- if(curve_system_manager->primitive == CURVE_TRIANGLES) {
- /* camera facing planes */
- if(curve_system_manager->curve_shape == CURVE_RIBBON) {
- curve_system_manager->triangle_method = CURVE_CAMERA_TRIANGLES;
- curve_system_manager->resolution = 1;
- }
- else if(curve_system_manager->curve_shape == CURVE_THICK) {
- curve_system_manager->triangle_method = CURVE_TESSELATED_TRIANGLES;
- }
- }
- /* Line Segments */
- else if(curve_system_manager->primitive == CURVE_LINE_SEGMENTS) {
- if(curve_system_manager->curve_shape == CURVE_RIBBON) {
- /* tangent shading */
- curve_system_manager->line_method = CURVE_UNCORRECTED;
- curve_system_manager->use_encasing = true;
- curve_system_manager->use_backfacing = false;
- curve_system_manager->use_tangent_normal_geometry = true;
- }
- else if(curve_system_manager->curve_shape == CURVE_THICK) {
- curve_system_manager->line_method = CURVE_ACCURATE;
- curve_system_manager->use_encasing = false;
- curve_system_manager->use_tangent_normal_geometry = false;
- }
- }
- /* Curve Segments */
- else if(curve_system_manager->primitive == CURVE_SEGMENTS) {
- if(curve_system_manager->curve_shape == CURVE_RIBBON) {
- curve_system_manager->primitive = CURVE_RIBBONS;
- curve_system_manager->use_backfacing = false;
- }
- }
-
- if(curve_system_manager->modified_mesh(prev_curve_system_manager)) {
- BL::BlendData::objects_iterator b_ob;
-
- for(b_data.objects.begin(b_ob); b_ob != b_data.objects.end(); ++b_ob) {
- if(object_is_mesh(*b_ob)) {
- BL::Object::particle_systems_iterator b_psys;
- for(b_ob->particle_systems.begin(b_psys); b_psys != b_ob->particle_systems.end(); ++b_psys) {
- if((b_psys->settings().render_type()==BL::ParticleSettings::render_type_PATH)&&(b_psys->settings().type()==BL::ParticleSettings::type_HAIR)) {
- BL::ID key = BKE_object_is_modified(*b_ob)? *b_ob: b_ob->data();
- mesh_map.set_recalc(key);
- object_map.set_recalc(*b_ob);
- }
- }
- }
- }
- }
-
- if(curve_system_manager->modified(prev_curve_system_manager))
- curve_system_manager->tag_update(scene);
+ PointerRNA csscene = RNA_pointer_get(&b_scene.ptr, "cycles_curves");
+
+ CurveSystemManager *curve_system_manager = scene->curve_system_manager;
+ CurveSystemManager prev_curve_system_manager = *curve_system_manager;
+
+ curve_system_manager->use_curves = get_boolean(csscene, "use_curves");
+ curve_system_manager->minimum_width = get_float(csscene, "minimum_width");
+ curve_system_manager->maximum_width = get_float(csscene, "maximum_width");
+
+ curve_system_manager->primitive = (CurvePrimitiveType)get_enum(
+ csscene, "primitive", CURVE_NUM_PRIMITIVE_TYPES, CURVE_LINE_SEGMENTS);
+ curve_system_manager->curve_shape = (CurveShapeType)get_enum(
+ csscene, "shape", CURVE_NUM_SHAPE_TYPES, CURVE_THICK);
+ curve_system_manager->resolution = get_int(csscene, "resolution");
+ curve_system_manager->subdivisions = get_int(csscene, "subdivisions");
+ curve_system_manager->use_backfacing = !get_boolean(csscene, "cull_backfacing");
+
+ /* Triangles */
+ if (curve_system_manager->primitive == CURVE_TRIANGLES) {
+ /* camera facing planes */
+ if (curve_system_manager->curve_shape == CURVE_RIBBON) {
+ curve_system_manager->triangle_method = CURVE_CAMERA_TRIANGLES;
+ curve_system_manager->resolution = 1;
+ }
+ else if (curve_system_manager->curve_shape == CURVE_THICK) {
+ curve_system_manager->triangle_method = CURVE_TESSELATED_TRIANGLES;
+ }
+ }
+ /* Line Segments */
+ else if (curve_system_manager->primitive == CURVE_LINE_SEGMENTS) {
+ if (curve_system_manager->curve_shape == CURVE_RIBBON) {
+ /* tangent shading */
+ curve_system_manager->line_method = CURVE_UNCORRECTED;
+ curve_system_manager->use_encasing = true;
+ curve_system_manager->use_backfacing = false;
+ curve_system_manager->use_tangent_normal_geometry = true;
+ }
+ else if (curve_system_manager->curve_shape == CURVE_THICK) {
+ curve_system_manager->line_method = CURVE_ACCURATE;
+ curve_system_manager->use_encasing = false;
+ curve_system_manager->use_tangent_normal_geometry = false;
+ }
+ }
+ /* Curve Segments */
+ else if (curve_system_manager->primitive == CURVE_SEGMENTS) {
+ if (curve_system_manager->curve_shape == CURVE_RIBBON) {
+ curve_system_manager->primitive = CURVE_RIBBONS;
+ curve_system_manager->use_backfacing = false;
+ }
+ }
+
+ if (curve_system_manager->modified_mesh(prev_curve_system_manager)) {
+ BL::BlendData::objects_iterator b_ob;
+
+ for (b_data.objects.begin(b_ob); b_ob != b_data.objects.end(); ++b_ob) {
+ if (object_is_mesh(*b_ob)) {
+ BL::Object::particle_systems_iterator b_psys;
+ for (b_ob->particle_systems.begin(b_psys); b_psys != b_ob->particle_systems.end();
+ ++b_psys) {
+ if ((b_psys->settings().render_type() == BL::ParticleSettings::render_type_PATH) &&
+ (b_psys->settings().type() == BL::ParticleSettings::type_HAIR)) {
+ BL::ID key = BKE_object_is_modified(*b_ob) ? *b_ob : b_ob->data();
+ mesh_map.set_recalc(key);
+ object_map.set_recalc(*b_ob);
+ }
+ }
+ }
+ }
+ }
+
+ if (curve_system_manager->modified(prev_curve_system_manager))
+ curve_system_manager->tag_update(scene);
}
-void BlenderSync::sync_curves(Mesh *mesh,
- BL::Mesh& b_mesh,
- BL::Object& b_ob,
- bool motion,
- int motion_step)
+void BlenderSync::sync_curves(
+ Mesh *mesh, BL::Mesh &b_mesh, BL::Object &b_ob, bool motion, int motion_step)
{
- if(!motion) {
- /* Clear stored curve data */
- mesh->curve_keys.clear();
- mesh->curve_radius.clear();
- mesh->curve_first_key.clear();
- mesh->curve_shader.clear();
- mesh->curve_attributes.clear();
- }
-
- /* obtain general settings */
- const bool use_curves = scene->curve_system_manager->use_curves;
-
- if(!(use_curves && b_ob.mode() != b_ob.mode_PARTICLE_EDIT)) {
- if(!motion)
- mesh->compute_bounds();
- return;
- }
-
- const int primitive = scene->curve_system_manager->primitive;
- const int triangle_method = scene->curve_system_manager->triangle_method;
- const int resolution = scene->curve_system_manager->resolution;
- const size_t vert_num = mesh->verts.size();
- const size_t tri_num = mesh->num_triangles();
- int used_res = 1;
-
- /* extract particle hair data - should be combined with connecting to mesh later*/
-
- ParticleCurveData CData;
-
- ObtainCacheParticleData(mesh, &b_mesh, &b_ob, &CData, !preview);
-
- /* add hair geometry to mesh */
- if(primitive == CURVE_TRIANGLES) {
- if(triangle_method == CURVE_CAMERA_TRIANGLES) {
- /* obtain camera parameters */
- float3 RotCam;
- Camera *camera = scene->camera;
- Transform &ctfm = camera->matrix;
- if(camera->type == CAMERA_ORTHOGRAPHIC) {
- RotCam = -make_float3(ctfm.x.z, ctfm.y.z, ctfm.z.z);
- }
- else {
- Transform tfm = get_transform(b_ob.matrix_world());
- Transform itfm = transform_quick_inverse(tfm);
- RotCam = transform_point(&itfm, make_float3(ctfm.x.w,
- ctfm.y.w,
- ctfm.z.w));
- }
- bool is_ortho = camera->type == CAMERA_ORTHOGRAPHIC;
- ExportCurveTrianglePlanes(mesh, &CData, RotCam, is_ortho);
- }
- else {
- ExportCurveTriangleGeometry(mesh, &CData, resolution);
- used_res = resolution;
- }
- }
- else {
- if(motion)
- ExportCurveSegmentsMotion(mesh, &CData, motion_step);
- else
- ExportCurveSegments(scene, mesh, &CData);
- }
-
- /* generated coordinates from first key. we should ideally get this from
- * blender to handle deforming objects */
- if(!motion) {
- if(mesh->need_attribute(scene, ATTR_STD_GENERATED)) {
- float3 loc, size;
- mesh_texture_space(b_mesh, loc, size);
-
- if(primitive == CURVE_TRIANGLES) {
- Attribute *attr_generated = mesh->attributes.add(ATTR_STD_GENERATED);
- float3 *generated = attr_generated->data_float3();
-
- for(size_t i = vert_num; i < mesh->verts.size(); i++)
- generated[i] = mesh->verts[i]*size - loc;
- }
- else {
- Attribute *attr_generated = mesh->curve_attributes.add(ATTR_STD_GENERATED);
- float3 *generated = attr_generated->data_float3();
-
- for(size_t i = 0; i < mesh->num_curves(); i++) {
- float3 co = mesh->curve_keys[mesh->get_curve(i).first_key];
- generated[i] = co*size - loc;
- }
- }
- }
- }
-
- /* create vertex color attributes */
- if(!motion) {
- BL::Mesh::vertex_colors_iterator l;
- int vcol_num = 0;
-
- for(b_mesh.vertex_colors.begin(l); l != b_mesh.vertex_colors.end(); ++l, vcol_num++) {
- if(!mesh->need_attribute(scene, ustring(l->name().c_str())))
- continue;
-
- ObtainCacheParticleVcol(mesh, &b_mesh, &b_ob, &CData, !preview, vcol_num);
-
- if(primitive == CURVE_TRIANGLES) {
- Attribute *attr_vcol = mesh->attributes.add(
- ustring(l->name().c_str()), TypeDesc::TypeColor, ATTR_ELEMENT_CORNER_BYTE);
-
- uchar4 *cdata = attr_vcol->data_uchar4();
-
- ExportCurveTriangleVcol(&CData, tri_num * 3, used_res, cdata);
- }
- else {
- Attribute *attr_vcol = mesh->curve_attributes.add(
- ustring(l->name().c_str()), TypeDesc::TypeColor, ATTR_ELEMENT_CURVE);
-
- float3 *fdata = attr_vcol->data_float3();
-
- if(fdata) {
- size_t i = 0;
-
- /* Encode vertex color using the sRGB curve. */
- for(size_t curve = 0; curve < CData.curve_vcol.size(); curve++) {
- fdata[i++] = color_srgb_to_linear_v3(CData.curve_vcol[curve]);
- }
- }
- }
- }
- }
-
- /* create UV attributes */
- if(!motion) {
- BL::Mesh::uv_layers_iterator l;
- int uv_num = 0;
-
- for(b_mesh.uv_layers.begin(l); l != b_mesh.uv_layers.end(); ++l, uv_num++) {
- bool active_render = l->active_render();
- AttributeStandard std = (active_render)? ATTR_STD_UV: ATTR_STD_NONE;
- ustring name = ustring(l->name().c_str());
-
- /* UV map */
- if(mesh->need_attribute(scene, name) || mesh->need_attribute(scene, std)) {
- Attribute *attr_uv;
-
- ObtainCacheParticleUV(mesh, &b_mesh, &b_ob, &CData, !preview, uv_num);
-
- if(primitive == CURVE_TRIANGLES) {
- if(active_render)
- attr_uv = mesh->attributes.add(std, name);
- else
- attr_uv = mesh->attributes.add(name, TypeFloat2, ATTR_ELEMENT_CORNER);
-
- float2 *uv = attr_uv->data_float2();
-
- ExportCurveTriangleUV(&CData, tri_num * 3, used_res, uv);
- }
- else {
- if(active_render)
- attr_uv = mesh->curve_attributes.add(std, name);
- else
- attr_uv = mesh->curve_attributes.add(name, TypeFloat2, ATTR_ELEMENT_CURVE);
-
- float2 *uv = attr_uv->data_float2();
-
- if(uv) {
- size_t i = 0;
-
- for(size_t curve = 0; curve < CData.curve_uv.size(); curve++) {
- uv[i++] = CData.curve_uv[curve];
- }
- }
- }
- }
- }
- }
-
- mesh->compute_bounds();
+ if (!motion) {
+ /* Clear stored curve data */
+ mesh->curve_keys.clear();
+ mesh->curve_radius.clear();
+ mesh->curve_first_key.clear();
+ mesh->curve_shader.clear();
+ mesh->curve_attributes.clear();
+ }
+
+ /* obtain general settings */
+ const bool use_curves = scene->curve_system_manager->use_curves;
+
+ if (!(use_curves && b_ob.mode() != b_ob.mode_PARTICLE_EDIT)) {
+ if (!motion)
+ mesh->compute_bounds();
+ return;
+ }
+
+ const int primitive = scene->curve_system_manager->primitive;
+ const int triangle_method = scene->curve_system_manager->triangle_method;
+ const int resolution = scene->curve_system_manager->resolution;
+ const size_t vert_num = mesh->verts.size();
+ const size_t tri_num = mesh->num_triangles();
+ int used_res = 1;
+
+ /* extract particle hair data - should be combined with connecting to mesh later*/
+
+ ParticleCurveData CData;
+
+ ObtainCacheParticleData(mesh, &b_mesh, &b_ob, &CData, !preview);
+
+ /* add hair geometry to mesh */
+ if (primitive == CURVE_TRIANGLES) {
+ if (triangle_method == CURVE_CAMERA_TRIANGLES) {
+ /* obtain camera parameters */
+ float3 RotCam;
+ Camera *camera = scene->camera;
+ Transform &ctfm = camera->matrix;
+ if (camera->type == CAMERA_ORTHOGRAPHIC) {
+ RotCam = -make_float3(ctfm.x.z, ctfm.y.z, ctfm.z.z);
+ }
+ else {
+ Transform tfm = get_transform(b_ob.matrix_world());
+ Transform itfm = transform_quick_inverse(tfm);
+ RotCam = transform_point(&itfm, make_float3(ctfm.x.w, ctfm.y.w, ctfm.z.w));
+ }
+ bool is_ortho = camera->type == CAMERA_ORTHOGRAPHIC;
+ ExportCurveTrianglePlanes(mesh, &CData, RotCam, is_ortho);
+ }
+ else {
+ ExportCurveTriangleGeometry(mesh, &CData, resolution);
+ used_res = resolution;
+ }
+ }
+ else {
+ if (motion)
+ ExportCurveSegmentsMotion(mesh, &CData, motion_step);
+ else
+ ExportCurveSegments(scene, mesh, &CData);
+ }
+
+ /* generated coordinates from first key. we should ideally get this from
+ * blender to handle deforming objects */
+ if (!motion) {
+ if (mesh->need_attribute(scene, ATTR_STD_GENERATED)) {
+ float3 loc, size;
+ mesh_texture_space(b_mesh, loc, size);
+
+ if (primitive == CURVE_TRIANGLES) {
+ Attribute *attr_generated = mesh->attributes.add(ATTR_STD_GENERATED);
+ float3 *generated = attr_generated->data_float3();
+
+ for (size_t i = vert_num; i < mesh->verts.size(); i++)
+ generated[i] = mesh->verts[i] * size - loc;
+ }
+ else {
+ Attribute *attr_generated = mesh->curve_attributes.add(ATTR_STD_GENERATED);
+ float3 *generated = attr_generated->data_float3();
+
+ for (size_t i = 0; i < mesh->num_curves(); i++) {
+ float3 co = mesh->curve_keys[mesh->get_curve(i).first_key];
+ generated[i] = co * size - loc;
+ }
+ }
+ }
+ }
+
+ /* create vertex color attributes */
+ if (!motion) {
+ BL::Mesh::vertex_colors_iterator l;
+ int vcol_num = 0;
+
+ for (b_mesh.vertex_colors.begin(l); l != b_mesh.vertex_colors.end(); ++l, vcol_num++) {
+ if (!mesh->need_attribute(scene, ustring(l->name().c_str())))
+ continue;
+
+ ObtainCacheParticleVcol(mesh, &b_mesh, &b_ob, &CData, !preview, vcol_num);
+
+ if (primitive == CURVE_TRIANGLES) {
+ Attribute *attr_vcol = mesh->attributes.add(
+ ustring(l->name().c_str()), TypeDesc::TypeColor, ATTR_ELEMENT_CORNER_BYTE);
+
+ uchar4 *cdata = attr_vcol->data_uchar4();
+
+ ExportCurveTriangleVcol(&CData, tri_num * 3, used_res, cdata);
+ }
+ else {
+ Attribute *attr_vcol = mesh->curve_attributes.add(
+ ustring(l->name().c_str()), TypeDesc::TypeColor, ATTR_ELEMENT_CURVE);
+
+ float3 *fdata = attr_vcol->data_float3();
+
+ if (fdata) {
+ size_t i = 0;
+
+ /* Encode vertex color using the sRGB curve. */
+ for (size_t curve = 0; curve < CData.curve_vcol.size(); curve++) {
+ fdata[i++] = color_srgb_to_linear_v3(CData.curve_vcol[curve]);
+ }
+ }
+ }
+ }
+ }
+
+ /* create UV attributes */
+ if (!motion) {
+ BL::Mesh::uv_layers_iterator l;
+ int uv_num = 0;
+
+ for (b_mesh.uv_layers.begin(l); l != b_mesh.uv_layers.end(); ++l, uv_num++) {
+ bool active_render = l->active_render();
+ AttributeStandard std = (active_render) ? ATTR_STD_UV : ATTR_STD_NONE;
+ ustring name = ustring(l->name().c_str());
+
+ /* UV map */
+ if (mesh->need_attribute(scene, name) || mesh->need_attribute(scene, std)) {
+ Attribute *attr_uv;
+
+ ObtainCacheParticleUV(mesh, &b_mesh, &b_ob, &CData, !preview, uv_num);
+
+ if (primitive == CURVE_TRIANGLES) {
+ if (active_render)
+ attr_uv = mesh->attributes.add(std, name);
+ else
+ attr_uv = mesh->attributes.add(name, TypeFloat2, ATTR_ELEMENT_CORNER);
+
+ float2 *uv = attr_uv->data_float2();
+
+ ExportCurveTriangleUV(&CData, tri_num * 3, used_res, uv);
+ }
+ else {
+ if (active_render)
+ attr_uv = mesh->curve_attributes.add(std, name);
+ else
+ attr_uv = mesh->curve_attributes.add(name, TypeFloat2, ATTR_ELEMENT_CURVE);
+
+ float2 *uv = attr_uv->data_float2();
+
+ if (uv) {
+ size_t i = 0;
+
+ for (size_t curve = 0; curve < CData.curve_uv.size(); curve++) {
+ uv[i++] = CData.curve_uv[curve];
+ }
+ }
+ }
+ }
+ }
+ }
+
+ mesh->compute_bounds();
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/blender/blender_device.cpp b/intern/cycles/blender/blender_device.cpp
index 969601b1c37..98fc0c6dec4 100644
--- a/intern/cycles/blender/blender_device.cpp
+++ b/intern/cycles/blender/blender_device.cpp
@@ -19,91 +19,89 @@
CCL_NAMESPACE_BEGIN
-int blender_device_threads(BL::Scene& b_scene)
+int blender_device_threads(BL::Scene &b_scene)
{
- BL::RenderSettings b_r = b_scene.render();
+ BL::RenderSettings b_r = b_scene.render();
- if(b_r.threads_mode() == BL::RenderSettings::threads_mode_FIXED)
- return b_r.threads();
- else
- return 0;
+ if (b_r.threads_mode() == BL::RenderSettings::threads_mode_FIXED)
+ return b_r.threads();
+ else
+ return 0;
}
-DeviceInfo blender_device_info(BL::Preferences& b_preferences, BL::Scene& b_scene, bool background)
+DeviceInfo blender_device_info(BL::Preferences &b_preferences, BL::Scene &b_scene, bool background)
{
- PointerRNA cscene = RNA_pointer_get(&b_scene.ptr, "cycles");
+ PointerRNA cscene = RNA_pointer_get(&b_scene.ptr, "cycles");
- /* Default to CPU device. */
- DeviceInfo device = Device::available_devices(DEVICE_MASK_CPU).front();
+ /* Default to CPU device. */
+ DeviceInfo device = Device::available_devices(DEVICE_MASK_CPU).front();
- if(get_enum(cscene, "device") == 2) {
- /* Find network device. */
- vector<DeviceInfo> devices = Device::available_devices(DEVICE_MASK_NETWORK);
- if(!devices.empty()) {
- device = devices.front();
- }
- }
- else if(get_enum(cscene, "device") == 1) {
- /* Find cycles preferences. */
- PointerRNA cpreferences;
+ if (get_enum(cscene, "device") == 2) {
+ /* Find network device. */
+ vector<DeviceInfo> devices = Device::available_devices(DEVICE_MASK_NETWORK);
+ if (!devices.empty()) {
+ device = devices.front();
+ }
+ }
+ else if (get_enum(cscene, "device") == 1) {
+ /* Find cycles preferences. */
+ PointerRNA cpreferences;
- BL::Preferences::addons_iterator b_addon_iter;
- for(b_preferences.addons.begin(b_addon_iter); b_addon_iter != b_preferences.addons.end(); ++b_addon_iter) {
- if(b_addon_iter->module() == "cycles") {
- cpreferences = b_addon_iter->preferences().ptr;
- break;
- }
- }
+ BL::Preferences::addons_iterator b_addon_iter;
+ for (b_preferences.addons.begin(b_addon_iter); b_addon_iter != b_preferences.addons.end();
+ ++b_addon_iter) {
+ if (b_addon_iter->module() == "cycles") {
+ cpreferences = b_addon_iter->preferences().ptr;
+ break;
+ }
+ }
- /* Test if we are using GPU devices. */
- enum ComputeDevice {
- COMPUTE_DEVICE_CPU = 0,
- COMPUTE_DEVICE_CUDA = 1,
- COMPUTE_DEVICE_OPENCL = 2,
- COMPUTE_DEVICE_NUM = 3,
- };
+ /* Test if we are using GPU devices. */
+ enum ComputeDevice {
+ COMPUTE_DEVICE_CPU = 0,
+ COMPUTE_DEVICE_CUDA = 1,
+ COMPUTE_DEVICE_OPENCL = 2,
+ COMPUTE_DEVICE_NUM = 3,
+ };
- ComputeDevice compute_device = (ComputeDevice)get_enum(cpreferences,
- "compute_device_type",
- COMPUTE_DEVICE_NUM,
- COMPUTE_DEVICE_CPU);
+ ComputeDevice compute_device = (ComputeDevice)get_enum(
+ cpreferences, "compute_device_type", COMPUTE_DEVICE_NUM, COMPUTE_DEVICE_CPU);
- if(compute_device != COMPUTE_DEVICE_CPU) {
- /* Query GPU devices with matching types. */
- uint mask = DEVICE_MASK_CPU;
- if(compute_device == COMPUTE_DEVICE_CUDA) {
- mask |= DEVICE_MASK_CUDA;
- }
- else if(compute_device == COMPUTE_DEVICE_OPENCL) {
- mask |= DEVICE_MASK_OPENCL;
- }
- vector<DeviceInfo> devices = Device::available_devices(mask);
+ if (compute_device != COMPUTE_DEVICE_CPU) {
+ /* Query GPU devices with matching types. */
+ uint mask = DEVICE_MASK_CPU;
+ if (compute_device == COMPUTE_DEVICE_CUDA) {
+ mask |= DEVICE_MASK_CUDA;
+ }
+ else if (compute_device == COMPUTE_DEVICE_OPENCL) {
+ mask |= DEVICE_MASK_OPENCL;
+ }
+ vector<DeviceInfo> devices = Device::available_devices(mask);
- /* Match device preferences and available devices. */
- vector<DeviceInfo> used_devices;
- RNA_BEGIN(&cpreferences, device, "devices") {
- if(get_boolean(device, "use")) {
- string id = get_string(device, "id");
- foreach(DeviceInfo& info, devices) {
- if(info.id == id) {
- used_devices.push_back(info);
- break;
- }
- }
- }
- } RNA_END;
+ /* Match device preferences and available devices. */
+ vector<DeviceInfo> used_devices;
+ RNA_BEGIN (&cpreferences, device, "devices") {
+ if (get_boolean(device, "use")) {
+ string id = get_string(device, "id");
+ foreach (DeviceInfo &info, devices) {
+ if (info.id == id) {
+ used_devices.push_back(info);
+ break;
+ }
+ }
+ }
+ }
+ RNA_END;
- if(!used_devices.empty()) {
- int threads = blender_device_threads(b_scene);
- device = Device::get_multi_device(used_devices,
- threads,
- background);
- }
- /* Else keep using the CPU device that was set before. */
- }
- }
+ if (!used_devices.empty()) {
+ int threads = blender_device_threads(b_scene);
+ device = Device::get_multi_device(used_devices, threads, background);
+ }
+ /* Else keep using the CPU device that was set before. */
+ }
+ }
- return device;
+ return device;
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/blender/blender_device.h b/intern/cycles/blender/blender_device.h
index 061020936e2..fd6c045c966 100644
--- a/intern/cycles/blender/blender_device.h
+++ b/intern/cycles/blender/blender_device.h
@@ -27,11 +27,13 @@
CCL_NAMESPACE_BEGIN
/* Get number of threads to use for rendering. */
-int blender_device_threads(BL::Scene& b_scene);
+int blender_device_threads(BL::Scene &b_scene);
/* Convert Blender settings to device specification. */
-DeviceInfo blender_device_info(BL::Preferences& b_preferences, BL::Scene& b_scene, bool background);
+DeviceInfo blender_device_info(BL::Preferences &b_preferences,
+ BL::Scene &b_scene,
+ bool background);
CCL_NAMESPACE_END
-#endif /* __BLENDER_DEVICE_H__ */
+#endif /* __BLENDER_DEVICE_H__ */
diff --git a/intern/cycles/blender/blender_logging.cpp b/intern/cycles/blender/blender_logging.cpp
index 3fca4efd097..b42a1f47821 100644
--- a/intern/cycles/blender/blender_logging.cpp
+++ b/intern/cycles/blender/blender_logging.cpp
@@ -19,15 +19,15 @@
void CCL_init_logging(const char *argv0)
{
- ccl::util_logging_init(argv0);
+ ccl::util_logging_init(argv0);
}
void CCL_start_debug_logging()
{
- ccl::util_logging_start();
+ ccl::util_logging_start();
}
void CCL_logging_verbosity_set(int verbosity)
{
- ccl::util_logging_verbosity_set(verbosity);
+ ccl::util_logging_verbosity_set(verbosity);
}
diff --git a/intern/cycles/blender/blender_mesh.cpp b/intern/cycles/blender/blender_mesh.cpp
index 9b2c2c8e5d5..de594f4fb6c 100644
--- a/intern/cycles/blender/blender_mesh.cpp
+++ b/intern/cycles/blender/blender_mesh.cpp
@@ -38,1241 +38,1174 @@ CCL_NAMESPACE_BEGIN
/* Tangent Space */
struct MikkUserData {
- MikkUserData(const BL::Mesh& b_mesh,
- const char *layer_name,
- const Mesh *mesh,
- float3 *tangent,
- float *tangent_sign)
- : mesh(mesh),
- texface(NULL),
- orco(NULL),
- tangent(tangent),
- tangent_sign(tangent_sign)
- {
- const AttributeSet& attributes = (mesh->subd_faces.size()) ?
- mesh->subd_attributes : mesh->attributes;
-
- Attribute *attr_vN = attributes.find(ATTR_STD_VERTEX_NORMAL);
- vertex_normal = attr_vN->data_float3();
-
- if(layer_name == NULL) {
- Attribute *attr_orco = attributes.find(ATTR_STD_GENERATED);
-
- if(attr_orco) {
- orco = attr_orco->data_float3();
- mesh_texture_space(*(BL::Mesh*)&b_mesh, orco_loc, orco_size);
- }
- }
- else {
- Attribute *attr_uv = attributes.find(ustring(layer_name));
- if(attr_uv != NULL) {
- texface = attr_uv->data_float2();
- }
- }
- }
-
- const Mesh *mesh;
- int num_faces;
-
- float3 *vertex_normal;
- float2 *texface;
- float3 *orco;
- float3 orco_loc, orco_size;
-
- float3 *tangent;
- float *tangent_sign;
+ MikkUserData(const BL::Mesh &b_mesh,
+ const char *layer_name,
+ const Mesh *mesh,
+ float3 *tangent,
+ float *tangent_sign)
+ : mesh(mesh), texface(NULL), orco(NULL), tangent(tangent), tangent_sign(tangent_sign)
+ {
+ const AttributeSet &attributes = (mesh->subd_faces.size()) ? mesh->subd_attributes :
+ mesh->attributes;
+
+ Attribute *attr_vN = attributes.find(ATTR_STD_VERTEX_NORMAL);
+ vertex_normal = attr_vN->data_float3();
+
+ if (layer_name == NULL) {
+ Attribute *attr_orco = attributes.find(ATTR_STD_GENERATED);
+
+ if (attr_orco) {
+ orco = attr_orco->data_float3();
+ mesh_texture_space(*(BL::Mesh *)&b_mesh, orco_loc, orco_size);
+ }
+ }
+ else {
+ Attribute *attr_uv = attributes.find(ustring(layer_name));
+ if (attr_uv != NULL) {
+ texface = attr_uv->data_float2();
+ }
+ }
+ }
+
+ const Mesh *mesh;
+ int num_faces;
+
+ float3 *vertex_normal;
+ float2 *texface;
+ float3 *orco;
+ float3 orco_loc, orco_size;
+
+ float3 *tangent;
+ float *tangent_sign;
};
static int mikk_get_num_faces(const SMikkTSpaceContext *context)
{
- const MikkUserData *userdata = (const MikkUserData *)context->m_pUserData;
- if(userdata->mesh->subd_faces.size()) {
- return userdata->mesh->subd_faces.size();
- }
- else {
- return userdata->mesh->num_triangles();
- }
+ const MikkUserData *userdata = (const MikkUserData *)context->m_pUserData;
+ if (userdata->mesh->subd_faces.size()) {
+ return userdata->mesh->subd_faces.size();
+ }
+ else {
+ return userdata->mesh->num_triangles();
+ }
}
-static int mikk_get_num_verts_of_face(const SMikkTSpaceContext *context,
- const int face_num)
+static int mikk_get_num_verts_of_face(const SMikkTSpaceContext *context, const int face_num)
{
- const MikkUserData *userdata = (const MikkUserData *)context->m_pUserData;
- if(userdata->mesh->subd_faces.size()) {
- const Mesh *mesh = userdata->mesh;
- return mesh->subd_faces[face_num].num_corners;
- }
- else {
- return 3;
- }
+ const MikkUserData *userdata = (const MikkUserData *)context->m_pUserData;
+ if (userdata->mesh->subd_faces.size()) {
+ const Mesh *mesh = userdata->mesh;
+ return mesh->subd_faces[face_num].num_corners;
+ }
+ else {
+ return 3;
+ }
}
static int mikk_vertex_index(const Mesh *mesh, const int face_num, const int vert_num)
{
- if(mesh->subd_faces.size()) {
- const Mesh::SubdFace& face = mesh->subd_faces[face_num];
- return mesh->subd_face_corners[face.start_corner + vert_num];
- }
- else {
- return mesh->triangles[face_num * 3 + vert_num];
- }
+ if (mesh->subd_faces.size()) {
+ const Mesh::SubdFace &face = mesh->subd_faces[face_num];
+ return mesh->subd_face_corners[face.start_corner + vert_num];
+ }
+ else {
+ return mesh->triangles[face_num * 3 + vert_num];
+ }
}
static int mikk_corner_index(const Mesh *mesh, const int face_num, const int vert_num)
{
- if(mesh->subd_faces.size()) {
- const Mesh::SubdFace& face = mesh->subd_faces[face_num];
- return face.start_corner + vert_num;
- }
- else {
- return face_num * 3 + vert_num;
- }
+ if (mesh->subd_faces.size()) {
+ const Mesh::SubdFace &face = mesh->subd_faces[face_num];
+ return face.start_corner + vert_num;
+ }
+ else {
+ return face_num * 3 + vert_num;
+ }
}
static void mikk_get_position(const SMikkTSpaceContext *context,
float P[3],
- const int face_num, const int vert_num)
+ const int face_num,
+ const int vert_num)
{
- const MikkUserData *userdata = (const MikkUserData *)context->m_pUserData;
- const Mesh *mesh = userdata->mesh;
- const int vertex_index = mikk_vertex_index(mesh, face_num, vert_num);
- const float3 vP = mesh->verts[vertex_index];
- P[0] = vP.x;
- P[1] = vP.y;
- P[2] = vP.z;
+ const MikkUserData *userdata = (const MikkUserData *)context->m_pUserData;
+ const Mesh *mesh = userdata->mesh;
+ const int vertex_index = mikk_vertex_index(mesh, face_num, vert_num);
+ const float3 vP = mesh->verts[vertex_index];
+ P[0] = vP.x;
+ P[1] = vP.y;
+ P[2] = vP.z;
}
static void mikk_get_texture_coordinate(const SMikkTSpaceContext *context,
float uv[2],
- const int face_num, const int vert_num)
+ const int face_num,
+ const int vert_num)
{
- const MikkUserData *userdata = (const MikkUserData *)context->m_pUserData;
- const Mesh *mesh = userdata->mesh;
- if(userdata->texface != NULL) {
- const int corner_index = mikk_corner_index(mesh, face_num, vert_num);
- float2 tfuv = userdata->texface[corner_index];
- uv[0] = tfuv.x;
- uv[1] = tfuv.y;
- }
- else if(userdata->orco != NULL) {
- const int vertex_index = mikk_vertex_index(mesh, face_num, vert_num);
- const float3 orco_loc = userdata->orco_loc;
- const float3 orco_size = userdata->orco_size;
- const float3 orco = (userdata->orco[vertex_index] + orco_loc) / orco_size;
-
- const float2 tmp = map_to_sphere(orco);
- uv[0] = tmp.x;
- uv[1] = tmp.y;
- }
- else {
- uv[0] = 0.0f;
- uv[1] = 0.0f;
- }
+ const MikkUserData *userdata = (const MikkUserData *)context->m_pUserData;
+ const Mesh *mesh = userdata->mesh;
+ if (userdata->texface != NULL) {
+ const int corner_index = mikk_corner_index(mesh, face_num, vert_num);
+ float2 tfuv = userdata->texface[corner_index];
+ uv[0] = tfuv.x;
+ uv[1] = tfuv.y;
+ }
+ else if (userdata->orco != NULL) {
+ const int vertex_index = mikk_vertex_index(mesh, face_num, vert_num);
+ const float3 orco_loc = userdata->orco_loc;
+ const float3 orco_size = userdata->orco_size;
+ const float3 orco = (userdata->orco[vertex_index] + orco_loc) / orco_size;
+
+ const float2 tmp = map_to_sphere(orco);
+ uv[0] = tmp.x;
+ uv[1] = tmp.y;
+ }
+ else {
+ uv[0] = 0.0f;
+ uv[1] = 0.0f;
+ }
}
-static void mikk_get_normal(const SMikkTSpaceContext *context, float N[3],
- const int face_num, const int vert_num)
+static void mikk_get_normal(const SMikkTSpaceContext *context,
+ float N[3],
+ const int face_num,
+ const int vert_num)
{
- const MikkUserData *userdata = (const MikkUserData *)context->m_pUserData;
- const Mesh *mesh = userdata->mesh;
- float3 vN;
- if(mesh->subd_faces.size()) {
- const Mesh::SubdFace& face = mesh->subd_faces[face_num];
- if(face.smooth) {
- const int vertex_index = mikk_vertex_index(mesh, face_num, vert_num);
- vN = userdata->vertex_normal[vertex_index];
- }
- else {
- vN = face.normal(mesh);
- }
- }
- else {
- if(mesh->smooth[face_num]) {
- const int vertex_index = mikk_vertex_index(mesh, face_num, vert_num);
- vN = userdata->vertex_normal[vertex_index];
- }
- else {
- const Mesh::Triangle tri = mesh->get_triangle(face_num);
- vN = tri.compute_normal(&mesh->verts[0]);
- }
- }
- N[0] = vN.x;
- N[1] = vN.y;
- N[2] = vN.z;
+ const MikkUserData *userdata = (const MikkUserData *)context->m_pUserData;
+ const Mesh *mesh = userdata->mesh;
+ float3 vN;
+ if (mesh->subd_faces.size()) {
+ const Mesh::SubdFace &face = mesh->subd_faces[face_num];
+ if (face.smooth) {
+ const int vertex_index = mikk_vertex_index(mesh, face_num, vert_num);
+ vN = userdata->vertex_normal[vertex_index];
+ }
+ else {
+ vN = face.normal(mesh);
+ }
+ }
+ else {
+ if (mesh->smooth[face_num]) {
+ const int vertex_index = mikk_vertex_index(mesh, face_num, vert_num);
+ vN = userdata->vertex_normal[vertex_index];
+ }
+ else {
+ const Mesh::Triangle tri = mesh->get_triangle(face_num);
+ vN = tri.compute_normal(&mesh->verts[0]);
+ }
+ }
+ N[0] = vN.x;
+ N[1] = vN.y;
+ N[2] = vN.z;
}
static void mikk_set_tangent_space(const SMikkTSpaceContext *context,
const float T[],
const float sign,
- const int face_num, const int vert_num)
+ const int face_num,
+ const int vert_num)
{
- MikkUserData *userdata = (MikkUserData *)context->m_pUserData;
- const Mesh *mesh = userdata->mesh;
- const int corner_index = mikk_corner_index(mesh, face_num, vert_num);
- userdata->tangent[corner_index] = make_float3(T[0], T[1], T[2]);
- if(userdata->tangent_sign != NULL) {
- userdata->tangent_sign[corner_index] = sign;
- }
+ MikkUserData *userdata = (MikkUserData *)context->m_pUserData;
+ const Mesh *mesh = userdata->mesh;
+ const int corner_index = mikk_corner_index(mesh, face_num, vert_num);
+ userdata->tangent[corner_index] = make_float3(T[0], T[1], T[2]);
+ if (userdata->tangent_sign != NULL) {
+ userdata->tangent_sign[corner_index] = sign;
+ }
}
-static void mikk_compute_tangents(const BL::Mesh& b_mesh,
- const char *layer_name,
- Mesh *mesh,
- bool need_sign,
- bool active_render)
+static void mikk_compute_tangents(
+ const BL::Mesh &b_mesh, const char *layer_name, Mesh *mesh, bool need_sign, bool active_render)
{
- /* Create tangent attributes. */
- AttributeSet& attributes = (mesh->subd_faces.size()) ?
- mesh->subd_attributes : mesh->attributes;
- Attribute *attr;
- ustring name;
- if(layer_name != NULL) {
- name = ustring((string(layer_name) + ".tangent").c_str());
- }
- else {
- name = ustring("orco.tangent");
- }
- if(active_render) {
- attr = attributes.add(ATTR_STD_UV_TANGENT, name);
- }
- else {
- attr = attributes.add(name, TypeDesc::TypeVector, ATTR_ELEMENT_CORNER);
- }
- float3 *tangent = attr->data_float3();
- /* Create bitangent sign attribute. */
- float *tangent_sign = NULL;
- if(need_sign) {
- Attribute *attr_sign;
- ustring name_sign;
- if(layer_name != NULL) {
- name_sign = ustring((string(layer_name) +
- ".tangent_sign").c_str());
- }
- else {
- name_sign = ustring("orco.tangent_sign");
- }
-
- if(active_render) {
- attr_sign = attributes.add(ATTR_STD_UV_TANGENT_SIGN, name_sign);
- }
- else {
- attr_sign = attributes.add(name_sign,
- TypeDesc::TypeFloat,
- ATTR_ELEMENT_CORNER);
- }
- tangent_sign = attr_sign->data_float();
- }
- /* Setup userdata. */
- MikkUserData userdata(b_mesh, layer_name, mesh, tangent, tangent_sign);
- /* Setup interface. */
- SMikkTSpaceInterface sm_interface;
- memset(&sm_interface, 0, sizeof(sm_interface));
- sm_interface.m_getNumFaces = mikk_get_num_faces;
- sm_interface.m_getNumVerticesOfFace = mikk_get_num_verts_of_face;
- sm_interface.m_getPosition = mikk_get_position;
- sm_interface.m_getTexCoord = mikk_get_texture_coordinate;
- sm_interface.m_getNormal = mikk_get_normal;
- sm_interface.m_setTSpaceBasic = mikk_set_tangent_space;
- /* Setup context. */
- SMikkTSpaceContext context;
- memset(&context, 0, sizeof(context));
- context.m_pUserData = &userdata;
- context.m_pInterface = &sm_interface;
- /* Compute tangents. */
- genTangSpaceDefault(&context);
+ /* Create tangent attributes. */
+ AttributeSet &attributes = (mesh->subd_faces.size()) ? mesh->subd_attributes : mesh->attributes;
+ Attribute *attr;
+ ustring name;
+ if (layer_name != NULL) {
+ name = ustring((string(layer_name) + ".tangent").c_str());
+ }
+ else {
+ name = ustring("orco.tangent");
+ }
+ if (active_render) {
+ attr = attributes.add(ATTR_STD_UV_TANGENT, name);
+ }
+ else {
+ attr = attributes.add(name, TypeDesc::TypeVector, ATTR_ELEMENT_CORNER);
+ }
+ float3 *tangent = attr->data_float3();
+ /* Create bitangent sign attribute. */
+ float *tangent_sign = NULL;
+ if (need_sign) {
+ Attribute *attr_sign;
+ ustring name_sign;
+ if (layer_name != NULL) {
+ name_sign = ustring((string(layer_name) + ".tangent_sign").c_str());
+ }
+ else {
+ name_sign = ustring("orco.tangent_sign");
+ }
+
+ if (active_render) {
+ attr_sign = attributes.add(ATTR_STD_UV_TANGENT_SIGN, name_sign);
+ }
+ else {
+ attr_sign = attributes.add(name_sign, TypeDesc::TypeFloat, ATTR_ELEMENT_CORNER);
+ }
+ tangent_sign = attr_sign->data_float();
+ }
+ /* Setup userdata. */
+ MikkUserData userdata(b_mesh, layer_name, mesh, tangent, tangent_sign);
+ /* Setup interface. */
+ SMikkTSpaceInterface sm_interface;
+ memset(&sm_interface, 0, sizeof(sm_interface));
+ sm_interface.m_getNumFaces = mikk_get_num_faces;
+ sm_interface.m_getNumVerticesOfFace = mikk_get_num_verts_of_face;
+ sm_interface.m_getPosition = mikk_get_position;
+ sm_interface.m_getTexCoord = mikk_get_texture_coordinate;
+ sm_interface.m_getNormal = mikk_get_normal;
+ sm_interface.m_setTSpaceBasic = mikk_set_tangent_space;
+ /* Setup context. */
+ SMikkTSpaceContext context;
+ memset(&context, 0, sizeof(context));
+ context.m_pUserData = &userdata;
+ context.m_pInterface = &sm_interface;
+ /* Compute tangents. */
+ genTangSpaceDefault(&context);
}
/* Create Volume Attribute */
-static void create_mesh_volume_attribute(BL::Object& b_ob,
- Mesh *mesh,
- ImageManager *image_manager,
- AttributeStandard std,
- float frame)
+static void create_mesh_volume_attribute(
+ BL::Object &b_ob, Mesh *mesh, ImageManager *image_manager, AttributeStandard std, float frame)
{
- BL::SmokeDomainSettings b_domain = object_smoke_domain_find(b_ob);
-
- if(!b_domain)
- return;
-
- mesh->volume_isovalue = b_domain.clipping();
-
- Attribute *attr = mesh->attributes.add(std);
- VoxelAttribute *volume_data = attr->data_voxel();
- ImageMetaData metadata;
- bool animated = false;
- bool use_alpha = true;
-
- volume_data->manager = image_manager;
- volume_data->slot = image_manager->add_image(
- Attribute::standard_name(std),
- b_ob.ptr.data,
- animated,
- frame,
- INTERPOLATION_LINEAR,
- EXTENSION_CLIP,
- use_alpha,
- metadata);
+ BL::SmokeDomainSettings b_domain = object_smoke_domain_find(b_ob);
+
+ if (!b_domain)
+ return;
+
+ mesh->volume_isovalue = b_domain.clipping();
+
+ Attribute *attr = mesh->attributes.add(std);
+ VoxelAttribute *volume_data = attr->data_voxel();
+ ImageMetaData metadata;
+ bool animated = false;
+ bool use_alpha = true;
+
+ volume_data->manager = image_manager;
+ volume_data->slot = image_manager->add_image(Attribute::standard_name(std),
+ b_ob.ptr.data,
+ animated,
+ frame,
+ INTERPOLATION_LINEAR,
+ EXTENSION_CLIP,
+ use_alpha,
+ metadata);
}
-static void create_mesh_volume_attributes(Scene *scene,
- BL::Object& b_ob,
- Mesh *mesh,
- float frame)
+static void create_mesh_volume_attributes(Scene *scene, BL::Object &b_ob, Mesh *mesh, float frame)
{
- /* for smoke volume rendering */
- if(mesh->need_attribute(scene, ATTR_STD_VOLUME_DENSITY))
- create_mesh_volume_attribute(b_ob, mesh, scene->image_manager, ATTR_STD_VOLUME_DENSITY, frame);
- if(mesh->need_attribute(scene, ATTR_STD_VOLUME_COLOR))
- create_mesh_volume_attribute(b_ob, mesh, scene->image_manager, ATTR_STD_VOLUME_COLOR, frame);
- if(mesh->need_attribute(scene, ATTR_STD_VOLUME_FLAME))
- create_mesh_volume_attribute(b_ob, mesh, scene->image_manager, ATTR_STD_VOLUME_FLAME, frame);
- if(mesh->need_attribute(scene, ATTR_STD_VOLUME_HEAT))
- create_mesh_volume_attribute(b_ob, mesh, scene->image_manager, ATTR_STD_VOLUME_HEAT, frame);
- if(mesh->need_attribute(scene, ATTR_STD_VOLUME_TEMPERATURE))
- create_mesh_volume_attribute(b_ob, mesh, scene->image_manager, ATTR_STD_VOLUME_TEMPERATURE, frame);
- if(mesh->need_attribute(scene, ATTR_STD_VOLUME_VELOCITY))
- create_mesh_volume_attribute(b_ob, mesh, scene->image_manager, ATTR_STD_VOLUME_VELOCITY, frame);
+ /* for smoke volume rendering */
+ if (mesh->need_attribute(scene, ATTR_STD_VOLUME_DENSITY))
+ create_mesh_volume_attribute(b_ob, mesh, scene->image_manager, ATTR_STD_VOLUME_DENSITY, frame);
+ if (mesh->need_attribute(scene, ATTR_STD_VOLUME_COLOR))
+ create_mesh_volume_attribute(b_ob, mesh, scene->image_manager, ATTR_STD_VOLUME_COLOR, frame);
+ if (mesh->need_attribute(scene, ATTR_STD_VOLUME_FLAME))
+ create_mesh_volume_attribute(b_ob, mesh, scene->image_manager, ATTR_STD_VOLUME_FLAME, frame);
+ if (mesh->need_attribute(scene, ATTR_STD_VOLUME_HEAT))
+ create_mesh_volume_attribute(b_ob, mesh, scene->image_manager, ATTR_STD_VOLUME_HEAT, frame);
+ if (mesh->need_attribute(scene, ATTR_STD_VOLUME_TEMPERATURE))
+ create_mesh_volume_attribute(
+ b_ob, mesh, scene->image_manager, ATTR_STD_VOLUME_TEMPERATURE, frame);
+ if (mesh->need_attribute(scene, ATTR_STD_VOLUME_VELOCITY))
+ create_mesh_volume_attribute(
+ b_ob, mesh, scene->image_manager, ATTR_STD_VOLUME_VELOCITY, frame);
}
/* Create vertex color attributes. */
-static void attr_create_vertex_color(Scene *scene,
- Mesh *mesh,
- BL::Mesh& b_mesh,
- bool subdivision)
+static void attr_create_vertex_color(Scene *scene, Mesh *mesh, BL::Mesh &b_mesh, bool subdivision)
{
- if(subdivision) {
- BL::Mesh::vertex_colors_iterator l;
-
- for(b_mesh.vertex_colors.begin(l); l != b_mesh.vertex_colors.end(); ++l) {
- if(!mesh->need_attribute(scene, ustring(l->name().c_str())))
- continue;
-
- Attribute *attr = mesh->subd_attributes.add(ustring(l->name().c_str()),
- TypeDesc::TypeColor,
- ATTR_ELEMENT_CORNER_BYTE);
-
- BL::Mesh::polygons_iterator p;
- uchar4 *cdata = attr->data_uchar4();
-
- for(b_mesh.polygons.begin(p); p != b_mesh.polygons.end(); ++p) {
- int n = p->loop_total();
- for(int i = 0; i < n; i++) {
- float3 color = get_float3(l->data[p->loop_start() + i].color());
- /* Compress/encode vertex color using the sRGB curve. */
- *(cdata++) = color_float_to_byte(color_srgb_to_linear_v3(color));
- }
- }
- }
- }
- else {
- BL::Mesh::vertex_colors_iterator l;
- for(b_mesh.vertex_colors.begin(l); l != b_mesh.vertex_colors.end(); ++l) {
- if(!mesh->need_attribute(scene, ustring(l->name().c_str())))
- continue;
-
- Attribute *attr = mesh->attributes.add(ustring(l->name().c_str()),
- TypeDesc::TypeColor,
- ATTR_ELEMENT_CORNER_BYTE);
-
- BL::Mesh::loop_triangles_iterator t;
- uchar4 *cdata = attr->data_uchar4();
-
- for(b_mesh.loop_triangles.begin(t); t != b_mesh.loop_triangles.end(); ++t) {
- int3 li = get_int3(t->loops());
- float3 c1 = get_float3(l->data[li[0]].color());
- float3 c2 = get_float3(l->data[li[1]].color());
- float3 c3 = get_float3(l->data[li[2]].color());
-
- /* Compress/encode vertex color using the sRGB curve. */
- cdata[0] = color_float_to_byte(color_srgb_to_linear_v3(c1));
- cdata[1] = color_float_to_byte(color_srgb_to_linear_v3(c2));
- cdata[2] = color_float_to_byte(color_srgb_to_linear_v3(c3));
- cdata += 3;
- }
- }
- }
+ if (subdivision) {
+ BL::Mesh::vertex_colors_iterator l;
+
+ for (b_mesh.vertex_colors.begin(l); l != b_mesh.vertex_colors.end(); ++l) {
+ if (!mesh->need_attribute(scene, ustring(l->name().c_str())))
+ continue;
+
+ Attribute *attr = mesh->subd_attributes.add(
+ ustring(l->name().c_str()), TypeDesc::TypeColor, ATTR_ELEMENT_CORNER_BYTE);
+
+ BL::Mesh::polygons_iterator p;
+ uchar4 *cdata = attr->data_uchar4();
+
+ for (b_mesh.polygons.begin(p); p != b_mesh.polygons.end(); ++p) {
+ int n = p->loop_total();
+ for (int i = 0; i < n; i++) {
+ float3 color = get_float3(l->data[p->loop_start() + i].color());
+ /* Compress/encode vertex color using the sRGB curve. */
+ *(cdata++) = color_float_to_byte(color_srgb_to_linear_v3(color));
+ }
+ }
+ }
+ }
+ else {
+ BL::Mesh::vertex_colors_iterator l;
+ for (b_mesh.vertex_colors.begin(l); l != b_mesh.vertex_colors.end(); ++l) {
+ if (!mesh->need_attribute(scene, ustring(l->name().c_str())))
+ continue;
+
+ Attribute *attr = mesh->attributes.add(
+ ustring(l->name().c_str()), TypeDesc::TypeColor, ATTR_ELEMENT_CORNER_BYTE);
+
+ BL::Mesh::loop_triangles_iterator t;
+ uchar4 *cdata = attr->data_uchar4();
+
+ for (b_mesh.loop_triangles.begin(t); t != b_mesh.loop_triangles.end(); ++t) {
+ int3 li = get_int3(t->loops());
+ float3 c1 = get_float3(l->data[li[0]].color());
+ float3 c2 = get_float3(l->data[li[1]].color());
+ float3 c3 = get_float3(l->data[li[2]].color());
+
+ /* Compress/encode vertex color using the sRGB curve. */
+ cdata[0] = color_float_to_byte(color_srgb_to_linear_v3(c1));
+ cdata[1] = color_float_to_byte(color_srgb_to_linear_v3(c2));
+ cdata[2] = color_float_to_byte(color_srgb_to_linear_v3(c3));
+ cdata += 3;
+ }
+ }
+ }
}
/* Create uv map attributes. */
-static void attr_create_uv_map(Scene *scene,
- Mesh *mesh,
- BL::Mesh& b_mesh)
+static void attr_create_uv_map(Scene *scene, Mesh *mesh, BL::Mesh &b_mesh)
{
- if(b_mesh.uv_layers.length() != 0) {
- BL::Mesh::uv_layers_iterator l;
-
- for(b_mesh.uv_layers.begin(l); l != b_mesh.uv_layers.end(); ++l) {
- const bool active_render = l->active_render();
- AttributeStandard uv_std = (active_render)? ATTR_STD_UV: ATTR_STD_NONE;
- ustring uv_name = ustring(l->name().c_str());
- AttributeStandard tangent_std = (active_render)? ATTR_STD_UV_TANGENT
- : ATTR_STD_NONE;
- ustring tangent_name = ustring(
- (string(l->name().c_str()) + ".tangent").c_str());
-
- /* Denotes whether UV map was requested directly. */
- const bool need_uv = mesh->need_attribute(scene, uv_name) ||
- mesh->need_attribute(scene, uv_std);
- /* Denotes whether tangent was requested directly. */
- const bool need_tangent =
- mesh->need_attribute(scene, tangent_name) ||
- (active_render && mesh->need_attribute(scene, tangent_std));
-
- /* UV map */
- /* NOTE: We create temporary UV layer if its needed for tangent but
- * wasn't requested by other nodes in shaders.
- */
- Attribute *uv_attr = NULL;
- if(need_uv || need_tangent) {
- if(active_render) {
- uv_attr = mesh->attributes.add(uv_std, uv_name);
- }
- else {
- uv_attr = mesh->attributes.add(uv_name,
- TypeFloat2,
- ATTR_ELEMENT_CORNER);
- }
-
- BL::Mesh::loop_triangles_iterator t;
- float2 *fdata = uv_attr->data_float2();
-
- for(b_mesh.loop_triangles.begin(t); t != b_mesh.loop_triangles.end(); ++t) {
- int3 li = get_int3(t->loops());
- fdata[0] = get_float2(l->data[li[0]].uv());
- fdata[1] = get_float2(l->data[li[1]].uv());
- fdata[2] = get_float2(l->data[li[2]].uv());
- fdata += 3;
- }
- }
-
- /* UV tangent */
- if(need_tangent) {
- AttributeStandard sign_std =
- (active_render)? ATTR_STD_UV_TANGENT_SIGN
- : ATTR_STD_NONE;
- ustring sign_name = ustring(
- (string(l->name().c_str()) + ".tangent_sign").c_str());
- bool need_sign = (mesh->need_attribute(scene, sign_name) ||
- mesh->need_attribute(scene, sign_std));
- mikk_compute_tangents(b_mesh,
- l->name().c_str(),
- mesh,
- need_sign,
- active_render);
- }
- /* Remove temporarily created UV attribute. */
- if(!need_uv && uv_attr != NULL) {
- mesh->attributes.remove(uv_attr);
- }
- }
- }
- else if(mesh->need_attribute(scene, ATTR_STD_UV_TANGENT)) {
- bool need_sign = mesh->need_attribute(scene, ATTR_STD_UV_TANGENT_SIGN);
- mikk_compute_tangents(b_mesh, NULL, mesh, need_sign, true);
- if(!mesh->need_attribute(scene, ATTR_STD_GENERATED)) {
- mesh->attributes.remove(ATTR_STD_GENERATED);
- }
- }
+ if (b_mesh.uv_layers.length() != 0) {
+ BL::Mesh::uv_layers_iterator l;
+
+ for (b_mesh.uv_layers.begin(l); l != b_mesh.uv_layers.end(); ++l) {
+ const bool active_render = l->active_render();
+ AttributeStandard uv_std = (active_render) ? ATTR_STD_UV : ATTR_STD_NONE;
+ ustring uv_name = ustring(l->name().c_str());
+ AttributeStandard tangent_std = (active_render) ? ATTR_STD_UV_TANGENT : ATTR_STD_NONE;
+ ustring tangent_name = ustring((string(l->name().c_str()) + ".tangent").c_str());
+
+ /* Denotes whether UV map was requested directly. */
+ const bool need_uv = mesh->need_attribute(scene, uv_name) ||
+ mesh->need_attribute(scene, uv_std);
+ /* Denotes whether tangent was requested directly. */
+ const bool need_tangent = mesh->need_attribute(scene, tangent_name) ||
+ (active_render && mesh->need_attribute(scene, tangent_std));
+
+ /* UV map */
+ /* NOTE: We create temporary UV layer if its needed for tangent but
+ * wasn't requested by other nodes in shaders.
+ */
+ Attribute *uv_attr = NULL;
+ if (need_uv || need_tangent) {
+ if (active_render) {
+ uv_attr = mesh->attributes.add(uv_std, uv_name);
+ }
+ else {
+ uv_attr = mesh->attributes.add(uv_name, TypeFloat2, ATTR_ELEMENT_CORNER);
+ }
+
+ BL::Mesh::loop_triangles_iterator t;
+ float2 *fdata = uv_attr->data_float2();
+
+ for (b_mesh.loop_triangles.begin(t); t != b_mesh.loop_triangles.end(); ++t) {
+ int3 li = get_int3(t->loops());
+ fdata[0] = get_float2(l->data[li[0]].uv());
+ fdata[1] = get_float2(l->data[li[1]].uv());
+ fdata[2] = get_float2(l->data[li[2]].uv());
+ fdata += 3;
+ }
+ }
+
+ /* UV tangent */
+ if (need_tangent) {
+ AttributeStandard sign_std = (active_render) ? ATTR_STD_UV_TANGENT_SIGN : ATTR_STD_NONE;
+ ustring sign_name = ustring((string(l->name().c_str()) + ".tangent_sign").c_str());
+ bool need_sign = (mesh->need_attribute(scene, sign_name) ||
+ mesh->need_attribute(scene, sign_std));
+ mikk_compute_tangents(b_mesh, l->name().c_str(), mesh, need_sign, active_render);
+ }
+ /* Remove temporarily created UV attribute. */
+ if (!need_uv && uv_attr != NULL) {
+ mesh->attributes.remove(uv_attr);
+ }
+ }
+ }
+ else if (mesh->need_attribute(scene, ATTR_STD_UV_TANGENT)) {
+ bool need_sign = mesh->need_attribute(scene, ATTR_STD_UV_TANGENT_SIGN);
+ mikk_compute_tangents(b_mesh, NULL, mesh, need_sign, true);
+ if (!mesh->need_attribute(scene, ATTR_STD_GENERATED)) {
+ mesh->attributes.remove(ATTR_STD_GENERATED);
+ }
+ }
}
-static void attr_create_subd_uv_map(Scene *scene,
- Mesh *mesh,
- BL::Mesh& b_mesh,
- bool subdivide_uvs)
+static void attr_create_subd_uv_map(Scene *scene, Mesh *mesh, BL::Mesh &b_mesh, bool subdivide_uvs)
{
- if(b_mesh.uv_layers.length() != 0) {
- BL::Mesh::uv_layers_iterator l;
- int i = 0;
-
- for(b_mesh.uv_layers.begin(l); l != b_mesh.uv_layers.end(); ++l, ++i) {
- bool active_render = l->active_render();
- AttributeStandard uv_std = (active_render)? ATTR_STD_UV: ATTR_STD_NONE;
- ustring uv_name = ustring(l->name().c_str());
- AttributeStandard tangent_std = (active_render)? ATTR_STD_UV_TANGENT
- : ATTR_STD_NONE;
- ustring tangent_name = ustring(
- (string(l->name().c_str()) + ".tangent").c_str());
-
- /* Denotes whether UV map was requested directly. */
- const bool need_uv = mesh->need_attribute(scene, uv_name) ||
- mesh->need_attribute(scene, uv_std);
- /* Denotes whether tangent was requested directly. */
- const bool need_tangent =
- mesh->need_attribute(scene, tangent_name) ||
- (active_render && mesh->need_attribute(scene, tangent_std));
-
- Attribute *uv_attr = NULL;
-
- /* UV map */
- if(need_uv || need_tangent) {
- if(active_render)
- uv_attr = mesh->subd_attributes.add(uv_std, uv_name);
- else
- uv_attr = mesh->subd_attributes.add(uv_name, TypeFloat2, ATTR_ELEMENT_CORNER);
-
- if(subdivide_uvs) {
- uv_attr->flags |= ATTR_SUBDIVIDED;
- }
-
- BL::Mesh::polygons_iterator p;
- float2 *fdata = uv_attr->data_float2();
-
- for(b_mesh.polygons.begin(p); p != b_mesh.polygons.end(); ++p) {
- int n = p->loop_total();
- for(int j = 0; j < n; j++) {
- *(fdata++) = get_float2(l->data[p->loop_start() + j].uv());
- }
- }
- }
-
- /* UV tangent */
- if(need_tangent) {
- AttributeStandard sign_std =
- (active_render)? ATTR_STD_UV_TANGENT_SIGN
- : ATTR_STD_NONE;
- ustring sign_name = ustring(
- (string(l->name().c_str()) + ".tangent_sign").c_str());
- bool need_sign = (mesh->need_attribute(scene, sign_name) ||
- mesh->need_attribute(scene, sign_std));
- mikk_compute_tangents(b_mesh,
- l->name().c_str(),
- mesh,
- need_sign,
- active_render);
- }
- /* Remove temporarily created UV attribute. */
- if(!need_uv && uv_attr != NULL) {
- mesh->subd_attributes.remove(uv_attr);
- }
- }
- }
- else if(mesh->need_attribute(scene, ATTR_STD_UV_TANGENT)) {
- bool need_sign = mesh->need_attribute(scene, ATTR_STD_UV_TANGENT_SIGN);
- mikk_compute_tangents(b_mesh, NULL, mesh, need_sign, true);
- if(!mesh->need_attribute(scene, ATTR_STD_GENERATED)) {
- mesh->subd_attributes.remove(ATTR_STD_GENERATED);
- }
- }
+ if (b_mesh.uv_layers.length() != 0) {
+ BL::Mesh::uv_layers_iterator l;
+ int i = 0;
+
+ for (b_mesh.uv_layers.begin(l); l != b_mesh.uv_layers.end(); ++l, ++i) {
+ bool active_render = l->active_render();
+ AttributeStandard uv_std = (active_render) ? ATTR_STD_UV : ATTR_STD_NONE;
+ ustring uv_name = ustring(l->name().c_str());
+ AttributeStandard tangent_std = (active_render) ? ATTR_STD_UV_TANGENT : ATTR_STD_NONE;
+ ustring tangent_name = ustring((string(l->name().c_str()) + ".tangent").c_str());
+
+ /* Denotes whether UV map was requested directly. */
+ const bool need_uv = mesh->need_attribute(scene, uv_name) ||
+ mesh->need_attribute(scene, uv_std);
+ /* Denotes whether tangent was requested directly. */
+ const bool need_tangent = mesh->need_attribute(scene, tangent_name) ||
+ (active_render && mesh->need_attribute(scene, tangent_std));
+
+ Attribute *uv_attr = NULL;
+
+ /* UV map */
+ if (need_uv || need_tangent) {
+ if (active_render)
+ uv_attr = mesh->subd_attributes.add(uv_std, uv_name);
+ else
+ uv_attr = mesh->subd_attributes.add(uv_name, TypeFloat2, ATTR_ELEMENT_CORNER);
+
+ if (subdivide_uvs) {
+ uv_attr->flags |= ATTR_SUBDIVIDED;
+ }
+
+ BL::Mesh::polygons_iterator p;
+ float2 *fdata = uv_attr->data_float2();
+
+ for (b_mesh.polygons.begin(p); p != b_mesh.polygons.end(); ++p) {
+ int n = p->loop_total();
+ for (int j = 0; j < n; j++) {
+ *(fdata++) = get_float2(l->data[p->loop_start() + j].uv());
+ }
+ }
+ }
+
+ /* UV tangent */
+ if (need_tangent) {
+ AttributeStandard sign_std = (active_render) ? ATTR_STD_UV_TANGENT_SIGN : ATTR_STD_NONE;
+ ustring sign_name = ustring((string(l->name().c_str()) + ".tangent_sign").c_str());
+ bool need_sign = (mesh->need_attribute(scene, sign_name) ||
+ mesh->need_attribute(scene, sign_std));
+ mikk_compute_tangents(b_mesh, l->name().c_str(), mesh, need_sign, active_render);
+ }
+ /* Remove temporarily created UV attribute. */
+ if (!need_uv && uv_attr != NULL) {
+ mesh->subd_attributes.remove(uv_attr);
+ }
+ }
+ }
+ else if (mesh->need_attribute(scene, ATTR_STD_UV_TANGENT)) {
+ bool need_sign = mesh->need_attribute(scene, ATTR_STD_UV_TANGENT_SIGN);
+ mikk_compute_tangents(b_mesh, NULL, mesh, need_sign, true);
+ if (!mesh->need_attribute(scene, ATTR_STD_GENERATED)) {
+ mesh->subd_attributes.remove(ATTR_STD_GENERATED);
+ }
+ }
}
/* Create vertex pointiness attributes. */
/* Compare vertices by sum of their coordinates. */
class VertexAverageComparator {
-public:
- VertexAverageComparator(const array<float3>& verts)
- : verts_(verts) {
- }
-
- bool operator()(const int& vert_idx_a, const int& vert_idx_b)
- {
- const float3 &vert_a = verts_[vert_idx_a];
- const float3 &vert_b = verts_[vert_idx_b];
- if(vert_a == vert_b) {
- /* Special case for doubles, so we ensure ordering. */
- return vert_idx_a > vert_idx_b;
- }
- const float x1 = vert_a.x + vert_a.y + vert_a.z;
- const float x2 = vert_b.x + vert_b.y + vert_b.z;
- return x1 < x2;
- }
-
-protected:
- const array<float3>& verts_;
+ public:
+ VertexAverageComparator(const array<float3> &verts) : verts_(verts)
+ {
+ }
+
+ bool operator()(const int &vert_idx_a, const int &vert_idx_b)
+ {
+ const float3 &vert_a = verts_[vert_idx_a];
+ const float3 &vert_b = verts_[vert_idx_b];
+ if (vert_a == vert_b) {
+ /* Special case for doubles, so we ensure ordering. */
+ return vert_idx_a > vert_idx_b;
+ }
+ const float x1 = vert_a.x + vert_a.y + vert_a.z;
+ const float x2 = vert_b.x + vert_b.y + vert_b.z;
+ return x1 < x2;
+ }
+
+ protected:
+ const array<float3> &verts_;
};
-static void attr_create_pointiness(Scene *scene,
- Mesh *mesh,
- BL::Mesh& b_mesh,
- bool subdivision)
+static void attr_create_pointiness(Scene *scene, Mesh *mesh, BL::Mesh &b_mesh, bool subdivision)
{
- if(!mesh->need_attribute(scene, ATTR_STD_POINTINESS)) {
- return;
- }
- const int num_verts = b_mesh.vertices.length();
- if(num_verts == 0) {
- return;
- }
- /* STEP 1: Find out duplicated vertices and point duplicates to a single
- * original vertex.
- */
- vector<int> sorted_vert_indeices(num_verts);
- for(int vert_index = 0; vert_index < num_verts; ++vert_index) {
- sorted_vert_indeices[vert_index] = vert_index;
- }
- VertexAverageComparator compare(mesh->verts);
- sort(sorted_vert_indeices.begin(), sorted_vert_indeices.end(), compare);
- /* This array stores index of the original vertex for the given vertex
- * index.
- */
- vector<int> vert_orig_index(num_verts);
- for(int sorted_vert_index = 0;
- sorted_vert_index < num_verts;
- ++sorted_vert_index)
- {
- const int vert_index = sorted_vert_indeices[sorted_vert_index];
- const float3 &vert_co = mesh->verts[vert_index];
- bool found = false;
- for(int other_sorted_vert_index = sorted_vert_index + 1;
- other_sorted_vert_index < num_verts;
- ++other_sorted_vert_index)
- {
- const int other_vert_index =
- sorted_vert_indeices[other_sorted_vert_index];
- const float3 &other_vert_co = mesh->verts[other_vert_index];
- /* We are too far away now, we wouldn't have duplicate. */
- if((other_vert_co.x + other_vert_co.y + other_vert_co.z) -
- (vert_co.x + vert_co.y + vert_co.z) > 3 * FLT_EPSILON)
- {
- break;
- }
- /* Found duplicate. */
- if(len_squared(other_vert_co - vert_co) < FLT_EPSILON) {
- found = true;
- vert_orig_index[vert_index] = other_vert_index;
- break;
- }
- }
- if(!found) {
- vert_orig_index[vert_index] = vert_index;
- }
- }
- /* Make sure we always points to the very first orig vertex. */
- for(int vert_index = 0; vert_index < num_verts; ++vert_index) {
- int orig_index = vert_orig_index[vert_index];
- while(orig_index != vert_orig_index[orig_index]) {
- orig_index = vert_orig_index[orig_index];
- }
- vert_orig_index[vert_index] = orig_index;
- }
- sorted_vert_indeices.free_memory();
- /* STEP 2: Calculate vertex normals taking into account their possible
- * duplicates which gets "welded" together.
- */
- vector<float3> vert_normal(num_verts, make_float3(0.0f, 0.0f, 0.0f));
- /* First we accumulate all vertex normals in the original index. */
- for(int vert_index = 0; vert_index < num_verts; ++vert_index) {
- const float3 normal = get_float3(b_mesh.vertices[vert_index].normal());
- const int orig_index = vert_orig_index[vert_index];
- vert_normal[orig_index] += normal;
- }
- /* Then we normalize the accumulated result and flush it to all duplicates
- * as well.
- */
- for(int vert_index = 0; vert_index < num_verts; ++vert_index) {
- const int orig_index = vert_orig_index[vert_index];
- vert_normal[vert_index] = normalize(vert_normal[orig_index]);
- }
- /* STEP 3: Calculate pointiness using single ring neighborhood. */
- vector<int> counter(num_verts, 0);
- vector<float> raw_data(num_verts, 0.0f);
- vector<float3> edge_accum(num_verts, make_float3(0.0f, 0.0f, 0.0f));
- BL::Mesh::edges_iterator e;
- EdgeMap visited_edges;
- int edge_index = 0;
- memset(&counter[0], 0, sizeof(int) * counter.size());
- for(b_mesh.edges.begin(e); e != b_mesh.edges.end(); ++e, ++edge_index) {
- const int v0 = vert_orig_index[b_mesh.edges[edge_index].vertices()[0]],
- v1 = vert_orig_index[b_mesh.edges[edge_index].vertices()[1]];
- if(visited_edges.exists(v0, v1)) {
- continue;
- }
- visited_edges.insert(v0, v1);
- float3 co0 = get_float3(b_mesh.vertices[v0].co()),
- co1 = get_float3(b_mesh.vertices[v1].co());
- float3 edge = normalize(co1 - co0);
- edge_accum[v0] += edge;
- edge_accum[v1] += -edge;
- ++counter[v0];
- ++counter[v1];
- }
- for(int vert_index = 0; vert_index < num_verts; ++vert_index) {
- const int orig_index = vert_orig_index[vert_index];
- if(orig_index != vert_index) {
- /* Skip duplicates, they'll be overwritten later on. */
- continue;
- }
- if(counter[vert_index] > 0) {
- const float3 normal = vert_normal[vert_index];
- const float angle =
- safe_acosf(dot(normal,
- edge_accum[vert_index] / counter[vert_index]));
- raw_data[vert_index] = angle * M_1_PI_F;
- }
- else {
- raw_data[vert_index] = 0.0f;
- }
- }
- /* STEP 3: Blur vertices to approximate 2 ring neighborhood. */
- AttributeSet& attributes = (subdivision)? mesh->subd_attributes: mesh->attributes;
- Attribute *attr = attributes.add(ATTR_STD_POINTINESS);
- float *data = attr->data_float();
- memcpy(data, &raw_data[0], sizeof(float) * raw_data.size());
- memset(&counter[0], 0, sizeof(int) * counter.size());
- edge_index = 0;
- visited_edges.clear();
- for(b_mesh.edges.begin(e); e != b_mesh.edges.end(); ++e, ++edge_index) {
- const int v0 = vert_orig_index[b_mesh.edges[edge_index].vertices()[0]],
- v1 = vert_orig_index[b_mesh.edges[edge_index].vertices()[1]];
- if(visited_edges.exists(v0, v1)) {
- continue;
- }
- visited_edges.insert(v0, v1);
- data[v0] += raw_data[v1];
- data[v1] += raw_data[v0];
- ++counter[v0];
- ++counter[v1];
- }
- for(int vert_index = 0; vert_index < num_verts; ++vert_index) {
- data[vert_index] /= counter[vert_index] + 1;
- }
- /* STEP 4: Copy attribute to the duplicated vertices. */
- for(int vert_index = 0; vert_index < num_verts; ++vert_index) {
- const int orig_index = vert_orig_index[vert_index];
- data[vert_index] = data[orig_index];
- }
+ if (!mesh->need_attribute(scene, ATTR_STD_POINTINESS)) {
+ return;
+ }
+ const int num_verts = b_mesh.vertices.length();
+ if (num_verts == 0) {
+ return;
+ }
+ /* STEP 1: Find out duplicated vertices and point duplicates to a single
+ * original vertex.
+ */
+ vector<int> sorted_vert_indeices(num_verts);
+ for (int vert_index = 0; vert_index < num_verts; ++vert_index) {
+ sorted_vert_indeices[vert_index] = vert_index;
+ }
+ VertexAverageComparator compare(mesh->verts);
+ sort(sorted_vert_indeices.begin(), sorted_vert_indeices.end(), compare);
+ /* This array stores index of the original vertex for the given vertex
+ * index.
+ */
+ vector<int> vert_orig_index(num_verts);
+ for (int sorted_vert_index = 0; sorted_vert_index < num_verts; ++sorted_vert_index) {
+ const int vert_index = sorted_vert_indeices[sorted_vert_index];
+ const float3 &vert_co = mesh->verts[vert_index];
+ bool found = false;
+ for (int other_sorted_vert_index = sorted_vert_index + 1; other_sorted_vert_index < num_verts;
+ ++other_sorted_vert_index) {
+ const int other_vert_index = sorted_vert_indeices[other_sorted_vert_index];
+ const float3 &other_vert_co = mesh->verts[other_vert_index];
+ /* We are too far away now, we wouldn't have duplicate. */
+ if ((other_vert_co.x + other_vert_co.y + other_vert_co.z) -
+ (vert_co.x + vert_co.y + vert_co.z) >
+ 3 * FLT_EPSILON) {
+ break;
+ }
+ /* Found duplicate. */
+ if (len_squared(other_vert_co - vert_co) < FLT_EPSILON) {
+ found = true;
+ vert_orig_index[vert_index] = other_vert_index;
+ break;
+ }
+ }
+ if (!found) {
+ vert_orig_index[vert_index] = vert_index;
+ }
+ }
+ /* Make sure we always points to the very first orig vertex. */
+ for (int vert_index = 0; vert_index < num_verts; ++vert_index) {
+ int orig_index = vert_orig_index[vert_index];
+ while (orig_index != vert_orig_index[orig_index]) {
+ orig_index = vert_orig_index[orig_index];
+ }
+ vert_orig_index[vert_index] = orig_index;
+ }
+ sorted_vert_indeices.free_memory();
+ /* STEP 2: Calculate vertex normals taking into account their possible
+ * duplicates which gets "welded" together.
+ */
+ vector<float3> vert_normal(num_verts, make_float3(0.0f, 0.0f, 0.0f));
+ /* First we accumulate all vertex normals in the original index. */
+ for (int vert_index = 0; vert_index < num_verts; ++vert_index) {
+ const float3 normal = get_float3(b_mesh.vertices[vert_index].normal());
+ const int orig_index = vert_orig_index[vert_index];
+ vert_normal[orig_index] += normal;
+ }
+ /* Then we normalize the accumulated result and flush it to all duplicates
+ * as well.
+ */
+ for (int vert_index = 0; vert_index < num_verts; ++vert_index) {
+ const int orig_index = vert_orig_index[vert_index];
+ vert_normal[vert_index] = normalize(vert_normal[orig_index]);
+ }
+ /* STEP 3: Calculate pointiness using single ring neighborhood. */
+ vector<int> counter(num_verts, 0);
+ vector<float> raw_data(num_verts, 0.0f);
+ vector<float3> edge_accum(num_verts, make_float3(0.0f, 0.0f, 0.0f));
+ BL::Mesh::edges_iterator e;
+ EdgeMap visited_edges;
+ int edge_index = 0;
+ memset(&counter[0], 0, sizeof(int) * counter.size());
+ for (b_mesh.edges.begin(e); e != b_mesh.edges.end(); ++e, ++edge_index) {
+ const int v0 = vert_orig_index[b_mesh.edges[edge_index].vertices()[0]],
+ v1 = vert_orig_index[b_mesh.edges[edge_index].vertices()[1]];
+ if (visited_edges.exists(v0, v1)) {
+ continue;
+ }
+ visited_edges.insert(v0, v1);
+ float3 co0 = get_float3(b_mesh.vertices[v0].co()), co1 = get_float3(b_mesh.vertices[v1].co());
+ float3 edge = normalize(co1 - co0);
+ edge_accum[v0] += edge;
+ edge_accum[v1] += -edge;
+ ++counter[v0];
+ ++counter[v1];
+ }
+ for (int vert_index = 0; vert_index < num_verts; ++vert_index) {
+ const int orig_index = vert_orig_index[vert_index];
+ if (orig_index != vert_index) {
+ /* Skip duplicates, they'll be overwritten later on. */
+ continue;
+ }
+ if (counter[vert_index] > 0) {
+ const float3 normal = vert_normal[vert_index];
+ const float angle = safe_acosf(dot(normal, edge_accum[vert_index] / counter[vert_index]));
+ raw_data[vert_index] = angle * M_1_PI_F;
+ }
+ else {
+ raw_data[vert_index] = 0.0f;
+ }
+ }
+ /* STEP 3: Blur vertices to approximate 2 ring neighborhood. */
+ AttributeSet &attributes = (subdivision) ? mesh->subd_attributes : mesh->attributes;
+ Attribute *attr = attributes.add(ATTR_STD_POINTINESS);
+ float *data = attr->data_float();
+ memcpy(data, &raw_data[0], sizeof(float) * raw_data.size());
+ memset(&counter[0], 0, sizeof(int) * counter.size());
+ edge_index = 0;
+ visited_edges.clear();
+ for (b_mesh.edges.begin(e); e != b_mesh.edges.end(); ++e, ++edge_index) {
+ const int v0 = vert_orig_index[b_mesh.edges[edge_index].vertices()[0]],
+ v1 = vert_orig_index[b_mesh.edges[edge_index].vertices()[1]];
+ if (visited_edges.exists(v0, v1)) {
+ continue;
+ }
+ visited_edges.insert(v0, v1);
+ data[v0] += raw_data[v1];
+ data[v1] += raw_data[v0];
+ ++counter[v0];
+ ++counter[v1];
+ }
+ for (int vert_index = 0; vert_index < num_verts; ++vert_index) {
+ data[vert_index] /= counter[vert_index] + 1;
+ }
+ /* STEP 4: Copy attribute to the duplicated vertices. */
+ for (int vert_index = 0; vert_index < num_verts; ++vert_index) {
+ const int orig_index = vert_orig_index[vert_index];
+ data[vert_index] = data[orig_index];
+ }
}
/* Create Mesh */
static void create_mesh(Scene *scene,
Mesh *mesh,
- BL::Mesh& b_mesh,
- const vector<Shader*>& used_shaders,
+ BL::Mesh &b_mesh,
+ const vector<Shader *> &used_shaders,
bool subdivision = false,
bool subdivide_uvs = true)
{
- /* count vertices and faces */
- int numverts = b_mesh.vertices.length();
- int numfaces = (!subdivision) ? b_mesh.loop_triangles.length() : b_mesh.polygons.length();
- int numtris = 0;
- int numcorners = 0;
- int numngons = 0;
- bool use_loop_normals = b_mesh.use_auto_smooth() && (mesh->subdivision_type != Mesh::SUBDIVISION_CATMULL_CLARK);
-
- /* If no faces, create empty mesh. */
- if(numfaces == 0) {
- return;
- }
-
- if(!subdivision) {
- numtris = numfaces;
- }
- else {
- BL::Mesh::polygons_iterator p;
- for(b_mesh.polygons.begin(p); p != b_mesh.polygons.end(); ++p) {
- numngons += (p->loop_total() == 4)? 0: 1;
- numcorners += p->loop_total();
- }
- }
-
- /* allocate memory */
- mesh->reserve_mesh(numverts, numtris);
- mesh->reserve_subd_faces(numfaces, numngons, numcorners);
-
- /* create vertex coordinates and normals */
- BL::Mesh::vertices_iterator v;
- for(b_mesh.vertices.begin(v); v != b_mesh.vertices.end(); ++v)
- mesh->add_vertex(get_float3(v->co()));
-
- AttributeSet& attributes = (subdivision)? mesh->subd_attributes: mesh->attributes;
- Attribute *attr_N = attributes.add(ATTR_STD_VERTEX_NORMAL);
- float3 *N = attr_N->data_float3();
-
- for(b_mesh.vertices.begin(v); v != b_mesh.vertices.end(); ++v, ++N)
- *N = get_float3(v->normal());
- N = attr_N->data_float3();
-
- /* create generated coordinates from undeformed coordinates */
- const bool need_default_tangent =
- (subdivision == false) &&
- (b_mesh.uv_layers.length() == 0) &&
- (mesh->need_attribute(scene, ATTR_STD_UV_TANGENT));
- if(mesh->need_attribute(scene, ATTR_STD_GENERATED) ||
- need_default_tangent)
- {
- Attribute *attr = attributes.add(ATTR_STD_GENERATED);
- attr->flags |= ATTR_SUBDIVIDED;
-
- float3 loc, size;
- mesh_texture_space(b_mesh, loc, size);
-
- float3 *generated = attr->data_float3();
- size_t i = 0;
-
- for(b_mesh.vertices.begin(v); v != b_mesh.vertices.end(); ++v) {
- generated[i++] = get_float3(v->undeformed_co())*size - loc;
- }
- }
-
- /* create faces */
- if(!subdivision) {
- BL::Mesh::loop_triangles_iterator t;
-
- for(b_mesh.loop_triangles.begin(t); t != b_mesh.loop_triangles.end(); ++t) {
- BL::MeshPolygon p = b_mesh.polygons[t->polygon_index()];
- int3 vi = get_int3(t->vertices());
-
- int shader = clamp(p.material_index(), 0, used_shaders.size()-1);
- bool smooth = p.use_smooth() || use_loop_normals;
-
- if(use_loop_normals) {
- BL::Array<float, 9> loop_normals = t->split_normals();
- for(int i = 0; i < 3; i++) {
- N[vi[i]] = make_float3(loop_normals[i * 3],
- loop_normals[i * 3 + 1],
- loop_normals[i * 3 + 2]);
- }
- }
-
- /* Create triangles.
- *
- * NOTE: Autosmooth is already taken care about.
- */
- mesh->add_triangle(vi[0], vi[1], vi[2], shader, smooth);
- }
- }
- else {
- BL::Mesh::polygons_iterator p;
- vector<int> vi;
-
- for(b_mesh.polygons.begin(p); p != b_mesh.polygons.end(); ++p) {
- int n = p->loop_total();
- int shader = clamp(p->material_index(), 0, used_shaders.size()-1);
- bool smooth = p->use_smooth() || use_loop_normals;
-
- vi.resize(n);
- for(int i = 0; i < n; i++) {
- /* NOTE: Autosmooth is already taken care about. */
- vi[i] = b_mesh.loops[p->loop_start() + i].vertex_index();
- }
-
- /* create subd faces */
- mesh->add_subd_face(&vi[0], n, shader, smooth);
- }
- }
-
- /* Create all needed attributes.
- * The calculate functions will check whether they're needed or not.
- */
- attr_create_pointiness(scene, mesh, b_mesh, subdivision);
- attr_create_vertex_color(scene, mesh, b_mesh, subdivision);
-
- if(subdivision) {
- attr_create_subd_uv_map(scene, mesh, b_mesh, subdivide_uvs);
- }
- else {
- attr_create_uv_map(scene, mesh, b_mesh);
- }
-
- /* for volume objects, create a matrix to transform from object space to
- * mesh texture space. this does not work with deformations but that can
- * probably only be done well with a volume grid mapping of coordinates */
- if(mesh->need_attribute(scene, ATTR_STD_GENERATED_TRANSFORM)) {
- Attribute *attr = mesh->attributes.add(ATTR_STD_GENERATED_TRANSFORM);
- Transform *tfm = attr->data_transform();
-
- float3 loc, size;
- mesh_texture_space(b_mesh, loc, size);
-
- *tfm = transform_translate(-loc)*transform_scale(size);
- }
+ /* count vertices and faces */
+ int numverts = b_mesh.vertices.length();
+ int numfaces = (!subdivision) ? b_mesh.loop_triangles.length() : b_mesh.polygons.length();
+ int numtris = 0;
+ int numcorners = 0;
+ int numngons = 0;
+ bool use_loop_normals = b_mesh.use_auto_smooth() &&
+ (mesh->subdivision_type != Mesh::SUBDIVISION_CATMULL_CLARK);
+
+ /* If no faces, create empty mesh. */
+ if (numfaces == 0) {
+ return;
+ }
+
+ if (!subdivision) {
+ numtris = numfaces;
+ }
+ else {
+ BL::Mesh::polygons_iterator p;
+ for (b_mesh.polygons.begin(p); p != b_mesh.polygons.end(); ++p) {
+ numngons += (p->loop_total() == 4) ? 0 : 1;
+ numcorners += p->loop_total();
+ }
+ }
+
+ /* allocate memory */
+ mesh->reserve_mesh(numverts, numtris);
+ mesh->reserve_subd_faces(numfaces, numngons, numcorners);
+
+ /* create vertex coordinates and normals */
+ BL::Mesh::vertices_iterator v;
+ for (b_mesh.vertices.begin(v); v != b_mesh.vertices.end(); ++v)
+ mesh->add_vertex(get_float3(v->co()));
+
+ AttributeSet &attributes = (subdivision) ? mesh->subd_attributes : mesh->attributes;
+ Attribute *attr_N = attributes.add(ATTR_STD_VERTEX_NORMAL);
+ float3 *N = attr_N->data_float3();
+
+ for (b_mesh.vertices.begin(v); v != b_mesh.vertices.end(); ++v, ++N)
+ *N = get_float3(v->normal());
+ N = attr_N->data_float3();
+
+ /* create generated coordinates from undeformed coordinates */
+ const bool need_default_tangent = (subdivision == false) && (b_mesh.uv_layers.length() == 0) &&
+ (mesh->need_attribute(scene, ATTR_STD_UV_TANGENT));
+ if (mesh->need_attribute(scene, ATTR_STD_GENERATED) || need_default_tangent) {
+ Attribute *attr = attributes.add(ATTR_STD_GENERATED);
+ attr->flags |= ATTR_SUBDIVIDED;
+
+ float3 loc, size;
+ mesh_texture_space(b_mesh, loc, size);
+
+ float3 *generated = attr->data_float3();
+ size_t i = 0;
+
+ for (b_mesh.vertices.begin(v); v != b_mesh.vertices.end(); ++v) {
+ generated[i++] = get_float3(v->undeformed_co()) * size - loc;
+ }
+ }
+
+ /* create faces */
+ if (!subdivision) {
+ BL::Mesh::loop_triangles_iterator t;
+
+ for (b_mesh.loop_triangles.begin(t); t != b_mesh.loop_triangles.end(); ++t) {
+ BL::MeshPolygon p = b_mesh.polygons[t->polygon_index()];
+ int3 vi = get_int3(t->vertices());
+
+ int shader = clamp(p.material_index(), 0, used_shaders.size() - 1);
+ bool smooth = p.use_smooth() || use_loop_normals;
+
+ if (use_loop_normals) {
+ BL::Array<float, 9> loop_normals = t->split_normals();
+ for (int i = 0; i < 3; i++) {
+ N[vi[i]] = make_float3(
+ loop_normals[i * 3], loop_normals[i * 3 + 1], loop_normals[i * 3 + 2]);
+ }
+ }
+
+ /* Create triangles.
+ *
+ * NOTE: Autosmooth is already taken care about.
+ */
+ mesh->add_triangle(vi[0], vi[1], vi[2], shader, smooth);
+ }
+ }
+ else {
+ BL::Mesh::polygons_iterator p;
+ vector<int> vi;
+
+ for (b_mesh.polygons.begin(p); p != b_mesh.polygons.end(); ++p) {
+ int n = p->loop_total();
+ int shader = clamp(p->material_index(), 0, used_shaders.size() - 1);
+ bool smooth = p->use_smooth() || use_loop_normals;
+
+ vi.resize(n);
+ for (int i = 0; i < n; i++) {
+ /* NOTE: Autosmooth is already taken care about. */
+ vi[i] = b_mesh.loops[p->loop_start() + i].vertex_index();
+ }
+
+ /* create subd faces */
+ mesh->add_subd_face(&vi[0], n, shader, smooth);
+ }
+ }
+
+ /* Create all needed attributes.
+ * The calculate functions will check whether they're needed or not.
+ */
+ attr_create_pointiness(scene, mesh, b_mesh, subdivision);
+ attr_create_vertex_color(scene, mesh, b_mesh, subdivision);
+
+ if (subdivision) {
+ attr_create_subd_uv_map(scene, mesh, b_mesh, subdivide_uvs);
+ }
+ else {
+ attr_create_uv_map(scene, mesh, b_mesh);
+ }
+
+ /* for volume objects, create a matrix to transform from object space to
+ * mesh texture space. this does not work with deformations but that can
+ * probably only be done well with a volume grid mapping of coordinates */
+ if (mesh->need_attribute(scene, ATTR_STD_GENERATED_TRANSFORM)) {
+ Attribute *attr = mesh->attributes.add(ATTR_STD_GENERATED_TRANSFORM);
+ Transform *tfm = attr->data_transform();
+
+ float3 loc, size;
+ mesh_texture_space(b_mesh, loc, size);
+
+ *tfm = transform_translate(-loc) * transform_scale(size);
+ }
}
static void create_subd_mesh(Scene *scene,
Mesh *mesh,
- BL::Object& b_ob,
- BL::Mesh& b_mesh,
- const vector<Shader*>& used_shaders,
+ BL::Object &b_ob,
+ BL::Mesh &b_mesh,
+ const vector<Shader *> &used_shaders,
float dicing_rate,
int max_subdivisions)
{
- BL::SubsurfModifier subsurf_mod(b_ob.modifiers[b_ob.modifiers.length()-1]);
- bool subdivide_uvs = subsurf_mod.uv_smooth() != BL::SubsurfModifier::uv_smooth_NONE;
+ BL::SubsurfModifier subsurf_mod(b_ob.modifiers[b_ob.modifiers.length() - 1]);
+ bool subdivide_uvs = subsurf_mod.uv_smooth() != BL::SubsurfModifier::uv_smooth_NONE;
- create_mesh(scene, mesh, b_mesh, used_shaders, true, subdivide_uvs);
+ create_mesh(scene, mesh, b_mesh, used_shaders, true, subdivide_uvs);
- /* export creases */
- size_t num_creases = 0;
- BL::Mesh::edges_iterator e;
+ /* export creases */
+ size_t num_creases = 0;
+ BL::Mesh::edges_iterator e;
- for(b_mesh.edges.begin(e); e != b_mesh.edges.end(); ++e) {
- if(e->crease() != 0.0f) {
- num_creases++;
- }
- }
+ for (b_mesh.edges.begin(e); e != b_mesh.edges.end(); ++e) {
+ if (e->crease() != 0.0f) {
+ num_creases++;
+ }
+ }
- mesh->subd_creases.resize(num_creases);
+ mesh->subd_creases.resize(num_creases);
- Mesh::SubdEdgeCrease* crease = mesh->subd_creases.data();
- for(b_mesh.edges.begin(e); e != b_mesh.edges.end(); ++e) {
- if(e->crease() != 0.0f) {
- crease->v[0] = e->vertices()[0];
- crease->v[1] = e->vertices()[1];
- crease->crease = e->crease();
+ Mesh::SubdEdgeCrease *crease = mesh->subd_creases.data();
+ for (b_mesh.edges.begin(e); e != b_mesh.edges.end(); ++e) {
+ if (e->crease() != 0.0f) {
+ crease->v[0] = e->vertices()[0];
+ crease->v[1] = e->vertices()[1];
+ crease->crease = e->crease();
- crease++;
- }
- }
+ crease++;
+ }
+ }
- /* set subd params */
- if(!mesh->subd_params) {
- mesh->subd_params = new SubdParams(mesh);
- }
- SubdParams& sdparams = *mesh->subd_params;
+ /* set subd params */
+ if (!mesh->subd_params) {
+ mesh->subd_params = new SubdParams(mesh);
+ }
+ SubdParams &sdparams = *mesh->subd_params;
- PointerRNA cobj = RNA_pointer_get(&b_ob.ptr, "cycles");
+ PointerRNA cobj = RNA_pointer_get(&b_ob.ptr, "cycles");
- sdparams.dicing_rate = max(0.1f, RNA_float_get(&cobj, "dicing_rate") * dicing_rate);
- sdparams.max_level = max_subdivisions;
+ sdparams.dicing_rate = max(0.1f, RNA_float_get(&cobj, "dicing_rate") * dicing_rate);
+ sdparams.max_level = max_subdivisions;
- sdparams.objecttoworld = get_transform(b_ob.matrix_world());
+ sdparams.objecttoworld = get_transform(b_ob.matrix_world());
}
/* Sync */
-static void sync_mesh_fluid_motion(BL::Object& b_ob, Scene *scene, Mesh *mesh)
+static void sync_mesh_fluid_motion(BL::Object &b_ob, Scene *scene, Mesh *mesh)
{
- if(scene->need_motion() == Scene::MOTION_NONE)
- return;
+ if (scene->need_motion() == Scene::MOTION_NONE)
+ return;
- BL::DomainFluidSettings b_fluid_domain = object_fluid_domain_find(b_ob);
+ BL::DomainFluidSettings b_fluid_domain = object_fluid_domain_find(b_ob);
- if(!b_fluid_domain)
- return;
+ if (!b_fluid_domain)
+ return;
- /* If the mesh has modifiers following the fluid domain we can't export motion. */
- if(b_fluid_domain.fluid_mesh_vertices.length() != mesh->verts.size())
- return;
+ /* If the mesh has modifiers following the fluid domain we can't export motion. */
+ if (b_fluid_domain.fluid_mesh_vertices.length() != mesh->verts.size())
+ return;
- /* Find or add attribute */
- float3 *P = &mesh->verts[0];
- Attribute *attr_mP = mesh->attributes.find(ATTR_STD_MOTION_VERTEX_POSITION);
+ /* Find or add attribute */
+ float3 *P = &mesh->verts[0];
+ Attribute *attr_mP = mesh->attributes.find(ATTR_STD_MOTION_VERTEX_POSITION);
- if(!attr_mP) {
- attr_mP = mesh->attributes.add(ATTR_STD_MOTION_VERTEX_POSITION);
- }
+ if (!attr_mP) {
+ attr_mP = mesh->attributes.add(ATTR_STD_MOTION_VERTEX_POSITION);
+ }
- /* Only export previous and next frame, we don't have any in between data. */
- float motion_times[2] = {-1.0f, 1.0f};
- for(int step = 0; step < 2; step++) {
- float relative_time = motion_times[step] * scene->motion_shutter_time() * 0.5f;
- float3 *mP = attr_mP->data_float3() + step*mesh->verts.size();
+ /* Only export previous and next frame, we don't have any in between data. */
+ float motion_times[2] = {-1.0f, 1.0f};
+ for (int step = 0; step < 2; step++) {
+ float relative_time = motion_times[step] * scene->motion_shutter_time() * 0.5f;
+ float3 *mP = attr_mP->data_float3() + step * mesh->verts.size();
- BL::DomainFluidSettings::fluid_mesh_vertices_iterator fvi;
- int i = 0;
+ BL::DomainFluidSettings::fluid_mesh_vertices_iterator fvi;
+ int i = 0;
- for(b_fluid_domain.fluid_mesh_vertices.begin(fvi); fvi != b_fluid_domain.fluid_mesh_vertices.end(); ++fvi, ++i) {
- mP[i] = P[i] + get_float3(fvi->velocity()) * relative_time;
- }
- }
+ for (b_fluid_domain.fluid_mesh_vertices.begin(fvi);
+ fvi != b_fluid_domain.fluid_mesh_vertices.end();
+ ++fvi, ++i) {
+ mP[i] = P[i] + get_float3(fvi->velocity()) * relative_time;
+ }
+ }
}
-Mesh *BlenderSync::sync_mesh(BL::Depsgraph& b_depsgraph,
- BL::Object& b_ob,
- BL::Object& b_ob_instance,
+Mesh *BlenderSync::sync_mesh(BL::Depsgraph &b_depsgraph,
+ BL::Object &b_ob,
+ BL::Object &b_ob_instance,
bool object_updated,
bool show_self,
bool show_particles)
{
- /* test if we can instance or if the object is modified */
- BL::ID b_ob_data = b_ob.data();
- BL::ID key = (BKE_object_is_modified(b_ob))? b_ob_instance: b_ob_data;
- BL::Material material_override = view_layer.material_override;
-
- /* find shader indices */
- vector<Shader*> used_shaders;
-
- BL::Object::material_slots_iterator slot;
- for(b_ob.material_slots.begin(slot); slot != b_ob.material_slots.end(); ++slot) {
- if(material_override) {
- find_shader(material_override, used_shaders, scene->default_surface);
- }
- else {
- BL::ID b_material(slot->material());
- find_shader(b_material, used_shaders, scene->default_surface);
- }
- }
-
- if(used_shaders.size() == 0) {
- if(material_override)
- find_shader(material_override, used_shaders, scene->default_surface);
- else
- used_shaders.push_back(scene->default_surface);
- }
-
- /* test if we need to sync */
- int requested_geometry_flags = Mesh::GEOMETRY_NONE;
- if(view_layer.use_surfaces) {
- requested_geometry_flags |= Mesh::GEOMETRY_TRIANGLES;
- }
- if(view_layer.use_hair) {
- requested_geometry_flags |= Mesh::GEOMETRY_CURVES;
- }
- Mesh *mesh;
-
- if(!mesh_map.sync(&mesh, key)) {
- /* if transform was applied to mesh, need full update */
- if(object_updated && mesh->transform_applied);
- /* test if shaders changed, these can be object level so mesh
- * does not get tagged for recalc */
- else if(mesh->used_shaders != used_shaders);
- else if(requested_geometry_flags != mesh->geometry_flags);
- else {
- /* even if not tagged for recalc, we may need to sync anyway
- * because the shader needs different mesh attributes */
- bool attribute_recalc = false;
-
- foreach(Shader *shader, mesh->used_shaders)
- if(shader->need_update_mesh)
- attribute_recalc = true;
-
- if(!attribute_recalc)
- return mesh;
- }
- }
-
- /* ensure we only sync instanced meshes once */
- if(mesh_synced.find(mesh) != mesh_synced.end())
- return mesh;
-
- progress.set_sync_status("Synchronizing object", b_ob.name());
-
- mesh_synced.insert(mesh);
-
- /* create derived mesh */
- array<int> oldtriangles;
- array<Mesh::SubdFace> oldsubd_faces;
- array<int> oldsubd_face_corners;
- oldtriangles.steal_data(mesh->triangles);
- oldsubd_faces.steal_data(mesh->subd_faces);
- oldsubd_face_corners.steal_data(mesh->subd_face_corners);
-
- /* compares curve_keys rather than strands in order to handle quick hair
- * adjustments in dynamic BVH - other methods could probably do this better*/
- array<float3> oldcurve_keys;
- array<float> oldcurve_radius;
- oldcurve_keys.steal_data(mesh->curve_keys);
- oldcurve_radius.steal_data(mesh->curve_radius);
-
- mesh->clear();
- mesh->used_shaders = used_shaders;
- mesh->name = ustring(b_ob_data.name().c_str());
-
- if(requested_geometry_flags != Mesh::GEOMETRY_NONE) {
- /* Adaptive subdivision setup. Not for baking since that requires
- * exact mapping to the Blender mesh. */
- if(scene->bake_manager->get_baking()) {
- mesh->subdivision_type = Mesh::SUBDIVISION_NONE;
- }
- else {
- mesh->subdivision_type = object_subdivision_type(b_ob, preview, experimental);
- }
-
- /* For some reason, meshes do not need this... */
- bool need_undeformed = mesh->need_attribute(scene, ATTR_STD_GENERATED);
-
- BL::Mesh b_mesh = object_to_mesh(b_data,
- b_ob,
- b_depsgraph,
- need_undeformed,
- mesh->subdivision_type);
-
- if(b_mesh) {
- /* Sync mesh itself. */
- if(view_layer.use_surfaces && show_self) {
- if(mesh->subdivision_type != Mesh::SUBDIVISION_NONE)
- create_subd_mesh(scene, mesh, b_ob, b_mesh, used_shaders,
- dicing_rate, max_subdivisions);
- else
- create_mesh(scene, mesh, b_mesh, used_shaders, false);
-
- create_mesh_volume_attributes(scene, b_ob, mesh, b_scene.frame_current());
- }
-
- /* Sync hair curves. */
- if(view_layer.use_hair && show_particles && mesh->subdivision_type == Mesh::SUBDIVISION_NONE) {
- sync_curves(mesh, b_mesh, b_ob, false);
- }
-
- free_object_to_mesh(b_data, b_ob, b_mesh);
- }
- }
- mesh->geometry_flags = requested_geometry_flags;
-
- /* fluid motion */
- sync_mesh_fluid_motion(b_ob, scene, mesh);
-
- /* tag update */
- bool rebuild = (oldtriangles != mesh->triangles) ||
- (oldsubd_faces != mesh->subd_faces) ||
- (oldsubd_face_corners != mesh->subd_face_corners) ||
- (oldcurve_keys != mesh->curve_keys) ||
- (oldcurve_radius != mesh->curve_radius);
-
- mesh->tag_update(scene, rebuild);
-
- return mesh;
+ /* test if we can instance or if the object is modified */
+ BL::ID b_ob_data = b_ob.data();
+ BL::ID key = (BKE_object_is_modified(b_ob)) ? b_ob_instance : b_ob_data;
+ BL::Material material_override = view_layer.material_override;
+
+ /* find shader indices */
+ vector<Shader *> used_shaders;
+
+ BL::Object::material_slots_iterator slot;
+ for (b_ob.material_slots.begin(slot); slot != b_ob.material_slots.end(); ++slot) {
+ if (material_override) {
+ find_shader(material_override, used_shaders, scene->default_surface);
+ }
+ else {
+ BL::ID b_material(slot->material());
+ find_shader(b_material, used_shaders, scene->default_surface);
+ }
+ }
+
+ if (used_shaders.size() == 0) {
+ if (material_override)
+ find_shader(material_override, used_shaders, scene->default_surface);
+ else
+ used_shaders.push_back(scene->default_surface);
+ }
+
+ /* test if we need to sync */
+ int requested_geometry_flags = Mesh::GEOMETRY_NONE;
+ if (view_layer.use_surfaces) {
+ requested_geometry_flags |= Mesh::GEOMETRY_TRIANGLES;
+ }
+ if (view_layer.use_hair) {
+ requested_geometry_flags |= Mesh::GEOMETRY_CURVES;
+ }
+ Mesh *mesh;
+
+ if (!mesh_map.sync(&mesh, key)) {
+ /* if transform was applied to mesh, need full update */
+ if (object_updated && mesh->transform_applied)
+ ;
+ /* test if shaders changed, these can be object level so mesh
+ * does not get tagged for recalc */
+ else if (mesh->used_shaders != used_shaders)
+ ;
+ else if (requested_geometry_flags != mesh->geometry_flags)
+ ;
+ else {
+ /* even if not tagged for recalc, we may need to sync anyway
+ * because the shader needs different mesh attributes */
+ bool attribute_recalc = false;
+
+ foreach (Shader *shader, mesh->used_shaders)
+ if (shader->need_update_mesh)
+ attribute_recalc = true;
+
+ if (!attribute_recalc)
+ return mesh;
+ }
+ }
+
+ /* ensure we only sync instanced meshes once */
+ if (mesh_synced.find(mesh) != mesh_synced.end())
+ return mesh;
+
+ progress.set_sync_status("Synchronizing object", b_ob.name());
+
+ mesh_synced.insert(mesh);
+
+ /* create derived mesh */
+ array<int> oldtriangles;
+ array<Mesh::SubdFace> oldsubd_faces;
+ array<int> oldsubd_face_corners;
+ oldtriangles.steal_data(mesh->triangles);
+ oldsubd_faces.steal_data(mesh->subd_faces);
+ oldsubd_face_corners.steal_data(mesh->subd_face_corners);
+
+ /* compares curve_keys rather than strands in order to handle quick hair
+ * adjustments in dynamic BVH - other methods could probably do this better*/
+ array<float3> oldcurve_keys;
+ array<float> oldcurve_radius;
+ oldcurve_keys.steal_data(mesh->curve_keys);
+ oldcurve_radius.steal_data(mesh->curve_radius);
+
+ mesh->clear();
+ mesh->used_shaders = used_shaders;
+ mesh->name = ustring(b_ob_data.name().c_str());
+
+ if (requested_geometry_flags != Mesh::GEOMETRY_NONE) {
+ /* Adaptive subdivision setup. Not for baking since that requires
+ * exact mapping to the Blender mesh. */
+ if (scene->bake_manager->get_baking()) {
+ mesh->subdivision_type = Mesh::SUBDIVISION_NONE;
+ }
+ else {
+ mesh->subdivision_type = object_subdivision_type(b_ob, preview, experimental);
+ }
+
+ /* For some reason, meshes do not need this... */
+ bool need_undeformed = mesh->need_attribute(scene, ATTR_STD_GENERATED);
+
+ BL::Mesh b_mesh = object_to_mesh(
+ b_data, b_ob, b_depsgraph, need_undeformed, mesh->subdivision_type);
+
+ if (b_mesh) {
+ /* Sync mesh itself. */
+ if (view_layer.use_surfaces && show_self) {
+ if (mesh->subdivision_type != Mesh::SUBDIVISION_NONE)
+ create_subd_mesh(scene, mesh, b_ob, b_mesh, used_shaders, dicing_rate, max_subdivisions);
+ else
+ create_mesh(scene, mesh, b_mesh, used_shaders, false);
+
+ create_mesh_volume_attributes(scene, b_ob, mesh, b_scene.frame_current());
+ }
+
+ /* Sync hair curves. */
+ if (view_layer.use_hair && show_particles &&
+ mesh->subdivision_type == Mesh::SUBDIVISION_NONE) {
+ sync_curves(mesh, b_mesh, b_ob, false);
+ }
+
+ free_object_to_mesh(b_data, b_ob, b_mesh);
+ }
+ }
+ mesh->geometry_flags = requested_geometry_flags;
+
+ /* fluid motion */
+ sync_mesh_fluid_motion(b_ob, scene, mesh);
+
+ /* tag update */
+ bool rebuild = (oldtriangles != mesh->triangles) || (oldsubd_faces != mesh->subd_faces) ||
+ (oldsubd_face_corners != mesh->subd_face_corners) ||
+ (oldcurve_keys != mesh->curve_keys) || (oldcurve_radius != mesh->curve_radius);
+
+ mesh->tag_update(scene, rebuild);
+
+ return mesh;
}
-void BlenderSync::sync_mesh_motion(BL::Depsgraph& b_depsgraph,
- BL::Object& b_ob,
+void BlenderSync::sync_mesh_motion(BL::Depsgraph &b_depsgraph,
+ BL::Object &b_ob,
Object *object,
float motion_time)
{
- /* ensure we only sync instanced meshes once */
- Mesh *mesh = object->mesh;
-
- if(mesh_motion_synced.find(mesh) != mesh_motion_synced.end())
- return;
-
- mesh_motion_synced.insert(mesh);
-
- /* ensure we only motion sync meshes that also had mesh synced, to avoid
- * unnecessary work and to ensure that its attributes were clear */
- if(mesh_synced.find(mesh) == mesh_synced.end())
- return;
-
- /* Find time matching motion step required by mesh. */
- int motion_step = mesh->motion_step(motion_time);
- if(motion_step < 0) {
- return;
- }
-
- /* skip empty meshes */
- const size_t numverts = mesh->verts.size();
- const size_t numkeys = mesh->curve_keys.size();
-
- if(!numverts && !numkeys)
- return;
-
- /* skip objects without deforming modifiers. this is not totally reliable,
- * would need a more extensive check to see which objects are animated */
- BL::Mesh b_mesh(PointerRNA_NULL);
-
- /* fluid motion is exported immediate with mesh, skip here */
- BL::DomainFluidSettings b_fluid_domain = object_fluid_domain_find(b_ob);
- if(b_fluid_domain)
- return;
-
- if(ccl::BKE_object_is_deform_modified(b_ob, b_scene, preview)) {
- /* get derived mesh */
- b_mesh = object_to_mesh(b_data,
- b_ob,
- b_depsgraph,
- false,
- Mesh::SUBDIVISION_NONE);
- }
-
- if(!b_mesh) {
- /* if we have no motion blur on this frame, but on other frames, copy */
- if(numverts) {
- /* triangles */
- Attribute *attr_mP = mesh->attributes.find(ATTR_STD_MOTION_VERTEX_POSITION);
-
- if(attr_mP) {
- Attribute *attr_mN = mesh->attributes.find(ATTR_STD_MOTION_VERTEX_NORMAL);
- Attribute *attr_N = mesh->attributes.find(ATTR_STD_VERTEX_NORMAL);
- float3 *P = &mesh->verts[0];
- float3 *N = (attr_N)? attr_N->data_float3(): NULL;
-
- memcpy(attr_mP->data_float3() + motion_step*numverts, P, sizeof(float3)*numverts);
- if(attr_mN)
- memcpy(attr_mN->data_float3() + motion_step*numverts, N, sizeof(float3)*numverts);
- }
- }
-
- if(numkeys) {
- /* curves */
- Attribute *attr_mP = mesh->curve_attributes.find(ATTR_STD_MOTION_VERTEX_POSITION);
-
- if(attr_mP) {
- float3 *keys = &mesh->curve_keys[0];
- memcpy(attr_mP->data_float3() + motion_step*numkeys, keys, sizeof(float3)*numkeys);
- }
- }
-
- return;
- }
-
- /* TODO(sergey): Perform preliminary check for number of verticies. */
- if(numverts) {
- /* Find attributes. */
- Attribute *attr_mP = mesh->attributes.find(ATTR_STD_MOTION_VERTEX_POSITION);
- Attribute *attr_mN = mesh->attributes.find(ATTR_STD_MOTION_VERTEX_NORMAL);
- Attribute *attr_N = mesh->attributes.find(ATTR_STD_VERTEX_NORMAL);
- bool new_attribute = false;
- /* Add new attributes if they don't exist already. */
- if(!attr_mP) {
- attr_mP = mesh->attributes.add(ATTR_STD_MOTION_VERTEX_POSITION);
- if(attr_N)
- attr_mN = mesh->attributes.add(ATTR_STD_MOTION_VERTEX_NORMAL);
-
- new_attribute = true;
- }
- /* Load vertex data from mesh. */
- float3 *mP = attr_mP->data_float3() + motion_step*numverts;
- float3 *mN = (attr_mN)? attr_mN->data_float3() + motion_step*numverts: NULL;
- /* NOTE: We don't copy more that existing amount of vertices to prevent
- * possible memory corruption.
- */
- BL::Mesh::vertices_iterator v;
- int i = 0;
- for(b_mesh.vertices.begin(v); v != b_mesh.vertices.end() && i < numverts; ++v, ++i) {
- mP[i] = get_float3(v->co());
- if(mN)
- mN[i] = get_float3(v->normal());
- }
- if(new_attribute) {
- /* In case of new attribute, we verify if there really was any motion. */
- if(b_mesh.vertices.length() != numverts ||
- memcmp(mP, &mesh->verts[0], sizeof(float3)*numverts) == 0)
- {
- /* no motion, remove attributes again */
- if(b_mesh.vertices.length() != numverts) {
- VLOG(1) << "Topology differs, disabling motion blur for object "
- << b_ob.name();
- }
- else {
- VLOG(1) << "No actual deformation motion for object "
- << b_ob.name();
- }
- mesh->attributes.remove(ATTR_STD_MOTION_VERTEX_POSITION);
- if(attr_mN)
- mesh->attributes.remove(ATTR_STD_MOTION_VERTEX_NORMAL);
- }
- else if(motion_step > 0) {
- VLOG(1) << "Filling deformation motion for object " << b_ob.name();
- /* motion, fill up previous steps that we might have skipped because
- * they had no motion, but we need them anyway now */
- float3 *P = &mesh->verts[0];
- float3 *N = (attr_N)? attr_N->data_float3(): NULL;
- for(int step = 0; step < motion_step; step++) {
- memcpy(attr_mP->data_float3() + step*numverts, P, sizeof(float3)*numverts);
- if(attr_mN)
- memcpy(attr_mN->data_float3() + step*numverts, N, sizeof(float3)*numverts);
- }
- }
- }
- else {
- if(b_mesh.vertices.length() != numverts) {
- VLOG(1) << "Topology differs, discarding motion blur for object "
- << b_ob.name() << " at time " << motion_step;
- memcpy(mP, &mesh->verts[0], sizeof(float3)*numverts);
- if(mN != NULL) {
- memcpy(mN, attr_N->data_float3(), sizeof(float3)*numverts);
- }
- }
- }
- }
-
- /* hair motion */
- if(numkeys)
- sync_curves(mesh, b_mesh, b_ob, true, motion_step);
-
- /* free derived mesh */
- free_object_to_mesh(b_data, b_ob, b_mesh);
+ /* ensure we only sync instanced meshes once */
+ Mesh *mesh = object->mesh;
+
+ if (mesh_motion_synced.find(mesh) != mesh_motion_synced.end())
+ return;
+
+ mesh_motion_synced.insert(mesh);
+
+ /* ensure we only motion sync meshes that also had mesh synced, to avoid
+ * unnecessary work and to ensure that its attributes were clear */
+ if (mesh_synced.find(mesh) == mesh_synced.end())
+ return;
+
+ /* Find time matching motion step required by mesh. */
+ int motion_step = mesh->motion_step(motion_time);
+ if (motion_step < 0) {
+ return;
+ }
+
+ /* skip empty meshes */
+ const size_t numverts = mesh->verts.size();
+ const size_t numkeys = mesh->curve_keys.size();
+
+ if (!numverts && !numkeys)
+ return;
+
+ /* skip objects without deforming modifiers. this is not totally reliable,
+ * would need a more extensive check to see which objects are animated */
+ BL::Mesh b_mesh(PointerRNA_NULL);
+
+ /* fluid motion is exported immediate with mesh, skip here */
+ BL::DomainFluidSettings b_fluid_domain = object_fluid_domain_find(b_ob);
+ if (b_fluid_domain)
+ return;
+
+ if (ccl::BKE_object_is_deform_modified(b_ob, b_scene, preview)) {
+ /* get derived mesh */
+ b_mesh = object_to_mesh(b_data, b_ob, b_depsgraph, false, Mesh::SUBDIVISION_NONE);
+ }
+
+ if (!b_mesh) {
+ /* if we have no motion blur on this frame, but on other frames, copy */
+ if (numverts) {
+ /* triangles */
+ Attribute *attr_mP = mesh->attributes.find(ATTR_STD_MOTION_VERTEX_POSITION);
+
+ if (attr_mP) {
+ Attribute *attr_mN = mesh->attributes.find(ATTR_STD_MOTION_VERTEX_NORMAL);
+ Attribute *attr_N = mesh->attributes.find(ATTR_STD_VERTEX_NORMAL);
+ float3 *P = &mesh->verts[0];
+ float3 *N = (attr_N) ? attr_N->data_float3() : NULL;
+
+ memcpy(attr_mP->data_float3() + motion_step * numverts, P, sizeof(float3) * numverts);
+ if (attr_mN)
+ memcpy(attr_mN->data_float3() + motion_step * numverts, N, sizeof(float3) * numverts);
+ }
+ }
+
+ if (numkeys) {
+ /* curves */
+ Attribute *attr_mP = mesh->curve_attributes.find(ATTR_STD_MOTION_VERTEX_POSITION);
+
+ if (attr_mP) {
+ float3 *keys = &mesh->curve_keys[0];
+ memcpy(attr_mP->data_float3() + motion_step * numkeys, keys, sizeof(float3) * numkeys);
+ }
+ }
+
+ return;
+ }
+
+ /* TODO(sergey): Perform preliminary check for number of verticies. */
+ if (numverts) {
+ /* Find attributes. */
+ Attribute *attr_mP = mesh->attributes.find(ATTR_STD_MOTION_VERTEX_POSITION);
+ Attribute *attr_mN = mesh->attributes.find(ATTR_STD_MOTION_VERTEX_NORMAL);
+ Attribute *attr_N = mesh->attributes.find(ATTR_STD_VERTEX_NORMAL);
+ bool new_attribute = false;
+ /* Add new attributes if they don't exist already. */
+ if (!attr_mP) {
+ attr_mP = mesh->attributes.add(ATTR_STD_MOTION_VERTEX_POSITION);
+ if (attr_N)
+ attr_mN = mesh->attributes.add(ATTR_STD_MOTION_VERTEX_NORMAL);
+
+ new_attribute = true;
+ }
+ /* Load vertex data from mesh. */
+ float3 *mP = attr_mP->data_float3() + motion_step * numverts;
+ float3 *mN = (attr_mN) ? attr_mN->data_float3() + motion_step * numverts : NULL;
+ /* NOTE: We don't copy more that existing amount of vertices to prevent
+ * possible memory corruption.
+ */
+ BL::Mesh::vertices_iterator v;
+ int i = 0;
+ for (b_mesh.vertices.begin(v); v != b_mesh.vertices.end() && i < numverts; ++v, ++i) {
+ mP[i] = get_float3(v->co());
+ if (mN)
+ mN[i] = get_float3(v->normal());
+ }
+ if (new_attribute) {
+ /* In case of new attribute, we verify if there really was any motion. */
+ if (b_mesh.vertices.length() != numverts ||
+ memcmp(mP, &mesh->verts[0], sizeof(float3) * numverts) == 0) {
+ /* no motion, remove attributes again */
+ if (b_mesh.vertices.length() != numverts) {
+ VLOG(1) << "Topology differs, disabling motion blur for object " << b_ob.name();
+ }
+ else {
+ VLOG(1) << "No actual deformation motion for object " << b_ob.name();
+ }
+ mesh->attributes.remove(ATTR_STD_MOTION_VERTEX_POSITION);
+ if (attr_mN)
+ mesh->attributes.remove(ATTR_STD_MOTION_VERTEX_NORMAL);
+ }
+ else if (motion_step > 0) {
+ VLOG(1) << "Filling deformation motion for object " << b_ob.name();
+ /* motion, fill up previous steps that we might have skipped because
+ * they had no motion, but we need them anyway now */
+ float3 *P = &mesh->verts[0];
+ float3 *N = (attr_N) ? attr_N->data_float3() : NULL;
+ for (int step = 0; step < motion_step; step++) {
+ memcpy(attr_mP->data_float3() + step * numverts, P, sizeof(float3) * numverts);
+ if (attr_mN)
+ memcpy(attr_mN->data_float3() + step * numverts, N, sizeof(float3) * numverts);
+ }
+ }
+ }
+ else {
+ if (b_mesh.vertices.length() != numverts) {
+ VLOG(1) << "Topology differs, discarding motion blur for object " << b_ob.name()
+ << " at time " << motion_step;
+ memcpy(mP, &mesh->verts[0], sizeof(float3) * numverts);
+ if (mN != NULL) {
+ memcpy(mN, attr_N->data_float3(), sizeof(float3) * numverts);
+ }
+ }
+ }
+ }
+
+ /* hair motion */
+ if (numkeys)
+ sync_curves(mesh, b_mesh, b_ob, true, motion_step);
+
+ /* free derived mesh */
+ free_object_to_mesh(b_data, b_ob, b_mesh);
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/blender/blender_object.cpp b/intern/cycles/blender/blender_object.cpp
index a296488a14a..095ecd59985 100644
--- a/intern/cycles/blender/blender_object.cpp
+++ b/intern/cycles/blender/blender_object.cpp
@@ -37,646 +37,631 @@ CCL_NAMESPACE_BEGIN
/* Utilities */
-bool BlenderSync::BKE_object_is_modified(BL::Object& b_ob)
+bool BlenderSync::BKE_object_is_modified(BL::Object &b_ob)
{
- /* test if we can instance or if the object is modified */
- if(b_ob.type() == BL::Object::type_META) {
- /* multi-user and dupli metaballs are fused, can't instance */
- return true;
- }
- else if(ccl::BKE_object_is_modified(b_ob, b_scene, preview)) {
- /* modifiers */
- return true;
- }
- else {
- /* object level material links */
- BL::Object::material_slots_iterator slot;
- for(b_ob.material_slots.begin(slot); slot != b_ob.material_slots.end(); ++slot)
- if(slot->link() == BL::MaterialSlot::link_OBJECT)
- return true;
- }
-
- return false;
+ /* test if we can instance or if the object is modified */
+ if (b_ob.type() == BL::Object::type_META) {
+ /* multi-user and dupli metaballs are fused, can't instance */
+ return true;
+ }
+ else if (ccl::BKE_object_is_modified(b_ob, b_scene, preview)) {
+ /* modifiers */
+ return true;
+ }
+ else {
+ /* object level material links */
+ BL::Object::material_slots_iterator slot;
+ for (b_ob.material_slots.begin(slot); slot != b_ob.material_slots.end(); ++slot)
+ if (slot->link() == BL::MaterialSlot::link_OBJECT)
+ return true;
+ }
+
+ return false;
}
-bool BlenderSync::object_is_mesh(BL::Object& b_ob)
+bool BlenderSync::object_is_mesh(BL::Object &b_ob)
{
- BL::ID b_ob_data = b_ob.data();
-
- if(!b_ob_data) {
- return false;
- }
-
- if(b_ob.type() == BL::Object::type_CURVE) {
- /* Skip exporting curves without faces, overhead can be
- * significant if there are many for path animation. */
- BL::Curve b_curve(b_ob.data());
-
- return (b_curve.bevel_object() ||
- b_curve.extrude() != 0.0f ||
- b_curve.bevel_depth() != 0.0f ||
- b_curve.dimensions() == BL::Curve::dimensions_2D ||
- b_ob.modifiers.length());
- }
- else {
- return (b_ob_data.is_a(&RNA_Mesh) ||
- b_ob_data.is_a(&RNA_Curve) ||
- b_ob_data.is_a(&RNA_MetaBall));
- }
+ BL::ID b_ob_data = b_ob.data();
+
+ if (!b_ob_data) {
+ return false;
+ }
+
+ if (b_ob.type() == BL::Object::type_CURVE) {
+ /* Skip exporting curves without faces, overhead can be
+ * significant if there are many for path animation. */
+ BL::Curve b_curve(b_ob.data());
+
+ return (b_curve.bevel_object() || b_curve.extrude() != 0.0f || b_curve.bevel_depth() != 0.0f ||
+ b_curve.dimensions() == BL::Curve::dimensions_2D || b_ob.modifiers.length());
+ }
+ else {
+ return (b_ob_data.is_a(&RNA_Mesh) || b_ob_data.is_a(&RNA_Curve) ||
+ b_ob_data.is_a(&RNA_MetaBall));
+ }
}
-bool BlenderSync::object_is_light(BL::Object& b_ob)
+bool BlenderSync::object_is_light(BL::Object &b_ob)
{
- BL::ID b_ob_data = b_ob.data();
+ BL::ID b_ob_data = b_ob.data();
- return (b_ob_data && b_ob_data.is_a(&RNA_Light));
+ return (b_ob_data && b_ob_data.is_a(&RNA_Light));
}
-static uint object_ray_visibility(BL::Object& b_ob)
+static uint object_ray_visibility(BL::Object &b_ob)
{
- PointerRNA cvisibility = RNA_pointer_get(&b_ob.ptr, "cycles_visibility");
- uint flag = 0;
+ PointerRNA cvisibility = RNA_pointer_get(&b_ob.ptr, "cycles_visibility");
+ uint flag = 0;
- flag |= get_boolean(cvisibility, "camera")? PATH_RAY_CAMERA: 0;
- flag |= get_boolean(cvisibility, "diffuse")? PATH_RAY_DIFFUSE: 0;
- flag |= get_boolean(cvisibility, "glossy")? PATH_RAY_GLOSSY: 0;
- flag |= get_boolean(cvisibility, "transmission")? PATH_RAY_TRANSMIT: 0;
- flag |= get_boolean(cvisibility, "shadow")? PATH_RAY_SHADOW: 0;
- flag |= get_boolean(cvisibility, "scatter")? PATH_RAY_VOLUME_SCATTER: 0;
+ flag |= get_boolean(cvisibility, "camera") ? PATH_RAY_CAMERA : 0;
+ flag |= get_boolean(cvisibility, "diffuse") ? PATH_RAY_DIFFUSE : 0;
+ flag |= get_boolean(cvisibility, "glossy") ? PATH_RAY_GLOSSY : 0;
+ flag |= get_boolean(cvisibility, "transmission") ? PATH_RAY_TRANSMIT : 0;
+ flag |= get_boolean(cvisibility, "shadow") ? PATH_RAY_SHADOW : 0;
+ flag |= get_boolean(cvisibility, "scatter") ? PATH_RAY_VOLUME_SCATTER : 0;
- return flag;
+ return flag;
}
/* Light */
-void BlenderSync::sync_light(BL::Object& b_parent,
+void BlenderSync::sync_light(BL::Object &b_parent,
int persistent_id[OBJECT_PERSISTENT_ID_SIZE],
- BL::Object& b_ob,
- BL::Object& b_ob_instance,
+ BL::Object &b_ob,
+ BL::Object &b_ob_instance,
int random_id,
- Transform& tfm,
+ Transform &tfm,
bool *use_portal)
{
- /* test if we need to sync */
- Light *light;
- ObjectKey key(b_parent, persistent_id, b_ob_instance);
-
- if(!light_map.sync(&light, b_ob, b_parent, key)) {
- if(light->is_portal)
- *use_portal = true;
- return;
- }
-
- BL::Light b_light(b_ob.data());
-
- /* type */
- switch(b_light.type()) {
- case BL::Light::type_POINT: {
- BL::PointLight b_point_light(b_light);
- light->size = b_point_light.shadow_soft_size();
- light->type = LIGHT_POINT;
- break;
- }
- case BL::Light::type_SPOT: {
- BL::SpotLight b_spot_light(b_light);
- light->size = b_spot_light.shadow_soft_size();
- light->type = LIGHT_SPOT;
- light->spot_angle = b_spot_light.spot_size();
- light->spot_smooth = b_spot_light.spot_blend();
- break;
- }
- /* Hemi were removed from 2.8 */
- // case BL::Light::type_HEMI: {
- // light->type = LIGHT_DISTANT;
- // light->size = 0.0f;
- // break;
- // }
- case BL::Light::type_SUN: {
- BL::SunLight b_sun_light(b_light);
- light->size = b_sun_light.shadow_soft_size();
- light->type = LIGHT_DISTANT;
- break;
- }
- case BL::Light::type_AREA: {
- BL::AreaLight b_area_light(b_light);
- light->size = 1.0f;
- light->axisu = transform_get_column(&tfm, 0);
- light->axisv = transform_get_column(&tfm, 1);
- light->sizeu = b_area_light.size();
- switch(b_area_light.shape()) {
- case BL::AreaLight::shape_SQUARE:
- light->sizev = light->sizeu;
- light->round = false;
- break;
- case BL::AreaLight::shape_RECTANGLE:
- light->sizev = b_area_light.size_y();
- light->round = false;
- break;
- case BL::AreaLight::shape_DISK:
- light->sizev = light->sizeu;
- light->round = true;
- break;
- case BL::AreaLight::shape_ELLIPSE:
- light->sizev = b_area_light.size_y();
- light->round = true;
- break;
- }
- light->type = LIGHT_AREA;
- break;
- }
- }
-
- /* location and (inverted!) direction */
- light->co = transform_get_column(&tfm, 3);
- light->dir = -transform_get_column(&tfm, 2);
- light->tfm = tfm;
-
- /* shader */
- vector<Shader*> used_shaders;
- find_shader(b_light, used_shaders, scene->default_light);
- light->shader = used_shaders[0];
-
- /* shadow */
- PointerRNA cscene = RNA_pointer_get(&b_scene.ptr, "cycles");
- PointerRNA clight = RNA_pointer_get(&b_light.ptr, "cycles");
- light->cast_shadow = get_boolean(clight, "cast_shadow");
- light->use_mis = get_boolean(clight, "use_multiple_importance_sampling");
-
- int samples = get_int(clight, "samples");
- if(get_boolean(cscene, "use_square_samples"))
- light->samples = samples * samples;
- else
- light->samples = samples;
-
- light->max_bounces = get_int(clight, "max_bounces");
-
- if(b_ob != b_ob_instance) {
- light->random_id = random_id;
- }
- else {
- light->random_id = hash_int_2d(hash_string(b_ob.name().c_str()), 0);
- }
-
- if(light->type == LIGHT_AREA)
- light->is_portal = get_boolean(clight, "is_portal");
- else
- light->is_portal = false;
-
- if(light->is_portal)
- *use_portal = true;
-
- /* visibility */
- uint visibility = object_ray_visibility(b_ob);
- light->use_diffuse = (visibility & PATH_RAY_DIFFUSE) != 0;
- light->use_glossy = (visibility & PATH_RAY_GLOSSY) != 0;
- light->use_transmission = (visibility & PATH_RAY_TRANSMIT) != 0;
- light->use_scatter = (visibility & PATH_RAY_VOLUME_SCATTER) != 0;
-
- /* tag */
- light->tag_update(scene);
+ /* test if we need to sync */
+ Light *light;
+ ObjectKey key(b_parent, persistent_id, b_ob_instance);
+
+ if (!light_map.sync(&light, b_ob, b_parent, key)) {
+ if (light->is_portal)
+ *use_portal = true;
+ return;
+ }
+
+ BL::Light b_light(b_ob.data());
+
+ /* type */
+ switch (b_light.type()) {
+ case BL::Light::type_POINT: {
+ BL::PointLight b_point_light(b_light);
+ light->size = b_point_light.shadow_soft_size();
+ light->type = LIGHT_POINT;
+ break;
+ }
+ case BL::Light::type_SPOT: {
+ BL::SpotLight b_spot_light(b_light);
+ light->size = b_spot_light.shadow_soft_size();
+ light->type = LIGHT_SPOT;
+ light->spot_angle = b_spot_light.spot_size();
+ light->spot_smooth = b_spot_light.spot_blend();
+ break;
+ }
+ /* Hemi were removed from 2.8 */
+ // case BL::Light::type_HEMI: {
+ // light->type = LIGHT_DISTANT;
+ // light->size = 0.0f;
+ // break;
+ // }
+ case BL::Light::type_SUN: {
+ BL::SunLight b_sun_light(b_light);
+ light->size = b_sun_light.shadow_soft_size();
+ light->type = LIGHT_DISTANT;
+ break;
+ }
+ case BL::Light::type_AREA: {
+ BL::AreaLight b_area_light(b_light);
+ light->size = 1.0f;
+ light->axisu = transform_get_column(&tfm, 0);
+ light->axisv = transform_get_column(&tfm, 1);
+ light->sizeu = b_area_light.size();
+ switch (b_area_light.shape()) {
+ case BL::AreaLight::shape_SQUARE:
+ light->sizev = light->sizeu;
+ light->round = false;
+ break;
+ case BL::AreaLight::shape_RECTANGLE:
+ light->sizev = b_area_light.size_y();
+ light->round = false;
+ break;
+ case BL::AreaLight::shape_DISK:
+ light->sizev = light->sizeu;
+ light->round = true;
+ break;
+ case BL::AreaLight::shape_ELLIPSE:
+ light->sizev = b_area_light.size_y();
+ light->round = true;
+ break;
+ }
+ light->type = LIGHT_AREA;
+ break;
+ }
+ }
+
+ /* location and (inverted!) direction */
+ light->co = transform_get_column(&tfm, 3);
+ light->dir = -transform_get_column(&tfm, 2);
+ light->tfm = tfm;
+
+ /* shader */
+ vector<Shader *> used_shaders;
+ find_shader(b_light, used_shaders, scene->default_light);
+ light->shader = used_shaders[0];
+
+ /* shadow */
+ PointerRNA cscene = RNA_pointer_get(&b_scene.ptr, "cycles");
+ PointerRNA clight = RNA_pointer_get(&b_light.ptr, "cycles");
+ light->cast_shadow = get_boolean(clight, "cast_shadow");
+ light->use_mis = get_boolean(clight, "use_multiple_importance_sampling");
+
+ int samples = get_int(clight, "samples");
+ if (get_boolean(cscene, "use_square_samples"))
+ light->samples = samples * samples;
+ else
+ light->samples = samples;
+
+ light->max_bounces = get_int(clight, "max_bounces");
+
+ if (b_ob != b_ob_instance) {
+ light->random_id = random_id;
+ }
+ else {
+ light->random_id = hash_int_2d(hash_string(b_ob.name().c_str()), 0);
+ }
+
+ if (light->type == LIGHT_AREA)
+ light->is_portal = get_boolean(clight, "is_portal");
+ else
+ light->is_portal = false;
+
+ if (light->is_portal)
+ *use_portal = true;
+
+ /* visibility */
+ uint visibility = object_ray_visibility(b_ob);
+ light->use_diffuse = (visibility & PATH_RAY_DIFFUSE) != 0;
+ light->use_glossy = (visibility & PATH_RAY_GLOSSY) != 0;
+ light->use_transmission = (visibility & PATH_RAY_TRANSMIT) != 0;
+ light->use_scatter = (visibility & PATH_RAY_VOLUME_SCATTER) != 0;
+
+ /* tag */
+ light->tag_update(scene);
}
void BlenderSync::sync_background_light(bool use_portal)
{
- BL::World b_world = b_scene.world();
-
- if(b_world) {
- PointerRNA cscene = RNA_pointer_get(&b_scene.ptr, "cycles");
- PointerRNA cworld = RNA_pointer_get(&b_world.ptr, "cycles");
-
- enum SamplingMethod {
- SAMPLING_NONE = 0,
- SAMPLING_AUTOMATIC,
- SAMPLING_MANUAL,
- SAMPLING_NUM
- };
- int sampling_method = get_enum(cworld, "sampling_method", SAMPLING_NUM, SAMPLING_AUTOMATIC);
- bool sample_as_light = (sampling_method != SAMPLING_NONE);
-
- if(sample_as_light || use_portal) {
- /* test if we need to sync */
- Light *light;
- ObjectKey key(b_world, 0, b_world);
-
- if(light_map.sync(&light, b_world, b_world, key) ||
- world_recalc ||
- b_world.ptr.data != world_map)
- {
- light->type = LIGHT_BACKGROUND;
- if(sampling_method == SAMPLING_MANUAL) {
- light->map_resolution = get_int(cworld, "sample_map_resolution");
- }
- else {
- light->map_resolution = 0;
- }
- light->shader = scene->default_background;
- light->use_mis = sample_as_light;
- light->max_bounces = get_int(cworld, "max_bounces");
-
- int samples = get_int(cworld, "samples");
- if(get_boolean(cscene, "use_square_samples"))
- light->samples = samples * samples;
- else
- light->samples = samples;
-
- light->tag_update(scene);
- light_map.set_recalc(b_world);
- }
- }
- }
-
- world_map = b_world.ptr.data;
- world_recalc = false;
+ BL::World b_world = b_scene.world();
+
+ if (b_world) {
+ PointerRNA cscene = RNA_pointer_get(&b_scene.ptr, "cycles");
+ PointerRNA cworld = RNA_pointer_get(&b_world.ptr, "cycles");
+
+ enum SamplingMethod { SAMPLING_NONE = 0, SAMPLING_AUTOMATIC, SAMPLING_MANUAL, SAMPLING_NUM };
+ int sampling_method = get_enum(cworld, "sampling_method", SAMPLING_NUM, SAMPLING_AUTOMATIC);
+ bool sample_as_light = (sampling_method != SAMPLING_NONE);
+
+ if (sample_as_light || use_portal) {
+ /* test if we need to sync */
+ Light *light;
+ ObjectKey key(b_world, 0, b_world);
+
+ if (light_map.sync(&light, b_world, b_world, key) || world_recalc ||
+ b_world.ptr.data != world_map) {
+ light->type = LIGHT_BACKGROUND;
+ if (sampling_method == SAMPLING_MANUAL) {
+ light->map_resolution = get_int(cworld, "sample_map_resolution");
+ }
+ else {
+ light->map_resolution = 0;
+ }
+ light->shader = scene->default_background;
+ light->use_mis = sample_as_light;
+ light->max_bounces = get_int(cworld, "max_bounces");
+
+ int samples = get_int(cworld, "samples");
+ if (get_boolean(cscene, "use_square_samples"))
+ light->samples = samples * samples;
+ else
+ light->samples = samples;
+
+ light->tag_update(scene);
+ light_map.set_recalc(b_world);
+ }
+ }
+ }
+
+ world_map = b_world.ptr.data;
+ world_recalc = false;
}
/* Object */
-Object *BlenderSync::sync_object(BL::Depsgraph& b_depsgraph,
- BL::ViewLayer& b_view_layer,
- BL::DepsgraphObjectInstance& b_instance,
+Object *BlenderSync::sync_object(BL::Depsgraph &b_depsgraph,
+ BL::ViewLayer &b_view_layer,
+ BL::DepsgraphObjectInstance &b_instance,
float motion_time,
bool show_self,
bool show_particles,
- BlenderObjectCulling& culling,
+ BlenderObjectCulling &culling,
bool *use_portal)
{
- const bool is_instance = b_instance.is_instance();
- BL::Object b_ob = b_instance.object();
- BL::Object b_parent = is_instance ? b_instance.parent()
- : b_instance.object();
- BL::Object b_ob_instance = is_instance ? b_instance.instance_object()
- : b_ob;
- const bool motion = motion_time != 0.0f;
- /*const*/ Transform tfm = get_transform(b_ob.matrix_world());
- int *persistent_id = NULL;
- BL::Array<int, OBJECT_PERSISTENT_ID_SIZE> persistent_id_array;
- if(is_instance) {
- persistent_id_array = b_instance.persistent_id();
- persistent_id = persistent_id_array.data;
- }
-
- /* light is handled separately */
- if(!motion && object_is_light(b_ob)) {
- /* TODO: don't use lights for excluded layers used as mask layer,
- * when dynamic overrides are back. */
+ const bool is_instance = b_instance.is_instance();
+ BL::Object b_ob = b_instance.object();
+ BL::Object b_parent = is_instance ? b_instance.parent() : b_instance.object();
+ BL::Object b_ob_instance = is_instance ? b_instance.instance_object() : b_ob;
+ const bool motion = motion_time != 0.0f;
+ /*const*/ Transform tfm = get_transform(b_ob.matrix_world());
+ int *persistent_id = NULL;
+ BL::Array<int, OBJECT_PERSISTENT_ID_SIZE> persistent_id_array;
+ if (is_instance) {
+ persistent_id_array = b_instance.persistent_id();
+ persistent_id = persistent_id_array.data;
+ }
+
+ /* light is handled separately */
+ if (!motion && object_is_light(b_ob)) {
+ /* TODO: don't use lights for excluded layers used as mask layer,
+ * when dynamic overrides are back. */
#if 0
- if(!((layer_flag & view_layer.holdout_layer) &&
- (layer_flag & view_layer.exclude_layer)))
+ if(!((layer_flag & view_layer.holdout_layer) &&
+ (layer_flag & view_layer.exclude_layer)))
#endif
- {
- sync_light(b_parent,
- persistent_id,
- b_ob,
- b_ob_instance,
- is_instance ? b_instance.random_id() : 0,
- tfm,
- use_portal);
- }
-
- return NULL;
- }
-
- /* only interested in object that we can create meshes from */
- if(!object_is_mesh(b_ob)) {
- return NULL;
- }
-
- /* Perform object culling. */
- if(culling.test(scene, b_ob, tfm)) {
- return NULL;
- }
-
- /* Visibility flags for both parent and child. */
- PointerRNA cobject = RNA_pointer_get(&b_ob.ptr, "cycles");
- bool use_holdout = get_boolean(cobject, "is_holdout") ||
- b_parent.holdout_get(PointerRNA_NULL, b_view_layer);
- uint visibility = object_ray_visibility(b_ob) & PATH_RAY_ALL_VISIBILITY;
-
- if(b_parent.ptr.data != b_ob.ptr.data) {
- visibility &= object_ray_visibility(b_parent);
- }
-
- /* TODO: make holdout objects on excluded layer invisible for non-camera rays. */
+ {
+ sync_light(b_parent,
+ persistent_id,
+ b_ob,
+ b_ob_instance,
+ is_instance ? b_instance.random_id() : 0,
+ tfm,
+ use_portal);
+ }
+
+ return NULL;
+ }
+
+ /* only interested in object that we can create meshes from */
+ if (!object_is_mesh(b_ob)) {
+ return NULL;
+ }
+
+ /* Perform object culling. */
+ if (culling.test(scene, b_ob, tfm)) {
+ return NULL;
+ }
+
+ /* Visibility flags for both parent and child. */
+ PointerRNA cobject = RNA_pointer_get(&b_ob.ptr, "cycles");
+ bool use_holdout = get_boolean(cobject, "is_holdout") ||
+ b_parent.holdout_get(PointerRNA_NULL, b_view_layer);
+ uint visibility = object_ray_visibility(b_ob) & PATH_RAY_ALL_VISIBILITY;
+
+ if (b_parent.ptr.data != b_ob.ptr.data) {
+ visibility &= object_ray_visibility(b_parent);
+ }
+
+ /* TODO: make holdout objects on excluded layer invisible for non-camera rays. */
#if 0
- if(use_holdout && (layer_flag & view_layer.exclude_layer)) {
- visibility &= ~(PATH_RAY_ALL_VISIBILITY - PATH_RAY_CAMERA);
- }
+ if(use_holdout && (layer_flag & view_layer.exclude_layer)) {
+ visibility &= ~(PATH_RAY_ALL_VISIBILITY - PATH_RAY_CAMERA);
+ }
#endif
- /* Clear camera visibility for indirect only objects. */
- bool use_indirect_only = b_parent.indirect_only_get(PointerRNA_NULL, b_view_layer);
- if(use_indirect_only) {
- visibility &= ~PATH_RAY_CAMERA;
- }
-
- /* Don't export completely invisible objects. */
- if(visibility == 0) {
- return NULL;
- }
-
- /* key to lookup object */
- ObjectKey key(b_parent, persistent_id, b_ob_instance);
- Object *object;
-
- /* motion vector case */
- if(motion) {
- object = object_map.find(key);
-
- if(object && object->use_motion()) {
- /* Set transform at matching motion time step. */
- int time_index = object->motion_step(motion_time);
- if(time_index >= 0) {
- object->motion[time_index] = tfm;
- }
-
- /* mesh deformation */
- if(object->mesh)
- sync_mesh_motion(b_depsgraph, b_ob, object, motion_time);
- }
-
- return object;
- }
-
- /* test if we need to sync */
- bool object_updated = false;
-
- if(object_map.sync(&object, b_ob, b_parent, key))
- object_updated = true;
-
- /* mesh sync */
- object->mesh = sync_mesh(b_depsgraph, b_ob, b_ob_instance, object_updated, show_self, show_particles);
-
- /* special case not tracked by object update flags */
-
- /* holdout */
- if(use_holdout != object->use_holdout) {
- object->use_holdout = use_holdout;
- scene->object_manager->tag_update(scene);
- object_updated = true;
- }
-
- if(visibility != object->visibility) {
- object->visibility = visibility;
- object_updated = true;
- }
-
- bool is_shadow_catcher = get_boolean(cobject, "is_shadow_catcher");
- if(is_shadow_catcher != object->is_shadow_catcher) {
- object->is_shadow_catcher = is_shadow_catcher;
- object_updated = true;
- }
-
- /* sync the asset name for Cryptomatte */
- BL::Object parent = b_ob.parent();
- ustring parent_name;
- if(parent) {
- while(parent.parent()) {
- parent = parent.parent();
- }
- parent_name = parent.name();
- }
- else {
- parent_name = b_ob.name();
- }
- if(object->asset_name != parent_name) {
- object->asset_name = parent_name;
- object_updated = true;
- }
-
- /* object sync
- * transform comparison should not be needed, but duplis don't work perfect
- * in the depsgraph and may not signal changes, so this is a workaround */
- if(object_updated || (object->mesh && object->mesh->need_update) || tfm != object->tfm) {
- object->name = b_ob.name().c_str();
- object->pass_id = b_ob.pass_index();
- object->tfm = tfm;
- object->motion.clear();
-
- /* motion blur */
- Scene::MotionType need_motion = scene->need_motion();
- if(need_motion != Scene::MOTION_NONE && object->mesh) {
- Mesh *mesh = object->mesh;
- mesh->use_motion_blur = false;
- mesh->motion_steps = 0;
-
- uint motion_steps;
-
- if(need_motion == Scene::MOTION_BLUR) {
- motion_steps = object_motion_steps(b_parent, b_ob);
- mesh->motion_steps = motion_steps;
- if(motion_steps && object_use_deform_motion(b_parent, b_ob)) {
- mesh->use_motion_blur = true;
- }
- }
- else {
- motion_steps = 3;
- mesh->motion_steps = motion_steps;
- }
-
- object->motion.clear();
- object->motion.resize(motion_steps, transform_empty());
-
- if(motion_steps) {
- object->motion[motion_steps/2] = tfm;
-
- for(size_t step = 0; step < motion_steps; step++) {
- motion_times.insert(object->motion_time(step));
- }
- }
- }
-
- /* dupli texture coordinates and random_id */
- if(is_instance) {
- object->dupli_generated = 0.5f*get_float3(b_instance.orco()) - make_float3(0.5f, 0.5f, 0.5f);
- object->dupli_uv = get_float2(b_instance.uv());
- object->random_id = b_instance.random_id();
- }
- else {
- object->dupli_generated = make_float3(0.0f, 0.0f, 0.0f);
- object->dupli_uv = make_float2(0.0f, 0.0f);
- object->random_id = hash_int_2d(hash_string(object->name.c_str()), 0);
- }
-
- object->tag_update(scene);
- }
-
- if(is_instance) {
- /* Sync possible particle data. */
- sync_dupli_particle(b_parent, b_instance, object);
- }
-
- return object;
+ /* Clear camera visibility for indirect only objects. */
+ bool use_indirect_only = b_parent.indirect_only_get(PointerRNA_NULL, b_view_layer);
+ if (use_indirect_only) {
+ visibility &= ~PATH_RAY_CAMERA;
+ }
+
+ /* Don't export completely invisible objects. */
+ if (visibility == 0) {
+ return NULL;
+ }
+
+ /* key to lookup object */
+ ObjectKey key(b_parent, persistent_id, b_ob_instance);
+ Object *object;
+
+ /* motion vector case */
+ if (motion) {
+ object = object_map.find(key);
+
+ if (object && object->use_motion()) {
+ /* Set transform at matching motion time step. */
+ int time_index = object->motion_step(motion_time);
+ if (time_index >= 0) {
+ object->motion[time_index] = tfm;
+ }
+
+ /* mesh deformation */
+ if (object->mesh)
+ sync_mesh_motion(b_depsgraph, b_ob, object, motion_time);
+ }
+
+ return object;
+ }
+
+ /* test if we need to sync */
+ bool object_updated = false;
+
+ if (object_map.sync(&object, b_ob, b_parent, key))
+ object_updated = true;
+
+ /* mesh sync */
+ object->mesh = sync_mesh(
+ b_depsgraph, b_ob, b_ob_instance, object_updated, show_self, show_particles);
+
+ /* special case not tracked by object update flags */
+
+ /* holdout */
+ if (use_holdout != object->use_holdout) {
+ object->use_holdout = use_holdout;
+ scene->object_manager->tag_update(scene);
+ object_updated = true;
+ }
+
+ if (visibility != object->visibility) {
+ object->visibility = visibility;
+ object_updated = true;
+ }
+
+ bool is_shadow_catcher = get_boolean(cobject, "is_shadow_catcher");
+ if (is_shadow_catcher != object->is_shadow_catcher) {
+ object->is_shadow_catcher = is_shadow_catcher;
+ object_updated = true;
+ }
+
+ /* sync the asset name for Cryptomatte */
+ BL::Object parent = b_ob.parent();
+ ustring parent_name;
+ if (parent) {
+ while (parent.parent()) {
+ parent = parent.parent();
+ }
+ parent_name = parent.name();
+ }
+ else {
+ parent_name = b_ob.name();
+ }
+ if (object->asset_name != parent_name) {
+ object->asset_name = parent_name;
+ object_updated = true;
+ }
+
+ /* object sync
+ * transform comparison should not be needed, but duplis don't work perfect
+ * in the depsgraph and may not signal changes, so this is a workaround */
+ if (object_updated || (object->mesh && object->mesh->need_update) || tfm != object->tfm) {
+ object->name = b_ob.name().c_str();
+ object->pass_id = b_ob.pass_index();
+ object->tfm = tfm;
+ object->motion.clear();
+
+ /* motion blur */
+ Scene::MotionType need_motion = scene->need_motion();
+ if (need_motion != Scene::MOTION_NONE && object->mesh) {
+ Mesh *mesh = object->mesh;
+ mesh->use_motion_blur = false;
+ mesh->motion_steps = 0;
+
+ uint motion_steps;
+
+ if (need_motion == Scene::MOTION_BLUR) {
+ motion_steps = object_motion_steps(b_parent, b_ob);
+ mesh->motion_steps = motion_steps;
+ if (motion_steps && object_use_deform_motion(b_parent, b_ob)) {
+ mesh->use_motion_blur = true;
+ }
+ }
+ else {
+ motion_steps = 3;
+ mesh->motion_steps = motion_steps;
+ }
+
+ object->motion.clear();
+ object->motion.resize(motion_steps, transform_empty());
+
+ if (motion_steps) {
+ object->motion[motion_steps / 2] = tfm;
+
+ for (size_t step = 0; step < motion_steps; step++) {
+ motion_times.insert(object->motion_time(step));
+ }
+ }
+ }
+
+ /* dupli texture coordinates and random_id */
+ if (is_instance) {
+ object->dupli_generated = 0.5f * get_float3(b_instance.orco()) -
+ make_float3(0.5f, 0.5f, 0.5f);
+ object->dupli_uv = get_float2(b_instance.uv());
+ object->random_id = b_instance.random_id();
+ }
+ else {
+ object->dupli_generated = make_float3(0.0f, 0.0f, 0.0f);
+ object->dupli_uv = make_float2(0.0f, 0.0f);
+ object->random_id = hash_int_2d(hash_string(object->name.c_str()), 0);
+ }
+
+ object->tag_update(scene);
+ }
+
+ if (is_instance) {
+ /* Sync possible particle data. */
+ sync_dupli_particle(b_parent, b_instance, object);
+ }
+
+ return object;
}
/* Object Loop */
-void BlenderSync::sync_objects(BL::Depsgraph& b_depsgraph, float motion_time)
+void BlenderSync::sync_objects(BL::Depsgraph &b_depsgraph, float motion_time)
{
- /* layer data */
- bool motion = motion_time != 0.0f;
-
- if(!motion) {
- /* prepare for sync */
- light_map.pre_sync();
- mesh_map.pre_sync();
- object_map.pre_sync();
- particle_system_map.pre_sync();
- motion_times.clear();
- }
- else {
- mesh_motion_synced.clear();
- }
-
- /* initialize culling */
- BlenderObjectCulling culling(scene, b_scene);
-
- /* object loop */
- bool cancel = false;
- bool use_portal = false;
-
- BL::ViewLayer b_view_layer = b_depsgraph.view_layer_eval();
-
- BL::Depsgraph::object_instances_iterator b_instance_iter;
- for(b_depsgraph.object_instances.begin(b_instance_iter);
- b_instance_iter != b_depsgraph.object_instances.end() && !cancel;
- ++b_instance_iter)
- {
- BL::DepsgraphObjectInstance b_instance = *b_instance_iter;
- BL::Object b_ob = b_instance.object();
-
- /* load per-object culling data */
- culling.init_object(scene, b_ob);
-
- /* test if object needs to be hidden */
- const bool show_self = b_instance.show_self();
- const bool show_particles = b_instance.show_particles();
-
- if(show_self || show_particles) {
- /* object itself */
- sync_object(b_depsgraph,
- b_view_layer,
- b_instance,
- motion_time,
- show_self,
- show_particles,
- culling,
- &use_portal);
- }
-
- cancel = progress.get_cancel();
- }
-
- progress.set_sync_status("");
-
- if(!cancel && !motion) {
- sync_background_light(use_portal);
-
- /* handle removed data and modified pointers */
- if(light_map.post_sync())
- scene->light_manager->tag_update(scene);
- if(mesh_map.post_sync())
- scene->mesh_manager->tag_update(scene);
- if(object_map.post_sync())
- scene->object_manager->tag_update(scene);
- if(particle_system_map.post_sync())
- scene->particle_system_manager->tag_update(scene);
- }
-
- if(motion)
- mesh_motion_synced.clear();
+ /* layer data */
+ bool motion = motion_time != 0.0f;
+
+ if (!motion) {
+ /* prepare for sync */
+ light_map.pre_sync();
+ mesh_map.pre_sync();
+ object_map.pre_sync();
+ particle_system_map.pre_sync();
+ motion_times.clear();
+ }
+ else {
+ mesh_motion_synced.clear();
+ }
+
+ /* initialize culling */
+ BlenderObjectCulling culling(scene, b_scene);
+
+ /* object loop */
+ bool cancel = false;
+ bool use_portal = false;
+
+ BL::ViewLayer b_view_layer = b_depsgraph.view_layer_eval();
+
+ BL::Depsgraph::object_instances_iterator b_instance_iter;
+ for (b_depsgraph.object_instances.begin(b_instance_iter);
+ b_instance_iter != b_depsgraph.object_instances.end() && !cancel;
+ ++b_instance_iter) {
+ BL::DepsgraphObjectInstance b_instance = *b_instance_iter;
+ BL::Object b_ob = b_instance.object();
+
+ /* load per-object culling data */
+ culling.init_object(scene, b_ob);
+
+ /* test if object needs to be hidden */
+ const bool show_self = b_instance.show_self();
+ const bool show_particles = b_instance.show_particles();
+
+ if (show_self || show_particles) {
+ /* object itself */
+ sync_object(b_depsgraph,
+ b_view_layer,
+ b_instance,
+ motion_time,
+ show_self,
+ show_particles,
+ culling,
+ &use_portal);
+ }
+
+ cancel = progress.get_cancel();
+ }
+
+ progress.set_sync_status("");
+
+ if (!cancel && !motion) {
+ sync_background_light(use_portal);
+
+ /* handle removed data and modified pointers */
+ if (light_map.post_sync())
+ scene->light_manager->tag_update(scene);
+ if (mesh_map.post_sync())
+ scene->mesh_manager->tag_update(scene);
+ if (object_map.post_sync())
+ scene->object_manager->tag_update(scene);
+ if (particle_system_map.post_sync())
+ scene->particle_system_manager->tag_update(scene);
+ }
+
+ if (motion)
+ mesh_motion_synced.clear();
}
-void BlenderSync::sync_motion(BL::RenderSettings& b_render,
- BL::Depsgraph& b_depsgraph,
- BL::Object& b_override,
- int width, int height,
+void BlenderSync::sync_motion(BL::RenderSettings &b_render,
+ BL::Depsgraph &b_depsgraph,
+ BL::Object &b_override,
+ int width,
+ int height,
void **python_thread_state)
{
- if(scene->need_motion() == Scene::MOTION_NONE)
- return;
-
- /* get camera object here to deal with camera switch */
- BL::Object b_cam = b_scene.camera();
- if(b_override)
- b_cam = b_override;
-
- Camera prevcam = *(scene->camera);
-
- int frame_center = b_scene.frame_current();
- float subframe_center = b_scene.frame_subframe();
- float frame_center_delta = 0.0f;
-
- if(scene->need_motion() != Scene::MOTION_PASS &&
- scene->camera->motion_position != Camera::MOTION_POSITION_CENTER)
- {
- float shuttertime = scene->camera->shuttertime;
- if(scene->camera->motion_position == Camera::MOTION_POSITION_END) {
- frame_center_delta = -shuttertime * 0.5f;
- }
- else {
- assert(scene->camera->motion_position == Camera::MOTION_POSITION_START);
- frame_center_delta = shuttertime * 0.5f;
- }
-
- float time = frame_center + subframe_center + frame_center_delta;
- int frame = (int)floorf(time);
- float subframe = time - frame;
- python_thread_state_restore(python_thread_state);
- b_engine.frame_set(frame, subframe);
- python_thread_state_save(python_thread_state);
- sync_camera_motion(b_render, b_cam, width, height, 0.0f);
- sync_objects(b_depsgraph, 0.0f);
- }
-
- /* always sample these times for camera motion */
- motion_times.insert(-1.0f);
- motion_times.insert(1.0f);
-
- /* note iteration over motion_times set happens in sorted order */
- foreach(float relative_time, motion_times) {
- /* center time is already handled. */
- if(relative_time == 0.0f) {
- continue;
- }
-
- VLOG(1) << "Synchronizing motion for the relative time "
- << relative_time << ".";
-
- /* fixed shutter time to get previous and next frame for motion pass */
- float shuttertime = scene->motion_shutter_time();
-
- /* compute frame and subframe time */
- float time = frame_center + subframe_center + frame_center_delta + relative_time * shuttertime * 0.5f;
- int frame = (int)floorf(time);
- float subframe = time - frame;
-
- /* change frame */
- python_thread_state_restore(python_thread_state);
- b_engine.frame_set(frame, subframe);
- python_thread_state_save(python_thread_state);
-
- /* sync camera, only supports two times at the moment */
- if(relative_time == -1.0f || relative_time == 1.0f) {
- sync_camera_motion(b_render,
- b_cam,
- width, height,
- relative_time);
- }
-
- /* sync object */
- sync_objects(b_depsgraph, relative_time);
- }
-
- /* we need to set the python thread state again because this
- * function assumes it is being executed from python and will
- * try to save the thread state */
- python_thread_state_restore(python_thread_state);
- b_engine.frame_set(frame_center, subframe_center);
- python_thread_state_save(python_thread_state);
-
- /* tag camera for motion update */
- if(scene->camera->motion_modified(prevcam))
- scene->camera->tag_update();
+ if (scene->need_motion() == Scene::MOTION_NONE)
+ return;
+
+ /* get camera object here to deal with camera switch */
+ BL::Object b_cam = b_scene.camera();
+ if (b_override)
+ b_cam = b_override;
+
+ Camera prevcam = *(scene->camera);
+
+ int frame_center = b_scene.frame_current();
+ float subframe_center = b_scene.frame_subframe();
+ float frame_center_delta = 0.0f;
+
+ if (scene->need_motion() != Scene::MOTION_PASS &&
+ scene->camera->motion_position != Camera::MOTION_POSITION_CENTER) {
+ float shuttertime = scene->camera->shuttertime;
+ if (scene->camera->motion_position == Camera::MOTION_POSITION_END) {
+ frame_center_delta = -shuttertime * 0.5f;
+ }
+ else {
+ assert(scene->camera->motion_position == Camera::MOTION_POSITION_START);
+ frame_center_delta = shuttertime * 0.5f;
+ }
+
+ float time = frame_center + subframe_center + frame_center_delta;
+ int frame = (int)floorf(time);
+ float subframe = time - frame;
+ python_thread_state_restore(python_thread_state);
+ b_engine.frame_set(frame, subframe);
+ python_thread_state_save(python_thread_state);
+ sync_camera_motion(b_render, b_cam, width, height, 0.0f);
+ sync_objects(b_depsgraph, 0.0f);
+ }
+
+ /* always sample these times for camera motion */
+ motion_times.insert(-1.0f);
+ motion_times.insert(1.0f);
+
+ /* note iteration over motion_times set happens in sorted order */
+ foreach (float relative_time, motion_times) {
+ /* center time is already handled. */
+ if (relative_time == 0.0f) {
+ continue;
+ }
+
+ VLOG(1) << "Synchronizing motion for the relative time " << relative_time << ".";
+
+ /* fixed shutter time to get previous and next frame for motion pass */
+ float shuttertime = scene->motion_shutter_time();
+
+ /* compute frame and subframe time */
+ float time = frame_center + subframe_center + frame_center_delta +
+ relative_time * shuttertime * 0.5f;
+ int frame = (int)floorf(time);
+ float subframe = time - frame;
+
+ /* change frame */
+ python_thread_state_restore(python_thread_state);
+ b_engine.frame_set(frame, subframe);
+ python_thread_state_save(python_thread_state);
+
+ /* sync camera, only supports two times at the moment */
+ if (relative_time == -1.0f || relative_time == 1.0f) {
+ sync_camera_motion(b_render, b_cam, width, height, relative_time);
+ }
+
+ /* sync object */
+ sync_objects(b_depsgraph, relative_time);
+ }
+
+ /* we need to set the python thread state again because this
+ * function assumes it is being executed from python and will
+ * try to save the thread state */
+ python_thread_state_restore(python_thread_state);
+ b_engine.frame_set(frame_center, subframe_center);
+ python_thread_state_save(python_thread_state);
+
+ /* tag camera for motion update */
+ if (scene->camera->motion_modified(prevcam))
+ scene->camera->tag_update();
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/blender/blender_object_cull.cpp b/intern/cycles/blender/blender_object_cull.cpp
index 680d9d7b1ff..74f8fb1dc53 100644
--- a/intern/cycles/blender/blender_object_cull.cpp
+++ b/intern/cycles/blender/blender_object_cull.cpp
@@ -22,72 +22,69 @@
CCL_NAMESPACE_BEGIN
-BlenderObjectCulling::BlenderObjectCulling(Scene *scene, BL::Scene& b_scene)
- : use_scene_camera_cull_(false),
- use_camera_cull_(false),
- camera_cull_margin_(0.0f),
- use_scene_distance_cull_(false),
- use_distance_cull_(false),
- distance_cull_margin_(0.0f)
+BlenderObjectCulling::BlenderObjectCulling(Scene *scene, BL::Scene &b_scene)
+ : use_scene_camera_cull_(false),
+ use_camera_cull_(false),
+ camera_cull_margin_(0.0f),
+ use_scene_distance_cull_(false),
+ use_distance_cull_(false),
+ distance_cull_margin_(0.0f)
{
- if(b_scene.render().use_simplify()) {
- PointerRNA cscene = RNA_pointer_get(&b_scene.ptr, "cycles");
-
- use_scene_camera_cull_ = scene->camera->type != CAMERA_PANORAMA &&
- !b_scene.render().use_multiview() &&
- get_boolean(cscene, "use_camera_cull");
- use_scene_distance_cull_ = scene->camera->type != CAMERA_PANORAMA &&
- !b_scene.render().use_multiview() &&
- get_boolean(cscene, "use_distance_cull");
-
- camera_cull_margin_ = get_float(cscene, "camera_cull_margin");
- distance_cull_margin_ = get_float(cscene, "distance_cull_margin");
-
- if(distance_cull_margin_ == 0.0f) {
- use_scene_distance_cull_ = false;
- }
- }
+ if (b_scene.render().use_simplify()) {
+ PointerRNA cscene = RNA_pointer_get(&b_scene.ptr, "cycles");
+
+ use_scene_camera_cull_ = scene->camera->type != CAMERA_PANORAMA &&
+ !b_scene.render().use_multiview() &&
+ get_boolean(cscene, "use_camera_cull");
+ use_scene_distance_cull_ = scene->camera->type != CAMERA_PANORAMA &&
+ !b_scene.render().use_multiview() &&
+ get_boolean(cscene, "use_distance_cull");
+
+ camera_cull_margin_ = get_float(cscene, "camera_cull_margin");
+ distance_cull_margin_ = get_float(cscene, "distance_cull_margin");
+
+ if (distance_cull_margin_ == 0.0f) {
+ use_scene_distance_cull_ = false;
+ }
+ }
}
-void BlenderObjectCulling::init_object(Scene *scene, BL::Object& b_ob)
+void BlenderObjectCulling::init_object(Scene *scene, BL::Object &b_ob)
{
- if(!use_scene_camera_cull_ && !use_scene_distance_cull_) {
- return;
- }
+ if (!use_scene_camera_cull_ && !use_scene_distance_cull_) {
+ return;
+ }
- PointerRNA cobject = RNA_pointer_get(&b_ob.ptr, "cycles");
+ PointerRNA cobject = RNA_pointer_get(&b_ob.ptr, "cycles");
- use_camera_cull_ = use_scene_camera_cull_ && get_boolean(cobject, "use_camera_cull");
- use_distance_cull_ = use_scene_distance_cull_ && get_boolean(cobject, "use_distance_cull");
+ use_camera_cull_ = use_scene_camera_cull_ && get_boolean(cobject, "use_camera_cull");
+ use_distance_cull_ = use_scene_distance_cull_ && get_boolean(cobject, "use_distance_cull");
- if(use_camera_cull_ || use_distance_cull_) {
- /* Need to have proper projection matrix. */
- scene->camera->update(scene);
- }
+ if (use_camera_cull_ || use_distance_cull_) {
+ /* Need to have proper projection matrix. */
+ scene->camera->update(scene);
+ }
}
-bool BlenderObjectCulling::test(Scene *scene, BL::Object& b_ob, Transform& tfm)
+bool BlenderObjectCulling::test(Scene *scene, BL::Object &b_ob, Transform &tfm)
{
- if(!use_camera_cull_ && !use_distance_cull_) {
- return false;
- }
-
- /* Compute world space bounding box corners. */
- float3 bb[8];
- BL::Array<float, 24> boundbox = b_ob.bound_box();
- for(int i = 0; i < 8; ++i) {
- float3 p = make_float3(boundbox[3 * i + 0],
- boundbox[3 * i + 1],
- boundbox[3 * i + 2]);
- bb[i] = transform_point(&tfm, p);
- }
-
- bool camera_culled = use_camera_cull_ && test_camera(scene, bb);
- bool distance_culled = use_distance_cull_ && test_distance(scene, bb);
-
- return ((camera_culled && distance_culled) ||
- (camera_culled && !use_distance_cull_) ||
- (distance_culled && !use_camera_cull_));
+ if (!use_camera_cull_ && !use_distance_cull_) {
+ return false;
+ }
+
+ /* Compute world space bounding box corners. */
+ float3 bb[8];
+ BL::Array<float, 24> boundbox = b_ob.bound_box();
+ for (int i = 0; i < 8; ++i) {
+ float3 p = make_float3(boundbox[3 * i + 0], boundbox[3 * i + 1], boundbox[3 * i + 2]);
+ bb[i] = transform_point(&tfm, p);
+ }
+
+ bool camera_culled = use_camera_cull_ && test_camera(scene, bb);
+ bool distance_culled = use_distance_cull_ && test_distance(scene, bb);
+
+ return ((camera_culled && distance_culled) || (camera_culled && !use_distance_cull_) ||
+ (distance_culled && !use_camera_cull_));
}
/* TODO(sergey): Not really optimal, consider approaches based on k-DOP in order
@@ -95,54 +92,50 @@ bool BlenderObjectCulling::test(Scene *scene, BL::Object& b_ob, Transform& tfm)
*/
bool BlenderObjectCulling::test_camera(Scene *scene, float3 bb[8])
{
- Camera *cam = scene->camera;
- const ProjectionTransform& worldtondc = cam->worldtondc;
- float3 bb_min = make_float3(FLT_MAX, FLT_MAX, FLT_MAX),
- bb_max = make_float3(-FLT_MAX, -FLT_MAX, -FLT_MAX);
- bool all_behind = true;
- for(int i = 0; i < 8; ++i) {
- float3 p = bb[i];
- float4 b = make_float4(p.x, p.y, p.z, 1.0f);
- float4 c = make_float4(dot(worldtondc.x, b),
- dot(worldtondc.y, b),
- dot(worldtondc.z, b),
- dot(worldtondc.w, b));
- p = float4_to_float3(c / c.w);
- if(c.z < 0.0f) {
- p.x = 1.0f - p.x;
- p.y = 1.0f - p.y;
- }
- if(c.z >= -camera_cull_margin_) {
- all_behind = false;
- }
- bb_min = min(bb_min, p);
- bb_max = max(bb_max, p);
- }
- if(all_behind) {
- return true;
- }
- return (bb_min.x >= 1.0f + camera_cull_margin_ ||
- bb_min.y >= 1.0f + camera_cull_margin_ ||
- bb_max.x <= -camera_cull_margin_ ||
- bb_max.y <= -camera_cull_margin_);
+ Camera *cam = scene->camera;
+ const ProjectionTransform &worldtondc = cam->worldtondc;
+ float3 bb_min = make_float3(FLT_MAX, FLT_MAX, FLT_MAX),
+ bb_max = make_float3(-FLT_MAX, -FLT_MAX, -FLT_MAX);
+ bool all_behind = true;
+ for (int i = 0; i < 8; ++i) {
+ float3 p = bb[i];
+ float4 b = make_float4(p.x, p.y, p.z, 1.0f);
+ float4 c = make_float4(
+ dot(worldtondc.x, b), dot(worldtondc.y, b), dot(worldtondc.z, b), dot(worldtondc.w, b));
+ p = float4_to_float3(c / c.w);
+ if (c.z < 0.0f) {
+ p.x = 1.0f - p.x;
+ p.y = 1.0f - p.y;
+ }
+ if (c.z >= -camera_cull_margin_) {
+ all_behind = false;
+ }
+ bb_min = min(bb_min, p);
+ bb_max = max(bb_max, p);
+ }
+ if (all_behind) {
+ return true;
+ }
+ return (bb_min.x >= 1.0f + camera_cull_margin_ || bb_min.y >= 1.0f + camera_cull_margin_ ||
+ bb_max.x <= -camera_cull_margin_ || bb_max.y <= -camera_cull_margin_);
}
bool BlenderObjectCulling::test_distance(Scene *scene, float3 bb[8])
{
- float3 camera_position = transform_get_column(&scene->camera->matrix, 3);
- float3 bb_min = make_float3(FLT_MAX, FLT_MAX, FLT_MAX),
- bb_max = make_float3(-FLT_MAX, -FLT_MAX, -FLT_MAX);
-
- /* Find min & max points for x & y & z on bounding box */
- for(int i = 0; i < 8; ++i) {
- float3 p = bb[i];
- bb_min = min(bb_min, p);
- bb_max = max(bb_max, p);
- }
-
- float3 closest_point = max(min(bb_max,camera_position),bb_min);
- return (len_squared(camera_position - closest_point) >
- distance_cull_margin_ * distance_cull_margin_);
+ float3 camera_position = transform_get_column(&scene->camera->matrix, 3);
+ float3 bb_min = make_float3(FLT_MAX, FLT_MAX, FLT_MAX),
+ bb_max = make_float3(-FLT_MAX, -FLT_MAX, -FLT_MAX);
+
+ /* Find min & max points for x & y & z on bounding box */
+ for (int i = 0; i < 8; ++i) {
+ float3 p = bb[i];
+ bb_min = min(bb_min, p);
+ bb_max = max(bb_max, p);
+ }
+
+ float3 closest_point = max(min(bb_max, camera_position), bb_min);
+ return (len_squared(camera_position - closest_point) >
+ distance_cull_margin_ * distance_cull_margin_);
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/blender/blender_object_cull.h b/intern/cycles/blender/blender_object_cull.h
index 6e2a22438ec..0879db4f802 100644
--- a/intern/cycles/blender/blender_object_cull.h
+++ b/intern/cycles/blender/blender_object_cull.h
@@ -24,26 +24,25 @@ CCL_NAMESPACE_BEGIN
class Scene;
-class BlenderObjectCulling
-{
-public:
- BlenderObjectCulling(Scene *scene, BL::Scene& b_scene);
-
- void init_object(Scene *scene, BL::Object& b_ob);
- bool test(Scene *scene, BL::Object& b_ob, Transform& tfm);
-
-private:
- bool test_camera(Scene *scene, float3 bb[8]);
- bool test_distance(Scene *scene, float3 bb[8]);
-
- bool use_scene_camera_cull_;
- bool use_camera_cull_;
- float camera_cull_margin_;
- bool use_scene_distance_cull_;
- bool use_distance_cull_;
- float distance_cull_margin_;
+class BlenderObjectCulling {
+ public:
+ BlenderObjectCulling(Scene *scene, BL::Scene &b_scene);
+
+ void init_object(Scene *scene, BL::Object &b_ob);
+ bool test(Scene *scene, BL::Object &b_ob, Transform &tfm);
+
+ private:
+ bool test_camera(Scene *scene, float3 bb[8]);
+ bool test_distance(Scene *scene, float3 bb[8]);
+
+ bool use_scene_camera_cull_;
+ bool use_camera_cull_;
+ float camera_cull_margin_;
+ bool use_scene_distance_cull_;
+ bool use_distance_cull_;
+ float distance_cull_margin_;
};
CCL_NAMESPACE_END
-#endif /* __BLENDER_OBJECT_CULL_H__ */
+#endif /* __BLENDER_OBJECT_CULL_H__ */
diff --git a/intern/cycles/blender/blender_particles.cpp b/intern/cycles/blender/blender_particles.cpp
index a733a499826..d74f132ed60 100644
--- a/intern/cycles/blender/blender_particles.cpp
+++ b/intern/cycles/blender/blender_particles.cpp
@@ -27,66 +27,66 @@ CCL_NAMESPACE_BEGIN
/* Utilities */
-bool BlenderSync::sync_dupli_particle(BL::Object& b_ob,
- BL::DepsgraphObjectInstance& b_instance,
+bool BlenderSync::sync_dupli_particle(BL::Object &b_ob,
+ BL::DepsgraphObjectInstance &b_instance,
Object *object)
{
- /* test if this dupli was generated from a particle sytem */
- BL::ParticleSystem b_psys = b_instance.particle_system();
- if(!b_psys)
- return false;
-
- object->hide_on_missing_motion = true;
-
- /* test if we need particle data */
- if(!object->mesh->need_attribute(scene, ATTR_STD_PARTICLE))
- return false;
-
- /* don't handle child particles yet */
- BL::Array<int, OBJECT_PERSISTENT_ID_SIZE> persistent_id = b_instance.persistent_id();
-
- if(persistent_id[0] >= b_psys.particles.length())
- return false;
-
- /* find particle system */
- ParticleSystemKey key(b_ob, persistent_id);
- ParticleSystem *psys;
-
- bool first_use = !particle_system_map.is_used(key);
- bool need_update = particle_system_map.sync(&psys, b_ob, b_instance.object(), key);
-
- /* no update needed? */
- if(!need_update && !object->mesh->need_update && !scene->object_manager->need_update)
- return true;
-
- /* first time used in this sync loop? clear and tag update */
- if(first_use) {
- psys->particles.clear();
- psys->tag_update(scene);
- }
-
- /* add particle */
- BL::Particle b_pa = b_psys.particles[persistent_id[0]];
- Particle pa;
-
- pa.index = persistent_id[0];
- pa.age = b_scene.frame_current() - b_pa.birth_time();
- pa.lifetime = b_pa.lifetime();
- pa.location = get_float3(b_pa.location());
- pa.rotation = get_float4(b_pa.rotation());
- pa.size = b_pa.size();
- pa.velocity = get_float3(b_pa.velocity());
- pa.angular_velocity = get_float3(b_pa.angular_velocity());
-
- psys->particles.push_back_slow(pa);
-
- if(object->particle_index != psys->particles.size() - 1)
- scene->object_manager->tag_update(scene);
- object->particle_system = psys;
- object->particle_index = psys->particles.size() - 1;
-
- /* return that this object has particle data */
- return true;
+ /* test if this dupli was generated from a particle sytem */
+ BL::ParticleSystem b_psys = b_instance.particle_system();
+ if (!b_psys)
+ return false;
+
+ object->hide_on_missing_motion = true;
+
+ /* test if we need particle data */
+ if (!object->mesh->need_attribute(scene, ATTR_STD_PARTICLE))
+ return false;
+
+ /* don't handle child particles yet */
+ BL::Array<int, OBJECT_PERSISTENT_ID_SIZE> persistent_id = b_instance.persistent_id();
+
+ if (persistent_id[0] >= b_psys.particles.length())
+ return false;
+
+ /* find particle system */
+ ParticleSystemKey key(b_ob, persistent_id);
+ ParticleSystem *psys;
+
+ bool first_use = !particle_system_map.is_used(key);
+ bool need_update = particle_system_map.sync(&psys, b_ob, b_instance.object(), key);
+
+ /* no update needed? */
+ if (!need_update && !object->mesh->need_update && !scene->object_manager->need_update)
+ return true;
+
+ /* first time used in this sync loop? clear and tag update */
+ if (first_use) {
+ psys->particles.clear();
+ psys->tag_update(scene);
+ }
+
+ /* add particle */
+ BL::Particle b_pa = b_psys.particles[persistent_id[0]];
+ Particle pa;
+
+ pa.index = persistent_id[0];
+ pa.age = b_scene.frame_current() - b_pa.birth_time();
+ pa.lifetime = b_pa.lifetime();
+ pa.location = get_float3(b_pa.location());
+ pa.rotation = get_float4(b_pa.rotation());
+ pa.size = b_pa.size();
+ pa.velocity = get_float3(b_pa.velocity());
+ pa.angular_velocity = get_float3(b_pa.angular_velocity());
+
+ psys->particles.push_back_slow(pa);
+
+ if (object->particle_index != psys->particles.size() - 1)
+ scene->object_manager->tag_update(scene);
+ object->particle_system = psys;
+ object->particle_index = psys->particles.size() - 1;
+
+ /* return that this object has particle data */
+ return true;
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/blender/blender_python.cpp b/intern/cycles/blender/blender_python.cpp
index ccd783073a3..ffd1c70a4e4 100644
--- a/intern/cycles/blender/blender_python.cpp
+++ b/intern/cycles/blender/blender_python.cpp
@@ -35,14 +35,14 @@
#include "util/util_types.h"
#ifdef WITH_OSL
-#include "render/osl.h"
+# include "render/osl.h"
-#include <OSL/oslquery.h>
-#include <OSL/oslconfig.h>
+# include <OSL/oslquery.h>
+# include <OSL/oslconfig.h>
#endif
#ifdef WITH_OPENCL
-#include "device/device_intern.h"
+# include "device/device_intern.h"
#endif
CCL_NAMESPACE_BEGIN
@@ -54,9 +54,9 @@ bool debug_flags_set = false;
void *pylong_as_voidptr_typesafe(PyObject *object)
{
- if(object == Py_None)
- return NULL;
- return PyLong_AsVoidPtr(object);
+ if (object == Py_None)
+ return NULL;
+ return PyLong_AsVoidPtr(object);
}
/* Synchronize debug flags from a given Blender scene.
@@ -64,48 +64,48 @@ void *pylong_as_voidptr_typesafe(PyObject *object)
*/
bool debug_flags_sync_from_scene(BL::Scene b_scene)
{
- DebugFlagsRef flags = DebugFlags();
- PointerRNA cscene = RNA_pointer_get(&b_scene.ptr, "cycles");
- /* Backup some settings for comparison. */
- DebugFlags::OpenCL::DeviceType opencl_device_type = flags.opencl.device_type;
- /* Synchronize shared flags. */
- flags.viewport_static_bvh = get_enum(cscene, "debug_bvh_type");
- /* Synchronize CPU flags. */
- flags.cpu.avx2 = get_boolean(cscene, "debug_use_cpu_avx2");
- flags.cpu.avx = get_boolean(cscene, "debug_use_cpu_avx");
- flags.cpu.sse41 = get_boolean(cscene, "debug_use_cpu_sse41");
- flags.cpu.sse3 = get_boolean(cscene, "debug_use_cpu_sse3");
- flags.cpu.sse2 = get_boolean(cscene, "debug_use_cpu_sse2");
- flags.cpu.bvh_layout = (BVHLayout)get_enum(cscene, "debug_bvh_layout");
- flags.cpu.split_kernel = get_boolean(cscene, "debug_use_cpu_split_kernel");
- /* Synchronize CUDA flags. */
- flags.cuda.adaptive_compile = get_boolean(cscene, "debug_use_cuda_adaptive_compile");
- flags.cuda.split_kernel = get_boolean(cscene, "debug_use_cuda_split_kernel");
- /* Synchronize OpenCL device type. */
- switch(get_enum(cscene, "debug_opencl_device_type")) {
- case 0:
- flags.opencl.device_type = DebugFlags::OpenCL::DEVICE_NONE;
- break;
- case 1:
- flags.opencl.device_type = DebugFlags::OpenCL::DEVICE_ALL;
- break;
- case 2:
- flags.opencl.device_type = DebugFlags::OpenCL::DEVICE_DEFAULT;
- break;
- case 3:
- flags.opencl.device_type = DebugFlags::OpenCL::DEVICE_CPU;
- break;
- case 4:
- flags.opencl.device_type = DebugFlags::OpenCL::DEVICE_GPU;
- break;
- case 5:
- flags.opencl.device_type = DebugFlags::OpenCL::DEVICE_ACCELERATOR;
- break;
- }
- /* Synchronize other OpenCL flags. */
- flags.opencl.debug = get_boolean(cscene, "debug_use_opencl_debug");
- flags.opencl.mem_limit = ((size_t)get_int(cscene, "debug_opencl_mem_limit"))*1024*1024;
- return flags.opencl.device_type != opencl_device_type;
+ DebugFlagsRef flags = DebugFlags();
+ PointerRNA cscene = RNA_pointer_get(&b_scene.ptr, "cycles");
+ /* Backup some settings for comparison. */
+ DebugFlags::OpenCL::DeviceType opencl_device_type = flags.opencl.device_type;
+ /* Synchronize shared flags. */
+ flags.viewport_static_bvh = get_enum(cscene, "debug_bvh_type");
+ /* Synchronize CPU flags. */
+ flags.cpu.avx2 = get_boolean(cscene, "debug_use_cpu_avx2");
+ flags.cpu.avx = get_boolean(cscene, "debug_use_cpu_avx");
+ flags.cpu.sse41 = get_boolean(cscene, "debug_use_cpu_sse41");
+ flags.cpu.sse3 = get_boolean(cscene, "debug_use_cpu_sse3");
+ flags.cpu.sse2 = get_boolean(cscene, "debug_use_cpu_sse2");
+ flags.cpu.bvh_layout = (BVHLayout)get_enum(cscene, "debug_bvh_layout");
+ flags.cpu.split_kernel = get_boolean(cscene, "debug_use_cpu_split_kernel");
+ /* Synchronize CUDA flags. */
+ flags.cuda.adaptive_compile = get_boolean(cscene, "debug_use_cuda_adaptive_compile");
+ flags.cuda.split_kernel = get_boolean(cscene, "debug_use_cuda_split_kernel");
+ /* Synchronize OpenCL device type. */
+ switch (get_enum(cscene, "debug_opencl_device_type")) {
+ case 0:
+ flags.opencl.device_type = DebugFlags::OpenCL::DEVICE_NONE;
+ break;
+ case 1:
+ flags.opencl.device_type = DebugFlags::OpenCL::DEVICE_ALL;
+ break;
+ case 2:
+ flags.opencl.device_type = DebugFlags::OpenCL::DEVICE_DEFAULT;
+ break;
+ case 3:
+ flags.opencl.device_type = DebugFlags::OpenCL::DEVICE_CPU;
+ break;
+ case 4:
+ flags.opencl.device_type = DebugFlags::OpenCL::DEVICE_GPU;
+ break;
+ case 5:
+ flags.opencl.device_type = DebugFlags::OpenCL::DEVICE_ACCELERATOR;
+ break;
+ }
+ /* Synchronize other OpenCL flags. */
+ flags.opencl.debug = get_boolean(cscene, "debug_use_opencl_debug");
+ flags.opencl.mem_limit = ((size_t)get_int(cscene, "debug_opencl_mem_limit")) * 1024 * 1024;
+ return flags.opencl.device_type != opencl_device_type;
}
/* Reset debug flags to default values.
@@ -113,928 +113,958 @@ bool debug_flags_sync_from_scene(BL::Scene b_scene)
*/
bool debug_flags_reset()
{
- DebugFlagsRef flags = DebugFlags();
- /* Backup some settings for comparison. */
- DebugFlags::OpenCL::DeviceType opencl_device_type = flags.opencl.device_type;
- flags.reset();
- return flags.opencl.device_type != opencl_device_type;
+ DebugFlagsRef flags = DebugFlags();
+ /* Backup some settings for comparison. */
+ DebugFlags::OpenCL::DeviceType opencl_device_type = flags.opencl.device_type;
+ flags.reset();
+ return flags.opencl.device_type != opencl_device_type;
}
-} /* namespace */
+} /* namespace */
void python_thread_state_save(void **python_thread_state)
{
- *python_thread_state = (void*)PyEval_SaveThread();
+ *python_thread_state = (void *)PyEval_SaveThread();
}
void python_thread_state_restore(void **python_thread_state)
{
- PyEval_RestoreThread((PyThreadState*)*python_thread_state);
- *python_thread_state = NULL;
+ PyEval_RestoreThread((PyThreadState *)*python_thread_state);
+ *python_thread_state = NULL;
}
static const char *PyC_UnicodeAsByte(PyObject *py_str, PyObject **coerce)
{
- const char *result = _PyUnicode_AsString(py_str);
- if(result) {
- /* 99% of the time this is enough but we better support non unicode
- * chars since blender doesnt limit this.
- */
- return result;
- }
- else {
- PyErr_Clear();
- if(PyBytes_Check(py_str)) {
- return PyBytes_AS_STRING(py_str);
- }
- else if((*coerce = PyUnicode_EncodeFSDefault(py_str))) {
- return PyBytes_AS_STRING(*coerce);
- }
- else {
- /* Clear the error, so Cycles can be at leadt used without
- * GPU and OSL support,
- */
- PyErr_Clear();
- return "";
- }
- }
+ const char *result = _PyUnicode_AsString(py_str);
+ if (result) {
+ /* 99% of the time this is enough but we better support non unicode
+ * chars since blender doesnt limit this.
+ */
+ return result;
+ }
+ else {
+ PyErr_Clear();
+ if (PyBytes_Check(py_str)) {
+ return PyBytes_AS_STRING(py_str);
+ }
+ else if ((*coerce = PyUnicode_EncodeFSDefault(py_str))) {
+ return PyBytes_AS_STRING(*coerce);
+ }
+ else {
+ /* Clear the error, so Cycles can be at leadt used without
+ * GPU and OSL support,
+ */
+ PyErr_Clear();
+ return "";
+ }
+ }
}
static PyObject *init_func(PyObject * /*self*/, PyObject *args)
{
- PyObject *path, *user_path;
- int headless;
+ PyObject *path, *user_path;
+ int headless;
- if(!PyArg_ParseTuple(args, "OOi", &path, &user_path, &headless)) {
- return NULL;
- }
+ if (!PyArg_ParseTuple(args, "OOi", &path, &user_path, &headless)) {
+ return NULL;
+ }
- PyObject *path_coerce = NULL, *user_path_coerce = NULL;
- path_init(PyC_UnicodeAsByte(path, &path_coerce),
- PyC_UnicodeAsByte(user_path, &user_path_coerce));
- Py_XDECREF(path_coerce);
- Py_XDECREF(user_path_coerce);
+ PyObject *path_coerce = NULL, *user_path_coerce = NULL;
+ path_init(PyC_UnicodeAsByte(path, &path_coerce),
+ PyC_UnicodeAsByte(user_path, &user_path_coerce));
+ Py_XDECREF(path_coerce);
+ Py_XDECREF(user_path_coerce);
- BlenderSession::headless = headless;
+ BlenderSession::headless = headless;
- VLOG(2) << "Debug flags initialized to:\n"
- << DebugFlags();
+ VLOG(2) << "Debug flags initialized to:\n" << DebugFlags();
- Py_RETURN_NONE;
+ Py_RETURN_NONE;
}
-
static PyObject *exit_func(PyObject * /*self*/, PyObject * /*args*/)
{
- ShaderManager::free_memory();
- TaskScheduler::free_memory();
- Device::free_memory();
- Py_RETURN_NONE;
+ ShaderManager::free_memory();
+ TaskScheduler::free_memory();
+ Device::free_memory();
+ Py_RETURN_NONE;
}
static PyObject *create_func(PyObject * /*self*/, PyObject *args)
{
- PyObject *pyengine, *pypreferences, *pydata, *pyregion, *pyv3d, *pyrv3d;
- int preview_osl;
-
- if(!PyArg_ParseTuple(args, "OOOOOOi", &pyengine, &pypreferences, &pydata,
- &pyregion, &pyv3d, &pyrv3d, &preview_osl))
- {
- return NULL;
- }
-
- /* RNA */
- PointerRNA engineptr;
- RNA_pointer_create(NULL, &RNA_RenderEngine, (void*)PyLong_AsVoidPtr(pyengine), &engineptr);
- BL::RenderEngine engine(engineptr);
-
- PointerRNA preferencesptr;
- RNA_pointer_create(NULL, &RNA_Preferences, (void*)PyLong_AsVoidPtr(pypreferences), &preferencesptr);
- BL::Preferences preferences(preferencesptr);
-
- PointerRNA dataptr;
- RNA_main_pointer_create((Main*)PyLong_AsVoidPtr(pydata), &dataptr);
- BL::BlendData data(dataptr);
-
- PointerRNA regionptr;
- RNA_pointer_create(NULL, &RNA_Region, pylong_as_voidptr_typesafe(pyregion), &regionptr);
- BL::Region region(regionptr);
-
- PointerRNA v3dptr;
- RNA_pointer_create(NULL, &RNA_SpaceView3D, pylong_as_voidptr_typesafe(pyv3d), &v3dptr);
- BL::SpaceView3D v3d(v3dptr);
-
- PointerRNA rv3dptr;
- RNA_pointer_create(NULL, &RNA_RegionView3D, pylong_as_voidptr_typesafe(pyrv3d), &rv3dptr);
- BL::RegionView3D rv3d(rv3dptr);
-
- /* create session */
- BlenderSession *session;
-
- if(rv3d) {
- /* interactive viewport session */
- int width = region.width();
- int height = region.height();
-
- session = new BlenderSession(engine, preferences, data, v3d, rv3d, width, height);
- }
- else {
- /* offline session or preview render */
- session = new BlenderSession(engine, preferences, data, preview_osl);
- }
-
- return PyLong_FromVoidPtr(session);
+ PyObject *pyengine, *pypreferences, *pydata, *pyregion, *pyv3d, *pyrv3d;
+ int preview_osl;
+
+ if (!PyArg_ParseTuple(args,
+ "OOOOOOi",
+ &pyengine,
+ &pypreferences,
+ &pydata,
+ &pyregion,
+ &pyv3d,
+ &pyrv3d,
+ &preview_osl)) {
+ return NULL;
+ }
+
+ /* RNA */
+ PointerRNA engineptr;
+ RNA_pointer_create(NULL, &RNA_RenderEngine, (void *)PyLong_AsVoidPtr(pyengine), &engineptr);
+ BL::RenderEngine engine(engineptr);
+
+ PointerRNA preferencesptr;
+ RNA_pointer_create(
+ NULL, &RNA_Preferences, (void *)PyLong_AsVoidPtr(pypreferences), &preferencesptr);
+ BL::Preferences preferences(preferencesptr);
+
+ PointerRNA dataptr;
+ RNA_main_pointer_create((Main *)PyLong_AsVoidPtr(pydata), &dataptr);
+ BL::BlendData data(dataptr);
+
+ PointerRNA regionptr;
+ RNA_pointer_create(NULL, &RNA_Region, pylong_as_voidptr_typesafe(pyregion), &regionptr);
+ BL::Region region(regionptr);
+
+ PointerRNA v3dptr;
+ RNA_pointer_create(NULL, &RNA_SpaceView3D, pylong_as_voidptr_typesafe(pyv3d), &v3dptr);
+ BL::SpaceView3D v3d(v3dptr);
+
+ PointerRNA rv3dptr;
+ RNA_pointer_create(NULL, &RNA_RegionView3D, pylong_as_voidptr_typesafe(pyrv3d), &rv3dptr);
+ BL::RegionView3D rv3d(rv3dptr);
+
+ /* create session */
+ BlenderSession *session;
+
+ if (rv3d) {
+ /* interactive viewport session */
+ int width = region.width();
+ int height = region.height();
+
+ session = new BlenderSession(engine, preferences, data, v3d, rv3d, width, height);
+ }
+ else {
+ /* offline session or preview render */
+ session = new BlenderSession(engine, preferences, data, preview_osl);
+ }
+
+ return PyLong_FromVoidPtr(session);
}
static PyObject *free_func(PyObject * /*self*/, PyObject *value)
{
- delete (BlenderSession*)PyLong_AsVoidPtr(value);
+ delete (BlenderSession *)PyLong_AsVoidPtr(value);
- Py_RETURN_NONE;
+ Py_RETURN_NONE;
}
static PyObject *render_func(PyObject * /*self*/, PyObject *args)
{
- PyObject *pysession, *pydepsgraph;
+ PyObject *pysession, *pydepsgraph;
- if(!PyArg_ParseTuple(args, "OO", &pysession, &pydepsgraph))
- return NULL;
+ if (!PyArg_ParseTuple(args, "OO", &pysession, &pydepsgraph))
+ return NULL;
- BlenderSession *session = (BlenderSession*)PyLong_AsVoidPtr(pysession);
+ BlenderSession *session = (BlenderSession *)PyLong_AsVoidPtr(pysession);
- PointerRNA depsgraphptr;
- RNA_pointer_create(NULL, &RNA_Depsgraph, (ID*)PyLong_AsVoidPtr(pydepsgraph), &depsgraphptr);
- BL::Depsgraph b_depsgraph(depsgraphptr);
+ PointerRNA depsgraphptr;
+ RNA_pointer_create(NULL, &RNA_Depsgraph, (ID *)PyLong_AsVoidPtr(pydepsgraph), &depsgraphptr);
+ BL::Depsgraph b_depsgraph(depsgraphptr);
- python_thread_state_save(&session->python_thread_state);
+ python_thread_state_save(&session->python_thread_state);
- session->render(b_depsgraph);
+ session->render(b_depsgraph);
- python_thread_state_restore(&session->python_thread_state);
+ python_thread_state_restore(&session->python_thread_state);
- Py_RETURN_NONE;
+ Py_RETURN_NONE;
}
/* pixel_array and result passed as pointers */
static PyObject *bake_func(PyObject * /*self*/, PyObject *args)
{
- PyObject *pysession, *pydepsgraph, *pyobject;
- PyObject *pypixel_array, *pyresult;
- const char *pass_type;
- int num_pixels, depth, object_id, pass_filter;
-
- if(!PyArg_ParseTuple(args, "OOOsiiOiiO", &pysession, &pydepsgraph, &pyobject, &pass_type, &pass_filter, &object_id, &pypixel_array, &num_pixels, &depth, &pyresult))
- return NULL;
-
- BlenderSession *session = (BlenderSession*)PyLong_AsVoidPtr(pysession);
-
- PointerRNA depsgraphptr;
- RNA_pointer_create(NULL, &RNA_Depsgraph, PyLong_AsVoidPtr(pydepsgraph), &depsgraphptr);
- BL::Depsgraph b_depsgraph(depsgraphptr);
-
- PointerRNA objectptr;
- RNA_id_pointer_create((ID*)PyLong_AsVoidPtr(pyobject), &objectptr);
- BL::Object b_object(objectptr);
-
- void *b_result = PyLong_AsVoidPtr(pyresult);
-
- PointerRNA bakepixelptr;
- RNA_pointer_create(NULL, &RNA_BakePixel, PyLong_AsVoidPtr(pypixel_array), &bakepixelptr);
- BL::BakePixel b_bake_pixel(bakepixelptr);
-
- python_thread_state_save(&session->python_thread_state);
-
- session->bake(b_depsgraph, b_object, pass_type, pass_filter, object_id, b_bake_pixel, (size_t)num_pixels, depth, (float *)b_result);
-
- python_thread_state_restore(&session->python_thread_state);
-
- Py_RETURN_NONE;
+ PyObject *pysession, *pydepsgraph, *pyobject;
+ PyObject *pypixel_array, *pyresult;
+ const char *pass_type;
+ int num_pixels, depth, object_id, pass_filter;
+
+ if (!PyArg_ParseTuple(args,
+ "OOOsiiOiiO",
+ &pysession,
+ &pydepsgraph,
+ &pyobject,
+ &pass_type,
+ &pass_filter,
+ &object_id,
+ &pypixel_array,
+ &num_pixels,
+ &depth,
+ &pyresult))
+ return NULL;
+
+ BlenderSession *session = (BlenderSession *)PyLong_AsVoidPtr(pysession);
+
+ PointerRNA depsgraphptr;
+ RNA_pointer_create(NULL, &RNA_Depsgraph, PyLong_AsVoidPtr(pydepsgraph), &depsgraphptr);
+ BL::Depsgraph b_depsgraph(depsgraphptr);
+
+ PointerRNA objectptr;
+ RNA_id_pointer_create((ID *)PyLong_AsVoidPtr(pyobject), &objectptr);
+ BL::Object b_object(objectptr);
+
+ void *b_result = PyLong_AsVoidPtr(pyresult);
+
+ PointerRNA bakepixelptr;
+ RNA_pointer_create(NULL, &RNA_BakePixel, PyLong_AsVoidPtr(pypixel_array), &bakepixelptr);
+ BL::BakePixel b_bake_pixel(bakepixelptr);
+
+ python_thread_state_save(&session->python_thread_state);
+
+ session->bake(b_depsgraph,
+ b_object,
+ pass_type,
+ pass_filter,
+ object_id,
+ b_bake_pixel,
+ (size_t)num_pixels,
+ depth,
+ (float *)b_result);
+
+ python_thread_state_restore(&session->python_thread_state);
+
+ Py_RETURN_NONE;
}
static PyObject *draw_func(PyObject * /*self*/, PyObject *args)
{
- PyObject *pysession, *pygraph, *pyv3d, *pyrv3d;
+ PyObject *pysession, *pygraph, *pyv3d, *pyrv3d;
- if(!PyArg_ParseTuple(args, "OOOO", &pysession, &pygraph, &pyv3d, &pyrv3d))
- return NULL;
+ if (!PyArg_ParseTuple(args, "OOOO", &pysession, &pygraph, &pyv3d, &pyrv3d))
+ return NULL;
- BlenderSession *session = (BlenderSession*)PyLong_AsVoidPtr(pysession);
+ BlenderSession *session = (BlenderSession *)PyLong_AsVoidPtr(pysession);
- if(PyLong_AsVoidPtr(pyrv3d)) {
- /* 3d view drawing */
- int viewport[4];
- glGetIntegerv(GL_VIEWPORT, viewport);
+ if (PyLong_AsVoidPtr(pyrv3d)) {
+ /* 3d view drawing */
+ int viewport[4];
+ glGetIntegerv(GL_VIEWPORT, viewport);
- session->draw(viewport[2], viewport[3]);
- }
+ session->draw(viewport[2], viewport[3]);
+ }
- Py_RETURN_NONE;
+ Py_RETURN_NONE;
}
static PyObject *reset_func(PyObject * /*self*/, PyObject *args)
{
- PyObject *pysession, *pydata, *pydepsgraph;
+ PyObject *pysession, *pydata, *pydepsgraph;
- if(!PyArg_ParseTuple(args, "OOO", &pysession, &pydata, &pydepsgraph))
- return NULL;
+ if (!PyArg_ParseTuple(args, "OOO", &pysession, &pydata, &pydepsgraph))
+ return NULL;
- BlenderSession *session = (BlenderSession*)PyLong_AsVoidPtr(pysession);
+ BlenderSession *session = (BlenderSession *)PyLong_AsVoidPtr(pysession);
- PointerRNA dataptr;
- RNA_main_pointer_create((Main*)PyLong_AsVoidPtr(pydata), &dataptr);
- BL::BlendData b_data(dataptr);
+ PointerRNA dataptr;
+ RNA_main_pointer_create((Main *)PyLong_AsVoidPtr(pydata), &dataptr);
+ BL::BlendData b_data(dataptr);
- PointerRNA depsgraphptr;
- RNA_pointer_create(NULL, &RNA_Depsgraph, PyLong_AsVoidPtr(pydepsgraph), &depsgraphptr);
- BL::Depsgraph b_depsgraph(depsgraphptr);
+ PointerRNA depsgraphptr;
+ RNA_pointer_create(NULL, &RNA_Depsgraph, PyLong_AsVoidPtr(pydepsgraph), &depsgraphptr);
+ BL::Depsgraph b_depsgraph(depsgraphptr);
- python_thread_state_save(&session->python_thread_state);
+ python_thread_state_save(&session->python_thread_state);
- session->reset_session(b_data, b_depsgraph);
+ session->reset_session(b_data, b_depsgraph);
- python_thread_state_restore(&session->python_thread_state);
+ python_thread_state_restore(&session->python_thread_state);
- Py_RETURN_NONE;
+ Py_RETURN_NONE;
}
static PyObject *sync_func(PyObject * /*self*/, PyObject *args)
{
- PyObject *pysession, *pydepsgraph;
+ PyObject *pysession, *pydepsgraph;
- if(!PyArg_ParseTuple(args, "OO", &pysession, &pydepsgraph))
- return NULL;
+ if (!PyArg_ParseTuple(args, "OO", &pysession, &pydepsgraph))
+ return NULL;
- BlenderSession *session = (BlenderSession*)PyLong_AsVoidPtr(pysession);
+ BlenderSession *session = (BlenderSession *)PyLong_AsVoidPtr(pysession);
- PointerRNA depsgraphptr;
- RNA_pointer_create(NULL, &RNA_Depsgraph, PyLong_AsVoidPtr(pydepsgraph), &depsgraphptr);
- BL::Depsgraph b_depsgraph(depsgraphptr);
+ PointerRNA depsgraphptr;
+ RNA_pointer_create(NULL, &RNA_Depsgraph, PyLong_AsVoidPtr(pydepsgraph), &depsgraphptr);
+ BL::Depsgraph b_depsgraph(depsgraphptr);
- python_thread_state_save(&session->python_thread_state);
+ python_thread_state_save(&session->python_thread_state);
- session->synchronize(b_depsgraph);
+ session->synchronize(b_depsgraph);
- python_thread_state_restore(&session->python_thread_state);
+ python_thread_state_restore(&session->python_thread_state);
- Py_RETURN_NONE;
+ Py_RETURN_NONE;
}
-static PyObject *available_devices_func(PyObject * /*self*/, PyObject * args)
+static PyObject *available_devices_func(PyObject * /*self*/, PyObject *args)
{
- const char *type_name;
- if(!PyArg_ParseTuple(args, "s", &type_name)) {
- return NULL;
- }
-
- DeviceType type = Device::type_from_string(type_name);
- uint mask = (type == DEVICE_NONE) ? DEVICE_MASK_ALL : DEVICE_MASK(type);
- mask |= DEVICE_MASK_CPU;
-
- vector<DeviceInfo> devices = Device::available_devices(mask);
- PyObject *ret = PyTuple_New(devices.size());
-
- for(size_t i = 0; i < devices.size(); i++) {
- DeviceInfo& device = devices[i];
- string type_name = Device::string_from_type(device.type);
- PyObject *device_tuple = PyTuple_New(3);
- PyTuple_SET_ITEM(device_tuple, 0, PyUnicode_FromString(device.description.c_str()));
- PyTuple_SET_ITEM(device_tuple, 1, PyUnicode_FromString(type_name.c_str()));
- PyTuple_SET_ITEM(device_tuple, 2, PyUnicode_FromString(device.id.c_str()));
- PyTuple_SET_ITEM(ret, i, device_tuple);
- }
-
- return ret;
+ const char *type_name;
+ if (!PyArg_ParseTuple(args, "s", &type_name)) {
+ return NULL;
+ }
+
+ DeviceType type = Device::type_from_string(type_name);
+ uint mask = (type == DEVICE_NONE) ? DEVICE_MASK_ALL : DEVICE_MASK(type);
+ mask |= DEVICE_MASK_CPU;
+
+ vector<DeviceInfo> devices = Device::available_devices(mask);
+ PyObject *ret = PyTuple_New(devices.size());
+
+ for (size_t i = 0; i < devices.size(); i++) {
+ DeviceInfo &device = devices[i];
+ string type_name = Device::string_from_type(device.type);
+ PyObject *device_tuple = PyTuple_New(3);
+ PyTuple_SET_ITEM(device_tuple, 0, PyUnicode_FromString(device.description.c_str()));
+ PyTuple_SET_ITEM(device_tuple, 1, PyUnicode_FromString(type_name.c_str()));
+ PyTuple_SET_ITEM(device_tuple, 2, PyUnicode_FromString(device.id.c_str()));
+ PyTuple_SET_ITEM(ret, i, device_tuple);
+ }
+
+ return ret;
}
#ifdef WITH_OSL
static PyObject *osl_update_node_func(PyObject * /*self*/, PyObject *args)
{
- PyObject *pydata, *pynodegroup, *pynode;
- const char *filepath = NULL;
-
- if(!PyArg_ParseTuple(args, "OOOs", &pydata, &pynodegroup, &pynode, &filepath))
- return NULL;
-
- /* RNA */
- PointerRNA dataptr;
- RNA_main_pointer_create((Main*)PyLong_AsVoidPtr(pydata), &dataptr);
- BL::BlendData b_data(dataptr);
-
- PointerRNA nodeptr;
- RNA_pointer_create((ID*)PyLong_AsVoidPtr(pynodegroup), &RNA_ShaderNodeScript, (void*)PyLong_AsVoidPtr(pynode), &nodeptr);
- BL::ShaderNodeScript b_node(nodeptr);
-
- /* update bytecode hash */
- string bytecode = b_node.bytecode();
-
- if(!bytecode.empty()) {
- MD5Hash md5;
- md5.append((const uint8_t*)bytecode.c_str(), bytecode.size());
- b_node.bytecode_hash(md5.get_hex().c_str());
- }
- else
- b_node.bytecode_hash("");
-
- /* query from file path */
- OSL::OSLQuery query;
-
- if(!OSLShaderManager::osl_query(query, filepath))
- Py_RETURN_FALSE;
-
- /* add new sockets from parameters */
- set<void*> used_sockets;
-
- for(int i = 0; i < query.nparams(); i++) {
- const OSL::OSLQuery::Parameter *param = query.getparam(i);
-
- /* skip unsupported types */
- if(param->varlenarray || param->isstruct || param->type.arraylen > 1)
- continue;
-
- /* determine socket type */
- string socket_type;
- BL::NodeSocket::type_enum data_type = BL::NodeSocket::type_VALUE;
- float4 default_float4 = make_float4(0.0f, 0.0f, 0.0f, 1.0f);
- float default_float = 0.0f;
- int default_int = 0;
- string default_string = "";
-
- if(param->isclosure) {
- socket_type = "NodeSocketShader";
- data_type = BL::NodeSocket::type_SHADER;
- }
- else if(param->type.vecsemantics == TypeDesc::COLOR) {
- socket_type = "NodeSocketColor";
- data_type = BL::NodeSocket::type_RGBA;
-
- if(param->validdefault) {
- default_float4[0] = param->fdefault[0];
- default_float4[1] = param->fdefault[1];
- default_float4[2] = param->fdefault[2];
- }
- }
- else if(param->type.vecsemantics == TypeDesc::POINT ||
- param->type.vecsemantics == TypeDesc::VECTOR ||
- param->type.vecsemantics == TypeDesc::NORMAL)
- {
- socket_type = "NodeSocketVector";
- data_type = BL::NodeSocket::type_VECTOR;
-
- if(param->validdefault) {
- default_float4[0] = param->fdefault[0];
- default_float4[1] = param->fdefault[1];
- default_float4[2] = param->fdefault[2];
- }
- }
- else if(param->type.aggregate == TypeDesc::SCALAR) {
- if(param->type.basetype == TypeDesc::INT) {
- socket_type = "NodeSocketInt";
- data_type = BL::NodeSocket::type_INT;
- if(param->validdefault)
- default_int = param->idefault[0];
- }
- else if(param->type.basetype == TypeDesc::FLOAT) {
- socket_type = "NodeSocketFloat";
- data_type = BL::NodeSocket::type_VALUE;
- if(param->validdefault)
- default_float = param->fdefault[0];
- }
- else if(param->type.basetype == TypeDesc::STRING) {
- socket_type = "NodeSocketString";
- data_type = BL::NodeSocket::type_STRING;
- if(param->validdefault)
- default_string = param->sdefault[0].string();
- }
- else
- continue;
- }
- else
- continue;
-
- /* find socket socket */
- BL::NodeSocket b_sock(PointerRNA_NULL);
- if(param->isoutput) {
- b_sock = b_node.outputs[param->name.string()];
- /* remove if type no longer matches */
- if(b_sock && b_sock.bl_idname() != socket_type) {
- b_node.outputs.remove(b_data, b_sock);
- b_sock = BL::NodeSocket(PointerRNA_NULL);
- }
- }
- else {
- b_sock = b_node.inputs[param->name.string()];
- /* remove if type no longer matches */
- if(b_sock && b_sock.bl_idname() != socket_type) {
- b_node.inputs.remove(b_data, b_sock);
- b_sock = BL::NodeSocket(PointerRNA_NULL);
- }
- }
-
- if(!b_sock) {
- /* create new socket */
- if(param->isoutput)
- b_sock = b_node.outputs.create(b_data, socket_type.c_str(), param->name.c_str(), param->name.c_str());
- else
- b_sock = b_node.inputs.create(b_data, socket_type.c_str(), param->name.c_str(), param->name.c_str());
-
- /* set default value */
- if(data_type == BL::NodeSocket::type_VALUE) {
- set_float(b_sock.ptr, "default_value", default_float);
- }
- else if(data_type == BL::NodeSocket::type_INT) {
- set_int(b_sock.ptr, "default_value", default_int);
- }
- else if(data_type == BL::NodeSocket::type_RGBA) {
- set_float4(b_sock.ptr, "default_value", default_float4);
- }
- else if(data_type == BL::NodeSocket::type_VECTOR) {
- set_float3(b_sock.ptr, "default_value", float4_to_float3(default_float4));
- }
- else if(data_type == BL::NodeSocket::type_STRING) {
- set_string(b_sock.ptr, "default_value", default_string);
- }
- }
-
- used_sockets.insert(b_sock.ptr.data);
- }
-
- /* remove unused parameters */
- bool removed;
-
- do {
- BL::Node::inputs_iterator b_input;
- BL::Node::outputs_iterator b_output;
-
- removed = false;
-
- for(b_node.inputs.begin(b_input); b_input != b_node.inputs.end(); ++b_input) {
- if(used_sockets.find(b_input->ptr.data) == used_sockets.end()) {
- b_node.inputs.remove(b_data, *b_input);
- removed = true;
- break;
- }
- }
-
- for(b_node.outputs.begin(b_output); b_output != b_node.outputs.end(); ++b_output) {
- if(used_sockets.find(b_output->ptr.data) == used_sockets.end()) {
- b_node.outputs.remove(b_data, *b_output);
- removed = true;
- break;
- }
- }
- } while(removed);
-
- Py_RETURN_TRUE;
+ PyObject *pydata, *pynodegroup, *pynode;
+ const char *filepath = NULL;
+
+ if (!PyArg_ParseTuple(args, "OOOs", &pydata, &pynodegroup, &pynode, &filepath))
+ return NULL;
+
+ /* RNA */
+ PointerRNA dataptr;
+ RNA_main_pointer_create((Main *)PyLong_AsVoidPtr(pydata), &dataptr);
+ BL::BlendData b_data(dataptr);
+
+ PointerRNA nodeptr;
+ RNA_pointer_create((ID *)PyLong_AsVoidPtr(pynodegroup),
+ &RNA_ShaderNodeScript,
+ (void *)PyLong_AsVoidPtr(pynode),
+ &nodeptr);
+ BL::ShaderNodeScript b_node(nodeptr);
+
+ /* update bytecode hash */
+ string bytecode = b_node.bytecode();
+
+ if (!bytecode.empty()) {
+ MD5Hash md5;
+ md5.append((const uint8_t *)bytecode.c_str(), bytecode.size());
+ b_node.bytecode_hash(md5.get_hex().c_str());
+ }
+ else
+ b_node.bytecode_hash("");
+
+ /* query from file path */
+ OSL::OSLQuery query;
+
+ if (!OSLShaderManager::osl_query(query, filepath))
+ Py_RETURN_FALSE;
+
+ /* add new sockets from parameters */
+ set<void *> used_sockets;
+
+ for (int i = 0; i < query.nparams(); i++) {
+ const OSL::OSLQuery::Parameter *param = query.getparam(i);
+
+ /* skip unsupported types */
+ if (param->varlenarray || param->isstruct || param->type.arraylen > 1)
+ continue;
+
+ /* determine socket type */
+ string socket_type;
+ BL::NodeSocket::type_enum data_type = BL::NodeSocket::type_VALUE;
+ float4 default_float4 = make_float4(0.0f, 0.0f, 0.0f, 1.0f);
+ float default_float = 0.0f;
+ int default_int = 0;
+ string default_string = "";
+
+ if (param->isclosure) {
+ socket_type = "NodeSocketShader";
+ data_type = BL::NodeSocket::type_SHADER;
+ }
+ else if (param->type.vecsemantics == TypeDesc::COLOR) {
+ socket_type = "NodeSocketColor";
+ data_type = BL::NodeSocket::type_RGBA;
+
+ if (param->validdefault) {
+ default_float4[0] = param->fdefault[0];
+ default_float4[1] = param->fdefault[1];
+ default_float4[2] = param->fdefault[2];
+ }
+ }
+ else if (param->type.vecsemantics == TypeDesc::POINT ||
+ param->type.vecsemantics == TypeDesc::VECTOR ||
+ param->type.vecsemantics == TypeDesc::NORMAL) {
+ socket_type = "NodeSocketVector";
+ data_type = BL::NodeSocket::type_VECTOR;
+
+ if (param->validdefault) {
+ default_float4[0] = param->fdefault[0];
+ default_float4[1] = param->fdefault[1];
+ default_float4[2] = param->fdefault[2];
+ }
+ }
+ else if (param->type.aggregate == TypeDesc::SCALAR) {
+ if (param->type.basetype == TypeDesc::INT) {
+ socket_type = "NodeSocketInt";
+ data_type = BL::NodeSocket::type_INT;
+ if (param->validdefault)
+ default_int = param->idefault[0];
+ }
+ else if (param->type.basetype == TypeDesc::FLOAT) {
+ socket_type = "NodeSocketFloat";
+ data_type = BL::NodeSocket::type_VALUE;
+ if (param->validdefault)
+ default_float = param->fdefault[0];
+ }
+ else if (param->type.basetype == TypeDesc::STRING) {
+ socket_type = "NodeSocketString";
+ data_type = BL::NodeSocket::type_STRING;
+ if (param->validdefault)
+ default_string = param->sdefault[0].string();
+ }
+ else
+ continue;
+ }
+ else
+ continue;
+
+ /* find socket socket */
+ BL::NodeSocket b_sock(PointerRNA_NULL);
+ if (param->isoutput) {
+ b_sock = b_node.outputs[param->name.string()];
+ /* remove if type no longer matches */
+ if (b_sock && b_sock.bl_idname() != socket_type) {
+ b_node.outputs.remove(b_data, b_sock);
+ b_sock = BL::NodeSocket(PointerRNA_NULL);
+ }
+ }
+ else {
+ b_sock = b_node.inputs[param->name.string()];
+ /* remove if type no longer matches */
+ if (b_sock && b_sock.bl_idname() != socket_type) {
+ b_node.inputs.remove(b_data, b_sock);
+ b_sock = BL::NodeSocket(PointerRNA_NULL);
+ }
+ }
+
+ if (!b_sock) {
+ /* create new socket */
+ if (param->isoutput)
+ b_sock = b_node.outputs.create(
+ b_data, socket_type.c_str(), param->name.c_str(), param->name.c_str());
+ else
+ b_sock = b_node.inputs.create(
+ b_data, socket_type.c_str(), param->name.c_str(), param->name.c_str());
+
+ /* set default value */
+ if (data_type == BL::NodeSocket::type_VALUE) {
+ set_float(b_sock.ptr, "default_value", default_float);
+ }
+ else if (data_type == BL::NodeSocket::type_INT) {
+ set_int(b_sock.ptr, "default_value", default_int);
+ }
+ else if (data_type == BL::NodeSocket::type_RGBA) {
+ set_float4(b_sock.ptr, "default_value", default_float4);
+ }
+ else if (data_type == BL::NodeSocket::type_VECTOR) {
+ set_float3(b_sock.ptr, "default_value", float4_to_float3(default_float4));
+ }
+ else if (data_type == BL::NodeSocket::type_STRING) {
+ set_string(b_sock.ptr, "default_value", default_string);
+ }
+ }
+
+ used_sockets.insert(b_sock.ptr.data);
+ }
+
+ /* remove unused parameters */
+ bool removed;
+
+ do {
+ BL::Node::inputs_iterator b_input;
+ BL::Node::outputs_iterator b_output;
+
+ removed = false;
+
+ for (b_node.inputs.begin(b_input); b_input != b_node.inputs.end(); ++b_input) {
+ if (used_sockets.find(b_input->ptr.data) == used_sockets.end()) {
+ b_node.inputs.remove(b_data, *b_input);
+ removed = true;
+ break;
+ }
+ }
+
+ for (b_node.outputs.begin(b_output); b_output != b_node.outputs.end(); ++b_output) {
+ if (used_sockets.find(b_output->ptr.data) == used_sockets.end()) {
+ b_node.outputs.remove(b_data, *b_output);
+ removed = true;
+ break;
+ }
+ }
+ } while (removed);
+
+ Py_RETURN_TRUE;
}
static PyObject *osl_compile_func(PyObject * /*self*/, PyObject *args)
{
- const char *inputfile = NULL, *outputfile = NULL;
+ const char *inputfile = NULL, *outputfile = NULL;
- if(!PyArg_ParseTuple(args, "ss", &inputfile, &outputfile))
- return NULL;
+ if (!PyArg_ParseTuple(args, "ss", &inputfile, &outputfile))
+ return NULL;
- /* return */
- if(!OSLShaderManager::osl_compile(inputfile, outputfile))
- Py_RETURN_FALSE;
+ /* return */
+ if (!OSLShaderManager::osl_compile(inputfile, outputfile))
+ Py_RETURN_FALSE;
- Py_RETURN_TRUE;
+ Py_RETURN_TRUE;
}
#endif
static PyObject *system_info_func(PyObject * /*self*/, PyObject * /*value*/)
{
- string system_info = Device::device_capabilities();
- return PyUnicode_FromString(system_info.c_str());
+ string system_info = Device::device_capabilities();
+ return PyUnicode_FromString(system_info.c_str());
}
#ifdef WITH_OPENCL
static PyObject *opencl_disable_func(PyObject * /*self*/, PyObject * /*value*/)
{
- VLOG(2) << "Disabling OpenCL platform.";
- DebugFlags().opencl.device_type = DebugFlags::OpenCL::DEVICE_NONE;
- Py_RETURN_NONE;
+ VLOG(2) << "Disabling OpenCL platform.";
+ DebugFlags().opencl.device_type = DebugFlags::OpenCL::DEVICE_NONE;
+ Py_RETURN_NONE;
}
static PyObject *opencl_compile_func(PyObject * /*self*/, PyObject *args)
{
- PyObject *sequence = PySequence_Fast(args, "Arguments must be a sequence");
- if(sequence == NULL) {
- Py_RETURN_FALSE;
- }
-
- vector<string> parameters;
- for(Py_ssize_t i = 0; i < PySequence_Fast_GET_SIZE(sequence); i++) {
- PyObject *item = PySequence_Fast_GET_ITEM(sequence, i);
- PyObject *item_as_string = PyObject_Str(item);
- const char *parameter_string = PyUnicode_AsUTF8(item_as_string);
- parameters.push_back(parameter_string);
- Py_DECREF(item_as_string);
- }
- Py_DECREF(sequence);
-
- if (device_opencl_compile_kernel(parameters)) {
- Py_RETURN_TRUE;
- }
- else {
- Py_RETURN_FALSE;
- }
+ PyObject *sequence = PySequence_Fast(args, "Arguments must be a sequence");
+ if (sequence == NULL) {
+ Py_RETURN_FALSE;
+ }
+
+ vector<string> parameters;
+ for (Py_ssize_t i = 0; i < PySequence_Fast_GET_SIZE(sequence); i++) {
+ PyObject *item = PySequence_Fast_GET_ITEM(sequence, i);
+ PyObject *item_as_string = PyObject_Str(item);
+ const char *parameter_string = PyUnicode_AsUTF8(item_as_string);
+ parameters.push_back(parameter_string);
+ Py_DECREF(item_as_string);
+ }
+ Py_DECREF(sequence);
+
+ if (device_opencl_compile_kernel(parameters)) {
+ Py_RETURN_TRUE;
+ }
+ else {
+ Py_RETURN_FALSE;
+ }
}
#endif
-static bool image_parse_filepaths(PyObject *pyfilepaths, vector<string>& filepaths)
+static bool image_parse_filepaths(PyObject *pyfilepaths, vector<string> &filepaths)
{
- if(PyUnicode_Check(pyfilepaths)) {
- const char *filepath = PyUnicode_AsUTF8(pyfilepaths);
- filepaths.push_back(filepath);
- return true;
- }
-
- PyObject *sequence = PySequence_Fast(pyfilepaths, "File paths must be a string or sequence of strings");
- if(sequence == NULL) {
- return false;
- }
-
- for(Py_ssize_t i = 0; i < PySequence_Fast_GET_SIZE(sequence); i++) {
- PyObject *item = PySequence_Fast_GET_ITEM(sequence, i);
- const char *filepath = PyUnicode_AsUTF8(item);
- if(filepath == NULL) {
- PyErr_SetString(PyExc_ValueError, "File paths must be a string or sequence of strings.");
- Py_DECREF(sequence);
- return false;
- }
- filepaths.push_back(filepath);
- }
- Py_DECREF(sequence);
-
- return true;
+ if (PyUnicode_Check(pyfilepaths)) {
+ const char *filepath = PyUnicode_AsUTF8(pyfilepaths);
+ filepaths.push_back(filepath);
+ return true;
+ }
+
+ PyObject *sequence = PySequence_Fast(pyfilepaths,
+ "File paths must be a string or sequence of strings");
+ if (sequence == NULL) {
+ return false;
+ }
+
+ for (Py_ssize_t i = 0; i < PySequence_Fast_GET_SIZE(sequence); i++) {
+ PyObject *item = PySequence_Fast_GET_ITEM(sequence, i);
+ const char *filepath = PyUnicode_AsUTF8(item);
+ if (filepath == NULL) {
+ PyErr_SetString(PyExc_ValueError, "File paths must be a string or sequence of strings.");
+ Py_DECREF(sequence);
+ return false;
+ }
+ filepaths.push_back(filepath);
+ }
+ Py_DECREF(sequence);
+
+ return true;
}
static PyObject *denoise_func(PyObject * /*self*/, PyObject *args, PyObject *keywords)
{
- static const char *keyword_list[] = {"preferences", "scene", "view_layer",
- "input", "output",
- "tile_size", "samples", NULL};
- PyObject *pypreferences, *pyscene, *pyviewlayer;
- PyObject *pyinput, *pyoutput = NULL;
- int tile_size = 0, samples = 0;
-
- if (!PyArg_ParseTupleAndKeywords(args, keywords, "OOOO|Oii", (char**)keyword_list,
- &pypreferences, &pyscene, &pyviewlayer,
- &pyinput, &pyoutput,
- &tile_size, &samples)) {
- return NULL;
- }
-
- /* Get device specification from preferences and scene. */
- PointerRNA preferencesptr;
- RNA_pointer_create(NULL, &RNA_Preferences, (void*)PyLong_AsVoidPtr(pypreferences), &preferencesptr);
- BL::Preferences b_preferences(preferencesptr);
-
- PointerRNA sceneptr;
- RNA_id_pointer_create((ID*)PyLong_AsVoidPtr(pyscene), &sceneptr);
- BL::Scene b_scene(sceneptr);
-
- DeviceInfo device = blender_device_info(b_preferences, b_scene, true);
-
- /* Get denoising parameters from view layer. */
- PointerRNA viewlayerptr;
- RNA_pointer_create((ID*)PyLong_AsVoidPtr(pyscene), &RNA_ViewLayer, PyLong_AsVoidPtr(pyviewlayer), &viewlayerptr);
- PointerRNA cviewlayer = RNA_pointer_get(&viewlayerptr, "cycles");
-
- DenoiseParams params;
- params.radius = get_int(cviewlayer, "denoising_radius");
- params.strength = get_float(cviewlayer, "denoising_strength");
- params.feature_strength = get_float(cviewlayer, "denoising_feature_strength");
- params.relative_pca = get_boolean(cviewlayer, "denoising_relative_pca");
- params.neighbor_frames = get_int(cviewlayer, "denoising_neighbor_frames");
-
- /* Parse file paths list. */
- vector<string> input, output;
-
- if(!image_parse_filepaths(pyinput, input)) {
- return NULL;
- }
-
- if(pyoutput) {
- if(!image_parse_filepaths(pyoutput, output)) {
- return NULL;
- }
- }
- else {
- output = input;
- }
-
- if(input.empty()) {
- PyErr_SetString(PyExc_ValueError, "No input file paths specified.");
- return NULL;
- }
- if(input.size() != output.size()) {
- PyErr_SetString(PyExc_ValueError, "Number of input and output file paths does not match.");
- return NULL;
- }
-
- /* Create denoiser. */
- Denoiser denoiser(device);
- denoiser.params = params;
- denoiser.input = input;
- denoiser.output = output;
-
- if (tile_size > 0) {
- denoiser.tile_size = make_int2(tile_size, tile_size);
- }
- if (samples > 0) {
- denoiser.samples_override = samples;
- }
-
- /* Run denoiser. */
- if(!denoiser.run()) {
- PyErr_SetString(PyExc_ValueError, denoiser.error.c_str());
- return NULL;
- }
-
- Py_RETURN_NONE;
+ static const char *keyword_list[] = {
+ "preferences", "scene", "view_layer", "input", "output", "tile_size", "samples", NULL};
+ PyObject *pypreferences, *pyscene, *pyviewlayer;
+ PyObject *pyinput, *pyoutput = NULL;
+ int tile_size = 0, samples = 0;
+
+ if (!PyArg_ParseTupleAndKeywords(args,
+ keywords,
+ "OOOO|Oii",
+ (char **)keyword_list,
+ &pypreferences,
+ &pyscene,
+ &pyviewlayer,
+ &pyinput,
+ &pyoutput,
+ &tile_size,
+ &samples)) {
+ return NULL;
+ }
+
+ /* Get device specification from preferences and scene. */
+ PointerRNA preferencesptr;
+ RNA_pointer_create(
+ NULL, &RNA_Preferences, (void *)PyLong_AsVoidPtr(pypreferences), &preferencesptr);
+ BL::Preferences b_preferences(preferencesptr);
+
+ PointerRNA sceneptr;
+ RNA_id_pointer_create((ID *)PyLong_AsVoidPtr(pyscene), &sceneptr);
+ BL::Scene b_scene(sceneptr);
+
+ DeviceInfo device = blender_device_info(b_preferences, b_scene, true);
+
+ /* Get denoising parameters from view layer. */
+ PointerRNA viewlayerptr;
+ RNA_pointer_create((ID *)PyLong_AsVoidPtr(pyscene),
+ &RNA_ViewLayer,
+ PyLong_AsVoidPtr(pyviewlayer),
+ &viewlayerptr);
+ PointerRNA cviewlayer = RNA_pointer_get(&viewlayerptr, "cycles");
+
+ DenoiseParams params;
+ params.radius = get_int(cviewlayer, "denoising_radius");
+ params.strength = get_float(cviewlayer, "denoising_strength");
+ params.feature_strength = get_float(cviewlayer, "denoising_feature_strength");
+ params.relative_pca = get_boolean(cviewlayer, "denoising_relative_pca");
+ params.neighbor_frames = get_int(cviewlayer, "denoising_neighbor_frames");
+
+ /* Parse file paths list. */
+ vector<string> input, output;
+
+ if (!image_parse_filepaths(pyinput, input)) {
+ return NULL;
+ }
+
+ if (pyoutput) {
+ if (!image_parse_filepaths(pyoutput, output)) {
+ return NULL;
+ }
+ }
+ else {
+ output = input;
+ }
+
+ if (input.empty()) {
+ PyErr_SetString(PyExc_ValueError, "No input file paths specified.");
+ return NULL;
+ }
+ if (input.size() != output.size()) {
+ PyErr_SetString(PyExc_ValueError, "Number of input and output file paths does not match.");
+ return NULL;
+ }
+
+ /* Create denoiser. */
+ Denoiser denoiser(device);
+ denoiser.params = params;
+ denoiser.input = input;
+ denoiser.output = output;
+
+ if (tile_size > 0) {
+ denoiser.tile_size = make_int2(tile_size, tile_size);
+ }
+ if (samples > 0) {
+ denoiser.samples_override = samples;
+ }
+
+ /* Run denoiser. */
+ if (!denoiser.run()) {
+ PyErr_SetString(PyExc_ValueError, denoiser.error.c_str());
+ return NULL;
+ }
+
+ Py_RETURN_NONE;
}
static PyObject *merge_func(PyObject * /*self*/, PyObject *args, PyObject *keywords)
{
- static const char *keyword_list[] = {"input", "output", NULL};
- PyObject *pyinput, *pyoutput = NULL;
-
- if (!PyArg_ParseTupleAndKeywords(args, keywords, "OO", (char**)keyword_list, &pyinput, &pyoutput)) {
- return NULL;
- }
-
- /* Parse input list. */
- vector<string> input;
- if(!image_parse_filepaths(pyinput, input)) {
- return NULL;
- }
-
- /* Parse output string. */
- if(!PyUnicode_Check(pyoutput)) {
- PyErr_SetString(PyExc_ValueError, "Output must be a string.");
- return NULL;
- }
- string output = PyUnicode_AsUTF8(pyoutput);
-
- /* Merge. */
- ImageMerger merger;
- merger.input = input;
- merger.output = output;
-
- if(!merger.run()) {
- PyErr_SetString(PyExc_ValueError, merger.error.c_str());
- return NULL;
- }
-
- Py_RETURN_NONE;
+ static const char *keyword_list[] = {"input", "output", NULL};
+ PyObject *pyinput, *pyoutput = NULL;
+
+ if (!PyArg_ParseTupleAndKeywords(
+ args, keywords, "OO", (char **)keyword_list, &pyinput, &pyoutput)) {
+ return NULL;
+ }
+
+ /* Parse input list. */
+ vector<string> input;
+ if (!image_parse_filepaths(pyinput, input)) {
+ return NULL;
+ }
+
+ /* Parse output string. */
+ if (!PyUnicode_Check(pyoutput)) {
+ PyErr_SetString(PyExc_ValueError, "Output must be a string.");
+ return NULL;
+ }
+ string output = PyUnicode_AsUTF8(pyoutput);
+
+ /* Merge. */
+ ImageMerger merger;
+ merger.input = input;
+ merger.output = output;
+
+ if (!merger.run()) {
+ PyErr_SetString(PyExc_ValueError, merger.error.c_str());
+ return NULL;
+ }
+
+ Py_RETURN_NONE;
}
-
static PyObject *debug_flags_update_func(PyObject * /*self*/, PyObject *args)
{
- PyObject *pyscene;
- if(!PyArg_ParseTuple(args, "O", &pyscene)) {
- return NULL;
- }
+ PyObject *pyscene;
+ if (!PyArg_ParseTuple(args, "O", &pyscene)) {
+ return NULL;
+ }
- PointerRNA sceneptr;
- RNA_id_pointer_create((ID*)PyLong_AsVoidPtr(pyscene), &sceneptr);
- BL::Scene b_scene(sceneptr);
+ PointerRNA sceneptr;
+ RNA_id_pointer_create((ID *)PyLong_AsVoidPtr(pyscene), &sceneptr);
+ BL::Scene b_scene(sceneptr);
- if(debug_flags_sync_from_scene(b_scene)) {
- VLOG(2) << "Tagging device list for update.";
- Device::tag_update();
- }
+ if (debug_flags_sync_from_scene(b_scene)) {
+ VLOG(2) << "Tagging device list for update.";
+ Device::tag_update();
+ }
- VLOG(2) << "Debug flags set to:\n"
- << DebugFlags();
+ VLOG(2) << "Debug flags set to:\n" << DebugFlags();
- debug_flags_set = true;
+ debug_flags_set = true;
- Py_RETURN_NONE;
+ Py_RETURN_NONE;
}
static PyObject *debug_flags_reset_func(PyObject * /*self*/, PyObject * /*args*/)
{
- if(debug_flags_reset()) {
- VLOG(2) << "Tagging device list for update.";
- Device::tag_update();
- }
- if(debug_flags_set) {
- VLOG(2) << "Debug flags reset to:\n"
- << DebugFlags();
- debug_flags_set = false;
- }
- Py_RETURN_NONE;
+ if (debug_flags_reset()) {
+ VLOG(2) << "Tagging device list for update.";
+ Device::tag_update();
+ }
+ if (debug_flags_set) {
+ VLOG(2) << "Debug flags reset to:\n" << DebugFlags();
+ debug_flags_set = false;
+ }
+ Py_RETURN_NONE;
}
static PyObject *set_resumable_chunk_func(PyObject * /*self*/, PyObject *args)
{
- int num_resumable_chunks, current_resumable_chunk;
- if(!PyArg_ParseTuple(args, "ii",
- &num_resumable_chunks,
- &current_resumable_chunk)) {
- Py_RETURN_NONE;
- }
-
- if(num_resumable_chunks <= 0) {
- fprintf(stderr, "Cycles: Bad value for number of resumable chunks.\n");
- abort();
- Py_RETURN_NONE;
- }
- if(current_resumable_chunk < 1 ||
- current_resumable_chunk > num_resumable_chunks)
- {
- fprintf(stderr, "Cycles: Bad value for current resumable chunk number.\n");
- abort();
- Py_RETURN_NONE;
- }
-
- VLOG(1) << "Initialized resumable render: "
- << "num_resumable_chunks=" << num_resumable_chunks << ", "
- << "current_resumable_chunk=" << current_resumable_chunk;
- BlenderSession::num_resumable_chunks = num_resumable_chunks;
- BlenderSession::current_resumable_chunk = current_resumable_chunk;
-
- printf("Cycles: Will render chunk %d of %d\n",
- current_resumable_chunk,
- num_resumable_chunks);
-
- Py_RETURN_NONE;
+ int num_resumable_chunks, current_resumable_chunk;
+ if (!PyArg_ParseTuple(args, "ii", &num_resumable_chunks, &current_resumable_chunk)) {
+ Py_RETURN_NONE;
+ }
+
+ if (num_resumable_chunks <= 0) {
+ fprintf(stderr, "Cycles: Bad value for number of resumable chunks.\n");
+ abort();
+ Py_RETURN_NONE;
+ }
+ if (current_resumable_chunk < 1 || current_resumable_chunk > num_resumable_chunks) {
+ fprintf(stderr, "Cycles: Bad value for current resumable chunk number.\n");
+ abort();
+ Py_RETURN_NONE;
+ }
+
+ VLOG(1) << "Initialized resumable render: "
+ << "num_resumable_chunks=" << num_resumable_chunks << ", "
+ << "current_resumable_chunk=" << current_resumable_chunk;
+ BlenderSession::num_resumable_chunks = num_resumable_chunks;
+ BlenderSession::current_resumable_chunk = current_resumable_chunk;
+
+ printf("Cycles: Will render chunk %d of %d\n", current_resumable_chunk, num_resumable_chunks);
+
+ Py_RETURN_NONE;
}
static PyObject *set_resumable_chunk_range_func(PyObject * /*self*/, PyObject *args)
{
- int num_chunks, start_chunk, end_chunk;
- if(!PyArg_ParseTuple(args, "iii",
- &num_chunks,
- &start_chunk,
- &end_chunk)) {
- Py_RETURN_NONE;
- }
-
- if(num_chunks <= 0) {
- fprintf(stderr, "Cycles: Bad value for number of resumable chunks.\n");
- abort();
- Py_RETURN_NONE;
- }
- if(start_chunk < 1 || start_chunk > num_chunks) {
- fprintf(stderr, "Cycles: Bad value for start chunk number.\n");
- abort();
- Py_RETURN_NONE;
- }
- if(end_chunk < 1 || end_chunk > num_chunks) {
- fprintf(stderr, "Cycles: Bad value for start chunk number.\n");
- abort();
- Py_RETURN_NONE;
- }
- if(start_chunk > end_chunk) {
- fprintf(stderr, "Cycles: End chunk should be higher than start one.\n");
- abort();
- Py_RETURN_NONE;
- }
-
- VLOG(1) << "Initialized resumable render: "
- << "num_resumable_chunks=" << num_chunks << ", "
- << "start_resumable_chunk=" << start_chunk
- << "end_resumable_chunk=" << end_chunk;
- BlenderSession::num_resumable_chunks = num_chunks;
- BlenderSession::start_resumable_chunk = start_chunk;
- BlenderSession::end_resumable_chunk = end_chunk;
-
- printf("Cycles: Will render chunks %d to %d of %d\n",
- start_chunk,
- end_chunk,
- num_chunks);
-
- Py_RETURN_NONE;
+ int num_chunks, start_chunk, end_chunk;
+ if (!PyArg_ParseTuple(args, "iii", &num_chunks, &start_chunk, &end_chunk)) {
+ Py_RETURN_NONE;
+ }
+
+ if (num_chunks <= 0) {
+ fprintf(stderr, "Cycles: Bad value for number of resumable chunks.\n");
+ abort();
+ Py_RETURN_NONE;
+ }
+ if (start_chunk < 1 || start_chunk > num_chunks) {
+ fprintf(stderr, "Cycles: Bad value for start chunk number.\n");
+ abort();
+ Py_RETURN_NONE;
+ }
+ if (end_chunk < 1 || end_chunk > num_chunks) {
+ fprintf(stderr, "Cycles: Bad value for start chunk number.\n");
+ abort();
+ Py_RETURN_NONE;
+ }
+ if (start_chunk > end_chunk) {
+ fprintf(stderr, "Cycles: End chunk should be higher than start one.\n");
+ abort();
+ Py_RETURN_NONE;
+ }
+
+ VLOG(1) << "Initialized resumable render: "
+ << "num_resumable_chunks=" << num_chunks << ", "
+ << "start_resumable_chunk=" << start_chunk << "end_resumable_chunk=" << end_chunk;
+ BlenderSession::num_resumable_chunks = num_chunks;
+ BlenderSession::start_resumable_chunk = start_chunk;
+ BlenderSession::end_resumable_chunk = end_chunk;
+
+ printf("Cycles: Will render chunks %d to %d of %d\n", start_chunk, end_chunk, num_chunks);
+
+ Py_RETURN_NONE;
}
static PyObject *enable_print_stats_func(PyObject * /*self*/, PyObject * /*args*/)
{
- BlenderSession::print_render_stats = true;
- Py_RETURN_NONE;
+ BlenderSession::print_render_stats = true;
+ Py_RETURN_NONE;
}
static PyObject *get_device_types_func(PyObject * /*self*/, PyObject * /*args*/)
{
- vector<DeviceType> device_types = Device::available_types();
- bool has_cuda = false, has_opencl = false;
- foreach(DeviceType device_type, device_types) {
- has_cuda |= (device_type == DEVICE_CUDA);
- has_opencl |= (device_type == DEVICE_OPENCL);
- }
- PyObject *list = PyTuple_New(2);
- PyTuple_SET_ITEM(list, 0, PyBool_FromLong(has_cuda));
- PyTuple_SET_ITEM(list, 1, PyBool_FromLong(has_opencl));
- return list;
+ vector<DeviceType> device_types = Device::available_types();
+ bool has_cuda = false, has_opencl = false;
+ foreach (DeviceType device_type, device_types) {
+ has_cuda |= (device_type == DEVICE_CUDA);
+ has_opencl |= (device_type == DEVICE_OPENCL);
+ }
+ PyObject *list = PyTuple_New(2);
+ PyTuple_SET_ITEM(list, 0, PyBool_FromLong(has_cuda));
+ PyTuple_SET_ITEM(list, 1, PyBool_FromLong(has_opencl));
+ return list;
}
static PyMethodDef methods[] = {
- {"init", init_func, METH_VARARGS, ""},
- {"exit", exit_func, METH_VARARGS, ""},
- {"create", create_func, METH_VARARGS, ""},
- {"free", free_func, METH_O, ""},
- {"render", render_func, METH_VARARGS, ""},
- {"bake", bake_func, METH_VARARGS, ""},
- {"draw", draw_func, METH_VARARGS, ""},
- {"sync", sync_func, METH_VARARGS, ""},
- {"reset", reset_func, METH_VARARGS, ""},
+ {"init", init_func, METH_VARARGS, ""},
+ {"exit", exit_func, METH_VARARGS, ""},
+ {"create", create_func, METH_VARARGS, ""},
+ {"free", free_func, METH_O, ""},
+ {"render", render_func, METH_VARARGS, ""},
+ {"bake", bake_func, METH_VARARGS, ""},
+ {"draw", draw_func, METH_VARARGS, ""},
+ {"sync", sync_func, METH_VARARGS, ""},
+ {"reset", reset_func, METH_VARARGS, ""},
#ifdef WITH_OSL
- {"osl_update_node", osl_update_node_func, METH_VARARGS, ""},
- {"osl_compile", osl_compile_func, METH_VARARGS, ""},
+ {"osl_update_node", osl_update_node_func, METH_VARARGS, ""},
+ {"osl_compile", osl_compile_func, METH_VARARGS, ""},
#endif
- {"available_devices", available_devices_func, METH_VARARGS, ""},
- {"system_info", system_info_func, METH_NOARGS, ""},
+ {"available_devices", available_devices_func, METH_VARARGS, ""},
+ {"system_info", system_info_func, METH_NOARGS, ""},
#ifdef WITH_OPENCL
- {"opencl_disable", opencl_disable_func, METH_NOARGS, ""},
- {"opencl_compile", opencl_compile_func, METH_VARARGS, ""},
+ {"opencl_disable", opencl_disable_func, METH_NOARGS, ""},
+ {"opencl_compile", opencl_compile_func, METH_VARARGS, ""},
#endif
- /* Standalone denoising */
- {"denoise", (PyCFunction)denoise_func, METH_VARARGS|METH_KEYWORDS, ""},
- {"merge", (PyCFunction)merge_func, METH_VARARGS|METH_KEYWORDS, ""},
+ /* Standalone denoising */
+ {"denoise", (PyCFunction)denoise_func, METH_VARARGS | METH_KEYWORDS, ""},
+ {"merge", (PyCFunction)merge_func, METH_VARARGS | METH_KEYWORDS, ""},
- /* Debugging routines */
- {"debug_flags_update", debug_flags_update_func, METH_VARARGS, ""},
- {"debug_flags_reset", debug_flags_reset_func, METH_NOARGS, ""},
+ /* Debugging routines */
+ {"debug_flags_update", debug_flags_update_func, METH_VARARGS, ""},
+ {"debug_flags_reset", debug_flags_reset_func, METH_NOARGS, ""},
- /* Statistics. */
- {"enable_print_stats", enable_print_stats_func, METH_NOARGS, ""},
+ /* Statistics. */
+ {"enable_print_stats", enable_print_stats_func, METH_NOARGS, ""},
- /* Resumable render */
- {"set_resumable_chunk", set_resumable_chunk_func, METH_VARARGS, ""},
- {"set_resumable_chunk_range", set_resumable_chunk_range_func, METH_VARARGS, ""},
+ /* Resumable render */
+ {"set_resumable_chunk", set_resumable_chunk_func, METH_VARARGS, ""},
+ {"set_resumable_chunk_range", set_resumable_chunk_range_func, METH_VARARGS, ""},
- /* Compute Device selection */
- {"get_device_types", get_device_types_func, METH_VARARGS, ""},
+ /* Compute Device selection */
+ {"get_device_types", get_device_types_func, METH_VARARGS, ""},
- {NULL, NULL, 0, NULL},
+ {NULL, NULL, 0, NULL},
};
static struct PyModuleDef module = {
- PyModuleDef_HEAD_INIT,
- "_cycles",
- "Blender cycles render integration",
- -1,
- methods,
- NULL, NULL, NULL, NULL,
+ PyModuleDef_HEAD_INIT,
+ "_cycles",
+ "Blender cycles render integration",
+ -1,
+ methods,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
};
CCL_NAMESPACE_END
void *CCL_python_module_init()
{
- PyObject *mod = PyModule_Create(&ccl::module);
+ PyObject *mod = PyModule_Create(&ccl::module);
#ifdef WITH_OSL
- /* TODO(sergey): This gives us library we've been linking against.
- * In theory with dynamic OSL library it might not be
- * accurate, but there's nothing in OSL API which we
- * might use to get version in runtime.
- */
- int curversion = OSL_LIBRARY_VERSION_CODE;
- PyModule_AddObject(mod, "with_osl", Py_True);
- Py_INCREF(Py_True);
- PyModule_AddObject(mod, "osl_version",
- Py_BuildValue("(iii)",
- curversion / 10000, (curversion / 100) % 100, curversion % 100));
- PyModule_AddObject(mod, "osl_version_string",
- PyUnicode_FromFormat("%2d, %2d, %2d",
- curversion / 10000, (curversion / 100) % 100, curversion % 100));
+ /* TODO(sergey): This gives us library we've been linking against.
+ * In theory with dynamic OSL library it might not be
+ * accurate, but there's nothing in OSL API which we
+ * might use to get version in runtime.
+ */
+ int curversion = OSL_LIBRARY_VERSION_CODE;
+ PyModule_AddObject(mod, "with_osl", Py_True);
+ Py_INCREF(Py_True);
+ PyModule_AddObject(
+ mod,
+ "osl_version",
+ Py_BuildValue("(iii)", curversion / 10000, (curversion / 100) % 100, curversion % 100));
+ PyModule_AddObject(
+ mod,
+ "osl_version_string",
+ PyUnicode_FromFormat(
+ "%2d, %2d, %2d", curversion / 10000, (curversion / 100) % 100, curversion % 100));
#else
- PyModule_AddObject(mod, "with_osl", Py_False);
- Py_INCREF(Py_False);
- PyModule_AddStringConstant(mod, "osl_version", "unknown");
- PyModule_AddStringConstant(mod, "osl_version_string", "unknown");
+ PyModule_AddObject(mod, "with_osl", Py_False);
+ Py_INCREF(Py_False);
+ PyModule_AddStringConstant(mod, "osl_version", "unknown");
+ PyModule_AddStringConstant(mod, "osl_version_string", "unknown");
#endif
#ifdef WITH_CYCLES_DEBUG
- PyModule_AddObject(mod, "with_cycles_debug", Py_True);
- Py_INCREF(Py_True);
+ 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);
+ 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);
+ PyModule_AddObject(mod, "with_network", Py_True);
+ Py_INCREF(Py_True);
#else /* WITH_NETWORK */
- PyModule_AddObject(mod, "with_network", Py_False);
- Py_INCREF(Py_False);
-#endif /* WITH_NETWORK */
+ PyModule_AddObject(mod, "with_network", Py_False);
+ Py_INCREF(Py_False);
+#endif /* WITH_NETWORK */
#ifdef WITH_EMBREE
- PyModule_AddObject(mod, "with_embree", Py_True);
- Py_INCREF(Py_True);
+ PyModule_AddObject(mod, "with_embree", Py_True);
+ Py_INCREF(Py_True);
#else /* WITH_EMBREE */
- PyModule_AddObject(mod, "with_embree", Py_False);
- Py_INCREF(Py_False);
-#endif /* WITH_EMBREE */
+ PyModule_AddObject(mod, "with_embree", Py_False);
+ Py_INCREF(Py_False);
+#endif /* WITH_EMBREE */
- return (void*)mod;
+ return (void *)mod;
}
diff --git a/intern/cycles/blender/blender_session.cpp b/intern/cycles/blender/blender_session.cpp
index cf856c3b3d4..29a97bf6546 100644
--- a/intern/cycles/blender/blender_session.cpp
+++ b/intern/cycles/blender/blender_session.cpp
@@ -53,1051 +53,1070 @@ int BlenderSession::start_resumable_chunk = 0;
int BlenderSession::end_resumable_chunk = 0;
bool BlenderSession::print_render_stats = false;
-BlenderSession::BlenderSession(BL::RenderEngine& b_engine,
- BL::Preferences& b_userpref,
- BL::BlendData& b_data,
+BlenderSession::BlenderSession(BL::RenderEngine &b_engine,
+ BL::Preferences &b_userpref,
+ BL::BlendData &b_data,
bool preview_osl)
-: session(NULL),
- sync(NULL),
- b_engine(b_engine),
- b_userpref(b_userpref),
- b_data(b_data),
- b_render(b_engine.render()),
- b_depsgraph(PointerRNA_NULL),
- b_scene(PointerRNA_NULL),
- b_v3d(PointerRNA_NULL),
- b_rv3d(PointerRNA_NULL),
- width(0),
- height(0),
- preview_osl(preview_osl),
- python_thread_state(NULL)
+ : session(NULL),
+ sync(NULL),
+ b_engine(b_engine),
+ b_userpref(b_userpref),
+ b_data(b_data),
+ b_render(b_engine.render()),
+ b_depsgraph(PointerRNA_NULL),
+ b_scene(PointerRNA_NULL),
+ b_v3d(PointerRNA_NULL),
+ b_rv3d(PointerRNA_NULL),
+ width(0),
+ height(0),
+ preview_osl(preview_osl),
+ python_thread_state(NULL)
{
- /* offline render */
- background = true;
- last_redraw_time = 0.0;
- start_resize_time = 0.0;
- last_status_time = 0.0;
+ /* offline render */
+ background = true;
+ last_redraw_time = 0.0;
+ start_resize_time = 0.0;
+ last_status_time = 0.0;
}
-BlenderSession::BlenderSession(BL::RenderEngine& b_engine,
- BL::Preferences& b_userpref,
- BL::BlendData& b_data,
- BL::SpaceView3D& b_v3d,
- BL::RegionView3D& b_rv3d,
- int width, int height)
-: session(NULL),
- sync(NULL),
- b_engine(b_engine),
- b_userpref(b_userpref),
- b_data(b_data),
- b_render(b_engine.render()),
- b_depsgraph(PointerRNA_NULL),
- b_scene(PointerRNA_NULL),
- b_v3d(b_v3d),
- b_rv3d(b_rv3d),
- width(width),
- height(height),
- preview_osl(false),
- python_thread_state(NULL)
+BlenderSession::BlenderSession(BL::RenderEngine &b_engine,
+ BL::Preferences &b_userpref,
+ BL::BlendData &b_data,
+ BL::SpaceView3D &b_v3d,
+ BL::RegionView3D &b_rv3d,
+ int width,
+ int height)
+ : session(NULL),
+ sync(NULL),
+ b_engine(b_engine),
+ b_userpref(b_userpref),
+ b_data(b_data),
+ b_render(b_engine.render()),
+ b_depsgraph(PointerRNA_NULL),
+ b_scene(PointerRNA_NULL),
+ b_v3d(b_v3d),
+ b_rv3d(b_rv3d),
+ width(width),
+ height(height),
+ preview_osl(false),
+ python_thread_state(NULL)
{
- /* 3d view render */
- background = false;
- last_redraw_time = 0.0;
- start_resize_time = 0.0;
- last_status_time = 0.0;
+ /* 3d view render */
+ background = false;
+ last_redraw_time = 0.0;
+ start_resize_time = 0.0;
+ last_status_time = 0.0;
}
BlenderSession::~BlenderSession()
{
- free_session();
+ free_session();
}
void BlenderSession::create()
{
- create_session();
+ create_session();
}
void BlenderSession::create_session()
{
- SessionParams session_params = BlenderSync::get_session_params(b_engine, b_userpref, b_scene, background);
- SceneParams scene_params = BlenderSync::get_scene_params(b_scene, background);
- bool session_pause = BlenderSync::get_session_pause(b_scene, background);
-
- /* reset status/progress */
- last_status = "";
- last_error = "";
- last_progress = -1.0f;
- start_resize_time = 0.0;
-
- /* create session */
- session = new Session(session_params);
- session->scene = scene;
- session->progress.set_update_callback(function_bind(&BlenderSession::tag_redraw, this));
- session->progress.set_cancel_callback(function_bind(&BlenderSession::test_cancel, this));
- session->set_pause(session_pause);
-
- /* create scene */
- scene = new Scene(scene_params, session->device);
- scene->name = b_scene.name();
-
- /* setup callbacks for builtin image support */
- scene->image_manager->builtin_image_info_cb = function_bind(&BlenderSession::builtin_image_info, this, _1, _2, _3);
- scene->image_manager->builtin_image_pixels_cb = function_bind(&BlenderSession::builtin_image_pixels, this, _1, _2, _3, _4, _5);
- scene->image_manager->builtin_image_float_pixels_cb = function_bind(&BlenderSession::builtin_image_float_pixels, this, _1, _2, _3, _4, _5);
-
- session->scene = scene;
-
- /* There is no single depsgraph to use for the entire render.
- * So we need to handle this differently.
- *
- * We could loop over the final render result render layers in pipeline and keep Cycles unaware of multiple layers,
- * or perhaps move syncing further down in the pipeline.
- */
- /* create sync */
- sync = new BlenderSync(b_engine, b_data, b_scene, scene, !background, session->progress);
- BL::Object b_camera_override(b_engine.camera_override());
- if(b_v3d) {
- sync->sync_view(b_v3d, b_rv3d, width, height);
- }
- else {
- sync->sync_camera(b_render, b_camera_override, width, height, "");
- }
-
- /* set buffer parameters */
- BufferParams buffer_params = BlenderSync::get_buffer_params(b_render, b_v3d, b_rv3d, scene->camera, width, height);
- session->reset(buffer_params, session_params.samples);
-
- b_engine.use_highlight_tiles(session_params.progressive_refine == false);
-
- update_resumable_tile_manager(session_params.samples);
+ SessionParams session_params = BlenderSync::get_session_params(
+ b_engine, b_userpref, b_scene, background);
+ SceneParams scene_params = BlenderSync::get_scene_params(b_scene, background);
+ bool session_pause = BlenderSync::get_session_pause(b_scene, background);
+
+ /* reset status/progress */
+ last_status = "";
+ last_error = "";
+ last_progress = -1.0f;
+ start_resize_time = 0.0;
+
+ /* create session */
+ session = new Session(session_params);
+ session->scene = scene;
+ session->progress.set_update_callback(function_bind(&BlenderSession::tag_redraw, this));
+ session->progress.set_cancel_callback(function_bind(&BlenderSession::test_cancel, this));
+ session->set_pause(session_pause);
+
+ /* create scene */
+ scene = new Scene(scene_params, session->device);
+ scene->name = b_scene.name();
+
+ /* setup callbacks for builtin image support */
+ scene->image_manager->builtin_image_info_cb = function_bind(
+ &BlenderSession::builtin_image_info, this, _1, _2, _3);
+ scene->image_manager->builtin_image_pixels_cb = function_bind(
+ &BlenderSession::builtin_image_pixels, this, _1, _2, _3, _4, _5);
+ scene->image_manager->builtin_image_float_pixels_cb = function_bind(
+ &BlenderSession::builtin_image_float_pixels, this, _1, _2, _3, _4, _5);
+
+ session->scene = scene;
+
+ /* There is no single depsgraph to use for the entire render.
+ * So we need to handle this differently.
+ *
+ * We could loop over the final render result render layers in pipeline and keep Cycles unaware of multiple layers,
+ * or perhaps move syncing further down in the pipeline.
+ */
+ /* create sync */
+ sync = new BlenderSync(b_engine, b_data, b_scene, scene, !background, session->progress);
+ BL::Object b_camera_override(b_engine.camera_override());
+ if (b_v3d) {
+ sync->sync_view(b_v3d, b_rv3d, width, height);
+ }
+ else {
+ sync->sync_camera(b_render, b_camera_override, width, height, "");
+ }
+
+ /* set buffer parameters */
+ BufferParams buffer_params = BlenderSync::get_buffer_params(
+ b_render, b_v3d, b_rv3d, scene->camera, width, height);
+ session->reset(buffer_params, session_params.samples);
+
+ b_engine.use_highlight_tiles(session_params.progressive_refine == false);
+
+ update_resumable_tile_manager(session_params.samples);
}
-void BlenderSession::reset_session(BL::BlendData& b_data, BL::Depsgraph& b_depsgraph)
+void BlenderSession::reset_session(BL::BlendData &b_data, BL::Depsgraph &b_depsgraph)
{
- this->b_data = b_data;
- this->b_depsgraph = b_depsgraph;
- this->b_scene = b_depsgraph.scene_eval();
-
- if(preview_osl) {
- PointerRNA cscene = RNA_pointer_get(&b_scene.ptr, "cycles");
- RNA_boolean_set(&cscene, "shading_system", preview_osl);
- }
-
- if(b_v3d) {
- this->b_render = b_scene.render();
- }
- else {
- this->b_render = b_engine.render();
- width = render_resolution_x(b_render);
- height = render_resolution_y(b_render);
- }
-
- if(session == NULL) {
- create();
- }
-
- if(b_v3d) {
- /* NOTE: We need to create session, but all the code from below
- * will make viewport render to stuck on initialization.
- */
- return;
- }
-
- SessionParams session_params = BlenderSync::get_session_params(b_engine, b_userpref, b_scene, background);
- SceneParams scene_params = BlenderSync::get_scene_params(b_scene, background);
-
- if(scene->params.modified(scene_params) ||
- session->params.modified(session_params) ||
- !scene_params.persistent_data)
- {
- /* if scene or session parameters changed, it's easier to simply re-create
- * them rather than trying to distinguish which settings need to be updated
- */
- free_session();
- create_session();
- return;
- }
-
- session->progress.reset();
- scene->reset();
-
- session->tile_manager.set_tile_order(session_params.tile_order);
-
- /* peak memory usage should show current render peak, not peak for all renders
- * made by this render session
- */
- session->stats.mem_peak = session->stats.mem_used;
-
- /* There is no single depsgraph to use for the entire render.
- * See note on create_session().
- */
- /* sync object should be re-created */
- sync = new BlenderSync(b_engine, b_data, b_scene, scene, !background, session->progress);
-
- BL::SpaceView3D b_null_space_view3d(PointerRNA_NULL);
- BL::RegionView3D b_null_region_view3d(PointerRNA_NULL);
- BufferParams buffer_params = BlenderSync::get_buffer_params(b_render,
- b_null_space_view3d,
- b_null_region_view3d,
- scene->camera,
- width, height);
- session->reset(buffer_params, session_params.samples);
-
- b_engine.use_highlight_tiles(session_params.progressive_refine == false);
-
- /* reset time */
- start_resize_time = 0.0;
+ this->b_data = b_data;
+ this->b_depsgraph = b_depsgraph;
+ this->b_scene = b_depsgraph.scene_eval();
+
+ if (preview_osl) {
+ PointerRNA cscene = RNA_pointer_get(&b_scene.ptr, "cycles");
+ RNA_boolean_set(&cscene, "shading_system", preview_osl);
+ }
+
+ if (b_v3d) {
+ this->b_render = b_scene.render();
+ }
+ else {
+ this->b_render = b_engine.render();
+ width = render_resolution_x(b_render);
+ height = render_resolution_y(b_render);
+ }
+
+ if (session == NULL) {
+ create();
+ }
+
+ if (b_v3d) {
+ /* NOTE: We need to create session, but all the code from below
+ * will make viewport render to stuck on initialization.
+ */
+ return;
+ }
+
+ SessionParams session_params = BlenderSync::get_session_params(
+ b_engine, b_userpref, b_scene, background);
+ SceneParams scene_params = BlenderSync::get_scene_params(b_scene, background);
+
+ if (scene->params.modified(scene_params) || session->params.modified(session_params) ||
+ !scene_params.persistent_data) {
+ /* if scene or session parameters changed, it's easier to simply re-create
+ * them rather than trying to distinguish which settings need to be updated
+ */
+ free_session();
+ create_session();
+ return;
+ }
+
+ session->progress.reset();
+ scene->reset();
+
+ session->tile_manager.set_tile_order(session_params.tile_order);
+
+ /* peak memory usage should show current render peak, not peak for all renders
+ * made by this render session
+ */
+ session->stats.mem_peak = session->stats.mem_used;
+
+ /* There is no single depsgraph to use for the entire render.
+ * See note on create_session().
+ */
+ /* sync object should be re-created */
+ sync = new BlenderSync(b_engine, b_data, b_scene, scene, !background, session->progress);
+
+ BL::SpaceView3D b_null_space_view3d(PointerRNA_NULL);
+ BL::RegionView3D b_null_region_view3d(PointerRNA_NULL);
+ BufferParams buffer_params = BlenderSync::get_buffer_params(
+ b_render, b_null_space_view3d, b_null_region_view3d, scene->camera, width, height);
+ session->reset(buffer_params, session_params.samples);
+
+ b_engine.use_highlight_tiles(session_params.progressive_refine == false);
+
+ /* reset time */
+ start_resize_time = 0.0;
}
void BlenderSession::free_session()
{
- if(sync)
- delete sync;
+ if (sync)
+ delete sync;
- delete session;
+ delete session;
}
-static ShaderEvalType get_shader_type(const string& pass_type)
+static ShaderEvalType get_shader_type(const string &pass_type)
{
- const char *shader_type = pass_type.c_str();
-
- /* data passes */
- if(strcmp(shader_type, "NORMAL")==0)
- return SHADER_EVAL_NORMAL;
- else if(strcmp(shader_type, "UV")==0)
- return SHADER_EVAL_UV;
- else if(strcmp(shader_type, "ROUGHNESS")==0)
- return SHADER_EVAL_ROUGHNESS;
- else if(strcmp(shader_type, "DIFFUSE_COLOR")==0)
- return SHADER_EVAL_DIFFUSE_COLOR;
- else if(strcmp(shader_type, "GLOSSY_COLOR")==0)
- return SHADER_EVAL_GLOSSY_COLOR;
- else if(strcmp(shader_type, "TRANSMISSION_COLOR")==0)
- return SHADER_EVAL_TRANSMISSION_COLOR;
- else if(strcmp(shader_type, "SUBSURFACE_COLOR")==0)
- return SHADER_EVAL_SUBSURFACE_COLOR;
- else if(strcmp(shader_type, "EMIT")==0)
- return SHADER_EVAL_EMISSION;
-
- /* light passes */
- else if(strcmp(shader_type, "AO")==0)
- return SHADER_EVAL_AO;
- else if(strcmp(shader_type, "COMBINED")==0)
- return SHADER_EVAL_COMBINED;
- else if(strcmp(shader_type, "SHADOW")==0)
- return SHADER_EVAL_SHADOW;
- else if(strcmp(shader_type, "DIFFUSE")==0)
- return SHADER_EVAL_DIFFUSE;
- else if(strcmp(shader_type, "GLOSSY")==0)
- return SHADER_EVAL_GLOSSY;
- else if(strcmp(shader_type, "TRANSMISSION")==0)
- return SHADER_EVAL_TRANSMISSION;
- else if(strcmp(shader_type, "SUBSURFACE")==0)
- return SHADER_EVAL_SUBSURFACE;
-
- /* extra */
- else if(strcmp(shader_type, "ENVIRONMENT")==0)
- return SHADER_EVAL_ENVIRONMENT;
-
- else
- return SHADER_EVAL_BAKE;
+ const char *shader_type = pass_type.c_str();
+
+ /* data passes */
+ if (strcmp(shader_type, "NORMAL") == 0)
+ return SHADER_EVAL_NORMAL;
+ else if (strcmp(shader_type, "UV") == 0)
+ return SHADER_EVAL_UV;
+ else if (strcmp(shader_type, "ROUGHNESS") == 0)
+ return SHADER_EVAL_ROUGHNESS;
+ else if (strcmp(shader_type, "DIFFUSE_COLOR") == 0)
+ return SHADER_EVAL_DIFFUSE_COLOR;
+ else if (strcmp(shader_type, "GLOSSY_COLOR") == 0)
+ return SHADER_EVAL_GLOSSY_COLOR;
+ else if (strcmp(shader_type, "TRANSMISSION_COLOR") == 0)
+ return SHADER_EVAL_TRANSMISSION_COLOR;
+ else if (strcmp(shader_type, "SUBSURFACE_COLOR") == 0)
+ return SHADER_EVAL_SUBSURFACE_COLOR;
+ else if (strcmp(shader_type, "EMIT") == 0)
+ return SHADER_EVAL_EMISSION;
+
+ /* light passes */
+ else if (strcmp(shader_type, "AO") == 0)
+ return SHADER_EVAL_AO;
+ else if (strcmp(shader_type, "COMBINED") == 0)
+ return SHADER_EVAL_COMBINED;
+ else if (strcmp(shader_type, "SHADOW") == 0)
+ return SHADER_EVAL_SHADOW;
+ else if (strcmp(shader_type, "DIFFUSE") == 0)
+ return SHADER_EVAL_DIFFUSE;
+ else if (strcmp(shader_type, "GLOSSY") == 0)
+ return SHADER_EVAL_GLOSSY;
+ else if (strcmp(shader_type, "TRANSMISSION") == 0)
+ return SHADER_EVAL_TRANSMISSION;
+ else if (strcmp(shader_type, "SUBSURFACE") == 0)
+ return SHADER_EVAL_SUBSURFACE;
+
+ /* extra */
+ else if (strcmp(shader_type, "ENVIRONMENT") == 0)
+ return SHADER_EVAL_ENVIRONMENT;
+
+ else
+ return SHADER_EVAL_BAKE;
}
-static BL::RenderResult begin_render_result(BL::RenderEngine& b_engine,
- int x, int y,
- int w, int h,
+static BL::RenderResult begin_render_result(BL::RenderEngine &b_engine,
+ int x,
+ int y,
+ int w,
+ int h,
const char *layername,
const char *viewname)
{
- return b_engine.begin_result(x, y, w, h, layername, viewname);
+ return b_engine.begin_result(x, y, w, h, layername, viewname);
}
-static void end_render_result(BL::RenderEngine& b_engine,
- BL::RenderResult& b_rr,
+static void end_render_result(BL::RenderEngine &b_engine,
+ BL::RenderResult &b_rr,
bool cancel,
bool highlight,
bool do_merge_results)
{
- b_engine.end_result(b_rr, (int)cancel, (int) highlight, (int)do_merge_results);
+ b_engine.end_result(b_rr, (int)cancel, (int)highlight, (int)do_merge_results);
}
-void BlenderSession::do_write_update_render_tile(RenderTile& rtile, bool do_update_only, bool highlight)
+void BlenderSession::do_write_update_render_tile(RenderTile &rtile,
+ bool do_update_only,
+ bool highlight)
{
- int x = rtile.x - session->tile_manager.params.full_x;
- int y = rtile.y - session->tile_manager.params.full_y;
- int w = rtile.w;
- int h = rtile.h;
-
- /* get render result */
- BL::RenderResult b_rr = begin_render_result(b_engine, x, y, w, h, b_rlay_name.c_str(), b_rview_name.c_str());
-
- /* can happen if the intersected rectangle gives 0 width or height */
- if(b_rr.ptr.data == NULL) {
- return;
- }
-
- BL::RenderResult::layers_iterator b_single_rlay;
- b_rr.layers.begin(b_single_rlay);
-
- /* layer will be missing if it was disabled in the UI */
- if(b_single_rlay == b_rr.layers.end())
- return;
-
- BL::RenderLayer b_rlay = *b_single_rlay;
-
- if(do_update_only) {
- /* Sample would be zero at initial tile update, which is only needed
- * to tag tile form blender side as IN PROGRESS for proper highlight
- * no buffers should be sent to blender yet. For denoise we also
- * keep showing the noisy buffers until denoise is done. */
- bool merge = (rtile.sample != 0) && (rtile.task != RenderTile::DENOISE);
-
- if(merge) {
- update_render_result(b_rr, b_rlay, rtile);
- }
-
- end_render_result(b_engine, b_rr, true, highlight, merge);
- }
- else {
- /* Write final render result. */
- write_render_result(b_rr, b_rlay, rtile);
- end_render_result(b_engine, b_rr, false, false, true);
- }
+ int x = rtile.x - session->tile_manager.params.full_x;
+ int y = rtile.y - session->tile_manager.params.full_y;
+ int w = rtile.w;
+ int h = rtile.h;
+
+ /* get render result */
+ BL::RenderResult b_rr = begin_render_result(
+ b_engine, x, y, w, h, b_rlay_name.c_str(), b_rview_name.c_str());
+
+ /* can happen if the intersected rectangle gives 0 width or height */
+ if (b_rr.ptr.data == NULL) {
+ return;
+ }
+
+ BL::RenderResult::layers_iterator b_single_rlay;
+ b_rr.layers.begin(b_single_rlay);
+
+ /* layer will be missing if it was disabled in the UI */
+ if (b_single_rlay == b_rr.layers.end())
+ return;
+
+ BL::RenderLayer b_rlay = *b_single_rlay;
+
+ if (do_update_only) {
+ /* Sample would be zero at initial tile update, which is only needed
+ * to tag tile form blender side as IN PROGRESS for proper highlight
+ * no buffers should be sent to blender yet. For denoise we also
+ * keep showing the noisy buffers until denoise is done. */
+ bool merge = (rtile.sample != 0) && (rtile.task != RenderTile::DENOISE);
+
+ if (merge) {
+ update_render_result(b_rr, b_rlay, rtile);
+ }
+
+ end_render_result(b_engine, b_rr, true, highlight, merge);
+ }
+ else {
+ /* Write final render result. */
+ write_render_result(b_rr, b_rlay, rtile);
+ end_render_result(b_engine, b_rr, false, false, true);
+ }
}
-void BlenderSession::write_render_tile(RenderTile& rtile)
+void BlenderSession::write_render_tile(RenderTile &rtile)
{
- do_write_update_render_tile(rtile, false, false);
+ do_write_update_render_tile(rtile, false, false);
}
-void BlenderSession::update_render_tile(RenderTile& rtile, bool highlight)
+void BlenderSession::update_render_tile(RenderTile &rtile, bool highlight)
{
- /* use final write for preview renders, otherwise render result wouldn't be
- * be updated in blender side
- * would need to be investigated a bit further, but for now shall be fine
- */
- if(!b_engine.is_preview())
- do_write_update_render_tile(rtile, true, highlight);
- else
- do_write_update_render_tile(rtile, false, false);
+ /* use final write for preview renders, otherwise render result wouldn't be
+ * be updated in blender side
+ * would need to be investigated a bit further, but for now shall be fine
+ */
+ if (!b_engine.is_preview())
+ do_write_update_render_tile(rtile, true, highlight);
+ else
+ do_write_update_render_tile(rtile, false, false);
}
-static void add_cryptomatte_layer(BL::RenderResult& b_rr, string name, string manifest)
+static void add_cryptomatte_layer(BL::RenderResult &b_rr, string name, string manifest)
{
- string identifier = string_printf("%08x", util_murmur_hash3(name.c_str(), name.length(), 0));
- string prefix = "cryptomatte/" + identifier.substr(0, 7) + "/";
+ string identifier = string_printf("%08x", util_murmur_hash3(name.c_str(), name.length(), 0));
+ string prefix = "cryptomatte/" + identifier.substr(0, 7) + "/";
- render_add_metadata(b_rr, prefix+"name", name);
- render_add_metadata(b_rr, prefix+"hash", "MurmurHash3_32");
- render_add_metadata(b_rr, prefix+"conversion", "uint32_to_float32");
- render_add_metadata(b_rr, prefix+"manifest", manifest);
+ render_add_metadata(b_rr, prefix + "name", name);
+ render_add_metadata(b_rr, prefix + "hash", "MurmurHash3_32");
+ render_add_metadata(b_rr, prefix + "conversion", "uint32_to_float32");
+ render_add_metadata(b_rr, prefix + "manifest", manifest);
}
-void BlenderSession::stamp_view_layer_metadata(Scene *scene, const string& view_layer_name)
+void BlenderSession::stamp_view_layer_metadata(Scene *scene, const string &view_layer_name)
{
- BL::RenderResult b_rr = b_engine.get_result();
- string prefix = "cycles." + view_layer_name + ".";
-
- /* Configured number of samples for the view layer. */
- b_rr.stamp_data_add_field(
- (prefix + "samples").c_str(),
- to_string(session->params.samples).c_str());
-
- /* Store ranged samples information. */
- if(session->tile_manager.range_num_samples != -1) {
- b_rr.stamp_data_add_field(
- (prefix + "range_start_sample").c_str(),
- to_string(session->tile_manager.range_start_sample).c_str());
- b_rr.stamp_data_add_field(
- (prefix + "range_num_samples").c_str(),
- to_string(session->tile_manager.range_num_samples).c_str());
- }
-
- /* Write cryptomatte metadata. */
- if(scene->film->cryptomatte_passes & CRYPT_OBJECT) {
- add_cryptomatte_layer(b_rr, view_layer_name + ".CryptoObject",
- scene->object_manager->get_cryptomatte_objects(scene));
- }
- if(scene->film->cryptomatte_passes & CRYPT_MATERIAL) {
- add_cryptomatte_layer(b_rr, view_layer_name + ".CryptoMaterial",
- scene->shader_manager->get_cryptomatte_materials(scene));
- }
- if(scene->film->cryptomatte_passes & CRYPT_ASSET) {
- add_cryptomatte_layer(b_rr, view_layer_name + ".CryptoAsset",
- scene->object_manager->get_cryptomatte_assets(scene));
- }
-
- /* Store synchronization and bare-render times. */
- double total_time, render_time;
- session->progress.get_time(total_time, render_time);
- b_rr.stamp_data_add_field((prefix + "total_time").c_str(),
- time_human_readable_from_seconds(total_time).c_str());
- b_rr.stamp_data_add_field((prefix + "render_time").c_str(),
- time_human_readable_from_seconds(render_time).c_str());
- b_rr.stamp_data_add_field((prefix + "synchronization_time").c_str(),
- time_human_readable_from_seconds(total_time - render_time).c_str());
+ BL::RenderResult b_rr = b_engine.get_result();
+ string prefix = "cycles." + view_layer_name + ".";
+
+ /* Configured number of samples for the view layer. */
+ b_rr.stamp_data_add_field((prefix + "samples").c_str(),
+ to_string(session->params.samples).c_str());
+
+ /* Store ranged samples information. */
+ if (session->tile_manager.range_num_samples != -1) {
+ b_rr.stamp_data_add_field((prefix + "range_start_sample").c_str(),
+ to_string(session->tile_manager.range_start_sample).c_str());
+ b_rr.stamp_data_add_field((prefix + "range_num_samples").c_str(),
+ to_string(session->tile_manager.range_num_samples).c_str());
+ }
+
+ /* Write cryptomatte metadata. */
+ if (scene->film->cryptomatte_passes & CRYPT_OBJECT) {
+ add_cryptomatte_layer(b_rr,
+ view_layer_name + ".CryptoObject",
+ scene->object_manager->get_cryptomatte_objects(scene));
+ }
+ if (scene->film->cryptomatte_passes & CRYPT_MATERIAL) {
+ add_cryptomatte_layer(b_rr,
+ view_layer_name + ".CryptoMaterial",
+ scene->shader_manager->get_cryptomatte_materials(scene));
+ }
+ if (scene->film->cryptomatte_passes & CRYPT_ASSET) {
+ add_cryptomatte_layer(b_rr,
+ view_layer_name + ".CryptoAsset",
+ scene->object_manager->get_cryptomatte_assets(scene));
+ }
+
+ /* Store synchronization and bare-render times. */
+ double total_time, render_time;
+ session->progress.get_time(total_time, render_time);
+ b_rr.stamp_data_add_field((prefix + "total_time").c_str(),
+ time_human_readable_from_seconds(total_time).c_str());
+ b_rr.stamp_data_add_field((prefix + "render_time").c_str(),
+ time_human_readable_from_seconds(render_time).c_str());
+ b_rr.stamp_data_add_field((prefix + "synchronization_time").c_str(),
+ time_human_readable_from_seconds(total_time - render_time).c_str());
}
-void BlenderSession::render(BL::Depsgraph& b_depsgraph_)
+void BlenderSession::render(BL::Depsgraph &b_depsgraph_)
{
- b_depsgraph = b_depsgraph_;
-
- /* set callback to write out render results */
- session->write_render_tile_cb = function_bind(&BlenderSession::write_render_tile, this, _1);
- session->update_render_tile_cb = function_bind(&BlenderSession::update_render_tile, this, _1, _2);
-
- /* get buffer parameters */
- SessionParams session_params = BlenderSync::get_session_params(b_engine, b_userpref, b_scene, background);
- BufferParams buffer_params = BlenderSync::get_buffer_params(b_render, b_v3d, b_rv3d, scene->camera, width, height);
-
- /* render each layer */
- BL::ViewLayer b_view_layer = b_depsgraph.view_layer_eval();
-
- /* temporary render result to find needed passes and views */
- BL::RenderResult b_rr = begin_render_result(b_engine, 0, 0, 1, 1, b_view_layer.name().c_str(), NULL);
- BL::RenderResult::layers_iterator b_single_rlay;
- b_rr.layers.begin(b_single_rlay);
- BL::RenderLayer b_rlay = *b_single_rlay;
- b_rlay_name = b_view_layer.name();
-
- /* add passes */
- vector<Pass> passes = sync->sync_render_passes(b_rlay, b_view_layer);
- buffer_params.passes = passes;
-
- PointerRNA crl = RNA_pointer_get(&b_view_layer.ptr, "cycles");
- bool full_denoising = get_boolean(crl, "use_denoising");
- bool write_denoising_passes = get_boolean(crl, "denoising_store_passes");
-
- bool run_denoising = full_denoising || write_denoising_passes;
-
- session->tile_manager.schedule_denoising = run_denoising;
- buffer_params.denoising_data_pass = run_denoising;
- buffer_params.denoising_clean_pass = (scene->film->denoising_flags & DENOISING_CLEAN_ALL_PASSES);
- buffer_params.denoising_prefiltered_pass = write_denoising_passes;
-
- session->params.run_denoising = run_denoising;
- session->params.full_denoising = full_denoising;
- session->params.write_denoising_passes = write_denoising_passes;
- session->params.denoising.radius = get_int(crl, "denoising_radius");
- session->params.denoising.strength = get_float(crl, "denoising_strength");
- session->params.denoising.feature_strength = get_float(crl, "denoising_feature_strength");
- session->params.denoising.relative_pca = get_boolean(crl, "denoising_relative_pca");
-
- scene->film->denoising_data_pass = buffer_params.denoising_data_pass;
- scene->film->denoising_clean_pass = buffer_params.denoising_clean_pass;
- scene->film->denoising_prefiltered_pass = buffer_params.denoising_prefiltered_pass;
-
- scene->film->pass_alpha_threshold = b_view_layer.pass_alpha_threshold();
- scene->film->tag_passes_update(scene, passes);
- scene->film->tag_update(scene);
- scene->integrator->tag_update(scene);
-
- BL::RenderResult::views_iterator b_view_iter;
-
- int num_views = 0;
- for(b_rr.views.begin(b_view_iter); b_view_iter != b_rr.views.end(); ++b_view_iter) {
- num_views++;
- }
-
- int view_index = 0;
- for(b_rr.views.begin(b_view_iter); b_view_iter != b_rr.views.end(); ++b_view_iter, ++view_index) {
- b_rview_name = b_view_iter->name();
-
- /* set the current view */
- b_engine.active_view_set(b_rview_name.c_str());
-
- /* update scene */
- BL::Object b_camera_override(b_engine.camera_override());
- sync->sync_camera(b_render, b_camera_override, width, height, b_rview_name.c_str());
- sync->sync_data(b_render,
- b_depsgraph,
- b_v3d,
- b_camera_override,
- width, height,
- &python_thread_state);
- builtin_images_load();
-
- /* Attempt to free all data which is held by Blender side, since at this
- * point we knwo that we've got everything to render current view layer.
- */
- /* At the moment we only free if we are not doing multi-view (or if we are rendering the last view).
- * See T58142/D4239 for discussion.
- */
- if(view_index == num_views - 1) {
- free_blender_memory_if_possible();
- }
-
- /* Make sure all views have different noise patterns. - hardcoded value just to make it random */
- if(view_index != 0) {
- scene->integrator->seed += hash_int_2d(scene->integrator->seed, hash_int(view_index * 0xdeadbeef));
- scene->integrator->tag_update(scene);
- }
-
- /* Update number of samples per layer. */
- int samples = sync->get_layer_samples();
- bool bound_samples = sync->get_layer_bound_samples();
- int effective_layer_samples;
-
- if(samples != 0 && (!bound_samples || (samples < session_params.samples)))
- effective_layer_samples = samples;
- else
- effective_layer_samples = session_params.samples;
-
- /* Update tile manager if we're doing resumable render. */
- update_resumable_tile_manager(effective_layer_samples);
-
- /* Update session itself. */
- session->reset(buffer_params, effective_layer_samples);
-
- /* render */
- session->start();
- session->wait();
-
- if(!b_engine.is_preview() && background && print_render_stats) {
- RenderStats stats;
- session->collect_statistics(&stats);
- printf("Render statistics:\n%s\n", stats.full_report().c_str());
- }
-
- if(session->progress.get_cancel())
- break;
- }
-
- /* add metadata */
- stamp_view_layer_metadata(scene, b_rlay_name);
-
- /* free result without merging */
- end_render_result(b_engine, b_rr, true, true, false);
-
- double total_time, render_time;
- session->progress.get_time(total_time, render_time);
- VLOG(1) << "Total render time: " << total_time;
- VLOG(1) << "Render time (without synchronization): " << render_time;
-
- /* clear callback */
- session->write_render_tile_cb = function_null;
- session->update_render_tile_cb = function_null;
-
- /* TODO: find a way to clear this data for persistent data render */
+ b_depsgraph = b_depsgraph_;
+
+ /* set callback to write out render results */
+ session->write_render_tile_cb = function_bind(&BlenderSession::write_render_tile, this, _1);
+ session->update_render_tile_cb = function_bind(
+ &BlenderSession::update_render_tile, this, _1, _2);
+
+ /* get buffer parameters */
+ SessionParams session_params = BlenderSync::get_session_params(
+ b_engine, b_userpref, b_scene, background);
+ BufferParams buffer_params = BlenderSync::get_buffer_params(
+ b_render, b_v3d, b_rv3d, scene->camera, width, height);
+
+ /* render each layer */
+ BL::ViewLayer b_view_layer = b_depsgraph.view_layer_eval();
+
+ /* temporary render result to find needed passes and views */
+ BL::RenderResult b_rr = begin_render_result(
+ b_engine, 0, 0, 1, 1, b_view_layer.name().c_str(), NULL);
+ BL::RenderResult::layers_iterator b_single_rlay;
+ b_rr.layers.begin(b_single_rlay);
+ BL::RenderLayer b_rlay = *b_single_rlay;
+ b_rlay_name = b_view_layer.name();
+
+ /* add passes */
+ vector<Pass> passes = sync->sync_render_passes(b_rlay, b_view_layer);
+ buffer_params.passes = passes;
+
+ PointerRNA crl = RNA_pointer_get(&b_view_layer.ptr, "cycles");
+ bool full_denoising = get_boolean(crl, "use_denoising");
+ bool write_denoising_passes = get_boolean(crl, "denoising_store_passes");
+
+ bool run_denoising = full_denoising || write_denoising_passes;
+
+ session->tile_manager.schedule_denoising = run_denoising;
+ buffer_params.denoising_data_pass = run_denoising;
+ buffer_params.denoising_clean_pass = (scene->film->denoising_flags & DENOISING_CLEAN_ALL_PASSES);
+ buffer_params.denoising_prefiltered_pass = write_denoising_passes;
+
+ session->params.run_denoising = run_denoising;
+ session->params.full_denoising = full_denoising;
+ session->params.write_denoising_passes = write_denoising_passes;
+ session->params.denoising.radius = get_int(crl, "denoising_radius");
+ session->params.denoising.strength = get_float(crl, "denoising_strength");
+ session->params.denoising.feature_strength = get_float(crl, "denoising_feature_strength");
+ session->params.denoising.relative_pca = get_boolean(crl, "denoising_relative_pca");
+
+ scene->film->denoising_data_pass = buffer_params.denoising_data_pass;
+ scene->film->denoising_clean_pass = buffer_params.denoising_clean_pass;
+ scene->film->denoising_prefiltered_pass = buffer_params.denoising_prefiltered_pass;
+
+ scene->film->pass_alpha_threshold = b_view_layer.pass_alpha_threshold();
+ scene->film->tag_passes_update(scene, passes);
+ scene->film->tag_update(scene);
+ scene->integrator->tag_update(scene);
+
+ BL::RenderResult::views_iterator b_view_iter;
+
+ int num_views = 0;
+ for (b_rr.views.begin(b_view_iter); b_view_iter != b_rr.views.end(); ++b_view_iter) {
+ num_views++;
+ }
+
+ int view_index = 0;
+ for (b_rr.views.begin(b_view_iter); b_view_iter != b_rr.views.end();
+ ++b_view_iter, ++view_index) {
+ b_rview_name = b_view_iter->name();
+
+ /* set the current view */
+ b_engine.active_view_set(b_rview_name.c_str());
+
+ /* update scene */
+ BL::Object b_camera_override(b_engine.camera_override());
+ sync->sync_camera(b_render, b_camera_override, width, height, b_rview_name.c_str());
+ sync->sync_data(
+ b_render, b_depsgraph, b_v3d, b_camera_override, width, height, &python_thread_state);
+ builtin_images_load();
+
+ /* Attempt to free all data which is held by Blender side, since at this
+ * point we knwo that we've got everything to render current view layer.
+ */
+ /* At the moment we only free if we are not doing multi-view (or if we are rendering the last view).
+ * See T58142/D4239 for discussion.
+ */
+ if (view_index == num_views - 1) {
+ free_blender_memory_if_possible();
+ }
+
+ /* Make sure all views have different noise patterns. - hardcoded value just to make it random */
+ if (view_index != 0) {
+ scene->integrator->seed += hash_int_2d(scene->integrator->seed,
+ hash_int(view_index * 0xdeadbeef));
+ scene->integrator->tag_update(scene);
+ }
+
+ /* Update number of samples per layer. */
+ int samples = sync->get_layer_samples();
+ bool bound_samples = sync->get_layer_bound_samples();
+ int effective_layer_samples;
+
+ if (samples != 0 && (!bound_samples || (samples < session_params.samples)))
+ effective_layer_samples = samples;
+ else
+ effective_layer_samples = session_params.samples;
+
+ /* Update tile manager if we're doing resumable render. */
+ update_resumable_tile_manager(effective_layer_samples);
+
+ /* Update session itself. */
+ session->reset(buffer_params, effective_layer_samples);
+
+ /* render */
+ session->start();
+ session->wait();
+
+ if (!b_engine.is_preview() && background && print_render_stats) {
+ RenderStats stats;
+ session->collect_statistics(&stats);
+ printf("Render statistics:\n%s\n", stats.full_report().c_str());
+ }
+
+ if (session->progress.get_cancel())
+ break;
+ }
+
+ /* add metadata */
+ stamp_view_layer_metadata(scene, b_rlay_name);
+
+ /* free result without merging */
+ end_render_result(b_engine, b_rr, true, true, false);
+
+ double total_time, render_time;
+ session->progress.get_time(total_time, render_time);
+ VLOG(1) << "Total render time: " << total_time;
+ VLOG(1) << "Render time (without synchronization): " << render_time;
+
+ /* clear callback */
+ session->write_render_tile_cb = function_null;
+ session->update_render_tile_cb = function_null;
+
+ /* TODO: find a way to clear this data for persistent data render */
#if 0
- /* free all memory used (host and device), so we wouldn't leave render
- * engine with extra memory allocated
- */
+ /* free all memory used (host and device), so we wouldn't leave render
+ * engine with extra memory allocated
+ */
- session->device_free();
+ session->device_free();
- delete sync;
- sync = NULL;
+ delete sync;
+ sync = NULL;
#endif
}
-static void populate_bake_data(BakeData *data, const
- int object_id,
- BL::BakePixel& pixel_array,
+static void populate_bake_data(BakeData *data,
+ const int object_id,
+ BL::BakePixel &pixel_array,
const int num_pixels)
{
- BL::BakePixel bp = pixel_array;
-
- int i;
- for(i = 0; i < num_pixels; i++) {
- if(bp.object_id() == object_id) {
- data->set(i, bp.primitive_id(), bp.uv(), bp.du_dx(), bp.du_dy(), bp.dv_dx(), bp.dv_dy());
- } else {
- data->set_null(i);
- }
- bp = bp.next();
- }
+ BL::BakePixel bp = pixel_array;
+
+ int i;
+ for (i = 0; i < num_pixels; i++) {
+ if (bp.object_id() == object_id) {
+ data->set(i, bp.primitive_id(), bp.uv(), bp.du_dx(), bp.du_dy(), bp.dv_dx(), bp.dv_dy());
+ }
+ else {
+ data->set_null(i);
+ }
+ bp = bp.next();
+ }
}
static int bake_pass_filter_get(const int pass_filter)
{
- int flag = BAKE_FILTER_NONE;
-
- if((pass_filter & BL::BakeSettings::pass_filter_DIRECT) != 0)
- flag |= BAKE_FILTER_DIRECT;
- if((pass_filter & BL::BakeSettings::pass_filter_INDIRECT) != 0)
- flag |= BAKE_FILTER_INDIRECT;
- if((pass_filter & BL::BakeSettings::pass_filter_COLOR) != 0)
- flag |= BAKE_FILTER_COLOR;
-
- if((pass_filter & BL::BakeSettings::pass_filter_DIFFUSE) != 0)
- flag |= BAKE_FILTER_DIFFUSE;
- if((pass_filter & BL::BakeSettings::pass_filter_GLOSSY) != 0)
- flag |= BAKE_FILTER_GLOSSY;
- if((pass_filter & BL::BakeSettings::pass_filter_TRANSMISSION) != 0)
- flag |= BAKE_FILTER_TRANSMISSION;
- if((pass_filter & BL::BakeSettings::pass_filter_SUBSURFACE) != 0)
- flag |= BAKE_FILTER_SUBSURFACE;
-
- if((pass_filter & BL::BakeSettings::pass_filter_EMIT) != 0)
- flag |= BAKE_FILTER_EMISSION;
- if((pass_filter & BL::BakeSettings::pass_filter_AO) != 0)
- flag |= BAKE_FILTER_AO;
-
- return flag;
+ int flag = BAKE_FILTER_NONE;
+
+ if ((pass_filter & BL::BakeSettings::pass_filter_DIRECT) != 0)
+ flag |= BAKE_FILTER_DIRECT;
+ if ((pass_filter & BL::BakeSettings::pass_filter_INDIRECT) != 0)
+ flag |= BAKE_FILTER_INDIRECT;
+ if ((pass_filter & BL::BakeSettings::pass_filter_COLOR) != 0)
+ flag |= BAKE_FILTER_COLOR;
+
+ if ((pass_filter & BL::BakeSettings::pass_filter_DIFFUSE) != 0)
+ flag |= BAKE_FILTER_DIFFUSE;
+ if ((pass_filter & BL::BakeSettings::pass_filter_GLOSSY) != 0)
+ flag |= BAKE_FILTER_GLOSSY;
+ if ((pass_filter & BL::BakeSettings::pass_filter_TRANSMISSION) != 0)
+ flag |= BAKE_FILTER_TRANSMISSION;
+ if ((pass_filter & BL::BakeSettings::pass_filter_SUBSURFACE) != 0)
+ flag |= BAKE_FILTER_SUBSURFACE;
+
+ if ((pass_filter & BL::BakeSettings::pass_filter_EMIT) != 0)
+ flag |= BAKE_FILTER_EMISSION;
+ if ((pass_filter & BL::BakeSettings::pass_filter_AO) != 0)
+ flag |= BAKE_FILTER_AO;
+
+ return flag;
}
-void BlenderSession::bake(BL::Depsgraph& b_depsgraph_,
- BL::Object& b_object,
- const string& pass_type,
+void BlenderSession::bake(BL::Depsgraph &b_depsgraph_,
+ BL::Object &b_object,
+ const string &pass_type,
const int pass_filter,
const int object_id,
- BL::BakePixel& pixel_array,
+ BL::BakePixel &pixel_array,
const size_t num_pixels,
const int /*depth*/,
float result[])
{
- b_depsgraph = b_depsgraph_;
-
- ShaderEvalType shader_type = get_shader_type(pass_type);
-
- /* Set baking flag in advance, so kernel loading can check if we need
- * any baking capabilities.
- */
- scene->bake_manager->set_baking(true);
-
- /* ensure kernels are loaded before we do any scene updates */
- session->load_kernels();
-
- if(shader_type == SHADER_EVAL_UV) {
- /* force UV to be available */
- Pass::add(PASS_UV, scene->film->passes);
- }
-
- int bake_pass_filter = bake_pass_filter_get(pass_filter);
- bake_pass_filter = BakeManager::shader_type_to_pass_filter(shader_type, bake_pass_filter);
-
- /* force use_light_pass to be true if we bake more than just colors */
- if(bake_pass_filter & ~BAKE_FILTER_COLOR) {
- Pass::add(PASS_LIGHT, scene->film->passes);
- }
-
- /* create device and update scene */
- scene->film->tag_update(scene);
- scene->integrator->tag_update(scene);
-
- if(!session->progress.get_cancel()) {
- /* update scene */
- BL::Object b_camera_override(b_engine.camera_override());
- sync->sync_camera(b_render, b_camera_override, width, height, "");
- sync->sync_data(b_render,
- b_depsgraph,
- b_v3d,
- b_camera_override,
- width, height,
- &python_thread_state);
- builtin_images_load();
- }
-
- BakeData *bake_data = NULL;
-
- if(!session->progress.get_cancel()) {
- /* get buffer parameters */
- SessionParams session_params = BlenderSync::get_session_params(b_engine, b_userpref, b_scene, background);
- BufferParams buffer_params = BlenderSync::get_buffer_params(b_render, b_v3d, b_rv3d, scene->camera, width, height);
-
- scene->bake_manager->set_shader_limit((size_t)b_engine.tile_x(), (size_t)b_engine.tile_y());
-
- /* set number of samples */
- session->tile_manager.set_samples(session_params.samples);
- session->reset(buffer_params, session_params.samples);
- session->update_scene();
-
- /* find object index. todo: is arbitrary - copied from mesh_displace.cpp */
- size_t object_index = OBJECT_NONE;
- int tri_offset = 0;
-
- for(size_t i = 0; i < scene->objects.size(); i++) {
- if(strcmp(scene->objects[i]->name.c_str(), b_object.name().c_str()) == 0) {
- object_index = i;
- tri_offset = scene->objects[i]->mesh->tri_offset;
- break;
- }
- }
-
- /* Object might have been disabled for rendering or excluded in some
- * other way, in that case Blender will report a warning afterwards. */
- if (object_index != OBJECT_NONE) {
- int object = object_index;
-
- bake_data = scene->bake_manager->init(object, tri_offset, num_pixels);
- populate_bake_data(bake_data, object_id, pixel_array, num_pixels);
- }
-
- /* set number of samples */
- session->tile_manager.set_samples(session_params.samples);
- session->reset(buffer_params, session_params.samples);
- session->update_scene();
-
- session->progress.set_update_callback(function_bind(&BlenderSession::update_bake_progress, this));
- }
-
- /* Perform bake. Check cancel to avoid crash with incomplete scene data. */
- if(!session->progress.get_cancel() && bake_data) {
- scene->bake_manager->bake(scene->device, &scene->dscene, scene, session->progress, shader_type, bake_pass_filter, bake_data, result);
- }
-
- /* free all memory used (host and device), so we wouldn't leave render
- * engine with extra memory allocated
- */
-
- session->device_free();
-
- delete sync;
- sync = NULL;
+ b_depsgraph = b_depsgraph_;
+
+ ShaderEvalType shader_type = get_shader_type(pass_type);
+
+ /* Set baking flag in advance, so kernel loading can check if we need
+ * any baking capabilities.
+ */
+ scene->bake_manager->set_baking(true);
+
+ /* ensure kernels are loaded before we do any scene updates */
+ session->load_kernels();
+
+ if (shader_type == SHADER_EVAL_UV) {
+ /* force UV to be available */
+ Pass::add(PASS_UV, scene->film->passes);
+ }
+
+ int bake_pass_filter = bake_pass_filter_get(pass_filter);
+ bake_pass_filter = BakeManager::shader_type_to_pass_filter(shader_type, bake_pass_filter);
+
+ /* force use_light_pass to be true if we bake more than just colors */
+ if (bake_pass_filter & ~BAKE_FILTER_COLOR) {
+ Pass::add(PASS_LIGHT, scene->film->passes);
+ }
+
+ /* create device and update scene */
+ scene->film->tag_update(scene);
+ scene->integrator->tag_update(scene);
+
+ if (!session->progress.get_cancel()) {
+ /* update scene */
+ BL::Object b_camera_override(b_engine.camera_override());
+ sync->sync_camera(b_render, b_camera_override, width, height, "");
+ sync->sync_data(
+ b_render, b_depsgraph, b_v3d, b_camera_override, width, height, &python_thread_state);
+ builtin_images_load();
+ }
+
+ BakeData *bake_data = NULL;
+
+ if (!session->progress.get_cancel()) {
+ /* get buffer parameters */
+ SessionParams session_params = BlenderSync::get_session_params(
+ b_engine, b_userpref, b_scene, background);
+ BufferParams buffer_params = BlenderSync::get_buffer_params(
+ b_render, b_v3d, b_rv3d, scene->camera, width, height);
+
+ scene->bake_manager->set_shader_limit((size_t)b_engine.tile_x(), (size_t)b_engine.tile_y());
+
+ /* set number of samples */
+ session->tile_manager.set_samples(session_params.samples);
+ session->reset(buffer_params, session_params.samples);
+ session->update_scene();
+
+ /* find object index. todo: is arbitrary - copied from mesh_displace.cpp */
+ size_t object_index = OBJECT_NONE;
+ int tri_offset = 0;
+
+ for (size_t i = 0; i < scene->objects.size(); i++) {
+ if (strcmp(scene->objects[i]->name.c_str(), b_object.name().c_str()) == 0) {
+ object_index = i;
+ tri_offset = scene->objects[i]->mesh->tri_offset;
+ break;
+ }
+ }
+
+ /* Object might have been disabled for rendering or excluded in some
+ * other way, in that case Blender will report a warning afterwards. */
+ if (object_index != OBJECT_NONE) {
+ int object = object_index;
+
+ bake_data = scene->bake_manager->init(object, tri_offset, num_pixels);
+ populate_bake_data(bake_data, object_id, pixel_array, num_pixels);
+ }
+
+ /* set number of samples */
+ session->tile_manager.set_samples(session_params.samples);
+ session->reset(buffer_params, session_params.samples);
+ session->update_scene();
+
+ session->progress.set_update_callback(
+ function_bind(&BlenderSession::update_bake_progress, this));
+ }
+
+ /* Perform bake. Check cancel to avoid crash with incomplete scene data. */
+ if (!session->progress.get_cancel() && bake_data) {
+ scene->bake_manager->bake(scene->device,
+ &scene->dscene,
+ scene,
+ session->progress,
+ shader_type,
+ bake_pass_filter,
+ bake_data,
+ result);
+ }
+
+ /* free all memory used (host and device), so we wouldn't leave render
+ * engine with extra memory allocated
+ */
+
+ session->device_free();
+
+ delete sync;
+ sync = NULL;
}
-void BlenderSession::do_write_update_render_result(BL::RenderResult& b_rr,
- BL::RenderLayer& b_rlay,
- RenderTile& rtile,
+void BlenderSession::do_write_update_render_result(BL::RenderResult &b_rr,
+ BL::RenderLayer &b_rlay,
+ RenderTile &rtile,
bool do_update_only)
{
- RenderBuffers *buffers = rtile.buffers;
-
- /* copy data from device */
- if(!buffers->copy_from_device())
- return;
-
- float exposure = scene->film->exposure;
-
- vector<float> pixels(rtile.w*rtile.h*4);
-
- /* Adjust absolute sample number to the range. */
- int sample = rtile.sample;
- const int range_start_sample = session->tile_manager.range_start_sample;
- if(range_start_sample != -1) {
- sample -= range_start_sample;
- }
-
- if(!do_update_only) {
- /* copy each pass */
- BL::RenderLayer::passes_iterator b_iter;
-
- for(b_rlay.passes.begin(b_iter); b_iter != b_rlay.passes.end(); ++b_iter) {
- BL::RenderPass b_pass(*b_iter);
-
- /* find matching pass type */
- PassType pass_type = BlenderSync::get_pass_type(b_pass);
- int components = b_pass.channels();
-
- bool read = false;
- if(pass_type != PASS_NONE) {
- /* copy pixels */
- read = buffers->get_pass_rect(pass_type, exposure, sample, components, &pixels[0], b_pass.name());
- }
- else {
- int denoising_offset = BlenderSync::get_denoising_pass(b_pass);
- if(denoising_offset >= 0) {
- read = buffers->get_denoising_pass_rect(denoising_offset, 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_name("Combined", b_rview_name.c_str()));
- if(buffers->get_pass_rect(PASS_COMBINED, exposure, sample, 4, &pixels[0], "Combined"))
- b_combined_pass.rect(&pixels[0]);
- }
-
- /* tag result as updated */
- b_engine.update_result(b_rr);
+ RenderBuffers *buffers = rtile.buffers;
+
+ /* copy data from device */
+ if (!buffers->copy_from_device())
+ return;
+
+ float exposure = scene->film->exposure;
+
+ vector<float> pixels(rtile.w * rtile.h * 4);
+
+ /* Adjust absolute sample number to the range. */
+ int sample = rtile.sample;
+ const int range_start_sample = session->tile_manager.range_start_sample;
+ if (range_start_sample != -1) {
+ sample -= range_start_sample;
+ }
+
+ if (!do_update_only) {
+ /* copy each pass */
+ BL::RenderLayer::passes_iterator b_iter;
+
+ for (b_rlay.passes.begin(b_iter); b_iter != b_rlay.passes.end(); ++b_iter) {
+ BL::RenderPass b_pass(*b_iter);
+
+ /* find matching pass type */
+ PassType pass_type = BlenderSync::get_pass_type(b_pass);
+ int components = b_pass.channels();
+
+ bool read = false;
+ if (pass_type != PASS_NONE) {
+ /* copy pixels */
+ read = buffers->get_pass_rect(
+ pass_type, exposure, sample, components, &pixels[0], b_pass.name());
+ }
+ else {
+ int denoising_offset = BlenderSync::get_denoising_pass(b_pass);
+ if (denoising_offset >= 0) {
+ read = buffers->get_denoising_pass_rect(
+ denoising_offset, 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_name("Combined", b_rview_name.c_str()));
+ if (buffers->get_pass_rect(PASS_COMBINED, exposure, sample, 4, &pixels[0], "Combined"))
+ b_combined_pass.rect(&pixels[0]);
+ }
+
+ /* tag result as updated */
+ b_engine.update_result(b_rr);
}
-void BlenderSession::write_render_result(BL::RenderResult& b_rr,
- BL::RenderLayer& b_rlay,
- RenderTile& rtile)
+void BlenderSession::write_render_result(BL::RenderResult &b_rr,
+ BL::RenderLayer &b_rlay,
+ RenderTile &rtile)
{
- do_write_update_render_result(b_rr, b_rlay, rtile, false);
+ do_write_update_render_result(b_rr, b_rlay, rtile, false);
}
-void BlenderSession::update_render_result(BL::RenderResult& b_rr,
- BL::RenderLayer& b_rlay,
- RenderTile& rtile)
+void BlenderSession::update_render_result(BL::RenderResult &b_rr,
+ BL::RenderLayer &b_rlay,
+ RenderTile &rtile)
{
- do_write_update_render_result(b_rr, b_rlay, rtile, true);
+ do_write_update_render_result(b_rr, b_rlay, rtile, true);
}
-void BlenderSession::synchronize(BL::Depsgraph& b_depsgraph_)
+void BlenderSession::synchronize(BL::Depsgraph &b_depsgraph_)
{
- /* only used for viewport render */
- if(!b_v3d)
- return;
-
- /* on session/scene parameter changes, we recreate session entirely */
- SessionParams session_params = BlenderSync::get_session_params(b_engine, b_userpref, b_scene, background);
- SceneParams scene_params = BlenderSync::get_scene_params(b_scene, background);
- bool session_pause = BlenderSync::get_session_pause(b_scene, background);
-
- if(session->params.modified(session_params) ||
- scene->params.modified(scene_params))
- {
- free_session();
- create_session();
- return;
- }
-
- /* increase samples, but never decrease */
- session->set_samples(session_params.samples);
- session->set_pause(session_pause);
-
- /* copy recalc flags, outside of mutex so we can decide to do the real
- * synchronization at a later time to not block on running updates */
- sync->sync_recalc(b_depsgraph_);
-
- /* don't do synchronization if on pause */
- if(session_pause) {
- tag_update();
- return;
- }
-
- /* try to acquire mutex. if we don't want to or can't, come back later */
- if(!session->ready_to_reset() || !session->scene->mutex.try_lock()) {
- tag_update();
- return;
- }
-
- /* data and camera synchronize */
- b_depsgraph = b_depsgraph_;
-
- BL::Object b_camera_override(b_engine.camera_override());
- sync->sync_data(b_render,
- b_depsgraph,
- b_v3d,
- b_camera_override,
- width, height,
- &python_thread_state);
-
- if(b_rv3d)
- sync->sync_view(b_v3d, b_rv3d, width, height);
- else
- sync->sync_camera(b_render, b_camera_override, width, height, "");
-
- builtin_images_load();
-
- /* unlock */
- session->scene->mutex.unlock();
-
- /* reset if needed */
- if(scene->need_reset()) {
- BufferParams buffer_params = BlenderSync::get_buffer_params(b_render, b_v3d, b_rv3d, scene->camera, width, height);
- session->reset(buffer_params, session_params.samples);
-
- /* reset time */
- start_resize_time = 0.0;
- }
-
- /* Start rendering thread, if it's not running already. Do this
- * after all scene data has been synced at least once. */
- session->start();
+ /* only used for viewport render */
+ if (!b_v3d)
+ return;
+
+ /* on session/scene parameter changes, we recreate session entirely */
+ SessionParams session_params = BlenderSync::get_session_params(
+ b_engine, b_userpref, b_scene, background);
+ SceneParams scene_params = BlenderSync::get_scene_params(b_scene, background);
+ bool session_pause = BlenderSync::get_session_pause(b_scene, background);
+
+ if (session->params.modified(session_params) || scene->params.modified(scene_params)) {
+ free_session();
+ create_session();
+ return;
+ }
+
+ /* increase samples, but never decrease */
+ session->set_samples(session_params.samples);
+ session->set_pause(session_pause);
+
+ /* copy recalc flags, outside of mutex so we can decide to do the real
+ * synchronization at a later time to not block on running updates */
+ sync->sync_recalc(b_depsgraph_);
+
+ /* don't do synchronization if on pause */
+ if (session_pause) {
+ tag_update();
+ return;
+ }
+
+ /* try to acquire mutex. if we don't want to or can't, come back later */
+ if (!session->ready_to_reset() || !session->scene->mutex.try_lock()) {
+ tag_update();
+ return;
+ }
+
+ /* data and camera synchronize */
+ b_depsgraph = b_depsgraph_;
+
+ BL::Object b_camera_override(b_engine.camera_override());
+ sync->sync_data(
+ b_render, b_depsgraph, b_v3d, b_camera_override, width, height, &python_thread_state);
+
+ if (b_rv3d)
+ sync->sync_view(b_v3d, b_rv3d, width, height);
+ else
+ sync->sync_camera(b_render, b_camera_override, width, height, "");
+
+ builtin_images_load();
+
+ /* unlock */
+ session->scene->mutex.unlock();
+
+ /* reset if needed */
+ if (scene->need_reset()) {
+ BufferParams buffer_params = BlenderSync::get_buffer_params(
+ b_render, b_v3d, b_rv3d, scene->camera, width, height);
+ session->reset(buffer_params, session_params.samples);
+
+ /* reset time */
+ start_resize_time = 0.0;
+ }
+
+ /* Start rendering thread, if it's not running already. Do this
+ * after all scene data has been synced at least once. */
+ session->start();
}
bool BlenderSession::draw(int w, int h)
{
- /* pause in redraw in case update is not being called due to final render */
- session->set_pause(BlenderSync::get_session_pause(b_scene, background));
-
- /* before drawing, we verify camera and viewport size changes, because
- * we do not get update callbacks for those, we must detect them here */
- if(session->ready_to_reset()) {
- bool reset = false;
-
- /* if dimensions changed, reset */
- if(width != w || height != h) {
- if(start_resize_time == 0.0) {
- /* don't react immediately to resizes to avoid flickery resizing
- * of the viewport, and some window managers changing the window
- * size temporarily on unminimize */
- start_resize_time = time_dt();
- tag_redraw();
- }
- else if(time_dt() - start_resize_time < 0.2) {
- tag_redraw();
- }
- else {
- width = w;
- height = h;
- reset = true;
- }
- }
-
- /* try to acquire mutex. if we can't, come back later */
- if(!session->scene->mutex.try_lock()) {
- tag_update();
- }
- else {
- /* update camera from 3d view */
-
- sync->sync_view(b_v3d, b_rv3d, width, height);
-
- if(scene->camera->need_update)
- reset = true;
-
- session->scene->mutex.unlock();
- }
-
- /* reset if requested */
- if(reset) {
- SessionParams session_params = BlenderSync::get_session_params(b_engine, b_userpref, b_scene, background);
- BufferParams buffer_params = BlenderSync::get_buffer_params(b_render, b_v3d, b_rv3d, scene->camera, width, height);
- bool session_pause = BlenderSync::get_session_pause(b_scene, background);
-
- if(session_pause == false) {
- session->reset(buffer_params, session_params.samples);
- start_resize_time = 0.0;
- }
- }
- }
- else {
- tag_update();
- }
-
- /* update status and progress for 3d view draw */
- update_status_progress();
-
- /* draw */
- BufferParams buffer_params = BlenderSync::get_buffer_params(b_render, b_v3d, b_rv3d, scene->camera, width, height);
- DeviceDrawParams draw_params;
-
- if(session->params.display_buffer_linear) {
- draw_params.bind_display_space_shader_cb = function_bind(&BL::RenderEngine::bind_display_space_shader, &b_engine, b_scene);
- draw_params.unbind_display_space_shader_cb = function_bind(&BL::RenderEngine::unbind_display_space_shader, &b_engine);
- }
-
- return !session->draw(buffer_params, draw_params);
+ /* pause in redraw in case update is not being called due to final render */
+ session->set_pause(BlenderSync::get_session_pause(b_scene, background));
+
+ /* before drawing, we verify camera and viewport size changes, because
+ * we do not get update callbacks for those, we must detect them here */
+ if (session->ready_to_reset()) {
+ bool reset = false;
+
+ /* if dimensions changed, reset */
+ if (width != w || height != h) {
+ if (start_resize_time == 0.0) {
+ /* don't react immediately to resizes to avoid flickery resizing
+ * of the viewport, and some window managers changing the window
+ * size temporarily on unminimize */
+ start_resize_time = time_dt();
+ tag_redraw();
+ }
+ else if (time_dt() - start_resize_time < 0.2) {
+ tag_redraw();
+ }
+ else {
+ width = w;
+ height = h;
+ reset = true;
+ }
+ }
+
+ /* try to acquire mutex. if we can't, come back later */
+ if (!session->scene->mutex.try_lock()) {
+ tag_update();
+ }
+ else {
+ /* update camera from 3d view */
+
+ sync->sync_view(b_v3d, b_rv3d, width, height);
+
+ if (scene->camera->need_update)
+ reset = true;
+
+ session->scene->mutex.unlock();
+ }
+
+ /* reset if requested */
+ if (reset) {
+ SessionParams session_params = BlenderSync::get_session_params(
+ b_engine, b_userpref, b_scene, background);
+ BufferParams buffer_params = BlenderSync::get_buffer_params(
+ b_render, b_v3d, b_rv3d, scene->camera, width, height);
+ bool session_pause = BlenderSync::get_session_pause(b_scene, background);
+
+ if (session_pause == false) {
+ session->reset(buffer_params, session_params.samples);
+ start_resize_time = 0.0;
+ }
+ }
+ }
+ else {
+ tag_update();
+ }
+
+ /* update status and progress for 3d view draw */
+ update_status_progress();
+
+ /* draw */
+ BufferParams buffer_params = BlenderSync::get_buffer_params(
+ b_render, b_v3d, b_rv3d, scene->camera, width, height);
+ DeviceDrawParams draw_params;
+
+ if (session->params.display_buffer_linear) {
+ draw_params.bind_display_space_shader_cb = function_bind(
+ &BL::RenderEngine::bind_display_space_shader, &b_engine, b_scene);
+ draw_params.unbind_display_space_shader_cb = function_bind(
+ &BL::RenderEngine::unbind_display_space_shader, &b_engine);
+ }
+
+ return !session->draw(buffer_params, draw_params);
}
-void BlenderSession::get_status(string& status, string& substatus)
+void BlenderSession::get_status(string &status, string &substatus)
{
- session->progress.get_status(status, substatus);
+ session->progress.get_status(status, substatus);
}
-void BlenderSession::get_kernel_status(string& kernel_status)
+void BlenderSession::get_kernel_status(string &kernel_status)
{
- session->progress.get_kernel_status(kernel_status);
+ session->progress.get_kernel_status(kernel_status);
}
-void BlenderSession::get_progress(float& progress, double& total_time, double& render_time)
+void BlenderSession::get_progress(float &progress, double &total_time, double &render_time)
{
- session->progress.get_time(total_time, render_time);
- progress = session->progress.get_progress();
+ session->progress.get_time(total_time, render_time);
+ progress = session->progress.get_progress();
}
void BlenderSession::update_bake_progress()
{
- float progress = session->progress.get_progress();
+ float progress = session->progress.get_progress();
- if(progress != last_progress) {
- b_engine.update_progress(progress);
- last_progress = progress;
- }
+ if (progress != last_progress) {
+ b_engine.update_progress(progress);
+ last_progress = progress;
+ }
}
void BlenderSession::update_status_progress()
{
- string timestatus, status, substatus, kernel_status;
- string scene_status = "";
- float progress;
- double total_time, remaining_time = 0, render_time;
- float mem_used = (float)session->stats.mem_used / 1024.0f / 1024.0f;
- float mem_peak = (float)session->stats.mem_peak / 1024.0f / 1024.0f;
-
- get_status(status, substatus);
- get_kernel_status(kernel_status);
- get_progress(progress, total_time, render_time);
-
- if(progress > 0)
- remaining_time = (1.0 - (double)progress) * (render_time / (double)progress);
-
- if(background) {
- scene_status += " | " + scene->name;
- if(b_rlay_name != "")
- scene_status += ", " + b_rlay_name;
-
- if(b_rview_name != "")
- scene_status += ", " + b_rview_name;
-
- if(remaining_time > 0) {
- timestatus += "Remaining:" + time_human_readable_from_seconds(remaining_time) + " | ";
- }
-
- timestatus += string_printf("Mem:%.2fM, Peak:%.2fM", (double)mem_used, (double)mem_peak);
-
- if(status.size() > 0)
- status = " | " + status;
- if(substatus.size() > 0)
- status += " | " + substatus;
- if(kernel_status.size() > 0)
- status += " | " + kernel_status;
- }
-
- double current_time = time_dt();
- /* When rendering in a window, redraw the status at least once per second to keep the elapsed and remaining time up-to-date.
- * For headless rendering, only report when something significant changes to keep the console output readable. */
- if(status != last_status || (!headless && (current_time - last_status_time) > 1.0)) {
- b_engine.update_stats("", (timestatus + scene_status + status).c_str());
- b_engine.update_memory_stats(mem_used, mem_peak);
- last_status = status;
- last_status_time = current_time;
- }
- if(progress != last_progress) {
- b_engine.update_progress(progress);
- last_progress = progress;
- }
-
- if(session->progress.get_error()) {
- string error = session->progress.get_error_message();
- if(error != last_error) {
- /* TODO(sergey): Currently C++ RNA API doesn't let us to
- * use mnemonic name for the variable. Would be nice to
- * have this figured out.
- *
- * For until then, 1 << 5 means RPT_ERROR.
- */
- b_engine.report(1 << 5, error.c_str());
- b_engine.error_set(error.c_str());
- last_error = error;
- }
- }
+ string timestatus, status, substatus, kernel_status;
+ string scene_status = "";
+ float progress;
+ double total_time, remaining_time = 0, render_time;
+ float mem_used = (float)session->stats.mem_used / 1024.0f / 1024.0f;
+ float mem_peak = (float)session->stats.mem_peak / 1024.0f / 1024.0f;
+
+ get_status(status, substatus);
+ get_kernel_status(kernel_status);
+ get_progress(progress, total_time, render_time);
+
+ if (progress > 0)
+ remaining_time = (1.0 - (double)progress) * (render_time / (double)progress);
+
+ if (background) {
+ scene_status += " | " + scene->name;
+ if (b_rlay_name != "")
+ scene_status += ", " + b_rlay_name;
+
+ if (b_rview_name != "")
+ scene_status += ", " + b_rview_name;
+
+ if (remaining_time > 0) {
+ timestatus += "Remaining:" + time_human_readable_from_seconds(remaining_time) + " | ";
+ }
+
+ timestatus += string_printf("Mem:%.2fM, Peak:%.2fM", (double)mem_used, (double)mem_peak);
+
+ if (status.size() > 0)
+ status = " | " + status;
+ if (substatus.size() > 0)
+ status += " | " + substatus;
+ if (kernel_status.size() > 0)
+ status += " | " + kernel_status;
+ }
+
+ double current_time = time_dt();
+ /* When rendering in a window, redraw the status at least once per second to keep the elapsed and remaining time up-to-date.
+ * For headless rendering, only report when something significant changes to keep the console output readable. */
+ if (status != last_status || (!headless && (current_time - last_status_time) > 1.0)) {
+ b_engine.update_stats("", (timestatus + scene_status + status).c_str());
+ b_engine.update_memory_stats(mem_used, mem_peak);
+ last_status = status;
+ last_status_time = current_time;
+ }
+ if (progress != last_progress) {
+ b_engine.update_progress(progress);
+ last_progress = progress;
+ }
+
+ if (session->progress.get_error()) {
+ string error = session->progress.get_error_message();
+ if (error != last_error) {
+ /* TODO(sergey): Currently C++ RNA API doesn't let us to
+ * use mnemonic name for the variable. Would be nice to
+ * have this figured out.
+ *
+ * For until then, 1 << 5 means RPT_ERROR.
+ */
+ b_engine.report(1 << 5, error.c_str());
+ b_engine.error_set(error.c_str());
+ last_error = error;
+ }
+ }
}
void BlenderSession::tag_update()
{
- /* tell blender that we want to get another update callback */
- b_engine.tag_update();
+ /* tell blender that we want to get another update callback */
+ b_engine.tag_update();
}
void BlenderSession::tag_redraw()
{
- if(background) {
- /* update stats and progress, only for background here because
- * in 3d view we do it in draw for thread safety reasons */
- update_status_progress();
-
- /* offline render, redraw if timeout passed */
- if(time_dt() - last_redraw_time > 1.0) {
- b_engine.tag_redraw();
- last_redraw_time = time_dt();
- }
- }
- else {
- /* tell blender that we want to redraw */
- b_engine.tag_redraw();
- }
+ if (background) {
+ /* update stats and progress, only for background here because
+ * in 3d view we do it in draw for thread safety reasons */
+ update_status_progress();
+
+ /* offline render, redraw if timeout passed */
+ if (time_dt() - last_redraw_time > 1.0) {
+ b_engine.tag_redraw();
+ last_redraw_time = time_dt();
+ }
+ }
+ else {
+ /* tell blender that we want to redraw */
+ b_engine.tag_redraw();
+ }
}
void BlenderSession::test_cancel()
{
- /* test if we need to cancel rendering */
- if(background)
- if(b_engine.test_break())
- session->progress.set_cancel("Cancelled");
+ /* test if we need to cancel rendering */
+ if (background)
+ if (b_engine.test_break())
+ session->progress.set_cancel("Cancelled");
}
/* builtin image file name is actually an image datablock name with
@@ -1107,89 +1126,88 @@ void BlenderSession::test_cancel()
*/
int BlenderSession::builtin_image_frame(const string &builtin_name)
{
- int last = builtin_name.find_last_of('@');
- return atoi(builtin_name.substr(last + 1, builtin_name.size() - last - 1).c_str());
+ int last = builtin_name.find_last_of('@');
+ return atoi(builtin_name.substr(last + 1, builtin_name.size() - last - 1).c_str());
}
void BlenderSession::builtin_image_info(const string &builtin_name,
void *builtin_data,
- ImageMetaData& metadata)
+ ImageMetaData &metadata)
{
- /* empty image */
- metadata.width = 1;
- metadata.height = 1;
-
- if(!builtin_data)
- return;
-
- /* recover ID pointer */
- PointerRNA ptr;
- RNA_id_pointer_create((ID*)builtin_data, &ptr);
- BL::ID b_id(ptr);
-
- if(b_id.is_a(&RNA_Image)) {
- /* image data */
- BL::Image b_image(b_id);
-
- metadata.builtin_free_cache = !b_image.has_data();
- metadata.is_float = b_image.is_float();
- metadata.width = b_image.size()[0];
- metadata.height = b_image.size()[1];
- metadata.depth = 1;
- metadata.channels = b_image.channels();
- }
- else if(b_id.is_a(&RNA_Object)) {
- /* smoke volume data */
- BL::Object b_ob(b_id);
- BL::SmokeDomainSettings b_domain = object_smoke_domain_find(b_ob);
-
- metadata.is_float = true;
- metadata.depth = 1;
- metadata.channels = 1;
-
- if(!b_domain)
- return;
-
- if(builtin_name == Attribute::standard_name(ATTR_STD_VOLUME_DENSITY) ||
- builtin_name == Attribute::standard_name(ATTR_STD_VOLUME_FLAME) ||
- builtin_name == Attribute::standard_name(ATTR_STD_VOLUME_HEAT) ||
- builtin_name == Attribute::standard_name(ATTR_STD_VOLUME_TEMPERATURE))
- metadata.channels = 1;
- else if(builtin_name == Attribute::standard_name(ATTR_STD_VOLUME_COLOR))
- metadata.channels = 4;
- else if(builtin_name == Attribute::standard_name(ATTR_STD_VOLUME_VELOCITY))
- metadata.channels = 3;
- else
- return;
-
- int3 resolution = get_int3(b_domain.domain_resolution());
- int amplify = (b_domain.use_high_resolution())? b_domain.amplify() + 1: 1;
-
- /* Velocity and heat data is always low-resolution. */
- if(builtin_name == Attribute::standard_name(ATTR_STD_VOLUME_VELOCITY) ||
- builtin_name == Attribute::standard_name(ATTR_STD_VOLUME_HEAT))
- {
- amplify = 1;
- }
-
- metadata.width = resolution.x * amplify;
- metadata.height = resolution.y * amplify;
- metadata.depth = resolution.z * amplify;
- }
- else {
- /* TODO(sergey): Check we're indeed in shader node tree. */
- PointerRNA ptr;
- RNA_pointer_create(NULL, &RNA_Node, builtin_data, &ptr);
- BL::Node b_node(ptr);
- if(b_node.is_a(&RNA_ShaderNodeTexPointDensity)) {
- BL::ShaderNodeTexPointDensity b_point_density_node(b_node);
- metadata.channels = 4;
- metadata.width = b_point_density_node.resolution();
- metadata.height = metadata.width;
- metadata.depth = metadata.width;
- metadata.is_float = true;
- }
- }
+ /* empty image */
+ metadata.width = 1;
+ metadata.height = 1;
+
+ if (!builtin_data)
+ return;
+
+ /* recover ID pointer */
+ PointerRNA ptr;
+ RNA_id_pointer_create((ID *)builtin_data, &ptr);
+ BL::ID b_id(ptr);
+
+ if (b_id.is_a(&RNA_Image)) {
+ /* image data */
+ BL::Image b_image(b_id);
+
+ metadata.builtin_free_cache = !b_image.has_data();
+ metadata.is_float = b_image.is_float();
+ metadata.width = b_image.size()[0];
+ metadata.height = b_image.size()[1];
+ metadata.depth = 1;
+ metadata.channels = b_image.channels();
+ }
+ else if (b_id.is_a(&RNA_Object)) {
+ /* smoke volume data */
+ BL::Object b_ob(b_id);
+ BL::SmokeDomainSettings b_domain = object_smoke_domain_find(b_ob);
+
+ metadata.is_float = true;
+ metadata.depth = 1;
+ metadata.channels = 1;
+
+ if (!b_domain)
+ return;
+
+ if (builtin_name == Attribute::standard_name(ATTR_STD_VOLUME_DENSITY) ||
+ builtin_name == Attribute::standard_name(ATTR_STD_VOLUME_FLAME) ||
+ builtin_name == Attribute::standard_name(ATTR_STD_VOLUME_HEAT) ||
+ builtin_name == Attribute::standard_name(ATTR_STD_VOLUME_TEMPERATURE))
+ metadata.channels = 1;
+ else if (builtin_name == Attribute::standard_name(ATTR_STD_VOLUME_COLOR))
+ metadata.channels = 4;
+ else if (builtin_name == Attribute::standard_name(ATTR_STD_VOLUME_VELOCITY))
+ metadata.channels = 3;
+ else
+ return;
+
+ int3 resolution = get_int3(b_domain.domain_resolution());
+ int amplify = (b_domain.use_high_resolution()) ? b_domain.amplify() + 1 : 1;
+
+ /* Velocity and heat data is always low-resolution. */
+ if (builtin_name == Attribute::standard_name(ATTR_STD_VOLUME_VELOCITY) ||
+ builtin_name == Attribute::standard_name(ATTR_STD_VOLUME_HEAT)) {
+ amplify = 1;
+ }
+
+ metadata.width = resolution.x * amplify;
+ metadata.height = resolution.y * amplify;
+ metadata.depth = resolution.z * amplify;
+ }
+ else {
+ /* TODO(sergey): Check we're indeed in shader node tree. */
+ PointerRNA ptr;
+ RNA_pointer_create(NULL, &RNA_Node, builtin_data, &ptr);
+ BL::Node b_node(ptr);
+ if (b_node.is_a(&RNA_ShaderNodeTexPointDensity)) {
+ BL::ShaderNodeTexPointDensity b_point_density_node(b_node);
+ metadata.channels = 4;
+ metadata.width = b_point_density_node.resolution();
+ metadata.height = metadata.width;
+ metadata.depth = metadata.width;
+ metadata.is_float = true;
+ }
+ }
}
bool BlenderSession::builtin_image_pixels(const string &builtin_name,
@@ -1198,61 +1216,61 @@ bool BlenderSession::builtin_image_pixels(const string &builtin_name,
const size_t pixels_size,
const bool free_cache)
{
- if(!builtin_data) {
- return false;
- }
-
- const int frame = builtin_image_frame(builtin_name);
-
- PointerRNA ptr;
- RNA_id_pointer_create((ID*)builtin_data, &ptr);
- BL::Image b_image(ptr);
-
- const int width = b_image.size()[0];
- const int height = b_image.size()[1];
- const int channels = b_image.channels();
-
- unsigned char *image_pixels = image_get_pixels_for_frame(b_image, frame);
- const size_t num_pixels = ((size_t)width) * height;
-
- if(image_pixels && num_pixels * channels == pixels_size) {
- memcpy(pixels, image_pixels, pixels_size * sizeof(unsigned char));
- }
- else {
- if(channels == 1) {
- memset(pixels, 0, pixels_size * sizeof(unsigned char));
- }
- else {
- const size_t num_pixels_safe = pixels_size / channels;
- unsigned char *cp = pixels;
- for(size_t i = 0; i < num_pixels_safe; i++, cp += channels) {
- cp[0] = 255;
- cp[1] = 0;
- cp[2] = 255;
- if(channels == 4) {
- cp[3] = 255;
- }
- }
- }
- }
-
- if(image_pixels) {
- MEM_freeN(image_pixels);
- }
-
- /* Free image buffers to save memory during render. */
- if(free_cache) {
- b_image.buffers_free();
- }
-
- /* Premultiply, byte images are always straight for Blender. */
- unsigned char *cp = pixels;
- for(size_t i = 0; i < num_pixels; i++, cp += channels) {
- cp[0] = (cp[0] * cp[3]) >> 8;
- cp[1] = (cp[1] * cp[3]) >> 8;
- cp[2] = (cp[2] * cp[3]) >> 8;
- }
- return true;
+ if (!builtin_data) {
+ return false;
+ }
+
+ const int frame = builtin_image_frame(builtin_name);
+
+ PointerRNA ptr;
+ RNA_id_pointer_create((ID *)builtin_data, &ptr);
+ BL::Image b_image(ptr);
+
+ const int width = b_image.size()[0];
+ const int height = b_image.size()[1];
+ const int channels = b_image.channels();
+
+ unsigned char *image_pixels = image_get_pixels_for_frame(b_image, frame);
+ const size_t num_pixels = ((size_t)width) * height;
+
+ if (image_pixels && num_pixels * channels == pixels_size) {
+ memcpy(pixels, image_pixels, pixels_size * sizeof(unsigned char));
+ }
+ else {
+ if (channels == 1) {
+ memset(pixels, 0, pixels_size * sizeof(unsigned char));
+ }
+ else {
+ const size_t num_pixels_safe = pixels_size / channels;
+ unsigned char *cp = pixels;
+ for (size_t i = 0; i < num_pixels_safe; i++, cp += channels) {
+ cp[0] = 255;
+ cp[1] = 0;
+ cp[2] = 255;
+ if (channels == 4) {
+ cp[3] = 255;
+ }
+ }
+ }
+ }
+
+ if (image_pixels) {
+ MEM_freeN(image_pixels);
+ }
+
+ /* Free image buffers to save memory during render. */
+ if (free_cache) {
+ b_image.buffers_free();
+ }
+
+ /* Premultiply, byte images are always straight for Blender. */
+ unsigned char *cp = pixels;
+ for (size_t i = 0; i < num_pixels; i++, cp += channels) {
+ cp[0] = (cp[0] * cp[3]) >> 8;
+ cp[1] = (cp[1] * cp[3]) >> 8;
+ cp[2] = (cp[2] * cp[3]) >> 8;
+ }
+ return true;
}
bool BlenderSession::builtin_image_float_pixels(const string &builtin_name,
@@ -1261,225 +1279,225 @@ bool BlenderSession::builtin_image_float_pixels(const string &builtin_name,
const size_t pixels_size,
const bool free_cache)
{
- if(!builtin_data) {
- return false;
- }
-
- PointerRNA ptr;
- RNA_id_pointer_create((ID*)builtin_data, &ptr);
- BL::ID b_id(ptr);
-
- if(b_id.is_a(&RNA_Image)) {
- /* image data */
- BL::Image b_image(b_id);
- int frame = builtin_image_frame(builtin_name);
-
- const int width = b_image.size()[0];
- const int height = b_image.size()[1];
- const int channels = b_image.channels();
-
- float *image_pixels;
- image_pixels = image_get_float_pixels_for_frame(b_image, frame);
- const size_t num_pixels = ((size_t)width) * height;
-
- if(image_pixels && num_pixels * channels == pixels_size) {
- memcpy(pixels, image_pixels, pixels_size * sizeof(float));
- }
- else {
- if(channels == 1) {
- memset(pixels, 0, num_pixels * sizeof(float));
- }
- else {
- const size_t num_pixels_safe = pixels_size / channels;
- float *fp = pixels;
- for(int i = 0; i < num_pixels_safe; i++, fp += channels) {
- fp[0] = 1.0f;
- fp[1] = 0.0f;
- fp[2] = 1.0f;
- if(channels == 4) {
- fp[3] = 1.0f;
- }
- }
- }
- }
-
- if(image_pixels) {
- MEM_freeN(image_pixels);
- }
-
- /* Free image buffers to save memory during render. */
- if(free_cache) {
- b_image.buffers_free();
- }
-
- return true;
- }
- else if(b_id.is_a(&RNA_Object)) {
- /* smoke volume data */
- BL::Object b_ob(b_id);
- BL::SmokeDomainSettings b_domain = object_smoke_domain_find(b_ob);
-
- if(!b_domain) {
- return false;
- }
-
- int3 resolution = get_int3(b_domain.domain_resolution());
- int length, amplify = (b_domain.use_high_resolution())? b_domain.amplify() + 1: 1;
-
- /* Velocity and heat data is always low-resolution. */
- if(builtin_name == Attribute::standard_name(ATTR_STD_VOLUME_VELOCITY) ||
- builtin_name == Attribute::standard_name(ATTR_STD_VOLUME_HEAT))
- {
- amplify = 1;
- }
-
- const int width = resolution.x * amplify;
- const int height = resolution.y * amplify;
- const int depth = resolution.z * amplify;
- const size_t num_pixels = ((size_t)width) * height * depth;
-
- if(builtin_name == Attribute::standard_name(ATTR_STD_VOLUME_DENSITY)) {
- SmokeDomainSettings_density_grid_get_length(&b_domain.ptr, &length);
- if(length == num_pixels) {
- SmokeDomainSettings_density_grid_get(&b_domain.ptr, pixels);
- return true;
- }
- }
- else if(builtin_name == Attribute::standard_name(ATTR_STD_VOLUME_FLAME)) {
- /* this is in range 0..1, and interpreted by the OpenGL smoke viewer
- * as 1500..3000 K with the first part faded to zero density */
- SmokeDomainSettings_flame_grid_get_length(&b_domain.ptr, &length);
- if(length == num_pixels) {
- SmokeDomainSettings_flame_grid_get(&b_domain.ptr, pixels);
- return true;
- }
- }
- else if(builtin_name == Attribute::standard_name(ATTR_STD_VOLUME_COLOR)) {
- /* the RGB is "premultiplied" by density for better interpolation results */
- SmokeDomainSettings_color_grid_get_length(&b_domain.ptr, &length);
- if(length == num_pixels*4) {
- SmokeDomainSettings_color_grid_get(&b_domain.ptr, pixels);
- return true;
- }
- }
- else if(builtin_name == Attribute::standard_name(ATTR_STD_VOLUME_VELOCITY)) {
- SmokeDomainSettings_velocity_grid_get_length(&b_domain.ptr, &length);
- if(length == num_pixels*3) {
- SmokeDomainSettings_velocity_grid_get(&b_domain.ptr, pixels);
- return true;
- }
- }
- else if(builtin_name == Attribute::standard_name(ATTR_STD_VOLUME_HEAT)) {
- SmokeDomainSettings_heat_grid_get_length(&b_domain.ptr, &length);
- if(length == num_pixels) {
- SmokeDomainSettings_heat_grid_get(&b_domain.ptr, pixels);
- return true;
- }
- }
- else if(builtin_name == Attribute::standard_name(ATTR_STD_VOLUME_TEMPERATURE)) {
- SmokeDomainSettings_temperature_grid_get_length(&b_domain.ptr, &length);
- if(length == num_pixels) {
- SmokeDomainSettings_temperature_grid_get(&b_domain.ptr, pixels);
- return true;
- }
- }
- else {
- fprintf(stderr,
- "Cycles error: unknown volume attribute %s, skipping\n",
- builtin_name.c_str());
- pixels[0] = 0.0f;
- return false;
- }
-
- fprintf(stderr, "Cycles error: unexpected smoke volume resolution, skipping\n");
- }
- else {
- /* We originally were passing view_layer here but in reality we need a
- * a depsgraph to pass to the RE_point_density_minmax() function.
- */
- /* TODO(sergey): Check we're indeed in shader node tree. */
- PointerRNA ptr;
- RNA_pointer_create(NULL, &RNA_Node, builtin_data, &ptr);
- BL::Node b_node(ptr);
- if(b_node.is_a(&RNA_ShaderNodeTexPointDensity)) {
- BL::ShaderNodeTexPointDensity b_point_density_node(b_node);
- int length;
- b_point_density_node.calc_point_density(b_depsgraph, &length, &pixels);
- }
- }
-
- return false;
+ if (!builtin_data) {
+ return false;
+ }
+
+ PointerRNA ptr;
+ RNA_id_pointer_create((ID *)builtin_data, &ptr);
+ BL::ID b_id(ptr);
+
+ if (b_id.is_a(&RNA_Image)) {
+ /* image data */
+ BL::Image b_image(b_id);
+ int frame = builtin_image_frame(builtin_name);
+
+ const int width = b_image.size()[0];
+ const int height = b_image.size()[1];
+ const int channels = b_image.channels();
+
+ float *image_pixels;
+ image_pixels = image_get_float_pixels_for_frame(b_image, frame);
+ const size_t num_pixels = ((size_t)width) * height;
+
+ if (image_pixels && num_pixels * channels == pixels_size) {
+ memcpy(pixels, image_pixels, pixels_size * sizeof(float));
+ }
+ else {
+ if (channels == 1) {
+ memset(pixels, 0, num_pixels * sizeof(float));
+ }
+ else {
+ const size_t num_pixels_safe = pixels_size / channels;
+ float *fp = pixels;
+ for (int i = 0; i < num_pixels_safe; i++, fp += channels) {
+ fp[0] = 1.0f;
+ fp[1] = 0.0f;
+ fp[2] = 1.0f;
+ if (channels == 4) {
+ fp[3] = 1.0f;
+ }
+ }
+ }
+ }
+
+ if (image_pixels) {
+ MEM_freeN(image_pixels);
+ }
+
+ /* Free image buffers to save memory during render. */
+ if (free_cache) {
+ b_image.buffers_free();
+ }
+
+ return true;
+ }
+ else if (b_id.is_a(&RNA_Object)) {
+ /* smoke volume data */
+ BL::Object b_ob(b_id);
+ BL::SmokeDomainSettings b_domain = object_smoke_domain_find(b_ob);
+
+ if (!b_domain) {
+ return false;
+ }
+
+ int3 resolution = get_int3(b_domain.domain_resolution());
+ int length, amplify = (b_domain.use_high_resolution()) ? b_domain.amplify() + 1 : 1;
+
+ /* Velocity and heat data is always low-resolution. */
+ if (builtin_name == Attribute::standard_name(ATTR_STD_VOLUME_VELOCITY) ||
+ builtin_name == Attribute::standard_name(ATTR_STD_VOLUME_HEAT)) {
+ amplify = 1;
+ }
+
+ const int width = resolution.x * amplify;
+ const int height = resolution.y * amplify;
+ const int depth = resolution.z * amplify;
+ const size_t num_pixels = ((size_t)width) * height * depth;
+
+ if (builtin_name == Attribute::standard_name(ATTR_STD_VOLUME_DENSITY)) {
+ SmokeDomainSettings_density_grid_get_length(&b_domain.ptr, &length);
+ if (length == num_pixels) {
+ SmokeDomainSettings_density_grid_get(&b_domain.ptr, pixels);
+ return true;
+ }
+ }
+ else if (builtin_name == Attribute::standard_name(ATTR_STD_VOLUME_FLAME)) {
+ /* this is in range 0..1, and interpreted by the OpenGL smoke viewer
+ * as 1500..3000 K with the first part faded to zero density */
+ SmokeDomainSettings_flame_grid_get_length(&b_domain.ptr, &length);
+ if (length == num_pixels) {
+ SmokeDomainSettings_flame_grid_get(&b_domain.ptr, pixels);
+ return true;
+ }
+ }
+ else if (builtin_name == Attribute::standard_name(ATTR_STD_VOLUME_COLOR)) {
+ /* the RGB is "premultiplied" by density for better interpolation results */
+ SmokeDomainSettings_color_grid_get_length(&b_domain.ptr, &length);
+ if (length == num_pixels * 4) {
+ SmokeDomainSettings_color_grid_get(&b_domain.ptr, pixels);
+ return true;
+ }
+ }
+ else if (builtin_name == Attribute::standard_name(ATTR_STD_VOLUME_VELOCITY)) {
+ SmokeDomainSettings_velocity_grid_get_length(&b_domain.ptr, &length);
+ if (length == num_pixels * 3) {
+ SmokeDomainSettings_velocity_grid_get(&b_domain.ptr, pixels);
+ return true;
+ }
+ }
+ else if (builtin_name == Attribute::standard_name(ATTR_STD_VOLUME_HEAT)) {
+ SmokeDomainSettings_heat_grid_get_length(&b_domain.ptr, &length);
+ if (length == num_pixels) {
+ SmokeDomainSettings_heat_grid_get(&b_domain.ptr, pixels);
+ return true;
+ }
+ }
+ else if (builtin_name == Attribute::standard_name(ATTR_STD_VOLUME_TEMPERATURE)) {
+ SmokeDomainSettings_temperature_grid_get_length(&b_domain.ptr, &length);
+ if (length == num_pixels) {
+ SmokeDomainSettings_temperature_grid_get(&b_domain.ptr, pixels);
+ return true;
+ }
+ }
+ else {
+ fprintf(
+ stderr, "Cycles error: unknown volume attribute %s, skipping\n", builtin_name.c_str());
+ pixels[0] = 0.0f;
+ return false;
+ }
+
+ fprintf(stderr, "Cycles error: unexpected smoke volume resolution, skipping\n");
+ }
+ else {
+ /* We originally were passing view_layer here but in reality we need a
+ * a depsgraph to pass to the RE_point_density_minmax() function.
+ */
+ /* TODO(sergey): Check we're indeed in shader node tree. */
+ PointerRNA ptr;
+ RNA_pointer_create(NULL, &RNA_Node, builtin_data, &ptr);
+ BL::Node b_node(ptr);
+ if (b_node.is_a(&RNA_ShaderNodeTexPointDensity)) {
+ BL::ShaderNodeTexPointDensity b_point_density_node(b_node);
+ int length;
+ b_point_density_node.calc_point_density(b_depsgraph, &length, &pixels);
+ }
+ }
+
+ return false;
}
void BlenderSession::builtin_images_load()
{
- /* Force builtin images to be loaded along with Blender data sync. This
- * is needed because we may be reading from depsgraph evaluated data which
- * can be freed by Blender before Cycles reads it. */
- ImageManager *manager = session->scene->image_manager;
- Device *device = session->device;
- manager->device_load_builtin(device, session->scene, session->progress);
+ /* Force builtin images to be loaded along with Blender data sync. This
+ * is needed because we may be reading from depsgraph evaluated data which
+ * can be freed by Blender before Cycles reads it. */
+ ImageManager *manager = session->scene->image_manager;
+ Device *device = session->device;
+ manager->device_load_builtin(device, session->scene, session->progress);
}
void BlenderSession::update_resumable_tile_manager(int num_samples)
{
- const int num_resumable_chunks = BlenderSession::num_resumable_chunks,
- current_resumable_chunk = BlenderSession::current_resumable_chunk;
- if(num_resumable_chunks == 0) {
- return;
- }
-
- if (num_resumable_chunks > num_samples) {
- fprintf(stderr, "Cycles warning: more sample chunks (%d) than samples (%d), "
- "this will cause some samples to be included in multiple chunks.\n",
- num_resumable_chunks, num_samples);
- }
-
- const float num_samples_per_chunk = (float)num_samples / num_resumable_chunks;
-
- float range_start_sample, range_num_samples;
- if(current_resumable_chunk != 0) {
- /* Single chunk rendering. */
- range_start_sample = num_samples_per_chunk * (current_resumable_chunk - 1);
- range_num_samples = num_samples_per_chunk;
- }
- else {
- /* Ranged-chunks. */
- const int num_chunks = end_resumable_chunk - start_resumable_chunk + 1;
- range_start_sample = num_samples_per_chunk * (start_resumable_chunk - 1);
- range_num_samples = num_chunks * num_samples_per_chunk;
- }
-
- /* Round after doing the multiplications with num_chunks and num_samples_per_chunk
- * to allow for many small chunks. */
- int rounded_range_start_sample = (int)floor(range_start_sample + 0.5f);
- int rounded_range_num_samples = max((int)floor(range_num_samples + 0.5f), 1);
-
- /* Make sure we don't overshoot. */
- if(rounded_range_start_sample + rounded_range_num_samples > num_samples) {
- rounded_range_num_samples = num_samples - rounded_range_num_samples;
- }
-
- VLOG(1) << "Samples range start is " << range_start_sample << ", "
- << "number of samples to render is " << range_num_samples;
-
- scene->integrator->start_sample = rounded_range_start_sample;
- scene->integrator->tag_update(scene);
-
- session->tile_manager.range_start_sample = rounded_range_start_sample;
- session->tile_manager.range_num_samples = rounded_range_num_samples;
+ const int num_resumable_chunks = BlenderSession::num_resumable_chunks,
+ current_resumable_chunk = BlenderSession::current_resumable_chunk;
+ if (num_resumable_chunks == 0) {
+ return;
+ }
+
+ if (num_resumable_chunks > num_samples) {
+ fprintf(stderr,
+ "Cycles warning: more sample chunks (%d) than samples (%d), "
+ "this will cause some samples to be included in multiple chunks.\n",
+ num_resumable_chunks,
+ num_samples);
+ }
+
+ const float num_samples_per_chunk = (float)num_samples / num_resumable_chunks;
+
+ float range_start_sample, range_num_samples;
+ if (current_resumable_chunk != 0) {
+ /* Single chunk rendering. */
+ range_start_sample = num_samples_per_chunk * (current_resumable_chunk - 1);
+ range_num_samples = num_samples_per_chunk;
+ }
+ else {
+ /* Ranged-chunks. */
+ const int num_chunks = end_resumable_chunk - start_resumable_chunk + 1;
+ range_start_sample = num_samples_per_chunk * (start_resumable_chunk - 1);
+ range_num_samples = num_chunks * num_samples_per_chunk;
+ }
+
+ /* Round after doing the multiplications with num_chunks and num_samples_per_chunk
+ * to allow for many small chunks. */
+ int rounded_range_start_sample = (int)floor(range_start_sample + 0.5f);
+ int rounded_range_num_samples = max((int)floor(range_num_samples + 0.5f), 1);
+
+ /* Make sure we don't overshoot. */
+ if (rounded_range_start_sample + rounded_range_num_samples > num_samples) {
+ rounded_range_num_samples = num_samples - rounded_range_num_samples;
+ }
+
+ VLOG(1) << "Samples range start is " << range_start_sample << ", "
+ << "number of samples to render is " << range_num_samples;
+
+ scene->integrator->start_sample = rounded_range_start_sample;
+ scene->integrator->tag_update(scene);
+
+ session->tile_manager.range_start_sample = rounded_range_start_sample;
+ session->tile_manager.range_num_samples = rounded_range_num_samples;
}
void BlenderSession::free_blender_memory_if_possible()
{
- if(!background) {
- /* During interactive render we can not free anything: attempts to save
- * memory would cause things to be allocated and evaluated for every
- * updated sample.
- */
- return;
- }
- b_engine.free_blender_memory();
+ if (!background) {
+ /* During interactive render we can not free anything: attempts to save
+ * memory would cause things to be allocated and evaluated for every
+ * updated sample.
+ */
+ return;
+ }
+ b_engine.free_blender_memory();
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/blender/blender_session.h b/intern/cycles/blender/blender_session.h
index 2bfb9e56c37..f0107d4e0b1 100644
--- a/intern/cycles/blender/blender_session.h
+++ b/intern/cycles/blender/blender_session.h
@@ -33,159 +33,153 @@ class RenderBuffers;
class RenderTile;
class BlenderSession {
-public:
- BlenderSession(BL::RenderEngine& b_engine,
- BL::Preferences& b_userpref,
- BL::BlendData& b_data,
- bool preview_osl);
-
- BlenderSession(BL::RenderEngine& b_engine,
- BL::Preferences& b_userpref,
- BL::BlendData& b_data,
- BL::SpaceView3D& b_v3d,
- BL::RegionView3D& b_rv3d,
- int width, int height);
-
- ~BlenderSession();
-
- void create();
-
- /* session */
- void create_session();
- void free_session();
-
- void reset_session(BL::BlendData& b_data,
- BL::Depsgraph& b_depsgraph);
-
- /* offline render */
- void render(BL::Depsgraph& b_depsgraph);
-
- void bake(BL::Depsgraph& b_depsgrah,
- BL::Object& b_object,
- const string& pass_type,
- const int custom_flag,
- const int object_id,
- BL::BakePixel& pixel_array,
- const size_t num_pixels,
- const int depth,
- float pixels[]);
-
- void write_render_result(BL::RenderResult& b_rr,
- BL::RenderLayer& b_rlay,
- RenderTile& rtile);
- void write_render_tile(RenderTile& rtile);
-
- /* update functions are used to update display buffer only after sample was rendered
- * only needed for better visual feedback */
- void update_render_result(BL::RenderResult& b_rr,
- BL::RenderLayer& b_rlay,
- RenderTile& rtile);
- void update_render_tile(RenderTile& rtile, bool highlight);
-
- /* interactive updates */
- void synchronize(BL::Depsgraph& b_depsgraph);
-
- /* drawing */
- bool draw(int w, int h);
- void tag_redraw();
- void tag_update();
- void get_status(string& status, string& substatus);
- void get_kernel_status(string& kernel_status);
- void get_progress(float& progress, double& total_time, double& render_time);
- void test_cancel();
- void update_status_progress();
- void update_bake_progress();
-
- bool background;
- Session *session;
- Scene *scene;
- BlenderSync *sync;
- double last_redraw_time;
-
- BL::RenderEngine b_engine;
- BL::Preferences b_userpref;
- BL::BlendData b_data;
- BL::RenderSettings b_render;
- BL::Depsgraph b_depsgraph;
- /* NOTE: Blender's scene might become invalid after call
- * free_blender_memory_if_possible().
- */
- BL::Scene b_scene;
- BL::SpaceView3D b_v3d;
- BL::RegionView3D b_rv3d;
- string b_rlay_name;
- string b_rview_name;
-
- string last_status;
- string last_error;
- float last_progress;
- double last_status_time;
-
- int width, height;
- bool preview_osl;
- double start_resize_time;
-
- void *python_thread_state;
-
- /* Global state which is common for all render sessions created from Blender.
- * Usually denotes command line arguments.
- */
-
- /* Blender is running from the command line, no windows are shown and some
- * extra render optimization is possible (possible to free draw-only data and
- * so on.
- */
- static bool headless;
-
- /* ** Resumable render ** */
-
- /* Overall number of chunks in which the sample range is to be devided. */
- static int num_resumable_chunks;
-
- /* Current resumable chunk index to render. */
- static int current_resumable_chunk;
-
- /* Alternative to single-chunk rendering to render a range of chunks. */
- static int start_resumable_chunk;
- static int end_resumable_chunk;
-
- static bool print_render_stats;
-
-protected:
- void stamp_view_layer_metadata(Scene *scene, const string& view_layer_name);
-
- void do_write_update_render_result(BL::RenderResult& b_rr,
- BL::RenderLayer& b_rlay,
- RenderTile& rtile,
- bool do_update_only);
- void do_write_update_render_tile(RenderTile& rtile, bool do_update_only, bool highlight);
-
- int builtin_image_frame(const string &builtin_name);
- void builtin_image_info(const string &builtin_name,
- void *builtin_data,
- ImageMetaData& metadata);
- bool builtin_image_pixels(const string &builtin_name,
- void *builtin_data,
- unsigned char *pixels,
- const size_t pixels_size,
- const bool free_cache);
- bool builtin_image_float_pixels(const string &builtin_name,
- void *builtin_data,
- float *pixels,
- const size_t pixels_size,
- const bool free_cache);
- void builtin_images_load();
-
- /* Update tile manager to reflect resumable render settings. */
- void update_resumable_tile_manager(int num_samples);
-
- /* Is used after each render layer synchronization is done with the goal
- * of freeing render engine data which is held from Blender side (for
- * example, dependency graph).
- */
- void free_blender_memory_if_possible();
+ public:
+ BlenderSession(BL::RenderEngine &b_engine,
+ BL::Preferences &b_userpref,
+ BL::BlendData &b_data,
+ bool preview_osl);
+
+ BlenderSession(BL::RenderEngine &b_engine,
+ BL::Preferences &b_userpref,
+ BL::BlendData &b_data,
+ BL::SpaceView3D &b_v3d,
+ BL::RegionView3D &b_rv3d,
+ int width,
+ int height);
+
+ ~BlenderSession();
+
+ void create();
+
+ /* session */
+ void create_session();
+ void free_session();
+
+ void reset_session(BL::BlendData &b_data, BL::Depsgraph &b_depsgraph);
+
+ /* offline render */
+ void render(BL::Depsgraph &b_depsgraph);
+
+ void bake(BL::Depsgraph &b_depsgrah,
+ BL::Object &b_object,
+ const string &pass_type,
+ const int custom_flag,
+ const int object_id,
+ BL::BakePixel &pixel_array,
+ const size_t num_pixels,
+ const int depth,
+ float pixels[]);
+
+ void write_render_result(BL::RenderResult &b_rr, BL::RenderLayer &b_rlay, RenderTile &rtile);
+ void write_render_tile(RenderTile &rtile);
+
+ /* update functions are used to update display buffer only after sample was rendered
+ * only needed for better visual feedback */
+ void update_render_result(BL::RenderResult &b_rr, BL::RenderLayer &b_rlay, RenderTile &rtile);
+ void update_render_tile(RenderTile &rtile, bool highlight);
+
+ /* interactive updates */
+ void synchronize(BL::Depsgraph &b_depsgraph);
+
+ /* drawing */
+ bool draw(int w, int h);
+ void tag_redraw();
+ void tag_update();
+ void get_status(string &status, string &substatus);
+ void get_kernel_status(string &kernel_status);
+ void get_progress(float &progress, double &total_time, double &render_time);
+ void test_cancel();
+ void update_status_progress();
+ void update_bake_progress();
+
+ bool background;
+ Session *session;
+ Scene *scene;
+ BlenderSync *sync;
+ double last_redraw_time;
+
+ BL::RenderEngine b_engine;
+ BL::Preferences b_userpref;
+ BL::BlendData b_data;
+ BL::RenderSettings b_render;
+ BL::Depsgraph b_depsgraph;
+ /* NOTE: Blender's scene might become invalid after call
+ * free_blender_memory_if_possible().
+ */
+ BL::Scene b_scene;
+ BL::SpaceView3D b_v3d;
+ BL::RegionView3D b_rv3d;
+ string b_rlay_name;
+ string b_rview_name;
+
+ string last_status;
+ string last_error;
+ float last_progress;
+ double last_status_time;
+
+ int width, height;
+ bool preview_osl;
+ double start_resize_time;
+
+ void *python_thread_state;
+
+ /* Global state which is common for all render sessions created from Blender.
+ * Usually denotes command line arguments.
+ */
+
+ /* Blender is running from the command line, no windows are shown and some
+ * extra render optimization is possible (possible to free draw-only data and
+ * so on.
+ */
+ static bool headless;
+
+ /* ** Resumable render ** */
+
+ /* Overall number of chunks in which the sample range is to be devided. */
+ static int num_resumable_chunks;
+
+ /* Current resumable chunk index to render. */
+ static int current_resumable_chunk;
+
+ /* Alternative to single-chunk rendering to render a range of chunks. */
+ static int start_resumable_chunk;
+ static int end_resumable_chunk;
+
+ static bool print_render_stats;
+
+ protected:
+ void stamp_view_layer_metadata(Scene *scene, const string &view_layer_name);
+
+ void do_write_update_render_result(BL::RenderResult &b_rr,
+ BL::RenderLayer &b_rlay,
+ RenderTile &rtile,
+ bool do_update_only);
+ void do_write_update_render_tile(RenderTile &rtile, bool do_update_only, bool highlight);
+
+ int builtin_image_frame(const string &builtin_name);
+ void builtin_image_info(const string &builtin_name, void *builtin_data, ImageMetaData &metadata);
+ bool builtin_image_pixels(const string &builtin_name,
+ void *builtin_data,
+ unsigned char *pixels,
+ const size_t pixels_size,
+ const bool free_cache);
+ bool builtin_image_float_pixels(const string &builtin_name,
+ void *builtin_data,
+ float *pixels,
+ const size_t pixels_size,
+ const bool free_cache);
+ void builtin_images_load();
+
+ /* Update tile manager to reflect resumable render settings. */
+ void update_resumable_tile_manager(int num_samples);
+
+ /* Is used after each render layer synchronization is done with the goal
+ * of freeing render engine data which is held from Blender side (for
+ * example, dependency graph).
+ */
+ void free_blender_memory_if_possible();
};
CCL_NAMESPACE_END
-#endif /* __BLENDER_SESSION_H__ */
+#endif /* __BLENDER_SESSION_H__ */
diff --git a/intern/cycles/blender/blender_shader.cpp b/intern/cycles/blender/blender_shader.cpp
index 44ff29d4bf8..169c4d414a6 100644
--- a/intern/cycles/blender/blender_shader.cpp
+++ b/intern/cycles/blender/blender_shader.cpp
@@ -34,1449 +34,1416 @@
CCL_NAMESPACE_BEGIN
-typedef map<void*, ShaderInput*> PtrInputMap;
-typedef map<void*, ShaderOutput*> PtrOutputMap;
-typedef map<string, ConvertNode*> ProxyMap;
+typedef map<void *, ShaderInput *> PtrInputMap;
+typedef map<void *, ShaderOutput *> PtrOutputMap;
+typedef map<string, ConvertNode *> ProxyMap;
/* Find */
-void BlenderSync::find_shader(BL::ID& id,
- vector<Shader*>& used_shaders,
- Shader *default_shader)
+void BlenderSync::find_shader(BL::ID &id, vector<Shader *> &used_shaders, Shader *default_shader)
{
- Shader *shader = (id)? shader_map.find(id): default_shader;
+ Shader *shader = (id) ? shader_map.find(id) : default_shader;
- used_shaders.push_back(shader);
- shader->tag_used(scene);
+ used_shaders.push_back(shader);
+ shader->tag_used(scene);
}
/* RNA translation utilities */
-static VolumeSampling get_volume_sampling(PointerRNA& ptr)
+static VolumeSampling get_volume_sampling(PointerRNA &ptr)
{
- return (VolumeSampling)get_enum(ptr,
- "volume_sampling",
- VOLUME_NUM_SAMPLING,
- VOLUME_SAMPLING_DISTANCE);
+ return (VolumeSampling)get_enum(
+ ptr, "volume_sampling", VOLUME_NUM_SAMPLING, VOLUME_SAMPLING_DISTANCE);
}
-static VolumeInterpolation get_volume_interpolation(PointerRNA& ptr)
+static VolumeInterpolation get_volume_interpolation(PointerRNA &ptr)
{
- return (VolumeInterpolation)get_enum(ptr,
- "volume_interpolation",
- VOLUME_NUM_INTERPOLATION,
- VOLUME_INTERPOLATION_LINEAR);
+ return (VolumeInterpolation)get_enum(
+ ptr, "volume_interpolation", VOLUME_NUM_INTERPOLATION, VOLUME_INTERPOLATION_LINEAR);
}
-static DisplacementMethod get_displacement_method(PointerRNA& ptr)
+static DisplacementMethod get_displacement_method(PointerRNA &ptr)
{
- return (DisplacementMethod)get_enum(ptr,
- "displacement_method",
- DISPLACE_NUM_METHODS,
- DISPLACE_BUMP);
+ return (DisplacementMethod)get_enum(
+ ptr, "displacement_method", DISPLACE_NUM_METHODS, DISPLACE_BUMP);
}
static int validate_enum_value(int value, int num_values, int default_value)
{
- if(value >= num_values) {
- return default_value;
- }
- return value;
+ if (value >= num_values) {
+ return default_value;
+ }
+ return value;
}
-template<typename NodeType>
-static InterpolationType get_image_interpolation(NodeType& b_node)
+template<typename NodeType> static InterpolationType get_image_interpolation(NodeType &b_node)
{
- int value = b_node.interpolation();
- return (InterpolationType)validate_enum_value(value,
- INTERPOLATION_NUM_TYPES,
- INTERPOLATION_LINEAR);
+ int value = b_node.interpolation();
+ return (InterpolationType)validate_enum_value(
+ value, INTERPOLATION_NUM_TYPES, INTERPOLATION_LINEAR);
}
-template<typename NodeType>
-static ExtensionType get_image_extension(NodeType& b_node)
+template<typename NodeType> static ExtensionType get_image_extension(NodeType &b_node)
{
- int value = b_node.extension();
- return (ExtensionType)validate_enum_value(value,
- EXTENSION_NUM_TYPES,
- EXTENSION_REPEAT);
+ int value = b_node.extension();
+ return (ExtensionType)validate_enum_value(value, EXTENSION_NUM_TYPES, EXTENSION_REPEAT);
}
/* Graph */
-static BL::NodeSocket get_node_output(BL::Node& b_node, const string& name)
+static BL::NodeSocket get_node_output(BL::Node &b_node, const string &name)
{
- BL::Node::outputs_iterator b_out;
+ BL::Node::outputs_iterator b_out;
- for(b_node.outputs.begin(b_out); b_out != b_node.outputs.end(); ++b_out)
- if(b_out->name() == name)
- return *b_out;
+ for (b_node.outputs.begin(b_out); b_out != b_node.outputs.end(); ++b_out)
+ if (b_out->name() == name)
+ return *b_out;
- assert(0);
+ assert(0);
- return *b_out;
+ return *b_out;
}
-static float3 get_node_output_rgba(BL::Node& b_node, const string& name)
+static float3 get_node_output_rgba(BL::Node &b_node, const string &name)
{
- BL::NodeSocket b_sock = get_node_output(b_node, name);
- float value[4];
- RNA_float_get_array(&b_sock.ptr, "default_value", value);
- return make_float3(value[0], value[1], value[2]);
+ BL::NodeSocket b_sock = get_node_output(b_node, name);
+ float value[4];
+ RNA_float_get_array(&b_sock.ptr, "default_value", value);
+ return make_float3(value[0], value[1], value[2]);
}
-static float get_node_output_value(BL::Node& b_node, const string& name)
+static float get_node_output_value(BL::Node &b_node, const string &name)
{
- BL::NodeSocket b_sock = get_node_output(b_node, name);
- return RNA_float_get(&b_sock.ptr, "default_value");
+ BL::NodeSocket b_sock = get_node_output(b_node, name);
+ return RNA_float_get(&b_sock.ptr, "default_value");
}
-static float3 get_node_output_vector(BL::Node& b_node, const string& name)
+static float3 get_node_output_vector(BL::Node &b_node, const string &name)
{
- BL::NodeSocket b_sock = get_node_output(b_node, name);
- float value[3];
- RNA_float_get_array(&b_sock.ptr, "default_value", value);
- return make_float3(value[0], value[1], value[2]);
+ BL::NodeSocket b_sock = get_node_output(b_node, name);
+ float value[3];
+ RNA_float_get_array(&b_sock.ptr, "default_value", value);
+ return make_float3(value[0], value[1], value[2]);
}
-static SocketType::Type convert_socket_type(BL::NodeSocket& b_socket)
+static SocketType::Type convert_socket_type(BL::NodeSocket &b_socket)
{
- switch(b_socket.type()) {
- case BL::NodeSocket::type_VALUE:
- return SocketType::FLOAT;
- case BL::NodeSocket::type_INT:
- return SocketType::INT;
- case BL::NodeSocket::type_VECTOR:
- return SocketType::VECTOR;
- case BL::NodeSocket::type_RGBA:
- return SocketType::COLOR;
- case BL::NodeSocket::type_STRING:
- return SocketType::STRING;
- case BL::NodeSocket::type_SHADER:
- return SocketType::CLOSURE;
-
- default:
- return SocketType::UNDEFINED;
- }
+ switch (b_socket.type()) {
+ case BL::NodeSocket::type_VALUE:
+ return SocketType::FLOAT;
+ case BL::NodeSocket::type_INT:
+ return SocketType::INT;
+ case BL::NodeSocket::type_VECTOR:
+ return SocketType::VECTOR;
+ case BL::NodeSocket::type_RGBA:
+ return SocketType::COLOR;
+ case BL::NodeSocket::type_STRING:
+ return SocketType::STRING;
+ case BL::NodeSocket::type_SHADER:
+ return SocketType::CLOSURE;
+
+ default:
+ return SocketType::UNDEFINED;
+ }
}
static void set_default_value(ShaderInput *input,
- BL::NodeSocket& b_sock,
- BL::BlendData& b_data,
- BL::ID& b_id)
+ BL::NodeSocket &b_sock,
+ BL::BlendData &b_data,
+ BL::ID &b_id)
{
- Node *node = input->parent;
- const SocketType& socket = input->socket_type;
-
- /* copy values for non linked inputs */
- switch(input->type()) {
- case SocketType::FLOAT: {
- node->set(socket, get_float(b_sock.ptr, "default_value"));
- break;
- }
- case SocketType::INT: {
- node->set(socket, get_int(b_sock.ptr, "default_value"));
- break;
- }
- case SocketType::COLOR: {
- node->set(socket, float4_to_float3(get_float4(b_sock.ptr, "default_value")));
- break;
- }
- case SocketType::NORMAL:
- case SocketType::POINT:
- case SocketType::VECTOR: {
- node->set(socket, get_float3(b_sock.ptr, "default_value"));
- break;
- }
- case SocketType::STRING: {
- node->set(socket, (ustring)blender_absolute_path(b_data, b_id, get_string(b_sock.ptr, "default_value")));
- break;
- }
- default:
- break;
- }
+ Node *node = input->parent;
+ const SocketType &socket = input->socket_type;
+
+ /* copy values for non linked inputs */
+ switch (input->type()) {
+ case SocketType::FLOAT: {
+ node->set(socket, get_float(b_sock.ptr, "default_value"));
+ break;
+ }
+ case SocketType::INT: {
+ node->set(socket, get_int(b_sock.ptr, "default_value"));
+ break;
+ }
+ case SocketType::COLOR: {
+ node->set(socket, float4_to_float3(get_float4(b_sock.ptr, "default_value")));
+ break;
+ }
+ case SocketType::NORMAL:
+ case SocketType::POINT:
+ case SocketType::VECTOR: {
+ node->set(socket, get_float3(b_sock.ptr, "default_value"));
+ break;
+ }
+ case SocketType::STRING: {
+ node->set(
+ socket,
+ (ustring)blender_absolute_path(b_data, b_id, get_string(b_sock.ptr, "default_value")));
+ break;
+ }
+ default:
+ break;
+ }
}
-static void get_tex_mapping(TextureMapping *mapping, BL::TexMapping& b_mapping)
+static void get_tex_mapping(TextureMapping *mapping, BL::TexMapping &b_mapping)
{
- if(!b_mapping)
- return;
+ if (!b_mapping)
+ return;
- mapping->translation = get_float3(b_mapping.translation());
- mapping->rotation = get_float3(b_mapping.rotation());
- mapping->scale = get_float3(b_mapping.scale());
- mapping->type = (TextureMapping::Type)b_mapping.vector_type();
+ mapping->translation = get_float3(b_mapping.translation());
+ mapping->rotation = get_float3(b_mapping.rotation());
+ mapping->scale = get_float3(b_mapping.scale());
+ mapping->type = (TextureMapping::Type)b_mapping.vector_type();
- mapping->x_mapping = (TextureMapping::Mapping)b_mapping.mapping_x();
- mapping->y_mapping = (TextureMapping::Mapping)b_mapping.mapping_y();
- mapping->z_mapping = (TextureMapping::Mapping)b_mapping.mapping_z();
+ mapping->x_mapping = (TextureMapping::Mapping)b_mapping.mapping_x();
+ mapping->y_mapping = (TextureMapping::Mapping)b_mapping.mapping_y();
+ mapping->z_mapping = (TextureMapping::Mapping)b_mapping.mapping_z();
}
-static void get_tex_mapping(TextureMapping *mapping,
- BL::ShaderNodeMapping& b_mapping)
+static void get_tex_mapping(TextureMapping *mapping, BL::ShaderNodeMapping &b_mapping)
{
- if(!b_mapping)
- return;
+ if (!b_mapping)
+ return;
- mapping->translation = get_float3(b_mapping.translation());
- mapping->rotation = get_float3(b_mapping.rotation());
- mapping->scale = get_float3(b_mapping.scale());
- mapping->type = (TextureMapping::Type)b_mapping.vector_type();
+ mapping->translation = get_float3(b_mapping.translation());
+ mapping->rotation = get_float3(b_mapping.rotation());
+ mapping->scale = get_float3(b_mapping.scale());
+ mapping->type = (TextureMapping::Type)b_mapping.vector_type();
- mapping->use_minmax = b_mapping.use_min() || b_mapping.use_max();
+ mapping->use_minmax = b_mapping.use_min() || b_mapping.use_max();
- if(b_mapping.use_min())
- mapping->min = get_float3(b_mapping.min());
- if(b_mapping.use_max())
- mapping->max = get_float3(b_mapping.max());
+ if (b_mapping.use_min())
+ mapping->min = get_float3(b_mapping.min());
+ if (b_mapping.use_max())
+ mapping->max = get_float3(b_mapping.max());
}
static ShaderNode *add_node(Scene *scene,
- BL::RenderEngine& b_engine,
- BL::BlendData& b_data,
- BL::Depsgraph& b_depsgraph,
- BL::Scene& b_scene,
+ BL::RenderEngine &b_engine,
+ BL::BlendData &b_data,
+ BL::Depsgraph &b_depsgraph,
+ BL::Scene &b_scene,
ShaderGraph *graph,
- BL::ShaderNodeTree& b_ntree,
- BL::ShaderNode& b_node)
+ BL::ShaderNodeTree &b_ntree,
+ BL::ShaderNode &b_node)
{
- ShaderNode *node = NULL;
-
- /* existing blender nodes */
- if(b_node.is_a(&RNA_ShaderNodeRGBCurve)) {
- BL::ShaderNodeRGBCurve b_curve_node(b_node);
- BL::CurveMapping mapping(b_curve_node.mapping());
- RGBCurvesNode *curves = new RGBCurvesNode();
- curvemapping_color_to_array(mapping,
- curves->curves,
- RAMP_TABLE_SIZE,
- true);
- curvemapping_minmax(mapping, true, &curves->min_x, &curves->max_x);
- node = curves;
- }
- if(b_node.is_a(&RNA_ShaderNodeVectorCurve)) {
- BL::ShaderNodeVectorCurve b_curve_node(b_node);
- BL::CurveMapping mapping(b_curve_node.mapping());
- VectorCurvesNode *curves = new VectorCurvesNode();
- curvemapping_color_to_array(mapping,
- curves->curves,
- RAMP_TABLE_SIZE,
- false);
- curvemapping_minmax(mapping, false, &curves->min_x, &curves->max_x);
- node = curves;
- }
- else if(b_node.is_a(&RNA_ShaderNodeValToRGB)) {
- RGBRampNode *ramp = new RGBRampNode();
- BL::ShaderNodeValToRGB b_ramp_node(b_node);
- BL::ColorRamp b_color_ramp(b_ramp_node.color_ramp());
- colorramp_to_array(b_color_ramp, ramp->ramp, ramp->ramp_alpha, RAMP_TABLE_SIZE);
- ramp->interpolate = b_color_ramp.interpolation() != BL::ColorRamp::interpolation_CONSTANT;
- node = ramp;
- }
- else if(b_node.is_a(&RNA_ShaderNodeRGB)) {
- ColorNode *color = new ColorNode();
- color->value = get_node_output_rgba(b_node, "Color");
- node = color;
- }
- else if(b_node.is_a(&RNA_ShaderNodeValue)) {
- ValueNode *value = new ValueNode();
- value->value = get_node_output_value(b_node, "Value");
- node = value;
- }
- else if(b_node.is_a(&RNA_ShaderNodeCameraData)) {
- node = new CameraNode();
- }
- else if(b_node.is_a(&RNA_ShaderNodeInvert)) {
- node = new InvertNode();
- }
- else if(b_node.is_a(&RNA_ShaderNodeGamma)) {
- node = new GammaNode();
- }
- else if(b_node.is_a(&RNA_ShaderNodeBrightContrast)) {
- node = new BrightContrastNode();
- }
- else if(b_node.is_a(&RNA_ShaderNodeMixRGB)) {
- BL::ShaderNodeMixRGB b_mix_node(b_node);
- MixNode *mix = new MixNode();
- mix->type = (NodeMix)b_mix_node.blend_type();
- mix->use_clamp = b_mix_node.use_clamp();
- node = mix;
- }
- else if(b_node.is_a(&RNA_ShaderNodeSeparateRGB)) {
- node = new SeparateRGBNode();
- }
- else if(b_node.is_a(&RNA_ShaderNodeCombineRGB)) {
- node = new CombineRGBNode();
- }
- else if(b_node.is_a(&RNA_ShaderNodeSeparateHSV)) {
- node = new SeparateHSVNode();
- }
- else if(b_node.is_a(&RNA_ShaderNodeCombineHSV)) {
- node = new CombineHSVNode();
- }
- else if(b_node.is_a(&RNA_ShaderNodeSeparateXYZ)) {
- node = new SeparateXYZNode();
- }
- else if(b_node.is_a(&RNA_ShaderNodeCombineXYZ)) {
- node = new CombineXYZNode();
- }
- else if(b_node.is_a(&RNA_ShaderNodeHueSaturation)) {
- node = new HSVNode();
- }
- else if(b_node.is_a(&RNA_ShaderNodeRGBToBW)) {
- node = new RGBToBWNode();
- }
- else if(b_node.is_a(&RNA_ShaderNodeMath)) {
- BL::ShaderNodeMath b_math_node(b_node);
- MathNode *math = new MathNode();
- math->type = (NodeMath)b_math_node.operation();
- math->use_clamp = b_math_node.use_clamp();
- node = math;
- }
- else if(b_node.is_a(&RNA_ShaderNodeVectorMath)) {
- BL::ShaderNodeVectorMath b_vector_math_node(b_node);
- VectorMathNode *vmath = new VectorMathNode();
- vmath->type = (NodeVectorMath)b_vector_math_node.operation();
- node = vmath;
- }
- else if(b_node.is_a(&RNA_ShaderNodeVectorTransform)) {
- BL::ShaderNodeVectorTransform b_vector_transform_node(b_node);
- VectorTransformNode *vtransform = new VectorTransformNode();
- vtransform->type = (NodeVectorTransformType)b_vector_transform_node.vector_type();
- vtransform->convert_from = (NodeVectorTransformConvertSpace)b_vector_transform_node.convert_from();
- vtransform->convert_to = (NodeVectorTransformConvertSpace)b_vector_transform_node.convert_to();
- node = vtransform;
- }
- else if(b_node.is_a(&RNA_ShaderNodeNormal)) {
- BL::Node::outputs_iterator out_it;
- b_node.outputs.begin(out_it);
-
- NormalNode *norm = new NormalNode();
- norm->direction = get_node_output_vector(b_node, "Normal");
- node = norm;
- }
- else if(b_node.is_a(&RNA_ShaderNodeMapping)) {
- BL::ShaderNodeMapping b_mapping_node(b_node);
- MappingNode *mapping = new MappingNode();
-
- get_tex_mapping(&mapping->tex_mapping, b_mapping_node);
-
- node = mapping;
- }
- else if(b_node.is_a(&RNA_ShaderNodeFresnel)) {
- node = new FresnelNode();
- }
- else if(b_node.is_a(&RNA_ShaderNodeLayerWeight)) {
- node = new LayerWeightNode();
- }
- else if(b_node.is_a(&RNA_ShaderNodeAddShader)) {
- node = new AddClosureNode();
- }
- else if(b_node.is_a(&RNA_ShaderNodeMixShader)) {
- node = new MixClosureNode();
- }
- else if(b_node.is_a(&RNA_ShaderNodeAttribute)) {
- BL::ShaderNodeAttribute b_attr_node(b_node);
- AttributeNode *attr = new AttributeNode();
- attr->attribute = b_attr_node.attribute_name();
- node = attr;
- }
- else if(b_node.is_a(&RNA_ShaderNodeBackground)) {
- node = new BackgroundNode();
- }
- else if(b_node.is_a(&RNA_ShaderNodeHoldout)) {
- node = new HoldoutNode();
- }
- else if(b_node.is_a(&RNA_ShaderNodeBsdfAnisotropic)) {
- BL::ShaderNodeBsdfAnisotropic b_aniso_node(b_node);
- AnisotropicBsdfNode *aniso = new AnisotropicBsdfNode();
-
- switch(b_aniso_node.distribution()) {
- case BL::ShaderNodeBsdfAnisotropic::distribution_BECKMANN:
- aniso->distribution = CLOSURE_BSDF_MICROFACET_BECKMANN_ANISO_ID;
- break;
- case BL::ShaderNodeBsdfAnisotropic::distribution_GGX:
- aniso->distribution = CLOSURE_BSDF_MICROFACET_GGX_ANISO_ID;
- break;
- case BL::ShaderNodeBsdfAnisotropic::distribution_MULTI_GGX:
- aniso->distribution = CLOSURE_BSDF_MICROFACET_MULTI_GGX_ANISO_ID;
- break;
- case BL::ShaderNodeBsdfAnisotropic::distribution_ASHIKHMIN_SHIRLEY:
- aniso->distribution = CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ANISO_ID;
- break;
- }
-
- node = aniso;
- }
- else if(b_node.is_a(&RNA_ShaderNodeBsdfDiffuse)) {
- node = new DiffuseBsdfNode();
- }
- else if(b_node.is_a(&RNA_ShaderNodeSubsurfaceScattering)) {
- BL::ShaderNodeSubsurfaceScattering b_subsurface_node(b_node);
-
- SubsurfaceScatteringNode *subsurface = new SubsurfaceScatteringNode();
-
- switch(b_subsurface_node.falloff()) {
- case BL::ShaderNodeSubsurfaceScattering::falloff_CUBIC:
- subsurface->falloff = CLOSURE_BSSRDF_CUBIC_ID;
- break;
- case BL::ShaderNodeSubsurfaceScattering::falloff_GAUSSIAN:
- subsurface->falloff = CLOSURE_BSSRDF_GAUSSIAN_ID;
- break;
- case BL::ShaderNodeSubsurfaceScattering::falloff_BURLEY:
- subsurface->falloff = CLOSURE_BSSRDF_BURLEY_ID;
- break;
- case BL::ShaderNodeSubsurfaceScattering::falloff_RANDOM_WALK:
- subsurface->falloff = CLOSURE_BSSRDF_RANDOM_WALK_ID;
- break;
- }
-
- node = subsurface;
- }
- else if(b_node.is_a(&RNA_ShaderNodeBsdfGlossy)) {
- BL::ShaderNodeBsdfGlossy b_glossy_node(b_node);
- GlossyBsdfNode *glossy = new GlossyBsdfNode();
-
- switch(b_glossy_node.distribution()) {
- case BL::ShaderNodeBsdfGlossy::distribution_SHARP:
- glossy->distribution = CLOSURE_BSDF_REFLECTION_ID;
- break;
- case BL::ShaderNodeBsdfGlossy::distribution_BECKMANN:
- glossy->distribution = CLOSURE_BSDF_MICROFACET_BECKMANN_ID;
- break;
- case BL::ShaderNodeBsdfGlossy::distribution_GGX:
- glossy->distribution = CLOSURE_BSDF_MICROFACET_GGX_ID;
- break;
- case BL::ShaderNodeBsdfGlossy::distribution_ASHIKHMIN_SHIRLEY:
- glossy->distribution = CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ID;
- break;
- case BL::ShaderNodeBsdfGlossy::distribution_MULTI_GGX:
- glossy->distribution = CLOSURE_BSDF_MICROFACET_MULTI_GGX_ID;
- break;
- }
- node = glossy;
- }
- else if(b_node.is_a(&RNA_ShaderNodeBsdfGlass)) {
- BL::ShaderNodeBsdfGlass b_glass_node(b_node);
- GlassBsdfNode *glass = new GlassBsdfNode();
- switch(b_glass_node.distribution()) {
- case BL::ShaderNodeBsdfGlass::distribution_SHARP:
- glass->distribution = CLOSURE_BSDF_SHARP_GLASS_ID;
- break;
- case BL::ShaderNodeBsdfGlass::distribution_BECKMANN:
- glass->distribution = CLOSURE_BSDF_MICROFACET_BECKMANN_GLASS_ID;
- break;
- case BL::ShaderNodeBsdfGlass::distribution_GGX:
- glass->distribution = CLOSURE_BSDF_MICROFACET_GGX_GLASS_ID;
- break;
- case BL::ShaderNodeBsdfGlass::distribution_MULTI_GGX:
- glass->distribution = CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID;
- break;
- }
- node = glass;
- }
- else if(b_node.is_a(&RNA_ShaderNodeBsdfRefraction)) {
- BL::ShaderNodeBsdfRefraction b_refraction_node(b_node);
- RefractionBsdfNode *refraction = new RefractionBsdfNode();
- switch(b_refraction_node.distribution()) {
- case BL::ShaderNodeBsdfRefraction::distribution_SHARP:
- refraction->distribution = CLOSURE_BSDF_REFRACTION_ID;
- break;
- case BL::ShaderNodeBsdfRefraction::distribution_BECKMANN:
- refraction->distribution = CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID;
- break;
- case BL::ShaderNodeBsdfRefraction::distribution_GGX:
- refraction->distribution = CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID;
- break;
- }
- node = refraction;
- }
- else if(b_node.is_a(&RNA_ShaderNodeBsdfToon)) {
- BL::ShaderNodeBsdfToon b_toon_node(b_node);
- ToonBsdfNode *toon = new ToonBsdfNode();
- switch(b_toon_node.component()) {
- case BL::ShaderNodeBsdfToon::component_DIFFUSE:
- toon->component = CLOSURE_BSDF_DIFFUSE_TOON_ID;
- break;
- case BL::ShaderNodeBsdfToon::component_GLOSSY:
- toon->component = CLOSURE_BSDF_GLOSSY_TOON_ID;
- break;
- }
- node = toon;
- }
- else if(b_node.is_a(&RNA_ShaderNodeBsdfHair)) {
- BL::ShaderNodeBsdfHair b_hair_node(b_node);
- HairBsdfNode *hair = new HairBsdfNode();
- switch(b_hair_node.component()) {
- case BL::ShaderNodeBsdfHair::component_Reflection:
- hair->component = CLOSURE_BSDF_HAIR_REFLECTION_ID;
- break;
- case BL::ShaderNodeBsdfHair::component_Transmission:
- hair->component = CLOSURE_BSDF_HAIR_TRANSMISSION_ID;
- break;
- }
- node = hair;
- }
- else if(b_node.is_a(&RNA_ShaderNodeBsdfHairPrincipled)) {
- BL::ShaderNodeBsdfHairPrincipled b_principled_hair_node(b_node);
- PrincipledHairBsdfNode *principled_hair = new PrincipledHairBsdfNode();
- principled_hair->parametrization = (NodePrincipledHairParametrization) get_enum(b_principled_hair_node.ptr, "parametrization", NODE_PRINCIPLED_HAIR_NUM, NODE_PRINCIPLED_HAIR_REFLECTANCE);
- node = principled_hair;
- }
- else if(b_node.is_a(&RNA_ShaderNodeBsdfPrincipled)) {
- BL::ShaderNodeBsdfPrincipled b_principled_node(b_node);
- PrincipledBsdfNode *principled = new PrincipledBsdfNode();
- switch (b_principled_node.distribution()) {
- case BL::ShaderNodeBsdfPrincipled::distribution_GGX:
- principled->distribution = CLOSURE_BSDF_MICROFACET_GGX_GLASS_ID;
- break;
- case BL::ShaderNodeBsdfPrincipled::distribution_MULTI_GGX:
- principled->distribution = CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID;
- break;
- }
- switch (b_principled_node.subsurface_method()) {
- case BL::ShaderNodeBsdfPrincipled::subsurface_method_BURLEY:
- principled->subsurface_method = CLOSURE_BSSRDF_PRINCIPLED_ID;
- break;
- case BL::ShaderNodeBsdfPrincipled::subsurface_method_RANDOM_WALK:
- principled->subsurface_method = CLOSURE_BSSRDF_PRINCIPLED_RANDOM_WALK_ID;
- break;
- }
- node = principled;
- }
- else if(b_node.is_a(&RNA_ShaderNodeBsdfTranslucent)) {
- node = new TranslucentBsdfNode();
- }
- else if(b_node.is_a(&RNA_ShaderNodeBsdfTransparent)) {
- node = new TransparentBsdfNode();
- }
- else if(b_node.is_a(&RNA_ShaderNodeBsdfVelvet)) {
- node = new VelvetBsdfNode();
- }
- else if(b_node.is_a(&RNA_ShaderNodeEmission)) {
- node = new EmissionNode();
- }
- else if(b_node.is_a(&RNA_ShaderNodeAmbientOcclusion)) {
- BL::ShaderNodeAmbientOcclusion b_ao_node(b_node);
- AmbientOcclusionNode *ao = new AmbientOcclusionNode();
- ao->samples = b_ao_node.samples();
- ao->inside = b_ao_node.inside();
- ao->only_local = b_ao_node.only_local();
- node = ao;
- }
- else if(b_node.is_a(&RNA_ShaderNodeVolumeScatter)) {
- node = new ScatterVolumeNode();
- }
- else if(b_node.is_a(&RNA_ShaderNodeVolumeAbsorption)) {
- node = new AbsorptionVolumeNode();
- }
- else if(b_node.is_a(&RNA_ShaderNodeVolumePrincipled)) {
- PrincipledVolumeNode *principled = new PrincipledVolumeNode();
- node = principled;
- }
- else if(b_node.is_a(&RNA_ShaderNodeNewGeometry)) {
- node = new GeometryNode();
- }
- else if(b_node.is_a(&RNA_ShaderNodeWireframe)) {
- BL::ShaderNodeWireframe b_wireframe_node(b_node);
- WireframeNode *wire = new WireframeNode();
- wire->use_pixel_size = b_wireframe_node.use_pixel_size();
- node = wire;
- }
- else if(b_node.is_a(&RNA_ShaderNodeWavelength)) {
- node = new WavelengthNode();
- }
- else if(b_node.is_a(&RNA_ShaderNodeBlackbody)) {
- node = new BlackbodyNode();
- }
- else if(b_node.is_a(&RNA_ShaderNodeLightPath)) {
- node = new LightPathNode();
- }
- else if(b_node.is_a(&RNA_ShaderNodeLightFalloff)) {
- node = new LightFalloffNode();
- }
- else if(b_node.is_a(&RNA_ShaderNodeObjectInfo)) {
- node = new ObjectInfoNode();
- }
- else if(b_node.is_a(&RNA_ShaderNodeParticleInfo)) {
- node = new ParticleInfoNode();
- }
- else if(b_node.is_a(&RNA_ShaderNodeHairInfo)) {
- node = new HairInfoNode();
- }
- else if(b_node.is_a(&RNA_ShaderNodeBump)) {
- BL::ShaderNodeBump b_bump_node(b_node);
- BumpNode *bump = new BumpNode();
- bump->invert = b_bump_node.invert();
- node = bump;
- }
- else if(b_node.is_a(&RNA_ShaderNodeScript)) {
+ ShaderNode *node = NULL;
+
+ /* existing blender nodes */
+ if (b_node.is_a(&RNA_ShaderNodeRGBCurve)) {
+ BL::ShaderNodeRGBCurve b_curve_node(b_node);
+ BL::CurveMapping mapping(b_curve_node.mapping());
+ RGBCurvesNode *curves = new RGBCurvesNode();
+ curvemapping_color_to_array(mapping, curves->curves, RAMP_TABLE_SIZE, true);
+ curvemapping_minmax(mapping, true, &curves->min_x, &curves->max_x);
+ node = curves;
+ }
+ if (b_node.is_a(&RNA_ShaderNodeVectorCurve)) {
+ BL::ShaderNodeVectorCurve b_curve_node(b_node);
+ BL::CurveMapping mapping(b_curve_node.mapping());
+ VectorCurvesNode *curves = new VectorCurvesNode();
+ curvemapping_color_to_array(mapping, curves->curves, RAMP_TABLE_SIZE, false);
+ curvemapping_minmax(mapping, false, &curves->min_x, &curves->max_x);
+ node = curves;
+ }
+ else if (b_node.is_a(&RNA_ShaderNodeValToRGB)) {
+ RGBRampNode *ramp = new RGBRampNode();
+ BL::ShaderNodeValToRGB b_ramp_node(b_node);
+ BL::ColorRamp b_color_ramp(b_ramp_node.color_ramp());
+ colorramp_to_array(b_color_ramp, ramp->ramp, ramp->ramp_alpha, RAMP_TABLE_SIZE);
+ ramp->interpolate = b_color_ramp.interpolation() != BL::ColorRamp::interpolation_CONSTANT;
+ node = ramp;
+ }
+ else if (b_node.is_a(&RNA_ShaderNodeRGB)) {
+ ColorNode *color = new ColorNode();
+ color->value = get_node_output_rgba(b_node, "Color");
+ node = color;
+ }
+ else if (b_node.is_a(&RNA_ShaderNodeValue)) {
+ ValueNode *value = new ValueNode();
+ value->value = get_node_output_value(b_node, "Value");
+ node = value;
+ }
+ else if (b_node.is_a(&RNA_ShaderNodeCameraData)) {
+ node = new CameraNode();
+ }
+ else if (b_node.is_a(&RNA_ShaderNodeInvert)) {
+ node = new InvertNode();
+ }
+ else if (b_node.is_a(&RNA_ShaderNodeGamma)) {
+ node = new GammaNode();
+ }
+ else if (b_node.is_a(&RNA_ShaderNodeBrightContrast)) {
+ node = new BrightContrastNode();
+ }
+ else if (b_node.is_a(&RNA_ShaderNodeMixRGB)) {
+ BL::ShaderNodeMixRGB b_mix_node(b_node);
+ MixNode *mix = new MixNode();
+ mix->type = (NodeMix)b_mix_node.blend_type();
+ mix->use_clamp = b_mix_node.use_clamp();
+ node = mix;
+ }
+ else if (b_node.is_a(&RNA_ShaderNodeSeparateRGB)) {
+ node = new SeparateRGBNode();
+ }
+ else if (b_node.is_a(&RNA_ShaderNodeCombineRGB)) {
+ node = new CombineRGBNode();
+ }
+ else if (b_node.is_a(&RNA_ShaderNodeSeparateHSV)) {
+ node = new SeparateHSVNode();
+ }
+ else if (b_node.is_a(&RNA_ShaderNodeCombineHSV)) {
+ node = new CombineHSVNode();
+ }
+ else if (b_node.is_a(&RNA_ShaderNodeSeparateXYZ)) {
+ node = new SeparateXYZNode();
+ }
+ else if (b_node.is_a(&RNA_ShaderNodeCombineXYZ)) {
+ node = new CombineXYZNode();
+ }
+ else if (b_node.is_a(&RNA_ShaderNodeHueSaturation)) {
+ node = new HSVNode();
+ }
+ else if (b_node.is_a(&RNA_ShaderNodeRGBToBW)) {
+ node = new RGBToBWNode();
+ }
+ else if (b_node.is_a(&RNA_ShaderNodeMath)) {
+ BL::ShaderNodeMath b_math_node(b_node);
+ MathNode *math = new MathNode();
+ math->type = (NodeMath)b_math_node.operation();
+ math->use_clamp = b_math_node.use_clamp();
+ node = math;
+ }
+ else if (b_node.is_a(&RNA_ShaderNodeVectorMath)) {
+ BL::ShaderNodeVectorMath b_vector_math_node(b_node);
+ VectorMathNode *vmath = new VectorMathNode();
+ vmath->type = (NodeVectorMath)b_vector_math_node.operation();
+ node = vmath;
+ }
+ else if (b_node.is_a(&RNA_ShaderNodeVectorTransform)) {
+ BL::ShaderNodeVectorTransform b_vector_transform_node(b_node);
+ VectorTransformNode *vtransform = new VectorTransformNode();
+ vtransform->type = (NodeVectorTransformType)b_vector_transform_node.vector_type();
+ vtransform->convert_from = (NodeVectorTransformConvertSpace)
+ b_vector_transform_node.convert_from();
+ vtransform->convert_to = (NodeVectorTransformConvertSpace)b_vector_transform_node.convert_to();
+ node = vtransform;
+ }
+ else if (b_node.is_a(&RNA_ShaderNodeNormal)) {
+ BL::Node::outputs_iterator out_it;
+ b_node.outputs.begin(out_it);
+
+ NormalNode *norm = new NormalNode();
+ norm->direction = get_node_output_vector(b_node, "Normal");
+ node = norm;
+ }
+ else if (b_node.is_a(&RNA_ShaderNodeMapping)) {
+ BL::ShaderNodeMapping b_mapping_node(b_node);
+ MappingNode *mapping = new MappingNode();
+
+ get_tex_mapping(&mapping->tex_mapping, b_mapping_node);
+
+ node = mapping;
+ }
+ else if (b_node.is_a(&RNA_ShaderNodeFresnel)) {
+ node = new FresnelNode();
+ }
+ else if (b_node.is_a(&RNA_ShaderNodeLayerWeight)) {
+ node = new LayerWeightNode();
+ }
+ else if (b_node.is_a(&RNA_ShaderNodeAddShader)) {
+ node = new AddClosureNode();
+ }
+ else if (b_node.is_a(&RNA_ShaderNodeMixShader)) {
+ node = new MixClosureNode();
+ }
+ else if (b_node.is_a(&RNA_ShaderNodeAttribute)) {
+ BL::ShaderNodeAttribute b_attr_node(b_node);
+ AttributeNode *attr = new AttributeNode();
+ attr->attribute = b_attr_node.attribute_name();
+ node = attr;
+ }
+ else if (b_node.is_a(&RNA_ShaderNodeBackground)) {
+ node = new BackgroundNode();
+ }
+ else if (b_node.is_a(&RNA_ShaderNodeHoldout)) {
+ node = new HoldoutNode();
+ }
+ else if (b_node.is_a(&RNA_ShaderNodeBsdfAnisotropic)) {
+ BL::ShaderNodeBsdfAnisotropic b_aniso_node(b_node);
+ AnisotropicBsdfNode *aniso = new AnisotropicBsdfNode();
+
+ switch (b_aniso_node.distribution()) {
+ case BL::ShaderNodeBsdfAnisotropic::distribution_BECKMANN:
+ aniso->distribution = CLOSURE_BSDF_MICROFACET_BECKMANN_ANISO_ID;
+ break;
+ case BL::ShaderNodeBsdfAnisotropic::distribution_GGX:
+ aniso->distribution = CLOSURE_BSDF_MICROFACET_GGX_ANISO_ID;
+ break;
+ case BL::ShaderNodeBsdfAnisotropic::distribution_MULTI_GGX:
+ aniso->distribution = CLOSURE_BSDF_MICROFACET_MULTI_GGX_ANISO_ID;
+ break;
+ case BL::ShaderNodeBsdfAnisotropic::distribution_ASHIKHMIN_SHIRLEY:
+ aniso->distribution = CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ANISO_ID;
+ break;
+ }
+
+ node = aniso;
+ }
+ else if (b_node.is_a(&RNA_ShaderNodeBsdfDiffuse)) {
+ node = new DiffuseBsdfNode();
+ }
+ else if (b_node.is_a(&RNA_ShaderNodeSubsurfaceScattering)) {
+ BL::ShaderNodeSubsurfaceScattering b_subsurface_node(b_node);
+
+ SubsurfaceScatteringNode *subsurface = new SubsurfaceScatteringNode();
+
+ switch (b_subsurface_node.falloff()) {
+ case BL::ShaderNodeSubsurfaceScattering::falloff_CUBIC:
+ subsurface->falloff = CLOSURE_BSSRDF_CUBIC_ID;
+ break;
+ case BL::ShaderNodeSubsurfaceScattering::falloff_GAUSSIAN:
+ subsurface->falloff = CLOSURE_BSSRDF_GAUSSIAN_ID;
+ break;
+ case BL::ShaderNodeSubsurfaceScattering::falloff_BURLEY:
+ subsurface->falloff = CLOSURE_BSSRDF_BURLEY_ID;
+ break;
+ case BL::ShaderNodeSubsurfaceScattering::falloff_RANDOM_WALK:
+ subsurface->falloff = CLOSURE_BSSRDF_RANDOM_WALK_ID;
+ break;
+ }
+
+ node = subsurface;
+ }
+ else if (b_node.is_a(&RNA_ShaderNodeBsdfGlossy)) {
+ BL::ShaderNodeBsdfGlossy b_glossy_node(b_node);
+ GlossyBsdfNode *glossy = new GlossyBsdfNode();
+
+ switch (b_glossy_node.distribution()) {
+ case BL::ShaderNodeBsdfGlossy::distribution_SHARP:
+ glossy->distribution = CLOSURE_BSDF_REFLECTION_ID;
+ break;
+ case BL::ShaderNodeBsdfGlossy::distribution_BECKMANN:
+ glossy->distribution = CLOSURE_BSDF_MICROFACET_BECKMANN_ID;
+ break;
+ case BL::ShaderNodeBsdfGlossy::distribution_GGX:
+ glossy->distribution = CLOSURE_BSDF_MICROFACET_GGX_ID;
+ break;
+ case BL::ShaderNodeBsdfGlossy::distribution_ASHIKHMIN_SHIRLEY:
+ glossy->distribution = CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ID;
+ break;
+ case BL::ShaderNodeBsdfGlossy::distribution_MULTI_GGX:
+ glossy->distribution = CLOSURE_BSDF_MICROFACET_MULTI_GGX_ID;
+ break;
+ }
+ node = glossy;
+ }
+ else if (b_node.is_a(&RNA_ShaderNodeBsdfGlass)) {
+ BL::ShaderNodeBsdfGlass b_glass_node(b_node);
+ GlassBsdfNode *glass = new GlassBsdfNode();
+ switch (b_glass_node.distribution()) {
+ case BL::ShaderNodeBsdfGlass::distribution_SHARP:
+ glass->distribution = CLOSURE_BSDF_SHARP_GLASS_ID;
+ break;
+ case BL::ShaderNodeBsdfGlass::distribution_BECKMANN:
+ glass->distribution = CLOSURE_BSDF_MICROFACET_BECKMANN_GLASS_ID;
+ break;
+ case BL::ShaderNodeBsdfGlass::distribution_GGX:
+ glass->distribution = CLOSURE_BSDF_MICROFACET_GGX_GLASS_ID;
+ break;
+ case BL::ShaderNodeBsdfGlass::distribution_MULTI_GGX:
+ glass->distribution = CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID;
+ break;
+ }
+ node = glass;
+ }
+ else if (b_node.is_a(&RNA_ShaderNodeBsdfRefraction)) {
+ BL::ShaderNodeBsdfRefraction b_refraction_node(b_node);
+ RefractionBsdfNode *refraction = new RefractionBsdfNode();
+ switch (b_refraction_node.distribution()) {
+ case BL::ShaderNodeBsdfRefraction::distribution_SHARP:
+ refraction->distribution = CLOSURE_BSDF_REFRACTION_ID;
+ break;
+ case BL::ShaderNodeBsdfRefraction::distribution_BECKMANN:
+ refraction->distribution = CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID;
+ break;
+ case BL::ShaderNodeBsdfRefraction::distribution_GGX:
+ refraction->distribution = CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID;
+ break;
+ }
+ node = refraction;
+ }
+ else if (b_node.is_a(&RNA_ShaderNodeBsdfToon)) {
+ BL::ShaderNodeBsdfToon b_toon_node(b_node);
+ ToonBsdfNode *toon = new ToonBsdfNode();
+ switch (b_toon_node.component()) {
+ case BL::ShaderNodeBsdfToon::component_DIFFUSE:
+ toon->component = CLOSURE_BSDF_DIFFUSE_TOON_ID;
+ break;
+ case BL::ShaderNodeBsdfToon::component_GLOSSY:
+ toon->component = CLOSURE_BSDF_GLOSSY_TOON_ID;
+ break;
+ }
+ node = toon;
+ }
+ else if (b_node.is_a(&RNA_ShaderNodeBsdfHair)) {
+ BL::ShaderNodeBsdfHair b_hair_node(b_node);
+ HairBsdfNode *hair = new HairBsdfNode();
+ switch (b_hair_node.component()) {
+ case BL::ShaderNodeBsdfHair::component_Reflection:
+ hair->component = CLOSURE_BSDF_HAIR_REFLECTION_ID;
+ break;
+ case BL::ShaderNodeBsdfHair::component_Transmission:
+ hair->component = CLOSURE_BSDF_HAIR_TRANSMISSION_ID;
+ break;
+ }
+ node = hair;
+ }
+ else if (b_node.is_a(&RNA_ShaderNodeBsdfHairPrincipled)) {
+ BL::ShaderNodeBsdfHairPrincipled b_principled_hair_node(b_node);
+ PrincipledHairBsdfNode *principled_hair = new PrincipledHairBsdfNode();
+ principled_hair->parametrization = (NodePrincipledHairParametrization)get_enum(
+ b_principled_hair_node.ptr,
+ "parametrization",
+ NODE_PRINCIPLED_HAIR_NUM,
+ NODE_PRINCIPLED_HAIR_REFLECTANCE);
+ node = principled_hair;
+ }
+ else if (b_node.is_a(&RNA_ShaderNodeBsdfPrincipled)) {
+ BL::ShaderNodeBsdfPrincipled b_principled_node(b_node);
+ PrincipledBsdfNode *principled = new PrincipledBsdfNode();
+ switch (b_principled_node.distribution()) {
+ case BL::ShaderNodeBsdfPrincipled::distribution_GGX:
+ principled->distribution = CLOSURE_BSDF_MICROFACET_GGX_GLASS_ID;
+ break;
+ case BL::ShaderNodeBsdfPrincipled::distribution_MULTI_GGX:
+ principled->distribution = CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID;
+ break;
+ }
+ switch (b_principled_node.subsurface_method()) {
+ case BL::ShaderNodeBsdfPrincipled::subsurface_method_BURLEY:
+ principled->subsurface_method = CLOSURE_BSSRDF_PRINCIPLED_ID;
+ break;
+ case BL::ShaderNodeBsdfPrincipled::subsurface_method_RANDOM_WALK:
+ principled->subsurface_method = CLOSURE_BSSRDF_PRINCIPLED_RANDOM_WALK_ID;
+ break;
+ }
+ node = principled;
+ }
+ else if (b_node.is_a(&RNA_ShaderNodeBsdfTranslucent)) {
+ node = new TranslucentBsdfNode();
+ }
+ else if (b_node.is_a(&RNA_ShaderNodeBsdfTransparent)) {
+ node = new TransparentBsdfNode();
+ }
+ else if (b_node.is_a(&RNA_ShaderNodeBsdfVelvet)) {
+ node = new VelvetBsdfNode();
+ }
+ else if (b_node.is_a(&RNA_ShaderNodeEmission)) {
+ node = new EmissionNode();
+ }
+ else if (b_node.is_a(&RNA_ShaderNodeAmbientOcclusion)) {
+ BL::ShaderNodeAmbientOcclusion b_ao_node(b_node);
+ AmbientOcclusionNode *ao = new AmbientOcclusionNode();
+ ao->samples = b_ao_node.samples();
+ ao->inside = b_ao_node.inside();
+ ao->only_local = b_ao_node.only_local();
+ node = ao;
+ }
+ else if (b_node.is_a(&RNA_ShaderNodeVolumeScatter)) {
+ node = new ScatterVolumeNode();
+ }
+ else if (b_node.is_a(&RNA_ShaderNodeVolumeAbsorption)) {
+ node = new AbsorptionVolumeNode();
+ }
+ else if (b_node.is_a(&RNA_ShaderNodeVolumePrincipled)) {
+ PrincipledVolumeNode *principled = new PrincipledVolumeNode();
+ node = principled;
+ }
+ else if (b_node.is_a(&RNA_ShaderNodeNewGeometry)) {
+ node = new GeometryNode();
+ }
+ else if (b_node.is_a(&RNA_ShaderNodeWireframe)) {
+ BL::ShaderNodeWireframe b_wireframe_node(b_node);
+ WireframeNode *wire = new WireframeNode();
+ wire->use_pixel_size = b_wireframe_node.use_pixel_size();
+ node = wire;
+ }
+ else if (b_node.is_a(&RNA_ShaderNodeWavelength)) {
+ node = new WavelengthNode();
+ }
+ else if (b_node.is_a(&RNA_ShaderNodeBlackbody)) {
+ node = new BlackbodyNode();
+ }
+ else if (b_node.is_a(&RNA_ShaderNodeLightPath)) {
+ node = new LightPathNode();
+ }
+ else if (b_node.is_a(&RNA_ShaderNodeLightFalloff)) {
+ node = new LightFalloffNode();
+ }
+ else if (b_node.is_a(&RNA_ShaderNodeObjectInfo)) {
+ node = new ObjectInfoNode();
+ }
+ else if (b_node.is_a(&RNA_ShaderNodeParticleInfo)) {
+ node = new ParticleInfoNode();
+ }
+ else if (b_node.is_a(&RNA_ShaderNodeHairInfo)) {
+ node = new HairInfoNode();
+ }
+ else if (b_node.is_a(&RNA_ShaderNodeBump)) {
+ BL::ShaderNodeBump b_bump_node(b_node);
+ BumpNode *bump = new BumpNode();
+ bump->invert = b_bump_node.invert();
+ node = bump;
+ }
+ else if (b_node.is_a(&RNA_ShaderNodeScript)) {
#ifdef WITH_OSL
- if(scene->shader_manager->use_osl()) {
- /* create script node */
- BL::ShaderNodeScript b_script_node(b_node);
-
- OSLShaderManager *manager = (OSLShaderManager*)scene->shader_manager;
- string bytecode_hash = b_script_node.bytecode_hash();
-
- if(!bytecode_hash.empty()) {
- node = manager->osl_node("", bytecode_hash, b_script_node.bytecode());
- }
- else {
- string absolute_filepath = blender_absolute_path(b_data, b_ntree, b_script_node.filepath());
- node = manager->osl_node(absolute_filepath, "");
- }
- }
+ if (scene->shader_manager->use_osl()) {
+ /* create script node */
+ BL::ShaderNodeScript b_script_node(b_node);
+
+ OSLShaderManager *manager = (OSLShaderManager *)scene->shader_manager;
+ string bytecode_hash = b_script_node.bytecode_hash();
+
+ if (!bytecode_hash.empty()) {
+ node = manager->osl_node("", bytecode_hash, b_script_node.bytecode());
+ }
+ else {
+ string absolute_filepath = blender_absolute_path(
+ b_data, b_ntree, b_script_node.filepath());
+ node = manager->osl_node(absolute_filepath, "");
+ }
+ }
#else
- (void) b_data;
- (void) b_ntree;
+ (void)b_data;
+ (void)b_ntree;
#endif
- }
- else if(b_node.is_a(&RNA_ShaderNodeTexImage)) {
- BL::ShaderNodeTexImage b_image_node(b_node);
- BL::Image b_image(b_image_node.image());
- BL::ImageUser b_image_user(b_image_node.image_user());
- ImageTextureNode *image = new ImageTextureNode();
- if(b_image) {
- /* builtin images will use callback-based reading because
- * they could only be loaded correct from blender side
- */
- bool is_builtin = b_image.packed_file() ||
- b_image.source() == BL::Image::source_GENERATED ||
- b_image.source() == BL::Image::source_MOVIE ||
- (b_engine.is_preview() &&
- b_image.source() != BL::Image::source_SEQUENCE);
-
- if(is_builtin) {
- /* for builtin images we're using image datablock name to find an image to
- * read pixels from later
- *
- * also store frame number as well, so there's no differences in handling
- * builtin names for packed images and movies
- */
- int scene_frame = b_scene.frame_current();
- int image_frame = image_user_frame_number(b_image_user,
- scene_frame);
- image->filename = b_image.name() + "@" + string_printf("%d", image_frame);
- image->builtin_data = b_image.ptr.data;
- }
- else {
- image->filename = image_user_file_path(b_image_user,
- b_image,
- b_scene.frame_current());
- image->builtin_data = NULL;
- }
-
- image->animated = b_image_node.image_user().use_auto_refresh();
- image->use_alpha = b_image.use_alpha();
-
- /* TODO: restore */
- /* TODO(sergey): Does not work properly when we change builtin type. */
+ }
+ else if (b_node.is_a(&RNA_ShaderNodeTexImage)) {
+ BL::ShaderNodeTexImage b_image_node(b_node);
+ BL::Image b_image(b_image_node.image());
+ BL::ImageUser b_image_user(b_image_node.image_user());
+ ImageTextureNode *image = new ImageTextureNode();
+ if (b_image) {
+ /* builtin images will use callback-based reading because
+ * they could only be loaded correct from blender side
+ */
+ bool is_builtin = b_image.packed_file() || b_image.source() == BL::Image::source_GENERATED ||
+ b_image.source() == BL::Image::source_MOVIE ||
+ (b_engine.is_preview() && b_image.source() != BL::Image::source_SEQUENCE);
+
+ if (is_builtin) {
+ /* for builtin images we're using image datablock name to find an image to
+ * read pixels from later
+ *
+ * also store frame number as well, so there's no differences in handling
+ * builtin names for packed images and movies
+ */
+ int scene_frame = b_scene.frame_current();
+ int image_frame = image_user_frame_number(b_image_user, scene_frame);
+ image->filename = b_image.name() + "@" + string_printf("%d", image_frame);
+ image->builtin_data = b_image.ptr.data;
+ }
+ else {
+ image->filename = image_user_file_path(b_image_user, b_image, b_scene.frame_current());
+ image->builtin_data = NULL;
+ }
+
+ image->animated = b_image_node.image_user().use_auto_refresh();
+ image->use_alpha = b_image.use_alpha();
+
+ /* TODO: restore */
+ /* TODO(sergey): Does not work properly when we change builtin type. */
#if 0
- if(b_image.is_updated()) {
- scene->image_manager->tag_reload_image(
- image->filename.string(),
- image->builtin_data,
- get_image_interpolation(b_image_node),
- get_image_extension(b_image_node),
- image->use_alpha);
- }
+ if(b_image.is_updated()) {
+ scene->image_manager->tag_reload_image(
+ image->filename.string(),
+ image->builtin_data,
+ get_image_interpolation(b_image_node),
+ get_image_extension(b_image_node),
+ image->use_alpha);
+ }
#endif
- }
- image->color_space = (NodeImageColorSpace)b_image_node.color_space();
- image->projection = (NodeImageProjection)b_image_node.projection();
- image->interpolation = get_image_interpolation(b_image_node);
- image->extension = get_image_extension(b_image_node);
- image->projection_blend = b_image_node.projection_blend();
- BL::TexMapping b_texture_mapping(b_image_node.texture_mapping());
- get_tex_mapping(&image->tex_mapping, b_texture_mapping);
- node = image;
- }
- else if(b_node.is_a(&RNA_ShaderNodeTexEnvironment)) {
- BL::ShaderNodeTexEnvironment b_env_node(b_node);
- BL::Image b_image(b_env_node.image());
- BL::ImageUser b_image_user(b_env_node.image_user());
- EnvironmentTextureNode *env = new EnvironmentTextureNode();
- if(b_image) {
- bool is_builtin = b_image.packed_file() ||
- b_image.source() == BL::Image::source_GENERATED ||
- b_image.source() == BL::Image::source_MOVIE ||
- (b_engine.is_preview() &&
- b_image.source() != BL::Image::source_SEQUENCE);
-
- if(is_builtin) {
- int scene_frame = b_scene.frame_current();
- int image_frame = image_user_frame_number(b_image_user,
- scene_frame);
- env->filename = b_image.name() + "@" + string_printf("%d", image_frame);
- env->builtin_data = b_image.ptr.data;
- }
- else {
- env->filename = image_user_file_path(b_image_user,
- b_image,
- b_scene.frame_current());
- env->builtin_data = NULL;
- }
-
- env->animated = b_env_node.image_user().use_auto_refresh();
- env->use_alpha = b_image.use_alpha();
-
- /* TODO: restore */
- /* TODO(sergey): Does not work properly when we change builtin type. */
+ }
+ image->color_space = (NodeImageColorSpace)b_image_node.color_space();
+ image->projection = (NodeImageProjection)b_image_node.projection();
+ image->interpolation = get_image_interpolation(b_image_node);
+ image->extension = get_image_extension(b_image_node);
+ image->projection_blend = b_image_node.projection_blend();
+ BL::TexMapping b_texture_mapping(b_image_node.texture_mapping());
+ get_tex_mapping(&image->tex_mapping, b_texture_mapping);
+ node = image;
+ }
+ else if (b_node.is_a(&RNA_ShaderNodeTexEnvironment)) {
+ BL::ShaderNodeTexEnvironment b_env_node(b_node);
+ BL::Image b_image(b_env_node.image());
+ BL::ImageUser b_image_user(b_env_node.image_user());
+ EnvironmentTextureNode *env = new EnvironmentTextureNode();
+ if (b_image) {
+ bool is_builtin = b_image.packed_file() || b_image.source() == BL::Image::source_GENERATED ||
+ b_image.source() == BL::Image::source_MOVIE ||
+ (b_engine.is_preview() && b_image.source() != BL::Image::source_SEQUENCE);
+
+ if (is_builtin) {
+ int scene_frame = b_scene.frame_current();
+ int image_frame = image_user_frame_number(b_image_user, scene_frame);
+ env->filename = b_image.name() + "@" + string_printf("%d", image_frame);
+ env->builtin_data = b_image.ptr.data;
+ }
+ else {
+ env->filename = image_user_file_path(b_image_user, b_image, b_scene.frame_current());
+ env->builtin_data = NULL;
+ }
+
+ env->animated = b_env_node.image_user().use_auto_refresh();
+ env->use_alpha = b_image.use_alpha();
+
+ /* TODO: restore */
+ /* TODO(sergey): Does not work properly when we change builtin type. */
#if 0
- if(b_image.is_updated()) {
- scene->image_manager->tag_reload_image(
- env->filename.string(),
- env->builtin_data,
- get_image_interpolation(b_env_node),
- EXTENSION_REPEAT,
- env->use_alpha);
- }
+ if(b_image.is_updated()) {
+ scene->image_manager->tag_reload_image(
+ env->filename.string(),
+ env->builtin_data,
+ get_image_interpolation(b_env_node),
+ EXTENSION_REPEAT,
+ env->use_alpha);
+ }
#endif
- }
- env->color_space = (NodeImageColorSpace)b_env_node.color_space();
- env->interpolation = get_image_interpolation(b_env_node);
- env->projection = (NodeEnvironmentProjection)b_env_node.projection();
- BL::TexMapping b_texture_mapping(b_env_node.texture_mapping());
- get_tex_mapping(&env->tex_mapping, b_texture_mapping);
- node = env;
- }
- else if(b_node.is_a(&RNA_ShaderNodeTexGradient)) {
- BL::ShaderNodeTexGradient b_gradient_node(b_node);
- GradientTextureNode *gradient = new GradientTextureNode();
- gradient->type = (NodeGradientType)b_gradient_node.gradient_type();
- BL::TexMapping b_texture_mapping(b_gradient_node.texture_mapping());
- get_tex_mapping(&gradient->tex_mapping, b_texture_mapping);
- node = gradient;
- }
- else if(b_node.is_a(&RNA_ShaderNodeTexVoronoi)) {
- BL::ShaderNodeTexVoronoi b_voronoi_node(b_node);
- VoronoiTextureNode *voronoi = new VoronoiTextureNode();
- voronoi->coloring = (NodeVoronoiColoring)b_voronoi_node.coloring();
- voronoi->metric = (NodeVoronoiDistanceMetric)b_voronoi_node.distance();
- voronoi->feature = (NodeVoronoiFeature)b_voronoi_node.feature();
- BL::TexMapping b_texture_mapping(b_voronoi_node.texture_mapping());
- get_tex_mapping(&voronoi->tex_mapping, b_texture_mapping);
- node = voronoi;
- }
- else if(b_node.is_a(&RNA_ShaderNodeTexMagic)) {
- BL::ShaderNodeTexMagic b_magic_node(b_node);
- MagicTextureNode *magic = new MagicTextureNode();
- magic->depth = b_magic_node.turbulence_depth();
- BL::TexMapping b_texture_mapping(b_magic_node.texture_mapping());
- get_tex_mapping(&magic->tex_mapping, b_texture_mapping);
- node = magic;
- }
- else if(b_node.is_a(&RNA_ShaderNodeTexWave)) {
- BL::ShaderNodeTexWave b_wave_node(b_node);
- WaveTextureNode *wave = new WaveTextureNode();
- wave->type = (NodeWaveType)b_wave_node.wave_type();
- wave->profile = (NodeWaveProfile)b_wave_node.wave_profile();
- BL::TexMapping b_texture_mapping(b_wave_node.texture_mapping());
- get_tex_mapping(&wave->tex_mapping, b_texture_mapping);
- node = wave;
- }
- else if(b_node.is_a(&RNA_ShaderNodeTexChecker)) {
- BL::ShaderNodeTexChecker b_checker_node(b_node);
- CheckerTextureNode *checker = new CheckerTextureNode();
- BL::TexMapping b_texture_mapping(b_checker_node.texture_mapping());
- get_tex_mapping(&checker->tex_mapping, b_texture_mapping);
- node = checker;
- }
- else if(b_node.is_a(&RNA_ShaderNodeTexBrick)) {
- BL::ShaderNodeTexBrick b_brick_node(b_node);
- BrickTextureNode *brick = new BrickTextureNode();
- brick->offset = b_brick_node.offset();
- brick->offset_frequency = b_brick_node.offset_frequency();
- brick->squash = b_brick_node.squash();
- brick->squash_frequency = b_brick_node.squash_frequency();
- BL::TexMapping b_texture_mapping(b_brick_node.texture_mapping());
- get_tex_mapping(&brick->tex_mapping, b_texture_mapping);
- node = brick;
- }
- else if(b_node.is_a(&RNA_ShaderNodeTexNoise)) {
- BL::ShaderNodeTexNoise b_noise_node(b_node);
- NoiseTextureNode *noise = new NoiseTextureNode();
- BL::TexMapping b_texture_mapping(b_noise_node.texture_mapping());
- get_tex_mapping(&noise->tex_mapping, b_texture_mapping);
- node = noise;
- }
- else if(b_node.is_a(&RNA_ShaderNodeTexMusgrave)) {
- BL::ShaderNodeTexMusgrave b_musgrave_node(b_node);
- MusgraveTextureNode *musgrave = new MusgraveTextureNode();
- musgrave->type = (NodeMusgraveType)b_musgrave_node.musgrave_type();
- BL::TexMapping b_texture_mapping(b_musgrave_node.texture_mapping());
- get_tex_mapping(&musgrave->tex_mapping, b_texture_mapping);
- node = musgrave;
- }
- else if(b_node.is_a(&RNA_ShaderNodeTexCoord)) {
- BL::ShaderNodeTexCoord b_tex_coord_node(b_node);
- TextureCoordinateNode *tex_coord = new TextureCoordinateNode();
- tex_coord->from_dupli = b_tex_coord_node.from_instancer();
- if(b_tex_coord_node.object()) {
- tex_coord->use_transform = true;
- tex_coord->ob_tfm = get_transform(b_tex_coord_node.object().matrix_world());
- }
- node = tex_coord;
- }
- else if(b_node.is_a(&RNA_ShaderNodeTexSky)) {
- BL::ShaderNodeTexSky b_sky_node(b_node);
- SkyTextureNode *sky = new SkyTextureNode();
- sky->type = (NodeSkyType)b_sky_node.sky_type();
- sky->sun_direction = normalize(get_float3(b_sky_node.sun_direction()));
- sky->turbidity = b_sky_node.turbidity();
- sky->ground_albedo = b_sky_node.ground_albedo();
- BL::TexMapping b_texture_mapping(b_sky_node.texture_mapping());
- get_tex_mapping(&sky->tex_mapping, b_texture_mapping);
- node = sky;
- }
- else if(b_node.is_a(&RNA_ShaderNodeTexIES)) {
- BL::ShaderNodeTexIES b_ies_node(b_node);
- IESLightNode *ies = new IESLightNode();
- switch(b_ies_node.mode()) {
- case BL::ShaderNodeTexIES::mode_EXTERNAL:
- ies->filename = blender_absolute_path(b_data, b_ntree, b_ies_node.filepath());
- break;
- case BL::ShaderNodeTexIES::mode_INTERNAL:
- ies->ies = get_text_datablock_content(b_ies_node.ies().ptr);
- if(ies->ies.empty()) {
- ies->ies = "\n";
- }
- break;
- }
- node = ies;
- }
- else if(b_node.is_a(&RNA_ShaderNodeNormalMap)) {
- BL::ShaderNodeNormalMap b_normal_map_node(b_node);
- NormalMapNode *nmap = new NormalMapNode();
- nmap->space = (NodeNormalMapSpace)b_normal_map_node.space();
- nmap->attribute = b_normal_map_node.uv_map();
- node = nmap;
- }
- else if(b_node.is_a(&RNA_ShaderNodeTangent)) {
- BL::ShaderNodeTangent b_tangent_node(b_node);
- TangentNode *tangent = new TangentNode();
- tangent->direction_type = (NodeTangentDirectionType)b_tangent_node.direction_type();
- tangent->axis = (NodeTangentAxis)b_tangent_node.axis();
- tangent->attribute = b_tangent_node.uv_map();
- node = tangent;
- }
- else if(b_node.is_a(&RNA_ShaderNodeUVMap)) {
- BL::ShaderNodeUVMap b_uvmap_node(b_node);
- UVMapNode *uvm = new UVMapNode();
- uvm->attribute = b_uvmap_node.uv_map();
- uvm->from_dupli = b_uvmap_node.from_instancer();
- node = uvm;
- }
- else if(b_node.is_a(&RNA_ShaderNodeTexPointDensity)) {
- BL::ShaderNodeTexPointDensity b_point_density_node(b_node);
- PointDensityTextureNode *point_density = new PointDensityTextureNode();
- point_density->filename = b_point_density_node.name();
- point_density->space = (NodeTexVoxelSpace)b_point_density_node.space();
- point_density->interpolation = get_image_interpolation(b_point_density_node);
- point_density->builtin_data = b_point_density_node.ptr.data;
- point_density->image_manager = scene->image_manager;
-
- /* TODO(sergey): Use more proper update flag. */
- if(true) {
- point_density->add_image();
- b_point_density_node.cache_point_density(b_depsgraph);
- scene->image_manager->tag_reload_image(
- point_density->filename.string(),
- point_density->builtin_data,
- point_density->interpolation,
- EXTENSION_CLIP,
- true);
- }
- node = point_density;
-
- /* Transformation form world space to texture space.
- *
- * NOTE: Do this after the texture is cached, this is because getting
- * min/max will need to access this cache.
- */
- BL::Object b_ob(b_point_density_node.object());
- if(b_ob) {
- float3 loc, size;
- point_density_texture_space(b_depsgraph,
- b_point_density_node,
- loc,
- size);
- point_density->tfm =
- transform_translate(-loc) * transform_scale(size) *
- transform_inverse(get_transform(b_ob.matrix_world()));
- }
- }
- else if(b_node.is_a(&RNA_ShaderNodeBevel)) {
- BL::ShaderNodeBevel b_bevel_node(b_node);
- BevelNode *bevel = new BevelNode();
- bevel->samples = b_bevel_node.samples();
- node = bevel;
- }
- else if(b_node.is_a(&RNA_ShaderNodeDisplacement)) {
- BL::ShaderNodeDisplacement b_disp_node(b_node);
- DisplacementNode *disp = new DisplacementNode();
- disp->space = (NodeNormalMapSpace)b_disp_node.space();
- node = disp;
- }
- else if(b_node.is_a(&RNA_ShaderNodeVectorDisplacement)) {
- BL::ShaderNodeVectorDisplacement b_disp_node(b_node);
- VectorDisplacementNode *disp = new VectorDisplacementNode();
- disp->space = (NodeNormalMapSpace)b_disp_node.space();
- disp->attribute = "";
- node = disp;
- }
-
- if(node) {
- node->name = b_node.name();
- graph->add(node);
- }
-
- return node;
+ }
+ env->color_space = (NodeImageColorSpace)b_env_node.color_space();
+ env->interpolation = get_image_interpolation(b_env_node);
+ env->projection = (NodeEnvironmentProjection)b_env_node.projection();
+ BL::TexMapping b_texture_mapping(b_env_node.texture_mapping());
+ get_tex_mapping(&env->tex_mapping, b_texture_mapping);
+ node = env;
+ }
+ else if (b_node.is_a(&RNA_ShaderNodeTexGradient)) {
+ BL::ShaderNodeTexGradient b_gradient_node(b_node);
+ GradientTextureNode *gradient = new GradientTextureNode();
+ gradient->type = (NodeGradientType)b_gradient_node.gradient_type();
+ BL::TexMapping b_texture_mapping(b_gradient_node.texture_mapping());
+ get_tex_mapping(&gradient->tex_mapping, b_texture_mapping);
+ node = gradient;
+ }
+ else if (b_node.is_a(&RNA_ShaderNodeTexVoronoi)) {
+ BL::ShaderNodeTexVoronoi b_voronoi_node(b_node);
+ VoronoiTextureNode *voronoi = new VoronoiTextureNode();
+ voronoi->coloring = (NodeVoronoiColoring)b_voronoi_node.coloring();
+ voronoi->metric = (NodeVoronoiDistanceMetric)b_voronoi_node.distance();
+ voronoi->feature = (NodeVoronoiFeature)b_voronoi_node.feature();
+ BL::TexMapping b_texture_mapping(b_voronoi_node.texture_mapping());
+ get_tex_mapping(&voronoi->tex_mapping, b_texture_mapping);
+ node = voronoi;
+ }
+ else if (b_node.is_a(&RNA_ShaderNodeTexMagic)) {
+ BL::ShaderNodeTexMagic b_magic_node(b_node);
+ MagicTextureNode *magic = new MagicTextureNode();
+ magic->depth = b_magic_node.turbulence_depth();
+ BL::TexMapping b_texture_mapping(b_magic_node.texture_mapping());
+ get_tex_mapping(&magic->tex_mapping, b_texture_mapping);
+ node = magic;
+ }
+ else if (b_node.is_a(&RNA_ShaderNodeTexWave)) {
+ BL::ShaderNodeTexWave b_wave_node(b_node);
+ WaveTextureNode *wave = new WaveTextureNode();
+ wave->type = (NodeWaveType)b_wave_node.wave_type();
+ wave->profile = (NodeWaveProfile)b_wave_node.wave_profile();
+ BL::TexMapping b_texture_mapping(b_wave_node.texture_mapping());
+ get_tex_mapping(&wave->tex_mapping, b_texture_mapping);
+ node = wave;
+ }
+ else if (b_node.is_a(&RNA_ShaderNodeTexChecker)) {
+ BL::ShaderNodeTexChecker b_checker_node(b_node);
+ CheckerTextureNode *checker = new CheckerTextureNode();
+ BL::TexMapping b_texture_mapping(b_checker_node.texture_mapping());
+ get_tex_mapping(&checker->tex_mapping, b_texture_mapping);
+ node = checker;
+ }
+ else if (b_node.is_a(&RNA_ShaderNodeTexBrick)) {
+ BL::ShaderNodeTexBrick b_brick_node(b_node);
+ BrickTextureNode *brick = new BrickTextureNode();
+ brick->offset = b_brick_node.offset();
+ brick->offset_frequency = b_brick_node.offset_frequency();
+ brick->squash = b_brick_node.squash();
+ brick->squash_frequency = b_brick_node.squash_frequency();
+ BL::TexMapping b_texture_mapping(b_brick_node.texture_mapping());
+ get_tex_mapping(&brick->tex_mapping, b_texture_mapping);
+ node = brick;
+ }
+ else if (b_node.is_a(&RNA_ShaderNodeTexNoise)) {
+ BL::ShaderNodeTexNoise b_noise_node(b_node);
+ NoiseTextureNode *noise = new NoiseTextureNode();
+ BL::TexMapping b_texture_mapping(b_noise_node.texture_mapping());
+ get_tex_mapping(&noise->tex_mapping, b_texture_mapping);
+ node = noise;
+ }
+ else if (b_node.is_a(&RNA_ShaderNodeTexMusgrave)) {
+ BL::ShaderNodeTexMusgrave b_musgrave_node(b_node);
+ MusgraveTextureNode *musgrave = new MusgraveTextureNode();
+ musgrave->type = (NodeMusgraveType)b_musgrave_node.musgrave_type();
+ BL::TexMapping b_texture_mapping(b_musgrave_node.texture_mapping());
+ get_tex_mapping(&musgrave->tex_mapping, b_texture_mapping);
+ node = musgrave;
+ }
+ else if (b_node.is_a(&RNA_ShaderNodeTexCoord)) {
+ BL::ShaderNodeTexCoord b_tex_coord_node(b_node);
+ TextureCoordinateNode *tex_coord = new TextureCoordinateNode();
+ tex_coord->from_dupli = b_tex_coord_node.from_instancer();
+ if (b_tex_coord_node.object()) {
+ tex_coord->use_transform = true;
+ tex_coord->ob_tfm = get_transform(b_tex_coord_node.object().matrix_world());
+ }
+ node = tex_coord;
+ }
+ else if (b_node.is_a(&RNA_ShaderNodeTexSky)) {
+ BL::ShaderNodeTexSky b_sky_node(b_node);
+ SkyTextureNode *sky = new SkyTextureNode();
+ sky->type = (NodeSkyType)b_sky_node.sky_type();
+ sky->sun_direction = normalize(get_float3(b_sky_node.sun_direction()));
+ sky->turbidity = b_sky_node.turbidity();
+ sky->ground_albedo = b_sky_node.ground_albedo();
+ BL::TexMapping b_texture_mapping(b_sky_node.texture_mapping());
+ get_tex_mapping(&sky->tex_mapping, b_texture_mapping);
+ node = sky;
+ }
+ else if (b_node.is_a(&RNA_ShaderNodeTexIES)) {
+ BL::ShaderNodeTexIES b_ies_node(b_node);
+ IESLightNode *ies = new IESLightNode();
+ switch (b_ies_node.mode()) {
+ case BL::ShaderNodeTexIES::mode_EXTERNAL:
+ ies->filename = blender_absolute_path(b_data, b_ntree, b_ies_node.filepath());
+ break;
+ case BL::ShaderNodeTexIES::mode_INTERNAL:
+ ies->ies = get_text_datablock_content(b_ies_node.ies().ptr);
+ if (ies->ies.empty()) {
+ ies->ies = "\n";
+ }
+ break;
+ }
+ node = ies;
+ }
+ else if (b_node.is_a(&RNA_ShaderNodeNormalMap)) {
+ BL::ShaderNodeNormalMap b_normal_map_node(b_node);
+ NormalMapNode *nmap = new NormalMapNode();
+ nmap->space = (NodeNormalMapSpace)b_normal_map_node.space();
+ nmap->attribute = b_normal_map_node.uv_map();
+ node = nmap;
+ }
+ else if (b_node.is_a(&RNA_ShaderNodeTangent)) {
+ BL::ShaderNodeTangent b_tangent_node(b_node);
+ TangentNode *tangent = new TangentNode();
+ tangent->direction_type = (NodeTangentDirectionType)b_tangent_node.direction_type();
+ tangent->axis = (NodeTangentAxis)b_tangent_node.axis();
+ tangent->attribute = b_tangent_node.uv_map();
+ node = tangent;
+ }
+ else if (b_node.is_a(&RNA_ShaderNodeUVMap)) {
+ BL::ShaderNodeUVMap b_uvmap_node(b_node);
+ UVMapNode *uvm = new UVMapNode();
+ uvm->attribute = b_uvmap_node.uv_map();
+ uvm->from_dupli = b_uvmap_node.from_instancer();
+ node = uvm;
+ }
+ else if (b_node.is_a(&RNA_ShaderNodeTexPointDensity)) {
+ BL::ShaderNodeTexPointDensity b_point_density_node(b_node);
+ PointDensityTextureNode *point_density = new PointDensityTextureNode();
+ point_density->filename = b_point_density_node.name();
+ point_density->space = (NodeTexVoxelSpace)b_point_density_node.space();
+ point_density->interpolation = get_image_interpolation(b_point_density_node);
+ point_density->builtin_data = b_point_density_node.ptr.data;
+ point_density->image_manager = scene->image_manager;
+
+ /* TODO(sergey): Use more proper update flag. */
+ if (true) {
+ point_density->add_image();
+ b_point_density_node.cache_point_density(b_depsgraph);
+ scene->image_manager->tag_reload_image(point_density->filename.string(),
+ point_density->builtin_data,
+ point_density->interpolation,
+ EXTENSION_CLIP,
+ true);
+ }
+ node = point_density;
+
+ /* Transformation form world space to texture space.
+ *
+ * NOTE: Do this after the texture is cached, this is because getting
+ * min/max will need to access this cache.
+ */
+ BL::Object b_ob(b_point_density_node.object());
+ if (b_ob) {
+ float3 loc, size;
+ point_density_texture_space(b_depsgraph, b_point_density_node, loc, size);
+ point_density->tfm = transform_translate(-loc) * transform_scale(size) *
+ transform_inverse(get_transform(b_ob.matrix_world()));
+ }
+ }
+ else if (b_node.is_a(&RNA_ShaderNodeBevel)) {
+ BL::ShaderNodeBevel b_bevel_node(b_node);
+ BevelNode *bevel = new BevelNode();
+ bevel->samples = b_bevel_node.samples();
+ node = bevel;
+ }
+ else if (b_node.is_a(&RNA_ShaderNodeDisplacement)) {
+ BL::ShaderNodeDisplacement b_disp_node(b_node);
+ DisplacementNode *disp = new DisplacementNode();
+ disp->space = (NodeNormalMapSpace)b_disp_node.space();
+ node = disp;
+ }
+ else if (b_node.is_a(&RNA_ShaderNodeVectorDisplacement)) {
+ BL::ShaderNodeVectorDisplacement b_disp_node(b_node);
+ VectorDisplacementNode *disp = new VectorDisplacementNode();
+ disp->space = (NodeNormalMapSpace)b_disp_node.space();
+ disp->attribute = "";
+ node = disp;
+ }
+
+ if (node) {
+ node->name = b_node.name();
+ graph->add(node);
+ }
+
+ return node;
}
static bool node_use_modified_socket_name(ShaderNode *node)
{
- if(node->special_type == SHADER_SPECIAL_TYPE_SCRIPT)
- return false;
+ if (node->special_type == SHADER_SPECIAL_TYPE_SCRIPT)
+ return false;
- return true;
+ return true;
}
static ShaderInput *node_find_input_by_name(ShaderNode *node,
- BL::Node& b_node,
- BL::NodeSocket& b_socket)
+ BL::Node &b_node,
+ BL::NodeSocket &b_socket)
{
- string name = b_socket.name();
+ string name = b_socket.name();
- if(node_use_modified_socket_name(node)) {
- BL::Node::inputs_iterator b_input;
- bool found = false;
- int counter = 0, total = 0;
+ if (node_use_modified_socket_name(node)) {
+ BL::Node::inputs_iterator b_input;
+ bool found = false;
+ int counter = 0, total = 0;
- for(b_node.inputs.begin(b_input); b_input != b_node.inputs.end(); ++b_input) {
- if(b_input->name() == name) {
- if(!found)
- counter++;
- total++;
- }
+ for (b_node.inputs.begin(b_input); b_input != b_node.inputs.end(); ++b_input) {
+ if (b_input->name() == name) {
+ if (!found)
+ counter++;
+ total++;
+ }
- if(b_input->ptr.data == b_socket.ptr.data)
- found = true;
- }
+ if (b_input->ptr.data == b_socket.ptr.data)
+ found = true;
+ }
- /* rename if needed */
- if(name == "Shader")
- name = "Closure";
+ /* rename if needed */
+ if (name == "Shader")
+ name = "Closure";
- if(total > 1)
- name = string_printf("%s%d", name.c_str(), counter);
- }
+ if (total > 1)
+ name = string_printf("%s%d", name.c_str(), counter);
+ }
- return node->input(name.c_str());
+ return node->input(name.c_str());
}
static ShaderOutput *node_find_output_by_name(ShaderNode *node,
- BL::Node& b_node,
- BL::NodeSocket& b_socket)
+ BL::Node &b_node,
+ BL::NodeSocket &b_socket)
{
- string name = b_socket.name();
+ string name = b_socket.name();
- if(node_use_modified_socket_name(node)) {
- BL::Node::outputs_iterator b_output;
- bool found = false;
- int counter = 0, total = 0;
+ if (node_use_modified_socket_name(node)) {
+ BL::Node::outputs_iterator b_output;
+ bool found = false;
+ int counter = 0, total = 0;
- for(b_node.outputs.begin(b_output); b_output != b_node.outputs.end(); ++b_output) {
- if(b_output->name() == name) {
- if(!found)
- counter++;
- total++;
- }
+ for (b_node.outputs.begin(b_output); b_output != b_node.outputs.end(); ++b_output) {
+ if (b_output->name() == name) {
+ if (!found)
+ counter++;
+ total++;
+ }
- if(b_output->ptr.data == b_socket.ptr.data)
- found = true;
- }
+ if (b_output->ptr.data == b_socket.ptr.data)
+ found = true;
+ }
- /* rename if needed */
- if(name == "Shader")
- name = "Closure";
+ /* rename if needed */
+ if (name == "Shader")
+ name = "Closure";
- if(total > 1)
- name = string_printf("%s%d", name.c_str(), counter);
- }
+ if (total > 1)
+ name = string_printf("%s%d", name.c_str(), counter);
+ }
- return node->output(name.c_str());
+ return node->output(name.c_str());
}
static void add_nodes(Scene *scene,
- BL::RenderEngine& b_engine,
- BL::BlendData& b_data,
- BL::Depsgraph& b_depsgraph,
- BL::Scene& b_scene,
+ BL::RenderEngine &b_engine,
+ BL::BlendData &b_data,
+ BL::Depsgraph &b_depsgraph,
+ BL::Scene &b_scene,
ShaderGraph *graph,
- BL::ShaderNodeTree& b_ntree,
+ BL::ShaderNodeTree &b_ntree,
const ProxyMap &proxy_input_map,
const ProxyMap &proxy_output_map)
{
- /* add nodes */
- BL::ShaderNodeTree::nodes_iterator b_node;
- PtrInputMap input_map;
- PtrOutputMap output_map;
-
- BL::Node::inputs_iterator b_input;
- BL::Node::outputs_iterator b_output;
-
- /* find the node to use for output if there are multiple */
- BL::ShaderNode output_node = b_ntree.get_output_node(BL::ShaderNodeOutputMaterial::target_CYCLES);
-
- /* add nodes */
- for(b_ntree.nodes.begin(b_node); b_node != b_ntree.nodes.end(); ++b_node) {
- if(b_node->mute() || b_node->is_a(&RNA_NodeReroute)) {
- /* replace muted node with internal links */
- BL::Node::internal_links_iterator b_link;
- for(b_node->internal_links.begin(b_link); b_link != b_node->internal_links.end(); ++b_link) {
- BL::NodeSocket to_socket(b_link->to_socket());
- SocketType::Type to_socket_type = convert_socket_type(to_socket);
- if(to_socket_type == SocketType::UNDEFINED) {
- continue;
- }
-
- ConvertNode *proxy = new ConvertNode(to_socket_type, to_socket_type, true);
-
- input_map[b_link->from_socket().ptr.data] = proxy->inputs[0];
- output_map[b_link->to_socket().ptr.data] = proxy->outputs[0];
-
- graph->add(proxy);
- }
- }
- else if(b_node->is_a(&RNA_ShaderNodeGroup) ||
- b_node->is_a(&RNA_NodeCustomGroup) ||
- b_node->is_a(&RNA_ShaderNodeCustomGroup)) {
-
- BL::ShaderNodeTree b_group_ntree(PointerRNA_NULL);
- if(b_node->is_a(&RNA_ShaderNodeGroup))
- b_group_ntree = BL::ShaderNodeTree(((BL::NodeGroup)(*b_node)).node_tree());
- else if (b_node->is_a(&RNA_NodeCustomGroup))
- b_group_ntree = BL::ShaderNodeTree(((BL::NodeCustomGroup)(*b_node)).node_tree());
- else
- b_group_ntree = BL::ShaderNodeTree(((BL::ShaderNodeCustomGroup)(*b_node)).node_tree());
-
- ProxyMap group_proxy_input_map, group_proxy_output_map;
-
- /* Add a proxy node for each socket
- * Do this even if the node group has no internal tree,
- * so that links have something to connect to and assert won't fail.
- */
- for(b_node->inputs.begin(b_input); b_input != b_node->inputs.end(); ++b_input) {
- SocketType::Type input_type = convert_socket_type(*b_input);
- if(input_type == SocketType::UNDEFINED) {
- continue;
- }
-
- ConvertNode *proxy = new ConvertNode(input_type, input_type, true);
- graph->add(proxy);
-
- /* register the proxy node for internal binding */
- group_proxy_input_map[b_input->identifier()] = proxy;
-
- input_map[b_input->ptr.data] = proxy->inputs[0];
-
- set_default_value(proxy->inputs[0], *b_input, b_data, b_ntree);
- }
- for(b_node->outputs.begin(b_output); b_output != b_node->outputs.end(); ++b_output) {
- SocketType::Type output_type = convert_socket_type(*b_output);
- if(output_type == SocketType::UNDEFINED) {
- continue;
- }
-
- ConvertNode *proxy = new ConvertNode(output_type, output_type, true);
- graph->add(proxy);
-
- /* register the proxy node for internal binding */
- group_proxy_output_map[b_output->identifier()] = proxy;
-
- output_map[b_output->ptr.data] = proxy->outputs[0];
- }
-
- if(b_group_ntree) {
- add_nodes(scene,
- b_engine,
- b_data,
- b_depsgraph,
- b_scene,
- graph,
- b_group_ntree,
- group_proxy_input_map,
- group_proxy_output_map);
- }
- }
- else if(b_node->is_a(&RNA_NodeGroupInput)) {
- /* map each socket to a proxy node */
- for(b_node->outputs.begin(b_output); b_output != b_node->outputs.end(); ++b_output) {
- ProxyMap::const_iterator proxy_it = proxy_input_map.find(b_output->identifier());
- if(proxy_it != proxy_input_map.end()) {
- ConvertNode *proxy = proxy_it->second;
-
- output_map[b_output->ptr.data] = proxy->outputs[0];
- }
- }
- }
- else if(b_node->is_a(&RNA_NodeGroupOutput)) {
- BL::NodeGroupOutput b_output_node(*b_node);
- /* only the active group output is used */
- if(b_output_node.is_active_output()) {
- /* map each socket to a proxy node */
- for(b_node->inputs.begin(b_input); b_input != b_node->inputs.end(); ++b_input) {
- ProxyMap::const_iterator proxy_it = proxy_output_map.find(b_input->identifier());
- if(proxy_it != proxy_output_map.end()) {
- ConvertNode *proxy = proxy_it->second;
-
- input_map[b_input->ptr.data] = proxy->inputs[0];
-
- set_default_value(proxy->inputs[0], *b_input, b_data, b_ntree);
- }
- }
- }
- }
- else {
- ShaderNode *node = NULL;
-
- if(b_node->ptr.data == output_node.ptr.data) {
- node = graph->output();
- }
- else {
- BL::ShaderNode b_shader_node(*b_node);
- node = add_node(scene,
- b_engine,
- b_data,
- b_depsgraph,
- b_scene,
- graph,
- b_ntree,
- b_shader_node);
- }
-
- if(node) {
- /* map node sockets for linking */
- for(b_node->inputs.begin(b_input); b_input != b_node->inputs.end(); ++b_input) {
- ShaderInput *input = node_find_input_by_name(node, *b_node, *b_input);
- if(!input) {
- /* XXX should not happen, report error? */
- continue;
- }
- input_map[b_input->ptr.data] = input;
-
- set_default_value(input, *b_input, b_data, b_ntree);
- }
- for(b_node->outputs.begin(b_output); b_output != b_node->outputs.end(); ++b_output) {
- ShaderOutput *output = node_find_output_by_name(node, *b_node, *b_output);
- if(!output) {
- /* XXX should not happen, report error? */
- continue;
- }
- output_map[b_output->ptr.data] = output;
- }
- }
- }
- }
-
- /* connect nodes */
- BL::NodeTree::links_iterator b_link;
-
- for(b_ntree.links.begin(b_link); b_link != b_ntree.links.end(); ++b_link) {
- /* Ignore invalid links to avoid unwanted cycles created in graph. */
- if(!b_link->is_valid()) {
- continue;
- }
- /* get blender link data */
- BL::NodeSocket b_from_sock = b_link->from_socket();
- BL::NodeSocket b_to_sock = b_link->to_socket();
-
- ShaderOutput *output = 0;
- ShaderInput *input = 0;
-
- PtrOutputMap::iterator output_it = output_map.find(b_from_sock.ptr.data);
- if(output_it != output_map.end())
- output = output_it->second;
- PtrInputMap::iterator input_it = input_map.find(b_to_sock.ptr.data);
- if(input_it != input_map.end())
- input = input_it->second;
-
- /* either node may be NULL when the node was not exported, typically
- * because the node type is not supported */
- if(output && input)
- graph->connect(output, input);
- }
+ /* add nodes */
+ BL::ShaderNodeTree::nodes_iterator b_node;
+ PtrInputMap input_map;
+ PtrOutputMap output_map;
+
+ BL::Node::inputs_iterator b_input;
+ BL::Node::outputs_iterator b_output;
+
+ /* find the node to use for output if there are multiple */
+ BL::ShaderNode output_node = b_ntree.get_output_node(
+ BL::ShaderNodeOutputMaterial::target_CYCLES);
+
+ /* add nodes */
+ for (b_ntree.nodes.begin(b_node); b_node != b_ntree.nodes.end(); ++b_node) {
+ if (b_node->mute() || b_node->is_a(&RNA_NodeReroute)) {
+ /* replace muted node with internal links */
+ BL::Node::internal_links_iterator b_link;
+ for (b_node->internal_links.begin(b_link); b_link != b_node->internal_links.end();
+ ++b_link) {
+ BL::NodeSocket to_socket(b_link->to_socket());
+ SocketType::Type to_socket_type = convert_socket_type(to_socket);
+ if (to_socket_type == SocketType::UNDEFINED) {
+ continue;
+ }
+
+ ConvertNode *proxy = new ConvertNode(to_socket_type, to_socket_type, true);
+
+ input_map[b_link->from_socket().ptr.data] = proxy->inputs[0];
+ output_map[b_link->to_socket().ptr.data] = proxy->outputs[0];
+
+ graph->add(proxy);
+ }
+ }
+ else if (b_node->is_a(&RNA_ShaderNodeGroup) || b_node->is_a(&RNA_NodeCustomGroup) ||
+ b_node->is_a(&RNA_ShaderNodeCustomGroup)) {
+
+ BL::ShaderNodeTree b_group_ntree(PointerRNA_NULL);
+ if (b_node->is_a(&RNA_ShaderNodeGroup))
+ b_group_ntree = BL::ShaderNodeTree(((BL::NodeGroup)(*b_node)).node_tree());
+ else if (b_node->is_a(&RNA_NodeCustomGroup))
+ b_group_ntree = BL::ShaderNodeTree(((BL::NodeCustomGroup)(*b_node)).node_tree());
+ else
+ b_group_ntree = BL::ShaderNodeTree(((BL::ShaderNodeCustomGroup)(*b_node)).node_tree());
+
+ ProxyMap group_proxy_input_map, group_proxy_output_map;
+
+ /* Add a proxy node for each socket
+ * Do this even if the node group has no internal tree,
+ * so that links have something to connect to and assert won't fail.
+ */
+ for (b_node->inputs.begin(b_input); b_input != b_node->inputs.end(); ++b_input) {
+ SocketType::Type input_type = convert_socket_type(*b_input);
+ if (input_type == SocketType::UNDEFINED) {
+ continue;
+ }
+
+ ConvertNode *proxy = new ConvertNode(input_type, input_type, true);
+ graph->add(proxy);
+
+ /* register the proxy node for internal binding */
+ group_proxy_input_map[b_input->identifier()] = proxy;
+
+ input_map[b_input->ptr.data] = proxy->inputs[0];
+
+ set_default_value(proxy->inputs[0], *b_input, b_data, b_ntree);
+ }
+ for (b_node->outputs.begin(b_output); b_output != b_node->outputs.end(); ++b_output) {
+ SocketType::Type output_type = convert_socket_type(*b_output);
+ if (output_type == SocketType::UNDEFINED) {
+ continue;
+ }
+
+ ConvertNode *proxy = new ConvertNode(output_type, output_type, true);
+ graph->add(proxy);
+
+ /* register the proxy node for internal binding */
+ group_proxy_output_map[b_output->identifier()] = proxy;
+
+ output_map[b_output->ptr.data] = proxy->outputs[0];
+ }
+
+ if (b_group_ntree) {
+ add_nodes(scene,
+ b_engine,
+ b_data,
+ b_depsgraph,
+ b_scene,
+ graph,
+ b_group_ntree,
+ group_proxy_input_map,
+ group_proxy_output_map);
+ }
+ }
+ else if (b_node->is_a(&RNA_NodeGroupInput)) {
+ /* map each socket to a proxy node */
+ for (b_node->outputs.begin(b_output); b_output != b_node->outputs.end(); ++b_output) {
+ ProxyMap::const_iterator proxy_it = proxy_input_map.find(b_output->identifier());
+ if (proxy_it != proxy_input_map.end()) {
+ ConvertNode *proxy = proxy_it->second;
+
+ output_map[b_output->ptr.data] = proxy->outputs[0];
+ }
+ }
+ }
+ else if (b_node->is_a(&RNA_NodeGroupOutput)) {
+ BL::NodeGroupOutput b_output_node(*b_node);
+ /* only the active group output is used */
+ if (b_output_node.is_active_output()) {
+ /* map each socket to a proxy node */
+ for (b_node->inputs.begin(b_input); b_input != b_node->inputs.end(); ++b_input) {
+ ProxyMap::const_iterator proxy_it = proxy_output_map.find(b_input->identifier());
+ if (proxy_it != proxy_output_map.end()) {
+ ConvertNode *proxy = proxy_it->second;
+
+ input_map[b_input->ptr.data] = proxy->inputs[0];
+
+ set_default_value(proxy->inputs[0], *b_input, b_data, b_ntree);
+ }
+ }
+ }
+ }
+ else {
+ ShaderNode *node = NULL;
+
+ if (b_node->ptr.data == output_node.ptr.data) {
+ node = graph->output();
+ }
+ else {
+ BL::ShaderNode b_shader_node(*b_node);
+ node = add_node(
+ scene, b_engine, b_data, b_depsgraph, b_scene, graph, b_ntree, b_shader_node);
+ }
+
+ if (node) {
+ /* map node sockets for linking */
+ for (b_node->inputs.begin(b_input); b_input != b_node->inputs.end(); ++b_input) {
+ ShaderInput *input = node_find_input_by_name(node, *b_node, *b_input);
+ if (!input) {
+ /* XXX should not happen, report error? */
+ continue;
+ }
+ input_map[b_input->ptr.data] = input;
+
+ set_default_value(input, *b_input, b_data, b_ntree);
+ }
+ for (b_node->outputs.begin(b_output); b_output != b_node->outputs.end(); ++b_output) {
+ ShaderOutput *output = node_find_output_by_name(node, *b_node, *b_output);
+ if (!output) {
+ /* XXX should not happen, report error? */
+ continue;
+ }
+ output_map[b_output->ptr.data] = output;
+ }
+ }
+ }
+ }
+
+ /* connect nodes */
+ BL::NodeTree::links_iterator b_link;
+
+ for (b_ntree.links.begin(b_link); b_link != b_ntree.links.end(); ++b_link) {
+ /* Ignore invalid links to avoid unwanted cycles created in graph. */
+ if (!b_link->is_valid()) {
+ continue;
+ }
+ /* get blender link data */
+ BL::NodeSocket b_from_sock = b_link->from_socket();
+ BL::NodeSocket b_to_sock = b_link->to_socket();
+
+ ShaderOutput *output = 0;
+ ShaderInput *input = 0;
+
+ PtrOutputMap::iterator output_it = output_map.find(b_from_sock.ptr.data);
+ if (output_it != output_map.end())
+ output = output_it->second;
+ PtrInputMap::iterator input_it = input_map.find(b_to_sock.ptr.data);
+ if (input_it != input_map.end())
+ input = input_it->second;
+
+ /* either node may be NULL when the node was not exported, typically
+ * because the node type is not supported */
+ if (output && input)
+ graph->connect(output, input);
+ }
}
static void add_nodes(Scene *scene,
- BL::RenderEngine& b_engine,
- BL::BlendData& b_data,
- BL::Depsgraph& b_depsgraph,
- BL::Scene& b_scene,
+ BL::RenderEngine &b_engine,
+ BL::BlendData &b_data,
+ BL::Depsgraph &b_depsgraph,
+ BL::Scene &b_scene,
ShaderGraph *graph,
- BL::ShaderNodeTree& b_ntree)
+ BL::ShaderNodeTree &b_ntree)
{
- static const ProxyMap empty_proxy_map;
- add_nodes(scene,
- b_engine,
- b_data,
- b_depsgraph,
- b_scene,
- graph,
- b_ntree,
- empty_proxy_map,
- empty_proxy_map);
+ static const ProxyMap empty_proxy_map;
+ add_nodes(scene,
+ b_engine,
+ b_data,
+ b_depsgraph,
+ b_scene,
+ graph,
+ b_ntree,
+ empty_proxy_map,
+ empty_proxy_map);
}
/* Sync Materials */
-void BlenderSync::sync_materials(BL::Depsgraph& b_depsgraph, bool update_all)
+void BlenderSync::sync_materials(BL::Depsgraph &b_depsgraph, bool update_all)
{
- shader_map.set_default(scene->default_surface);
-
- TaskPool pool;
- set<Shader*> updated_shaders;
-
- BL::Depsgraph::ids_iterator b_id;
- for(b_depsgraph.ids.begin(b_id); b_id != b_depsgraph.ids.end(); ++b_id) {
- if(!b_id->is_a(&RNA_Material)) {
- continue;
- }
-
- BL::Material b_mat(*b_id);
- Shader *shader;
-
- /* test if we need to sync */
- if(shader_map.sync(&shader, b_mat) || shader->need_sync_object || update_all) {
- ShaderGraph *graph = new ShaderGraph();
-
- shader->name = b_mat.name().c_str();
- shader->pass_id = b_mat.pass_index();
- shader->need_sync_object = false;
-
- /* create nodes */
- if(b_mat.use_nodes() && b_mat.node_tree()) {
- BL::ShaderNodeTree b_ntree(b_mat.node_tree());
-
- add_nodes(scene, b_engine, b_data, b_depsgraph, b_scene, graph, b_ntree);
- }
- else {
- DiffuseBsdfNode *diffuse = new DiffuseBsdfNode();
- diffuse->color = get_float3(b_mat.diffuse_color());
- graph->add(diffuse);
-
- ShaderNode *out = graph->output();
- graph->connect(diffuse->output("BSDF"), out->input("Surface"));
- }
-
- /* settings */
- PointerRNA cmat = RNA_pointer_get(&b_mat.ptr, "cycles");
- shader->use_mis = get_boolean(cmat, "sample_as_light");
- shader->use_transparent_shadow = get_boolean(cmat, "use_transparent_shadow");
- shader->heterogeneous_volume = !get_boolean(cmat, "homogeneous_volume");
- shader->volume_sampling_method = get_volume_sampling(cmat);
- shader->volume_interpolation_method = get_volume_interpolation(cmat);
- shader->displacement_method = get_displacement_method(cmat);
-
- shader->set_graph(graph);
-
- /* By simplifying the shader graph as soon as possible, some
- * redundant shader nodes might be removed which prevents loading
- * unnecessary attributes later.
- *
- * However, since graph simplification also accounts for e.g. mix
- * weight, this would cause frequent expensive resyncs in interactive
- * sessions, so for those sessions optimization is only performed
- * right before compiling.
- */
- if(!preview) {
- pool.push(function_bind(&ShaderGraph::simplify, graph, scene));
- /* NOTE: Update shaders out of the threads since those routines
- * are accessing and writing to a global context.
- */
- updated_shaders.insert(shader);
- }
- else {
- /* NOTE: Update tagging can access links which are being
- * optimized out.
- */
- shader->tag_update(scene);
- }
- }
- }
-
- pool.wait_work();
-
- foreach(Shader *shader, updated_shaders) {
- shader->tag_update(scene);
- }
+ shader_map.set_default(scene->default_surface);
+
+ TaskPool pool;
+ set<Shader *> updated_shaders;
+
+ BL::Depsgraph::ids_iterator b_id;
+ for (b_depsgraph.ids.begin(b_id); b_id != b_depsgraph.ids.end(); ++b_id) {
+ if (!b_id->is_a(&RNA_Material)) {
+ continue;
+ }
+
+ BL::Material b_mat(*b_id);
+ Shader *shader;
+
+ /* test if we need to sync */
+ if (shader_map.sync(&shader, b_mat) || shader->need_sync_object || update_all) {
+ ShaderGraph *graph = new ShaderGraph();
+
+ shader->name = b_mat.name().c_str();
+ shader->pass_id = b_mat.pass_index();
+ shader->need_sync_object = false;
+
+ /* create nodes */
+ if (b_mat.use_nodes() && b_mat.node_tree()) {
+ BL::ShaderNodeTree b_ntree(b_mat.node_tree());
+
+ add_nodes(scene, b_engine, b_data, b_depsgraph, b_scene, graph, b_ntree);
+ }
+ else {
+ DiffuseBsdfNode *diffuse = new DiffuseBsdfNode();
+ diffuse->color = get_float3(b_mat.diffuse_color());
+ graph->add(diffuse);
+
+ ShaderNode *out = graph->output();
+ graph->connect(diffuse->output("BSDF"), out->input("Surface"));
+ }
+
+ /* settings */
+ PointerRNA cmat = RNA_pointer_get(&b_mat.ptr, "cycles");
+ shader->use_mis = get_boolean(cmat, "sample_as_light");
+ shader->use_transparent_shadow = get_boolean(cmat, "use_transparent_shadow");
+ shader->heterogeneous_volume = !get_boolean(cmat, "homogeneous_volume");
+ shader->volume_sampling_method = get_volume_sampling(cmat);
+ shader->volume_interpolation_method = get_volume_interpolation(cmat);
+ shader->displacement_method = get_displacement_method(cmat);
+
+ shader->set_graph(graph);
+
+ /* By simplifying the shader graph as soon as possible, some
+ * redundant shader nodes might be removed which prevents loading
+ * unnecessary attributes later.
+ *
+ * However, since graph simplification also accounts for e.g. mix
+ * weight, this would cause frequent expensive resyncs in interactive
+ * sessions, so for those sessions optimization is only performed
+ * right before compiling.
+ */
+ if (!preview) {
+ pool.push(function_bind(&ShaderGraph::simplify, graph, scene));
+ /* NOTE: Update shaders out of the threads since those routines
+ * are accessing and writing to a global context.
+ */
+ updated_shaders.insert(shader);
+ }
+ else {
+ /* NOTE: Update tagging can access links which are being
+ * optimized out.
+ */
+ shader->tag_update(scene);
+ }
+ }
+ }
+
+ pool.wait_work();
+
+ foreach (Shader *shader, updated_shaders) {
+ shader->tag_update(scene);
+ }
}
/* Sync World */
-void BlenderSync::sync_world(BL::Depsgraph& b_depsgraph, bool update_all)
+void BlenderSync::sync_world(BL::Depsgraph &b_depsgraph, bool update_all)
{
- Background *background = scene->background;
- Background prevbackground = *background;
-
- BL::World b_world = b_scene.world();
-
- if(world_recalc || update_all || b_world.ptr.data != world_map) {
- Shader *shader = scene->default_background;
- ShaderGraph *graph = new ShaderGraph();
-
- /* create nodes */
- if(b_world && b_world.use_nodes() && b_world.node_tree()) {
- BL::ShaderNodeTree b_ntree(b_world.node_tree());
-
- add_nodes(scene, b_engine, b_data, b_depsgraph, b_scene, graph, b_ntree);
-
- /* volume */
- PointerRNA cworld = RNA_pointer_get(&b_world.ptr, "cycles");
- shader->heterogeneous_volume = !get_boolean(cworld, "homogeneous_volume");
- shader->volume_sampling_method = get_volume_sampling(cworld);
- shader->volume_interpolation_method = get_volume_interpolation(cworld);
- }
- else if(b_world) {
- BackgroundNode *background = new BackgroundNode();
- background->color = get_float3(b_world.color());
- graph->add(background);
-
- ShaderNode *out = graph->output();
- graph->connect(background->output("Background"), out->input("Surface"));
- }
-
- if(b_world) {
- /* AO */
- BL::WorldLighting b_light = b_world.light_settings();
-
- background->use_ao = b_light.use_ambient_occlusion();
- background->ao_factor = b_light.ao_factor();
- background->ao_distance = b_light.distance();
-
- /* visibility */
- PointerRNA cvisibility = RNA_pointer_get(&b_world.ptr, "cycles_visibility");
- uint visibility = 0;
-
- visibility |= get_boolean(cvisibility, "camera")? PATH_RAY_CAMERA: 0;
- visibility |= get_boolean(cvisibility, "diffuse")? PATH_RAY_DIFFUSE: 0;
- visibility |= get_boolean(cvisibility, "glossy")? PATH_RAY_GLOSSY: 0;
- visibility |= get_boolean(cvisibility, "transmission")? PATH_RAY_TRANSMIT: 0;
- visibility |= get_boolean(cvisibility, "scatter")? PATH_RAY_VOLUME_SCATTER: 0;
-
- background->visibility = visibility;
- }
- else {
- background->use_ao = false;
- background->ao_factor = 0.0f;
- background->ao_distance = FLT_MAX;
- }
-
- shader->set_graph(graph);
- shader->tag_update(scene);
- background->tag_update(scene);
- }
-
- PointerRNA cscene = RNA_pointer_get(&b_scene.ptr, "cycles");
-
- /* when doing preview render check for BI's transparency settings,
- * this is so because Blender's preview render routines are not able
- * to tweak all cycles's settings depending on different circumstances
- */
- if(b_engine.is_preview() == false)
- background->transparent = get_boolean(cscene, "film_transparent");
- else
- background->transparent = b_scene.render().alpha_mode() == BL::RenderSettings::alpha_mode_TRANSPARENT;
-
- if(background->transparent) {
- background->transparent_glass = get_boolean(cscene, "film_transparent_glass");
- background->transparent_roughness_threshold = get_float(cscene, "film_transparent_roughness");
- }
- else {
- background->transparent_glass = false;
- background->transparent_roughness_threshold = 0.0f;
- }
-
- background->use_shader = view_layer.use_background_shader;
- background->use_ao = background->use_ao && view_layer.use_background_ao;
-
- if(background->modified(prevbackground))
- background->tag_update(scene);
+ Background *background = scene->background;
+ Background prevbackground = *background;
+
+ BL::World b_world = b_scene.world();
+
+ if (world_recalc || update_all || b_world.ptr.data != world_map) {
+ Shader *shader = scene->default_background;
+ ShaderGraph *graph = new ShaderGraph();
+
+ /* create nodes */
+ if (b_world && b_world.use_nodes() && b_world.node_tree()) {
+ BL::ShaderNodeTree b_ntree(b_world.node_tree());
+
+ add_nodes(scene, b_engine, b_data, b_depsgraph, b_scene, graph, b_ntree);
+
+ /* volume */
+ PointerRNA cworld = RNA_pointer_get(&b_world.ptr, "cycles");
+ shader->heterogeneous_volume = !get_boolean(cworld, "homogeneous_volume");
+ shader->volume_sampling_method = get_volume_sampling(cworld);
+ shader->volume_interpolation_method = get_volume_interpolation(cworld);
+ }
+ else if (b_world) {
+ BackgroundNode *background = new BackgroundNode();
+ background->color = get_float3(b_world.color());
+ graph->add(background);
+
+ ShaderNode *out = graph->output();
+ graph->connect(background->output("Background"), out->input("Surface"));
+ }
+
+ if (b_world) {
+ /* AO */
+ BL::WorldLighting b_light = b_world.light_settings();
+
+ background->use_ao = b_light.use_ambient_occlusion();
+ background->ao_factor = b_light.ao_factor();
+ background->ao_distance = b_light.distance();
+
+ /* visibility */
+ PointerRNA cvisibility = RNA_pointer_get(&b_world.ptr, "cycles_visibility");
+ uint visibility = 0;
+
+ visibility |= get_boolean(cvisibility, "camera") ? PATH_RAY_CAMERA : 0;
+ visibility |= get_boolean(cvisibility, "diffuse") ? PATH_RAY_DIFFUSE : 0;
+ visibility |= get_boolean(cvisibility, "glossy") ? PATH_RAY_GLOSSY : 0;
+ visibility |= get_boolean(cvisibility, "transmission") ? PATH_RAY_TRANSMIT : 0;
+ visibility |= get_boolean(cvisibility, "scatter") ? PATH_RAY_VOLUME_SCATTER : 0;
+
+ background->visibility = visibility;
+ }
+ else {
+ background->use_ao = false;
+ background->ao_factor = 0.0f;
+ background->ao_distance = FLT_MAX;
+ }
+
+ shader->set_graph(graph);
+ shader->tag_update(scene);
+ background->tag_update(scene);
+ }
+
+ PointerRNA cscene = RNA_pointer_get(&b_scene.ptr, "cycles");
+
+ /* when doing preview render check for BI's transparency settings,
+ * this is so because Blender's preview render routines are not able
+ * to tweak all cycles's settings depending on different circumstances
+ */
+ if (b_engine.is_preview() == false)
+ background->transparent = get_boolean(cscene, "film_transparent");
+ else
+ background->transparent = b_scene.render().alpha_mode() ==
+ BL::RenderSettings::alpha_mode_TRANSPARENT;
+
+ if (background->transparent) {
+ background->transparent_glass = get_boolean(cscene, "film_transparent_glass");
+ background->transparent_roughness_threshold = get_float(cscene, "film_transparent_roughness");
+ }
+ else {
+ background->transparent_glass = false;
+ background->transparent_roughness_threshold = 0.0f;
+ }
+
+ background->use_shader = view_layer.use_background_shader;
+ background->use_ao = background->use_ao && view_layer.use_background_ao;
+
+ if (background->modified(prevbackground))
+ background->tag_update(scene);
}
/* Sync Lights */
-void BlenderSync::sync_lights(BL::Depsgraph& b_depsgraph, bool update_all)
+void BlenderSync::sync_lights(BL::Depsgraph &b_depsgraph, bool update_all)
{
- shader_map.set_default(scene->default_light);
-
- BL::Depsgraph::ids_iterator b_id;
- for(b_depsgraph.ids.begin(b_id); b_id != b_depsgraph.ids.end(); ++b_id) {
- if(!b_id->is_a(&RNA_Light)) {
- continue;
- }
-
- BL::Light b_light(*b_id);
- Shader *shader;
-
- /* test if we need to sync */
- if(shader_map.sync(&shader, b_light) || update_all) {
- ShaderGraph *graph = new ShaderGraph();
-
- /* create nodes */
- if(b_light.use_nodes() && b_light.node_tree()) {
- shader->name = b_light.name().c_str();
-
- BL::ShaderNodeTree b_ntree(b_light.node_tree());
-
- add_nodes(scene, b_engine, b_data, b_depsgraph, b_scene, graph, b_ntree);
- }
- else {
- float strength = 1.0f;
-
- if(b_light.type() == BL::Light::type_POINT ||
- b_light.type() == BL::Light::type_SPOT ||
- b_light.type() == BL::Light::type_AREA)
- {
- strength = 100.0f;
- }
-
- EmissionNode *emission = new EmissionNode();
- emission->color = get_float3(b_light.color());
- emission->strength = strength;
- graph->add(emission);
-
- ShaderNode *out = graph->output();
- graph->connect(emission->output("Emission"), out->input("Surface"));
- }
-
- shader->set_graph(graph);
- shader->tag_update(scene);
- }
- }
+ shader_map.set_default(scene->default_light);
+
+ BL::Depsgraph::ids_iterator b_id;
+ for (b_depsgraph.ids.begin(b_id); b_id != b_depsgraph.ids.end(); ++b_id) {
+ if (!b_id->is_a(&RNA_Light)) {
+ continue;
+ }
+
+ BL::Light b_light(*b_id);
+ Shader *shader;
+
+ /* test if we need to sync */
+ if (shader_map.sync(&shader, b_light) || update_all) {
+ ShaderGraph *graph = new ShaderGraph();
+
+ /* create nodes */
+ if (b_light.use_nodes() && b_light.node_tree()) {
+ shader->name = b_light.name().c_str();
+
+ BL::ShaderNodeTree b_ntree(b_light.node_tree());
+
+ add_nodes(scene, b_engine, b_data, b_depsgraph, b_scene, graph, b_ntree);
+ }
+ else {
+ float strength = 1.0f;
+
+ if (b_light.type() == BL::Light::type_POINT || b_light.type() == BL::Light::type_SPOT ||
+ b_light.type() == BL::Light::type_AREA) {
+ strength = 100.0f;
+ }
+
+ EmissionNode *emission = new EmissionNode();
+ emission->color = get_float3(b_light.color());
+ emission->strength = strength;
+ graph->add(emission);
+
+ ShaderNode *out = graph->output();
+ graph->connect(emission->output("Emission"), out->input("Surface"));
+ }
+
+ shader->set_graph(graph);
+ shader->tag_update(scene);
+ }
+ }
}
-void BlenderSync::sync_shaders(BL::Depsgraph& b_depsgraph)
+void BlenderSync::sync_shaders(BL::Depsgraph &b_depsgraph)
{
- /* for auto refresh images */
- bool auto_refresh_update = false;
+ /* for auto refresh images */
+ bool auto_refresh_update = false;
- if(preview) {
- ImageManager *image_manager = scene->image_manager;
- int frame = b_scene.frame_current();
- auto_refresh_update = image_manager->set_animation_frame_update(frame);
- }
+ if (preview) {
+ ImageManager *image_manager = scene->image_manager;
+ int frame = b_scene.frame_current();
+ auto_refresh_update = image_manager->set_animation_frame_update(frame);
+ }
- shader_map.pre_sync();
+ shader_map.pre_sync();
- sync_world(b_depsgraph, auto_refresh_update);
- sync_lights(b_depsgraph, auto_refresh_update);
- sync_materials(b_depsgraph, auto_refresh_update);
+ sync_world(b_depsgraph, auto_refresh_update);
+ sync_lights(b_depsgraph, auto_refresh_update);
+ sync_materials(b_depsgraph, auto_refresh_update);
- /* false = don't delete unused shaders, not supported */
- shader_map.post_sync(false);
+ /* false = don't delete unused shaders, not supported */
+ shader_map.post_sync(false);
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/blender/blender_sync.cpp b/intern/cycles/blender/blender_sync.cpp
index 063a2cd4d16..0ab6d88487e 100644
--- a/intern/cycles/blender/blender_sync.cpp
+++ b/intern/cycles/blender/blender_sync.cpp
@@ -45,32 +45,33 @@ static const char *cryptomatte_prefix = "Crypto";
/* Constructor */
-BlenderSync::BlenderSync(BL::RenderEngine& b_engine,
- BL::BlendData& b_data,
- BL::Scene& b_scene,
+BlenderSync::BlenderSync(BL::RenderEngine &b_engine,
+ BL::BlendData &b_data,
+ BL::Scene &b_scene,
Scene *scene,
bool preview,
Progress &progress)
-: b_engine(b_engine),
- b_data(b_data),
- b_scene(b_scene),
- shader_map(&scene->shaders),
- object_map(&scene->objects),
- mesh_map(&scene->meshes),
- light_map(&scene->lights),
- particle_system_map(&scene->particle_systems),
- world_map(NULL),
- world_recalc(false),
- scene(scene),
- preview(preview),
- experimental(false),
- dicing_rate(1.0f),
- max_subdivisions(12),
- progress(progress)
+ : b_engine(b_engine),
+ b_data(b_data),
+ b_scene(b_scene),
+ shader_map(&scene->shaders),
+ object_map(&scene->objects),
+ mesh_map(&scene->meshes),
+ light_map(&scene->lights),
+ particle_system_map(&scene->particle_systems),
+ world_map(NULL),
+ world_recalc(false),
+ scene(scene),
+ preview(preview),
+ experimental(false),
+ dicing_rate(1.0f),
+ max_subdivisions(12),
+ progress(progress)
{
- PointerRNA cscene = RNA_pointer_get(&b_scene.ptr, "cycles");
- dicing_rate = preview ? RNA_float_get(&cscene, "preview_dicing_rate") : RNA_float_get(&cscene, "dicing_rate");
- max_subdivisions = RNA_int_get(&cscene, "max_subdivisions");
+ PointerRNA cscene = RNA_pointer_get(&b_scene.ptr, "cycles");
+ dicing_rate = preview ? RNA_float_get(&cscene, "preview_dicing_rate") :
+ RNA_float_get(&cscene, "dicing_rate");
+ max_subdivisions = RNA_int_get(&cscene, "max_subdivisions");
}
BlenderSync::~BlenderSync()
@@ -79,788 +80,776 @@ BlenderSync::~BlenderSync()
/* Sync */
-void BlenderSync::sync_recalc(BL::Depsgraph& b_depsgraph)
+void BlenderSync::sync_recalc(BL::Depsgraph &b_depsgraph)
{
- /* Sync recalc flags from blender to cycles. Actual update is done separate,
- * so we can do it later on if doing it immediate is not suitable. */
-
- bool has_updated_objects = b_depsgraph.id_type_updated(BL::DriverTarget::id_type_OBJECT);
-
- if(experimental) {
- /* Mark all meshes as needing to be exported again if dicing changed. */
- PointerRNA cscene = RNA_pointer_get(&b_scene.ptr, "cycles");
- bool dicing_prop_changed = false;
-
- float updated_dicing_rate = preview ? RNA_float_get(&cscene, "preview_dicing_rate")
- : RNA_float_get(&cscene, "dicing_rate");
-
- if(dicing_rate != updated_dicing_rate) {
- dicing_rate = updated_dicing_rate;
- dicing_prop_changed = true;
- }
-
- int updated_max_subdivisions = RNA_int_get(&cscene, "max_subdivisions");
-
- if(max_subdivisions != updated_max_subdivisions) {
- max_subdivisions = updated_max_subdivisions;
- dicing_prop_changed = true;
- }
-
- if(dicing_prop_changed) {
- for(const pair<void*, Mesh*>& iter: mesh_map.key_to_scene_data()) {
- Mesh *mesh = iter.second;
- if(mesh->subdivision_type != Mesh::SUBDIVISION_NONE) {
- mesh_map.set_recalc(iter.first);
- }
- }
- }
- }
-
- /* Iterate over all IDs in this depsgraph. */
- BL::Depsgraph::updates_iterator b_update;
- for(b_depsgraph.updates.begin(b_update); b_update != b_depsgraph.updates.end(); ++b_update) {
- BL::ID b_id(b_update->id());
-
- /* Material */
- if(b_id.is_a(&RNA_Material)) {
- BL::Material b_mat(b_id);
- shader_map.set_recalc(b_mat);
- }
- /* Light */
- else if(b_id.is_a(&RNA_Light)) {
- BL::Light b_light(b_id);
- shader_map.set_recalc(b_light);
- }
- /* Object */
- else if(b_id.is_a(&RNA_Object)) {
- BL::Object b_ob(b_id);
- const bool updated_geometry = b_update->is_updated_geometry();
-
- if(b_update->is_updated_transform()) {
- object_map.set_recalc(b_ob);
- light_map.set_recalc(b_ob);
- }
-
- if(object_is_mesh(b_ob)) {
- if(updated_geometry ||
- (object_subdivision_type(b_ob, preview, experimental) != Mesh::SUBDIVISION_NONE))
- {
- BL::ID key = BKE_object_is_modified(b_ob)? b_ob: b_ob.data();
- mesh_map.set_recalc(key);
- }
- }
- else if(object_is_light(b_ob)) {
- if(updated_geometry) {
- light_map.set_recalc(b_ob);
- }
- }
-
- if(updated_geometry) {
- BL::Object::particle_systems_iterator b_psys;
- for(b_ob.particle_systems.begin(b_psys); b_psys != b_ob.particle_systems.end(); ++b_psys)
- particle_system_map.set_recalc(b_ob);
- }
- }
- /* Mesh */
- else if(b_id.is_a(&RNA_Mesh)) {
- BL::Mesh b_mesh(b_id);
- mesh_map.set_recalc(b_mesh);
- }
- /* World */
- else if(b_id.is_a(&RNA_World)) {
- BL::World b_world(b_id);
- if(world_map == b_world.ptr.data) {
- world_recalc = true;
- }
- }
- }
-
- /* Updates shader with object dependency if objects changed. */
- if(has_updated_objects) {
- if(scene->default_background->has_object_dependency) {
- world_recalc = true;
- }
-
- foreach(Shader *shader, scene->shaders) {
- if(shader->has_object_dependency) {
- shader->need_sync_object = true;
- }
- }
- }
+ /* Sync recalc flags from blender to cycles. Actual update is done separate,
+ * so we can do it later on if doing it immediate is not suitable. */
+
+ bool has_updated_objects = b_depsgraph.id_type_updated(BL::DriverTarget::id_type_OBJECT);
+
+ if (experimental) {
+ /* Mark all meshes as needing to be exported again if dicing changed. */
+ PointerRNA cscene = RNA_pointer_get(&b_scene.ptr, "cycles");
+ bool dicing_prop_changed = false;
+
+ float updated_dicing_rate = preview ? RNA_float_get(&cscene, "preview_dicing_rate") :
+ RNA_float_get(&cscene, "dicing_rate");
+
+ if (dicing_rate != updated_dicing_rate) {
+ dicing_rate = updated_dicing_rate;
+ dicing_prop_changed = true;
+ }
+
+ int updated_max_subdivisions = RNA_int_get(&cscene, "max_subdivisions");
+
+ if (max_subdivisions != updated_max_subdivisions) {
+ max_subdivisions = updated_max_subdivisions;
+ dicing_prop_changed = true;
+ }
+
+ if (dicing_prop_changed) {
+ for (const pair<void *, Mesh *> &iter : mesh_map.key_to_scene_data()) {
+ Mesh *mesh = iter.second;
+ if (mesh->subdivision_type != Mesh::SUBDIVISION_NONE) {
+ mesh_map.set_recalc(iter.first);
+ }
+ }
+ }
+ }
+
+ /* Iterate over all IDs in this depsgraph. */
+ BL::Depsgraph::updates_iterator b_update;
+ for (b_depsgraph.updates.begin(b_update); b_update != b_depsgraph.updates.end(); ++b_update) {
+ BL::ID b_id(b_update->id());
+
+ /* Material */
+ if (b_id.is_a(&RNA_Material)) {
+ BL::Material b_mat(b_id);
+ shader_map.set_recalc(b_mat);
+ }
+ /* Light */
+ else if (b_id.is_a(&RNA_Light)) {
+ BL::Light b_light(b_id);
+ shader_map.set_recalc(b_light);
+ }
+ /* Object */
+ else if (b_id.is_a(&RNA_Object)) {
+ BL::Object b_ob(b_id);
+ const bool updated_geometry = b_update->is_updated_geometry();
+
+ if (b_update->is_updated_transform()) {
+ object_map.set_recalc(b_ob);
+ light_map.set_recalc(b_ob);
+ }
+
+ if (object_is_mesh(b_ob)) {
+ if (updated_geometry ||
+ (object_subdivision_type(b_ob, preview, experimental) != Mesh::SUBDIVISION_NONE)) {
+ BL::ID key = BKE_object_is_modified(b_ob) ? b_ob : b_ob.data();
+ mesh_map.set_recalc(key);
+ }
+ }
+ else if (object_is_light(b_ob)) {
+ if (updated_geometry) {
+ light_map.set_recalc(b_ob);
+ }
+ }
+
+ if (updated_geometry) {
+ BL::Object::particle_systems_iterator b_psys;
+ for (b_ob.particle_systems.begin(b_psys); b_psys != b_ob.particle_systems.end(); ++b_psys)
+ particle_system_map.set_recalc(b_ob);
+ }
+ }
+ /* Mesh */
+ else if (b_id.is_a(&RNA_Mesh)) {
+ BL::Mesh b_mesh(b_id);
+ mesh_map.set_recalc(b_mesh);
+ }
+ /* World */
+ else if (b_id.is_a(&RNA_World)) {
+ BL::World b_world(b_id);
+ if (world_map == b_world.ptr.data) {
+ world_recalc = true;
+ }
+ }
+ }
+
+ /* Updates shader with object dependency if objects changed. */
+ if (has_updated_objects) {
+ if (scene->default_background->has_object_dependency) {
+ world_recalc = true;
+ }
+
+ foreach (Shader *shader, scene->shaders) {
+ if (shader->has_object_dependency) {
+ shader->need_sync_object = true;
+ }
+ }
+ }
}
-void BlenderSync::sync_data(BL::RenderSettings& b_render,
- BL::Depsgraph& b_depsgraph,
- BL::SpaceView3D& b_v3d,
- BL::Object& b_override,
- int width, int height,
+void BlenderSync::sync_data(BL::RenderSettings &b_render,
+ BL::Depsgraph &b_depsgraph,
+ BL::SpaceView3D &b_v3d,
+ BL::Object &b_override,
+ int width,
+ int height,
void **python_thread_state)
{
- BL::ViewLayer b_view_layer = b_depsgraph.view_layer_eval();
-
- sync_view_layer(b_v3d, b_view_layer);
- sync_integrator();
- sync_film();
- sync_shaders(b_depsgraph);
- sync_images();
- sync_curve_settings();
-
- mesh_synced.clear(); /* use for objects and motion sync */
-
- if(scene->need_motion() == Scene::MOTION_PASS ||
- scene->need_motion() == Scene::MOTION_NONE ||
- scene->camera->motion_position == Camera::MOTION_POSITION_CENTER)
- {
- sync_objects(b_depsgraph);
- }
- sync_motion(b_render,
- b_depsgraph,
- b_override,
- width, height,
- python_thread_state);
-
- mesh_synced.clear();
-
- free_data_after_sync(b_depsgraph);
+ BL::ViewLayer b_view_layer = b_depsgraph.view_layer_eval();
+
+ sync_view_layer(b_v3d, b_view_layer);
+ sync_integrator();
+ sync_film();
+ sync_shaders(b_depsgraph);
+ sync_images();
+ sync_curve_settings();
+
+ mesh_synced.clear(); /* use for objects and motion sync */
+
+ if (scene->need_motion() == Scene::MOTION_PASS || scene->need_motion() == Scene::MOTION_NONE ||
+ scene->camera->motion_position == Camera::MOTION_POSITION_CENTER) {
+ sync_objects(b_depsgraph);
+ }
+ sync_motion(b_render, b_depsgraph, b_override, width, height, python_thread_state);
+
+ mesh_synced.clear();
+
+ free_data_after_sync(b_depsgraph);
}
/* Integrator */
void BlenderSync::sync_integrator()
{
- BL::RenderSettings r = b_scene.render();
- PointerRNA cscene = RNA_pointer_get(&b_scene.ptr, "cycles");
-
- experimental = (get_enum(cscene, "feature_set") != 0);
-
- Integrator *integrator = scene->integrator;
- Integrator previntegrator = *integrator;
-
- integrator->max_bounce = get_int(cscene, "max_bounces");
-
- integrator->max_diffuse_bounce = get_int(cscene, "diffuse_bounces");
- integrator->max_glossy_bounce = get_int(cscene, "glossy_bounces");
- integrator->max_transmission_bounce = get_int(cscene, "transmission_bounces");
- integrator->max_volume_bounce = get_int(cscene, "volume_bounces");
-
- integrator->transparent_max_bounce = get_int(cscene, "transparent_max_bounces");
-
- integrator->volume_max_steps = get_int(cscene, "volume_max_steps");
- integrator->volume_step_size = get_float(cscene, "volume_step_size");
-
- integrator->caustics_reflective = get_boolean(cscene, "caustics_reflective");
- integrator->caustics_refractive = get_boolean(cscene, "caustics_refractive");
- integrator->filter_glossy = get_float(cscene, "blur_glossy");
-
- integrator->seed = get_int(cscene, "seed");
- if(get_boolean(cscene, "use_animated_seed")) {
- integrator->seed = hash_int_2d(b_scene.frame_current(),
- get_int(cscene, "seed"));
- if(b_scene.frame_subframe() != 0.0f) {
- /* TODO(sergey): Ideally should be some sort of hash_merge,
- * but this is good enough for now.
- */
- integrator->seed += hash_int_2d((int)(b_scene.frame_subframe() * (float)INT_MAX),
- get_int(cscene, "seed"));
- }
- }
-
- integrator->sampling_pattern = (SamplingPattern)get_enum(
- cscene,
- "sampling_pattern",
- SAMPLING_NUM_PATTERNS,
- SAMPLING_PATTERN_SOBOL);
-
- integrator->sample_clamp_direct = get_float(cscene, "sample_clamp_direct");
- integrator->sample_clamp_indirect = get_float(cscene, "sample_clamp_indirect");
- if(!preview) {
- if(integrator->motion_blur != r.use_motion_blur()) {
- scene->object_manager->tag_update(scene);
- scene->camera->tag_update();
- }
-
- integrator->motion_blur = r.use_motion_blur();
- }
-
- integrator->method = (Integrator::Method)get_enum(cscene,
- "progressive",
- Integrator::NUM_METHODS,
- Integrator::PATH);
-
- integrator->sample_all_lights_direct = get_boolean(cscene, "sample_all_lights_direct");
- integrator->sample_all_lights_indirect = get_boolean(cscene, "sample_all_lights_indirect");
- integrator->light_sampling_threshold = get_float(cscene, "light_sampling_threshold");
-
- int diffuse_samples = get_int(cscene, "diffuse_samples");
- int glossy_samples = get_int(cscene, "glossy_samples");
- int transmission_samples = get_int(cscene, "transmission_samples");
- int ao_samples = get_int(cscene, "ao_samples");
- int mesh_light_samples = get_int(cscene, "mesh_light_samples");
- int subsurface_samples = get_int(cscene, "subsurface_samples");
- int volume_samples = get_int(cscene, "volume_samples");
-
- if(get_boolean(cscene, "use_square_samples")) {
- integrator->diffuse_samples = diffuse_samples * diffuse_samples;
- integrator->glossy_samples = glossy_samples * glossy_samples;
- integrator->transmission_samples = transmission_samples * transmission_samples;
- integrator->ao_samples = ao_samples * ao_samples;
- integrator->mesh_light_samples = mesh_light_samples * mesh_light_samples;
- integrator->subsurface_samples = subsurface_samples * subsurface_samples;
- integrator->volume_samples = volume_samples * volume_samples;
- }
- else {
- integrator->diffuse_samples = diffuse_samples;
- integrator->glossy_samples = glossy_samples;
- integrator->transmission_samples = transmission_samples;
- integrator->ao_samples = ao_samples;
- integrator->mesh_light_samples = mesh_light_samples;
- integrator->subsurface_samples = subsurface_samples;
- integrator->volume_samples = volume_samples;
- }
-
- if(b_scene.render().use_simplify()) {
- if(preview) {
- integrator->ao_bounces = get_int(cscene, "ao_bounces");
- }
- else {
- integrator->ao_bounces = get_int(cscene, "ao_bounces_render");
- }
- }
- else {
- integrator->ao_bounces = 0;
- }
-
- if(integrator->modified(previntegrator))
- integrator->tag_update(scene);
+ BL::RenderSettings r = b_scene.render();
+ PointerRNA cscene = RNA_pointer_get(&b_scene.ptr, "cycles");
+
+ experimental = (get_enum(cscene, "feature_set") != 0);
+
+ Integrator *integrator = scene->integrator;
+ Integrator previntegrator = *integrator;
+
+ integrator->max_bounce = get_int(cscene, "max_bounces");
+
+ integrator->max_diffuse_bounce = get_int(cscene, "diffuse_bounces");
+ integrator->max_glossy_bounce = get_int(cscene, "glossy_bounces");
+ integrator->max_transmission_bounce = get_int(cscene, "transmission_bounces");
+ integrator->max_volume_bounce = get_int(cscene, "volume_bounces");
+
+ integrator->transparent_max_bounce = get_int(cscene, "transparent_max_bounces");
+
+ integrator->volume_max_steps = get_int(cscene, "volume_max_steps");
+ integrator->volume_step_size = get_float(cscene, "volume_step_size");
+
+ integrator->caustics_reflective = get_boolean(cscene, "caustics_reflective");
+ integrator->caustics_refractive = get_boolean(cscene, "caustics_refractive");
+ integrator->filter_glossy = get_float(cscene, "blur_glossy");
+
+ integrator->seed = get_int(cscene, "seed");
+ if (get_boolean(cscene, "use_animated_seed")) {
+ integrator->seed = hash_int_2d(b_scene.frame_current(), get_int(cscene, "seed"));
+ if (b_scene.frame_subframe() != 0.0f) {
+ /* TODO(sergey): Ideally should be some sort of hash_merge,
+ * but this is good enough for now.
+ */
+ integrator->seed += hash_int_2d((int)(b_scene.frame_subframe() * (float)INT_MAX),
+ get_int(cscene, "seed"));
+ }
+ }
+
+ integrator->sampling_pattern = (SamplingPattern)get_enum(
+ cscene, "sampling_pattern", SAMPLING_NUM_PATTERNS, SAMPLING_PATTERN_SOBOL);
+
+ integrator->sample_clamp_direct = get_float(cscene, "sample_clamp_direct");
+ integrator->sample_clamp_indirect = get_float(cscene, "sample_clamp_indirect");
+ if (!preview) {
+ if (integrator->motion_blur != r.use_motion_blur()) {
+ scene->object_manager->tag_update(scene);
+ scene->camera->tag_update();
+ }
+
+ integrator->motion_blur = r.use_motion_blur();
+ }
+
+ integrator->method = (Integrator::Method)get_enum(
+ cscene, "progressive", Integrator::NUM_METHODS, Integrator::PATH);
+
+ integrator->sample_all_lights_direct = get_boolean(cscene, "sample_all_lights_direct");
+ integrator->sample_all_lights_indirect = get_boolean(cscene, "sample_all_lights_indirect");
+ integrator->light_sampling_threshold = get_float(cscene, "light_sampling_threshold");
+
+ int diffuse_samples = get_int(cscene, "diffuse_samples");
+ int glossy_samples = get_int(cscene, "glossy_samples");
+ int transmission_samples = get_int(cscene, "transmission_samples");
+ int ao_samples = get_int(cscene, "ao_samples");
+ int mesh_light_samples = get_int(cscene, "mesh_light_samples");
+ int subsurface_samples = get_int(cscene, "subsurface_samples");
+ int volume_samples = get_int(cscene, "volume_samples");
+
+ if (get_boolean(cscene, "use_square_samples")) {
+ integrator->diffuse_samples = diffuse_samples * diffuse_samples;
+ integrator->glossy_samples = glossy_samples * glossy_samples;
+ integrator->transmission_samples = transmission_samples * transmission_samples;
+ integrator->ao_samples = ao_samples * ao_samples;
+ integrator->mesh_light_samples = mesh_light_samples * mesh_light_samples;
+ integrator->subsurface_samples = subsurface_samples * subsurface_samples;
+ integrator->volume_samples = volume_samples * volume_samples;
+ }
+ else {
+ integrator->diffuse_samples = diffuse_samples;
+ integrator->glossy_samples = glossy_samples;
+ integrator->transmission_samples = transmission_samples;
+ integrator->ao_samples = ao_samples;
+ integrator->mesh_light_samples = mesh_light_samples;
+ integrator->subsurface_samples = subsurface_samples;
+ integrator->volume_samples = volume_samples;
+ }
+
+ if (b_scene.render().use_simplify()) {
+ if (preview) {
+ integrator->ao_bounces = get_int(cscene, "ao_bounces");
+ }
+ else {
+ integrator->ao_bounces = get_int(cscene, "ao_bounces_render");
+ }
+ }
+ else {
+ integrator->ao_bounces = 0;
+ }
+
+ if (integrator->modified(previntegrator))
+ integrator->tag_update(scene);
}
/* Film */
void BlenderSync::sync_film()
{
- PointerRNA cscene = RNA_pointer_get(&b_scene.ptr, "cycles");
-
- Film *film = scene->film;
- Film prevfilm = *film;
-
- film->exposure = get_float(cscene, "film_exposure");
- film->filter_type = (FilterType)get_enum(cscene,
- "pixel_filter_type",
- FILTER_NUM_TYPES,
- FILTER_BLACKMAN_HARRIS);
- film->filter_width = (film->filter_type == FILTER_BOX)? 1.0f: get_float(cscene, "filter_width");
-
- if(b_scene.world()) {
- BL::WorldMistSettings b_mist = b_scene.world().mist_settings();
-
- film->mist_start = b_mist.start();
- film->mist_depth = b_mist.depth();
-
- switch(b_mist.falloff()) {
- case BL::WorldMistSettings::falloff_QUADRATIC:
- film->mist_falloff = 2.0f;
- break;
- case BL::WorldMistSettings::falloff_LINEAR:
- film->mist_falloff = 1.0f;
- break;
- case BL::WorldMistSettings::falloff_INVERSE_QUADRATIC:
- film->mist_falloff = 0.5f;
- break;
- }
- }
-
- if(film->modified(prevfilm))
- film->tag_update(scene);
+ PointerRNA cscene = RNA_pointer_get(&b_scene.ptr, "cycles");
+
+ Film *film = scene->film;
+ Film prevfilm = *film;
+
+ film->exposure = get_float(cscene, "film_exposure");
+ film->filter_type = (FilterType)get_enum(
+ cscene, "pixel_filter_type", FILTER_NUM_TYPES, FILTER_BLACKMAN_HARRIS);
+ film->filter_width = (film->filter_type == FILTER_BOX) ? 1.0f :
+ get_float(cscene, "filter_width");
+
+ if (b_scene.world()) {
+ BL::WorldMistSettings b_mist = b_scene.world().mist_settings();
+
+ film->mist_start = b_mist.start();
+ film->mist_depth = b_mist.depth();
+
+ switch (b_mist.falloff()) {
+ case BL::WorldMistSettings::falloff_QUADRATIC:
+ film->mist_falloff = 2.0f;
+ break;
+ case BL::WorldMistSettings::falloff_LINEAR:
+ film->mist_falloff = 1.0f;
+ break;
+ case BL::WorldMistSettings::falloff_INVERSE_QUADRATIC:
+ film->mist_falloff = 0.5f;
+ break;
+ }
+ }
+
+ if (film->modified(prevfilm))
+ film->tag_update(scene);
}
/* Render Layer */
-void BlenderSync::sync_view_layer(BL::SpaceView3D& /*b_v3d*/, BL::ViewLayer& b_view_layer)
+void BlenderSync::sync_view_layer(BL::SpaceView3D & /*b_v3d*/, BL::ViewLayer &b_view_layer)
{
- /* render layer */
- view_layer.name = b_view_layer.name();
- view_layer.use_background_shader = b_view_layer.use_sky();
- view_layer.use_background_ao = b_view_layer.use_ao();
- view_layer.use_surfaces = b_view_layer.use_solid();
- view_layer.use_hair = b_view_layer.use_strand();
-
- /* Material override. */
- view_layer.material_override = b_view_layer.material_override();
-
- /* Sample override. */
- PointerRNA cscene = RNA_pointer_get(&b_scene.ptr, "cycles");
- int use_layer_samples = get_enum(cscene, "use_layer_samples");
-
- view_layer.bound_samples = (use_layer_samples == 1);
- view_layer.samples = 0;
-
- if(use_layer_samples != 2) {
- int samples = b_view_layer.samples();
- if(get_boolean(cscene, "use_square_samples"))
- view_layer.samples = samples * samples;
- else
- view_layer.samples = samples;
- }
-
+ /* render layer */
+ view_layer.name = b_view_layer.name();
+ view_layer.use_background_shader = b_view_layer.use_sky();
+ view_layer.use_background_ao = b_view_layer.use_ao();
+ view_layer.use_surfaces = b_view_layer.use_solid();
+ view_layer.use_hair = b_view_layer.use_strand();
+
+ /* Material override. */
+ view_layer.material_override = b_view_layer.material_override();
+
+ /* Sample override. */
+ PointerRNA cscene = RNA_pointer_get(&b_scene.ptr, "cycles");
+ int use_layer_samples = get_enum(cscene, "use_layer_samples");
+
+ view_layer.bound_samples = (use_layer_samples == 1);
+ view_layer.samples = 0;
+
+ if (use_layer_samples != 2) {
+ int samples = b_view_layer.samples();
+ if (get_boolean(cscene, "use_square_samples"))
+ view_layer.samples = samples * samples;
+ else
+ view_layer.samples = samples;
+ }
}
/* Images */
void BlenderSync::sync_images()
{
- /* Sync is a convention for this API, but currently it frees unused buffers. */
-
- const bool is_interface_locked = b_engine.render() &&
- b_engine.render().use_lock_interface();
- if(is_interface_locked == false && BlenderSession::headless == false) {
- /* If interface is not locked, it's possible image is needed for
- * the display.
- */
- return;
- }
- /* Free buffers used by images which are not needed for render. */
- BL::BlendData::images_iterator b_image;
- for(b_data.images.begin(b_image);
- b_image != b_data.images.end();
- ++b_image)
- {
- /* TODO(sergey): Consider making it an utility function to check
- * whether image is considered builtin.
- */
- const bool is_builtin = b_image->packed_file() ||
- b_image->source() == BL::Image::source_GENERATED ||
- b_image->source() == BL::Image::source_MOVIE ||
- b_engine.is_preview();
- if(is_builtin == false) {
- b_image->buffers_free();
- }
- /* TODO(sergey): Free builtin images not used by any shader. */
- }
+ /* Sync is a convention for this API, but currently it frees unused buffers. */
+
+ const bool is_interface_locked = b_engine.render() && b_engine.render().use_lock_interface();
+ if (is_interface_locked == false && BlenderSession::headless == false) {
+ /* If interface is not locked, it's possible image is needed for
+ * the display.
+ */
+ return;
+ }
+ /* Free buffers used by images which are not needed for render. */
+ BL::BlendData::images_iterator b_image;
+ for (b_data.images.begin(b_image); b_image != b_data.images.end(); ++b_image) {
+ /* TODO(sergey): Consider making it an utility function to check
+ * whether image is considered builtin.
+ */
+ const bool is_builtin = b_image->packed_file() ||
+ b_image->source() == BL::Image::source_GENERATED ||
+ b_image->source() == BL::Image::source_MOVIE || b_engine.is_preview();
+ if (is_builtin == false) {
+ b_image->buffers_free();
+ }
+ /* TODO(sergey): Free builtin images not used by any shader. */
+ }
}
/* Passes */
-PassType BlenderSync::get_pass_type(BL::RenderPass& b_pass)
+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("VolumeDir", PASS_VOLUME_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("VolumeInd", PASS_VOLUME_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);
+ 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("VolumeDir", PASS_VOLUME_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("VolumeInd", PASS_VOLUME_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);
+ 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
- MAP_PASS("Debug Render Time", PASS_RENDER_TIME);
- if(string_startswith(name, cryptomatte_prefix)) {
- return PASS_CRYPTOMATTE;
- }
+ MAP_PASS("Debug Render Time", PASS_RENDER_TIME);
+ if (string_startswith(name, cryptomatte_prefix)) {
+ return PASS_CRYPTOMATTE;
+ }
#undef MAP_PASS
- return PASS_NONE;
+ return PASS_NONE;
}
-int BlenderSync::get_denoising_pass(BL::RenderPass& b_pass)
+int BlenderSync::get_denoising_pass(BL::RenderPass &b_pass)
{
- string name = b_pass.name();
-
- if(name == "Noisy Image") return DENOISING_PASS_PREFILTERED_COLOR;
-
- if(name.substr(0, 10) != "Denoising ") {
- return -1;
- }
- name = name.substr(10);
-
-#define MAP_PASS(passname, offset) if(name == passname) return offset;
- MAP_PASS("Normal", DENOISING_PASS_PREFILTERED_NORMAL);
- MAP_PASS("Albedo", DENOISING_PASS_PREFILTERED_ALBEDO);
- MAP_PASS("Depth", DENOISING_PASS_PREFILTERED_DEPTH);
- MAP_PASS("Shadowing", DENOISING_PASS_PREFILTERED_SHADOWING);
- MAP_PASS("Variance", DENOISING_PASS_PREFILTERED_VARIANCE);
- MAP_PASS("Intensity", DENOISING_PASS_PREFILTERED_INTENSITY);
- MAP_PASS("Clean", DENOISING_PASS_CLEAN);
+ string name = b_pass.name();
+
+ if (name == "Noisy Image")
+ return DENOISING_PASS_PREFILTERED_COLOR;
+
+ if (name.substr(0, 10) != "Denoising ") {
+ return -1;
+ }
+ name = name.substr(10);
+
+#define MAP_PASS(passname, offset) \
+ if (name == passname) \
+ return offset;
+ MAP_PASS("Normal", DENOISING_PASS_PREFILTERED_NORMAL);
+ MAP_PASS("Albedo", DENOISING_PASS_PREFILTERED_ALBEDO);
+ MAP_PASS("Depth", DENOISING_PASS_PREFILTERED_DEPTH);
+ MAP_PASS("Shadowing", DENOISING_PASS_PREFILTERED_SHADOWING);
+ MAP_PASS("Variance", DENOISING_PASS_PREFILTERED_VARIANCE);
+ MAP_PASS("Intensity", DENOISING_PASS_PREFILTERED_INTENSITY);
+ MAP_PASS("Clean", DENOISING_PASS_CLEAN);
#undef MAP_PASS
- return -1;
+ return -1;
}
-vector<Pass> BlenderSync::sync_render_passes(BL::RenderLayer& b_rlay,
- BL::ViewLayer& b_view_layer)
+vector<Pass> BlenderSync::sync_render_passes(BL::RenderLayer &b_rlay, BL::ViewLayer &b_view_layer)
{
- vector<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);
- }
-
- PointerRNA crp = RNA_pointer_get(&b_view_layer.ptr, "cycles");
- bool full_denoising = get_boolean(crp, "use_denoising");
- bool write_denoising_passes = get_boolean(crp, "denoising_store_passes");
-
- scene->film->denoising_flags = 0;
- if(full_denoising || write_denoising_passes) {
-#define MAP_OPTION(name, flag) if(!get_boolean(crp, name)) scene->film->denoising_flags |= flag;
- MAP_OPTION("denoising_diffuse_direct", DENOISING_CLEAN_DIFFUSE_DIR);
- MAP_OPTION("denoising_diffuse_indirect", DENOISING_CLEAN_DIFFUSE_IND);
- MAP_OPTION("denoising_glossy_direct", DENOISING_CLEAN_GLOSSY_DIR);
- MAP_OPTION("denoising_glossy_indirect", DENOISING_CLEAN_GLOSSY_IND);
- MAP_OPTION("denoising_transmission_direct", DENOISING_CLEAN_TRANSMISSION_DIR);
- MAP_OPTION("denoising_transmission_indirect", DENOISING_CLEAN_TRANSMISSION_IND);
- MAP_OPTION("denoising_subsurface_direct", DENOISING_CLEAN_SUBSURFACE_DIR);
- MAP_OPTION("denoising_subsurface_indirect", DENOISING_CLEAN_SUBSURFACE_IND);
+ vector<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);
+ }
+
+ PointerRNA crp = RNA_pointer_get(&b_view_layer.ptr, "cycles");
+ bool full_denoising = get_boolean(crp, "use_denoising");
+ bool write_denoising_passes = get_boolean(crp, "denoising_store_passes");
+
+ scene->film->denoising_flags = 0;
+ if (full_denoising || write_denoising_passes) {
+#define MAP_OPTION(name, flag) \
+ if (!get_boolean(crp, name)) \
+ scene->film->denoising_flags |= flag;
+ MAP_OPTION("denoising_diffuse_direct", DENOISING_CLEAN_DIFFUSE_DIR);
+ MAP_OPTION("denoising_diffuse_indirect", DENOISING_CLEAN_DIFFUSE_IND);
+ MAP_OPTION("denoising_glossy_direct", DENOISING_CLEAN_GLOSSY_DIR);
+ MAP_OPTION("denoising_glossy_indirect", DENOISING_CLEAN_GLOSSY_IND);
+ MAP_OPTION("denoising_transmission_direct", DENOISING_CLEAN_TRANSMISSION_DIR);
+ MAP_OPTION("denoising_transmission_indirect", DENOISING_CLEAN_TRANSMISSION_IND);
+ MAP_OPTION("denoising_subsurface_direct", DENOISING_CLEAN_SUBSURFACE_DIR);
+ MAP_OPTION("denoising_subsurface_indirect", DENOISING_CLEAN_SUBSURFACE_IND);
#undef MAP_OPTION
- b_engine.add_pass("Noisy Image", 4, "RGBA", b_view_layer.name().c_str());
- }
-
- if(write_denoising_passes) {
- b_engine.add_pass("Denoising Normal", 3, "XYZ", b_view_layer.name().c_str());
- b_engine.add_pass("Denoising Albedo", 3, "RGB", b_view_layer.name().c_str());
- b_engine.add_pass("Denoising Depth", 1, "Z", b_view_layer.name().c_str());
- b_engine.add_pass("Denoising Shadowing", 1, "X", b_view_layer.name().c_str());
- b_engine.add_pass("Denoising Variance", 3, "RGB", b_view_layer.name().c_str());
- b_engine.add_pass("Denoising Intensity", 1, "X", b_view_layer.name().c_str());
-
- if(scene->film->denoising_flags & DENOISING_CLEAN_ALL_PASSES) {
- b_engine.add_pass("Denoising Clean", 3, "RGB", b_view_layer.name().c_str());
- }
- }
+ b_engine.add_pass("Noisy Image", 4, "RGBA", b_view_layer.name().c_str());
+ }
+
+ if (write_denoising_passes) {
+ b_engine.add_pass("Denoising Normal", 3, "XYZ", b_view_layer.name().c_str());
+ b_engine.add_pass("Denoising Albedo", 3, "RGB", b_view_layer.name().c_str());
+ b_engine.add_pass("Denoising Depth", 1, "Z", b_view_layer.name().c_str());
+ b_engine.add_pass("Denoising Shadowing", 1, "X", b_view_layer.name().c_str());
+ b_engine.add_pass("Denoising Variance", 3, "RGB", b_view_layer.name().c_str());
+ b_engine.add_pass("Denoising Intensity", 1, "X", b_view_layer.name().c_str());
+
+ if (scene->film->denoising_flags & DENOISING_CLEAN_ALL_PASSES) {
+ b_engine.add_pass("Denoising Clean", 3, "RGB", b_view_layer.name().c_str());
+ }
+ }
#ifdef __KERNEL_DEBUG__
- if(get_boolean(crp, "pass_debug_bvh_traversed_nodes")) {
- b_engine.add_pass("Debug BVH Traversed Nodes", 1, "X", b_view_layer.name().c_str());
- Pass::add(PASS_BVH_TRAVERSED_NODES, passes);
- }
- if(get_boolean(crp, "pass_debug_bvh_traversed_instances")) {
- b_engine.add_pass("Debug BVH Traversed Instances", 1, "X", b_view_layer.name().c_str());
- Pass::add(PASS_BVH_TRAVERSED_INSTANCES, passes);
- }
- if(get_boolean(crp, "pass_debug_bvh_intersections")) {
- b_engine.add_pass("Debug BVH Intersections", 1, "X", b_view_layer.name().c_str());
- Pass::add(PASS_BVH_INTERSECTIONS, passes);
- }
- if(get_boolean(crp, "pass_debug_ray_bounces")) {
- b_engine.add_pass("Debug Ray Bounces", 1, "X", b_view_layer.name().c_str());
- Pass::add(PASS_RAY_BOUNCES, passes);
- }
+ if (get_boolean(crp, "pass_debug_bvh_traversed_nodes")) {
+ b_engine.add_pass("Debug BVH Traversed Nodes", 1, "X", b_view_layer.name().c_str());
+ Pass::add(PASS_BVH_TRAVERSED_NODES, passes);
+ }
+ if (get_boolean(crp, "pass_debug_bvh_traversed_instances")) {
+ b_engine.add_pass("Debug BVH Traversed Instances", 1, "X", b_view_layer.name().c_str());
+ Pass::add(PASS_BVH_TRAVERSED_INSTANCES, passes);
+ }
+ if (get_boolean(crp, "pass_debug_bvh_intersections")) {
+ b_engine.add_pass("Debug BVH Intersections", 1, "X", b_view_layer.name().c_str());
+ Pass::add(PASS_BVH_INTERSECTIONS, passes);
+ }
+ if (get_boolean(crp, "pass_debug_ray_bounces")) {
+ b_engine.add_pass("Debug Ray Bounces", 1, "X", b_view_layer.name().c_str());
+ Pass::add(PASS_RAY_BOUNCES, passes);
+ }
#endif
- if(get_boolean(crp, "pass_debug_render_time")) {
- b_engine.add_pass("Debug Render Time", 1, "X", b_view_layer.name().c_str());
- Pass::add(PASS_RENDER_TIME, passes);
- }
- if(get_boolean(crp, "use_pass_volume_direct")) {
- b_engine.add_pass("VolumeDir", 3, "RGB", b_view_layer.name().c_str());
- Pass::add(PASS_VOLUME_DIRECT, passes);
- }
- if(get_boolean(crp, "use_pass_volume_indirect")) {
- b_engine.add_pass("VolumeInd", 3, "RGB", b_view_layer.name().c_str());
- Pass::add(PASS_VOLUME_INDIRECT, passes);
- }
-
- /* Cryptomatte stores two ID/weight pairs per RGBA layer.
- * User facing paramter is the number of pairs. */
- int crypto_depth = min(16, get_int(crp, "pass_crypto_depth")) / 2;
- scene->film->cryptomatte_depth = crypto_depth;
- scene->film->cryptomatte_passes = CRYPT_NONE;
- if(get_boolean(crp, "use_pass_crypto_object")) {
- for(int i = 0; i < crypto_depth; ++i) {
- string passname = cryptomatte_prefix + string_printf("Object%02d", i);
- b_engine.add_pass(passname.c_str(), 4, "RGBA", b_view_layer.name().c_str());
- Pass::add(PASS_CRYPTOMATTE, passes, passname.c_str());
- }
- scene->film->cryptomatte_passes = (CryptomatteType)(scene->film->cryptomatte_passes | CRYPT_OBJECT);
- }
- if(get_boolean(crp, "use_pass_crypto_material")) {
- for(int i = 0; i < crypto_depth; ++i) {
- string passname = cryptomatte_prefix + string_printf("Material%02d", i);
- b_engine.add_pass(passname.c_str(), 4, "RGBA", b_view_layer.name().c_str());
- Pass::add(PASS_CRYPTOMATTE, passes, passname.c_str());
- }
- scene->film->cryptomatte_passes = (CryptomatteType)(scene->film->cryptomatte_passes | CRYPT_MATERIAL);
- }
- if(get_boolean(crp, "use_pass_crypto_asset")) {
- for(int i = 0; i < crypto_depth; ++i) {
- string passname = cryptomatte_prefix + string_printf("Asset%02d", i);
- b_engine.add_pass(passname.c_str(), 4, "RGBA", b_view_layer.name().c_str());
- Pass::add(PASS_CRYPTOMATTE, passes, passname.c_str());
- }
- scene->film->cryptomatte_passes = (CryptomatteType)(scene->film->cryptomatte_passes | CRYPT_ASSET);
- }
- if(get_boolean(crp, "pass_crypto_accurate") && scene->film->cryptomatte_passes != CRYPT_NONE) {
- scene->film->cryptomatte_passes = (CryptomatteType)(scene->film->cryptomatte_passes | CRYPT_ACCURATE);
- }
-
- return passes;
+ if (get_boolean(crp, "pass_debug_render_time")) {
+ b_engine.add_pass("Debug Render Time", 1, "X", b_view_layer.name().c_str());
+ Pass::add(PASS_RENDER_TIME, passes);
+ }
+ if (get_boolean(crp, "use_pass_volume_direct")) {
+ b_engine.add_pass("VolumeDir", 3, "RGB", b_view_layer.name().c_str());
+ Pass::add(PASS_VOLUME_DIRECT, passes);
+ }
+ if (get_boolean(crp, "use_pass_volume_indirect")) {
+ b_engine.add_pass("VolumeInd", 3, "RGB", b_view_layer.name().c_str());
+ Pass::add(PASS_VOLUME_INDIRECT, passes);
+ }
+
+ /* Cryptomatte stores two ID/weight pairs per RGBA layer.
+ * User facing paramter is the number of pairs. */
+ int crypto_depth = min(16, get_int(crp, "pass_crypto_depth")) / 2;
+ scene->film->cryptomatte_depth = crypto_depth;
+ scene->film->cryptomatte_passes = CRYPT_NONE;
+ if (get_boolean(crp, "use_pass_crypto_object")) {
+ for (int i = 0; i < crypto_depth; ++i) {
+ string passname = cryptomatte_prefix + string_printf("Object%02d", i);
+ b_engine.add_pass(passname.c_str(), 4, "RGBA", b_view_layer.name().c_str());
+ Pass::add(PASS_CRYPTOMATTE, passes, passname.c_str());
+ }
+ scene->film->cryptomatte_passes = (CryptomatteType)(scene->film->cryptomatte_passes |
+ CRYPT_OBJECT);
+ }
+ if (get_boolean(crp, "use_pass_crypto_material")) {
+ for (int i = 0; i < crypto_depth; ++i) {
+ string passname = cryptomatte_prefix + string_printf("Material%02d", i);
+ b_engine.add_pass(passname.c_str(), 4, "RGBA", b_view_layer.name().c_str());
+ Pass::add(PASS_CRYPTOMATTE, passes, passname.c_str());
+ }
+ scene->film->cryptomatte_passes = (CryptomatteType)(scene->film->cryptomatte_passes |
+ CRYPT_MATERIAL);
+ }
+ if (get_boolean(crp, "use_pass_crypto_asset")) {
+ for (int i = 0; i < crypto_depth; ++i) {
+ string passname = cryptomatte_prefix + string_printf("Asset%02d", i);
+ b_engine.add_pass(passname.c_str(), 4, "RGBA", b_view_layer.name().c_str());
+ Pass::add(PASS_CRYPTOMATTE, passes, passname.c_str());
+ }
+ scene->film->cryptomatte_passes = (CryptomatteType)(scene->film->cryptomatte_passes |
+ CRYPT_ASSET);
+ }
+ if (get_boolean(crp, "pass_crypto_accurate") && scene->film->cryptomatte_passes != CRYPT_NONE) {
+ scene->film->cryptomatte_passes = (CryptomatteType)(scene->film->cryptomatte_passes |
+ CRYPT_ACCURATE);
+ }
+
+ return passes;
}
-void BlenderSync::free_data_after_sync(BL::Depsgraph& b_depsgraph)
+void BlenderSync::free_data_after_sync(BL::Depsgraph &b_depsgraph)
{
- /* When viewport display is not needed during render we can force some
- * caches to be releases from blender side in order to reduce peak memory
- * footprint during synchronization process.
- */
- const bool is_interface_locked = b_engine.render() &&
- b_engine.render().use_lock_interface();
- const bool can_free_caches = BlenderSession::headless || is_interface_locked;
- if(!can_free_caches) {
- return;
- }
- /* TODO(sergey): We can actually remove the whole dependency graph,
- * but that will need some API support first.
- */
- BL::Depsgraph::objects_iterator b_ob;
- for(b_depsgraph.objects.begin(b_ob);
- b_ob != b_depsgraph.objects.end();
- ++b_ob)
- {
- b_ob->cache_release();
- }
+ /* When viewport display is not needed during render we can force some
+ * caches to be releases from blender side in order to reduce peak memory
+ * footprint during synchronization process.
+ */
+ const bool is_interface_locked = b_engine.render() && b_engine.render().use_lock_interface();
+ const bool can_free_caches = BlenderSession::headless || is_interface_locked;
+ if (!can_free_caches) {
+ return;
+ }
+ /* TODO(sergey): We can actually remove the whole dependency graph,
+ * but that will need some API support first.
+ */
+ BL::Depsgraph::objects_iterator b_ob;
+ for (b_depsgraph.objects.begin(b_ob); b_ob != b_depsgraph.objects.end(); ++b_ob) {
+ b_ob->cache_release();
+ }
}
/* Scene Parameters */
-SceneParams BlenderSync::get_scene_params(BL::Scene& b_scene,
- bool background)
+SceneParams BlenderSync::get_scene_params(BL::Scene &b_scene, bool background)
{
- BL::RenderSettings r = b_scene.render();
- SceneParams params;
- PointerRNA cscene = RNA_pointer_get(&b_scene.ptr, "cycles");
- const bool shadingsystem = RNA_boolean_get(&cscene, "shading_system");
-
- if(shadingsystem == 0)
- params.shadingsystem = SHADINGSYSTEM_SVM;
- else if(shadingsystem == 1)
- params.shadingsystem = SHADINGSYSTEM_OSL;
-
- if(background || DebugFlags().viewport_static_bvh)
- params.bvh_type = SceneParams::BVH_STATIC;
- else
- params.bvh_type = SceneParams::BVH_DYNAMIC;
-
- params.use_bvh_spatial_split = RNA_boolean_get(&cscene, "debug_use_spatial_splits");
- params.use_bvh_unaligned_nodes = RNA_boolean_get(&cscene, "debug_use_hair_bvh");
- params.num_bvh_time_steps = RNA_int_get(&cscene, "debug_bvh_time_steps");
-
- if(background && params.shadingsystem != SHADINGSYSTEM_OSL)
- params.persistent_data = r.use_persistent_data();
- else
- params.persistent_data = false;
-
- int texture_limit;
- if(background) {
- texture_limit = RNA_enum_get(&cscene, "texture_limit_render");
- }
- else {
- texture_limit = RNA_enum_get(&cscene, "texture_limit");
- }
- if(texture_limit > 0 && b_scene.render().use_simplify()) {
- params.texture_limit = 1 << (texture_limit + 6);
- }
- else {
- params.texture_limit = 0;
- }
-
- /* TODO(sergey): Once OSL supports per-microarchitecture optimization get
- * rid of this.
- */
- if(params.shadingsystem == SHADINGSYSTEM_OSL) {
- params.bvh_layout = BVH_LAYOUT_BVH4;
- }
- else {
- params.bvh_layout = DebugFlags().cpu.bvh_layout;
- }
+ BL::RenderSettings r = b_scene.render();
+ SceneParams params;
+ PointerRNA cscene = RNA_pointer_get(&b_scene.ptr, "cycles");
+ const bool shadingsystem = RNA_boolean_get(&cscene, "shading_system");
+
+ if (shadingsystem == 0)
+ params.shadingsystem = SHADINGSYSTEM_SVM;
+ else if (shadingsystem == 1)
+ params.shadingsystem = SHADINGSYSTEM_OSL;
+
+ if (background || DebugFlags().viewport_static_bvh)
+ params.bvh_type = SceneParams::BVH_STATIC;
+ else
+ params.bvh_type = SceneParams::BVH_DYNAMIC;
+
+ params.use_bvh_spatial_split = RNA_boolean_get(&cscene, "debug_use_spatial_splits");
+ params.use_bvh_unaligned_nodes = RNA_boolean_get(&cscene, "debug_use_hair_bvh");
+ params.num_bvh_time_steps = RNA_int_get(&cscene, "debug_bvh_time_steps");
+
+ if (background && params.shadingsystem != SHADINGSYSTEM_OSL)
+ params.persistent_data = r.use_persistent_data();
+ else
+ params.persistent_data = false;
+
+ int texture_limit;
+ if (background) {
+ texture_limit = RNA_enum_get(&cscene, "texture_limit_render");
+ }
+ else {
+ texture_limit = RNA_enum_get(&cscene, "texture_limit");
+ }
+ if (texture_limit > 0 && b_scene.render().use_simplify()) {
+ params.texture_limit = 1 << (texture_limit + 6);
+ }
+ else {
+ params.texture_limit = 0;
+ }
+
+ /* TODO(sergey): Once OSL supports per-microarchitecture optimization get
+ * rid of this.
+ */
+ if (params.shadingsystem == SHADINGSYSTEM_OSL) {
+ params.bvh_layout = BVH_LAYOUT_BVH4;
+ }
+ else {
+ params.bvh_layout = DebugFlags().cpu.bvh_layout;
+ }
#ifdef WITH_EMBREE
- params.bvh_layout = RNA_boolean_get(&cscene, "use_bvh_embree") ? BVH_LAYOUT_EMBREE : params.bvh_layout;
+ params.bvh_layout = RNA_boolean_get(&cscene, "use_bvh_embree") ? BVH_LAYOUT_EMBREE :
+ params.bvh_layout;
#endif
- return params;
+ return params;
}
/* Session Parameters */
-bool BlenderSync::get_session_pause(BL::Scene& b_scene, bool background)
+bool BlenderSync::get_session_pause(BL::Scene &b_scene, bool background)
{
- PointerRNA cscene = RNA_pointer_get(&b_scene.ptr, "cycles");
- return (background)? false: get_boolean(cscene, "preview_pause");
+ PointerRNA cscene = RNA_pointer_get(&b_scene.ptr, "cycles");
+ return (background) ? false : get_boolean(cscene, "preview_pause");
}
-SessionParams BlenderSync::get_session_params(BL::RenderEngine& b_engine,
- BL::Preferences& b_preferences,
- BL::Scene& b_scene,
+SessionParams BlenderSync::get_session_params(BL::RenderEngine &b_engine,
+ BL::Preferences &b_preferences,
+ BL::Scene &b_scene,
bool background)
{
- SessionParams params;
- PointerRNA cscene = RNA_pointer_get(&b_scene.ptr, "cycles");
-
- /* feature set */
- params.experimental = (get_enum(cscene, "feature_set") != 0);
-
- /* Background */
- params.background = background;
-
- /* Device */
- params.threads = blender_device_threads(b_scene);
- params.device = blender_device_info(b_preferences, b_scene, params.background);
-
- /* samples */
- int samples = get_int(cscene, "samples");
- int aa_samples = get_int(cscene, "aa_samples");
- int preview_samples = get_int(cscene, "preview_samples");
- int preview_aa_samples = get_int(cscene, "preview_aa_samples");
-
- if(get_boolean(cscene, "use_square_samples")) {
- aa_samples = aa_samples * aa_samples;
- preview_aa_samples = preview_aa_samples * preview_aa_samples;
-
- samples = samples * samples;
- preview_samples = preview_samples * preview_samples;
- }
-
- if(get_enum(cscene, "progressive") == 0) {
- if(background) {
- params.samples = aa_samples;
- }
- else {
- params.samples = preview_aa_samples;
- if(params.samples == 0)
- params.samples = INT_MAX;
- }
- }
- else {
- if(background) {
- params.samples = samples;
- }
- else {
- params.samples = preview_samples;
- if(params.samples == 0)
- params.samples = INT_MAX;
- }
- }
-
- /* Clamp samples. */
- params.samples = min(params.samples, Integrator::MAX_SAMPLES);
-
- /* tiles */
- const bool is_cpu = (params.device.type == DEVICE_CPU);
- if(!is_cpu && !background) {
- /* currently GPU could be much slower than CPU when using tiles,
- * still need to be investigated, but meanwhile make it possible
- * to work in viewport smoothly
- */
- int debug_tile_size = get_int(cscene, "debug_tile_size");
-
- params.tile_size = make_int2(debug_tile_size, debug_tile_size);
- }
- else {
- int tile_x = b_engine.tile_x();
- int tile_y = b_engine.tile_y();
-
- params.tile_size = make_int2(tile_x, tile_y);
- }
-
- if((BlenderSession::headless == false) && background) {
- params.tile_order = (TileOrder)get_enum(cscene, "tile_order");
- }
- else {
- params.tile_order = TILE_BOTTOM_TO_TOP;
- }
-
- /* other parameters */
- params.start_resolution = get_int(cscene, "preview_start_resolution");
- params.pixel_size = b_engine.get_preview_pixel_size(b_scene);
-
- /* other parameters */
- params.cancel_timeout = (double)get_float(cscene, "debug_cancel_timeout");
- params.reset_timeout = (double)get_float(cscene, "debug_reset_timeout");
- params.text_timeout = (double)get_float(cscene, "debug_text_timeout");
-
- /* progressive refine */
- BL::RenderSettings b_r = b_scene.render();
- params.progressive_refine = (b_engine.is_preview() ||
- get_boolean(cscene, "use_progressive_refine")) &&
- !b_r.use_save_buffers();
-
- if(params.progressive_refine) {
- BL::Scene::view_layers_iterator b_view_layer;
- for(b_scene.view_layers.begin(b_view_layer); b_view_layer != b_scene.view_layers.end(); ++b_view_layer) {
- PointerRNA crl = RNA_pointer_get(&b_view_layer->ptr, "cycles");
- if(get_boolean(crl, "use_denoising")) {
- params.progressive_refine = false;
- }
- }
- }
-
- if(background) {
- if(params.progressive_refine)
- params.progressive = true;
- else
- params.progressive = false;
-
- params.start_resolution = INT_MAX;
- params.pixel_size = 1;
- }
- else
- params.progressive = true;
-
- /* shading system - scene level needs full refresh */
- const bool shadingsystem = RNA_boolean_get(&cscene, "shading_system");
-
- if(shadingsystem == 0)
- params.shadingsystem = SHADINGSYSTEM_SVM;
- else if(shadingsystem == 1)
- params.shadingsystem = SHADINGSYSTEM_OSL;
-
- /* color managagement */
- params.display_buffer_linear = b_engine.support_display_space_shader(b_scene);
-
- if(b_engine.is_preview()) {
- /* For preview rendering we're using same timeout as
- * blender's job update.
- */
- params.progressive_update_timeout = 0.1;
- }
-
- params.use_profiling = params.device.has_profiling && !b_engine.is_preview() &&
- background && BlenderSession::print_render_stats;
-
- return params;
+ SessionParams params;
+ PointerRNA cscene = RNA_pointer_get(&b_scene.ptr, "cycles");
+
+ /* feature set */
+ params.experimental = (get_enum(cscene, "feature_set") != 0);
+
+ /* Background */
+ params.background = background;
+
+ /* Device */
+ params.threads = blender_device_threads(b_scene);
+ params.device = blender_device_info(b_preferences, b_scene, params.background);
+
+ /* samples */
+ int samples = get_int(cscene, "samples");
+ int aa_samples = get_int(cscene, "aa_samples");
+ int preview_samples = get_int(cscene, "preview_samples");
+ int preview_aa_samples = get_int(cscene, "preview_aa_samples");
+
+ if (get_boolean(cscene, "use_square_samples")) {
+ aa_samples = aa_samples * aa_samples;
+ preview_aa_samples = preview_aa_samples * preview_aa_samples;
+
+ samples = samples * samples;
+ preview_samples = preview_samples * preview_samples;
+ }
+
+ if (get_enum(cscene, "progressive") == 0) {
+ if (background) {
+ params.samples = aa_samples;
+ }
+ else {
+ params.samples = preview_aa_samples;
+ if (params.samples == 0)
+ params.samples = INT_MAX;
+ }
+ }
+ else {
+ if (background) {
+ params.samples = samples;
+ }
+ else {
+ params.samples = preview_samples;
+ if (params.samples == 0)
+ params.samples = INT_MAX;
+ }
+ }
+
+ /* Clamp samples. */
+ params.samples = min(params.samples, Integrator::MAX_SAMPLES);
+
+ /* tiles */
+ const bool is_cpu = (params.device.type == DEVICE_CPU);
+ if (!is_cpu && !background) {
+ /* currently GPU could be much slower than CPU when using tiles,
+ * still need to be investigated, but meanwhile make it possible
+ * to work in viewport smoothly
+ */
+ int debug_tile_size = get_int(cscene, "debug_tile_size");
+
+ params.tile_size = make_int2(debug_tile_size, debug_tile_size);
+ }
+ else {
+ int tile_x = b_engine.tile_x();
+ int tile_y = b_engine.tile_y();
+
+ params.tile_size = make_int2(tile_x, tile_y);
+ }
+
+ if ((BlenderSession::headless == false) && background) {
+ params.tile_order = (TileOrder)get_enum(cscene, "tile_order");
+ }
+ else {
+ params.tile_order = TILE_BOTTOM_TO_TOP;
+ }
+
+ /* other parameters */
+ params.start_resolution = get_int(cscene, "preview_start_resolution");
+ params.pixel_size = b_engine.get_preview_pixel_size(b_scene);
+
+ /* other parameters */
+ params.cancel_timeout = (double)get_float(cscene, "debug_cancel_timeout");
+ params.reset_timeout = (double)get_float(cscene, "debug_reset_timeout");
+ params.text_timeout = (double)get_float(cscene, "debug_text_timeout");
+
+ /* progressive refine */
+ BL::RenderSettings b_r = b_scene.render();
+ params.progressive_refine = (b_engine.is_preview() ||
+ get_boolean(cscene, "use_progressive_refine")) &&
+ !b_r.use_save_buffers();
+
+ if (params.progressive_refine) {
+ BL::Scene::view_layers_iterator b_view_layer;
+ for (b_scene.view_layers.begin(b_view_layer); b_view_layer != b_scene.view_layers.end();
+ ++b_view_layer) {
+ PointerRNA crl = RNA_pointer_get(&b_view_layer->ptr, "cycles");
+ if (get_boolean(crl, "use_denoising")) {
+ params.progressive_refine = false;
+ }
+ }
+ }
+
+ if (background) {
+ if (params.progressive_refine)
+ params.progressive = true;
+ else
+ params.progressive = false;
+
+ params.start_resolution = INT_MAX;
+ params.pixel_size = 1;
+ }
+ else
+ params.progressive = true;
+
+ /* shading system - scene level needs full refresh */
+ const bool shadingsystem = RNA_boolean_get(&cscene, "shading_system");
+
+ if (shadingsystem == 0)
+ params.shadingsystem = SHADINGSYSTEM_SVM;
+ else if (shadingsystem == 1)
+ params.shadingsystem = SHADINGSYSTEM_OSL;
+
+ /* color managagement */
+ params.display_buffer_linear = b_engine.support_display_space_shader(b_scene);
+
+ if (b_engine.is_preview()) {
+ /* For preview rendering we're using same timeout as
+ * blender's job update.
+ */
+ params.progressive_update_timeout = 0.1;
+ }
+
+ params.use_profiling = params.device.has_profiling && !b_engine.is_preview() && background &&
+ BlenderSession::print_render_stats;
+
+ return params;
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/blender/blender_sync.h b/intern/cycles/blender/blender_sync.h
index 8af3fde3323..00afceebde3 100644
--- a/intern/cycles/blender/blender_sync.h
+++ b/intern/cycles/blender/blender_sync.h
@@ -49,171 +49,173 @@ class ShaderGraph;
class ShaderNode;
class BlenderSync {
-public:
- BlenderSync(BL::RenderEngine& b_engine,
- BL::BlendData& b_data,
- BL::Scene& b_scene,
- Scene *scene,
- bool preview,
- Progress &progress);
- ~BlenderSync();
-
- /* sync */
- void sync_recalc(BL::Depsgraph& b_depsgraph);
- void sync_data(BL::RenderSettings& b_render,
- BL::Depsgraph& b_depsgraph,
- BL::SpaceView3D& b_v3d,
- BL::Object& b_override,
- int width, int height,
- void **python_thread_state);
- void sync_view_layer(BL::SpaceView3D& b_v3d, BL::ViewLayer& b_view_layer);
- vector<Pass> sync_render_passes(BL::RenderLayer& b_render_layer,
- BL::ViewLayer& b_view_layer);
- void sync_integrator();
- void sync_camera(BL::RenderSettings& b_render,
- BL::Object& b_override,
- int width, int height,
- const char *viewname);
- void sync_view(BL::SpaceView3D& b_v3d,
- BL::RegionView3D& b_rv3d,
- int width, int height);
- inline int get_layer_samples() { return view_layer.samples; }
- inline int get_layer_bound_samples() { return view_layer.bound_samples; }
-
- /* get parameters */
- static SceneParams get_scene_params(BL::Scene& b_scene,
- bool background);
- static SessionParams get_session_params(BL::RenderEngine& b_engine,
- BL::Preferences& b_userpref,
- BL::Scene& b_scene,
- bool background);
- static bool get_session_pause(BL::Scene& b_scene, bool background);
- static BufferParams get_buffer_params(BL::RenderSettings& b_render,
- BL::SpaceView3D& b_v3d,
- BL::RegionView3D& b_rv3d,
- Camera *cam,
- int width, int height);
-
- static PassType get_pass_type(BL::RenderPass& b_pass);
- static int get_denoising_pass(BL::RenderPass& b_pass);
-
-private:
- /* sync */
- void sync_lights(BL::Depsgraph& b_depsgraph, bool update_all);
- void sync_materials(BL::Depsgraph& b_depsgraph, bool update_all);
- void sync_objects(BL::Depsgraph& b_depsgraph, float motion_time = 0.0f);
- void sync_motion(BL::RenderSettings& b_render,
- BL::Depsgraph& b_depsgraph,
- BL::Object& b_override,
- int width, int height,
- void **python_thread_state);
- void sync_film();
- void sync_view();
- void sync_world(BL::Depsgraph& b_depsgraph, bool update_all);
- void sync_shaders(BL::Depsgraph& b_depsgraph);
- void sync_curve_settings();
-
- void sync_nodes(Shader *shader, BL::ShaderNodeTree& b_ntree);
- Mesh *sync_mesh(BL::Depsgraph& b_depsgrpah,
- BL::Object& b_ob,
- BL::Object& b_ob_instance,
- bool object_updated,
- bool show_self,
- bool show_particles);
- void sync_curves(Mesh *mesh,
- BL::Mesh& b_mesh,
- BL::Object& b_ob,
- bool motion,
- int motion_step = 0);
- Object *sync_object(BL::Depsgraph& b_depsgraph,
- BL::ViewLayer& b_view_layer,
- BL::DepsgraphObjectInstance& b_instance,
- float motion_time,
- bool show_self,
- bool show_particles,
- BlenderObjectCulling& culling,
- bool *use_portal);
- void sync_light(BL::Object& b_parent,
- int persistent_id[OBJECT_PERSISTENT_ID_SIZE],
- BL::Object& b_ob,
- BL::Object& b_ob_instance,
- int random_id,
- Transform& tfm,
- bool *use_portal);
- void sync_background_light(bool use_portal);
- void sync_mesh_motion(BL::Depsgraph& b_depsgraph,
- BL::Object& b_ob,
- Object *object,
- float motion_time);
- void sync_camera_motion(BL::RenderSettings& b_render,
- BL::Object& b_ob,
- int width, int height,
- float motion_time);
-
- /* particles */
- bool sync_dupli_particle(BL::Object& b_ob,
- BL::DepsgraphObjectInstance& b_instance,
- Object *object);
-
- /* Images. */
- void sync_images();
-
- /* Early data free. */
- void free_data_after_sync(BL::Depsgraph& b_depsgraph);
-
- /* util */
- void find_shader(BL::ID& id, vector<Shader*>& used_shaders, Shader *default_shader);
- bool BKE_object_is_modified(BL::Object& b_ob);
- bool object_is_mesh(BL::Object& b_ob);
- bool object_is_light(BL::Object& b_ob);
-
- /* variables */
- BL::RenderEngine b_engine;
- BL::BlendData b_data;
- BL::Scene b_scene;
-
- id_map<void*, Shader> shader_map;
- id_map<ObjectKey, Object> object_map;
- id_map<void*, Mesh> mesh_map;
- id_map<ObjectKey, Light> light_map;
- id_map<ParticleSystemKey, ParticleSystem> particle_system_map;
- set<Mesh*> mesh_synced;
- set<Mesh*> mesh_motion_synced;
- set<float> motion_times;
- void *world_map;
- bool world_recalc;
-
- Scene *scene;
- bool preview;
- bool experimental;
-
- float dicing_rate;
- int max_subdivisions;
-
- struct RenderLayerInfo {
- RenderLayerInfo()
- : material_override(PointerRNA_NULL),
- use_background_shader(true),
- use_background_ao(true),
- use_surfaces(true),
- use_hair(true),
- samples(0),
- bound_samples(false)
- {}
-
- string name;
- BL::Material material_override;
- bool use_background_shader;
- bool use_background_ao;
- bool use_surfaces;
- bool use_hair;
- int samples;
- bool bound_samples;
- } view_layer;
-
- Progress &progress;
+ public:
+ BlenderSync(BL::RenderEngine &b_engine,
+ BL::BlendData &b_data,
+ BL::Scene &b_scene,
+ Scene *scene,
+ bool preview,
+ Progress &progress);
+ ~BlenderSync();
+
+ /* sync */
+ void sync_recalc(BL::Depsgraph &b_depsgraph);
+ void sync_data(BL::RenderSettings &b_render,
+ BL::Depsgraph &b_depsgraph,
+ BL::SpaceView3D &b_v3d,
+ BL::Object &b_override,
+ int width,
+ int height,
+ void **python_thread_state);
+ void sync_view_layer(BL::SpaceView3D &b_v3d, BL::ViewLayer &b_view_layer);
+ vector<Pass> sync_render_passes(BL::RenderLayer &b_render_layer, BL::ViewLayer &b_view_layer);
+ void sync_integrator();
+ void sync_camera(BL::RenderSettings &b_render,
+ BL::Object &b_override,
+ int width,
+ int height,
+ const char *viewname);
+ void sync_view(BL::SpaceView3D &b_v3d, BL::RegionView3D &b_rv3d, int width, int height);
+ inline int get_layer_samples()
+ {
+ return view_layer.samples;
+ }
+ inline int get_layer_bound_samples()
+ {
+ return view_layer.bound_samples;
+ }
+
+ /* get parameters */
+ static SceneParams get_scene_params(BL::Scene &b_scene, bool background);
+ static SessionParams get_session_params(BL::RenderEngine &b_engine,
+ BL::Preferences &b_userpref,
+ BL::Scene &b_scene,
+ bool background);
+ static bool get_session_pause(BL::Scene &b_scene, bool background);
+ static BufferParams get_buffer_params(BL::RenderSettings &b_render,
+ BL::SpaceView3D &b_v3d,
+ BL::RegionView3D &b_rv3d,
+ Camera *cam,
+ int width,
+ int height);
+
+ static PassType get_pass_type(BL::RenderPass &b_pass);
+ static int get_denoising_pass(BL::RenderPass &b_pass);
+
+ private:
+ /* sync */
+ void sync_lights(BL::Depsgraph &b_depsgraph, bool update_all);
+ void sync_materials(BL::Depsgraph &b_depsgraph, bool update_all);
+ void sync_objects(BL::Depsgraph &b_depsgraph, float motion_time = 0.0f);
+ void sync_motion(BL::RenderSettings &b_render,
+ BL::Depsgraph &b_depsgraph,
+ BL::Object &b_override,
+ int width,
+ int height,
+ void **python_thread_state);
+ void sync_film();
+ void sync_view();
+ void sync_world(BL::Depsgraph &b_depsgraph, bool update_all);
+ void sync_shaders(BL::Depsgraph &b_depsgraph);
+ void sync_curve_settings();
+
+ void sync_nodes(Shader *shader, BL::ShaderNodeTree &b_ntree);
+ Mesh *sync_mesh(BL::Depsgraph &b_depsgrpah,
+ BL::Object &b_ob,
+ BL::Object &b_ob_instance,
+ bool object_updated,
+ bool show_self,
+ bool show_particles);
+ void sync_curves(
+ Mesh *mesh, BL::Mesh &b_mesh, BL::Object &b_ob, bool motion, int motion_step = 0);
+ Object *sync_object(BL::Depsgraph &b_depsgraph,
+ BL::ViewLayer &b_view_layer,
+ BL::DepsgraphObjectInstance &b_instance,
+ float motion_time,
+ bool show_self,
+ bool show_particles,
+ BlenderObjectCulling &culling,
+ bool *use_portal);
+ void sync_light(BL::Object &b_parent,
+ int persistent_id[OBJECT_PERSISTENT_ID_SIZE],
+ BL::Object &b_ob,
+ BL::Object &b_ob_instance,
+ int random_id,
+ Transform &tfm,
+ bool *use_portal);
+ void sync_background_light(bool use_portal);
+ void sync_mesh_motion(BL::Depsgraph &b_depsgraph,
+ BL::Object &b_ob,
+ Object *object,
+ float motion_time);
+ void sync_camera_motion(
+ BL::RenderSettings &b_render, BL::Object &b_ob, int width, int height, float motion_time);
+
+ /* particles */
+ bool sync_dupli_particle(BL::Object &b_ob,
+ BL::DepsgraphObjectInstance &b_instance,
+ Object *object);
+
+ /* Images. */
+ void sync_images();
+
+ /* Early data free. */
+ void free_data_after_sync(BL::Depsgraph &b_depsgraph);
+
+ /* util */
+ void find_shader(BL::ID &id, vector<Shader *> &used_shaders, Shader *default_shader);
+ bool BKE_object_is_modified(BL::Object &b_ob);
+ bool object_is_mesh(BL::Object &b_ob);
+ bool object_is_light(BL::Object &b_ob);
+
+ /* variables */
+ BL::RenderEngine b_engine;
+ BL::BlendData b_data;
+ BL::Scene b_scene;
+
+ id_map<void *, Shader> shader_map;
+ id_map<ObjectKey, Object> object_map;
+ id_map<void *, Mesh> mesh_map;
+ id_map<ObjectKey, Light> light_map;
+ id_map<ParticleSystemKey, ParticleSystem> particle_system_map;
+ set<Mesh *> mesh_synced;
+ set<Mesh *> mesh_motion_synced;
+ set<float> motion_times;
+ void *world_map;
+ bool world_recalc;
+
+ Scene *scene;
+ bool preview;
+ bool experimental;
+
+ float dicing_rate;
+ int max_subdivisions;
+
+ struct RenderLayerInfo {
+ RenderLayerInfo()
+ : material_override(PointerRNA_NULL),
+ use_background_shader(true),
+ use_background_ao(true),
+ use_surfaces(true),
+ use_hair(true),
+ samples(0),
+ bound_samples(false)
+ {
+ }
+
+ string name;
+ BL::Material material_override;
+ bool use_background_shader;
+ bool use_background_ao;
+ bool use_surfaces;
+ bool use_hair;
+ int samples;
+ bool bound_samples;
+ } view_layer;
+
+ Progress &progress;
};
CCL_NAMESPACE_END
-#endif /* __BLENDER_SYNC_H__ */
+#endif /* __BLENDER_SYNC_H__ */
diff --git a/intern/cycles/blender/blender_texture.cpp b/intern/cycles/blender/blender_texture.cpp
index a0371a7eed8..7b05f361a29 100644
--- a/intern/cycles/blender/blender_texture.cpp
+++ b/intern/cycles/blender/blender_texture.cpp
@@ -22,36 +22,36 @@ namespace {
/* Point density helpers. */
-void density_texture_space_invert(float3& loc,
- float3& size)
+void density_texture_space_invert(float3 &loc, float3 &size)
{
- if(size.x != 0.0f) size.x = 0.5f/size.x;
- if(size.y != 0.0f) size.y = 0.5f/size.y;
- if(size.z != 0.0f) size.z = 0.5f/size.z;
-
- loc = loc*size - make_float3(0.5f, 0.5f, 0.5f);
+ if (size.x != 0.0f)
+ size.x = 0.5f / size.x;
+ if (size.y != 0.0f)
+ size.y = 0.5f / size.y;
+ if (size.z != 0.0f)
+ size.z = 0.5f / size.z;
+
+ loc = loc * size - make_float3(0.5f, 0.5f, 0.5f);
}
-} /* namespace */
+} /* namespace */
-void point_density_texture_space(BL::Depsgraph& b_depsgraph,
- BL::ShaderNodeTexPointDensity& b_point_density_node,
- float3& loc,
- float3& size)
+void point_density_texture_space(BL::Depsgraph &b_depsgraph,
+ BL::ShaderNodeTexPointDensity &b_point_density_node,
+ float3 &loc,
+ float3 &size)
{
- BL::Object b_ob(b_point_density_node.object());
- if(!b_ob) {
- loc = make_float3(0.0f, 0.0f, 0.0f);
- size = make_float3(0.0f, 0.0f, 0.0f);
- return;
- }
- float3 min, max;
- b_point_density_node.calc_point_density_minmax(b_depsgraph,
- &min[0],
- &max[0]);
- loc = (min + max) * 0.5f;
- size = (max - min) * 0.5f;
- density_texture_space_invert(loc, size);
+ BL::Object b_ob(b_point_density_node.object());
+ if (!b_ob) {
+ loc = make_float3(0.0f, 0.0f, 0.0f);
+ size = make_float3(0.0f, 0.0f, 0.0f);
+ return;
+ }
+ float3 min, max;
+ b_point_density_node.calc_point_density_minmax(b_depsgraph, &min[0], &max[0]);
+ loc = (min + max) * 0.5f;
+ size = (max - min) * 0.5f;
+ density_texture_space_invert(loc, size);
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/blender/blender_texture.h b/intern/cycles/blender/blender_texture.h
index b4e166c5cdd..896bf62da70 100644
--- a/intern/cycles/blender/blender_texture.h
+++ b/intern/cycles/blender/blender_texture.h
@@ -22,11 +22,11 @@
CCL_NAMESPACE_BEGIN
-void point_density_texture_space(BL::Depsgraph& b_depsgraph,
- BL::ShaderNodeTexPointDensity& b_point_density_node,
- float3& loc,
- float3& size);
+void point_density_texture_space(BL::Depsgraph &b_depsgraph,
+ BL::ShaderNodeTexPointDensity &b_point_density_node,
+ float3 &loc,
+ float3 &size);
CCL_NAMESPACE_END
-#endif /* __BLENDER_TEXTURE_H__ */
+#endif /* __BLENDER_TEXTURE_H__ */
diff --git a/intern/cycles/blender/blender_util.h b/intern/cycles/blender/blender_util.h
index f302b09459f..e68f92474bf 100644
--- a/intern/cycles/blender/blender_util.h
+++ b/intern/cycles/blender/blender_util.h
@@ -43,338 +43,320 @@ CCL_NAMESPACE_BEGIN
void python_thread_state_save(void **python_thread_state);
void python_thread_state_restore(void **python_thread_state);
-static inline BL::Mesh object_to_mesh(BL::BlendData& data,
- BL::Object& object,
- BL::Depsgraph& depsgraph,
+static inline BL::Mesh object_to_mesh(BL::BlendData &data,
+ BL::Object &object,
+ BL::Depsgraph &depsgraph,
bool calc_undeformed,
Mesh::SubdivisionType subdivision_type)
{
- /* TODO: make this work with copy-on-write, modifiers are already evaluated. */
+ /* TODO: make this work with copy-on-write, modifiers are already evaluated. */
#if 0
- bool subsurf_mod_show_render = false;
- bool subsurf_mod_show_viewport = false;
+ bool subsurf_mod_show_render = false;
+ bool subsurf_mod_show_viewport = false;
- if(subdivision_type != Mesh::SUBDIVISION_NONE) {
- BL::Modifier subsurf_mod = object.modifiers[object.modifiers.length()-1];
+ if(subdivision_type != Mesh::SUBDIVISION_NONE) {
+ BL::Modifier subsurf_mod = object.modifiers[object.modifiers.length()-1];
- subsurf_mod_show_render = subsurf_mod.show_render();
- subsurf_mod_show_viewport = subsurf_mod.show_viewport();
+ subsurf_mod_show_render = subsurf_mod.show_render();
+ subsurf_mod_show_viewport = subsurf_mod.show_viewport();
- subsurf_mod.show_render(false);
- subsurf_mod.show_viewport(false);
- }
+ subsurf_mod.show_render(false);
+ subsurf_mod.show_viewport(false);
+ }
#endif
- BL::Mesh mesh(PointerRNA_NULL);
- if(object.type() == BL::Object::type_MESH) {
- /* TODO: calc_undeformed is not used. */
- mesh = BL::Mesh(object.data());
-
- /* Make a copy to split faces if we use autosmooth, otherwise not needed.
- * Also in edit mode do we need to make a copy, to ensure data layers like
- * UV are not empty. */
- if (mesh.is_editmode() ||
- (mesh.use_auto_smooth() && subdivision_type == Mesh::SUBDIVISION_NONE))
- {
- mesh = data.meshes.new_from_object(depsgraph, object, false, false);
- }
- }
- else {
- mesh = data.meshes.new_from_object(depsgraph, object, true, calc_undeformed);
- }
+ BL::Mesh mesh(PointerRNA_NULL);
+ if (object.type() == BL::Object::type_MESH) {
+ /* TODO: calc_undeformed is not used. */
+ mesh = BL::Mesh(object.data());
+
+ /* Make a copy to split faces if we use autosmooth, otherwise not needed.
+ * Also in edit mode do we need to make a copy, to ensure data layers like
+ * UV are not empty. */
+ if (mesh.is_editmode() ||
+ (mesh.use_auto_smooth() && subdivision_type == Mesh::SUBDIVISION_NONE)) {
+ mesh = data.meshes.new_from_object(depsgraph, object, false, false);
+ }
+ }
+ else {
+ mesh = data.meshes.new_from_object(depsgraph, object, true, calc_undeformed);
+ }
#if 0
- if(subdivision_type != Mesh::SUBDIVISION_NONE) {
- BL::Modifier subsurf_mod = object.modifiers[object.modifiers.length()-1];
+ if(subdivision_type != Mesh::SUBDIVISION_NONE) {
+ BL::Modifier subsurf_mod = object.modifiers[object.modifiers.length()-1];
- subsurf_mod.show_render(subsurf_mod_show_render);
- subsurf_mod.show_viewport(subsurf_mod_show_viewport);
- }
+ subsurf_mod.show_render(subsurf_mod_show_render);
+ subsurf_mod.show_viewport(subsurf_mod_show_viewport);
+ }
#endif
- if((bool)mesh && subdivision_type == Mesh::SUBDIVISION_NONE) {
- if(mesh.use_auto_smooth()) {
- mesh.split_faces(false);
- }
+ if ((bool)mesh && subdivision_type == Mesh::SUBDIVISION_NONE) {
+ if (mesh.use_auto_smooth()) {
+ mesh.split_faces(false);
+ }
- mesh.calc_loop_triangles();
- }
+ mesh.calc_loop_triangles();
+ }
- return mesh;
+ return mesh;
}
-static inline void free_object_to_mesh(BL::BlendData& data,
- BL::Object& object,
- BL::Mesh& mesh)
+static inline void free_object_to_mesh(BL::BlendData &data, BL::Object &object, BL::Mesh &mesh)
{
- /* Free mesh if we didn't just use the existing one. */
- if(object.data().ptr.data != mesh.ptr.data) {
- data.meshes.remove(mesh, false, true, false);
- }
+ /* Free mesh if we didn't just use the existing one. */
+ if (object.data().ptr.data != mesh.ptr.data) {
+ data.meshes.remove(mesh, false, true, false);
+ }
}
-static inline void colorramp_to_array(BL::ColorRamp& ramp,
- array<float3>& ramp_color,
- array<float>& ramp_alpha,
+static inline void colorramp_to_array(BL::ColorRamp &ramp,
+ array<float3> &ramp_color,
+ array<float> &ramp_alpha,
int size)
{
- ramp_color.resize(size);
- ramp_alpha.resize(size);
+ ramp_color.resize(size);
+ ramp_alpha.resize(size);
- for(int i = 0; i < size; i++) {
- float color[4];
+ for (int i = 0; i < size; i++) {
+ float color[4];
- ramp.evaluate((float)i/(float)(size-1), color);
- ramp_color[i] = make_float3(color[0], color[1], color[2]);
- ramp_alpha[i] = color[3];
- }
+ ramp.evaluate((float)i / (float)(size - 1), color);
+ ramp_color[i] = make_float3(color[0], color[1], color[2]);
+ ramp_alpha[i] = color[3];
+ }
}
-static inline void curvemap_minmax_curve(/*const*/ BL::CurveMap& curve,
- float *min_x,
- float *max_x)
+static inline void curvemap_minmax_curve(/*const*/ BL::CurveMap &curve, float *min_x, float *max_x)
{
- *min_x = min(*min_x, curve.points[0].location()[0]);
- *max_x = max(*max_x, curve.points[curve.points.length() - 1].location()[0]);
+ *min_x = min(*min_x, curve.points[0].location()[0]);
+ *max_x = max(*max_x, curve.points[curve.points.length() - 1].location()[0]);
}
-static inline void curvemapping_minmax(/*const*/ BL::CurveMapping& cumap,
+static inline void curvemapping_minmax(/*const*/ BL::CurveMapping &cumap,
bool rgb_curve,
float *min_x,
float *max_x)
{
- /* const int num_curves = cumap.curves.length(); */ /* Gives linking error so far. */
- const int num_curves = rgb_curve? 4: 3;
- *min_x = FLT_MAX;
- *max_x = -FLT_MAX;
- for(int i = 0; i < num_curves; ++i) {
- BL::CurveMap map(cumap.curves[i]);
- curvemap_minmax_curve(map, min_x, max_x);
- }
+ /* const int num_curves = cumap.curves.length(); */ /* Gives linking error so far. */
+ const int num_curves = rgb_curve ? 4 : 3;
+ *min_x = FLT_MAX;
+ *max_x = -FLT_MAX;
+ for (int i = 0; i < num_curves; ++i) {
+ BL::CurveMap map(cumap.curves[i]);
+ curvemap_minmax_curve(map, min_x, max_x);
+ }
}
-static inline void curvemapping_to_array(BL::CurveMapping& cumap,
- array<float>& data,
- int size)
+static inline void curvemapping_to_array(BL::CurveMapping &cumap, array<float> &data, int size)
{
- cumap.update();
- BL::CurveMap curve = cumap.curves[0];
- data.resize(size);
- for(int i = 0; i < size; i++) {
- float t = (float)i/(float)(size-1);
- data[i] = curve.evaluate(t);
- }
+ cumap.update();
+ BL::CurveMap curve = cumap.curves[0];
+ data.resize(size);
+ for (int i = 0; i < size; i++) {
+ float t = (float)i / (float)(size - 1);
+ data[i] = curve.evaluate(t);
+ }
}
-static inline void curvemapping_color_to_array(BL::CurveMapping& cumap,
- array<float3>& data,
+static inline void curvemapping_color_to_array(BL::CurveMapping &cumap,
+ array<float3> &data,
int size,
bool rgb_curve)
{
- float min_x = 0.0f, max_x = 1.0f;
+ float min_x = 0.0f, max_x = 1.0f;
- /* TODO(sergey): There is no easy way to automatically guess what is
- * the range to be used here for the case when mapping is applied on
- * top of another mapping (i.e. R curve applied on top of common
- * one).
- *
- * Using largest possible range form all curves works correct for the
- * cases like vector curves and should be good enough heuristic for
- * the color curves as well.
- *
- * There might be some better estimations here tho.
- */
- curvemapping_minmax(cumap, rgb_curve, &min_x, &max_x);
+ /* TODO(sergey): There is no easy way to automatically guess what is
+ * the range to be used here for the case when mapping is applied on
+ * top of another mapping (i.e. R curve applied on top of common
+ * one).
+ *
+ * Using largest possible range form all curves works correct for the
+ * cases like vector curves and should be good enough heuristic for
+ * the color curves as well.
+ *
+ * There might be some better estimations here tho.
+ */
+ curvemapping_minmax(cumap, rgb_curve, &min_x, &max_x);
- const float range_x = max_x - min_x;
+ const float range_x = max_x - min_x;
- cumap.update();
+ cumap.update();
- BL::CurveMap mapR = cumap.curves[0];
- BL::CurveMap mapG = cumap.curves[1];
- BL::CurveMap mapB = cumap.curves[2];
+ BL::CurveMap mapR = cumap.curves[0];
+ BL::CurveMap mapG = cumap.curves[1];
+ BL::CurveMap mapB = cumap.curves[2];
- data.resize(size);
+ data.resize(size);
- if(rgb_curve) {
- BL::CurveMap mapI = cumap.curves[3];
- for(int i = 0; i < size; i++) {
- const float t = min_x + (float)i/(float)(size-1) * range_x;
- data[i] = make_float3(mapR.evaluate(mapI.evaluate(t)),
- mapG.evaluate(mapI.evaluate(t)),
- mapB.evaluate(mapI.evaluate(t)));
- }
- }
- else {
- for(int i = 0; i < size; i++) {
- float t = min_x + (float)i/(float)(size-1) * range_x;
- data[i] = make_float3(mapR.evaluate(t),
- mapG.evaluate(t),
- mapB.evaluate(t));
- }
- }
+ if (rgb_curve) {
+ BL::CurveMap mapI = cumap.curves[3];
+ for (int i = 0; i < size; i++) {
+ const float t = min_x + (float)i / (float)(size - 1) * range_x;
+ data[i] = make_float3(mapR.evaluate(mapI.evaluate(t)),
+ mapG.evaluate(mapI.evaluate(t)),
+ mapB.evaluate(mapI.evaluate(t)));
+ }
+ }
+ else {
+ for (int i = 0; i < size; i++) {
+ float t = min_x + (float)i / (float)(size - 1) * range_x;
+ data[i] = make_float3(mapR.evaluate(t), mapG.evaluate(t), mapB.evaluate(t));
+ }
+ }
}
-static inline bool BKE_object_is_modified(BL::Object& self,
- BL::Scene& scene,
- bool preview)
+static inline bool BKE_object_is_modified(BL::Object &self, BL::Scene &scene, bool preview)
{
- return self.is_modified(scene, (preview)? (1<<0): (1<<1))? true: false;
+ return self.is_modified(scene, (preview) ? (1 << 0) : (1 << 1)) ? true : false;
}
-static inline bool BKE_object_is_deform_modified(BL::Object& self,
- BL::Scene& scene,
- bool preview)
+static inline bool BKE_object_is_deform_modified(BL::Object &self, BL::Scene &scene, bool preview)
{
- return self.is_deform_modified(scene, (preview)? (1<<0): (1<<1))? true: false;
+ return self.is_deform_modified(scene, (preview) ? (1 << 0) : (1 << 1)) ? true : false;
}
-static inline int render_resolution_x(BL::RenderSettings& b_render)
+static inline int render_resolution_x(BL::RenderSettings &b_render)
{
- return b_render.resolution_x()*b_render.resolution_percentage()/100;
+ return b_render.resolution_x() * b_render.resolution_percentage() / 100;
}
-static inline int render_resolution_y(BL::RenderSettings& b_render)
+static inline int render_resolution_y(BL::RenderSettings &b_render)
{
- return b_render.resolution_y()*b_render.resolution_percentage()/100;
+ return b_render.resolution_y() * b_render.resolution_percentage() / 100;
}
-static inline string image_user_file_path(BL::ImageUser& iuser,
- BL::Image& ima,
- int cfra)
+static inline string image_user_file_path(BL::ImageUser &iuser, BL::Image &ima, int cfra)
{
- char filepath[1024];
- BKE_image_user_frame_calc(iuser.ptr.data, cfra);
- BKE_image_user_file_path(iuser.ptr.data, ima.ptr.data, filepath);
- return string(filepath);
+ char filepath[1024];
+ BKE_image_user_frame_calc(iuser.ptr.data, cfra);
+ BKE_image_user_file_path(iuser.ptr.data, ima.ptr.data, filepath);
+ return string(filepath);
}
-static inline int image_user_frame_number(BL::ImageUser& iuser, int cfra)
+static inline int image_user_frame_number(BL::ImageUser &iuser, int cfra)
{
- BKE_image_user_frame_calc(iuser.ptr.data, cfra);
- return iuser.frame_current();
+ BKE_image_user_frame_calc(iuser.ptr.data, cfra);
+ return iuser.frame_current();
}
-static inline unsigned char *image_get_pixels_for_frame(BL::Image& image,
- int frame)
+static inline unsigned char *image_get_pixels_for_frame(BL::Image &image, int frame)
{
- return BKE_image_get_pixels_for_frame(image.ptr.data, frame);
+ return BKE_image_get_pixels_for_frame(image.ptr.data, frame);
}
-static inline float *image_get_float_pixels_for_frame(BL::Image& image,
- int frame)
+static inline float *image_get_float_pixels_for_frame(BL::Image &image, int frame)
{
- return BKE_image_get_float_pixels_for_frame(image.ptr.data, frame);
+ return BKE_image_get_float_pixels_for_frame(image.ptr.data, frame);
}
-static inline void render_add_metadata(BL::RenderResult& b_rr, string name, string value)
+static inline void render_add_metadata(BL::RenderResult &b_rr, string name, string value)
{
- b_rr.stamp_data_add_field(name.c_str(), value.c_str());
+ b_rr.stamp_data_add_field(name.c_str(), value.c_str());
}
-
/* Utilities */
-static inline Transform get_transform(const BL::Array<float, 16>& array)
+static inline Transform get_transform(const BL::Array<float, 16> &array)
{
- ProjectionTransform projection;
+ ProjectionTransform projection;
- /* We assume both types to be just 16 floats, and transpose because blender
- * use column major matrix order while we use row major. */
- memcpy((void *)&projection, &array, sizeof(float)*16);
- projection = projection_transpose(projection);
+ /* We assume both types to be just 16 floats, and transpose because blender
+ * use column major matrix order while we use row major. */
+ memcpy((void *)&projection, &array, sizeof(float) * 16);
+ projection = projection_transpose(projection);
- /* Drop last row, matrix is assumed to be affine transform. */
- return projection_to_transform(projection);
+ /* Drop last row, matrix is assumed to be affine transform. */
+ return projection_to_transform(projection);
}
-static inline float2 get_float2(const BL::Array<float, 2>& array)
+static inline float2 get_float2(const BL::Array<float, 2> &array)
{
- return make_float2(array[0], array[1]);
+ return make_float2(array[0], array[1]);
}
-static inline float3 get_float3(const BL::Array<float, 2>& array)
+static inline float3 get_float3(const BL::Array<float, 2> &array)
{
- return make_float3(array[0], array[1], 0.0f);
+ return make_float3(array[0], array[1], 0.0f);
}
-static inline float3 get_float3(const BL::Array<float, 3>& array)
+static inline float3 get_float3(const BL::Array<float, 3> &array)
{
- return make_float3(array[0], array[1], array[2]);
+ return make_float3(array[0], array[1], array[2]);
}
-static inline float3 get_float3(const BL::Array<float, 4>& array)
+static inline float3 get_float3(const BL::Array<float, 4> &array)
{
- return make_float3(array[0], array[1], array[2]);
+ return make_float3(array[0], array[1], array[2]);
}
-static inline float4 get_float4(const BL::Array<float, 4>& array)
+static inline float4 get_float4(const BL::Array<float, 4> &array)
{
- return make_float4(array[0], array[1], array[2], array[3]);
+ return make_float4(array[0], array[1], array[2], array[3]);
}
-static inline int3 get_int3(const BL::Array<int, 3>& array)
+static inline int3 get_int3(const BL::Array<int, 3> &array)
{
- return make_int3(array[0], array[1], array[2]);
+ return make_int3(array[0], array[1], array[2]);
}
-static inline int4 get_int4(const BL::Array<int, 4>& array)
+static inline int4 get_int4(const BL::Array<int, 4> &array)
{
- return make_int4(array[0], array[1], array[2], array[3]);
+ return make_int4(array[0], array[1], array[2], array[3]);
}
-static inline float3 get_float3(PointerRNA& ptr, const char *name)
+static inline float3 get_float3(PointerRNA &ptr, const char *name)
{
- float3 f;
- RNA_float_get_array(&ptr, name, &f.x);
- return f;
+ float3 f;
+ RNA_float_get_array(&ptr, name, &f.x);
+ return f;
}
-static inline void set_float3(PointerRNA& ptr, const char *name, float3 value)
+static inline void set_float3(PointerRNA &ptr, const char *name, float3 value)
{
- RNA_float_set_array(&ptr, name, &value.x);
+ RNA_float_set_array(&ptr, name, &value.x);
}
-static inline float4 get_float4(PointerRNA& ptr, const char *name)
+static inline float4 get_float4(PointerRNA &ptr, const char *name)
{
- float4 f;
- RNA_float_get_array(&ptr, name, &f.x);
- return f;
+ float4 f;
+ RNA_float_get_array(&ptr, name, &f.x);
+ return f;
}
-static inline void set_float4(PointerRNA& ptr, const char *name, float4 value)
+static inline void set_float4(PointerRNA &ptr, const char *name, float4 value)
{
- RNA_float_set_array(&ptr, name, &value.x);
+ RNA_float_set_array(&ptr, name, &value.x);
}
-static inline bool get_boolean(PointerRNA& ptr, const char *name)
+static inline bool get_boolean(PointerRNA &ptr, const char *name)
{
- return RNA_boolean_get(&ptr, name)? true: false;
+ return RNA_boolean_get(&ptr, name) ? true : false;
}
-static inline void set_boolean(PointerRNA& ptr, const char *name, bool value)
+static inline void set_boolean(PointerRNA &ptr, const char *name, bool value)
{
- RNA_boolean_set(&ptr, name, (int)value);
+ RNA_boolean_set(&ptr, name, (int)value);
}
-static inline float get_float(PointerRNA& ptr, const char *name)
+static inline float get_float(PointerRNA &ptr, const char *name)
{
- return RNA_float_get(&ptr, name);
+ return RNA_float_get(&ptr, name);
}
-static inline void set_float(PointerRNA& ptr, const char *name, float value)
+static inline void set_float(PointerRNA &ptr, const char *name, float value)
{
- RNA_float_set(&ptr, name, value);
+ RNA_float_set(&ptr, name, value);
}
-static inline int get_int(PointerRNA& ptr, const char *name)
+static inline int get_int(PointerRNA &ptr, const char *name)
{
- return RNA_int_get(&ptr, name);
+ return RNA_int_get(&ptr, name);
}
-static inline void set_int(PointerRNA& ptr, const char *name, int value)
+static inline void set_int(PointerRNA &ptr, const char *name, int value)
{
- RNA_int_set(&ptr, name, value);
+ RNA_int_set(&ptr, name, value);
}
/* Get a RNA enum value with sanity check: if the RNA value is above num_values
@@ -384,215 +366,214 @@ static inline void set_int(PointerRNA& ptr, const char *name, int value)
* from 0 to num_values-1. Be careful to use it with enums where some values are
* deprecated!
*/
-static inline int get_enum(PointerRNA& ptr,
+static inline int get_enum(PointerRNA &ptr,
const char *name,
int num_values = -1,
int default_value = -1)
{
- int value = RNA_enum_get(&ptr, name);
- if(num_values != -1 && value >= num_values) {
- assert(default_value != -1);
- value = default_value;
- }
- return value;
+ int value = RNA_enum_get(&ptr, name);
+ if (num_values != -1 && value >= num_values) {
+ assert(default_value != -1);
+ value = default_value;
+ }
+ return value;
}
-static inline string get_enum_identifier(PointerRNA& ptr, const char *name)
+static inline string get_enum_identifier(PointerRNA &ptr, const char *name)
{
- PropertyRNA *prop = RNA_struct_find_property(&ptr, name);
- const char *identifier = "";
- int value = RNA_property_enum_get(&ptr, prop);
+ PropertyRNA *prop = RNA_struct_find_property(&ptr, name);
+ const char *identifier = "";
+ int value = RNA_property_enum_get(&ptr, prop);
- RNA_property_enum_identifier(NULL, &ptr, prop, value, &identifier);
+ RNA_property_enum_identifier(NULL, &ptr, prop, value, &identifier);
- return string(identifier);
+ return string(identifier);
}
-static inline void set_enum(PointerRNA& ptr, const char *name, int value)
+static inline void set_enum(PointerRNA &ptr, const char *name, int value)
{
- RNA_enum_set(&ptr, name, value);
+ RNA_enum_set(&ptr, name, value);
}
-static inline void set_enum(PointerRNA& ptr, const char *name, const string &identifier)
+static inline void set_enum(PointerRNA &ptr, const char *name, const string &identifier)
{
- RNA_enum_set_identifier(NULL, &ptr, name, identifier.c_str());
+ RNA_enum_set_identifier(NULL, &ptr, name, identifier.c_str());
}
-static inline string get_string(PointerRNA& ptr, const char *name)
+static inline string get_string(PointerRNA &ptr, const char *name)
{
- char cstrbuf[1024];
- char *cstr = RNA_string_get_alloc(&ptr, name, cstrbuf, sizeof(cstrbuf));
- string str(cstr);
- if(cstr != cstrbuf)
- MEM_freeN(cstr);
+ char cstrbuf[1024];
+ char *cstr = RNA_string_get_alloc(&ptr, name, cstrbuf, sizeof(cstrbuf));
+ string str(cstr);
+ if (cstr != cstrbuf)
+ MEM_freeN(cstr);
- return str;
+ return str;
}
-static inline void set_string(PointerRNA& ptr, const char *name, const string &value)
+static inline void set_string(PointerRNA &ptr, const char *name, const string &value)
{
- RNA_string_set(&ptr, name, value.c_str());
+ RNA_string_set(&ptr, name, value.c_str());
}
/* Relative Paths */
-static inline string blender_absolute_path(BL::BlendData& b_data,
- BL::ID& b_id,
- const string& path)
+static inline string blender_absolute_path(BL::BlendData &b_data, BL::ID &b_id, const string &path)
{
- if(path.size() >= 2 && path[0] == '/' && path[1] == '/') {
- string dirname;
+ if (path.size() >= 2 && path[0] == '/' && path[1] == '/') {
+ string dirname;
- if(b_id.library()) {
- BL::ID b_library_id(b_id.library());
- dirname = blender_absolute_path(b_data,
- b_library_id,
- b_id.library().filepath());
- }
- else
- dirname = b_data.filepath();
+ if (b_id.library()) {
+ BL::ID b_library_id(b_id.library());
+ dirname = blender_absolute_path(b_data, b_library_id, b_id.library().filepath());
+ }
+ else
+ dirname = b_data.filepath();
- return path_join(path_dirname(dirname), path.substr(2));
- }
+ return path_join(path_dirname(dirname), path.substr(2));
+ }
- return path;
+ return path;
}
-static inline string get_text_datablock_content(const PointerRNA& ptr)
+static inline string get_text_datablock_content(const PointerRNA &ptr)
{
- if(ptr.data == NULL) {
- return "";
- }
+ if (ptr.data == NULL) {
+ return "";
+ }
- string content;
- BL::Text::lines_iterator iter;
- for(iter.begin(ptr); iter; ++iter) {
- content += iter->body() + "\n";
- }
+ string content;
+ BL::Text::lines_iterator iter;
+ for (iter.begin(ptr); iter; ++iter) {
+ content += iter->body() + "\n";
+ }
- return content;
+ return content;
}
/* Texture Space */
-static inline void mesh_texture_space(BL::Mesh& b_mesh,
- float3& loc,
- float3& size)
+static inline void mesh_texture_space(BL::Mesh &b_mesh, float3 &loc, float3 &size)
{
- loc = get_float3(b_mesh.texspace_location());
- size = get_float3(b_mesh.texspace_size());
+ loc = get_float3(b_mesh.texspace_location());
+ size = get_float3(b_mesh.texspace_size());
- if(size.x != 0.0f) size.x = 0.5f/size.x;
- if(size.y != 0.0f) size.y = 0.5f/size.y;
- if(size.z != 0.0f) size.z = 0.5f/size.z;
+ if (size.x != 0.0f)
+ size.x = 0.5f / size.x;
+ if (size.y != 0.0f)
+ size.y = 0.5f / size.y;
+ if (size.z != 0.0f)
+ size.z = 0.5f / size.z;
- loc = loc*size - make_float3(0.5f, 0.5f, 0.5f);
+ loc = loc * size - make_float3(0.5f, 0.5f, 0.5f);
}
/* Object motion steps, returns 0 if no motion blur needed. */
-static inline uint object_motion_steps(BL::Object& b_parent, BL::Object& b_ob)
+static inline uint object_motion_steps(BL::Object &b_parent, BL::Object &b_ob)
{
- /* Get motion enabled and steps from object itself. */
- PointerRNA cobject = RNA_pointer_get(&b_ob.ptr, "cycles");
- bool use_motion = get_boolean(cobject, "use_motion_blur");
- if(!use_motion) {
- return 0;
- }
+ /* Get motion enabled and steps from object itself. */
+ PointerRNA cobject = RNA_pointer_get(&b_ob.ptr, "cycles");
+ bool use_motion = get_boolean(cobject, "use_motion_blur");
+ if (!use_motion) {
+ return 0;
+ }
- uint steps = max(1, get_int(cobject, "motion_steps"));
+ uint steps = max(1, get_int(cobject, "motion_steps"));
- /* Also check parent object, so motion blur and steps can be
- * controlled by dupligroup duplicator for linked groups. */
- if(b_parent.ptr.data != b_ob.ptr.data) {
- PointerRNA parent_cobject = RNA_pointer_get(&b_parent.ptr, "cycles");
- use_motion &= get_boolean(parent_cobject, "use_motion_blur");
+ /* Also check parent object, so motion blur and steps can be
+ * controlled by dupligroup duplicator for linked groups. */
+ if (b_parent.ptr.data != b_ob.ptr.data) {
+ PointerRNA parent_cobject = RNA_pointer_get(&b_parent.ptr, "cycles");
+ use_motion &= get_boolean(parent_cobject, "use_motion_blur");
- if(!use_motion) {
- return 0;
- }
+ if (!use_motion) {
+ return 0;
+ }
- steps = max(steps, get_int(parent_cobject, "motion_steps"));
- }
+ steps = max(steps, get_int(parent_cobject, "motion_steps"));
+ }
- /* Use uneven number of steps so we get one keyframe at the current frame,
- * and use 2^(steps - 1) so objects with more/fewer steps still have samples
- * at the same times, to avoid sampling at many different times. */
- return (2 << (steps - 1)) + 1;
+ /* Use uneven number of steps so we get one keyframe at the current frame,
+ * and use 2^(steps - 1) so objects with more/fewer steps still have samples
+ * at the same times, to avoid sampling at many different times. */
+ return (2 << (steps - 1)) + 1;
}
/* object uses deformation motion blur */
-static inline bool object_use_deform_motion(BL::Object& b_parent,
- BL::Object& b_ob)
+static inline bool object_use_deform_motion(BL::Object &b_parent, BL::Object &b_ob)
{
- PointerRNA cobject = RNA_pointer_get(&b_ob.ptr, "cycles");
- bool use_deform_motion = get_boolean(cobject, "use_deform_motion");
- /* If motion blur is enabled for the object we also check
- * whether it's enabled for the parent object as well.
- *
- * This way we can control motion blur from the dupligroup
- * duplicator much easier.
- */
- if(use_deform_motion && b_parent.ptr.data != b_ob.ptr.data) {
- PointerRNA parent_cobject = RNA_pointer_get(&b_parent.ptr, "cycles");
- use_deform_motion &= get_boolean(parent_cobject, "use_deform_motion");
- }
- return use_deform_motion;
+ PointerRNA cobject = RNA_pointer_get(&b_ob.ptr, "cycles");
+ bool use_deform_motion = get_boolean(cobject, "use_deform_motion");
+ /* If motion blur is enabled for the object we also check
+ * whether it's enabled for the parent object as well.
+ *
+ * This way we can control motion blur from the dupligroup
+ * duplicator much easier.
+ */
+ if (use_deform_motion && b_parent.ptr.data != b_ob.ptr.data) {
+ PointerRNA parent_cobject = RNA_pointer_get(&b_parent.ptr, "cycles");
+ use_deform_motion &= get_boolean(parent_cobject, "use_deform_motion");
+ }
+ return use_deform_motion;
}
-static inline BL::SmokeDomainSettings object_smoke_domain_find(BL::Object& b_ob)
+static inline BL::SmokeDomainSettings object_smoke_domain_find(BL::Object &b_ob)
{
- BL::Object::modifiers_iterator b_mod;
+ BL::Object::modifiers_iterator b_mod;
- for(b_ob.modifiers.begin(b_mod); b_mod != b_ob.modifiers.end(); ++b_mod) {
- if(b_mod->is_a(&RNA_SmokeModifier)) {
- BL::SmokeModifier b_smd(*b_mod);
+ for (b_ob.modifiers.begin(b_mod); b_mod != b_ob.modifiers.end(); ++b_mod) {
+ if (b_mod->is_a(&RNA_SmokeModifier)) {
+ BL::SmokeModifier b_smd(*b_mod);
- if(b_smd.smoke_type() == BL::SmokeModifier::smoke_type_DOMAIN)
- return b_smd.domain_settings();
- }
- }
+ if (b_smd.smoke_type() == BL::SmokeModifier::smoke_type_DOMAIN)
+ return b_smd.domain_settings();
+ }
+ }
- return BL::SmokeDomainSettings(PointerRNA_NULL);
+ return BL::SmokeDomainSettings(PointerRNA_NULL);
}
static inline BL::DomainFluidSettings object_fluid_domain_find(BL::Object b_ob)
{
- BL::Object::modifiers_iterator b_mod;
+ BL::Object::modifiers_iterator b_mod;
- for(b_ob.modifiers.begin(b_mod); b_mod != b_ob.modifiers.end(); ++b_mod) {
- if(b_mod->is_a(&RNA_FluidSimulationModifier)) {
- BL::FluidSimulationModifier b_fmd(*b_mod);
- BL::FluidSettings fss = b_fmd.settings();
+ for (b_ob.modifiers.begin(b_mod); b_mod != b_ob.modifiers.end(); ++b_mod) {
+ if (b_mod->is_a(&RNA_FluidSimulationModifier)) {
+ BL::FluidSimulationModifier b_fmd(*b_mod);
+ BL::FluidSettings fss = b_fmd.settings();
- if(fss.type() == BL::FluidSettings::type_DOMAIN)
- return (BL::DomainFluidSettings)b_fmd.settings();
- }
- }
+ if (fss.type() == BL::FluidSettings::type_DOMAIN)
+ return (BL::DomainFluidSettings)b_fmd.settings();
+ }
+ }
- return BL::DomainFluidSettings(PointerRNA_NULL);
+ return BL::DomainFluidSettings(PointerRNA_NULL);
}
-static inline Mesh::SubdivisionType object_subdivision_type(BL::Object& b_ob, bool preview, bool experimental)
+static inline Mesh::SubdivisionType object_subdivision_type(BL::Object &b_ob,
+ bool preview,
+ bool experimental)
{
- PointerRNA cobj = RNA_pointer_get(&b_ob.ptr, "cycles");
+ PointerRNA cobj = RNA_pointer_get(&b_ob.ptr, "cycles");
- if(cobj.data && b_ob.modifiers.length() > 0 && experimental) {
- BL::Modifier mod = b_ob.modifiers[b_ob.modifiers.length()-1];
- bool enabled = preview ? mod.show_viewport() : mod.show_render();
+ if (cobj.data && b_ob.modifiers.length() > 0 && experimental) {
+ BL::Modifier mod = b_ob.modifiers[b_ob.modifiers.length() - 1];
+ bool enabled = preview ? mod.show_viewport() : mod.show_render();
- if(enabled && mod.type() == BL::Modifier::type_SUBSURF && RNA_boolean_get(&cobj, "use_adaptive_subdivision")) {
- BL::SubsurfModifier subsurf(mod);
+ if (enabled && mod.type() == BL::Modifier::type_SUBSURF &&
+ RNA_boolean_get(&cobj, "use_adaptive_subdivision")) {
+ BL::SubsurfModifier subsurf(mod);
- if(subsurf.subdivision_type() == BL::SubsurfModifier::subdivision_type_CATMULL_CLARK) {
- return Mesh::SUBDIVISION_CATMULL_CLARK;
- }
- else {
- return Mesh::SUBDIVISION_LINEAR;
- }
- }
- }
+ if (subsurf.subdivision_type() == BL::SubsurfModifier::subdivision_type_CATMULL_CLARK) {
+ return Mesh::SUBDIVISION_CATMULL_CLARK;
+ }
+ else {
+ return Mesh::SUBDIVISION_LINEAR;
+ }
+ }
+ }
- return Mesh::SUBDIVISION_NONE;
+ return Mesh::SUBDIVISION_NONE;
}
/* ID Map
@@ -600,144 +581,143 @@ static inline Mesh::SubdivisionType object_subdivision_type(BL::Object& b_ob, bo
* Utility class to keep in sync with blender data.
* Used for objects, meshes, lights and shaders. */
-template<typename K, typename T>
-class id_map {
-public:
- id_map(vector<T*> *scene_data_)
- {
- scene_data = scene_data_;
- }
-
- T *find(const BL::ID& id)
- {
- return find(id.ptr.id.data);
- }
-
- T *find(const K& key)
- {
- if(b_map.find(key) != b_map.end()) {
- T *data = b_map[key];
- return data;
- }
-
- return NULL;
- }
-
- void set_recalc(const BL::ID& id)
- {
- b_recalc.insert(id.ptr.data);
- }
-
- void set_recalc(void *id_ptr)
- {
- b_recalc.insert(id_ptr);
- }
-
- bool has_recalc()
- {
- return !(b_recalc.empty());
- }
-
- void pre_sync()
- {
- used_set.clear();
- }
-
- bool sync(T **r_data, const BL::ID& id)
- {
- return sync(r_data, id, id, id.ptr.id.data);
- }
-
- bool sync(T **r_data, const BL::ID& id, const BL::ID& parent, const K& key)
- {
- T *data = find(key);
- bool recalc;
-
- if(!data) {
- /* add data if it didn't exist yet */
- data = new T();
- scene_data->push_back(data);
- b_map[key] = data;
- recalc = true;
- }
- else {
- recalc = (b_recalc.find(id.ptr.data) != b_recalc.end());
- if(parent.ptr.data)
- recalc = recalc || (b_recalc.find(parent.ptr.data) != b_recalc.end());
- }
-
- used(data);
-
- *r_data = data;
- return recalc;
- }
-
- bool is_used(const K& key)
- {
- T *data = find(key);
- return (data) ? used_set.find(data) != used_set.end() : false;
- }
-
- void used(T *data)
- {
- /* tag data as still in use */
- used_set.insert(data);
- }
-
- void set_default(T *data)
- {
- b_map[NULL] = data;
- }
-
- bool post_sync(bool do_delete = true)
- {
- /* remove unused data */
- vector<T*> new_scene_data;
- typename vector<T*>::iterator it;
- bool deleted = false;
-
- for(it = scene_data->begin(); it != scene_data->end(); it++) {
- T *data = *it;
-
- if(do_delete && used_set.find(data) == used_set.end()) {
- delete data;
- deleted = true;
- }
- else
- new_scene_data.push_back(data);
- }
-
- *scene_data = new_scene_data;
-
- /* update mapping */
- map<K, T*> new_map;
- typedef pair<const K, T*> TMapPair;
- typename map<K, T*>::iterator jt;
-
- for(jt = b_map.begin(); jt != b_map.end(); jt++) {
- TMapPair& pair = *jt;
-
- if(used_set.find(pair.second) != used_set.end())
- new_map[pair.first] = pair.second;
- }
-
- used_set.clear();
- b_recalc.clear();
- b_map = new_map;
-
- return deleted;
- }
-
- const map<K, T*>& key_to_scene_data()
- {
- return b_map;
- }
-
-protected:
- vector<T*> *scene_data;
- map<K, T*> b_map;
- set<T*> used_set;
- set<void*> b_recalc;
+template<typename K, typename T> class id_map {
+ public:
+ id_map(vector<T *> *scene_data_)
+ {
+ scene_data = scene_data_;
+ }
+
+ T *find(const BL::ID &id)
+ {
+ return find(id.ptr.id.data);
+ }
+
+ T *find(const K &key)
+ {
+ if (b_map.find(key) != b_map.end()) {
+ T *data = b_map[key];
+ return data;
+ }
+
+ return NULL;
+ }
+
+ void set_recalc(const BL::ID &id)
+ {
+ b_recalc.insert(id.ptr.data);
+ }
+
+ void set_recalc(void *id_ptr)
+ {
+ b_recalc.insert(id_ptr);
+ }
+
+ bool has_recalc()
+ {
+ return !(b_recalc.empty());
+ }
+
+ void pre_sync()
+ {
+ used_set.clear();
+ }
+
+ bool sync(T **r_data, const BL::ID &id)
+ {
+ return sync(r_data, id, id, id.ptr.id.data);
+ }
+
+ bool sync(T **r_data, const BL::ID &id, const BL::ID &parent, const K &key)
+ {
+ T *data = find(key);
+ bool recalc;
+
+ if (!data) {
+ /* add data if it didn't exist yet */
+ data = new T();
+ scene_data->push_back(data);
+ b_map[key] = data;
+ recalc = true;
+ }
+ else {
+ recalc = (b_recalc.find(id.ptr.data) != b_recalc.end());
+ if (parent.ptr.data)
+ recalc = recalc || (b_recalc.find(parent.ptr.data) != b_recalc.end());
+ }
+
+ used(data);
+
+ *r_data = data;
+ return recalc;
+ }
+
+ bool is_used(const K &key)
+ {
+ T *data = find(key);
+ return (data) ? used_set.find(data) != used_set.end() : false;
+ }
+
+ void used(T *data)
+ {
+ /* tag data as still in use */
+ used_set.insert(data);
+ }
+
+ void set_default(T *data)
+ {
+ b_map[NULL] = data;
+ }
+
+ bool post_sync(bool do_delete = true)
+ {
+ /* remove unused data */
+ vector<T *> new_scene_data;
+ typename vector<T *>::iterator it;
+ bool deleted = false;
+
+ for (it = scene_data->begin(); it != scene_data->end(); it++) {
+ T *data = *it;
+
+ if (do_delete && used_set.find(data) == used_set.end()) {
+ delete data;
+ deleted = true;
+ }
+ else
+ new_scene_data.push_back(data);
+ }
+
+ *scene_data = new_scene_data;
+
+ /* update mapping */
+ map<K, T *> new_map;
+ typedef pair<const K, T *> TMapPair;
+ typename map<K, T *>::iterator jt;
+
+ for (jt = b_map.begin(); jt != b_map.end(); jt++) {
+ TMapPair &pair = *jt;
+
+ if (used_set.find(pair.second) != used_set.end())
+ new_map[pair.first] = pair.second;
+ }
+
+ used_set.clear();
+ b_recalc.clear();
+ b_map = new_map;
+
+ return deleted;
+ }
+
+ const map<K, T *> &key_to_scene_data()
+ {
+ return b_map;
+ }
+
+ protected:
+ vector<T *> *scene_data;
+ map<K, T *> b_map;
+ set<T *> used_set;
+ set<void *> b_recalc;
};
/* Object Key */
@@ -745,91 +725,95 @@ protected:
enum { OBJECT_PERSISTENT_ID_SIZE = 16 };
struct ObjectKey {
- void *parent;
- int id[OBJECT_PERSISTENT_ID_SIZE];
- void *ob;
-
- ObjectKey(void *parent_, int id_[OBJECT_PERSISTENT_ID_SIZE], void *ob_)
- : parent(parent_), ob(ob_)
- {
- if(id_)
- memcpy(id, id_, sizeof(id));
- else
- memset(id, 0, sizeof(id));
- }
-
- bool operator<(const ObjectKey& k) const
- {
- if(ob < k.ob) {
- return true;
- }
- else if(ob == k.ob) {
- if(parent < k.parent)
- return true;
- else if(parent == k.parent)
- return memcmp(id, k.id, sizeof(id)) < 0;
- }
-
- return false;
- }
+ void *parent;
+ int id[OBJECT_PERSISTENT_ID_SIZE];
+ void *ob;
+
+ ObjectKey(void *parent_, int id_[OBJECT_PERSISTENT_ID_SIZE], void *ob_)
+ : parent(parent_), ob(ob_)
+ {
+ if (id_)
+ memcpy(id, id_, sizeof(id));
+ else
+ memset(id, 0, sizeof(id));
+ }
+
+ bool operator<(const ObjectKey &k) const
+ {
+ if (ob < k.ob) {
+ return true;
+ }
+ else if (ob == k.ob) {
+ if (parent < k.parent)
+ return true;
+ else if (parent == k.parent)
+ return memcmp(id, k.id, sizeof(id)) < 0;
+ }
+
+ return false;
+ }
};
/* Particle System Key */
struct ParticleSystemKey {
- void *ob;
- int id[OBJECT_PERSISTENT_ID_SIZE];
-
- ParticleSystemKey(void *ob_, int id_[OBJECT_PERSISTENT_ID_SIZE])
- : ob(ob_)
- {
- if(id_)
- memcpy(id, id_, sizeof(id));
- else
- memset(id, 0, sizeof(id));
- }
-
- bool operator<(const ParticleSystemKey& k) const
- {
- /* first id is particle index, we don't compare that */
- if(ob < k.ob)
- return true;
- else if(ob == k.ob)
- return memcmp(id+1, k.id+1, sizeof(int)*(OBJECT_PERSISTENT_ID_SIZE-1)) < 0;
-
- return false;
- }
+ void *ob;
+ int id[OBJECT_PERSISTENT_ID_SIZE];
+
+ ParticleSystemKey(void *ob_, int id_[OBJECT_PERSISTENT_ID_SIZE]) : ob(ob_)
+ {
+ if (id_)
+ memcpy(id, id_, sizeof(id));
+ else
+ memset(id, 0, sizeof(id));
+ }
+
+ bool operator<(const ParticleSystemKey &k) const
+ {
+ /* first id is particle index, we don't compare that */
+ if (ob < k.ob)
+ return true;
+ else if (ob == k.ob)
+ return memcmp(id + 1, k.id + 1, sizeof(int) * (OBJECT_PERSISTENT_ID_SIZE - 1)) < 0;
+
+ return false;
+ }
};
class EdgeMap {
-public:
- EdgeMap() {
- }
-
- void clear() {
- edges_.clear();
- }
-
- void insert(int v0, int v1) {
- get_sorted_verts(v0, v1);
- edges_.insert(std::pair<int, int>(v0, v1));
- }
-
- bool exists(int v0, int v1) {
- get_sorted_verts(v0, v1);
- return edges_.find(std::pair<int, int>(v0, v1)) != edges_.end();
- }
-
-protected:
- void get_sorted_verts(int& v0, int& v1) {
- if(v0 > v1) {
- swap(v0, v1);
- }
- }
-
- set< std::pair<int, int> > edges_;
+ public:
+ EdgeMap()
+ {
+ }
+
+ void clear()
+ {
+ edges_.clear();
+ }
+
+ void insert(int v0, int v1)
+ {
+ get_sorted_verts(v0, v1);
+ edges_.insert(std::pair<int, int>(v0, v1));
+ }
+
+ bool exists(int v0, int v1)
+ {
+ get_sorted_verts(v0, v1);
+ return edges_.find(std::pair<int, int>(v0, v1)) != edges_.end();
+ }
+
+ protected:
+ void get_sorted_verts(int &v0, int &v1)
+ {
+ if (v0 > v1) {
+ swap(v0, v1);
+ }
+ }
+
+ set<std::pair<int, int>> edges_;
};
CCL_NAMESPACE_END
-#endif /* __BLENDER_UTIL_H__ */
+#endif /* __BLENDER_UTIL_H__ */
diff --git a/intern/cycles/bvh/CMakeLists.txt b/intern/cycles/bvh/CMakeLists.txt
index ea31838d816..36bbd937e1a 100644
--- a/intern/cycles/bvh/CMakeLists.txt
+++ b/intern/cycles/bvh/CMakeLists.txt
@@ -1,42 +1,42 @@
set(INC
- ..
+ ..
)
set(INC_SYS
)
set(SRC
- bvh.cpp
- bvh2.cpp
- bvh4.cpp
- bvh8.cpp
- bvh_binning.cpp
- bvh_build.cpp
- bvh_embree.cpp
- bvh_node.cpp
- bvh_sort.cpp
- bvh_split.cpp
- bvh_unaligned.cpp
+ bvh.cpp
+ bvh2.cpp
+ bvh4.cpp
+ bvh8.cpp
+ bvh_binning.cpp
+ bvh_build.cpp
+ bvh_embree.cpp
+ bvh_node.cpp
+ bvh_sort.cpp
+ bvh_split.cpp
+ bvh_unaligned.cpp
)
set(SRC_HEADERS
- bvh.h
- bvh2.h
- bvh4.h
- bvh8.h
- bvh_binning.h
- bvh_build.h
- bvh_embree.h
- bvh_node.h
- bvh_params.h
- bvh_sort.h
- bvh_split.h
- bvh_unaligned.h
+ bvh.h
+ bvh2.h
+ bvh4.h
+ bvh8.h
+ bvh_binning.h
+ bvh_build.h
+ bvh_embree.h
+ bvh_node.h
+ bvh_params.h
+ bvh_sort.h
+ bvh_split.h
+ bvh_unaligned.h
)
set(LIB
- cycles_render
+ cycles_render
)
include_directories(${INC})
diff --git a/intern/cycles/bvh/bvh.cpp b/intern/cycles/bvh/bvh.cpp
index af012bbf3ac..53c66777928 100644
--- a/intern/cycles/bvh/bvh.cpp
+++ b/intern/cycles/bvh/bvh.cpp
@@ -27,7 +27,7 @@
#include "bvh/bvh_node.h"
#ifdef WITH_EMBREE
-#include "bvh/bvh_embree.h"
+# include "bvh/bvh_embree.h"
#endif
#include "util/util_foreach.h"
@@ -40,533 +40,529 @@ CCL_NAMESPACE_BEGIN
const char *bvh_layout_name(BVHLayout layout)
{
- switch(layout) {
- case BVH_LAYOUT_BVH2: return "BVH2";
- case BVH_LAYOUT_BVH4: return "BVH4";
- case BVH_LAYOUT_BVH8: return "BVH8";
- case BVH_LAYOUT_NONE: return "NONE";
- case BVH_LAYOUT_EMBREE: return "EMBREE";
- case BVH_LAYOUT_ALL: return "ALL";
- }
- LOG(DFATAL) << "Unsupported BVH layout was passed.";
- return "";
+ switch (layout) {
+ case BVH_LAYOUT_BVH2:
+ return "BVH2";
+ case BVH_LAYOUT_BVH4:
+ return "BVH4";
+ case BVH_LAYOUT_BVH8:
+ return "BVH8";
+ case BVH_LAYOUT_NONE:
+ return "NONE";
+ case BVH_LAYOUT_EMBREE:
+ return "EMBREE";
+ case BVH_LAYOUT_ALL:
+ return "ALL";
+ }
+ LOG(DFATAL) << "Unsupported BVH layout was passed.";
+ return "";
}
-BVHLayout BVHParams::best_bvh_layout(BVHLayout requested_layout,
- BVHLayoutMask supported_layouts)
+BVHLayout BVHParams::best_bvh_layout(BVHLayout requested_layout, BVHLayoutMask supported_layouts)
{
- const BVHLayoutMask requested_layout_mask = (BVHLayoutMask)requested_layout;
- /* Check whether requested layout is supported, if so -- no need to do
- * any extra computation.
- */
- if(supported_layouts & requested_layout_mask) {
- return requested_layout;
- }
- /* Some bit magic to get widest supported BVH layout. */
- /* This is a mask of supported BVH layouts which are narrower than the
- * requested one.
- */
- const BVHLayoutMask allowed_layouts_mask =
- (supported_layouts & (requested_layout_mask - 1));
- /* We get widest from allowed ones and convert mask to actual layout. */
- const BVHLayoutMask widest_allowed_layout_mask = __bsr(allowed_layouts_mask);
- return (BVHLayout)(1 << widest_allowed_layout_mask);
+ const BVHLayoutMask requested_layout_mask = (BVHLayoutMask)requested_layout;
+ /* Check whether requested layout is supported, if so -- no need to do
+ * any extra computation.
+ */
+ if (supported_layouts & requested_layout_mask) {
+ return requested_layout;
+ }
+ /* Some bit magic to get widest supported BVH layout. */
+ /* This is a mask of supported BVH layouts which are narrower than the
+ * requested one.
+ */
+ const BVHLayoutMask allowed_layouts_mask = (supported_layouts & (requested_layout_mask - 1));
+ /* We get widest from allowed ones and convert mask to actual layout. */
+ const BVHLayoutMask widest_allowed_layout_mask = __bsr(allowed_layouts_mask);
+ return (BVHLayout)(1 << widest_allowed_layout_mask);
}
/* Pack Utility */
-BVHStackEntry::BVHStackEntry(const BVHNode *n, int i)
- : node(n), idx(i)
+BVHStackEntry::BVHStackEntry(const BVHNode *n, int i) : node(n), idx(i)
{
}
int BVHStackEntry::encodeIdx() const
{
- return (node->is_leaf())? ~idx: idx;
+ return (node->is_leaf()) ? ~idx : idx;
}
/* BVH */
-BVH::BVH(const BVHParams& params_, const vector<Object*>& objects_)
-: params(params_), objects(objects_)
+BVH::BVH(const BVHParams &params_, const vector<Object *> &objects_)
+ : params(params_), objects(objects_)
{
}
-BVH *BVH::create(const BVHParams& params, const vector<Object*>& objects)
+BVH *BVH::create(const BVHParams &params, const vector<Object *> &objects)
{
- switch(params.bvh_layout) {
- case BVH_LAYOUT_BVH2:
- return new BVH2(params, objects);
- case BVH_LAYOUT_BVH4:
- return new BVH4(params, objects);
- case BVH_LAYOUT_BVH8:
- return new BVH8(params, objects);
- case BVH_LAYOUT_EMBREE:
+ switch (params.bvh_layout) {
+ case BVH_LAYOUT_BVH2:
+ return new BVH2(params, objects);
+ case BVH_LAYOUT_BVH4:
+ return new BVH4(params, objects);
+ case BVH_LAYOUT_BVH8:
+ return new BVH8(params, objects);
+ case BVH_LAYOUT_EMBREE:
#ifdef WITH_EMBREE
- return new BVHEmbree(params, objects);
+ return new BVHEmbree(params, objects);
#endif
- case BVH_LAYOUT_NONE:
- case BVH_LAYOUT_ALL:
- break;
- }
- LOG(DFATAL) << "Requested unsupported BVH layout.";
- return NULL;
+ case BVH_LAYOUT_NONE:
+ case BVH_LAYOUT_ALL:
+ break;
+ }
+ LOG(DFATAL) << "Requested unsupported BVH layout.";
+ return NULL;
}
/* Building */
-void BVH::build(Progress& progress, Stats*)
+void BVH::build(Progress &progress, Stats *)
{
- progress.set_substatus("Building BVH");
-
- /* build nodes */
- BVHBuild bvh_build(objects,
- pack.prim_type,
- pack.prim_index,
- pack.prim_object,
- pack.prim_time,
- params,
- progress);
- BVHNode *bvh2_root = bvh_build.run();
-
- if(progress.get_cancel()) {
- if(bvh2_root != NULL) {
- bvh2_root->deleteSubtree();
- }
- return;
- }
-
- /* BVH builder returns tree in a binary mode (with two children per inner
- * node. Need to adopt that for a wider BVH implementations. */
- BVHNode *root = widen_children_nodes(bvh2_root);
- if(root != bvh2_root) {
- bvh2_root->deleteSubtree();
- }
-
- if(progress.get_cancel()) {
- if(root != NULL) {
- root->deleteSubtree();
- }
- return;
- }
-
- /* pack triangles */
- progress.set_substatus("Packing BVH triangles and strands");
- pack_primitives();
-
- if(progress.get_cancel()) {
- root->deleteSubtree();
- return;
- }
-
- /* pack nodes */
- progress.set_substatus("Packing BVH nodes");
- pack_nodes(root);
-
- /* free build nodes */
- root->deleteSubtree();
+ progress.set_substatus("Building BVH");
+
+ /* build nodes */
+ BVHBuild bvh_build(objects,
+ pack.prim_type,
+ pack.prim_index,
+ pack.prim_object,
+ pack.prim_time,
+ params,
+ progress);
+ BVHNode *bvh2_root = bvh_build.run();
+
+ if (progress.get_cancel()) {
+ if (bvh2_root != NULL) {
+ bvh2_root->deleteSubtree();
+ }
+ return;
+ }
+
+ /* BVH builder returns tree in a binary mode (with two children per inner
+ * node. Need to adopt that for a wider BVH implementations. */
+ BVHNode *root = widen_children_nodes(bvh2_root);
+ if (root != bvh2_root) {
+ bvh2_root->deleteSubtree();
+ }
+
+ if (progress.get_cancel()) {
+ if (root != NULL) {
+ root->deleteSubtree();
+ }
+ return;
+ }
+
+ /* pack triangles */
+ progress.set_substatus("Packing BVH triangles and strands");
+ pack_primitives();
+
+ if (progress.get_cancel()) {
+ root->deleteSubtree();
+ return;
+ }
+
+ /* pack nodes */
+ progress.set_substatus("Packing BVH nodes");
+ pack_nodes(root);
+
+ /* free build nodes */
+ root->deleteSubtree();
}
/* Refitting */
-void BVH::refit(Progress& progress)
+void BVH::refit(Progress &progress)
{
- progress.set_substatus("Packing BVH primitives");
- pack_primitives();
+ progress.set_substatus("Packing BVH primitives");
+ pack_primitives();
- if(progress.get_cancel()) return;
+ if (progress.get_cancel())
+ return;
- progress.set_substatus("Refitting BVH nodes");
- refit_nodes();
+ progress.set_substatus("Refitting BVH nodes");
+ refit_nodes();
}
-void BVH::refit_primitives(int start, int end, BoundBox& bbox, uint& visibility)
+void BVH::refit_primitives(int start, int end, BoundBox &bbox, uint &visibility)
{
- /* Refit range of primitives. */
- for(int prim = start; prim < end; prim++) {
- int pidx = pack.prim_index[prim];
- int tob = pack.prim_object[prim];
- Object *ob = objects[tob];
-
- if(pidx == -1) {
- /* Object instance. */
- bbox.grow(ob->bounds);
- }
- else {
- /* Primitives. */
- const Mesh *mesh = ob->mesh;
-
- if(pack.prim_type[prim] & PRIMITIVE_ALL_CURVE) {
- /* Curves. */
- int str_offset = (params.top_level)? mesh->curve_offset: 0;
- Mesh::Curve curve = mesh->get_curve(pidx - str_offset);
- int k = PRIMITIVE_UNPACK_SEGMENT(pack.prim_type[prim]);
-
- curve.bounds_grow(k, &mesh->curve_keys[0], &mesh->curve_radius[0], bbox);
-
- visibility |= PATH_RAY_CURVE;
-
- /* Motion curves. */
- if(mesh->use_motion_blur) {
- Attribute *attr = mesh->curve_attributes.find(ATTR_STD_MOTION_VERTEX_POSITION);
-
- if(attr) {
- size_t mesh_size = mesh->curve_keys.size();
- size_t steps = mesh->motion_steps - 1;
- float3 *key_steps = attr->data_float3();
-
- for(size_t i = 0; i < steps; i++)
- curve.bounds_grow(k, key_steps + i*mesh_size, &mesh->curve_radius[0], bbox);
- }
- }
- }
- else {
- /* Triangles. */
- int tri_offset = (params.top_level)? mesh->tri_offset: 0;
- Mesh::Triangle triangle = mesh->get_triangle(pidx - tri_offset);
- const float3 *vpos = &mesh->verts[0];
-
- triangle.bounds_grow(vpos, bbox);
-
- /* Motion triangles. */
- if(mesh->use_motion_blur) {
- Attribute *attr = mesh->attributes.find(ATTR_STD_MOTION_VERTEX_POSITION);
-
- if(attr) {
- size_t mesh_size = mesh->verts.size();
- size_t steps = mesh->motion_steps - 1;
- float3 *vert_steps = attr->data_float3();
-
- for(size_t i = 0; i < steps; i++)
- triangle.bounds_grow(vert_steps + i*mesh_size, bbox);
- }
- }
- }
- }
- visibility |= ob->visibility_for_tracing();
-
- }
+ /* Refit range of primitives. */
+ for (int prim = start; prim < end; prim++) {
+ int pidx = pack.prim_index[prim];
+ int tob = pack.prim_object[prim];
+ Object *ob = objects[tob];
+
+ if (pidx == -1) {
+ /* Object instance. */
+ bbox.grow(ob->bounds);
+ }
+ else {
+ /* Primitives. */
+ const Mesh *mesh = ob->mesh;
+
+ if (pack.prim_type[prim] & PRIMITIVE_ALL_CURVE) {
+ /* Curves. */
+ int str_offset = (params.top_level) ? mesh->curve_offset : 0;
+ Mesh::Curve curve = mesh->get_curve(pidx - str_offset);
+ int k = PRIMITIVE_UNPACK_SEGMENT(pack.prim_type[prim]);
+
+ curve.bounds_grow(k, &mesh->curve_keys[0], &mesh->curve_radius[0], bbox);
+
+ visibility |= PATH_RAY_CURVE;
+
+ /* Motion curves. */
+ if (mesh->use_motion_blur) {
+ Attribute *attr = mesh->curve_attributes.find(ATTR_STD_MOTION_VERTEX_POSITION);
+
+ if (attr) {
+ size_t mesh_size = mesh->curve_keys.size();
+ size_t steps = mesh->motion_steps - 1;
+ float3 *key_steps = attr->data_float3();
+
+ for (size_t i = 0; i < steps; i++)
+ curve.bounds_grow(k, key_steps + i * mesh_size, &mesh->curve_radius[0], bbox);
+ }
+ }
+ }
+ else {
+ /* Triangles. */
+ int tri_offset = (params.top_level) ? mesh->tri_offset : 0;
+ Mesh::Triangle triangle = mesh->get_triangle(pidx - tri_offset);
+ const float3 *vpos = &mesh->verts[0];
+
+ triangle.bounds_grow(vpos, bbox);
+
+ /* Motion triangles. */
+ if (mesh->use_motion_blur) {
+ Attribute *attr = mesh->attributes.find(ATTR_STD_MOTION_VERTEX_POSITION);
+
+ if (attr) {
+ size_t mesh_size = mesh->verts.size();
+ size_t steps = mesh->motion_steps - 1;
+ float3 *vert_steps = attr->data_float3();
+
+ for (size_t i = 0; i < steps; i++)
+ triangle.bounds_grow(vert_steps + i * mesh_size, bbox);
+ }
+ }
+ }
+ }
+ visibility |= ob->visibility_for_tracing();
+ }
}
/* Triangles */
void BVH::pack_triangle(int idx, float4 tri_verts[3])
{
- int tob = pack.prim_object[idx];
- assert(tob >= 0 && tob < objects.size());
- const Mesh *mesh = objects[tob]->mesh;
-
- int tidx = pack.prim_index[idx];
- Mesh::Triangle t = mesh->get_triangle(tidx);
- const float3 *vpos = &mesh->verts[0];
- float3 v0 = vpos[t.v[0]];
- float3 v1 = vpos[t.v[1]];
- float3 v2 = vpos[t.v[2]];
-
- tri_verts[0] = float3_to_float4(v0);
- tri_verts[1] = float3_to_float4(v1);
- tri_verts[2] = float3_to_float4(v2);
+ int tob = pack.prim_object[idx];
+ assert(tob >= 0 && tob < objects.size());
+ const Mesh *mesh = objects[tob]->mesh;
+
+ int tidx = pack.prim_index[idx];
+ Mesh::Triangle t = mesh->get_triangle(tidx);
+ const float3 *vpos = &mesh->verts[0];
+ float3 v0 = vpos[t.v[0]];
+ float3 v1 = vpos[t.v[1]];
+ float3 v2 = vpos[t.v[2]];
+
+ tri_verts[0] = float3_to_float4(v0);
+ tri_verts[1] = float3_to_float4(v1);
+ tri_verts[2] = float3_to_float4(v2);
}
void BVH::pack_primitives()
{
- const size_t tidx_size = pack.prim_index.size();
- size_t num_prim_triangles = 0;
- /* Count number of triangles primitives in BVH. */
- for(unsigned int i = 0; i < tidx_size; i++) {
- if((pack.prim_index[i] != -1)) {
- if((pack.prim_type[i] & PRIMITIVE_ALL_TRIANGLE) != 0) {
- ++num_prim_triangles;
- }
- }
- }
- /* Reserve size for arrays. */
- pack.prim_tri_index.clear();
- pack.prim_tri_index.resize(tidx_size);
- pack.prim_tri_verts.clear();
- pack.prim_tri_verts.resize(num_prim_triangles * 3);
- pack.prim_visibility.clear();
- pack.prim_visibility.resize(tidx_size);
- /* Fill in all the arrays. */
- size_t prim_triangle_index = 0;
- for(unsigned int i = 0; i < tidx_size; i++) {
- if(pack.prim_index[i] != -1) {
- int tob = pack.prim_object[i];
- Object *ob = objects[tob];
- if((pack.prim_type[i] & PRIMITIVE_ALL_TRIANGLE) != 0) {
- pack_triangle(i, (float4*)&pack.prim_tri_verts[3 * prim_triangle_index]);
- pack.prim_tri_index[i] = 3 * prim_triangle_index;
- ++prim_triangle_index;
- }
- else {
- pack.prim_tri_index[i] = -1;
- }
- pack.prim_visibility[i] = ob->visibility_for_tracing();
- if(pack.prim_type[i] & PRIMITIVE_ALL_CURVE) {
- pack.prim_visibility[i] |= PATH_RAY_CURVE;
- }
- }
- else {
- pack.prim_tri_index[i] = -1;
- pack.prim_visibility[i] = 0;
- }
- }
+ const size_t tidx_size = pack.prim_index.size();
+ size_t num_prim_triangles = 0;
+ /* Count number of triangles primitives in BVH. */
+ for (unsigned int i = 0; i < tidx_size; i++) {
+ if ((pack.prim_index[i] != -1)) {
+ if ((pack.prim_type[i] & PRIMITIVE_ALL_TRIANGLE) != 0) {
+ ++num_prim_triangles;
+ }
+ }
+ }
+ /* Reserve size for arrays. */
+ pack.prim_tri_index.clear();
+ pack.prim_tri_index.resize(tidx_size);
+ pack.prim_tri_verts.clear();
+ pack.prim_tri_verts.resize(num_prim_triangles * 3);
+ pack.prim_visibility.clear();
+ pack.prim_visibility.resize(tidx_size);
+ /* Fill in all the arrays. */
+ size_t prim_triangle_index = 0;
+ for (unsigned int i = 0; i < tidx_size; i++) {
+ if (pack.prim_index[i] != -1) {
+ int tob = pack.prim_object[i];
+ Object *ob = objects[tob];
+ if ((pack.prim_type[i] & PRIMITIVE_ALL_TRIANGLE) != 0) {
+ pack_triangle(i, (float4 *)&pack.prim_tri_verts[3 * prim_triangle_index]);
+ pack.prim_tri_index[i] = 3 * prim_triangle_index;
+ ++prim_triangle_index;
+ }
+ else {
+ pack.prim_tri_index[i] = -1;
+ }
+ pack.prim_visibility[i] = ob->visibility_for_tracing();
+ if (pack.prim_type[i] & PRIMITIVE_ALL_CURVE) {
+ pack.prim_visibility[i] |= PATH_RAY_CURVE;
+ }
+ }
+ else {
+ pack.prim_tri_index[i] = -1;
+ pack.prim_visibility[i] = 0;
+ }
+ }
}
/* Pack Instances */
void BVH::pack_instances(size_t nodes_size, size_t leaf_nodes_size)
{
- /* The BVH's for instances are built separately, but for traversal all
- * BVH's are stored in global arrays. This function merges them into the
- * top level BVH, adjusting indexes and offsets where appropriate.
- */
- const bool use_qbvh = (params.bvh_layout == BVH_LAYOUT_BVH4);
- const bool use_obvh = (params.bvh_layout == BVH_LAYOUT_BVH8);
-
- /* Adjust primitive index to point to the triangle in the global array, for
- * meshes with transform applied and already in the top level BVH.
- */
- for(size_t i = 0; i < pack.prim_index.size(); i++)
- if(pack.prim_index[i] != -1) {
- if(pack.prim_type[i] & PRIMITIVE_ALL_CURVE)
- pack.prim_index[i] += objects[pack.prim_object[i]]->mesh->curve_offset;
- else
- pack.prim_index[i] += objects[pack.prim_object[i]]->mesh->tri_offset;
- }
-
- /* track offsets of instanced BVH data in global array */
- size_t prim_offset = pack.prim_index.size();
- size_t nodes_offset = nodes_size;
- size_t nodes_leaf_offset = leaf_nodes_size;
-
- /* clear array that gives the node indexes for instanced objects */
- pack.object_node.clear();
-
- /* reserve */
- size_t prim_index_size = pack.prim_index.size();
- size_t prim_tri_verts_size = pack.prim_tri_verts.size();
-
- size_t pack_prim_index_offset = prim_index_size;
- size_t pack_prim_tri_verts_offset = prim_tri_verts_size;
- size_t pack_nodes_offset = nodes_size;
- size_t pack_leaf_nodes_offset = leaf_nodes_size;
- size_t object_offset = 0;
-
- map<Mesh*, int> mesh_map;
-
- foreach(Object *ob, objects) {
- Mesh *mesh = ob->mesh;
- BVH *bvh = mesh->bvh;
-
- if(mesh->need_build_bvh()) {
- if(mesh_map.find(mesh) == mesh_map.end()) {
- prim_index_size += bvh->pack.prim_index.size();
- prim_tri_verts_size += bvh->pack.prim_tri_verts.size();
- nodes_size += bvh->pack.nodes.size();
- leaf_nodes_size += bvh->pack.leaf_nodes.size();
-
- mesh_map[mesh] = 1;
- }
- }
- }
-
- mesh_map.clear();
-
- pack.prim_index.resize(prim_index_size);
- pack.prim_type.resize(prim_index_size);
- pack.prim_object.resize(prim_index_size);
- pack.prim_visibility.resize(prim_index_size);
- pack.prim_tri_verts.resize(prim_tri_verts_size);
- pack.prim_tri_index.resize(prim_index_size);
- pack.nodes.resize(nodes_size);
- pack.leaf_nodes.resize(leaf_nodes_size);
- pack.object_node.resize(objects.size());
-
- if(params.num_motion_curve_steps > 0 || params.num_motion_triangle_steps > 0) {
- pack.prim_time.resize(prim_index_size);
- }
-
- int *pack_prim_index = (pack.prim_index.size())? &pack.prim_index[0]: NULL;
- int *pack_prim_type = (pack.prim_type.size())? &pack.prim_type[0]: NULL;
- int *pack_prim_object = (pack.prim_object.size())? &pack.prim_object[0]: NULL;
- uint *pack_prim_visibility = (pack.prim_visibility.size())? &pack.prim_visibility[0]: NULL;
- float4 *pack_prim_tri_verts = (pack.prim_tri_verts.size())? &pack.prim_tri_verts[0]: NULL;
- uint *pack_prim_tri_index = (pack.prim_tri_index.size())? &pack.prim_tri_index[0]: NULL;
- int4 *pack_nodes = (pack.nodes.size())? &pack.nodes[0]: NULL;
- int4 *pack_leaf_nodes = (pack.leaf_nodes.size())? &pack.leaf_nodes[0]: NULL;
- float2 *pack_prim_time = (pack.prim_time.size())? &pack.prim_time[0]: NULL;
-
- /* merge */
- foreach(Object *ob, objects) {
- Mesh *mesh = ob->mesh;
-
- /* We assume that if mesh doesn't need own BVH it was already included
- * into a top-level BVH and no packing here is needed.
- */
- if(!mesh->need_build_bvh()) {
- pack.object_node[object_offset++] = 0;
- continue;
- }
-
- /* if mesh already added once, don't add it again, but used set
- * node offset for this object */
- map<Mesh*, int>::iterator it = mesh_map.find(mesh);
-
- if(mesh_map.find(mesh) != mesh_map.end()) {
- int noffset = it->second;
- pack.object_node[object_offset++] = noffset;
- continue;
- }
-
- BVH *bvh = mesh->bvh;
-
- int noffset = nodes_offset;
- int noffset_leaf = nodes_leaf_offset;
- int mesh_tri_offset = mesh->tri_offset;
- int mesh_curve_offset = mesh->curve_offset;
-
- /* fill in node indexes for instances */
- if(bvh->pack.root_index == -1)
- pack.object_node[object_offset++] = -noffset_leaf-1;
- else
- pack.object_node[object_offset++] = noffset;
-
- mesh_map[mesh] = pack.object_node[object_offset-1];
-
- /* merge primitive, object and triangle indexes */
- if(bvh->pack.prim_index.size()) {
- size_t bvh_prim_index_size = bvh->pack.prim_index.size();
- int *bvh_prim_index = &bvh->pack.prim_index[0];
- int *bvh_prim_type = &bvh->pack.prim_type[0];
- uint *bvh_prim_visibility = &bvh->pack.prim_visibility[0];
- uint *bvh_prim_tri_index = &bvh->pack.prim_tri_index[0];
- float2 *bvh_prim_time = bvh->pack.prim_time.size()? &bvh->pack.prim_time[0]: NULL;
-
- for(size_t i = 0; i < bvh_prim_index_size; i++) {
- if(bvh->pack.prim_type[i] & PRIMITIVE_ALL_CURVE) {
- pack_prim_index[pack_prim_index_offset] = bvh_prim_index[i] + mesh_curve_offset;
- pack_prim_tri_index[pack_prim_index_offset] = -1;
- }
- else {
- pack_prim_index[pack_prim_index_offset] = bvh_prim_index[i] + mesh_tri_offset;
- pack_prim_tri_index[pack_prim_index_offset] =
- bvh_prim_tri_index[i] + pack_prim_tri_verts_offset;
- }
-
- pack_prim_type[pack_prim_index_offset] = bvh_prim_type[i];
- pack_prim_visibility[pack_prim_index_offset] = bvh_prim_visibility[i];
- pack_prim_object[pack_prim_index_offset] = 0; // unused for instances
- if(bvh_prim_time != NULL) {
- pack_prim_time[pack_prim_index_offset] = bvh_prim_time[i];
- }
- pack_prim_index_offset++;
- }
- }
-
- /* Merge triangle vertices data. */
- if(bvh->pack.prim_tri_verts.size()) {
- const size_t prim_tri_size = bvh->pack.prim_tri_verts.size();
- memcpy(pack_prim_tri_verts + pack_prim_tri_verts_offset,
- &bvh->pack.prim_tri_verts[0],
- prim_tri_size*sizeof(float4));
- pack_prim_tri_verts_offset += prim_tri_size;
- }
-
- /* merge nodes */
- if(bvh->pack.leaf_nodes.size()) {
- int4 *leaf_nodes_offset = &bvh->pack.leaf_nodes[0];
- size_t leaf_nodes_offset_size = bvh->pack.leaf_nodes.size();
- for(size_t i = 0, j = 0;
- i < leaf_nodes_offset_size;
- i += BVH_NODE_LEAF_SIZE, j++)
- {
- int4 data = leaf_nodes_offset[i];
- data.x += prim_offset;
- data.y += prim_offset;
- pack_leaf_nodes[pack_leaf_nodes_offset] = data;
- for(int j = 1; j < BVH_NODE_LEAF_SIZE; ++j) {
- pack_leaf_nodes[pack_leaf_nodes_offset + j] = leaf_nodes_offset[i + j];
- }
- pack_leaf_nodes_offset += BVH_NODE_LEAF_SIZE;
- }
- }
-
- if(bvh->pack.nodes.size()) {
- int4 *bvh_nodes = &bvh->pack.nodes[0];
- size_t bvh_nodes_size = bvh->pack.nodes.size();
-
- for(size_t i = 0, j = 0; i < bvh_nodes_size; j++) {
- size_t nsize, nsize_bbox;
- if(bvh_nodes[i].x & PATH_RAY_NODE_UNALIGNED) {
- if(use_obvh) {
- nsize = BVH_UNALIGNED_ONODE_SIZE;
- nsize_bbox = BVH_UNALIGNED_ONODE_SIZE-1;
- }
- else {
- nsize = use_qbvh
- ? BVH_UNALIGNED_QNODE_SIZE
- : BVH_UNALIGNED_NODE_SIZE;
- nsize_bbox = (use_qbvh) ? BVH_UNALIGNED_QNODE_SIZE-1 : 0;
- }
- }
- else {
- if(use_obvh) {
- nsize = BVH_ONODE_SIZE;
- nsize_bbox = BVH_ONODE_SIZE-1;
- }
- else {
- nsize = (use_qbvh)? BVH_QNODE_SIZE: BVH_NODE_SIZE;
- nsize_bbox = (use_qbvh)? BVH_QNODE_SIZE-1 : 0;
- }
- }
-
- memcpy(pack_nodes + pack_nodes_offset,
- bvh_nodes + i,
- nsize_bbox*sizeof(int4));
-
- /* Modify offsets into arrays */
- int4 data = bvh_nodes[i + nsize_bbox];
- int4 data1 = bvh_nodes[i + nsize_bbox-1];
- if(use_obvh) {
- data.z += (data.z < 0) ? -noffset_leaf : noffset;
- data.w += (data.w < 0) ? -noffset_leaf : noffset;
- data.x += (data.x < 0) ? -noffset_leaf : noffset;
- data.y += (data.y < 0) ? -noffset_leaf : noffset;
- data1.z += (data1.z < 0) ? -noffset_leaf : noffset;
- data1.w += (data1.w < 0) ? -noffset_leaf : noffset;
- data1.x += (data1.x < 0) ? -noffset_leaf : noffset;
- data1.y += (data1.y < 0) ? -noffset_leaf : noffset;
- }
- else {
- data.z += (data.z < 0) ? -noffset_leaf : noffset;
- data.w += (data.w < 0) ? -noffset_leaf : noffset;
- if(use_qbvh) {
- data.x += (data.x < 0)? -noffset_leaf: noffset;
- data.y += (data.y < 0)? -noffset_leaf: noffset;
- }
- }
- pack_nodes[pack_nodes_offset + nsize_bbox] = data;
- if(use_obvh) {
- pack_nodes[pack_nodes_offset + nsize_bbox - 1] = data1;
- }
-
- /* Usually this copies nothing, but we better
- * be prepared for possible node size extension.
- */
- memcpy(&pack_nodes[pack_nodes_offset + nsize_bbox+1],
- &bvh_nodes[i + nsize_bbox+1],
- sizeof(int4) * (nsize - (nsize_bbox+1)));
-
- pack_nodes_offset += nsize;
- i += nsize;
- }
- }
-
- nodes_offset += bvh->pack.nodes.size();
- nodes_leaf_offset += bvh->pack.leaf_nodes.size();
- prim_offset += bvh->pack.prim_index.size();
- }
+ /* The BVH's for instances are built separately, but for traversal all
+ * BVH's are stored in global arrays. This function merges them into the
+ * top level BVH, adjusting indexes and offsets where appropriate.
+ */
+ const bool use_qbvh = (params.bvh_layout == BVH_LAYOUT_BVH4);
+ const bool use_obvh = (params.bvh_layout == BVH_LAYOUT_BVH8);
+
+ /* Adjust primitive index to point to the triangle in the global array, for
+ * meshes with transform applied and already in the top level BVH.
+ */
+ for (size_t i = 0; i < pack.prim_index.size(); i++)
+ if (pack.prim_index[i] != -1) {
+ if (pack.prim_type[i] & PRIMITIVE_ALL_CURVE)
+ pack.prim_index[i] += objects[pack.prim_object[i]]->mesh->curve_offset;
+ else
+ pack.prim_index[i] += objects[pack.prim_object[i]]->mesh->tri_offset;
+ }
+
+ /* track offsets of instanced BVH data in global array */
+ size_t prim_offset = pack.prim_index.size();
+ size_t nodes_offset = nodes_size;
+ size_t nodes_leaf_offset = leaf_nodes_size;
+
+ /* clear array that gives the node indexes for instanced objects */
+ pack.object_node.clear();
+
+ /* reserve */
+ size_t prim_index_size = pack.prim_index.size();
+ size_t prim_tri_verts_size = pack.prim_tri_verts.size();
+
+ size_t pack_prim_index_offset = prim_index_size;
+ size_t pack_prim_tri_verts_offset = prim_tri_verts_size;
+ size_t pack_nodes_offset = nodes_size;
+ size_t pack_leaf_nodes_offset = leaf_nodes_size;
+ size_t object_offset = 0;
+
+ map<Mesh *, int> mesh_map;
+
+ foreach (Object *ob, objects) {
+ Mesh *mesh = ob->mesh;
+ BVH *bvh = mesh->bvh;
+
+ if (mesh->need_build_bvh()) {
+ if (mesh_map.find(mesh) == mesh_map.end()) {
+ prim_index_size += bvh->pack.prim_index.size();
+ prim_tri_verts_size += bvh->pack.prim_tri_verts.size();
+ nodes_size += bvh->pack.nodes.size();
+ leaf_nodes_size += bvh->pack.leaf_nodes.size();
+
+ mesh_map[mesh] = 1;
+ }
+ }
+ }
+
+ mesh_map.clear();
+
+ pack.prim_index.resize(prim_index_size);
+ pack.prim_type.resize(prim_index_size);
+ pack.prim_object.resize(prim_index_size);
+ pack.prim_visibility.resize(prim_index_size);
+ pack.prim_tri_verts.resize(prim_tri_verts_size);
+ pack.prim_tri_index.resize(prim_index_size);
+ pack.nodes.resize(nodes_size);
+ pack.leaf_nodes.resize(leaf_nodes_size);
+ pack.object_node.resize(objects.size());
+
+ if (params.num_motion_curve_steps > 0 || params.num_motion_triangle_steps > 0) {
+ pack.prim_time.resize(prim_index_size);
+ }
+
+ int *pack_prim_index = (pack.prim_index.size()) ? &pack.prim_index[0] : NULL;
+ int *pack_prim_type = (pack.prim_type.size()) ? &pack.prim_type[0] : NULL;
+ int *pack_prim_object = (pack.prim_object.size()) ? &pack.prim_object[0] : NULL;
+ uint *pack_prim_visibility = (pack.prim_visibility.size()) ? &pack.prim_visibility[0] : NULL;
+ float4 *pack_prim_tri_verts = (pack.prim_tri_verts.size()) ? &pack.prim_tri_verts[0] : NULL;
+ uint *pack_prim_tri_index = (pack.prim_tri_index.size()) ? &pack.prim_tri_index[0] : NULL;
+ int4 *pack_nodes = (pack.nodes.size()) ? &pack.nodes[0] : NULL;
+ int4 *pack_leaf_nodes = (pack.leaf_nodes.size()) ? &pack.leaf_nodes[0] : NULL;
+ float2 *pack_prim_time = (pack.prim_time.size()) ? &pack.prim_time[0] : NULL;
+
+ /* merge */
+ foreach (Object *ob, objects) {
+ Mesh *mesh = ob->mesh;
+
+ /* We assume that if mesh doesn't need own BVH it was already included
+ * into a top-level BVH and no packing here is needed.
+ */
+ if (!mesh->need_build_bvh()) {
+ pack.object_node[object_offset++] = 0;
+ continue;
+ }
+
+ /* if mesh already added once, don't add it again, but used set
+ * node offset for this object */
+ map<Mesh *, int>::iterator it = mesh_map.find(mesh);
+
+ if (mesh_map.find(mesh) != mesh_map.end()) {
+ int noffset = it->second;
+ pack.object_node[object_offset++] = noffset;
+ continue;
+ }
+
+ BVH *bvh = mesh->bvh;
+
+ int noffset = nodes_offset;
+ int noffset_leaf = nodes_leaf_offset;
+ int mesh_tri_offset = mesh->tri_offset;
+ int mesh_curve_offset = mesh->curve_offset;
+
+ /* fill in node indexes for instances */
+ if (bvh->pack.root_index == -1)
+ pack.object_node[object_offset++] = -noffset_leaf - 1;
+ else
+ pack.object_node[object_offset++] = noffset;
+
+ mesh_map[mesh] = pack.object_node[object_offset - 1];
+
+ /* merge primitive, object and triangle indexes */
+ if (bvh->pack.prim_index.size()) {
+ size_t bvh_prim_index_size = bvh->pack.prim_index.size();
+ int *bvh_prim_index = &bvh->pack.prim_index[0];
+ int *bvh_prim_type = &bvh->pack.prim_type[0];
+ uint *bvh_prim_visibility = &bvh->pack.prim_visibility[0];
+ uint *bvh_prim_tri_index = &bvh->pack.prim_tri_index[0];
+ float2 *bvh_prim_time = bvh->pack.prim_time.size() ? &bvh->pack.prim_time[0] : NULL;
+
+ for (size_t i = 0; i < bvh_prim_index_size; i++) {
+ if (bvh->pack.prim_type[i] & PRIMITIVE_ALL_CURVE) {
+ pack_prim_index[pack_prim_index_offset] = bvh_prim_index[i] + mesh_curve_offset;
+ pack_prim_tri_index[pack_prim_index_offset] = -1;
+ }
+ else {
+ pack_prim_index[pack_prim_index_offset] = bvh_prim_index[i] + mesh_tri_offset;
+ pack_prim_tri_index[pack_prim_index_offset] = bvh_prim_tri_index[i] +
+ pack_prim_tri_verts_offset;
+ }
+
+ pack_prim_type[pack_prim_index_offset] = bvh_prim_type[i];
+ pack_prim_visibility[pack_prim_index_offset] = bvh_prim_visibility[i];
+ pack_prim_object[pack_prim_index_offset] = 0; // unused for instances
+ if (bvh_prim_time != NULL) {
+ pack_prim_time[pack_prim_index_offset] = bvh_prim_time[i];
+ }
+ pack_prim_index_offset++;
+ }
+ }
+
+ /* Merge triangle vertices data. */
+ if (bvh->pack.prim_tri_verts.size()) {
+ const size_t prim_tri_size = bvh->pack.prim_tri_verts.size();
+ memcpy(pack_prim_tri_verts + pack_prim_tri_verts_offset,
+ &bvh->pack.prim_tri_verts[0],
+ prim_tri_size * sizeof(float4));
+ pack_prim_tri_verts_offset += prim_tri_size;
+ }
+
+ /* merge nodes */
+ if (bvh->pack.leaf_nodes.size()) {
+ int4 *leaf_nodes_offset = &bvh->pack.leaf_nodes[0];
+ size_t leaf_nodes_offset_size = bvh->pack.leaf_nodes.size();
+ for (size_t i = 0, j = 0; i < leaf_nodes_offset_size; i += BVH_NODE_LEAF_SIZE, j++) {
+ int4 data = leaf_nodes_offset[i];
+ data.x += prim_offset;
+ data.y += prim_offset;
+ pack_leaf_nodes[pack_leaf_nodes_offset] = data;
+ for (int j = 1; j < BVH_NODE_LEAF_SIZE; ++j) {
+ pack_leaf_nodes[pack_leaf_nodes_offset + j] = leaf_nodes_offset[i + j];
+ }
+ pack_leaf_nodes_offset += BVH_NODE_LEAF_SIZE;
+ }
+ }
+
+ if (bvh->pack.nodes.size()) {
+ int4 *bvh_nodes = &bvh->pack.nodes[0];
+ size_t bvh_nodes_size = bvh->pack.nodes.size();
+
+ for (size_t i = 0, j = 0; i < bvh_nodes_size; j++) {
+ size_t nsize, nsize_bbox;
+ if (bvh_nodes[i].x & PATH_RAY_NODE_UNALIGNED) {
+ if (use_obvh) {
+ nsize = BVH_UNALIGNED_ONODE_SIZE;
+ nsize_bbox = BVH_UNALIGNED_ONODE_SIZE - 1;
+ }
+ else {
+ nsize = use_qbvh ? BVH_UNALIGNED_QNODE_SIZE : BVH_UNALIGNED_NODE_SIZE;
+ nsize_bbox = (use_qbvh) ? BVH_UNALIGNED_QNODE_SIZE - 1 : 0;
+ }
+ }
+ else {
+ if (use_obvh) {
+ nsize = BVH_ONODE_SIZE;
+ nsize_bbox = BVH_ONODE_SIZE - 1;
+ }
+ else {
+ nsize = (use_qbvh) ? BVH_QNODE_SIZE : BVH_NODE_SIZE;
+ nsize_bbox = (use_qbvh) ? BVH_QNODE_SIZE - 1 : 0;
+ }
+ }
+
+ memcpy(pack_nodes + pack_nodes_offset, bvh_nodes + i, nsize_bbox * sizeof(int4));
+
+ /* Modify offsets into arrays */
+ int4 data = bvh_nodes[i + nsize_bbox];
+ int4 data1 = bvh_nodes[i + nsize_bbox - 1];
+ if (use_obvh) {
+ data.z += (data.z < 0) ? -noffset_leaf : noffset;
+ data.w += (data.w < 0) ? -noffset_leaf : noffset;
+ data.x += (data.x < 0) ? -noffset_leaf : noffset;
+ data.y += (data.y < 0) ? -noffset_leaf : noffset;
+ data1.z += (data1.z < 0) ? -noffset_leaf : noffset;
+ data1.w += (data1.w < 0) ? -noffset_leaf : noffset;
+ data1.x += (data1.x < 0) ? -noffset_leaf : noffset;
+ data1.y += (data1.y < 0) ? -noffset_leaf : noffset;
+ }
+ else {
+ data.z += (data.z < 0) ? -noffset_leaf : noffset;
+ data.w += (data.w < 0) ? -noffset_leaf : noffset;
+ if (use_qbvh) {
+ data.x += (data.x < 0) ? -noffset_leaf : noffset;
+ data.y += (data.y < 0) ? -noffset_leaf : noffset;
+ }
+ }
+ pack_nodes[pack_nodes_offset + nsize_bbox] = data;
+ if (use_obvh) {
+ pack_nodes[pack_nodes_offset + nsize_bbox - 1] = data1;
+ }
+
+ /* Usually this copies nothing, but we better
+ * be prepared for possible node size extension.
+ */
+ memcpy(&pack_nodes[pack_nodes_offset + nsize_bbox + 1],
+ &bvh_nodes[i + nsize_bbox + 1],
+ sizeof(int4) * (nsize - (nsize_bbox + 1)));
+
+ pack_nodes_offset += nsize;
+ i += nsize;
+ }
+ }
+
+ nodes_offset += bvh->pack.nodes.size();
+ nodes_leaf_offset += bvh->pack.leaf_nodes.size();
+ prim_offset += bvh->pack.prim_index.size();
+ }
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/bvh/bvh.h b/intern/cycles/bvh/bvh.h
index 33a069eeaf5..edce3ca6f2a 100644
--- a/intern/cycles/bvh/bvh.h
+++ b/intern/cycles/bvh/bvh.h
@@ -34,96 +34,92 @@ class LeafNode;
class Object;
class Progress;
-#define BVH_ALIGN 4096
+#define BVH_ALIGN 4096
#define TRI_NODE_SIZE 3
/* Packed BVH
*
* BVH stored as it will be used for traversal on the rendering device. */
struct PackedBVH {
- /* BVH nodes storage, one node is 4x int4, and contains two bounding boxes,
- * and child, triangle or object indexes depending on the node type */
- array<int4> nodes;
- /* BVH leaf nodes storage. */
- array<int4> leaf_nodes;
- /* object index to BVH node index mapping for instances */
- array<int> object_node;
- /* Mapping from primitive index to index in triangle array. */
- array<uint> prim_tri_index;
- /* Continuous storage of triangle vertices. */
- array<float4> prim_tri_verts;
- /* primitive type - triangle or strand */
- array<int> prim_type;
- /* visibility visibilitys for primitives */
- array<uint> prim_visibility;
- /* mapping from BVH primitive index to true primitive index, as primitives
- * may be duplicated due to spatial splits. -1 for instances. */
- array<int> prim_index;
- /* mapping from BVH primitive index, to the object id of that primitive. */
- array<int> prim_object;
- /* Time range of BVH primitive. */
- array<float2> prim_time;
-
- /* index of the root node. */
- int root_index;
-
- PackedBVH()
- {
- root_index = 0;
- }
+ /* BVH nodes storage, one node is 4x int4, and contains two bounding boxes,
+ * and child, triangle or object indexes depending on the node type */
+ array<int4> nodes;
+ /* BVH leaf nodes storage. */
+ array<int4> leaf_nodes;
+ /* object index to BVH node index mapping for instances */
+ array<int> object_node;
+ /* Mapping from primitive index to index in triangle array. */
+ array<uint> prim_tri_index;
+ /* Continuous storage of triangle vertices. */
+ array<float4> prim_tri_verts;
+ /* primitive type - triangle or strand */
+ array<int> prim_type;
+ /* visibility visibilitys for primitives */
+ array<uint> prim_visibility;
+ /* mapping from BVH primitive index to true primitive index, as primitives
+ * may be duplicated due to spatial splits. -1 for instances. */
+ array<int> prim_index;
+ /* mapping from BVH primitive index, to the object id of that primitive. */
+ array<int> prim_object;
+ /* Time range of BVH primitive. */
+ array<float2> prim_time;
+
+ /* index of the root node. */
+ int root_index;
+
+ PackedBVH()
+ {
+ root_index = 0;
+ }
};
-enum BVH_TYPE {
- bvh2,
- bvh4,
- bvh8
-};
+enum BVH_TYPE { bvh2, bvh4, bvh8 };
/* BVH */
-class BVH
-{
-public:
- PackedBVH pack;
- BVHParams params;
- vector<Object*> objects;
+class BVH {
+ public:
+ PackedBVH pack;
+ BVHParams params;
+ vector<Object *> objects;
- static BVH *create(const BVHParams& params, const vector<Object*>& objects);
- virtual ~BVH() {}
+ static BVH *create(const BVHParams &params, const vector<Object *> &objects);
+ virtual ~BVH()
+ {
+ }
- virtual void build(Progress& progress, Stats *stats=NULL);
- void refit(Progress& progress);
+ virtual void build(Progress &progress, Stats *stats = NULL);
+ void refit(Progress &progress);
-protected:
- BVH(const BVHParams& params, const vector<Object*>& objects);
+ protected:
+ BVH(const BVHParams &params, const vector<Object *> &objects);
- /* Refit range of primitives. */
- void refit_primitives(int start, int end, BoundBox& bbox, uint& visibility);
+ /* Refit range of primitives. */
+ void refit_primitives(int start, int end, BoundBox &bbox, uint &visibility);
- /* triangles and strands */
- void pack_primitives();
- void pack_triangle(int idx, float4 storage[3]);
+ /* triangles and strands */
+ void pack_primitives();
+ void pack_triangle(int idx, float4 storage[3]);
- /* merge instance BVH's */
- void pack_instances(size_t nodes_size, size_t leaf_nodes_size);
+ /* merge instance BVH's */
+ void pack_instances(size_t nodes_size, size_t leaf_nodes_size);
- /* for subclasses to implement */
- virtual void pack_nodes(const BVHNode *root) = 0;
- virtual void refit_nodes() = 0;
+ /* for subclasses to implement */
+ virtual void pack_nodes(const BVHNode *root) = 0;
+ virtual void refit_nodes() = 0;
- virtual BVHNode *widen_children_nodes(const BVHNode *root) = 0;
+ virtual BVHNode *widen_children_nodes(const BVHNode *root) = 0;
};
/* Pack Utility */
-struct BVHStackEntry
-{
- const BVHNode *node;
- int idx;
+struct BVHStackEntry {
+ const BVHNode *node;
+ int idx;
- BVHStackEntry(const BVHNode *n = 0, int i = 0);
- int encodeIdx() const;
+ BVHStackEntry(const BVHNode *n = 0, int i = 0);
+ int encodeIdx() const;
};
CCL_NAMESPACE_END
-#endif /* __BVH_H__ */
+#endif /* __BVH_H__ */
diff --git a/intern/cycles/bvh/bvh2.cpp b/intern/cycles/bvh/bvh2.cpp
index e5dc4e6b1a8..f419d413ef6 100644
--- a/intern/cycles/bvh/bvh2.cpp
+++ b/intern/cycles/bvh/bvh2.cpp
@@ -25,276 +25,268 @@
CCL_NAMESPACE_BEGIN
-BVH2::BVH2(const BVHParams& params_, const vector<Object*>& objects_)
-: BVH(params_, objects_)
+BVH2::BVH2(const BVHParams &params_, const vector<Object *> &objects_) : BVH(params_, objects_)
{
}
BVHNode *BVH2::widen_children_nodes(const BVHNode *root)
{
- return const_cast<BVHNode *>(root);
+ return const_cast<BVHNode *>(root);
}
-void BVH2::pack_leaf(const BVHStackEntry& e,
- const LeafNode *leaf)
+void BVH2::pack_leaf(const BVHStackEntry &e, const LeafNode *leaf)
{
- assert(e.idx + BVH_NODE_LEAF_SIZE <= pack.leaf_nodes.size());
- float4 data[BVH_NODE_LEAF_SIZE];
- memset(data, 0, sizeof(data));
- if(leaf->num_triangles() == 1 && pack.prim_index[leaf->lo] == -1) {
- /* object */
- data[0].x = __int_as_float(~(leaf->lo));
- data[0].y = __int_as_float(0);
- }
- else {
- /* triangle */
- data[0].x = __int_as_float(leaf->lo);
- data[0].y = __int_as_float(leaf->hi);
- }
- data[0].z = __uint_as_float(leaf->visibility);
- if(leaf->num_triangles() != 0) {
- data[0].w = __uint_as_float(pack.prim_type[leaf->lo]);
- }
-
- memcpy(&pack.leaf_nodes[e.idx], data, sizeof(float4)*BVH_NODE_LEAF_SIZE);
+ assert(e.idx + BVH_NODE_LEAF_SIZE <= pack.leaf_nodes.size());
+ float4 data[BVH_NODE_LEAF_SIZE];
+ memset(data, 0, sizeof(data));
+ if (leaf->num_triangles() == 1 && pack.prim_index[leaf->lo] == -1) {
+ /* object */
+ data[0].x = __int_as_float(~(leaf->lo));
+ data[0].y = __int_as_float(0);
+ }
+ else {
+ /* triangle */
+ data[0].x = __int_as_float(leaf->lo);
+ data[0].y = __int_as_float(leaf->hi);
+ }
+ data[0].z = __uint_as_float(leaf->visibility);
+ if (leaf->num_triangles() != 0) {
+ data[0].w = __uint_as_float(pack.prim_type[leaf->lo]);
+ }
+
+ memcpy(&pack.leaf_nodes[e.idx], data, sizeof(float4) * BVH_NODE_LEAF_SIZE);
}
-void BVH2::pack_inner(const BVHStackEntry& e,
- const BVHStackEntry& e0,
- const BVHStackEntry& e1)
+void BVH2::pack_inner(const BVHStackEntry &e, const BVHStackEntry &e0, const BVHStackEntry &e1)
{
- if(e0.node->is_unaligned || e1.node->is_unaligned) {
- pack_unaligned_inner(e, e0, e1);
- } else {
- pack_aligned_inner(e, e0, e1);
- }
+ if (e0.node->is_unaligned || e1.node->is_unaligned) {
+ pack_unaligned_inner(e, e0, e1);
+ }
+ else {
+ pack_aligned_inner(e, e0, e1);
+ }
}
-void BVH2::pack_aligned_inner(const BVHStackEntry& e,
- const BVHStackEntry& e0,
- const BVHStackEntry& e1)
+void BVH2::pack_aligned_inner(const BVHStackEntry &e,
+ const BVHStackEntry &e0,
+ const BVHStackEntry &e1)
{
- pack_aligned_node(e.idx,
- e0.node->bounds, e1.node->bounds,
- e0.encodeIdx(), e1.encodeIdx(),
- e0.node->visibility, e1.node->visibility);
+ pack_aligned_node(e.idx,
+ e0.node->bounds,
+ e1.node->bounds,
+ e0.encodeIdx(),
+ e1.encodeIdx(),
+ e0.node->visibility,
+ e1.node->visibility);
}
void BVH2::pack_aligned_node(int idx,
- const BoundBox& b0,
- const BoundBox& b1,
- int c0, int c1,
- uint visibility0, uint visibility1)
+ const BoundBox &b0,
+ const BoundBox &b1,
+ int c0,
+ int c1,
+ uint visibility0,
+ uint visibility1)
{
- assert(idx + BVH_NODE_SIZE <= pack.nodes.size());
- assert(c0 < 0 || c0 < pack.nodes.size());
- assert(c1 < 0 || c1 < pack.nodes.size());
-
- int4 data[BVH_NODE_SIZE] = {
- make_int4(visibility0 & ~PATH_RAY_NODE_UNALIGNED,
- visibility1 & ~PATH_RAY_NODE_UNALIGNED,
- c0, c1),
- make_int4(__float_as_int(b0.min.x),
- __float_as_int(b1.min.x),
- __float_as_int(b0.max.x),
- __float_as_int(b1.max.x)),
- make_int4(__float_as_int(b0.min.y),
- __float_as_int(b1.min.y),
- __float_as_int(b0.max.y),
- __float_as_int(b1.max.y)),
- make_int4(__float_as_int(b0.min.z),
- __float_as_int(b1.min.z),
- __float_as_int(b0.max.z),
- __float_as_int(b1.max.z)),
- };
-
- memcpy(&pack.nodes[idx], data, sizeof(int4)*BVH_NODE_SIZE);
+ assert(idx + BVH_NODE_SIZE <= pack.nodes.size());
+ assert(c0 < 0 || c0 < pack.nodes.size());
+ assert(c1 < 0 || c1 < pack.nodes.size());
+
+ int4 data[BVH_NODE_SIZE] = {
+ make_int4(
+ visibility0 & ~PATH_RAY_NODE_UNALIGNED, visibility1 & ~PATH_RAY_NODE_UNALIGNED, c0, c1),
+ make_int4(__float_as_int(b0.min.x),
+ __float_as_int(b1.min.x),
+ __float_as_int(b0.max.x),
+ __float_as_int(b1.max.x)),
+ make_int4(__float_as_int(b0.min.y),
+ __float_as_int(b1.min.y),
+ __float_as_int(b0.max.y),
+ __float_as_int(b1.max.y)),
+ make_int4(__float_as_int(b0.min.z),
+ __float_as_int(b1.min.z),
+ __float_as_int(b0.max.z),
+ __float_as_int(b1.max.z)),
+ };
+
+ memcpy(&pack.nodes[idx], data, sizeof(int4) * BVH_NODE_SIZE);
}
-void BVH2::pack_unaligned_inner(const BVHStackEntry& e,
- const BVHStackEntry& e0,
- const BVHStackEntry& e1)
+void BVH2::pack_unaligned_inner(const BVHStackEntry &e,
+ const BVHStackEntry &e0,
+ const BVHStackEntry &e1)
{
- pack_unaligned_node(e.idx,
- e0.node->get_aligned_space(),
- e1.node->get_aligned_space(),
- e0.node->bounds,
- e1.node->bounds,
- e0.encodeIdx(), e1.encodeIdx(),
- e0.node->visibility, e1.node->visibility);
+ pack_unaligned_node(e.idx,
+ e0.node->get_aligned_space(),
+ e1.node->get_aligned_space(),
+ e0.node->bounds,
+ e1.node->bounds,
+ e0.encodeIdx(),
+ e1.encodeIdx(),
+ e0.node->visibility,
+ e1.node->visibility);
}
void BVH2::pack_unaligned_node(int idx,
- const Transform& aligned_space0,
- const Transform& aligned_space1,
- const BoundBox& bounds0,
- const BoundBox& bounds1,
- int c0, int c1,
- uint visibility0, uint visibility1)
+ const Transform &aligned_space0,
+ const Transform &aligned_space1,
+ const BoundBox &bounds0,
+ const BoundBox &bounds1,
+ int c0,
+ int c1,
+ uint visibility0,
+ uint visibility1)
{
- assert(idx + BVH_UNALIGNED_NODE_SIZE <= pack.nodes.size());
- assert(c0 < 0 || c0 < pack.nodes.size());
- assert(c1 < 0 || c1 < pack.nodes.size());
-
- float4 data[BVH_UNALIGNED_NODE_SIZE];
- Transform space0 = BVHUnaligned::compute_node_transform(bounds0,
- aligned_space0);
- Transform space1 = BVHUnaligned::compute_node_transform(bounds1,
- aligned_space1);
- data[0] = make_float4(__int_as_float(visibility0 | PATH_RAY_NODE_UNALIGNED),
- __int_as_float(visibility1 | PATH_RAY_NODE_UNALIGNED),
- __int_as_float(c0),
- __int_as_float(c1));
-
- data[1] = space0.x;
- data[2] = space0.y;
- data[3] = space0.z;
- data[4] = space1.x;
- data[5] = space1.y;
- data[6] = space1.z;
-
- memcpy(&pack.nodes[idx], data, sizeof(float4)*BVH_UNALIGNED_NODE_SIZE);
+ assert(idx + BVH_UNALIGNED_NODE_SIZE <= pack.nodes.size());
+ assert(c0 < 0 || c0 < pack.nodes.size());
+ assert(c1 < 0 || c1 < pack.nodes.size());
+
+ float4 data[BVH_UNALIGNED_NODE_SIZE];
+ Transform space0 = BVHUnaligned::compute_node_transform(bounds0, aligned_space0);
+ Transform space1 = BVHUnaligned::compute_node_transform(bounds1, aligned_space1);
+ data[0] = make_float4(__int_as_float(visibility0 | PATH_RAY_NODE_UNALIGNED),
+ __int_as_float(visibility1 | PATH_RAY_NODE_UNALIGNED),
+ __int_as_float(c0),
+ __int_as_float(c1));
+
+ data[1] = space0.x;
+ data[2] = space0.y;
+ data[3] = space0.z;
+ data[4] = space1.x;
+ data[5] = space1.y;
+ data[6] = space1.z;
+
+ memcpy(&pack.nodes[idx], data, sizeof(float4) * BVH_UNALIGNED_NODE_SIZE);
}
void BVH2::pack_nodes(const BVHNode *root)
{
- const size_t num_nodes = root->getSubtreeSize(BVH_STAT_NODE_COUNT);
- const size_t num_leaf_nodes = root->getSubtreeSize(BVH_STAT_LEAF_COUNT);
- assert(num_leaf_nodes <= num_nodes);
- const size_t num_inner_nodes = num_nodes - num_leaf_nodes;
- size_t node_size;
- if(params.use_unaligned_nodes) {
- const size_t num_unaligned_nodes =
- root->getSubtreeSize(BVH_STAT_UNALIGNED_INNER_COUNT);
- node_size = (num_unaligned_nodes * BVH_UNALIGNED_NODE_SIZE) +
- (num_inner_nodes - num_unaligned_nodes) * BVH_NODE_SIZE;
- }
- else {
- node_size = num_inner_nodes * BVH_NODE_SIZE;
- }
- /* Resize arrays */
- pack.nodes.clear();
- pack.leaf_nodes.clear();
- /* For top level BVH, first merge existing BVH's so we know the offsets. */
- if(params.top_level) {
- pack_instances(node_size, num_leaf_nodes*BVH_NODE_LEAF_SIZE);
- }
- else {
- pack.nodes.resize(node_size);
- pack.leaf_nodes.resize(num_leaf_nodes*BVH_NODE_LEAF_SIZE);
- }
-
- int nextNodeIdx = 0, nextLeafNodeIdx = 0;
-
- vector<BVHStackEntry> stack;
- stack.reserve(BVHParams::MAX_DEPTH*2);
- if(root->is_leaf()) {
- stack.push_back(BVHStackEntry(root, nextLeafNodeIdx++));
- }
- else {
- stack.push_back(BVHStackEntry(root, nextNodeIdx));
- nextNodeIdx += root->has_unaligned() ? BVH_UNALIGNED_NODE_SIZE
- : BVH_NODE_SIZE;
- }
-
- while(stack.size()) {
- BVHStackEntry e = stack.back();
- stack.pop_back();
-
- if(e.node->is_leaf()) {
- /* leaf node */
- const LeafNode *leaf = reinterpret_cast<const LeafNode*>(e.node);
- pack_leaf(e, leaf);
- }
- else {
- /* inner node */
- int idx[2];
- for(int i = 0; i < 2; ++i) {
- if(e.node->get_child(i)->is_leaf()) {
- idx[i] = nextLeafNodeIdx++;
- }
- else {
- idx[i] = nextNodeIdx;
- nextNodeIdx += e.node->get_child(i)->has_unaligned()
- ? BVH_UNALIGNED_NODE_SIZE
- : BVH_NODE_SIZE;
- }
- }
-
- stack.push_back(BVHStackEntry(e.node->get_child(0), idx[0]));
- stack.push_back(BVHStackEntry(e.node->get_child(1), idx[1]));
-
- pack_inner(e, stack[stack.size()-2], stack[stack.size()-1]);
- }
- }
- assert(node_size == nextNodeIdx);
- /* root index to start traversal at, to handle case of single leaf node */
- pack.root_index = (root->is_leaf())? -1: 0;
+ const size_t num_nodes = root->getSubtreeSize(BVH_STAT_NODE_COUNT);
+ const size_t num_leaf_nodes = root->getSubtreeSize(BVH_STAT_LEAF_COUNT);
+ assert(num_leaf_nodes <= num_nodes);
+ const size_t num_inner_nodes = num_nodes - num_leaf_nodes;
+ size_t node_size;
+ if (params.use_unaligned_nodes) {
+ const size_t num_unaligned_nodes = root->getSubtreeSize(BVH_STAT_UNALIGNED_INNER_COUNT);
+ node_size = (num_unaligned_nodes * BVH_UNALIGNED_NODE_SIZE) +
+ (num_inner_nodes - num_unaligned_nodes) * BVH_NODE_SIZE;
+ }
+ else {
+ node_size = num_inner_nodes * BVH_NODE_SIZE;
+ }
+ /* Resize arrays */
+ pack.nodes.clear();
+ pack.leaf_nodes.clear();
+ /* For top level BVH, first merge existing BVH's so we know the offsets. */
+ if (params.top_level) {
+ pack_instances(node_size, num_leaf_nodes * BVH_NODE_LEAF_SIZE);
+ }
+ else {
+ pack.nodes.resize(node_size);
+ pack.leaf_nodes.resize(num_leaf_nodes * BVH_NODE_LEAF_SIZE);
+ }
+
+ int nextNodeIdx = 0, nextLeafNodeIdx = 0;
+
+ vector<BVHStackEntry> stack;
+ stack.reserve(BVHParams::MAX_DEPTH * 2);
+ if (root->is_leaf()) {
+ stack.push_back(BVHStackEntry(root, nextLeafNodeIdx++));
+ }
+ else {
+ stack.push_back(BVHStackEntry(root, nextNodeIdx));
+ nextNodeIdx += root->has_unaligned() ? BVH_UNALIGNED_NODE_SIZE : BVH_NODE_SIZE;
+ }
+
+ while (stack.size()) {
+ BVHStackEntry e = stack.back();
+ stack.pop_back();
+
+ if (e.node->is_leaf()) {
+ /* leaf node */
+ const LeafNode *leaf = reinterpret_cast<const LeafNode *>(e.node);
+ pack_leaf(e, leaf);
+ }
+ else {
+ /* inner node */
+ int idx[2];
+ for (int i = 0; i < 2; ++i) {
+ if (e.node->get_child(i)->is_leaf()) {
+ idx[i] = nextLeafNodeIdx++;
+ }
+ else {
+ idx[i] = nextNodeIdx;
+ nextNodeIdx += e.node->get_child(i)->has_unaligned() ? BVH_UNALIGNED_NODE_SIZE :
+ BVH_NODE_SIZE;
+ }
+ }
+
+ stack.push_back(BVHStackEntry(e.node->get_child(0), idx[0]));
+ stack.push_back(BVHStackEntry(e.node->get_child(1), idx[1]));
+
+ pack_inner(e, stack[stack.size() - 2], stack[stack.size() - 1]);
+ }
+ }
+ assert(node_size == nextNodeIdx);
+ /* root index to start traversal at, to handle case of single leaf node */
+ pack.root_index = (root->is_leaf()) ? -1 : 0;
}
void BVH2::refit_nodes()
{
- assert(!params.top_level);
+ assert(!params.top_level);
- BoundBox bbox = BoundBox::empty;
- uint visibility = 0;
- refit_node(0, (pack.root_index == -1)? true: false, bbox, visibility);
+ BoundBox bbox = BoundBox::empty;
+ uint visibility = 0;
+ refit_node(0, (pack.root_index == -1) ? true : false, bbox, visibility);
}
-void BVH2::refit_node(int idx, bool leaf, BoundBox& bbox, uint& visibility)
+void BVH2::refit_node(int idx, bool leaf, BoundBox &bbox, uint &visibility)
{
- if(leaf) {
- /* refit leaf node */
- assert(idx + BVH_NODE_LEAF_SIZE <= pack.leaf_nodes.size());
- const int4 *data = &pack.leaf_nodes[idx];
- const int c0 = data[0].x;
- const int c1 = data[0].y;
-
- BVH::refit_primitives(c0, c1, bbox, visibility);
-
- /* TODO(sergey): De-duplicate with pack_leaf(). */
- float4 leaf_data[BVH_NODE_LEAF_SIZE];
- leaf_data[0].x = __int_as_float(c0);
- leaf_data[0].y = __int_as_float(c1);
- leaf_data[0].z = __uint_as_float(visibility);
- leaf_data[0].w = __uint_as_float(data[0].w);
- memcpy(&pack.leaf_nodes[idx], leaf_data, sizeof(float4)*BVH_NODE_LEAF_SIZE);
- }
- else {
- assert(idx + BVH_NODE_SIZE <= pack.nodes.size());
-
- const int4 *data = &pack.nodes[idx];
- const bool is_unaligned = (data[0].x & PATH_RAY_NODE_UNALIGNED) != 0;
- const int c0 = data[0].z;
- const int c1 = data[0].w;
- /* refit inner node, set bbox from children */
- BoundBox bbox0 = BoundBox::empty, bbox1 = BoundBox::empty;
- uint visibility0 = 0, visibility1 = 0;
-
- refit_node((c0 < 0)? -c0-1: c0, (c0 < 0), bbox0, visibility0);
- refit_node((c1 < 0)? -c1-1: c1, (c1 < 0), bbox1, visibility1);
-
- if(is_unaligned) {
- Transform aligned_space = transform_identity();
- pack_unaligned_node(idx,
- aligned_space, aligned_space,
- bbox0, bbox1,
- c0, c1,
- visibility0,
- visibility1);
- }
- else {
- pack_aligned_node(idx,
- bbox0, bbox1,
- c0, c1,
- visibility0,
- visibility1);
- }
-
- bbox.grow(bbox0);
- bbox.grow(bbox1);
- visibility = visibility0|visibility1;
- }
+ if (leaf) {
+ /* refit leaf node */
+ assert(idx + BVH_NODE_LEAF_SIZE <= pack.leaf_nodes.size());
+ const int4 *data = &pack.leaf_nodes[idx];
+ const int c0 = data[0].x;
+ const int c1 = data[0].y;
+
+ BVH::refit_primitives(c0, c1, bbox, visibility);
+
+ /* TODO(sergey): De-duplicate with pack_leaf(). */
+ float4 leaf_data[BVH_NODE_LEAF_SIZE];
+ leaf_data[0].x = __int_as_float(c0);
+ leaf_data[0].y = __int_as_float(c1);
+ leaf_data[0].z = __uint_as_float(visibility);
+ leaf_data[0].w = __uint_as_float(data[0].w);
+ memcpy(&pack.leaf_nodes[idx], leaf_data, sizeof(float4) * BVH_NODE_LEAF_SIZE);
+ }
+ else {
+ assert(idx + BVH_NODE_SIZE <= pack.nodes.size());
+
+ const int4 *data = &pack.nodes[idx];
+ const bool is_unaligned = (data[0].x & PATH_RAY_NODE_UNALIGNED) != 0;
+ const int c0 = data[0].z;
+ const int c1 = data[0].w;
+ /* refit inner node, set bbox from children */
+ BoundBox bbox0 = BoundBox::empty, bbox1 = BoundBox::empty;
+ uint visibility0 = 0, visibility1 = 0;
+
+ refit_node((c0 < 0) ? -c0 - 1 : c0, (c0 < 0), bbox0, visibility0);
+ refit_node((c1 < 0) ? -c1 - 1 : c1, (c1 < 0), bbox1, visibility1);
+
+ if (is_unaligned) {
+ Transform aligned_space = transform_identity();
+ pack_unaligned_node(
+ idx, aligned_space, aligned_space, bbox0, bbox1, c0, c1, visibility0, visibility1);
+ }
+ else {
+ pack_aligned_node(idx, bbox0, bbox1, c0, c1, visibility0, visibility1);
+ }
+
+ bbox.grow(bbox0);
+ bbox.grow(bbox1);
+ visibility = visibility0 | visibility1;
+ }
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/bvh/bvh2.h b/intern/cycles/bvh/bvh2.h
index 6afa6c21796..c6a4e6fa73a 100644
--- a/intern/cycles/bvh/bvh2.h
+++ b/intern/cycles/bvh/bvh2.h
@@ -34,8 +34,8 @@ class LeafNode;
class Object;
class Progress;
-#define BVH_NODE_SIZE 4
-#define BVH_NODE_LEAF_SIZE 1
+#define BVH_NODE_SIZE 4
+#define BVH_NODE_LEAF_SIZE 1
#define BVH_UNALIGNED_NODE_SIZE 7
/* BVH2
@@ -43,48 +43,49 @@ class Progress;
* Typical BVH with each node having two children.
*/
class BVH2 : public BVH {
-protected:
- /* constructor */
- friend class BVH;
- BVH2(const BVHParams& params, const vector<Object*>& objects);
+ protected:
+ /* constructor */
+ friend class BVH;
+ BVH2(const BVHParams &params, const vector<Object *> &objects);
- /* Building process. */
- virtual BVHNode *widen_children_nodes(const BVHNode *root) override;
+ /* Building process. */
+ virtual BVHNode *widen_children_nodes(const BVHNode *root) override;
- /* pack */
- void pack_nodes(const BVHNode *root) override;
+ /* pack */
+ void pack_nodes(const BVHNode *root) override;
- void pack_leaf(const BVHStackEntry& e,
- const LeafNode *leaf);
- void pack_inner(const BVHStackEntry& e,
- const BVHStackEntry& e0,
- const BVHStackEntry& e1);
+ void pack_leaf(const BVHStackEntry &e, const LeafNode *leaf);
+ void pack_inner(const BVHStackEntry &e, const BVHStackEntry &e0, const BVHStackEntry &e1);
- void pack_aligned_inner(const BVHStackEntry& e,
- const BVHStackEntry& e0,
- const BVHStackEntry& e1);
- void pack_aligned_node(int idx,
- const BoundBox& b0,
- const BoundBox& b1,
- int c0, int c1,
- uint visibility0, uint visibility1);
+ void pack_aligned_inner(const BVHStackEntry &e,
+ const BVHStackEntry &e0,
+ const BVHStackEntry &e1);
+ void pack_aligned_node(int idx,
+ const BoundBox &b0,
+ const BoundBox &b1,
+ int c0,
+ int c1,
+ uint visibility0,
+ uint visibility1);
- void pack_unaligned_inner(const BVHStackEntry& e,
- const BVHStackEntry& e0,
- const BVHStackEntry& e1);
- void pack_unaligned_node(int idx,
- const Transform& aligned_space0,
- const Transform& aligned_space1,
- const BoundBox& b0,
- const BoundBox& b1,
- int c0, int c1,
- uint visibility0, uint visibility1);
+ void pack_unaligned_inner(const BVHStackEntry &e,
+ const BVHStackEntry &e0,
+ const BVHStackEntry &e1);
+ void pack_unaligned_node(int idx,
+ const Transform &aligned_space0,
+ const Transform &aligned_space1,
+ const BoundBox &b0,
+ const BoundBox &b1,
+ int c0,
+ int c1,
+ uint visibility0,
+ uint visibility1);
- /* refit */
- void refit_nodes() override;
- void refit_node(int idx, bool leaf, BoundBox& bbox, uint& visibility);
+ /* refit */
+ void refit_nodes() override;
+ void refit_node(int idx, bool leaf, BoundBox &bbox, uint &visibility);
};
CCL_NAMESPACE_END
-#endif /* __BVH2_H__ */
+#endif /* __BVH2_H__ */
diff --git a/intern/cycles/bvh/bvh4.cpp b/intern/cycles/bvh/bvh4.cpp
index a7c4cea85ce..850bdf5b8b4 100644
--- a/intern/cycles/bvh/bvh4.cpp
+++ b/intern/cycles/bvh/bvh4.cpp
@@ -31,141 +31,131 @@ CCL_NAMESPACE_BEGIN
* life easier all over the place.
*/
-BVH4::BVH4(const BVHParams& params_, const vector<Object*>& objects_)
-: BVH(params_, objects_)
+BVH4::BVH4(const BVHParams &params_, const vector<Object *> &objects_) : BVH(params_, objects_)
{
- params.bvh_layout = BVH_LAYOUT_BVH4;
+ params.bvh_layout = BVH_LAYOUT_BVH4;
}
namespace {
BVHNode *bvh_node_merge_children_recursively(const BVHNode *node)
{
- if(node->is_leaf()) {
- return new LeafNode(*reinterpret_cast<const LeafNode *>(node));
- }
- /* Collect nodes of one layer deeper, allowing us to have more childrem in
- * an inner layer. */
- assert(node->num_children() <= 2);
- const BVHNode *children[4];
- const BVHNode *child0 = node->get_child(0);
- const BVHNode *child1 = node->get_child(1);
- int num_children = 0;
- if(child0->is_leaf()) {
- children[num_children++] = child0;
- }
- else {
- children[num_children++] = child0->get_child(0);
- children[num_children++] = child0->get_child(1);
- }
- if(child1->is_leaf()) {
- children[num_children++] = child1;
- }
- else {
- children[num_children++] = child1->get_child(0);
- children[num_children++] = child1->get_child(1);
- }
- /* Merge children in subtrees. */
- BVHNode *children4[4];
- for(int i = 0; i < num_children; ++i) {
- children4[i] = bvh_node_merge_children_recursively(children[i]);
- }
- /* Allocate new node. */
- BVHNode *node4 = new InnerNode(node->bounds, children4, num_children);
- /* TODO(sergey): Consider doing this from the InnerNode() constructor.
- * But in order to do this nicely need to think of how to pass all the
- * parameters there. */
- if(node->is_unaligned) {
- node4->is_unaligned = true;
- node4->aligned_space = new Transform();
- *node4->aligned_space = *node->aligned_space;
- }
- return node4;
+ if (node->is_leaf()) {
+ return new LeafNode(*reinterpret_cast<const LeafNode *>(node));
+ }
+ /* Collect nodes of one layer deeper, allowing us to have more childrem in
+ * an inner layer. */
+ assert(node->num_children() <= 2);
+ const BVHNode *children[4];
+ const BVHNode *child0 = node->get_child(0);
+ const BVHNode *child1 = node->get_child(1);
+ int num_children = 0;
+ if (child0->is_leaf()) {
+ children[num_children++] = child0;
+ }
+ else {
+ children[num_children++] = child0->get_child(0);
+ children[num_children++] = child0->get_child(1);
+ }
+ if (child1->is_leaf()) {
+ children[num_children++] = child1;
+ }
+ else {
+ children[num_children++] = child1->get_child(0);
+ children[num_children++] = child1->get_child(1);
+ }
+ /* Merge children in subtrees. */
+ BVHNode *children4[4];
+ for (int i = 0; i < num_children; ++i) {
+ children4[i] = bvh_node_merge_children_recursively(children[i]);
+ }
+ /* Allocate new node. */
+ BVHNode *node4 = new InnerNode(node->bounds, children4, num_children);
+ /* TODO(sergey): Consider doing this from the InnerNode() constructor.
+ * But in order to do this nicely need to think of how to pass all the
+ * parameters there. */
+ if (node->is_unaligned) {
+ node4->is_unaligned = true;
+ node4->aligned_space = new Transform();
+ *node4->aligned_space = *node->aligned_space;
+ }
+ return node4;
}
} // namespace
BVHNode *BVH4::widen_children_nodes(const BVHNode *root)
{
- if(root == NULL) {
- return NULL;
- }
- if(root->is_leaf()) {
- return const_cast<BVHNode *>(root);
- }
- BVHNode *root4 = bvh_node_merge_children_recursively(root);
- /* TODO(sergey): Pack children nodes to parents which has less that 4
- * children. */
- return root4;
+ if (root == NULL) {
+ return NULL;
+ }
+ if (root->is_leaf()) {
+ return const_cast<BVHNode *>(root);
+ }
+ BVHNode *root4 = bvh_node_merge_children_recursively(root);
+ /* TODO(sergey): Pack children nodes to parents which has less that 4
+ * children. */
+ return root4;
}
-void BVH4::pack_leaf(const BVHStackEntry& e, const LeafNode *leaf)
+void BVH4::pack_leaf(const BVHStackEntry &e, const LeafNode *leaf)
{
- float4 data[BVH_QNODE_LEAF_SIZE];
- memset(data, 0, sizeof(data));
- if(leaf->num_triangles() == 1 && pack.prim_index[leaf->lo] == -1) {
- /* object */
- data[0].x = __int_as_float(~(leaf->lo));
- data[0].y = __int_as_float(0);
- }
- else {
- /* triangle */
- data[0].x = __int_as_float(leaf->lo);
- data[0].y = __int_as_float(leaf->hi);
- }
- data[0].z = __uint_as_float(leaf->visibility);
- if(leaf->num_triangles() != 0) {
- data[0].w = __uint_as_float(pack.prim_type[leaf->lo]);
- }
-
- memcpy(&pack.leaf_nodes[e.idx], data, sizeof(float4)*BVH_QNODE_LEAF_SIZE);
+ float4 data[BVH_QNODE_LEAF_SIZE];
+ memset(data, 0, sizeof(data));
+ if (leaf->num_triangles() == 1 && pack.prim_index[leaf->lo] == -1) {
+ /* object */
+ data[0].x = __int_as_float(~(leaf->lo));
+ data[0].y = __int_as_float(0);
+ }
+ else {
+ /* triangle */
+ data[0].x = __int_as_float(leaf->lo);
+ data[0].y = __int_as_float(leaf->hi);
+ }
+ data[0].z = __uint_as_float(leaf->visibility);
+ if (leaf->num_triangles() != 0) {
+ data[0].w = __uint_as_float(pack.prim_type[leaf->lo]);
+ }
+
+ memcpy(&pack.leaf_nodes[e.idx], data, sizeof(float4) * BVH_QNODE_LEAF_SIZE);
}
-void BVH4::pack_inner(const BVHStackEntry& e,
- const BVHStackEntry *en,
- int num)
+void BVH4::pack_inner(const BVHStackEntry &e, const BVHStackEntry *en, int num)
{
- bool has_unaligned = false;
- /* Check whether we have to create unaligned node or all nodes are aligned
- * and we can cut some corner here.
- */
- if(params.use_unaligned_nodes) {
- for(int i = 0; i < num; i++) {
- if(en[i].node->is_unaligned) {
- has_unaligned = true;
- break;
- }
- }
- }
- if(has_unaligned) {
- /* There's no unaligned children, pack into AABB node. */
- pack_unaligned_inner(e, en, num);
- }
- else {
- /* Create unaligned node with orientation transform for each of the
- * children.
- */
- pack_aligned_inner(e, en, num);
- }
+ bool has_unaligned = false;
+ /* Check whether we have to create unaligned node or all nodes are aligned
+ * and we can cut some corner here.
+ */
+ if (params.use_unaligned_nodes) {
+ for (int i = 0; i < num; i++) {
+ if (en[i].node->is_unaligned) {
+ has_unaligned = true;
+ break;
+ }
+ }
+ }
+ if (has_unaligned) {
+ /* There's no unaligned children, pack into AABB node. */
+ pack_unaligned_inner(e, en, num);
+ }
+ else {
+ /* Create unaligned node with orientation transform for each of the
+ * children.
+ */
+ pack_aligned_inner(e, en, num);
+ }
}
-void BVH4::pack_aligned_inner(const BVHStackEntry& e,
- const BVHStackEntry *en,
- int num)
+void BVH4::pack_aligned_inner(const BVHStackEntry &e, const BVHStackEntry *en, int num)
{
- BoundBox bounds[4];
- int child[4];
- for(int i = 0; i < num; ++i) {
- bounds[i] = en[i].node->bounds;
- child[i] = en[i].encodeIdx();
- }
- pack_aligned_node(e.idx,
- bounds,
- child,
- e.node->visibility,
- e.node->time_from,
- e.node->time_to,
- num);
+ BoundBox bounds[4];
+ int child[4];
+ for (int i = 0; i < num; ++i) {
+ bounds[i] = en[i].node->bounds;
+ child[i] = en[i].encodeIdx();
+ }
+ pack_aligned_node(
+ e.idx, bounds, child, e.node->visibility, e.node->time_from, e.node->time_to, num);
}
void BVH4::pack_aligned_node(int idx,
@@ -176,66 +166,64 @@ void BVH4::pack_aligned_node(int idx,
const float time_to,
const int num)
{
- float4 data[BVH_QNODE_SIZE];
- memset(data, 0, sizeof(data));
+ float4 data[BVH_QNODE_SIZE];
+ memset(data, 0, sizeof(data));
- data[0].x = __uint_as_float(visibility & ~PATH_RAY_NODE_UNALIGNED);
- data[0].y = time_from;
- data[0].z = time_to;
+ data[0].x = __uint_as_float(visibility & ~PATH_RAY_NODE_UNALIGNED);
+ data[0].y = time_from;
+ data[0].z = time_to;
- for(int i = 0; i < num; i++) {
- float3 bb_min = bounds[i].min;
- float3 bb_max = bounds[i].max;
+ for (int i = 0; i < num; i++) {
+ float3 bb_min = bounds[i].min;
+ float3 bb_max = bounds[i].max;
- data[1][i] = bb_min.x;
- data[2][i] = bb_max.x;
- data[3][i] = bb_min.y;
- data[4][i] = bb_max.y;
- data[5][i] = bb_min.z;
- data[6][i] = bb_max.z;
+ data[1][i] = bb_min.x;
+ data[2][i] = bb_max.x;
+ data[3][i] = bb_min.y;
+ data[4][i] = bb_max.y;
+ data[5][i] = bb_min.z;
+ data[6][i] = bb_max.z;
- data[7][i] = __int_as_float(child[i]);
- }
+ data[7][i] = __int_as_float(child[i]);
+ }
- for(int i = num; i < 4; i++) {
- /* We store BB which would never be recorded as intersection
- * so kernel might safely assume there are always 4 child nodes.
- */
- data[1][i] = FLT_MAX;
- data[2][i] = -FLT_MAX;
+ for (int i = num; i < 4; i++) {
+ /* We store BB which would never be recorded as intersection
+ * so kernel might safely assume there are always 4 child nodes.
+ */
+ data[1][i] = FLT_MAX;
+ data[2][i] = -FLT_MAX;
- data[3][i] = FLT_MAX;
- data[4][i] = -FLT_MAX;
+ data[3][i] = FLT_MAX;
+ data[4][i] = -FLT_MAX;
- data[5][i] = FLT_MAX;
- data[6][i] = -FLT_MAX;
+ data[5][i] = FLT_MAX;
+ data[6][i] = -FLT_MAX;
- data[7][i] = __int_as_float(0);
- }
+ data[7][i] = __int_as_float(0);
+ }
- memcpy(&pack.nodes[idx], data, sizeof(float4)*BVH_QNODE_SIZE);
+ memcpy(&pack.nodes[idx], data, sizeof(float4) * BVH_QNODE_SIZE);
}
-void BVH4::pack_unaligned_inner(const BVHStackEntry& e,
- const BVHStackEntry *en,
- int num)
+void BVH4::pack_unaligned_inner(const BVHStackEntry &e, const BVHStackEntry *en, int num)
{
- Transform aligned_space[4];
- BoundBox bounds[4];
- int child[4];
- for(int i = 0; i < num; ++i) {
- aligned_space[i] = en[i].node->get_aligned_space();
- bounds[i] = en[i].node->bounds;
- child[i] = en[i].encodeIdx();
- }
- pack_unaligned_node(e.idx,
- aligned_space,
- bounds,
- child,
- e.node->visibility,
- e.node->time_from,
- e.node->time_to,
- num);
+ Transform aligned_space[4];
+ BoundBox bounds[4];
+ int child[4];
+ for (int i = 0; i < num; ++i) {
+ aligned_space[i] = en[i].node->get_aligned_space();
+ bounds[i] = en[i].node->bounds;
+ child[i] = en[i].encodeIdx();
+ }
+ pack_unaligned_node(e.idx,
+ aligned_space,
+ bounds,
+ child,
+ e.node->visibility,
+ e.node->time_from,
+ e.node->time_to,
+ num);
}
void BVH4::pack_unaligned_node(int idx,
@@ -247,235 +235,211 @@ void BVH4::pack_unaligned_node(int idx,
const float time_to,
const int num)
{
- float4 data[BVH_UNALIGNED_QNODE_SIZE];
- memset(data, 0, sizeof(data));
+ float4 data[BVH_UNALIGNED_QNODE_SIZE];
+ memset(data, 0, sizeof(data));
- data[0].x = __uint_as_float(visibility | PATH_RAY_NODE_UNALIGNED);
- data[0].y = time_from;
- data[0].z = time_to;
+ data[0].x = __uint_as_float(visibility | PATH_RAY_NODE_UNALIGNED);
+ data[0].y = time_from;
+ data[0].z = time_to;
- for(int i = 0; i < num; i++) {
- Transform space = BVHUnaligned::compute_node_transform(
- bounds[i],
- aligned_space[i]);
+ for (int i = 0; i < num; i++) {
+ Transform space = BVHUnaligned::compute_node_transform(bounds[i], aligned_space[i]);
- data[1][i] = space.x.x;
- data[2][i] = space.x.y;
- data[3][i] = space.x.z;
+ data[1][i] = space.x.x;
+ data[2][i] = space.x.y;
+ data[3][i] = space.x.z;
- data[4][i] = space.y.x;
- data[5][i] = space.y.y;
- data[6][i] = space.y.z;
+ data[4][i] = space.y.x;
+ data[5][i] = space.y.y;
+ data[6][i] = space.y.z;
- data[7][i] = space.z.x;
- data[8][i] = space.z.y;
- data[9][i] = space.z.z;
+ data[7][i] = space.z.x;
+ data[8][i] = space.z.y;
+ data[9][i] = space.z.z;
- data[10][i] = space.x.w;
- data[11][i] = space.y.w;
- data[12][i] = space.z.w;
+ data[10][i] = space.x.w;
+ data[11][i] = space.y.w;
+ data[12][i] = space.z.w;
- data[13][i] = __int_as_float(child[i]);
- }
+ data[13][i] = __int_as_float(child[i]);
+ }
- for(int i = num; i < 4; i++) {
- /* We store BB which would never be recorded as intersection
- * so kernel might safely assume there are always 4 child nodes.
- */
+ for (int i = num; i < 4; i++) {
+ /* We store BB which would never be recorded as intersection
+ * so kernel might safely assume there are always 4 child nodes.
+ */
- data[1][i] = NAN;
- data[2][i] = NAN;
- data[3][i] = NAN;
+ data[1][i] = NAN;
+ data[2][i] = NAN;
+ data[3][i] = NAN;
- data[4][i] = NAN;
- data[5][i] = NAN;
- data[6][i] = NAN;
+ data[4][i] = NAN;
+ data[5][i] = NAN;
+ data[6][i] = NAN;
- data[7][i] = NAN;
- data[8][i] = NAN;
- data[9][i] = NAN;
+ data[7][i] = NAN;
+ data[8][i] = NAN;
+ data[9][i] = NAN;
- data[10][i] = NAN;
- data[11][i] = NAN;
- data[12][i] = NAN;
+ data[10][i] = NAN;
+ data[11][i] = NAN;
+ data[12][i] = NAN;
- data[13][i] = __int_as_float(0);
- }
+ data[13][i] = __int_as_float(0);
+ }
- memcpy(&pack.nodes[idx], data, sizeof(float4)*BVH_UNALIGNED_QNODE_SIZE);
+ memcpy(&pack.nodes[idx], data, sizeof(float4) * BVH_UNALIGNED_QNODE_SIZE);
}
/* Quad SIMD Nodes */
void BVH4::pack_nodes(const BVHNode *root)
{
- /* Calculate size of the arrays required. */
- const size_t num_nodes = root->getSubtreeSize(BVH_STAT_NODE_COUNT);
- const size_t num_leaf_nodes = root->getSubtreeSize(BVH_STAT_LEAF_COUNT);
- assert(num_leaf_nodes <= num_nodes);
- const size_t num_inner_nodes = num_nodes - num_leaf_nodes;
- size_t node_size;
- if(params.use_unaligned_nodes) {
- const size_t num_unaligned_nodes =
- root->getSubtreeSize(BVH_STAT_UNALIGNED_INNER_COUNT);
- node_size = (num_unaligned_nodes * BVH_UNALIGNED_QNODE_SIZE) +
- (num_inner_nodes - num_unaligned_nodes) * BVH_QNODE_SIZE;
- }
- else {
- node_size = num_inner_nodes * BVH_QNODE_SIZE;
- }
- /* Resize arrays. */
- pack.nodes.clear();
- pack.leaf_nodes.clear();
- /* For top level BVH, first merge existing BVH's so we know the offsets. */
- if(params.top_level) {
- pack_instances(node_size, num_leaf_nodes*BVH_QNODE_LEAF_SIZE);
- }
- else {
- pack.nodes.resize(node_size);
- pack.leaf_nodes.resize(num_leaf_nodes*BVH_QNODE_LEAF_SIZE);
- }
-
- int nextNodeIdx = 0, nextLeafNodeIdx = 0;
-
- vector<BVHStackEntry> stack;
- stack.reserve(BVHParams::MAX_DEPTH*2);
- if(root->is_leaf()) {
- stack.push_back(BVHStackEntry(root, nextLeafNodeIdx++));
- }
- else {
- stack.push_back(BVHStackEntry(root, nextNodeIdx));
- nextNodeIdx += root->has_unaligned() ? BVH_UNALIGNED_QNODE_SIZE
- : BVH_QNODE_SIZE;
- }
-
- while(stack.size()) {
- BVHStackEntry e = stack.back();
- stack.pop_back();
-
- if(e.node->is_leaf()) {
- /* leaf node */
- const LeafNode *leaf = reinterpret_cast<const LeafNode*>(e.node);
- pack_leaf(e, leaf);
- }
- else {
- /* Inner node. */
- /* Collect nodes. */
- const BVHNode *children[4];
- const int num_children = e.node->num_children();
- /* Push entries on the stack. */
- for(int i = 0; i < num_children; ++i) {
- int idx;
- children[i] = e.node->get_child(i);
- assert(children[i] != NULL);
- if(children[i]->is_leaf()) {
- idx = nextLeafNodeIdx++;
- }
- else {
- idx = nextNodeIdx;
- nextNodeIdx += children[i]->has_unaligned()
- ? BVH_UNALIGNED_QNODE_SIZE
- : BVH_QNODE_SIZE;
- }
- stack.push_back(BVHStackEntry(children[i], idx));
- }
- /* Set node. */
- pack_inner(e, &stack[stack.size() - num_children], num_children);
- }
- }
-
- assert(node_size == nextNodeIdx);
- /* Root index to start traversal at, to handle case of single leaf node. */
- pack.root_index = (root->is_leaf())? -1: 0;
+ /* Calculate size of the arrays required. */
+ const size_t num_nodes = root->getSubtreeSize(BVH_STAT_NODE_COUNT);
+ const size_t num_leaf_nodes = root->getSubtreeSize(BVH_STAT_LEAF_COUNT);
+ assert(num_leaf_nodes <= num_nodes);
+ const size_t num_inner_nodes = num_nodes - num_leaf_nodes;
+ size_t node_size;
+ if (params.use_unaligned_nodes) {
+ const size_t num_unaligned_nodes = root->getSubtreeSize(BVH_STAT_UNALIGNED_INNER_COUNT);
+ node_size = (num_unaligned_nodes * BVH_UNALIGNED_QNODE_SIZE) +
+ (num_inner_nodes - num_unaligned_nodes) * BVH_QNODE_SIZE;
+ }
+ else {
+ node_size = num_inner_nodes * BVH_QNODE_SIZE;
+ }
+ /* Resize arrays. */
+ pack.nodes.clear();
+ pack.leaf_nodes.clear();
+ /* For top level BVH, first merge existing BVH's so we know the offsets. */
+ if (params.top_level) {
+ pack_instances(node_size, num_leaf_nodes * BVH_QNODE_LEAF_SIZE);
+ }
+ else {
+ pack.nodes.resize(node_size);
+ pack.leaf_nodes.resize(num_leaf_nodes * BVH_QNODE_LEAF_SIZE);
+ }
+
+ int nextNodeIdx = 0, nextLeafNodeIdx = 0;
+
+ vector<BVHStackEntry> stack;
+ stack.reserve(BVHParams::MAX_DEPTH * 2);
+ if (root->is_leaf()) {
+ stack.push_back(BVHStackEntry(root, nextLeafNodeIdx++));
+ }
+ else {
+ stack.push_back(BVHStackEntry(root, nextNodeIdx));
+ nextNodeIdx += root->has_unaligned() ? BVH_UNALIGNED_QNODE_SIZE : BVH_QNODE_SIZE;
+ }
+
+ while (stack.size()) {
+ BVHStackEntry e = stack.back();
+ stack.pop_back();
+
+ if (e.node->is_leaf()) {
+ /* leaf node */
+ const LeafNode *leaf = reinterpret_cast<const LeafNode *>(e.node);
+ pack_leaf(e, leaf);
+ }
+ else {
+ /* Inner node. */
+ /* Collect nodes. */
+ const BVHNode *children[4];
+ const int num_children = e.node->num_children();
+ /* Push entries on the stack. */
+ for (int i = 0; i < num_children; ++i) {
+ int idx;
+ children[i] = e.node->get_child(i);
+ assert(children[i] != NULL);
+ if (children[i]->is_leaf()) {
+ idx = nextLeafNodeIdx++;
+ }
+ else {
+ idx = nextNodeIdx;
+ nextNodeIdx += children[i]->has_unaligned() ? BVH_UNALIGNED_QNODE_SIZE : BVH_QNODE_SIZE;
+ }
+ stack.push_back(BVHStackEntry(children[i], idx));
+ }
+ /* Set node. */
+ pack_inner(e, &stack[stack.size() - num_children], num_children);
+ }
+ }
+
+ assert(node_size == nextNodeIdx);
+ /* Root index to start traversal at, to handle case of single leaf node. */
+ pack.root_index = (root->is_leaf()) ? -1 : 0;
}
void BVH4::refit_nodes()
{
- assert(!params.top_level);
+ assert(!params.top_level);
- BoundBox bbox = BoundBox::empty;
- uint visibility = 0;
- refit_node(0, (pack.root_index == -1)? true: false, bbox, visibility);
+ BoundBox bbox = BoundBox::empty;
+ uint visibility = 0;
+ refit_node(0, (pack.root_index == -1) ? true : false, bbox, visibility);
}
-void BVH4::refit_node(int idx, bool leaf, BoundBox& bbox, uint& visibility)
+void BVH4::refit_node(int idx, bool leaf, BoundBox &bbox, uint &visibility)
{
- if(leaf) {
- /* Refit leaf node. */
- int4 *data = &pack.leaf_nodes[idx];
- int4 c = data[0];
-
- BVH::refit_primitives(c.x, c.y, bbox, visibility);
-
- /* TODO(sergey): This is actually a copy of pack_leaf(),
- * but this chunk of code only knows actual data and has
- * no idea about BVHNode.
- *
- * Would be nice to de-duplicate code, but trying to make
- * making code more general ends up in much nastier code
- * in my opinion so far.
- *
- * Same applies to the inner nodes case below.
- */
- float4 leaf_data[BVH_QNODE_LEAF_SIZE];
- leaf_data[0].x = __int_as_float(c.x);
- leaf_data[0].y = __int_as_float(c.y);
- leaf_data[0].z = __uint_as_float(visibility);
- leaf_data[0].w = __uint_as_float(c.w);
- memcpy(&pack.leaf_nodes[idx], leaf_data, sizeof(float4)*BVH_QNODE_LEAF_SIZE);
- }
- else {
- int4 *data = &pack.nodes[idx];
- bool is_unaligned = (data[0].x & PATH_RAY_NODE_UNALIGNED) != 0;
- int4 c;
- if(is_unaligned) {
- c = data[13];
- }
- else {
- c = data[7];
- }
- /* Refit inner node, set bbox from children. */
- BoundBox child_bbox[4] = {BoundBox::empty,
- BoundBox::empty,
- BoundBox::empty,
- BoundBox::empty};
- uint child_visibility[4] = {0};
- int num_nodes = 0;
-
- for(int i = 0; i < 4; ++i) {
- if(c[i] != 0) {
- refit_node((c[i] < 0)? -c[i]-1: c[i], (c[i] < 0),
- child_bbox[i], child_visibility[i]);
- ++num_nodes;
- bbox.grow(child_bbox[i]);
- visibility |= child_visibility[i];
- }
- }
-
- if(is_unaligned) {
- Transform aligned_space[4] = {transform_identity(),
- transform_identity(),
- transform_identity(),
- transform_identity()};
- pack_unaligned_node(idx,
- aligned_space,
- child_bbox,
- &c[0],
- visibility,
- 0.0f,
- 1.0f,
- num_nodes);
- }
- else {
- pack_aligned_node(idx,
- child_bbox,
- &c[0],
- visibility,
- 0.0f,
- 1.0f,
- num_nodes);
- }
- }
+ if (leaf) {
+ /* Refit leaf node. */
+ int4 *data = &pack.leaf_nodes[idx];
+ int4 c = data[0];
+
+ BVH::refit_primitives(c.x, c.y, bbox, visibility);
+
+ /* TODO(sergey): This is actually a copy of pack_leaf(),
+ * but this chunk of code only knows actual data and has
+ * no idea about BVHNode.
+ *
+ * Would be nice to de-duplicate code, but trying to make
+ * making code more general ends up in much nastier code
+ * in my opinion so far.
+ *
+ * Same applies to the inner nodes case below.
+ */
+ float4 leaf_data[BVH_QNODE_LEAF_SIZE];
+ leaf_data[0].x = __int_as_float(c.x);
+ leaf_data[0].y = __int_as_float(c.y);
+ leaf_data[0].z = __uint_as_float(visibility);
+ leaf_data[0].w = __uint_as_float(c.w);
+ memcpy(&pack.leaf_nodes[idx], leaf_data, sizeof(float4) * BVH_QNODE_LEAF_SIZE);
+ }
+ else {
+ int4 *data = &pack.nodes[idx];
+ bool is_unaligned = (data[0].x & PATH_RAY_NODE_UNALIGNED) != 0;
+ int4 c;
+ if (is_unaligned) {
+ c = data[13];
+ }
+ else {
+ c = data[7];
+ }
+ /* Refit inner node, set bbox from children. */
+ BoundBox child_bbox[4] = {BoundBox::empty, BoundBox::empty, BoundBox::empty, BoundBox::empty};
+ uint child_visibility[4] = {0};
+ int num_nodes = 0;
+
+ for (int i = 0; i < 4; ++i) {
+ if (c[i] != 0) {
+ refit_node((c[i] < 0) ? -c[i] - 1 : c[i], (c[i] < 0), child_bbox[i], child_visibility[i]);
+ ++num_nodes;
+ bbox.grow(child_bbox[i]);
+ visibility |= child_visibility[i];
+ }
+ }
+
+ if (is_unaligned) {
+ Transform aligned_space[4] = {
+ transform_identity(), transform_identity(), transform_identity(), transform_identity()};
+ pack_unaligned_node(
+ idx, aligned_space, child_bbox, &c[0], visibility, 0.0f, 1.0f, num_nodes);
+ }
+ else {
+ pack_aligned_node(idx, child_bbox, &c[0], visibility, 0.0f, 1.0f, num_nodes);
+ }
+ }
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/bvh/bvh4.h b/intern/cycles/bvh/bvh4.h
index caa0e2c8182..38b0961d3df 100644
--- a/intern/cycles/bvh/bvh4.h
+++ b/intern/cycles/bvh/bvh4.h
@@ -34,8 +34,8 @@ class LeafNode;
class Object;
class Progress;
-#define BVH_QNODE_SIZE 8
-#define BVH_QNODE_LEAF_SIZE 1
+#define BVH_QNODE_SIZE 8
+#define BVH_QNODE_LEAF_SIZE 1
#define BVH_UNALIGNED_QNODE_SIZE 14
/* BVH4
@@ -43,48 +43,44 @@ class Progress;
* Quad BVH, with each node having four children, to use with SIMD instructions.
*/
class BVH4 : public BVH {
-protected:
- /* constructor */
- friend class BVH;
- BVH4(const BVHParams& params, const vector<Object*>& objects);
+ protected:
+ /* constructor */
+ friend class BVH;
+ BVH4(const BVHParams &params, const vector<Object *> &objects);
- /* Building process. */
- virtual BVHNode *widen_children_nodes(const BVHNode *root) override;
+ /* Building process. */
+ virtual BVHNode *widen_children_nodes(const BVHNode *root) override;
- /* pack */
- void pack_nodes(const BVHNode *root) override;
+ /* pack */
+ void pack_nodes(const BVHNode *root) override;
- void pack_leaf(const BVHStackEntry& e, const LeafNode *leaf);
- void pack_inner(const BVHStackEntry& e, const BVHStackEntry *en, int num);
+ void pack_leaf(const BVHStackEntry &e, const LeafNode *leaf);
+ void pack_inner(const BVHStackEntry &e, const BVHStackEntry *en, int num);
- void pack_aligned_inner(const BVHStackEntry& e,
- const BVHStackEntry *en,
- int num);
- void pack_aligned_node(int idx,
- const BoundBox *bounds,
- const int *child,
- const uint visibility,
- const float time_from,
- const float time_to,
- const int num);
+ void pack_aligned_inner(const BVHStackEntry &e, const BVHStackEntry *en, int num);
+ void pack_aligned_node(int idx,
+ const BoundBox *bounds,
+ const int *child,
+ const uint visibility,
+ const float time_from,
+ const float time_to,
+ const int num);
- void pack_unaligned_inner(const BVHStackEntry& e,
- const BVHStackEntry *en,
- int num);
- void pack_unaligned_node(int idx,
- const Transform *aligned_space,
- const BoundBox *bounds,
- const int *child,
- const uint visibility,
- const float time_from,
- const float time_to,
- const int num);
+ void pack_unaligned_inner(const BVHStackEntry &e, const BVHStackEntry *en, int num);
+ void pack_unaligned_node(int idx,
+ const Transform *aligned_space,
+ const BoundBox *bounds,
+ const int *child,
+ const uint visibility,
+ const float time_from,
+ const float time_to,
+ const int num);
- /* refit */
- void refit_nodes() override;
- void refit_node(int idx, bool leaf, BoundBox& bbox, uint& visibility);
+ /* refit */
+ void refit_nodes() override;
+ void refit_node(int idx, bool leaf, BoundBox &bbox, uint &visibility);
};
CCL_NAMESPACE_END
-#endif /* __BVH4_H__ */
+#endif /* __BVH4_H__ */
diff --git a/intern/cycles/bvh/bvh8.cpp b/intern/cycles/bvh/bvh8.cpp
index af930b2f2df..e812d806b94 100644
--- a/intern/cycles/bvh/bvh8.cpp
+++ b/intern/cycles/bvh/bvh8.cpp
@@ -36,8 +36,7 @@
CCL_NAMESPACE_BEGIN
-BVH8::BVH8(const BVHParams& params_, const vector<Object*>& objects_)
-: BVH(params_, objects_)
+BVH8::BVH8(const BVHParams &params_, const vector<Object *> &objects_) : BVH(params_, objects_)
{
}
@@ -45,159 +44,148 @@ namespace {
BVHNode *bvh_node_merge_children_recursively(const BVHNode *node)
{
- if(node->is_leaf()) {
- return new LeafNode(*reinterpret_cast<const LeafNode *>(node));
- }
- /* Collect nodes of two layer deeper, allowing us to have more childrem in
- * an inner layer. */
- assert(node->num_children() <= 2);
- const BVHNode *children[8];
- const BVHNode *child0 = node->get_child(0);
- const BVHNode *child1 = node->get_child(1);
- int num_children = 0;
- if(child0->is_leaf()) {
- children[num_children++] = child0;
- }
- else {
- const BVHNode *child00 = child0->get_child(0),
- *child01 = child0->get_child(1);
- if(child00->is_leaf()) {
- children[num_children++] = child00;
- }
- else {
- children[num_children++] = child00->get_child(0);
- children[num_children++] = child00->get_child(1);
- }
- if(child01->is_leaf()) {
- children[num_children++] = child01;
- }
- else {
- children[num_children++] = child01->get_child(0);
- children[num_children++] = child01->get_child(1);
- }
- }
- if(child1->is_leaf()) {
- children[num_children++] = child1;
- }
- else {
- const BVHNode *child10 = child1->get_child(0),
- *child11 = child1->get_child(1);
- if(child10->is_leaf()) {
- children[num_children++] = child10;
- }
- else {
- children[num_children++] = child10->get_child(0);
- children[num_children++] = child10->get_child(1);
- }
- if(child11->is_leaf()) {
- children[num_children++] = child11;
- }
- else {
- children[num_children++] = child11->get_child(0);
- children[num_children++] = child11->get_child(1);
- }
- }
- /* Merge children in subtrees. */
- BVHNode *children4[8];
- for(int i = 0; i < num_children; ++i) {
- children4[i] = bvh_node_merge_children_recursively(children[i]);
- }
- /* Allocate new node. */
- BVHNode *node8 = new InnerNode(node->bounds, children4, num_children);
- /* TODO(sergey): Consider doing this from the InnerNode() constructor.
- * But in order to do this nicely need to think of how to pass all the
- * parameters there. */
- if(node->is_unaligned) {
- node8->is_unaligned = true;
- node8->aligned_space = new Transform();
- *node8->aligned_space = *node->aligned_space;
- }
- return node8;
+ if (node->is_leaf()) {
+ return new LeafNode(*reinterpret_cast<const LeafNode *>(node));
+ }
+ /* Collect nodes of two layer deeper, allowing us to have more childrem in
+ * an inner layer. */
+ assert(node->num_children() <= 2);
+ const BVHNode *children[8];
+ const BVHNode *child0 = node->get_child(0);
+ const BVHNode *child1 = node->get_child(1);
+ int num_children = 0;
+ if (child0->is_leaf()) {
+ children[num_children++] = child0;
+ }
+ else {
+ const BVHNode *child00 = child0->get_child(0), *child01 = child0->get_child(1);
+ if (child00->is_leaf()) {
+ children[num_children++] = child00;
+ }
+ else {
+ children[num_children++] = child00->get_child(0);
+ children[num_children++] = child00->get_child(1);
+ }
+ if (child01->is_leaf()) {
+ children[num_children++] = child01;
+ }
+ else {
+ children[num_children++] = child01->get_child(0);
+ children[num_children++] = child01->get_child(1);
+ }
+ }
+ if (child1->is_leaf()) {
+ children[num_children++] = child1;
+ }
+ else {
+ const BVHNode *child10 = child1->get_child(0), *child11 = child1->get_child(1);
+ if (child10->is_leaf()) {
+ children[num_children++] = child10;
+ }
+ else {
+ children[num_children++] = child10->get_child(0);
+ children[num_children++] = child10->get_child(1);
+ }
+ if (child11->is_leaf()) {
+ children[num_children++] = child11;
+ }
+ else {
+ children[num_children++] = child11->get_child(0);
+ children[num_children++] = child11->get_child(1);
+ }
+ }
+ /* Merge children in subtrees. */
+ BVHNode *children4[8];
+ for (int i = 0; i < num_children; ++i) {
+ children4[i] = bvh_node_merge_children_recursively(children[i]);
+ }
+ /* Allocate new node. */
+ BVHNode *node8 = new InnerNode(node->bounds, children4, num_children);
+ /* TODO(sergey): Consider doing this from the InnerNode() constructor.
+ * But in order to do this nicely need to think of how to pass all the
+ * parameters there. */
+ if (node->is_unaligned) {
+ node8->is_unaligned = true;
+ node8->aligned_space = new Transform();
+ *node8->aligned_space = *node->aligned_space;
+ }
+ return node8;
}
} // namespace
BVHNode *BVH8::widen_children_nodes(const BVHNode *root)
{
- if(root == NULL) {
- return NULL;
- }
- if(root->is_leaf()) {
- return const_cast<BVHNode *>(root);
- }
- BVHNode *root8 = bvh_node_merge_children_recursively(root);
- /* TODO(sergey): Pack children nodes to parents which has less that 4
- * children. */
- return root8;
+ if (root == NULL) {
+ return NULL;
+ }
+ if (root->is_leaf()) {
+ return const_cast<BVHNode *>(root);
+ }
+ BVHNode *root8 = bvh_node_merge_children_recursively(root);
+ /* TODO(sergey): Pack children nodes to parents which has less that 4
+ * children. */
+ return root8;
}
-void BVH8::pack_leaf(const BVHStackEntry& e, const LeafNode *leaf)
+void BVH8::pack_leaf(const BVHStackEntry &e, const LeafNode *leaf)
{
- float4 data[BVH_ONODE_LEAF_SIZE];
- memset(data, 0, sizeof(data));
- if(leaf->num_triangles() == 1 && pack.prim_index[leaf->lo] == -1) {
- /* object */
- data[0].x = __int_as_float(~(leaf->lo));
- data[0].y = __int_as_float(0);
- }
- else {
- /* triangle */
- data[0].x = __int_as_float(leaf->lo);
- data[0].y = __int_as_float(leaf->hi);
- }
- data[0].z = __uint_as_float(leaf->visibility);
- if(leaf->num_triangles() != 0) {
- data[0].w = __uint_as_float(pack.prim_type[leaf->lo]);
- }
-
- memcpy(&pack.leaf_nodes[e.idx], data, sizeof(float4)*BVH_ONODE_LEAF_SIZE);
+ float4 data[BVH_ONODE_LEAF_SIZE];
+ memset(data, 0, sizeof(data));
+ if (leaf->num_triangles() == 1 && pack.prim_index[leaf->lo] == -1) {
+ /* object */
+ data[0].x = __int_as_float(~(leaf->lo));
+ data[0].y = __int_as_float(0);
+ }
+ else {
+ /* triangle */
+ data[0].x = __int_as_float(leaf->lo);
+ data[0].y = __int_as_float(leaf->hi);
+ }
+ data[0].z = __uint_as_float(leaf->visibility);
+ if (leaf->num_triangles() != 0) {
+ data[0].w = __uint_as_float(pack.prim_type[leaf->lo]);
+ }
+
+ memcpy(&pack.leaf_nodes[e.idx], data, sizeof(float4) * BVH_ONODE_LEAF_SIZE);
}
-void BVH8::pack_inner(const BVHStackEntry& e,
- const BVHStackEntry *en,
- int num)
+void BVH8::pack_inner(const BVHStackEntry &e, const BVHStackEntry *en, int num)
{
- bool has_unaligned = false;
- /* Check whether we have to create unaligned node or all nodes are aligned
- * and we can cut some corner here.
- */
- if(params.use_unaligned_nodes) {
- for(int i = 0; i < num; i++) {
- if(en[i].node->is_unaligned) {
- has_unaligned = true;
- break;
- }
- }
- }
- if(has_unaligned) {
- /* There's no unaligned children, pack into AABB node. */
- pack_unaligned_inner(e, en, num);
- }
- else {
- /* Create unaligned node with orientation transform for each of the
- * children.
- */
- pack_aligned_inner(e, en, num);
- }
+ bool has_unaligned = false;
+ /* Check whether we have to create unaligned node or all nodes are aligned
+ * and we can cut some corner here.
+ */
+ if (params.use_unaligned_nodes) {
+ for (int i = 0; i < num; i++) {
+ if (en[i].node->is_unaligned) {
+ has_unaligned = true;
+ break;
+ }
+ }
+ }
+ if (has_unaligned) {
+ /* There's no unaligned children, pack into AABB node. */
+ pack_unaligned_inner(e, en, num);
+ }
+ else {
+ /* Create unaligned node with orientation transform for each of the
+ * children.
+ */
+ pack_aligned_inner(e, en, num);
+ }
}
-void BVH8::pack_aligned_inner(const BVHStackEntry& e,
- const BVHStackEntry *en,
- int num)
+void BVH8::pack_aligned_inner(const BVHStackEntry &e, const BVHStackEntry *en, int num)
{
- BoundBox bounds[8];
- int child[8];
- for(int i = 0; i < num; ++i) {
- bounds[i] = en[i].node->bounds;
- child[i] = en[i].encodeIdx();
- }
- pack_aligned_node(e.idx,
- bounds,
- child,
- e.node->visibility,
- e.node->time_from,
- e.node->time_to,
- num);
+ BoundBox bounds[8];
+ int child[8];
+ for (int i = 0; i < num; ++i) {
+ bounds[i] = en[i].node->bounds;
+ child[i] = en[i].encodeIdx();
+ }
+ pack_aligned_node(
+ e.idx, bounds, child, e.node->visibility, e.node->time_from, e.node->time_to, num);
}
void BVH8::pack_aligned_node(int idx,
@@ -208,66 +196,64 @@ void BVH8::pack_aligned_node(int idx,
const float time_to,
const int num)
{
- float8 data[8];
- memset(data, 0, sizeof(data));
+ float8 data[8];
+ memset(data, 0, sizeof(data));
- data[0].a = __uint_as_float(visibility & ~PATH_RAY_NODE_UNALIGNED);
- data[0].b = time_from;
- data[0].c = time_to;
+ data[0].a = __uint_as_float(visibility & ~PATH_RAY_NODE_UNALIGNED);
+ data[0].b = time_from;
+ data[0].c = time_to;
- for(int i = 0; i < num; i++) {
- float3 bb_min = bounds[i].min;
- float3 bb_max = bounds[i].max;
+ for (int i = 0; i < num; i++) {
+ float3 bb_min = bounds[i].min;
+ float3 bb_max = bounds[i].max;
- data[1][i] = bb_min.x;
- data[2][i] = bb_max.x;
- data[3][i] = bb_min.y;
- data[4][i] = bb_max.y;
- data[5][i] = bb_min.z;
- data[6][i] = bb_max.z;
+ data[1][i] = bb_min.x;
+ data[2][i] = bb_max.x;
+ data[3][i] = bb_min.y;
+ data[4][i] = bb_max.y;
+ data[5][i] = bb_min.z;
+ data[6][i] = bb_max.z;
- data[7][i] = __int_as_float(child[i]);
- }
+ data[7][i] = __int_as_float(child[i]);
+ }
- for(int i = num; i < 8; i++) {
- /* We store BB which would never be recorded as intersection
- * so kernel might safely assume there are always 4 child nodes.
- */
- data[1][i] = FLT_MAX;
- data[2][i] = -FLT_MAX;
+ for (int i = num; i < 8; i++) {
+ /* We store BB which would never be recorded as intersection
+ * so kernel might safely assume there are always 4 child nodes.
+ */
+ data[1][i] = FLT_MAX;
+ data[2][i] = -FLT_MAX;
- data[3][i] = FLT_MAX;
- data[4][i] = -FLT_MAX;
+ data[3][i] = FLT_MAX;
+ data[4][i] = -FLT_MAX;
- data[5][i] = FLT_MAX;
- data[6][i] = -FLT_MAX;
+ data[5][i] = FLT_MAX;
+ data[6][i] = -FLT_MAX;
- data[7][i] = __int_as_float(0);
- }
+ data[7][i] = __int_as_float(0);
+ }
- memcpy(&pack.nodes[idx], data, sizeof(float4)*BVH_ONODE_SIZE);
+ memcpy(&pack.nodes[idx], data, sizeof(float4) * BVH_ONODE_SIZE);
}
-void BVH8::pack_unaligned_inner(const BVHStackEntry& e,
- const BVHStackEntry *en,
- int num)
+void BVH8::pack_unaligned_inner(const BVHStackEntry &e, const BVHStackEntry *en, int num)
{
- Transform aligned_space[8];
- BoundBox bounds[8];
- int child[8];
- for(int i = 0; i < num; ++i) {
- aligned_space[i] = en[i].node->get_aligned_space();
- bounds[i] = en[i].node->bounds;
- child[i] = en[i].encodeIdx();
- }
- pack_unaligned_node(e.idx,
- aligned_space,
- bounds,
- child,
- e.node->visibility,
- e.node->time_from,
- e.node->time_to,
- num);
+ Transform aligned_space[8];
+ BoundBox bounds[8];
+ int child[8];
+ for (int i = 0; i < num; ++i) {
+ aligned_space[i] = en[i].node->get_aligned_space();
+ bounds[i] = en[i].node->bounds;
+ child[i] = en[i].encodeIdx();
+ }
+ pack_unaligned_node(e.idx,
+ aligned_space,
+ bounds,
+ child,
+ e.node->visibility,
+ e.node->time_from,
+ e.node->time_to,
+ num);
}
void BVH8::pack_unaligned_node(int idx,
@@ -279,283 +265,275 @@ void BVH8::pack_unaligned_node(int idx,
const float time_to,
const int num)
{
- float8 data[BVH_UNALIGNED_ONODE_SIZE];
- memset(data, 0, sizeof(data));
+ float8 data[BVH_UNALIGNED_ONODE_SIZE];
+ memset(data, 0, sizeof(data));
- data[0].a = __uint_as_float(visibility | PATH_RAY_NODE_UNALIGNED);
- data[0].b = time_from;
- data[0].c = time_to;
+ data[0].a = __uint_as_float(visibility | PATH_RAY_NODE_UNALIGNED);
+ data[0].b = time_from;
+ data[0].c = time_to;
- for(int i = 0; i < num; i++) {
- Transform space = BVHUnaligned::compute_node_transform(
- bounds[i],
- aligned_space[i]);
+ for (int i = 0; i < num; i++) {
+ Transform space = BVHUnaligned::compute_node_transform(bounds[i], aligned_space[i]);
- data[1][i] = space.x.x;
- data[2][i] = space.x.y;
- data[3][i] = space.x.z;
+ data[1][i] = space.x.x;
+ data[2][i] = space.x.y;
+ data[3][i] = space.x.z;
- data[4][i] = space.y.x;
- data[5][i] = space.y.y;
- data[6][i] = space.y.z;
+ data[4][i] = space.y.x;
+ data[5][i] = space.y.y;
+ data[6][i] = space.y.z;
- data[7][i] = space.z.x;
- data[8][i] = space.z.y;
- data[9][i] = space.z.z;
+ data[7][i] = space.z.x;
+ data[8][i] = space.z.y;
+ data[9][i] = space.z.z;
- data[10][i] = space.x.w;
- data[11][i] = space.y.w;
- data[12][i] = space.z.w;
+ data[10][i] = space.x.w;
+ data[11][i] = space.y.w;
+ data[12][i] = space.z.w;
- data[13][i] = __int_as_float(child[i]);
- }
+ data[13][i] = __int_as_float(child[i]);
+ }
- for(int i = num; i < 8; i++) {
- /* We store BB which would never be recorded as intersection
- * so kernel might safely assume there are always 4 child nodes.
- */
+ for (int i = num; i < 8; i++) {
+ /* We store BB which would never be recorded as intersection
+ * so kernel might safely assume there are always 4 child nodes.
+ */
- data[1][i] = NAN;
- data[2][i] = NAN;
- data[3][i] = NAN;
+ data[1][i] = NAN;
+ data[2][i] = NAN;
+ data[3][i] = NAN;
- data[4][i] = NAN;
- data[5][i] = NAN;
- data[6][i] = NAN;
+ data[4][i] = NAN;
+ data[5][i] = NAN;
+ data[6][i] = NAN;
- data[7][i] = NAN;
- data[8][i] = NAN;
- data[9][i] = NAN;
+ data[7][i] = NAN;
+ data[8][i] = NAN;
+ data[9][i] = NAN;
- data[10][i] = NAN;
- data[11][i] = NAN;
- data[12][i] = NAN;
+ data[10][i] = NAN;
+ data[11][i] = NAN;
+ data[12][i] = NAN;
- data[13][i] = __int_as_float(0);
- }
+ data[13][i] = __int_as_float(0);
+ }
- memcpy(&pack.nodes[idx], data, sizeof(float4)*BVH_UNALIGNED_ONODE_SIZE);
+ memcpy(&pack.nodes[idx], data, sizeof(float4) * BVH_UNALIGNED_ONODE_SIZE);
}
/* Quad SIMD Nodes */
void BVH8::pack_nodes(const BVHNode *root)
{
- /* Calculate size of the arrays required. */
- const size_t num_nodes = root->getSubtreeSize(BVH_STAT_NODE_COUNT);
- const size_t num_leaf_nodes = root->getSubtreeSize(BVH_STAT_LEAF_COUNT);
- assert(num_leaf_nodes <= num_nodes);
- const size_t num_inner_nodes = num_nodes - num_leaf_nodes;
- size_t node_size;
- if(params.use_unaligned_nodes) {
- const size_t num_unaligned_nodes =
- root->getSubtreeSize(BVH_STAT_UNALIGNED_INNER_COUNT);
- node_size = (num_unaligned_nodes * BVH_UNALIGNED_ONODE_SIZE) +
- (num_inner_nodes - num_unaligned_nodes) * BVH_ONODE_SIZE;
- }
- else {
- node_size = num_inner_nodes * BVH_ONODE_SIZE;
- }
- /* Resize arrays. */
- pack.nodes.clear();
- pack.leaf_nodes.clear();
- /* For top level BVH, first merge existing BVH's so we know the offsets. */
- if(params.top_level) {
- pack_instances(node_size, num_leaf_nodes*BVH_ONODE_LEAF_SIZE);
- }
- else {
- pack.nodes.resize(node_size);
- pack.leaf_nodes.resize(num_leaf_nodes*BVH_ONODE_LEAF_SIZE);
- }
-
- int nextNodeIdx = 0, nextLeafNodeIdx = 0;
-
- vector<BVHStackEntry> stack;
- stack.reserve(BVHParams::MAX_DEPTH*2);
- if(root->is_leaf()) {
- stack.push_back(BVHStackEntry(root, nextLeafNodeIdx++));
- }
- else {
- stack.push_back(BVHStackEntry(root, nextNodeIdx));
- nextNodeIdx += root->has_unaligned() ? BVH_UNALIGNED_ONODE_SIZE
- : BVH_ONODE_SIZE;
- }
-
- while(stack.size()) {
- BVHStackEntry e = stack.back();
- stack.pop_back();
-
- if(e.node->is_leaf()) {
- /* leaf node */
- const LeafNode *leaf = reinterpret_cast<const LeafNode*>(e.node);
- pack_leaf(e, leaf);
- }
- else {
- /* Inner node. */
- /* Collect nodes. */
- const BVHNode *children[8];
- int num_children = e.node->num_children();
- /* Push entries on the stack. */
- for(int i = 0; i < num_children; ++i) {
- int idx;
- children[i] = e.node->get_child(i);
- if(children[i]->is_leaf()) {
- idx = nextLeafNodeIdx++;
- }
- else {
- idx = nextNodeIdx;
- nextNodeIdx += children[i]->has_unaligned()
- ? BVH_UNALIGNED_ONODE_SIZE
- : BVH_ONODE_SIZE;
- }
- stack.push_back(BVHStackEntry(children[i], idx));
- }
- /* Set node. */
- pack_inner(e, &stack[stack.size() - num_children], num_children);
- }
- }
-
- assert(node_size == nextNodeIdx);
- /* Root index to start traversal at, to handle case of single leaf node. */
- pack.root_index = (root->is_leaf()) ? -1 : 0;
+ /* Calculate size of the arrays required. */
+ const size_t num_nodes = root->getSubtreeSize(BVH_STAT_NODE_COUNT);
+ const size_t num_leaf_nodes = root->getSubtreeSize(BVH_STAT_LEAF_COUNT);
+ assert(num_leaf_nodes <= num_nodes);
+ const size_t num_inner_nodes = num_nodes - num_leaf_nodes;
+ size_t node_size;
+ if (params.use_unaligned_nodes) {
+ const size_t num_unaligned_nodes = root->getSubtreeSize(BVH_STAT_UNALIGNED_INNER_COUNT);
+ node_size = (num_unaligned_nodes * BVH_UNALIGNED_ONODE_SIZE) +
+ (num_inner_nodes - num_unaligned_nodes) * BVH_ONODE_SIZE;
+ }
+ else {
+ node_size = num_inner_nodes * BVH_ONODE_SIZE;
+ }
+ /* Resize arrays. */
+ pack.nodes.clear();
+ pack.leaf_nodes.clear();
+ /* For top level BVH, first merge existing BVH's so we know the offsets. */
+ if (params.top_level) {
+ pack_instances(node_size, num_leaf_nodes * BVH_ONODE_LEAF_SIZE);
+ }
+ else {
+ pack.nodes.resize(node_size);
+ pack.leaf_nodes.resize(num_leaf_nodes * BVH_ONODE_LEAF_SIZE);
+ }
+
+ int nextNodeIdx = 0, nextLeafNodeIdx = 0;
+
+ vector<BVHStackEntry> stack;
+ stack.reserve(BVHParams::MAX_DEPTH * 2);
+ if (root->is_leaf()) {
+ stack.push_back(BVHStackEntry(root, nextLeafNodeIdx++));
+ }
+ else {
+ stack.push_back(BVHStackEntry(root, nextNodeIdx));
+ nextNodeIdx += root->has_unaligned() ? BVH_UNALIGNED_ONODE_SIZE : BVH_ONODE_SIZE;
+ }
+
+ while (stack.size()) {
+ BVHStackEntry e = stack.back();
+ stack.pop_back();
+
+ if (e.node->is_leaf()) {
+ /* leaf node */
+ const LeafNode *leaf = reinterpret_cast<const LeafNode *>(e.node);
+ pack_leaf(e, leaf);
+ }
+ else {
+ /* Inner node. */
+ /* Collect nodes. */
+ const BVHNode *children[8];
+ int num_children = e.node->num_children();
+ /* Push entries on the stack. */
+ for (int i = 0; i < num_children; ++i) {
+ int idx;
+ children[i] = e.node->get_child(i);
+ if (children[i]->is_leaf()) {
+ idx = nextLeafNodeIdx++;
+ }
+ else {
+ idx = nextNodeIdx;
+ nextNodeIdx += children[i]->has_unaligned() ? BVH_UNALIGNED_ONODE_SIZE : BVH_ONODE_SIZE;
+ }
+ stack.push_back(BVHStackEntry(children[i], idx));
+ }
+ /* Set node. */
+ pack_inner(e, &stack[stack.size() - num_children], num_children);
+ }
+ }
+
+ assert(node_size == nextNodeIdx);
+ /* Root index to start traversal at, to handle case of single leaf node. */
+ pack.root_index = (root->is_leaf()) ? -1 : 0;
}
void BVH8::refit_nodes()
{
- assert(!params.top_level);
+ assert(!params.top_level);
- BoundBox bbox = BoundBox::empty;
- uint visibility = 0;
- refit_node(0, (pack.root_index == -1)? true: false, bbox, visibility);
+ BoundBox bbox = BoundBox::empty;
+ uint visibility = 0;
+ refit_node(0, (pack.root_index == -1) ? true : false, bbox, visibility);
}
-void BVH8::refit_node(int idx, bool leaf, BoundBox& bbox, uint& visibility)
+void BVH8::refit_node(int idx, bool leaf, BoundBox &bbox, uint &visibility)
{
- if(leaf) {
- int4 *data = &pack.leaf_nodes[idx];
- int4 c = data[0];
- /* Refit leaf node. */
- for(int prim = c.x; prim < c.y; prim++) {
- int pidx = pack.prim_index[prim];
- int tob = pack.prim_object[prim];
- Object *ob = objects[tob];
-
- if(pidx == -1) {
- /* Object instance. */
- bbox.grow(ob->bounds);
- }
- else {
- /* Primitives. */
- const Mesh *mesh = ob->mesh;
-
- if(pack.prim_type[prim] & PRIMITIVE_ALL_CURVE) {
- /* Curves. */
- int str_offset = (params.top_level) ? mesh->curve_offset : 0;
- Mesh::Curve curve = mesh->get_curve(pidx - str_offset);
- int k = PRIMITIVE_UNPACK_SEGMENT(pack.prim_type[prim]);
-
- curve.bounds_grow(k, &mesh->curve_keys[0], &mesh->curve_radius[0], bbox);
-
- visibility |= PATH_RAY_CURVE;
-
- /* Motion curves. */
- if(mesh->use_motion_blur) {
- Attribute *attr = mesh->curve_attributes.find(ATTR_STD_MOTION_VERTEX_POSITION);
-
- if(attr) {
- size_t mesh_size = mesh->curve_keys.size();
- size_t steps = mesh->motion_steps - 1;
- float3 *key_steps = attr->data_float3();
-
- for(size_t i = 0; i < steps; i++) {
- curve.bounds_grow(k, key_steps + i*mesh_size, &mesh->curve_radius[0], bbox);
- }
- }
- }
- }
- else {
- /* Triangles. */
- int tri_offset = (params.top_level) ? mesh->tri_offset : 0;
- Mesh::Triangle triangle = mesh->get_triangle(pidx - tri_offset);
- const float3 *vpos = &mesh->verts[0];
-
- triangle.bounds_grow(vpos, bbox);
-
- /* Motion triangles. */
- if(mesh->use_motion_blur) {
- Attribute *attr = mesh->attributes.find(ATTR_STD_MOTION_VERTEX_POSITION);
-
- if(attr) {
- size_t mesh_size = mesh->verts.size();
- size_t steps = mesh->motion_steps - 1;
- float3 *vert_steps = attr->data_float3();
-
- for(size_t i = 0; i < steps; i++) {
- triangle.bounds_grow(vert_steps + i*mesh_size, bbox);
- }
- }
- }
- }
- }
-
- visibility |= ob->visibility;
- }
-
- float4 leaf_data[BVH_ONODE_LEAF_SIZE];
- leaf_data[0].x = __int_as_float(c.x);
- leaf_data[0].y = __int_as_float(c.y);
- leaf_data[0].z = __uint_as_float(visibility);
- leaf_data[0].w = __uint_as_float(c.w);
- memcpy(&pack.leaf_nodes[idx], leaf_data, sizeof(float4)*BVH_ONODE_LEAF_SIZE);
- }
- else {
- float8 *data = (float8*)&pack.nodes[idx];
- bool is_unaligned = (__float_as_uint(data[0].a) & PATH_RAY_NODE_UNALIGNED) != 0;
- /* Refit inner node, set bbox from children. */
- BoundBox child_bbox[8] = { BoundBox::empty, BoundBox::empty,
- BoundBox::empty, BoundBox::empty,
- BoundBox::empty, BoundBox::empty,
- BoundBox::empty, BoundBox::empty };
- int child[8];
- uint child_visibility[8] = { 0 };
- int num_nodes = 0;
-
- for(int i = 0; i < 8; ++i) {
- child[i] = __float_as_int(data[(is_unaligned) ? 13: 7][i]);
-
- if(child[i] != 0) {
- refit_node((child[i] < 0)? -child[i]-1: child[i], (child[i] < 0),
- child_bbox[i], child_visibility[i]);
- ++num_nodes;
- bbox.grow(child_bbox[i]);
- visibility |= child_visibility[i];
- }
- }
-
- if(is_unaligned) {
- Transform aligned_space[8] = { transform_identity(), transform_identity(),
- transform_identity(), transform_identity(),
- transform_identity(), transform_identity(),
- transform_identity(), transform_identity()};
- pack_unaligned_node(idx,
- aligned_space,
- child_bbox,
- child,
- visibility,
- 0.0f,
- 1.0f,
- num_nodes);
- }
- else {
- pack_aligned_node(idx,
- child_bbox,
- child,
- visibility,
- 0.0f,
- 1.0f,
- num_nodes);
- }
- }
+ if (leaf) {
+ int4 *data = &pack.leaf_nodes[idx];
+ int4 c = data[0];
+ /* Refit leaf node. */
+ for (int prim = c.x; prim < c.y; prim++) {
+ int pidx = pack.prim_index[prim];
+ int tob = pack.prim_object[prim];
+ Object *ob = objects[tob];
+
+ if (pidx == -1) {
+ /* Object instance. */
+ bbox.grow(ob->bounds);
+ }
+ else {
+ /* Primitives. */
+ const Mesh *mesh = ob->mesh;
+
+ if (pack.prim_type[prim] & PRIMITIVE_ALL_CURVE) {
+ /* Curves. */
+ int str_offset = (params.top_level) ? mesh->curve_offset : 0;
+ Mesh::Curve curve = mesh->get_curve(pidx - str_offset);
+ int k = PRIMITIVE_UNPACK_SEGMENT(pack.prim_type[prim]);
+
+ curve.bounds_grow(k, &mesh->curve_keys[0], &mesh->curve_radius[0], bbox);
+
+ visibility |= PATH_RAY_CURVE;
+
+ /* Motion curves. */
+ if (mesh->use_motion_blur) {
+ Attribute *attr = mesh->curve_attributes.find(ATTR_STD_MOTION_VERTEX_POSITION);
+
+ if (attr) {
+ size_t mesh_size = mesh->curve_keys.size();
+ size_t steps = mesh->motion_steps - 1;
+ float3 *key_steps = attr->data_float3();
+
+ for (size_t i = 0; i < steps; i++) {
+ curve.bounds_grow(k, key_steps + i * mesh_size, &mesh->curve_radius[0], bbox);
+ }
+ }
+ }
+ }
+ else {
+ /* Triangles. */
+ int tri_offset = (params.top_level) ? mesh->tri_offset : 0;
+ Mesh::Triangle triangle = mesh->get_triangle(pidx - tri_offset);
+ const float3 *vpos = &mesh->verts[0];
+
+ triangle.bounds_grow(vpos, bbox);
+
+ /* Motion triangles. */
+ if (mesh->use_motion_blur) {
+ Attribute *attr = mesh->attributes.find(ATTR_STD_MOTION_VERTEX_POSITION);
+
+ if (attr) {
+ size_t mesh_size = mesh->verts.size();
+ size_t steps = mesh->motion_steps - 1;
+ float3 *vert_steps = attr->data_float3();
+
+ for (size_t i = 0; i < steps; i++) {
+ triangle.bounds_grow(vert_steps + i * mesh_size, bbox);
+ }
+ }
+ }
+ }
+ }
+
+ visibility |= ob->visibility;
+ }
+
+ float4 leaf_data[BVH_ONODE_LEAF_SIZE];
+ leaf_data[0].x = __int_as_float(c.x);
+ leaf_data[0].y = __int_as_float(c.y);
+ leaf_data[0].z = __uint_as_float(visibility);
+ leaf_data[0].w = __uint_as_float(c.w);
+ memcpy(&pack.leaf_nodes[idx], leaf_data, sizeof(float4) * BVH_ONODE_LEAF_SIZE);
+ }
+ else {
+ float8 *data = (float8 *)&pack.nodes[idx];
+ bool is_unaligned = (__float_as_uint(data[0].a) & PATH_RAY_NODE_UNALIGNED) != 0;
+ /* Refit inner node, set bbox from children. */
+ BoundBox child_bbox[8] = {BoundBox::empty,
+ BoundBox::empty,
+ BoundBox::empty,
+ BoundBox::empty,
+ BoundBox::empty,
+ BoundBox::empty,
+ BoundBox::empty,
+ BoundBox::empty};
+ int child[8];
+ uint child_visibility[8] = {0};
+ int num_nodes = 0;
+
+ for (int i = 0; i < 8; ++i) {
+ child[i] = __float_as_int(data[(is_unaligned) ? 13 : 7][i]);
+
+ if (child[i] != 0) {
+ refit_node((child[i] < 0) ? -child[i] - 1 : child[i],
+ (child[i] < 0),
+ child_bbox[i],
+ child_visibility[i]);
+ ++num_nodes;
+ bbox.grow(child_bbox[i]);
+ visibility |= child_visibility[i];
+ }
+ }
+
+ if (is_unaligned) {
+ Transform aligned_space[8] = {transform_identity(),
+ transform_identity(),
+ transform_identity(),
+ transform_identity(),
+ transform_identity(),
+ transform_identity(),
+ transform_identity(),
+ transform_identity()};
+ pack_unaligned_node(
+ idx, aligned_space, child_bbox, child, visibility, 0.0f, 1.0f, num_nodes);
+ }
+ else {
+ pack_aligned_node(idx, child_bbox, child, visibility, 0.0f, 1.0f, num_nodes);
+ }
+ }
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/bvh/bvh8.h b/intern/cycles/bvh/bvh8.h
index 277e2f2d653..fc07eadcada 100644
--- a/intern/cycles/bvh/bvh8.h
+++ b/intern/cycles/bvh/bvh8.h
@@ -45,8 +45,8 @@ class LeafNode;
class Object;
class Progress;
-#define BVH_ONODE_SIZE 16
-#define BVH_ONODE_LEAF_SIZE 1
+#define BVH_ONODE_SIZE 16
+#define BVH_ONODE_LEAF_SIZE 1
#define BVH_UNALIGNED_ONODE_SIZE 28
/* BVH8
@@ -54,48 +54,44 @@ class Progress;
* Octo BVH, with each node having eight children, to use with SIMD instructions.
*/
class BVH8 : public BVH {
-protected:
- /* constructor */
- friend class BVH;
- BVH8(const BVHParams& params, const vector<Object*>& objects);
+ protected:
+ /* constructor */
+ friend class BVH;
+ BVH8(const BVHParams &params, const vector<Object *> &objects);
- /* Building process. */
- virtual BVHNode *widen_children_nodes(const BVHNode *root) override;
+ /* Building process. */
+ virtual BVHNode *widen_children_nodes(const BVHNode *root) override;
- /* pack */
- void pack_nodes(const BVHNode *root) override;
+ /* pack */
+ void pack_nodes(const BVHNode *root) override;
- void pack_leaf(const BVHStackEntry& e, const LeafNode *leaf);
- void pack_inner(const BVHStackEntry& e, const BVHStackEntry *en, int num);
+ void pack_leaf(const BVHStackEntry &e, const LeafNode *leaf);
+ void pack_inner(const BVHStackEntry &e, const BVHStackEntry *en, int num);
- void pack_aligned_inner(const BVHStackEntry& e,
- const BVHStackEntry *en,
- int num);
- void pack_aligned_node(int idx,
- const BoundBox *bounds,
- const int *child,
- const uint visibility,
- const float time_from,
- const float time_to,
- const int num);
+ void pack_aligned_inner(const BVHStackEntry &e, const BVHStackEntry *en, int num);
+ void pack_aligned_node(int idx,
+ const BoundBox *bounds,
+ const int *child,
+ const uint visibility,
+ const float time_from,
+ const float time_to,
+ const int num);
- void pack_unaligned_inner(const BVHStackEntry& e,
- const BVHStackEntry *en,
- int num);
- void pack_unaligned_node(int idx,
- const Transform *aligned_space,
- const BoundBox *bounds,
- const int *child,
- const uint visibility,
- const float time_from,
- const float time_to,
- const int num);
+ void pack_unaligned_inner(const BVHStackEntry &e, const BVHStackEntry *en, int num);
+ void pack_unaligned_node(int idx,
+ const Transform *aligned_space,
+ const BoundBox *bounds,
+ const int *child,
+ const uint visibility,
+ const float time_from,
+ const float time_to,
+ const int num);
- /* refit */
- void refit_nodes() override;
- void refit_node(int idx, bool leaf, BoundBox& bbox, uint& visibility);
+ /* refit */
+ void refit_nodes() override;
+ void refit_node(int idx, bool leaf, BoundBox &bbox, uint &visibility);
};
CCL_NAMESPACE_END
-#endif /* __BVH8_H__ */
+#endif /* __BVH8_H__ */
diff --git a/intern/cycles/bvh/bvh_binning.cpp b/intern/cycles/bvh/bvh_binning.cpp
index f574f31b358..d51143c578e 100644
--- a/intern/cycles/bvh/bvh_binning.cpp
+++ b/intern/cycles/bvh/bvh_binning.cpp
@@ -29,225 +29,265 @@ CCL_NAMESPACE_BEGIN
/* SSE replacements */
-__forceinline void prefetch_L1 (const void* /*ptr*/) { }
-__forceinline void prefetch_L2 (const void* /*ptr*/) { }
-__forceinline void prefetch_L3 (const void* /*ptr*/) { }
-__forceinline void prefetch_NTA(const void* /*ptr*/) { }
+__forceinline void prefetch_L1(const void * /*ptr*/)
+{
+}
+__forceinline void prefetch_L2(const void * /*ptr*/)
+{
+}
+__forceinline void prefetch_L3(const void * /*ptr*/)
+{
+}
+__forceinline void prefetch_NTA(const void * /*ptr*/)
+{
+}
-template<size_t src> __forceinline float extract(const int4& b)
-{ return b[src]; }
-template<size_t dst> __forceinline const float4 insert(const float4& a, const float b)
-{ float4 r = a; r[dst] = b; return r; }
+template<size_t src> __forceinline float extract(const int4 &b)
+{
+ return b[src];
+}
+template<size_t dst> __forceinline const float4 insert(const float4 &a, const float b)
+{
+ float4 r = a;
+ r[dst] = b;
+ return r;
+}
-__forceinline int get_best_dimension(const float4& bestSAH)
+__forceinline int get_best_dimension(const float4 &bestSAH)
{
- // return (int)__bsf(movemask(reduce_min(bestSAH) == bestSAH));
+ // return (int)__bsf(movemask(reduce_min(bestSAH) == bestSAH));
- float minSAH = min(bestSAH.x, min(bestSAH.y, bestSAH.z));
+ float minSAH = min(bestSAH.x, min(bestSAH.y, bestSAH.z));
- if(bestSAH.x == minSAH) return 0;
- else if(bestSAH.y == minSAH) return 1;
- else return 2;
+ if (bestSAH.x == minSAH)
+ return 0;
+ else if (bestSAH.y == minSAH)
+ return 1;
+ else
+ return 2;
}
/* BVH Object Binning */
-BVHObjectBinning::BVHObjectBinning(const BVHRange& job,
+BVHObjectBinning::BVHObjectBinning(const BVHRange &job,
BVHReference *prims,
const BVHUnaligned *unaligned_heuristic,
const Transform *aligned_space)
-: BVHRange(job),
- splitSAH(FLT_MAX),
- dim(0),
- pos(0),
- unaligned_heuristic_(unaligned_heuristic),
- aligned_space_(aligned_space)
+ : BVHRange(job),
+ splitSAH(FLT_MAX),
+ dim(0),
+ pos(0),
+ unaligned_heuristic_(unaligned_heuristic),
+ aligned_space_(aligned_space)
{
- if(aligned_space_ == NULL) {
- bounds_ = bounds();
- cent_bounds_ = cent_bounds();
- }
- else {
- /* TODO(sergey): With some additional storage we can avoid
- * need in re-calculating this.
- */
- bounds_ = unaligned_heuristic->compute_aligned_boundbox(
- *this,
- prims,
- *aligned_space,
- &cent_bounds_);
- }
-
- /* compute number of bins to use and precompute scaling factor for binning */
- num_bins = min(size_t(MAX_BINS), size_t(4.0f + 0.05f*size()));
- scale = rcp(cent_bounds_.size()) * make_float3((float)num_bins);
-
- /* initialize binning counter and bounds */
- BoundBox bin_bounds[MAX_BINS][4]; /* bounds for every bin in every dimension */
- int4 bin_count[MAX_BINS]; /* number of primitives mapped to bin */
-
- for(size_t i = 0; i < num_bins; i++) {
- bin_count[i] = make_int4(0);
- bin_bounds[i][0] = bin_bounds[i][1] = bin_bounds[i][2] = BoundBox::empty;
- }
-
- /* map geometry to bins, unrolled once */
- {
- ssize_t i;
-
- for(i = 0; i < ssize_t(size()) - 1; i += 2) {
- prefetch_L2(&prims[start() + i + 8]);
-
- /* map even and odd primitive to bin */
- const BVHReference& prim0 = prims[start() + i + 0];
- const BVHReference& prim1 = prims[start() + i + 1];
-
- BoundBox bounds0 = get_prim_bounds(prim0);
- BoundBox bounds1 = get_prim_bounds(prim1);
-
- int4 bin0 = get_bin(bounds0);
- int4 bin1 = get_bin(bounds1);
-
- /* increase bounds for bins for even primitive */
- int b00 = (int)extract<0>(bin0); bin_count[b00][0]++; bin_bounds[b00][0].grow(bounds0);
- int b01 = (int)extract<1>(bin0); bin_count[b01][1]++; bin_bounds[b01][1].grow(bounds0);
- int b02 = (int)extract<2>(bin0); bin_count[b02][2]++; bin_bounds[b02][2].grow(bounds0);
-
- /* increase bounds of bins for odd primitive */
- int b10 = (int)extract<0>(bin1); bin_count[b10][0]++; bin_bounds[b10][0].grow(bounds1);
- int b11 = (int)extract<1>(bin1); bin_count[b11][1]++; bin_bounds[b11][1].grow(bounds1);
- int b12 = (int)extract<2>(bin1); bin_count[b12][2]++; bin_bounds[b12][2].grow(bounds1);
- }
-
- /* for uneven number of primitives */
- if(i < ssize_t(size())) {
- /* map primitive to bin */
- const BVHReference& prim0 = prims[start() + i];
- BoundBox bounds0 = get_prim_bounds(prim0);
- int4 bin0 = get_bin(bounds0);
-
- /* increase bounds of bins */
- int b00 = (int)extract<0>(bin0); bin_count[b00][0]++; bin_bounds[b00][0].grow(bounds0);
- int b01 = (int)extract<1>(bin0); bin_count[b01][1]++; bin_bounds[b01][1].grow(bounds0);
- int b02 = (int)extract<2>(bin0); bin_count[b02][2]++; bin_bounds[b02][2].grow(bounds0);
- }
- }
-
- /* sweep from right to left and compute parallel prefix of merged bounds */
- float4 r_area[MAX_BINS]; /* area of bounds of primitives on the right */
- float4 r_count[MAX_BINS]; /* number of primitives on the right */
- int4 count = make_int4(0);
-
- BoundBox bx = BoundBox::empty;
- BoundBox by = BoundBox::empty;
- BoundBox bz = BoundBox::empty;
-
- for(size_t i = num_bins - 1; i > 0; i--) {
- count = count + bin_count[i];
- r_count[i] = blocks(count);
-
- bx = merge(bx,bin_bounds[i][0]); r_area[i][0] = bx.half_area();
- by = merge(by,bin_bounds[i][1]); r_area[i][1] = by.half_area();
- bz = merge(bz,bin_bounds[i][2]); r_area[i][2] = bz.half_area();
- r_area[i][3] = r_area[i][2];
- }
-
- /* sweep from left to right and compute SAH */
- int4 ii = make_int4(1);
- float4 bestSAH = make_float4(FLT_MAX);
- int4 bestSplit = make_int4(-1);
-
- count = make_int4(0);
-
- bx = BoundBox::empty;
- by = BoundBox::empty;
- bz = BoundBox::empty;
-
- for(size_t i = 1; i < num_bins; i++, ii += make_int4(1)) {
- count = count + bin_count[i-1];
-
- bx = merge(bx,bin_bounds[i-1][0]); float Ax = bx.half_area();
- by = merge(by,bin_bounds[i-1][1]); float Ay = by.half_area();
- bz = merge(bz,bin_bounds[i-1][2]); float Az = bz.half_area();
-
- float4 lCount = blocks(count);
- float4 lArea = make_float4(Ax,Ay,Az,Az);
- float4 sah = lArea*lCount + r_area[i]*r_count[i];
-
- bestSplit = select(sah < bestSAH,ii,bestSplit);
- bestSAH = min(sah,bestSAH);
- }
-
- int4 mask = float3_to_float4(cent_bounds_.size()) <= make_float4(0.0f);
- bestSAH = insert<3>(select(mask, make_float4(FLT_MAX), bestSAH), FLT_MAX);
-
- /* find best dimension */
- dim = get_best_dimension(bestSAH);
- splitSAH = bestSAH[dim];
- pos = bestSplit[dim];
- leafSAH = bounds_.half_area() * blocks(size());
+ if (aligned_space_ == NULL) {
+ bounds_ = bounds();
+ cent_bounds_ = cent_bounds();
+ }
+ else {
+ /* TODO(sergey): With some additional storage we can avoid
+ * need in re-calculating this.
+ */
+ bounds_ = unaligned_heuristic->compute_aligned_boundbox(
+ *this, prims, *aligned_space, &cent_bounds_);
+ }
+
+ /* compute number of bins to use and precompute scaling factor for binning */
+ num_bins = min(size_t(MAX_BINS), size_t(4.0f + 0.05f * size()));
+ scale = rcp(cent_bounds_.size()) * make_float3((float)num_bins);
+
+ /* initialize binning counter and bounds */
+ BoundBox bin_bounds[MAX_BINS][4]; /* bounds for every bin in every dimension */
+ int4 bin_count[MAX_BINS]; /* number of primitives mapped to bin */
+
+ for (size_t i = 0; i < num_bins; i++) {
+ bin_count[i] = make_int4(0);
+ bin_bounds[i][0] = bin_bounds[i][1] = bin_bounds[i][2] = BoundBox::empty;
+ }
+
+ /* map geometry to bins, unrolled once */
+ {
+ ssize_t i;
+
+ for (i = 0; i < ssize_t(size()) - 1; i += 2) {
+ prefetch_L2(&prims[start() + i + 8]);
+
+ /* map even and odd primitive to bin */
+ const BVHReference &prim0 = prims[start() + i + 0];
+ const BVHReference &prim1 = prims[start() + i + 1];
+
+ BoundBox bounds0 = get_prim_bounds(prim0);
+ BoundBox bounds1 = get_prim_bounds(prim1);
+
+ int4 bin0 = get_bin(bounds0);
+ int4 bin1 = get_bin(bounds1);
+
+ /* increase bounds for bins for even primitive */
+ int b00 = (int)extract<0>(bin0);
+ bin_count[b00][0]++;
+ bin_bounds[b00][0].grow(bounds0);
+ int b01 = (int)extract<1>(bin0);
+ bin_count[b01][1]++;
+ bin_bounds[b01][1].grow(bounds0);
+ int b02 = (int)extract<2>(bin0);
+ bin_count[b02][2]++;
+ bin_bounds[b02][2].grow(bounds0);
+
+ /* increase bounds of bins for odd primitive */
+ int b10 = (int)extract<0>(bin1);
+ bin_count[b10][0]++;
+ bin_bounds[b10][0].grow(bounds1);
+ int b11 = (int)extract<1>(bin1);
+ bin_count[b11][1]++;
+ bin_bounds[b11][1].grow(bounds1);
+ int b12 = (int)extract<2>(bin1);
+ bin_count[b12][2]++;
+ bin_bounds[b12][2].grow(bounds1);
+ }
+
+ /* for uneven number of primitives */
+ if (i < ssize_t(size())) {
+ /* map primitive to bin */
+ const BVHReference &prim0 = prims[start() + i];
+ BoundBox bounds0 = get_prim_bounds(prim0);
+ int4 bin0 = get_bin(bounds0);
+
+ /* increase bounds of bins */
+ int b00 = (int)extract<0>(bin0);
+ bin_count[b00][0]++;
+ bin_bounds[b00][0].grow(bounds0);
+ int b01 = (int)extract<1>(bin0);
+ bin_count[b01][1]++;
+ bin_bounds[b01][1].grow(bounds0);
+ int b02 = (int)extract<2>(bin0);
+ bin_count[b02][2]++;
+ bin_bounds[b02][2].grow(bounds0);
+ }
+ }
+
+ /* sweep from right to left and compute parallel prefix of merged bounds */
+ float4 r_area[MAX_BINS]; /* area of bounds of primitives on the right */
+ float4 r_count[MAX_BINS]; /* number of primitives on the right */
+ int4 count = make_int4(0);
+
+ BoundBox bx = BoundBox::empty;
+ BoundBox by = BoundBox::empty;
+ BoundBox bz = BoundBox::empty;
+
+ for (size_t i = num_bins - 1; i > 0; i--) {
+ count = count + bin_count[i];
+ r_count[i] = blocks(count);
+
+ bx = merge(bx, bin_bounds[i][0]);
+ r_area[i][0] = bx.half_area();
+ by = merge(by, bin_bounds[i][1]);
+ r_area[i][1] = by.half_area();
+ bz = merge(bz, bin_bounds[i][2]);
+ r_area[i][2] = bz.half_area();
+ r_area[i][3] = r_area[i][2];
+ }
+
+ /* sweep from left to right and compute SAH */
+ int4 ii = make_int4(1);
+ float4 bestSAH = make_float4(FLT_MAX);
+ int4 bestSplit = make_int4(-1);
+
+ count = make_int4(0);
+
+ bx = BoundBox::empty;
+ by = BoundBox::empty;
+ bz = BoundBox::empty;
+
+ for (size_t i = 1; i < num_bins; i++, ii += make_int4(1)) {
+ count = count + bin_count[i - 1];
+
+ bx = merge(bx, bin_bounds[i - 1][0]);
+ float Ax = bx.half_area();
+ by = merge(by, bin_bounds[i - 1][1]);
+ float Ay = by.half_area();
+ bz = merge(bz, bin_bounds[i - 1][2]);
+ float Az = bz.half_area();
+
+ float4 lCount = blocks(count);
+ float4 lArea = make_float4(Ax, Ay, Az, Az);
+ float4 sah = lArea * lCount + r_area[i] * r_count[i];
+
+ bestSplit = select(sah < bestSAH, ii, bestSplit);
+ bestSAH = min(sah, bestSAH);
+ }
+
+ int4 mask = float3_to_float4(cent_bounds_.size()) <= make_float4(0.0f);
+ bestSAH = insert<3>(select(mask, make_float4(FLT_MAX), bestSAH), FLT_MAX);
+
+ /* find best dimension */
+ dim = get_best_dimension(bestSAH);
+ splitSAH = bestSAH[dim];
+ pos = bestSplit[dim];
+ leafSAH = bounds_.half_area() * blocks(size());
}
-void BVHObjectBinning::split(BVHReference* prims,
- BVHObjectBinning& left_o,
- BVHObjectBinning& right_o) const
+void BVHObjectBinning::split(BVHReference *prims,
+ BVHObjectBinning &left_o,
+ BVHObjectBinning &right_o) const
{
- size_t N = size();
-
- BoundBox lgeom_bounds = BoundBox::empty;
- BoundBox rgeom_bounds = BoundBox::empty;
- BoundBox lcent_bounds = BoundBox::empty;
- BoundBox rcent_bounds = BoundBox::empty;
-
- ssize_t l = 0, r = N-1;
-
- while(l <= r) {
- prefetch_L2(&prims[start() + l + 8]);
- prefetch_L2(&prims[start() + r - 8]);
-
- BVHReference prim = prims[start() + l];
- BoundBox unaligned_bounds = get_prim_bounds(prim);
- float3 unaligned_center = unaligned_bounds.center2();
- float3 center = prim.bounds().center2();
-
- if(get_bin(unaligned_center)[dim] < pos) {
- lgeom_bounds.grow(prim.bounds());
- lcent_bounds.grow(center);
- l++;
- }
- else {
- rgeom_bounds.grow(prim.bounds());
- rcent_bounds.grow(center);
- swap(prims[start()+l],prims[start()+r]);
- r--;
- }
- }
- /* finish */
- if(l != 0 && N-1-r != 0) {
- right_o = BVHObjectBinning(BVHRange(rgeom_bounds, rcent_bounds, start() + l, N-1-r), prims);
- left_o = BVHObjectBinning(BVHRange(lgeom_bounds, lcent_bounds, start(), l), prims);
- return;
- }
-
- /* object medium split if we did not make progress, can happen when all
- * primitives have same centroid */
- lgeom_bounds = BoundBox::empty;
- rgeom_bounds = BoundBox::empty;
- lcent_bounds = BoundBox::empty;
- rcent_bounds = BoundBox::empty;
-
- for(size_t i = 0; i < N/2; i++) {
- lgeom_bounds.grow(prims[start()+i].bounds());
- lcent_bounds.grow(prims[start()+i].bounds().center2());
- }
-
- for(size_t i = N/2; i < N; i++) {
- rgeom_bounds.grow(prims[start()+i].bounds());
- rcent_bounds.grow(prims[start()+i].bounds().center2());
- }
-
- right_o = BVHObjectBinning(BVHRange(rgeom_bounds, rcent_bounds, start() + N/2, N/2 + N%2), prims);
- left_o = BVHObjectBinning(BVHRange(lgeom_bounds, lcent_bounds, start(), N/2), prims);
+ size_t N = size();
+
+ BoundBox lgeom_bounds = BoundBox::empty;
+ BoundBox rgeom_bounds = BoundBox::empty;
+ BoundBox lcent_bounds = BoundBox::empty;
+ BoundBox rcent_bounds = BoundBox::empty;
+
+ ssize_t l = 0, r = N - 1;
+
+ while (l <= r) {
+ prefetch_L2(&prims[start() + l + 8]);
+ prefetch_L2(&prims[start() + r - 8]);
+
+ BVHReference prim = prims[start() + l];
+ BoundBox unaligned_bounds = get_prim_bounds(prim);
+ float3 unaligned_center = unaligned_bounds.center2();
+ float3 center = prim.bounds().center2();
+
+ if (get_bin(unaligned_center)[dim] < pos) {
+ lgeom_bounds.grow(prim.bounds());
+ lcent_bounds.grow(center);
+ l++;
+ }
+ else {
+ rgeom_bounds.grow(prim.bounds());
+ rcent_bounds.grow(center);
+ swap(prims[start() + l], prims[start() + r]);
+ r--;
+ }
+ }
+ /* finish */
+ if (l != 0 && N - 1 - r != 0) {
+ right_o = BVHObjectBinning(BVHRange(rgeom_bounds, rcent_bounds, start() + l, N - 1 - r),
+ prims);
+ left_o = BVHObjectBinning(BVHRange(lgeom_bounds, lcent_bounds, start(), l), prims);
+ return;
+ }
+
+ /* object medium split if we did not make progress, can happen when all
+ * primitives have same centroid */
+ lgeom_bounds = BoundBox::empty;
+ rgeom_bounds = BoundBox::empty;
+ lcent_bounds = BoundBox::empty;
+ rcent_bounds = BoundBox::empty;
+
+ for (size_t i = 0; i < N / 2; i++) {
+ lgeom_bounds.grow(prims[start() + i].bounds());
+ lcent_bounds.grow(prims[start() + i].bounds().center2());
+ }
+
+ for (size_t i = N / 2; i < N; i++) {
+ rgeom_bounds.grow(prims[start() + i].bounds());
+ rcent_bounds.grow(prims[start() + i].bounds().center2());
+ }
+
+ right_o = BVHObjectBinning(BVHRange(rgeom_bounds, rcent_bounds, start() + N / 2, N / 2 + N % 2),
+ prims);
+ left_o = BVHObjectBinning(BVHRange(lgeom_bounds, lcent_bounds, start(), N / 2), prims);
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/bvh/bvh_binning.h b/intern/cycles/bvh/bvh_binning.h
index c2e259b1696..ae6dba2805d 100644
--- a/intern/cycles/bvh/bvh_binning.h
+++ b/intern/cycles/bvh/bvh_binning.h
@@ -34,81 +34,82 @@ class BVHBuild;
* location to different sets. The SAH is evaluated by computing the number of
* blocks occupied by the primitives in the partitions. */
-class BVHObjectBinning : public BVHRange
-{
-public:
- __forceinline BVHObjectBinning() : leafSAH(FLT_MAX) {}
-
- BVHObjectBinning(const BVHRange& job,
- BVHReference *prims,
- const BVHUnaligned *unaligned_heuristic = NULL,
- const Transform *aligned_space = NULL);
-
- void split(BVHReference *prims,
- BVHObjectBinning& left_o,
- BVHObjectBinning& right_o) const;
-
- __forceinline const BoundBox& unaligned_bounds() { return bounds_; }
-
- float splitSAH; /* SAH cost of the best split */
- float leafSAH; /* SAH cost of creating a leaf */
-
-protected:
- int dim; /* best split dimension */
- int pos; /* best split position */
- size_t num_bins; /* actual number of bins to use */
- float3 scale; /* scaling factor to compute bin */
-
- /* Effective bounds and centroid bounds. */
- BoundBox bounds_;
- BoundBox cent_bounds_;
-
- const BVHUnaligned *unaligned_heuristic_;
- const Transform *aligned_space_;
-
- enum { MAX_BINS = 32 };
- enum { LOG_BLOCK_SIZE = 2 };
-
- /* computes the bin numbers for each dimension for a box. */
- __forceinline int4 get_bin(const BoundBox& box) const
- {
- int4 a = make_int4((box.center2() - cent_bounds_.min)*scale - make_float3(0.5f));
- int4 mn = make_int4(0);
- int4 mx = make_int4((int)num_bins-1);
-
- return clamp(a, mn, mx);
- }
-
- /* computes the bin numbers for each dimension for a point. */
- __forceinline int4 get_bin(const float3& c) const
- {
- return make_int4((c - cent_bounds_.min)*scale - make_float3(0.5f));
- }
-
- /* compute the number of blocks occupied for each dimension. */
- __forceinline float4 blocks(const int4& a) const
- {
- return make_float4((a + make_int4((1 << LOG_BLOCK_SIZE)-1)) >> LOG_BLOCK_SIZE);
- }
-
- /* compute the number of blocks occupied in one dimension. */
- __forceinline int blocks(size_t a) const
- {
- return (int)((a+((1LL << LOG_BLOCK_SIZE)-1)) >> LOG_BLOCK_SIZE);
- }
-
- __forceinline BoundBox get_prim_bounds(const BVHReference& prim) const
- {
- if(aligned_space_ == NULL) {
- return prim.bounds();
- }
- else {
- return unaligned_heuristic_->compute_aligned_prim_boundbox(
- prim, *aligned_space_);
- }
- }
+class BVHObjectBinning : public BVHRange {
+ public:
+ __forceinline BVHObjectBinning() : leafSAH(FLT_MAX)
+ {
+ }
+
+ BVHObjectBinning(const BVHRange &job,
+ BVHReference *prims,
+ const BVHUnaligned *unaligned_heuristic = NULL,
+ const Transform *aligned_space = NULL);
+
+ void split(BVHReference *prims, BVHObjectBinning &left_o, BVHObjectBinning &right_o) const;
+
+ __forceinline const BoundBox &unaligned_bounds()
+ {
+ return bounds_;
+ }
+
+ float splitSAH; /* SAH cost of the best split */
+ float leafSAH; /* SAH cost of creating a leaf */
+
+ protected:
+ int dim; /* best split dimension */
+ int pos; /* best split position */
+ size_t num_bins; /* actual number of bins to use */
+ float3 scale; /* scaling factor to compute bin */
+
+ /* Effective bounds and centroid bounds. */
+ BoundBox bounds_;
+ BoundBox cent_bounds_;
+
+ const BVHUnaligned *unaligned_heuristic_;
+ const Transform *aligned_space_;
+
+ enum { MAX_BINS = 32 };
+ enum { LOG_BLOCK_SIZE = 2 };
+
+ /* computes the bin numbers for each dimension for a box. */
+ __forceinline int4 get_bin(const BoundBox &box) const
+ {
+ int4 a = make_int4((box.center2() - cent_bounds_.min) * scale - make_float3(0.5f));
+ int4 mn = make_int4(0);
+ int4 mx = make_int4((int)num_bins - 1);
+
+ return clamp(a, mn, mx);
+ }
+
+ /* computes the bin numbers for each dimension for a point. */
+ __forceinline int4 get_bin(const float3 &c) const
+ {
+ return make_int4((c - cent_bounds_.min) * scale - make_float3(0.5f));
+ }
+
+ /* compute the number of blocks occupied for each dimension. */
+ __forceinline float4 blocks(const int4 &a) const
+ {
+ return make_float4((a + make_int4((1 << LOG_BLOCK_SIZE) - 1)) >> LOG_BLOCK_SIZE);
+ }
+
+ /* compute the number of blocks occupied in one dimension. */
+ __forceinline int blocks(size_t a) const
+ {
+ return (int)((a + ((1LL << LOG_BLOCK_SIZE) - 1)) >> LOG_BLOCK_SIZE);
+ }
+
+ __forceinline BoundBox get_prim_bounds(const BVHReference &prim) const
+ {
+ if (aligned_space_ == NULL) {
+ return prim.bounds();
+ }
+ else {
+ return unaligned_heuristic_->compute_aligned_prim_boundbox(prim, *aligned_space_);
+ }
+ }
};
CCL_NAMESPACE_END
-#endif /* __BVH_BINNING_H__ */
+#endif /* __BVH_BINNING_H__ */
diff --git a/intern/cycles/bvh/bvh_build.cpp b/intern/cycles/bvh/bvh_build.cpp
index c0b3d683e37..1d9b006e8cb 100644
--- a/intern/cycles/bvh/bvh_build.cpp
+++ b/intern/cycles/bvh/bvh_build.cpp
@@ -41,72 +41,65 @@ CCL_NAMESPACE_BEGIN
/* BVH Build Task */
class BVHBuildTask : public Task {
-public:
- BVHBuildTask(BVHBuild *build,
- InnerNode *node,
- int child,
- const BVHObjectBinning& range,
- int level)
- : range_(range)
- {
- run = function_bind(&BVHBuild::thread_build_node,
- build,
- node,
- child,
- &range_,
- level);
- }
-private:
- BVHObjectBinning range_;
+ public:
+ BVHBuildTask(
+ BVHBuild *build, InnerNode *node, int child, const BVHObjectBinning &range, int level)
+ : range_(range)
+ {
+ run = function_bind(&BVHBuild::thread_build_node, build, node, child, &range_, level);
+ }
+
+ private:
+ BVHObjectBinning range_;
};
class BVHSpatialSplitBuildTask : public Task {
-public:
- BVHSpatialSplitBuildTask(BVHBuild *build,
- InnerNode *node,
- int child,
- const BVHRange& range,
- const vector<BVHReference>& references,
- int level)
- : range_(range),
- references_(references.begin() + range.start(),
- references.begin() + range.end())
- {
- range_.set_start(0);
- run = function_bind(&BVHBuild::thread_build_spatial_split_node,
- build,
- node,
- child,
- &range_,
- &references_,
- level,
- _1);
- }
-private:
- BVHRange range_;
- vector<BVHReference> references_;
+ public:
+ BVHSpatialSplitBuildTask(BVHBuild *build,
+ InnerNode *node,
+ int child,
+ const BVHRange &range,
+ const vector<BVHReference> &references,
+ int level)
+ : range_(range),
+ references_(references.begin() + range.start(), references.begin() + range.end())
+ {
+ range_.set_start(0);
+ run = function_bind(&BVHBuild::thread_build_spatial_split_node,
+ build,
+ node,
+ child,
+ &range_,
+ &references_,
+ level,
+ _1);
+ }
+
+ private:
+ BVHRange range_;
+ vector<BVHReference> references_;
};
/* Constructor / Destructor */
-BVHBuild::BVHBuild(const vector<Object*>& objects_,
- array<int>& prim_type_,
- array<int>& prim_index_,
- array<int>& prim_object_,
- array<float2>& prim_time_,
- const BVHParams& params_,
- Progress& progress_)
- : objects(objects_),
- prim_type(prim_type_),
- prim_index(prim_index_),
- prim_object(prim_object_),
- prim_time(prim_time_),
- params(params_),
- progress(progress_),
- progress_start_time(0.0),
- unaligned_heuristic(objects_)
+BVHBuild::BVHBuild(const vector<Object *> &objects_,
+ array<int> &prim_type_,
+ array<int> &prim_index_,
+ array<int> &prim_object_,
+ array<float2> &prim_time_,
+ const BVHParams &params_,
+ Progress &progress_)
+ : objects(objects_),
+ prim_type(prim_type_),
+ prim_index(prim_index_),
+ prim_object(prim_object_),
+ prim_time(prim_time_),
+ params(params_),
+ progress(progress_),
+ progress_start_time(0.0),
+ unaligned_heuristic(objects_)
{
- spatial_min_overlap = 0.0f;
+ spatial_min_overlap = 0.0f;
}
BVHBuild::~BVHBuild()
@@ -115,467 +108,440 @@ BVHBuild::~BVHBuild()
/* Adding References */
-void BVHBuild::add_reference_triangles(BoundBox& root, BoundBox& center, Mesh *mesh, int i)
+void BVHBuild::add_reference_triangles(BoundBox &root, BoundBox &center, Mesh *mesh, int i)
{
- const Attribute *attr_mP = NULL;
- if(mesh->has_motion_blur()) {
- attr_mP = mesh->attributes.find(ATTR_STD_MOTION_VERTEX_POSITION);
- }
- const size_t num_triangles = mesh->num_triangles();
- for(uint j = 0; j < num_triangles; j++) {
- Mesh::Triangle t = mesh->get_triangle(j);
- const float3 *verts = &mesh->verts[0];
- if(attr_mP == NULL) {
- BoundBox bounds = BoundBox::empty;
- t.bounds_grow(verts, bounds);
- if(bounds.valid() && t.valid(verts)) {
- references.push_back(BVHReference(bounds,
- j,
- i,
- PRIMITIVE_TRIANGLE));
- root.grow(bounds);
- center.grow(bounds.center2());
- }
- }
- else if(params.num_motion_triangle_steps == 0 || params.use_spatial_split) {
- /* Motion triangles, simple case: single node for the whole
- * primitive. Lowest memory footprint and faster BVH build but
- * least optimal ray-tracing.
- */
- /* TODO(sergey): Support motion steps for spatially split BVH. */
- const size_t num_verts = mesh->verts.size();
- const size_t num_steps = mesh->motion_steps;
- const float3 *vert_steps = attr_mP->data_float3();
- BoundBox bounds = BoundBox::empty;
- t.bounds_grow(verts, bounds);
- for(size_t step = 0; step < num_steps - 1; step++) {
- t.bounds_grow(vert_steps + step*num_verts, bounds);
- }
- if(bounds.valid()) {
- references.push_back(
- BVHReference(bounds,
- j,
- i,
- PRIMITIVE_MOTION_TRIANGLE));
- root.grow(bounds);
- center.grow(bounds.center2());
- }
- }
- else {
- /* Motion triangles, trace optimized case: we split triangle
- * primitives into separate nodes for each of the time steps.
- * This way we minimize overlap of neighbor curve primitives.
- */
- const int num_bvh_steps = params.num_motion_curve_steps * 2 + 1;
- const float num_bvh_steps_inv_1 = 1.0f / (num_bvh_steps - 1);
- const size_t num_verts = mesh->verts.size();
- const size_t num_steps = mesh->motion_steps;
- const float3 *vert_steps = attr_mP->data_float3();
- /* Calculate bounding box of the previous time step.
- * Will be reused later to avoid duplicated work on
- * calculating BVH time step boundbox.
- */
- float3 prev_verts[3];
- t.motion_verts(verts,
- vert_steps,
- num_verts,
- num_steps,
- 0.0f,
- prev_verts);
- BoundBox prev_bounds = BoundBox::empty;
- prev_bounds.grow(prev_verts[0]);
- prev_bounds.grow(prev_verts[1]);
- prev_bounds.grow(prev_verts[2]);
- /* Create all primitive time steps, */
- for(int bvh_step = 1; bvh_step < num_bvh_steps; ++bvh_step) {
- const float curr_time = (float)(bvh_step) * num_bvh_steps_inv_1;
- float3 curr_verts[3];
- t.motion_verts(verts,
- vert_steps,
- num_verts,
- num_steps,
- curr_time,
- curr_verts);
- BoundBox curr_bounds = BoundBox::empty;
- curr_bounds.grow(curr_verts[0]);
- curr_bounds.grow(curr_verts[1]);
- curr_bounds.grow(curr_verts[2]);
- BoundBox bounds = prev_bounds;
- bounds.grow(curr_bounds);
- if(bounds.valid()) {
- const float prev_time = (float)(bvh_step - 1) * num_bvh_steps_inv_1;
- references.push_back(
- BVHReference(bounds,
- j,
- i,
- PRIMITIVE_MOTION_TRIANGLE,
- prev_time,
- curr_time));
- root.grow(bounds);
- center.grow(bounds.center2());
- }
- /* Current time boundbox becomes previous one for the
- * next time step.
- */
- prev_bounds = curr_bounds;
- }
- }
- }
+ const Attribute *attr_mP = NULL;
+ if (mesh->has_motion_blur()) {
+ attr_mP = mesh->attributes.find(ATTR_STD_MOTION_VERTEX_POSITION);
+ }
+ const size_t num_triangles = mesh->num_triangles();
+ for (uint j = 0; j < num_triangles; j++) {
+ Mesh::Triangle t = mesh->get_triangle(j);
+ const float3 *verts = &mesh->verts[0];
+ if (attr_mP == NULL) {
+ BoundBox bounds = BoundBox::empty;
+ t.bounds_grow(verts, bounds);
+ if (bounds.valid() && t.valid(verts)) {
+ references.push_back(BVHReference(bounds, j, i, PRIMITIVE_TRIANGLE));
+ root.grow(bounds);
+ center.grow(bounds.center2());
+ }
+ }
+ else if (params.num_motion_triangle_steps == 0 || params.use_spatial_split) {
+ /* Motion triangles, simple case: single node for the whole
+ * primitive. Lowest memory footprint and faster BVH build but
+ * least optimal ray-tracing.
+ */
+ /* TODO(sergey): Support motion steps for spatially split BVH. */
+ const size_t num_verts = mesh->verts.size();
+ const size_t num_steps = mesh->motion_steps;
+ const float3 *vert_steps = attr_mP->data_float3();
+ BoundBox bounds = BoundBox::empty;
+ t.bounds_grow(verts, bounds);
+ for (size_t step = 0; step < num_steps - 1; step++) {
+ t.bounds_grow(vert_steps + step * num_verts, bounds);
+ }
+ if (bounds.valid()) {
+ references.push_back(BVHReference(bounds, j, i, PRIMITIVE_MOTION_TRIANGLE));
+ root.grow(bounds);
+ center.grow(bounds.center2());
+ }
+ }
+ else {
+ /* Motion triangles, trace optimized case: we split triangle
+ * primitives into separate nodes for each of the time steps.
+ * This way we minimize overlap of neighbor curve primitives.
+ */
+ const int num_bvh_steps = params.num_motion_curve_steps * 2 + 1;
+ const float num_bvh_steps_inv_1 = 1.0f / (num_bvh_steps - 1);
+ const size_t num_verts = mesh->verts.size();
+ const size_t num_steps = mesh->motion_steps;
+ const float3 *vert_steps = attr_mP->data_float3();
+ /* Calculate bounding box of the previous time step.
+ * Will be reused later to avoid duplicated work on
+ * calculating BVH time step boundbox.
+ */
+ float3 prev_verts[3];
+ t.motion_verts(verts, vert_steps, num_verts, num_steps, 0.0f, prev_verts);
+ BoundBox prev_bounds = BoundBox::empty;
+ prev_bounds.grow(prev_verts[0]);
+ prev_bounds.grow(prev_verts[1]);
+ prev_bounds.grow(prev_verts[2]);
+ /* Create all primitive time steps, */
+ for (int bvh_step = 1; bvh_step < num_bvh_steps; ++bvh_step) {
+ const float curr_time = (float)(bvh_step)*num_bvh_steps_inv_1;
+ float3 curr_verts[3];
+ t.motion_verts(verts, vert_steps, num_verts, num_steps, curr_time, curr_verts);
+ BoundBox curr_bounds = BoundBox::empty;
+ curr_bounds.grow(curr_verts[0]);
+ curr_bounds.grow(curr_verts[1]);
+ curr_bounds.grow(curr_verts[2]);
+ BoundBox bounds = prev_bounds;
+ bounds.grow(curr_bounds);
+ if (bounds.valid()) {
+ const float prev_time = (float)(bvh_step - 1) * num_bvh_steps_inv_1;
+ references.push_back(
+ BVHReference(bounds, j, i, PRIMITIVE_MOTION_TRIANGLE, prev_time, curr_time));
+ root.grow(bounds);
+ center.grow(bounds.center2());
+ }
+ /* Current time boundbox becomes previous one for the
+ * next time step.
+ */
+ prev_bounds = curr_bounds;
+ }
+ }
+ }
}
-void BVHBuild::add_reference_curves(BoundBox& root, BoundBox& center, Mesh *mesh, int i)
+void BVHBuild::add_reference_curves(BoundBox &root, BoundBox &center, Mesh *mesh, int i)
{
- const Attribute *curve_attr_mP = NULL;
- if(mesh->has_motion_blur()) {
- curve_attr_mP = mesh->curve_attributes.find(ATTR_STD_MOTION_VERTEX_POSITION);
- }
- const size_t num_curves = mesh->num_curves();
- for(uint j = 0; j < num_curves; j++) {
- const Mesh::Curve curve = mesh->get_curve(j);
- const float *curve_radius = &mesh->curve_radius[0];
- for(int k = 0; k < curve.num_keys - 1; k++) {
- if(curve_attr_mP == NULL) {
- /* Really simple logic for static hair. */
- BoundBox bounds = BoundBox::empty;
- curve.bounds_grow(k, &mesh->curve_keys[0], curve_radius, bounds);
- if(bounds.valid()) {
- int packed_type = PRIMITIVE_PACK_SEGMENT(PRIMITIVE_CURVE, k);
- references.push_back(BVHReference(bounds, j, i, packed_type));
- root.grow(bounds);
- center.grow(bounds.center2());
- }
- }
- else if(params.num_motion_curve_steps == 0 || params.use_spatial_split) {
- /* Simple case of motion curves: single node for the while
- * shutter time. Lowest memory usage but less optimal
- * rendering.
- */
- /* TODO(sergey): Support motion steps for spatially split BVH. */
- BoundBox bounds = BoundBox::empty;
- curve.bounds_grow(k, &mesh->curve_keys[0], curve_radius, bounds);
- const size_t num_keys = mesh->curve_keys.size();
- const size_t num_steps = mesh->motion_steps;
- const float3 *key_steps = curve_attr_mP->data_float3();
- for(size_t step = 0; step < num_steps - 1; step++) {
- curve.bounds_grow(k,
- key_steps + step*num_keys,
- curve_radius,
- bounds);
- }
- if(bounds.valid()) {
- int packed_type = PRIMITIVE_PACK_SEGMENT(PRIMITIVE_MOTION_CURVE, k);
- references.push_back(BVHReference(bounds,
- j,
- i,
- packed_type));
- root.grow(bounds);
- center.grow(bounds.center2());
- }
- }
- else {
- /* Motion curves, trace optimized case: we split curve keys
- * primitives into separate nodes for each of the time steps.
- * This way we minimize overlap of neighbor curve primitives.
- */
- const int num_bvh_steps = params.num_motion_curve_steps * 2 + 1;
- const float num_bvh_steps_inv_1 = 1.0f / (num_bvh_steps - 1);
- const size_t num_steps = mesh->motion_steps;
- const float3 *curve_keys = &mesh->curve_keys[0];
- const float3 *key_steps = curve_attr_mP->data_float3();
- const size_t num_keys = mesh->curve_keys.size();
- /* Calculate bounding box of the previous time step.
- * Will be reused later to avoid duplicated work on
- * calculating BVH time step boundbox.
- */
- float4 prev_keys[4];
- curve.cardinal_motion_keys(curve_keys,
- curve_radius,
- key_steps,
- num_keys,
- num_steps,
- 0.0f,
- k - 1, k, k + 1, k + 2,
- prev_keys);
- BoundBox prev_bounds = BoundBox::empty;
- curve.bounds_grow(prev_keys, prev_bounds);
- /* Create all primitive time steps, */
- for(int bvh_step = 1; bvh_step < num_bvh_steps; ++bvh_step) {
- const float curr_time = (float)(bvh_step) * num_bvh_steps_inv_1;
- float4 curr_keys[4];
- curve.cardinal_motion_keys(curve_keys,
- curve_radius,
- key_steps,
- num_keys,
- num_steps,
- curr_time,
- k - 1, k, k + 1, k + 2,
- curr_keys);
- BoundBox curr_bounds = BoundBox::empty;
- curve.bounds_grow(curr_keys, curr_bounds);
- BoundBox bounds = prev_bounds;
- bounds.grow(curr_bounds);
- if(bounds.valid()) {
- const float prev_time = (float)(bvh_step - 1) * num_bvh_steps_inv_1;
- int packed_type = PRIMITIVE_PACK_SEGMENT(PRIMITIVE_MOTION_CURVE, k);
- references.push_back(BVHReference(bounds,
- j,
- i,
- packed_type,
- prev_time,
- curr_time));
- root.grow(bounds);
- center.grow(bounds.center2());
- }
- /* Current time boundbox becomes previous one for the
- * next time step.
- */
- prev_bounds = curr_bounds;
- }
- }
- }
- }
+ const Attribute *curve_attr_mP = NULL;
+ if (mesh->has_motion_blur()) {
+ curve_attr_mP = mesh->curve_attributes.find(ATTR_STD_MOTION_VERTEX_POSITION);
+ }
+ const size_t num_curves = mesh->num_curves();
+ for (uint j = 0; j < num_curves; j++) {
+ const Mesh::Curve curve = mesh->get_curve(j);
+ const float *curve_radius = &mesh->curve_radius[0];
+ for (int k = 0; k < curve.num_keys - 1; k++) {
+ if (curve_attr_mP == NULL) {
+ /* Really simple logic for static hair. */
+ BoundBox bounds = BoundBox::empty;
+ curve.bounds_grow(k, &mesh->curve_keys[0], curve_radius, bounds);
+ if (bounds.valid()) {
+ int packed_type = PRIMITIVE_PACK_SEGMENT(PRIMITIVE_CURVE, k);
+ references.push_back(BVHReference(bounds, j, i, packed_type));
+ root.grow(bounds);
+ center.grow(bounds.center2());
+ }
+ }
+ else if (params.num_motion_curve_steps == 0 || params.use_spatial_split) {
+ /* Simple case of motion curves: single node for the while
+ * shutter time. Lowest memory usage but less optimal
+ * rendering.
+ */
+ /* TODO(sergey): Support motion steps for spatially split BVH. */
+ BoundBox bounds = BoundBox::empty;
+ curve.bounds_grow(k, &mesh->curve_keys[0], curve_radius, bounds);
+ const size_t num_keys = mesh->curve_keys.size();
+ const size_t num_steps = mesh->motion_steps;
+ const float3 *key_steps = curve_attr_mP->data_float3();
+ for (size_t step = 0; step < num_steps - 1; step++) {
+ curve.bounds_grow(k, key_steps + step * num_keys, curve_radius, bounds);
+ }
+ if (bounds.valid()) {
+ int packed_type = PRIMITIVE_PACK_SEGMENT(PRIMITIVE_MOTION_CURVE, k);
+ references.push_back(BVHReference(bounds, j, i, packed_type));
+ root.grow(bounds);
+ center.grow(bounds.center2());
+ }
+ }
+ else {
+ /* Motion curves, trace optimized case: we split curve keys
+ * primitives into separate nodes for each of the time steps.
+ * This way we minimize overlap of neighbor curve primitives.
+ */
+ const int num_bvh_steps = params.num_motion_curve_steps * 2 + 1;
+ const float num_bvh_steps_inv_1 = 1.0f / (num_bvh_steps - 1);
+ const size_t num_steps = mesh->motion_steps;
+ const float3 *curve_keys = &mesh->curve_keys[0];
+ const float3 *key_steps = curve_attr_mP->data_float3();
+ const size_t num_keys = mesh->curve_keys.size();
+ /* Calculate bounding box of the previous time step.
+ * Will be reused later to avoid duplicated work on
+ * calculating BVH time step boundbox.
+ */
+ float4 prev_keys[4];
+ curve.cardinal_motion_keys(curve_keys,
+ curve_radius,
+ key_steps,
+ num_keys,
+ num_steps,
+ 0.0f,
+ k - 1,
+ k,
+ k + 1,
+ k + 2,
+ prev_keys);
+ BoundBox prev_bounds = BoundBox::empty;
+ curve.bounds_grow(prev_keys, prev_bounds);
+ /* Create all primitive time steps, */
+ for (int bvh_step = 1; bvh_step < num_bvh_steps; ++bvh_step) {
+ const float curr_time = (float)(bvh_step)*num_bvh_steps_inv_1;
+ float4 curr_keys[4];
+ curve.cardinal_motion_keys(curve_keys,
+ curve_radius,
+ key_steps,
+ num_keys,
+ num_steps,
+ curr_time,
+ k - 1,
+ k,
+ k + 1,
+ k + 2,
+ curr_keys);
+ BoundBox curr_bounds = BoundBox::empty;
+ curve.bounds_grow(curr_keys, curr_bounds);
+ BoundBox bounds = prev_bounds;
+ bounds.grow(curr_bounds);
+ if (bounds.valid()) {
+ const float prev_time = (float)(bvh_step - 1) * num_bvh_steps_inv_1;
+ int packed_type = PRIMITIVE_PACK_SEGMENT(PRIMITIVE_MOTION_CURVE, k);
+ references.push_back(BVHReference(bounds, j, i, packed_type, prev_time, curr_time));
+ root.grow(bounds);
+ center.grow(bounds.center2());
+ }
+ /* Current time boundbox becomes previous one for the
+ * next time step.
+ */
+ prev_bounds = curr_bounds;
+ }
+ }
+ }
+ }
}
-void BVHBuild::add_reference_mesh(BoundBox& root, BoundBox& center, Mesh *mesh, int i)
+void BVHBuild::add_reference_mesh(BoundBox &root, BoundBox &center, Mesh *mesh, int i)
{
- if(params.primitive_mask & PRIMITIVE_ALL_TRIANGLE) {
- add_reference_triangles(root, center, mesh, i);
- }
- if(params.primitive_mask & PRIMITIVE_ALL_CURVE) {
- add_reference_curves(root, center, mesh, i);
- }
+ if (params.primitive_mask & PRIMITIVE_ALL_TRIANGLE) {
+ add_reference_triangles(root, center, mesh, i);
+ }
+ if (params.primitive_mask & PRIMITIVE_ALL_CURVE) {
+ add_reference_curves(root, center, mesh, i);
+ }
}
-void BVHBuild::add_reference_object(BoundBox& root, BoundBox& center, Object *ob, int i)
+void BVHBuild::add_reference_object(BoundBox &root, BoundBox &center, Object *ob, int i)
{
- references.push_back(BVHReference(ob->bounds, -1, i, 0));
- root.grow(ob->bounds);
- center.grow(ob->bounds.center2());
+ references.push_back(BVHReference(ob->bounds, -1, i, 0));
+ root.grow(ob->bounds);
+ center.grow(ob->bounds.center2());
}
static size_t count_curve_segments(Mesh *mesh)
{
- size_t num = 0, num_curves = mesh->num_curves();
+ size_t num = 0, num_curves = mesh->num_curves();
- for(size_t i = 0; i < num_curves; i++)
- num += mesh->get_curve(i).num_keys - 1;
+ for (size_t i = 0; i < num_curves; i++)
+ num += mesh->get_curve(i).num_keys - 1;
- return num;
+ return num;
}
-void BVHBuild::add_references(BVHRange& root)
+void BVHBuild::add_references(BVHRange &root)
{
- /* reserve space for references */
- size_t num_alloc_references = 0;
-
- foreach(Object *ob, objects) {
- if(params.top_level) {
- if(!ob->is_traceable()) {
- continue;
- }
- if(!ob->mesh->is_instanced()) {
- if(params.primitive_mask & PRIMITIVE_ALL_TRIANGLE) {
- num_alloc_references += ob->mesh->num_triangles();
- }
- if(params.primitive_mask & PRIMITIVE_ALL_CURVE) {
- num_alloc_references += count_curve_segments(ob->mesh);
- }
- }
- else
- num_alloc_references++;
- }
- else {
- if(params.primitive_mask & PRIMITIVE_ALL_TRIANGLE) {
- num_alloc_references += ob->mesh->num_triangles();
- }
- if(params.primitive_mask & PRIMITIVE_ALL_CURVE) {
- num_alloc_references += count_curve_segments(ob->mesh);
- }
- }
- }
-
- references.reserve(num_alloc_references);
-
- /* add references from objects */
- BoundBox bounds = BoundBox::empty, center = BoundBox::empty;
- int i = 0;
-
- foreach(Object *ob, objects) {
- if(params.top_level) {
- if(!ob->is_traceable()) {
- ++i;
- continue;
- }
- if(!ob->mesh->is_instanced())
- add_reference_mesh(bounds, center, ob->mesh, i);
- else
- add_reference_object(bounds, center, ob, i);
- }
- else
- add_reference_mesh(bounds, center, ob->mesh, i);
-
- i++;
-
- if(progress.get_cancel()) return;
- }
-
- /* happens mostly on empty meshes */
- if(!bounds.valid())
- bounds.grow(make_float3(0.0f, 0.0f, 0.0f));
-
- root = BVHRange(bounds, center, 0, references.size());
+ /* reserve space for references */
+ size_t num_alloc_references = 0;
+
+ foreach (Object *ob, objects) {
+ if (params.top_level) {
+ if (!ob->is_traceable()) {
+ continue;
+ }
+ if (!ob->mesh->is_instanced()) {
+ if (params.primitive_mask & PRIMITIVE_ALL_TRIANGLE) {
+ num_alloc_references += ob->mesh->num_triangles();
+ }
+ if (params.primitive_mask & PRIMITIVE_ALL_CURVE) {
+ num_alloc_references += count_curve_segments(ob->mesh);
+ }
+ }
+ else
+ num_alloc_references++;
+ }
+ else {
+ if (params.primitive_mask & PRIMITIVE_ALL_TRIANGLE) {
+ num_alloc_references += ob->mesh->num_triangles();
+ }
+ if (params.primitive_mask & PRIMITIVE_ALL_CURVE) {
+ num_alloc_references += count_curve_segments(ob->mesh);
+ }
+ }
+ }
+
+ references.reserve(num_alloc_references);
+
+ /* add references from objects */
+ BoundBox bounds = BoundBox::empty, center = BoundBox::empty;
+ int i = 0;
+
+ foreach (Object *ob, objects) {
+ if (params.top_level) {
+ if (!ob->is_traceable()) {
+ ++i;
+ continue;
+ }
+ if (!ob->mesh->is_instanced())
+ add_reference_mesh(bounds, center, ob->mesh, i);
+ else
+ add_reference_object(bounds, center, ob, i);
+ }
+ else
+ add_reference_mesh(bounds, center, ob->mesh, i);
+
+ i++;
+
+ if (progress.get_cancel())
+ return;
+ }
+
+ /* happens mostly on empty meshes */
+ if (!bounds.valid())
+ bounds.grow(make_float3(0.0f, 0.0f, 0.0f));
+
+ root = BVHRange(bounds, center, 0, references.size());
}
/* Build */
-BVHNode* BVHBuild::run()
+BVHNode *BVHBuild::run()
{
- BVHRange root;
-
- /* add references */
- add_references(root);
-
- if(progress.get_cancel())
- return NULL;
-
- /* init spatial splits */
- if(params.top_level) {
- /* NOTE: Technically it is supported by the builder but it's not really
- * optimized for speed yet and not really clear yet if it has measurable
- * improvement on render time. Needs some extra investigation before
- * enabling spatial split for top level BVH.
- */
- params.use_spatial_split = false;
- }
-
- spatial_min_overlap = root.bounds().safe_area() * params.spatial_split_alpha;
- if(params.use_spatial_split) {
- /* NOTE: The API here tries to be as much ready for multi-threaded build
- * as possible, but at the same time it tries not to introduce any
- * changes in behavior for until all refactoring needed for threading is
- * finished.
- *
- * So we currently allocate single storage for now, which is only used by
- * the only thread working on the spatial BVH build.
- */
- spatial_storage.resize(TaskScheduler::num_threads() + 1);
- size_t num_bins = max(root.size(), (int)BVHParams::NUM_SPATIAL_BINS) - 1;
- foreach(BVHSpatialStorage &storage, spatial_storage) {
- storage.right_bounds.clear();
- }
- spatial_storage[0].right_bounds.resize(num_bins);
- }
- spatial_free_index = 0;
-
- need_prim_time = params.num_motion_curve_steps > 0 ||
- params.num_motion_triangle_steps > 0;
-
- /* init progress updates */
- double build_start_time;
- build_start_time = progress_start_time = time_dt();
- progress_count = 0;
- progress_total = references.size();
- progress_original_total = progress_total;
-
- prim_type.resize(references.size());
- prim_index.resize(references.size());
- prim_object.resize(references.size());
- if(need_prim_time) {
- prim_time.resize(references.size());
- }
- else {
- prim_time.resize(0);
- }
-
- /* build recursively */
- BVHNode *rootnode;
-
- if(params.use_spatial_split) {
- /* Perform multithreaded spatial split build. */
- rootnode = build_node(root, &references, 0, 0);
- task_pool.wait_work();
- }
- else {
- /* Perform multithreaded binning build. */
- BVHObjectBinning rootbin(root, (references.size())? &references[0]: NULL);
- rootnode = build_node(rootbin, 0);
- task_pool.wait_work();
- }
-
- /* delete if we canceled */
- if(rootnode) {
- if(progress.get_cancel()) {
- rootnode->deleteSubtree();
- rootnode = NULL;
- VLOG(1) << "BVH build cancelled.";
- }
- else {
- /*rotate(rootnode, 4, 5);*/
- rootnode->update_visibility();
- rootnode->update_time();
- }
- if(rootnode != NULL) {
- VLOG(1) << "BVH build statistics:\n"
- << " Build time: " << time_dt() - build_start_time << "\n"
- << " Total number of nodes: "
- << string_human_readable_number(rootnode->getSubtreeSize(BVH_STAT_NODE_COUNT)) << "\n"
- << " Number of inner nodes: "
- << string_human_readable_number(rootnode->getSubtreeSize(BVH_STAT_INNER_COUNT)) << "\n"
- << " Number of leaf nodes: "
- << string_human_readable_number(rootnode->getSubtreeSize(BVH_STAT_LEAF_COUNT)) << "\n"
- << " Number of unaligned nodes: "
- << string_human_readable_number(rootnode->getSubtreeSize(BVH_STAT_UNALIGNED_COUNT)) << "\n"
- << " Allocation slop factor: "
- << ((prim_type.capacity() != 0)
- ? (float)prim_type.size() / prim_type.capacity()
- : 1.0f) << "\n"
- << " Maximum depth: "
- << string_human_readable_number(rootnode->getSubtreeSize(BVH_STAT_DEPTH)) << "\n";
- }
- }
-
-
- return rootnode;
+ BVHRange root;
+
+ /* add references */
+ add_references(root);
+
+ if (progress.get_cancel())
+ return NULL;
+
+ /* init spatial splits */
+ if (params.top_level) {
+ /* NOTE: Technically it is supported by the builder but it's not really
+ * optimized for speed yet and not really clear yet if it has measurable
+ * improvement on render time. Needs some extra investigation before
+ * enabling spatial split for top level BVH.
+ */
+ params.use_spatial_split = false;
+ }
+
+ spatial_min_overlap = root.bounds().safe_area() * params.spatial_split_alpha;
+ if (params.use_spatial_split) {
+ /* NOTE: The API here tries to be as much ready for multi-threaded build
+ * as possible, but at the same time it tries not to introduce any
+ * changes in behavior for until all refactoring needed for threading is
+ * finished.
+ *
+ * So we currently allocate single storage for now, which is only used by
+ * the only thread working on the spatial BVH build.
+ */
+ spatial_storage.resize(TaskScheduler::num_threads() + 1);
+ size_t num_bins = max(root.size(), (int)BVHParams::NUM_SPATIAL_BINS) - 1;
+ foreach (BVHSpatialStorage &storage, spatial_storage) {
+ storage.right_bounds.clear();
+ }
+ spatial_storage[0].right_bounds.resize(num_bins);
+ }
+ spatial_free_index = 0;
+
+ need_prim_time = params.num_motion_curve_steps > 0 || params.num_motion_triangle_steps > 0;
+
+ /* init progress updates */
+ double build_start_time;
+ build_start_time = progress_start_time = time_dt();
+ progress_count = 0;
+ progress_total = references.size();
+ progress_original_total = progress_total;
+
+ prim_type.resize(references.size());
+ prim_index.resize(references.size());
+ prim_object.resize(references.size());
+ if (need_prim_time) {
+ prim_time.resize(references.size());
+ }
+ else {
+ prim_time.resize(0);
+ }
+
+ /* build recursively */
+ BVHNode *rootnode;
+
+ if (params.use_spatial_split) {
+ /* Perform multithreaded spatial split build. */
+ rootnode = build_node(root, &references, 0, 0);
+ task_pool.wait_work();
+ }
+ else {
+ /* Perform multithreaded binning build. */
+ BVHObjectBinning rootbin(root, (references.size()) ? &references[0] : NULL);
+ rootnode = build_node(rootbin, 0);
+ task_pool.wait_work();
+ }
+
+ /* delete if we canceled */
+ if (rootnode) {
+ if (progress.get_cancel()) {
+ rootnode->deleteSubtree();
+ rootnode = NULL;
+ VLOG(1) << "BVH build cancelled.";
+ }
+ else {
+ /*rotate(rootnode, 4, 5);*/
+ rootnode->update_visibility();
+ rootnode->update_time();
+ }
+ if (rootnode != NULL) {
+ VLOG(1) << "BVH build statistics:\n"
+ << " Build time: " << time_dt() - build_start_time << "\n"
+ << " Total number of nodes: "
+ << string_human_readable_number(rootnode->getSubtreeSize(BVH_STAT_NODE_COUNT))
+ << "\n"
+ << " Number of inner nodes: "
+ << string_human_readable_number(rootnode->getSubtreeSize(BVH_STAT_INNER_COUNT))
+ << "\n"
+ << " Number of leaf nodes: "
+ << string_human_readable_number(rootnode->getSubtreeSize(BVH_STAT_LEAF_COUNT))
+ << "\n"
+ << " Number of unaligned nodes: "
+ << string_human_readable_number(rootnode->getSubtreeSize(BVH_STAT_UNALIGNED_COUNT))
+ << "\n"
+ << " Allocation slop factor: "
+ << ((prim_type.capacity() != 0) ? (float)prim_type.size() / prim_type.capacity() :
+ 1.0f)
+ << "\n"
+ << " Maximum depth: "
+ << string_human_readable_number(rootnode->getSubtreeSize(BVH_STAT_DEPTH)) << "\n";
+ }
+ }
+
+ return rootnode;
}
void BVHBuild::progress_update()
{
- if(time_dt() - progress_start_time < 0.25)
- return;
+ if (time_dt() - progress_start_time < 0.25)
+ return;
- double progress_start = (double)progress_count/(double)progress_total;
- double duplicates = (double)(progress_total - progress_original_total)/(double)progress_total;
+ double progress_start = (double)progress_count / (double)progress_total;
+ double duplicates = (double)(progress_total - progress_original_total) / (double)progress_total;
- string msg = string_printf("Building BVH %.0f%%, duplicates %.0f%%",
- progress_start * 100.0, duplicates * 100.0);
+ string msg = string_printf(
+ "Building BVH %.0f%%, duplicates %.0f%%", progress_start * 100.0, duplicates * 100.0);
- progress.set_substatus(msg);
- progress_start_time = time_dt();
+ progress.set_substatus(msg);
+ progress_start_time = time_dt();
}
-void BVHBuild::thread_build_node(InnerNode *inner,
- int child,
- BVHObjectBinning *range,
- int level)
+void BVHBuild::thread_build_node(InnerNode *inner, int child, BVHObjectBinning *range, int level)
{
- if(progress.get_cancel())
- return;
+ if (progress.get_cancel())
+ return;
- /* build nodes */
- BVHNode *node = build_node(*range, level);
+ /* build nodes */
+ BVHNode *node = build_node(*range, level);
- /* set child in inner node */
- inner->children[child] = node;
+ /* set child in inner node */
+ inner->children[child] = node;
- /* update progress */
- if(range->size() < THREAD_TASK_SIZE) {
- /*rotate(node, INT_MAX, 5);*/
+ /* update progress */
+ if (range->size() < THREAD_TASK_SIZE) {
+ /*rotate(node, INT_MAX, 5);*/
- thread_scoped_lock lock(build_mutex);
+ thread_scoped_lock lock(build_mutex);
- progress_count += range->size();
- progress_update();
- }
+ progress_count += range->size();
+ progress_update();
+ }
}
void BVHBuild::thread_build_spatial_split_node(InnerNode *inner,
@@ -585,567 +551,528 @@ void BVHBuild::thread_build_spatial_split_node(InnerNode *inner,
int level,
int thread_id)
{
- if(progress.get_cancel()) {
- return;
- }
+ if (progress.get_cancel()) {
+ return;
+ }
- /* build nodes */
- BVHNode *node = build_node(*range, references, level, thread_id);
+ /* build nodes */
+ BVHNode *node = build_node(*range, references, level, thread_id);
- /* set child in inner node */
- inner->children[child] = node;
+ /* set child in inner node */
+ inner->children[child] = node;
}
-bool BVHBuild::range_within_max_leaf_size(const BVHRange& range,
- const vector<BVHReference>& references) const
+bool BVHBuild::range_within_max_leaf_size(const BVHRange &range,
+ const vector<BVHReference> &references) const
{
- size_t size = range.size();
- size_t max_leaf_size = max(params.max_triangle_leaf_size, params.max_curve_leaf_size);
-
- if(size > max_leaf_size)
- return false;
-
- size_t num_triangles = 0;
- size_t num_motion_triangles = 0;
- size_t num_curves = 0;
- size_t num_motion_curves = 0;
-
- for(int i = 0; i < size; i++) {
- const BVHReference& ref = references[range.start() + i];
-
- if(ref.prim_type() & PRIMITIVE_CURVE)
- num_curves++;
- if(ref.prim_type() & PRIMITIVE_MOTION_CURVE)
- num_motion_curves++;
- else if(ref.prim_type() & PRIMITIVE_TRIANGLE)
- num_triangles++;
- else if(ref.prim_type() & PRIMITIVE_MOTION_TRIANGLE)
- num_motion_triangles++;
- }
-
- return (num_triangles <= params.max_triangle_leaf_size) &&
- (num_motion_triangles <= params.max_motion_triangle_leaf_size) &&
- (num_curves <= params.max_curve_leaf_size) &&
- (num_motion_curves <= params.max_motion_curve_leaf_size);
+ size_t size = range.size();
+ size_t max_leaf_size = max(params.max_triangle_leaf_size, params.max_curve_leaf_size);
+
+ if (size > max_leaf_size)
+ return false;
+
+ size_t num_triangles = 0;
+ size_t num_motion_triangles = 0;
+ size_t num_curves = 0;
+ size_t num_motion_curves = 0;
+
+ for (int i = 0; i < size; i++) {
+ const BVHReference &ref = references[range.start() + i];
+
+ if (ref.prim_type() & PRIMITIVE_CURVE)
+ num_curves++;
+ if (ref.prim_type() & PRIMITIVE_MOTION_CURVE)
+ num_motion_curves++;
+ else if (ref.prim_type() & PRIMITIVE_TRIANGLE)
+ num_triangles++;
+ else if (ref.prim_type() & PRIMITIVE_MOTION_TRIANGLE)
+ num_motion_triangles++;
+ }
+
+ return (num_triangles <= params.max_triangle_leaf_size) &&
+ (num_motion_triangles <= params.max_motion_triangle_leaf_size) &&
+ (num_curves <= params.max_curve_leaf_size) &&
+ (num_motion_curves <= params.max_motion_curve_leaf_size);
}
/* multithreaded binning builder */
-BVHNode* BVHBuild::build_node(const BVHObjectBinning& range, int level)
+BVHNode *BVHBuild::build_node(const BVHObjectBinning &range, int level)
{
- size_t size = range.size();
- float leafSAH = params.sah_primitive_cost * range.leafSAH;
- float splitSAH = params.sah_node_cost * range.bounds().half_area() + params.sah_primitive_cost * range.splitSAH;
-
- /* Have at least one inner node on top level, for performance and correct
- * visibility tests, since object instances do not check visibility flag.
- */
- if(!(range.size() > 0 && params.top_level && level == 0)) {
- /* Make leaf node when threshold reached or SAH tells us. */
- if((params.small_enough_for_leaf(size, level)) ||
- (range_within_max_leaf_size(range, references) && leafSAH < splitSAH))
- {
- return create_leaf_node(range, references);
- }
- }
-
- BVHObjectBinning unaligned_range;
- float unalignedSplitSAH = FLT_MAX;
- float unalignedLeafSAH = FLT_MAX;
- Transform aligned_space;
- bool do_unalinged_split = false;
- if(params.use_unaligned_nodes &&
- splitSAH > params.unaligned_split_threshold*leafSAH)
- {
- aligned_space = unaligned_heuristic.compute_aligned_space(
- range, &references[0]);
- unaligned_range = BVHObjectBinning(range,
- &references[0],
- &unaligned_heuristic,
- &aligned_space);
- unalignedSplitSAH = params.sah_node_cost * unaligned_range.unaligned_bounds().half_area() +
- params.sah_primitive_cost * unaligned_range.splitSAH;
- unalignedLeafSAH = params.sah_primitive_cost * unaligned_range.leafSAH;
- if(!(range.size() > 0 && params.top_level && level == 0)) {
- if(unalignedLeafSAH < unalignedSplitSAH && unalignedSplitSAH < splitSAH &&
- range_within_max_leaf_size(range, references))
- {
- return create_leaf_node(range, references);
- }
- }
- /* Check whether unaligned split is better than the regular one. */
- if(unalignedSplitSAH < splitSAH) {
- do_unalinged_split = true;
- }
- }
-
- /* Perform split. */
- BVHObjectBinning left, right;
- if(do_unalinged_split) {
- unaligned_range.split(&references[0], left, right);
- }
- else {
- range.split(&references[0], left, right);
- }
-
- BoundBox bounds;
- if(do_unalinged_split) {
- bounds = unaligned_heuristic.compute_aligned_boundbox(
- range, &references[0], aligned_space);
- }
- else {
- bounds = range.bounds();
- }
-
- /* Create inner node. */
- InnerNode *inner;
- if(range.size() < THREAD_TASK_SIZE) {
- /* local build */
- BVHNode *leftnode = build_node(left, level + 1);
- BVHNode *rightnode = build_node(right, level + 1);
-
- inner = new InnerNode(bounds, leftnode, rightnode);
- }
- else {
- /* Threaded build */
- inner = new InnerNode(bounds);
-
- task_pool.push(new BVHBuildTask(this, inner, 0, left, level + 1), true);
- task_pool.push(new BVHBuildTask(this, inner, 1, right, level + 1), true);
- }
-
- if(do_unalinged_split) {
- inner->set_aligned_space(aligned_space);
- }
-
- return inner;
+ size_t size = range.size();
+ float leafSAH = params.sah_primitive_cost * range.leafSAH;
+ float splitSAH = params.sah_node_cost * range.bounds().half_area() +
+ params.sah_primitive_cost * range.splitSAH;
+
+ /* Have at least one inner node on top level, for performance and correct
+ * visibility tests, since object instances do not check visibility flag.
+ */
+ if (!(range.size() > 0 && params.top_level && level == 0)) {
+ /* Make leaf node when threshold reached or SAH tells us. */
+ if ((params.small_enough_for_leaf(size, level)) ||
+ (range_within_max_leaf_size(range, references) && leafSAH < splitSAH)) {
+ return create_leaf_node(range, references);
+ }
+ }
+
+ BVHObjectBinning unaligned_range;
+ float unalignedSplitSAH = FLT_MAX;
+ float unalignedLeafSAH = FLT_MAX;
+ Transform aligned_space;
+ bool do_unalinged_split = false;
+ if (params.use_unaligned_nodes && splitSAH > params.unaligned_split_threshold * leafSAH) {
+ aligned_space = unaligned_heuristic.compute_aligned_space(range, &references[0]);
+ unaligned_range = BVHObjectBinning(
+ range, &references[0], &unaligned_heuristic, &aligned_space);
+ unalignedSplitSAH = params.sah_node_cost * unaligned_range.unaligned_bounds().half_area() +
+ params.sah_primitive_cost * unaligned_range.splitSAH;
+ unalignedLeafSAH = params.sah_primitive_cost * unaligned_range.leafSAH;
+ if (!(range.size() > 0 && params.top_level && level == 0)) {
+ if (unalignedLeafSAH < unalignedSplitSAH && unalignedSplitSAH < splitSAH &&
+ range_within_max_leaf_size(range, references)) {
+ return create_leaf_node(range, references);
+ }
+ }
+ /* Check whether unaligned split is better than the regular one. */
+ if (unalignedSplitSAH < splitSAH) {
+ do_unalinged_split = true;
+ }
+ }
+
+ /* Perform split. */
+ BVHObjectBinning left, right;
+ if (do_unalinged_split) {
+ unaligned_range.split(&references[0], left, right);
+ }
+ else {
+ range.split(&references[0], left, right);
+ }
+
+ BoundBox bounds;
+ if (do_unalinged_split) {
+ bounds = unaligned_heuristic.compute_aligned_boundbox(range, &references[0], aligned_space);
+ }
+ else {
+ bounds = range.bounds();
+ }
+
+ /* Create inner node. */
+ InnerNode *inner;
+ if (range.size() < THREAD_TASK_SIZE) {
+ /* local build */
+ BVHNode *leftnode = build_node(left, level + 1);
+ BVHNode *rightnode = build_node(right, level + 1);
+
+ inner = new InnerNode(bounds, leftnode, rightnode);
+ }
+ else {
+ /* Threaded build */
+ inner = new InnerNode(bounds);
+
+ task_pool.push(new BVHBuildTask(this, inner, 0, left, level + 1), true);
+ task_pool.push(new BVHBuildTask(this, inner, 1, right, level + 1), true);
+ }
+
+ if (do_unalinged_split) {
+ inner->set_aligned_space(aligned_space);
+ }
+
+ return inner;
}
/* multithreaded spatial split builder */
-BVHNode* BVHBuild::build_node(const BVHRange& range,
+BVHNode *BVHBuild::build_node(const BVHRange &range,
vector<BVHReference> *references,
int level,
int thread_id)
{
- /* Update progress.
- *
- * TODO(sergey): Currently it matches old behavior, but we can move it to the
- * task thread (which will mimic non=split builder) and save some CPU ticks
- * on checking cancel status.
- */
- progress_update();
- if(progress.get_cancel()) {
- return NULL;
- }
-
- /* Small enough or too deep => create leaf. */
- if(!(range.size() > 0 && params.top_level && level == 0)) {
- if(params.small_enough_for_leaf(range.size(), level)) {
- progress_count += range.size();
- return create_leaf_node(range, *references);
- }
- }
-
- /* Perform splitting test. */
- BVHSpatialStorage *storage = &spatial_storage[thread_id];
- BVHMixedSplit split(this, storage, range, references, level);
-
- if(!(range.size() > 0 && params.top_level && level == 0)) {
- if(split.no_split) {
- progress_count += range.size();
- return create_leaf_node(range, *references);
- }
- }
- float leafSAH = params.sah_primitive_cost * split.leafSAH;
- float splitSAH = params.sah_node_cost * range.bounds().half_area() +
- params.sah_primitive_cost * split.nodeSAH;
-
- BVHMixedSplit unaligned_split;
- float unalignedSplitSAH = FLT_MAX;
- /* float unalignedLeafSAH = FLT_MAX; */
- Transform aligned_space;
- bool do_unalinged_split = false;
- if(params.use_unaligned_nodes &&
- splitSAH > params.unaligned_split_threshold*leafSAH)
- {
- aligned_space =
- unaligned_heuristic.compute_aligned_space(range, &references->at(0));
- unaligned_split = BVHMixedSplit(this,
- storage,
- range,
- references,
- level,
- &unaligned_heuristic,
- &aligned_space);
- /* unalignedLeafSAH = params.sah_primitive_cost * split.leafSAH; */
- unalignedSplitSAH = params.sah_node_cost * unaligned_split.bounds.half_area() +
- params.sah_primitive_cost * unaligned_split.nodeSAH;
- /* TOOD(sergey): Check we can create leaf already. */
- /* Check whether unaligned split is better than the regulat one. */
- if(unalignedSplitSAH < splitSAH) {
- do_unalinged_split = true;
- }
- }
-
- /* Do split. */
- BVHRange left, right;
- if(do_unalinged_split) {
- unaligned_split.split(this, left, right, range);
- }
- else {
- split.split(this, left, right, range);
- }
-
- progress_total += left.size() + right.size() - range.size();
-
- BoundBox bounds;
- if(do_unalinged_split) {
- bounds = unaligned_heuristic.compute_aligned_boundbox(
- range, &references->at(0), aligned_space);
- }
- else {
- bounds = range.bounds();
- }
-
- /* Create inner node. */
- InnerNode *inner;
- if(range.size() < THREAD_TASK_SIZE) {
- /* Local build. */
-
- /* Build left node. */
- vector<BVHReference> copy(references->begin() + right.start(),
- references->begin() + right.end());
- right.set_start(0);
-
- BVHNode *leftnode = build_node(left, references, level + 1, thread_id);
-
- /* Build right node. */
- BVHNode *rightnode = build_node(right, &copy, level + 1, thread_id);
-
- inner = new InnerNode(bounds, leftnode, rightnode);
- }
- else {
- /* Threaded build. */
- inner = new InnerNode(bounds);
- task_pool.push(new BVHSpatialSplitBuildTask(this,
- inner,
- 0,
- left,
- *references,
- level + 1),
- true);
- task_pool.push(new BVHSpatialSplitBuildTask(this,
- inner,
- 1,
- right,
- *references,
- level + 1),
- true);
- }
-
- if(do_unalinged_split) {
- inner->set_aligned_space(aligned_space);
- }
-
- return inner;
+ /* Update progress.
+ *
+ * TODO(sergey): Currently it matches old behavior, but we can move it to the
+ * task thread (which will mimic non=split builder) and save some CPU ticks
+ * on checking cancel status.
+ */
+ progress_update();
+ if (progress.get_cancel()) {
+ return NULL;
+ }
+
+ /* Small enough or too deep => create leaf. */
+ if (!(range.size() > 0 && params.top_level && level == 0)) {
+ if (params.small_enough_for_leaf(range.size(), level)) {
+ progress_count += range.size();
+ return create_leaf_node(range, *references);
+ }
+ }
+
+ /* Perform splitting test. */
+ BVHSpatialStorage *storage = &spatial_storage[thread_id];
+ BVHMixedSplit split(this, storage, range, references, level);
+
+ if (!(range.size() > 0 && params.top_level && level == 0)) {
+ if (split.no_split) {
+ progress_count += range.size();
+ return create_leaf_node(range, *references);
+ }
+ }
+ float leafSAH = params.sah_primitive_cost * split.leafSAH;
+ float splitSAH = params.sah_node_cost * range.bounds().half_area() +
+ params.sah_primitive_cost * split.nodeSAH;
+
+ BVHMixedSplit unaligned_split;
+ float unalignedSplitSAH = FLT_MAX;
+ /* float unalignedLeafSAH = FLT_MAX; */
+ Transform aligned_space;
+ bool do_unalinged_split = false;
+ if (params.use_unaligned_nodes && splitSAH > params.unaligned_split_threshold * leafSAH) {
+ aligned_space = unaligned_heuristic.compute_aligned_space(range, &references->at(0));
+ unaligned_split = BVHMixedSplit(
+ this, storage, range, references, level, &unaligned_heuristic, &aligned_space);
+ /* unalignedLeafSAH = params.sah_primitive_cost * split.leafSAH; */
+ unalignedSplitSAH = params.sah_node_cost * unaligned_split.bounds.half_area() +
+ params.sah_primitive_cost * unaligned_split.nodeSAH;
+ /* TOOD(sergey): Check we can create leaf already. */
+ /* Check whether unaligned split is better than the regulat one. */
+ if (unalignedSplitSAH < splitSAH) {
+ do_unalinged_split = true;
+ }
+ }
+
+ /* Do split. */
+ BVHRange left, right;
+ if (do_unalinged_split) {
+ unaligned_split.split(this, left, right, range);
+ }
+ else {
+ split.split(this, left, right, range);
+ }
+
+ progress_total += left.size() + right.size() - range.size();
+
+ BoundBox bounds;
+ if (do_unalinged_split) {
+ bounds = unaligned_heuristic.compute_aligned_boundbox(
+ range, &references->at(0), aligned_space);
+ }
+ else {
+ bounds = range.bounds();
+ }
+
+ /* Create inner node. */
+ InnerNode *inner;
+ if (range.size() < THREAD_TASK_SIZE) {
+ /* Local build. */
+
+ /* Build left node. */
+ vector<BVHReference> copy(references->begin() + right.start(),
+ references->begin() + right.end());
+ right.set_start(0);
+
+ BVHNode *leftnode = build_node(left, references, level + 1, thread_id);
+
+ /* Build right node. */
+ BVHNode *rightnode = build_node(right, &copy, level + 1, thread_id);
+
+ inner = new InnerNode(bounds, leftnode, rightnode);
+ }
+ else {
+ /* Threaded build. */
+ inner = new InnerNode(bounds);
+ task_pool.push(new BVHSpatialSplitBuildTask(this, inner, 0, left, *references, level + 1),
+ true);
+ task_pool.push(new BVHSpatialSplitBuildTask(this, inner, 1, right, *references, level + 1),
+ true);
+ }
+
+ if (do_unalinged_split) {
+ inner->set_aligned_space(aligned_space);
+ }
+
+ return inner;
}
/* Create Nodes */
BVHNode *BVHBuild::create_object_leaf_nodes(const BVHReference *ref, int start, int num)
{
- if(num == 0) {
- BoundBox bounds = BoundBox::empty;
- return new LeafNode(bounds, 0, 0, 0);
- }
- else if(num == 1) {
- assert(start < prim_type.size());
- prim_type[start] = ref->prim_type();
- prim_index[start] = ref->prim_index();
- prim_object[start] = ref->prim_object();
- if(need_prim_time) {
- prim_time[start] = make_float2(ref->time_from(), ref->time_to());
- }
-
- const uint visibility = objects[ref->prim_object()]->visibility_for_tracing();
- BVHNode *leaf_node = new LeafNode(ref->bounds(), visibility, start, start+1);
- leaf_node->time_from = ref->time_from();
- leaf_node->time_to = ref->time_to();
- return leaf_node;
- }
- else {
- int mid = num/2;
- BVHNode *leaf0 = create_object_leaf_nodes(ref, start, mid);
- BVHNode *leaf1 = create_object_leaf_nodes(ref+mid, start+mid, num-mid);
-
- BoundBox bounds = BoundBox::empty;
- bounds.grow(leaf0->bounds);
- bounds.grow(leaf1->bounds);
-
- BVHNode *inner_node = new InnerNode(bounds, leaf0, leaf1);
- inner_node->time_from = min(leaf0->time_from, leaf1->time_from);
- inner_node->time_to = max(leaf0->time_to, leaf1->time_to);
- return inner_node;
- }
+ if (num == 0) {
+ BoundBox bounds = BoundBox::empty;
+ return new LeafNode(bounds, 0, 0, 0);
+ }
+ else if (num == 1) {
+ assert(start < prim_type.size());
+ prim_type[start] = ref->prim_type();
+ prim_index[start] = ref->prim_index();
+ prim_object[start] = ref->prim_object();
+ if (need_prim_time) {
+ prim_time[start] = make_float2(ref->time_from(), ref->time_to());
+ }
+
+ const uint visibility = objects[ref->prim_object()]->visibility_for_tracing();
+ BVHNode *leaf_node = new LeafNode(ref->bounds(), visibility, start, start + 1);
+ leaf_node->time_from = ref->time_from();
+ leaf_node->time_to = ref->time_to();
+ return leaf_node;
+ }
+ else {
+ int mid = num / 2;
+ BVHNode *leaf0 = create_object_leaf_nodes(ref, start, mid);
+ BVHNode *leaf1 = create_object_leaf_nodes(ref + mid, start + mid, num - mid);
+
+ BoundBox bounds = BoundBox::empty;
+ bounds.grow(leaf0->bounds);
+ bounds.grow(leaf1->bounds);
+
+ BVHNode *inner_node = new InnerNode(bounds, leaf0, leaf1);
+ inner_node->time_from = min(leaf0->time_from, leaf1->time_from);
+ inner_node->time_to = max(leaf0->time_to, leaf1->time_to);
+ return inner_node;
+ }
}
-BVHNode* BVHBuild::create_leaf_node(const BVHRange& range,
- const vector<BVHReference>& references)
+BVHNode *BVHBuild::create_leaf_node(const BVHRange &range, const vector<BVHReference> &references)
{
- /* This is a bit overallocating here (considering leaf size into account),
- * but chunk-based re-allocation in vector makes it difficult to use small
- * size of stack storage here. Some tweaks are possible tho.
- *
- * NOTES:
- * - If the size is too big, we'll have inefficient stack usage,
- * and lots of cache misses.
- * - If the size is too small, then we can run out of memory
- * allowed to be used by vector.
- * In practice it wouldn't mean crash, just allocator will fallback
- * to heap which is slower.
- * - Optimistic re-allocation in STL could jump us out of stack usage
- * because re-allocation happens in chunks and size of those chunks we
- * can not control.
- */
- typedef StackAllocator<256, int> LeafStackAllocator;
- typedef StackAllocator<256, float2> LeafTimeStackAllocator;
- typedef StackAllocator<256, BVHReference> LeafReferenceStackAllocator;
-
- vector<int, LeafStackAllocator> p_type[PRIMITIVE_NUM_TOTAL];
- vector<int, LeafStackAllocator> p_index[PRIMITIVE_NUM_TOTAL];
- vector<int, LeafStackAllocator> p_object[PRIMITIVE_NUM_TOTAL];
- vector<float2, LeafTimeStackAllocator> p_time[PRIMITIVE_NUM_TOTAL];
- vector<BVHReference, LeafReferenceStackAllocator> p_ref[PRIMITIVE_NUM_TOTAL];
-
- /* TODO(sergey): In theory we should be able to store references. */
- vector<BVHReference, LeafReferenceStackAllocator> object_references;
-
- uint visibility[PRIMITIVE_NUM_TOTAL] = {0};
- /* NOTE: Keep initializtion in sync with actual number of primitives. */
- BoundBox bounds[PRIMITIVE_NUM_TOTAL] = {BoundBox::empty,
- BoundBox::empty,
- BoundBox::empty,
- BoundBox::empty};
- int ob_num = 0;
- int num_new_prims = 0;
- /* Fill in per-type type/index array. */
- for(int i = 0; i < range.size(); i++) {
- const BVHReference& ref = references[range.start() + i];
- if(ref.prim_index() != -1) {
- int type_index = bitscan(ref.prim_type() & PRIMITIVE_ALL);
- p_ref[type_index].push_back(ref);
- p_type[type_index].push_back(ref.prim_type());
- p_index[type_index].push_back(ref.prim_index());
- p_object[type_index].push_back(ref.prim_object());
- p_time[type_index].push_back(make_float2(ref.time_from(),
- ref.time_to()));
-
- bounds[type_index].grow(ref.bounds());
- visibility[type_index] |= objects[ref.prim_object()]->visibility_for_tracing();
- if(ref.prim_type() & PRIMITIVE_ALL_CURVE) {
- visibility[type_index] |= PATH_RAY_CURVE;
- }
- ++num_new_prims;
- }
- else {
- object_references.push_back(ref);
- ++ob_num;
- }
- }
-
- /* Create leaf nodes for every existing primitive.
- *
- * Here we write primitive types, indices and objects to a temporary array.
- * This way we keep all the heavy memory allocation code outside of the
- * thread lock in the case of spatial split building.
- *
- * TODO(sergey): With some pointer trickery we can write directly to the
- * destination buffers for the non-spatial split BVH.
- */
- BVHNode *leaves[PRIMITIVE_NUM_TOTAL + 1] = {NULL};
- int num_leaves = 0;
- size_t start_index = 0;
- vector<int, LeafStackAllocator> local_prim_type,
- local_prim_index,
- local_prim_object;
- vector<float2, LeafTimeStackAllocator> local_prim_time;
- local_prim_type.resize(num_new_prims);
- local_prim_index.resize(num_new_prims);
- local_prim_object.resize(num_new_prims);
- if(need_prim_time) {
- local_prim_time.resize(num_new_prims);
- }
- for(int i = 0; i < PRIMITIVE_NUM_TOTAL; ++i) {
- int num = (int)p_type[i].size();
- if(num != 0) {
- assert(p_type[i].size() == p_index[i].size());
- assert(p_type[i].size() == p_object[i].size());
- Transform aligned_space;
- bool alignment_found = false;
- for(int j = 0; j < num; ++j) {
- const int index = start_index + j;
- local_prim_type[index] = p_type[i][j];
- local_prim_index[index] = p_index[i][j];
- local_prim_object[index] = p_object[i][j];
- if(need_prim_time) {
- local_prim_time[index] = p_time[i][j];
- }
- if(params.use_unaligned_nodes && !alignment_found) {
- alignment_found =
- unaligned_heuristic.compute_aligned_space(p_ref[i][j],
- &aligned_space);
- }
- }
- LeafNode *leaf_node = new LeafNode(bounds[i],
- visibility[i],
- start_index,
- start_index + num);
- if(true) {
- float time_from = 1.0f, time_to = 0.0f;
- for(int j = 0; j < num; ++j) {
- const BVHReference &ref = p_ref[i][j];
- time_from = min(time_from, ref.time_from());
- time_to = max(time_to, ref.time_to());
- }
- leaf_node->time_from = time_from;
- leaf_node->time_to = time_to;
- }
- if(alignment_found) {
- /* Need to recalculate leaf bounds with new alignment. */
- leaf_node->bounds = BoundBox::empty;
- for(int j = 0; j < num; ++j) {
- const BVHReference &ref = p_ref[i][j];
- BoundBox ref_bounds =
- unaligned_heuristic.compute_aligned_prim_boundbox(
- ref,
- aligned_space);
- leaf_node->bounds.grow(ref_bounds);
- }
- /* Set alignment space. */
- leaf_node->set_aligned_space(aligned_space);
- }
- leaves[num_leaves++] = leaf_node;
- start_index += num;
- }
- }
- /* Get size of new data to be copied to the packed arrays. */
- const int num_new_leaf_data = start_index;
- const size_t new_leaf_data_size = sizeof(int) * num_new_leaf_data;
- /* Copy actual data to the packed array. */
- if(params.use_spatial_split) {
- spatial_spin_lock.lock();
- /* We use first free index in the packed arrays and mode pointer to the
- * end of the current range.
- *
- * This doesn't give deterministic packed arrays, but it shouldn't really
- * matter because order of children in BVH is deterministic.
- */
- start_index = spatial_free_index;
- spatial_free_index += range.size();
- /* Extend an array when needed. */
- const size_t range_end = start_index + range.size();
- if(prim_type.size() < range_end) {
- /* Avoid extra re-allocations by pre-allocating bigger array in an
- * advance.
- */
- if(range_end >= prim_type.capacity()) {
- float progress = (float)progress_count/(float)progress_total;
- float factor = (1.0f - progress);
- const size_t reserve = (size_t)(range_end + (float)range_end*factor);
- prim_type.reserve(reserve);
- prim_index.reserve(reserve);
- prim_object.reserve(reserve);
- if(need_prim_time) {
- prim_time.reserve(reserve);
- }
- }
-
- prim_type.resize(range_end);
- prim_index.resize(range_end);
- prim_object.resize(range_end);
- if(need_prim_time) {
- prim_time.resize(range_end);
- }
- }
- /* Perform actual data copy. */
- if(new_leaf_data_size > 0) {
- memcpy(&prim_type[start_index], &local_prim_type[0], new_leaf_data_size);
- memcpy(&prim_index[start_index], &local_prim_index[0], new_leaf_data_size);
- memcpy(&prim_object[start_index], &local_prim_object[0], new_leaf_data_size);
- if(need_prim_time) {
- memcpy(&prim_time[start_index], &local_prim_time[0], sizeof(float2)*num_new_leaf_data);
- }
- }
- spatial_spin_lock.unlock();
- }
- else {
- /* For the regular BVH builder we simply copy new data starting at the
- * range start. This is totally thread-safe, all threads are living
- * inside of their own range.
- */
- start_index = range.start();
- if(new_leaf_data_size > 0) {
- memcpy(&prim_type[start_index], &local_prim_type[0], new_leaf_data_size);
- memcpy(&prim_index[start_index], &local_prim_index[0], new_leaf_data_size);
- memcpy(&prim_object[start_index], &local_prim_object[0], new_leaf_data_size);
- if(need_prim_time) {
- memcpy(&prim_time[start_index], &local_prim_time[0], sizeof(float2)*num_new_leaf_data);
- }
- }
- }
-
- /* So far leaves were created with the zero-based index in an arrays,
- * here we modify the indices to correspond to actual packed array start
- * index.
- */
- for(int i = 0; i < num_leaves; ++i) {
- LeafNode *leaf = (LeafNode *)leaves[i];
- leaf->lo += start_index;
- leaf->hi += start_index;
- }
-
- /* Create leaf node for object. */
- if(num_leaves == 0 || ob_num) {
- /* Only create object leaf nodes if there are objects or no other
- * nodes created.
- */
- const BVHReference *ref = (ob_num)? &object_references[0]: NULL;
- leaves[num_leaves] = create_object_leaf_nodes(ref,
- start_index + num_new_leaf_data,
- ob_num);
- ++num_leaves;
- }
-
- /* TODO(sergey): Need to take care of alignment when number of leaves
- * is more than 1.
- */
- if(num_leaves == 1) {
- /* Simplest case: single leaf, just return it.
- * In all the rest cases we'll be creating intermediate inner node with
- * an appropriate bounding box.
- */
- return leaves[0];
- }
- else if(num_leaves == 2) {
- return new InnerNode(range.bounds(), leaves[0], leaves[1]);
- }
- else if(num_leaves == 3) {
- BoundBox inner_bounds = merge(leaves[1]->bounds, leaves[2]->bounds);
- BVHNode *inner = new InnerNode(inner_bounds, leaves[1], leaves[2]);
- return new InnerNode(range.bounds(), leaves[0], inner);
- } else {
- /* Should be doing more branches if more primitive types added. */
- assert(num_leaves <= 5);
- BoundBox inner_bounds_a = merge(leaves[0]->bounds, leaves[1]->bounds);
- BoundBox inner_bounds_b = merge(leaves[2]->bounds, leaves[3]->bounds);
- BVHNode *inner_a = new InnerNode(inner_bounds_a, leaves[0], leaves[1]);
- BVHNode *inner_b = new InnerNode(inner_bounds_b, leaves[2], leaves[3]);
- BoundBox inner_bounds_c = merge(inner_a->bounds, inner_b->bounds);
- BVHNode *inner_c = new InnerNode(inner_bounds_c, inner_a, inner_b);
- if(num_leaves == 5) {
- return new InnerNode(range.bounds(), inner_c, leaves[4]);
- }
- return inner_c;
- }
+ /* This is a bit overallocating here (considering leaf size into account),
+ * but chunk-based re-allocation in vector makes it difficult to use small
+ * size of stack storage here. Some tweaks are possible tho.
+ *
+ * NOTES:
+ * - If the size is too big, we'll have inefficient stack usage,
+ * and lots of cache misses.
+ * - If the size is too small, then we can run out of memory
+ * allowed to be used by vector.
+ * In practice it wouldn't mean crash, just allocator will fallback
+ * to heap which is slower.
+ * - Optimistic re-allocation in STL could jump us out of stack usage
+ * because re-allocation happens in chunks and size of those chunks we
+ * can not control.
+ */
+ typedef StackAllocator<256, int> LeafStackAllocator;
+ typedef StackAllocator<256, float2> LeafTimeStackAllocator;
+ typedef StackAllocator<256, BVHReference> LeafReferenceStackAllocator;
+
+ vector<int, LeafStackAllocator> p_type[PRIMITIVE_NUM_TOTAL];
+ vector<int, LeafStackAllocator> p_index[PRIMITIVE_NUM_TOTAL];
+ vector<int, LeafStackAllocator> p_object[PRIMITIVE_NUM_TOTAL];
+ vector<float2, LeafTimeStackAllocator> p_time[PRIMITIVE_NUM_TOTAL];
+ vector<BVHReference, LeafReferenceStackAllocator> p_ref[PRIMITIVE_NUM_TOTAL];
+
+ /* TODO(sergey): In theory we should be able to store references. */
+ vector<BVHReference, LeafReferenceStackAllocator> object_references;
+
+ uint visibility[PRIMITIVE_NUM_TOTAL] = {0};
+ /* NOTE: Keep initializtion in sync with actual number of primitives. */
+ BoundBox bounds[PRIMITIVE_NUM_TOTAL] = {
+ BoundBox::empty, BoundBox::empty, BoundBox::empty, BoundBox::empty};
+ int ob_num = 0;
+ int num_new_prims = 0;
+ /* Fill in per-type type/index array. */
+ for (int i = 0; i < range.size(); i++) {
+ const BVHReference &ref = references[range.start() + i];
+ if (ref.prim_index() != -1) {
+ int type_index = bitscan(ref.prim_type() & PRIMITIVE_ALL);
+ p_ref[type_index].push_back(ref);
+ p_type[type_index].push_back(ref.prim_type());
+ p_index[type_index].push_back(ref.prim_index());
+ p_object[type_index].push_back(ref.prim_object());
+ p_time[type_index].push_back(make_float2(ref.time_from(), ref.time_to()));
+
+ bounds[type_index].grow(ref.bounds());
+ visibility[type_index] |= objects[ref.prim_object()]->visibility_for_tracing();
+ if (ref.prim_type() & PRIMITIVE_ALL_CURVE) {
+ visibility[type_index] |= PATH_RAY_CURVE;
+ }
+ ++num_new_prims;
+ }
+ else {
+ object_references.push_back(ref);
+ ++ob_num;
+ }
+ }
+
+ /* Create leaf nodes for every existing primitive.
+ *
+ * Here we write primitive types, indices and objects to a temporary array.
+ * This way we keep all the heavy memory allocation code outside of the
+ * thread lock in the case of spatial split building.
+ *
+ * TODO(sergey): With some pointer trickery we can write directly to the
+ * destination buffers for the non-spatial split BVH.
+ */
+ BVHNode *leaves[PRIMITIVE_NUM_TOTAL + 1] = {NULL};
+ int num_leaves = 0;
+ size_t start_index = 0;
+ vector<int, LeafStackAllocator> local_prim_type, local_prim_index, local_prim_object;
+ vector<float2, LeafTimeStackAllocator> local_prim_time;
+ local_prim_type.resize(num_new_prims);
+ local_prim_index.resize(num_new_prims);
+ local_prim_object.resize(num_new_prims);
+ if (need_prim_time) {
+ local_prim_time.resize(num_new_prims);
+ }
+ for (int i = 0; i < PRIMITIVE_NUM_TOTAL; ++i) {
+ int num = (int)p_type[i].size();
+ if (num != 0) {
+ assert(p_type[i].size() == p_index[i].size());
+ assert(p_type[i].size() == p_object[i].size());
+ Transform aligned_space;
+ bool alignment_found = false;
+ for (int j = 0; j < num; ++j) {
+ const int index = start_index + j;
+ local_prim_type[index] = p_type[i][j];
+ local_prim_index[index] = p_index[i][j];
+ local_prim_object[index] = p_object[i][j];
+ if (need_prim_time) {
+ local_prim_time[index] = p_time[i][j];
+ }
+ if (params.use_unaligned_nodes && !alignment_found) {
+ alignment_found = unaligned_heuristic.compute_aligned_space(p_ref[i][j], &aligned_space);
+ }
+ }
+ LeafNode *leaf_node = new LeafNode(bounds[i], visibility[i], start_index, start_index + num);
+ if (true) {
+ float time_from = 1.0f, time_to = 0.0f;
+ for (int j = 0; j < num; ++j) {
+ const BVHReference &ref = p_ref[i][j];
+ time_from = min(time_from, ref.time_from());
+ time_to = max(time_to, ref.time_to());
+ }
+ leaf_node->time_from = time_from;
+ leaf_node->time_to = time_to;
+ }
+ if (alignment_found) {
+ /* Need to recalculate leaf bounds with new alignment. */
+ leaf_node->bounds = BoundBox::empty;
+ for (int j = 0; j < num; ++j) {
+ const BVHReference &ref = p_ref[i][j];
+ BoundBox ref_bounds = unaligned_heuristic.compute_aligned_prim_boundbox(ref,
+ aligned_space);
+ leaf_node->bounds.grow(ref_bounds);
+ }
+ /* Set alignment space. */
+ leaf_node->set_aligned_space(aligned_space);
+ }
+ leaves[num_leaves++] = leaf_node;
+ start_index += num;
+ }
+ }
+ /* Get size of new data to be copied to the packed arrays. */
+ const int num_new_leaf_data = start_index;
+ const size_t new_leaf_data_size = sizeof(int) * num_new_leaf_data;
+ /* Copy actual data to the packed array. */
+ if (params.use_spatial_split) {
+ spatial_spin_lock.lock();
+ /* We use first free index in the packed arrays and mode pointer to the
+ * end of the current range.
+ *
+ * This doesn't give deterministic packed arrays, but it shouldn't really
+ * matter because order of children in BVH is deterministic.
+ */
+ start_index = spatial_free_index;
+ spatial_free_index += range.size();
+ /* Extend an array when needed. */
+ const size_t range_end = start_index + range.size();
+ if (prim_type.size() < range_end) {
+ /* Avoid extra re-allocations by pre-allocating bigger array in an
+ * advance.
+ */
+ if (range_end >= prim_type.capacity()) {
+ float progress = (float)progress_count / (float)progress_total;
+ float factor = (1.0f - progress);
+ const size_t reserve = (size_t)(range_end + (float)range_end * factor);
+ prim_type.reserve(reserve);
+ prim_index.reserve(reserve);
+ prim_object.reserve(reserve);
+ if (need_prim_time) {
+ prim_time.reserve(reserve);
+ }
+ }
+
+ prim_type.resize(range_end);
+ prim_index.resize(range_end);
+ prim_object.resize(range_end);
+ if (need_prim_time) {
+ prim_time.resize(range_end);
+ }
+ }
+ /* Perform actual data copy. */
+ if (new_leaf_data_size > 0) {
+ memcpy(&prim_type[start_index], &local_prim_type[0], new_leaf_data_size);
+ memcpy(&prim_index[start_index], &local_prim_index[0], new_leaf_data_size);
+ memcpy(&prim_object[start_index], &local_prim_object[0], new_leaf_data_size);
+ if (need_prim_time) {
+ memcpy(&prim_time[start_index], &local_prim_time[0], sizeof(float2) * num_new_leaf_data);
+ }
+ }
+ spatial_spin_lock.unlock();
+ }
+ else {
+ /* For the regular BVH builder we simply copy new data starting at the
+ * range start. This is totally thread-safe, all threads are living
+ * inside of their own range.
+ */
+ start_index = range.start();
+ if (new_leaf_data_size > 0) {
+ memcpy(&prim_type[start_index], &local_prim_type[0], new_leaf_data_size);
+ memcpy(&prim_index[start_index], &local_prim_index[0], new_leaf_data_size);
+ memcpy(&prim_object[start_index], &local_prim_object[0], new_leaf_data_size);
+ if (need_prim_time) {
+ memcpy(&prim_time[start_index], &local_prim_time[0], sizeof(float2) * num_new_leaf_data);
+ }
+ }
+ }
+
+ /* So far leaves were created with the zero-based index in an arrays,
+ * here we modify the indices to correspond to actual packed array start
+ * index.
+ */
+ for (int i = 0; i < num_leaves; ++i) {
+ LeafNode *leaf = (LeafNode *)leaves[i];
+ leaf->lo += start_index;
+ leaf->hi += start_index;
+ }
+
+ /* Create leaf node for object. */
+ if (num_leaves == 0 || ob_num) {
+ /* Only create object leaf nodes if there are objects or no other
+ * nodes created.
+ */
+ const BVHReference *ref = (ob_num) ? &object_references[0] : NULL;
+ leaves[num_leaves] = create_object_leaf_nodes(ref, start_index + num_new_leaf_data, ob_num);
+ ++num_leaves;
+ }
+
+ /* TODO(sergey): Need to take care of alignment when number of leaves
+ * is more than 1.
+ */
+ if (num_leaves == 1) {
+ /* Simplest case: single leaf, just return it.
+ * In all the rest cases we'll be creating intermediate inner node with
+ * an appropriate bounding box.
+ */
+ return leaves[0];
+ }
+ else if (num_leaves == 2) {
+ return new InnerNode(range.bounds(), leaves[0], leaves[1]);
+ }
+ else if (num_leaves == 3) {
+ BoundBox inner_bounds = merge(leaves[1]->bounds, leaves[2]->bounds);
+ BVHNode *inner = new InnerNode(inner_bounds, leaves[1], leaves[2]);
+ return new InnerNode(range.bounds(), leaves[0], inner);
+ }
+ else {
+ /* Should be doing more branches if more primitive types added. */
+ assert(num_leaves <= 5);
+ BoundBox inner_bounds_a = merge(leaves[0]->bounds, leaves[1]->bounds);
+ BoundBox inner_bounds_b = merge(leaves[2]->bounds, leaves[3]->bounds);
+ BVHNode *inner_a = new InnerNode(inner_bounds_a, leaves[0], leaves[1]);
+ BVHNode *inner_b = new InnerNode(inner_bounds_b, leaves[2], leaves[3]);
+ BoundBox inner_bounds_c = merge(inner_a->bounds, inner_b->bounds);
+ BVHNode *inner_c = new InnerNode(inner_bounds_c, inner_a, inner_b);
+ if (num_leaves == 5) {
+ return new InnerNode(range.bounds(), inner_c, leaves[4]);
+ }
+ return inner_c;
+ }
#undef MAX_ITEMS_PER_LEAF
}
@@ -1154,81 +1081,81 @@ BVHNode* BVHBuild::create_leaf_node(const BVHRange& range,
void BVHBuild::rotate(BVHNode *node, int max_depth, int iterations)
{
- /* in tested scenes, this resulted in slightly slower raytracing, so disabled
- * it for now. could be implementation bug, or depend on the scene */
- if(node)
- for(int i = 0; i < iterations; i++)
- rotate(node, max_depth);
+ /* in tested scenes, this resulted in slightly slower raytracing, so disabled
+ * it for now. could be implementation bug, or depend on the scene */
+ if (node)
+ for (int i = 0; i < iterations; i++)
+ rotate(node, max_depth);
}
void BVHBuild::rotate(BVHNode *node, int max_depth)
{
- /* nothing to rotate if we reached a leaf node. */
- if(node->is_leaf() || max_depth < 0)
- return;
-
- InnerNode *parent = (InnerNode*)node;
-
- /* rotate all children first */
- for(size_t c = 0; c < 2; c++)
- rotate(parent->children[c], max_depth-1);
-
- /* compute current area of all children */
- BoundBox bounds0 = parent->children[0]->bounds;
- BoundBox bounds1 = parent->children[1]->bounds;
-
- float area0 = bounds0.half_area();
- float area1 = bounds1.half_area();
- float4 child_area = make_float4(area0, area1, 0.0f, 0.0f);
-
- /* find best rotation. we pick a target child of a first child, and swap
- * this with an other child. we perform the best such swap. */
- float best_cost = FLT_MAX;
- int best_child = -1, best_target = -1, best_other = -1;
-
- for(size_t c = 0; c < 2; c++) {
- /* ignore leaf nodes as we cannot descent into */
- if(parent->children[c]->is_leaf())
- continue;
-
- InnerNode *child = (InnerNode*)parent->children[c];
- BoundBox& other = (c == 0)? bounds1: bounds0;
-
- /* transpose child bounds */
- BoundBox target0 = child->children[0]->bounds;
- BoundBox target1 = child->children[1]->bounds;
-
- /* compute cost for both possible swaps */
- float cost0 = merge(other, target1).half_area() - child_area[c];
- float cost1 = merge(target0, other).half_area() - child_area[c];
-
- if(min(cost0,cost1) < best_cost) {
- best_child = (int)c;
- best_other = (int)(1-c);
-
- if(cost0 < cost1) {
- best_cost = cost0;
- best_target = 0;
- }
- else {
- best_cost = cost0;
- best_target = 1;
- }
- }
- }
-
- /* if we did not find a swap that improves the SAH then do nothing */
- if(best_cost >= 0)
- return;
-
- assert(best_child == 0 || best_child == 1);
- assert(best_target != -1);
-
- /* perform the best found tree rotation */
- InnerNode *child = (InnerNode*)parent->children[best_child];
-
- swap(parent->children[best_other], child->children[best_target]);
- child->bounds = merge(child->children[0]->bounds, child->children[1]->bounds);
+ /* nothing to rotate if we reached a leaf node. */
+ if (node->is_leaf() || max_depth < 0)
+ return;
+
+ InnerNode *parent = (InnerNode *)node;
+
+ /* rotate all children first */
+ for (size_t c = 0; c < 2; c++)
+ rotate(parent->children[c], max_depth - 1);
+
+ /* compute current area of all children */
+ BoundBox bounds0 = parent->children[0]->bounds;
+ BoundBox bounds1 = parent->children[1]->bounds;
+
+ float area0 = bounds0.half_area();
+ float area1 = bounds1.half_area();
+ float4 child_area = make_float4(area0, area1, 0.0f, 0.0f);
+
+ /* find best rotation. we pick a target child of a first child, and swap
+ * this with an other child. we perform the best such swap. */
+ float best_cost = FLT_MAX;
+ int best_child = -1, best_target = -1, best_other = -1;
+
+ for (size_t c = 0; c < 2; c++) {
+ /* ignore leaf nodes as we cannot descent into */
+ if (parent->children[c]->is_leaf())
+ continue;
+
+ InnerNode *child = (InnerNode *)parent->children[c];
+ BoundBox &other = (c == 0) ? bounds1 : bounds0;
+
+ /* transpose child bounds */
+ BoundBox target0 = child->children[0]->bounds;
+ BoundBox target1 = child->children[1]->bounds;
+
+ /* compute cost for both possible swaps */
+ float cost0 = merge(other, target1).half_area() - child_area[c];
+ float cost1 = merge(target0, other).half_area() - child_area[c];
+
+ if (min(cost0, cost1) < best_cost) {
+ best_child = (int)c;
+ best_other = (int)(1 - c);
+
+ if (cost0 < cost1) {
+ best_cost = cost0;
+ best_target = 0;
+ }
+ else {
+ best_cost = cost0;
+ best_target = 1;
+ }
+ }
+ }
+
+ /* if we did not find a swap that improves the SAH then do nothing */
+ if (best_cost >= 0)
+ return;
+
+ assert(best_child == 0 || best_child == 1);
+ assert(best_target != -1);
+
+ /* perform the best found tree rotation */
+ InnerNode *child = (InnerNode *)parent->children[best_child];
+
+ swap(parent->children[best_other], child->children[best_target]);
+ child->bounds = merge(child->children[0]->bounds, child->children[1]->bounds);
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/bvh/bvh_build.h b/intern/cycles/bvh/bvh_build.h
index dd95a5cc0e8..9685e26cfac 100644
--- a/intern/cycles/bvh/bvh_build.h
+++ b/intern/cycles/bvh/bvh_build.h
@@ -41,106 +41,101 @@ class Progress;
/* BVH Builder */
-class BVHBuild
-{
-public:
- /* Constructor/Destructor */
- BVHBuild(const vector<Object*>& objects,
- array<int>& prim_type,
- array<int>& prim_index,
- array<int>& prim_object,
- array<float2>& prim_time,
- const BVHParams& params,
- Progress& progress);
- ~BVHBuild();
-
- BVHNode *run();
-
-protected:
- friend class BVHMixedSplit;
- friend class BVHObjectSplit;
- friend class BVHSpatialSplit;
- friend class BVHBuildTask;
- friend class BVHSpatialSplitBuildTask;
- friend class BVHObjectBinning;
-
- /* Adding references. */
- void add_reference_triangles(BoundBox& root, BoundBox& center, Mesh *mesh, int i);
- void add_reference_curves(BoundBox& root, BoundBox& center, Mesh *mesh, int i);
- void add_reference_mesh(BoundBox& root, BoundBox& center, Mesh *mesh, int i);
- void add_reference_object(BoundBox& root, BoundBox& center, Object *ob, int i);
- void add_references(BVHRange& root);
-
- /* Building. */
- BVHNode *build_node(const BVHRange& range,
- vector<BVHReference> *references,
- int level,
- int thread_id);
- BVHNode *build_node(const BVHObjectBinning& range, int level);
- BVHNode *create_leaf_node(const BVHRange& range,
- const vector<BVHReference>& references);
- BVHNode *create_object_leaf_nodes(const BVHReference *ref, int start, int num);
-
- bool range_within_max_leaf_size(const BVHRange& range,
- const vector<BVHReference>& references) const;
-
- /* Threads. */
- enum { THREAD_TASK_SIZE = 4096 };
- void thread_build_node(InnerNode *node,
- int child,
- BVHObjectBinning *range,
- int level);
- void thread_build_spatial_split_node(InnerNode *node,
- int child,
- BVHRange *range,
- vector<BVHReference> *references,
- int level,
- int thread_id);
- thread_mutex build_mutex;
-
- /* Progress. */
- void progress_update();
-
- /* Tree rotations. */
- void rotate(BVHNode *node, int max_depth);
- void rotate(BVHNode *node, int max_depth, int iterations);
-
- /* Objects and primitive references. */
- vector<Object*> objects;
- vector<BVHReference> references;
- int num_original_references;
-
- /* Output primitive indexes and objects. */
- array<int>& prim_type;
- array<int>& prim_index;
- array<int>& prim_object;
- array<float2>& prim_time;
-
- bool need_prim_time;
-
- /* Build parameters. */
- BVHParams params;
-
- /* Progress reporting. */
- Progress& progress;
- double progress_start_time;
- size_t progress_count;
- size_t progress_total;
- size_t progress_original_total;
-
- /* Spatial splitting. */
- float spatial_min_overlap;
- vector<BVHSpatialStorage> spatial_storage;
- size_t spatial_free_index;
- thread_spin_lock spatial_spin_lock;
-
- /* Threads. */
- TaskPool task_pool;
-
- /* Unaligned building. */
- BVHUnaligned unaligned_heuristic;
+class BVHBuild {
+ public:
+ /* Constructor/Destructor */
+ BVHBuild(const vector<Object *> &objects,
+ array<int> &prim_type,
+ array<int> &prim_index,
+ array<int> &prim_object,
+ array<float2> &prim_time,
+ const BVHParams &params,
+ Progress &progress);
+ ~BVHBuild();
+
+ BVHNode *run();
+
+ protected:
+ friend class BVHMixedSplit;
+ friend class BVHObjectSplit;
+ friend class BVHSpatialSplit;
+ friend class BVHBuildTask;
+ friend class BVHSpatialSplitBuildTask;
+ friend class BVHObjectBinning;
+
+ /* Adding references. */
+ void add_reference_triangles(BoundBox &root, BoundBox &center, Mesh *mesh, int i);
+ void add_reference_curves(BoundBox &root, BoundBox &center, Mesh *mesh, int i);
+ void add_reference_mesh(BoundBox &root, BoundBox &center, Mesh *mesh, int i);
+ void add_reference_object(BoundBox &root, BoundBox &center, Object *ob, int i);
+ void add_references(BVHRange &root);
+
+ /* Building. */
+ BVHNode *build_node(const BVHRange &range,
+ vector<BVHReference> *references,
+ int level,
+ int thread_id);
+ BVHNode *build_node(const BVHObjectBinning &range, int level);
+ BVHNode *create_leaf_node(const BVHRange &range, const vector<BVHReference> &references);
+ BVHNode *create_object_leaf_nodes(const BVHReference *ref, int start, int num);
+
+ bool range_within_max_leaf_size(const BVHRange &range,
+ const vector<BVHReference> &references) const;
+
+ /* Threads. */
+ enum { THREAD_TASK_SIZE = 4096 };
+ void thread_build_node(InnerNode *node, int child, BVHObjectBinning *range, int level);
+ void thread_build_spatial_split_node(InnerNode *node,
+ int child,
+ BVHRange *range,
+ vector<BVHReference> *references,
+ int level,
+ int thread_id);
+ thread_mutex build_mutex;
+
+ /* Progress. */
+ void progress_update();
+
+ /* Tree rotations. */
+ void rotate(BVHNode *node, int max_depth);
+ void rotate(BVHNode *node, int max_depth, int iterations);
+
+ /* Objects and primitive references. */
+ vector<Object *> objects;
+ vector<BVHReference> references;
+ int num_original_references;
+
+ /* Output primitive indexes and objects. */
+ array<int> &prim_type;
+ array<int> &prim_index;
+ array<int> &prim_object;
+ array<float2> &prim_time;
+
+ bool need_prim_time;
+
+ /* Build parameters. */
+ BVHParams params;
+
+ /* Progress reporting. */
+ Progress &progress;
+ double progress_start_time;
+ size_t progress_count;
+ size_t progress_total;
+ size_t progress_original_total;
+
+ /* Spatial splitting. */
+ float spatial_min_overlap;
+ vector<BVHSpatialStorage> spatial_storage;
+ size_t spatial_free_index;
+ thread_spin_lock spatial_spin_lock;
+
+ /* Threads. */
+ TaskPool task_pool;
+
+ /* Unaligned building. */
+ BVHUnaligned unaligned_heuristic;
};
CCL_NAMESPACE_END
-#endif /* __BVH_BUILD_H__ */
+#endif /* __BVH_BUILD_H__ */
diff --git a/intern/cycles/bvh/bvh_embree.cpp b/intern/cycles/bvh/bvh_embree.cpp
index fa9993d8ac3..5ef9622aba2 100644
--- a/intern/cycles/bvh/bvh_embree.cpp
+++ b/intern/cycles/bvh/bvh_embree.cpp
@@ -34,28 +34,28 @@
#ifdef WITH_EMBREE
-#include <pmmintrin.h>
-#include <xmmintrin.h>
-#include <embree3/rtcore_geometry.h>
+# include <pmmintrin.h>
+# include <xmmintrin.h>
+# include <embree3/rtcore_geometry.h>
-#include "bvh/bvh_embree.h"
+# include "bvh/bvh_embree.h"
/* Kernel includes are necessary so that the filter function for Embree can access the packed BVH. */
-#include "kernel/bvh/bvh_embree.h"
-#include "kernel/kernel_compat_cpu.h"
-#include "kernel/split/kernel_split_data_types.h"
-#include "kernel/kernel_globals.h"
-#include "kernel/kernel_random.h"
-
-#include "render/mesh.h"
-#include "render/object.h"
-#include "util/util_foreach.h"
-#include "util/util_logging.h"
-#include "util/util_progress.h"
+# include "kernel/bvh/bvh_embree.h"
+# include "kernel/kernel_compat_cpu.h"
+# include "kernel/split/kernel_split_data_types.h"
+# include "kernel/kernel_globals.h"
+# include "kernel/kernel_random.h"
+
+# include "render/mesh.h"
+# include "render/object.h"
+# include "util/util_foreach.h"
+# include "util/util_logging.h"
+# include "util/util_progress.h"
CCL_NAMESPACE_BEGIN
-#define IS_HAIR(x) (x & 1)
+# define IS_HAIR(x) (x & 1)
/* This gets called by Embree at every valid ray/object intersection.
* Things like recording subsurface or shadow hits for later evaluation
@@ -64,215 +64,217 @@ CCL_NAMESPACE_BEGIN
*/
static void rtc_filter_func(const RTCFilterFunctionNArguments *args)
{
- /* Current implementation in Cycles assumes only single-ray intersection queries. */
- assert(args->N == 1);
-
- const RTCRay *ray = (RTCRay*)args->ray;
- const RTCHit *hit = (RTCHit*)args->hit;
- CCLIntersectContext *ctx = ((IntersectContext*)args->context)->userRayExt;
- KernelGlobals *kg = ctx->kg;
-
- /* Check if there is backfacing hair to ignore. */
- if(IS_HAIR(hit->geomID) && (kernel_data.curve.curveflags & CURVE_KN_INTERPOLATE)
- && !(kernel_data.curve.curveflags & CURVE_KN_BACKFACING)
- && !(kernel_data.curve.curveflags & CURVE_KN_RIBBONS)) {
- if(dot(make_float3(ray->dir_x, ray->dir_y, ray->dir_z), make_float3(hit->Ng_x, hit->Ng_y, hit->Ng_z)) > 0.0f) {
- *args->valid = 0;
- return;
- }
- }
+ /* Current implementation in Cycles assumes only single-ray intersection queries. */
+ assert(args->N == 1);
+
+ const RTCRay *ray = (RTCRay *)args->ray;
+ const RTCHit *hit = (RTCHit *)args->hit;
+ CCLIntersectContext *ctx = ((IntersectContext *)args->context)->userRayExt;
+ KernelGlobals *kg = ctx->kg;
+
+ /* Check if there is backfacing hair to ignore. */
+ if (IS_HAIR(hit->geomID) && (kernel_data.curve.curveflags & CURVE_KN_INTERPOLATE) &&
+ !(kernel_data.curve.curveflags & CURVE_KN_BACKFACING) &&
+ !(kernel_data.curve.curveflags & CURVE_KN_RIBBONS)) {
+ if (dot(make_float3(ray->dir_x, ray->dir_y, ray->dir_z),
+ make_float3(hit->Ng_x, hit->Ng_y, hit->Ng_z)) > 0.0f) {
+ *args->valid = 0;
+ return;
+ }
+ }
}
-static void rtc_filter_occluded_func(const RTCFilterFunctionNArguments* args)
+static void rtc_filter_occluded_func(const RTCFilterFunctionNArguments *args)
{
- assert(args->N == 1);
-
- const RTCRay *ray = (RTCRay*)args->ray;
- RTCHit *hit = (RTCHit*)args->hit;
- CCLIntersectContext *ctx = ((IntersectContext*)args->context)->userRayExt;
- KernelGlobals *kg = ctx->kg;
-
- /* For all ray types: Check if there is backfacing hair to ignore */
- if(IS_HAIR(hit->geomID) && (kernel_data.curve.curveflags & CURVE_KN_INTERPOLATE)
- && !(kernel_data.curve.curveflags & CURVE_KN_BACKFACING)
- && !(kernel_data.curve.curveflags & CURVE_KN_RIBBONS)) {
- if(dot(make_float3(ray->dir_x, ray->dir_y, ray->dir_z), make_float3(hit->Ng_x, hit->Ng_y, hit->Ng_z)) > 0.0f) {
- *args->valid = 0;
- return;
- }
- }
-
- switch(ctx->type) {
- case CCLIntersectContext::RAY_SHADOW_ALL: {
- /* Append the intersection to the end of the array. */
- if(ctx->num_hits < ctx->max_hits) {
- Intersection current_isect;
- kernel_embree_convert_hit(kg, ray, hit, &current_isect);
- for(size_t i = 0; i < ctx->max_hits; ++i) {
- if(current_isect.object == ctx->isect_s[i].object &&
- current_isect.prim == ctx->isect_s[i].prim &&
- current_isect.t == ctx->isect_s[i].t) {
- /* This intersection was already recorded, skip it. */
- *args->valid = 0;
- break;
- }
- }
- Intersection *isect = &ctx->isect_s[ctx->num_hits];
- ++ctx->num_hits;
- *isect = current_isect;
- int prim = kernel_tex_fetch(__prim_index, isect->prim);
- int shader = 0;
- if(kernel_tex_fetch(__prim_type, isect->prim) & PRIMITIVE_ALL_TRIANGLE) {
- shader = kernel_tex_fetch(__tri_shader, prim);
- }
- else {
- float4 str = kernel_tex_fetch(__curves, prim);
- shader = __float_as_int(str.z);
- }
- int flag = kernel_tex_fetch(__shaders, shader & SHADER_MASK).flags;
- /* If no transparent shadows, all light is blocked. */
- if(flag & (SD_HAS_TRANSPARENT_SHADOW)) {
- /* This tells Embree to continue tracing. */
- *args->valid = 0;
- }
- }
- else {
- /* Increase the number of hits beyond ray.max_hits
- * so that the caller can detect this as opaque. */
- ++ctx->num_hits;
- }
- break;
- }
- case CCLIntersectContext::RAY_SSS: {
- /* No intersection information requested, just return a hit. */
- if(ctx->max_hits == 0) {
- break;
- }
-
- /* Ignore curves. */
- if(hit->geomID & 1) {
- /* This tells Embree to continue tracing. */
- *args->valid = 0;
- break;
- }
-
- /* See triangle_intersect_subsurface() for the native equivalent. */
- for(int i = min(ctx->max_hits, ctx->ss_isect->num_hits) - 1; i >= 0; --i) {
- if(ctx->ss_isect->hits[i].t == ray->tfar) {
- /* This tells Embree to continue tracing. */
- *args->valid = 0;
- break;
- }
- }
-
- ++ctx->ss_isect->num_hits;
- int hit_idx;
-
- if(ctx->ss_isect->num_hits <= ctx->max_hits) {
- hit_idx = ctx->ss_isect->num_hits - 1;
- }
- else {
- /* reservoir sampling: if we are at the maximum number of
- * hits, randomly replace element or skip it */
- hit_idx = lcg_step_uint(ctx->lcg_state) % ctx->ss_isect->num_hits;
-
- if(hit_idx >= ctx->max_hits) {
- /* This tells Embree to continue tracing. */
- *args->valid = 0;
- break;
- }
- }
- /* record intersection */
- kernel_embree_convert_local_hit(kg, ray, hit, &ctx->ss_isect->hits[hit_idx], ctx->sss_object_id);
- ctx->ss_isect->Ng[hit_idx].x = hit->Ng_x;
- ctx->ss_isect->Ng[hit_idx].y = hit->Ng_y;
- ctx->ss_isect->Ng[hit_idx].z = hit->Ng_z;
- ctx->ss_isect->Ng[hit_idx] = normalize(ctx->ss_isect->Ng[hit_idx]);
- /* This tells Embree to continue tracing .*/
- *args->valid = 0;
- break;
- }
- case CCLIntersectContext::RAY_VOLUME_ALL: {
- /* Append the intersection to the end of the array. */
- if(ctx->num_hits < ctx->max_hits) {
- Intersection current_isect;
- kernel_embree_convert_hit(kg, ray, hit, &current_isect);
- for(size_t i = 0; i < ctx->max_hits; ++i) {
- if(current_isect.object == ctx->isect_s[i].object &&
- current_isect.prim == ctx->isect_s[i].prim &&
- current_isect.t == ctx->isect_s[i].t) {
- /* This intersection was already recorded, skip it. */
- *args->valid = 0;
- break;
- }
- }
- Intersection *isect = &ctx->isect_s[ctx->num_hits];
- ++ctx->num_hits;
- *isect = current_isect;
- /* Only primitives from volume object. */
- uint tri_object = (isect->object == OBJECT_NONE) ?
- kernel_tex_fetch(__prim_object, isect->prim) : isect->object;
- int object_flag = kernel_tex_fetch(__object_flag, tri_object);
- if((object_flag & SD_OBJECT_HAS_VOLUME) == 0) {
- --ctx->num_hits;
- }
- /* This tells Embree to continue tracing. */
- *args->valid = 0;
- break;
- }
- }
- case CCLIntersectContext::RAY_REGULAR:
- default:
- /* Nothing to do here. */
- break;
- }
+ assert(args->N == 1);
+
+ const RTCRay *ray = (RTCRay *)args->ray;
+ RTCHit *hit = (RTCHit *)args->hit;
+ CCLIntersectContext *ctx = ((IntersectContext *)args->context)->userRayExt;
+ KernelGlobals *kg = ctx->kg;
+
+ /* For all ray types: Check if there is backfacing hair to ignore */
+ if (IS_HAIR(hit->geomID) && (kernel_data.curve.curveflags & CURVE_KN_INTERPOLATE) &&
+ !(kernel_data.curve.curveflags & CURVE_KN_BACKFACING) &&
+ !(kernel_data.curve.curveflags & CURVE_KN_RIBBONS)) {
+ if (dot(make_float3(ray->dir_x, ray->dir_y, ray->dir_z),
+ make_float3(hit->Ng_x, hit->Ng_y, hit->Ng_z)) > 0.0f) {
+ *args->valid = 0;
+ return;
+ }
+ }
+
+ switch (ctx->type) {
+ case CCLIntersectContext::RAY_SHADOW_ALL: {
+ /* Append the intersection to the end of the array. */
+ if (ctx->num_hits < ctx->max_hits) {
+ Intersection current_isect;
+ kernel_embree_convert_hit(kg, ray, hit, &current_isect);
+ for (size_t i = 0; i < ctx->max_hits; ++i) {
+ if (current_isect.object == ctx->isect_s[i].object &&
+ current_isect.prim == ctx->isect_s[i].prim && current_isect.t == ctx->isect_s[i].t) {
+ /* This intersection was already recorded, skip it. */
+ *args->valid = 0;
+ break;
+ }
+ }
+ Intersection *isect = &ctx->isect_s[ctx->num_hits];
+ ++ctx->num_hits;
+ *isect = current_isect;
+ int prim = kernel_tex_fetch(__prim_index, isect->prim);
+ int shader = 0;
+ if (kernel_tex_fetch(__prim_type, isect->prim) & PRIMITIVE_ALL_TRIANGLE) {
+ shader = kernel_tex_fetch(__tri_shader, prim);
+ }
+ else {
+ float4 str = kernel_tex_fetch(__curves, prim);
+ shader = __float_as_int(str.z);
+ }
+ int flag = kernel_tex_fetch(__shaders, shader & SHADER_MASK).flags;
+ /* If no transparent shadows, all light is blocked. */
+ if (flag & (SD_HAS_TRANSPARENT_SHADOW)) {
+ /* This tells Embree to continue tracing. */
+ *args->valid = 0;
+ }
+ }
+ else {
+ /* Increase the number of hits beyond ray.max_hits
+ * so that the caller can detect this as opaque. */
+ ++ctx->num_hits;
+ }
+ break;
+ }
+ case CCLIntersectContext::RAY_SSS: {
+ /* No intersection information requested, just return a hit. */
+ if (ctx->max_hits == 0) {
+ break;
+ }
+
+ /* Ignore curves. */
+ if (hit->geomID & 1) {
+ /* This tells Embree to continue tracing. */
+ *args->valid = 0;
+ break;
+ }
+
+ /* See triangle_intersect_subsurface() for the native equivalent. */
+ for (int i = min(ctx->max_hits, ctx->ss_isect->num_hits) - 1; i >= 0; --i) {
+ if (ctx->ss_isect->hits[i].t == ray->tfar) {
+ /* This tells Embree to continue tracing. */
+ *args->valid = 0;
+ break;
+ }
+ }
+
+ ++ctx->ss_isect->num_hits;
+ int hit_idx;
+
+ if (ctx->ss_isect->num_hits <= ctx->max_hits) {
+ hit_idx = ctx->ss_isect->num_hits - 1;
+ }
+ else {
+ /* reservoir sampling: if we are at the maximum number of
+ * hits, randomly replace element or skip it */
+ hit_idx = lcg_step_uint(ctx->lcg_state) % ctx->ss_isect->num_hits;
+
+ if (hit_idx >= ctx->max_hits) {
+ /* This tells Embree to continue tracing. */
+ *args->valid = 0;
+ break;
+ }
+ }
+ /* record intersection */
+ kernel_embree_convert_local_hit(
+ kg, ray, hit, &ctx->ss_isect->hits[hit_idx], ctx->sss_object_id);
+ ctx->ss_isect->Ng[hit_idx].x = hit->Ng_x;
+ ctx->ss_isect->Ng[hit_idx].y = hit->Ng_y;
+ ctx->ss_isect->Ng[hit_idx].z = hit->Ng_z;
+ ctx->ss_isect->Ng[hit_idx] = normalize(ctx->ss_isect->Ng[hit_idx]);
+ /* This tells Embree to continue tracing .*/
+ *args->valid = 0;
+ break;
+ }
+ case CCLIntersectContext::RAY_VOLUME_ALL: {
+ /* Append the intersection to the end of the array. */
+ if (ctx->num_hits < ctx->max_hits) {
+ Intersection current_isect;
+ kernel_embree_convert_hit(kg, ray, hit, &current_isect);
+ for (size_t i = 0; i < ctx->max_hits; ++i) {
+ if (current_isect.object == ctx->isect_s[i].object &&
+ current_isect.prim == ctx->isect_s[i].prim && current_isect.t == ctx->isect_s[i].t) {
+ /* This intersection was already recorded, skip it. */
+ *args->valid = 0;
+ break;
+ }
+ }
+ Intersection *isect = &ctx->isect_s[ctx->num_hits];
+ ++ctx->num_hits;
+ *isect = current_isect;
+ /* Only primitives from volume object. */
+ uint tri_object = (isect->object == OBJECT_NONE) ?
+ kernel_tex_fetch(__prim_object, isect->prim) :
+ isect->object;
+ int object_flag = kernel_tex_fetch(__object_flag, tri_object);
+ if ((object_flag & SD_OBJECT_HAS_VOLUME) == 0) {
+ --ctx->num_hits;
+ }
+ /* This tells Embree to continue tracing. */
+ *args->valid = 0;
+ break;
+ }
+ }
+ case CCLIntersectContext::RAY_REGULAR:
+ default:
+ /* Nothing to do here. */
+ break;
+ }
}
static size_t unaccounted_mem = 0;
-static bool rtc_memory_monitor_func(void* userPtr, const ssize_t bytes, const bool)
+static bool rtc_memory_monitor_func(void *userPtr, const ssize_t bytes, const bool)
{
- Stats *stats = (Stats*)userPtr;
- if(stats) {
- if(bytes > 0) {
- stats->mem_alloc(bytes);
- }
- else {
- stats->mem_free(-bytes);
- }
- }
- else {
- /* A stats pointer may not yet be available. Keep track of the memory usage for later. */
- if(bytes >= 0) {
- atomic_add_and_fetch_z(&unaccounted_mem, bytes);
- }
- else {
- atomic_sub_and_fetch_z(&unaccounted_mem, -bytes);
- }
- }
- return true;
+ Stats *stats = (Stats *)userPtr;
+ if (stats) {
+ if (bytes > 0) {
+ stats->mem_alloc(bytes);
+ }
+ else {
+ stats->mem_free(-bytes);
+ }
+ }
+ else {
+ /* A stats pointer may not yet be available. Keep track of the memory usage for later. */
+ if (bytes >= 0) {
+ atomic_add_and_fetch_z(&unaccounted_mem, bytes);
+ }
+ else {
+ atomic_sub_and_fetch_z(&unaccounted_mem, -bytes);
+ }
+ }
+ return true;
}
-static void rtc_error_func(void*, enum RTCError, const char* str)
+static void rtc_error_func(void *, enum RTCError, const char *str)
{
- VLOG(1) << str;
+ VLOG(1) << str;
}
static double progress_start_time = 0.0f;
-static bool rtc_progress_func(void* user_ptr, const double n)
+static bool rtc_progress_func(void *user_ptr, const double n)
{
- Progress *progress = (Progress*)user_ptr;
+ Progress *progress = (Progress *)user_ptr;
- if(time_dt() - progress_start_time < 0.25) {
- return true;
- }
+ if (time_dt() - progress_start_time < 0.25) {
+ return true;
+ }
- string msg = string_printf("Building BVH %.0f%%", n * 100.0);
- progress->set_substatus(msg);
- progress_start_time = time_dt();
+ string msg = string_printf("Building BVH %.0f%%", n * 100.0);
+ progress->set_substatus(msg);
+ progress_start_time = time_dt();
- return !progress->get_cancel();
+ return !progress->get_cancel();
}
/* This is to have a shared device between all BVH instances.
@@ -281,665 +283,679 @@ RTCDevice BVHEmbree::rtc_shared_device = NULL;
int BVHEmbree::rtc_shared_users = 0;
thread_mutex BVHEmbree::rtc_shared_mutex;
-BVHEmbree::BVHEmbree(const BVHParams& params_, const vector<Object*>& objects_)
-: BVH(params_, objects_), scene(NULL), mem_used(0), top_level(NULL), stats(NULL),
- curve_subdivisions(params.curve_subdivisions), build_quality(RTC_BUILD_QUALITY_REFIT),
- use_curves(params_.curve_flags & CURVE_KN_INTERPOLATE),
- use_ribbons(params.curve_flags & CURVE_KN_RIBBONS), dynamic_scene(true)
+BVHEmbree::BVHEmbree(const BVHParams &params_, const vector<Object *> &objects_)
+ : BVH(params_, objects_),
+ scene(NULL),
+ mem_used(0),
+ top_level(NULL),
+ stats(NULL),
+ curve_subdivisions(params.curve_subdivisions),
+ build_quality(RTC_BUILD_QUALITY_REFIT),
+ use_curves(params_.curve_flags & CURVE_KN_INTERPOLATE),
+ use_ribbons(params.curve_flags & CURVE_KN_RIBBONS),
+ dynamic_scene(true)
{
- _MM_SET_FLUSH_ZERO_MODE(_MM_FLUSH_ZERO_ON);
- _MM_SET_DENORMALS_ZERO_MODE(_MM_DENORMALS_ZERO_ON);
- thread_scoped_lock lock(rtc_shared_mutex);
- if(rtc_shared_users == 0) {
- rtc_shared_device = rtcNewDevice("verbose=0");
- /* Check here if Embree was built with the correct flags. */
- ssize_t ret = rtcGetDeviceProperty (rtc_shared_device,RTC_DEVICE_PROPERTY_RAY_MASK_SUPPORTED);
- if(ret != 1) {
- assert(0);
- VLOG(1) << "Embree is compiled without the RTC_DEVICE_PROPERTY_RAY_MASK_SUPPORTED flag."\
- "Ray visiblity will not work.";
- }
- ret = rtcGetDeviceProperty (rtc_shared_device,RTC_DEVICE_PROPERTY_FILTER_FUNCTION_SUPPORTED);
- if(ret != 1) {
- assert(0);
- VLOG(1) << "Embree is compiled without the RTC_DEVICE_PROPERTY_FILTER_FUNCTION_SUPPORTED flag."\
- "Renders may not look as expected.";
- }
- ret = rtcGetDeviceProperty (rtc_shared_device,RTC_DEVICE_PROPERTY_CURVE_GEOMETRY_SUPPORTED);
- if(ret != 1) {
- assert(0);
- VLOG(1) << "Embree is compiled without the RTC_DEVICE_PROPERTY_CURVE_GEOMETRY_SUPPORTED flag. "\
- "Line primitives will not be rendered.";
- }
- ret = rtcGetDeviceProperty (rtc_shared_device,RTC_DEVICE_PROPERTY_TRIANGLE_GEOMETRY_SUPPORTED);
- if(ret != 1) {
- assert(0);
- VLOG(1) << "Embree is compiled without the RTC_DEVICE_PROPERTY_TRIANGLE_GEOMETRY_SUPPORTED flag. "\
- "Triangle primitives will not be rendered.";
- }
- ret = rtcGetDeviceProperty (rtc_shared_device,RTC_DEVICE_PROPERTY_BACKFACE_CULLING_ENABLED);
- if(ret != 0) {
- assert(0);
- VLOG(1) << "Embree is compiled with the RTC_DEVICE_PROPERTY_BACKFACE_CULLING_ENABLED flag. "\
- "Renders may not look as expected.";
- }
- }
- ++rtc_shared_users;
-
- rtcSetDeviceErrorFunction(rtc_shared_device, rtc_error_func, NULL);
-
- pack.root_index = -1;
+ _MM_SET_FLUSH_ZERO_MODE(_MM_FLUSH_ZERO_ON);
+ _MM_SET_DENORMALS_ZERO_MODE(_MM_DENORMALS_ZERO_ON);
+ thread_scoped_lock lock(rtc_shared_mutex);
+ if (rtc_shared_users == 0) {
+ rtc_shared_device = rtcNewDevice("verbose=0");
+ /* Check here if Embree was built with the correct flags. */
+ ssize_t ret = rtcGetDeviceProperty(rtc_shared_device, RTC_DEVICE_PROPERTY_RAY_MASK_SUPPORTED);
+ if (ret != 1) {
+ assert(0);
+ VLOG(1) << "Embree is compiled without the RTC_DEVICE_PROPERTY_RAY_MASK_SUPPORTED flag."
+ "Ray visiblity will not work.";
+ }
+ ret = rtcGetDeviceProperty(rtc_shared_device, RTC_DEVICE_PROPERTY_FILTER_FUNCTION_SUPPORTED);
+ if (ret != 1) {
+ assert(0);
+ VLOG(1)
+ << "Embree is compiled without the RTC_DEVICE_PROPERTY_FILTER_FUNCTION_SUPPORTED flag."
+ "Renders may not look as expected.";
+ }
+ ret = rtcGetDeviceProperty(rtc_shared_device, RTC_DEVICE_PROPERTY_CURVE_GEOMETRY_SUPPORTED);
+ if (ret != 1) {
+ assert(0);
+ VLOG(1)
+ << "Embree is compiled without the RTC_DEVICE_PROPERTY_CURVE_GEOMETRY_SUPPORTED flag. "
+ "Line primitives will not be rendered.";
+ }
+ ret = rtcGetDeviceProperty(rtc_shared_device, RTC_DEVICE_PROPERTY_TRIANGLE_GEOMETRY_SUPPORTED);
+ if (ret != 1) {
+ assert(0);
+ VLOG(1) << "Embree is compiled without the RTC_DEVICE_PROPERTY_TRIANGLE_GEOMETRY_SUPPORTED "
+ "flag. "
+ "Triangle primitives will not be rendered.";
+ }
+ ret = rtcGetDeviceProperty(rtc_shared_device, RTC_DEVICE_PROPERTY_BACKFACE_CULLING_ENABLED);
+ if (ret != 0) {
+ assert(0);
+ VLOG(1) << "Embree is compiled with the RTC_DEVICE_PROPERTY_BACKFACE_CULLING_ENABLED flag. "
+ "Renders may not look as expected.";
+ }
+ }
+ ++rtc_shared_users;
+
+ rtcSetDeviceErrorFunction(rtc_shared_device, rtc_error_func, NULL);
+
+ pack.root_index = -1;
}
BVHEmbree::~BVHEmbree()
{
- if(!params.top_level) {
- destroy(scene);
- }
+ if (!params.top_level) {
+ destroy(scene);
+ }
}
void BVHEmbree::destroy(RTCScene scene)
{
- if(scene) {
- rtcReleaseScene(scene);
- scene = NULL;
- }
- thread_scoped_lock lock(rtc_shared_mutex);
- --rtc_shared_users;
- if(rtc_shared_users == 0) {
- rtcReleaseDevice (rtc_shared_device);
- rtc_shared_device = NULL;
- }
+ if (scene) {
+ rtcReleaseScene(scene);
+ scene = NULL;
+ }
+ thread_scoped_lock lock(rtc_shared_mutex);
+ --rtc_shared_users;
+ if (rtc_shared_users == 0) {
+ rtcReleaseDevice(rtc_shared_device);
+ rtc_shared_device = NULL;
+ }
}
void BVHEmbree::delete_rtcScene()
{
- if(scene) {
- /* When this BVH is used as an instance in a top level BVH, don't delete now
- * Let the top_level BVH know that it should delete it later. */
- if(top_level) {
- top_level->add_delayed_delete_scene(scene);
- }
- else {
- rtcReleaseScene(scene);
- if(delayed_delete_scenes.size()) {
- foreach(RTCScene s, delayed_delete_scenes) {
- rtcReleaseScene(s);
- }
- }
- delayed_delete_scenes.clear();
- }
- scene = NULL;
- }
+ if (scene) {
+ /* When this BVH is used as an instance in a top level BVH, don't delete now
+ * Let the top_level BVH know that it should delete it later. */
+ if (top_level) {
+ top_level->add_delayed_delete_scene(scene);
+ }
+ else {
+ rtcReleaseScene(scene);
+ if (delayed_delete_scenes.size()) {
+ foreach (RTCScene s, delayed_delete_scenes) {
+ rtcReleaseScene(s);
+ }
+ }
+ delayed_delete_scenes.clear();
+ }
+ scene = NULL;
+ }
}
-void BVHEmbree::build(Progress& progress, Stats *stats_)
+void BVHEmbree::build(Progress &progress, Stats *stats_)
{
- assert(rtc_shared_device);
- stats = stats_;
- rtcSetDeviceMemoryMonitorFunction(rtc_shared_device, rtc_memory_monitor_func, stats);
-
- progress.set_substatus("Building BVH");
-
- if(scene) {
- rtcReleaseScene(scene);
- scene = NULL;
- }
-
- const bool dynamic = params.bvh_type == SceneParams::BVH_DYNAMIC;
-
- scene = rtcNewScene(rtc_shared_device);
- const RTCSceneFlags scene_flags = (dynamic ? RTC_SCENE_FLAG_DYNAMIC : RTC_SCENE_FLAG_NONE) |
- RTC_SCENE_FLAG_COMPACT | RTC_SCENE_FLAG_ROBUST;
- rtcSetSceneFlags(scene, scene_flags);
- build_quality = dynamic ? RTC_BUILD_QUALITY_LOW :
- (params.use_spatial_split ? RTC_BUILD_QUALITY_HIGH : RTC_BUILD_QUALITY_MEDIUM);
- rtcSetSceneBuildQuality(scene, build_quality);
-
- /* Count triangles and curves first, reserve arrays once. */
- size_t prim_count = 0;
-
- foreach(Object *ob, objects) {
- if (params.top_level) {
- if (!ob->is_traceable()) {
- continue;
- }
- if (!ob->mesh->is_instanced()) {
- if(params.primitive_mask & PRIMITIVE_ALL_TRIANGLE) {
- prim_count += ob->mesh->num_triangles();
- }
- if (params.primitive_mask & PRIMITIVE_ALL_CURVE) {
- for (size_t j = 0; j < ob->mesh->num_curves(); ++j) {
- prim_count += ob->mesh->get_curve(j).num_segments();
- }
- }
- }
- else {
- ++prim_count;
- }
- }
- else {
- if (params.primitive_mask & PRIMITIVE_ALL_TRIANGLE && ob->mesh->num_triangles() > 0) {
- prim_count += ob->mesh->num_triangles();
- }
- if (params.primitive_mask & PRIMITIVE_ALL_CURVE) {
- for (size_t j = 0; j < ob->mesh->num_curves(); ++j) {
- prim_count += ob->mesh->get_curve(j).num_segments();
- }
- }
- }
- }
-
- pack.prim_object.reserve(prim_count);
- pack.prim_type.reserve(prim_count);
- pack.prim_index.reserve(prim_count);
- pack.prim_tri_index.reserve(prim_count);
-
- int i = 0;
-
- pack.object_node.clear();
-
- foreach(Object *ob, objects) {
- if(params.top_level) {
- if(!ob->is_traceable()) {
- ++i;
- continue;
- }
- if(!ob->mesh->is_instanced()) {
- add_object(ob, i);
- }
- else {
- add_instance(ob, i);
- }
- }
- else {
- add_object(ob, i);
- }
- ++i;
- if(progress.get_cancel()) return;
- }
-
- if(progress.get_cancel()) {
- delete_rtcScene();
- stats = NULL;
- return;
- }
-
- rtcSetSceneProgressMonitorFunction(scene, rtc_progress_func, &progress);
- rtcCommitScene(scene);
-
- pack_primitives();
-
- if(progress.get_cancel()) {
- delete_rtcScene();
- stats = NULL;
- return;
- }
-
- progress.set_substatus("Packing geometry");
- pack_nodes(NULL);
-
- stats = NULL;
+ assert(rtc_shared_device);
+ stats = stats_;
+ rtcSetDeviceMemoryMonitorFunction(rtc_shared_device, rtc_memory_monitor_func, stats);
+
+ progress.set_substatus("Building BVH");
+
+ if (scene) {
+ rtcReleaseScene(scene);
+ scene = NULL;
+ }
+
+ const bool dynamic = params.bvh_type == SceneParams::BVH_DYNAMIC;
+
+ scene = rtcNewScene(rtc_shared_device);
+ const RTCSceneFlags scene_flags = (dynamic ? RTC_SCENE_FLAG_DYNAMIC : RTC_SCENE_FLAG_NONE) |
+ RTC_SCENE_FLAG_COMPACT | RTC_SCENE_FLAG_ROBUST;
+ rtcSetSceneFlags(scene, scene_flags);
+ build_quality = dynamic ? RTC_BUILD_QUALITY_LOW :
+ (params.use_spatial_split ? RTC_BUILD_QUALITY_HIGH :
+ RTC_BUILD_QUALITY_MEDIUM);
+ rtcSetSceneBuildQuality(scene, build_quality);
+
+ /* Count triangles and curves first, reserve arrays once. */
+ size_t prim_count = 0;
+
+ foreach (Object *ob, objects) {
+ if (params.top_level) {
+ if (!ob->is_traceable()) {
+ continue;
+ }
+ if (!ob->mesh->is_instanced()) {
+ if (params.primitive_mask & PRIMITIVE_ALL_TRIANGLE) {
+ prim_count += ob->mesh->num_triangles();
+ }
+ if (params.primitive_mask & PRIMITIVE_ALL_CURVE) {
+ for (size_t j = 0; j < ob->mesh->num_curves(); ++j) {
+ prim_count += ob->mesh->get_curve(j).num_segments();
+ }
+ }
+ }
+ else {
+ ++prim_count;
+ }
+ }
+ else {
+ if (params.primitive_mask & PRIMITIVE_ALL_TRIANGLE && ob->mesh->num_triangles() > 0) {
+ prim_count += ob->mesh->num_triangles();
+ }
+ if (params.primitive_mask & PRIMITIVE_ALL_CURVE) {
+ for (size_t j = 0; j < ob->mesh->num_curves(); ++j) {
+ prim_count += ob->mesh->get_curve(j).num_segments();
+ }
+ }
+ }
+ }
+
+ pack.prim_object.reserve(prim_count);
+ pack.prim_type.reserve(prim_count);
+ pack.prim_index.reserve(prim_count);
+ pack.prim_tri_index.reserve(prim_count);
+
+ int i = 0;
+
+ pack.object_node.clear();
+
+ foreach (Object *ob, objects) {
+ if (params.top_level) {
+ if (!ob->is_traceable()) {
+ ++i;
+ continue;
+ }
+ if (!ob->mesh->is_instanced()) {
+ add_object(ob, i);
+ }
+ else {
+ add_instance(ob, i);
+ }
+ }
+ else {
+ add_object(ob, i);
+ }
+ ++i;
+ if (progress.get_cancel())
+ return;
+ }
+
+ if (progress.get_cancel()) {
+ delete_rtcScene();
+ stats = NULL;
+ return;
+ }
+
+ rtcSetSceneProgressMonitorFunction(scene, rtc_progress_func, &progress);
+ rtcCommitScene(scene);
+
+ pack_primitives();
+
+ if (progress.get_cancel()) {
+ delete_rtcScene();
+ stats = NULL;
+ return;
+ }
+
+ progress.set_substatus("Packing geometry");
+ pack_nodes(NULL);
+
+ stats = NULL;
}
BVHNode *BVHEmbree::widen_children_nodes(const BVHNode * /*root*/)
{
- assert(!"Must not be called.");
- return NULL;
+ assert(!"Must not be called.");
+ return NULL;
}
void BVHEmbree::add_object(Object *ob, int i)
{
- Mesh *mesh = ob->mesh;
- if(params.primitive_mask & PRIMITIVE_ALL_TRIANGLE && mesh->num_triangles() > 0) {
- add_triangles(ob, i);
- }
- if(params.primitive_mask & PRIMITIVE_ALL_CURVE && mesh->num_curves() > 0) {
- add_curves(ob, i);
- }
+ Mesh *mesh = ob->mesh;
+ if (params.primitive_mask & PRIMITIVE_ALL_TRIANGLE && mesh->num_triangles() > 0) {
+ add_triangles(ob, i);
+ }
+ if (params.primitive_mask & PRIMITIVE_ALL_CURVE && mesh->num_curves() > 0) {
+ add_curves(ob, i);
+ }
}
void BVHEmbree::add_instance(Object *ob, int i)
{
- if(!ob || !ob->mesh) {
- assert(0);
- return;
- }
- BVHEmbree *instance_bvh = (BVHEmbree*)(ob->mesh->bvh);
-
- if(instance_bvh->top_level != this) {
- instance_bvh->top_level = this;
- }
-
- const size_t num_motion_steps = ob->use_motion() ? ob->motion.size() : 1;
- RTCGeometry geom_id = rtcNewGeometry(rtc_shared_device, RTC_GEOMETRY_TYPE_INSTANCE);
- rtcSetGeometryInstancedScene(geom_id, instance_bvh->scene);
- rtcSetGeometryTimeStepCount(geom_id, num_motion_steps);
-
- if(ob->use_motion()) {
- for(size_t step = 0; step < num_motion_steps; ++step) {
- rtcSetGeometryTransform(geom_id, step, RTC_FORMAT_FLOAT3X4_ROW_MAJOR, (const float*)&ob->motion[step]);
- }
- }
- else {
- rtcSetGeometryTransform(geom_id, 0, RTC_FORMAT_FLOAT3X4_ROW_MAJOR, (const float*)&ob->tfm);
- }
-
- pack.prim_index.push_back_slow(-1);
- pack.prim_object.push_back_slow(i);
- pack.prim_type.push_back_slow(PRIMITIVE_NONE);
- pack.prim_tri_index.push_back_slow(-1);
-
- rtcSetGeometryUserData(geom_id, (void*) instance_bvh->scene);
- rtcSetGeometryMask(geom_id, ob->visibility);
-
- rtcCommitGeometry(geom_id);
- rtcAttachGeometryByID(scene, geom_id, i*2);
- rtcReleaseGeometry(geom_id);
+ if (!ob || !ob->mesh) {
+ assert(0);
+ return;
+ }
+ BVHEmbree *instance_bvh = (BVHEmbree *)(ob->mesh->bvh);
+
+ if (instance_bvh->top_level != this) {
+ instance_bvh->top_level = this;
+ }
+
+ const size_t num_motion_steps = ob->use_motion() ? ob->motion.size() : 1;
+ RTCGeometry geom_id = rtcNewGeometry(rtc_shared_device, RTC_GEOMETRY_TYPE_INSTANCE);
+ rtcSetGeometryInstancedScene(geom_id, instance_bvh->scene);
+ rtcSetGeometryTimeStepCount(geom_id, num_motion_steps);
+
+ if (ob->use_motion()) {
+ for (size_t step = 0; step < num_motion_steps; ++step) {
+ rtcSetGeometryTransform(
+ geom_id, step, RTC_FORMAT_FLOAT3X4_ROW_MAJOR, (const float *)&ob->motion[step]);
+ }
+ }
+ else {
+ rtcSetGeometryTransform(geom_id, 0, RTC_FORMAT_FLOAT3X4_ROW_MAJOR, (const float *)&ob->tfm);
+ }
+
+ pack.prim_index.push_back_slow(-1);
+ pack.prim_object.push_back_slow(i);
+ pack.prim_type.push_back_slow(PRIMITIVE_NONE);
+ pack.prim_tri_index.push_back_slow(-1);
+
+ rtcSetGeometryUserData(geom_id, (void *)instance_bvh->scene);
+ rtcSetGeometryMask(geom_id, ob->visibility);
+
+ rtcCommitGeometry(geom_id);
+ rtcAttachGeometryByID(scene, geom_id, i * 2);
+ rtcReleaseGeometry(geom_id);
}
void BVHEmbree::add_triangles(Object *ob, int i)
{
- size_t prim_offset = pack.prim_index.size();
- Mesh *mesh = ob->mesh;
- const Attribute *attr_mP = NULL;
- size_t num_motion_steps = 1;
- if(mesh->has_motion_blur()) {
- attr_mP = mesh->attributes.find(ATTR_STD_MOTION_VERTEX_POSITION);
- if(attr_mP) {
- num_motion_steps = mesh->motion_steps;
- if(num_motion_steps > RTC_MAX_TIME_STEP_COUNT) {
- assert(0);
- num_motion_steps = RTC_MAX_TIME_STEP_COUNT;
- }
- }
- }
-
- const size_t num_triangles = mesh->num_triangles();
- RTCGeometry geom_id = rtcNewGeometry(rtc_shared_device, RTC_GEOMETRY_TYPE_TRIANGLE);
- rtcSetGeometryBuildQuality(geom_id, build_quality);
- rtcSetGeometryTimeStepCount(geom_id, num_motion_steps);
-
- unsigned *rtc_indices = (unsigned*)rtcSetNewGeometryBuffer(geom_id, RTC_BUFFER_TYPE_INDEX, 0,
- RTC_FORMAT_UINT3, sizeof (int) * 3, num_triangles);
- assert(rtc_indices);
- if(!rtc_indices) {
- VLOG(1) << "Embree could not create new geometry buffer for mesh " << mesh->name.c_str() << ".\n";
- return;
- }
- for(size_t j = 0; j < num_triangles; ++j) {
- Mesh::Triangle t = mesh->get_triangle(j);
- rtc_indices[j*3] = t.v[0];
- rtc_indices[j*3+1] = t.v[1];
- rtc_indices[j*3+2] = t.v[2];
- }
-
- update_tri_vertex_buffer(geom_id, mesh);
-
- size_t prim_object_size = pack.prim_object.size();
- pack.prim_object.resize(prim_object_size + num_triangles);
- size_t prim_type_size = pack.prim_type.size();
- pack.prim_type.resize(prim_type_size + num_triangles);
- size_t prim_index_size = pack.prim_index.size();
- pack.prim_index.resize(prim_index_size + num_triangles);
- pack.prim_tri_index.resize(prim_index_size + num_triangles);
- int prim_type = (num_motion_steps > 1 ? PRIMITIVE_MOTION_TRIANGLE : PRIMITIVE_TRIANGLE);
-
- for(size_t j = 0; j < num_triangles; ++j) {
- pack.prim_object[prim_object_size + j] = i;
- pack.prim_type[prim_type_size + j] = prim_type;
- pack.prim_index[prim_index_size + j] = j;
- pack.prim_tri_index[prim_index_size + j] = j;
- }
-
- rtcSetGeometryUserData(geom_id, (void*) prim_offset);
- rtcSetGeometryIntersectFilterFunction(geom_id, rtc_filter_func);
- rtcSetGeometryOccludedFilterFunction(geom_id, rtc_filter_occluded_func);
- rtcSetGeometryMask(geom_id, ob->visibility);
-
- rtcCommitGeometry(geom_id);
- rtcAttachGeometryByID(scene, geom_id, i*2);
- rtcReleaseGeometry(geom_id);
+ size_t prim_offset = pack.prim_index.size();
+ Mesh *mesh = ob->mesh;
+ const Attribute *attr_mP = NULL;
+ size_t num_motion_steps = 1;
+ if (mesh->has_motion_blur()) {
+ attr_mP = mesh->attributes.find(ATTR_STD_MOTION_VERTEX_POSITION);
+ if (attr_mP) {
+ num_motion_steps = mesh->motion_steps;
+ if (num_motion_steps > RTC_MAX_TIME_STEP_COUNT) {
+ assert(0);
+ num_motion_steps = RTC_MAX_TIME_STEP_COUNT;
+ }
+ }
+ }
+
+ const size_t num_triangles = mesh->num_triangles();
+ RTCGeometry geom_id = rtcNewGeometry(rtc_shared_device, RTC_GEOMETRY_TYPE_TRIANGLE);
+ rtcSetGeometryBuildQuality(geom_id, build_quality);
+ rtcSetGeometryTimeStepCount(geom_id, num_motion_steps);
+
+ unsigned *rtc_indices = (unsigned *)rtcSetNewGeometryBuffer(
+ geom_id, RTC_BUFFER_TYPE_INDEX, 0, RTC_FORMAT_UINT3, sizeof(int) * 3, num_triangles);
+ assert(rtc_indices);
+ if (!rtc_indices) {
+ VLOG(1) << "Embree could not create new geometry buffer for mesh " << mesh->name.c_str()
+ << ".\n";
+ return;
+ }
+ for (size_t j = 0; j < num_triangles; ++j) {
+ Mesh::Triangle t = mesh->get_triangle(j);
+ rtc_indices[j * 3] = t.v[0];
+ rtc_indices[j * 3 + 1] = t.v[1];
+ rtc_indices[j * 3 + 2] = t.v[2];
+ }
+
+ update_tri_vertex_buffer(geom_id, mesh);
+
+ size_t prim_object_size = pack.prim_object.size();
+ pack.prim_object.resize(prim_object_size + num_triangles);
+ size_t prim_type_size = pack.prim_type.size();
+ pack.prim_type.resize(prim_type_size + num_triangles);
+ size_t prim_index_size = pack.prim_index.size();
+ pack.prim_index.resize(prim_index_size + num_triangles);
+ pack.prim_tri_index.resize(prim_index_size + num_triangles);
+ int prim_type = (num_motion_steps > 1 ? PRIMITIVE_MOTION_TRIANGLE : PRIMITIVE_TRIANGLE);
+
+ for (size_t j = 0; j < num_triangles; ++j) {
+ pack.prim_object[prim_object_size + j] = i;
+ pack.prim_type[prim_type_size + j] = prim_type;
+ pack.prim_index[prim_index_size + j] = j;
+ pack.prim_tri_index[prim_index_size + j] = j;
+ }
+
+ rtcSetGeometryUserData(geom_id, (void *)prim_offset);
+ rtcSetGeometryIntersectFilterFunction(geom_id, rtc_filter_func);
+ rtcSetGeometryOccludedFilterFunction(geom_id, rtc_filter_occluded_func);
+ rtcSetGeometryMask(geom_id, ob->visibility);
+
+ rtcCommitGeometry(geom_id);
+ rtcAttachGeometryByID(scene, geom_id, i * 2);
+ rtcReleaseGeometry(geom_id);
}
-void BVHEmbree::update_tri_vertex_buffer(RTCGeometry geom_id, const Mesh* mesh)
+void BVHEmbree::update_tri_vertex_buffer(RTCGeometry geom_id, const Mesh *mesh)
{
- const Attribute *attr_mP = NULL;
- size_t num_motion_steps = 1;
- int t_mid = 0;
- if(mesh->has_motion_blur()) {
- attr_mP = mesh->attributes.find(ATTR_STD_MOTION_VERTEX_POSITION);
- if(attr_mP) {
- num_motion_steps = mesh->motion_steps;
- t_mid = (num_motion_steps - 1) / 2;
- if(num_motion_steps > RTC_MAX_TIME_STEP_COUNT) {
- assert(0);
- num_motion_steps = RTC_MAX_TIME_STEP_COUNT;
- }
- }
- }
- const size_t num_verts = mesh->verts.size();
-
- for(int t = 0; t < num_motion_steps; ++t) {
- const float3 *verts;
- if(t == t_mid) {
- verts = &mesh->verts[0];
- }
- else {
- int t_ = (t > t_mid) ? (t - 1) : t;
- verts = &attr_mP->data_float3()[t_ * num_verts];
- }
-
- float *rtc_verts = (float*) rtcSetNewGeometryBuffer(geom_id, RTC_BUFFER_TYPE_VERTEX, t,
- RTC_FORMAT_FLOAT3, sizeof(float) * 3, num_verts + 1);
- assert(rtc_verts);
- if(rtc_verts) {
- for(size_t j = 0; j < num_verts; ++j) {
- rtc_verts[0] = verts[j].x;
- rtc_verts[1] = verts[j].y;
- rtc_verts[2] = verts[j].z;
- rtc_verts += 3;
- }
- }
- }
+ const Attribute *attr_mP = NULL;
+ size_t num_motion_steps = 1;
+ int t_mid = 0;
+ if (mesh->has_motion_blur()) {
+ attr_mP = mesh->attributes.find(ATTR_STD_MOTION_VERTEX_POSITION);
+ if (attr_mP) {
+ num_motion_steps = mesh->motion_steps;
+ t_mid = (num_motion_steps - 1) / 2;
+ if (num_motion_steps > RTC_MAX_TIME_STEP_COUNT) {
+ assert(0);
+ num_motion_steps = RTC_MAX_TIME_STEP_COUNT;
+ }
+ }
+ }
+ const size_t num_verts = mesh->verts.size();
+
+ for (int t = 0; t < num_motion_steps; ++t) {
+ const float3 *verts;
+ if (t == t_mid) {
+ verts = &mesh->verts[0];
+ }
+ else {
+ int t_ = (t > t_mid) ? (t - 1) : t;
+ verts = &attr_mP->data_float3()[t_ * num_verts];
+ }
+
+ float *rtc_verts = (float *)rtcSetNewGeometryBuffer(
+ geom_id, RTC_BUFFER_TYPE_VERTEX, t, RTC_FORMAT_FLOAT3, sizeof(float) * 3, num_verts + 1);
+ assert(rtc_verts);
+ if (rtc_verts) {
+ for (size_t j = 0; j < num_verts; ++j) {
+ rtc_verts[0] = verts[j].x;
+ rtc_verts[1] = verts[j].y;
+ rtc_verts[2] = verts[j].z;
+ rtc_verts += 3;
+ }
+ }
+ }
}
-void BVHEmbree::update_curve_vertex_buffer(RTCGeometry geom_id, const Mesh* mesh)
+void BVHEmbree::update_curve_vertex_buffer(RTCGeometry geom_id, const Mesh *mesh)
{
- const Attribute *attr_mP = NULL;
- size_t num_motion_steps = 1;
- if(mesh->has_motion_blur()) {
- attr_mP = mesh->curve_attributes.find(ATTR_STD_MOTION_VERTEX_POSITION);
- if(attr_mP) {
- num_motion_steps = mesh->motion_steps;
- }
- }
-
- const size_t num_curves = mesh->num_curves();
- size_t num_keys = 0;
- for(size_t j = 0; j < num_curves; ++j) {
- const Mesh::Curve c = mesh->get_curve(j);
- num_keys += c.num_keys;
- }
-
- /* Copy the CV data to Embree */
- const int t_mid = (num_motion_steps - 1) / 2;
- const float *curve_radius = &mesh->curve_radius[0];
- for(int t = 0; t < num_motion_steps; ++t) {
- const float3 *verts;
- if(t == t_mid || attr_mP == NULL) {
- verts = &mesh->curve_keys[0];
- }
- else {
- int t_ = (t > t_mid) ? (t - 1) : t;
- verts = &attr_mP->data_float3()[t_ * num_keys];
- }
-
- float4 *rtc_verts = (float4*)rtcSetNewGeometryBuffer(geom_id, RTC_BUFFER_TYPE_VERTEX, t,
- RTC_FORMAT_FLOAT4, sizeof (float) * 4, num_keys);
- float4 *rtc_tangents = NULL;
- if(use_curves) {
- rtc_tangents = (float4*)rtcSetNewGeometryBuffer(geom_id, RTC_BUFFER_TYPE_TANGENT, t,
- RTC_FORMAT_FLOAT4, sizeof (float) * 4, num_keys);
- assert(rtc_tangents);
- }
- assert(rtc_verts);
- if(rtc_verts) {
- if(use_curves && rtc_tangents) {
- const size_t num_curves = mesh->num_curves();
- for(size_t j = 0; j < num_curves; ++j) {
- Mesh::Curve c = mesh->get_curve(j);
- int fk = c.first_key;
- rtc_verts[0] = float3_to_float4(verts[fk]);
- rtc_verts[0].w = curve_radius[fk];
- rtc_tangents[0] = float3_to_float4(verts[fk + 1] - verts[fk]);
- rtc_tangents[0].w = curve_radius[fk + 1] - curve_radius[fk];
- ++fk;
- int k = 1;
- for(;k < c.num_segments(); ++k, ++fk) {
- rtc_verts[k] = float3_to_float4(verts[fk]);
- rtc_verts[k].w = curve_radius[fk];
- rtc_tangents[k] = float3_to_float4((verts[fk + 1] - verts[fk - 1]) * 0.5f);
- rtc_tangents[k].w = (curve_radius[fk + 1] - curve_radius[fk - 1]) * 0.5f;
- }
- rtc_verts[k] = float3_to_float4(verts[fk]);
- rtc_verts[k].w = curve_radius[fk];
- rtc_tangents[k] = float3_to_float4(verts[fk] - verts[fk - 1]);
- rtc_tangents[k].w = curve_radius[fk] - curve_radius[fk - 1];
- rtc_verts += c.num_keys;
- rtc_tangents += c.num_keys;
- }
- }
- else {
- for(size_t j = 0; j < num_keys; ++j) {
- rtc_verts[j] = float3_to_float4(verts[j]);
- rtc_verts[j].w = curve_radius[j];
- }
- }
- }
- }
+ const Attribute *attr_mP = NULL;
+ size_t num_motion_steps = 1;
+ if (mesh->has_motion_blur()) {
+ attr_mP = mesh->curve_attributes.find(ATTR_STD_MOTION_VERTEX_POSITION);
+ if (attr_mP) {
+ num_motion_steps = mesh->motion_steps;
+ }
+ }
+
+ const size_t num_curves = mesh->num_curves();
+ size_t num_keys = 0;
+ for (size_t j = 0; j < num_curves; ++j) {
+ const Mesh::Curve c = mesh->get_curve(j);
+ num_keys += c.num_keys;
+ }
+
+ /* Copy the CV data to Embree */
+ const int t_mid = (num_motion_steps - 1) / 2;
+ const float *curve_radius = &mesh->curve_radius[0];
+ for (int t = 0; t < num_motion_steps; ++t) {
+ const float3 *verts;
+ if (t == t_mid || attr_mP == NULL) {
+ verts = &mesh->curve_keys[0];
+ }
+ else {
+ int t_ = (t > t_mid) ? (t - 1) : t;
+ verts = &attr_mP->data_float3()[t_ * num_keys];
+ }
+
+ float4 *rtc_verts = (float4 *)rtcSetNewGeometryBuffer(
+ geom_id, RTC_BUFFER_TYPE_VERTEX, t, RTC_FORMAT_FLOAT4, sizeof(float) * 4, num_keys);
+ float4 *rtc_tangents = NULL;
+ if (use_curves) {
+ rtc_tangents = (float4 *)rtcSetNewGeometryBuffer(
+ geom_id, RTC_BUFFER_TYPE_TANGENT, t, RTC_FORMAT_FLOAT4, sizeof(float) * 4, num_keys);
+ assert(rtc_tangents);
+ }
+ assert(rtc_verts);
+ if (rtc_verts) {
+ if (use_curves && rtc_tangents) {
+ const size_t num_curves = mesh->num_curves();
+ for (size_t j = 0; j < num_curves; ++j) {
+ Mesh::Curve c = mesh->get_curve(j);
+ int fk = c.first_key;
+ rtc_verts[0] = float3_to_float4(verts[fk]);
+ rtc_verts[0].w = curve_radius[fk];
+ rtc_tangents[0] = float3_to_float4(verts[fk + 1] - verts[fk]);
+ rtc_tangents[0].w = curve_radius[fk + 1] - curve_radius[fk];
+ ++fk;
+ int k = 1;
+ for (; k < c.num_segments(); ++k, ++fk) {
+ rtc_verts[k] = float3_to_float4(verts[fk]);
+ rtc_verts[k].w = curve_radius[fk];
+ rtc_tangents[k] = float3_to_float4((verts[fk + 1] - verts[fk - 1]) * 0.5f);
+ rtc_tangents[k].w = (curve_radius[fk + 1] - curve_radius[fk - 1]) * 0.5f;
+ }
+ rtc_verts[k] = float3_to_float4(verts[fk]);
+ rtc_verts[k].w = curve_radius[fk];
+ rtc_tangents[k] = float3_to_float4(verts[fk] - verts[fk - 1]);
+ rtc_tangents[k].w = curve_radius[fk] - curve_radius[fk - 1];
+ rtc_verts += c.num_keys;
+ rtc_tangents += c.num_keys;
+ }
+ }
+ else {
+ for (size_t j = 0; j < num_keys; ++j) {
+ rtc_verts[j] = float3_to_float4(verts[j]);
+ rtc_verts[j].w = curve_radius[j];
+ }
+ }
+ }
+ }
}
void BVHEmbree::add_curves(Object *ob, int i)
{
- size_t prim_offset = pack.prim_index.size();
- const Mesh *mesh = ob->mesh;
- const Attribute *attr_mP = NULL;
- size_t num_motion_steps = 1;
- if(mesh->has_motion_blur()) {
- attr_mP = mesh->curve_attributes.find(ATTR_STD_MOTION_VERTEX_POSITION);
- if(attr_mP) {
- num_motion_steps = mesh->motion_steps;
- }
- }
-
- const size_t num_curves = mesh->num_curves();
- size_t num_segments = 0;
- for(size_t j = 0; j < num_curves; ++j) {
- Mesh::Curve c = mesh->get_curve(j);
- assert(c.num_segments() > 0);
- num_segments += c.num_segments();
- }
-
- /* Make room for Cycles specific data. */
- size_t prim_object_size = pack.prim_object.size();
- pack.prim_object.resize(prim_object_size + num_segments);
- size_t prim_type_size = pack.prim_type.size();
- pack.prim_type.resize(prim_type_size + num_segments);
- size_t prim_index_size = pack.prim_index.size();
- pack.prim_index.resize(prim_index_size + num_segments);
- size_t prim_tri_index_size = pack.prim_index.size();
- pack.prim_tri_index.resize(prim_tri_index_size + num_segments);
-
- enum RTCGeometryType type = (!use_curves) ? RTC_GEOMETRY_TYPE_FLAT_LINEAR_CURVE :
- (use_ribbons ? RTC_GEOMETRY_TYPE_FLAT_HERMITE_CURVE :
- RTC_GEOMETRY_TYPE_ROUND_HERMITE_CURVE);
-
- RTCGeometry geom_id = rtcNewGeometry(rtc_shared_device, type);
- rtcSetGeometryTessellationRate(geom_id, curve_subdivisions);
- unsigned *rtc_indices = (unsigned*) rtcSetNewGeometryBuffer(geom_id, RTC_BUFFER_TYPE_INDEX, 0,
- RTC_FORMAT_UINT, sizeof (int), num_segments);
- size_t rtc_index = 0;
- for(size_t j = 0; j < num_curves; ++j) {
- Mesh::Curve c = mesh->get_curve(j);
- for(size_t k = 0; k < c.num_segments(); ++k) {
- rtc_indices[rtc_index] = c.first_key + k;
- /* Cycles specific data. */
- pack.prim_object[prim_object_size + rtc_index] = i;
- pack.prim_type[prim_type_size + rtc_index] = (PRIMITIVE_PACK_SEGMENT(num_motion_steps > 1 ?
- PRIMITIVE_MOTION_CURVE : PRIMITIVE_CURVE, k));
- pack.prim_index[prim_index_size + rtc_index] = j;
- pack.prim_tri_index[prim_tri_index_size + rtc_index] = rtc_index;
-
- ++rtc_index;
- }
- }
-
- rtcSetGeometryBuildQuality(geom_id, build_quality);
- rtcSetGeometryTimeStepCount(geom_id, num_motion_steps);
-
- update_curve_vertex_buffer(geom_id, mesh);
-
- rtcSetGeometryUserData(geom_id, (void*) prim_offset);
- rtcSetGeometryIntersectFilterFunction(geom_id, rtc_filter_func);
- rtcSetGeometryOccludedFilterFunction(geom_id, rtc_filter_occluded_func);
- rtcSetGeometryMask(geom_id, ob->visibility);
-
- rtcCommitGeometry(geom_id);
- rtcAttachGeometryByID(scene, geom_id, i * 2 + 1);
- rtcReleaseGeometry(geom_id);
+ size_t prim_offset = pack.prim_index.size();
+ const Mesh *mesh = ob->mesh;
+ const Attribute *attr_mP = NULL;
+ size_t num_motion_steps = 1;
+ if (mesh->has_motion_blur()) {
+ attr_mP = mesh->curve_attributes.find(ATTR_STD_MOTION_VERTEX_POSITION);
+ if (attr_mP) {
+ num_motion_steps = mesh->motion_steps;
+ }
+ }
+
+ const size_t num_curves = mesh->num_curves();
+ size_t num_segments = 0;
+ for (size_t j = 0; j < num_curves; ++j) {
+ Mesh::Curve c = mesh->get_curve(j);
+ assert(c.num_segments() > 0);
+ num_segments += c.num_segments();
+ }
+
+ /* Make room for Cycles specific data. */
+ size_t prim_object_size = pack.prim_object.size();
+ pack.prim_object.resize(prim_object_size + num_segments);
+ size_t prim_type_size = pack.prim_type.size();
+ pack.prim_type.resize(prim_type_size + num_segments);
+ size_t prim_index_size = pack.prim_index.size();
+ pack.prim_index.resize(prim_index_size + num_segments);
+ size_t prim_tri_index_size = pack.prim_index.size();
+ pack.prim_tri_index.resize(prim_tri_index_size + num_segments);
+
+ enum RTCGeometryType type = (!use_curves) ?
+ RTC_GEOMETRY_TYPE_FLAT_LINEAR_CURVE :
+ (use_ribbons ? RTC_GEOMETRY_TYPE_FLAT_HERMITE_CURVE :
+ RTC_GEOMETRY_TYPE_ROUND_HERMITE_CURVE);
+
+ RTCGeometry geom_id = rtcNewGeometry(rtc_shared_device, type);
+ rtcSetGeometryTessellationRate(geom_id, curve_subdivisions);
+ unsigned *rtc_indices = (unsigned *)rtcSetNewGeometryBuffer(
+ geom_id, RTC_BUFFER_TYPE_INDEX, 0, RTC_FORMAT_UINT, sizeof(int), num_segments);
+ size_t rtc_index = 0;
+ for (size_t j = 0; j < num_curves; ++j) {
+ Mesh::Curve c = mesh->get_curve(j);
+ for (size_t k = 0; k < c.num_segments(); ++k) {
+ rtc_indices[rtc_index] = c.first_key + k;
+ /* Cycles specific data. */
+ pack.prim_object[prim_object_size + rtc_index] = i;
+ pack.prim_type[prim_type_size + rtc_index] = (PRIMITIVE_PACK_SEGMENT(
+ num_motion_steps > 1 ? PRIMITIVE_MOTION_CURVE : PRIMITIVE_CURVE, k));
+ pack.prim_index[prim_index_size + rtc_index] = j;
+ pack.prim_tri_index[prim_tri_index_size + rtc_index] = rtc_index;
+
+ ++rtc_index;
+ }
+ }
+
+ rtcSetGeometryBuildQuality(geom_id, build_quality);
+ rtcSetGeometryTimeStepCount(geom_id, num_motion_steps);
+
+ update_curve_vertex_buffer(geom_id, mesh);
+
+ rtcSetGeometryUserData(geom_id, (void *)prim_offset);
+ rtcSetGeometryIntersectFilterFunction(geom_id, rtc_filter_func);
+ rtcSetGeometryOccludedFilterFunction(geom_id, rtc_filter_occluded_func);
+ rtcSetGeometryMask(geom_id, ob->visibility);
+
+ rtcCommitGeometry(geom_id);
+ rtcAttachGeometryByID(scene, geom_id, i * 2 + 1);
+ rtcReleaseGeometry(geom_id);
}
void BVHEmbree::pack_nodes(const BVHNode *)
{
- /* Quite a bit of this code is for compatibility with Cycles' native BVH. */
- if(!params.top_level) {
- return;
- }
-
- for(size_t i = 0; i < pack.prim_index.size(); ++i) {
- if(pack.prim_index[i] != -1) {
- if(pack.prim_type[i] & PRIMITIVE_ALL_CURVE)
- pack.prim_index[i] += objects[pack.prim_object[i]]->mesh->curve_offset;
- else
- pack.prim_index[i] += objects[pack.prim_object[i]]->mesh->tri_offset;
- }
- }
-
- size_t prim_offset = pack.prim_index.size();
-
- /* reserve */
- size_t prim_index_size = pack.prim_index.size();
- size_t prim_tri_verts_size = pack.prim_tri_verts.size();
-
- size_t pack_prim_index_offset = prim_index_size;
- size_t pack_prim_tri_verts_offset = prim_tri_verts_size;
- size_t object_offset = 0;
-
- map<Mesh*, int> mesh_map;
-
- foreach(Object *ob, objects) {
- Mesh *mesh = ob->mesh;
- BVH *bvh = mesh->bvh;
-
- if(mesh->need_build_bvh()) {
- if(mesh_map.find(mesh) == mesh_map.end()) {
- prim_index_size += bvh->pack.prim_index.size();
- prim_tri_verts_size += bvh->pack.prim_tri_verts.size();
- mesh_map[mesh] = 1;
- }
- }
- }
-
- mesh_map.clear();
-
- pack.prim_index.resize(prim_index_size);
- pack.prim_type.resize(prim_index_size);
- pack.prim_object.resize(prim_index_size);
- pack.prim_visibility.clear();
- pack.prim_tri_verts.resize(prim_tri_verts_size);
- pack.prim_tri_index.resize(prim_index_size);
- pack.object_node.resize(objects.size());
-
- int *pack_prim_index = (pack.prim_index.size())? &pack.prim_index[0]: NULL;
- int *pack_prim_type = (pack.prim_type.size())? &pack.prim_type[0]: NULL;
- int *pack_prim_object = (pack.prim_object.size())? &pack.prim_object[0]: NULL;
- float4 *pack_prim_tri_verts = (pack.prim_tri_verts.size())? &pack.prim_tri_verts[0]: NULL;
- uint *pack_prim_tri_index = (pack.prim_tri_index.size())? &pack.prim_tri_index[0]: NULL;
-
- /* merge */
- foreach(Object *ob, objects) {
- Mesh *mesh = ob->mesh;
-
- /* We assume that if mesh doesn't need own BVH it was already included
- * into a top-level BVH and no packing here is needed.
- */
- if(!mesh->need_build_bvh()) {
- pack.object_node[object_offset++] = prim_offset;
- continue;
- }
-
- /* if mesh already added once, don't add it again, but used set
- * node offset for this object */
- map<Mesh*, int>::iterator it = mesh_map.find(mesh);
-
- if(mesh_map.find(mesh) != mesh_map.end()) {
- int noffset = it->second;
- pack.object_node[object_offset++] = noffset;
- continue;
- }
-
- BVHEmbree *bvh = (BVHEmbree*)mesh->bvh;
-
- rtc_memory_monitor_func(stats, unaccounted_mem, true);
- unaccounted_mem = 0;
-
- int mesh_tri_offset = mesh->tri_offset;
- int mesh_curve_offset = mesh->curve_offset;
-
- /* fill in node indexes for instances */
- pack.object_node[object_offset++] = prim_offset;
-
- mesh_map[mesh] = pack.object_node[object_offset-1];
-
- /* merge primitive, object and triangle indexes */
- if(bvh->pack.prim_index.size()) {
- size_t bvh_prim_index_size = bvh->pack.prim_index.size();
- int *bvh_prim_index = &bvh->pack.prim_index[0];
- int *bvh_prim_type = &bvh->pack.prim_type[0];
- uint *bvh_prim_tri_index = &bvh->pack.prim_tri_index[0];
-
- for(size_t i = 0; i < bvh_prim_index_size; ++i) {
- if(bvh->pack.prim_type[i] & PRIMITIVE_ALL_CURVE) {
- pack_prim_index[pack_prim_index_offset] = bvh_prim_index[i] + mesh_curve_offset;
- pack_prim_tri_index[pack_prim_index_offset] = -1;
- }
- else {
- pack_prim_index[pack_prim_index_offset] = bvh_prim_index[i] + mesh_tri_offset;
- pack_prim_tri_index[pack_prim_index_offset] =
- bvh_prim_tri_index[i] + pack_prim_tri_verts_offset;
- }
-
- pack_prim_type[pack_prim_index_offset] = bvh_prim_type[i];
- pack_prim_object[pack_prim_index_offset] = 0;
-
- ++pack_prim_index_offset;
- }
- }
-
- /* Merge triangle vertices data. */
- if(bvh->pack.prim_tri_verts.size()) {
- const size_t prim_tri_size = bvh->pack.prim_tri_verts.size();
- memcpy(pack_prim_tri_verts + pack_prim_tri_verts_offset,
- &bvh->pack.prim_tri_verts[0],
- prim_tri_size*sizeof(float4));
- pack_prim_tri_verts_offset += prim_tri_size;
- }
-
- prim_offset += bvh->pack.prim_index.size();
- }
+ /* Quite a bit of this code is for compatibility with Cycles' native BVH. */
+ if (!params.top_level) {
+ return;
+ }
+
+ for (size_t i = 0; i < pack.prim_index.size(); ++i) {
+ if (pack.prim_index[i] != -1) {
+ if (pack.prim_type[i] & PRIMITIVE_ALL_CURVE)
+ pack.prim_index[i] += objects[pack.prim_object[i]]->mesh->curve_offset;
+ else
+ pack.prim_index[i] += objects[pack.prim_object[i]]->mesh->tri_offset;
+ }
+ }
+
+ size_t prim_offset = pack.prim_index.size();
+
+ /* reserve */
+ size_t prim_index_size = pack.prim_index.size();
+ size_t prim_tri_verts_size = pack.prim_tri_verts.size();
+
+ size_t pack_prim_index_offset = prim_index_size;
+ size_t pack_prim_tri_verts_offset = prim_tri_verts_size;
+ size_t object_offset = 0;
+
+ map<Mesh *, int> mesh_map;
+
+ foreach (Object *ob, objects) {
+ Mesh *mesh = ob->mesh;
+ BVH *bvh = mesh->bvh;
+
+ if (mesh->need_build_bvh()) {
+ if (mesh_map.find(mesh) == mesh_map.end()) {
+ prim_index_size += bvh->pack.prim_index.size();
+ prim_tri_verts_size += bvh->pack.prim_tri_verts.size();
+ mesh_map[mesh] = 1;
+ }
+ }
+ }
+
+ mesh_map.clear();
+
+ pack.prim_index.resize(prim_index_size);
+ pack.prim_type.resize(prim_index_size);
+ pack.prim_object.resize(prim_index_size);
+ pack.prim_visibility.clear();
+ pack.prim_tri_verts.resize(prim_tri_verts_size);
+ pack.prim_tri_index.resize(prim_index_size);
+ pack.object_node.resize(objects.size());
+
+ int *pack_prim_index = (pack.prim_index.size()) ? &pack.prim_index[0] : NULL;
+ int *pack_prim_type = (pack.prim_type.size()) ? &pack.prim_type[0] : NULL;
+ int *pack_prim_object = (pack.prim_object.size()) ? &pack.prim_object[0] : NULL;
+ float4 *pack_prim_tri_verts = (pack.prim_tri_verts.size()) ? &pack.prim_tri_verts[0] : NULL;
+ uint *pack_prim_tri_index = (pack.prim_tri_index.size()) ? &pack.prim_tri_index[0] : NULL;
+
+ /* merge */
+ foreach (Object *ob, objects) {
+ Mesh *mesh = ob->mesh;
+
+ /* We assume that if mesh doesn't need own BVH it was already included
+ * into a top-level BVH and no packing here is needed.
+ */
+ if (!mesh->need_build_bvh()) {
+ pack.object_node[object_offset++] = prim_offset;
+ continue;
+ }
+
+ /* if mesh already added once, don't add it again, but used set
+ * node offset for this object */
+ map<Mesh *, int>::iterator it = mesh_map.find(mesh);
+
+ if (mesh_map.find(mesh) != mesh_map.end()) {
+ int noffset = it->second;
+ pack.object_node[object_offset++] = noffset;
+ continue;
+ }
+
+ BVHEmbree *bvh = (BVHEmbree *)mesh->bvh;
+
+ rtc_memory_monitor_func(stats, unaccounted_mem, true);
+ unaccounted_mem = 0;
+
+ int mesh_tri_offset = mesh->tri_offset;
+ int mesh_curve_offset = mesh->curve_offset;
+
+ /* fill in node indexes for instances */
+ pack.object_node[object_offset++] = prim_offset;
+
+ mesh_map[mesh] = pack.object_node[object_offset - 1];
+
+ /* merge primitive, object and triangle indexes */
+ if (bvh->pack.prim_index.size()) {
+ size_t bvh_prim_index_size = bvh->pack.prim_index.size();
+ int *bvh_prim_index = &bvh->pack.prim_index[0];
+ int *bvh_prim_type = &bvh->pack.prim_type[0];
+ uint *bvh_prim_tri_index = &bvh->pack.prim_tri_index[0];
+
+ for (size_t i = 0; i < bvh_prim_index_size; ++i) {
+ if (bvh->pack.prim_type[i] & PRIMITIVE_ALL_CURVE) {
+ pack_prim_index[pack_prim_index_offset] = bvh_prim_index[i] + mesh_curve_offset;
+ pack_prim_tri_index[pack_prim_index_offset] = -1;
+ }
+ else {
+ pack_prim_index[pack_prim_index_offset] = bvh_prim_index[i] + mesh_tri_offset;
+ pack_prim_tri_index[pack_prim_index_offset] = bvh_prim_tri_index[i] +
+ pack_prim_tri_verts_offset;
+ }
+
+ pack_prim_type[pack_prim_index_offset] = bvh_prim_type[i];
+ pack_prim_object[pack_prim_index_offset] = 0;
+
+ ++pack_prim_index_offset;
+ }
+ }
+
+ /* Merge triangle vertices data. */
+ if (bvh->pack.prim_tri_verts.size()) {
+ const size_t prim_tri_size = bvh->pack.prim_tri_verts.size();
+ memcpy(pack_prim_tri_verts + pack_prim_tri_verts_offset,
+ &bvh->pack.prim_tri_verts[0],
+ prim_tri_size * sizeof(float4));
+ pack_prim_tri_verts_offset += prim_tri_size;
+ }
+
+ prim_offset += bvh->pack.prim_index.size();
+ }
}
void BVHEmbree::refit_nodes()
{
- /* Update all vertex buffers, then tell Embree to rebuild/-fit the BVHs. */
- unsigned geom_id = 0;
- foreach(Object *ob, objects) {
- if(!params.top_level || (ob->is_traceable() && !ob->mesh->is_instanced())) {
- if(params.primitive_mask & PRIMITIVE_ALL_TRIANGLE && ob->mesh->num_triangles() > 0) {
- update_tri_vertex_buffer(rtcGetGeometry(scene, geom_id), ob->mesh);
- rtcCommitGeometry(rtcGetGeometry(scene,geom_id));
- }
-
- if(params.primitive_mask & PRIMITIVE_ALL_CURVE && ob->mesh->num_curves() > 0) {
- update_curve_vertex_buffer(rtcGetGeometry(scene, geom_id+1), ob->mesh);
- rtcCommitGeometry(rtcGetGeometry(scene,geom_id+1));
- }
- }
- geom_id += 2;
- }
- rtcCommitScene(scene);
+ /* Update all vertex buffers, then tell Embree to rebuild/-fit the BVHs. */
+ unsigned geom_id = 0;
+ foreach (Object *ob, objects) {
+ if (!params.top_level || (ob->is_traceable() && !ob->mesh->is_instanced())) {
+ if (params.primitive_mask & PRIMITIVE_ALL_TRIANGLE && ob->mesh->num_triangles() > 0) {
+ update_tri_vertex_buffer(rtcGetGeometry(scene, geom_id), ob->mesh);
+ rtcCommitGeometry(rtcGetGeometry(scene, geom_id));
+ }
+
+ if (params.primitive_mask & PRIMITIVE_ALL_CURVE && ob->mesh->num_curves() > 0) {
+ update_curve_vertex_buffer(rtcGetGeometry(scene, geom_id + 1), ob->mesh);
+ rtcCommitGeometry(rtcGetGeometry(scene, geom_id + 1));
+ }
+ }
+ geom_id += 2;
+ }
+ rtcCommitScene(scene);
}
CCL_NAMESPACE_END
-#endif /* WITH_EMBREE */
+#endif /* WITH_EMBREE */
diff --git a/intern/cycles/bvh/bvh_embree.h b/intern/cycles/bvh/bvh_embree.h
index 983b6dc07da..60702713583 100644
--- a/intern/cycles/bvh/bvh_embree.h
+++ b/intern/cycles/bvh/bvh_embree.h
@@ -19,65 +19,68 @@
#ifdef WITH_EMBREE
-#include <embree3/rtcore.h>
-#include <embree3/rtcore_scene.h>
+# include <embree3/rtcore.h>
+# include <embree3/rtcore_scene.h>
-#include "bvh/bvh.h"
-#include "bvh/bvh_params.h"
+# include "bvh/bvh.h"
+# include "bvh/bvh_params.h"
-#include "util/util_thread.h"
-#include "util/util_types.h"
-#include "util/util_vector.h"
+# include "util/util_thread.h"
+# include "util/util_types.h"
+# include "util/util_vector.h"
CCL_NAMESPACE_BEGIN
class Mesh;
-class BVHEmbree : public BVH
-{
-public:
- virtual void build(Progress& progress, Stats *stats) override;
- virtual ~BVHEmbree();
- RTCScene scene;
- static void destroy(RTCScene);
-
- /* Building process. */
- virtual BVHNode *widen_children_nodes(const BVHNode *root) override;
-
-protected:
- friend class BVH;
- BVHEmbree(const BVHParams& params, const vector<Object*>& objects);
-
- virtual void pack_nodes(const BVHNode*) override;
- virtual void refit_nodes() override;
-
- void add_object(Object *ob, int i);
- void add_instance(Object *ob, int i);
- void add_curves(Object *ob, int i);
- void add_triangles(Object *ob, int i);
-
- ssize_t mem_used;
-
- void add_delayed_delete_scene(RTCScene scene) { delayed_delete_scenes.push_back(scene); }
- BVHEmbree *top_level;
-private:
- void delete_rtcScene();
- void update_tri_vertex_buffer(RTCGeometry geom_id, const Mesh* mesh);
- void update_curve_vertex_buffer(RTCGeometry geom_id, const Mesh* mesh);
-
- static RTCDevice rtc_shared_device;
- static int rtc_shared_users;
- static thread_mutex rtc_shared_mutex;
-
- Stats *stats;
- vector<RTCScene> delayed_delete_scenes;
- int curve_subdivisions;
- enum RTCBuildQuality build_quality;
- bool use_curves, use_ribbons, dynamic_scene;
+class BVHEmbree : public BVH {
+ public:
+ virtual void build(Progress &progress, Stats *stats) override;
+ virtual ~BVHEmbree();
+ RTCScene scene;
+ static void destroy(RTCScene);
+
+ /* Building process. */
+ virtual BVHNode *widen_children_nodes(const BVHNode *root) override;
+
+ protected:
+ friend class BVH;
+ BVHEmbree(const BVHParams &params, const vector<Object *> &objects);
+
+ virtual void pack_nodes(const BVHNode *) override;
+ virtual void refit_nodes() override;
+
+ void add_object(Object *ob, int i);
+ void add_instance(Object *ob, int i);
+ void add_curves(Object *ob, int i);
+ void add_triangles(Object *ob, int i);
+
+ ssize_t mem_used;
+
+ void add_delayed_delete_scene(RTCScene scene)
+ {
+ delayed_delete_scenes.push_back(scene);
+ }
+ BVHEmbree *top_level;
+
+ private:
+ void delete_rtcScene();
+ void update_tri_vertex_buffer(RTCGeometry geom_id, const Mesh *mesh);
+ void update_curve_vertex_buffer(RTCGeometry geom_id, const Mesh *mesh);
+
+ static RTCDevice rtc_shared_device;
+ static int rtc_shared_users;
+ static thread_mutex rtc_shared_mutex;
+
+ Stats *stats;
+ vector<RTCScene> delayed_delete_scenes;
+ int curve_subdivisions;
+ enum RTCBuildQuality build_quality;
+ bool use_curves, use_ribbons, dynamic_scene;
};
CCL_NAMESPACE_END
-#endif /* WITH_EMBREE */
+#endif /* WITH_EMBREE */
-#endif /* __BVH_EMBREE_H__ */
+#endif /* __BVH_EMBREE_H__ */
diff --git a/intern/cycles/bvh/bvh_node.cpp b/intern/cycles/bvh/bvh_node.cpp
index 614fb6be88a..38b554acfbf 100644
--- a/intern/cycles/bvh/bvh_node.cpp
+++ b/intern/cycles/bvh/bvh_node.cpp
@@ -28,199 +28,197 @@ CCL_NAMESPACE_BEGIN
int BVHNode::getSubtreeSize(BVH_STAT stat) const
{
- int cnt = 0;
-
- switch(stat)
- {
- case BVH_STAT_NODE_COUNT:
- cnt = 1;
- break;
- case BVH_STAT_LEAF_COUNT:
- cnt = is_leaf() ? 1 : 0;
- break;
- case BVH_STAT_INNER_COUNT:
- cnt = is_leaf() ? 0 : 1;
- break;
- case BVH_STAT_TRIANGLE_COUNT:
- cnt = is_leaf() ? reinterpret_cast<const LeafNode*>(this)->num_triangles() : 0;
- break;
- case BVH_STAT_CHILDNODE_COUNT:
- cnt = num_children();
- break;
- case BVH_STAT_ALIGNED_COUNT:
- if(!is_unaligned) {
- cnt = 1;
- }
- break;
- case BVH_STAT_UNALIGNED_COUNT:
- if(is_unaligned) {
- cnt = 1;
- }
- break;
- case BVH_STAT_ALIGNED_INNER_COUNT:
- if(!is_leaf()) {
- bool has_unaligned = false;
- for(int j = 0; j < num_children(); j++) {
- has_unaligned |= get_child(j)->is_unaligned;
- }
- cnt += has_unaligned? 0: 1;
- }
- break;
- case BVH_STAT_UNALIGNED_INNER_COUNT:
- if(!is_leaf()) {
- bool has_unaligned = false;
- for(int j = 0; j < num_children(); j++) {
- has_unaligned |= get_child(j)->is_unaligned;
- }
- cnt += has_unaligned? 1: 0;
- }
- break;
- case BVH_STAT_ALIGNED_LEAF_COUNT:
- cnt = (is_leaf() && !is_unaligned) ? 1 : 0;
- break;
- case BVH_STAT_UNALIGNED_LEAF_COUNT:
- cnt = (is_leaf() && is_unaligned) ? 1 : 0;
- break;
- case BVH_STAT_DEPTH:
- if(is_leaf()) {
- cnt = 1;
- }
- else {
- for(int i = 0; i < num_children(); i++) {
- cnt = max(cnt, get_child(i)->getSubtreeSize(stat));
- }
- cnt += 1;
- }
- return cnt;
- default:
- assert(0); /* unknown mode */
- }
-
- if(!is_leaf())
- for(int i = 0; i < num_children(); i++)
- cnt += get_child(i)->getSubtreeSize(stat);
-
- return cnt;
+ int cnt = 0;
+
+ switch (stat) {
+ case BVH_STAT_NODE_COUNT:
+ cnt = 1;
+ break;
+ case BVH_STAT_LEAF_COUNT:
+ cnt = is_leaf() ? 1 : 0;
+ break;
+ case BVH_STAT_INNER_COUNT:
+ cnt = is_leaf() ? 0 : 1;
+ break;
+ case BVH_STAT_TRIANGLE_COUNT:
+ cnt = is_leaf() ? reinterpret_cast<const LeafNode *>(this)->num_triangles() : 0;
+ break;
+ case BVH_STAT_CHILDNODE_COUNT:
+ cnt = num_children();
+ break;
+ case BVH_STAT_ALIGNED_COUNT:
+ if (!is_unaligned) {
+ cnt = 1;
+ }
+ break;
+ case BVH_STAT_UNALIGNED_COUNT:
+ if (is_unaligned) {
+ cnt = 1;
+ }
+ break;
+ case BVH_STAT_ALIGNED_INNER_COUNT:
+ if (!is_leaf()) {
+ bool has_unaligned = false;
+ for (int j = 0; j < num_children(); j++) {
+ has_unaligned |= get_child(j)->is_unaligned;
+ }
+ cnt += has_unaligned ? 0 : 1;
+ }
+ break;
+ case BVH_STAT_UNALIGNED_INNER_COUNT:
+ if (!is_leaf()) {
+ bool has_unaligned = false;
+ for (int j = 0; j < num_children(); j++) {
+ has_unaligned |= get_child(j)->is_unaligned;
+ }
+ cnt += has_unaligned ? 1 : 0;
+ }
+ break;
+ case BVH_STAT_ALIGNED_LEAF_COUNT:
+ cnt = (is_leaf() && !is_unaligned) ? 1 : 0;
+ break;
+ case BVH_STAT_UNALIGNED_LEAF_COUNT:
+ cnt = (is_leaf() && is_unaligned) ? 1 : 0;
+ break;
+ case BVH_STAT_DEPTH:
+ if (is_leaf()) {
+ cnt = 1;
+ }
+ else {
+ for (int i = 0; i < num_children(); i++) {
+ cnt = max(cnt, get_child(i)->getSubtreeSize(stat));
+ }
+ cnt += 1;
+ }
+ return cnt;
+ default:
+ assert(0); /* unknown mode */
+ }
+
+ if (!is_leaf())
+ for (int i = 0; i < num_children(); i++)
+ cnt += get_child(i)->getSubtreeSize(stat);
+
+ return cnt;
}
void BVHNode::deleteSubtree()
{
- for(int i = 0; i < num_children(); i++)
- if(get_child(i))
- get_child(i)->deleteSubtree();
+ for (int i = 0; i < num_children(); i++)
+ if (get_child(i))
+ get_child(i)->deleteSubtree();
- delete this;
+ delete this;
}
-float BVHNode::computeSubtreeSAHCost(const BVHParams& p, float probability) const
+float BVHNode::computeSubtreeSAHCost(const BVHParams &p, float probability) const
{
- float SAH = probability * p.cost(num_children(), num_triangles());
+ float SAH = probability * p.cost(num_children(), num_triangles());
- for(int i = 0; i < num_children(); i++) {
- BVHNode *child = get_child(i);
- SAH += child->computeSubtreeSAHCost(p, probability * child->bounds.safe_area()/bounds.safe_area());
- }
+ for (int i = 0; i < num_children(); i++) {
+ BVHNode *child = get_child(i);
+ SAH += child->computeSubtreeSAHCost(
+ p, probability * child->bounds.safe_area() / bounds.safe_area());
+ }
- return SAH;
+ return SAH;
}
uint BVHNode::update_visibility()
{
- if(!is_leaf() && visibility == 0) {
- InnerNode *inner = (InnerNode*)this;
- BVHNode *child0 = inner->children[0];
- BVHNode *child1 = inner->children[1];
+ if (!is_leaf() && visibility == 0) {
+ InnerNode *inner = (InnerNode *)this;
+ BVHNode *child0 = inner->children[0];
+ BVHNode *child1 = inner->children[1];
- visibility = child0->update_visibility()|child1->update_visibility();
- }
+ visibility = child0->update_visibility() | child1->update_visibility();
+ }
- return visibility;
+ return visibility;
}
void BVHNode::update_time()
{
- if(!is_leaf()) {
- InnerNode *inner = (InnerNode*)this;
- BVHNode *child0 = inner->children[0];
- BVHNode *child1 = inner->children[1];
- child0->update_time();
- child1->update_time();
- time_from = min(child0->time_from, child1->time_from);
- time_to = max(child0->time_to, child1->time_to);
- }
+ if (!is_leaf()) {
+ InnerNode *inner = (InnerNode *)this;
+ BVHNode *child0 = inner->children[0];
+ BVHNode *child1 = inner->children[1];
+ child0->update_time();
+ child1->update_time();
+ time_from = min(child0->time_from, child1->time_from);
+ time_to = max(child0->time_to, child1->time_to);
+ }
}
namespace {
struct DumpTraversalContext {
- /* Descriptor of wile where writing is happening. */
- FILE *stream;
- /* Unique identifier of the node current. */
- int id;
+ /* Descriptor of wile where writing is happening. */
+ FILE *stream;
+ /* Unique identifier of the node current. */
+ int id;
};
-void dump_subtree(DumpTraversalContext *context,
- const BVHNode *node,
- const BVHNode *parent = NULL)
+void dump_subtree(DumpTraversalContext *context, const BVHNode *node, const BVHNode *parent = NULL)
{
- if(node->is_leaf()) {
- fprintf(context->stream,
- " node_%p [label=\"%d\",fillcolor=\"#ccccee\",style=filled]\n",
- node,
- context->id);
- }
- else {
- fprintf(context->stream,
- " node_%p [label=\"%d\",fillcolor=\"#cceecc\",style=filled]\n",
- node,
- context->id);
- }
- if(parent != NULL) {
- fprintf(context->stream, " node_%p -> node_%p;\n", parent, node);
- }
- context->id += 1;
- for(int i = 0; i < node->num_children(); ++i) {
- dump_subtree(context, node->get_child(i), node);
- }
+ if (node->is_leaf()) {
+ fprintf(context->stream,
+ " node_%p [label=\"%d\",fillcolor=\"#ccccee\",style=filled]\n",
+ node,
+ context->id);
+ }
+ else {
+ fprintf(context->stream,
+ " node_%p [label=\"%d\",fillcolor=\"#cceecc\",style=filled]\n",
+ node,
+ context->id);
+ }
+ if (parent != NULL) {
+ fprintf(context->stream, " node_%p -> node_%p;\n", parent, node);
+ }
+ context->id += 1;
+ for (int i = 0; i < node->num_children(); ++i) {
+ dump_subtree(context, node->get_child(i), node);
+ }
}
} // namespace
void BVHNode::dump_graph(const char *filename)
{
- DumpTraversalContext context;
- context.stream = fopen(filename, "w");
- if(context.stream == NULL) {
- return;
- }
- context.id = 0;
- fprintf(context.stream, "digraph BVH {\n");
- dump_subtree(&context, this);
- fprintf(context.stream, "}\n");
- fclose(context.stream);
+ DumpTraversalContext context;
+ context.stream = fopen(filename, "w");
+ if (context.stream == NULL) {
+ return;
+ }
+ context.id = 0;
+ fprintf(context.stream, "digraph BVH {\n");
+ dump_subtree(&context, this);
+ fprintf(context.stream, "}\n");
+ fclose(context.stream);
}
/* Inner Node */
void InnerNode::print(int depth) const
{
- for(int i = 0; i < depth; i++)
- printf(" ");
+ for (int i = 0; i < depth; i++)
+ printf(" ");
- printf("inner node %p\n", (void*)this);
+ printf("inner node %p\n", (void *)this);
- if(children[0])
- children[0]->print(depth+1);
- if(children[1])
- children[1]->print(depth+1);
+ if (children[0])
+ children[0]->print(depth + 1);
+ if (children[1])
+ children[1]->print(depth + 1);
}
void LeafNode::print(int depth) const
{
- for(int i = 0; i < depth; i++)
- printf(" ");
+ for (int i = 0; i < depth; i++)
+ printf(" ");
- printf("leaf node %d to %d\n", lo, hi);
+ printf("leaf node %d to %d\n", lo, hi);
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/bvh/bvh_node.h b/intern/cycles/bvh/bvh_node.h
index d9105d69739..797dd5b694e 100644
--- a/intern/cycles/bvh/bvh_node.h
+++ b/intern/cycles/bvh/bvh_node.h
@@ -24,227 +24,232 @@
CCL_NAMESPACE_BEGIN
enum BVH_STAT {
- BVH_STAT_NODE_COUNT,
- BVH_STAT_INNER_COUNT,
- BVH_STAT_LEAF_COUNT,
- BVH_STAT_TRIANGLE_COUNT,
- BVH_STAT_CHILDNODE_COUNT,
- BVH_STAT_ALIGNED_COUNT,
- BVH_STAT_UNALIGNED_COUNT,
- BVH_STAT_ALIGNED_INNER_COUNT,
- BVH_STAT_UNALIGNED_INNER_COUNT,
- BVH_STAT_ALIGNED_LEAF_COUNT,
- BVH_STAT_UNALIGNED_LEAF_COUNT,
- BVH_STAT_DEPTH,
+ BVH_STAT_NODE_COUNT,
+ BVH_STAT_INNER_COUNT,
+ BVH_STAT_LEAF_COUNT,
+ BVH_STAT_TRIANGLE_COUNT,
+ BVH_STAT_CHILDNODE_COUNT,
+ BVH_STAT_ALIGNED_COUNT,
+ BVH_STAT_UNALIGNED_COUNT,
+ BVH_STAT_ALIGNED_INNER_COUNT,
+ BVH_STAT_UNALIGNED_INNER_COUNT,
+ BVH_STAT_ALIGNED_LEAF_COUNT,
+ BVH_STAT_UNALIGNED_LEAF_COUNT,
+ BVH_STAT_DEPTH,
};
class BVHParams;
-class BVHNode
-{
-public:
- virtual ~BVHNode()
- {
- delete aligned_space;
- }
-
- virtual bool is_leaf() const = 0;
- virtual int num_children() const = 0;
- virtual BVHNode *get_child(int i) const = 0;
- virtual int num_triangles() const { return 0; }
- virtual void print(int depth = 0) const = 0;
-
- inline void set_aligned_space(const Transform& aligned_space)
- {
- is_unaligned = true;
- if(this->aligned_space == NULL) {
- this->aligned_space = new Transform(aligned_space);
- }
- else {
- *this->aligned_space = aligned_space;
- }
- }
-
- inline Transform get_aligned_space() const
- {
- if(aligned_space == NULL) {
- return transform_identity();
- }
- return *aligned_space;
- }
-
- inline bool has_unaligned() const
- {
- if(is_leaf()) {
- return false;
- }
- for(int i = 0; i < num_children(); ++i) {
- if(get_child(i)->is_unaligned) {
- return true;
- }
- }
- return false;
- }
-
- // Subtree functions
- int getSubtreeSize(BVH_STAT stat=BVH_STAT_NODE_COUNT) const;
- float computeSubtreeSAHCost(const BVHParams& p, float probability = 1.0f) const;
- void deleteSubtree();
-
- uint update_visibility();
- void update_time();
-
- /* Dump the content of the tree as a graphviz file. */
- void dump_graph(const char *filename);
-
- // Properties.
- BoundBox bounds;
- uint visibility;
-
- bool is_unaligned;
-
- /* TODO(sergey): Can be stored as 3x3 matrix, but better to have some
- * utilities and type defines in util_transform first.
- */
- Transform *aligned_space;
-
- float time_from, time_to;
-
-protected:
- explicit BVHNode(const BoundBox& bounds)
- : bounds(bounds),
- visibility(0),
- is_unaligned(false),
- aligned_space(NULL),
- time_from(0.0f),
- time_to(1.0f)
- {
- }
-
- explicit BVHNode(const BVHNode& other)
- : bounds(other.bounds),
- visibility(other.visibility),
- is_unaligned(other.is_unaligned),
- aligned_space(NULL),
- time_from(other.time_from),
- time_to(other.time_to)
- {
- if(other.aligned_space != NULL) {
- assert(other.is_unaligned);
- aligned_space = new Transform();
- *aligned_space = *other.aligned_space;
- }
- else {
- assert(!other.is_unaligned);
- }
- }
+class BVHNode {
+ public:
+ virtual ~BVHNode()
+ {
+ delete aligned_space;
+ }
+
+ virtual bool is_leaf() const = 0;
+ virtual int num_children() const = 0;
+ virtual BVHNode *get_child(int i) const = 0;
+ virtual int num_triangles() const
+ {
+ return 0;
+ }
+ virtual void print(int depth = 0) const = 0;
+
+ inline void set_aligned_space(const Transform &aligned_space)
+ {
+ is_unaligned = true;
+ if (this->aligned_space == NULL) {
+ this->aligned_space = new Transform(aligned_space);
+ }
+ else {
+ *this->aligned_space = aligned_space;
+ }
+ }
+
+ inline Transform get_aligned_space() const
+ {
+ if (aligned_space == NULL) {
+ return transform_identity();
+ }
+ return *aligned_space;
+ }
+
+ inline bool has_unaligned() const
+ {
+ if (is_leaf()) {
+ return false;
+ }
+ for (int i = 0; i < num_children(); ++i) {
+ if (get_child(i)->is_unaligned) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ // Subtree functions
+ int getSubtreeSize(BVH_STAT stat = BVH_STAT_NODE_COUNT) const;
+ float computeSubtreeSAHCost(const BVHParams &p, float probability = 1.0f) const;
+ void deleteSubtree();
+
+ uint update_visibility();
+ void update_time();
+
+ /* Dump the content of the tree as a graphviz file. */
+ void dump_graph(const char *filename);
+
+ // Properties.
+ BoundBox bounds;
+ uint visibility;
+
+ bool is_unaligned;
+
+ /* TODO(sergey): Can be stored as 3x3 matrix, but better to have some
+ * utilities and type defines in util_transform first.
+ */
+ Transform *aligned_space;
+
+ float time_from, time_to;
+
+ protected:
+ explicit BVHNode(const BoundBox &bounds)
+ : bounds(bounds),
+ visibility(0),
+ is_unaligned(false),
+ aligned_space(NULL),
+ time_from(0.0f),
+ time_to(1.0f)
+ {
+ }
+
+ explicit BVHNode(const BVHNode &other)
+ : bounds(other.bounds),
+ visibility(other.visibility),
+ is_unaligned(other.is_unaligned),
+ aligned_space(NULL),
+ time_from(other.time_from),
+ time_to(other.time_to)
+ {
+ if (other.aligned_space != NULL) {
+ assert(other.is_unaligned);
+ aligned_space = new Transform();
+ *aligned_space = *other.aligned_space;
+ }
+ else {
+ assert(!other.is_unaligned);
+ }
+ }
};
-class InnerNode : public BVHNode
-{
-public:
- static constexpr int kNumMaxChildren = 8;
-
- InnerNode(const BoundBox& bounds,
- BVHNode* child0,
- BVHNode* child1)
- : BVHNode(bounds),
- num_children_(2)
- {
- children[0] = child0;
- children[1] = child1;
- reset_unused_children();
-
- if(child0 && child1) {
- visibility = child0->visibility | child1->visibility;
- }
- else {
- /* Happens on build cancel. */
- visibility = 0;
- }
- }
-
- InnerNode(const BoundBox& bounds,
- BVHNode** children,
- const int num_children)
- : BVHNode(bounds),
- num_children_(num_children)
- {
- visibility = 0;
- time_from = FLT_MAX;
- time_to = -FLT_MAX;
- for(int i = 0; i < num_children; ++i) {
- assert(children[i] != NULL);
- visibility |= children[i]->visibility;
- this->children[i] = children[i];
- time_from = min(time_from, children[i]->time_from);
- time_to = max(time_to, children[i]->time_to);
- }
- reset_unused_children();
- }
-
- /* NOTE: This function is only used during binary BVH builder, and it
- * supposed to be configured to have 2 children which will be filled in in a
- * bit. But this is important to have children reset to NULL. */
- explicit InnerNode(const BoundBox& bounds)
- : BVHNode(bounds),
- num_children_(0)
- {
- reset_unused_children();
- visibility = 0;
- num_children_ = 2;
- }
-
- bool is_leaf() const { return false; }
- int num_children() const { return num_children_; }
- BVHNode *get_child(int i) const
- {
- assert(i >= 0 && i < num_children_);
- return children[i];
- }
- void print(int depth) const;
-
- int num_children_;
- BVHNode *children[kNumMaxChildren];
-
-protected:
- void reset_unused_children()
- {
- for(int i = num_children_; i < kNumMaxChildren; ++i) {
- children[i] = NULL;
- }
- }
+class InnerNode : public BVHNode {
+ public:
+ static constexpr int kNumMaxChildren = 8;
+
+ InnerNode(const BoundBox &bounds, BVHNode *child0, BVHNode *child1)
+ : BVHNode(bounds), num_children_(2)
+ {
+ children[0] = child0;
+ children[1] = child1;
+ reset_unused_children();
+
+ if (child0 && child1) {
+ visibility = child0->visibility | child1->visibility;
+ }
+ else {
+ /* Happens on build cancel. */
+ visibility = 0;
+ }
+ }
+
+ InnerNode(const BoundBox &bounds, BVHNode **children, const int num_children)
+ : BVHNode(bounds), num_children_(num_children)
+ {
+ visibility = 0;
+ time_from = FLT_MAX;
+ time_to = -FLT_MAX;
+ for (int i = 0; i < num_children; ++i) {
+ assert(children[i] != NULL);
+ visibility |= children[i]->visibility;
+ this->children[i] = children[i];
+ time_from = min(time_from, children[i]->time_from);
+ time_to = max(time_to, children[i]->time_to);
+ }
+ reset_unused_children();
+ }
+
+ /* NOTE: This function is only used during binary BVH builder, and it
+ * supposed to be configured to have 2 children which will be filled in in a
+ * bit. But this is important to have children reset to NULL. */
+ explicit InnerNode(const BoundBox &bounds) : BVHNode(bounds), num_children_(0)
+ {
+ reset_unused_children();
+ visibility = 0;
+ num_children_ = 2;
+ }
+
+ bool is_leaf() const
+ {
+ return false;
+ }
+ int num_children() const
+ {
+ return num_children_;
+ }
+ BVHNode *get_child(int i) const
+ {
+ assert(i >= 0 && i < num_children_);
+ return children[i];
+ }
+ void print(int depth) const;
+
+ int num_children_;
+ BVHNode *children[kNumMaxChildren];
+
+ protected:
+ void reset_unused_children()
+ {
+ for (int i = num_children_; i < kNumMaxChildren; ++i) {
+ children[i] = NULL;
+ }
+ }
};
-class LeafNode : public BVHNode
-{
-public:
- LeafNode(const BoundBox& bounds, uint visibility, int lo, int hi)
- : BVHNode(bounds),
- lo(lo),
- hi(hi)
- {
- this->bounds = bounds;
- this->visibility = visibility;
- }
-
- LeafNode(const LeafNode& other)
- : BVHNode(other),
- lo(other.lo),
- hi(other.hi)
- {
- }
-
- bool is_leaf() const { return true; }
- int num_children() const { return 0; }
- BVHNode *get_child(int) const { return NULL; }
- int num_triangles() const { return hi - lo; }
- void print(int depth) const;
-
- int lo;
- int hi;
+class LeafNode : public BVHNode {
+ public:
+ LeafNode(const BoundBox &bounds, uint visibility, int lo, int hi)
+ : BVHNode(bounds), lo(lo), hi(hi)
+ {
+ this->bounds = bounds;
+ this->visibility = visibility;
+ }
+
+ LeafNode(const LeafNode &other) : BVHNode(other), lo(other.lo), hi(other.hi)
+ {
+ }
+
+ bool is_leaf() const
+ {
+ return true;
+ }
+ int num_children() const
+ {
+ return 0;
+ }
+ BVHNode *get_child(int) const
+ {
+ return NULL;
+ }
+ int num_triangles() const
+ {
+ return hi - lo;
+ }
+ void print(int depth) const;
+
+ int lo;
+ int hi;
};
CCL_NAMESPACE_END
-#endif /* __BVH_NODE_H__ */
+#endif /* __BVH_NODE_H__ */
diff --git a/intern/cycles/bvh/bvh_params.h b/intern/cycles/bvh/bvh_params.h
index 6408d56da80..2731662a39d 100644
--- a/intern/cycles/bvh/bvh_params.h
+++ b/intern/cycles/bvh/bvh_params.h
@@ -43,120 +43,121 @@ const char *bvh_layout_name(BVHLayout layout);
/* BVH Parameters */
-class BVHParams
-{
-public:
-
- /* spatial split area threshold */
- bool use_spatial_split;
- float spatial_split_alpha;
-
- /* Unaligned nodes creation threshold */
- float unaligned_split_threshold;
-
- /* SAH costs */
- float sah_node_cost;
- float sah_primitive_cost;
-
- /* number of primitives in leaf */
- int min_leaf_size;
- int max_triangle_leaf_size;
- int max_motion_triangle_leaf_size;
- int max_curve_leaf_size;
- int max_motion_curve_leaf_size;
-
- /* object or mesh level bvh */
- bool top_level;
-
- /* BVH layout to be built. */
- BVHLayout bvh_layout;
-
- /* Mask of primitives to be included into the BVH. */
- int primitive_mask;
-
- /* Use unaligned bounding boxes.
- * Only used for curves BVH.
- */
- bool use_unaligned_nodes;
-
- /* Split time range to this number of steps and create leaf node for each
- * of this time steps.
- *
- * Speeds up rendering of motion curve primitives in the cost of higher
- * memory usage.
- */
- int num_motion_curve_steps;
-
- /* Same as above, but for triangle primitives. */
- int num_motion_triangle_steps;
-
- /* Same as in SceneParams. */
- int bvh_type;
-
- /* These are needed for Embree. */
- int curve_flags;
- int curve_subdivisions;
-
- /* fixed parameters */
- enum {
- MAX_DEPTH = 64,
- MAX_SPATIAL_DEPTH = 48,
- NUM_SPATIAL_BINS = 32
- };
-
- BVHParams()
- {
- use_spatial_split = true;
- spatial_split_alpha = 1e-5f;
-
- unaligned_split_threshold = 0.7f;
-
- /* todo: see if splitting up primitive cost to be separate for triangles
- * and curves can help. so far in tests it doesn't help, but why? */
- sah_node_cost = 1.0f;
- sah_primitive_cost = 1.0f;
-
- min_leaf_size = 1;
- max_triangle_leaf_size = 8;
- max_motion_triangle_leaf_size = 8;
- max_curve_leaf_size = 1;
- max_motion_curve_leaf_size = 4;
-
- top_level = false;
- bvh_layout = BVH_LAYOUT_BVH2;
- use_unaligned_nodes = false;
-
- primitive_mask = PRIMITIVE_ALL;
-
- num_motion_curve_steps = 0;
- num_motion_triangle_steps = 0;
-
- bvh_type = 0;
-
- curve_flags = 0;
- curve_subdivisions = 4;
- }
-
- /* SAH costs */
- __forceinline float cost(int num_nodes, int num_primitives) const
- { return node_cost(num_nodes) + primitive_cost(num_primitives); }
-
- __forceinline float primitive_cost(int n) const
- { return n*sah_primitive_cost; }
-
- __forceinline float node_cost(int n) const
- { return n*sah_node_cost; }
-
- __forceinline bool small_enough_for_leaf(int size, int level)
- { return (size <= min_leaf_size || level >= MAX_DEPTH); }
-
- /* Gets best matching BVH.
- *
- * If the requested layout is supported by the device, it will be used.
- * Otherwise, widest supported layout below that will be used.
- */
- static BVHLayout best_bvh_layout(BVHLayout requested_layout,
- BVHLayoutMask supported_layouts);
+class BVHParams {
+ public:
+ /* spatial split area threshold */
+ bool use_spatial_split;
+ float spatial_split_alpha;
+
+ /* Unaligned nodes creation threshold */
+ float unaligned_split_threshold;
+
+ /* SAH costs */
+ float sah_node_cost;
+ float sah_primitive_cost;
+
+ /* number of primitives in leaf */
+ int min_leaf_size;
+ int max_triangle_leaf_size;
+ int max_motion_triangle_leaf_size;
+ int max_curve_leaf_size;
+ int max_motion_curve_leaf_size;
+
+ /* object or mesh level bvh */
+ bool top_level;
+
+ /* BVH layout to be built. */
+ BVHLayout bvh_layout;
+
+ /* Mask of primitives to be included into the BVH. */
+ int primitive_mask;
+
+ /* Use unaligned bounding boxes.
+ * Only used for curves BVH.
+ */
+ bool use_unaligned_nodes;
+
+ /* Split time range to this number of steps and create leaf node for each
+ * of this time steps.
+ *
+ * Speeds up rendering of motion curve primitives in the cost of higher
+ * memory usage.
+ */
+ int num_motion_curve_steps;
+
+ /* Same as above, but for triangle primitives. */
+ int num_motion_triangle_steps;
+
+ /* Same as in SceneParams. */
+ int bvh_type;
+
+ /* These are needed for Embree. */
+ int curve_flags;
+ int curve_subdivisions;
+
+ /* fixed parameters */
+ enum { MAX_DEPTH = 64, MAX_SPATIAL_DEPTH = 48, NUM_SPATIAL_BINS = 32 };
+
+ BVHParams()
+ {
+ use_spatial_split = true;
+ spatial_split_alpha = 1e-5f;
+
+ unaligned_split_threshold = 0.7f;
+
+ /* todo: see if splitting up primitive cost to be separate for triangles
+ * and curves can help. so far in tests it doesn't help, but why? */
+ sah_node_cost = 1.0f;
+ sah_primitive_cost = 1.0f;
+
+ min_leaf_size = 1;
+ max_triangle_leaf_size = 8;
+ max_motion_triangle_leaf_size = 8;
+ max_curve_leaf_size = 1;
+ max_motion_curve_leaf_size = 4;
+
+ top_level = false;
+ bvh_layout = BVH_LAYOUT_BVH2;
+ use_unaligned_nodes = false;
+
+ primitive_mask = PRIMITIVE_ALL;
+
+ num_motion_curve_steps = 0;
+ num_motion_triangle_steps = 0;
+
+ bvh_type = 0;
+
+ curve_flags = 0;
+ curve_subdivisions = 4;
+ }
+
+ /* SAH costs */
+ __forceinline float cost(int num_nodes, int num_primitives) const
+ {
+ return node_cost(num_nodes) + primitive_cost(num_primitives);
+ }
+
+ __forceinline float primitive_cost(int n) const
+ {
+ return n * sah_primitive_cost;
+ }
+
+ __forceinline float node_cost(int n) const
+ {
+ return n * sah_node_cost;
+ }
+
+ __forceinline bool small_enough_for_leaf(int size, int level)
+ {
+ return (size <= min_leaf_size || level >= MAX_DEPTH);
+ }
+
+ /* Gets best matching BVH.
+ *
+ * If the requested layout is supported by the device, it will be used.
+ * Otherwise, widest supported layout below that will be used.
+ */
+ static BVHLayout best_bvh_layout(BVHLayout requested_layout, BVHLayoutMask supported_layouts);
};
/* BVH Reference
@@ -164,49 +165,65 @@ public:
* Reference to a primitive. Primitive index and object are sneakily packed
* into BoundBox to reduce memory usage and align nicely */
-class BVHReference
-{
-public:
- __forceinline BVHReference() {}
-
- __forceinline BVHReference(const BoundBox& bounds_,
- int prim_index_,
- int prim_object_,
- int prim_type,
- float time_from = 0.0f,
- float time_to = 1.0f)
- : rbounds(bounds_),
- time_from_(time_from),
- time_to_(time_to)
- {
- rbounds.min.w = __int_as_float(prim_index_);
- rbounds.max.w = __int_as_float(prim_object_);
- type = prim_type;
- }
-
- __forceinline const BoundBox& bounds() const { return rbounds; }
- __forceinline int prim_index() const { return __float_as_int(rbounds.min.w); }
- __forceinline int prim_object() const { return __float_as_int(rbounds.max.w); }
- __forceinline int prim_type() const { return type; }
- __forceinline float time_from() const { return time_from_; }
- __forceinline float time_to() const { return time_to_; }
-
-
- BVHReference& operator=(const BVHReference &arg) {
- if(&arg != this) {
- /* TODO(sergey): Check if it is still faster to memcpy() with
- * modern compilers.
- */
- memcpy((void *)this, &arg, sizeof(BVHReference));
- }
- return *this;
- }
-
-
-protected:
- BoundBox rbounds;
- uint type;
- float time_from_, time_to_;
+class BVHReference {
+ public:
+ __forceinline BVHReference()
+ {
+ }
+
+ __forceinline BVHReference(const BoundBox &bounds_,
+ int prim_index_,
+ int prim_object_,
+ int prim_type,
+ float time_from = 0.0f,
+ float time_to = 1.0f)
+ : rbounds(bounds_), time_from_(time_from), time_to_(time_to)
+ {
+ rbounds.min.w = __int_as_float(prim_index_);
+ rbounds.max.w = __int_as_float(prim_object_);
+ type = prim_type;
+ }
+
+ __forceinline const BoundBox &bounds() const
+ {
+ return rbounds;
+ }
+ __forceinline int prim_index() const
+ {
+ return __float_as_int(rbounds.min.w);
+ }
+ __forceinline int prim_object() const
+ {
+ return __float_as_int(rbounds.max.w);
+ }
+ __forceinline int prim_type() const
+ {
+ return type;
+ }
+ __forceinline float time_from() const
+ {
+ return time_from_;
+ }
+ __forceinline float time_to() const
+ {
+ return time_to_;
+ }
+
+ BVHReference &operator=(const BVHReference &arg)
+ {
+ if (&arg != this) {
+ /* TODO(sergey): Check if it is still faster to memcpy() with
+ * modern compilers.
+ */
+ memcpy((void *)this, &arg, sizeof(BVHReference));
+ }
+ return *this;
+ }
+
+ protected:
+ BoundBox rbounds;
+ uint type;
+ float time_from_, time_to_;
};
/* BVH Range
@@ -215,53 +232,68 @@ protected:
* the reference array of a subset of primitives Again uses trickery to pack
* integers into BoundBox for alignment purposes. */
-class BVHRange
-{
-public:
- __forceinline BVHRange()
- {
- rbounds.min.w = __int_as_float(0);
- rbounds.max.w = __int_as_float(0);
- }
-
- __forceinline BVHRange(const BoundBox& bounds_, int start_, int size_)
- : rbounds(bounds_)
- {
- rbounds.min.w = __int_as_float(start_);
- rbounds.max.w = __int_as_float(size_);
- }
-
- __forceinline BVHRange(const BoundBox& bounds_, const BoundBox& cbounds_, int start_, int size_)
- : rbounds(bounds_), cbounds(cbounds_)
- {
- rbounds.min.w = __int_as_float(start_);
- rbounds.max.w = __int_as_float(size_);
- }
-
- __forceinline void set_start(int start_) { rbounds.min.w = __int_as_float(start_); }
-
- __forceinline const BoundBox& bounds() const { return rbounds; }
- __forceinline const BoundBox& cent_bounds() const { return cbounds; }
- __forceinline int start() const { return __float_as_int(rbounds.min.w); }
- __forceinline int size() const { return __float_as_int(rbounds.max.w); }
- __forceinline int end() const { return start() + size(); }
-
-protected:
- BoundBox rbounds;
- BoundBox cbounds;
+class BVHRange {
+ public:
+ __forceinline BVHRange()
+ {
+ rbounds.min.w = __int_as_float(0);
+ rbounds.max.w = __int_as_float(0);
+ }
+
+ __forceinline BVHRange(const BoundBox &bounds_, int start_, int size_) : rbounds(bounds_)
+ {
+ rbounds.min.w = __int_as_float(start_);
+ rbounds.max.w = __int_as_float(size_);
+ }
+
+ __forceinline BVHRange(const BoundBox &bounds_, const BoundBox &cbounds_, int start_, int size_)
+ : rbounds(bounds_), cbounds(cbounds_)
+ {
+ rbounds.min.w = __int_as_float(start_);
+ rbounds.max.w = __int_as_float(size_);
+ }
+
+ __forceinline void set_start(int start_)
+ {
+ rbounds.min.w = __int_as_float(start_);
+ }
+
+ __forceinline const BoundBox &bounds() const
+ {
+ return rbounds;
+ }
+ __forceinline const BoundBox &cent_bounds() const
+ {
+ return cbounds;
+ }
+ __forceinline int start() const
+ {
+ return __float_as_int(rbounds.min.w);
+ }
+ __forceinline int size() const
+ {
+ return __float_as_int(rbounds.max.w);
+ }
+ __forceinline int end() const
+ {
+ return start() + size();
+ }
+
+ protected:
+ BoundBox rbounds;
+ BoundBox cbounds;
};
/* BVH Spatial Bin */
-struct BVHSpatialBin
-{
- BoundBox bounds;
- int enter;
- int exit;
+struct BVHSpatialBin {
+ BoundBox bounds;
+ int enter;
+ int exit;
- __forceinline BVHSpatialBin()
- {
- }
+ __forceinline BVHSpatialBin()
+ {
+ }
};
/* BVH Spatial Storage
@@ -272,18 +304,18 @@ struct BVHSpatialBin
*/
struct BVHSpatialStorage {
- /* Accumulated bounds when sweeping from right to left. */
- vector<BoundBox> right_bounds;
+ /* Accumulated bounds when sweeping from right to left. */
+ vector<BoundBox> right_bounds;
- /* Bins used for histogram when selecting best split plane. */
- BVHSpatialBin bins[3][BVHParams::NUM_SPATIAL_BINS];
+ /* Bins used for histogram when selecting best split plane. */
+ BVHSpatialBin bins[3][BVHParams::NUM_SPATIAL_BINS];
- /* Temporary storage for the new references. Used by spatial split to store
- * new references in before they're getting inserted into actual array,
- */
- vector<BVHReference> new_references;
+ /* Temporary storage for the new references. Used by spatial split to store
+ * new references in before they're getting inserted into actual array,
+ */
+ vector<BVHReference> new_references;
};
CCL_NAMESPACE_END
-#endif /* __BVH_PARAMS_H__ */
+#endif /* __BVH_PARAMS_H__ */
diff --git a/intern/cycles/bvh/bvh_sort.cpp b/intern/cycles/bvh/bvh_sort.cpp
index f4f73ab2f2f..4498a759c08 100644
--- a/intern/cycles/bvh/bvh_sort.cpp
+++ b/intern/cycles/bvh/bvh_sort.cpp
@@ -27,79 +27,77 @@ CCL_NAMESPACE_BEGIN
static const int BVH_SORT_THRESHOLD = 4096;
struct BVHReferenceCompare {
-public:
- int dim;
- const BVHUnaligned *unaligned_heuristic;
- const Transform *aligned_space;
-
- BVHReferenceCompare(int dim,
- const BVHUnaligned *unaligned_heuristic,
- const Transform *aligned_space)
- : dim(dim),
- unaligned_heuristic(unaligned_heuristic),
- aligned_space(aligned_space)
- {
- }
-
- __forceinline BoundBox get_prim_bounds(const BVHReference& prim) const
- {
- return (aligned_space != NULL)
- ? unaligned_heuristic->compute_aligned_prim_boundbox(
- prim, *aligned_space)
- : prim.bounds();
- }
-
- /* Compare two references.
- *
- * Returns value is similar to return value of strcmp().
- */
- __forceinline int compare(const BVHReference& ra,
- const BVHReference& rb) const
- {
- BoundBox ra_bounds = get_prim_bounds(ra),
- rb_bounds = get_prim_bounds(rb);
- float ca = ra_bounds.min[dim] + ra_bounds.max[dim];
- float cb = rb_bounds.min[dim] + rb_bounds.max[dim];
-
- if(ca < cb) return -1;
- else if(ca > cb) return 1;
- else if(ra.prim_object() < rb.prim_object()) return -1;
- else if(ra.prim_object() > rb.prim_object()) return 1;
- else if(ra.prim_index() < rb.prim_index()) return -1;
- else if(ra.prim_index() > rb.prim_index()) return 1;
- else if(ra.prim_type() < rb.prim_type()) return -1;
- else if(ra.prim_type() > rb.prim_type()) return 1;
-
- return 0;
- }
-
- bool operator()(const BVHReference& ra, const BVHReference& rb)
- {
- return (compare(ra, rb) < 0);
- }
+ public:
+ int dim;
+ const BVHUnaligned *unaligned_heuristic;
+ const Transform *aligned_space;
+
+ BVHReferenceCompare(int dim,
+ const BVHUnaligned *unaligned_heuristic,
+ const Transform *aligned_space)
+ : dim(dim), unaligned_heuristic(unaligned_heuristic), aligned_space(aligned_space)
+ {
+ }
+
+ __forceinline BoundBox get_prim_bounds(const BVHReference &prim) const
+ {
+ return (aligned_space != NULL) ?
+ unaligned_heuristic->compute_aligned_prim_boundbox(prim, *aligned_space) :
+ prim.bounds();
+ }
+
+ /* Compare two references.
+ *
+ * Returns value is similar to return value of strcmp().
+ */
+ __forceinline int compare(const BVHReference &ra, const BVHReference &rb) const
+ {
+ BoundBox ra_bounds = get_prim_bounds(ra), rb_bounds = get_prim_bounds(rb);
+ float ca = ra_bounds.min[dim] + ra_bounds.max[dim];
+ float cb = rb_bounds.min[dim] + rb_bounds.max[dim];
+
+ if (ca < cb)
+ return -1;
+ else if (ca > cb)
+ return 1;
+ else if (ra.prim_object() < rb.prim_object())
+ return -1;
+ else if (ra.prim_object() > rb.prim_object())
+ return 1;
+ else if (ra.prim_index() < rb.prim_index())
+ return -1;
+ else if (ra.prim_index() > rb.prim_index())
+ return 1;
+ else if (ra.prim_type() < rb.prim_type())
+ return -1;
+ else if (ra.prim_type() > rb.prim_type())
+ return 1;
+
+ return 0;
+ }
+
+ bool operator()(const BVHReference &ra, const BVHReference &rb)
+ {
+ return (compare(ra, rb) < 0);
+ }
};
static void bvh_reference_sort_threaded(TaskPool *task_pool,
BVHReference *data,
const int job_start,
const int job_end,
- const BVHReferenceCompare& compare);
+ const BVHReferenceCompare &compare);
class BVHSortTask : public Task {
-public:
- BVHSortTask(TaskPool *task_pool,
- BVHReference *data,
- const int job_start,
- const int job_end,
- const BVHReferenceCompare& compare)
- {
- run = function_bind(bvh_reference_sort_threaded,
- task_pool,
- data,
- job_start,
- job_end,
- compare);
- }
+ public:
+ BVHSortTask(TaskPool *task_pool,
+ BVHReference *data,
+ const int job_start,
+ const int job_end,
+ const BVHReferenceCompare &compare)
+ {
+ run = function_bind(bvh_reference_sort_threaded, task_pool, data, job_start, job_end, compare);
+ }
};
/* Multi-threaded reference sort. */
@@ -107,74 +105,71 @@ static void bvh_reference_sort_threaded(TaskPool *task_pool,
BVHReference *data,
const int job_start,
const int job_end,
- const BVHReferenceCompare& compare)
+ const BVHReferenceCompare &compare)
{
- int start = job_start, end = job_end;
- bool have_work = (start < end);
- while(have_work) {
- const int count = job_end - job_start;
- if(count < BVH_SORT_THRESHOLD) {
- /* Number of reference low enough, faster to finish the job
- * in one thread rather than to spawn more threads.
- */
- sort(data+job_start, data+job_end+1, compare);
- break;
- }
- /* Single QSort step.
- * Use median-of-three method for the pivot point.
- */
- int left = start, right = end;
- int center = (left + right) >> 1;
- if(compare.compare(data[left], data[center]) > 0) {
- swap(data[left], data[center]);
- }
- if(compare.compare(data[left], data[right]) > 0) {
- swap(data[left], data[right]);
- }
- if(compare.compare(data[center], data[right]) > 0) {
- swap(data[center], data[right]);
- }
- swap(data[center], data[right - 1]);
- BVHReference median = data[right - 1];
- do {
- while(compare.compare(data[left], median) < 0) {
- ++left;
- }
- while(compare.compare(data[right], median) > 0) {
- --right;
- }
- if(left <= right) {
- swap(data[left], data[right]);
- ++left;
- --right;
- }
- } while(left <= right);
- /* We only create one new task here to reduce downside effects of
- * latency in TaskScheduler.
- * So generally current thread keeps working on the left part of the
- * array, and we create new task for the right side.
- * However, if there's nothing to be done in the left side of the array
- * we don't create any tasks and make it so current thread works on the
- * right side.
- */
- have_work = false;
- if(left < end) {
- if(start < right) {
- task_pool->push(new BVHSortTask(task_pool,
- data,
- left, end,
- compare), true);
- }
- else {
- start = left;
- have_work = true;
- }
- }
- if(start < right) {
- end = right;
- have_work = true;
- }
- }
+ int start = job_start, end = job_end;
+ bool have_work = (start < end);
+ while (have_work) {
+ const int count = job_end - job_start;
+ if (count < BVH_SORT_THRESHOLD) {
+ /* Number of reference low enough, faster to finish the job
+ * in one thread rather than to spawn more threads.
+ */
+ sort(data + job_start, data + job_end + 1, compare);
+ break;
+ }
+ /* Single QSort step.
+ * Use median-of-three method for the pivot point.
+ */
+ int left = start, right = end;
+ int center = (left + right) >> 1;
+ if (compare.compare(data[left], data[center]) > 0) {
+ swap(data[left], data[center]);
+ }
+ if (compare.compare(data[left], data[right]) > 0) {
+ swap(data[left], data[right]);
+ }
+ if (compare.compare(data[center], data[right]) > 0) {
+ swap(data[center], data[right]);
+ }
+ swap(data[center], data[right - 1]);
+ BVHReference median = data[right - 1];
+ do {
+ while (compare.compare(data[left], median) < 0) {
+ ++left;
+ }
+ while (compare.compare(data[right], median) > 0) {
+ --right;
+ }
+ if (left <= right) {
+ swap(data[left], data[right]);
+ ++left;
+ --right;
+ }
+ } while (left <= right);
+ /* We only create one new task here to reduce downside effects of
+ * latency in TaskScheduler.
+ * So generally current thread keeps working on the left part of the
+ * array, and we create new task for the right side.
+ * However, if there's nothing to be done in the left side of the array
+ * we don't create any tasks and make it so current thread works on the
+ * right side.
+ */
+ have_work = false;
+ if (left < end) {
+ if (start < right) {
+ task_pool->push(new BVHSortTask(task_pool, data, left, end, compare), true);
+ }
+ else {
+ start = left;
+ have_work = true;
+ }
+ }
+ if (start < right) {
+ end = right;
+ have_work = true;
+ }
+ }
}
void bvh_reference_sort(int start,
@@ -184,20 +179,20 @@ void bvh_reference_sort(int start,
const BVHUnaligned *unaligned_heuristic,
const Transform *aligned_space)
{
- const int count = end - start;
- BVHReferenceCompare compare(dim, unaligned_heuristic, aligned_space);
- if(count < BVH_SORT_THRESHOLD) {
- /* It is important to not use any mutex if array is small enough,
- * otherwise we end up in situation when we're going to sleep far
- * too often.
- */
- sort(data+start, data+end, compare);
- }
- else {
- TaskPool task_pool;
- bvh_reference_sort_threaded(&task_pool, data, start, end - 1, compare);
- task_pool.wait_work();
- }
+ const int count = end - start;
+ BVHReferenceCompare compare(dim, unaligned_heuristic, aligned_space);
+ if (count < BVH_SORT_THRESHOLD) {
+ /* It is important to not use any mutex if array is small enough,
+ * otherwise we end up in situation when we're going to sleep far
+ * too often.
+ */
+ sort(data + start, data + end, compare);
+ }
+ else {
+ TaskPool task_pool;
+ bvh_reference_sort_threaded(&task_pool, data, start, end - 1, compare);
+ task_pool.wait_work();
+ }
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/bvh/bvh_sort.h b/intern/cycles/bvh/bvh_sort.h
index 6910cc1e9b4..936401d8607 100644
--- a/intern/cycles/bvh/bvh_sort.h
+++ b/intern/cycles/bvh/bvh_sort.h
@@ -35,4 +35,4 @@ void bvh_reference_sort(int start,
CCL_NAMESPACE_END
-#endif /* __BVH_SORT_H__ */
+#endif /* __BVH_SORT_H__ */
diff --git a/intern/cycles/bvh/bvh_split.cpp b/intern/cycles/bvh/bvh_split.cpp
index c55ba40b565..bd261c10d55 100644
--- a/intern/cycles/bvh/bvh_split.cpp
+++ b/intern/cycles/bvh/bvh_split.cpp
@@ -31,322 +31,314 @@ CCL_NAMESPACE_BEGIN
BVHObjectSplit::BVHObjectSplit(BVHBuild *builder,
BVHSpatialStorage *storage,
- const BVHRange& range,
+ const BVHRange &range,
vector<BVHReference> *references,
float nodeSAH,
const BVHUnaligned *unaligned_heuristic,
const Transform *aligned_space)
-: sah(FLT_MAX),
- dim(0),
- num_left(0),
- left_bounds(BoundBox::empty),
- right_bounds(BoundBox::empty),
- storage_(storage),
- references_(references),
- unaligned_heuristic_(unaligned_heuristic),
- aligned_space_(aligned_space)
+ : sah(FLT_MAX),
+ dim(0),
+ num_left(0),
+ left_bounds(BoundBox::empty),
+ right_bounds(BoundBox::empty),
+ storage_(storage),
+ references_(references),
+ unaligned_heuristic_(unaligned_heuristic),
+ aligned_space_(aligned_space)
{
- const BVHReference *ref_ptr = &references_->at(range.start());
- float min_sah = FLT_MAX;
-
- storage_->right_bounds.resize(range.size());
-
- for(int dim = 0; dim < 3; dim++) {
- /* Sort references. */
- bvh_reference_sort(range.start(),
- range.end(),
- &references_->at(0),
- dim,
- unaligned_heuristic_,
- aligned_space_);
-
- /* sweep right to left and determine bounds. */
- BoundBox right_bounds = BoundBox::empty;
- for(int i = range.size() - 1; i > 0; i--) {
- BoundBox prim_bounds = get_prim_bounds(ref_ptr[i]);
- right_bounds.grow(prim_bounds);
- storage_->right_bounds[i - 1] = right_bounds;
- }
-
- /* sweep left to right and select lowest SAH. */
- BoundBox left_bounds = BoundBox::empty;
-
- for(int i = 1; i < range.size(); i++) {
- BoundBox prim_bounds = get_prim_bounds(ref_ptr[i - 1]);
- left_bounds.grow(prim_bounds);
- right_bounds = storage_->right_bounds[i - 1];
-
- float sah = nodeSAH +
- left_bounds.safe_area() * builder->params.primitive_cost(i) +
- right_bounds.safe_area() * builder->params.primitive_cost(range.size() - i);
-
- if(sah < min_sah) {
- min_sah = sah;
-
- this->sah = sah;
- this->dim = dim;
- this->num_left = i;
- this->left_bounds = left_bounds;
- this->right_bounds = right_bounds;
- }
- }
- }
+ const BVHReference *ref_ptr = &references_->at(range.start());
+ float min_sah = FLT_MAX;
+
+ storage_->right_bounds.resize(range.size());
+
+ for (int dim = 0; dim < 3; dim++) {
+ /* Sort references. */
+ bvh_reference_sort(range.start(),
+ range.end(),
+ &references_->at(0),
+ dim,
+ unaligned_heuristic_,
+ aligned_space_);
+
+ /* sweep right to left and determine bounds. */
+ BoundBox right_bounds = BoundBox::empty;
+ for (int i = range.size() - 1; i > 0; i--) {
+ BoundBox prim_bounds = get_prim_bounds(ref_ptr[i]);
+ right_bounds.grow(prim_bounds);
+ storage_->right_bounds[i - 1] = right_bounds;
+ }
+
+ /* sweep left to right and select lowest SAH. */
+ BoundBox left_bounds = BoundBox::empty;
+
+ for (int i = 1; i < range.size(); i++) {
+ BoundBox prim_bounds = get_prim_bounds(ref_ptr[i - 1]);
+ left_bounds.grow(prim_bounds);
+ right_bounds = storage_->right_bounds[i - 1];
+
+ float sah = nodeSAH + left_bounds.safe_area() * builder->params.primitive_cost(i) +
+ right_bounds.safe_area() * builder->params.primitive_cost(range.size() - i);
+
+ if (sah < min_sah) {
+ min_sah = sah;
+
+ this->sah = sah;
+ this->dim = dim;
+ this->num_left = i;
+ this->left_bounds = left_bounds;
+ this->right_bounds = right_bounds;
+ }
+ }
+ }
}
-void BVHObjectSplit::split(BVHRange& left,
- BVHRange& right,
- const BVHRange& range)
+void BVHObjectSplit::split(BVHRange &left, BVHRange &right, const BVHRange &range)
{
- assert(references_->size() > 0);
- /* sort references according to split */
- bvh_reference_sort(range.start(),
- range.end(),
- &references_->at(0),
- this->dim,
- unaligned_heuristic_,
- aligned_space_);
-
- BoundBox effective_left_bounds, effective_right_bounds;
- const int num_right = range.size() - this->num_left;
- if(aligned_space_ == NULL) {
- effective_left_bounds = left_bounds;
- effective_right_bounds = right_bounds;
- }
- else {
- effective_left_bounds = BoundBox::empty;
- effective_right_bounds = BoundBox::empty;
- for(int i = 0; i < this->num_left; ++i) {
- BoundBox prim_boundbox = references_->at(range.start() + i).bounds();
- effective_left_bounds.grow(prim_boundbox);
- }
- for(int i = 0; i < num_right; ++i) {
- BoundBox prim_boundbox = references_->at(range.start() + this->num_left + i).bounds();
- effective_right_bounds.grow(prim_boundbox);
- }
- }
-
- /* split node ranges */
- left = BVHRange(effective_left_bounds, range.start(), this->num_left);
- right = BVHRange(effective_right_bounds, left.end(), num_right);
+ assert(references_->size() > 0);
+ /* sort references according to split */
+ bvh_reference_sort(range.start(),
+ range.end(),
+ &references_->at(0),
+ this->dim,
+ unaligned_heuristic_,
+ aligned_space_);
+
+ BoundBox effective_left_bounds, effective_right_bounds;
+ const int num_right = range.size() - this->num_left;
+ if (aligned_space_ == NULL) {
+ effective_left_bounds = left_bounds;
+ effective_right_bounds = right_bounds;
+ }
+ else {
+ effective_left_bounds = BoundBox::empty;
+ effective_right_bounds = BoundBox::empty;
+ for (int i = 0; i < this->num_left; ++i) {
+ BoundBox prim_boundbox = references_->at(range.start() + i).bounds();
+ effective_left_bounds.grow(prim_boundbox);
+ }
+ for (int i = 0; i < num_right; ++i) {
+ BoundBox prim_boundbox = references_->at(range.start() + this->num_left + i).bounds();
+ effective_right_bounds.grow(prim_boundbox);
+ }
+ }
+
+ /* split node ranges */
+ left = BVHRange(effective_left_bounds, range.start(), this->num_left);
+ right = BVHRange(effective_right_bounds, left.end(), num_right);
}
/* Spatial Split */
-BVHSpatialSplit::BVHSpatialSplit(const BVHBuild& builder,
+BVHSpatialSplit::BVHSpatialSplit(const BVHBuild &builder,
BVHSpatialStorage *storage,
- const BVHRange& range,
+ const BVHRange &range,
vector<BVHReference> *references,
float nodeSAH,
const BVHUnaligned *unaligned_heuristic,
const Transform *aligned_space)
-: sah(FLT_MAX),
- dim(0),
- pos(0.0f),
- storage_(storage),
- references_(references),
- unaligned_heuristic_(unaligned_heuristic),
- aligned_space_(aligned_space)
+ : sah(FLT_MAX),
+ dim(0),
+ pos(0.0f),
+ storage_(storage),
+ references_(references),
+ unaligned_heuristic_(unaligned_heuristic),
+ aligned_space_(aligned_space)
{
- /* initialize bins. */
- BoundBox range_bounds;
- if(aligned_space == NULL) {
- range_bounds = range.bounds();
- }
- else {
- range_bounds = unaligned_heuristic->compute_aligned_boundbox(
- range,
- &references->at(0),
- *aligned_space);
- }
-
- float3 origin = range_bounds.min;
- float3 binSize = (range_bounds.max - origin) * (1.0f / (float)BVHParams::NUM_SPATIAL_BINS);
- float3 invBinSize = 1.0f / binSize;
-
- for(int dim = 0; dim < 3; dim++) {
- for(int i = 0; i < BVHParams::NUM_SPATIAL_BINS; i++) {
- BVHSpatialBin& bin = storage_->bins[dim][i];
-
- bin.bounds = BoundBox::empty;
- bin.enter = 0;
- bin.exit = 0;
- }
- }
-
- /* chop references into bins. */
- for(unsigned int refIdx = range.start(); refIdx < range.end(); refIdx++) {
- const BVHReference& ref = references_->at(refIdx);
- BoundBox prim_bounds = get_prim_bounds(ref);
- float3 firstBinf = (prim_bounds.min - origin) * invBinSize;
- float3 lastBinf = (prim_bounds.max - origin) * invBinSize;
- int3 firstBin = make_int3((int)firstBinf.x, (int)firstBinf.y, (int)firstBinf.z);
- int3 lastBin = make_int3((int)lastBinf.x, (int)lastBinf.y, (int)lastBinf.z);
-
- firstBin = clamp(firstBin, 0, BVHParams::NUM_SPATIAL_BINS - 1);
- lastBin = clamp(lastBin, firstBin, BVHParams::NUM_SPATIAL_BINS - 1);
-
- for(int dim = 0; dim < 3; dim++) {
- BVHReference currRef(get_prim_bounds(ref),
- ref.prim_index(),
- ref.prim_object(),
- ref.prim_type());
-
- for(int i = firstBin[dim]; i < lastBin[dim]; i++) {
- BVHReference leftRef, rightRef;
-
- split_reference(builder, leftRef, rightRef, currRef, dim, origin[dim] + binSize[dim] * (float)(i + 1));
- storage_->bins[dim][i].bounds.grow(leftRef.bounds());
- currRef = rightRef;
- }
-
- storage_->bins[dim][lastBin[dim]].bounds.grow(currRef.bounds());
- storage_->bins[dim][firstBin[dim]].enter++;
- storage_->bins[dim][lastBin[dim]].exit++;
- }
- }
-
- /* select best split plane. */
- storage_->right_bounds.resize(BVHParams::NUM_SPATIAL_BINS);
- for(int dim = 0; dim < 3; dim++) {
- /* sweep right to left and determine bounds. */
- BoundBox right_bounds = BoundBox::empty;
- for(int i = BVHParams::NUM_SPATIAL_BINS - 1; i > 0; i--) {
- right_bounds.grow(storage_->bins[dim][i].bounds);
- storage_->right_bounds[i - 1] = right_bounds;
- }
-
- /* sweep left to right and select lowest SAH. */
- BoundBox left_bounds = BoundBox::empty;
- int leftNum = 0;
- int rightNum = range.size();
-
- for(int i = 1; i < BVHParams::NUM_SPATIAL_BINS; i++) {
- left_bounds.grow(storage_->bins[dim][i - 1].bounds);
- leftNum += storage_->bins[dim][i - 1].enter;
- rightNum -= storage_->bins[dim][i - 1].exit;
-
- float sah = nodeSAH +
- left_bounds.safe_area() * builder.params.primitive_cost(leftNum) +
- storage_->right_bounds[i - 1].safe_area() * builder.params.primitive_cost(rightNum);
-
- if(sah < this->sah) {
- this->sah = sah;
- this->dim = dim;
- this->pos = origin[dim] + binSize[dim] * (float)i;
- }
- }
- }
+ /* initialize bins. */
+ BoundBox range_bounds;
+ if (aligned_space == NULL) {
+ range_bounds = range.bounds();
+ }
+ else {
+ range_bounds = unaligned_heuristic->compute_aligned_boundbox(
+ range, &references->at(0), *aligned_space);
+ }
+
+ float3 origin = range_bounds.min;
+ float3 binSize = (range_bounds.max - origin) * (1.0f / (float)BVHParams::NUM_SPATIAL_BINS);
+ float3 invBinSize = 1.0f / binSize;
+
+ for (int dim = 0; dim < 3; dim++) {
+ for (int i = 0; i < BVHParams::NUM_SPATIAL_BINS; i++) {
+ BVHSpatialBin &bin = storage_->bins[dim][i];
+
+ bin.bounds = BoundBox::empty;
+ bin.enter = 0;
+ bin.exit = 0;
+ }
+ }
+
+ /* chop references into bins. */
+ for (unsigned int refIdx = range.start(); refIdx < range.end(); refIdx++) {
+ const BVHReference &ref = references_->at(refIdx);
+ BoundBox prim_bounds = get_prim_bounds(ref);
+ float3 firstBinf = (prim_bounds.min - origin) * invBinSize;
+ float3 lastBinf = (prim_bounds.max - origin) * invBinSize;
+ int3 firstBin = make_int3((int)firstBinf.x, (int)firstBinf.y, (int)firstBinf.z);
+ int3 lastBin = make_int3((int)lastBinf.x, (int)lastBinf.y, (int)lastBinf.z);
+
+ firstBin = clamp(firstBin, 0, BVHParams::NUM_SPATIAL_BINS - 1);
+ lastBin = clamp(lastBin, firstBin, BVHParams::NUM_SPATIAL_BINS - 1);
+
+ for (int dim = 0; dim < 3; dim++) {
+ BVHReference currRef(
+ get_prim_bounds(ref), ref.prim_index(), ref.prim_object(), ref.prim_type());
+
+ for (int i = firstBin[dim]; i < lastBin[dim]; i++) {
+ BVHReference leftRef, rightRef;
+
+ split_reference(
+ builder, leftRef, rightRef, currRef, dim, origin[dim] + binSize[dim] * (float)(i + 1));
+ storage_->bins[dim][i].bounds.grow(leftRef.bounds());
+ currRef = rightRef;
+ }
+
+ storage_->bins[dim][lastBin[dim]].bounds.grow(currRef.bounds());
+ storage_->bins[dim][firstBin[dim]].enter++;
+ storage_->bins[dim][lastBin[dim]].exit++;
+ }
+ }
+
+ /* select best split plane. */
+ storage_->right_bounds.resize(BVHParams::NUM_SPATIAL_BINS);
+ for (int dim = 0; dim < 3; dim++) {
+ /* sweep right to left and determine bounds. */
+ BoundBox right_bounds = BoundBox::empty;
+ for (int i = BVHParams::NUM_SPATIAL_BINS - 1; i > 0; i--) {
+ right_bounds.grow(storage_->bins[dim][i].bounds);
+ storage_->right_bounds[i - 1] = right_bounds;
+ }
+
+ /* sweep left to right and select lowest SAH. */
+ BoundBox left_bounds = BoundBox::empty;
+ int leftNum = 0;
+ int rightNum = range.size();
+
+ for (int i = 1; i < BVHParams::NUM_SPATIAL_BINS; i++) {
+ left_bounds.grow(storage_->bins[dim][i - 1].bounds);
+ leftNum += storage_->bins[dim][i - 1].enter;
+ rightNum -= storage_->bins[dim][i - 1].exit;
+
+ float sah = nodeSAH + left_bounds.safe_area() * builder.params.primitive_cost(leftNum) +
+ storage_->right_bounds[i - 1].safe_area() *
+ builder.params.primitive_cost(rightNum);
+
+ if (sah < this->sah) {
+ this->sah = sah;
+ this->dim = dim;
+ this->pos = origin[dim] + binSize[dim] * (float)i;
+ }
+ }
+ }
}
void BVHSpatialSplit::split(BVHBuild *builder,
- BVHRange& left,
- BVHRange& right,
- const BVHRange& range)
+ BVHRange &left,
+ BVHRange &right,
+ const BVHRange &range)
{
- /* Categorize references and compute bounds.
- *
- * Left-hand side: [left_start, left_end[
- * Uncategorized/split: [left_end, right_start[
- * Right-hand side: [right_start, refs.size()[ */
-
- vector<BVHReference>& refs = *references_;
- int left_start = range.start();
- int left_end = left_start;
- int right_start = range.end();
- int right_end = range.end();
- BoundBox left_bounds = BoundBox::empty;
- BoundBox right_bounds = BoundBox::empty;
-
- for(int i = left_end; i < right_start; i++) {
- BoundBox prim_bounds = get_prim_bounds(refs[i]);
- if(prim_bounds.max[this->dim] <= this->pos) {
- /* entirely on the left-hand side */
- left_bounds.grow(prim_bounds);
- swap(refs[i], refs[left_end++]);
- }
- else if(prim_bounds.min[this->dim] >= this->pos) {
- /* entirely on the right-hand side */
- right_bounds.grow(prim_bounds);
- swap(refs[i--], refs[--right_start]);
- }
- }
-
- /* Duplicate or unsplit references intersecting both sides.
- *
- * Duplication happens into a temporary pre-allocated vector in order to
- * reduce number of memmove() calls happening in vector.insert().
- */
- vector<BVHReference>& new_refs = storage_->new_references;
- new_refs.clear();
- new_refs.reserve(right_start - left_end);
- while(left_end < right_start) {
- /* split reference. */
- BVHReference curr_ref(get_prim_bounds(refs[left_end]),
- refs[left_end].prim_index(),
- refs[left_end].prim_object(),
- refs[left_end].prim_type());
- BVHReference lref, rref;
- split_reference(*builder, lref, rref, curr_ref, this->dim, this->pos);
-
- /* compute SAH for duplicate/unsplit candidates. */
- BoundBox lub = left_bounds; // Unsplit to left: new left-hand bounds.
- BoundBox rub = right_bounds; // Unsplit to right: new right-hand bounds.
- BoundBox ldb = left_bounds; // Duplicate: new left-hand bounds.
- BoundBox rdb = right_bounds; // Duplicate: new right-hand bounds.
-
- lub.grow(curr_ref.bounds());
- rub.grow(curr_ref.bounds());
- ldb.grow(lref.bounds());
- rdb.grow(rref.bounds());
-
- float lac = builder->params.primitive_cost(left_end - left_start);
- float rac = builder->params.primitive_cost(right_end - right_start);
- float lbc = builder->params.primitive_cost(left_end - left_start + 1);
- float rbc = builder->params.primitive_cost(right_end - right_start + 1);
-
- float unsplitLeftSAH = lub.safe_area() * lbc + right_bounds.safe_area() * rac;
- float unsplitRightSAH = left_bounds.safe_area() * lac + rub.safe_area() * rbc;
- float duplicateSAH = ldb.safe_area() * lbc + rdb.safe_area() * rbc;
- float minSAH = min(min(unsplitLeftSAH, unsplitRightSAH), duplicateSAH);
-
- if(minSAH == unsplitLeftSAH) {
- /* unsplit to left */
- left_bounds = lub;
- left_end++;
- }
- else if(minSAH == unsplitRightSAH) {
- /* unsplit to right */
- right_bounds = rub;
- swap(refs[left_end], refs[--right_start]);
- }
- else {
- /* duplicate */
- left_bounds = ldb;
- right_bounds = rdb;
- refs[left_end++] = lref;
- new_refs.push_back(rref);
- right_end++;
- }
- }
- /* Insert duplicated references into actual array in one go. */
- if(new_refs.size() != 0) {
- refs.insert(refs.begin() + (right_end - new_refs.size()),
- new_refs.begin(),
- new_refs.end());
- }
- if(aligned_space_ != NULL) {
- left_bounds = right_bounds = BoundBox::empty;
- for(int i = left_start; i < left_end - left_start; ++i) {
- BoundBox prim_boundbox = references_->at(i).bounds();
- left_bounds.grow(prim_boundbox);
- }
- for(int i = right_start; i < right_end - right_start; ++i) {
- BoundBox prim_boundbox = references_->at(i).bounds();
- right_bounds.grow(prim_boundbox);
- }
- }
- left = BVHRange(left_bounds, left_start, left_end - left_start);
- right = BVHRange(right_bounds, right_start, right_end - right_start);
+ /* Categorize references and compute bounds.
+ *
+ * Left-hand side: [left_start, left_end[
+ * Uncategorized/split: [left_end, right_start[
+ * Right-hand side: [right_start, refs.size()[ */
+
+ vector<BVHReference> &refs = *references_;
+ int left_start = range.start();
+ int left_end = left_start;
+ int right_start = range.end();
+ int right_end = range.end();
+ BoundBox left_bounds = BoundBox::empty;
+ BoundBox right_bounds = BoundBox::empty;
+
+ for (int i = left_end; i < right_start; i++) {
+ BoundBox prim_bounds = get_prim_bounds(refs[i]);
+ if (prim_bounds.max[this->dim] <= this->pos) {
+ /* entirely on the left-hand side */
+ left_bounds.grow(prim_bounds);
+ swap(refs[i], refs[left_end++]);
+ }
+ else if (prim_bounds.min[this->dim] >= this->pos) {
+ /* entirely on the right-hand side */
+ right_bounds.grow(prim_bounds);
+ swap(refs[i--], refs[--right_start]);
+ }
+ }
+
+ /* Duplicate or unsplit references intersecting both sides.
+ *
+ * Duplication happens into a temporary pre-allocated vector in order to
+ * reduce number of memmove() calls happening in vector.insert().
+ */
+ vector<BVHReference> &new_refs = storage_->new_references;
+ new_refs.clear();
+ new_refs.reserve(right_start - left_end);
+ while (left_end < right_start) {
+ /* split reference. */
+ BVHReference curr_ref(get_prim_bounds(refs[left_end]),
+ refs[left_end].prim_index(),
+ refs[left_end].prim_object(),
+ refs[left_end].prim_type());
+ BVHReference lref, rref;
+ split_reference(*builder, lref, rref, curr_ref, this->dim, this->pos);
+
+ /* compute SAH for duplicate/unsplit candidates. */
+ BoundBox lub = left_bounds; // Unsplit to left: new left-hand bounds.
+ BoundBox rub = right_bounds; // Unsplit to right: new right-hand bounds.
+ BoundBox ldb = left_bounds; // Duplicate: new left-hand bounds.
+ BoundBox rdb = right_bounds; // Duplicate: new right-hand bounds.
+
+ lub.grow(curr_ref.bounds());
+ rub.grow(curr_ref.bounds());
+ ldb.grow(lref.bounds());
+ rdb.grow(rref.bounds());
+
+ float lac = builder->params.primitive_cost(left_end - left_start);
+ float rac = builder->params.primitive_cost(right_end - right_start);
+ float lbc = builder->params.primitive_cost(left_end - left_start + 1);
+ float rbc = builder->params.primitive_cost(right_end - right_start + 1);
+
+ float unsplitLeftSAH = lub.safe_area() * lbc + right_bounds.safe_area() * rac;
+ float unsplitRightSAH = left_bounds.safe_area() * lac + rub.safe_area() * rbc;
+ float duplicateSAH = ldb.safe_area() * lbc + rdb.safe_area() * rbc;
+ float minSAH = min(min(unsplitLeftSAH, unsplitRightSAH), duplicateSAH);
+
+ if (minSAH == unsplitLeftSAH) {
+ /* unsplit to left */
+ left_bounds = lub;
+ left_end++;
+ }
+ else if (minSAH == unsplitRightSAH) {
+ /* unsplit to right */
+ right_bounds = rub;
+ swap(refs[left_end], refs[--right_start]);
+ }
+ else {
+ /* duplicate */
+ left_bounds = ldb;
+ right_bounds = rdb;
+ refs[left_end++] = lref;
+ new_refs.push_back(rref);
+ right_end++;
+ }
+ }
+ /* Insert duplicated references into actual array in one go. */
+ if (new_refs.size() != 0) {
+ refs.insert(refs.begin() + (right_end - new_refs.size()), new_refs.begin(), new_refs.end());
+ }
+ if (aligned_space_ != NULL) {
+ left_bounds = right_bounds = BoundBox::empty;
+ for (int i = left_start; i < left_end - left_start; ++i) {
+ BoundBox prim_boundbox = references_->at(i).bounds();
+ left_bounds.grow(prim_boundbox);
+ }
+ for (int i = right_start; i < right_end - right_start; ++i) {
+ BoundBox prim_boundbox = references_->at(i).bounds();
+ right_bounds.grow(prim_boundbox);
+ }
+ }
+ left = BVHRange(left_bounds, left_start, left_end - left_start);
+ right = BVHRange(right_bounds, right_start, right_end - right_start);
}
void BVHSpatialSplit::split_triangle_primitive(const Mesh *mesh,
@@ -354,36 +346,36 @@ void BVHSpatialSplit::split_triangle_primitive(const Mesh *mesh,
int prim_index,
int dim,
float pos,
- BoundBox& left_bounds,
- BoundBox& right_bounds)
+ BoundBox &left_bounds,
+ BoundBox &right_bounds)
{
- Mesh::Triangle t = mesh->get_triangle(prim_index);
- const float3 *verts = &mesh->verts[0];
- float3 v1 = tfm ? transform_point(tfm, verts[t.v[2]]) : verts[t.v[2]];
- v1 = get_unaligned_point(v1);
-
- for(int i = 0; i < 3; i++) {
- float3 v0 = v1;
- int vindex = t.v[i];
- v1 = tfm ? transform_point(tfm, verts[vindex]) : verts[vindex];
- v1 = get_unaligned_point(v1);
- float v0p = v0[dim];
- float v1p = v1[dim];
-
- /* insert vertex to the boxes it belongs to. */
- if(v0p <= pos)
- left_bounds.grow(v0);
-
- if(v0p >= pos)
- right_bounds.grow(v0);
-
- /* edge intersects the plane => insert intersection to both boxes. */
- if((v0p < pos && v1p > pos) || (v0p > pos && v1p < pos)) {
- float3 t = lerp(v0, v1, clamp((pos - v0p) / (v1p - v0p), 0.0f, 1.0f));
- left_bounds.grow(t);
- right_bounds.grow(t);
- }
- }
+ Mesh::Triangle t = mesh->get_triangle(prim_index);
+ const float3 *verts = &mesh->verts[0];
+ float3 v1 = tfm ? transform_point(tfm, verts[t.v[2]]) : verts[t.v[2]];
+ v1 = get_unaligned_point(v1);
+
+ for (int i = 0; i < 3; i++) {
+ float3 v0 = v1;
+ int vindex = t.v[i];
+ v1 = tfm ? transform_point(tfm, verts[vindex]) : verts[vindex];
+ v1 = get_unaligned_point(v1);
+ float v0p = v0[dim];
+ float v1p = v1[dim];
+
+ /* insert vertex to the boxes it belongs to. */
+ if (v0p <= pos)
+ left_bounds.grow(v0);
+
+ if (v0p >= pos)
+ right_bounds.grow(v0);
+
+ /* edge intersects the plane => insert intersection to both boxes. */
+ if ((v0p < pos && v1p > pos) || (v0p > pos && v1p < pos)) {
+ float3 t = lerp(v0, v1, clamp((pos - v0p) / (v1p - v0p), 0.0f, 1.0f));
+ left_bounds.grow(t);
+ right_bounds.grow(t);
+ }
+ }
}
void BVHSpatialSplit::split_curve_primitive(const Mesh *mesh,
@@ -392,163 +384,125 @@ void BVHSpatialSplit::split_curve_primitive(const Mesh *mesh,
int segment_index,
int dim,
float pos,
- BoundBox& left_bounds,
- BoundBox& right_bounds)
+ BoundBox &left_bounds,
+ BoundBox &right_bounds)
{
- /* curve split: NOTE - Currently ignores curve width and needs to be fixed.*/
- Mesh::Curve curve = mesh->get_curve(prim_index);
- const int k0 = curve.first_key + segment_index;
- const int k1 = k0 + 1;
- float3 v0 = mesh->curve_keys[k0];
- float3 v1 = mesh->curve_keys[k1];
-
- if(tfm != NULL) {
- v0 = transform_point(tfm, v0);
- v1 = transform_point(tfm, v1);
- }
- v0 = get_unaligned_point(v0);
- v1 = get_unaligned_point(v1);
-
- float v0p = v0[dim];
- float v1p = v1[dim];
-
- /* insert vertex to the boxes it belongs to. */
- if(v0p <= pos)
- left_bounds.grow(v0);
-
- if(v0p >= pos)
- right_bounds.grow(v0);
-
- if(v1p <= pos)
- left_bounds.grow(v1);
-
- if(v1p >= pos)
- right_bounds.grow(v1);
-
- /* edge intersects the plane => insert intersection to both boxes. */
- if((v0p < pos && v1p > pos) || (v0p > pos && v1p < pos)) {
- float3 t = lerp(v0, v1, clamp((pos - v0p) / (v1p - v0p), 0.0f, 1.0f));
- left_bounds.grow(t);
- right_bounds.grow(t);
- }
+ /* curve split: NOTE - Currently ignores curve width and needs to be fixed.*/
+ Mesh::Curve curve = mesh->get_curve(prim_index);
+ const int k0 = curve.first_key + segment_index;
+ const int k1 = k0 + 1;
+ float3 v0 = mesh->curve_keys[k0];
+ float3 v1 = mesh->curve_keys[k1];
+
+ if (tfm != NULL) {
+ v0 = transform_point(tfm, v0);
+ v1 = transform_point(tfm, v1);
+ }
+ v0 = get_unaligned_point(v0);
+ v1 = get_unaligned_point(v1);
+
+ float v0p = v0[dim];
+ float v1p = v1[dim];
+
+ /* insert vertex to the boxes it belongs to. */
+ if (v0p <= pos)
+ left_bounds.grow(v0);
+
+ if (v0p >= pos)
+ right_bounds.grow(v0);
+
+ if (v1p <= pos)
+ left_bounds.grow(v1);
+
+ if (v1p >= pos)
+ right_bounds.grow(v1);
+
+ /* edge intersects the plane => insert intersection to both boxes. */
+ if ((v0p < pos && v1p > pos) || (v0p > pos && v1p < pos)) {
+ float3 t = lerp(v0, v1, clamp((pos - v0p) / (v1p - v0p), 0.0f, 1.0f));
+ left_bounds.grow(t);
+ right_bounds.grow(t);
+ }
}
-void BVHSpatialSplit::split_triangle_reference(const BVHReference& ref,
+void BVHSpatialSplit::split_triangle_reference(const BVHReference &ref,
const Mesh *mesh,
int dim,
float pos,
- BoundBox& left_bounds,
- BoundBox& right_bounds)
+ BoundBox &left_bounds,
+ BoundBox &right_bounds)
{
- split_triangle_primitive(mesh,
- NULL,
- ref.prim_index(),
- dim,
- pos,
- left_bounds,
- right_bounds);
+ split_triangle_primitive(mesh, NULL, ref.prim_index(), dim, pos, left_bounds, right_bounds);
}
-void BVHSpatialSplit::split_curve_reference(const BVHReference& ref,
+void BVHSpatialSplit::split_curve_reference(const BVHReference &ref,
const Mesh *mesh,
int dim,
float pos,
- BoundBox& left_bounds,
- BoundBox& right_bounds)
+ BoundBox &left_bounds,
+ BoundBox &right_bounds)
{
- split_curve_primitive(mesh,
- NULL,
- ref.prim_index(),
- PRIMITIVE_UNPACK_SEGMENT(ref.prim_type()),
- dim,
- pos,
- left_bounds,
- right_bounds);
+ split_curve_primitive(mesh,
+ NULL,
+ ref.prim_index(),
+ PRIMITIVE_UNPACK_SEGMENT(ref.prim_type()),
+ dim,
+ pos,
+ left_bounds,
+ right_bounds);
}
-void BVHSpatialSplit::split_object_reference(const Object *object,
- int dim,
- float pos,
- BoundBox& left_bounds,
- BoundBox& right_bounds)
+void BVHSpatialSplit::split_object_reference(
+ const Object *object, int dim, float pos, BoundBox &left_bounds, BoundBox &right_bounds)
{
- Mesh *mesh = object->mesh;
- for(int tri_idx = 0; tri_idx < mesh->num_triangles(); ++tri_idx) {
- split_triangle_primitive(mesh,
- &object->tfm,
- tri_idx,
- dim,
- pos,
- left_bounds,
- right_bounds);
- }
- for(int curve_idx = 0; curve_idx < mesh->num_curves(); ++curve_idx) {
- Mesh::Curve curve = mesh->get_curve(curve_idx);
- for(int segment_idx = 0;
- segment_idx < curve.num_keys - 1;
- ++segment_idx)
- {
- split_curve_primitive(mesh,
- &object->tfm,
- curve_idx,
- segment_idx,
- dim,
- pos,
- left_bounds,
- right_bounds);
- }
- }
+ Mesh *mesh = object->mesh;
+ for (int tri_idx = 0; tri_idx < mesh->num_triangles(); ++tri_idx) {
+ split_triangle_primitive(mesh, &object->tfm, tri_idx, dim, pos, left_bounds, right_bounds);
+ }
+ for (int curve_idx = 0; curve_idx < mesh->num_curves(); ++curve_idx) {
+ Mesh::Curve curve = mesh->get_curve(curve_idx);
+ for (int segment_idx = 0; segment_idx < curve.num_keys - 1; ++segment_idx) {
+ split_curve_primitive(
+ mesh, &object->tfm, curve_idx, segment_idx, dim, pos, left_bounds, right_bounds);
+ }
+ }
}
-void BVHSpatialSplit::split_reference(const BVHBuild& builder,
- BVHReference& left,
- BVHReference& right,
- const BVHReference& ref,
+void BVHSpatialSplit::split_reference(const BVHBuild &builder,
+ BVHReference &left,
+ BVHReference &right,
+ const BVHReference &ref,
int dim,
float pos)
{
- /* initialize boundboxes */
- BoundBox left_bounds = BoundBox::empty;
- BoundBox right_bounds = BoundBox::empty;
-
- /* loop over vertices/edges. */
- const Object *ob = builder.objects[ref.prim_object()];
- const Mesh *mesh = ob->mesh;
-
- if(ref.prim_type() & PRIMITIVE_ALL_TRIANGLE) {
- split_triangle_reference(ref,
- mesh,
- dim,
- pos,
- left_bounds,
- right_bounds);
- }
- else if(ref.prim_type() & PRIMITIVE_ALL_CURVE) {
- split_curve_reference(ref,
- mesh,
- dim,
- pos,
- left_bounds,
- right_bounds);
- }
- else {
- split_object_reference(ob,
- dim,
- pos,
- left_bounds,
- right_bounds);
- }
-
- /* intersect with original bounds. */
- left_bounds.max[dim] = pos;
- right_bounds.min[dim] = pos;
-
- left_bounds.intersect(ref.bounds());
- right_bounds.intersect(ref.bounds());
-
- /* set references */
- left = BVHReference(left_bounds, ref.prim_index(), ref.prim_object(), ref.prim_type());
- right = BVHReference(right_bounds, ref.prim_index(), ref.prim_object(), ref.prim_type());
+ /* initialize boundboxes */
+ BoundBox left_bounds = BoundBox::empty;
+ BoundBox right_bounds = BoundBox::empty;
+
+ /* loop over vertices/edges. */
+ const Object *ob = builder.objects[ref.prim_object()];
+ const Mesh *mesh = ob->mesh;
+
+ if (ref.prim_type() & PRIMITIVE_ALL_TRIANGLE) {
+ split_triangle_reference(ref, mesh, dim, pos, left_bounds, right_bounds);
+ }
+ else if (ref.prim_type() & PRIMITIVE_ALL_CURVE) {
+ split_curve_reference(ref, mesh, dim, pos, left_bounds, right_bounds);
+ }
+ else {
+ split_object_reference(ob, dim, pos, left_bounds, right_bounds);
+ }
+
+ /* intersect with original bounds. */
+ left_bounds.max[dim] = pos;
+ right_bounds.min[dim] = pos;
+
+ left_bounds.intersect(ref.bounds());
+ right_bounds.intersect(ref.bounds());
+
+ /* set references */
+ left = BVHReference(left_bounds, ref.prim_index(), ref.prim_object(), ref.prim_type());
+ right = BVHReference(right_bounds, ref.prim_index(), ref.prim_object(), ref.prim_type());
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/bvh/bvh_split.h b/intern/cycles/bvh/bvh_split.h
index cb47deab211..eddd1c27f49 100644
--- a/intern/cycles/bvh/bvh_split.h
+++ b/intern/cycles/bvh/bvh_split.h
@@ -28,235 +28,211 @@ struct Transform;
/* Object Split */
-class BVHObjectSplit
-{
-public:
- float sah;
- int dim;
- int num_left;
- BoundBox left_bounds;
- BoundBox right_bounds;
-
- BVHObjectSplit() {}
- BVHObjectSplit(BVHBuild *builder,
- BVHSpatialStorage *storage,
- const BVHRange& range,
- vector<BVHReference> *references,
- float nodeSAH,
- const BVHUnaligned *unaligned_heuristic = NULL,
- const Transform *aligned_space = NULL);
-
- void split(BVHRange& left,
- BVHRange& right,
- const BVHRange& range);
-
-protected:
- BVHSpatialStorage *storage_;
- vector<BVHReference> *references_;
- const BVHUnaligned *unaligned_heuristic_;
- const Transform *aligned_space_;
-
- __forceinline BoundBox get_prim_bounds(const BVHReference& prim) const
- {
- if(aligned_space_ == NULL) {
- return prim.bounds();
- }
- else {
- return unaligned_heuristic_->compute_aligned_prim_boundbox(
- prim, *aligned_space_);
- }
- }
+class BVHObjectSplit {
+ public:
+ float sah;
+ int dim;
+ int num_left;
+ BoundBox left_bounds;
+ BoundBox right_bounds;
+
+ BVHObjectSplit()
+ {
+ }
+ BVHObjectSplit(BVHBuild *builder,
+ BVHSpatialStorage *storage,
+ const BVHRange &range,
+ vector<BVHReference> *references,
+ float nodeSAH,
+ const BVHUnaligned *unaligned_heuristic = NULL,
+ const Transform *aligned_space = NULL);
+
+ void split(BVHRange &left, BVHRange &right, const BVHRange &range);
+
+ protected:
+ BVHSpatialStorage *storage_;
+ vector<BVHReference> *references_;
+ const BVHUnaligned *unaligned_heuristic_;
+ const Transform *aligned_space_;
+
+ __forceinline BoundBox get_prim_bounds(const BVHReference &prim) const
+ {
+ if (aligned_space_ == NULL) {
+ return prim.bounds();
+ }
+ else {
+ return unaligned_heuristic_->compute_aligned_prim_boundbox(prim, *aligned_space_);
+ }
+ }
};
/* Spatial Split */
-class BVHSpatialSplit
-{
-public:
- float sah;
- int dim;
- float pos;
-
- BVHSpatialSplit() : sah(FLT_MAX),
- dim(0),
- pos(0.0f),
- storage_(NULL),
- references_(NULL) {}
- BVHSpatialSplit(const BVHBuild& builder,
- BVHSpatialStorage *storage,
- const BVHRange& range,
- vector<BVHReference> *references,
- float nodeSAH,
- const BVHUnaligned *unaligned_heuristic = NULL,
- const Transform *aligned_space = NULL);
-
- void split(BVHBuild *builder,
- BVHRange& left,
- BVHRange& right,
- const BVHRange& range);
-
- void split_reference(const BVHBuild& builder,
- BVHReference& left,
- BVHReference& right,
- const BVHReference& ref,
- int dim,
- float pos);
-
-protected:
- BVHSpatialStorage *storage_;
- vector<BVHReference> *references_;
- const BVHUnaligned *unaligned_heuristic_;
- const Transform *aligned_space_;
-
- /* Lower-level functions which calculates boundaries of left and right nodes
- * needed for spatial split.
- *
- * Operates directly with primitive specified by it's index, reused by higher
- * level splitting functions.
- */
- void split_triangle_primitive(const Mesh *mesh,
- const Transform *tfm,
- int prim_index,
- int dim,
- float pos,
- BoundBox& left_bounds,
- BoundBox& right_bounds);
- void split_curve_primitive(const Mesh *mesh,
- const Transform *tfm,
- int prim_index,
- int segment_index,
- int dim,
- float pos,
- BoundBox& left_bounds,
- BoundBox& right_bounds);
-
- /* Lower-level functions which calculates boundaries of left and right nodes
- * needed for spatial split.
- *
- * Operates with BVHReference, internally uses lower level API functions.
- */
- void split_triangle_reference(const BVHReference& ref,
- const Mesh *mesh,
- int dim,
- float pos,
- BoundBox& left_bounds,
- BoundBox& right_bounds);
- void split_curve_reference(const BVHReference& ref,
- const Mesh *mesh,
- int dim,
- float pos,
- BoundBox& left_bounds,
- BoundBox& right_bounds);
- void split_object_reference(const Object *object,
- int dim,
- float pos,
- BoundBox& left_bounds,
- BoundBox& right_bounds);
-
- __forceinline BoundBox get_prim_bounds(const BVHReference& prim) const
- {
- if(aligned_space_ == NULL) {
- return prim.bounds();
- }
- else {
- return unaligned_heuristic_->compute_aligned_prim_boundbox(
- prim, *aligned_space_);
- }
- }
-
- __forceinline float3 get_unaligned_point(const float3& point) const
- {
- if(aligned_space_ == NULL) {
- return point;
- }
- else {
- return transform_point(aligned_space_, point);
- }
- }
+class BVHSpatialSplit {
+ public:
+ float sah;
+ int dim;
+ float pos;
+
+ BVHSpatialSplit() : sah(FLT_MAX), dim(0), pos(0.0f), storage_(NULL), references_(NULL)
+ {
+ }
+ BVHSpatialSplit(const BVHBuild &builder,
+ BVHSpatialStorage *storage,
+ const BVHRange &range,
+ vector<BVHReference> *references,
+ float nodeSAH,
+ const BVHUnaligned *unaligned_heuristic = NULL,
+ const Transform *aligned_space = NULL);
+
+ void split(BVHBuild *builder, BVHRange &left, BVHRange &right, const BVHRange &range);
+
+ void split_reference(const BVHBuild &builder,
+ BVHReference &left,
+ BVHReference &right,
+ const BVHReference &ref,
+ int dim,
+ float pos);
+
+ protected:
+ BVHSpatialStorage *storage_;
+ vector<BVHReference> *references_;
+ const BVHUnaligned *unaligned_heuristic_;
+ const Transform *aligned_space_;
+
+ /* Lower-level functions which calculates boundaries of left and right nodes
+ * needed for spatial split.
+ *
+ * Operates directly with primitive specified by it's index, reused by higher
+ * level splitting functions.
+ */
+ void split_triangle_primitive(const Mesh *mesh,
+ const Transform *tfm,
+ int prim_index,
+ int dim,
+ float pos,
+ BoundBox &left_bounds,
+ BoundBox &right_bounds);
+ void split_curve_primitive(const Mesh *mesh,
+ const Transform *tfm,
+ int prim_index,
+ int segment_index,
+ int dim,
+ float pos,
+ BoundBox &left_bounds,
+ BoundBox &right_bounds);
+
+ /* Lower-level functions which calculates boundaries of left and right nodes
+ * needed for spatial split.
+ *
+ * Operates with BVHReference, internally uses lower level API functions.
+ */
+ void split_triangle_reference(const BVHReference &ref,
+ const Mesh *mesh,
+ int dim,
+ float pos,
+ BoundBox &left_bounds,
+ BoundBox &right_bounds);
+ void split_curve_reference(const BVHReference &ref,
+ const Mesh *mesh,
+ int dim,
+ float pos,
+ BoundBox &left_bounds,
+ BoundBox &right_bounds);
+ void split_object_reference(
+ const Object *object, int dim, float pos, BoundBox &left_bounds, BoundBox &right_bounds);
+
+ __forceinline BoundBox get_prim_bounds(const BVHReference &prim) const
+ {
+ if (aligned_space_ == NULL) {
+ return prim.bounds();
+ }
+ else {
+ return unaligned_heuristic_->compute_aligned_prim_boundbox(prim, *aligned_space_);
+ }
+ }
+
+ __forceinline float3 get_unaligned_point(const float3 &point) const
+ {
+ if (aligned_space_ == NULL) {
+ return point;
+ }
+ else {
+ return transform_point(aligned_space_, point);
+ }
+ }
};
/* Mixed Object-Spatial Split */
-class BVHMixedSplit
-{
-public:
- BVHObjectSplit object;
- BVHSpatialSplit spatial;
-
- float leafSAH;
- float nodeSAH;
- float minSAH;
-
- bool no_split;
-
- BoundBox bounds;
-
- BVHMixedSplit() {}
-
- __forceinline BVHMixedSplit(BVHBuild *builder,
- BVHSpatialStorage *storage,
- const BVHRange& range,
- vector<BVHReference> *references,
- int level,
- const BVHUnaligned *unaligned_heuristic = NULL,
- const Transform *aligned_space = NULL)
- {
- if(aligned_space == NULL) {
- bounds = range.bounds();
- }
- else {
- bounds = unaligned_heuristic->compute_aligned_boundbox(
- range,
- &references->at(0),
- *aligned_space);
- }
- /* find split candidates. */
- float area = bounds.safe_area();
-
- leafSAH = area * builder->params.primitive_cost(range.size());
- nodeSAH = area * builder->params.node_cost(2);
-
- object = BVHObjectSplit(builder,
- storage,
- range,
- references,
- nodeSAH,
- unaligned_heuristic,
- aligned_space);
-
- if(builder->params.use_spatial_split && level < BVHParams::MAX_SPATIAL_DEPTH) {
- BoundBox overlap = object.left_bounds;
- overlap.intersect(object.right_bounds);
-
- if(overlap.safe_area() >= builder->spatial_min_overlap) {
- spatial = BVHSpatialSplit(*builder,
- storage,
- range,
- references,
- nodeSAH,
- unaligned_heuristic,
- aligned_space);
- }
- }
-
- /* leaf SAH is the lowest => create leaf. */
- minSAH = min(min(leafSAH, object.sah), spatial.sah);
- no_split = (minSAH == leafSAH &&
- builder->range_within_max_leaf_size(range, *references));
- }
-
- __forceinline void split(BVHBuild *builder,
- BVHRange& left,
- BVHRange& right,
- const BVHRange& range)
- {
- if(builder->params.use_spatial_split && minSAH == spatial.sah)
- spatial.split(builder, left, right, range);
- if(!left.size() || !right.size())
- object.split(left, right, range);
- }
+class BVHMixedSplit {
+ public:
+ BVHObjectSplit object;
+ BVHSpatialSplit spatial;
+
+ float leafSAH;
+ float nodeSAH;
+ float minSAH;
+
+ bool no_split;
+
+ BoundBox bounds;
+
+ BVHMixedSplit()
+ {
+ }
+
+ __forceinline BVHMixedSplit(BVHBuild *builder,
+ BVHSpatialStorage *storage,
+ const BVHRange &range,
+ vector<BVHReference> *references,
+ int level,
+ const BVHUnaligned *unaligned_heuristic = NULL,
+ const Transform *aligned_space = NULL)
+ {
+ if (aligned_space == NULL) {
+ bounds = range.bounds();
+ }
+ else {
+ bounds = unaligned_heuristic->compute_aligned_boundbox(
+ range, &references->at(0), *aligned_space);
+ }
+ /* find split candidates. */
+ float area = bounds.safe_area();
+
+ leafSAH = area * builder->params.primitive_cost(range.size());
+ nodeSAH = area * builder->params.node_cost(2);
+
+ object = BVHObjectSplit(
+ builder, storage, range, references, nodeSAH, unaligned_heuristic, aligned_space);
+
+ if (builder->params.use_spatial_split && level < BVHParams::MAX_SPATIAL_DEPTH) {
+ BoundBox overlap = object.left_bounds;
+ overlap.intersect(object.right_bounds);
+
+ if (overlap.safe_area() >= builder->spatial_min_overlap) {
+ spatial = BVHSpatialSplit(
+ *builder, storage, range, references, nodeSAH, unaligned_heuristic, aligned_space);
+ }
+ }
+
+ /* leaf SAH is the lowest => create leaf. */
+ minSAH = min(min(leafSAH, object.sah), spatial.sah);
+ no_split = (minSAH == leafSAH && builder->range_within_max_leaf_size(range, *references));
+ }
+
+ __forceinline void split(BVHBuild *builder,
+ BVHRange &left,
+ BVHRange &right,
+ const BVHRange &range)
+ {
+ if (builder->params.use_spatial_split && minSAH == spatial.sah)
+ spatial.split(builder, left, right, range);
+ if (!left.size() || !right.size())
+ object.split(left, right, range);
+ }
};
CCL_NAMESPACE_END
-#endif /* __BVH_SPLIT_H__ */
+#endif /* __BVH_SPLIT_H__ */
diff --git a/intern/cycles/bvh/bvh_unaligned.cpp b/intern/cycles/bvh/bvh_unaligned.cpp
index 910f82137c5..1843ca403a5 100644
--- a/intern/cycles/bvh/bvh_unaligned.cpp
+++ b/intern/cycles/bvh/bvh_unaligned.cpp
@@ -27,150 +27,137 @@
CCL_NAMESPACE_BEGIN
-
-BVHUnaligned::BVHUnaligned(const vector<Object*>& objects)
- : objects_(objects)
+BVHUnaligned::BVHUnaligned(const vector<Object *> &objects) : objects_(objects)
{
}
-Transform BVHUnaligned::compute_aligned_space(
- const BVHObjectBinning& range,
- const BVHReference *references) const
+Transform BVHUnaligned::compute_aligned_space(const BVHObjectBinning &range,
+ const BVHReference *references) const
{
- for(int i = range.start(); i < range.end(); ++i) {
- const BVHReference& ref = references[i];
- Transform aligned_space;
- /* Use first primitive which defines correct direction to define
- * the orientation space.
- */
- if(compute_aligned_space(ref, &aligned_space)) {
- return aligned_space;
- }
- }
- return transform_identity();
+ for (int i = range.start(); i < range.end(); ++i) {
+ const BVHReference &ref = references[i];
+ Transform aligned_space;
+ /* Use first primitive which defines correct direction to define
+ * the orientation space.
+ */
+ if (compute_aligned_space(ref, &aligned_space)) {
+ return aligned_space;
+ }
+ }
+ return transform_identity();
}
-Transform BVHUnaligned::compute_aligned_space(
- const BVHRange& range,
- const BVHReference *references) const
+Transform BVHUnaligned::compute_aligned_space(const BVHRange &range,
+ const BVHReference *references) const
{
- for(int i = range.start(); i < range.end(); ++i) {
- const BVHReference& ref = references[i];
- Transform aligned_space;
- /* Use first primitive which defines correct direction to define
- * the orientation space.
- */
- if(compute_aligned_space(ref, &aligned_space)) {
- return aligned_space;
- }
- }
- return transform_identity();
+ for (int i = range.start(); i < range.end(); ++i) {
+ const BVHReference &ref = references[i];
+ Transform aligned_space;
+ /* Use first primitive which defines correct direction to define
+ * the orientation space.
+ */
+ if (compute_aligned_space(ref, &aligned_space)) {
+ return aligned_space;
+ }
+ }
+ return transform_identity();
}
-bool BVHUnaligned::compute_aligned_space(const BVHReference& ref,
- Transform *aligned_space) const
+bool BVHUnaligned::compute_aligned_space(const BVHReference &ref, Transform *aligned_space) const
{
- const Object *object = objects_[ref.prim_object()];
- const int packed_type = ref.prim_type();
- const int type = (packed_type & PRIMITIVE_ALL);
- if(type & PRIMITIVE_CURVE) {
- const int curve_index = ref.prim_index();
- const int segment = PRIMITIVE_UNPACK_SEGMENT(packed_type);
- const Mesh *mesh = object->mesh;
- const Mesh::Curve& curve = mesh->get_curve(curve_index);
- const int key = curve.first_key + segment;
- const float3 v1 = mesh->curve_keys[key],
- v2 = mesh->curve_keys[key + 1];
- float length;
- const float3 axis = normalize_len(v2 - v1, &length);
- if(length > 1e-6f) {
- *aligned_space = make_transform_frame(axis);
- return true;
- }
- }
- *aligned_space = transform_identity();
- return false;
+ const Object *object = objects_[ref.prim_object()];
+ const int packed_type = ref.prim_type();
+ const int type = (packed_type & PRIMITIVE_ALL);
+ if (type & PRIMITIVE_CURVE) {
+ const int curve_index = ref.prim_index();
+ const int segment = PRIMITIVE_UNPACK_SEGMENT(packed_type);
+ const Mesh *mesh = object->mesh;
+ const Mesh::Curve &curve = mesh->get_curve(curve_index);
+ const int key = curve.first_key + segment;
+ const float3 v1 = mesh->curve_keys[key], v2 = mesh->curve_keys[key + 1];
+ float length;
+ const float3 axis = normalize_len(v2 - v1, &length);
+ if (length > 1e-6f) {
+ *aligned_space = make_transform_frame(axis);
+ return true;
+ }
+ }
+ *aligned_space = transform_identity();
+ return false;
}
-BoundBox BVHUnaligned::compute_aligned_prim_boundbox(
- const BVHReference& prim,
- const Transform& aligned_space) const
+BoundBox BVHUnaligned::compute_aligned_prim_boundbox(const BVHReference &prim,
+ const Transform &aligned_space) const
{
- BoundBox bounds = BoundBox::empty;
- const Object *object = objects_[prim.prim_object()];
- const int packed_type = prim.prim_type();
- const int type = (packed_type & PRIMITIVE_ALL);
- if(type & PRIMITIVE_CURVE) {
- const int curve_index = prim.prim_index();
- const int segment = PRIMITIVE_UNPACK_SEGMENT(packed_type);
- const Mesh *mesh = object->mesh;
- const Mesh::Curve& curve = mesh->get_curve(curve_index);
- curve.bounds_grow(segment,
- &mesh->curve_keys[0],
- &mesh->curve_radius[0],
- aligned_space,
- bounds);
- }
- else {
- bounds = prim.bounds().transformed(&aligned_space);
- }
- return bounds;
+ BoundBox bounds = BoundBox::empty;
+ const Object *object = objects_[prim.prim_object()];
+ const int packed_type = prim.prim_type();
+ const int type = (packed_type & PRIMITIVE_ALL);
+ if (type & PRIMITIVE_CURVE) {
+ const int curve_index = prim.prim_index();
+ const int segment = PRIMITIVE_UNPACK_SEGMENT(packed_type);
+ const Mesh *mesh = object->mesh;
+ const Mesh::Curve &curve = mesh->get_curve(curve_index);
+ curve.bounds_grow(
+ segment, &mesh->curve_keys[0], &mesh->curve_radius[0], aligned_space, bounds);
+ }
+ else {
+ bounds = prim.bounds().transformed(&aligned_space);
+ }
+ return bounds;
}
-BoundBox BVHUnaligned::compute_aligned_boundbox(
- const BVHObjectBinning& range,
- const BVHReference *references,
- const Transform& aligned_space,
- BoundBox *cent_bounds) const
+BoundBox BVHUnaligned::compute_aligned_boundbox(const BVHObjectBinning &range,
+ const BVHReference *references,
+ const Transform &aligned_space,
+ BoundBox *cent_bounds) const
{
- BoundBox bounds = BoundBox::empty;
- if(cent_bounds != NULL) {
- *cent_bounds = BoundBox::empty;
- }
- for(int i = range.start(); i < range.end(); ++i) {
- const BVHReference& ref = references[i];
- BoundBox ref_bounds = compute_aligned_prim_boundbox(ref, aligned_space);
- bounds.grow(ref_bounds);
- if(cent_bounds != NULL) {
- cent_bounds->grow(ref_bounds.center2());
- }
- }
- return bounds;
+ BoundBox bounds = BoundBox::empty;
+ if (cent_bounds != NULL) {
+ *cent_bounds = BoundBox::empty;
+ }
+ for (int i = range.start(); i < range.end(); ++i) {
+ const BVHReference &ref = references[i];
+ BoundBox ref_bounds = compute_aligned_prim_boundbox(ref, aligned_space);
+ bounds.grow(ref_bounds);
+ if (cent_bounds != NULL) {
+ cent_bounds->grow(ref_bounds.center2());
+ }
+ }
+ return bounds;
}
-BoundBox BVHUnaligned::compute_aligned_boundbox(
- const BVHRange& range,
- const BVHReference *references,
- const Transform& aligned_space,
- BoundBox *cent_bounds) const
+BoundBox BVHUnaligned::compute_aligned_boundbox(const BVHRange &range,
+ const BVHReference *references,
+ const Transform &aligned_space,
+ BoundBox *cent_bounds) const
{
- BoundBox bounds = BoundBox::empty;
- if(cent_bounds != NULL) {
- *cent_bounds = BoundBox::empty;
- }
- for(int i = range.start(); i < range.end(); ++i) {
- const BVHReference& ref = references[i];
- BoundBox ref_bounds = compute_aligned_prim_boundbox(ref, aligned_space);
- bounds.grow(ref_bounds);
- if(cent_bounds != NULL) {
- cent_bounds->grow(ref_bounds.center2());
- }
- }
- return bounds;
+ BoundBox bounds = BoundBox::empty;
+ if (cent_bounds != NULL) {
+ *cent_bounds = BoundBox::empty;
+ }
+ for (int i = range.start(); i < range.end(); ++i) {
+ const BVHReference &ref = references[i];
+ BoundBox ref_bounds = compute_aligned_prim_boundbox(ref, aligned_space);
+ bounds.grow(ref_bounds);
+ if (cent_bounds != NULL) {
+ cent_bounds->grow(ref_bounds.center2());
+ }
+ }
+ return bounds;
}
-Transform BVHUnaligned::compute_node_transform(
- const BoundBox& bounds,
- const Transform& aligned_space)
+Transform BVHUnaligned::compute_node_transform(const BoundBox &bounds,
+ const Transform &aligned_space)
{
- Transform space = aligned_space;
- space.x.w -= bounds.min.x;
- space.y.w -= bounds.min.y;
- space.z.w -= bounds.min.z;
- float3 dim = bounds.max - bounds.min;
- return transform_scale(1.0f / max(1e-18f, dim.x),
- 1.0f / max(1e-18f, dim.y),
- 1.0f / max(1e-18f, dim.z)) * space;
+ Transform space = aligned_space;
+ space.x.w -= bounds.min.x;
+ space.y.w -= bounds.min.y;
+ space.z.w -= bounds.min.z;
+ float3 dim = bounds.max - bounds.min;
+ return transform_scale(
+ 1.0f / max(1e-18f, dim.x), 1.0f / max(1e-18f, dim.y), 1.0f / max(1e-18f, dim.z)) *
+ space;
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/bvh/bvh_unaligned.h b/intern/cycles/bvh/bvh_unaligned.h
index bcfb6ed68da..e8a9a25daa8 100644
--- a/intern/cycles/bvh/bvh_unaligned.h
+++ b/intern/cycles/bvh/bvh_unaligned.h
@@ -30,51 +30,44 @@ class Object;
/* Helper class to perform calculations needed for unaligned nodes. */
class BVHUnaligned {
-public:
- BVHUnaligned(const vector<Object*>& objects);
+ public:
+ BVHUnaligned(const vector<Object *> &objects);
- /* Calculate alignment for the oriented node for a given range. */
- Transform compute_aligned_space(
- const BVHObjectBinning& range,
- const BVHReference *references) const;
- Transform compute_aligned_space(
- const BVHRange& range,
- const BVHReference *references) const;
+ /* Calculate alignment for the oriented node for a given range. */
+ Transform compute_aligned_space(const BVHObjectBinning &range,
+ const BVHReference *references) const;
+ Transform compute_aligned_space(const BVHRange &range, const BVHReference *references) const;
- /* Calculate alignment for the oriented node for a given reference.
- *
- * Return true when space was calculated successfully.
- */
- bool compute_aligned_space(const BVHReference& ref,
- Transform *aligned_space) const;
+ /* Calculate alignment for the oriented node for a given reference.
+ *
+ * Return true when space was calculated successfully.
+ */
+ bool compute_aligned_space(const BVHReference &ref, Transform *aligned_space) const;
- /* Calculate primitive's bounding box in given space. */
- BoundBox compute_aligned_prim_boundbox(
- const BVHReference& prim,
- const Transform& aligned_space) const;
+ /* Calculate primitive's bounding box in given space. */
+ BoundBox compute_aligned_prim_boundbox(const BVHReference &prim,
+ const Transform &aligned_space) const;
- /* Calculate bounding box in given space. */
- BoundBox compute_aligned_boundbox(
- const BVHObjectBinning& range,
- const BVHReference *references,
- const Transform& aligned_space,
- BoundBox *cent_bounds = NULL) const;
- BoundBox compute_aligned_boundbox(
- const BVHRange& range,
- const BVHReference *references,
- const Transform& aligned_space,
- BoundBox *cent_bounds = NULL) const;
+ /* Calculate bounding box in given space. */
+ BoundBox compute_aligned_boundbox(const BVHObjectBinning &range,
+ const BVHReference *references,
+ const Transform &aligned_space,
+ BoundBox *cent_bounds = NULL) const;
+ BoundBox compute_aligned_boundbox(const BVHRange &range,
+ const BVHReference *references,
+ const Transform &aligned_space,
+ BoundBox *cent_bounds = NULL) const;
- /* Calculate affine transform for node packing.
- * Bounds will be in the range of 0..1.
- */
- static Transform compute_node_transform(const BoundBox& bounds,
- const Transform& aligned_space);
-protected:
- /* List of objects BVH is being created for. */
- const vector<Object*>& objects_;
+ /* Calculate affine transform for node packing.
+ * Bounds will be in the range of 0..1.
+ */
+ static Transform compute_node_transform(const BoundBox &bounds, const Transform &aligned_space);
+
+ protected:
+ /* List of objects BVH is being created for. */
+ const vector<Object *> &objects_;
};
CCL_NAMESPACE_END
-#endif /* __BVH_UNALIGNED_H__ */
+#endif /* __BVH_UNALIGNED_H__ */
diff --git a/intern/cycles/cmake/external_libs.cmake b/intern/cycles/cmake/external_libs.cmake
index d0f473a2939..5bf681792ca 100644
--- a/intern/cycles/cmake/external_libs.cmake
+++ b/intern/cycles/cmake/external_libs.cmake
@@ -2,24 +2,24 @@
# Precompiled libraries tips and hints, for find_package().
if(CYCLES_STANDALONE_REPOSITORY)
- if(APPLE OR WIN32)
- include(precompiled_libs)
- endif()
+ if(APPLE OR WIN32)
+ include(precompiled_libs)
+ endif()
endif()
###########################################################################
# GLUT
if(WITH_CYCLES_STANDALONE AND WITH_CYCLES_STANDALONE_GUI)
- set(GLUT_ROOT_PATH ${CYCLES_GLUT})
+ set(GLUT_ROOT_PATH ${CYCLES_GLUT})
- find_package(GLUT)
- message(STATUS "GLUT_FOUND=${GLUT_FOUND}")
+ find_package(GLUT)
+ message(STATUS "GLUT_FOUND=${GLUT_FOUND}")
- include_directories(
- SYSTEM
- ${GLUT_INCLUDE_DIR}
- )
+ include_directories(
+ SYSTEM
+ ${GLUT_INCLUDE_DIR}
+ )
endif()
###########################################################################
@@ -27,125 +27,125 @@ endif()
# Workaround for unconventional variable name use in Blender.
if(NOT CYCLES_STANDALONE_REPOSITORY)
- set(GLEW_INCLUDE_DIR "${GLEW_INCLUDE_PATH}")
+ set(GLEW_INCLUDE_DIR "${GLEW_INCLUDE_PATH}")
endif()
if(WITH_CYCLES_STANDALONE)
- set(CYCLES_APP_GLEW_LIBRARY ${BLENDER_GLEW_LIBRARIES})
+ set(CYCLES_APP_GLEW_LIBRARY ${BLENDER_GLEW_LIBRARIES})
endif()
###########################################################################
# CUDA
if(WITH_CYCLES_CUDA_BINARIES OR NOT WITH_CUDA_DYNLOAD)
- find_package(CUDA) # Try to auto locate CUDA toolkit
- if(CUDA_FOUND)
- message(STATUS "CUDA nvcc = ${CUDA_NVCC_EXECUTABLE}")
- else()
- message(STATUS "CUDA compiler not found, disabling WITH_CYCLES_CUDA_BINARIES")
- set(WITH_CYCLES_CUDA_BINARIES OFF)
- if(NOT WITH_CUDA_DYNLOAD)
- message(STATUS "Additionally falling back to dynamic CUDA load")
- set(WITH_CUDA_DYNLOAD ON)
- endif()
- endif()
+ find_package(CUDA) # Try to auto locate CUDA toolkit
+ if(CUDA_FOUND)
+ message(STATUS "CUDA nvcc = ${CUDA_NVCC_EXECUTABLE}")
+ else()
+ message(STATUS "CUDA compiler not found, disabling WITH_CYCLES_CUDA_BINARIES")
+ set(WITH_CYCLES_CUDA_BINARIES OFF)
+ if(NOT WITH_CUDA_DYNLOAD)
+ message(STATUS "Additionally falling back to dynamic CUDA load")
+ set(WITH_CUDA_DYNLOAD ON)
+ endif()
+ endif()
endif()
# Packages which are being found by Blender when building from inside Blender
# source code. but which we need to take care of when building Cycles from a
# standalone repository
if(CYCLES_STANDALONE_REPOSITORY)
- # PThreads
- # TODO(sergey): Bloody exception, handled in precompiled_libs.cmake.
- if(NOT WIN32)
- set(CMAKE_THREAD_PREFER_PTHREAD TRUE)
- find_package(Threads REQUIRED)
- set(PTHREADS_LIBRARIES ${CMAKE_THREAD_LIBS_INIT})
- endif()
-
- ####
- # OpenGL
-
- # TODO(sergey): We currently re-use the same variable name as we use
- # in Blender. Ideally we need to make it CYCLES_GL_LIBRARIES.
- find_package(OpenGL REQUIRED)
- find_package(GLEW REQUIRED)
- list(APPEND BLENDER_GL_LIBRARIES
- "${OPENGL_gl_LIBRARY}"
- "${OPENGL_glu_LIBRARY}"
- "${GLEW_LIBRARY}"
- )
-
- ####
- # OpenImageIO
- find_package(OpenImageIO REQUIRED)
- if(OPENIMAGEIO_PUGIXML_FOUND)
- set(PUGIXML_INCLUDE_DIR "${OPENIMAGEIO_INCLUDE_DIR/OpenImageIO}")
- set(PUGIXML_LIBRARIES "")
- else()
- find_package(PugiXML REQUIRED)
- endif()
-
- # OIIO usually depends on OpenEXR, so find this library
- # but don't make it required.
- find_package(OpenEXR)
-
- ####
- # OpenShadingLanguage
- if(WITH_CYCLES_OSL)
- find_package(OpenShadingLanguage REQUIRED)
- find_package(LLVM REQUIRED)
- endif()
-
- ####
- # OpenColorIO
- if(WITH_OPENCOLORIO)
- find_package(OpenColorIO REQUIRED)
- endif()
-
- ####
- # Boost
- set(__boost_packages filesystem regex system thread date_time)
- if(WITH_CYCLES_NETWORK)
- list(APPEND __boost_packages serialization)
- endif()
- if(WITH_CYCLES_OSL)
- # TODO(sergey): This is because of the way how our precompiled
- # libraries works, could be different for someone's else libs..
- if(APPLE OR MSVC)
- list(APPEND __boost_packages wave)
- elseif(NOT (${OSL_LIBRARY_VERSION_MAJOR} EQUAL "1" AND ${OSL_LIBRARY_VERSION_MINOR} LESS "6"))
- list(APPEND __boost_packages wave)
- endif()
- endif()
- find_package(Boost 1.48 COMPONENTS ${__boost_packages} REQUIRED)
- if(NOT Boost_FOUND)
- # Try to find non-multithreaded if -mt not found, this flag
- # doesn't matter for us, it has nothing to do with thread
- # safety, but keep it to not disturb build setups.
- set(Boost_USE_MULTITHREADED OFF)
- find_package(Boost 1.48 COMPONENTS ${__boost_packages})
- endif()
- unset(__boost_packages)
- set(BOOST_INCLUDE_DIR ${Boost_INCLUDE_DIRS})
- set(BOOST_LIBRARIES ${Boost_LIBRARIES})
- set(BOOST_LIBPATH ${Boost_LIBRARY_DIRS})
- set(BOOST_DEFINITIONS "-DBOOST_ALL_NO_LIB")
-
- ####
- # embree
- if(WITH_CYCLES_EMBREE)
- find_package(embree 3.2.4 REQUIRED)
- endif()
-
- ####
- # Logging
- if(WITH_CYCLES_LOGGING)
- find_package(Glog REQUIRED)
- find_package(Gflags REQUIRED)
- endif()
-
- unset(_lib_DIR)
+ # PThreads
+ # TODO(sergey): Bloody exception, handled in precompiled_libs.cmake.
+ if(NOT WIN32)
+ set(CMAKE_THREAD_PREFER_PTHREAD TRUE)
+ find_package(Threads REQUIRED)
+ set(PTHREADS_LIBRARIES ${CMAKE_THREAD_LIBS_INIT})
+ endif()
+
+ ####
+ # OpenGL
+
+ # TODO(sergey): We currently re-use the same variable name as we use
+ # in Blender. Ideally we need to make it CYCLES_GL_LIBRARIES.
+ find_package(OpenGL REQUIRED)
+ find_package(GLEW REQUIRED)
+ list(APPEND BLENDER_GL_LIBRARIES
+ "${OPENGL_gl_LIBRARY}"
+ "${OPENGL_glu_LIBRARY}"
+ "${GLEW_LIBRARY}"
+ )
+
+ ####
+ # OpenImageIO
+ find_package(OpenImageIO REQUIRED)
+ if(OPENIMAGEIO_PUGIXML_FOUND)
+ set(PUGIXML_INCLUDE_DIR "${OPENIMAGEIO_INCLUDE_DIR/OpenImageIO}")
+ set(PUGIXML_LIBRARIES "")
+ else()
+ find_package(PugiXML REQUIRED)
+ endif()
+
+ # OIIO usually depends on OpenEXR, so find this library
+ # but don't make it required.
+ find_package(OpenEXR)
+
+ ####
+ # OpenShadingLanguage
+ if(WITH_CYCLES_OSL)
+ find_package(OpenShadingLanguage REQUIRED)
+ find_package(LLVM REQUIRED)
+ endif()
+
+ ####
+ # OpenColorIO
+ if(WITH_OPENCOLORIO)
+ find_package(OpenColorIO REQUIRED)
+ endif()
+
+ ####
+ # Boost
+ set(__boost_packages filesystem regex system thread date_time)
+ if(WITH_CYCLES_NETWORK)
+ list(APPEND __boost_packages serialization)
+ endif()
+ if(WITH_CYCLES_OSL)
+ # TODO(sergey): This is because of the way how our precompiled
+ # libraries works, could be different for someone's else libs..
+ if(APPLE OR MSVC)
+ list(APPEND __boost_packages wave)
+ elseif(NOT (${OSL_LIBRARY_VERSION_MAJOR} EQUAL "1" AND ${OSL_LIBRARY_VERSION_MINOR} LESS "6"))
+ list(APPEND __boost_packages wave)
+ endif()
+ endif()
+ find_package(Boost 1.48 COMPONENTS ${__boost_packages} REQUIRED)
+ if(NOT Boost_FOUND)
+ # Try to find non-multithreaded if -mt not found, this flag
+ # doesn't matter for us, it has nothing to do with thread
+ # safety, but keep it to not disturb build setups.
+ set(Boost_USE_MULTITHREADED OFF)
+ find_package(Boost 1.48 COMPONENTS ${__boost_packages})
+ endif()
+ unset(__boost_packages)
+ set(BOOST_INCLUDE_DIR ${Boost_INCLUDE_DIRS})
+ set(BOOST_LIBRARIES ${Boost_LIBRARIES})
+ set(BOOST_LIBPATH ${Boost_LIBRARY_DIRS})
+ set(BOOST_DEFINITIONS "-DBOOST_ALL_NO_LIB")
+
+ ####
+ # embree
+ if(WITH_CYCLES_EMBREE)
+ find_package(embree 3.2.4 REQUIRED)
+ endif()
+
+ ####
+ # Logging
+ if(WITH_CYCLES_LOGGING)
+ find_package(Glog REQUIRED)
+ find_package(Gflags REQUIRED)
+ endif()
+
+ unset(_lib_DIR)
else()
- set(LLVM_LIBRARIES ${LLVM_LIBRARY})
+ set(LLVM_LIBRARIES ${LLVM_LIBRARY})
endif()
diff --git a/intern/cycles/cmake/macros.cmake b/intern/cycles/cmake/macros.cmake
index ab8182ba4a7..0efd8bb7ea8 100644
--- a/intern/cycles/cmake/macros.cmake
+++ b/intern/cycles/cmake/macros.cmake
@@ -1,15 +1,15 @@
function(cycles_set_solution_folder target)
- if(WINDOWS_USE_VISUAL_STUDIO_FOLDERS)
- get_filename_component(folderdir ${CMAKE_CURRENT_SOURCE_DIR} DIRECTORY)
- string(REPLACE ${CMAKE_SOURCE_DIR} "" folderdir ${folderdir})
- set_target_properties(${target} PROPERTIES FOLDER ${folderdir})
- endif()
+ if(WINDOWS_USE_VISUAL_STUDIO_FOLDERS)
+ get_filename_component(folderdir ${CMAKE_CURRENT_SOURCE_DIR} DIRECTORY)
+ string(REPLACE ${CMAKE_SOURCE_DIR} "" folderdir ${folderdir})
+ set_target_properties(${target} PROPERTIES FOLDER ${folderdir})
+ endif()
endfunction()
macro(cycles_add_library target library_deps)
- add_library(${target} ${ARGN})
- if(NOT ("${library_deps}" STREQUAL ""))
- target_link_libraries(${target} "${library_deps}")
- endif()
- cycles_set_solution_folder(${target})
+ add_library(${target} ${ARGN})
+ if(NOT ("${library_deps}" STREQUAL ""))
+ target_link_libraries(${target} "${library_deps}")
+ endif()
+ cycles_set_solution_folder(${target})
endmacro()
diff --git a/intern/cycles/device/CMakeLists.txt b/intern/cycles/device/CMakeLists.txt
index d804a07bcab..75f4a72bee3 100644
--- a/intern/cycles/device/CMakeLists.txt
+++ b/intern/cycles/device/CMakeLists.txt
@@ -1,61 +1,61 @@
set(INC
- ..
- ../../glew-mx
+ ..
+ ../../glew-mx
)
set(INC_SYS
- ${GLEW_INCLUDE_DIR}
- ../../../extern/clew/include
+ ${GLEW_INCLUDE_DIR}
+ ../../../extern/clew/include
)
if(WITH_CUDA_DYNLOAD)
- list(APPEND INC
- ../../../extern/cuew/include
- )
- add_definitions(-DWITH_CUDA_DYNLOAD)
+ list(APPEND INC
+ ../../../extern/cuew/include
+ )
+ add_definitions(-DWITH_CUDA_DYNLOAD)
else()
- list(APPEND INC_SYS
- ${CUDA_TOOLKIT_INCLUDE}
- )
- add_definitions(-DCYCLES_CUDA_NVCC_EXECUTABLE="${CUDA_NVCC_EXECUTABLE}")
+ list(APPEND INC_SYS
+ ${CUDA_TOOLKIT_INCLUDE}
+ )
+ add_definitions(-DCYCLES_CUDA_NVCC_EXECUTABLE="${CUDA_NVCC_EXECUTABLE}")
endif()
set(SRC
- device.cpp
- device_cpu.cpp
- device_cuda.cpp
- device_denoising.cpp
- device_memory.cpp
- device_multi.cpp
- device_opencl.cpp
- device_split_kernel.cpp
- device_task.cpp
+ device.cpp
+ device_cpu.cpp
+ device_cuda.cpp
+ device_denoising.cpp
+ device_memory.cpp
+ device_multi.cpp
+ device_opencl.cpp
+ device_split_kernel.cpp
+ device_task.cpp
)
set(SRC_OPENCL
- opencl/opencl.h
- opencl/memory_manager.h
+ opencl/opencl.h
+ opencl/memory_manager.h
- opencl/opencl_split.cpp
- opencl/opencl_util.cpp
- opencl/memory_manager.cpp
+ opencl/opencl_split.cpp
+ opencl/opencl_util.cpp
+ opencl/memory_manager.cpp
)
if(WITH_CYCLES_NETWORK)
- list(APPEND SRC
- device_network.cpp
- )
+ list(APPEND SRC
+ device_network.cpp
+ )
endif()
set(SRC_HEADERS
- device.h
- device_denoising.h
- device_memory.h
- device_intern.h
- device_network.h
- device_split_kernel.h
- device_task.h
+ device.h
+ device_denoising.h
+ device_memory.h
+ device_intern.h
+ device_network.h
+ device_split_kernel.h
+ device_task.h
)
set(LIB
@@ -63,27 +63,27 @@ set(LIB
)
if(WITH_CUDA_DYNLOAD)
- list(APPEND LIB
- extern_cuew
- )
+ list(APPEND LIB
+ extern_cuew
+ )
else()
- list(APPEND LIB
- ${CUDA_CUDA_LIBRARY}
- )
+ list(APPEND LIB
+ ${CUDA_CUDA_LIBRARY}
+ )
endif()
add_definitions(${GL_DEFINITIONS})
if(WITH_CYCLES_NETWORK)
- add_definitions(-DWITH_NETWORK)
+ add_definitions(-DWITH_NETWORK)
endif()
if(WITH_CYCLES_DEVICE_OPENCL)
- add_definitions(-DWITH_OPENCL)
+ add_definitions(-DWITH_OPENCL)
endif()
if(WITH_CYCLES_DEVICE_CUDA)
- add_definitions(-DWITH_CUDA)
+ add_definitions(-DWITH_CUDA)
endif()
if(WITH_CYCLES_DEVICE_MULTI)
- add_definitions(-DWITH_MULTI)
+ add_definitions(-DWITH_MULTI)
endif()
include_directories(${INC})
diff --git a/intern/cycles/device/device.cpp b/intern/cycles/device/device.cpp
index e74637472ef..16a68e8b855 100644
--- a/intern/cycles/device/device.cpp
+++ b/intern/cycles/device/device.cpp
@@ -44,572 +44,577 @@ uint Device::devices_initialized_mask = 0;
/* Device Requested Features */
-std::ostream& operator <<(std::ostream &os,
- const DeviceRequestedFeatures& requested_features)
+std::ostream &operator<<(std::ostream &os, const DeviceRequestedFeatures &requested_features)
{
- os << "Experimental features: "
- << (requested_features.experimental ? "On" : "Off") << std::endl;
- os << "Max nodes group: " << requested_features.max_nodes_group << std::endl;
- /* TODO(sergey): Decode bitflag into list of names. */
- os << "Nodes features: " << requested_features.nodes_features << std::endl;
- os << "Use Hair: "
- << string_from_bool(requested_features.use_hair) << std::endl;
- os << "Use Object Motion: "
- << string_from_bool(requested_features.use_object_motion) << std::endl;
- os << "Use Camera Motion: "
- << string_from_bool(requested_features.use_camera_motion) << std::endl;
- os << "Use Baking: "
- << string_from_bool(requested_features.use_baking) << std::endl;
- os << "Use Subsurface: "
- << string_from_bool(requested_features.use_subsurface) << std::endl;
- os << "Use Volume: "
- << string_from_bool(requested_features.use_volume) << std::endl;
- os << "Use Branched Integrator: "
- << string_from_bool(requested_features.use_integrator_branched) << std::endl;
- os << "Use Patch Evaluation: "
- << string_from_bool(requested_features.use_patch_evaluation) << std::endl;
- os << "Use Transparent Shadows: "
- << string_from_bool(requested_features.use_transparent) << std::endl;
- os << "Use Principled BSDF: "
- << string_from_bool(requested_features.use_principled) << std::endl;
- os << "Use Denoising: "
- << string_from_bool(requested_features.use_denoising) << std::endl;
- os << "Use Displacement: "
- << string_from_bool(requested_features.use_true_displacement) << std::endl;
- os << "Use Background Light: "
- << string_from_bool(requested_features.use_background_light) << std::endl;
- return os;
+ os << "Experimental features: " << (requested_features.experimental ? "On" : "Off") << std::endl;
+ os << "Max nodes group: " << requested_features.max_nodes_group << std::endl;
+ /* TODO(sergey): Decode bitflag into list of names. */
+ os << "Nodes features: " << requested_features.nodes_features << std::endl;
+ os << "Use Hair: " << string_from_bool(requested_features.use_hair) << std::endl;
+ os << "Use Object Motion: " << string_from_bool(requested_features.use_object_motion)
+ << std::endl;
+ os << "Use Camera Motion: " << string_from_bool(requested_features.use_camera_motion)
+ << std::endl;
+ os << "Use Baking: " << string_from_bool(requested_features.use_baking) << std::endl;
+ os << "Use Subsurface: " << string_from_bool(requested_features.use_subsurface) << std::endl;
+ os << "Use Volume: " << string_from_bool(requested_features.use_volume) << std::endl;
+ os << "Use Branched Integrator: " << string_from_bool(requested_features.use_integrator_branched)
+ << std::endl;
+ os << "Use Patch Evaluation: " << string_from_bool(requested_features.use_patch_evaluation)
+ << std::endl;
+ os << "Use Transparent Shadows: " << string_from_bool(requested_features.use_transparent)
+ << std::endl;
+ os << "Use Principled BSDF: " << string_from_bool(requested_features.use_principled)
+ << std::endl;
+ os << "Use Denoising: " << string_from_bool(requested_features.use_denoising) << std::endl;
+ os << "Use Displacement: " << string_from_bool(requested_features.use_true_displacement)
+ << std::endl;
+ os << "Use Background Light: " << string_from_bool(requested_features.use_background_light)
+ << std::endl;
+ return os;
}
/* Device */
Device::~Device()
{
- if(!background) {
- if(vertex_buffer != 0) {
- glDeleteBuffers(1, &vertex_buffer);
- }
- if(fallback_shader_program != 0) {
- glDeleteProgram(fallback_shader_program);
- }
- }
+ if (!background) {
+ if (vertex_buffer != 0) {
+ glDeleteBuffers(1, &vertex_buffer);
+ }
+ if (fallback_shader_program != 0) {
+ glDeleteProgram(fallback_shader_program);
+ }
+ }
}
/* TODO move shaders to standalone .glsl file. */
const char *FALLBACK_VERTEX_SHADER =
-"#version 330\n"
-"uniform vec2 fullscreen;\n"
-"in vec2 texCoord;\n"
-"in vec2 pos;\n"
-"out vec2 texCoord_interp;\n"
-"\n"
-"vec2 normalize_coordinates()\n"
-"{\n"
-" return (vec2(2.0) * (pos / fullscreen)) - vec2(1.0);\n"
-"}\n"
-"\n"
-"void main()\n"
-"{\n"
-" gl_Position = vec4(normalize_coordinates(), 0.0, 1.0);\n"
-" texCoord_interp = texCoord;\n"
-"}\n\0";
+ "#version 330\n"
+ "uniform vec2 fullscreen;\n"
+ "in vec2 texCoord;\n"
+ "in vec2 pos;\n"
+ "out vec2 texCoord_interp;\n"
+ "\n"
+ "vec2 normalize_coordinates()\n"
+ "{\n"
+ " return (vec2(2.0) * (pos / fullscreen)) - vec2(1.0);\n"
+ "}\n"
+ "\n"
+ "void main()\n"
+ "{\n"
+ " gl_Position = vec4(normalize_coordinates(), 0.0, 1.0);\n"
+ " texCoord_interp = texCoord;\n"
+ "}\n\0";
const char *FALLBACK_FRAGMENT_SHADER =
-"#version 330\n"
-"uniform sampler2D image_texture;\n"
-"in vec2 texCoord_interp;\n"
-"out vec4 fragColor;\n"
-"\n"
-"void main()\n"
-"{\n"
-" fragColor = texture(image_texture, texCoord_interp);\n"
-"}\n\0";
+ "#version 330\n"
+ "uniform sampler2D image_texture;\n"
+ "in vec2 texCoord_interp;\n"
+ "out vec4 fragColor;\n"
+ "\n"
+ "void main()\n"
+ "{\n"
+ " fragColor = texture(image_texture, texCoord_interp);\n"
+ "}\n\0";
static void shader_print_errors(const char *task, const char *log, const char *code)
{
- LOG(ERROR) << "Shader: " << task << " error:";
- LOG(ERROR) << "===== shader string ====";
-
- stringstream stream(code);
- string partial;
-
- int line = 1;
- while(getline(stream, partial, '\n')) {
- if(line < 10) {
- LOG(ERROR) << " " << line << " " << partial;
- }
- else {
- LOG(ERROR) << line << " " << partial;
- }
- line++;
- }
- LOG(ERROR) << log;
+ LOG(ERROR) << "Shader: " << task << " error:";
+ LOG(ERROR) << "===== shader string ====";
+
+ stringstream stream(code);
+ string partial;
+
+ int line = 1;
+ while (getline(stream, partial, '\n')) {
+ if (line < 10) {
+ LOG(ERROR) << " " << line << " " << partial;
+ }
+ else {
+ LOG(ERROR) << line << " " << partial;
+ }
+ line++;
+ }
+ LOG(ERROR) << log;
}
static int bind_fallback_shader(void)
{
- GLint status;
- GLchar log[5000];
- GLsizei length = 0;
- GLuint program = 0;
+ GLint status;
+ GLchar log[5000];
+ GLsizei length = 0;
+ GLuint program = 0;
- struct Shader {
- const char *source;
- GLenum type;
- } shaders[2] = {
- {FALLBACK_VERTEX_SHADER, GL_VERTEX_SHADER},
- {FALLBACK_FRAGMENT_SHADER, GL_FRAGMENT_SHADER}
- };
+ struct Shader {
+ const char *source;
+ GLenum type;
+ } shaders[2] = {{FALLBACK_VERTEX_SHADER, GL_VERTEX_SHADER},
+ {FALLBACK_FRAGMENT_SHADER, GL_FRAGMENT_SHADER}};
- program = glCreateProgram();
+ program = glCreateProgram();
- for(int i = 0; i < 2; i++) {
- GLuint shader = glCreateShader(shaders[i].type);
+ for (int i = 0; i < 2; i++) {
+ GLuint shader = glCreateShader(shaders[i].type);
- string source_str = shaders[i].source;
- const char *c_str = source_str.c_str();
+ string source_str = shaders[i].source;
+ const char *c_str = source_str.c_str();
- glShaderSource(shader, 1, &c_str, NULL);
- glCompileShader(shader);
+ glShaderSource(shader, 1, &c_str, NULL);
+ glCompileShader(shader);
- glGetShaderiv(shader, GL_COMPILE_STATUS, &status);
+ glGetShaderiv(shader, GL_COMPILE_STATUS, &status);
- if(!status) {
- glGetShaderInfoLog(shader, sizeof(log), &length, log);
- shader_print_errors("compile", log, c_str);
- return 0;
- }
+ if (!status) {
+ glGetShaderInfoLog(shader, sizeof(log), &length, log);
+ shader_print_errors("compile", log, c_str);
+ return 0;
+ }
- glAttachShader(program, shader);
- }
+ glAttachShader(program, shader);
+ }
- /* Link output. */
- glBindFragDataLocation(program, 0, "fragColor");
+ /* Link output. */
+ glBindFragDataLocation(program, 0, "fragColor");
- /* Link and error check. */
- glLinkProgram(program);
+ /* Link and error check. */
+ glLinkProgram(program);
- glGetProgramiv(program, GL_LINK_STATUS, &status);
- if(!status) {
- glGetShaderInfoLog(program, sizeof(log), &length, log);
- shader_print_errors("linking", log, FALLBACK_VERTEX_SHADER);
- shader_print_errors("linking", log, FALLBACK_FRAGMENT_SHADER);
- return 0;
- }
+ glGetProgramiv(program, GL_LINK_STATUS, &status);
+ if (!status) {
+ glGetShaderInfoLog(program, sizeof(log), &length, log);
+ shader_print_errors("linking", log, FALLBACK_VERTEX_SHADER);
+ shader_print_errors("linking", log, FALLBACK_FRAGMENT_SHADER);
+ return 0;
+ }
- return program;
+ return program;
}
bool Device::bind_fallback_display_space_shader(const float width, const float height)
{
- if(fallback_status == FALLBACK_SHADER_STATUS_ERROR) {
- return false;
- }
-
- if(fallback_status == FALLBACK_SHADER_STATUS_NONE) {
- fallback_shader_program = bind_fallback_shader();
- fallback_status = FALLBACK_SHADER_STATUS_ERROR;
-
- if(fallback_shader_program == 0) {
- return false;
- }
-
- glUseProgram(fallback_shader_program);
- image_texture_location = glGetUniformLocation(fallback_shader_program, "image_texture");
- if(image_texture_location < 0) {
- LOG(ERROR) << "Shader doesn't containt the 'image_texture' uniform.";
- return false;
- }
-
- fullscreen_location = glGetUniformLocation(fallback_shader_program, "fullscreen");
- if(fullscreen_location < 0) {
- LOG(ERROR) << "Shader doesn't containt the 'fullscreen' uniform.";
- return false;
- }
-
- fallback_status = FALLBACK_SHADER_STATUS_SUCCESS;
- }
-
- /* Run this every time. */
- glUseProgram(fallback_shader_program);
- glUniform1i(image_texture_location, 0);
- glUniform2f(fullscreen_location, width, height);
- return true;
+ if (fallback_status == FALLBACK_SHADER_STATUS_ERROR) {
+ return false;
+ }
+
+ if (fallback_status == FALLBACK_SHADER_STATUS_NONE) {
+ fallback_shader_program = bind_fallback_shader();
+ fallback_status = FALLBACK_SHADER_STATUS_ERROR;
+
+ if (fallback_shader_program == 0) {
+ return false;
+ }
+
+ glUseProgram(fallback_shader_program);
+ image_texture_location = glGetUniformLocation(fallback_shader_program, "image_texture");
+ if (image_texture_location < 0) {
+ LOG(ERROR) << "Shader doesn't containt the 'image_texture' uniform.";
+ return false;
+ }
+
+ fullscreen_location = glGetUniformLocation(fallback_shader_program, "fullscreen");
+ if (fullscreen_location < 0) {
+ LOG(ERROR) << "Shader doesn't containt the 'fullscreen' uniform.";
+ return false;
+ }
+
+ fallback_status = FALLBACK_SHADER_STATUS_SUCCESS;
+ }
+
+ /* Run this every time. */
+ glUseProgram(fallback_shader_program);
+ glUniform1i(image_texture_location, 0);
+ glUniform2f(fullscreen_location, width, height);
+ return true;
}
-void Device::draw_pixels(
- device_memory& rgba, int y,
- int w, int h, int width, int height,
- int dx, int dy, int dw, int dh,
- bool transparent, const DeviceDrawParams &draw_params)
+void Device::draw_pixels(device_memory &rgba,
+ int y,
+ int w,
+ int h,
+ int width,
+ int height,
+ int dx,
+ int dy,
+ int dw,
+ int dh,
+ bool transparent,
+ const DeviceDrawParams &draw_params)
{
- const bool use_fallback_shader = (draw_params.bind_display_space_shader_cb == NULL);
-
- assert(rgba.type == MEM_PIXELS);
- mem_copy_from(rgba, y, w, h, rgba.memory_elements_size(1));
-
- GLuint texid;
- glActiveTexture(GL_TEXTURE0);
- glGenTextures(1, &texid);
- glBindTexture(GL_TEXTURE_2D, texid);
-
- if(rgba.data_type == TYPE_HALF) {
- GLhalf *data_pointer = (GLhalf*)rgba.host_pointer;
- data_pointer += 4 * y * w;
- glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, w, h, 0, GL_RGBA, GL_HALF_FLOAT, data_pointer);
- }
- else {
- uint8_t *data_pointer = (uint8_t*)rgba.host_pointer;
- data_pointer += 4 * y * w;
- glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, data_pointer);
- }
-
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
-
- if(transparent) {
- glEnable(GL_BLEND);
- glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
- }
-
- GLint shader_program;
- if(use_fallback_shader) {
- if(!bind_fallback_display_space_shader(dw, dh)) {
- return;
- }
- shader_program = fallback_shader_program;
- }
- else {
- draw_params.bind_display_space_shader_cb();
- glGetIntegerv(GL_CURRENT_PROGRAM, &shader_program);
- }
-
- if(!vertex_buffer) {
- glGenBuffers(1, &vertex_buffer);
- }
-
- glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer);
- /* invalidate old contents - avoids stalling if buffer is still waiting in queue to be rendered */
- glBufferData(GL_ARRAY_BUFFER, 16 * sizeof(float), NULL, GL_STREAM_DRAW);
-
- float *vpointer = (float *)glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY);
-
- if(vpointer) {
- /* texture coordinate - vertex pair */
- vpointer[0] = 0.0f;
- vpointer[1] = 0.0f;
- vpointer[2] = dx;
- vpointer[3] = dy;
-
- vpointer[4] = 1.0f;
- vpointer[5] = 0.0f;
- vpointer[6] = (float)width + dx;
- vpointer[7] = dy;
-
- vpointer[8] = 1.0f;
- vpointer[9] = 1.0f;
- vpointer[10] = (float)width + dx;
- vpointer[11] = (float)height + dy;
-
- vpointer[12] = 0.0f;
- vpointer[13] = 1.0f;
- vpointer[14] = dx;
- vpointer[15] = (float)height + dy;
-
- if(vertex_buffer) {
- glUnmapBuffer(GL_ARRAY_BUFFER);
- }
- }
-
- GLuint vertex_array_object;
- GLuint position_attribute, texcoord_attribute;
-
- glGenVertexArrays(1, &vertex_array_object);
- glBindVertexArray(vertex_array_object);
-
- texcoord_attribute = glGetAttribLocation(shader_program, "texCoord");
- position_attribute = glGetAttribLocation(shader_program, "pos");
-
- glEnableVertexAttribArray(texcoord_attribute);
- glEnableVertexAttribArray(position_attribute);
-
- glVertexAttribPointer(texcoord_attribute, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), (const GLvoid *)0);
- glVertexAttribPointer(position_attribute, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), (const GLvoid *)(sizeof(float) * 2));
-
- glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
-
- if(vertex_buffer) {
- glBindBuffer(GL_ARRAY_BUFFER, 0);
- }
-
- if(use_fallback_shader) {
- glUseProgram(0);
- }
- else {
- draw_params.unbind_display_space_shader_cb();
- }
-
- glDeleteVertexArrays(1, &vertex_array_object);
- glBindTexture(GL_TEXTURE_2D, 0);
- glDeleteTextures(1, &texid);
-
- if(transparent) {
- glDisable(GL_BLEND);
- }
+ const bool use_fallback_shader = (draw_params.bind_display_space_shader_cb == NULL);
+
+ assert(rgba.type == MEM_PIXELS);
+ mem_copy_from(rgba, y, w, h, rgba.memory_elements_size(1));
+
+ GLuint texid;
+ glActiveTexture(GL_TEXTURE0);
+ glGenTextures(1, &texid);
+ glBindTexture(GL_TEXTURE_2D, texid);
+
+ if (rgba.data_type == TYPE_HALF) {
+ GLhalf *data_pointer = (GLhalf *)rgba.host_pointer;
+ data_pointer += 4 * y * w;
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, w, h, 0, GL_RGBA, GL_HALF_FLOAT, data_pointer);
+ }
+ else {
+ uint8_t *data_pointer = (uint8_t *)rgba.host_pointer;
+ data_pointer += 4 * y * w;
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, data_pointer);
+ }
+
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+
+ if (transparent) {
+ glEnable(GL_BLEND);
+ glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
+ }
+
+ GLint shader_program;
+ if (use_fallback_shader) {
+ if (!bind_fallback_display_space_shader(dw, dh)) {
+ return;
+ }
+ shader_program = fallback_shader_program;
+ }
+ else {
+ draw_params.bind_display_space_shader_cb();
+ glGetIntegerv(GL_CURRENT_PROGRAM, &shader_program);
+ }
+
+ if (!vertex_buffer) {
+ glGenBuffers(1, &vertex_buffer);
+ }
+
+ glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer);
+ /* invalidate old contents - avoids stalling if buffer is still waiting in queue to be rendered */
+ glBufferData(GL_ARRAY_BUFFER, 16 * sizeof(float), NULL, GL_STREAM_DRAW);
+
+ float *vpointer = (float *)glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY);
+
+ if (vpointer) {
+ /* texture coordinate - vertex pair */
+ vpointer[0] = 0.0f;
+ vpointer[1] = 0.0f;
+ vpointer[2] = dx;
+ vpointer[3] = dy;
+
+ vpointer[4] = 1.0f;
+ vpointer[5] = 0.0f;
+ vpointer[6] = (float)width + dx;
+ vpointer[7] = dy;
+
+ vpointer[8] = 1.0f;
+ vpointer[9] = 1.0f;
+ vpointer[10] = (float)width + dx;
+ vpointer[11] = (float)height + dy;
+
+ vpointer[12] = 0.0f;
+ vpointer[13] = 1.0f;
+ vpointer[14] = dx;
+ vpointer[15] = (float)height + dy;
+
+ if (vertex_buffer) {
+ glUnmapBuffer(GL_ARRAY_BUFFER);
+ }
+ }
+
+ GLuint vertex_array_object;
+ GLuint position_attribute, texcoord_attribute;
+
+ glGenVertexArrays(1, &vertex_array_object);
+ glBindVertexArray(vertex_array_object);
+
+ texcoord_attribute = glGetAttribLocation(shader_program, "texCoord");
+ position_attribute = glGetAttribLocation(shader_program, "pos");
+
+ glEnableVertexAttribArray(texcoord_attribute);
+ glEnableVertexAttribArray(position_attribute);
+
+ glVertexAttribPointer(
+ texcoord_attribute, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), (const GLvoid *)0);
+ glVertexAttribPointer(position_attribute,
+ 2,
+ GL_FLOAT,
+ GL_FALSE,
+ 4 * sizeof(float),
+ (const GLvoid *)(sizeof(float) * 2));
+
+ glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
+
+ if (vertex_buffer) {
+ glBindBuffer(GL_ARRAY_BUFFER, 0);
+ }
+
+ if (use_fallback_shader) {
+ glUseProgram(0);
+ }
+ else {
+ draw_params.unbind_display_space_shader_cb();
+ }
+
+ glDeleteVertexArrays(1, &vertex_array_object);
+ glBindTexture(GL_TEXTURE_2D, 0);
+ glDeleteTextures(1, &texid);
+
+ if (transparent) {
+ glDisable(GL_BLEND);
+ }
}
-Device *Device::create(DeviceInfo& info, Stats &stats, Profiler &profiler, bool background)
+Device *Device::create(DeviceInfo &info, Stats &stats, Profiler &profiler, bool background)
{
- Device *device;
+ Device *device;
- switch(info.type) {
- case DEVICE_CPU:
- device = device_cpu_create(info, stats, profiler, background);
- break;
+ switch (info.type) {
+ case DEVICE_CPU:
+ device = device_cpu_create(info, stats, profiler, background);
+ break;
#ifdef WITH_CUDA
- case DEVICE_CUDA:
- if(device_cuda_init())
- device = device_cuda_create(info, stats, profiler, background);
- else
- device = NULL;
- break;
+ case DEVICE_CUDA:
+ if (device_cuda_init())
+ device = device_cuda_create(info, stats, profiler, background);
+ else
+ device = NULL;
+ break;
#endif
#ifdef WITH_MULTI
- case DEVICE_MULTI:
- device = device_multi_create(info, stats, profiler, background);
- break;
+ case DEVICE_MULTI:
+ device = device_multi_create(info, stats, profiler, background);
+ break;
#endif
#ifdef WITH_NETWORK
- case DEVICE_NETWORK:
- device = device_network_create(info, stats, profiler, "127.0.0.1");
- break;
+ case DEVICE_NETWORK:
+ device = device_network_create(info, stats, profiler, "127.0.0.1");
+ break;
#endif
#ifdef WITH_OPENCL
- case DEVICE_OPENCL:
- if(device_opencl_init())
- device = device_opencl_create(info, stats, profiler, background);
- else
- device = NULL;
- break;
+ case DEVICE_OPENCL:
+ if (device_opencl_init())
+ device = device_opencl_create(info, stats, profiler, background);
+ else
+ device = NULL;
+ break;
#endif
- default:
- return NULL;
- }
+ default:
+ return NULL;
+ }
- return device;
+ return device;
}
DeviceType Device::type_from_string(const char *name)
{
- if(strcmp(name, "CPU") == 0)
- return DEVICE_CPU;
- else if(strcmp(name, "CUDA") == 0)
- return DEVICE_CUDA;
- else if(strcmp(name, "OPENCL") == 0)
- return DEVICE_OPENCL;
- else if(strcmp(name, "NETWORK") == 0)
- return DEVICE_NETWORK;
- else if(strcmp(name, "MULTI") == 0)
- return DEVICE_MULTI;
-
- return DEVICE_NONE;
+ if (strcmp(name, "CPU") == 0)
+ return DEVICE_CPU;
+ else if (strcmp(name, "CUDA") == 0)
+ return DEVICE_CUDA;
+ else if (strcmp(name, "OPENCL") == 0)
+ return DEVICE_OPENCL;
+ else if (strcmp(name, "NETWORK") == 0)
+ return DEVICE_NETWORK;
+ else if (strcmp(name, "MULTI") == 0)
+ return DEVICE_MULTI;
+
+ return DEVICE_NONE;
}
string Device::string_from_type(DeviceType type)
{
- if(type == DEVICE_CPU)
- return "CPU";
- else if(type == DEVICE_CUDA)
- return "CUDA";
- else if(type == DEVICE_OPENCL)
- return "OPENCL";
- else if(type == DEVICE_NETWORK)
- return "NETWORK";
- else if(type == DEVICE_MULTI)
- return "MULTI";
-
- return "";
+ if (type == DEVICE_CPU)
+ return "CPU";
+ else if (type == DEVICE_CUDA)
+ return "CUDA";
+ else if (type == DEVICE_OPENCL)
+ return "OPENCL";
+ else if (type == DEVICE_NETWORK)
+ return "NETWORK";
+ else if (type == DEVICE_MULTI)
+ return "MULTI";
+
+ return "";
}
vector<DeviceType> Device::available_types()
{
- vector<DeviceType> types;
- types.push_back(DEVICE_CPU);
+ vector<DeviceType> types;
+ types.push_back(DEVICE_CPU);
#ifdef WITH_CUDA
- types.push_back(DEVICE_CUDA);
+ types.push_back(DEVICE_CUDA);
#endif
#ifdef WITH_OPENCL
- types.push_back(DEVICE_OPENCL);
+ types.push_back(DEVICE_OPENCL);
#endif
#ifdef WITH_NETWORK
- types.push_back(DEVICE_NETWORK);
+ types.push_back(DEVICE_NETWORK);
#endif
- return types;
+ return types;
}
vector<DeviceInfo> Device::available_devices(uint mask)
{
- /* Lazy initialize devices. On some platforms OpenCL or CUDA drivers can
- * be broken and cause crashes when only trying to get device info, so
- * we don't want to do any initialization until the user chooses to. */
- thread_scoped_lock lock(device_mutex);
- vector<DeviceInfo> devices;
+ /* Lazy initialize devices. On some platforms OpenCL or CUDA drivers can
+ * be broken and cause crashes when only trying to get device info, so
+ * we don't want to do any initialization until the user chooses to. */
+ thread_scoped_lock lock(device_mutex);
+ vector<DeviceInfo> devices;
#ifdef WITH_OPENCL
- if(mask & DEVICE_MASK_OPENCL) {
- if(!(devices_initialized_mask & DEVICE_MASK_OPENCL)) {
- if(device_opencl_init()) {
- device_opencl_info(opencl_devices);
- }
- devices_initialized_mask |= DEVICE_MASK_OPENCL;
- }
- foreach(DeviceInfo& info, opencl_devices) {
- devices.push_back(info);
- }
- }
+ if (mask & DEVICE_MASK_OPENCL) {
+ if (!(devices_initialized_mask & DEVICE_MASK_OPENCL)) {
+ if (device_opencl_init()) {
+ device_opencl_info(opencl_devices);
+ }
+ devices_initialized_mask |= DEVICE_MASK_OPENCL;
+ }
+ foreach (DeviceInfo &info, opencl_devices) {
+ devices.push_back(info);
+ }
+ }
#endif
#ifdef WITH_CUDA
- if(mask & DEVICE_MASK_CUDA) {
- if(!(devices_initialized_mask & DEVICE_MASK_CUDA)) {
- if(device_cuda_init()) {
- device_cuda_info(cuda_devices);
- }
- devices_initialized_mask |= DEVICE_MASK_CUDA;
- }
- foreach(DeviceInfo& info, cuda_devices) {
- devices.push_back(info);
- }
- }
+ if (mask & DEVICE_MASK_CUDA) {
+ if (!(devices_initialized_mask & DEVICE_MASK_CUDA)) {
+ if (device_cuda_init()) {
+ device_cuda_info(cuda_devices);
+ }
+ devices_initialized_mask |= DEVICE_MASK_CUDA;
+ }
+ foreach (DeviceInfo &info, cuda_devices) {
+ devices.push_back(info);
+ }
+ }
#endif
- if(mask & DEVICE_MASK_CPU) {
- if(!(devices_initialized_mask & DEVICE_MASK_CPU)) {
- device_cpu_info(cpu_devices);
- devices_initialized_mask |= DEVICE_MASK_CPU;
- }
- foreach(DeviceInfo& info, cpu_devices) {
- devices.push_back(info);
- }
- }
+ if (mask & DEVICE_MASK_CPU) {
+ if (!(devices_initialized_mask & DEVICE_MASK_CPU)) {
+ device_cpu_info(cpu_devices);
+ devices_initialized_mask |= DEVICE_MASK_CPU;
+ }
+ foreach (DeviceInfo &info, cpu_devices) {
+ devices.push_back(info);
+ }
+ }
#ifdef WITH_NETWORK
- if(mask & DEVICE_MASK_NETWORK) {
- if(!(devices_initialized_mask & DEVICE_MASK_NETWORK)) {
- device_network_info(network_devices);
- devices_initialized_mask |= DEVICE_MASK_NETWORK;
- }
- foreach(DeviceInfo& info, network_devices) {
- devices.push_back(info);
- }
- }
+ if (mask & DEVICE_MASK_NETWORK) {
+ if (!(devices_initialized_mask & DEVICE_MASK_NETWORK)) {
+ device_network_info(network_devices);
+ devices_initialized_mask |= DEVICE_MASK_NETWORK;
+ }
+ foreach (DeviceInfo &info, network_devices) {
+ devices.push_back(info);
+ }
+ }
#endif
- return devices;
+ return devices;
}
string Device::device_capabilities(uint mask)
{
- thread_scoped_lock lock(device_mutex);
- string capabilities = "";
+ thread_scoped_lock lock(device_mutex);
+ string capabilities = "";
- if(mask & DEVICE_MASK_CPU) {
- capabilities += "\nCPU device capabilities: ";
- capabilities += device_cpu_capabilities() + "\n";
- }
+ if (mask & DEVICE_MASK_CPU) {
+ capabilities += "\nCPU device capabilities: ";
+ capabilities += device_cpu_capabilities() + "\n";
+ }
#ifdef WITH_OPENCL
- if(mask & DEVICE_MASK_OPENCL) {
- if(device_opencl_init()) {
- capabilities += "\nOpenCL device capabilities:\n";
- capabilities += device_opencl_capabilities();
- }
- }
+ if (mask & DEVICE_MASK_OPENCL) {
+ if (device_opencl_init()) {
+ capabilities += "\nOpenCL device capabilities:\n";
+ capabilities += device_opencl_capabilities();
+ }
+ }
#endif
#ifdef WITH_CUDA
- if(mask & DEVICE_MASK_CUDA) {
- if(device_cuda_init()) {
- capabilities += "\nCUDA device capabilities:\n";
- capabilities += device_cuda_capabilities();
- }
- }
+ if (mask & DEVICE_MASK_CUDA) {
+ if (device_cuda_init()) {
+ capabilities += "\nCUDA device capabilities:\n";
+ capabilities += device_cuda_capabilities();
+ }
+ }
#endif
- return capabilities;
+ return capabilities;
}
-DeviceInfo Device::get_multi_device(const vector<DeviceInfo>& subdevices, int threads, bool background)
+DeviceInfo Device::get_multi_device(const vector<DeviceInfo> &subdevices,
+ int threads,
+ bool background)
{
- assert(subdevices.size() > 0);
-
- if(subdevices.size() == 1) {
- /* No multi device needed. */
- return subdevices.front();
- }
-
- DeviceInfo info;
- info.type = DEVICE_MULTI;
- info.id = "MULTI";
- info.description = "Multi Device";
- info.num = 0;
-
- info.has_half_images = true;
- info.has_volume_decoupled = true;
- info.has_osl = true;
- info.has_profiling = true;
-
- foreach(const DeviceInfo &device, subdevices) {
- /* Ensure CPU device does not slow down GPU. */
- if(device.type == DEVICE_CPU && subdevices.size() > 1) {
- if(background) {
- int orig_cpu_threads = (threads)? threads: system_cpu_thread_count();
- int cpu_threads = max(orig_cpu_threads - (subdevices.size() - 1), 0);
-
- VLOG(1) << "CPU render threads reduced from "
- << orig_cpu_threads << " to " << cpu_threads
- << ", to dedicate to GPU.";
-
- if(cpu_threads >= 1) {
- DeviceInfo cpu_device = device;
- cpu_device.cpu_threads = cpu_threads;
- info.multi_devices.push_back(cpu_device);
- }
- else {
- continue;
- }
- }
- else {
- VLOG(1) << "CPU render threads disabled for interactive render.";
- continue;
- }
- }
- else {
- info.multi_devices.push_back(device);
- }
-
- /* Accumulate device info. */
- info.has_half_images &= device.has_half_images;
- info.has_volume_decoupled &= device.has_volume_decoupled;
- info.has_osl &= device.has_osl;
- info.has_profiling &= device.has_profiling;
- }
-
- return info;
+ assert(subdevices.size() > 0);
+
+ if (subdevices.size() == 1) {
+ /* No multi device needed. */
+ return subdevices.front();
+ }
+
+ DeviceInfo info;
+ info.type = DEVICE_MULTI;
+ info.id = "MULTI";
+ info.description = "Multi Device";
+ info.num = 0;
+
+ info.has_half_images = true;
+ info.has_volume_decoupled = true;
+ info.has_osl = true;
+ info.has_profiling = true;
+
+ foreach (const DeviceInfo &device, subdevices) {
+ /* Ensure CPU device does not slow down GPU. */
+ if (device.type == DEVICE_CPU && subdevices.size() > 1) {
+ if (background) {
+ int orig_cpu_threads = (threads) ? threads : system_cpu_thread_count();
+ int cpu_threads = max(orig_cpu_threads - (subdevices.size() - 1), 0);
+
+ VLOG(1) << "CPU render threads reduced from " << orig_cpu_threads << " to " << cpu_threads
+ << ", to dedicate to GPU.";
+
+ if (cpu_threads >= 1) {
+ DeviceInfo cpu_device = device;
+ cpu_device.cpu_threads = cpu_threads;
+ info.multi_devices.push_back(cpu_device);
+ }
+ else {
+ continue;
+ }
+ }
+ else {
+ VLOG(1) << "CPU render threads disabled for interactive render.";
+ continue;
+ }
+ }
+ else {
+ info.multi_devices.push_back(device);
+ }
+
+ /* Accumulate device info. */
+ info.has_half_images &= device.has_half_images;
+ info.has_volume_decoupled &= device.has_volume_decoupled;
+ info.has_osl &= device.has_osl;
+ info.has_profiling &= device.has_profiling;
+ }
+
+ return info;
}
void Device::tag_update()
{
- free_memory();
+ free_memory();
}
void Device::free_memory()
{
- devices_initialized_mask = 0;
- cuda_devices.free_memory();
- opencl_devices.free_memory();
- cpu_devices.free_memory();
- network_devices.free_memory();
+ devices_initialized_mask = 0;
+ cuda_devices.free_memory();
+ opencl_devices.free_memory();
+ cpu_devices.free_memory();
+ network_devices.free_memory();
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/device/device.h b/intern/cycles/device/device.h
index aa0a8e434d2..15a0ceb4a19 100644
--- a/intern/cycles/device/device.h
+++ b/intern/cycles/device/device.h
@@ -40,384 +40,428 @@ class RenderTile;
/* Device Types */
enum DeviceType {
- DEVICE_NONE = 0,
- DEVICE_CPU,
- DEVICE_OPENCL,
- DEVICE_CUDA,
- DEVICE_NETWORK,
- DEVICE_MULTI
+ DEVICE_NONE = 0,
+ DEVICE_CPU,
+ DEVICE_OPENCL,
+ DEVICE_CUDA,
+ DEVICE_NETWORK,
+ DEVICE_MULTI
};
enum DeviceTypeMask {
- DEVICE_MASK_CPU = (1 << DEVICE_CPU),
- DEVICE_MASK_OPENCL = (1 << DEVICE_OPENCL),
- DEVICE_MASK_CUDA = (1 << DEVICE_CUDA),
- DEVICE_MASK_NETWORK = (1 << DEVICE_NETWORK),
- DEVICE_MASK_ALL = ~0
+ DEVICE_MASK_CPU = (1 << DEVICE_CPU),
+ DEVICE_MASK_OPENCL = (1 << DEVICE_OPENCL),
+ DEVICE_MASK_CUDA = (1 << DEVICE_CUDA),
+ DEVICE_MASK_NETWORK = (1 << DEVICE_NETWORK),
+ DEVICE_MASK_ALL = ~0
};
enum DeviceKernelStatus {
- DEVICE_KERNEL_WAITING_FOR_FEATURE_KERNEL = 0,
- DEVICE_KERNEL_FEATURE_KERNEL_AVAILABLE,
- DEVICE_KERNEL_USING_FEATURE_KERNEL,
- DEVICE_KERNEL_FEATURE_KERNEL_INVALID,
- DEVICE_KERNEL_UNKNOWN,
+ DEVICE_KERNEL_WAITING_FOR_FEATURE_KERNEL = 0,
+ DEVICE_KERNEL_FEATURE_KERNEL_AVAILABLE,
+ DEVICE_KERNEL_USING_FEATURE_KERNEL,
+ DEVICE_KERNEL_FEATURE_KERNEL_INVALID,
+ DEVICE_KERNEL_UNKNOWN,
};
#define DEVICE_MASK(type) (DeviceTypeMask)(1 << type)
class DeviceInfo {
-public:
- DeviceType type;
- string description;
- string id; /* used for user preferences, should stay fixed with changing hardware config */
- int num;
- bool display_device; /* GPU is used as a display device. */
- bool has_half_images; /* Support half-float textures. */
- bool has_volume_decoupled; /* Decoupled volume shading. */
- bool has_osl; /* Support Open Shading Language. */
- bool use_split_kernel; /* Use split or mega kernel. */
- bool has_profiling; /* Supports runtime collection of profiling info. */
- int cpu_threads;
- vector<DeviceInfo> multi_devices;
-
- DeviceInfo()
- {
- type = DEVICE_CPU;
- id = "CPU";
- num = 0;
- cpu_threads = 0;
- display_device = false;
- has_half_images = false;
- has_volume_decoupled = false;
- has_osl = false;
- use_split_kernel = false;
- has_profiling = false;
- }
-
- bool operator==(const DeviceInfo &info) {
- /* Multiple Devices with the same ID would be very bad. */
- assert(id != info.id || (type == info.type && num == info.num && description == info.description));
- return id == info.id;
- }
+ public:
+ DeviceType type;
+ string description;
+ string id; /* used for user preferences, should stay fixed with changing hardware config */
+ int num;
+ bool display_device; /* GPU is used as a display device. */
+ bool has_half_images; /* Support half-float textures. */
+ bool has_volume_decoupled; /* Decoupled volume shading. */
+ bool has_osl; /* Support Open Shading Language. */
+ bool use_split_kernel; /* Use split or mega kernel. */
+ bool has_profiling; /* Supports runtime collection of profiling info. */
+ int cpu_threads;
+ vector<DeviceInfo> multi_devices;
+
+ DeviceInfo()
+ {
+ type = DEVICE_CPU;
+ id = "CPU";
+ num = 0;
+ cpu_threads = 0;
+ display_device = false;
+ has_half_images = false;
+ has_volume_decoupled = false;
+ has_osl = false;
+ use_split_kernel = false;
+ has_profiling = false;
+ }
+
+ bool operator==(const DeviceInfo &info)
+ {
+ /* Multiple Devices with the same ID would be very bad. */
+ assert(id != info.id ||
+ (type == info.type && num == info.num && description == info.description));
+ return id == info.id;
+ }
};
class DeviceRequestedFeatures {
-public:
- /* Use experimental feature set. */
- bool experimental;
-
- /* Selective nodes compilation. */
-
- /* Identifier of a node group up to which all the nodes needs to be
- * compiled in. Nodes from higher group indices will be ignores.
- */
- int max_nodes_group;
-
- /* Features bitfield indicating which features from the requested group
- * will be compiled in. Nodes which corresponds to features which are not
- * in this bitfield will be ignored even if they're in the requested group.
- */
- int nodes_features;
-
- /* BVH/sampling kernel features. */
- bool use_hair;
- bool use_object_motion;
- bool use_camera_motion;
-
- /* Denotes whether baking functionality is needed. */
- bool use_baking;
-
- /* Use subsurface scattering materials. */
- bool use_subsurface;
-
- /* Use volume materials. */
- bool use_volume;
-
- /* Use branched integrator. */
- bool use_integrator_branched;
-
- /* Use OpenSubdiv patch evaluation */
- bool use_patch_evaluation;
-
- /* Use Transparent shadows */
- bool use_transparent;
-
- /* Use various shadow tricks, such as shadow catcher. */
- bool use_shadow_tricks;
-
- /* Per-uber shader usage flags. */
- bool use_principled;
-
- /* Denoising features. */
- bool use_denoising;
-
- /* Use raytracing in shaders. */
- bool use_shader_raytrace;
-
- /* Use true displacement */
- bool use_true_displacement;
-
- /* Use background lights */
- bool use_background_light;
-
- DeviceRequestedFeatures()
- {
- /* TODO(sergey): Find more meaningful defaults. */
- experimental = false;
- max_nodes_group = 0;
- nodes_features = 0;
- use_hair = false;
- use_object_motion = false;
- use_camera_motion = false;
- use_baking = false;
- use_subsurface = false;
- use_volume = false;
- use_integrator_branched = false;
- use_patch_evaluation = false;
- use_transparent = false;
- use_shadow_tricks = false;
- use_principled = false;
- use_denoising = false;
- use_shader_raytrace = false;
- use_true_displacement = false;
- use_background_light = false;
- }
-
- bool modified(const DeviceRequestedFeatures& requested_features)
- {
- return !(experimental == requested_features.experimental &&
- max_nodes_group == requested_features.max_nodes_group &&
- nodes_features == requested_features.nodes_features &&
- use_hair == requested_features.use_hair &&
- use_object_motion == requested_features.use_object_motion &&
- use_camera_motion == requested_features.use_camera_motion &&
- use_baking == requested_features.use_baking &&
- use_subsurface == requested_features.use_subsurface &&
- use_volume == requested_features.use_volume &&
- use_integrator_branched == requested_features.use_integrator_branched &&
- use_patch_evaluation == requested_features.use_patch_evaluation &&
- use_transparent == requested_features.use_transparent &&
- use_shadow_tricks == requested_features.use_shadow_tricks &&
- use_principled == requested_features.use_principled &&
- use_denoising == requested_features.use_denoising &&
- use_shader_raytrace == requested_features.use_shader_raytrace &&
- use_true_displacement == requested_features.use_true_displacement &&
- use_background_light == requested_features.use_background_light);
- }
-
- /* Convert the requested features structure to a build options,
- * which could then be passed to compilers.
- */
- string get_build_options() const
- {
- string build_options = "";
- if(experimental) {
- build_options += "-D__KERNEL_EXPERIMENTAL__ ";
- }
- build_options += "-D__NODES_MAX_GROUP__=" +
- string_printf("%d", max_nodes_group);
- build_options += " -D__NODES_FEATURES__=" +
- string_printf("%d", nodes_features);
- if(!use_hair) {
- build_options += " -D__NO_HAIR__";
- }
- if(!use_object_motion) {
- build_options += " -D__NO_OBJECT_MOTION__";
- }
- if(!use_camera_motion) {
- build_options += " -D__NO_CAMERA_MOTION__";
- }
- if(!use_baking) {
- build_options += " -D__NO_BAKING__";
- }
- if(!use_volume) {
- build_options += " -D__NO_VOLUME__";
- }
- if(!use_subsurface) {
- build_options += " -D__NO_SUBSURFACE__";
- }
- if(!use_integrator_branched) {
- build_options += " -D__NO_BRANCHED_PATH__";
- }
- if(!use_patch_evaluation) {
- build_options += " -D__NO_PATCH_EVAL__";
- }
- if(!use_transparent && !use_volume) {
- build_options += " -D__NO_TRANSPARENT__";
- }
- if(!use_shadow_tricks) {
- build_options += " -D__NO_SHADOW_TRICKS__";
- }
- if(!use_principled) {
- build_options += " -D__NO_PRINCIPLED__";
- }
- if(!use_denoising) {
- build_options += " -D__NO_DENOISING__";
- }
- if(!use_shader_raytrace) {
- build_options += " -D__NO_SHADER_RAYTRACE__";
- }
- return build_options;
- }
+ public:
+ /* Use experimental feature set. */
+ bool experimental;
+
+ /* Selective nodes compilation. */
+
+ /* Identifier of a node group up to which all the nodes needs to be
+ * compiled in. Nodes from higher group indices will be ignores.
+ */
+ int max_nodes_group;
+
+ /* Features bitfield indicating which features from the requested group
+ * will be compiled in. Nodes which corresponds to features which are not
+ * in this bitfield will be ignored even if they're in the requested group.
+ */
+ int nodes_features;
+
+ /* BVH/sampling kernel features. */
+ bool use_hair;
+ bool use_object_motion;
+ bool use_camera_motion;
+
+ /* Denotes whether baking functionality is needed. */
+ bool use_baking;
+
+ /* Use subsurface scattering materials. */
+ bool use_subsurface;
+
+ /* Use volume materials. */
+ bool use_volume;
+
+ /* Use branched integrator. */
+ bool use_integrator_branched;
+
+ /* Use OpenSubdiv patch evaluation */
+ bool use_patch_evaluation;
+
+ /* Use Transparent shadows */
+ bool use_transparent;
+
+ /* Use various shadow tricks, such as shadow catcher. */
+ bool use_shadow_tricks;
+
+ /* Per-uber shader usage flags. */
+ bool use_principled;
+
+ /* Denoising features. */
+ bool use_denoising;
+
+ /* Use raytracing in shaders. */
+ bool use_shader_raytrace;
+
+ /* Use true displacement */
+ bool use_true_displacement;
+
+ /* Use background lights */
+ bool use_background_light;
+
+ DeviceRequestedFeatures()
+ {
+ /* TODO(sergey): Find more meaningful defaults. */
+ experimental = false;
+ max_nodes_group = 0;
+ nodes_features = 0;
+ use_hair = false;
+ use_object_motion = false;
+ use_camera_motion = false;
+ use_baking = false;
+ use_subsurface = false;
+ use_volume = false;
+ use_integrator_branched = false;
+ use_patch_evaluation = false;
+ use_transparent = false;
+ use_shadow_tricks = false;
+ use_principled = false;
+ use_denoising = false;
+ use_shader_raytrace = false;
+ use_true_displacement = false;
+ use_background_light = false;
+ }
+
+ bool modified(const DeviceRequestedFeatures &requested_features)
+ {
+ return !(experimental == requested_features.experimental &&
+ max_nodes_group == requested_features.max_nodes_group &&
+ nodes_features == requested_features.nodes_features &&
+ use_hair == requested_features.use_hair &&
+ use_object_motion == requested_features.use_object_motion &&
+ use_camera_motion == requested_features.use_camera_motion &&
+ use_baking == requested_features.use_baking &&
+ use_subsurface == requested_features.use_subsurface &&
+ use_volume == requested_features.use_volume &&
+ use_integrator_branched == requested_features.use_integrator_branched &&
+ use_patch_evaluation == requested_features.use_patch_evaluation &&
+ use_transparent == requested_features.use_transparent &&
+ use_shadow_tricks == requested_features.use_shadow_tricks &&
+ use_principled == requested_features.use_principled &&
+ use_denoising == requested_features.use_denoising &&
+ use_shader_raytrace == requested_features.use_shader_raytrace &&
+ use_true_displacement == requested_features.use_true_displacement &&
+ use_background_light == requested_features.use_background_light);
+ }
+
+ /* Convert the requested features structure to a build options,
+ * which could then be passed to compilers.
+ */
+ string get_build_options() const
+ {
+ string build_options = "";
+ if (experimental) {
+ build_options += "-D__KERNEL_EXPERIMENTAL__ ";
+ }
+ build_options += "-D__NODES_MAX_GROUP__=" + string_printf("%d", max_nodes_group);
+ build_options += " -D__NODES_FEATURES__=" + string_printf("%d", nodes_features);
+ if (!use_hair) {
+ build_options += " -D__NO_HAIR__";
+ }
+ if (!use_object_motion) {
+ build_options += " -D__NO_OBJECT_MOTION__";
+ }
+ if (!use_camera_motion) {
+ build_options += " -D__NO_CAMERA_MOTION__";
+ }
+ if (!use_baking) {
+ build_options += " -D__NO_BAKING__";
+ }
+ if (!use_volume) {
+ build_options += " -D__NO_VOLUME__";
+ }
+ if (!use_subsurface) {
+ build_options += " -D__NO_SUBSURFACE__";
+ }
+ if (!use_integrator_branched) {
+ build_options += " -D__NO_BRANCHED_PATH__";
+ }
+ if (!use_patch_evaluation) {
+ build_options += " -D__NO_PATCH_EVAL__";
+ }
+ if (!use_transparent && !use_volume) {
+ build_options += " -D__NO_TRANSPARENT__";
+ }
+ if (!use_shadow_tricks) {
+ build_options += " -D__NO_SHADOW_TRICKS__";
+ }
+ if (!use_principled) {
+ build_options += " -D__NO_PRINCIPLED__";
+ }
+ if (!use_denoising) {
+ build_options += " -D__NO_DENOISING__";
+ }
+ if (!use_shader_raytrace) {
+ build_options += " -D__NO_SHADER_RAYTRACE__";
+ }
+ return build_options;
+ }
};
-std::ostream& operator <<(std::ostream &os,
- const DeviceRequestedFeatures& requested_features);
+std::ostream &operator<<(std::ostream &os, const DeviceRequestedFeatures &requested_features);
/* Device */
struct DeviceDrawParams {
- function<void()> bind_display_space_shader_cb;
- function<void()> unbind_display_space_shader_cb;
+ function<void()> bind_display_space_shader_cb;
+ function<void()> unbind_display_space_shader_cb;
};
class Device {
- friend class device_sub_ptr;
-protected:
- enum {
- FALLBACK_SHADER_STATUS_NONE = 0,
- FALLBACK_SHADER_STATUS_ERROR,
- FALLBACK_SHADER_STATUS_SUCCESS,
- };
-
- Device(DeviceInfo& info_, Stats &stats_, Profiler &profiler_, bool background) : background(background),
- vertex_buffer(0),
- fallback_status(FALLBACK_SHADER_STATUS_NONE), fallback_shader_program(0),
- info(info_), stats(stats_), profiler(profiler_) {}
-
- bool background;
- string error_msg;
-
- /* used for real time display */
- unsigned int vertex_buffer;
- int fallback_status, fallback_shader_program;
- int image_texture_location, fullscreen_location;
-
- bool bind_fallback_display_space_shader(const float width, const float height);
-
- virtual device_ptr mem_alloc_sub_ptr(device_memory& /*mem*/, int /*offset*/, int /*size*/)
- {
- /* Only required for devices that implement denoising. */
- assert(false);
- return (device_ptr) 0;
- }
- virtual void mem_free_sub_ptr(device_ptr /*ptr*/) {};
-
-public:
- virtual ~Device();
-
- /* info */
- DeviceInfo info;
- virtual const string& error_message() { return error_msg; }
- bool have_error() { return !error_message().empty(); }
- virtual void set_error(const string& error)
- {
- if(!have_error()) {
- error_msg = error;
- }
- fprintf(stderr, "%s\n", error.c_str());
- fflush(stderr);
- }
- virtual bool show_samples() const { return false; }
- virtual BVHLayoutMask get_bvh_layout_mask() const = 0;
-
- /* statistics */
- Stats &stats;
- Profiler &profiler;
-
- /* memory alignment */
- virtual int mem_sub_ptr_alignment() { return MIN_ALIGNMENT_CPU_DATA_TYPES; }
-
- /* constant memory */
- virtual void const_copy_to(const char *name, void *host, size_t size) = 0;
-
- /* open shading language, only for CPU device */
- virtual void *osl_memory() { return NULL; }
-
- /* load/compile kernels, must be called before adding tasks */
- virtual bool load_kernels(
- const DeviceRequestedFeatures& /*requested_features*/)
- { return true; }
-
- /* Wait for device to become available to upload data and receive tasks
- * This method is used by the OpenCL device to load the
- * optimized kernels or when not (yet) available load the
- * generic kernels (only during foreground rendering) */
- virtual bool wait_for_availability(
- const DeviceRequestedFeatures& /*requested_features*/)
- { return true; }
- /* Check if there are 'better' kernels available to be used
- * We can switch over to these kernels
- * This method is used to determine if we can switch the preview kernels
- * to regular kernels */
- virtual DeviceKernelStatus get_active_kernel_switch_state()
- { return DEVICE_KERNEL_USING_FEATURE_KERNEL; }
-
- /* tasks */
- virtual int get_split_task_count(DeviceTask& task) = 0;
- virtual void task_add(DeviceTask& task) = 0;
- virtual void task_wait() = 0;
- virtual void task_cancel() = 0;
-
- /* opengl drawing */
- virtual void draw_pixels(device_memory& mem, int y,
- int w, int h, int width, int height,
- int dx, int dy, int dw, int dh,
- bool transparent, const DeviceDrawParams &draw_params);
+ friend class device_sub_ptr;
+
+ protected:
+ enum {
+ FALLBACK_SHADER_STATUS_NONE = 0,
+ FALLBACK_SHADER_STATUS_ERROR,
+ FALLBACK_SHADER_STATUS_SUCCESS,
+ };
+
+ Device(DeviceInfo &info_, Stats &stats_, Profiler &profiler_, bool background)
+ : background(background),
+ vertex_buffer(0),
+ fallback_status(FALLBACK_SHADER_STATUS_NONE),
+ fallback_shader_program(0),
+ info(info_),
+ stats(stats_),
+ profiler(profiler_)
+ {
+ }
+
+ bool background;
+ string error_msg;
+
+ /* used for real time display */
+ unsigned int vertex_buffer;
+ int fallback_status, fallback_shader_program;
+ int image_texture_location, fullscreen_location;
+
+ bool bind_fallback_display_space_shader(const float width, const float height);
+
+ virtual device_ptr mem_alloc_sub_ptr(device_memory & /*mem*/, int /*offset*/, int /*size*/)
+ {
+ /* Only required for devices that implement denoising. */
+ assert(false);
+ return (device_ptr)0;
+ }
+ virtual void mem_free_sub_ptr(device_ptr /*ptr*/){};
+
+ public:
+ virtual ~Device();
+
+ /* info */
+ DeviceInfo info;
+ virtual const string &error_message()
+ {
+ return error_msg;
+ }
+ bool have_error()
+ {
+ return !error_message().empty();
+ }
+ virtual void set_error(const string &error)
+ {
+ if (!have_error()) {
+ error_msg = error;
+ }
+ fprintf(stderr, "%s\n", error.c_str());
+ fflush(stderr);
+ }
+ virtual bool show_samples() const
+ {
+ return false;
+ }
+ virtual BVHLayoutMask get_bvh_layout_mask() const = 0;
+
+ /* statistics */
+ Stats &stats;
+ Profiler &profiler;
+
+ /* memory alignment */
+ virtual int mem_sub_ptr_alignment()
+ {
+ return MIN_ALIGNMENT_CPU_DATA_TYPES;
+ }
+
+ /* constant memory */
+ virtual void const_copy_to(const char *name, void *host, size_t size) = 0;
+
+ /* open shading language, only for CPU device */
+ virtual void *osl_memory()
+ {
+ return NULL;
+ }
+
+ /* load/compile kernels, must be called before adding tasks */
+ virtual bool load_kernels(const DeviceRequestedFeatures & /*requested_features*/)
+ {
+ return true;
+ }
+
+ /* Wait for device to become available to upload data and receive tasks
+ * This method is used by the OpenCL device to load the
+ * optimized kernels or when not (yet) available load the
+ * generic kernels (only during foreground rendering) */
+ virtual bool wait_for_availability(const DeviceRequestedFeatures & /*requested_features*/)
+ {
+ return true;
+ }
+ /* Check if there are 'better' kernels available to be used
+ * We can switch over to these kernels
+ * This method is used to determine if we can switch the preview kernels
+ * to regular kernels */
+ virtual DeviceKernelStatus get_active_kernel_switch_state()
+ {
+ return DEVICE_KERNEL_USING_FEATURE_KERNEL;
+ }
+
+ /* tasks */
+ virtual int get_split_task_count(DeviceTask &task) = 0;
+ virtual void task_add(DeviceTask &task) = 0;
+ virtual void task_wait() = 0;
+ virtual void task_cancel() = 0;
+
+ /* opengl drawing */
+ virtual void draw_pixels(device_memory &mem,
+ int y,
+ int w,
+ int h,
+ int width,
+ int height,
+ int dx,
+ int dy,
+ int dw,
+ int dh,
+ bool transparent,
+ const DeviceDrawParams &draw_params);
#ifdef WITH_NETWORK
- /* networking */
- void server_run();
+ /* networking */
+ void server_run();
#endif
- /* multi device */
- virtual void map_tile(Device * /*sub_device*/, RenderTile& /*tile*/) {}
- virtual int device_number(Device * /*sub_device*/) { return 0; }
- virtual void map_neighbor_tiles(Device * /*sub_device*/, RenderTile * /*tiles*/) {}
- virtual void unmap_neighbor_tiles(Device * /*sub_device*/, RenderTile * /*tiles*/) {}
-
- /* static */
- static Device *create(DeviceInfo& info, Stats &stats, Profiler& profiler, bool background = true);
-
- static DeviceType type_from_string(const char *name);
- static string string_from_type(DeviceType type);
- static vector<DeviceType> available_types();
- static vector<DeviceInfo> available_devices(uint device_type_mask = DEVICE_MASK_ALL);
- static string device_capabilities(uint device_type_mask = DEVICE_MASK_ALL);
- static DeviceInfo get_multi_device(const vector<DeviceInfo>& subdevices,
- int threads,
- bool background);
-
- /* Tag devices lists for update. */
- static void tag_update();
-
- static void free_memory();
-
-protected:
- /* Memory allocation, only accessed through device_memory. */
- friend class MultiDevice;
- friend class DeviceServer;
- friend class device_memory;
-
- virtual void mem_alloc(device_memory& mem) = 0;
- virtual void mem_copy_to(device_memory& mem) = 0;
- virtual void mem_copy_from(device_memory& mem,
- int y, int w, int h, int elem) = 0;
- virtual void mem_zero(device_memory& mem) = 0;
- virtual void mem_free(device_memory& mem) = 0;
-
-private:
- /* Indicted whether device types and devices lists were initialized. */
- static bool need_types_update, need_devices_update;
- static thread_mutex device_mutex;
- static vector<DeviceInfo> cuda_devices;
- static vector<DeviceInfo> opencl_devices;
- static vector<DeviceInfo> cpu_devices;
- static vector<DeviceInfo> network_devices;
- static uint devices_initialized_mask;
+ /* multi device */
+ virtual void map_tile(Device * /*sub_device*/, RenderTile & /*tile*/)
+ {
+ }
+ virtual int device_number(Device * /*sub_device*/)
+ {
+ return 0;
+ }
+ virtual void map_neighbor_tiles(Device * /*sub_device*/, RenderTile * /*tiles*/)
+ {
+ }
+ virtual void unmap_neighbor_tiles(Device * /*sub_device*/, RenderTile * /*tiles*/)
+ {
+ }
+
+ /* static */
+ static Device *create(DeviceInfo &info,
+ Stats &stats,
+ Profiler &profiler,
+ bool background = true);
+
+ static DeviceType type_from_string(const char *name);
+ static string string_from_type(DeviceType type);
+ static vector<DeviceType> available_types();
+ static vector<DeviceInfo> available_devices(uint device_type_mask = DEVICE_MASK_ALL);
+ static string device_capabilities(uint device_type_mask = DEVICE_MASK_ALL);
+ static DeviceInfo get_multi_device(const vector<DeviceInfo> &subdevices,
+ int threads,
+ bool background);
+
+ /* Tag devices lists for update. */
+ static void tag_update();
+
+ static void free_memory();
+
+ protected:
+ /* Memory allocation, only accessed through device_memory. */
+ friend class MultiDevice;
+ friend class DeviceServer;
+ friend class device_memory;
+
+ virtual void mem_alloc(device_memory &mem) = 0;
+ virtual void mem_copy_to(device_memory &mem) = 0;
+ virtual void mem_copy_from(device_memory &mem, int y, int w, int h, int elem) = 0;
+ virtual void mem_zero(device_memory &mem) = 0;
+ virtual void mem_free(device_memory &mem) = 0;
+
+ private:
+ /* Indicted whether device types and devices lists were initialized. */
+ static bool need_types_update, need_devices_update;
+ static thread_mutex device_mutex;
+ static vector<DeviceInfo> cuda_devices;
+ static vector<DeviceInfo> opencl_devices;
+ static vector<DeviceInfo> cpu_devices;
+ static vector<DeviceInfo> network_devices;
+ static uint devices_initialized_mask;
};
CCL_NAMESPACE_END
-#endif /* __DEVICE_H__ */
+#endif /* __DEVICE_H__ */
diff --git a/intern/cycles/device/device_cpu.cpp b/intern/cycles/device/device_cpu.cpp
index 73f1fc02b08..837a8186064 100644
--- a/intern/cycles/device/device_cpu.cpp
+++ b/intern/cycles/device/device_cpu.cpp
@@ -61,1087 +61,1183 @@ class CPUDevice;
/* Has to be outside of the class to be shared across template instantiations. */
static const char *logged_architecture = "";
-template<typename F>
-class KernelFunctions {
-public:
- KernelFunctions()
- {
- kernel = (F)NULL;
- }
-
- KernelFunctions(F kernel_default,
- F kernel_sse2,
- F kernel_sse3,
- F kernel_sse41,
- F kernel_avx,
- F kernel_avx2)
- {
- const char *architecture_name = "default";
- kernel = kernel_default;
-
- /* Silence potential warnings about unused variables
- * when compiling without some architectures. */
- (void) kernel_sse2;
- (void) kernel_sse3;
- (void) kernel_sse41;
- (void) kernel_avx;
- (void) kernel_avx2;
+template<typename F> class KernelFunctions {
+ public:
+ KernelFunctions()
+ {
+ kernel = (F)NULL;
+ }
+
+ KernelFunctions(
+ F kernel_default, F kernel_sse2, F kernel_sse3, F kernel_sse41, F kernel_avx, F kernel_avx2)
+ {
+ const char *architecture_name = "default";
+ kernel = kernel_default;
+
+ /* Silence potential warnings about unused variables
+ * when compiling without some architectures. */
+ (void)kernel_sse2;
+ (void)kernel_sse3;
+ (void)kernel_sse41;
+ (void)kernel_avx;
+ (void)kernel_avx2;
#ifdef WITH_CYCLES_OPTIMIZED_KERNEL_AVX2
- if(DebugFlags().cpu.has_avx2() && system_cpu_support_avx2()) {
- architecture_name = "AVX2";
- kernel = kernel_avx2;
- }
- else
+ if (DebugFlags().cpu.has_avx2() && system_cpu_support_avx2()) {
+ architecture_name = "AVX2";
+ kernel = kernel_avx2;
+ }
+ else
#endif
#ifdef WITH_CYCLES_OPTIMIZED_KERNEL_AVX
- if(DebugFlags().cpu.has_avx() && system_cpu_support_avx()) {
- architecture_name = "AVX";
- kernel = kernel_avx;
- }
- else
+ if (DebugFlags().cpu.has_avx() && system_cpu_support_avx()) {
+ architecture_name = "AVX";
+ kernel = kernel_avx;
+ }
+ else
#endif
#ifdef WITH_CYCLES_OPTIMIZED_KERNEL_SSE41
- if(DebugFlags().cpu.has_sse41() && system_cpu_support_sse41()) {
- architecture_name = "SSE4.1";
- kernel = kernel_sse41;
- }
- else
+ if (DebugFlags().cpu.has_sse41() && system_cpu_support_sse41()) {
+ architecture_name = "SSE4.1";
+ kernel = kernel_sse41;
+ }
+ else
#endif
#ifdef WITH_CYCLES_OPTIMIZED_KERNEL_SSE3
- if(DebugFlags().cpu.has_sse3() && system_cpu_support_sse3()) {
- architecture_name = "SSE3";
- kernel = kernel_sse3;
- }
- else
+ if (DebugFlags().cpu.has_sse3() && system_cpu_support_sse3()) {
+ architecture_name = "SSE3";
+ kernel = kernel_sse3;
+ }
+ else
#endif
#ifdef WITH_CYCLES_OPTIMIZED_KERNEL_SSE2
- if(DebugFlags().cpu.has_sse2() && system_cpu_support_sse2()) {
- architecture_name = "SSE2";
- kernel = kernel_sse2;
- }
+ if (DebugFlags().cpu.has_sse2() && system_cpu_support_sse2()) {
+ architecture_name = "SSE2";
+ kernel = kernel_sse2;
+ }
#endif
- if(strcmp(architecture_name, logged_architecture) != 0) {
- VLOG(1) << "Will be using " << architecture_name << " kernels.";
- logged_architecture = architecture_name;
- }
- }
-
- inline F operator()() const {
- assert(kernel);
- return kernel;
- }
-protected:
- F kernel;
+ if (strcmp(architecture_name, logged_architecture) != 0) {
+ VLOG(1) << "Will be using " << architecture_name << " kernels.";
+ logged_architecture = architecture_name;
+ }
+ }
+
+ inline F operator()() const
+ {
+ assert(kernel);
+ return kernel;
+ }
+
+ protected:
+ F kernel;
};
class CPUSplitKernel : public DeviceSplitKernel {
- CPUDevice *device;
-public:
- explicit CPUSplitKernel(CPUDevice *device);
-
- virtual bool enqueue_split_kernel_data_init(const KernelDimensions& dim,
- RenderTile& rtile,
- int num_global_elements,
- device_memory& kernel_globals,
- device_memory& kernel_data_,
- device_memory& split_data,
- device_memory& ray_state,
- device_memory& queue_index,
- device_memory& use_queues_flag,
- device_memory& work_pool_wgs);
-
- virtual SplitKernelFunction* get_split_kernel_function(const string& kernel_name,
- const DeviceRequestedFeatures&);
- virtual int2 split_kernel_local_size();
- virtual int2 split_kernel_global_size(device_memory& kg, device_memory& data, DeviceTask *task);
- virtual uint64_t state_buffer_size(device_memory& kg, device_memory& data, size_t num_threads);
+ CPUDevice *device;
+
+ public:
+ explicit CPUSplitKernel(CPUDevice *device);
+
+ virtual bool enqueue_split_kernel_data_init(const KernelDimensions &dim,
+ RenderTile &rtile,
+ int num_global_elements,
+ device_memory &kernel_globals,
+ device_memory &kernel_data_,
+ device_memory &split_data,
+ device_memory &ray_state,
+ device_memory &queue_index,
+ device_memory &use_queues_flag,
+ device_memory &work_pool_wgs);
+
+ virtual SplitKernelFunction *get_split_kernel_function(const string &kernel_name,
+ const DeviceRequestedFeatures &);
+ virtual int2 split_kernel_local_size();
+ virtual int2 split_kernel_global_size(device_memory &kg, device_memory &data, DeviceTask *task);
+ virtual uint64_t state_buffer_size(device_memory &kg, device_memory &data, size_t num_threads);
};
-class CPUDevice : public Device
-{
-public:
- TaskPool task_pool;
- KernelGlobals kernel_globals;
+class CPUDevice : public Device {
+ public:
+ TaskPool task_pool;
+ KernelGlobals kernel_globals;
- device_vector<TextureInfo> texture_info;
- bool need_texture_info;
+ device_vector<TextureInfo> texture_info;
+ bool need_texture_info;
#ifdef WITH_OSL
- OSLGlobals osl_globals;
+ OSLGlobals osl_globals;
#endif
- bool use_split_kernel;
-
- DeviceRequestedFeatures requested_features;
-
- KernelFunctions<void(*)(KernelGlobals *, float *, int, int, int, int, int)> path_trace_kernel;
- KernelFunctions<void(*)(KernelGlobals *, uchar4 *, float *, float, int, int, int, int)> convert_to_half_float_kernel;
- KernelFunctions<void(*)(KernelGlobals *, uchar4 *, float *, float, int, int, int, int)> convert_to_byte_kernel;
- KernelFunctions<void(*)(KernelGlobals *, uint4 *, float4 *, int, int, int, int, int)> shader_kernel;
-
- KernelFunctions<void(*)(int, TileInfo*, int, int, float*, float*, float*, float*, float*, int*, int, int)> filter_divide_shadow_kernel;
- KernelFunctions<void(*)(int, TileInfo*, int, int, int, int, float*, float*, float, int*, int, int)> filter_get_feature_kernel;
- KernelFunctions<void(*)(int, int, int, int*, float*, float*, int, int*)> filter_write_feature_kernel;
- KernelFunctions<void(*)(int, int, float*, float*, float*, float*, int*, int)> filter_detect_outliers_kernel;
- KernelFunctions<void(*)(int, int, float*, float*, float*, float*, int*, int)> filter_combine_halves_kernel;
-
- KernelFunctions<void(*)(int, int, float*, float*, float*, float*, int*, int, int, int, float, float)> filter_nlm_calc_difference_kernel;
- KernelFunctions<void(*)(float*, float*, int*, int, int)> filter_nlm_blur_kernel;
- KernelFunctions<void(*)(float*, float*, int*, int, int)> filter_nlm_calc_weight_kernel;
- KernelFunctions<void(*)(int, int, float*, float*, float*, float*, float*, int*, int, int, int)> filter_nlm_update_output_kernel;
- KernelFunctions<void(*)(float*, float*, int*, int)> filter_nlm_normalize_kernel;
-
- KernelFunctions<void(*)(float*, TileInfo*, int, int, int, float*, int*, int*, int, int, bool, int, float)> filter_construct_transform_kernel;
- KernelFunctions<void(*)(int, int, int, float*, float*, float*, int*, float*, float3*, int*, int*, int, int, int, int, bool)> filter_nlm_construct_gramian_kernel;
- KernelFunctions<void(*)(int, int, int, float*, int*, float*, float3*, int*, int)> filter_finalize_kernel;
-
- KernelFunctions<void(*)(KernelGlobals *, ccl_constant KernelData*, ccl_global void*, int, ccl_global char*,
- int, int, int, int, int, int, int, int, ccl_global int*, int,
- ccl_global char*, ccl_global unsigned int*, unsigned int, ccl_global float*)> data_init_kernel;
- unordered_map<string, KernelFunctions<void(*)(KernelGlobals*, KernelData*)> > split_kernels;
+ bool use_split_kernel;
+
+ DeviceRequestedFeatures requested_features;
+
+ KernelFunctions<void (*)(KernelGlobals *, float *, int, int, int, int, int)> path_trace_kernel;
+ KernelFunctions<void (*)(KernelGlobals *, uchar4 *, float *, float, int, int, int, int)>
+ convert_to_half_float_kernel;
+ KernelFunctions<void (*)(KernelGlobals *, uchar4 *, float *, float, int, int, int, int)>
+ convert_to_byte_kernel;
+ KernelFunctions<void (*)(KernelGlobals *, uint4 *, float4 *, int, int, int, int, int)>
+ shader_kernel;
+
+ KernelFunctions<void (*)(
+ int, TileInfo *, int, int, float *, float *, float *, float *, float *, int *, int, int)>
+ filter_divide_shadow_kernel;
+ KernelFunctions<void (*)(
+ int, TileInfo *, int, int, int, int, float *, float *, float, int *, int, int)>
+ filter_get_feature_kernel;
+ KernelFunctions<void (*)(int, int, int, int *, float *, float *, int, int *)>
+ filter_write_feature_kernel;
+ KernelFunctions<void (*)(int, int, float *, float *, float *, float *, int *, int)>
+ filter_detect_outliers_kernel;
+ KernelFunctions<void (*)(int, int, float *, float *, float *, float *, int *, int)>
+ filter_combine_halves_kernel;
+
+ KernelFunctions<void (*)(
+ int, int, float *, float *, float *, float *, int *, int, int, int, float, float)>
+ filter_nlm_calc_difference_kernel;
+ KernelFunctions<void (*)(float *, float *, int *, int, int)> filter_nlm_blur_kernel;
+ KernelFunctions<void (*)(float *, float *, int *, int, int)> filter_nlm_calc_weight_kernel;
+ KernelFunctions<void (*)(
+ int, int, float *, float *, float *, float *, float *, int *, int, int, int)>
+ filter_nlm_update_output_kernel;
+ KernelFunctions<void (*)(float *, float *, int *, int)> filter_nlm_normalize_kernel;
+
+ KernelFunctions<void (*)(
+ float *, TileInfo *, int, int, int, float *, int *, int *, int, int, bool, int, float)>
+ filter_construct_transform_kernel;
+ KernelFunctions<void (*)(int,
+ int,
+ int,
+ float *,
+ float *,
+ float *,
+ int *,
+ float *,
+ float3 *,
+ int *,
+ int *,
+ int,
+ int,
+ int,
+ int,
+ bool)>
+ filter_nlm_construct_gramian_kernel;
+ KernelFunctions<void (*)(int, int, int, float *, int *, float *, float3 *, int *, int)>
+ filter_finalize_kernel;
+
+ KernelFunctions<void (*)(KernelGlobals *,
+ ccl_constant KernelData *,
+ ccl_global void *,
+ int,
+ ccl_global char *,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ int,
+ ccl_global int *,
+ int,
+ ccl_global char *,
+ ccl_global unsigned int *,
+ unsigned int,
+ ccl_global float *)>
+ data_init_kernel;
+ unordered_map<string, KernelFunctions<void (*)(KernelGlobals *, KernelData *)>> split_kernels;
#define KERNEL_FUNCTIONS(name) \
- KERNEL_NAME_EVAL(cpu, name), \
- KERNEL_NAME_EVAL(cpu_sse2, name), \
- KERNEL_NAME_EVAL(cpu_sse3, name), \
- KERNEL_NAME_EVAL(cpu_sse41, name), \
- KERNEL_NAME_EVAL(cpu_avx, name), \
- KERNEL_NAME_EVAL(cpu_avx2, name)
-
- CPUDevice(DeviceInfo& info_, Stats &stats_, Profiler &profiler_, bool background_)
- : Device(info_, stats_, profiler_, background_),
- texture_info(this, "__texture_info", MEM_TEXTURE),
-#define REGISTER_KERNEL(name) name ## _kernel(KERNEL_FUNCTIONS(name))
- REGISTER_KERNEL(path_trace),
- REGISTER_KERNEL(convert_to_half_float),
- REGISTER_KERNEL(convert_to_byte),
- REGISTER_KERNEL(shader),
- REGISTER_KERNEL(filter_divide_shadow),
- REGISTER_KERNEL(filter_get_feature),
- REGISTER_KERNEL(filter_write_feature),
- REGISTER_KERNEL(filter_detect_outliers),
- REGISTER_KERNEL(filter_combine_halves),
- REGISTER_KERNEL(filter_nlm_calc_difference),
- REGISTER_KERNEL(filter_nlm_blur),
- REGISTER_KERNEL(filter_nlm_calc_weight),
- REGISTER_KERNEL(filter_nlm_update_output),
- REGISTER_KERNEL(filter_nlm_normalize),
- REGISTER_KERNEL(filter_construct_transform),
- REGISTER_KERNEL(filter_nlm_construct_gramian),
- REGISTER_KERNEL(filter_finalize),
- REGISTER_KERNEL(data_init)
+ KERNEL_NAME_EVAL(cpu, name), KERNEL_NAME_EVAL(cpu_sse2, name), \
+ KERNEL_NAME_EVAL(cpu_sse3, name), KERNEL_NAME_EVAL(cpu_sse41, name), \
+ KERNEL_NAME_EVAL(cpu_avx, name), KERNEL_NAME_EVAL(cpu_avx2, name)
+
+ CPUDevice(DeviceInfo &info_, Stats &stats_, Profiler &profiler_, bool background_)
+ : Device(info_, stats_, profiler_, background_),
+ texture_info(this, "__texture_info", MEM_TEXTURE),
+#define REGISTER_KERNEL(name) name##_kernel(KERNEL_FUNCTIONS(name))
+ REGISTER_KERNEL(path_trace),
+ REGISTER_KERNEL(convert_to_half_float),
+ REGISTER_KERNEL(convert_to_byte),
+ REGISTER_KERNEL(shader),
+ REGISTER_KERNEL(filter_divide_shadow),
+ REGISTER_KERNEL(filter_get_feature),
+ REGISTER_KERNEL(filter_write_feature),
+ REGISTER_KERNEL(filter_detect_outliers),
+ REGISTER_KERNEL(filter_combine_halves),
+ REGISTER_KERNEL(filter_nlm_calc_difference),
+ REGISTER_KERNEL(filter_nlm_blur),
+ REGISTER_KERNEL(filter_nlm_calc_weight),
+ REGISTER_KERNEL(filter_nlm_update_output),
+ REGISTER_KERNEL(filter_nlm_normalize),
+ REGISTER_KERNEL(filter_construct_transform),
+ REGISTER_KERNEL(filter_nlm_construct_gramian),
+ REGISTER_KERNEL(filter_finalize),
+ REGISTER_KERNEL(data_init)
#undef REGISTER_KERNEL
- {
- if(info.cpu_threads == 0) {
- info.cpu_threads = TaskScheduler::num_threads();
- }
+ {
+ if (info.cpu_threads == 0) {
+ info.cpu_threads = TaskScheduler::num_threads();
+ }
#ifdef WITH_OSL
- kernel_globals.osl = &osl_globals;
+ kernel_globals.osl = &osl_globals;
#endif
- use_split_kernel = DebugFlags().cpu.split_kernel;
- if(use_split_kernel) {
- VLOG(1) << "Will be using split kernel.";
- }
- need_texture_info = false;
-
-#define REGISTER_SPLIT_KERNEL(name) split_kernels[#name] = KernelFunctions<void(*)(KernelGlobals*, KernelData*)>(KERNEL_FUNCTIONS(name))
- REGISTER_SPLIT_KERNEL(path_init);
- REGISTER_SPLIT_KERNEL(scene_intersect);
- REGISTER_SPLIT_KERNEL(lamp_emission);
- REGISTER_SPLIT_KERNEL(do_volume);
- REGISTER_SPLIT_KERNEL(queue_enqueue);
- REGISTER_SPLIT_KERNEL(indirect_background);
- REGISTER_SPLIT_KERNEL(shader_setup);
- REGISTER_SPLIT_KERNEL(shader_sort);
- REGISTER_SPLIT_KERNEL(shader_eval);
- REGISTER_SPLIT_KERNEL(holdout_emission_blurring_pathtermination_ao);
- REGISTER_SPLIT_KERNEL(subsurface_scatter);
- REGISTER_SPLIT_KERNEL(direct_lighting);
- REGISTER_SPLIT_KERNEL(shadow_blocked_ao);
- REGISTER_SPLIT_KERNEL(shadow_blocked_dl);
- REGISTER_SPLIT_KERNEL(enqueue_inactive);
- REGISTER_SPLIT_KERNEL(next_iteration_setup);
- REGISTER_SPLIT_KERNEL(indirect_subsurface);
- REGISTER_SPLIT_KERNEL(buffer_update);
+ use_split_kernel = DebugFlags().cpu.split_kernel;
+ if (use_split_kernel) {
+ VLOG(1) << "Will be using split kernel.";
+ }
+ need_texture_info = false;
+
+#define REGISTER_SPLIT_KERNEL(name) \
+ split_kernels[#name] = KernelFunctions<void (*)(KernelGlobals *, KernelData *)>( \
+ KERNEL_FUNCTIONS(name))
+ REGISTER_SPLIT_KERNEL(path_init);
+ REGISTER_SPLIT_KERNEL(scene_intersect);
+ REGISTER_SPLIT_KERNEL(lamp_emission);
+ REGISTER_SPLIT_KERNEL(do_volume);
+ REGISTER_SPLIT_KERNEL(queue_enqueue);
+ REGISTER_SPLIT_KERNEL(indirect_background);
+ REGISTER_SPLIT_KERNEL(shader_setup);
+ REGISTER_SPLIT_KERNEL(shader_sort);
+ REGISTER_SPLIT_KERNEL(shader_eval);
+ REGISTER_SPLIT_KERNEL(holdout_emission_blurring_pathtermination_ao);
+ REGISTER_SPLIT_KERNEL(subsurface_scatter);
+ REGISTER_SPLIT_KERNEL(direct_lighting);
+ REGISTER_SPLIT_KERNEL(shadow_blocked_ao);
+ REGISTER_SPLIT_KERNEL(shadow_blocked_dl);
+ REGISTER_SPLIT_KERNEL(enqueue_inactive);
+ REGISTER_SPLIT_KERNEL(next_iteration_setup);
+ REGISTER_SPLIT_KERNEL(indirect_subsurface);
+ REGISTER_SPLIT_KERNEL(buffer_update);
#undef REGISTER_SPLIT_KERNEL
#undef KERNEL_FUNCTIONS
- }
-
- ~CPUDevice()
- {
- task_pool.stop();
- texture_info.free();
- }
-
- virtual bool show_samples() const
- {
- return (info.cpu_threads == 1);
- }
-
- virtual BVHLayoutMask get_bvh_layout_mask() const {
- BVHLayoutMask bvh_layout_mask = BVH_LAYOUT_BVH2;
- if(DebugFlags().cpu.has_sse2() && system_cpu_support_sse2()) {
- bvh_layout_mask |= BVH_LAYOUT_BVH4;
- }
- if(DebugFlags().cpu.has_avx2() && system_cpu_support_avx2()) {
- bvh_layout_mask |= BVH_LAYOUT_BVH8;
- }
+ }
+
+ ~CPUDevice()
+ {
+ task_pool.stop();
+ texture_info.free();
+ }
+
+ virtual bool show_samples() const
+ {
+ return (info.cpu_threads == 1);
+ }
+
+ virtual BVHLayoutMask get_bvh_layout_mask() const
+ {
+ BVHLayoutMask bvh_layout_mask = BVH_LAYOUT_BVH2;
+ if (DebugFlags().cpu.has_sse2() && system_cpu_support_sse2()) {
+ bvh_layout_mask |= BVH_LAYOUT_BVH4;
+ }
+ if (DebugFlags().cpu.has_avx2() && system_cpu_support_avx2()) {
+ bvh_layout_mask |= BVH_LAYOUT_BVH8;
+ }
#ifdef WITH_EMBREE
- bvh_layout_mask |= BVH_LAYOUT_EMBREE;
-#endif /* WITH_EMBREE */
- return bvh_layout_mask;
- }
-
- void load_texture_info()
- {
- if(need_texture_info) {
- texture_info.copy_to_device();
- need_texture_info = false;
- }
- }
-
- void mem_alloc(device_memory& mem)
- {
- if(mem.type == MEM_TEXTURE) {
- assert(!"mem_alloc not supported for textures.");
- }
- else {
- if(mem.name) {
- VLOG(1) << "Buffer allocate: " << mem.name << ", "
- << string_human_readable_number(mem.memory_size()) << " bytes. ("
- << string_human_readable_size(mem.memory_size()) << ")";
- }
-
- if(mem.type == MEM_DEVICE_ONLY) {
- assert(!mem.host_pointer);
- size_t alignment = MIN_ALIGNMENT_CPU_DATA_TYPES;
- void *data = util_aligned_malloc(mem.memory_size(), alignment);
- mem.device_pointer = (device_ptr)data;
- }
- else {
- mem.device_pointer = (device_ptr)mem.host_pointer;
- }
-
- mem.device_size = mem.memory_size();
- stats.mem_alloc(mem.device_size);
- }
- }
-
- void mem_copy_to(device_memory& mem)
- {
- if(mem.type == MEM_TEXTURE) {
- tex_free(mem);
- tex_alloc(mem);
- }
- else if(mem.type == MEM_PIXELS) {
- assert(!"mem_copy_to not supported for pixels.");
- }
- else {
- if(!mem.device_pointer) {
- mem_alloc(mem);
- }
-
- /* copy is no-op */
- }
- }
-
- void mem_copy_from(device_memory& /*mem*/,
- int /*y*/, int /*w*/, int /*h*/,
- int /*elem*/)
- {
- /* no-op */
- }
-
- void mem_zero(device_memory& mem)
- {
- if(!mem.device_pointer) {
- mem_alloc(mem);
- }
-
- if(mem.device_pointer) {
- memset((void*)mem.device_pointer, 0, mem.memory_size());
- }
- }
-
- void mem_free(device_memory& mem)
- {
- if(mem.type == MEM_TEXTURE) {
- tex_free(mem);
- }
- else if(mem.device_pointer) {
- if(mem.type == MEM_DEVICE_ONLY) {
- util_aligned_free((void*)mem.device_pointer);
- }
- mem.device_pointer = 0;
- stats.mem_free(mem.device_size);
- mem.device_size = 0;
- }
- }
-
- virtual device_ptr mem_alloc_sub_ptr(device_memory& mem, int offset, int /*size*/)
- {
- return (device_ptr) (((char*) mem.device_pointer) + mem.memory_elements_size(offset));
- }
-
- void const_copy_to(const char *name, void *host, size_t size)
- {
- kernel_const_copy(&kernel_globals, name, host, size);
- }
-
- void tex_alloc(device_memory& mem)
- {
- VLOG(1) << "Texture allocate: " << mem.name << ", "
- << string_human_readable_number(mem.memory_size()) << " bytes. ("
- << string_human_readable_size(mem.memory_size()) << ")";
-
- if(mem.interpolation == INTERPOLATION_NONE) {
- /* Data texture. */
- kernel_tex_copy(&kernel_globals,
- mem.name,
- mem.host_pointer,
- mem.data_size);
- }
- else {
- /* Image Texture. */
- int flat_slot = 0;
- if(string_startswith(mem.name, "__tex_image")) {
- int pos = string(mem.name).rfind("_");
- flat_slot = atoi(mem.name + pos + 1);
- }
- else {
- assert(0);
- }
-
- if(flat_slot >= texture_info.size()) {
- /* Allocate some slots in advance, to reduce amount
- * of re-allocations. */
- texture_info.resize(flat_slot + 128);
- }
-
- TextureInfo& info = texture_info[flat_slot];
- info.data = (uint64_t)mem.host_pointer;
- info.cl_buffer = 0;
- info.interpolation = mem.interpolation;
- info.extension = mem.extension;
- info.width = mem.data_width;
- info.height = mem.data_height;
- info.depth = mem.data_depth;
-
- need_texture_info = true;
- }
-
- mem.device_pointer = (device_ptr)mem.host_pointer;
- mem.device_size = mem.memory_size();
- stats.mem_alloc(mem.device_size);
- }
-
- void tex_free(device_memory& mem)
- {
- if(mem.device_pointer) {
- mem.device_pointer = 0;
- stats.mem_free(mem.device_size);
- mem.device_size = 0;
- need_texture_info = true;
- }
- }
-
- void *osl_memory()
- {
+ bvh_layout_mask |= BVH_LAYOUT_EMBREE;
+#endif /* WITH_EMBREE */
+ return bvh_layout_mask;
+ }
+
+ void load_texture_info()
+ {
+ if (need_texture_info) {
+ texture_info.copy_to_device();
+ need_texture_info = false;
+ }
+ }
+
+ void mem_alloc(device_memory &mem)
+ {
+ if (mem.type == MEM_TEXTURE) {
+ assert(!"mem_alloc not supported for textures.");
+ }
+ else {
+ if (mem.name) {
+ VLOG(1) << "Buffer allocate: " << mem.name << ", "
+ << string_human_readable_number(mem.memory_size()) << " bytes. ("
+ << string_human_readable_size(mem.memory_size()) << ")";
+ }
+
+ if (mem.type == MEM_DEVICE_ONLY) {
+ assert(!mem.host_pointer);
+ size_t alignment = MIN_ALIGNMENT_CPU_DATA_TYPES;
+ void *data = util_aligned_malloc(mem.memory_size(), alignment);
+ mem.device_pointer = (device_ptr)data;
+ }
+ else {
+ mem.device_pointer = (device_ptr)mem.host_pointer;
+ }
+
+ mem.device_size = mem.memory_size();
+ stats.mem_alloc(mem.device_size);
+ }
+ }
+
+ void mem_copy_to(device_memory &mem)
+ {
+ if (mem.type == MEM_TEXTURE) {
+ tex_free(mem);
+ tex_alloc(mem);
+ }
+ else if (mem.type == MEM_PIXELS) {
+ assert(!"mem_copy_to not supported for pixels.");
+ }
+ else {
+ if (!mem.device_pointer) {
+ mem_alloc(mem);
+ }
+
+ /* copy is no-op */
+ }
+ }
+
+ void mem_copy_from(device_memory & /*mem*/, int /*y*/, int /*w*/, int /*h*/, int /*elem*/)
+ {
+ /* no-op */
+ }
+
+ void mem_zero(device_memory &mem)
+ {
+ if (!mem.device_pointer) {
+ mem_alloc(mem);
+ }
+
+ if (mem.device_pointer) {
+ memset((void *)mem.device_pointer, 0, mem.memory_size());
+ }
+ }
+
+ void mem_free(device_memory &mem)
+ {
+ if (mem.type == MEM_TEXTURE) {
+ tex_free(mem);
+ }
+ else if (mem.device_pointer) {
+ if (mem.type == MEM_DEVICE_ONLY) {
+ util_aligned_free((void *)mem.device_pointer);
+ }
+ mem.device_pointer = 0;
+ stats.mem_free(mem.device_size);
+ mem.device_size = 0;
+ }
+ }
+
+ virtual device_ptr mem_alloc_sub_ptr(device_memory &mem, int offset, int /*size*/)
+ {
+ return (device_ptr)(((char *)mem.device_pointer) + mem.memory_elements_size(offset));
+ }
+
+ void const_copy_to(const char *name, void *host, size_t size)
+ {
+ kernel_const_copy(&kernel_globals, name, host, size);
+ }
+
+ void tex_alloc(device_memory &mem)
+ {
+ VLOG(1) << "Texture allocate: " << mem.name << ", "
+ << string_human_readable_number(mem.memory_size()) << " bytes. ("
+ << string_human_readable_size(mem.memory_size()) << ")";
+
+ if (mem.interpolation == INTERPOLATION_NONE) {
+ /* Data texture. */
+ kernel_tex_copy(&kernel_globals, mem.name, mem.host_pointer, mem.data_size);
+ }
+ else {
+ /* Image Texture. */
+ int flat_slot = 0;
+ if (string_startswith(mem.name, "__tex_image")) {
+ int pos = string(mem.name).rfind("_");
+ flat_slot = atoi(mem.name + pos + 1);
+ }
+ else {
+ assert(0);
+ }
+
+ if (flat_slot >= texture_info.size()) {
+ /* Allocate some slots in advance, to reduce amount
+ * of re-allocations. */
+ texture_info.resize(flat_slot + 128);
+ }
+
+ TextureInfo &info = texture_info[flat_slot];
+ info.data = (uint64_t)mem.host_pointer;
+ info.cl_buffer = 0;
+ info.interpolation = mem.interpolation;
+ info.extension = mem.extension;
+ info.width = mem.data_width;
+ info.height = mem.data_height;
+ info.depth = mem.data_depth;
+
+ need_texture_info = true;
+ }
+
+ mem.device_pointer = (device_ptr)mem.host_pointer;
+ mem.device_size = mem.memory_size();
+ stats.mem_alloc(mem.device_size);
+ }
+
+ void tex_free(device_memory &mem)
+ {
+ if (mem.device_pointer) {
+ mem.device_pointer = 0;
+ stats.mem_free(mem.device_size);
+ mem.device_size = 0;
+ need_texture_info = true;
+ }
+ }
+
+ void *osl_memory()
+ {
#ifdef WITH_OSL
- return &osl_globals;
+ return &osl_globals;
#else
- return NULL;
+ return NULL;
#endif
- }
-
- void thread_run(DeviceTask *task)
- {
- if(task->type == DeviceTask::RENDER) {
- thread_render(*task);
- }
- else if(task->type == DeviceTask::FILM_CONVERT)
- thread_film_convert(*task);
- else if(task->type == DeviceTask::SHADER)
- thread_shader(*task);
- }
-
- class CPUDeviceTask : public DeviceTask {
- public:
- CPUDeviceTask(CPUDevice *device, DeviceTask& task)
- : DeviceTask(task)
- {
- run = function_bind(&CPUDevice::thread_run, device, this);
- }
- };
-
- bool denoising_non_local_means(device_ptr image_ptr, device_ptr guide_ptr, device_ptr variance_ptr, device_ptr out_ptr,
- DenoisingTask *task)
- {
- ProfilingHelper profiling(task->profiler, PROFILING_DENOISING_NON_LOCAL_MEANS);
-
- int4 rect = task->rect;
- int r = task->nlm_state.r;
- int f = task->nlm_state.f;
- float a = task->nlm_state.a;
- float k_2 = task->nlm_state.k_2;
-
- int w = align_up(rect.z-rect.x, 4);
- int h = rect.w-rect.y;
- int stride = task->buffer.stride;
- int channel_offset = task->nlm_state.is_color? task->buffer.pass_stride : 0;
-
- float *temporary_mem = (float*) task->buffer.temporary_mem.device_pointer;
- float *blurDifference = temporary_mem;
- float *difference = temporary_mem + task->buffer.pass_stride;
- float *weightAccum = temporary_mem + 2*task->buffer.pass_stride;
-
- memset(weightAccum, 0, sizeof(float)*w*h);
- memset((float*) out_ptr, 0, sizeof(float)*w*h);
-
- for(int i = 0; i < (2*r+1)*(2*r+1); i++) {
- int dy = i / (2*r+1) - r;
- int dx = i % (2*r+1) - r;
-
- int local_rect[4] = {max(0, -dx), max(0, -dy), rect.z-rect.x - max(0, dx), rect.w-rect.y - max(0, dy)};
- filter_nlm_calc_difference_kernel()(dx, dy,
- (float*) guide_ptr,
- (float*) variance_ptr,
- NULL,
- difference,
- local_rect,
- w, channel_offset,
- 0, a, k_2);
-
- filter_nlm_blur_kernel() (difference, blurDifference, local_rect, w, f);
- filter_nlm_calc_weight_kernel()(blurDifference, difference, local_rect, w, f);
- filter_nlm_blur_kernel() (difference, blurDifference, local_rect, w, f);
-
- filter_nlm_update_output_kernel()(dx, dy,
- blurDifference,
- (float*) image_ptr,
- difference,
- (float*) out_ptr,
- weightAccum,
- local_rect,
- channel_offset,
- stride, f);
- }
-
- int local_rect[4] = {0, 0, rect.z-rect.x, rect.w-rect.y};
- filter_nlm_normalize_kernel()((float*) out_ptr, weightAccum, local_rect, w);
-
- return true;
- }
-
- bool denoising_construct_transform(DenoisingTask *task)
- {
- ProfilingHelper profiling(task->profiler, PROFILING_DENOISING_CONSTRUCT_TRANSFORM);
-
- for(int y = 0; y < task->filter_area.w; y++) {
- for(int x = 0; x < task->filter_area.z; x++) {
- filter_construct_transform_kernel()((float*) task->buffer.mem.device_pointer,
- task->tile_info,
- x + task->filter_area.x,
- y + task->filter_area.y,
- y*task->filter_area.z + x,
- (float*) task->storage.transform.device_pointer,
- (int*) task->storage.rank.device_pointer,
- &task->rect.x,
- task->buffer.pass_stride,
- task->buffer.frame_stride,
- task->buffer.use_time,
- task->radius,
- task->pca_threshold);
- }
- }
- return true;
- }
-
- bool denoising_accumulate(device_ptr color_ptr,
- device_ptr color_variance_ptr,
- device_ptr scale_ptr,
- int frame,
- DenoisingTask *task)
- {
- ProfilingHelper profiling(task->profiler, PROFILING_DENOISING_RECONSTRUCT);
-
- float *temporary_mem = (float*) task->buffer.temporary_mem.device_pointer;
- float *difference = temporary_mem;
- float *blurDifference = temporary_mem + task->buffer.pass_stride;
-
- int r = task->radius;
- int frame_offset = frame * task->buffer.frame_stride;
- for(int i = 0; i < (2*r+1)*(2*r+1); i++) {
- int dy = i / (2*r+1) - r;
- int dx = i % (2*r+1) - r;
-
- int local_rect[4] = {max(0, -dx), max(0, -dy),
- task->reconstruction_state.source_w - max(0, dx),
- task->reconstruction_state.source_h - max(0, dy)};
- filter_nlm_calc_difference_kernel()(dx, dy,
- (float*) color_ptr,
- (float*) color_variance_ptr,
- (float*) scale_ptr,
- difference,
- local_rect,
- task->buffer.stride,
- task->buffer.pass_stride,
- frame_offset,
- 1.0f,
- task->nlm_k_2);
- filter_nlm_blur_kernel()(difference, blurDifference, local_rect, task->buffer.stride, 4);
- filter_nlm_calc_weight_kernel()(blurDifference, difference, local_rect, task->buffer.stride, 4);
- filter_nlm_blur_kernel()(difference, blurDifference, local_rect, task->buffer.stride, 4);
- filter_nlm_construct_gramian_kernel()(dx, dy,
- task->tile_info->frames[frame],
- blurDifference,
- (float*) task->buffer.mem.device_pointer,
- (float*) task->storage.transform.device_pointer,
- (int*) task->storage.rank.device_pointer,
- (float*) task->storage.XtWX.device_pointer,
- (float3*) task->storage.XtWY.device_pointer,
- local_rect,
- &task->reconstruction_state.filter_window.x,
- task->buffer.stride,
- 4,
- task->buffer.pass_stride,
- frame_offset,
- task->buffer.use_time);
- }
-
- return true;
- }
-
- bool denoising_solve(device_ptr output_ptr,
- DenoisingTask *task)
- {
- for(int y = 0; y < task->filter_area.w; y++) {
- for(int x = 0; x < task->filter_area.z; x++) {
- filter_finalize_kernel()(x,
- y,
- y*task->filter_area.z + x,
- (float*) output_ptr,
- (int*) task->storage.rank.device_pointer,
- (float*) task->storage.XtWX.device_pointer,
- (float3*) task->storage.XtWY.device_pointer,
- &task->reconstruction_state.buffer_params.x,
- task->render_buffer.samples);
- }
- }
- return true;
- }
-
- bool denoising_combine_halves(device_ptr a_ptr, device_ptr b_ptr,
- device_ptr mean_ptr, device_ptr variance_ptr,
- int r, int4 rect, DenoisingTask *task)
- {
- ProfilingHelper profiling(task->profiler, PROFILING_DENOISING_COMBINE_HALVES);
-
- for(int y = rect.y; y < rect.w; y++) {
- for(int x = rect.x; x < rect.z; x++) {
- filter_combine_halves_kernel()(x, y,
- (float*) mean_ptr,
- (float*) variance_ptr,
- (float*) a_ptr,
- (float*) b_ptr,
- &rect.x,
- r);
- }
- }
- return true;
- }
-
- bool denoising_divide_shadow(device_ptr a_ptr, device_ptr b_ptr,
- device_ptr sample_variance_ptr, device_ptr sv_variance_ptr,
- device_ptr buffer_variance_ptr, DenoisingTask *task)
- {
- ProfilingHelper profiling(task->profiler, PROFILING_DENOISING_DIVIDE_SHADOW);
-
- for(int y = task->rect.y; y < task->rect.w; y++) {
- for(int x = task->rect.x; x < task->rect.z; x++) {
- filter_divide_shadow_kernel()(task->render_buffer.samples,
- task->tile_info,
- x, y,
- (float*) a_ptr,
- (float*) b_ptr,
- (float*) sample_variance_ptr,
- (float*) sv_variance_ptr,
- (float*) buffer_variance_ptr,
- &task->rect.x,
- task->render_buffer.pass_stride,
- task->render_buffer.offset);
- }
- }
- return true;
- }
-
- bool denoising_get_feature(int mean_offset,
- int variance_offset,
- device_ptr mean_ptr,
- device_ptr variance_ptr,
- float scale,
- DenoisingTask *task)
- {
- ProfilingHelper profiling(task->profiler, PROFILING_DENOISING_GET_FEATURE);
-
- for(int y = task->rect.y; y < task->rect.w; y++) {
- for(int x = task->rect.x; x < task->rect.z; x++) {
- filter_get_feature_kernel()(task->render_buffer.samples,
- task->tile_info,
- mean_offset,
- variance_offset,
- x, y,
- (float*) mean_ptr,
- (float*) variance_ptr,
- scale,
- &task->rect.x,
- task->render_buffer.pass_stride,
- task->render_buffer.offset);
- }
- }
- return true;
- }
-
- bool denoising_write_feature(int out_offset,
- device_ptr from_ptr,
- device_ptr buffer_ptr,
- DenoisingTask *task)
- {
- for(int y = 0; y < task->filter_area.w; y++) {
- for(int x = 0; x < task->filter_area.z; x++) {
- filter_write_feature_kernel()(task->render_buffer.samples,
- x + task->filter_area.x,
- y + task->filter_area.y,
- &task->reconstruction_state.buffer_params.x,
- (float*) from_ptr,
- (float*) buffer_ptr,
- out_offset,
- &task->rect.x);
- }
- }
- return true;
- }
-
- bool denoising_detect_outliers(device_ptr image_ptr,
- device_ptr variance_ptr,
- device_ptr depth_ptr,
- device_ptr output_ptr,
- DenoisingTask *task)
- {
- ProfilingHelper profiling(task->profiler, PROFILING_DENOISING_DETECT_OUTLIERS);
-
- for(int y = task->rect.y; y < task->rect.w; y++) {
- for(int x = task->rect.x; x < task->rect.z; x++) {
- filter_detect_outliers_kernel()(x, y,
- (float*) image_ptr,
- (float*) variance_ptr,
- (float*) depth_ptr,
- (float*) output_ptr,
- &task->rect.x,
- task->buffer.pass_stride);
- }
- }
- return true;
- }
-
- void path_trace(DeviceTask &task, RenderTile &tile, KernelGlobals *kg)
- {
- const bool use_coverage = kernel_data.film.cryptomatte_passes & CRYPT_ACCURATE;
-
- scoped_timer timer(&tile.buffers->render_time);
-
- Coverage coverage(kg, tile);
- if(use_coverage) {
- coverage.init_path_trace();
- }
-
- float *render_buffer = (float*)tile.buffer;
- int start_sample = tile.start_sample;
- int end_sample = tile.start_sample + tile.num_samples;
-
- /* Needed for Embree. */
- SIMD_SET_FLUSH_TO_ZERO;
-
- for(int sample = start_sample; sample < end_sample; sample++) {
- if(task.get_cancel() || task_pool.canceled()) {
- if(task.need_finish_queue == false)
- break;
- }
-
- for(int y = tile.y; y < tile.y + tile.h; y++) {
- for(int x = tile.x; x < tile.x + tile.w; x++) {
- if(use_coverage) {
- coverage.init_pixel(x, y);
- }
- path_trace_kernel()(kg, render_buffer,
- sample, x, y, tile.offset, tile.stride);
- }
- }
-
- tile.sample = sample + 1;
-
- task.update_progress(&tile, tile.w*tile.h);
- }
- if(use_coverage) {
- coverage.finalize();
- }
- }
-
- void denoise(DenoisingTask& denoising, RenderTile &tile)
- {
- ProfilingHelper profiling(denoising.profiler, PROFILING_DENOISING);
-
- tile.sample = tile.start_sample + tile.num_samples;
-
- denoising.functions.construct_transform = function_bind(&CPUDevice::denoising_construct_transform, this, &denoising);
- denoising.functions.accumulate = function_bind(&CPUDevice::denoising_accumulate, this, _1, _2, _3, _4, &denoising);
- denoising.functions.solve = function_bind(&CPUDevice::denoising_solve, this, _1, &denoising);
- denoising.functions.divide_shadow = function_bind(&CPUDevice::denoising_divide_shadow, this, _1, _2, _3, _4, _5, &denoising);
- denoising.functions.non_local_means = function_bind(&CPUDevice::denoising_non_local_means, this, _1, _2, _3, _4, &denoising);
- denoising.functions.combine_halves = function_bind(&CPUDevice::denoising_combine_halves, this, _1, _2, _3, _4, _5, _6, &denoising);
- denoising.functions.get_feature = function_bind(&CPUDevice::denoising_get_feature, this, _1, _2, _3, _4, _5, &denoising);
- denoising.functions.write_feature = function_bind(&CPUDevice::denoising_write_feature, this, _1, _2, _3, &denoising);
- denoising.functions.detect_outliers = function_bind(&CPUDevice::denoising_detect_outliers, this, _1, _2, _3, _4, &denoising);
-
- denoising.filter_area = make_int4(tile.x, tile.y, tile.w, tile.h);
- denoising.render_buffer.samples = tile.sample;
- denoising.buffer.gpu_temporary_mem = false;
-
- denoising.run_denoising(&tile);
- }
-
- void thread_render(DeviceTask& task)
- {
- if(task_pool.canceled()) {
- if(task.need_finish_queue == false)
- return;
- }
-
- /* allocate buffer for kernel globals */
- device_only_memory<KernelGlobals> kgbuffer(this, "kernel_globals");
- kgbuffer.alloc_to_device(1);
-
- KernelGlobals *kg = new ((void*) kgbuffer.device_pointer) KernelGlobals(thread_kernel_globals_init());
-
- profiler.add_state(&kg->profiler);
-
- CPUSplitKernel *split_kernel = NULL;
- if(use_split_kernel) {
- split_kernel = new CPUSplitKernel(this);
- if(!split_kernel->load_kernels(requested_features)) {
- thread_kernel_globals_free((KernelGlobals*)kgbuffer.device_pointer);
- kgbuffer.free();
- delete split_kernel;
- return;
- }
- }
-
- RenderTile tile;
- DenoisingTask denoising(this, task);
- denoising.profiler = &kg->profiler;
-
- while(task.acquire_tile(this, tile)) {
- if(tile.task == RenderTile::PATH_TRACE) {
- if(use_split_kernel) {
- device_only_memory<uchar> void_buffer(this, "void_buffer");
- split_kernel->path_trace(&task, tile, kgbuffer, void_buffer);
- }
- else {
- path_trace(task, tile, kg);
- }
- }
- else if(tile.task == RenderTile::DENOISE) {
- denoise(denoising, tile);
- task.update_progress(&tile, tile.w*tile.h);
- }
-
- task.release_tile(tile);
-
- if(task_pool.canceled()) {
- if(task.need_finish_queue == false)
- break;
- }
- }
-
- profiler.remove_state(&kg->profiler);
-
- thread_kernel_globals_free((KernelGlobals*)kgbuffer.device_pointer);
- kg->~KernelGlobals();
- kgbuffer.free();
- delete split_kernel;
- }
-
- void thread_film_convert(DeviceTask& task)
- {
- float sample_scale = 1.0f/(task.sample + 1);
-
- if(task.rgba_half) {
- for(int y = task.y; y < task.y + task.h; y++)
- for(int x = task.x; x < task.x + task.w; x++)
- convert_to_half_float_kernel()(&kernel_globals, (uchar4*)task.rgba_half, (float*)task.buffer,
- sample_scale, x, y, task.offset, task.stride);
- }
- else {
- for(int y = task.y; y < task.y + task.h; y++)
- for(int x = task.x; x < task.x + task.w; x++)
- convert_to_byte_kernel()(&kernel_globals, (uchar4*)task.rgba_byte, (float*)task.buffer,
- sample_scale, x, y, task.offset, task.stride);
-
- }
- }
-
- void thread_shader(DeviceTask& task)
- {
- KernelGlobals kg = kernel_globals;
+ }
+
+ void thread_run(DeviceTask *task)
+ {
+ if (task->type == DeviceTask::RENDER) {
+ thread_render(*task);
+ }
+ else if (task->type == DeviceTask::FILM_CONVERT)
+ thread_film_convert(*task);
+ else if (task->type == DeviceTask::SHADER)
+ thread_shader(*task);
+ }
+
+ class CPUDeviceTask : public DeviceTask {
+ public:
+ CPUDeviceTask(CPUDevice *device, DeviceTask &task) : DeviceTask(task)
+ {
+ run = function_bind(&CPUDevice::thread_run, device, this);
+ }
+ };
+
+ bool denoising_non_local_means(device_ptr image_ptr,
+ device_ptr guide_ptr,
+ device_ptr variance_ptr,
+ device_ptr out_ptr,
+ DenoisingTask *task)
+ {
+ ProfilingHelper profiling(task->profiler, PROFILING_DENOISING_NON_LOCAL_MEANS);
+
+ int4 rect = task->rect;
+ int r = task->nlm_state.r;
+ int f = task->nlm_state.f;
+ float a = task->nlm_state.a;
+ float k_2 = task->nlm_state.k_2;
+
+ int w = align_up(rect.z - rect.x, 4);
+ int h = rect.w - rect.y;
+ int stride = task->buffer.stride;
+ int channel_offset = task->nlm_state.is_color ? task->buffer.pass_stride : 0;
+
+ float *temporary_mem = (float *)task->buffer.temporary_mem.device_pointer;
+ float *blurDifference = temporary_mem;
+ float *difference = temporary_mem + task->buffer.pass_stride;
+ float *weightAccum = temporary_mem + 2 * task->buffer.pass_stride;
+
+ memset(weightAccum, 0, sizeof(float) * w * h);
+ memset((float *)out_ptr, 0, sizeof(float) * w * h);
+
+ for (int i = 0; i < (2 * r + 1) * (2 * r + 1); i++) {
+ int dy = i / (2 * r + 1) - r;
+ int dx = i % (2 * r + 1) - r;
+
+ int local_rect[4] = {
+ max(0, -dx), max(0, -dy), rect.z - rect.x - max(0, dx), rect.w - rect.y - max(0, dy)};
+ filter_nlm_calc_difference_kernel()(dx,
+ dy,
+ (float *)guide_ptr,
+ (float *)variance_ptr,
+ NULL,
+ difference,
+ local_rect,
+ w,
+ channel_offset,
+ 0,
+ a,
+ k_2);
+
+ filter_nlm_blur_kernel()(difference, blurDifference, local_rect, w, f);
+ filter_nlm_calc_weight_kernel()(blurDifference, difference, local_rect, w, f);
+ filter_nlm_blur_kernel()(difference, blurDifference, local_rect, w, f);
+
+ filter_nlm_update_output_kernel()(dx,
+ dy,
+ blurDifference,
+ (float *)image_ptr,
+ difference,
+ (float *)out_ptr,
+ weightAccum,
+ local_rect,
+ channel_offset,
+ stride,
+ f);
+ }
+
+ int local_rect[4] = {0, 0, rect.z - rect.x, rect.w - rect.y};
+ filter_nlm_normalize_kernel()((float *)out_ptr, weightAccum, local_rect, w);
+
+ return true;
+ }
+
+ bool denoising_construct_transform(DenoisingTask *task)
+ {
+ ProfilingHelper profiling(task->profiler, PROFILING_DENOISING_CONSTRUCT_TRANSFORM);
+
+ for (int y = 0; y < task->filter_area.w; y++) {
+ for (int x = 0; x < task->filter_area.z; x++) {
+ filter_construct_transform_kernel()((float *)task->buffer.mem.device_pointer,
+ task->tile_info,
+ x + task->filter_area.x,
+ y + task->filter_area.y,
+ y * task->filter_area.z + x,
+ (float *)task->storage.transform.device_pointer,
+ (int *)task->storage.rank.device_pointer,
+ &task->rect.x,
+ task->buffer.pass_stride,
+ task->buffer.frame_stride,
+ task->buffer.use_time,
+ task->radius,
+ task->pca_threshold);
+ }
+ }
+ return true;
+ }
+
+ bool denoising_accumulate(device_ptr color_ptr,
+ device_ptr color_variance_ptr,
+ device_ptr scale_ptr,
+ int frame,
+ DenoisingTask *task)
+ {
+ ProfilingHelper profiling(task->profiler, PROFILING_DENOISING_RECONSTRUCT);
+
+ float *temporary_mem = (float *)task->buffer.temporary_mem.device_pointer;
+ float *difference = temporary_mem;
+ float *blurDifference = temporary_mem + task->buffer.pass_stride;
+
+ int r = task->radius;
+ int frame_offset = frame * task->buffer.frame_stride;
+ for (int i = 0; i < (2 * r + 1) * (2 * r + 1); i++) {
+ int dy = i / (2 * r + 1) - r;
+ int dx = i % (2 * r + 1) - r;
+
+ int local_rect[4] = {max(0, -dx),
+ max(0, -dy),
+ task->reconstruction_state.source_w - max(0, dx),
+ task->reconstruction_state.source_h - max(0, dy)};
+ filter_nlm_calc_difference_kernel()(dx,
+ dy,
+ (float *)color_ptr,
+ (float *)color_variance_ptr,
+ (float *)scale_ptr,
+ difference,
+ local_rect,
+ task->buffer.stride,
+ task->buffer.pass_stride,
+ frame_offset,
+ 1.0f,
+ task->nlm_k_2);
+ filter_nlm_blur_kernel()(difference, blurDifference, local_rect, task->buffer.stride, 4);
+ filter_nlm_calc_weight_kernel()(
+ blurDifference, difference, local_rect, task->buffer.stride, 4);
+ filter_nlm_blur_kernel()(difference, blurDifference, local_rect, task->buffer.stride, 4);
+ filter_nlm_construct_gramian_kernel()(dx,
+ dy,
+ task->tile_info->frames[frame],
+ blurDifference,
+ (float *)task->buffer.mem.device_pointer,
+ (float *)task->storage.transform.device_pointer,
+ (int *)task->storage.rank.device_pointer,
+ (float *)task->storage.XtWX.device_pointer,
+ (float3 *)task->storage.XtWY.device_pointer,
+ local_rect,
+ &task->reconstruction_state.filter_window.x,
+ task->buffer.stride,
+ 4,
+ task->buffer.pass_stride,
+ frame_offset,
+ task->buffer.use_time);
+ }
+
+ return true;
+ }
+
+ bool denoising_solve(device_ptr output_ptr, DenoisingTask *task)
+ {
+ for (int y = 0; y < task->filter_area.w; y++) {
+ for (int x = 0; x < task->filter_area.z; x++) {
+ filter_finalize_kernel()(x,
+ y,
+ y * task->filter_area.z + x,
+ (float *)output_ptr,
+ (int *)task->storage.rank.device_pointer,
+ (float *)task->storage.XtWX.device_pointer,
+ (float3 *)task->storage.XtWY.device_pointer,
+ &task->reconstruction_state.buffer_params.x,
+ task->render_buffer.samples);
+ }
+ }
+ return true;
+ }
+
+ bool denoising_combine_halves(device_ptr a_ptr,
+ device_ptr b_ptr,
+ device_ptr mean_ptr,
+ device_ptr variance_ptr,
+ int r,
+ int4 rect,
+ DenoisingTask *task)
+ {
+ ProfilingHelper profiling(task->profiler, PROFILING_DENOISING_COMBINE_HALVES);
+
+ for (int y = rect.y; y < rect.w; y++) {
+ for (int x = rect.x; x < rect.z; x++) {
+ filter_combine_halves_kernel()(x,
+ y,
+ (float *)mean_ptr,
+ (float *)variance_ptr,
+ (float *)a_ptr,
+ (float *)b_ptr,
+ &rect.x,
+ r);
+ }
+ }
+ return true;
+ }
+
+ bool denoising_divide_shadow(device_ptr a_ptr,
+ device_ptr b_ptr,
+ device_ptr sample_variance_ptr,
+ device_ptr sv_variance_ptr,
+ device_ptr buffer_variance_ptr,
+ DenoisingTask *task)
+ {
+ ProfilingHelper profiling(task->profiler, PROFILING_DENOISING_DIVIDE_SHADOW);
+
+ for (int y = task->rect.y; y < task->rect.w; y++) {
+ for (int x = task->rect.x; x < task->rect.z; x++) {
+ filter_divide_shadow_kernel()(task->render_buffer.samples,
+ task->tile_info,
+ x,
+ y,
+ (float *)a_ptr,
+ (float *)b_ptr,
+ (float *)sample_variance_ptr,
+ (float *)sv_variance_ptr,
+ (float *)buffer_variance_ptr,
+ &task->rect.x,
+ task->render_buffer.pass_stride,
+ task->render_buffer.offset);
+ }
+ }
+ return true;
+ }
+
+ bool denoising_get_feature(int mean_offset,
+ int variance_offset,
+ device_ptr mean_ptr,
+ device_ptr variance_ptr,
+ float scale,
+ DenoisingTask *task)
+ {
+ ProfilingHelper profiling(task->profiler, PROFILING_DENOISING_GET_FEATURE);
+
+ for (int y = task->rect.y; y < task->rect.w; y++) {
+ for (int x = task->rect.x; x < task->rect.z; x++) {
+ filter_get_feature_kernel()(task->render_buffer.samples,
+ task->tile_info,
+ mean_offset,
+ variance_offset,
+ x,
+ y,
+ (float *)mean_ptr,
+ (float *)variance_ptr,
+ scale,
+ &task->rect.x,
+ task->render_buffer.pass_stride,
+ task->render_buffer.offset);
+ }
+ }
+ return true;
+ }
+
+ bool denoising_write_feature(int out_offset,
+ device_ptr from_ptr,
+ device_ptr buffer_ptr,
+ DenoisingTask *task)
+ {
+ for (int y = 0; y < task->filter_area.w; y++) {
+ for (int x = 0; x < task->filter_area.z; x++) {
+ filter_write_feature_kernel()(task->render_buffer.samples,
+ x + task->filter_area.x,
+ y + task->filter_area.y,
+ &task->reconstruction_state.buffer_params.x,
+ (float *)from_ptr,
+ (float *)buffer_ptr,
+ out_offset,
+ &task->rect.x);
+ }
+ }
+ return true;
+ }
+
+ bool denoising_detect_outliers(device_ptr image_ptr,
+ device_ptr variance_ptr,
+ device_ptr depth_ptr,
+ device_ptr output_ptr,
+ DenoisingTask *task)
+ {
+ ProfilingHelper profiling(task->profiler, PROFILING_DENOISING_DETECT_OUTLIERS);
+
+ for (int y = task->rect.y; y < task->rect.w; y++) {
+ for (int x = task->rect.x; x < task->rect.z; x++) {
+ filter_detect_outliers_kernel()(x,
+ y,
+ (float *)image_ptr,
+ (float *)variance_ptr,
+ (float *)depth_ptr,
+ (float *)output_ptr,
+ &task->rect.x,
+ task->buffer.pass_stride);
+ }
+ }
+ return true;
+ }
+
+ void path_trace(DeviceTask &task, RenderTile &tile, KernelGlobals *kg)
+ {
+ const bool use_coverage = kernel_data.film.cryptomatte_passes & CRYPT_ACCURATE;
+
+ scoped_timer timer(&tile.buffers->render_time);
+
+ Coverage coverage(kg, tile);
+ if (use_coverage) {
+ coverage.init_path_trace();
+ }
+
+ float *render_buffer = (float *)tile.buffer;
+ int start_sample = tile.start_sample;
+ int end_sample = tile.start_sample + tile.num_samples;
+
+ /* Needed for Embree. */
+ SIMD_SET_FLUSH_TO_ZERO;
+
+ for (int sample = start_sample; sample < end_sample; sample++) {
+ if (task.get_cancel() || task_pool.canceled()) {
+ if (task.need_finish_queue == false)
+ break;
+ }
+
+ for (int y = tile.y; y < tile.y + tile.h; y++) {
+ for (int x = tile.x; x < tile.x + tile.w; x++) {
+ if (use_coverage) {
+ coverage.init_pixel(x, y);
+ }
+ path_trace_kernel()(kg, render_buffer, sample, x, y, tile.offset, tile.stride);
+ }
+ }
+
+ tile.sample = sample + 1;
+
+ task.update_progress(&tile, tile.w * tile.h);
+ }
+ if (use_coverage) {
+ coverage.finalize();
+ }
+ }
+
+ void denoise(DenoisingTask &denoising, RenderTile &tile)
+ {
+ ProfilingHelper profiling(denoising.profiler, PROFILING_DENOISING);
+
+ tile.sample = tile.start_sample + tile.num_samples;
+
+ denoising.functions.construct_transform = function_bind(
+ &CPUDevice::denoising_construct_transform, this, &denoising);
+ denoising.functions.accumulate = function_bind(
+ &CPUDevice::denoising_accumulate, this, _1, _2, _3, _4, &denoising);
+ denoising.functions.solve = function_bind(&CPUDevice::denoising_solve, this, _1, &denoising);
+ denoising.functions.divide_shadow = function_bind(
+ &CPUDevice::denoising_divide_shadow, this, _1, _2, _3, _4, _5, &denoising);
+ denoising.functions.non_local_means = function_bind(
+ &CPUDevice::denoising_non_local_means, this, _1, _2, _3, _4, &denoising);
+ denoising.functions.combine_halves = function_bind(
+ &CPUDevice::denoising_combine_halves, this, _1, _2, _3, _4, _5, _6, &denoising);
+ denoising.functions.get_feature = function_bind(
+ &CPUDevice::denoising_get_feature, this, _1, _2, _3, _4, _5, &denoising);
+ denoising.functions.write_feature = function_bind(
+ &CPUDevice::denoising_write_feature, this, _1, _2, _3, &denoising);
+ denoising.functions.detect_outliers = function_bind(
+ &CPUDevice::denoising_detect_outliers, this, _1, _2, _3, _4, &denoising);
+
+ denoising.filter_area = make_int4(tile.x, tile.y, tile.w, tile.h);
+ denoising.render_buffer.samples = tile.sample;
+ denoising.buffer.gpu_temporary_mem = false;
+
+ denoising.run_denoising(&tile);
+ }
+
+ void thread_render(DeviceTask &task)
+ {
+ if (task_pool.canceled()) {
+ if (task.need_finish_queue == false)
+ return;
+ }
+
+ /* allocate buffer for kernel globals */
+ device_only_memory<KernelGlobals> kgbuffer(this, "kernel_globals");
+ kgbuffer.alloc_to_device(1);
+
+ KernelGlobals *kg = new ((void *)kgbuffer.device_pointer)
+ KernelGlobals(thread_kernel_globals_init());
+
+ profiler.add_state(&kg->profiler);
+
+ CPUSplitKernel *split_kernel = NULL;
+ if (use_split_kernel) {
+ split_kernel = new CPUSplitKernel(this);
+ if (!split_kernel->load_kernels(requested_features)) {
+ thread_kernel_globals_free((KernelGlobals *)kgbuffer.device_pointer);
+ kgbuffer.free();
+ delete split_kernel;
+ return;
+ }
+ }
+
+ RenderTile tile;
+ DenoisingTask denoising(this, task);
+ denoising.profiler = &kg->profiler;
+
+ while (task.acquire_tile(this, tile)) {
+ if (tile.task == RenderTile::PATH_TRACE) {
+ if (use_split_kernel) {
+ device_only_memory<uchar> void_buffer(this, "void_buffer");
+ split_kernel->path_trace(&task, tile, kgbuffer, void_buffer);
+ }
+ else {
+ path_trace(task, tile, kg);
+ }
+ }
+ else if (tile.task == RenderTile::DENOISE) {
+ denoise(denoising, tile);
+ task.update_progress(&tile, tile.w * tile.h);
+ }
+
+ task.release_tile(tile);
+
+ if (task_pool.canceled()) {
+ if (task.need_finish_queue == false)
+ break;
+ }
+ }
+
+ profiler.remove_state(&kg->profiler);
+
+ thread_kernel_globals_free((KernelGlobals *)kgbuffer.device_pointer);
+ kg->~KernelGlobals();
+ kgbuffer.free();
+ delete split_kernel;
+ }
+
+ void thread_film_convert(DeviceTask &task)
+ {
+ float sample_scale = 1.0f / (task.sample + 1);
+
+ if (task.rgba_half) {
+ for (int y = task.y; y < task.y + task.h; y++)
+ for (int x = task.x; x < task.x + task.w; x++)
+ convert_to_half_float_kernel()(&kernel_globals,
+ (uchar4 *)task.rgba_half,
+ (float *)task.buffer,
+ sample_scale,
+ x,
+ y,
+ task.offset,
+ task.stride);
+ }
+ else {
+ for (int y = task.y; y < task.y + task.h; y++)
+ for (int x = task.x; x < task.x + task.w; x++)
+ convert_to_byte_kernel()(&kernel_globals,
+ (uchar4 *)task.rgba_byte,
+ (float *)task.buffer,
+ sample_scale,
+ x,
+ y,
+ task.offset,
+ task.stride);
+ }
+ }
+
+ void thread_shader(DeviceTask &task)
+ {
+ KernelGlobals kg = kernel_globals;
#ifdef WITH_OSL
- OSLShader::thread_init(&kg, &kernel_globals, &osl_globals);
+ OSLShader::thread_init(&kg, &kernel_globals, &osl_globals);
#endif
- for(int sample = 0; sample < task.num_samples; sample++) {
- for(int x = task.shader_x; x < task.shader_x + task.shader_w; x++)
- shader_kernel()(&kg,
- (uint4*)task.shader_input,
- (float4*)task.shader_output,
- task.shader_eval_type,
- task.shader_filter,
- x,
- task.offset,
- sample);
-
- if(task.get_cancel() || task_pool.canceled())
- break;
-
- task.update_progress(NULL);
-
- }
+ for (int sample = 0; sample < task.num_samples; sample++) {
+ for (int x = task.shader_x; x < task.shader_x + task.shader_w; x++)
+ shader_kernel()(&kg,
+ (uint4 *)task.shader_input,
+ (float4 *)task.shader_output,
+ task.shader_eval_type,
+ task.shader_filter,
+ x,
+ task.offset,
+ sample);
+
+ if (task.get_cancel() || task_pool.canceled())
+ break;
+
+ task.update_progress(NULL);
+ }
#ifdef WITH_OSL
- OSLShader::thread_free(&kg);
+ OSLShader::thread_free(&kg);
#endif
- }
-
- int get_split_task_count(DeviceTask& task)
- {
- if(task.type == DeviceTask::SHADER)
- return task.get_subtask_count(info.cpu_threads, 256);
- else
- return task.get_subtask_count(info.cpu_threads);
- }
-
- void task_add(DeviceTask& task)
- {
- /* Load texture info. */
- load_texture_info();
-
- /* split task into smaller ones */
- list<DeviceTask> tasks;
-
- if(task.type == DeviceTask::SHADER)
- task.split(tasks, info.cpu_threads, 256);
- else
- task.split(tasks, info.cpu_threads);
-
- foreach(DeviceTask& task, tasks)
- task_pool.push(new CPUDeviceTask(this, task));
- }
-
- void task_wait()
- {
- task_pool.wait_work();
- }
-
- void task_cancel()
- {
- task_pool.cancel();
- }
-
-protected:
- inline KernelGlobals thread_kernel_globals_init()
- {
- KernelGlobals kg = kernel_globals;
- kg.transparent_shadow_intersections = NULL;
- const int decoupled_count = sizeof(kg.decoupled_volume_steps) /
- sizeof(*kg.decoupled_volume_steps);
- for(int i = 0; i < decoupled_count; ++i) {
- kg.decoupled_volume_steps[i] = NULL;
- }
- kg.decoupled_volume_steps_index = 0;
- kg.coverage_asset = kg.coverage_object = kg.coverage_material = NULL;
+ }
+
+ int get_split_task_count(DeviceTask &task)
+ {
+ if (task.type == DeviceTask::SHADER)
+ return task.get_subtask_count(info.cpu_threads, 256);
+ else
+ return task.get_subtask_count(info.cpu_threads);
+ }
+
+ void task_add(DeviceTask &task)
+ {
+ /* Load texture info. */
+ load_texture_info();
+
+ /* split task into smaller ones */
+ list<DeviceTask> tasks;
+
+ if (task.type == DeviceTask::SHADER)
+ task.split(tasks, info.cpu_threads, 256);
+ else
+ task.split(tasks, info.cpu_threads);
+
+ foreach (DeviceTask &task, tasks)
+ task_pool.push(new CPUDeviceTask(this, task));
+ }
+
+ void task_wait()
+ {
+ task_pool.wait_work();
+ }
+
+ void task_cancel()
+ {
+ task_pool.cancel();
+ }
+
+ protected:
+ inline KernelGlobals thread_kernel_globals_init()
+ {
+ KernelGlobals kg = kernel_globals;
+ kg.transparent_shadow_intersections = NULL;
+ const int decoupled_count = sizeof(kg.decoupled_volume_steps) /
+ sizeof(*kg.decoupled_volume_steps);
+ for (int i = 0; i < decoupled_count; ++i) {
+ kg.decoupled_volume_steps[i] = NULL;
+ }
+ kg.decoupled_volume_steps_index = 0;
+ kg.coverage_asset = kg.coverage_object = kg.coverage_material = NULL;
#ifdef WITH_OSL
- OSLShader::thread_init(&kg, &kernel_globals, &osl_globals);
+ OSLShader::thread_init(&kg, &kernel_globals, &osl_globals);
#endif
- return kg;
- }
-
- inline void thread_kernel_globals_free(KernelGlobals *kg)
- {
- if(kg == NULL) {
- return;
- }
-
- if(kg->transparent_shadow_intersections != NULL) {
- free(kg->transparent_shadow_intersections);
- }
- const int decoupled_count = sizeof(kg->decoupled_volume_steps) /
- sizeof(*kg->decoupled_volume_steps);
- for(int i = 0; i < decoupled_count; ++i) {
- if(kg->decoupled_volume_steps[i] != NULL) {
- free(kg->decoupled_volume_steps[i]);
- }
- }
+ return kg;
+ }
+
+ inline void thread_kernel_globals_free(KernelGlobals *kg)
+ {
+ if (kg == NULL) {
+ return;
+ }
+
+ if (kg->transparent_shadow_intersections != NULL) {
+ free(kg->transparent_shadow_intersections);
+ }
+ const int decoupled_count = sizeof(kg->decoupled_volume_steps) /
+ sizeof(*kg->decoupled_volume_steps);
+ for (int i = 0; i < decoupled_count; ++i) {
+ if (kg->decoupled_volume_steps[i] != NULL) {
+ free(kg->decoupled_volume_steps[i]);
+ }
+ }
#ifdef WITH_OSL
- OSLShader::thread_free(kg);
+ OSLShader::thread_free(kg);
#endif
- }
+ }
- virtual bool load_kernels(const DeviceRequestedFeatures& requested_features_) {
- requested_features = requested_features_;
+ virtual bool load_kernels(const DeviceRequestedFeatures &requested_features_)
+ {
+ requested_features = requested_features_;
- return true;
- }
+ return true;
+ }
};
/* split kernel */
class CPUSplitKernelFunction : public SplitKernelFunction {
-public:
- CPUDevice* device;
- void (*func)(KernelGlobals *kg, KernelData *data);
-
- CPUSplitKernelFunction(CPUDevice* device) : device(device), func(NULL) {}
- ~CPUSplitKernelFunction() {}
-
- virtual bool enqueue(const KernelDimensions& dim, device_memory& kernel_globals, device_memory& data)
- {
- if(!func) {
- return false;
- }
-
- KernelGlobals *kg = (KernelGlobals*)kernel_globals.device_pointer;
- kg->global_size = make_int2(dim.global_size[0], dim.global_size[1]);
-
- for(int y = 0; y < dim.global_size[1]; y++) {
- for(int x = 0; x < dim.global_size[0]; x++) {
- kg->global_id = make_int2(x, y);
-
- func(kg, (KernelData*)data.device_pointer);
- }
- }
-
- return true;
- }
+ public:
+ CPUDevice *device;
+ void (*func)(KernelGlobals *kg, KernelData *data);
+
+ CPUSplitKernelFunction(CPUDevice *device) : device(device), func(NULL)
+ {
+ }
+ ~CPUSplitKernelFunction()
+ {
+ }
+
+ virtual bool enqueue(const KernelDimensions &dim,
+ device_memory &kernel_globals,
+ device_memory &data)
+ {
+ if (!func) {
+ return false;
+ }
+
+ KernelGlobals *kg = (KernelGlobals *)kernel_globals.device_pointer;
+ kg->global_size = make_int2(dim.global_size[0], dim.global_size[1]);
+
+ for (int y = 0; y < dim.global_size[1]; y++) {
+ for (int x = 0; x < dim.global_size[0]; x++) {
+ kg->global_id = make_int2(x, y);
+
+ func(kg, (KernelData *)data.device_pointer);
+ }
+ }
+
+ return true;
+ }
};
CPUSplitKernel::CPUSplitKernel(CPUDevice *device) : DeviceSplitKernel(device), device(device)
{
}
-bool CPUSplitKernel::enqueue_split_kernel_data_init(const KernelDimensions& dim,
- RenderTile& rtile,
+bool CPUSplitKernel::enqueue_split_kernel_data_init(const KernelDimensions &dim,
+ RenderTile &rtile,
int num_global_elements,
- device_memory& kernel_globals,
- device_memory& data,
- device_memory& split_data,
- device_memory& ray_state,
- device_memory& queue_index,
- device_memory& use_queues_flags,
- device_memory& work_pool_wgs)
+ device_memory &kernel_globals,
+ device_memory &data,
+ device_memory &split_data,
+ device_memory &ray_state,
+ device_memory &queue_index,
+ device_memory &use_queues_flags,
+ device_memory &work_pool_wgs)
{
- KernelGlobals *kg = (KernelGlobals*)kernel_globals.device_pointer;
- kg->global_size = make_int2(dim.global_size[0], dim.global_size[1]);
-
- for(int y = 0; y < dim.global_size[1]; y++) {
- for(int x = 0; x < dim.global_size[0]; x++) {
- kg->global_id = make_int2(x, y);
-
- device->data_init_kernel()((KernelGlobals*)kernel_globals.device_pointer,
- (KernelData*)data.device_pointer,
- (void*)split_data.device_pointer,
- num_global_elements,
- (char*)ray_state.device_pointer,
- rtile.start_sample,
- rtile.start_sample + rtile.num_samples,
- rtile.x,
- rtile.y,
- rtile.w,
- rtile.h,
- rtile.offset,
- rtile.stride,
- (int*)queue_index.device_pointer,
- dim.global_size[0] * dim.global_size[1],
- (char*)use_queues_flags.device_pointer,
- (uint*)work_pool_wgs.device_pointer,
- rtile.num_samples,
- (float*)rtile.buffer);
- }
- }
-
- return true;
+ KernelGlobals *kg = (KernelGlobals *)kernel_globals.device_pointer;
+ kg->global_size = make_int2(dim.global_size[0], dim.global_size[1]);
+
+ for (int y = 0; y < dim.global_size[1]; y++) {
+ for (int x = 0; x < dim.global_size[0]; x++) {
+ kg->global_id = make_int2(x, y);
+
+ device->data_init_kernel()((KernelGlobals *)kernel_globals.device_pointer,
+ (KernelData *)data.device_pointer,
+ (void *)split_data.device_pointer,
+ num_global_elements,
+ (char *)ray_state.device_pointer,
+ rtile.start_sample,
+ rtile.start_sample + rtile.num_samples,
+ rtile.x,
+ rtile.y,
+ rtile.w,
+ rtile.h,
+ rtile.offset,
+ rtile.stride,
+ (int *)queue_index.device_pointer,
+ dim.global_size[0] * dim.global_size[1],
+ (char *)use_queues_flags.device_pointer,
+ (uint *)work_pool_wgs.device_pointer,
+ rtile.num_samples,
+ (float *)rtile.buffer);
+ }
+ }
+
+ return true;
}
-SplitKernelFunction* CPUSplitKernel::get_split_kernel_function(const string& kernel_name,
- const DeviceRequestedFeatures&)
+SplitKernelFunction *CPUSplitKernel::get_split_kernel_function(const string &kernel_name,
+ const DeviceRequestedFeatures &)
{
- CPUSplitKernelFunction *kernel = new CPUSplitKernelFunction(device);
+ CPUSplitKernelFunction *kernel = new CPUSplitKernelFunction(device);
- kernel->func = device->split_kernels[kernel_name]();
- if(!kernel->func) {
- delete kernel;
- return NULL;
- }
+ kernel->func = device->split_kernels[kernel_name]();
+ if (!kernel->func) {
+ delete kernel;
+ return NULL;
+ }
- return kernel;
+ return kernel;
}
int2 CPUSplitKernel::split_kernel_local_size()
{
- return make_int2(1, 1);
+ return make_int2(1, 1);
}
-int2 CPUSplitKernel::split_kernel_global_size(device_memory& /*kg*/, device_memory& /*data*/, DeviceTask * /*task*/) {
- return make_int2(1, 1);
+int2 CPUSplitKernel::split_kernel_global_size(device_memory & /*kg*/,
+ device_memory & /*data*/,
+ DeviceTask * /*task*/)
+{
+ return make_int2(1, 1);
}
-uint64_t CPUSplitKernel::state_buffer_size(device_memory& kernel_globals, device_memory& /*data*/, size_t num_threads) {
- KernelGlobals *kg = (KernelGlobals*)kernel_globals.device_pointer;
+uint64_t CPUSplitKernel::state_buffer_size(device_memory &kernel_globals,
+ device_memory & /*data*/,
+ size_t num_threads)
+{
+ KernelGlobals *kg = (KernelGlobals *)kernel_globals.device_pointer;
- return split_data_buffer_size(kg, num_threads);
+ return split_data_buffer_size(kg, num_threads);
}
-Device *device_cpu_create(DeviceInfo& info, Stats &stats, Profiler &profiler, bool background)
+Device *device_cpu_create(DeviceInfo &info, Stats &stats, Profiler &profiler, bool background)
{
- return new CPUDevice(info, stats, profiler, background);
+ return new CPUDevice(info, stats, profiler, background);
}
-void device_cpu_info(vector<DeviceInfo>& devices)
+void device_cpu_info(vector<DeviceInfo> &devices)
{
- DeviceInfo info;
-
- info.type = DEVICE_CPU;
- info.description = system_cpu_brand_string();
- info.id = "CPU";
- info.num = 0;
- info.has_volume_decoupled = true;
- info.has_osl = true;
- info.has_half_images = true;
- info.has_profiling = true;
-
- devices.insert(devices.begin(), info);
+ DeviceInfo info;
+
+ info.type = DEVICE_CPU;
+ info.description = system_cpu_brand_string();
+ info.id = "CPU";
+ info.num = 0;
+ info.has_volume_decoupled = true;
+ info.has_osl = true;
+ info.has_half_images = true;
+ info.has_profiling = true;
+
+ devices.insert(devices.begin(), info);
}
string device_cpu_capabilities()
{
- string capabilities = "";
- capabilities += system_cpu_support_sse2() ? "SSE2 " : "";
- capabilities += system_cpu_support_sse3() ? "SSE3 " : "";
- capabilities += system_cpu_support_sse41() ? "SSE41 " : "";
- capabilities += system_cpu_support_avx() ? "AVX " : "";
- capabilities += system_cpu_support_avx2() ? "AVX2" : "";
- if(capabilities[capabilities.size() - 1] == ' ')
- capabilities.resize(capabilities.size() - 1);
- return capabilities;
+ string capabilities = "";
+ capabilities += system_cpu_support_sse2() ? "SSE2 " : "";
+ capabilities += system_cpu_support_sse3() ? "SSE3 " : "";
+ capabilities += system_cpu_support_sse41() ? "SSE41 " : "";
+ capabilities += system_cpu_support_avx() ? "AVX " : "";
+ capabilities += system_cpu_support_avx2() ? "AVX2" : "";
+ if (capabilities[capabilities.size() - 1] == ' ')
+ capabilities.resize(capabilities.size() - 1);
+ return capabilities;
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/device/device_cuda.cpp b/intern/cycles/device/device_cuda.cpp
index 3aa6bce155e..68bc3bd4045 100644
--- a/intern/cycles/device/device_cuda.cpp
+++ b/intern/cycles/device/device_cuda.cpp
@@ -62,2144 +62,2242 @@ namespace {
const char *cuewErrorString(CUresult result)
{
- /* We can only give error code here without major code duplication, that
- * should be enough since dynamic loading is only being disabled by folks
- * who knows what they're doing anyway.
- *
- * NOTE: Avoid call from several threads.
- */
- static string error;
- error = string_printf("%d", result);
- return error.c_str();
+ /* We can only give error code here without major code duplication, that
+ * should be enough since dynamic loading is only being disabled by folks
+ * who knows what they're doing anyway.
+ *
+ * NOTE: Avoid call from several threads.
+ */
+ static string error;
+ error = string_printf("%d", result);
+ return error.c_str();
}
const char *cuewCompilerPath()
{
- return CYCLES_CUDA_NVCC_EXECUTABLE;
+ return CYCLES_CUDA_NVCC_EXECUTABLE;
}
int cuewCompilerVersion()
{
- return (CUDA_VERSION / 100) + (CUDA_VERSION % 100 / 10);
+ return (CUDA_VERSION / 100) + (CUDA_VERSION % 100 / 10);
}
-} /* namespace */
-#endif /* WITH_CUDA_DYNLOAD */
+} /* namespace */
+#endif /* WITH_CUDA_DYNLOAD */
class CUDADevice;
class CUDASplitKernel : public DeviceSplitKernel {
- CUDADevice *device;
-public:
- explicit CUDASplitKernel(CUDADevice *device);
-
- virtual uint64_t state_buffer_size(device_memory& kg, device_memory& data, size_t num_threads);
-
- virtual bool enqueue_split_kernel_data_init(const KernelDimensions& dim,
- RenderTile& rtile,
- int num_global_elements,
- device_memory& kernel_globals,
- device_memory& kernel_data_,
- device_memory& split_data,
- device_memory& ray_state,
- device_memory& queue_index,
- device_memory& use_queues_flag,
- device_memory& work_pool_wgs);
-
- virtual SplitKernelFunction* get_split_kernel_function(const string& kernel_name,
- const DeviceRequestedFeatures&);
- virtual int2 split_kernel_local_size();
- virtual int2 split_kernel_global_size(device_memory& kg, device_memory& data, DeviceTask *task);
+ CUDADevice *device;
+
+ public:
+ explicit CUDASplitKernel(CUDADevice *device);
+
+ virtual uint64_t state_buffer_size(device_memory &kg, device_memory &data, size_t num_threads);
+
+ virtual bool enqueue_split_kernel_data_init(const KernelDimensions &dim,
+ RenderTile &rtile,
+ int num_global_elements,
+ device_memory &kernel_globals,
+ device_memory &kernel_data_,
+ device_memory &split_data,
+ device_memory &ray_state,
+ device_memory &queue_index,
+ device_memory &use_queues_flag,
+ device_memory &work_pool_wgs);
+
+ virtual SplitKernelFunction *get_split_kernel_function(const string &kernel_name,
+ const DeviceRequestedFeatures &);
+ virtual int2 split_kernel_local_size();
+ virtual int2 split_kernel_global_size(device_memory &kg, device_memory &data, DeviceTask *task);
};
/* Utility to push/pop CUDA context. */
class CUDAContextScope {
-public:
- CUDAContextScope(CUDADevice *device);
- ~CUDAContextScope();
+ public:
+ CUDAContextScope(CUDADevice *device);
+ ~CUDAContextScope();
-private:
- CUDADevice *device;
+ private:
+ CUDADevice *device;
};
-class CUDADevice : public Device
-{
-public:
- DedicatedTaskPool task_pool;
- CUdevice cuDevice;
- CUcontext cuContext;
- CUmodule cuModule, cuFilterModule;
- size_t device_texture_headroom;
- size_t device_working_headroom;
- bool move_texture_to_host;
- size_t map_host_used;
- size_t map_host_limit;
- int can_map_host;
- int cuDevId;
- int cuDevArchitecture;
- bool first_error;
- CUDASplitKernel *split_kernel;
-
- struct CUDAMem {
- CUDAMem()
- : texobject(0), array(0), map_host_pointer(0), free_map_host(false) {}
-
- CUtexObject texobject;
- CUarray array;
- void *map_host_pointer;
- bool free_map_host;
- };
- typedef map<device_memory*, CUDAMem> CUDAMemMap;
- CUDAMemMap cuda_mem_map;
-
- struct PixelMem {
- GLuint cuPBO;
- CUgraphicsResource cuPBOresource;
- GLuint cuTexId;
- int w, h;
- };
- map<device_ptr, PixelMem> pixel_mem_map;
-
- /* Bindless Textures */
- device_vector<TextureInfo> texture_info;
- bool need_texture_info;
-
- CUdeviceptr cuda_device_ptr(device_ptr mem)
- {
- return (CUdeviceptr)mem;
- }
-
- static bool have_precompiled_kernels()
- {
- string cubins_path = path_get("lib");
- return path_exists(cubins_path);
- }
-
- virtual bool show_samples() const
- {
- /* The CUDADevice only processes one tile at a time, so showing samples is fine. */
- return true;
- }
-
- virtual BVHLayoutMask get_bvh_layout_mask() const {
- return BVH_LAYOUT_BVH2;
- }
-
-/*#ifdef NDEBUG
+class CUDADevice : public Device {
+ public:
+ DedicatedTaskPool task_pool;
+ CUdevice cuDevice;
+ CUcontext cuContext;
+ CUmodule cuModule, cuFilterModule;
+ size_t device_texture_headroom;
+ size_t device_working_headroom;
+ bool move_texture_to_host;
+ size_t map_host_used;
+ size_t map_host_limit;
+ int can_map_host;
+ int cuDevId;
+ int cuDevArchitecture;
+ bool first_error;
+ CUDASplitKernel *split_kernel;
+
+ struct CUDAMem {
+ CUDAMem() : texobject(0), array(0), map_host_pointer(0), free_map_host(false)
+ {
+ }
+
+ CUtexObject texobject;
+ CUarray array;
+ void *map_host_pointer;
+ bool free_map_host;
+ };
+ typedef map<device_memory *, CUDAMem> CUDAMemMap;
+ CUDAMemMap cuda_mem_map;
+
+ struct PixelMem {
+ GLuint cuPBO;
+ CUgraphicsResource cuPBOresource;
+ GLuint cuTexId;
+ int w, h;
+ };
+ map<device_ptr, PixelMem> pixel_mem_map;
+
+ /* Bindless Textures */
+ device_vector<TextureInfo> texture_info;
+ bool need_texture_info;
+
+ CUdeviceptr cuda_device_ptr(device_ptr mem)
+ {
+ return (CUdeviceptr)mem;
+ }
+
+ static bool have_precompiled_kernels()
+ {
+ string cubins_path = path_get("lib");
+ return path_exists(cubins_path);
+ }
+
+ virtual bool show_samples() const
+ {
+ /* The CUDADevice only processes one tile at a time, so showing samples is fine. */
+ return true;
+ }
+
+ virtual BVHLayoutMask get_bvh_layout_mask() const
+ {
+ return BVH_LAYOUT_BVH2;
+ }
+
+ /*#ifdef NDEBUG
#define cuda_abort()
#else
#define cuda_abort() abort()
#endif*/
- void cuda_error_documentation()
- {
- if(first_error) {
- fprintf(stderr, "\nRefer to the Cycles GPU rendering documentation for possible solutions:\n");
- fprintf(stderr, "https://docs.blender.org/manual/en/dev/render/cycles/gpu_rendering.html\n\n");
- first_error = false;
- }
- }
+ void cuda_error_documentation()
+ {
+ if (first_error) {
+ fprintf(stderr,
+ "\nRefer to the Cycles GPU rendering documentation for possible solutions:\n");
+ fprintf(stderr,
+ "https://docs.blender.org/manual/en/dev/render/cycles/gpu_rendering.html\n\n");
+ first_error = false;
+ }
+ }
#define cuda_assert(stmt) \
- { \
- CUresult result = stmt; \
- \
- if(result != CUDA_SUCCESS) { \
- string message = string_printf("CUDA error: %s in %s, line %d", cuewErrorString(result), #stmt, __LINE__); \
- if(error_msg == "") \
- error_msg = message; \
- fprintf(stderr, "%s\n", message.c_str()); \
- /*cuda_abort();*/ \
- cuda_error_documentation(); \
- } \
- } (void) 0
-
- bool cuda_error_(CUresult result, const string& stmt)
- {
- if(result == CUDA_SUCCESS)
- return false;
-
- string message = string_printf("CUDA error at %s: %s", stmt.c_str(), cuewErrorString(result));
- if(error_msg == "")
- error_msg = message;
- fprintf(stderr, "%s\n", message.c_str());
- cuda_error_documentation();
- return true;
- }
+ { \
+ CUresult result = stmt; \
+\
+ if (result != CUDA_SUCCESS) { \
+ string message = string_printf( \
+ "CUDA error: %s in %s, line %d", cuewErrorString(result), #stmt, __LINE__); \
+ if (error_msg == "") \
+ error_msg = message; \
+ fprintf(stderr, "%s\n", message.c_str()); \
+ /*cuda_abort();*/ \
+ cuda_error_documentation(); \
+ } \
+ } \
+ (void)0
+
+ bool cuda_error_(CUresult result, const string &stmt)
+ {
+ if (result == CUDA_SUCCESS)
+ return false;
+
+ string message = string_printf("CUDA error at %s: %s", stmt.c_str(), cuewErrorString(result));
+ if (error_msg == "")
+ error_msg = message;
+ fprintf(stderr, "%s\n", message.c_str());
+ cuda_error_documentation();
+ return true;
+ }
#define cuda_error(stmt) cuda_error_(stmt, #stmt)
- void cuda_error_message(const string& message)
- {
- if(error_msg == "")
- error_msg = message;
- fprintf(stderr, "%s\n", message.c_str());
- cuda_error_documentation();
- }
-
- CUDADevice(DeviceInfo& info, Stats &stats, Profiler &profiler, bool background_)
- : Device(info, stats, profiler, background_),
- texture_info(this, "__texture_info", MEM_TEXTURE)
- {
- first_error = true;
- background = background_;
-
- cuDevId = info.num;
- cuDevice = 0;
- cuContext = 0;
-
- cuModule = 0;
- cuFilterModule = 0;
-
- split_kernel = NULL;
-
- need_texture_info = false;
-
- device_texture_headroom = 0;
- device_working_headroom = 0;
- move_texture_to_host = false;
- map_host_limit = 0;
- map_host_used = 0;
- can_map_host = 0;
-
- /* Intialize CUDA. */
- if(cuda_error(cuInit(0)))
- return;
-
- /* Setup device and context. */
- if(cuda_error(cuDeviceGet(&cuDevice, cuDevId)))
- return;
-
- /* CU_CTX_MAP_HOST for mapping host memory when out of device memory.
- * CU_CTX_LMEM_RESIZE_TO_MAX for reserving local memory ahead of render,
- * so we can predict which memory to map to host. */
- cuda_assert(cuDeviceGetAttribute(&can_map_host, CU_DEVICE_ATTRIBUTE_CAN_MAP_HOST_MEMORY, cuDevice));
-
- unsigned int ctx_flags = CU_CTX_LMEM_RESIZE_TO_MAX;
- if(can_map_host) {
- ctx_flags |= CU_CTX_MAP_HOST;
- init_host_memory();
- }
-
- /* Create context. */
- CUresult result;
-
- if(background) {
- result = cuCtxCreate(&cuContext, ctx_flags, cuDevice);
- }
- else {
- result = cuGLCtxCreate(&cuContext, ctx_flags, cuDevice);
-
- if(result != CUDA_SUCCESS) {
- result = cuCtxCreate(&cuContext, ctx_flags, cuDevice);
- background = true;
- }
- }
-
- if(cuda_error_(result, "cuCtxCreate"))
- return;
-
- int major, minor;
- cuDeviceGetAttribute(&major, CU_DEVICE_ATTRIBUTE_COMPUTE_CAPABILITY_MAJOR, cuDevId);
- cuDeviceGetAttribute(&minor, CU_DEVICE_ATTRIBUTE_COMPUTE_CAPABILITY_MINOR, cuDevId);
- cuDevArchitecture = major*100 + minor*10;
-
- /* Pop context set by cuCtxCreate. */
- cuCtxPopCurrent(NULL);
- }
-
- ~CUDADevice()
- {
- task_pool.stop();
-
- delete split_kernel;
-
- texture_info.free();
-
- cuda_assert(cuCtxDestroy(cuContext));
- }
-
- bool support_device(const DeviceRequestedFeatures& /*requested_features*/)
- {
- int major, minor;
- cuDeviceGetAttribute(&major, CU_DEVICE_ATTRIBUTE_COMPUTE_CAPABILITY_MAJOR, cuDevId);
- cuDeviceGetAttribute(&minor, CU_DEVICE_ATTRIBUTE_COMPUTE_CAPABILITY_MINOR, cuDevId);
-
- /* We only support sm_30 and above */
- if(major < 3) {
- cuda_error_message(string_printf("CUDA device supported only with compute capability 3.0 or up, found %d.%d.", major, minor));
- return false;
- }
-
- return true;
- }
-
- bool use_adaptive_compilation()
- {
- return DebugFlags().cuda.adaptive_compile;
- }
-
- bool use_split_kernel()
- {
- return DebugFlags().cuda.split_kernel;
- }
-
- /* Common NVCC flags which stays the same regardless of shading model,
- * kernel sources md5 and only depends on compiler or compilation settings.
- */
- string compile_kernel_get_common_cflags(
- const DeviceRequestedFeatures& requested_features,
- bool filter=false, bool split=false)
- {
- const int machine = system_cpu_bits();
- const string source_path = path_get("source");
- const string include_path = source_path;
- string cflags = string_printf("-m%d "
- "--ptxas-options=\"-v\" "
- "--use_fast_math "
- "-DNVCC "
- "-I\"%s\"",
- machine,
- include_path.c_str());
- if(!filter && use_adaptive_compilation()) {
- cflags += " " + requested_features.get_build_options();
- }
- const char *extra_cflags = getenv("CYCLES_CUDA_EXTRA_CFLAGS");
- if(extra_cflags) {
- cflags += string(" ") + string(extra_cflags);
- }
+ void cuda_error_message(const string &message)
+ {
+ if (error_msg == "")
+ error_msg = message;
+ fprintf(stderr, "%s\n", message.c_str());
+ cuda_error_documentation();
+ }
+
+ CUDADevice(DeviceInfo &info, Stats &stats, Profiler &profiler, bool background_)
+ : Device(info, stats, profiler, background_),
+ texture_info(this, "__texture_info", MEM_TEXTURE)
+ {
+ first_error = true;
+ background = background_;
+
+ cuDevId = info.num;
+ cuDevice = 0;
+ cuContext = 0;
+
+ cuModule = 0;
+ cuFilterModule = 0;
+
+ split_kernel = NULL;
+
+ need_texture_info = false;
+
+ device_texture_headroom = 0;
+ device_working_headroom = 0;
+ move_texture_to_host = false;
+ map_host_limit = 0;
+ map_host_used = 0;
+ can_map_host = 0;
+
+ /* Intialize CUDA. */
+ if (cuda_error(cuInit(0)))
+ return;
+
+ /* Setup device and context. */
+ if (cuda_error(cuDeviceGet(&cuDevice, cuDevId)))
+ return;
+
+ /* CU_CTX_MAP_HOST for mapping host memory when out of device memory.
+ * CU_CTX_LMEM_RESIZE_TO_MAX for reserving local memory ahead of render,
+ * so we can predict which memory to map to host. */
+ cuda_assert(
+ cuDeviceGetAttribute(&can_map_host, CU_DEVICE_ATTRIBUTE_CAN_MAP_HOST_MEMORY, cuDevice));
+
+ unsigned int ctx_flags = CU_CTX_LMEM_RESIZE_TO_MAX;
+ if (can_map_host) {
+ ctx_flags |= CU_CTX_MAP_HOST;
+ init_host_memory();
+ }
+
+ /* Create context. */
+ CUresult result;
+
+ if (background) {
+ result = cuCtxCreate(&cuContext, ctx_flags, cuDevice);
+ }
+ else {
+ result = cuGLCtxCreate(&cuContext, ctx_flags, cuDevice);
+
+ if (result != CUDA_SUCCESS) {
+ result = cuCtxCreate(&cuContext, ctx_flags, cuDevice);
+ background = true;
+ }
+ }
+
+ if (cuda_error_(result, "cuCtxCreate"))
+ return;
+
+ int major, minor;
+ cuDeviceGetAttribute(&major, CU_DEVICE_ATTRIBUTE_COMPUTE_CAPABILITY_MAJOR, cuDevId);
+ cuDeviceGetAttribute(&minor, CU_DEVICE_ATTRIBUTE_COMPUTE_CAPABILITY_MINOR, cuDevId);
+ cuDevArchitecture = major * 100 + minor * 10;
+
+ /* Pop context set by cuCtxCreate. */
+ cuCtxPopCurrent(NULL);
+ }
+
+ ~CUDADevice()
+ {
+ task_pool.stop();
+
+ delete split_kernel;
+
+ texture_info.free();
+
+ cuda_assert(cuCtxDestroy(cuContext));
+ }
+
+ bool support_device(const DeviceRequestedFeatures & /*requested_features*/)
+ {
+ int major, minor;
+ cuDeviceGetAttribute(&major, CU_DEVICE_ATTRIBUTE_COMPUTE_CAPABILITY_MAJOR, cuDevId);
+ cuDeviceGetAttribute(&minor, CU_DEVICE_ATTRIBUTE_COMPUTE_CAPABILITY_MINOR, cuDevId);
+
+ /* We only support sm_30 and above */
+ if (major < 3) {
+ cuda_error_message(string_printf(
+ "CUDA device supported only with compute capability 3.0 or up, found %d.%d.",
+ major,
+ minor));
+ return false;
+ }
+
+ return true;
+ }
+
+ bool use_adaptive_compilation()
+ {
+ return DebugFlags().cuda.adaptive_compile;
+ }
+
+ bool use_split_kernel()
+ {
+ return DebugFlags().cuda.split_kernel;
+ }
+
+ /* Common NVCC flags which stays the same regardless of shading model,
+ * kernel sources md5 and only depends on compiler or compilation settings.
+ */
+ string compile_kernel_get_common_cflags(const DeviceRequestedFeatures &requested_features,
+ bool filter = false,
+ bool split = false)
+ {
+ const int machine = system_cpu_bits();
+ const string source_path = path_get("source");
+ const string include_path = source_path;
+ string cflags = string_printf(
+ "-m%d "
+ "--ptxas-options=\"-v\" "
+ "--use_fast_math "
+ "-DNVCC "
+ "-I\"%s\"",
+ machine,
+ include_path.c_str());
+ if (!filter && use_adaptive_compilation()) {
+ cflags += " " + requested_features.get_build_options();
+ }
+ const char *extra_cflags = getenv("CYCLES_CUDA_EXTRA_CFLAGS");
+ if (extra_cflags) {
+ cflags += string(" ") + string(extra_cflags);
+ }
#ifdef WITH_CYCLES_DEBUG
- cflags += " -D__KERNEL_DEBUG__";
+ cflags += " -D__KERNEL_DEBUG__";
#endif
- if(split) {
- cflags += " -D__SPLIT__";
- }
-
- return cflags;
- }
-
- bool compile_check_compiler() {
- const char *nvcc = cuewCompilerPath();
- if(nvcc == NULL) {
- cuda_error_message("CUDA nvcc compiler not found. "
- "Install CUDA toolkit in default location.");
- return false;
- }
- const int cuda_version = cuewCompilerVersion();
- VLOG(1) << "Found nvcc " << nvcc
- << ", CUDA version " << cuda_version
- << ".";
- const int major = cuda_version / 10, minor = cuda_version % 10;
- if(cuda_version == 0) {
- cuda_error_message("CUDA nvcc compiler version could not be parsed.");
- return false;
- }
- if(cuda_version < 80) {
- printf("Unsupported CUDA version %d.%d detected, "
- "you need CUDA 8.0 or newer.\n",
- major, minor);
- return false;
- }
- else if(cuda_version != 101) {
- printf("CUDA version %d.%d detected, build may succeed but only "
- "CUDA 10.1 is officially supported.\n",
- major, minor);
- }
- return true;
- }
-
- string compile_kernel(const DeviceRequestedFeatures& requested_features,
- bool filter=false, bool split=false)
- {
- const char *name, *source;
- if(filter) {
- name = "filter";
- source = "filter.cu";
- }
- else if(split) {
- name = "kernel_split";
- source = "kernel_split.cu";
- }
- else {
- name = "kernel";
- source = "kernel.cu";
- }
- /* Compute cubin name. */
- int major, minor;
- cuDeviceGetAttribute(&major, CU_DEVICE_ATTRIBUTE_COMPUTE_CAPABILITY_MAJOR, cuDevId);
- cuDeviceGetAttribute(&minor, CU_DEVICE_ATTRIBUTE_COMPUTE_CAPABILITY_MINOR, cuDevId);
-
- /* Attempt to use kernel provided with Blender. */
- if(!use_adaptive_compilation()) {
- const string cubin = path_get(string_printf("lib/%s_sm_%d%d.cubin",
- name, major, minor));
- VLOG(1) << "Testing for pre-compiled kernel " << cubin << ".";
- if(path_exists(cubin)) {
- VLOG(1) << "Using precompiled kernel.";
- return cubin;
- }
- }
-
- const string common_cflags =
- compile_kernel_get_common_cflags(requested_features, filter, split);
-
- /* Try to use locally compiled kernel. */
- const string source_path = path_get("source");
- const string kernel_md5 = path_files_md5_hash(source_path);
-
- /* We include cflags into md5 so changing cuda toolkit or changing other
- * compiler command line arguments makes sure cubin gets re-built.
- */
- const string cubin_md5 = util_md5_string(kernel_md5 + common_cflags);
-
- const string cubin_file = string_printf("cycles_%s_sm%d%d_%s.cubin",
- name, major, minor,
- cubin_md5.c_str());
- const string cubin = path_cache_get(path_join("kernels", cubin_file));
- VLOG(1) << "Testing for locally compiled kernel " << cubin << ".";
- if(path_exists(cubin)) {
- VLOG(1) << "Using locally compiled kernel.";
- return cubin;
- }
+ if (split) {
+ cflags += " -D__SPLIT__";
+ }
+
+ return cflags;
+ }
+
+ bool compile_check_compiler()
+ {
+ const char *nvcc = cuewCompilerPath();
+ if (nvcc == NULL) {
+ cuda_error_message(
+ "CUDA nvcc compiler not found. "
+ "Install CUDA toolkit in default location.");
+ return false;
+ }
+ const int cuda_version = cuewCompilerVersion();
+ VLOG(1) << "Found nvcc " << nvcc << ", CUDA version " << cuda_version << ".";
+ const int major = cuda_version / 10, minor = cuda_version % 10;
+ if (cuda_version == 0) {
+ cuda_error_message("CUDA nvcc compiler version could not be parsed.");
+ return false;
+ }
+ if (cuda_version < 80) {
+ printf(
+ "Unsupported CUDA version %d.%d detected, "
+ "you need CUDA 8.0 or newer.\n",
+ major,
+ minor);
+ return false;
+ }
+ else if (cuda_version != 101) {
+ printf(
+ "CUDA version %d.%d detected, build may succeed but only "
+ "CUDA 10.1 is officially supported.\n",
+ major,
+ minor);
+ }
+ return true;
+ }
+
+ string compile_kernel(const DeviceRequestedFeatures &requested_features,
+ bool filter = false,
+ bool split = false)
+ {
+ const char *name, *source;
+ if (filter) {
+ name = "filter";
+ source = "filter.cu";
+ }
+ else if (split) {
+ name = "kernel_split";
+ source = "kernel_split.cu";
+ }
+ else {
+ name = "kernel";
+ source = "kernel.cu";
+ }
+ /* Compute cubin name. */
+ int major, minor;
+ cuDeviceGetAttribute(&major, CU_DEVICE_ATTRIBUTE_COMPUTE_CAPABILITY_MAJOR, cuDevId);
+ cuDeviceGetAttribute(&minor, CU_DEVICE_ATTRIBUTE_COMPUTE_CAPABILITY_MINOR, cuDevId);
+
+ /* Attempt to use kernel provided with Blender. */
+ if (!use_adaptive_compilation()) {
+ const string cubin = path_get(string_printf("lib/%s_sm_%d%d.cubin", name, major, minor));
+ VLOG(1) << "Testing for pre-compiled kernel " << cubin << ".";
+ if (path_exists(cubin)) {
+ VLOG(1) << "Using precompiled kernel.";
+ return cubin;
+ }
+ }
+
+ const string common_cflags = compile_kernel_get_common_cflags(
+ requested_features, filter, split);
+
+ /* Try to use locally compiled kernel. */
+ const string source_path = path_get("source");
+ const string kernel_md5 = path_files_md5_hash(source_path);
+
+ /* We include cflags into md5 so changing cuda toolkit or changing other
+ * compiler command line arguments makes sure cubin gets re-built.
+ */
+ const string cubin_md5 = util_md5_string(kernel_md5 + common_cflags);
+
+ const string cubin_file = string_printf(
+ "cycles_%s_sm%d%d_%s.cubin", name, major, minor, cubin_md5.c_str());
+ const string cubin = path_cache_get(path_join("kernels", cubin_file));
+ VLOG(1) << "Testing for locally compiled kernel " << cubin << ".";
+ if (path_exists(cubin)) {
+ VLOG(1) << "Using locally compiled kernel.";
+ return cubin;
+ }
#ifdef _WIN32
- if(have_precompiled_kernels()) {
- if(major < 3) {
- cuda_error_message(string_printf(
- "CUDA device requires compute capability 3.0 or up, "
- "found %d.%d. Your GPU is not supported.",
- major, minor));
- }
- else {
- cuda_error_message(string_printf(
- "CUDA binary kernel for this graphics card compute "
- "capability (%d.%d) not found.",
- major, minor));
- }
- return "";
- }
+ if (have_precompiled_kernels()) {
+ if (major < 3) {
+ cuda_error_message(
+ string_printf("CUDA device requires compute capability 3.0 or up, "
+ "found %d.%d. Your GPU is not supported.",
+ major,
+ minor));
+ }
+ else {
+ cuda_error_message(
+ string_printf("CUDA binary kernel for this graphics card compute "
+ "capability (%d.%d) not found.",
+ major,
+ minor));
+ }
+ return "";
+ }
#endif
- /* Compile. */
- if(!compile_check_compiler()) {
- return "";
- }
- const char *nvcc = cuewCompilerPath();
- const string kernel = path_join(
- path_join(source_path, "kernel"),
- path_join("kernels",
- path_join("cuda", source)));
- double starttime = time_dt();
- printf("Compiling CUDA kernel ...\n");
-
- path_create_directories(cubin);
-
- string command = string_printf("\"%s\" "
- "-arch=sm_%d%d "
- "--cubin \"%s\" "
- "-o \"%s\" "
- "%s ",
- nvcc,
- major, minor,
- kernel.c_str(),
- cubin.c_str(),
- common_cflags.c_str());
-
- printf("%s\n", command.c_str());
-
- if(system(command.c_str()) == -1) {
- cuda_error_message("Failed to execute compilation command, "
- "see console for details.");
- return "";
- }
-
- /* Verify if compilation succeeded */
- if(!path_exists(cubin)) {
- cuda_error_message("CUDA kernel compilation failed, "
- "see console for details.");
- return "";
- }
-
- printf("Kernel compilation finished in %.2lfs.\n", time_dt() - starttime);
-
- return cubin;
- }
-
- bool load_kernels(const DeviceRequestedFeatures& requested_features)
- {
- /* TODO(sergey): Support kernels re-load for CUDA devices.
- *
- * Currently re-loading kernel will invalidate memory pointers,
- * causing problems in cuCtxSynchronize.
- */
- if(cuFilterModule && cuModule) {
- VLOG(1) << "Skipping kernel reload, not currently supported.";
- return true;
- }
-
- /* check if cuda init succeeded */
- if(cuContext == 0)
- return false;
-
- /* check if GPU is supported */
- if(!support_device(requested_features))
- return false;
-
- /* get kernel */
- string cubin = compile_kernel(requested_features, false, use_split_kernel());
- if(cubin == "")
- return false;
-
- string filter_cubin = compile_kernel(requested_features, true, false);
- if(filter_cubin == "")
- return false;
-
- /* open module */
- CUDAContextScope scope(this);
-
- string cubin_data;
- CUresult result;
-
- if(path_read_text(cubin, cubin_data))
- result = cuModuleLoadData(&cuModule, cubin_data.c_str());
- else
- result = CUDA_ERROR_FILE_NOT_FOUND;
-
- if(cuda_error_(result, "cuModuleLoad"))
- cuda_error_message(string_printf("Failed loading CUDA kernel %s.", cubin.c_str()));
-
- if(path_read_text(filter_cubin, cubin_data))
- result = cuModuleLoadData(&cuFilterModule, cubin_data.c_str());
- else
- result = CUDA_ERROR_FILE_NOT_FOUND;
-
- if(cuda_error_(result, "cuModuleLoad"))
- cuda_error_message(string_printf("Failed loading CUDA kernel %s.", filter_cubin.c_str()));
-
- if(result == CUDA_SUCCESS) {
- reserve_local_memory(requested_features);
- }
-
- return (result == CUDA_SUCCESS);
- }
-
- void reserve_local_memory(const DeviceRequestedFeatures& requested_features)
- {
- if(use_split_kernel()) {
- /* Split kernel mostly uses global memory and adaptive compilation,
- * difficult to predict how much is needed currently. */
- return;
- }
-
- /* Together with CU_CTX_LMEM_RESIZE_TO_MAX, this reserves local memory
- * needed for kernel launches, so that we can reliably figure out when
- * to allocate scene data in mapped host memory. */
- CUDAContextScope scope(this);
-
- size_t total = 0, free_before = 0, free_after = 0;
- cuMemGetInfo(&free_before, &total);
-
- /* Get kernel function. */
- CUfunction cuPathTrace;
-
- if(requested_features.use_integrator_branched) {
- cuda_assert(cuModuleGetFunction(&cuPathTrace, cuModule, "kernel_cuda_branched_path_trace"));
- }
- else {
- cuda_assert(cuModuleGetFunction(&cuPathTrace, cuModule, "kernel_cuda_path_trace"));
- }
-
- cuda_assert(cuFuncSetCacheConfig(cuPathTrace, CU_FUNC_CACHE_PREFER_L1));
-
- int min_blocks, num_threads_per_block;
- cuda_assert(cuOccupancyMaxPotentialBlockSize(&min_blocks, &num_threads_per_block, cuPathTrace, NULL, 0, 0));
-
- /* Launch kernel, using just 1 block appears sufficient to reserve
- * memory for all multiprocessors. It would be good to do this in
- * parallel for the multi GPU case still to make it faster. */
- CUdeviceptr d_work_tiles = 0;
- uint total_work_size = 0;
-
- void *args[] = {&d_work_tiles,
- &total_work_size};
-
- cuda_assert(cuLaunchKernel(cuPathTrace,
- 1, 1, 1,
- num_threads_per_block, 1, 1,
- 0, 0, args, 0));
-
- cuda_assert(cuCtxSynchronize());
-
- cuMemGetInfo(&free_after, &total);
- VLOG(1) << "Local memory reserved "
- << string_human_readable_number(free_before - free_after) << " bytes. ("
- << string_human_readable_size(free_before - free_after) << ")";
+ /* Compile. */
+ if (!compile_check_compiler()) {
+ return "";
+ }
+ const char *nvcc = cuewCompilerPath();
+ const string kernel = path_join(path_join(source_path, "kernel"),
+ path_join("kernels", path_join("cuda", source)));
+ double starttime = time_dt();
+ printf("Compiling CUDA kernel ...\n");
+
+ path_create_directories(cubin);
+
+ string command = string_printf(
+ "\"%s\" "
+ "-arch=sm_%d%d "
+ "--cubin \"%s\" "
+ "-o \"%s\" "
+ "%s ",
+ nvcc,
+ major,
+ minor,
+ kernel.c_str(),
+ cubin.c_str(),
+ common_cflags.c_str());
+
+ printf("%s\n", command.c_str());
+
+ if (system(command.c_str()) == -1) {
+ cuda_error_message(
+ "Failed to execute compilation command, "
+ "see console for details.");
+ return "";
+ }
+
+ /* Verify if compilation succeeded */
+ if (!path_exists(cubin)) {
+ cuda_error_message(
+ "CUDA kernel compilation failed, "
+ "see console for details.");
+ return "";
+ }
+
+ printf("Kernel compilation finished in %.2lfs.\n", time_dt() - starttime);
+
+ return cubin;
+ }
+
+ bool load_kernels(const DeviceRequestedFeatures &requested_features)
+ {
+ /* TODO(sergey): Support kernels re-load for CUDA devices.
+ *
+ * Currently re-loading kernel will invalidate memory pointers,
+ * causing problems in cuCtxSynchronize.
+ */
+ if (cuFilterModule && cuModule) {
+ VLOG(1) << "Skipping kernel reload, not currently supported.";
+ return true;
+ }
+
+ /* check if cuda init succeeded */
+ if (cuContext == 0)
+ return false;
+
+ /* check if GPU is supported */
+ if (!support_device(requested_features))
+ return false;
+
+ /* get kernel */
+ string cubin = compile_kernel(requested_features, false, use_split_kernel());
+ if (cubin == "")
+ return false;
+
+ string filter_cubin = compile_kernel(requested_features, true, false);
+ if (filter_cubin == "")
+ return false;
+
+ /* open module */
+ CUDAContextScope scope(this);
+
+ string cubin_data;
+ CUresult result;
+
+ if (path_read_text(cubin, cubin_data))
+ result = cuModuleLoadData(&cuModule, cubin_data.c_str());
+ else
+ result = CUDA_ERROR_FILE_NOT_FOUND;
+
+ if (cuda_error_(result, "cuModuleLoad"))
+ cuda_error_message(string_printf("Failed loading CUDA kernel %s.", cubin.c_str()));
+
+ if (path_read_text(filter_cubin, cubin_data))
+ result = cuModuleLoadData(&cuFilterModule, cubin_data.c_str());
+ else
+ result = CUDA_ERROR_FILE_NOT_FOUND;
+
+ if (cuda_error_(result, "cuModuleLoad"))
+ cuda_error_message(string_printf("Failed loading CUDA kernel %s.", filter_cubin.c_str()));
+
+ if (result == CUDA_SUCCESS) {
+ reserve_local_memory(requested_features);
+ }
+
+ return (result == CUDA_SUCCESS);
+ }
+
+ void reserve_local_memory(const DeviceRequestedFeatures &requested_features)
+ {
+ if (use_split_kernel()) {
+ /* Split kernel mostly uses global memory and adaptive compilation,
+ * difficult to predict how much is needed currently. */
+ return;
+ }
+
+ /* Together with CU_CTX_LMEM_RESIZE_TO_MAX, this reserves local memory
+ * needed for kernel launches, so that we can reliably figure out when
+ * to allocate scene data in mapped host memory. */
+ CUDAContextScope scope(this);
+
+ size_t total = 0, free_before = 0, free_after = 0;
+ cuMemGetInfo(&free_before, &total);
+
+ /* Get kernel function. */
+ CUfunction cuPathTrace;
+
+ if (requested_features.use_integrator_branched) {
+ cuda_assert(cuModuleGetFunction(&cuPathTrace, cuModule, "kernel_cuda_branched_path_trace"));
+ }
+ else {
+ cuda_assert(cuModuleGetFunction(&cuPathTrace, cuModule, "kernel_cuda_path_trace"));
+ }
+
+ cuda_assert(cuFuncSetCacheConfig(cuPathTrace, CU_FUNC_CACHE_PREFER_L1));
+
+ int min_blocks, num_threads_per_block;
+ cuda_assert(cuOccupancyMaxPotentialBlockSize(
+ &min_blocks, &num_threads_per_block, cuPathTrace, NULL, 0, 0));
+
+ /* Launch kernel, using just 1 block appears sufficient to reserve
+ * memory for all multiprocessors. It would be good to do this in
+ * parallel for the multi GPU case still to make it faster. */
+ CUdeviceptr d_work_tiles = 0;
+ uint total_work_size = 0;
+
+ void *args[] = {&d_work_tiles, &total_work_size};
+
+ cuda_assert(cuLaunchKernel(cuPathTrace, 1, 1, 1, num_threads_per_block, 1, 1, 0, 0, args, 0));
+
+ cuda_assert(cuCtxSynchronize());
+
+ cuMemGetInfo(&free_after, &total);
+ VLOG(1) << "Local memory reserved " << string_human_readable_number(free_before - free_after)
+ << " bytes. (" << string_human_readable_size(free_before - free_after) << ")";
#if 0
- /* For testing mapped host memory, fill up device memory. */
- const size_t keep_mb = 1024;
-
- while(free_after > keep_mb * 1024 * 1024LL) {
- CUdeviceptr tmp;
- cuda_assert(cuMemAlloc(&tmp, 10 * 1024 * 1024LL));
- cuMemGetInfo(&free_after, &total);
- }
+ /* For testing mapped host memory, fill up device memory. */
+ const size_t keep_mb = 1024;
+
+ while(free_after > keep_mb * 1024 * 1024LL) {
+ CUdeviceptr tmp;
+ cuda_assert(cuMemAlloc(&tmp, 10 * 1024 * 1024LL));
+ cuMemGetInfo(&free_after, &total);
+ }
#endif
- }
-
- void init_host_memory()
- {
- /* Limit amount of host mapped memory, because allocating too much can
- * cause system instability. Leave at least half or 4 GB of system
- * memory free, whichever is smaller. */
- size_t default_limit = 4 * 1024 * 1024 * 1024LL;
- size_t system_ram = system_physical_ram();
-
- if(system_ram > 0) {
- if(system_ram / 2 > default_limit) {
- map_host_limit = system_ram - default_limit;
- }
- else {
- map_host_limit = system_ram / 2;
- }
- }
- else {
- VLOG(1) << "Mapped host memory disabled, failed to get system RAM";
- map_host_limit = 0;
- }
-
- /* Amount of device memory to keep is free after texture memory
- * and working memory allocations respectively. We set the working
- * memory limit headroom lower so that some space is left after all
- * texture memory allocations. */
- device_working_headroom = 32 * 1024 * 1024LL; // 32MB
- device_texture_headroom = 128 * 1024 * 1024LL; // 128MB
-
- VLOG(1) << "Mapped host memory limit set to "
- << string_human_readable_number(map_host_limit) << " bytes. ("
- << string_human_readable_size(map_host_limit) << ")";
- }
-
- void load_texture_info()
- {
- if(need_texture_info) {
- texture_info.copy_to_device();
- need_texture_info = false;
- }
- }
-
- void move_textures_to_host(size_t size, bool for_texture)
- {
- /* Signal to reallocate textures in host memory only. */
- move_texture_to_host = true;
-
- while(size > 0) {
- /* Find suitable memory allocation to move. */
- device_memory *max_mem = NULL;
- size_t max_size = 0;
- bool max_is_image = false;
-
- foreach(CUDAMemMap::value_type& pair, cuda_mem_map) {
- device_memory& mem = *pair.first;
- CUDAMem *cmem = &pair.second;
-
- bool is_texture = (mem.type == MEM_TEXTURE) && (&mem != &texture_info);
- bool is_image = is_texture && (mem.data_height > 1);
-
- /* Can't move this type of memory. */
- if(!is_texture || cmem->array) {
- continue;
- }
-
- /* Already in host memory. */
- if(cmem->map_host_pointer) {
- continue;
- }
-
- /* For other textures, only move image textures. */
- if(for_texture && !is_image) {
- continue;
- }
-
- /* Try to move largest allocation, prefer moving images. */
- if(is_image > max_is_image ||
- (is_image == max_is_image && mem.device_size > max_size)) {
- max_is_image = is_image;
- max_size = mem.device_size;
- max_mem = &mem;
- }
- }
-
- /* Move to host memory. This part is mutex protected since
- * multiple CUDA devices could be moving the memory. The
- * first one will do it, and the rest will adopt the pointer. */
- if(max_mem) {
- VLOG(1) << "Move memory from device to host: " << max_mem->name;
-
- static thread_mutex move_mutex;
- thread_scoped_lock lock(move_mutex);
-
- /* Preserve the original device pointer, in case of multi device
- * we can't change it because the pointer mapping would break. */
- device_ptr prev_pointer = max_mem->device_pointer;
- size_t prev_size = max_mem->device_size;
-
- tex_free(*max_mem);
- tex_alloc(*max_mem);
- size = (max_size >= size)? 0: size - max_size;
-
- max_mem->device_pointer = prev_pointer;
- max_mem->device_size = prev_size;
- }
- else {
- break;
- }
- }
-
- /* Update texture info array with new pointers. */
- load_texture_info();
-
- move_texture_to_host = false;
- }
-
- CUDAMem *generic_alloc(device_memory& mem, size_t pitch_padding = 0)
- {
- CUDAContextScope scope(this);
-
- CUdeviceptr device_pointer = 0;
- size_t size = mem.memory_size() + pitch_padding;
-
- CUresult mem_alloc_result = CUDA_ERROR_OUT_OF_MEMORY;
- const char *status = "";
-
- /* First try allocating in device memory, respecting headroom. We make
- * an exception for texture info. It is small and frequently accessed,
- * so treat it as working memory.
- *
- * If there is not enough room for working memory, we will try to move
- * textures to host memory, assuming the performance impact would have
- * been worse for working memory. */
- bool is_texture = (mem.type == MEM_TEXTURE) && (&mem != &texture_info);
- bool is_image = is_texture && (mem.data_height > 1);
-
- size_t headroom = (is_texture)? device_texture_headroom:
- device_working_headroom;
-
- size_t total = 0, free = 0;
- cuMemGetInfo(&free, &total);
-
- /* Move textures to host memory if needed. */
- if(!move_texture_to_host && !is_image && (size + headroom) >= free) {
- move_textures_to_host(size + headroom - free, is_texture);
- cuMemGetInfo(&free, &total);
- }
-
- /* Allocate in device memory. */
- if(!move_texture_to_host && (size + headroom) < free) {
- mem_alloc_result = cuMemAlloc(&device_pointer, size);
- if(mem_alloc_result == CUDA_SUCCESS) {
- status = " in device memory";
- }
- }
-
- /* Fall back to mapped host memory if needed and possible. */
- void *map_host_pointer = 0;
- bool free_map_host = false;
-
- if(mem_alloc_result != CUDA_SUCCESS && can_map_host &&
- map_host_used + size < map_host_limit) {
- if(mem.shared_pointer) {
- /* Another device already allocated host memory. */
- mem_alloc_result = CUDA_SUCCESS;
- map_host_pointer = mem.shared_pointer;
- }
- else {
- /* Allocate host memory ourselves. */
- mem_alloc_result = cuMemHostAlloc(&map_host_pointer, size,
- CU_MEMHOSTALLOC_DEVICEMAP |
- CU_MEMHOSTALLOC_WRITECOMBINED);
- mem.shared_pointer = map_host_pointer;
- free_map_host = true;
- }
-
- if(mem_alloc_result == CUDA_SUCCESS) {
- cuda_assert(cuMemHostGetDevicePointer_v2(&device_pointer, mem.shared_pointer, 0));
- map_host_used += size;
- status = " in host memory";
-
- /* Replace host pointer with our host allocation. Only works if
- * CUDA memory layout is the same and has no pitch padding. Also
- * does not work if we move textures to host during a render,
- * since other devices might be using the memory. */
- if(!move_texture_to_host && pitch_padding == 0 &&
- mem.host_pointer && mem.host_pointer != mem.shared_pointer) {
- memcpy(mem.shared_pointer, mem.host_pointer, size);
- mem.host_free();
- mem.host_pointer = mem.shared_pointer;
- }
- }
- else {
- status = " failed, out of host memory";
- }
- }
- else if(mem_alloc_result != CUDA_SUCCESS) {
- status = " failed, out of device and host memory";
- }
-
- if(mem_alloc_result != CUDA_SUCCESS) {
- cuda_assert(mem_alloc_result);
- }
-
- if(mem.name) {
- VLOG(1) << "Buffer allocate: " << mem.name << ", "
- << string_human_readable_number(mem.memory_size()) << " bytes. ("
- << string_human_readable_size(mem.memory_size()) << ")"
- << status;
- }
-
- mem.device_pointer = (device_ptr)device_pointer;
- mem.device_size = size;
- stats.mem_alloc(size);
-
- if(!mem.device_pointer) {
- return NULL;
- }
-
- /* Insert into map of allocations. */
- CUDAMem *cmem = &cuda_mem_map[&mem];
- cmem->map_host_pointer = map_host_pointer;
- cmem->free_map_host = free_map_host;
- return cmem;
- }
-
- void generic_copy_to(device_memory& mem)
- {
- if(mem.host_pointer && mem.device_pointer) {
- CUDAContextScope scope(this);
-
- if(mem.host_pointer != mem.shared_pointer) {
- cuda_assert(cuMemcpyHtoD(cuda_device_ptr(mem.device_pointer),
- mem.host_pointer,
- mem.memory_size()));
- }
- }
- }
-
- void generic_free(device_memory& mem)
- {
- if(mem.device_pointer) {
- CUDAContextScope scope(this);
- const CUDAMem& cmem = cuda_mem_map[&mem];
-
- if(cmem.map_host_pointer) {
- /* Free host memory. */
- if(cmem.free_map_host) {
- cuMemFreeHost(cmem.map_host_pointer);
- if(mem.host_pointer == mem.shared_pointer) {
- mem.host_pointer = 0;
- }
- mem.shared_pointer = 0;
- }
-
- map_host_used -= mem.device_size;
- }
- else {
- /* Free device memory. */
- cuMemFree(mem.device_pointer);
- }
-
- stats.mem_free(mem.device_size);
- mem.device_pointer = 0;
- mem.device_size = 0;
-
- cuda_mem_map.erase(cuda_mem_map.find(&mem));
- }
- }
-
- void mem_alloc(device_memory& mem)
- {
- if(mem.type == MEM_PIXELS && !background) {
- pixels_alloc(mem);
- }
- else if(mem.type == MEM_TEXTURE) {
- assert(!"mem_alloc not supported for textures.");
- }
- else {
- generic_alloc(mem);
- }
- }
-
- void mem_copy_to(device_memory& mem)
- {
- if(mem.type == MEM_PIXELS) {
- assert(!"mem_copy_to not supported for pixels.");
- }
- else if(mem.type == MEM_TEXTURE) {
- tex_free(mem);
- tex_alloc(mem);
- }
- else {
- if(!mem.device_pointer) {
- generic_alloc(mem);
- }
-
- generic_copy_to(mem);
- }
- }
-
- void mem_copy_from(device_memory& mem, int y, int w, int h, int elem)
- {
- if(mem.type == MEM_PIXELS && !background) {
- pixels_copy_from(mem, y, w, h);
- }
- else if(mem.type == MEM_TEXTURE) {
- assert(!"mem_copy_from not supported for textures.");
- }
- else {
- CUDAContextScope scope(this);
- size_t offset = elem*y*w;
- size_t size = elem*w*h;
-
- if(mem.host_pointer && mem.device_pointer) {
- cuda_assert(cuMemcpyDtoH((uchar*)mem.host_pointer + offset,
- (CUdeviceptr)(mem.device_pointer + offset), size));
- }
- else if(mem.host_pointer) {
- memset((char*)mem.host_pointer + offset, 0, size);
- }
- }
- }
-
- void mem_zero(device_memory& mem)
- {
- if(!mem.device_pointer) {
- mem_alloc(mem);
- }
-
- if(mem.host_pointer) {
- memset(mem.host_pointer, 0, mem.memory_size());
- }
-
- if(mem.device_pointer &&
- (!mem.host_pointer || mem.host_pointer != mem.shared_pointer)) {
- CUDAContextScope scope(this);
- cuda_assert(cuMemsetD8(cuda_device_ptr(mem.device_pointer), 0, mem.memory_size()));
- }
- }
-
- void mem_free(device_memory& mem)
- {
- if(mem.type == MEM_PIXELS && !background) {
- pixels_free(mem);
- }
- else if(mem.type == MEM_TEXTURE) {
- tex_free(mem);
- }
- else {
- generic_free(mem);
- }
- }
-
- virtual device_ptr mem_alloc_sub_ptr(device_memory& mem, int offset, int /*size*/)
- {
- return (device_ptr) (((char*) mem.device_pointer) + mem.memory_elements_size(offset));
- }
-
- void const_copy_to(const char *name, void *host, size_t size)
- {
- CUDAContextScope scope(this);
- CUdeviceptr mem;
- size_t bytes;
-
- cuda_assert(cuModuleGetGlobal(&mem, &bytes, cuModule, name));
- //assert(bytes == size);
- cuda_assert(cuMemcpyHtoD(mem, host, size));
- }
-
- void tex_alloc(device_memory& mem)
- {
- CUDAContextScope scope(this);
-
- /* General variables for both architectures */
- string bind_name = mem.name;
- size_t dsize = datatype_size(mem.data_type);
- size_t size = mem.memory_size();
-
- CUaddress_mode address_mode = CU_TR_ADDRESS_MODE_WRAP;
- switch(mem.extension) {
- case EXTENSION_REPEAT:
- address_mode = CU_TR_ADDRESS_MODE_WRAP;
- break;
- case EXTENSION_EXTEND:
- address_mode = CU_TR_ADDRESS_MODE_CLAMP;
- break;
- case EXTENSION_CLIP:
- address_mode = CU_TR_ADDRESS_MODE_BORDER;
- break;
- default:
- assert(0);
- break;
- }
-
- CUfilter_mode filter_mode;
- if(mem.interpolation == INTERPOLATION_CLOSEST) {
- filter_mode = CU_TR_FILTER_MODE_POINT;
- }
- else {
- filter_mode = CU_TR_FILTER_MODE_LINEAR;
- }
-
- /* Data Storage */
- if(mem.interpolation == INTERPOLATION_NONE) {
- generic_alloc(mem);
- generic_copy_to(mem);
-
- CUdeviceptr cumem;
- size_t cubytes;
-
- cuda_assert(cuModuleGetGlobal(&cumem, &cubytes, cuModule, bind_name.c_str()));
-
- if(cubytes == 8) {
- /* 64 bit device pointer */
- uint64_t ptr = mem.device_pointer;
- cuda_assert(cuMemcpyHtoD(cumem, (void*)&ptr, cubytes));
- }
- else {
- /* 32 bit device pointer */
- uint32_t ptr = (uint32_t)mem.device_pointer;
- cuda_assert(cuMemcpyHtoD(cumem, (void*)&ptr, cubytes));
- }
- return;
- }
-
- /* Image Texture Storage */
- CUarray_format_enum format;
- switch(mem.data_type) {
- case TYPE_UCHAR: format = CU_AD_FORMAT_UNSIGNED_INT8; break;
- case TYPE_UINT16: format = CU_AD_FORMAT_UNSIGNED_INT16; break;
- case TYPE_UINT: format = CU_AD_FORMAT_UNSIGNED_INT32; break;
- case TYPE_INT: format = CU_AD_FORMAT_SIGNED_INT32; break;
- case TYPE_FLOAT: format = CU_AD_FORMAT_FLOAT; break;
- case TYPE_HALF: format = CU_AD_FORMAT_HALF; break;
- default: assert(0); return;
- }
-
- CUDAMem *cmem = NULL;
- CUarray array_3d = NULL;
- size_t src_pitch = mem.data_width * dsize * mem.data_elements;
- size_t dst_pitch = src_pitch;
-
- if(mem.data_depth > 1) {
- /* 3D texture using array, there is no API for linear memory. */
- CUDA_ARRAY3D_DESCRIPTOR desc;
-
- desc.Width = mem.data_width;
- desc.Height = mem.data_height;
- desc.Depth = mem.data_depth;
- desc.Format = format;
- desc.NumChannels = mem.data_elements;
- desc.Flags = 0;
-
- VLOG(1) << "Array 3D allocate: " << mem.name << ", "
- << string_human_readable_number(mem.memory_size()) << " bytes. ("
- << string_human_readable_size(mem.memory_size()) << ")";
-
- cuda_assert(cuArray3DCreate(&array_3d, &desc));
-
- if(!array_3d) {
- return;
- }
-
- CUDA_MEMCPY3D param;
- memset(&param, 0, sizeof(param));
- param.dstMemoryType = CU_MEMORYTYPE_ARRAY;
- param.dstArray = array_3d;
- param.srcMemoryType = CU_MEMORYTYPE_HOST;
- param.srcHost = mem.host_pointer;
- param.srcPitch = src_pitch;
- param.WidthInBytes = param.srcPitch;
- param.Height = mem.data_height;
- param.Depth = mem.data_depth;
-
- cuda_assert(cuMemcpy3D(&param));
-
- mem.device_pointer = (device_ptr)array_3d;
- mem.device_size = size;
- stats.mem_alloc(size);
-
- cmem = &cuda_mem_map[&mem];
- cmem->texobject = 0;
- cmem->array = array_3d;
- }
- else if(mem.data_height > 0) {
- /* 2D texture, using pitch aligned linear memory. */
- int alignment = 0;
- cuda_assert(cuDeviceGetAttribute(&alignment, CU_DEVICE_ATTRIBUTE_TEXTURE_PITCH_ALIGNMENT, cuDevice));
- dst_pitch = align_up(src_pitch, alignment);
- size_t dst_size = dst_pitch * mem.data_height;
-
- cmem = generic_alloc(mem, dst_size - mem.memory_size());
- if(!cmem) {
- return;
- }
-
- CUDA_MEMCPY2D param;
- memset(&param, 0, sizeof(param));
- param.dstMemoryType = CU_MEMORYTYPE_DEVICE;
- param.dstDevice = mem.device_pointer;
- param.dstPitch = dst_pitch;
- param.srcMemoryType = CU_MEMORYTYPE_HOST;
- param.srcHost = mem.host_pointer;
- param.srcPitch = src_pitch;
- param.WidthInBytes = param.srcPitch;
- param.Height = mem.data_height;
-
- cuda_assert(cuMemcpy2DUnaligned(&param));
- }
- else {
- /* 1D texture, using linear memory. */
- cmem = generic_alloc(mem);
- if(!cmem) {
- return;
- }
-
- cuda_assert(cuMemcpyHtoD(mem.device_pointer, mem.host_pointer, size));
- }
-
- /* Kepler+, bindless textures. */
- int flat_slot = 0;
- if(string_startswith(mem.name, "__tex_image")) {
- int pos = string(mem.name).rfind("_");
- flat_slot = atoi(mem.name + pos + 1);
- }
- else {
- assert(0);
- }
-
- CUDA_RESOURCE_DESC resDesc;
- memset(&resDesc, 0, sizeof(resDesc));
-
- if(array_3d) {
- resDesc.resType = CU_RESOURCE_TYPE_ARRAY;
- resDesc.res.array.hArray = array_3d;
- resDesc.flags = 0;
- }
- else if(mem.data_height > 0) {
- resDesc.resType = CU_RESOURCE_TYPE_PITCH2D;
- resDesc.res.pitch2D.devPtr = mem.device_pointer;
- resDesc.res.pitch2D.format = format;
- resDesc.res.pitch2D.numChannels = mem.data_elements;
- resDesc.res.pitch2D.height = mem.data_height;
- resDesc.res.pitch2D.width = mem.data_width;
- resDesc.res.pitch2D.pitchInBytes = dst_pitch;
- }
- else {
- resDesc.resType = CU_RESOURCE_TYPE_LINEAR;
- resDesc.res.linear.devPtr = mem.device_pointer;
- resDesc.res.linear.format = format;
- resDesc.res.linear.numChannels = mem.data_elements;
- resDesc.res.linear.sizeInBytes = mem.device_size;
- }
-
- CUDA_TEXTURE_DESC texDesc;
- memset(&texDesc, 0, sizeof(texDesc));
- texDesc.addressMode[0] = address_mode;
- texDesc.addressMode[1] = address_mode;
- texDesc.addressMode[2] = address_mode;
- texDesc.filterMode = filter_mode;
- texDesc.flags = CU_TRSF_NORMALIZED_COORDINATES;
-
- cuda_assert(cuTexObjectCreate(&cmem->texobject, &resDesc, &texDesc, NULL));
-
- /* Resize once */
- if(flat_slot >= texture_info.size()) {
- /* Allocate some slots in advance, to reduce amount
- * of re-allocations. */
- texture_info.resize(flat_slot + 128);
- }
-
- /* Set Mapping and tag that we need to (re-)upload to device */
- TextureInfo& info = texture_info[flat_slot];
- info.data = (uint64_t)cmem->texobject;
- info.cl_buffer = 0;
- info.interpolation = mem.interpolation;
- info.extension = mem.extension;
- info.width = mem.data_width;
- info.height = mem.data_height;
- info.depth = mem.data_depth;
- need_texture_info = true;
- }
-
- void tex_free(device_memory& mem)
- {
- if(mem.device_pointer) {
- CUDAContextScope scope(this);
- const CUDAMem& cmem = cuda_mem_map[&mem];
-
- if(cmem.texobject) {
- /* Free bindless texture. */
- cuTexObjectDestroy(cmem.texobject);
- }
-
- if(cmem.array) {
- /* Free array. */
- cuArrayDestroy(cmem.array);
- stats.mem_free(mem.device_size);
- mem.device_pointer = 0;
- mem.device_size = 0;
-
- cuda_mem_map.erase(cuda_mem_map.find(&mem));
- }
- else {
- generic_free(mem);
- }
- }
- }
-
-#define CUDA_GET_BLOCKSIZE(func, w, h) \
- int threads_per_block; \
- cuda_assert(cuFuncGetAttribute(&threads_per_block, CU_FUNC_ATTRIBUTE_MAX_THREADS_PER_BLOCK, func)); \
- int threads = (int)sqrt((float)threads_per_block); \
- int xblocks = ((w) + threads - 1)/threads; \
- int yblocks = ((h) + threads - 1)/threads;
-
-#define CUDA_LAUNCH_KERNEL(func, args) \
- cuda_assert(cuLaunchKernel(func, \
- xblocks, yblocks, 1, \
- threads, threads, 1, \
- 0, 0, args, 0));
+ }
+
+ void init_host_memory()
+ {
+ /* Limit amount of host mapped memory, because allocating too much can
+ * cause system instability. Leave at least half or 4 GB of system
+ * memory free, whichever is smaller. */
+ size_t default_limit = 4 * 1024 * 1024 * 1024LL;
+ size_t system_ram = system_physical_ram();
+
+ if (system_ram > 0) {
+ if (system_ram / 2 > default_limit) {
+ map_host_limit = system_ram - default_limit;
+ }
+ else {
+ map_host_limit = system_ram / 2;
+ }
+ }
+ else {
+ VLOG(1) << "Mapped host memory disabled, failed to get system RAM";
+ map_host_limit = 0;
+ }
+
+ /* Amount of device memory to keep is free after texture memory
+ * and working memory allocations respectively. We set the working
+ * memory limit headroom lower so that some space is left after all
+ * texture memory allocations. */
+ device_working_headroom = 32 * 1024 * 1024LL; // 32MB
+ device_texture_headroom = 128 * 1024 * 1024LL; // 128MB
+
+ VLOG(1) << "Mapped host memory limit set to " << string_human_readable_number(map_host_limit)
+ << " bytes. (" << string_human_readable_size(map_host_limit) << ")";
+ }
+
+ void load_texture_info()
+ {
+ if (need_texture_info) {
+ texture_info.copy_to_device();
+ need_texture_info = false;
+ }
+ }
+
+ void move_textures_to_host(size_t size, bool for_texture)
+ {
+ /* Signal to reallocate textures in host memory only. */
+ move_texture_to_host = true;
+
+ while (size > 0) {
+ /* Find suitable memory allocation to move. */
+ device_memory *max_mem = NULL;
+ size_t max_size = 0;
+ bool max_is_image = false;
+
+ foreach (CUDAMemMap::value_type &pair, cuda_mem_map) {
+ device_memory &mem = *pair.first;
+ CUDAMem *cmem = &pair.second;
+
+ bool is_texture = (mem.type == MEM_TEXTURE) && (&mem != &texture_info);
+ bool is_image = is_texture && (mem.data_height > 1);
+
+ /* Can't move this type of memory. */
+ if (!is_texture || cmem->array) {
+ continue;
+ }
+
+ /* Already in host memory. */
+ if (cmem->map_host_pointer) {
+ continue;
+ }
+
+ /* For other textures, only move image textures. */
+ if (for_texture && !is_image) {
+ continue;
+ }
+
+ /* Try to move largest allocation, prefer moving images. */
+ if (is_image > max_is_image || (is_image == max_is_image && mem.device_size > max_size)) {
+ max_is_image = is_image;
+ max_size = mem.device_size;
+ max_mem = &mem;
+ }
+ }
+
+ /* Move to host memory. This part is mutex protected since
+ * multiple CUDA devices could be moving the memory. The
+ * first one will do it, and the rest will adopt the pointer. */
+ if (max_mem) {
+ VLOG(1) << "Move memory from device to host: " << max_mem->name;
+
+ static thread_mutex move_mutex;
+ thread_scoped_lock lock(move_mutex);
+
+ /* Preserve the original device pointer, in case of multi device
+ * we can't change it because the pointer mapping would break. */
+ device_ptr prev_pointer = max_mem->device_pointer;
+ size_t prev_size = max_mem->device_size;
+
+ tex_free(*max_mem);
+ tex_alloc(*max_mem);
+ size = (max_size >= size) ? 0 : size - max_size;
+
+ max_mem->device_pointer = prev_pointer;
+ max_mem->device_size = prev_size;
+ }
+ else {
+ break;
+ }
+ }
+
+ /* Update texture info array with new pointers. */
+ load_texture_info();
+
+ move_texture_to_host = false;
+ }
+
+ CUDAMem *generic_alloc(device_memory &mem, size_t pitch_padding = 0)
+ {
+ CUDAContextScope scope(this);
+
+ CUdeviceptr device_pointer = 0;
+ size_t size = mem.memory_size() + pitch_padding;
+
+ CUresult mem_alloc_result = CUDA_ERROR_OUT_OF_MEMORY;
+ const char *status = "";
+
+ /* First try allocating in device memory, respecting headroom. We make
+ * an exception for texture info. It is small and frequently accessed,
+ * so treat it as working memory.
+ *
+ * If there is not enough room for working memory, we will try to move
+ * textures to host memory, assuming the performance impact would have
+ * been worse for working memory. */
+ bool is_texture = (mem.type == MEM_TEXTURE) && (&mem != &texture_info);
+ bool is_image = is_texture && (mem.data_height > 1);
+
+ size_t headroom = (is_texture) ? device_texture_headroom : device_working_headroom;
+
+ size_t total = 0, free = 0;
+ cuMemGetInfo(&free, &total);
+
+ /* Move textures to host memory if needed. */
+ if (!move_texture_to_host && !is_image && (size + headroom) >= free) {
+ move_textures_to_host(size + headroom - free, is_texture);
+ cuMemGetInfo(&free, &total);
+ }
+
+ /* Allocate in device memory. */
+ if (!move_texture_to_host && (size + headroom) < free) {
+ mem_alloc_result = cuMemAlloc(&device_pointer, size);
+ if (mem_alloc_result == CUDA_SUCCESS) {
+ status = " in device memory";
+ }
+ }
+
+ /* Fall back to mapped host memory if needed and possible. */
+ void *map_host_pointer = 0;
+ bool free_map_host = false;
+
+ if (mem_alloc_result != CUDA_SUCCESS && can_map_host &&
+ map_host_used + size < map_host_limit) {
+ if (mem.shared_pointer) {
+ /* Another device already allocated host memory. */
+ mem_alloc_result = CUDA_SUCCESS;
+ map_host_pointer = mem.shared_pointer;
+ }
+ else {
+ /* Allocate host memory ourselves. */
+ mem_alloc_result = cuMemHostAlloc(
+ &map_host_pointer, size, CU_MEMHOSTALLOC_DEVICEMAP | CU_MEMHOSTALLOC_WRITECOMBINED);
+ mem.shared_pointer = map_host_pointer;
+ free_map_host = true;
+ }
+
+ if (mem_alloc_result == CUDA_SUCCESS) {
+ cuda_assert(cuMemHostGetDevicePointer_v2(&device_pointer, mem.shared_pointer, 0));
+ map_host_used += size;
+ status = " in host memory";
+
+ /* Replace host pointer with our host allocation. Only works if
+ * CUDA memory layout is the same and has no pitch padding. Also
+ * does not work if we move textures to host during a render,
+ * since other devices might be using the memory. */
+ if (!move_texture_to_host && pitch_padding == 0 && mem.host_pointer &&
+ mem.host_pointer != mem.shared_pointer) {
+ memcpy(mem.shared_pointer, mem.host_pointer, size);
+ mem.host_free();
+ mem.host_pointer = mem.shared_pointer;
+ }
+ }
+ else {
+ status = " failed, out of host memory";
+ }
+ }
+ else if (mem_alloc_result != CUDA_SUCCESS) {
+ status = " failed, out of device and host memory";
+ }
+
+ if (mem_alloc_result != CUDA_SUCCESS) {
+ cuda_assert(mem_alloc_result);
+ }
+
+ if (mem.name) {
+ VLOG(1) << "Buffer allocate: " << mem.name << ", "
+ << string_human_readable_number(mem.memory_size()) << " bytes. ("
+ << string_human_readable_size(mem.memory_size()) << ")" << status;
+ }
+
+ mem.device_pointer = (device_ptr)device_pointer;
+ mem.device_size = size;
+ stats.mem_alloc(size);
+
+ if (!mem.device_pointer) {
+ return NULL;
+ }
+
+ /* Insert into map of allocations. */
+ CUDAMem *cmem = &cuda_mem_map[&mem];
+ cmem->map_host_pointer = map_host_pointer;
+ cmem->free_map_host = free_map_host;
+ return cmem;
+ }
+
+ void generic_copy_to(device_memory &mem)
+ {
+ if (mem.host_pointer && mem.device_pointer) {
+ CUDAContextScope scope(this);
+
+ if (mem.host_pointer != mem.shared_pointer) {
+ cuda_assert(cuMemcpyHtoD(
+ cuda_device_ptr(mem.device_pointer), mem.host_pointer, mem.memory_size()));
+ }
+ }
+ }
+
+ void generic_free(device_memory &mem)
+ {
+ if (mem.device_pointer) {
+ CUDAContextScope scope(this);
+ const CUDAMem &cmem = cuda_mem_map[&mem];
+
+ if (cmem.map_host_pointer) {
+ /* Free host memory. */
+ if (cmem.free_map_host) {
+ cuMemFreeHost(cmem.map_host_pointer);
+ if (mem.host_pointer == mem.shared_pointer) {
+ mem.host_pointer = 0;
+ }
+ mem.shared_pointer = 0;
+ }
+
+ map_host_used -= mem.device_size;
+ }
+ else {
+ /* Free device memory. */
+ cuMemFree(mem.device_pointer);
+ }
+
+ stats.mem_free(mem.device_size);
+ mem.device_pointer = 0;
+ mem.device_size = 0;
+
+ cuda_mem_map.erase(cuda_mem_map.find(&mem));
+ }
+ }
+
+ void mem_alloc(device_memory &mem)
+ {
+ if (mem.type == MEM_PIXELS && !background) {
+ pixels_alloc(mem);
+ }
+ else if (mem.type == MEM_TEXTURE) {
+ assert(!"mem_alloc not supported for textures.");
+ }
+ else {
+ generic_alloc(mem);
+ }
+ }
+
+ void mem_copy_to(device_memory &mem)
+ {
+ if (mem.type == MEM_PIXELS) {
+ assert(!"mem_copy_to not supported for pixels.");
+ }
+ else if (mem.type == MEM_TEXTURE) {
+ tex_free(mem);
+ tex_alloc(mem);
+ }
+ else {
+ if (!mem.device_pointer) {
+ generic_alloc(mem);
+ }
+
+ generic_copy_to(mem);
+ }
+ }
+
+ void mem_copy_from(device_memory &mem, int y, int w, int h, int elem)
+ {
+ if (mem.type == MEM_PIXELS && !background) {
+ pixels_copy_from(mem, y, w, h);
+ }
+ else if (mem.type == MEM_TEXTURE) {
+ assert(!"mem_copy_from not supported for textures.");
+ }
+ else {
+ CUDAContextScope scope(this);
+ size_t offset = elem * y * w;
+ size_t size = elem * w * h;
+
+ if (mem.host_pointer && mem.device_pointer) {
+ cuda_assert(cuMemcpyDtoH(
+ (uchar *)mem.host_pointer + offset, (CUdeviceptr)(mem.device_pointer + offset), size));
+ }
+ else if (mem.host_pointer) {
+ memset((char *)mem.host_pointer + offset, 0, size);
+ }
+ }
+ }
+
+ void mem_zero(device_memory &mem)
+ {
+ if (!mem.device_pointer) {
+ mem_alloc(mem);
+ }
+
+ if (mem.host_pointer) {
+ memset(mem.host_pointer, 0, mem.memory_size());
+ }
+
+ if (mem.device_pointer && (!mem.host_pointer || mem.host_pointer != mem.shared_pointer)) {
+ CUDAContextScope scope(this);
+ cuda_assert(cuMemsetD8(cuda_device_ptr(mem.device_pointer), 0, mem.memory_size()));
+ }
+ }
+
+ void mem_free(device_memory &mem)
+ {
+ if (mem.type == MEM_PIXELS && !background) {
+ pixels_free(mem);
+ }
+ else if (mem.type == MEM_TEXTURE) {
+ tex_free(mem);
+ }
+ else {
+ generic_free(mem);
+ }
+ }
+
+ virtual device_ptr mem_alloc_sub_ptr(device_memory &mem, int offset, int /*size*/)
+ {
+ return (device_ptr)(((char *)mem.device_pointer) + mem.memory_elements_size(offset));
+ }
+
+ void const_copy_to(const char *name, void *host, size_t size)
+ {
+ CUDAContextScope scope(this);
+ CUdeviceptr mem;
+ size_t bytes;
+
+ cuda_assert(cuModuleGetGlobal(&mem, &bytes, cuModule, name));
+ //assert(bytes == size);
+ cuda_assert(cuMemcpyHtoD(mem, host, size));
+ }
+
+ void tex_alloc(device_memory &mem)
+ {
+ CUDAContextScope scope(this);
+
+ /* General variables for both architectures */
+ string bind_name = mem.name;
+ size_t dsize = datatype_size(mem.data_type);
+ size_t size = mem.memory_size();
+
+ CUaddress_mode address_mode = CU_TR_ADDRESS_MODE_WRAP;
+ switch (mem.extension) {
+ case EXTENSION_REPEAT:
+ address_mode = CU_TR_ADDRESS_MODE_WRAP;
+ break;
+ case EXTENSION_EXTEND:
+ address_mode = CU_TR_ADDRESS_MODE_CLAMP;
+ break;
+ case EXTENSION_CLIP:
+ address_mode = CU_TR_ADDRESS_MODE_BORDER;
+ break;
+ default:
+ assert(0);
+ break;
+ }
+
+ CUfilter_mode filter_mode;
+ if (mem.interpolation == INTERPOLATION_CLOSEST) {
+ filter_mode = CU_TR_FILTER_MODE_POINT;
+ }
+ else {
+ filter_mode = CU_TR_FILTER_MODE_LINEAR;
+ }
+
+ /* Data Storage */
+ if (mem.interpolation == INTERPOLATION_NONE) {
+ generic_alloc(mem);
+ generic_copy_to(mem);
+
+ CUdeviceptr cumem;
+ size_t cubytes;
+
+ cuda_assert(cuModuleGetGlobal(&cumem, &cubytes, cuModule, bind_name.c_str()));
+
+ if (cubytes == 8) {
+ /* 64 bit device pointer */
+ uint64_t ptr = mem.device_pointer;
+ cuda_assert(cuMemcpyHtoD(cumem, (void *)&ptr, cubytes));
+ }
+ else {
+ /* 32 bit device pointer */
+ uint32_t ptr = (uint32_t)mem.device_pointer;
+ cuda_assert(cuMemcpyHtoD(cumem, (void *)&ptr, cubytes));
+ }
+ return;
+ }
+
+ /* Image Texture Storage */
+ CUarray_format_enum format;
+ switch (mem.data_type) {
+ case TYPE_UCHAR:
+ format = CU_AD_FORMAT_UNSIGNED_INT8;
+ break;
+ case TYPE_UINT16:
+ format = CU_AD_FORMAT_UNSIGNED_INT16;
+ break;
+ case TYPE_UINT:
+ format = CU_AD_FORMAT_UNSIGNED_INT32;
+ break;
+ case TYPE_INT:
+ format = CU_AD_FORMAT_SIGNED_INT32;
+ break;
+ case TYPE_FLOAT:
+ format = CU_AD_FORMAT_FLOAT;
+ break;
+ case TYPE_HALF:
+ format = CU_AD_FORMAT_HALF;
+ break;
+ default:
+ assert(0);
+ return;
+ }
+
+ CUDAMem *cmem = NULL;
+ CUarray array_3d = NULL;
+ size_t src_pitch = mem.data_width * dsize * mem.data_elements;
+ size_t dst_pitch = src_pitch;
+
+ if (mem.data_depth > 1) {
+ /* 3D texture using array, there is no API for linear memory. */
+ CUDA_ARRAY3D_DESCRIPTOR desc;
+
+ desc.Width = mem.data_width;
+ desc.Height = mem.data_height;
+ desc.Depth = mem.data_depth;
+ desc.Format = format;
+ desc.NumChannels = mem.data_elements;
+ desc.Flags = 0;
+
+ VLOG(1) << "Array 3D allocate: " << mem.name << ", "
+ << string_human_readable_number(mem.memory_size()) << " bytes. ("
+ << string_human_readable_size(mem.memory_size()) << ")";
+
+ cuda_assert(cuArray3DCreate(&array_3d, &desc));
+
+ if (!array_3d) {
+ return;
+ }
+
+ CUDA_MEMCPY3D param;
+ memset(&param, 0, sizeof(param));
+ param.dstMemoryType = CU_MEMORYTYPE_ARRAY;
+ param.dstArray = array_3d;
+ param.srcMemoryType = CU_MEMORYTYPE_HOST;
+ param.srcHost = mem.host_pointer;
+ param.srcPitch = src_pitch;
+ param.WidthInBytes = param.srcPitch;
+ param.Height = mem.data_height;
+ param.Depth = mem.data_depth;
+
+ cuda_assert(cuMemcpy3D(&param));
+
+ mem.device_pointer = (device_ptr)array_3d;
+ mem.device_size = size;
+ stats.mem_alloc(size);
+
+ cmem = &cuda_mem_map[&mem];
+ cmem->texobject = 0;
+ cmem->array = array_3d;
+ }
+ else if (mem.data_height > 0) {
+ /* 2D texture, using pitch aligned linear memory. */
+ int alignment = 0;
+ cuda_assert(
+ cuDeviceGetAttribute(&alignment, CU_DEVICE_ATTRIBUTE_TEXTURE_PITCH_ALIGNMENT, cuDevice));
+ dst_pitch = align_up(src_pitch, alignment);
+ size_t dst_size = dst_pitch * mem.data_height;
+
+ cmem = generic_alloc(mem, dst_size - mem.memory_size());
+ if (!cmem) {
+ return;
+ }
+
+ CUDA_MEMCPY2D param;
+ memset(&param, 0, sizeof(param));
+ param.dstMemoryType = CU_MEMORYTYPE_DEVICE;
+ param.dstDevice = mem.device_pointer;
+ param.dstPitch = dst_pitch;
+ param.srcMemoryType = CU_MEMORYTYPE_HOST;
+ param.srcHost = mem.host_pointer;
+ param.srcPitch = src_pitch;
+ param.WidthInBytes = param.srcPitch;
+ param.Height = mem.data_height;
+
+ cuda_assert(cuMemcpy2DUnaligned(&param));
+ }
+ else {
+ /* 1D texture, using linear memory. */
+ cmem = generic_alloc(mem);
+ if (!cmem) {
+ return;
+ }
+
+ cuda_assert(cuMemcpyHtoD(mem.device_pointer, mem.host_pointer, size));
+ }
+
+ /* Kepler+, bindless textures. */
+ int flat_slot = 0;
+ if (string_startswith(mem.name, "__tex_image")) {
+ int pos = string(mem.name).rfind("_");
+ flat_slot = atoi(mem.name + pos + 1);
+ }
+ else {
+ assert(0);
+ }
+
+ CUDA_RESOURCE_DESC resDesc;
+ memset(&resDesc, 0, sizeof(resDesc));
+
+ if (array_3d) {
+ resDesc.resType = CU_RESOURCE_TYPE_ARRAY;
+ resDesc.res.array.hArray = array_3d;
+ resDesc.flags = 0;
+ }
+ else if (mem.data_height > 0) {
+ resDesc.resType = CU_RESOURCE_TYPE_PITCH2D;
+ resDesc.res.pitch2D.devPtr = mem.device_pointer;
+ resDesc.res.pitch2D.format = format;
+ resDesc.res.pitch2D.numChannels = mem.data_elements;
+ resDesc.res.pitch2D.height = mem.data_height;
+ resDesc.res.pitch2D.width = mem.data_width;
+ resDesc.res.pitch2D.pitchInBytes = dst_pitch;
+ }
+ else {
+ resDesc.resType = CU_RESOURCE_TYPE_LINEAR;
+ resDesc.res.linear.devPtr = mem.device_pointer;
+ resDesc.res.linear.format = format;
+ resDesc.res.linear.numChannels = mem.data_elements;
+ resDesc.res.linear.sizeInBytes = mem.device_size;
+ }
+
+ CUDA_TEXTURE_DESC texDesc;
+ memset(&texDesc, 0, sizeof(texDesc));
+ texDesc.addressMode[0] = address_mode;
+ texDesc.addressMode[1] = address_mode;
+ texDesc.addressMode[2] = address_mode;
+ texDesc.filterMode = filter_mode;
+ texDesc.flags = CU_TRSF_NORMALIZED_COORDINATES;
+
+ cuda_assert(cuTexObjectCreate(&cmem->texobject, &resDesc, &texDesc, NULL));
+
+ /* Resize once */
+ if (flat_slot >= texture_info.size()) {
+ /* Allocate some slots in advance, to reduce amount
+ * of re-allocations. */
+ texture_info.resize(flat_slot + 128);
+ }
+
+ /* Set Mapping and tag that we need to (re-)upload to device */
+ TextureInfo &info = texture_info[flat_slot];
+ info.data = (uint64_t)cmem->texobject;
+ info.cl_buffer = 0;
+ info.interpolation = mem.interpolation;
+ info.extension = mem.extension;
+ info.width = mem.data_width;
+ info.height = mem.data_height;
+ info.depth = mem.data_depth;
+ need_texture_info = true;
+ }
+
+ void tex_free(device_memory &mem)
+ {
+ if (mem.device_pointer) {
+ CUDAContextScope scope(this);
+ const CUDAMem &cmem = cuda_mem_map[&mem];
+
+ if (cmem.texobject) {
+ /* Free bindless texture. */
+ cuTexObjectDestroy(cmem.texobject);
+ }
+
+ if (cmem.array) {
+ /* Free array. */
+ cuArrayDestroy(cmem.array);
+ stats.mem_free(mem.device_size);
+ mem.device_pointer = 0;
+ mem.device_size = 0;
+
+ cuda_mem_map.erase(cuda_mem_map.find(&mem));
+ }
+ else {
+ generic_free(mem);
+ }
+ }
+ }
+
+#define CUDA_GET_BLOCKSIZE(func, w, h) \
+ int threads_per_block; \
+ cuda_assert( \
+ cuFuncGetAttribute(&threads_per_block, CU_FUNC_ATTRIBUTE_MAX_THREADS_PER_BLOCK, func)); \
+ int threads = (int)sqrt((float)threads_per_block); \
+ int xblocks = ((w) + threads - 1) / threads; \
+ int yblocks = ((h) + threads - 1) / threads;
+
+#define CUDA_LAUNCH_KERNEL(func, args) \
+ cuda_assert(cuLaunchKernel(func, xblocks, yblocks, 1, threads, threads, 1, 0, 0, args, 0));
/* Similar as above, but for 1-dimensional blocks. */
-#define CUDA_GET_BLOCKSIZE_1D(func, w, h) \
- int threads_per_block; \
- cuda_assert(cuFuncGetAttribute(&threads_per_block, CU_FUNC_ATTRIBUTE_MAX_THREADS_PER_BLOCK, func)); \
- int xblocks = ((w) + threads_per_block - 1)/threads_per_block; \
- int yblocks = h;
-
-#define CUDA_LAUNCH_KERNEL_1D(func, args) \
- cuda_assert(cuLaunchKernel(func, \
- xblocks, yblocks, 1, \
- threads_per_block, 1, 1, \
- 0, 0, args, 0));
-
- bool denoising_non_local_means(device_ptr image_ptr, device_ptr guide_ptr, device_ptr variance_ptr, device_ptr out_ptr,
- DenoisingTask *task)
- {
- if(have_error())
- return false;
-
- CUDAContextScope scope(this);
-
- int stride = task->buffer.stride;
- int w = task->buffer.width;
- int h = task->buffer.h;
- int r = task->nlm_state.r;
- int f = task->nlm_state.f;
- float a = task->nlm_state.a;
- float k_2 = task->nlm_state.k_2;
-
- int pass_stride = task->buffer.pass_stride;
- int num_shifts = (2*r+1)*(2*r+1);
- int channel_offset = task->nlm_state.is_color? task->buffer.pass_stride : 0;
- int frame_offset = 0;
-
- if(have_error())
- return false;
-
- CUdeviceptr difference = cuda_device_ptr(task->buffer.temporary_mem.device_pointer);
- CUdeviceptr blurDifference = difference + sizeof(float)*pass_stride*num_shifts;
- CUdeviceptr weightAccum = difference + 2*sizeof(float)*pass_stride*num_shifts;
- CUdeviceptr scale_ptr = 0;
-
- cuda_assert(cuMemsetD8(weightAccum, 0, sizeof(float)*pass_stride));
- cuda_assert(cuMemsetD8(out_ptr, 0, sizeof(float)*pass_stride));
-
- {
- CUfunction cuNLMCalcDifference, cuNLMBlur, cuNLMCalcWeight, cuNLMUpdateOutput;
- cuda_assert(cuModuleGetFunction(&cuNLMCalcDifference, cuFilterModule, "kernel_cuda_filter_nlm_calc_difference"));
- cuda_assert(cuModuleGetFunction(&cuNLMBlur, cuFilterModule, "kernel_cuda_filter_nlm_blur"));
- cuda_assert(cuModuleGetFunction(&cuNLMCalcWeight, cuFilterModule, "kernel_cuda_filter_nlm_calc_weight"));
- cuda_assert(cuModuleGetFunction(&cuNLMUpdateOutput, cuFilterModule, "kernel_cuda_filter_nlm_update_output"));
-
- cuda_assert(cuFuncSetCacheConfig(cuNLMCalcDifference, CU_FUNC_CACHE_PREFER_L1));
- cuda_assert(cuFuncSetCacheConfig(cuNLMBlur, CU_FUNC_CACHE_PREFER_L1));
- cuda_assert(cuFuncSetCacheConfig(cuNLMCalcWeight, CU_FUNC_CACHE_PREFER_L1));
- cuda_assert(cuFuncSetCacheConfig(cuNLMUpdateOutput, CU_FUNC_CACHE_PREFER_L1));
-
- CUDA_GET_BLOCKSIZE_1D(cuNLMCalcDifference, w*h, num_shifts);
-
- void *calc_difference_args[] = {&guide_ptr, &variance_ptr, &scale_ptr, &difference, &w, &h, &stride, &pass_stride, &r, &channel_offset, &frame_offset, &a, &k_2};
- void *blur_args[] = {&difference, &blurDifference, &w, &h, &stride, &pass_stride, &r, &f};
- void *calc_weight_args[] = {&blurDifference, &difference, &w, &h, &stride, &pass_stride, &r, &f};
- void *update_output_args[] = {&blurDifference, &image_ptr, &out_ptr, &weightAccum, &w, &h, &stride, &pass_stride, &channel_offset, &r, &f};
-
- CUDA_LAUNCH_KERNEL_1D(cuNLMCalcDifference, calc_difference_args);
- CUDA_LAUNCH_KERNEL_1D(cuNLMBlur, blur_args);
- CUDA_LAUNCH_KERNEL_1D(cuNLMCalcWeight, calc_weight_args);
- CUDA_LAUNCH_KERNEL_1D(cuNLMBlur, blur_args);
- CUDA_LAUNCH_KERNEL_1D(cuNLMUpdateOutput, update_output_args);
- }
-
- {
- CUfunction cuNLMNormalize;
- cuda_assert(cuModuleGetFunction(&cuNLMNormalize, cuFilterModule, "kernel_cuda_filter_nlm_normalize"));
- cuda_assert(cuFuncSetCacheConfig(cuNLMNormalize, CU_FUNC_CACHE_PREFER_L1));
- void *normalize_args[] = {&out_ptr, &weightAccum, &w, &h, &stride};
- CUDA_GET_BLOCKSIZE(cuNLMNormalize, w, h);
- CUDA_LAUNCH_KERNEL(cuNLMNormalize, normalize_args);
- cuda_assert(cuCtxSynchronize());
- }
-
- return !have_error();
- }
-
- bool denoising_construct_transform(DenoisingTask *task)
- {
- if(have_error())
- return false;
-
- CUDAContextScope scope(this);
-
- CUfunction cuFilterConstructTransform;
- cuda_assert(cuModuleGetFunction(&cuFilterConstructTransform, cuFilterModule, "kernel_cuda_filter_construct_transform"));
- cuda_assert(cuFuncSetCacheConfig(cuFilterConstructTransform, CU_FUNC_CACHE_PREFER_SHARED));
- CUDA_GET_BLOCKSIZE(cuFilterConstructTransform,
- task->storage.w,
- task->storage.h);
-
- void *args[] = {&task->buffer.mem.device_pointer,
- &task->tile_info_mem.device_pointer,
- &task->storage.transform.device_pointer,
- &task->storage.rank.device_pointer,
- &task->filter_area,
- &task->rect,
- &task->radius,
- &task->pca_threshold,
- &task->buffer.pass_stride,
- &task->buffer.frame_stride,
- &task->buffer.use_time};
- CUDA_LAUNCH_KERNEL(cuFilterConstructTransform, args);
- cuda_assert(cuCtxSynchronize());
-
- return !have_error();
- }
-
- bool denoising_accumulate(device_ptr color_ptr,
- device_ptr color_variance_ptr,
- device_ptr scale_ptr,
- int frame,
- DenoisingTask *task)
- {
- if(have_error())
- return false;
-
- CUDAContextScope scope(this);
-
- int r = task->radius;
- int f = 4;
- float a = 1.0f;
- float k_2 = task->nlm_k_2;
-
- int w = task->reconstruction_state.source_w;
- int h = task->reconstruction_state.source_h;
- int stride = task->buffer.stride;
- int frame_offset = frame * task->buffer.frame_stride;
- int t = task->tile_info->frames[frame];
-
- int pass_stride = task->buffer.pass_stride;
- int num_shifts = (2*r+1)*(2*r+1);
-
- if(have_error())
- return false;
-
- CUdeviceptr difference = cuda_device_ptr(task->buffer.temporary_mem.device_pointer);
- CUdeviceptr blurDifference = difference + sizeof(float)*pass_stride*num_shifts;
-
- CUfunction cuNLMCalcDifference, cuNLMBlur, cuNLMCalcWeight, cuNLMConstructGramian;
- cuda_assert(cuModuleGetFunction(&cuNLMCalcDifference, cuFilterModule, "kernel_cuda_filter_nlm_calc_difference"));
- cuda_assert(cuModuleGetFunction(&cuNLMBlur, cuFilterModule, "kernel_cuda_filter_nlm_blur"));
- cuda_assert(cuModuleGetFunction(&cuNLMCalcWeight, cuFilterModule, "kernel_cuda_filter_nlm_calc_weight"));
- cuda_assert(cuModuleGetFunction(&cuNLMConstructGramian, cuFilterModule, "kernel_cuda_filter_nlm_construct_gramian"));
-
- cuda_assert(cuFuncSetCacheConfig(cuNLMCalcDifference, CU_FUNC_CACHE_PREFER_L1));
- cuda_assert(cuFuncSetCacheConfig(cuNLMBlur, CU_FUNC_CACHE_PREFER_L1));
- cuda_assert(cuFuncSetCacheConfig(cuNLMCalcWeight, CU_FUNC_CACHE_PREFER_L1));
- cuda_assert(cuFuncSetCacheConfig(cuNLMConstructGramian, CU_FUNC_CACHE_PREFER_SHARED));
-
- CUDA_GET_BLOCKSIZE_1D(cuNLMCalcDifference,
- task->reconstruction_state.source_w * task->reconstruction_state.source_h,
- num_shifts);
-
- void *calc_difference_args[] = {&color_ptr,
- &color_variance_ptr,
- &scale_ptr,
- &difference,
- &w, &h,
- &stride, &pass_stride,
- &r, &pass_stride,
- &frame_offset,
- &a, &k_2};
- void *blur_args[] = {&difference, &blurDifference, &w, &h, &stride, &pass_stride, &r, &f};
- void *calc_weight_args[] = {&blurDifference, &difference, &w, &h, &stride, &pass_stride, &r, &f};
- void *construct_gramian_args[] = {&t,
- &blurDifference,
- &task->buffer.mem.device_pointer,
- &task->storage.transform.device_pointer,
- &task->storage.rank.device_pointer,
- &task->storage.XtWX.device_pointer,
- &task->storage.XtWY.device_pointer,
- &task->reconstruction_state.filter_window,
- &w, &h, &stride,
- &pass_stride, &r,
- &f,
- &frame_offset,
- &task->buffer.use_time};
-
- CUDA_LAUNCH_KERNEL_1D(cuNLMCalcDifference, calc_difference_args);
- CUDA_LAUNCH_KERNEL_1D(cuNLMBlur, blur_args);
- CUDA_LAUNCH_KERNEL_1D(cuNLMCalcWeight, calc_weight_args);
- CUDA_LAUNCH_KERNEL_1D(cuNLMBlur, blur_args);
- CUDA_LAUNCH_KERNEL_1D(cuNLMConstructGramian, construct_gramian_args);
- cuda_assert(cuCtxSynchronize());
-
- return !have_error();
- }
-
- bool denoising_solve(device_ptr output_ptr,
- DenoisingTask *task)
- {
- CUfunction cuFinalize;
- cuda_assert(cuModuleGetFunction(&cuFinalize, cuFilterModule, "kernel_cuda_filter_finalize"));
- cuda_assert(cuFuncSetCacheConfig(cuFinalize, CU_FUNC_CACHE_PREFER_L1));
- void *finalize_args[] = {&output_ptr,
- &task->storage.rank.device_pointer,
- &task->storage.XtWX.device_pointer,
- &task->storage.XtWY.device_pointer,
- &task->filter_area,
- &task->reconstruction_state.buffer_params.x,
- &task->render_buffer.samples};
- CUDA_GET_BLOCKSIZE(cuFinalize,
- task->reconstruction_state.source_w,
- task->reconstruction_state.source_h);
- CUDA_LAUNCH_KERNEL(cuFinalize, finalize_args);
- cuda_assert(cuCtxSynchronize());
-
- return !have_error();
- }
-
- bool denoising_combine_halves(device_ptr a_ptr, device_ptr b_ptr,
- device_ptr mean_ptr, device_ptr variance_ptr,
- int r, int4 rect, DenoisingTask *task)
- {
- if(have_error())
- return false;
-
- CUDAContextScope scope(this);
-
- CUfunction cuFilterCombineHalves;
- cuda_assert(cuModuleGetFunction(&cuFilterCombineHalves, cuFilterModule, "kernel_cuda_filter_combine_halves"));
- cuda_assert(cuFuncSetCacheConfig(cuFilterCombineHalves, CU_FUNC_CACHE_PREFER_L1));
- CUDA_GET_BLOCKSIZE(cuFilterCombineHalves,
- task->rect.z-task->rect.x,
- task->rect.w-task->rect.y);
-
- void *args[] = {&mean_ptr,
- &variance_ptr,
- &a_ptr,
- &b_ptr,
- &rect,
- &r};
- CUDA_LAUNCH_KERNEL(cuFilterCombineHalves, args);
- cuda_assert(cuCtxSynchronize());
-
- return !have_error();
- }
-
- bool denoising_divide_shadow(device_ptr a_ptr, device_ptr b_ptr,
- device_ptr sample_variance_ptr, device_ptr sv_variance_ptr,
- device_ptr buffer_variance_ptr, DenoisingTask *task)
- {
- if(have_error())
- return false;
-
- CUDAContextScope scope(this);
-
- CUfunction cuFilterDivideShadow;
- cuda_assert(cuModuleGetFunction(&cuFilterDivideShadow, cuFilterModule, "kernel_cuda_filter_divide_shadow"));
- cuda_assert(cuFuncSetCacheConfig(cuFilterDivideShadow, CU_FUNC_CACHE_PREFER_L1));
- CUDA_GET_BLOCKSIZE(cuFilterDivideShadow,
- task->rect.z-task->rect.x,
- task->rect.w-task->rect.y);
-
- void *args[] = {&task->render_buffer.samples,
- &task->tile_info_mem.device_pointer,
- &a_ptr,
- &b_ptr,
- &sample_variance_ptr,
- &sv_variance_ptr,
- &buffer_variance_ptr,
- &task->rect,
- &task->render_buffer.pass_stride,
- &task->render_buffer.offset};
- CUDA_LAUNCH_KERNEL(cuFilterDivideShadow, args);
- cuda_assert(cuCtxSynchronize());
-
- return !have_error();
- }
-
- bool denoising_get_feature(int mean_offset,
- int variance_offset,
- device_ptr mean_ptr,
- device_ptr variance_ptr,
- float scale,
- DenoisingTask *task)
- {
- if(have_error())
- return false;
-
- CUDAContextScope scope(this);
-
- CUfunction cuFilterGetFeature;
- cuda_assert(cuModuleGetFunction(&cuFilterGetFeature, cuFilterModule, "kernel_cuda_filter_get_feature"));
- cuda_assert(cuFuncSetCacheConfig(cuFilterGetFeature, CU_FUNC_CACHE_PREFER_L1));
- CUDA_GET_BLOCKSIZE(cuFilterGetFeature,
- task->rect.z-task->rect.x,
- task->rect.w-task->rect.y);
-
- void *args[] = {&task->render_buffer.samples,
- &task->tile_info_mem.device_pointer,
- &mean_offset,
- &variance_offset,
- &mean_ptr,
- &variance_ptr,
- &scale,
- &task->rect,
- &task->render_buffer.pass_stride,
- &task->render_buffer.offset};
- CUDA_LAUNCH_KERNEL(cuFilterGetFeature, args);
- cuda_assert(cuCtxSynchronize());
-
- return !have_error();
- }
-
- bool denoising_write_feature(int out_offset,
- device_ptr from_ptr,
- device_ptr buffer_ptr,
- DenoisingTask *task)
- {
- if(have_error())
- return false;
-
- CUDAContextScope scope(this);
-
- CUfunction cuFilterWriteFeature;
- cuda_assert(cuModuleGetFunction(&cuFilterWriteFeature, cuFilterModule, "kernel_cuda_filter_write_feature"));
- cuda_assert(cuFuncSetCacheConfig(cuFilterWriteFeature, CU_FUNC_CACHE_PREFER_L1));
- CUDA_GET_BLOCKSIZE(cuFilterWriteFeature,
- task->filter_area.z,
- task->filter_area.w);
-
- void *args[] = {&task->render_buffer.samples,
- &task->reconstruction_state.buffer_params,
- &task->filter_area,
- &from_ptr,
- &buffer_ptr,
- &out_offset,
- &task->rect};
- CUDA_LAUNCH_KERNEL(cuFilterWriteFeature, args);
- cuda_assert(cuCtxSynchronize());
-
- return !have_error();
- }
-
- bool denoising_detect_outliers(device_ptr image_ptr,
- device_ptr variance_ptr,
- device_ptr depth_ptr,
- device_ptr output_ptr,
- DenoisingTask *task)
- {
- if(have_error())
- return false;
-
- CUDAContextScope scope(this);
-
- CUfunction cuFilterDetectOutliers;
- cuda_assert(cuModuleGetFunction(&cuFilterDetectOutliers, cuFilterModule, "kernel_cuda_filter_detect_outliers"));
- cuda_assert(cuFuncSetCacheConfig(cuFilterDetectOutliers, CU_FUNC_CACHE_PREFER_L1));
- CUDA_GET_BLOCKSIZE(cuFilterDetectOutliers,
- task->rect.z-task->rect.x,
- task->rect.w-task->rect.y);
-
- void *args[] = {&image_ptr,
- &variance_ptr,
- &depth_ptr,
- &output_ptr,
- &task->rect,
- &task->buffer.pass_stride};
-
- CUDA_LAUNCH_KERNEL(cuFilterDetectOutliers, args);
- cuda_assert(cuCtxSynchronize());
-
- return !have_error();
- }
-
- void denoise(RenderTile &rtile, DenoisingTask& denoising)
- {
- denoising.functions.construct_transform = function_bind(&CUDADevice::denoising_construct_transform, this, &denoising);
- denoising.functions.accumulate = function_bind(&CUDADevice::denoising_accumulate, this, _1, _2, _3, _4, &denoising);
- denoising.functions.solve = function_bind(&CUDADevice::denoising_solve, this, _1, &denoising);
- denoising.functions.divide_shadow = function_bind(&CUDADevice::denoising_divide_shadow, this, _1, _2, _3, _4, _5, &denoising);
- denoising.functions.non_local_means = function_bind(&CUDADevice::denoising_non_local_means, this, _1, _2, _3, _4, &denoising);
- denoising.functions.combine_halves = function_bind(&CUDADevice::denoising_combine_halves, this, _1, _2, _3, _4, _5, _6, &denoising);
- denoising.functions.get_feature = function_bind(&CUDADevice::denoising_get_feature, this, _1, _2, _3, _4, _5, &denoising);
- denoising.functions.write_feature = function_bind(&CUDADevice::denoising_write_feature, this, _1, _2, _3, &denoising);
- denoising.functions.detect_outliers = function_bind(&CUDADevice::denoising_detect_outliers, this, _1, _2, _3, _4, &denoising);
-
- denoising.filter_area = make_int4(rtile.x, rtile.y, rtile.w, rtile.h);
- denoising.render_buffer.samples = rtile.sample;
- denoising.buffer.gpu_temporary_mem = true;
-
- denoising.run_denoising(&rtile);
- }
-
- void path_trace(DeviceTask& task, RenderTile& rtile, device_vector<WorkTile>& work_tiles)
- {
- scoped_timer timer(&rtile.buffers->render_time);
-
- if(have_error())
- return;
-
- CUDAContextScope scope(this);
- CUfunction cuPathTrace;
-
- /* Get kernel function. */
- if(task.integrator_branched) {
- cuda_assert(cuModuleGetFunction(&cuPathTrace, cuModule, "kernel_cuda_branched_path_trace"));
- }
- else {
- cuda_assert(cuModuleGetFunction(&cuPathTrace, cuModule, "kernel_cuda_path_trace"));
- }
-
- if(have_error()) {
- return;
- }
-
- cuda_assert(cuFuncSetCacheConfig(cuPathTrace, CU_FUNC_CACHE_PREFER_L1));
-
- /* Allocate work tile. */
- work_tiles.alloc(1);
-
- WorkTile *wtile = work_tiles.data();
- wtile->x = rtile.x;
- wtile->y = rtile.y;
- wtile->w = rtile.w;
- wtile->h = rtile.h;
- wtile->offset = rtile.offset;
- wtile->stride = rtile.stride;
- wtile->buffer = (float*)cuda_device_ptr(rtile.buffer);
-
- /* Prepare work size. More step samples render faster, but for now we
- * remain conservative for GPUs connected to a display to avoid driver
- * timeouts and display freezing. */
- int min_blocks, num_threads_per_block;
- cuda_assert(cuOccupancyMaxPotentialBlockSize(&min_blocks, &num_threads_per_block, cuPathTrace, NULL, 0, 0));
- if(!info.display_device) {
- min_blocks *= 8;
- }
-
- uint step_samples = divide_up(min_blocks * num_threads_per_block, wtile->w * wtile->h);
-
- /* Render all samples. */
- int start_sample = rtile.start_sample;
- int end_sample = rtile.start_sample + rtile.num_samples;
-
- for(int sample = start_sample; sample < end_sample; sample += step_samples) {
- /* Setup and copy work tile to device. */
- wtile->start_sample = sample;
- wtile->num_samples = min(step_samples, end_sample - sample);
- work_tiles.copy_to_device();
-
- CUdeviceptr d_work_tiles = cuda_device_ptr(work_tiles.device_pointer);
- uint total_work_size = wtile->w * wtile->h * wtile->num_samples;
- uint num_blocks = divide_up(total_work_size, num_threads_per_block);
-
- /* Launch kernel. */
- void *args[] = {&d_work_tiles,
- &total_work_size};
-
- cuda_assert(cuLaunchKernel(cuPathTrace,
- num_blocks, 1, 1,
- num_threads_per_block, 1, 1,
- 0, 0, args, 0));
-
- cuda_assert(cuCtxSynchronize());
-
- /* Update progress. */
- rtile.sample = sample + wtile->num_samples;
- task.update_progress(&rtile, rtile.w*rtile.h*wtile->num_samples);
-
- if(task.get_cancel()) {
- if(task.need_finish_queue == false)
- break;
- }
- }
- }
-
- void film_convert(DeviceTask& task, device_ptr buffer, device_ptr rgba_byte, device_ptr rgba_half)
- {
- if(have_error())
- return;
-
- CUDAContextScope scope(this);
-
- CUfunction cuFilmConvert;
- CUdeviceptr d_rgba = map_pixels((rgba_byte)? rgba_byte: rgba_half);
- CUdeviceptr d_buffer = cuda_device_ptr(buffer);
-
- /* get kernel function */
- if(rgba_half) {
- cuda_assert(cuModuleGetFunction(&cuFilmConvert, cuModule, "kernel_cuda_convert_to_half_float"));
- }
- else {
- cuda_assert(cuModuleGetFunction(&cuFilmConvert, cuModule, "kernel_cuda_convert_to_byte"));
- }
-
-
- float sample_scale = 1.0f/(task.sample + 1);
-
- /* pass in parameters */
- void *args[] = {&d_rgba,
- &d_buffer,
- &sample_scale,
- &task.x,
- &task.y,
- &task.w,
- &task.h,
- &task.offset,
- &task.stride};
-
- /* launch kernel */
- int threads_per_block;
- cuda_assert(cuFuncGetAttribute(&threads_per_block, CU_FUNC_ATTRIBUTE_MAX_THREADS_PER_BLOCK, cuFilmConvert));
-
- int xthreads = (int)sqrt(threads_per_block);
- int ythreads = (int)sqrt(threads_per_block);
- int xblocks = (task.w + xthreads - 1)/xthreads;
- int yblocks = (task.h + ythreads - 1)/ythreads;
-
- cuda_assert(cuFuncSetCacheConfig(cuFilmConvert, CU_FUNC_CACHE_PREFER_L1));
-
- cuda_assert(cuLaunchKernel(cuFilmConvert,
- xblocks , yblocks, 1, /* blocks */
- xthreads, ythreads, 1, /* threads */
- 0, 0, args, 0));
-
- unmap_pixels((rgba_byte)? rgba_byte: rgba_half);
-
- cuda_assert(cuCtxSynchronize());
- }
-
- void shader(DeviceTask& task)
- {
- if(have_error())
- return;
-
- CUDAContextScope scope(this);
-
- CUfunction cuShader;
- CUdeviceptr d_input = cuda_device_ptr(task.shader_input);
- CUdeviceptr d_output = cuda_device_ptr(task.shader_output);
-
- /* get kernel function */
- if(task.shader_eval_type >= SHADER_EVAL_BAKE) {
- cuda_assert(cuModuleGetFunction(&cuShader, cuModule, "kernel_cuda_bake"));
- }
- else if(task.shader_eval_type == SHADER_EVAL_DISPLACE) {
- cuda_assert(cuModuleGetFunction(&cuShader, cuModule, "kernel_cuda_displace"));
- }
- else {
- cuda_assert(cuModuleGetFunction(&cuShader, cuModule, "kernel_cuda_background"));
- }
-
- /* do tasks in smaller chunks, so we can cancel it */
- const int shader_chunk_size = 65536;
- const int start = task.shader_x;
- const int end = task.shader_x + task.shader_w;
- int offset = task.offset;
-
- bool canceled = false;
- for(int sample = 0; sample < task.num_samples && !canceled; sample++) {
- for(int shader_x = start; shader_x < end; shader_x += shader_chunk_size) {
- int shader_w = min(shader_chunk_size, end - shader_x);
-
- /* pass in parameters */
- void *args[8];
- int arg = 0;
- args[arg++] = &d_input;
- args[arg++] = &d_output;
- args[arg++] = &task.shader_eval_type;
- if(task.shader_eval_type >= SHADER_EVAL_BAKE) {
- args[arg++] = &task.shader_filter;
- }
- args[arg++] = &shader_x;
- args[arg++] = &shader_w;
- args[arg++] = &offset;
- args[arg++] = &sample;
-
- /* launch kernel */
- int threads_per_block;
- cuda_assert(cuFuncGetAttribute(&threads_per_block, CU_FUNC_ATTRIBUTE_MAX_THREADS_PER_BLOCK, cuShader));
-
- int xblocks = (shader_w + threads_per_block - 1)/threads_per_block;
-
- cuda_assert(cuFuncSetCacheConfig(cuShader, CU_FUNC_CACHE_PREFER_L1));
- cuda_assert(cuLaunchKernel(cuShader,
- xblocks , 1, 1, /* blocks */
- threads_per_block, 1, 1, /* threads */
- 0, 0, args, 0));
-
- cuda_assert(cuCtxSynchronize());
-
- if(task.get_cancel()) {
- canceled = true;
- break;
- }
- }
-
- task.update_progress(NULL);
- }
- }
-
- CUdeviceptr map_pixels(device_ptr mem)
- {
- if(!background) {
- PixelMem pmem = pixel_mem_map[mem];
- CUdeviceptr buffer;
-
- size_t bytes;
- cuda_assert(cuGraphicsMapResources(1, &pmem.cuPBOresource, 0));
- cuda_assert(cuGraphicsResourceGetMappedPointer(&buffer, &bytes, pmem.cuPBOresource));
-
- return buffer;
- }
-
- return cuda_device_ptr(mem);
- }
-
- void unmap_pixels(device_ptr mem)
- {
- if(!background) {
- PixelMem pmem = pixel_mem_map[mem];
-
- cuda_assert(cuGraphicsUnmapResources(1, &pmem.cuPBOresource, 0));
- }
- }
-
- void pixels_alloc(device_memory& mem)
- {
- PixelMem pmem;
-
- pmem.w = mem.data_width;
- pmem.h = mem.data_height;
-
- CUDAContextScope scope(this);
-
- glGenBuffers(1, &pmem.cuPBO);
- glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pmem.cuPBO);
- if(mem.data_type == TYPE_HALF)
- glBufferData(GL_PIXEL_UNPACK_BUFFER, pmem.w*pmem.h*sizeof(GLhalf)*4, NULL, GL_DYNAMIC_DRAW);
- else
- glBufferData(GL_PIXEL_UNPACK_BUFFER, pmem.w*pmem.h*sizeof(uint8_t)*4, NULL, GL_DYNAMIC_DRAW);
-
- glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
-
- glActiveTexture(GL_TEXTURE0);
- glGenTextures(1, &pmem.cuTexId);
- glBindTexture(GL_TEXTURE_2D, pmem.cuTexId);
- if(mem.data_type == TYPE_HALF)
- glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, pmem.w, pmem.h, 0, GL_RGBA, GL_HALF_FLOAT, NULL);
- else
- glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, pmem.w, pmem.h, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
- glBindTexture(GL_TEXTURE_2D, 0);
-
- CUresult result = cuGraphicsGLRegisterBuffer(&pmem.cuPBOresource, pmem.cuPBO, CU_GRAPHICS_MAP_RESOURCE_FLAGS_NONE);
-
- if(result == CUDA_SUCCESS) {
- mem.device_pointer = pmem.cuTexId;
- pixel_mem_map[mem.device_pointer] = pmem;
-
- mem.device_size = mem.memory_size();
- stats.mem_alloc(mem.device_size);
-
- return;
- }
- else {
- /* failed to register buffer, fallback to no interop */
- glDeleteBuffers(1, &pmem.cuPBO);
- glDeleteTextures(1, &pmem.cuTexId);
-
- background = true;
- }
- }
-
- void pixels_copy_from(device_memory& mem, int y, int w, int h)
- {
- PixelMem pmem = pixel_mem_map[mem.device_pointer];
-
- CUDAContextScope scope(this);
-
- glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pmem.cuPBO);
- uchar *pixels = (uchar*)glMapBuffer(GL_PIXEL_UNPACK_BUFFER, GL_READ_ONLY);
- size_t offset = sizeof(uchar)*4*y*w;
- memcpy((uchar*)mem.host_pointer + offset, pixels + offset, sizeof(uchar)*4*w*h);
- glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER);
- glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
- }
-
- void pixels_free(device_memory& mem)
- {
- if(mem.device_pointer) {
- PixelMem pmem = pixel_mem_map[mem.device_pointer];
-
- CUDAContextScope scope(this);
-
- cuda_assert(cuGraphicsUnregisterResource(pmem.cuPBOresource));
- glDeleteBuffers(1, &pmem.cuPBO);
- glDeleteTextures(1, &pmem.cuTexId);
-
- pixel_mem_map.erase(pixel_mem_map.find(mem.device_pointer));
- mem.device_pointer = 0;
-
- stats.mem_free(mem.device_size);
- mem.device_size = 0;
- }
- }
-
- void draw_pixels(
- device_memory& mem, int y,
- int w, int h, int width, int height,
- int dx, int dy, int dw, int dh, bool transparent,
- const DeviceDrawParams &draw_params)
- {
- assert(mem.type == MEM_PIXELS);
-
- if(!background) {
- const bool use_fallback_shader = (draw_params.bind_display_space_shader_cb == NULL);
- PixelMem pmem = pixel_mem_map[mem.device_pointer];
- float *vpointer;
-
- CUDAContextScope scope(this);
-
- /* for multi devices, this assumes the inefficient method that we allocate
- * all pixels on the device even though we only render to a subset */
- size_t offset = 4*y*w;
-
- if(mem.data_type == TYPE_HALF)
- offset *= sizeof(GLhalf);
- else
- offset *= sizeof(uint8_t);
-
- glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pmem.cuPBO);
- glActiveTexture(GL_TEXTURE0);
- glBindTexture(GL_TEXTURE_2D, pmem.cuTexId);
- if(mem.data_type == TYPE_HALF) {
- glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, w, h, GL_RGBA, GL_HALF_FLOAT, (void*)offset);
- }
- else {
- glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, (void*)offset);
- }
- glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
-
- if(transparent) {
- glEnable(GL_BLEND);
- glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
- }
-
- GLint shader_program;
- if(use_fallback_shader) {
- if(!bind_fallback_display_space_shader(dw, dh)) {
- return;
- }
- shader_program = fallback_shader_program;
- }
- else {
- draw_params.bind_display_space_shader_cb();
- glGetIntegerv(GL_CURRENT_PROGRAM, &shader_program);
- }
-
- if(!vertex_buffer) {
- glGenBuffers(1, &vertex_buffer);
- }
-
- glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer);
- /* invalidate old contents - avoids stalling if buffer is still waiting in queue to be rendered */
- glBufferData(GL_ARRAY_BUFFER, 16 * sizeof(float), NULL, GL_STREAM_DRAW);
-
- vpointer = (float *)glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY);
-
- if(vpointer) {
- /* texture coordinate - vertex pair */
- vpointer[0] = 0.0f;
- vpointer[1] = 0.0f;
- vpointer[2] = dx;
- vpointer[3] = dy;
-
- vpointer[4] = (float)w/(float)pmem.w;
- vpointer[5] = 0.0f;
- vpointer[6] = (float)width + dx;
- vpointer[7] = dy;
-
- vpointer[8] = (float)w/(float)pmem.w;
- vpointer[9] = (float)h/(float)pmem.h;
- vpointer[10] = (float)width + dx;
- vpointer[11] = (float)height + dy;
-
- vpointer[12] = 0.0f;
- vpointer[13] = (float)h/(float)pmem.h;
- vpointer[14] = dx;
- vpointer[15] = (float)height + dy;
-
- glUnmapBuffer(GL_ARRAY_BUFFER);
- }
-
- GLuint vertex_array_object;
- GLuint position_attribute, texcoord_attribute;
-
- glGenVertexArrays(1, &vertex_array_object);
- glBindVertexArray(vertex_array_object);
-
- texcoord_attribute = glGetAttribLocation(shader_program, "texCoord");
- position_attribute = glGetAttribLocation(shader_program, "pos");
-
- glEnableVertexAttribArray(texcoord_attribute);
- glEnableVertexAttribArray(position_attribute);
-
- glVertexAttribPointer(texcoord_attribute, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), (const GLvoid *)0);
- glVertexAttribPointer(position_attribute, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), (const GLvoid *)(sizeof(float) * 2));
-
- glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
-
- if(use_fallback_shader) {
- glUseProgram(0);
- }
- else {
- draw_params.unbind_display_space_shader_cb();
- }
-
- if(transparent) {
- glDisable(GL_BLEND);
- }
-
- glBindTexture(GL_TEXTURE_2D, 0);
-
- return;
- }
-
- Device::draw_pixels(mem, y, w, h, width, height, dx, dy, dw, dh, transparent, draw_params);
- }
-
- void thread_run(DeviceTask *task)
- {
- CUDAContextScope scope(this);
-
- if(task->type == DeviceTask::RENDER) {
- DeviceRequestedFeatures requested_features;
- if(use_split_kernel()) {
- if(split_kernel == NULL) {
- split_kernel = new CUDASplitKernel(this);
- split_kernel->load_kernels(requested_features);
- }
- }
-
- device_vector<WorkTile> work_tiles(this, "work_tiles", MEM_READ_ONLY);
-
- /* keep rendering tiles until done */
- RenderTile tile;
- DenoisingTask denoising(this, *task);
-
- while(task->acquire_tile(this, tile)) {
- if(tile.task == RenderTile::PATH_TRACE) {
- if(use_split_kernel()) {
- device_only_memory<uchar> void_buffer(this, "void_buffer");
- split_kernel->path_trace(task, tile, void_buffer, void_buffer);
- }
- else {
- path_trace(*task, tile, work_tiles);
- }
- }
- else if(tile.task == RenderTile::DENOISE) {
- tile.sample = tile.start_sample + tile.num_samples;
-
- denoise(tile, denoising);
-
- task->update_progress(&tile, tile.w*tile.h);
- }
-
- task->release_tile(tile);
-
- if(task->get_cancel()) {
- if(task->need_finish_queue == false)
- break;
- }
- }
-
- work_tiles.free();
- }
- else if(task->type == DeviceTask::SHADER) {
- shader(*task);
-
- cuda_assert(cuCtxSynchronize());
- }
- }
-
- class CUDADeviceTask : public DeviceTask {
- public:
- CUDADeviceTask(CUDADevice *device, DeviceTask& task)
- : DeviceTask(task)
- {
- run = function_bind(&CUDADevice::thread_run, device, this);
- }
- };
-
- int get_split_task_count(DeviceTask& /*task*/)
- {
- return 1;
- }
-
- void task_add(DeviceTask& task)
- {
- CUDAContextScope scope(this);
-
- /* Load texture info. */
- load_texture_info();
-
- /* Synchronize all memory copies before executing task. */
- cuda_assert(cuCtxSynchronize());
-
- if(task.type == DeviceTask::FILM_CONVERT) {
- /* must be done in main thread due to opengl access */
- film_convert(task, task.buffer, task.rgba_byte, task.rgba_half);
- }
- else {
- task_pool.push(new CUDADeviceTask(this, task));
- }
- }
-
- void task_wait()
- {
- task_pool.wait();
- }
-
- void task_cancel()
- {
- task_pool.cancel();
- }
-
- friend class CUDASplitKernelFunction;
- friend class CUDASplitKernel;
- friend class CUDAContextScope;
+#define CUDA_GET_BLOCKSIZE_1D(func, w, h) \
+ int threads_per_block; \
+ cuda_assert( \
+ cuFuncGetAttribute(&threads_per_block, CU_FUNC_ATTRIBUTE_MAX_THREADS_PER_BLOCK, func)); \
+ int xblocks = ((w) + threads_per_block - 1) / threads_per_block; \
+ int yblocks = h;
+
+#define CUDA_LAUNCH_KERNEL_1D(func, args) \
+ cuda_assert(cuLaunchKernel(func, xblocks, yblocks, 1, threads_per_block, 1, 1, 0, 0, args, 0));
+
+ bool denoising_non_local_means(device_ptr image_ptr,
+ device_ptr guide_ptr,
+ device_ptr variance_ptr,
+ device_ptr out_ptr,
+ DenoisingTask *task)
+ {
+ if (have_error())
+ return false;
+
+ CUDAContextScope scope(this);
+
+ int stride = task->buffer.stride;
+ int w = task->buffer.width;
+ int h = task->buffer.h;
+ int r = task->nlm_state.r;
+ int f = task->nlm_state.f;
+ float a = task->nlm_state.a;
+ float k_2 = task->nlm_state.k_2;
+
+ int pass_stride = task->buffer.pass_stride;
+ int num_shifts = (2 * r + 1) * (2 * r + 1);
+ int channel_offset = task->nlm_state.is_color ? task->buffer.pass_stride : 0;
+ int frame_offset = 0;
+
+ if (have_error())
+ return false;
+
+ CUdeviceptr difference = cuda_device_ptr(task->buffer.temporary_mem.device_pointer);
+ CUdeviceptr blurDifference = difference + sizeof(float) * pass_stride * num_shifts;
+ CUdeviceptr weightAccum = difference + 2 * sizeof(float) * pass_stride * num_shifts;
+ CUdeviceptr scale_ptr = 0;
+
+ cuda_assert(cuMemsetD8(weightAccum, 0, sizeof(float) * pass_stride));
+ cuda_assert(cuMemsetD8(out_ptr, 0, sizeof(float) * pass_stride));
+
+ {
+ CUfunction cuNLMCalcDifference, cuNLMBlur, cuNLMCalcWeight, cuNLMUpdateOutput;
+ cuda_assert(cuModuleGetFunction(
+ &cuNLMCalcDifference, cuFilterModule, "kernel_cuda_filter_nlm_calc_difference"));
+ cuda_assert(cuModuleGetFunction(&cuNLMBlur, cuFilterModule, "kernel_cuda_filter_nlm_blur"));
+ cuda_assert(cuModuleGetFunction(
+ &cuNLMCalcWeight, cuFilterModule, "kernel_cuda_filter_nlm_calc_weight"));
+ cuda_assert(cuModuleGetFunction(
+ &cuNLMUpdateOutput, cuFilterModule, "kernel_cuda_filter_nlm_update_output"));
+
+ cuda_assert(cuFuncSetCacheConfig(cuNLMCalcDifference, CU_FUNC_CACHE_PREFER_L1));
+ cuda_assert(cuFuncSetCacheConfig(cuNLMBlur, CU_FUNC_CACHE_PREFER_L1));
+ cuda_assert(cuFuncSetCacheConfig(cuNLMCalcWeight, CU_FUNC_CACHE_PREFER_L1));
+ cuda_assert(cuFuncSetCacheConfig(cuNLMUpdateOutput, CU_FUNC_CACHE_PREFER_L1));
+
+ CUDA_GET_BLOCKSIZE_1D(cuNLMCalcDifference, w * h, num_shifts);
+
+ void *calc_difference_args[] = {&guide_ptr,
+ &variance_ptr,
+ &scale_ptr,
+ &difference,
+ &w,
+ &h,
+ &stride,
+ &pass_stride,
+ &r,
+ &channel_offset,
+ &frame_offset,
+ &a,
+ &k_2};
+ void *blur_args[] = {&difference, &blurDifference, &w, &h, &stride, &pass_stride, &r, &f};
+ void *calc_weight_args[] = {
+ &blurDifference, &difference, &w, &h, &stride, &pass_stride, &r, &f};
+ void *update_output_args[] = {&blurDifference,
+ &image_ptr,
+ &out_ptr,
+ &weightAccum,
+ &w,
+ &h,
+ &stride,
+ &pass_stride,
+ &channel_offset,
+ &r,
+ &f};
+
+ CUDA_LAUNCH_KERNEL_1D(cuNLMCalcDifference, calc_difference_args);
+ CUDA_LAUNCH_KERNEL_1D(cuNLMBlur, blur_args);
+ CUDA_LAUNCH_KERNEL_1D(cuNLMCalcWeight, calc_weight_args);
+ CUDA_LAUNCH_KERNEL_1D(cuNLMBlur, blur_args);
+ CUDA_LAUNCH_KERNEL_1D(cuNLMUpdateOutput, update_output_args);
+ }
+
+ {
+ CUfunction cuNLMNormalize;
+ cuda_assert(cuModuleGetFunction(
+ &cuNLMNormalize, cuFilterModule, "kernel_cuda_filter_nlm_normalize"));
+ cuda_assert(cuFuncSetCacheConfig(cuNLMNormalize, CU_FUNC_CACHE_PREFER_L1));
+ void *normalize_args[] = {&out_ptr, &weightAccum, &w, &h, &stride};
+ CUDA_GET_BLOCKSIZE(cuNLMNormalize, w, h);
+ CUDA_LAUNCH_KERNEL(cuNLMNormalize, normalize_args);
+ cuda_assert(cuCtxSynchronize());
+ }
+
+ return !have_error();
+ }
+
+ bool denoising_construct_transform(DenoisingTask *task)
+ {
+ if (have_error())
+ return false;
+
+ CUDAContextScope scope(this);
+
+ CUfunction cuFilterConstructTransform;
+ cuda_assert(cuModuleGetFunction(
+ &cuFilterConstructTransform, cuFilterModule, "kernel_cuda_filter_construct_transform"));
+ cuda_assert(cuFuncSetCacheConfig(cuFilterConstructTransform, CU_FUNC_CACHE_PREFER_SHARED));
+ CUDA_GET_BLOCKSIZE(cuFilterConstructTransform, task->storage.w, task->storage.h);
+
+ void *args[] = {&task->buffer.mem.device_pointer,
+ &task->tile_info_mem.device_pointer,
+ &task->storage.transform.device_pointer,
+ &task->storage.rank.device_pointer,
+ &task->filter_area,
+ &task->rect,
+ &task->radius,
+ &task->pca_threshold,
+ &task->buffer.pass_stride,
+ &task->buffer.frame_stride,
+ &task->buffer.use_time};
+ CUDA_LAUNCH_KERNEL(cuFilterConstructTransform, args);
+ cuda_assert(cuCtxSynchronize());
+
+ return !have_error();
+ }
+
+ bool denoising_accumulate(device_ptr color_ptr,
+ device_ptr color_variance_ptr,
+ device_ptr scale_ptr,
+ int frame,
+ DenoisingTask *task)
+ {
+ if (have_error())
+ return false;
+
+ CUDAContextScope scope(this);
+
+ int r = task->radius;
+ int f = 4;
+ float a = 1.0f;
+ float k_2 = task->nlm_k_2;
+
+ int w = task->reconstruction_state.source_w;
+ int h = task->reconstruction_state.source_h;
+ int stride = task->buffer.stride;
+ int frame_offset = frame * task->buffer.frame_stride;
+ int t = task->tile_info->frames[frame];
+
+ int pass_stride = task->buffer.pass_stride;
+ int num_shifts = (2 * r + 1) * (2 * r + 1);
+
+ if (have_error())
+ return false;
+
+ CUdeviceptr difference = cuda_device_ptr(task->buffer.temporary_mem.device_pointer);
+ CUdeviceptr blurDifference = difference + sizeof(float) * pass_stride * num_shifts;
+
+ CUfunction cuNLMCalcDifference, cuNLMBlur, cuNLMCalcWeight, cuNLMConstructGramian;
+ cuda_assert(cuModuleGetFunction(
+ &cuNLMCalcDifference, cuFilterModule, "kernel_cuda_filter_nlm_calc_difference"));
+ cuda_assert(cuModuleGetFunction(&cuNLMBlur, cuFilterModule, "kernel_cuda_filter_nlm_blur"));
+ cuda_assert(cuModuleGetFunction(
+ &cuNLMCalcWeight, cuFilterModule, "kernel_cuda_filter_nlm_calc_weight"));
+ cuda_assert(cuModuleGetFunction(
+ &cuNLMConstructGramian, cuFilterModule, "kernel_cuda_filter_nlm_construct_gramian"));
+
+ cuda_assert(cuFuncSetCacheConfig(cuNLMCalcDifference, CU_FUNC_CACHE_PREFER_L1));
+ cuda_assert(cuFuncSetCacheConfig(cuNLMBlur, CU_FUNC_CACHE_PREFER_L1));
+ cuda_assert(cuFuncSetCacheConfig(cuNLMCalcWeight, CU_FUNC_CACHE_PREFER_L1));
+ cuda_assert(cuFuncSetCacheConfig(cuNLMConstructGramian, CU_FUNC_CACHE_PREFER_SHARED));
+
+ CUDA_GET_BLOCKSIZE_1D(cuNLMCalcDifference,
+ task->reconstruction_state.source_w *
+ task->reconstruction_state.source_h,
+ num_shifts);
+
+ void *calc_difference_args[] = {&color_ptr,
+ &color_variance_ptr,
+ &scale_ptr,
+ &difference,
+ &w,
+ &h,
+ &stride,
+ &pass_stride,
+ &r,
+ &pass_stride,
+ &frame_offset,
+ &a,
+ &k_2};
+ void *blur_args[] = {&difference, &blurDifference, &w, &h, &stride, &pass_stride, &r, &f};
+ void *calc_weight_args[] = {
+ &blurDifference, &difference, &w, &h, &stride, &pass_stride, &r, &f};
+ void *construct_gramian_args[] = {&t,
+ &blurDifference,
+ &task->buffer.mem.device_pointer,
+ &task->storage.transform.device_pointer,
+ &task->storage.rank.device_pointer,
+ &task->storage.XtWX.device_pointer,
+ &task->storage.XtWY.device_pointer,
+ &task->reconstruction_state.filter_window,
+ &w,
+ &h,
+ &stride,
+ &pass_stride,
+ &r,
+ &f,
+ &frame_offset,
+ &task->buffer.use_time};
+
+ CUDA_LAUNCH_KERNEL_1D(cuNLMCalcDifference, calc_difference_args);
+ CUDA_LAUNCH_KERNEL_1D(cuNLMBlur, blur_args);
+ CUDA_LAUNCH_KERNEL_1D(cuNLMCalcWeight, calc_weight_args);
+ CUDA_LAUNCH_KERNEL_1D(cuNLMBlur, blur_args);
+ CUDA_LAUNCH_KERNEL_1D(cuNLMConstructGramian, construct_gramian_args);
+ cuda_assert(cuCtxSynchronize());
+
+ return !have_error();
+ }
+
+ bool denoising_solve(device_ptr output_ptr, DenoisingTask *task)
+ {
+ CUfunction cuFinalize;
+ cuda_assert(cuModuleGetFunction(&cuFinalize, cuFilterModule, "kernel_cuda_filter_finalize"));
+ cuda_assert(cuFuncSetCacheConfig(cuFinalize, CU_FUNC_CACHE_PREFER_L1));
+ void *finalize_args[] = {&output_ptr,
+ &task->storage.rank.device_pointer,
+ &task->storage.XtWX.device_pointer,
+ &task->storage.XtWY.device_pointer,
+ &task->filter_area,
+ &task->reconstruction_state.buffer_params.x,
+ &task->render_buffer.samples};
+ CUDA_GET_BLOCKSIZE(
+ cuFinalize, task->reconstruction_state.source_w, task->reconstruction_state.source_h);
+ CUDA_LAUNCH_KERNEL(cuFinalize, finalize_args);
+ cuda_assert(cuCtxSynchronize());
+
+ return !have_error();
+ }
+
+ bool denoising_combine_halves(device_ptr a_ptr,
+ device_ptr b_ptr,
+ device_ptr mean_ptr,
+ device_ptr variance_ptr,
+ int r,
+ int4 rect,
+ DenoisingTask *task)
+ {
+ if (have_error())
+ return false;
+
+ CUDAContextScope scope(this);
+
+ CUfunction cuFilterCombineHalves;
+ cuda_assert(cuModuleGetFunction(
+ &cuFilterCombineHalves, cuFilterModule, "kernel_cuda_filter_combine_halves"));
+ cuda_assert(cuFuncSetCacheConfig(cuFilterCombineHalves, CU_FUNC_CACHE_PREFER_L1));
+ CUDA_GET_BLOCKSIZE(
+ cuFilterCombineHalves, task->rect.z - task->rect.x, task->rect.w - task->rect.y);
+
+ void *args[] = {&mean_ptr, &variance_ptr, &a_ptr, &b_ptr, &rect, &r};
+ CUDA_LAUNCH_KERNEL(cuFilterCombineHalves, args);
+ cuda_assert(cuCtxSynchronize());
+
+ return !have_error();
+ }
+
+ bool denoising_divide_shadow(device_ptr a_ptr,
+ device_ptr b_ptr,
+ device_ptr sample_variance_ptr,
+ device_ptr sv_variance_ptr,
+ device_ptr buffer_variance_ptr,
+ DenoisingTask *task)
+ {
+ if (have_error())
+ return false;
+
+ CUDAContextScope scope(this);
+
+ CUfunction cuFilterDivideShadow;
+ cuda_assert(cuModuleGetFunction(
+ &cuFilterDivideShadow, cuFilterModule, "kernel_cuda_filter_divide_shadow"));
+ cuda_assert(cuFuncSetCacheConfig(cuFilterDivideShadow, CU_FUNC_CACHE_PREFER_L1));
+ CUDA_GET_BLOCKSIZE(
+ cuFilterDivideShadow, task->rect.z - task->rect.x, task->rect.w - task->rect.y);
+
+ void *args[] = {&task->render_buffer.samples,
+ &task->tile_info_mem.device_pointer,
+ &a_ptr,
+ &b_ptr,
+ &sample_variance_ptr,
+ &sv_variance_ptr,
+ &buffer_variance_ptr,
+ &task->rect,
+ &task->render_buffer.pass_stride,
+ &task->render_buffer.offset};
+ CUDA_LAUNCH_KERNEL(cuFilterDivideShadow, args);
+ cuda_assert(cuCtxSynchronize());
+
+ return !have_error();
+ }
+
+ bool denoising_get_feature(int mean_offset,
+ int variance_offset,
+ device_ptr mean_ptr,
+ device_ptr variance_ptr,
+ float scale,
+ DenoisingTask *task)
+ {
+ if (have_error())
+ return false;
+
+ CUDAContextScope scope(this);
+
+ CUfunction cuFilterGetFeature;
+ cuda_assert(cuModuleGetFunction(
+ &cuFilterGetFeature, cuFilterModule, "kernel_cuda_filter_get_feature"));
+ cuda_assert(cuFuncSetCacheConfig(cuFilterGetFeature, CU_FUNC_CACHE_PREFER_L1));
+ CUDA_GET_BLOCKSIZE(
+ cuFilterGetFeature, task->rect.z - task->rect.x, task->rect.w - task->rect.y);
+
+ void *args[] = {&task->render_buffer.samples,
+ &task->tile_info_mem.device_pointer,
+ &mean_offset,
+ &variance_offset,
+ &mean_ptr,
+ &variance_ptr,
+ &scale,
+ &task->rect,
+ &task->render_buffer.pass_stride,
+ &task->render_buffer.offset};
+ CUDA_LAUNCH_KERNEL(cuFilterGetFeature, args);
+ cuda_assert(cuCtxSynchronize());
+
+ return !have_error();
+ }
+
+ bool denoising_write_feature(int out_offset,
+ device_ptr from_ptr,
+ device_ptr buffer_ptr,
+ DenoisingTask *task)
+ {
+ if (have_error())
+ return false;
+
+ CUDAContextScope scope(this);
+
+ CUfunction cuFilterWriteFeature;
+ cuda_assert(cuModuleGetFunction(
+ &cuFilterWriteFeature, cuFilterModule, "kernel_cuda_filter_write_feature"));
+ cuda_assert(cuFuncSetCacheConfig(cuFilterWriteFeature, CU_FUNC_CACHE_PREFER_L1));
+ CUDA_GET_BLOCKSIZE(cuFilterWriteFeature, task->filter_area.z, task->filter_area.w);
+
+ void *args[] = {&task->render_buffer.samples,
+ &task->reconstruction_state.buffer_params,
+ &task->filter_area,
+ &from_ptr,
+ &buffer_ptr,
+ &out_offset,
+ &task->rect};
+ CUDA_LAUNCH_KERNEL(cuFilterWriteFeature, args);
+ cuda_assert(cuCtxSynchronize());
+
+ return !have_error();
+ }
+
+ bool denoising_detect_outliers(device_ptr image_ptr,
+ device_ptr variance_ptr,
+ device_ptr depth_ptr,
+ device_ptr output_ptr,
+ DenoisingTask *task)
+ {
+ if (have_error())
+ return false;
+
+ CUDAContextScope scope(this);
+
+ CUfunction cuFilterDetectOutliers;
+ cuda_assert(cuModuleGetFunction(
+ &cuFilterDetectOutliers, cuFilterModule, "kernel_cuda_filter_detect_outliers"));
+ cuda_assert(cuFuncSetCacheConfig(cuFilterDetectOutliers, CU_FUNC_CACHE_PREFER_L1));
+ CUDA_GET_BLOCKSIZE(
+ cuFilterDetectOutliers, task->rect.z - task->rect.x, task->rect.w - task->rect.y);
+
+ void *args[] = {&image_ptr,
+ &variance_ptr,
+ &depth_ptr,
+ &output_ptr,
+ &task->rect,
+ &task->buffer.pass_stride};
+
+ CUDA_LAUNCH_KERNEL(cuFilterDetectOutliers, args);
+ cuda_assert(cuCtxSynchronize());
+
+ return !have_error();
+ }
+
+ void denoise(RenderTile &rtile, DenoisingTask &denoising)
+ {
+ denoising.functions.construct_transform = function_bind(
+ &CUDADevice::denoising_construct_transform, this, &denoising);
+ denoising.functions.accumulate = function_bind(
+ &CUDADevice::denoising_accumulate, this, _1, _2, _3, _4, &denoising);
+ denoising.functions.solve = function_bind(&CUDADevice::denoising_solve, this, _1, &denoising);
+ denoising.functions.divide_shadow = function_bind(
+ &CUDADevice::denoising_divide_shadow, this, _1, _2, _3, _4, _5, &denoising);
+ denoising.functions.non_local_means = function_bind(
+ &CUDADevice::denoising_non_local_means, this, _1, _2, _3, _4, &denoising);
+ denoising.functions.combine_halves = function_bind(
+ &CUDADevice::denoising_combine_halves, this, _1, _2, _3, _4, _5, _6, &denoising);
+ denoising.functions.get_feature = function_bind(
+ &CUDADevice::denoising_get_feature, this, _1, _2, _3, _4, _5, &denoising);
+ denoising.functions.write_feature = function_bind(
+ &CUDADevice::denoising_write_feature, this, _1, _2, _3, &denoising);
+ denoising.functions.detect_outliers = function_bind(
+ &CUDADevice::denoising_detect_outliers, this, _1, _2, _3, _4, &denoising);
+
+ denoising.filter_area = make_int4(rtile.x, rtile.y, rtile.w, rtile.h);
+ denoising.render_buffer.samples = rtile.sample;
+ denoising.buffer.gpu_temporary_mem = true;
+
+ denoising.run_denoising(&rtile);
+ }
+
+ void path_trace(DeviceTask &task, RenderTile &rtile, device_vector<WorkTile> &work_tiles)
+ {
+ scoped_timer timer(&rtile.buffers->render_time);
+
+ if (have_error())
+ return;
+
+ CUDAContextScope scope(this);
+ CUfunction cuPathTrace;
+
+ /* Get kernel function. */
+ if (task.integrator_branched) {
+ cuda_assert(cuModuleGetFunction(&cuPathTrace, cuModule, "kernel_cuda_branched_path_trace"));
+ }
+ else {
+ cuda_assert(cuModuleGetFunction(&cuPathTrace, cuModule, "kernel_cuda_path_trace"));
+ }
+
+ if (have_error()) {
+ return;
+ }
+
+ cuda_assert(cuFuncSetCacheConfig(cuPathTrace, CU_FUNC_CACHE_PREFER_L1));
+
+ /* Allocate work tile. */
+ work_tiles.alloc(1);
+
+ WorkTile *wtile = work_tiles.data();
+ wtile->x = rtile.x;
+ wtile->y = rtile.y;
+ wtile->w = rtile.w;
+ wtile->h = rtile.h;
+ wtile->offset = rtile.offset;
+ wtile->stride = rtile.stride;
+ wtile->buffer = (float *)cuda_device_ptr(rtile.buffer);
+
+ /* Prepare work size. More step samples render faster, but for now we
+ * remain conservative for GPUs connected to a display to avoid driver
+ * timeouts and display freezing. */
+ int min_blocks, num_threads_per_block;
+ cuda_assert(cuOccupancyMaxPotentialBlockSize(
+ &min_blocks, &num_threads_per_block, cuPathTrace, NULL, 0, 0));
+ if (!info.display_device) {
+ min_blocks *= 8;
+ }
+
+ uint step_samples = divide_up(min_blocks * num_threads_per_block, wtile->w * wtile->h);
+
+ /* Render all samples. */
+ int start_sample = rtile.start_sample;
+ int end_sample = rtile.start_sample + rtile.num_samples;
+
+ for (int sample = start_sample; sample < end_sample; sample += step_samples) {
+ /* Setup and copy work tile to device. */
+ wtile->start_sample = sample;
+ wtile->num_samples = min(step_samples, end_sample - sample);
+ work_tiles.copy_to_device();
+
+ CUdeviceptr d_work_tiles = cuda_device_ptr(work_tiles.device_pointer);
+ uint total_work_size = wtile->w * wtile->h * wtile->num_samples;
+ uint num_blocks = divide_up(total_work_size, num_threads_per_block);
+
+ /* Launch kernel. */
+ void *args[] = {&d_work_tiles, &total_work_size};
+
+ cuda_assert(cuLaunchKernel(
+ cuPathTrace, num_blocks, 1, 1, num_threads_per_block, 1, 1, 0, 0, args, 0));
+
+ cuda_assert(cuCtxSynchronize());
+
+ /* Update progress. */
+ rtile.sample = sample + wtile->num_samples;
+ task.update_progress(&rtile, rtile.w * rtile.h * wtile->num_samples);
+
+ if (task.get_cancel()) {
+ if (task.need_finish_queue == false)
+ break;
+ }
+ }
+ }
+
+ void film_convert(DeviceTask &task,
+ device_ptr buffer,
+ device_ptr rgba_byte,
+ device_ptr rgba_half)
+ {
+ if (have_error())
+ return;
+
+ CUDAContextScope scope(this);
+
+ CUfunction cuFilmConvert;
+ CUdeviceptr d_rgba = map_pixels((rgba_byte) ? rgba_byte : rgba_half);
+ CUdeviceptr d_buffer = cuda_device_ptr(buffer);
+
+ /* get kernel function */
+ if (rgba_half) {
+ cuda_assert(
+ cuModuleGetFunction(&cuFilmConvert, cuModule, "kernel_cuda_convert_to_half_float"));
+ }
+ else {
+ cuda_assert(cuModuleGetFunction(&cuFilmConvert, cuModule, "kernel_cuda_convert_to_byte"));
+ }
+
+ float sample_scale = 1.0f / (task.sample + 1);
+
+ /* pass in parameters */
+ void *args[] = {&d_rgba,
+ &d_buffer,
+ &sample_scale,
+ &task.x,
+ &task.y,
+ &task.w,
+ &task.h,
+ &task.offset,
+ &task.stride};
+
+ /* launch kernel */
+ int threads_per_block;
+ cuda_assert(cuFuncGetAttribute(
+ &threads_per_block, CU_FUNC_ATTRIBUTE_MAX_THREADS_PER_BLOCK, cuFilmConvert));
+
+ int xthreads = (int)sqrt(threads_per_block);
+ int ythreads = (int)sqrt(threads_per_block);
+ int xblocks = (task.w + xthreads - 1) / xthreads;
+ int yblocks = (task.h + ythreads - 1) / ythreads;
+
+ cuda_assert(cuFuncSetCacheConfig(cuFilmConvert, CU_FUNC_CACHE_PREFER_L1));
+
+ cuda_assert(cuLaunchKernel(cuFilmConvert,
+ xblocks,
+ yblocks,
+ 1, /* blocks */
+ xthreads,
+ ythreads,
+ 1, /* threads */
+ 0,
+ 0,
+ args,
+ 0));
+
+ unmap_pixels((rgba_byte) ? rgba_byte : rgba_half);
+
+ cuda_assert(cuCtxSynchronize());
+ }
+
+ void shader(DeviceTask &task)
+ {
+ if (have_error())
+ return;
+
+ CUDAContextScope scope(this);
+
+ CUfunction cuShader;
+ CUdeviceptr d_input = cuda_device_ptr(task.shader_input);
+ CUdeviceptr d_output = cuda_device_ptr(task.shader_output);
+
+ /* get kernel function */
+ if (task.shader_eval_type >= SHADER_EVAL_BAKE) {
+ cuda_assert(cuModuleGetFunction(&cuShader, cuModule, "kernel_cuda_bake"));
+ }
+ else if (task.shader_eval_type == SHADER_EVAL_DISPLACE) {
+ cuda_assert(cuModuleGetFunction(&cuShader, cuModule, "kernel_cuda_displace"));
+ }
+ else {
+ cuda_assert(cuModuleGetFunction(&cuShader, cuModule, "kernel_cuda_background"));
+ }
+
+ /* do tasks in smaller chunks, so we can cancel it */
+ const int shader_chunk_size = 65536;
+ const int start = task.shader_x;
+ const int end = task.shader_x + task.shader_w;
+ int offset = task.offset;
+
+ bool canceled = false;
+ for (int sample = 0; sample < task.num_samples && !canceled; sample++) {
+ for (int shader_x = start; shader_x < end; shader_x += shader_chunk_size) {
+ int shader_w = min(shader_chunk_size, end - shader_x);
+
+ /* pass in parameters */
+ void *args[8];
+ int arg = 0;
+ args[arg++] = &d_input;
+ args[arg++] = &d_output;
+ args[arg++] = &task.shader_eval_type;
+ if (task.shader_eval_type >= SHADER_EVAL_BAKE) {
+ args[arg++] = &task.shader_filter;
+ }
+ args[arg++] = &shader_x;
+ args[arg++] = &shader_w;
+ args[arg++] = &offset;
+ args[arg++] = &sample;
+
+ /* launch kernel */
+ int threads_per_block;
+ cuda_assert(cuFuncGetAttribute(
+ &threads_per_block, CU_FUNC_ATTRIBUTE_MAX_THREADS_PER_BLOCK, cuShader));
+
+ int xblocks = (shader_w + threads_per_block - 1) / threads_per_block;
+
+ cuda_assert(cuFuncSetCacheConfig(cuShader, CU_FUNC_CACHE_PREFER_L1));
+ cuda_assert(cuLaunchKernel(cuShader,
+ xblocks,
+ 1,
+ 1, /* blocks */
+ threads_per_block,
+ 1,
+ 1, /* threads */
+ 0,
+ 0,
+ args,
+ 0));
+
+ cuda_assert(cuCtxSynchronize());
+
+ if (task.get_cancel()) {
+ canceled = true;
+ break;
+ }
+ }
+
+ task.update_progress(NULL);
+ }
+ }
+
+ CUdeviceptr map_pixels(device_ptr mem)
+ {
+ if (!background) {
+ PixelMem pmem = pixel_mem_map[mem];
+ CUdeviceptr buffer;
+
+ size_t bytes;
+ cuda_assert(cuGraphicsMapResources(1, &pmem.cuPBOresource, 0));
+ cuda_assert(cuGraphicsResourceGetMappedPointer(&buffer, &bytes, pmem.cuPBOresource));
+
+ return buffer;
+ }
+
+ return cuda_device_ptr(mem);
+ }
+
+ void unmap_pixels(device_ptr mem)
+ {
+ if (!background) {
+ PixelMem pmem = pixel_mem_map[mem];
+
+ cuda_assert(cuGraphicsUnmapResources(1, &pmem.cuPBOresource, 0));
+ }
+ }
+
+ void pixels_alloc(device_memory &mem)
+ {
+ PixelMem pmem;
+
+ pmem.w = mem.data_width;
+ pmem.h = mem.data_height;
+
+ CUDAContextScope scope(this);
+
+ glGenBuffers(1, &pmem.cuPBO);
+ glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pmem.cuPBO);
+ if (mem.data_type == TYPE_HALF)
+ glBufferData(
+ GL_PIXEL_UNPACK_BUFFER, pmem.w * pmem.h * sizeof(GLhalf) * 4, NULL, GL_DYNAMIC_DRAW);
+ else
+ glBufferData(
+ GL_PIXEL_UNPACK_BUFFER, pmem.w * pmem.h * sizeof(uint8_t) * 4, NULL, GL_DYNAMIC_DRAW);
+
+ glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
+
+ glActiveTexture(GL_TEXTURE0);
+ glGenTextures(1, &pmem.cuTexId);
+ glBindTexture(GL_TEXTURE_2D, pmem.cuTexId);
+ if (mem.data_type == TYPE_HALF)
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, pmem.w, pmem.h, 0, GL_RGBA, GL_HALF_FLOAT, NULL);
+ else
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, pmem.w, pmem.h, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ glBindTexture(GL_TEXTURE_2D, 0);
+
+ CUresult result = cuGraphicsGLRegisterBuffer(
+ &pmem.cuPBOresource, pmem.cuPBO, CU_GRAPHICS_MAP_RESOURCE_FLAGS_NONE);
+
+ if (result == CUDA_SUCCESS) {
+ mem.device_pointer = pmem.cuTexId;
+ pixel_mem_map[mem.device_pointer] = pmem;
+
+ mem.device_size = mem.memory_size();
+ stats.mem_alloc(mem.device_size);
+
+ return;
+ }
+ else {
+ /* failed to register buffer, fallback to no interop */
+ glDeleteBuffers(1, &pmem.cuPBO);
+ glDeleteTextures(1, &pmem.cuTexId);
+
+ background = true;
+ }
+ }
+
+ void pixels_copy_from(device_memory &mem, int y, int w, int h)
+ {
+ PixelMem pmem = pixel_mem_map[mem.device_pointer];
+
+ CUDAContextScope scope(this);
+
+ glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pmem.cuPBO);
+ uchar *pixels = (uchar *)glMapBuffer(GL_PIXEL_UNPACK_BUFFER, GL_READ_ONLY);
+ size_t offset = sizeof(uchar) * 4 * y * w;
+ memcpy((uchar *)mem.host_pointer + offset, pixels + offset, sizeof(uchar) * 4 * w * h);
+ glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER);
+ glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
+ }
+
+ void pixels_free(device_memory &mem)
+ {
+ if (mem.device_pointer) {
+ PixelMem pmem = pixel_mem_map[mem.device_pointer];
+
+ CUDAContextScope scope(this);
+
+ cuda_assert(cuGraphicsUnregisterResource(pmem.cuPBOresource));
+ glDeleteBuffers(1, &pmem.cuPBO);
+ glDeleteTextures(1, &pmem.cuTexId);
+
+ pixel_mem_map.erase(pixel_mem_map.find(mem.device_pointer));
+ mem.device_pointer = 0;
+
+ stats.mem_free(mem.device_size);
+ mem.device_size = 0;
+ }
+ }
+
+ void draw_pixels(device_memory &mem,
+ int y,
+ int w,
+ int h,
+ int width,
+ int height,
+ int dx,
+ int dy,
+ int dw,
+ int dh,
+ bool transparent,
+ const DeviceDrawParams &draw_params)
+ {
+ assert(mem.type == MEM_PIXELS);
+
+ if (!background) {
+ const bool use_fallback_shader = (draw_params.bind_display_space_shader_cb == NULL);
+ PixelMem pmem = pixel_mem_map[mem.device_pointer];
+ float *vpointer;
+
+ CUDAContextScope scope(this);
+
+ /* for multi devices, this assumes the inefficient method that we allocate
+ * all pixels on the device even though we only render to a subset */
+ size_t offset = 4 * y * w;
+
+ if (mem.data_type == TYPE_HALF)
+ offset *= sizeof(GLhalf);
+ else
+ offset *= sizeof(uint8_t);
+
+ glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pmem.cuPBO);
+ glActiveTexture(GL_TEXTURE0);
+ glBindTexture(GL_TEXTURE_2D, pmem.cuTexId);
+ if (mem.data_type == TYPE_HALF) {
+ glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, w, h, GL_RGBA, GL_HALF_FLOAT, (void *)offset);
+ }
+ else {
+ glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, (void *)offset);
+ }
+ glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
+
+ if (transparent) {
+ glEnable(GL_BLEND);
+ glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
+ }
+
+ GLint shader_program;
+ if (use_fallback_shader) {
+ if (!bind_fallback_display_space_shader(dw, dh)) {
+ return;
+ }
+ shader_program = fallback_shader_program;
+ }
+ else {
+ draw_params.bind_display_space_shader_cb();
+ glGetIntegerv(GL_CURRENT_PROGRAM, &shader_program);
+ }
+
+ if (!vertex_buffer) {
+ glGenBuffers(1, &vertex_buffer);
+ }
+
+ glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer);
+ /* invalidate old contents - avoids stalling if buffer is still waiting in queue to be rendered */
+ glBufferData(GL_ARRAY_BUFFER, 16 * sizeof(float), NULL, GL_STREAM_DRAW);
+
+ vpointer = (float *)glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY);
+
+ if (vpointer) {
+ /* texture coordinate - vertex pair */
+ vpointer[0] = 0.0f;
+ vpointer[1] = 0.0f;
+ vpointer[2] = dx;
+ vpointer[3] = dy;
+
+ vpointer[4] = (float)w / (float)pmem.w;
+ vpointer[5] = 0.0f;
+ vpointer[6] = (float)width + dx;
+ vpointer[7] = dy;
+
+ vpointer[8] = (float)w / (float)pmem.w;
+ vpointer[9] = (float)h / (float)pmem.h;
+ vpointer[10] = (float)width + dx;
+ vpointer[11] = (float)height + dy;
+
+ vpointer[12] = 0.0f;
+ vpointer[13] = (float)h / (float)pmem.h;
+ vpointer[14] = dx;
+ vpointer[15] = (float)height + dy;
+
+ glUnmapBuffer(GL_ARRAY_BUFFER);
+ }
+
+ GLuint vertex_array_object;
+ GLuint position_attribute, texcoord_attribute;
+
+ glGenVertexArrays(1, &vertex_array_object);
+ glBindVertexArray(vertex_array_object);
+
+ texcoord_attribute = glGetAttribLocation(shader_program, "texCoord");
+ position_attribute = glGetAttribLocation(shader_program, "pos");
+
+ glEnableVertexAttribArray(texcoord_attribute);
+ glEnableVertexAttribArray(position_attribute);
+
+ glVertexAttribPointer(
+ texcoord_attribute, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), (const GLvoid *)0);
+ glVertexAttribPointer(position_attribute,
+ 2,
+ GL_FLOAT,
+ GL_FALSE,
+ 4 * sizeof(float),
+ (const GLvoid *)(sizeof(float) * 2));
+
+ glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
+
+ if (use_fallback_shader) {
+ glUseProgram(0);
+ }
+ else {
+ draw_params.unbind_display_space_shader_cb();
+ }
+
+ if (transparent) {
+ glDisable(GL_BLEND);
+ }
+
+ glBindTexture(GL_TEXTURE_2D, 0);
+
+ return;
+ }
+
+ Device::draw_pixels(mem, y, w, h, width, height, dx, dy, dw, dh, transparent, draw_params);
+ }
+
+ void thread_run(DeviceTask *task)
+ {
+ CUDAContextScope scope(this);
+
+ if (task->type == DeviceTask::RENDER) {
+ DeviceRequestedFeatures requested_features;
+ if (use_split_kernel()) {
+ if (split_kernel == NULL) {
+ split_kernel = new CUDASplitKernel(this);
+ split_kernel->load_kernels(requested_features);
+ }
+ }
+
+ device_vector<WorkTile> work_tiles(this, "work_tiles", MEM_READ_ONLY);
+
+ /* keep rendering tiles until done */
+ RenderTile tile;
+ DenoisingTask denoising(this, *task);
+
+ while (task->acquire_tile(this, tile)) {
+ if (tile.task == RenderTile::PATH_TRACE) {
+ if (use_split_kernel()) {
+ device_only_memory<uchar> void_buffer(this, "void_buffer");
+ split_kernel->path_trace(task, tile, void_buffer, void_buffer);
+ }
+ else {
+ path_trace(*task, tile, work_tiles);
+ }
+ }
+ else if (tile.task == RenderTile::DENOISE) {
+ tile.sample = tile.start_sample + tile.num_samples;
+
+ denoise(tile, denoising);
+
+ task->update_progress(&tile, tile.w * tile.h);
+ }
+
+ task->release_tile(tile);
+
+ if (task->get_cancel()) {
+ if (task->need_finish_queue == false)
+ break;
+ }
+ }
+
+ work_tiles.free();
+ }
+ else if (task->type == DeviceTask::SHADER) {
+ shader(*task);
+
+ cuda_assert(cuCtxSynchronize());
+ }
+ }
+
+ class CUDADeviceTask : public DeviceTask {
+ public:
+ CUDADeviceTask(CUDADevice *device, DeviceTask &task) : DeviceTask(task)
+ {
+ run = function_bind(&CUDADevice::thread_run, device, this);
+ }
+ };
+
+ int get_split_task_count(DeviceTask & /*task*/)
+ {
+ return 1;
+ }
+
+ void task_add(DeviceTask &task)
+ {
+ CUDAContextScope scope(this);
+
+ /* Load texture info. */
+ load_texture_info();
+
+ /* Synchronize all memory copies before executing task. */
+ cuda_assert(cuCtxSynchronize());
+
+ if (task.type == DeviceTask::FILM_CONVERT) {
+ /* must be done in main thread due to opengl access */
+ film_convert(task, task.buffer, task.rgba_byte, task.rgba_half);
+ }
+ else {
+ task_pool.push(new CUDADeviceTask(this, task));
+ }
+ }
+
+ void task_wait()
+ {
+ task_pool.wait();
+ }
+
+ void task_cancel()
+ {
+ task_pool.cancel();
+ }
+
+ friend class CUDASplitKernelFunction;
+ friend class CUDASplitKernel;
+ friend class CUDAContextScope;
};
/* redefine the cuda_assert macro so it can be used outside of the CUDADevice class
@@ -2207,496 +2305,501 @@ public:
*/
#undef cuda_assert
#define cuda_assert(stmt) \
- { \
- CUresult result = stmt; \
- \
- if(result != CUDA_SUCCESS) { \
- string message = string_printf("CUDA error: %s in %s", cuewErrorString(result), #stmt); \
- if(device->error_msg == "") \
- device->error_msg = message; \
- fprintf(stderr, "%s\n", message.c_str()); \
- /*cuda_abort();*/ \
- device->cuda_error_documentation(); \
- } \
- } (void) 0
-
+ { \
+ CUresult result = stmt; \
+\
+ if (result != CUDA_SUCCESS) { \
+ string message = string_printf("CUDA error: %s in %s", cuewErrorString(result), #stmt); \
+ if (device->error_msg == "") \
+ device->error_msg = message; \
+ fprintf(stderr, "%s\n", message.c_str()); \
+ /*cuda_abort();*/ \
+ device->cuda_error_documentation(); \
+ } \
+ } \
+ (void)0
/* CUDA context scope. */
-CUDAContextScope::CUDAContextScope(CUDADevice *device)
-: device(device)
+CUDAContextScope::CUDAContextScope(CUDADevice *device) : device(device)
{
- cuda_assert(cuCtxPushCurrent(device->cuContext));
+ cuda_assert(cuCtxPushCurrent(device->cuContext));
}
CUDAContextScope::~CUDAContextScope()
{
- cuda_assert(cuCtxPopCurrent(NULL));
+ cuda_assert(cuCtxPopCurrent(NULL));
}
/* split kernel */
-class CUDASplitKernelFunction : public SplitKernelFunction{
- CUDADevice* device;
- CUfunction func;
-public:
- CUDASplitKernelFunction(CUDADevice *device, CUfunction func) : device(device), func(func) {}
-
- /* enqueue the kernel, returns false if there is an error */
- bool enqueue(const KernelDimensions &dim, device_memory &/*kg*/, device_memory &/*data*/)
- {
- return enqueue(dim, NULL);
- }
-
- /* enqueue the kernel, returns false if there is an error */
- bool enqueue(const KernelDimensions &dim, void *args[])
- {
- if(device->have_error())
- return false;
-
- CUDAContextScope scope(device);
-
- /* we ignore dim.local_size for now, as this is faster */
- int threads_per_block;
- cuda_assert(cuFuncGetAttribute(&threads_per_block, CU_FUNC_ATTRIBUTE_MAX_THREADS_PER_BLOCK, func));
-
- int xblocks = (dim.global_size[0]*dim.global_size[1] + threads_per_block - 1)/threads_per_block;
-
- cuda_assert(cuFuncSetCacheConfig(func, CU_FUNC_CACHE_PREFER_L1));
-
- cuda_assert(cuLaunchKernel(func,
- xblocks, 1, 1, /* blocks */
- threads_per_block, 1, 1, /* threads */
- 0, 0, args, 0));
-
- return !device->have_error();
- }
+class CUDASplitKernelFunction : public SplitKernelFunction {
+ CUDADevice *device;
+ CUfunction func;
+
+ public:
+ CUDASplitKernelFunction(CUDADevice *device, CUfunction func) : device(device), func(func)
+ {
+ }
+
+ /* enqueue the kernel, returns false if there is an error */
+ bool enqueue(const KernelDimensions &dim, device_memory & /*kg*/, device_memory & /*data*/)
+ {
+ return enqueue(dim, NULL);
+ }
+
+ /* enqueue the kernel, returns false if there is an error */
+ bool enqueue(const KernelDimensions &dim, void *args[])
+ {
+ if (device->have_error())
+ return false;
+
+ CUDAContextScope scope(device);
+
+ /* we ignore dim.local_size for now, as this is faster */
+ int threads_per_block;
+ cuda_assert(
+ cuFuncGetAttribute(&threads_per_block, CU_FUNC_ATTRIBUTE_MAX_THREADS_PER_BLOCK, func));
+
+ int xblocks = (dim.global_size[0] * dim.global_size[1] + threads_per_block - 1) /
+ threads_per_block;
+
+ cuda_assert(cuFuncSetCacheConfig(func, CU_FUNC_CACHE_PREFER_L1));
+
+ cuda_assert(cuLaunchKernel(func,
+ xblocks,
+ 1,
+ 1, /* blocks */
+ threads_per_block,
+ 1,
+ 1, /* threads */
+ 0,
+ 0,
+ args,
+ 0));
+
+ return !device->have_error();
+ }
};
CUDASplitKernel::CUDASplitKernel(CUDADevice *device) : DeviceSplitKernel(device), device(device)
{
}
-uint64_t CUDASplitKernel::state_buffer_size(device_memory& /*kg*/, device_memory& /*data*/, size_t num_threads)
+uint64_t CUDASplitKernel::state_buffer_size(device_memory & /*kg*/,
+ device_memory & /*data*/,
+ size_t num_threads)
{
- CUDAContextScope scope(device);
+ CUDAContextScope scope(device);
- device_vector<uint64_t> size_buffer(device, "size_buffer", MEM_READ_WRITE);
- size_buffer.alloc(1);
- size_buffer.zero_to_device();
+ device_vector<uint64_t> size_buffer(device, "size_buffer", MEM_READ_WRITE);
+ size_buffer.alloc(1);
+ size_buffer.zero_to_device();
- uint threads = num_threads;
- CUdeviceptr d_size = device->cuda_device_ptr(size_buffer.device_pointer);
+ uint threads = num_threads;
+ CUdeviceptr d_size = device->cuda_device_ptr(size_buffer.device_pointer);
- struct args_t {
- uint* num_threads;
- CUdeviceptr* size;
- };
+ struct args_t {
+ uint *num_threads;
+ CUdeviceptr *size;
+ };
- args_t args = {
- &threads,
- &d_size
- };
+ args_t args = {&threads, &d_size};
- CUfunction state_buffer_size;
- cuda_assert(cuModuleGetFunction(&state_buffer_size, device->cuModule, "kernel_cuda_state_buffer_size"));
+ CUfunction state_buffer_size;
+ cuda_assert(
+ cuModuleGetFunction(&state_buffer_size, device->cuModule, "kernel_cuda_state_buffer_size"));
- cuda_assert(cuLaunchKernel(state_buffer_size,
- 1, 1, 1,
- 1, 1, 1,
- 0, 0, (void**)&args, 0));
+ cuda_assert(cuLaunchKernel(state_buffer_size, 1, 1, 1, 1, 1, 1, 0, 0, (void **)&args, 0));
- size_buffer.copy_from_device(0, 1, 1);
- size_t size = size_buffer[0];
- size_buffer.free();
+ size_buffer.copy_from_device(0, 1, 1);
+ size_t size = size_buffer[0];
+ size_buffer.free();
- return size;
+ return size;
}
-bool CUDASplitKernel::enqueue_split_kernel_data_init(const KernelDimensions& dim,
- RenderTile& rtile,
- int num_global_elements,
- device_memory& /*kernel_globals*/,
- device_memory& /*kernel_data*/,
- device_memory& split_data,
- device_memory& ray_state,
- device_memory& queue_index,
- device_memory& use_queues_flag,
- device_memory& work_pool_wgs)
+bool CUDASplitKernel::enqueue_split_kernel_data_init(const KernelDimensions &dim,
+ RenderTile &rtile,
+ int num_global_elements,
+ device_memory & /*kernel_globals*/,
+ device_memory & /*kernel_data*/,
+ device_memory &split_data,
+ device_memory &ray_state,
+ device_memory &queue_index,
+ device_memory &use_queues_flag,
+ device_memory &work_pool_wgs)
{
- CUDAContextScope scope(device);
-
- CUdeviceptr d_split_data = device->cuda_device_ptr(split_data.device_pointer);
- CUdeviceptr d_ray_state = device->cuda_device_ptr(ray_state.device_pointer);
- CUdeviceptr d_queue_index = device->cuda_device_ptr(queue_index.device_pointer);
- CUdeviceptr d_use_queues_flag = device->cuda_device_ptr(use_queues_flag.device_pointer);
- CUdeviceptr d_work_pool_wgs = device->cuda_device_ptr(work_pool_wgs.device_pointer);
-
- CUdeviceptr d_buffer = device->cuda_device_ptr(rtile.buffer);
-
- int end_sample = rtile.start_sample + rtile.num_samples;
- int queue_size = dim.global_size[0] * dim.global_size[1];
-
- struct args_t {
- CUdeviceptr* split_data_buffer;
- int* num_elements;
- CUdeviceptr* ray_state;
- int* start_sample;
- int* end_sample;
- int* sx;
- int* sy;
- int* sw;
- int* sh;
- int* offset;
- int* stride;
- CUdeviceptr* queue_index;
- int* queuesize;
- CUdeviceptr* use_queues_flag;
- CUdeviceptr* work_pool_wgs;
- int* num_samples;
- CUdeviceptr* buffer;
- };
-
- args_t args = {
- &d_split_data,
- &num_global_elements,
- &d_ray_state,
- &rtile.start_sample,
- &end_sample,
- &rtile.x,
- &rtile.y,
- &rtile.w,
- &rtile.h,
- &rtile.offset,
- &rtile.stride,
- &d_queue_index,
- &queue_size,
- &d_use_queues_flag,
- &d_work_pool_wgs,
- &rtile.num_samples,
- &d_buffer
- };
-
- CUfunction data_init;
- cuda_assert(cuModuleGetFunction(&data_init, device->cuModule, "kernel_cuda_path_trace_data_init"));
- if(device->have_error()) {
- return false;
- }
-
- CUDASplitKernelFunction(device, data_init).enqueue(dim, (void**)&args);
-
- return !device->have_error();
+ CUDAContextScope scope(device);
+
+ CUdeviceptr d_split_data = device->cuda_device_ptr(split_data.device_pointer);
+ CUdeviceptr d_ray_state = device->cuda_device_ptr(ray_state.device_pointer);
+ CUdeviceptr d_queue_index = device->cuda_device_ptr(queue_index.device_pointer);
+ CUdeviceptr d_use_queues_flag = device->cuda_device_ptr(use_queues_flag.device_pointer);
+ CUdeviceptr d_work_pool_wgs = device->cuda_device_ptr(work_pool_wgs.device_pointer);
+
+ CUdeviceptr d_buffer = device->cuda_device_ptr(rtile.buffer);
+
+ int end_sample = rtile.start_sample + rtile.num_samples;
+ int queue_size = dim.global_size[0] * dim.global_size[1];
+
+ struct args_t {
+ CUdeviceptr *split_data_buffer;
+ int *num_elements;
+ CUdeviceptr *ray_state;
+ int *start_sample;
+ int *end_sample;
+ int *sx;
+ int *sy;
+ int *sw;
+ int *sh;
+ int *offset;
+ int *stride;
+ CUdeviceptr *queue_index;
+ int *queuesize;
+ CUdeviceptr *use_queues_flag;
+ CUdeviceptr *work_pool_wgs;
+ int *num_samples;
+ CUdeviceptr *buffer;
+ };
+
+ args_t args = {&d_split_data,
+ &num_global_elements,
+ &d_ray_state,
+ &rtile.start_sample,
+ &end_sample,
+ &rtile.x,
+ &rtile.y,
+ &rtile.w,
+ &rtile.h,
+ &rtile.offset,
+ &rtile.stride,
+ &d_queue_index,
+ &queue_size,
+ &d_use_queues_flag,
+ &d_work_pool_wgs,
+ &rtile.num_samples,
+ &d_buffer};
+
+ CUfunction data_init;
+ cuda_assert(
+ cuModuleGetFunction(&data_init, device->cuModule, "kernel_cuda_path_trace_data_init"));
+ if (device->have_error()) {
+ return false;
+ }
+
+ CUDASplitKernelFunction(device, data_init).enqueue(dim, (void **)&args);
+
+ return !device->have_error();
}
-SplitKernelFunction* CUDASplitKernel::get_split_kernel_function(const string& kernel_name,
- const DeviceRequestedFeatures&)
+SplitKernelFunction *CUDASplitKernel::get_split_kernel_function(const string &kernel_name,
+ const DeviceRequestedFeatures &)
{
- CUDAContextScope scope(device);
- CUfunction func;
-
- cuda_assert(cuModuleGetFunction(&func, device->cuModule, (string("kernel_cuda_") + kernel_name).data()));
- if(device->have_error()) {
- device->cuda_error_message(string_printf("kernel \"kernel_cuda_%s\" not found in module", kernel_name.data()));
- return NULL;
- }
-
- return new CUDASplitKernelFunction(device, func);
+ CUDAContextScope scope(device);
+ CUfunction func;
+
+ cuda_assert(
+ cuModuleGetFunction(&func, device->cuModule, (string("kernel_cuda_") + kernel_name).data()));
+ if (device->have_error()) {
+ device->cuda_error_message(
+ string_printf("kernel \"kernel_cuda_%s\" not found in module", kernel_name.data()));
+ return NULL;
+ }
+
+ return new CUDASplitKernelFunction(device, func);
}
int2 CUDASplitKernel::split_kernel_local_size()
{
- return make_int2(32, 1);
+ return make_int2(32, 1);
}
-int2 CUDASplitKernel::split_kernel_global_size(device_memory& kg, device_memory& data, DeviceTask * /*task*/)
+int2 CUDASplitKernel::split_kernel_global_size(device_memory &kg,
+ device_memory &data,
+ DeviceTask * /*task*/)
{
- CUDAContextScope scope(device);
- size_t free;
- size_t total;
+ CUDAContextScope scope(device);
+ size_t free;
+ size_t total;
- cuda_assert(cuMemGetInfo(&free, &total));
+ cuda_assert(cuMemGetInfo(&free, &total));
- VLOG(1) << "Maximum device allocation size: "
- << string_human_readable_number(free) << " bytes. ("
- << string_human_readable_size(free) << ").";
+ VLOG(1) << "Maximum device allocation size: " << string_human_readable_number(free)
+ << " bytes. (" << string_human_readable_size(free) << ").";
- size_t num_elements = max_elements_for_max_buffer_size(kg, data, free / 2);
- size_t side = round_down((int)sqrt(num_elements), 32);
- int2 global_size = make_int2(side, round_down(num_elements / side, 16));
- VLOG(1) << "Global size: " << global_size << ".";
- return global_size;
+ size_t num_elements = max_elements_for_max_buffer_size(kg, data, free / 2);
+ size_t side = round_down((int)sqrt(num_elements), 32);
+ int2 global_size = make_int2(side, round_down(num_elements / side, 16));
+ VLOG(1) << "Global size: " << global_size << ".";
+ return global_size;
}
bool device_cuda_init()
{
#ifdef WITH_CUDA_DYNLOAD
- static bool initialized = false;
- static bool result = false;
-
- if(initialized)
- return result;
-
- initialized = true;
- int cuew_result = cuewInit(CUEW_INIT_CUDA);
- if(cuew_result == CUEW_SUCCESS) {
- VLOG(1) << "CUEW initialization succeeded";
- if(CUDADevice::have_precompiled_kernels()) {
- VLOG(1) << "Found precompiled kernels";
- result = true;
- }
-#ifndef _WIN32
- else if(cuewCompilerPath() != NULL) {
- VLOG(1) << "Found CUDA compiler " << cuewCompilerPath();
- result = true;
- }
- else {
- VLOG(1) << "Neither precompiled kernels nor CUDA compiler was found,"
- << " unable to use CUDA";
- }
-#endif
- }
- else {
- VLOG(1) << "CUEW initialization failed: "
- << ((cuew_result == CUEW_ERROR_ATEXIT_FAILED)
- ? "Error setting up atexit() handler"
- : "Error opening the library");
- }
-
- return result;
+ static bool initialized = false;
+ static bool result = false;
+
+ if (initialized)
+ return result;
+
+ initialized = true;
+ int cuew_result = cuewInit(CUEW_INIT_CUDA);
+ if (cuew_result == CUEW_SUCCESS) {
+ VLOG(1) << "CUEW initialization succeeded";
+ if (CUDADevice::have_precompiled_kernels()) {
+ VLOG(1) << "Found precompiled kernels";
+ result = true;
+ }
+# ifndef _WIN32
+ else if (cuewCompilerPath() != NULL) {
+ VLOG(1) << "Found CUDA compiler " << cuewCompilerPath();
+ result = true;
+ }
+ else {
+ VLOG(1) << "Neither precompiled kernels nor CUDA compiler was found,"
+ << " unable to use CUDA";
+ }
+# endif
+ }
+ else {
+ VLOG(1) << "CUEW initialization failed: "
+ << ((cuew_result == CUEW_ERROR_ATEXIT_FAILED) ? "Error setting up atexit() handler" :
+ "Error opening the library");
+ }
+
+ return result;
#else /* WITH_CUDA_DYNLOAD */
- return true;
-#endif /* WITH_CUDA_DYNLOAD */
+ return true;
+#endif /* WITH_CUDA_DYNLOAD */
}
-Device *device_cuda_create(DeviceInfo& info, Stats &stats, Profiler &profiler, bool background)
+Device *device_cuda_create(DeviceInfo &info, Stats &stats, Profiler &profiler, bool background)
{
- return new CUDADevice(info, stats, profiler, background);
+ return new CUDADevice(info, stats, profiler, background);
}
static CUresult device_cuda_safe_init()
{
#ifdef _WIN32
- __try {
- return cuInit(0);
- }
- __except(EXCEPTION_EXECUTE_HANDLER) {
- /* Ignore crashes inside the CUDA driver and hope we can
- * survive even with corrupted CUDA installs. */
- fprintf(stderr, "Cycles CUDA: driver crashed, continuing without CUDA.\n");
- }
-
- return CUDA_ERROR_NO_DEVICE;
+ __try {
+ return cuInit(0);
+ }
+ __except (EXCEPTION_EXECUTE_HANDLER) {
+ /* Ignore crashes inside the CUDA driver and hope we can
+ * survive even with corrupted CUDA installs. */
+ fprintf(stderr, "Cycles CUDA: driver crashed, continuing without CUDA.\n");
+ }
+
+ return CUDA_ERROR_NO_DEVICE;
#else
- return cuInit(0);
+ return cuInit(0);
#endif
}
-void device_cuda_info(vector<DeviceInfo>& devices)
+void device_cuda_info(vector<DeviceInfo> &devices)
{
- CUresult result = device_cuda_safe_init();
- if(result != CUDA_SUCCESS) {
- if(result != CUDA_ERROR_NO_DEVICE)
- fprintf(stderr, "CUDA cuInit: %s\n", cuewErrorString(result));
- return;
- }
-
- int count = 0;
- result = cuDeviceGetCount(&count);
- if(result != CUDA_SUCCESS) {
- fprintf(stderr, "CUDA cuDeviceGetCount: %s\n", cuewErrorString(result));
- return;
- }
-
- vector<DeviceInfo> display_devices;
-
- for(int num = 0; num < count; num++) {
- char name[256];
-
- result = cuDeviceGetName(name, 256, num);
- if(result != CUDA_SUCCESS) {
- fprintf(stderr, "CUDA cuDeviceGetName: %s\n", cuewErrorString(result));
- continue;
- }
-
- int major;
- cuDeviceGetAttribute(&major, CU_DEVICE_ATTRIBUTE_COMPUTE_CAPABILITY_MAJOR, num);
- if(major < 3) {
- VLOG(1) << "Ignoring device \"" << name
- << "\", this graphics card is no longer supported.";
- continue;
- }
-
- DeviceInfo info;
-
- info.type = DEVICE_CUDA;
- info.description = string(name);
- info.num = num;
-
- info.has_half_images = (major >= 3);
- info.has_volume_decoupled = false;
-
- int pci_location[3] = {0, 0, 0};
- cuDeviceGetAttribute(&pci_location[0], CU_DEVICE_ATTRIBUTE_PCI_DOMAIN_ID, num);
- cuDeviceGetAttribute(&pci_location[1], CU_DEVICE_ATTRIBUTE_PCI_BUS_ID, num);
- cuDeviceGetAttribute(&pci_location[2], CU_DEVICE_ATTRIBUTE_PCI_DEVICE_ID, num);
- info.id = string_printf("CUDA_%s_%04x:%02x:%02x",
- name,
- (unsigned int)pci_location[0],
- (unsigned int)pci_location[1],
- (unsigned int)pci_location[2]);
-
- /* If device has a kernel timeout and no compute preemption, we assume
- * it is connected to a display and will freeze the display while doing
- * computations. */
- int timeout_attr = 0, preempt_attr = 0;
- cuDeviceGetAttribute(&timeout_attr, CU_DEVICE_ATTRIBUTE_KERNEL_EXEC_TIMEOUT, num);
- cuDeviceGetAttribute(&preempt_attr, CU_DEVICE_ATTRIBUTE_COMPUTE_PREEMPTION_SUPPORTED, num);
-
- if(timeout_attr && !preempt_attr) {
- VLOG(1) << "Device is recognized as display.";
- info.description += " (Display)";
- info.display_device = true;
- display_devices.push_back(info);
- }
- else {
- devices.push_back(info);
- }
- VLOG(1) << "Added device \"" << name << "\" with id \"" << info.id << "\".";
- }
-
- if(!display_devices.empty())
- devices.insert(devices.end(), display_devices.begin(), display_devices.end());
+ CUresult result = device_cuda_safe_init();
+ if (result != CUDA_SUCCESS) {
+ if (result != CUDA_ERROR_NO_DEVICE)
+ fprintf(stderr, "CUDA cuInit: %s\n", cuewErrorString(result));
+ return;
+ }
+
+ int count = 0;
+ result = cuDeviceGetCount(&count);
+ if (result != CUDA_SUCCESS) {
+ fprintf(stderr, "CUDA cuDeviceGetCount: %s\n", cuewErrorString(result));
+ return;
+ }
+
+ vector<DeviceInfo> display_devices;
+
+ for (int num = 0; num < count; num++) {
+ char name[256];
+
+ result = cuDeviceGetName(name, 256, num);
+ if (result != CUDA_SUCCESS) {
+ fprintf(stderr, "CUDA cuDeviceGetName: %s\n", cuewErrorString(result));
+ continue;
+ }
+
+ int major;
+ cuDeviceGetAttribute(&major, CU_DEVICE_ATTRIBUTE_COMPUTE_CAPABILITY_MAJOR, num);
+ if (major < 3) {
+ VLOG(1) << "Ignoring device \"" << name << "\", this graphics card is no longer supported.";
+ continue;
+ }
+
+ DeviceInfo info;
+
+ info.type = DEVICE_CUDA;
+ info.description = string(name);
+ info.num = num;
+
+ info.has_half_images = (major >= 3);
+ info.has_volume_decoupled = false;
+
+ int pci_location[3] = {0, 0, 0};
+ cuDeviceGetAttribute(&pci_location[0], CU_DEVICE_ATTRIBUTE_PCI_DOMAIN_ID, num);
+ cuDeviceGetAttribute(&pci_location[1], CU_DEVICE_ATTRIBUTE_PCI_BUS_ID, num);
+ cuDeviceGetAttribute(&pci_location[2], CU_DEVICE_ATTRIBUTE_PCI_DEVICE_ID, num);
+ info.id = string_printf("CUDA_%s_%04x:%02x:%02x",
+ name,
+ (unsigned int)pci_location[0],
+ (unsigned int)pci_location[1],
+ (unsigned int)pci_location[2]);
+
+ /* If device has a kernel timeout and no compute preemption, we assume
+ * it is connected to a display and will freeze the display while doing
+ * computations. */
+ int timeout_attr = 0, preempt_attr = 0;
+ cuDeviceGetAttribute(&timeout_attr, CU_DEVICE_ATTRIBUTE_KERNEL_EXEC_TIMEOUT, num);
+ cuDeviceGetAttribute(&preempt_attr, CU_DEVICE_ATTRIBUTE_COMPUTE_PREEMPTION_SUPPORTED, num);
+
+ if (timeout_attr && !preempt_attr) {
+ VLOG(1) << "Device is recognized as display.";
+ info.description += " (Display)";
+ info.display_device = true;
+ display_devices.push_back(info);
+ }
+ else {
+ devices.push_back(info);
+ }
+ VLOG(1) << "Added device \"" << name << "\" with id \"" << info.id << "\".";
+ }
+
+ if (!display_devices.empty())
+ devices.insert(devices.end(), display_devices.begin(), display_devices.end());
}
string device_cuda_capabilities()
{
- CUresult result = device_cuda_safe_init();
- if(result != CUDA_SUCCESS) {
- if(result != CUDA_ERROR_NO_DEVICE) {
- return string("Error initializing CUDA: ") + cuewErrorString(result);
- }
- return "No CUDA device found\n";
- }
-
- int count;
- result = cuDeviceGetCount(&count);
- if(result != CUDA_SUCCESS) {
- return string("Error getting devices: ") + cuewErrorString(result);
- }
-
- string capabilities = "";
- for(int num = 0; num < count; num++) {
- char name[256];
- if(cuDeviceGetName(name, 256, num) != CUDA_SUCCESS) {
- continue;
- }
- capabilities += string("\t") + name + "\n";
- int value;
+ CUresult result = device_cuda_safe_init();
+ if (result != CUDA_SUCCESS) {
+ if (result != CUDA_ERROR_NO_DEVICE) {
+ return string("Error initializing CUDA: ") + cuewErrorString(result);
+ }
+ return "No CUDA device found\n";
+ }
+
+ int count;
+ result = cuDeviceGetCount(&count);
+ if (result != CUDA_SUCCESS) {
+ return string("Error getting devices: ") + cuewErrorString(result);
+ }
+
+ string capabilities = "";
+ for (int num = 0; num < count; num++) {
+ char name[256];
+ if (cuDeviceGetName(name, 256, num) != CUDA_SUCCESS) {
+ continue;
+ }
+ capabilities += string("\t") + name + "\n";
+ int value;
#define GET_ATTR(attr) \
- { \
- if(cuDeviceGetAttribute(&value, \
- CU_DEVICE_ATTRIBUTE_##attr, \
- num) == CUDA_SUCCESS) \
- { \
- capabilities += string_printf("\t\tCU_DEVICE_ATTRIBUTE_" #attr "\t\t\t%d\n", \
- value); \
- } \
- } (void) 0
- /* TODO(sergey): Strip all attributes which are not useful for us
- * or does not depend on the driver.
- */
- GET_ATTR(MAX_THREADS_PER_BLOCK);
- GET_ATTR(MAX_BLOCK_DIM_X);
- GET_ATTR(MAX_BLOCK_DIM_Y);
- GET_ATTR(MAX_BLOCK_DIM_Z);
- GET_ATTR(MAX_GRID_DIM_X);
- GET_ATTR(MAX_GRID_DIM_Y);
- GET_ATTR(MAX_GRID_DIM_Z);
- GET_ATTR(MAX_SHARED_MEMORY_PER_BLOCK);
- GET_ATTR(SHARED_MEMORY_PER_BLOCK);
- GET_ATTR(TOTAL_CONSTANT_MEMORY);
- GET_ATTR(WARP_SIZE);
- GET_ATTR(MAX_PITCH);
- GET_ATTR(MAX_REGISTERS_PER_BLOCK);
- GET_ATTR(REGISTERS_PER_BLOCK);
- GET_ATTR(CLOCK_RATE);
- GET_ATTR(TEXTURE_ALIGNMENT);
- GET_ATTR(GPU_OVERLAP);
- GET_ATTR(MULTIPROCESSOR_COUNT);
- GET_ATTR(KERNEL_EXEC_TIMEOUT);
- GET_ATTR(INTEGRATED);
- GET_ATTR(CAN_MAP_HOST_MEMORY);
- GET_ATTR(COMPUTE_MODE);
- GET_ATTR(MAXIMUM_TEXTURE1D_WIDTH);
- GET_ATTR(MAXIMUM_TEXTURE2D_WIDTH);
- GET_ATTR(MAXIMUM_TEXTURE2D_HEIGHT);
- GET_ATTR(MAXIMUM_TEXTURE3D_WIDTH);
- GET_ATTR(MAXIMUM_TEXTURE3D_HEIGHT);
- GET_ATTR(MAXIMUM_TEXTURE3D_DEPTH);
- GET_ATTR(MAXIMUM_TEXTURE2D_LAYERED_WIDTH);
- GET_ATTR(MAXIMUM_TEXTURE2D_LAYERED_HEIGHT);
- GET_ATTR(MAXIMUM_TEXTURE2D_LAYERED_LAYERS);
- GET_ATTR(MAXIMUM_TEXTURE2D_ARRAY_WIDTH);
- GET_ATTR(MAXIMUM_TEXTURE2D_ARRAY_HEIGHT);
- GET_ATTR(MAXIMUM_TEXTURE2D_ARRAY_NUMSLICES);
- GET_ATTR(SURFACE_ALIGNMENT);
- GET_ATTR(CONCURRENT_KERNELS);
- GET_ATTR(ECC_ENABLED);
- GET_ATTR(TCC_DRIVER);
- GET_ATTR(MEMORY_CLOCK_RATE);
- GET_ATTR(GLOBAL_MEMORY_BUS_WIDTH);
- GET_ATTR(L2_CACHE_SIZE);
- GET_ATTR(MAX_THREADS_PER_MULTIPROCESSOR);
- GET_ATTR(ASYNC_ENGINE_COUNT);
- GET_ATTR(UNIFIED_ADDRESSING);
- GET_ATTR(MAXIMUM_TEXTURE1D_LAYERED_WIDTH);
- GET_ATTR(MAXIMUM_TEXTURE1D_LAYERED_LAYERS);
- GET_ATTR(CAN_TEX2D_GATHER);
- GET_ATTR(MAXIMUM_TEXTURE2D_GATHER_WIDTH);
- GET_ATTR(MAXIMUM_TEXTURE2D_GATHER_HEIGHT);
- GET_ATTR(MAXIMUM_TEXTURE3D_WIDTH_ALTERNATE);
- GET_ATTR(MAXIMUM_TEXTURE3D_HEIGHT_ALTERNATE);
- GET_ATTR(MAXIMUM_TEXTURE3D_DEPTH_ALTERNATE);
- GET_ATTR(TEXTURE_PITCH_ALIGNMENT);
- GET_ATTR(MAXIMUM_TEXTURECUBEMAP_WIDTH);
- GET_ATTR(MAXIMUM_TEXTURECUBEMAP_LAYERED_WIDTH);
- GET_ATTR(MAXIMUM_TEXTURECUBEMAP_LAYERED_LAYERS);
- GET_ATTR(MAXIMUM_SURFACE1D_WIDTH);
- GET_ATTR(MAXIMUM_SURFACE2D_WIDTH);
- GET_ATTR(MAXIMUM_SURFACE2D_HEIGHT);
- GET_ATTR(MAXIMUM_SURFACE3D_WIDTH);
- GET_ATTR(MAXIMUM_SURFACE3D_HEIGHT);
- GET_ATTR(MAXIMUM_SURFACE3D_DEPTH);
- GET_ATTR(MAXIMUM_SURFACE1D_LAYERED_WIDTH);
- GET_ATTR(MAXIMUM_SURFACE1D_LAYERED_LAYERS);
- GET_ATTR(MAXIMUM_SURFACE2D_LAYERED_WIDTH);
- GET_ATTR(MAXIMUM_SURFACE2D_LAYERED_HEIGHT);
- GET_ATTR(MAXIMUM_SURFACE2D_LAYERED_LAYERS);
- GET_ATTR(MAXIMUM_SURFACECUBEMAP_WIDTH);
- GET_ATTR(MAXIMUM_SURFACECUBEMAP_LAYERED_WIDTH);
- GET_ATTR(MAXIMUM_SURFACECUBEMAP_LAYERED_LAYERS);
- GET_ATTR(MAXIMUM_TEXTURE1D_LINEAR_WIDTH);
- GET_ATTR(MAXIMUM_TEXTURE2D_LINEAR_WIDTH);
- GET_ATTR(MAXIMUM_TEXTURE2D_LINEAR_HEIGHT);
- GET_ATTR(MAXIMUM_TEXTURE2D_LINEAR_PITCH);
- GET_ATTR(MAXIMUM_TEXTURE2D_MIPMAPPED_WIDTH);
- GET_ATTR(MAXIMUM_TEXTURE2D_MIPMAPPED_HEIGHT);
- GET_ATTR(COMPUTE_CAPABILITY_MAJOR);
- GET_ATTR(COMPUTE_CAPABILITY_MINOR);
- GET_ATTR(MAXIMUM_TEXTURE1D_MIPMAPPED_WIDTH);
- GET_ATTR(STREAM_PRIORITIES_SUPPORTED);
- GET_ATTR(GLOBAL_L1_CACHE_SUPPORTED);
- GET_ATTR(LOCAL_L1_CACHE_SUPPORTED);
- GET_ATTR(MAX_SHARED_MEMORY_PER_MULTIPROCESSOR);
- GET_ATTR(MAX_REGISTERS_PER_MULTIPROCESSOR);
- GET_ATTR(MANAGED_MEMORY);
- GET_ATTR(MULTI_GPU_BOARD);
- GET_ATTR(MULTI_GPU_BOARD_GROUP_ID);
+ { \
+ if (cuDeviceGetAttribute(&value, CU_DEVICE_ATTRIBUTE_##attr, num) == CUDA_SUCCESS) { \
+ capabilities += string_printf("\t\tCU_DEVICE_ATTRIBUTE_" #attr "\t\t\t%d\n", value); \
+ } \
+ } \
+ (void)0
+ /* TODO(sergey): Strip all attributes which are not useful for us
+ * or does not depend on the driver.
+ */
+ GET_ATTR(MAX_THREADS_PER_BLOCK);
+ GET_ATTR(MAX_BLOCK_DIM_X);
+ GET_ATTR(MAX_BLOCK_DIM_Y);
+ GET_ATTR(MAX_BLOCK_DIM_Z);
+ GET_ATTR(MAX_GRID_DIM_X);
+ GET_ATTR(MAX_GRID_DIM_Y);
+ GET_ATTR(MAX_GRID_DIM_Z);
+ GET_ATTR(MAX_SHARED_MEMORY_PER_BLOCK);
+ GET_ATTR(SHARED_MEMORY_PER_BLOCK);
+ GET_ATTR(TOTAL_CONSTANT_MEMORY);
+ GET_ATTR(WARP_SIZE);
+ GET_ATTR(MAX_PITCH);
+ GET_ATTR(MAX_REGISTERS_PER_BLOCK);
+ GET_ATTR(REGISTERS_PER_BLOCK);
+ GET_ATTR(CLOCK_RATE);
+ GET_ATTR(TEXTURE_ALIGNMENT);
+ GET_ATTR(GPU_OVERLAP);
+ GET_ATTR(MULTIPROCESSOR_COUNT);
+ GET_ATTR(KERNEL_EXEC_TIMEOUT);
+ GET_ATTR(INTEGRATED);
+ GET_ATTR(CAN_MAP_HOST_MEMORY);
+ GET_ATTR(COMPUTE_MODE);
+ GET_ATTR(MAXIMUM_TEXTURE1D_WIDTH);
+ GET_ATTR(MAXIMUM_TEXTURE2D_WIDTH);
+ GET_ATTR(MAXIMUM_TEXTURE2D_HEIGHT);
+ GET_ATTR(MAXIMUM_TEXTURE3D_WIDTH);
+ GET_ATTR(MAXIMUM_TEXTURE3D_HEIGHT);
+ GET_ATTR(MAXIMUM_TEXTURE3D_DEPTH);
+ GET_ATTR(MAXIMUM_TEXTURE2D_LAYERED_WIDTH);
+ GET_ATTR(MAXIMUM_TEXTURE2D_LAYERED_HEIGHT);
+ GET_ATTR(MAXIMUM_TEXTURE2D_LAYERED_LAYERS);
+ GET_ATTR(MAXIMUM_TEXTURE2D_ARRAY_WIDTH);
+ GET_ATTR(MAXIMUM_TEXTURE2D_ARRAY_HEIGHT);
+ GET_ATTR(MAXIMUM_TEXTURE2D_ARRAY_NUMSLICES);
+ GET_ATTR(SURFACE_ALIGNMENT);
+ GET_ATTR(CONCURRENT_KERNELS);
+ GET_ATTR(ECC_ENABLED);
+ GET_ATTR(TCC_DRIVER);
+ GET_ATTR(MEMORY_CLOCK_RATE);
+ GET_ATTR(GLOBAL_MEMORY_BUS_WIDTH);
+ GET_ATTR(L2_CACHE_SIZE);
+ GET_ATTR(MAX_THREADS_PER_MULTIPROCESSOR);
+ GET_ATTR(ASYNC_ENGINE_COUNT);
+ GET_ATTR(UNIFIED_ADDRESSING);
+ GET_ATTR(MAXIMUM_TEXTURE1D_LAYERED_WIDTH);
+ GET_ATTR(MAXIMUM_TEXTURE1D_LAYERED_LAYERS);
+ GET_ATTR(CAN_TEX2D_GATHER);
+ GET_ATTR(MAXIMUM_TEXTURE2D_GATHER_WIDTH);
+ GET_ATTR(MAXIMUM_TEXTURE2D_GATHER_HEIGHT);
+ GET_ATTR(MAXIMUM_TEXTURE3D_WIDTH_ALTERNATE);
+ GET_ATTR(MAXIMUM_TEXTURE3D_HEIGHT_ALTERNATE);
+ GET_ATTR(MAXIMUM_TEXTURE3D_DEPTH_ALTERNATE);
+ GET_ATTR(TEXTURE_PITCH_ALIGNMENT);
+ GET_ATTR(MAXIMUM_TEXTURECUBEMAP_WIDTH);
+ GET_ATTR(MAXIMUM_TEXTURECUBEMAP_LAYERED_WIDTH);
+ GET_ATTR(MAXIMUM_TEXTURECUBEMAP_LAYERED_LAYERS);
+ GET_ATTR(MAXIMUM_SURFACE1D_WIDTH);
+ GET_ATTR(MAXIMUM_SURFACE2D_WIDTH);
+ GET_ATTR(MAXIMUM_SURFACE2D_HEIGHT);
+ GET_ATTR(MAXIMUM_SURFACE3D_WIDTH);
+ GET_ATTR(MAXIMUM_SURFACE3D_HEIGHT);
+ GET_ATTR(MAXIMUM_SURFACE3D_DEPTH);
+ GET_ATTR(MAXIMUM_SURFACE1D_LAYERED_WIDTH);
+ GET_ATTR(MAXIMUM_SURFACE1D_LAYERED_LAYERS);
+ GET_ATTR(MAXIMUM_SURFACE2D_LAYERED_WIDTH);
+ GET_ATTR(MAXIMUM_SURFACE2D_LAYERED_HEIGHT);
+ GET_ATTR(MAXIMUM_SURFACE2D_LAYERED_LAYERS);
+ GET_ATTR(MAXIMUM_SURFACECUBEMAP_WIDTH);
+ GET_ATTR(MAXIMUM_SURFACECUBEMAP_LAYERED_WIDTH);
+ GET_ATTR(MAXIMUM_SURFACECUBEMAP_LAYERED_LAYERS);
+ GET_ATTR(MAXIMUM_TEXTURE1D_LINEAR_WIDTH);
+ GET_ATTR(MAXIMUM_TEXTURE2D_LINEAR_WIDTH);
+ GET_ATTR(MAXIMUM_TEXTURE2D_LINEAR_HEIGHT);
+ GET_ATTR(MAXIMUM_TEXTURE2D_LINEAR_PITCH);
+ GET_ATTR(MAXIMUM_TEXTURE2D_MIPMAPPED_WIDTH);
+ GET_ATTR(MAXIMUM_TEXTURE2D_MIPMAPPED_HEIGHT);
+ GET_ATTR(COMPUTE_CAPABILITY_MAJOR);
+ GET_ATTR(COMPUTE_CAPABILITY_MINOR);
+ GET_ATTR(MAXIMUM_TEXTURE1D_MIPMAPPED_WIDTH);
+ GET_ATTR(STREAM_PRIORITIES_SUPPORTED);
+ GET_ATTR(GLOBAL_L1_CACHE_SUPPORTED);
+ GET_ATTR(LOCAL_L1_CACHE_SUPPORTED);
+ GET_ATTR(MAX_SHARED_MEMORY_PER_MULTIPROCESSOR);
+ GET_ATTR(MAX_REGISTERS_PER_MULTIPROCESSOR);
+ GET_ATTR(MANAGED_MEMORY);
+ GET_ATTR(MULTI_GPU_BOARD);
+ GET_ATTR(MULTI_GPU_BOARD_GROUP_ID);
#undef GET_ATTR
- capabilities += "\n";
- }
+ capabilities += "\n";
+ }
- return capabilities;
+ return capabilities;
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/device/device_denoising.cpp b/intern/cycles/device/device_denoising.cpp
index 1bb144ef85a..05a7fb8ae4d 100644
--- a/intern/cycles/device/device_denoising.cpp
+++ b/intern/cycles/device/device_denoising.cpp
@@ -21,314 +21,329 @@
CCL_NAMESPACE_BEGIN
DenoisingTask::DenoisingTask(Device *device, const DeviceTask &task)
-: tile_info_mem(device, "denoising tile info mem", MEM_READ_WRITE),
- profiler(NULL),
- storage(device),
- buffer(device),
- device(device)
+ : tile_info_mem(device, "denoising tile info mem", MEM_READ_WRITE),
+ profiler(NULL),
+ storage(device),
+ buffer(device),
+ device(device)
{
- radius = task.denoising.radius;
- nlm_k_2 = powf(2.0f, lerp(-5.0f, 3.0f, task.denoising.strength));
- if(task.denoising.relative_pca) {
- pca_threshold = -powf(10.0f, lerp(-8.0f, 0.0f, task.denoising.feature_strength));
- }
- else {
- pca_threshold = powf(10.0f, lerp(-5.0f, 3.0f, task.denoising.feature_strength));
- }
-
- render_buffer.frame_stride = task.frame_stride;
- render_buffer.pass_stride = task.pass_stride;
- render_buffer.offset = task.pass_denoising_data;
-
- target_buffer.pass_stride = task.target_pass_stride;
- target_buffer.denoising_clean_offset = task.pass_denoising_clean;
- target_buffer.offset = 0;
-
- functions.map_neighbor_tiles = function_bind(task.map_neighbor_tiles, _1, device);
- functions.unmap_neighbor_tiles = function_bind(task.unmap_neighbor_tiles, _1, device);
-
- tile_info = (TileInfo*) tile_info_mem.alloc(sizeof(TileInfo)/sizeof(int));
- tile_info->from_render = task.denoising_from_render? 1 : 0;
-
- tile_info->frames[0] = 0;
- tile_info->num_frames = min(task.denoising_frames.size() + 1, DENOISE_MAX_FRAMES);
- for(int i = 1; i < tile_info->num_frames; i++) {
- tile_info->frames[i] = task.denoising_frames[i-1];
- }
-
- write_passes = task.denoising_write_passes;
- do_filter = task.denoising_do_filter;
+ radius = task.denoising.radius;
+ nlm_k_2 = powf(2.0f, lerp(-5.0f, 3.0f, task.denoising.strength));
+ if (task.denoising.relative_pca) {
+ pca_threshold = -powf(10.0f, lerp(-8.0f, 0.0f, task.denoising.feature_strength));
+ }
+ else {
+ pca_threshold = powf(10.0f, lerp(-5.0f, 3.0f, task.denoising.feature_strength));
+ }
+
+ render_buffer.frame_stride = task.frame_stride;
+ render_buffer.pass_stride = task.pass_stride;
+ render_buffer.offset = task.pass_denoising_data;
+
+ target_buffer.pass_stride = task.target_pass_stride;
+ target_buffer.denoising_clean_offset = task.pass_denoising_clean;
+ target_buffer.offset = 0;
+
+ functions.map_neighbor_tiles = function_bind(task.map_neighbor_tiles, _1, device);
+ functions.unmap_neighbor_tiles = function_bind(task.unmap_neighbor_tiles, _1, device);
+
+ tile_info = (TileInfo *)tile_info_mem.alloc(sizeof(TileInfo) / sizeof(int));
+ tile_info->from_render = task.denoising_from_render ? 1 : 0;
+
+ tile_info->frames[0] = 0;
+ tile_info->num_frames = min(task.denoising_frames.size() + 1, DENOISE_MAX_FRAMES);
+ for (int i = 1; i < tile_info->num_frames; i++) {
+ tile_info->frames[i] = task.denoising_frames[i - 1];
+ }
+
+ write_passes = task.denoising_write_passes;
+ do_filter = task.denoising_do_filter;
}
DenoisingTask::~DenoisingTask()
{
- storage.XtWX.free();
- storage.XtWY.free();
- storage.transform.free();
- storage.rank.free();
- buffer.mem.free();
- buffer.temporary_mem.free();
- tile_info_mem.free();
+ storage.XtWX.free();
+ storage.XtWY.free();
+ storage.transform.free();
+ storage.rank.free();
+ buffer.mem.free();
+ buffer.temporary_mem.free();
+ tile_info_mem.free();
}
void DenoisingTask::set_render_buffer(RenderTile *rtiles)
{
- for(int i = 0; i < 9; i++) {
- tile_info->offsets[i] = rtiles[i].offset;
- tile_info->strides[i] = rtiles[i].stride;
- tile_info->buffers[i] = rtiles[i].buffer;
- }
- tile_info->x[0] = rtiles[3].x;
- tile_info->x[1] = rtiles[4].x;
- tile_info->x[2] = rtiles[5].x;
- tile_info->x[3] = rtiles[5].x + rtiles[5].w;
- tile_info->y[0] = rtiles[1].y;
- tile_info->y[1] = rtiles[4].y;
- tile_info->y[2] = rtiles[7].y;
- tile_info->y[3] = rtiles[7].y + rtiles[7].h;
-
- target_buffer.offset = rtiles[9].offset;
- target_buffer.stride = rtiles[9].stride;
- target_buffer.ptr = rtiles[9].buffer;
-
- if(write_passes && rtiles[9].buffers) {
- target_buffer.denoising_output_offset = rtiles[9].buffers->params.get_denoising_prefiltered_offset();
- }
- else {
- target_buffer.denoising_output_offset = 0;
- }
-
- tile_info_mem.copy_to_device();
+ for (int i = 0; i < 9; i++) {
+ tile_info->offsets[i] = rtiles[i].offset;
+ tile_info->strides[i] = rtiles[i].stride;
+ tile_info->buffers[i] = rtiles[i].buffer;
+ }
+ tile_info->x[0] = rtiles[3].x;
+ tile_info->x[1] = rtiles[4].x;
+ tile_info->x[2] = rtiles[5].x;
+ tile_info->x[3] = rtiles[5].x + rtiles[5].w;
+ tile_info->y[0] = rtiles[1].y;
+ tile_info->y[1] = rtiles[4].y;
+ tile_info->y[2] = rtiles[7].y;
+ tile_info->y[3] = rtiles[7].y + rtiles[7].h;
+
+ target_buffer.offset = rtiles[9].offset;
+ target_buffer.stride = rtiles[9].stride;
+ target_buffer.ptr = rtiles[9].buffer;
+
+ if (write_passes && rtiles[9].buffers) {
+ target_buffer.denoising_output_offset =
+ rtiles[9].buffers->params.get_denoising_prefiltered_offset();
+ }
+ else {
+ target_buffer.denoising_output_offset = 0;
+ }
+
+ tile_info_mem.copy_to_device();
}
void DenoisingTask::setup_denoising_buffer()
{
- /* Expand filter_area by radius pixels and clamp the result to the extent of the neighboring tiles */
- rect = rect_from_shape(filter_area.x, filter_area.y, filter_area.z, filter_area.w);
- rect = rect_expand(rect, radius);
- rect = rect_clip(rect, make_int4(tile_info->x[0], tile_info->y[0], tile_info->x[3], tile_info->y[3]));
-
- buffer.use_intensity = write_passes || (tile_info->num_frames > 1);
- buffer.passes = buffer.use_intensity? 15 : 14;
- buffer.width = rect.z - rect.x;
- buffer.stride = align_up(buffer.width, 4);
- buffer.h = rect.w - rect.y;
- int alignment_floats = divide_up(device->mem_sub_ptr_alignment(), sizeof(float));
- buffer.pass_stride = align_up(buffer.stride * buffer.h, alignment_floats);
- buffer.frame_stride = buffer.pass_stride * buffer.passes;
- /* Pad the total size by four floats since the SIMD kernels might go a bit over the end. */
- int mem_size = align_up(tile_info->num_frames * buffer.frame_stride + 4, alignment_floats);
- buffer.mem.alloc_to_device(mem_size, false);
- buffer.use_time = (tile_info->num_frames > 1);
-
- /* CPUs process shifts sequentially while GPUs process them in parallel. */
- int num_layers;
- if(buffer.gpu_temporary_mem) {
- /* Shadowing prefiltering uses a radius of 6, so allocate at least that much. */
- int max_radius = max(radius, 6);
- int num_shifts = (2*max_radius + 1) * (2*max_radius + 1);
- num_layers = 2*num_shifts + 1;
- }
- else {
- num_layers = 3;
- }
- /* Allocate two layers per shift as well as one for the weight accumulation. */
- buffer.temporary_mem.alloc_to_device(num_layers * buffer.pass_stride);
+ /* Expand filter_area by radius pixels and clamp the result to the extent of the neighboring tiles */
+ rect = rect_from_shape(filter_area.x, filter_area.y, filter_area.z, filter_area.w);
+ rect = rect_expand(rect, radius);
+ rect = rect_clip(rect,
+ make_int4(tile_info->x[0], tile_info->y[0], tile_info->x[3], tile_info->y[3]));
+
+ buffer.use_intensity = write_passes || (tile_info->num_frames > 1);
+ buffer.passes = buffer.use_intensity ? 15 : 14;
+ buffer.width = rect.z - rect.x;
+ buffer.stride = align_up(buffer.width, 4);
+ buffer.h = rect.w - rect.y;
+ int alignment_floats = divide_up(device->mem_sub_ptr_alignment(), sizeof(float));
+ buffer.pass_stride = align_up(buffer.stride * buffer.h, alignment_floats);
+ buffer.frame_stride = buffer.pass_stride * buffer.passes;
+ /* Pad the total size by four floats since the SIMD kernels might go a bit over the end. */
+ int mem_size = align_up(tile_info->num_frames * buffer.frame_stride + 4, alignment_floats);
+ buffer.mem.alloc_to_device(mem_size, false);
+ buffer.use_time = (tile_info->num_frames > 1);
+
+ /* CPUs process shifts sequentially while GPUs process them in parallel. */
+ int num_layers;
+ if (buffer.gpu_temporary_mem) {
+ /* Shadowing prefiltering uses a radius of 6, so allocate at least that much. */
+ int max_radius = max(radius, 6);
+ int num_shifts = (2 * max_radius + 1) * (2 * max_radius + 1);
+ num_layers = 2 * num_shifts + 1;
+ }
+ else {
+ num_layers = 3;
+ }
+ /* Allocate two layers per shift as well as one for the weight accumulation. */
+ buffer.temporary_mem.alloc_to_device(num_layers * buffer.pass_stride);
}
void DenoisingTask::prefilter_shadowing()
{
- device_ptr null_ptr = (device_ptr) 0;
-
- device_sub_ptr unfiltered_a (buffer.mem, 0, buffer.pass_stride);
- device_sub_ptr unfiltered_b (buffer.mem, 1*buffer.pass_stride, buffer.pass_stride);
- device_sub_ptr sample_var (buffer.mem, 2*buffer.pass_stride, buffer.pass_stride);
- device_sub_ptr sample_var_var (buffer.mem, 3*buffer.pass_stride, buffer.pass_stride);
- device_sub_ptr buffer_var (buffer.mem, 5*buffer.pass_stride, buffer.pass_stride);
- device_sub_ptr filtered_var (buffer.mem, 6*buffer.pass_stride, buffer.pass_stride);
-
- /* Get the A/B unfiltered passes, the combined sample variance, the estimated variance of the sample variance and the buffer variance. */
- functions.divide_shadow(*unfiltered_a, *unfiltered_b, *sample_var, *sample_var_var, *buffer_var);
-
- /* Smooth the (generally pretty noisy) buffer variance using the spatial information from the sample variance. */
- nlm_state.set_parameters(6, 3, 4.0f, 1.0f, false);
- functions.non_local_means(*buffer_var, *sample_var, *sample_var_var, *filtered_var);
-
- /* Reuse memory, the previous data isn't needed anymore. */
- device_ptr filtered_a = *buffer_var,
- filtered_b = *sample_var;
- /* Use the smoothed variance to filter the two shadow half images using each other for weight calculation. */
- nlm_state.set_parameters(5, 3, 1.0f, 0.25f, false);
- functions.non_local_means(*unfiltered_a, *unfiltered_b, *filtered_var, filtered_a);
- functions.non_local_means(*unfiltered_b, *unfiltered_a, *filtered_var, filtered_b);
-
- device_ptr residual_var = *sample_var_var;
- /* Estimate the residual variance between the two filtered halves. */
- functions.combine_halves(filtered_a, filtered_b, null_ptr, residual_var, 2, rect);
-
- device_ptr final_a = *unfiltered_a,
- final_b = *unfiltered_b;
- /* Use the residual variance for a second filter pass. */
- nlm_state.set_parameters(4, 2, 1.0f, 0.5f, false);
- functions.non_local_means(filtered_a, filtered_b, residual_var, final_a);
- functions.non_local_means(filtered_b, filtered_a, residual_var, final_b);
-
- /* Combine the two double-filtered halves to a final shadow feature. */
- device_sub_ptr shadow_pass(buffer.mem, 4*buffer.pass_stride, buffer.pass_stride);
- functions.combine_halves(final_a, final_b, *shadow_pass, null_ptr, 0, rect);
+ device_ptr null_ptr = (device_ptr)0;
+
+ device_sub_ptr unfiltered_a(buffer.mem, 0, buffer.pass_stride);
+ device_sub_ptr unfiltered_b(buffer.mem, 1 * buffer.pass_stride, buffer.pass_stride);
+ device_sub_ptr sample_var(buffer.mem, 2 * buffer.pass_stride, buffer.pass_stride);
+ device_sub_ptr sample_var_var(buffer.mem, 3 * buffer.pass_stride, buffer.pass_stride);
+ device_sub_ptr buffer_var(buffer.mem, 5 * buffer.pass_stride, buffer.pass_stride);
+ device_sub_ptr filtered_var(buffer.mem, 6 * buffer.pass_stride, buffer.pass_stride);
+
+ /* Get the A/B unfiltered passes, the combined sample variance, the estimated variance of the sample variance and the buffer variance. */
+ functions.divide_shadow(*unfiltered_a, *unfiltered_b, *sample_var, *sample_var_var, *buffer_var);
+
+ /* Smooth the (generally pretty noisy) buffer variance using the spatial information from the sample variance. */
+ nlm_state.set_parameters(6, 3, 4.0f, 1.0f, false);
+ functions.non_local_means(*buffer_var, *sample_var, *sample_var_var, *filtered_var);
+
+ /* Reuse memory, the previous data isn't needed anymore. */
+ device_ptr filtered_a = *buffer_var, filtered_b = *sample_var;
+ /* Use the smoothed variance to filter the two shadow half images using each other for weight calculation. */
+ nlm_state.set_parameters(5, 3, 1.0f, 0.25f, false);
+ functions.non_local_means(*unfiltered_a, *unfiltered_b, *filtered_var, filtered_a);
+ functions.non_local_means(*unfiltered_b, *unfiltered_a, *filtered_var, filtered_b);
+
+ device_ptr residual_var = *sample_var_var;
+ /* Estimate the residual variance between the two filtered halves. */
+ functions.combine_halves(filtered_a, filtered_b, null_ptr, residual_var, 2, rect);
+
+ device_ptr final_a = *unfiltered_a, final_b = *unfiltered_b;
+ /* Use the residual variance for a second filter pass. */
+ nlm_state.set_parameters(4, 2, 1.0f, 0.5f, false);
+ functions.non_local_means(filtered_a, filtered_b, residual_var, final_a);
+ functions.non_local_means(filtered_b, filtered_a, residual_var, final_b);
+
+ /* Combine the two double-filtered halves to a final shadow feature. */
+ device_sub_ptr shadow_pass(buffer.mem, 4 * buffer.pass_stride, buffer.pass_stride);
+ functions.combine_halves(final_a, final_b, *shadow_pass, null_ptr, 0, rect);
}
void DenoisingTask::prefilter_features()
{
- device_sub_ptr unfiltered (buffer.mem, 8*buffer.pass_stride, buffer.pass_stride);
- device_sub_ptr variance (buffer.mem, 9*buffer.pass_stride, buffer.pass_stride);
-
- int mean_from[] = { 0, 1, 2, 12, 6, 7, 8 };
- int variance_from[] = { 3, 4, 5, 13, 9, 10, 11};
- int pass_to[] = { 1, 2, 3, 0, 5, 6, 7};
- for(int pass = 0; pass < 7; pass++) {
- device_sub_ptr feature_pass(buffer.mem, pass_to[pass]*buffer.pass_stride, buffer.pass_stride);
- /* Get the unfiltered pass and its variance from the RenderBuffers. */
- functions.get_feature(mean_from[pass], variance_from[pass], *unfiltered, *variance, 1.0f / render_buffer.samples);
- /* Smooth the pass and store the result in the denoising buffers. */
- nlm_state.set_parameters(2, 2, 1.0f, 0.25f, false);
- functions.non_local_means(*unfiltered, *unfiltered, *variance, *feature_pass);
- }
+ device_sub_ptr unfiltered(buffer.mem, 8 * buffer.pass_stride, buffer.pass_stride);
+ device_sub_ptr variance(buffer.mem, 9 * buffer.pass_stride, buffer.pass_stride);
+
+ int mean_from[] = {0, 1, 2, 12, 6, 7, 8};
+ int variance_from[] = {3, 4, 5, 13, 9, 10, 11};
+ int pass_to[] = {1, 2, 3, 0, 5, 6, 7};
+ for (int pass = 0; pass < 7; pass++) {
+ device_sub_ptr feature_pass(
+ buffer.mem, pass_to[pass] * buffer.pass_stride, buffer.pass_stride);
+ /* Get the unfiltered pass and its variance from the RenderBuffers. */
+ functions.get_feature(mean_from[pass],
+ variance_from[pass],
+ *unfiltered,
+ *variance,
+ 1.0f / render_buffer.samples);
+ /* Smooth the pass and store the result in the denoising buffers. */
+ nlm_state.set_parameters(2, 2, 1.0f, 0.25f, false);
+ functions.non_local_means(*unfiltered, *unfiltered, *variance, *feature_pass);
+ }
}
void DenoisingTask::prefilter_color()
{
- int mean_from[] = {20, 21, 22};
- int variance_from[] = {23, 24, 25};
- int mean_to[] = { 8, 9, 10};
- int variance_to[] = {11, 12, 13};
- int num_color_passes = 3;
-
- device_only_memory<float> temporary_color(device, "denoising temporary color");
- temporary_color.alloc_to_device(3*buffer.pass_stride, false);
-
- for(int pass = 0; pass < num_color_passes; pass++) {
- device_sub_ptr color_pass(temporary_color, pass*buffer.pass_stride, buffer.pass_stride);
- device_sub_ptr color_var_pass(buffer.mem, variance_to[pass]*buffer.pass_stride, buffer.pass_stride);
- functions.get_feature(mean_from[pass], variance_from[pass], *color_pass, *color_var_pass, 1.0f / render_buffer.samples);
- }
-
- device_sub_ptr depth_pass (buffer.mem, 0, buffer.pass_stride);
- device_sub_ptr color_var_pass(buffer.mem, variance_to[0]*buffer.pass_stride, 3*buffer.pass_stride);
- device_sub_ptr output_pass (buffer.mem, mean_to[0]*buffer.pass_stride, 3*buffer.pass_stride);
- functions.detect_outliers(temporary_color.device_pointer, *color_var_pass, *depth_pass, *output_pass);
-
- if(buffer.use_intensity) {
- device_sub_ptr intensity_pass(buffer.mem, 14*buffer.pass_stride, buffer.pass_stride);
- nlm_state.set_parameters(radius, 4, 2.0f, nlm_k_2*4.0f, true);
- functions.non_local_means(*output_pass, *output_pass, *color_var_pass, *intensity_pass);
- }
+ int mean_from[] = {20, 21, 22};
+ int variance_from[] = {23, 24, 25};
+ int mean_to[] = {8, 9, 10};
+ int variance_to[] = {11, 12, 13};
+ int num_color_passes = 3;
+
+ device_only_memory<float> temporary_color(device, "denoising temporary color");
+ temporary_color.alloc_to_device(3 * buffer.pass_stride, false);
+
+ for (int pass = 0; pass < num_color_passes; pass++) {
+ device_sub_ptr color_pass(temporary_color, pass * buffer.pass_stride, buffer.pass_stride);
+ device_sub_ptr color_var_pass(
+ buffer.mem, variance_to[pass] * buffer.pass_stride, buffer.pass_stride);
+ functions.get_feature(mean_from[pass],
+ variance_from[pass],
+ *color_pass,
+ *color_var_pass,
+ 1.0f / render_buffer.samples);
+ }
+
+ device_sub_ptr depth_pass(buffer.mem, 0, buffer.pass_stride);
+ device_sub_ptr color_var_pass(
+ buffer.mem, variance_to[0] * buffer.pass_stride, 3 * buffer.pass_stride);
+ device_sub_ptr output_pass(buffer.mem, mean_to[0] * buffer.pass_stride, 3 * buffer.pass_stride);
+ functions.detect_outliers(
+ temporary_color.device_pointer, *color_var_pass, *depth_pass, *output_pass);
+
+ if (buffer.use_intensity) {
+ device_sub_ptr intensity_pass(buffer.mem, 14 * buffer.pass_stride, buffer.pass_stride);
+ nlm_state.set_parameters(radius, 4, 2.0f, nlm_k_2 * 4.0f, true);
+ functions.non_local_means(*output_pass, *output_pass, *color_var_pass, *intensity_pass);
+ }
}
void DenoisingTask::load_buffer()
{
- device_ptr null_ptr = (device_ptr) 0;
-
- int original_offset = render_buffer.offset;
-
- int num_passes = buffer.use_intensity? 15 : 14;
- for(int i = 0; i < tile_info->num_frames; i++) {
- for(int pass = 0; pass < num_passes; pass++) {
- device_sub_ptr to_pass(buffer.mem, i*buffer.frame_stride + pass*buffer.pass_stride, buffer.pass_stride);
- bool is_variance = (pass >= 11) && (pass <= 13);
- functions.get_feature(pass, -1, *to_pass, null_ptr, is_variance? (1.0f / render_buffer.samples) : 1.0f);
- }
- render_buffer.offset += render_buffer.frame_stride;
- }
-
- render_buffer.offset = original_offset;
+ device_ptr null_ptr = (device_ptr)0;
+
+ int original_offset = render_buffer.offset;
+
+ int num_passes = buffer.use_intensity ? 15 : 14;
+ for (int i = 0; i < tile_info->num_frames; i++) {
+ for (int pass = 0; pass < num_passes; pass++) {
+ device_sub_ptr to_pass(
+ buffer.mem, i * buffer.frame_stride + pass * buffer.pass_stride, buffer.pass_stride);
+ bool is_variance = (pass >= 11) && (pass <= 13);
+ functions.get_feature(
+ pass, -1, *to_pass, null_ptr, is_variance ? (1.0f / render_buffer.samples) : 1.0f);
+ }
+ render_buffer.offset += render_buffer.frame_stride;
+ }
+
+ render_buffer.offset = original_offset;
}
void DenoisingTask::write_buffer()
{
- reconstruction_state.buffer_params = make_int4(target_buffer.offset,
- target_buffer.stride,
- target_buffer.pass_stride,
- target_buffer.denoising_clean_offset);
- int num_passes = buffer.use_intensity? 15 : 14;
- for(int pass = 0; pass < num_passes; pass++) {
- device_sub_ptr from_pass(buffer.mem, pass*buffer.pass_stride, buffer.pass_stride);
- int out_offset = pass + target_buffer.denoising_output_offset;
- functions.write_feature(out_offset, *from_pass, target_buffer.ptr);
- }
+ reconstruction_state.buffer_params = make_int4(target_buffer.offset,
+ target_buffer.stride,
+ target_buffer.pass_stride,
+ target_buffer.denoising_clean_offset);
+ int num_passes = buffer.use_intensity ? 15 : 14;
+ for (int pass = 0; pass < num_passes; pass++) {
+ device_sub_ptr from_pass(buffer.mem, pass * buffer.pass_stride, buffer.pass_stride);
+ int out_offset = pass + target_buffer.denoising_output_offset;
+ functions.write_feature(out_offset, *from_pass, target_buffer.ptr);
+ }
}
void DenoisingTask::construct_transform()
{
- storage.w = filter_area.z;
- storage.h = filter_area.w;
+ storage.w = filter_area.z;
+ storage.h = filter_area.w;
- storage.transform.alloc_to_device(storage.w*storage.h*TRANSFORM_SIZE, false);
- storage.rank.alloc_to_device(storage.w*storage.h, false);
+ storage.transform.alloc_to_device(storage.w * storage.h * TRANSFORM_SIZE, false);
+ storage.rank.alloc_to_device(storage.w * storage.h, false);
- functions.construct_transform();
+ functions.construct_transform();
}
void DenoisingTask::reconstruct()
{
- storage.XtWX.alloc_to_device(storage.w*storage.h*XTWX_SIZE, false);
- storage.XtWY.alloc_to_device(storage.w*storage.h*XTWY_SIZE, false);
- storage.XtWX.zero_to_device();
- storage.XtWY.zero_to_device();
-
- reconstruction_state.filter_window = rect_from_shape(filter_area.x-rect.x, filter_area.y-rect.y, storage.w, storage.h);
- int tile_coordinate_offset = filter_area.y*target_buffer.stride + filter_area.x;
- reconstruction_state.buffer_params = make_int4(target_buffer.offset + tile_coordinate_offset,
- target_buffer.stride,
- target_buffer.pass_stride,
- target_buffer.denoising_clean_offset);
- reconstruction_state.source_w = rect.z-rect.x;
- reconstruction_state.source_h = rect.w-rect.y;
-
- device_sub_ptr color_ptr (buffer.mem, 8*buffer.pass_stride, 3*buffer.pass_stride);
- device_sub_ptr color_var_ptr(buffer.mem, 11*buffer.pass_stride, 3*buffer.pass_stride);
- for(int f = 0; f < tile_info->num_frames; f++) {
- device_ptr scale_ptr = 0;
- device_sub_ptr *scale_sub_ptr = NULL;
- if(tile_info->frames[f] != 0 && (tile_info->num_frames > 1)) {
- scale_sub_ptr = new device_sub_ptr(buffer.mem, 14*buffer.pass_stride, buffer.pass_stride);
- scale_ptr = **scale_sub_ptr;
- }
-
- functions.accumulate(*color_ptr, *color_var_ptr, scale_ptr, f);
- delete scale_sub_ptr;
- }
- functions.solve(target_buffer.ptr);
+ storage.XtWX.alloc_to_device(storage.w * storage.h * XTWX_SIZE, false);
+ storage.XtWY.alloc_to_device(storage.w * storage.h * XTWY_SIZE, false);
+ storage.XtWX.zero_to_device();
+ storage.XtWY.zero_to_device();
+
+ reconstruction_state.filter_window = rect_from_shape(
+ filter_area.x - rect.x, filter_area.y - rect.y, storage.w, storage.h);
+ int tile_coordinate_offset = filter_area.y * target_buffer.stride + filter_area.x;
+ reconstruction_state.buffer_params = make_int4(target_buffer.offset + tile_coordinate_offset,
+ target_buffer.stride,
+ target_buffer.pass_stride,
+ target_buffer.denoising_clean_offset);
+ reconstruction_state.source_w = rect.z - rect.x;
+ reconstruction_state.source_h = rect.w - rect.y;
+
+ device_sub_ptr color_ptr(buffer.mem, 8 * buffer.pass_stride, 3 * buffer.pass_stride);
+ device_sub_ptr color_var_ptr(buffer.mem, 11 * buffer.pass_stride, 3 * buffer.pass_stride);
+ for (int f = 0; f < tile_info->num_frames; f++) {
+ device_ptr scale_ptr = 0;
+ device_sub_ptr *scale_sub_ptr = NULL;
+ if (tile_info->frames[f] != 0 && (tile_info->num_frames > 1)) {
+ scale_sub_ptr = new device_sub_ptr(buffer.mem, 14 * buffer.pass_stride, buffer.pass_stride);
+ scale_ptr = **scale_sub_ptr;
+ }
+
+ functions.accumulate(*color_ptr, *color_var_ptr, scale_ptr, f);
+ delete scale_sub_ptr;
+ }
+ functions.solve(target_buffer.ptr);
}
void DenoisingTask::run_denoising(RenderTile *tile)
{
- RenderTile rtiles[10];
- rtiles[4] = *tile;
- functions.map_neighbor_tiles(rtiles);
- set_render_buffer(rtiles);
-
- setup_denoising_buffer();
-
- if(tile_info->from_render) {
- prefilter_shadowing();
- prefilter_features();
- prefilter_color();
- }
- else {
- load_buffer();
- }
-
- if(do_filter) {
- construct_transform();
- reconstruct();
- }
-
- if(write_passes) {
- write_buffer();
- }
-
- functions.unmap_neighbor_tiles(rtiles);
+ RenderTile rtiles[10];
+ rtiles[4] = *tile;
+ functions.map_neighbor_tiles(rtiles);
+ set_render_buffer(rtiles);
+
+ setup_denoising_buffer();
+
+ if (tile_info->from_render) {
+ prefilter_shadowing();
+ prefilter_features();
+ prefilter_color();
+ }
+ else {
+ load_buffer();
+ }
+
+ if (do_filter) {
+ construct_transform();
+ reconstruct();
+ }
+
+ if (write_passes) {
+ write_buffer();
+ }
+
+ functions.unmap_neighbor_tiles(rtiles);
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/device/device_denoising.h b/intern/cycles/device/device_denoising.h
index 5869aa05390..bd1d0193dbd 100644
--- a/intern/cycles/device/device_denoising.h
+++ b/intern/cycles/device/device_denoising.h
@@ -28,165 +28,169 @@
CCL_NAMESPACE_BEGIN
class DenoisingTask {
-public:
- /* Parameters of the denoising algorithm. */
- int radius;
- float nlm_k_2;
- float pca_threshold;
-
- /* Parameters of the RenderBuffers. */
- struct RenderBuffers {
- int offset;
- int pass_stride;
- int frame_stride;
- int samples;
- } render_buffer;
-
- /* Pointer and parameters of the target buffer. */
- struct TargetBuffer {
- int offset;
- int stride;
- int pass_stride;
- int denoising_clean_offset;
- int denoising_output_offset;
- device_ptr ptr;
- } target_buffer;
-
- TileInfo *tile_info;
- device_vector<int> tile_info_mem;
-
- ProfilingState *profiler;
-
- int4 rect;
- int4 filter_area;
-
- bool write_passes;
- bool do_filter;
-
- struct DeviceFunctions {
- function<bool(device_ptr image_ptr, /* Contains the values that are smoothed. */
- device_ptr guide_ptr, /* Contains the values that are used to calculate weights. */
- device_ptr variance_ptr, /* Contains the variance of the guide image. */
- device_ptr out_ptr /* The filtered output is written into this image. */
- )> non_local_means;
- function<bool(device_ptr color_ptr,
- device_ptr color_variance_ptr,
- device_ptr scale_ptr,
- int frame
- )> accumulate;
- function<bool(device_ptr output_ptr)> solve;
- function<bool()> construct_transform;
-
- function<bool(device_ptr a_ptr,
- device_ptr b_ptr,
- device_ptr mean_ptr,
- device_ptr variance_ptr,
- int r,
- int4 rect
- )> combine_halves;
- function<bool(device_ptr a_ptr,
- device_ptr b_ptr,
- device_ptr sample_variance_ptr,
- device_ptr sv_variance_ptr,
- device_ptr buffer_variance_ptr
- )> divide_shadow;
- function<bool(int mean_offset,
- int variance_offset,
- device_ptr mean_ptr,
- device_ptr variance_ptr,
- float scale
- )> get_feature;
- function<bool(device_ptr image_ptr,
- device_ptr variance_ptr,
- device_ptr depth_ptr,
- device_ptr output_ptr
- )> detect_outliers;
- function<bool(int out_offset,
- device_ptr frop_ptr,
- device_ptr buffer_ptr
- )> write_feature;
- function<void(RenderTile *rtiles)> map_neighbor_tiles;
- function<void(RenderTile *rtiles)> unmap_neighbor_tiles;
- } functions;
-
- /* Stores state of the current Reconstruction operation,
- * which is accessed by the device in order to perform the operation. */
- struct ReconstructionState {
- int4 filter_window;
- int4 buffer_params;
-
- int source_w;
- int source_h;
- } reconstruction_state;
-
- /* Stores state of the current NLM operation,
- * which is accessed by the device in order to perform the operation. */
- struct NLMState {
- int r; /* Search radius of the filter. */
- int f; /* Patch size of the filter. */
- float a; /* Variance compensation factor in the MSE estimation. */
- float k_2; /* Squared value of the k parameter of the filter. */
- bool is_color;
-
- void set_parameters(int r_, int f_, float a_, float k_2_, bool is_color_) { r = r_; f = f_; a = a_, k_2 = k_2_; is_color = is_color_; }
- } nlm_state;
-
- struct Storage {
- device_only_memory<float> transform;
- device_only_memory<int> rank;
- device_only_memory<float> XtWX;
- device_only_memory<float3> XtWY;
- int w;
- int h;
-
- Storage(Device *device)
- : transform(device, "denoising transform"),
- rank(device, "denoising rank"),
- XtWX(device, "denoising XtWX"),
- XtWY(device, "denoising XtWY")
- {}
- } storage;
-
- DenoisingTask(Device *device, const DeviceTask &task);
- ~DenoisingTask();
-
- void run_denoising(RenderTile *tile);
-
- struct DenoiseBuffers {
- int pass_stride;
- int passes;
- int stride;
- int h;
- int width;
- int frame_stride;
- device_only_memory<float> mem;
- device_only_memory<float> temporary_mem;
- bool use_time;
- bool use_intensity;
-
- bool gpu_temporary_mem;
-
- DenoiseBuffers(Device *device)
- : mem(device, "denoising pixel buffer"),
- temporary_mem(device, "denoising temporary mem")
- {}
- } buffer;
-
-protected:
- Device *device;
-
- void set_render_buffer(RenderTile *rtiles);
- void setup_denoising_buffer();
- void prefilter_shadowing();
- void prefilter_features();
- void prefilter_color();
- void construct_transform();
- void reconstruct();
-
- void load_buffer();
- void write_buffer();
+ public:
+ /* Parameters of the denoising algorithm. */
+ int radius;
+ float nlm_k_2;
+ float pca_threshold;
+
+ /* Parameters of the RenderBuffers. */
+ struct RenderBuffers {
+ int offset;
+ int pass_stride;
+ int frame_stride;
+ int samples;
+ } render_buffer;
+
+ /* Pointer and parameters of the target buffer. */
+ struct TargetBuffer {
+ int offset;
+ int stride;
+ int pass_stride;
+ int denoising_clean_offset;
+ int denoising_output_offset;
+ device_ptr ptr;
+ } target_buffer;
+
+ TileInfo *tile_info;
+ device_vector<int> tile_info_mem;
+
+ ProfilingState *profiler;
+
+ int4 rect;
+ int4 filter_area;
+
+ bool write_passes;
+ bool do_filter;
+
+ struct DeviceFunctions {
+ function<bool(
+ device_ptr image_ptr, /* Contains the values that are smoothed. */
+ device_ptr guide_ptr, /* Contains the values that are used to calculate weights. */
+ device_ptr variance_ptr, /* Contains the variance of the guide image. */
+ device_ptr out_ptr /* The filtered output is written into this image. */
+ )>
+ non_local_means;
+ function<bool(
+ device_ptr color_ptr, device_ptr color_variance_ptr, device_ptr scale_ptr, int frame)>
+ accumulate;
+ function<bool(device_ptr output_ptr)> solve;
+ function<bool()> construct_transform;
+
+ function<bool(device_ptr a_ptr,
+ device_ptr b_ptr,
+ device_ptr mean_ptr,
+ device_ptr variance_ptr,
+ int r,
+ int4 rect)>
+ combine_halves;
+ function<bool(device_ptr a_ptr,
+ device_ptr b_ptr,
+ device_ptr sample_variance_ptr,
+ device_ptr sv_variance_ptr,
+ device_ptr buffer_variance_ptr)>
+ divide_shadow;
+ function<bool(int mean_offset,
+ int variance_offset,
+ device_ptr mean_ptr,
+ device_ptr variance_ptr,
+ float scale)>
+ get_feature;
+ function<bool(device_ptr image_ptr,
+ device_ptr variance_ptr,
+ device_ptr depth_ptr,
+ device_ptr output_ptr)>
+ detect_outliers;
+ function<bool(int out_offset, device_ptr frop_ptr, device_ptr buffer_ptr)> write_feature;
+ function<void(RenderTile *rtiles)> map_neighbor_tiles;
+ function<void(RenderTile *rtiles)> unmap_neighbor_tiles;
+ } functions;
+
+ /* Stores state of the current Reconstruction operation,
+ * which is accessed by the device in order to perform the operation. */
+ struct ReconstructionState {
+ int4 filter_window;
+ int4 buffer_params;
+
+ int source_w;
+ int source_h;
+ } reconstruction_state;
+
+ /* Stores state of the current NLM operation,
+ * which is accessed by the device in order to perform the operation. */
+ struct NLMState {
+ int r; /* Search radius of the filter. */
+ int f; /* Patch size of the filter. */
+ float a; /* Variance compensation factor in the MSE estimation. */
+ float k_2; /* Squared value of the k parameter of the filter. */
+ bool is_color;
+
+ void set_parameters(int r_, int f_, float a_, float k_2_, bool is_color_)
+ {
+ r = r_;
+ f = f_;
+ a = a_, k_2 = k_2_;
+ is_color = is_color_;
+ }
+ } nlm_state;
+
+ struct Storage {
+ device_only_memory<float> transform;
+ device_only_memory<int> rank;
+ device_only_memory<float> XtWX;
+ device_only_memory<float3> XtWY;
+ int w;
+ int h;
+
+ Storage(Device *device)
+ : transform(device, "denoising transform"),
+ rank(device, "denoising rank"),
+ XtWX(device, "denoising XtWX"),
+ XtWY(device, "denoising XtWY")
+ {
+ }
+ } storage;
+
+ DenoisingTask(Device *device, const DeviceTask &task);
+ ~DenoisingTask();
+
+ void run_denoising(RenderTile *tile);
+
+ struct DenoiseBuffers {
+ int pass_stride;
+ int passes;
+ int stride;
+ int h;
+ int width;
+ int frame_stride;
+ device_only_memory<float> mem;
+ device_only_memory<float> temporary_mem;
+ bool use_time;
+ bool use_intensity;
+
+ bool gpu_temporary_mem;
+
+ DenoiseBuffers(Device *device)
+ : mem(device, "denoising pixel buffer"), temporary_mem(device, "denoising temporary mem")
+ {
+ }
+ } buffer;
+
+ protected:
+ Device *device;
+
+ void set_render_buffer(RenderTile *rtiles);
+ void setup_denoising_buffer();
+ void prefilter_shadowing();
+ void prefilter_features();
+ void prefilter_color();
+ void construct_transform();
+ void reconstruct();
+
+ void load_buffer();
+ void write_buffer();
};
CCL_NAMESPACE_END
-#endif /* __DEVICE_DENOISING_H__ */
+#endif /* __DEVICE_DENOISING_H__ */
diff --git a/intern/cycles/device/device_intern.h b/intern/cycles/device/device_intern.h
index 94df1e009eb..c393a3f9cda 100644
--- a/intern/cycles/device/device_intern.h
+++ b/intern/cycles/device/device_intern.h
@@ -21,19 +21,22 @@ CCL_NAMESPACE_BEGIN
class Device;
-Device *device_cpu_create(DeviceInfo& info, Stats &stats, Profiler &profiler, bool background);
+Device *device_cpu_create(DeviceInfo &info, Stats &stats, Profiler &profiler, bool background);
bool device_opencl_init();
-Device *device_opencl_create(DeviceInfo& info, Stats &stats, Profiler &profiler, bool background);
-bool device_opencl_compile_kernel(const vector<string>& parameters);
+Device *device_opencl_create(DeviceInfo &info, Stats &stats, Profiler &profiler, bool background);
+bool device_opencl_compile_kernel(const vector<string> &parameters);
bool device_cuda_init();
-Device *device_cuda_create(DeviceInfo& info, Stats &stats, Profiler &profiler, bool background);
-Device *device_network_create(DeviceInfo& info, Stats &stats, Profiler &profiler, const char *address);
-Device *device_multi_create(DeviceInfo& info, Stats &stats, Profiler &profiler, bool background);
-
-void device_cpu_info(vector<DeviceInfo>& devices);
-void device_opencl_info(vector<DeviceInfo>& devices);
-void device_cuda_info(vector<DeviceInfo>& devices);
-void device_network_info(vector<DeviceInfo>& devices);
+Device *device_cuda_create(DeviceInfo &info, Stats &stats, Profiler &profiler, bool background);
+Device *device_network_create(DeviceInfo &info,
+ Stats &stats,
+ Profiler &profiler,
+ const char *address);
+Device *device_multi_create(DeviceInfo &info, Stats &stats, Profiler &profiler, bool background);
+
+void device_cpu_info(vector<DeviceInfo> &devices);
+void device_opencl_info(vector<DeviceInfo> &devices);
+void device_cuda_info(vector<DeviceInfo> &devices);
+void device_network_info(vector<DeviceInfo> &devices);
string device_cpu_capabilities();
string device_opencl_capabilities();
@@ -41,4 +44,4 @@ string device_cuda_capabilities();
CCL_NAMESPACE_END
-#endif /* __DEVICE_INTERN_H__ */
+#endif /* __DEVICE_INTERN_H__ */
diff --git a/intern/cycles/device/device_memory.cpp b/intern/cycles/device/device_memory.cpp
index a8d29896553..859535307f4 100644
--- a/intern/cycles/device/device_memory.cpp
+++ b/intern/cycles/device/device_memory.cpp
@@ -22,21 +22,21 @@ CCL_NAMESPACE_BEGIN
/* Device Memory */
device_memory::device_memory(Device *device, const char *name, MemoryType type)
-: data_type(device_type_traits<uchar>::data_type),
- data_elements(device_type_traits<uchar>::num_elements),
- data_size(0),
- device_size(0),
- data_width(0),
- data_height(0),
- data_depth(0),
- type(type),
- name(name),
- interpolation(INTERPOLATION_NONE),
- extension(EXTENSION_REPEAT),
- device(device),
- device_pointer(0),
- host_pointer(0),
- shared_pointer(0)
+ : data_type(device_type_traits<uchar>::data_type),
+ data_elements(device_type_traits<uchar>::num_elements),
+ data_size(0),
+ device_size(0),
+ data_width(0),
+ data_height(0),
+ data_depth(0),
+ type(type),
+ name(name),
+ interpolation(INTERPOLATION_NONE),
+ extension(EXTENSION_REPEAT),
+ device(device),
+ device_pointer(0),
+ host_pointer(0),
+ shared_pointer(0)
{
}
@@ -46,95 +46,94 @@ device_memory::~device_memory()
void *device_memory::host_alloc(size_t size)
{
- if(!size) {
- return 0;
- }
+ if (!size) {
+ return 0;
+ }
- void *ptr = util_aligned_malloc(size, MIN_ALIGNMENT_CPU_DATA_TYPES);
+ void *ptr = util_aligned_malloc(size, MIN_ALIGNMENT_CPU_DATA_TYPES);
- if(ptr) {
- util_guarded_mem_alloc(size);
- }
- else {
- throw std::bad_alloc();
- }
+ if (ptr) {
+ util_guarded_mem_alloc(size);
+ }
+ else {
+ throw std::bad_alloc();
+ }
- return ptr;
+ return ptr;
}
void device_memory::host_free()
{
- if(host_pointer) {
- util_guarded_mem_free(memory_size());
- util_aligned_free((void*)host_pointer);
- host_pointer = 0;
- }
+ if (host_pointer) {
+ util_guarded_mem_free(memory_size());
+ util_aligned_free((void *)host_pointer);
+ host_pointer = 0;
+ }
}
void device_memory::device_alloc()
{
- assert(!device_pointer && type != MEM_TEXTURE);
- device->mem_alloc(*this);
+ assert(!device_pointer && type != MEM_TEXTURE);
+ device->mem_alloc(*this);
}
void device_memory::device_free()
{
- if(device_pointer) {
- device->mem_free(*this);
- }
+ if (device_pointer) {
+ device->mem_free(*this);
+ }
}
void device_memory::device_copy_to()
{
- if(host_pointer) {
- device->mem_copy_to(*this);
- }
+ if (host_pointer) {
+ device->mem_copy_to(*this);
+ }
}
void device_memory::device_copy_from(int y, int w, int h, int elem)
{
- assert(type != MEM_TEXTURE && type != MEM_READ_ONLY);
- device->mem_copy_from(*this, y, w, h, elem);
+ assert(type != MEM_TEXTURE && type != MEM_READ_ONLY);
+ device->mem_copy_from(*this, y, w, h, elem);
}
void device_memory::device_zero()
{
- if(data_size) {
- device->mem_zero(*this);
- }
+ if (data_size) {
+ device->mem_zero(*this);
+ }
}
void device_memory::swap_device(Device *new_device,
size_t new_device_size,
device_ptr new_device_ptr)
{
- original_device = device;
- original_device_size = device_size;
- original_device_ptr = device_pointer;
+ original_device = device;
+ original_device_size = device_size;
+ original_device_ptr = device_pointer;
- device = new_device;
- device_size = new_device_size;
- device_pointer = new_device_ptr;
+ device = new_device;
+ device_size = new_device_size;
+ device_pointer = new_device_ptr;
}
void device_memory::restore_device()
{
- device = original_device;
- device_size = original_device_size;
- device_pointer = original_device_ptr;
+ device = original_device;
+ device_size = original_device_size;
+ device_pointer = original_device_ptr;
}
/* Device Sub Ptr */
-device_sub_ptr::device_sub_ptr(device_memory& mem, int offset, int size)
-: device(mem.device)
+device_sub_ptr::device_sub_ptr(device_memory &mem, int offset, int size) : device(mem.device)
{
- ptr = device->mem_alloc_sub_ptr(mem, offset, size);
+ ptr = device->mem_alloc_sub_ptr(mem, offset, size);
}
device_sub_ptr::~device_sub_ptr()
{
- device->mem_free_sub_ptr(ptr);
+ device->mem_free_sub_ptr(ptr);
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/device/device_memory.h b/intern/cycles/device/device_memory.h
index e43834bdc8d..f50184efba7 100644
--- a/intern/cycles/device/device_memory.h
+++ b/intern/cycles/device/device_memory.h
@@ -31,152 +31,155 @@ CCL_NAMESPACE_BEGIN
class Device;
-enum MemoryType {
- MEM_READ_ONLY,
- MEM_READ_WRITE,
- MEM_DEVICE_ONLY,
- MEM_TEXTURE,
- MEM_PIXELS
-};
+enum MemoryType { MEM_READ_ONLY, MEM_READ_WRITE, MEM_DEVICE_ONLY, MEM_TEXTURE, MEM_PIXELS };
/* Supported Data Types */
enum DataType {
- TYPE_UNKNOWN,
- TYPE_UCHAR,
- TYPE_UINT16,
- TYPE_UINT,
- TYPE_INT,
- TYPE_FLOAT,
- TYPE_HALF,
- TYPE_UINT64,
+ TYPE_UNKNOWN,
+ TYPE_UCHAR,
+ TYPE_UINT16,
+ TYPE_UINT,
+ TYPE_INT,
+ TYPE_FLOAT,
+ TYPE_HALF,
+ TYPE_UINT64,
};
static inline size_t datatype_size(DataType datatype)
{
- switch(datatype) {
- case TYPE_UNKNOWN: return 1;
- case TYPE_UCHAR: return sizeof(uchar);
- case TYPE_FLOAT: return sizeof(float);
- case TYPE_UINT: return sizeof(uint);
- case TYPE_UINT16: return sizeof(uint16_t);
- case TYPE_INT: return sizeof(int);
- case TYPE_HALF: return sizeof(half);
- case TYPE_UINT64: return sizeof(uint64_t);
- default: return 0;
- }
+ switch (datatype) {
+ case TYPE_UNKNOWN:
+ return 1;
+ case TYPE_UCHAR:
+ return sizeof(uchar);
+ case TYPE_FLOAT:
+ return sizeof(float);
+ case TYPE_UINT:
+ return sizeof(uint);
+ case TYPE_UINT16:
+ return sizeof(uint16_t);
+ case TYPE_INT:
+ return sizeof(int);
+ case TYPE_HALF:
+ return sizeof(half);
+ case TYPE_UINT64:
+ return sizeof(uint64_t);
+ default:
+ return 0;
+ }
}
/* Traits for data types */
template<typename T> struct device_type_traits {
- static const DataType data_type = TYPE_UNKNOWN;
- static const int num_elements = sizeof(T);
+ static const DataType data_type = TYPE_UNKNOWN;
+ static const int num_elements = sizeof(T);
};
template<> struct device_type_traits<uchar> {
- static const DataType data_type = TYPE_UCHAR;
- static const int num_elements = 1;
+ static const DataType data_type = TYPE_UCHAR;
+ static const int num_elements = 1;
};
template<> struct device_type_traits<uchar2> {
- static const DataType data_type = TYPE_UCHAR;
- static const int num_elements = 2;
+ static const DataType data_type = TYPE_UCHAR;
+ static const int num_elements = 2;
};
template<> struct device_type_traits<uchar3> {
- static const DataType data_type = TYPE_UCHAR;
- static const int num_elements = 3;
+ static const DataType data_type = TYPE_UCHAR;
+ static const int num_elements = 3;
};
template<> struct device_type_traits<uchar4> {
- static const DataType data_type = TYPE_UCHAR;
- static const int num_elements = 4;
+ static const DataType data_type = TYPE_UCHAR;
+ static const int num_elements = 4;
};
template<> struct device_type_traits<uint> {
- static const DataType data_type = TYPE_UINT;
- static const int num_elements = 1;
+ static const DataType data_type = TYPE_UINT;
+ static const int num_elements = 1;
};
template<> struct device_type_traits<uint2> {
- static const DataType data_type = TYPE_UINT;
- static const int num_elements = 2;
+ static const DataType data_type = TYPE_UINT;
+ static const int num_elements = 2;
};
template<> struct device_type_traits<uint3> {
- static const DataType data_type = TYPE_UINT;
- static const int num_elements = 3;
+ static const DataType data_type = TYPE_UINT;
+ static const int num_elements = 3;
};
template<> struct device_type_traits<uint4> {
- static const DataType data_type = TYPE_UINT;
- static const int num_elements = 4;
+ static const DataType data_type = TYPE_UINT;
+ static const int num_elements = 4;
};
template<> struct device_type_traits<int> {
- static const DataType data_type = TYPE_INT;
- static const int num_elements = 1;
+ static const DataType data_type = TYPE_INT;
+ static const int num_elements = 1;
};
template<> struct device_type_traits<int2> {
- static const DataType data_type = TYPE_INT;
- static const int num_elements = 2;
+ static const DataType data_type = TYPE_INT;
+ static const int num_elements = 2;
};
template<> struct device_type_traits<int3> {
- static const DataType data_type = TYPE_INT;
- static const int num_elements = 3;
+ static const DataType data_type = TYPE_INT;
+ static const int num_elements = 3;
};
template<> struct device_type_traits<int4> {
- static const DataType data_type = TYPE_INT;
- static const int num_elements = 4;
+ static const DataType data_type = TYPE_INT;
+ static const int num_elements = 4;
};
template<> struct device_type_traits<float> {
- static const DataType data_type = TYPE_FLOAT;
- static const int num_elements = 1;
+ static const DataType data_type = TYPE_FLOAT;
+ static const int num_elements = 1;
};
template<> struct device_type_traits<float2> {
- static const DataType data_type = TYPE_FLOAT;
- static const int num_elements = 2;
+ static const DataType data_type = TYPE_FLOAT;
+ static const int num_elements = 2;
};
template<> struct device_type_traits<float3> {
- static const DataType data_type = TYPE_FLOAT;
- static const int num_elements = 4;
+ static const DataType data_type = TYPE_FLOAT;
+ static const int num_elements = 4;
};
template<> struct device_type_traits<float4> {
- static const DataType data_type = TYPE_FLOAT;
- static const int num_elements = 4;
+ static const DataType data_type = TYPE_FLOAT;
+ static const int num_elements = 4;
};
template<> struct device_type_traits<half> {
- static const DataType data_type = TYPE_HALF;
- static const int num_elements = 1;
+ static const DataType data_type = TYPE_HALF;
+ static const int num_elements = 1;
};
template<> struct device_type_traits<ushort4> {
- static const DataType data_type = TYPE_UINT16;
- static const int num_elements = 4;
+ static const DataType data_type = TYPE_UINT16;
+ static const int num_elements = 4;
};
template<> struct device_type_traits<uint16_t> {
- static const DataType data_type = TYPE_UINT16;
- static const int num_elements = 1;
+ static const DataType data_type = TYPE_UINT16;
+ static const int num_elements = 1;
};
template<> struct device_type_traits<half4> {
- static const DataType data_type = TYPE_HALF;
- static const int num_elements = 4;
+ static const DataType data_type = TYPE_HALF;
+ static const int num_elements = 4;
};
template<> struct device_type_traits<uint64_t> {
- static const DataType data_type = TYPE_UINT64;
- static const int num_elements = 1;
+ static const DataType data_type = TYPE_UINT64;
+ static const int num_elements = 1;
};
/* Device Memory
@@ -184,64 +187,67 @@ template<> struct device_type_traits<uint64_t> {
* Base class for all device memory. This should not be allocated directly,
* instead the appropriate subclass can be used. */
-class device_memory
-{
-public:
- size_t memory_size() { return data_size*data_elements*datatype_size(data_type); }
- size_t memory_elements_size(int elements) {
- return elements*data_elements*datatype_size(data_type);
- }
-
- /* Data information. */
- DataType data_type;
- int data_elements;
- size_t data_size;
- size_t device_size;
- size_t data_width;
- size_t data_height;
- size_t data_depth;
- MemoryType type;
- const char *name;
- InterpolationType interpolation;
- ExtensionType extension;
-
- /* Pointers. */
- Device *device;
- device_ptr device_pointer;
- void *host_pointer;
- void *shared_pointer;
-
- virtual ~device_memory();
-
- void swap_device(Device *new_device, size_t new_device_size, device_ptr new_device_ptr);
- void restore_device();
-
-protected:
- friend class CUDADevice;
-
- /* Only create through subclasses. */
- device_memory(Device *device, const char *name, MemoryType type);
-
- /* No copying allowed. */
- device_memory(const device_memory&);
- device_memory& operator = (const device_memory&);
-
- /* Host allocation on the device. All host_pointer memory should be
- * allocated with these functions, for devices that support using
- * the same pointer for host and device. */
- void *host_alloc(size_t size);
- void host_free();
-
- /* Device memory allocation and copying. */
- void device_alloc();
- void device_free();
- void device_copy_to();
- void device_copy_from(int y, int w, int h, int elem);
- void device_zero();
-
- device_ptr original_device_ptr;
- size_t original_device_size;
- Device *original_device;
+class device_memory {
+ public:
+ size_t memory_size()
+ {
+ return data_size * data_elements * datatype_size(data_type);
+ }
+ size_t memory_elements_size(int elements)
+ {
+ return elements * data_elements * datatype_size(data_type);
+ }
+
+ /* Data information. */
+ DataType data_type;
+ int data_elements;
+ size_t data_size;
+ size_t device_size;
+ size_t data_width;
+ size_t data_height;
+ size_t data_depth;
+ MemoryType type;
+ const char *name;
+ InterpolationType interpolation;
+ ExtensionType extension;
+
+ /* Pointers. */
+ Device *device;
+ device_ptr device_pointer;
+ void *host_pointer;
+ void *shared_pointer;
+
+ virtual ~device_memory();
+
+ void swap_device(Device *new_device, size_t new_device_size, device_ptr new_device_ptr);
+ void restore_device();
+
+ protected:
+ friend class CUDADevice;
+
+ /* Only create through subclasses. */
+ device_memory(Device *device, const char *name, MemoryType type);
+
+ /* No copying allowed. */
+ device_memory(const device_memory &);
+ device_memory &operator=(const device_memory &);
+
+ /* Host allocation on the device. All host_pointer memory should be
+ * allocated with these functions, for devices that support using
+ * the same pointer for host and device. */
+ void *host_alloc(size_t size);
+ void host_free();
+
+ /* Device memory allocation and copying. */
+ void device_alloc();
+ void device_free();
+ void device_copy_to();
+ void device_copy_from(int y, int w, int h, int elem);
+ void device_zero();
+
+ device_ptr original_device_ptr;
+ size_t original_device_size;
+ Device *original_device;
};
/* Device Only Memory
@@ -249,51 +255,49 @@ protected:
* Working memory only needed by the device, with no corresponding allocation
* on the host. Only used internally in the device implementations. */
-template<typename T>
-class device_only_memory : public device_memory
-{
-public:
- device_only_memory(Device *device, const char *name)
- : device_memory(device, name, MEM_DEVICE_ONLY)
- {
- data_type = device_type_traits<T>::data_type;
- data_elements = max(device_type_traits<T>::num_elements, 1);
- }
-
- virtual ~device_only_memory()
- {
- free();
- }
-
- void alloc_to_device(size_t num, bool shrink_to_fit = true)
- {
- size_t new_size = num;
- bool reallocate;
-
- if(shrink_to_fit) {
- reallocate = (data_size != new_size);
- }
- else {
- reallocate = (data_size < new_size);
- }
-
- if(reallocate) {
- device_free();
- data_size = new_size;
- device_alloc();
- }
- }
-
- void free()
- {
- device_free();
- data_size = 0;
- }
-
- void zero_to_device()
- {
- device_zero();
- }
+template<typename T> class device_only_memory : public device_memory {
+ public:
+ device_only_memory(Device *device, const char *name)
+ : device_memory(device, name, MEM_DEVICE_ONLY)
+ {
+ data_type = device_type_traits<T>::data_type;
+ data_elements = max(device_type_traits<T>::num_elements, 1);
+ }
+
+ virtual ~device_only_memory()
+ {
+ free();
+ }
+
+ void alloc_to_device(size_t num, bool shrink_to_fit = true)
+ {
+ size_t new_size = num;
+ bool reallocate;
+
+ if (shrink_to_fit) {
+ reallocate = (data_size != new_size);
+ }
+ else {
+ reallocate = (data_size < new_size);
+ }
+
+ if (reallocate) {
+ device_free();
+ data_size = new_size;
+ device_alloc();
+ }
+ }
+
+ void free()
+ {
+ device_free();
+ data_size = 0;
+ }
+
+ void zero_to_device()
+ {
+ device_zero();
+ }
};
/* Device Vector
@@ -307,135 +311,134 @@ public:
* automatically attached to kernel globals, using the provided name
* matching an entry in kernel_textures.h. */
-template<typename T> class device_vector : public device_memory
-{
-public:
- device_vector(Device *device, const char *name, MemoryType type)
- : device_memory(device, name, type)
- {
- data_type = device_type_traits<T>::data_type;
- data_elements = device_type_traits<T>::num_elements;
-
- assert(data_elements > 0);
- }
-
- virtual ~device_vector()
- {
- free();
- }
-
- /* Host memory allocation. */
- T *alloc(size_t width, size_t height = 0, size_t depth = 0)
- {
- size_t new_size = size(width, height, depth);
-
- if(new_size != data_size) {
- device_free();
- host_free();
- host_pointer = host_alloc(sizeof(T)*new_size);
- assert(device_pointer == 0);
- }
-
- data_size = new_size;
- data_width = width;
- data_height = height;
- data_depth = depth;
-
- return data();
- }
-
- /* Host memory resize. Only use this if the original data needs to be
- * preserved, it is faster to call alloc() if it can be discarded. */
- T *resize(size_t width, size_t height = 0, size_t depth = 0)
- {
- size_t new_size = size(width, height, depth);
-
- if(new_size != data_size) {
- void *new_ptr = host_alloc(sizeof(T)*new_size);
-
- if(new_size && data_size) {
- size_t min_size = ((new_size < data_size)? new_size: data_size);
- memcpy((T*)new_ptr, (T*)host_pointer, sizeof(T)*min_size);
- }
-
- device_free();
- host_free();
- host_pointer = new_ptr;
- assert(device_pointer == 0);
- }
-
- data_size = new_size;
- data_width = width;
- data_height = height;
- data_depth = depth;
-
- return data();
- }
-
- /* Take over data from an existing array. */
- void steal_data(array<T>& from)
- {
- device_free();
- host_free();
-
- data_size = from.size();
- data_width = 0;
- data_height = 0;
- data_depth = 0;
- host_pointer = from.steal_pointer();
- assert(device_pointer == 0);
- }
-
- /* Free device and host memory. */
- void free()
- {
- device_free();
- host_free();
-
- data_size = 0;
- data_width = 0;
- data_height = 0;
- data_depth = 0;
- host_pointer = 0;
- assert(device_pointer == 0);
- }
-
- size_t size()
- {
- return data_size;
- }
-
- T* data()
- {
- return (T*)host_pointer;
- }
-
- T& operator[](size_t i)
- {
- assert(i < data_size);
- return data()[i];
- }
-
- void copy_to_device()
- {
- device_copy_to();
- }
-
- void copy_from_device(int y, int w, int h)
- {
- device_copy_from(y, w, h, sizeof(T));
- }
-
- void zero_to_device()
- {
- device_zero();
- }
-
-protected:
- size_t size(size_t width, size_t height, size_t depth)
- {
- return width * ((height == 0)? 1: height) * ((depth == 0)? 1: depth);
- }
+template<typename T> class device_vector : public device_memory {
+ public:
+ device_vector(Device *device, const char *name, MemoryType type)
+ : device_memory(device, name, type)
+ {
+ data_type = device_type_traits<T>::data_type;
+ data_elements = device_type_traits<T>::num_elements;
+
+ assert(data_elements > 0);
+ }
+
+ virtual ~device_vector()
+ {
+ free();
+ }
+
+ /* Host memory allocation. */
+ T *alloc(size_t width, size_t height = 0, size_t depth = 0)
+ {
+ size_t new_size = size(width, height, depth);
+
+ if (new_size != data_size) {
+ device_free();
+ host_free();
+ host_pointer = host_alloc(sizeof(T) * new_size);
+ assert(device_pointer == 0);
+ }
+
+ data_size = new_size;
+ data_width = width;
+ data_height = height;
+ data_depth = depth;
+
+ return data();
+ }
+
+ /* Host memory resize. Only use this if the original data needs to be
+ * preserved, it is faster to call alloc() if it can be discarded. */
+ T *resize(size_t width, size_t height = 0, size_t depth = 0)
+ {
+ size_t new_size = size(width, height, depth);
+
+ if (new_size != data_size) {
+ void *new_ptr = host_alloc(sizeof(T) * new_size);
+
+ if (new_size && data_size) {
+ size_t min_size = ((new_size < data_size) ? new_size : data_size);
+ memcpy((T *)new_ptr, (T *)host_pointer, sizeof(T) * min_size);
+ }
+
+ device_free();
+ host_free();
+ host_pointer = new_ptr;
+ assert(device_pointer == 0);
+ }
+
+ data_size = new_size;
+ data_width = width;
+ data_height = height;
+ data_depth = depth;
+
+ return data();
+ }
+
+ /* Take over data from an existing array. */
+ void steal_data(array<T> &from)
+ {
+ device_free();
+ host_free();
+
+ data_size = from.size();
+ data_width = 0;
+ data_height = 0;
+ data_depth = 0;
+ host_pointer = from.steal_pointer();
+ assert(device_pointer == 0);
+ }
+
+ /* Free device and host memory. */
+ void free()
+ {
+ device_free();
+ host_free();
+
+ data_size = 0;
+ data_width = 0;
+ data_height = 0;
+ data_depth = 0;
+ host_pointer = 0;
+ assert(device_pointer == 0);
+ }
+
+ size_t size()
+ {
+ return data_size;
+ }
+
+ T *data()
+ {
+ return (T *)host_pointer;
+ }
+
+ T &operator[](size_t i)
+ {
+ assert(i < data_size);
+ return data()[i];
+ }
+
+ void copy_to_device()
+ {
+ device_copy_to();
+ }
+
+ void copy_from_device(int y, int w, int h)
+ {
+ device_copy_from(y, w, h, sizeof(T));
+ }
+
+ void zero_to_device()
+ {
+ device_zero();
+ }
+
+ protected:
+ size_t size(size_t width, size_t height, size_t depth)
+ {
+ return width * ((height == 0) ? 1 : height) * ((depth == 0) ? 1 : depth);
+ }
};
/* Pixel Memory
@@ -443,28 +446,26 @@ protected:
* Device memory to efficiently draw as pixels to the screen in interactive
* rendering. Only copying pixels from the device is supported, not copying to. */
-template<typename T> class device_pixels : public device_vector<T>
-{
-public:
- device_pixels(Device *device, const char *name)
- : device_vector<T>(device, name, MEM_PIXELS)
- {
- }
-
- void alloc_to_device(size_t width, size_t height, size_t depth = 0)
- {
- device_vector<T>::alloc(width, height, depth);
-
- if(!device_memory::device_pointer) {
- device_memory::device_alloc();
- }
- }
-
- T *copy_from_device(int y, int w, int h)
- {
- device_memory::device_copy_from(y, w, h, sizeof(T));
- return device_vector<T>::data();
- }
+template<typename T> class device_pixels : public device_vector<T> {
+ public:
+ device_pixels(Device *device, const char *name) : device_vector<T>(device, name, MEM_PIXELS)
+ {
+ }
+
+ void alloc_to_device(size_t width, size_t height, size_t depth = 0)
+ {
+ device_vector<T>::alloc(width, height, depth);
+
+ if (!device_memory::device_pointer) {
+ device_memory::device_alloc();
+ }
+ }
+
+ T *copy_from_device(int y, int w, int h)
+ {
+ device_memory::device_copy_from(y, w, h, sizeof(T));
+ return device_vector<T>::data();
+ }
};
/* Device Sub Memory
@@ -476,25 +477,24 @@ public:
* Note: some devices require offset and size of the sub_ptr to be properly
* aligned to device->mem_address_alingment(). */
-class device_sub_ptr
-{
-public:
- device_sub_ptr(device_memory& mem, int offset, int size);
- ~device_sub_ptr();
+class device_sub_ptr {
+ public:
+ device_sub_ptr(device_memory &mem, int offset, int size);
+ ~device_sub_ptr();
- device_ptr operator*() const
- {
- return ptr;
- }
+ device_ptr operator*() const
+ {
+ return ptr;
+ }
-protected:
- /* No copying. */
- device_sub_ptr& operator = (const device_sub_ptr&);
+ protected:
+ /* No copying. */
+ device_sub_ptr &operator=(const device_sub_ptr &);
- Device *device;
- device_ptr ptr;
+ Device *device;
+ device_ptr ptr;
};
CCL_NAMESPACE_END
-#endif /* __DEVICE_MEMORY_H__ */
+#endif /* __DEVICE_MEMORY_H__ */
diff --git a/intern/cycles/device/device_multi.cpp b/intern/cycles/device/device_multi.cpp
index bdb7c87fa57..4a40e106115 100644
--- a/intern/cycles/device/device_multi.cpp
+++ b/intern/cycles/device/device_multi.cpp
@@ -31,391 +31,406 @@
CCL_NAMESPACE_BEGIN
-class MultiDevice : public Device
-{
-public:
- struct SubDevice {
- explicit SubDevice(Device *device_)
- : device(device_) {}
-
- Device *device;
- map<device_ptr, device_ptr> ptr_map;
- };
-
- list<SubDevice> devices;
- device_ptr unique_key;
-
- MultiDevice(DeviceInfo& info, Stats &stats, Profiler &profiler, bool background_)
- : Device(info, stats, profiler, background_), unique_key(1)
- {
- foreach(DeviceInfo& subinfo, info.multi_devices) {
- Device *device = Device::create(subinfo, sub_stats_, profiler, background);
-
- /* Always add CPU devices at the back since GPU devices can change
- * host memory pointers, which CPU uses as device pointer. */
- if(subinfo.type == DEVICE_CPU) {
- devices.push_back(SubDevice(device));
- }
- else {
- devices.push_front(SubDevice(device));
- }
- }
+class MultiDevice : public Device {
+ public:
+ struct SubDevice {
+ explicit SubDevice(Device *device_) : device(device_)
+ {
+ }
+
+ Device *device;
+ map<device_ptr, device_ptr> ptr_map;
+ };
+
+ list<SubDevice> devices;
+ device_ptr unique_key;
+
+ MultiDevice(DeviceInfo &info, Stats &stats, Profiler &profiler, bool background_)
+ : Device(info, stats, profiler, background_), unique_key(1)
+ {
+ foreach (DeviceInfo &subinfo, info.multi_devices) {
+ Device *device = Device::create(subinfo, sub_stats_, profiler, background);
+
+ /* Always add CPU devices at the back since GPU devices can change
+ * host memory pointers, which CPU uses as device pointer. */
+ if (subinfo.type == DEVICE_CPU) {
+ devices.push_back(SubDevice(device));
+ }
+ else {
+ devices.push_front(SubDevice(device));
+ }
+ }
#ifdef WITH_NETWORK
- /* try to add network devices */
- ServerDiscovery discovery(true);
- time_sleep(1.0);
+ /* try to add network devices */
+ ServerDiscovery discovery(true);
+ time_sleep(1.0);
- vector<string> servers = discovery.get_server_list();
+ vector<string> servers = discovery.get_server_list();
- foreach(string& server, servers) {
- Device *device = device_network_create(info, stats, profiler, server.c_str());
- if(device)
- devices.push_back(SubDevice(device));
- }
+ foreach (string &server, servers) {
+ Device *device = device_network_create(info, stats, profiler, server.c_str());
+ if (device)
+ devices.push_back(SubDevice(device));
+ }
#endif
- }
-
- ~MultiDevice()
- {
- foreach(SubDevice& sub, devices)
- delete sub.device;
- }
-
- const string& error_message()
- {
- foreach(SubDevice& sub, devices) {
- if(sub.device->error_message() != "") {
- if(error_msg == "")
- error_msg = sub.device->error_message();
- break;
- }
- }
-
- return error_msg;
- }
-
- virtual bool show_samples() const
- {
- if(devices.size() > 1) {
- return false;
- }
- return devices.front().device->show_samples();
- }
-
- virtual BVHLayoutMask get_bvh_layout_mask() const {
- BVHLayoutMask bvh_layout_mask = BVH_LAYOUT_ALL;
- foreach(const SubDevice& sub_device, devices) {
- bvh_layout_mask &= sub_device.device->get_bvh_layout_mask();
- }
- return bvh_layout_mask;
- }
-
- bool load_kernels(const DeviceRequestedFeatures& requested_features)
- {
- foreach(SubDevice& sub, devices)
- if(!sub.device->load_kernels(requested_features))
- return false;
-
- return true;
- }
-
- bool wait_for_availability(const DeviceRequestedFeatures& requested_features)
- {
- foreach(SubDevice& sub, devices)
- if(!sub.device->wait_for_availability(requested_features))
- return false;
-
- return true;
- }
-
- DeviceKernelStatus get_active_kernel_switch_state()
- {
- DeviceKernelStatus result = DEVICE_KERNEL_USING_FEATURE_KERNEL;
-
- foreach(SubDevice& sub, devices) {
- DeviceKernelStatus subresult = sub.device->get_active_kernel_switch_state();
- switch (subresult) {
- case DEVICE_KERNEL_WAITING_FOR_FEATURE_KERNEL:
- result = subresult;
- break;
-
- case DEVICE_KERNEL_FEATURE_KERNEL_INVALID:
- case DEVICE_KERNEL_FEATURE_KERNEL_AVAILABLE:
- return subresult;
-
- case DEVICE_KERNEL_USING_FEATURE_KERNEL:
- case DEVICE_KERNEL_UNKNOWN:
- break;
- }
- }
- return result;
- }
-
- void mem_alloc(device_memory& mem)
- {
- device_ptr key = unique_key++;
-
- foreach(SubDevice& sub, devices) {
- mem.device = sub.device;
- mem.device_pointer = 0;
- mem.device_size = 0;
-
- sub.device->mem_alloc(mem);
- sub.ptr_map[key] = mem.device_pointer;
- }
-
- mem.device = this;
- mem.device_pointer = key;
- stats.mem_alloc(mem.device_size);
- }
-
- void mem_copy_to(device_memory& mem)
- {
- device_ptr existing_key = mem.device_pointer;
- device_ptr key = (existing_key)? existing_key: unique_key++;
- size_t existing_size = mem.device_size;
-
- foreach(SubDevice& sub, devices) {
- mem.device = sub.device;
- mem.device_pointer = (existing_key)? sub.ptr_map[existing_key]: 0;
- mem.device_size = existing_size;
-
- sub.device->mem_copy_to(mem);
- sub.ptr_map[key] = mem.device_pointer;
- }
-
- mem.device = this;
- mem.device_pointer = key;
- stats.mem_alloc(mem.device_size - existing_size);
- }
-
- void mem_copy_from(device_memory& mem, int y, int w, int h, int elem)
- {
- device_ptr key = mem.device_pointer;
- int i = 0, sub_h = h/devices.size();
-
- foreach(SubDevice& sub, devices) {
- int sy = y + i*sub_h;
- int sh = (i == (int)devices.size() - 1)? h - sub_h*i: sub_h;
-
- mem.device = sub.device;
- mem.device_pointer = sub.ptr_map[key];
-
- sub.device->mem_copy_from(mem, sy, w, sh, elem);
- i++;
- }
-
- mem.device = this;
- mem.device_pointer = key;
- }
-
- void mem_zero(device_memory& mem)
- {
- device_ptr existing_key = mem.device_pointer;
- device_ptr key = (existing_key)? existing_key: unique_key++;
- size_t existing_size = mem.device_size;
-
- foreach(SubDevice& sub, devices) {
- mem.device = sub.device;
- mem.device_pointer = (existing_key)? sub.ptr_map[existing_key]: 0;
- mem.device_size = existing_size;
-
- sub.device->mem_zero(mem);
- sub.ptr_map[key] = mem.device_pointer;
- }
-
- mem.device = this;
- mem.device_pointer = key;
- stats.mem_alloc(mem.device_size - existing_size);
- }
-
- void mem_free(device_memory& mem)
- {
- device_ptr key = mem.device_pointer;
- size_t existing_size = mem.device_size;
-
- foreach(SubDevice& sub, devices) {
- mem.device = sub.device;
- mem.device_pointer = sub.ptr_map[key];
- mem.device_size = existing_size;
-
- sub.device->mem_free(mem);
- sub.ptr_map.erase(sub.ptr_map.find(key));
- }
-
- mem.device = this;
- mem.device_pointer = 0;
- mem.device_size = 0;
- stats.mem_free(existing_size);
- }
-
- void const_copy_to(const char *name, void *host, size_t size)
- {
- foreach(SubDevice& sub, devices)
- sub.device->const_copy_to(name, host, size);
- }
-
- void draw_pixels(
- device_memory& rgba, int y,
- int w, int h, int width, int height,
- int dx, int dy, int dw, int dh,
- bool transparent, const DeviceDrawParams &draw_params)
- {
- device_ptr key = rgba.device_pointer;
- int i = 0, sub_h = h/devices.size();
- int sub_height = height/devices.size();
-
- foreach(SubDevice& sub, devices) {
- int sy = y + i*sub_h;
- int sh = (i == (int)devices.size() - 1)? h - sub_h*i: sub_h;
- int sheight = (i == (int)devices.size() - 1)? height - sub_height*i: sub_height;
- int sdy = dy + i*sub_height;
- /* adjust math for w/width */
-
- rgba.device_pointer = sub.ptr_map[key];
- sub.device->draw_pixels(rgba, sy, w, sh, width, sheight, dx, sdy, dw, dh, transparent, draw_params);
- i++;
- }
-
- rgba.device_pointer = key;
- }
-
- void map_tile(Device *sub_device, RenderTile& tile)
- {
- foreach(SubDevice& sub, devices) {
- if(sub.device == sub_device) {
- if(tile.buffer) tile.buffer = sub.ptr_map[tile.buffer];
- }
- }
- }
-
- int device_number(Device *sub_device)
- {
- int i = 0;
-
- foreach(SubDevice& sub, devices) {
- if(sub.device == sub_device)
- return i;
- i++;
- }
-
- return -1;
- }
-
- void map_neighbor_tiles(Device *sub_device, RenderTile *tiles)
- {
- for(int i = 0; i < 9; i++) {
- if(!tiles[i].buffers) {
- continue;
- }
-
- /* If the tile was rendered on another device, copy its memory to
- * to the current device now, for the duration of the denoising task.
- * Note that this temporarily modifies the RenderBuffers and calls
- * the device, so this function is not thread safe. */
- device_vector<float> &mem = tiles[i].buffers->buffer;
- if(mem.device != sub_device) {
- /* Only copy from device to host once. This is faster, but
- * also required for the case where a CPU thread is denoising
- * a tile rendered on the GPU. In that case we have to avoid
- * overwriting the buffer being denoised by the CPU thread. */
- if(!tiles[i].buffers->map_neighbor_copied) {
- tiles[i].buffers->map_neighbor_copied = true;
- mem.copy_from_device(0, mem.data_size, 1);
- }
-
- mem.swap_device(sub_device, 0, 0);
-
- mem.copy_to_device();
- tiles[i].buffer = mem.device_pointer;
- tiles[i].device_size = mem.device_size;
-
- mem.restore_device();
- }
- }
- }
-
- void unmap_neighbor_tiles(Device * sub_device, RenderTile * tiles)
- {
- /* Copy denoised result back to the host. */
- device_vector<float> &mem = tiles[9].buffers->buffer;
- mem.swap_device(sub_device, tiles[9].device_size, tiles[9].buffer);
- mem.copy_from_device(0, mem.data_size, 1);
- mem.restore_device();
- /* Copy denoised result to the original device. */
- mem.copy_to_device();
-
- for(int i = 0; i < 9; i++) {
- if(!tiles[i].buffers) {
- continue;
- }
-
- device_vector<float> &mem = tiles[i].buffers->buffer;
- if(mem.device != sub_device) {
- mem.swap_device(sub_device, tiles[i].device_size, tiles[i].buffer);
- sub_device->mem_free(mem);
- mem.restore_device();
- }
- }
- }
-
- int get_split_task_count(DeviceTask& task)
- {
- int total_tasks = 0;
- list<DeviceTask> tasks;
- task.split(tasks, devices.size());
- foreach(SubDevice& sub, devices) {
- if(!tasks.empty()) {
- DeviceTask subtask = tasks.front();
- tasks.pop_front();
-
- total_tasks += sub.device->get_split_task_count(subtask);
- }
- }
- return total_tasks;
- }
-
- void task_add(DeviceTask& task)
- {
- list<DeviceTask> tasks;
- task.split(tasks, devices.size());
-
- foreach(SubDevice& sub, devices) {
- if(!tasks.empty()) {
- DeviceTask subtask = tasks.front();
- tasks.pop_front();
-
- if(task.buffer) subtask.buffer = sub.ptr_map[task.buffer];
- if(task.rgba_byte) subtask.rgba_byte = sub.ptr_map[task.rgba_byte];
- if(task.rgba_half) subtask.rgba_half = sub.ptr_map[task.rgba_half];
- if(task.shader_input) subtask.shader_input = sub.ptr_map[task.shader_input];
- if(task.shader_output) subtask.shader_output = sub.ptr_map[task.shader_output];
-
- sub.device->task_add(subtask);
- }
- }
- }
-
- void task_wait()
- {
- foreach(SubDevice& sub, devices)
- sub.device->task_wait();
- }
-
- void task_cancel()
- {
- foreach(SubDevice& sub, devices)
- sub.device->task_cancel();
- }
-
-protected:
- Stats sub_stats_;
+ }
+
+ ~MultiDevice()
+ {
+ foreach (SubDevice &sub, devices)
+ delete sub.device;
+ }
+
+ const string &error_message()
+ {
+ foreach (SubDevice &sub, devices) {
+ if (sub.device->error_message() != "") {
+ if (error_msg == "")
+ error_msg = sub.device->error_message();
+ break;
+ }
+ }
+
+ return error_msg;
+ }
+
+ virtual bool show_samples() const
+ {
+ if (devices.size() > 1) {
+ return false;
+ }
+ return devices.front().device->show_samples();
+ }
+
+ virtual BVHLayoutMask get_bvh_layout_mask() const
+ {
+ BVHLayoutMask bvh_layout_mask = BVH_LAYOUT_ALL;
+ foreach (const SubDevice &sub_device, devices) {
+ bvh_layout_mask &= sub_device.device->get_bvh_layout_mask();
+ }
+ return bvh_layout_mask;
+ }
+
+ bool load_kernels(const DeviceRequestedFeatures &requested_features)
+ {
+ foreach (SubDevice &sub, devices)
+ if (!sub.device->load_kernels(requested_features))
+ return false;
+
+ return true;
+ }
+
+ bool wait_for_availability(const DeviceRequestedFeatures &requested_features)
+ {
+ foreach (SubDevice &sub, devices)
+ if (!sub.device->wait_for_availability(requested_features))
+ return false;
+
+ return true;
+ }
+
+ DeviceKernelStatus get_active_kernel_switch_state()
+ {
+ DeviceKernelStatus result = DEVICE_KERNEL_USING_FEATURE_KERNEL;
+
+ foreach (SubDevice &sub, devices) {
+ DeviceKernelStatus subresult = sub.device->get_active_kernel_switch_state();
+ switch (subresult) {
+ case DEVICE_KERNEL_WAITING_FOR_FEATURE_KERNEL:
+ result = subresult;
+ break;
+
+ case DEVICE_KERNEL_FEATURE_KERNEL_INVALID:
+ case DEVICE_KERNEL_FEATURE_KERNEL_AVAILABLE:
+ return subresult;
+
+ case DEVICE_KERNEL_USING_FEATURE_KERNEL:
+ case DEVICE_KERNEL_UNKNOWN:
+ break;
+ }
+ }
+ return result;
+ }
+
+ void mem_alloc(device_memory &mem)
+ {
+ device_ptr key = unique_key++;
+
+ foreach (SubDevice &sub, devices) {
+ mem.device = sub.device;
+ mem.device_pointer = 0;
+ mem.device_size = 0;
+
+ sub.device->mem_alloc(mem);
+ sub.ptr_map[key] = mem.device_pointer;
+ }
+
+ mem.device = this;
+ mem.device_pointer = key;
+ stats.mem_alloc(mem.device_size);
+ }
+
+ void mem_copy_to(device_memory &mem)
+ {
+ device_ptr existing_key = mem.device_pointer;
+ device_ptr key = (existing_key) ? existing_key : unique_key++;
+ size_t existing_size = mem.device_size;
+
+ foreach (SubDevice &sub, devices) {
+ mem.device = sub.device;
+ mem.device_pointer = (existing_key) ? sub.ptr_map[existing_key] : 0;
+ mem.device_size = existing_size;
+
+ sub.device->mem_copy_to(mem);
+ sub.ptr_map[key] = mem.device_pointer;
+ }
+
+ mem.device = this;
+ mem.device_pointer = key;
+ stats.mem_alloc(mem.device_size - existing_size);
+ }
+
+ void mem_copy_from(device_memory &mem, int y, int w, int h, int elem)
+ {
+ device_ptr key = mem.device_pointer;
+ int i = 0, sub_h = h / devices.size();
+
+ foreach (SubDevice &sub, devices) {
+ int sy = y + i * sub_h;
+ int sh = (i == (int)devices.size() - 1) ? h - sub_h * i : sub_h;
+
+ mem.device = sub.device;
+ mem.device_pointer = sub.ptr_map[key];
+
+ sub.device->mem_copy_from(mem, sy, w, sh, elem);
+ i++;
+ }
+
+ mem.device = this;
+ mem.device_pointer = key;
+ }
+
+ void mem_zero(device_memory &mem)
+ {
+ device_ptr existing_key = mem.device_pointer;
+ device_ptr key = (existing_key) ? existing_key : unique_key++;
+ size_t existing_size = mem.device_size;
+
+ foreach (SubDevice &sub, devices) {
+ mem.device = sub.device;
+ mem.device_pointer = (existing_key) ? sub.ptr_map[existing_key] : 0;
+ mem.device_size = existing_size;
+
+ sub.device->mem_zero(mem);
+ sub.ptr_map[key] = mem.device_pointer;
+ }
+
+ mem.device = this;
+ mem.device_pointer = key;
+ stats.mem_alloc(mem.device_size - existing_size);
+ }
+
+ void mem_free(device_memory &mem)
+ {
+ device_ptr key = mem.device_pointer;
+ size_t existing_size = mem.device_size;
+
+ foreach (SubDevice &sub, devices) {
+ mem.device = sub.device;
+ mem.device_pointer = sub.ptr_map[key];
+ mem.device_size = existing_size;
+
+ sub.device->mem_free(mem);
+ sub.ptr_map.erase(sub.ptr_map.find(key));
+ }
+
+ mem.device = this;
+ mem.device_pointer = 0;
+ mem.device_size = 0;
+ stats.mem_free(existing_size);
+ }
+
+ void const_copy_to(const char *name, void *host, size_t size)
+ {
+ foreach (SubDevice &sub, devices)
+ sub.device->const_copy_to(name, host, size);
+ }
+
+ void draw_pixels(device_memory &rgba,
+ int y,
+ int w,
+ int h,
+ int width,
+ int height,
+ int dx,
+ int dy,
+ int dw,
+ int dh,
+ bool transparent,
+ const DeviceDrawParams &draw_params)
+ {
+ device_ptr key = rgba.device_pointer;
+ int i = 0, sub_h = h / devices.size();
+ int sub_height = height / devices.size();
+
+ foreach (SubDevice &sub, devices) {
+ int sy = y + i * sub_h;
+ int sh = (i == (int)devices.size() - 1) ? h - sub_h * i : sub_h;
+ int sheight = (i == (int)devices.size() - 1) ? height - sub_height * i : sub_height;
+ int sdy = dy + i * sub_height;
+ /* adjust math for w/width */
+
+ rgba.device_pointer = sub.ptr_map[key];
+ sub.device->draw_pixels(
+ rgba, sy, w, sh, width, sheight, dx, sdy, dw, dh, transparent, draw_params);
+ i++;
+ }
+
+ rgba.device_pointer = key;
+ }
+
+ void map_tile(Device *sub_device, RenderTile &tile)
+ {
+ foreach (SubDevice &sub, devices) {
+ if (sub.device == sub_device) {
+ if (tile.buffer)
+ tile.buffer = sub.ptr_map[tile.buffer];
+ }
+ }
+ }
+
+ int device_number(Device *sub_device)
+ {
+ int i = 0;
+
+ foreach (SubDevice &sub, devices) {
+ if (sub.device == sub_device)
+ return i;
+ i++;
+ }
+
+ return -1;
+ }
+
+ void map_neighbor_tiles(Device *sub_device, RenderTile *tiles)
+ {
+ for (int i = 0; i < 9; i++) {
+ if (!tiles[i].buffers) {
+ continue;
+ }
+
+ /* If the tile was rendered on another device, copy its memory to
+ * to the current device now, for the duration of the denoising task.
+ * Note that this temporarily modifies the RenderBuffers and calls
+ * the device, so this function is not thread safe. */
+ device_vector<float> &mem = tiles[i].buffers->buffer;
+ if (mem.device != sub_device) {
+ /* Only copy from device to host once. This is faster, but
+ * also required for the case where a CPU thread is denoising
+ * a tile rendered on the GPU. In that case we have to avoid
+ * overwriting the buffer being denoised by the CPU thread. */
+ if (!tiles[i].buffers->map_neighbor_copied) {
+ tiles[i].buffers->map_neighbor_copied = true;
+ mem.copy_from_device(0, mem.data_size, 1);
+ }
+
+ mem.swap_device(sub_device, 0, 0);
+
+ mem.copy_to_device();
+ tiles[i].buffer = mem.device_pointer;
+ tiles[i].device_size = mem.device_size;
+
+ mem.restore_device();
+ }
+ }
+ }
+
+ void unmap_neighbor_tiles(Device *sub_device, RenderTile *tiles)
+ {
+ /* Copy denoised result back to the host. */
+ device_vector<float> &mem = tiles[9].buffers->buffer;
+ mem.swap_device(sub_device, tiles[9].device_size, tiles[9].buffer);
+ mem.copy_from_device(0, mem.data_size, 1);
+ mem.restore_device();
+ /* Copy denoised result to the original device. */
+ mem.copy_to_device();
+
+ for (int i = 0; i < 9; i++) {
+ if (!tiles[i].buffers) {
+ continue;
+ }
+
+ device_vector<float> &mem = tiles[i].buffers->buffer;
+ if (mem.device != sub_device) {
+ mem.swap_device(sub_device, tiles[i].device_size, tiles[i].buffer);
+ sub_device->mem_free(mem);
+ mem.restore_device();
+ }
+ }
+ }
+
+ int get_split_task_count(DeviceTask &task)
+ {
+ int total_tasks = 0;
+ list<DeviceTask> tasks;
+ task.split(tasks, devices.size());
+ foreach (SubDevice &sub, devices) {
+ if (!tasks.empty()) {
+ DeviceTask subtask = tasks.front();
+ tasks.pop_front();
+
+ total_tasks += sub.device->get_split_task_count(subtask);
+ }
+ }
+ return total_tasks;
+ }
+
+ void task_add(DeviceTask &task)
+ {
+ list<DeviceTask> tasks;
+ task.split(tasks, devices.size());
+
+ foreach (SubDevice &sub, devices) {
+ if (!tasks.empty()) {
+ DeviceTask subtask = tasks.front();
+ tasks.pop_front();
+
+ if (task.buffer)
+ subtask.buffer = sub.ptr_map[task.buffer];
+ if (task.rgba_byte)
+ subtask.rgba_byte = sub.ptr_map[task.rgba_byte];
+ if (task.rgba_half)
+ subtask.rgba_half = sub.ptr_map[task.rgba_half];
+ if (task.shader_input)
+ subtask.shader_input = sub.ptr_map[task.shader_input];
+ if (task.shader_output)
+ subtask.shader_output = sub.ptr_map[task.shader_output];
+
+ sub.device->task_add(subtask);
+ }
+ }
+ }
+
+ void task_wait()
+ {
+ foreach (SubDevice &sub, devices)
+ sub.device->task_wait();
+ }
+
+ void task_cancel()
+ {
+ foreach (SubDevice &sub, devices)
+ sub.device->task_cancel();
+ }
+
+ protected:
+ Stats sub_stats_;
};
-Device *device_multi_create(DeviceInfo& info, Stats &stats, Profiler& profiler, bool background)
+Device *device_multi_create(DeviceInfo &info, Stats &stats, Profiler &profiler, bool background)
{
- return new MultiDevice(info, stats, profiler, background);
+ return new MultiDevice(info, stats, profiler, background);
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/device/device_network.cpp b/intern/cycles/device/device_network.cpp
index 6736480e95a..80334ad8f22 100644
--- a/intern/cycles/device/device_network.cpp
+++ b/intern/cycles/device/device_network.cpp
@@ -33,767 +33,776 @@ typedef map<device_ptr, DataVector> DataMap;
typedef vector<RenderTile> TileList;
/* search a list of tiles and find the one that matches the passed render tile */
-static TileList::iterator tile_list_find(TileList& tile_list, RenderTile& tile)
+static TileList::iterator tile_list_find(TileList &tile_list, RenderTile &tile)
{
- for(TileList::iterator it = tile_list.begin(); it != tile_list.end(); ++it)
- if(tile.x == it->x && tile.y == it->y && tile.start_sample == it->start_sample)
- return it;
- return tile_list.end();
+ for (TileList::iterator it = tile_list.begin(); it != tile_list.end(); ++it)
+ if (tile.x == it->x && tile.y == it->y && tile.start_sample == it->start_sample)
+ return it;
+ return tile_list.end();
}
-class NetworkDevice : public Device
-{
-public:
- boost::asio::io_service io_service;
- tcp::socket socket;
- device_ptr mem_counter;
- DeviceTask the_task; /* todo: handle multiple tasks */
-
- thread_mutex rpc_lock;
-
- virtual bool show_samples() const
- {
- return false;
- }
-
- NetworkDevice(DeviceInfo& info, Stats &stats, Profiler &profiler, const char *address)
- : Device(info, stats, profiler, true), socket(io_service)
- {
- error_func = NetworkError();
- stringstream portstr;
- portstr << SERVER_PORT;
-
- tcp::resolver resolver(io_service);
- tcp::resolver::query query(address, portstr.str());
- tcp::resolver::iterator endpoint_iterator = resolver.resolve(query);
- tcp::resolver::iterator end;
+class NetworkDevice : public Device {
+ public:
+ boost::asio::io_service io_service;
+ tcp::socket socket;
+ device_ptr mem_counter;
+ DeviceTask the_task; /* todo: handle multiple tasks */
+
+ thread_mutex rpc_lock;
+
+ virtual bool show_samples() const
+ {
+ return false;
+ }
+
+ NetworkDevice(DeviceInfo &info, Stats &stats, Profiler &profiler, const char *address)
+ : Device(info, stats, profiler, true), socket(io_service)
+ {
+ error_func = NetworkError();
+ stringstream portstr;
+ portstr << SERVER_PORT;
+
+ tcp::resolver resolver(io_service);
+ tcp::resolver::query query(address, portstr.str());
+ tcp::resolver::iterator endpoint_iterator = resolver.resolve(query);
+ tcp::resolver::iterator end;
+
+ boost::system::error_code error = boost::asio::error::host_not_found;
+ while (error && endpoint_iterator != end) {
+ socket.close();
+ socket.connect(*endpoint_iterator++, error);
+ }
- boost::system::error_code error = boost::asio::error::host_not_found;
- while(error && endpoint_iterator != end)
- {
- socket.close();
- socket.connect(*endpoint_iterator++, error);
- }
-
- if(error)
- error_func.network_error(error.message());
+ if (error)
+ error_func.network_error(error.message());
- mem_counter = 0;
- }
+ mem_counter = 0;
+ }
- ~NetworkDevice()
- {
- RPCSend snd(socket, &error_func, "stop");
- snd.write();
- }
-
- virtual BVHLayoutMask get_bvh_layout_mask() const {
- return BVH_LAYOUT_BVH2;
- }
-
- void mem_alloc(device_memory& mem)
- {
- if(mem.name) {
- VLOG(1) << "Buffer allocate: " << mem.name << ", "
- << string_human_readable_number(mem.memory_size()) << " bytes. ("
- << string_human_readable_size(mem.memory_size()) << ")";
- }
-
- thread_scoped_lock lock(rpc_lock);
+ ~NetworkDevice()
+ {
+ RPCSend snd(socket, &error_func, "stop");
+ snd.write();
+ }
- mem.device_pointer = ++mem_counter;
+ virtual BVHLayoutMask get_bvh_layout_mask() const
+ {
+ return BVH_LAYOUT_BVH2;
+ }
- RPCSend snd(socket, &error_func, "mem_alloc");
- snd.add(mem);
- snd.write();
- }
+ void mem_alloc(device_memory &mem)
+ {
+ if (mem.name) {
+ VLOG(1) << "Buffer allocate: " << mem.name << ", "
+ << string_human_readable_number(mem.memory_size()) << " bytes. ("
+ << string_human_readable_size(mem.memory_size()) << ")";
+ }
- void mem_copy_to(device_memory& mem)
- {
- thread_scoped_lock lock(rpc_lock);
+ thread_scoped_lock lock(rpc_lock);
- RPCSend snd(socket, &error_func, "mem_copy_to");
+ mem.device_pointer = ++mem_counter;
- snd.add(mem);
- snd.write();
- snd.write_buffer(mem.host_pointer, mem.memory_size());
- }
+ RPCSend snd(socket, &error_func, "mem_alloc");
+ snd.add(mem);
+ snd.write();
+ }
- void mem_copy_from(device_memory& mem, int y, int w, int h, int elem)
- {
- thread_scoped_lock lock(rpc_lock);
+ void mem_copy_to(device_memory &mem)
+ {
+ thread_scoped_lock lock(rpc_lock);
- size_t data_size = mem.memory_size();
+ RPCSend snd(socket, &error_func, "mem_copy_to");
- RPCSend snd(socket, &error_func, "mem_copy_from");
+ snd.add(mem);
+ snd.write();
+ snd.write_buffer(mem.host_pointer, mem.memory_size());
+ }
- snd.add(mem);
- snd.add(y);
- snd.add(w);
- snd.add(h);
- snd.add(elem);
- snd.write();
+ void mem_copy_from(device_memory &mem, int y, int w, int h, int elem)
+ {
+ thread_scoped_lock lock(rpc_lock);
- RPCReceive rcv(socket, &error_func);
- rcv.read_buffer(mem.host_pointer, data_size);
- }
+ size_t data_size = mem.memory_size();
- void mem_zero(device_memory& mem)
- {
- thread_scoped_lock lock(rpc_lock);
+ RPCSend snd(socket, &error_func, "mem_copy_from");
- RPCSend snd(socket, &error_func, "mem_zero");
+ snd.add(mem);
+ snd.add(y);
+ snd.add(w);
+ snd.add(h);
+ snd.add(elem);
+ snd.write();
- snd.add(mem);
- snd.write();
- }
+ RPCReceive rcv(socket, &error_func);
+ rcv.read_buffer(mem.host_pointer, data_size);
+ }
- void mem_free(device_memory& mem)
- {
- if(mem.device_pointer) {
- thread_scoped_lock lock(rpc_lock);
-
- RPCSend snd(socket, &error_func, "mem_free");
-
- snd.add(mem);
- snd.write();
-
- mem.device_pointer = 0;
- }
- }
+ void mem_zero(device_memory &mem)
+ {
+ thread_scoped_lock lock(rpc_lock);
- void const_copy_to(const char *name, void *host, size_t size)
- {
- thread_scoped_lock lock(rpc_lock);
+ RPCSend snd(socket, &error_func, "mem_zero");
- RPCSend snd(socket, &error_func, "const_copy_to");
+ snd.add(mem);
+ snd.write();
+ }
- string name_string(name);
-
- snd.add(name_string);
- snd.add(size);
- snd.write();
- snd.write_buffer(host, size);
- }
-
- bool load_kernels(const DeviceRequestedFeatures& requested_features)
- {
- if(error_func.have_error())
- return false;
-
- thread_scoped_lock lock(rpc_lock);
-
- RPCSend snd(socket, &error_func, "load_kernels");
- snd.add(requested_features.experimental);
- snd.add(requested_features.max_closure);
- snd.add(requested_features.max_nodes_group);
- snd.add(requested_features.nodes_features);
- snd.write();
-
- bool result;
- RPCReceive rcv(socket, &error_func);
- rcv.read(result);
-
- return result;
- }
-
- void task_add(DeviceTask& task)
- {
- thread_scoped_lock lock(rpc_lock);
-
- the_task = task;
-
- RPCSend snd(socket, &error_func, "task_add");
- snd.add(task);
- snd.write();
- }
-
- void task_wait()
- {
- thread_scoped_lock lock(rpc_lock);
-
- RPCSend snd(socket, &error_func, "task_wait");
- snd.write();
-
- lock.unlock();
-
- TileList the_tiles;
-
- /* todo: run this threaded for connecting to multiple clients */
- for(;;) {
- if(error_func.have_error())
- break;
-
- RenderTile tile;
-
- lock.lock();
- RPCReceive rcv(socket, &error_func);
-
- if(rcv.name == "acquire_tile") {
- lock.unlock();
-
- /* todo: watch out for recursive calls! */
- if(the_task.acquire_tile(this, tile)) { /* write return as bool */
- the_tiles.push_back(tile);
-
- lock.lock();
- RPCSend snd(socket, &error_func, "acquire_tile");
- snd.add(tile);
- snd.write();
- lock.unlock();
- }
- else {
- lock.lock();
- RPCSend snd(socket, &error_func, "acquire_tile_none");
- snd.write();
- lock.unlock();
- }
- }
- else if(rcv.name == "release_tile") {
- rcv.read(tile);
- lock.unlock();
-
- TileList::iterator it = tile_list_find(the_tiles, tile);
- if(it != the_tiles.end()) {
- tile.buffers = it->buffers;
- the_tiles.erase(it);
- }
-
- assert(tile.buffers != NULL);
-
- the_task.release_tile(tile);
-
- lock.lock();
- RPCSend snd(socket, &error_func, "release_tile");
- snd.write();
- lock.unlock();
- }
- else if(rcv.name == "task_wait_done") {
- lock.unlock();
- break;
- }
- else
- lock.unlock();
- }
- }
-
- void task_cancel()
- {
- thread_scoped_lock lock(rpc_lock);
- RPCSend snd(socket, &error_func, "task_cancel");
- snd.write();
- }
-
- int get_split_task_count(DeviceTask&)
- {
- return 1;
- }
-
-private:
- NetworkError error_func;
+ void mem_free(device_memory &mem)
+ {
+ if (mem.device_pointer) {
+ thread_scoped_lock lock(rpc_lock);
+
+ RPCSend snd(socket, &error_func, "mem_free");
+
+ snd.add(mem);
+ snd.write();
+
+ mem.device_pointer = 0;
+ }
+ }
+
+ void const_copy_to(const char *name, void *host, size_t size)
+ {
+ thread_scoped_lock lock(rpc_lock);
+
+ RPCSend snd(socket, &error_func, "const_copy_to");
+
+ string name_string(name);
+
+ snd.add(name_string);
+ snd.add(size);
+ snd.write();
+ snd.write_buffer(host, size);
+ }
+
+ bool load_kernels(const DeviceRequestedFeatures &requested_features)
+ {
+ if (error_func.have_error())
+ return false;
+
+ thread_scoped_lock lock(rpc_lock);
+
+ RPCSend snd(socket, &error_func, "load_kernels");
+ snd.add(requested_features.experimental);
+ snd.add(requested_features.max_closure);
+ snd.add(requested_features.max_nodes_group);
+ snd.add(requested_features.nodes_features);
+ snd.write();
+
+ bool result;
+ RPCReceive rcv(socket, &error_func);
+ rcv.read(result);
+
+ return result;
+ }
+
+ void task_add(DeviceTask &task)
+ {
+ thread_scoped_lock lock(rpc_lock);
+
+ the_task = task;
+
+ RPCSend snd(socket, &error_func, "task_add");
+ snd.add(task);
+ snd.write();
+ }
+
+ void task_wait()
+ {
+ thread_scoped_lock lock(rpc_lock);
+
+ RPCSend snd(socket, &error_func, "task_wait");
+ snd.write();
+
+ lock.unlock();
+
+ TileList the_tiles;
+
+ /* todo: run this threaded for connecting to multiple clients */
+ for (;;) {
+ if (error_func.have_error())
+ break;
+
+ RenderTile tile;
+
+ lock.lock();
+ RPCReceive rcv(socket, &error_func);
+
+ if (rcv.name == "acquire_tile") {
+ lock.unlock();
+
+ /* todo: watch out for recursive calls! */
+ if (the_task.acquire_tile(this, tile)) { /* write return as bool */
+ the_tiles.push_back(tile);
+
+ lock.lock();
+ RPCSend snd(socket, &error_func, "acquire_tile");
+ snd.add(tile);
+ snd.write();
+ lock.unlock();
+ }
+ else {
+ lock.lock();
+ RPCSend snd(socket, &error_func, "acquire_tile_none");
+ snd.write();
+ lock.unlock();
+ }
+ }
+ else if (rcv.name == "release_tile") {
+ rcv.read(tile);
+ lock.unlock();
+
+ TileList::iterator it = tile_list_find(the_tiles, tile);
+ if (it != the_tiles.end()) {
+ tile.buffers = it->buffers;
+ the_tiles.erase(it);
+ }
+
+ assert(tile.buffers != NULL);
+
+ the_task.release_tile(tile);
+
+ lock.lock();
+ RPCSend snd(socket, &error_func, "release_tile");
+ snd.write();
+ lock.unlock();
+ }
+ else if (rcv.name == "task_wait_done") {
+ lock.unlock();
+ break;
+ }
+ else
+ lock.unlock();
+ }
+ }
+
+ void task_cancel()
+ {
+ thread_scoped_lock lock(rpc_lock);
+ RPCSend snd(socket, &error_func, "task_cancel");
+ snd.write();
+ }
+
+ int get_split_task_count(DeviceTask &)
+ {
+ return 1;
+ }
+
+ private:
+ NetworkError error_func;
};
-Device *device_network_create(DeviceInfo& info, Stats &stats, Profiler &profiler, const char *address)
+Device *device_network_create(DeviceInfo &info,
+ Stats &stats,
+ Profiler &profiler,
+ const char *address)
{
- return new NetworkDevice(info, stats, profiler, address);
+ return new NetworkDevice(info, stats, profiler, address);
}
-void device_network_info(vector<DeviceInfo>& devices)
+void device_network_info(vector<DeviceInfo> &devices)
{
- DeviceInfo info;
+ DeviceInfo info;
- info.type = DEVICE_NETWORK;
- info.description = "Network Device";
- info.id = "NETWORK";
- info.num = 0;
+ info.type = DEVICE_NETWORK;
+ info.description = "Network Device";
+ info.id = "NETWORK";
+ info.num = 0;
- /* todo: get this info from device */
- info.has_volume_decoupled = false;
- info.has_osl = false;
+ /* todo: get this info from device */
+ info.has_volume_decoupled = false;
+ info.has_osl = false;
- devices.push_back(info);
+ devices.push_back(info);
}
class DeviceServer {
-public:
- thread_mutex rpc_lock;
-
- void network_error(const string &message) {
- error_func.network_error(message);
- }
-
- bool have_error() { return error_func.have_error(); }
-
- DeviceServer(Device *device_, tcp::socket& socket_)
- : device(device_), socket(socket_), stop(false), blocked_waiting(false)
- {
- error_func = NetworkError();
- }
-
- void listen()
- {
- /* receive remote function calls */
- for(;;) {
- listen_step();
-
- if(stop)
- break;
- }
- }
-
-protected:
- void listen_step()
- {
- thread_scoped_lock lock(rpc_lock);
- RPCReceive rcv(socket, &error_func);
-
- if(rcv.name == "stop")
- stop = true;
- else
- process(rcv, lock);
- }
-
- /* create a memory buffer for a device buffer and insert it into mem_data */
- DataVector &data_vector_insert(device_ptr client_pointer, size_t data_size)
- {
- /* create a new DataVector and insert it into mem_data */
- pair<DataMap::iterator,bool> data_ins = mem_data.insert(
- DataMap::value_type(client_pointer, DataVector()));
-
- /* make sure it was a unique insertion */
- assert(data_ins.second);
-
- /* get a reference to the inserted vector */
- DataVector &data_v = data_ins.first->second;
-
- /* size the vector */
- data_v.resize(data_size);
-
- return data_v;
- }
-
- DataVector &data_vector_find(device_ptr client_pointer)
- {
- DataMap::iterator i = mem_data.find(client_pointer);
- assert(i != mem_data.end());
- return i->second;
- }
-
- /* setup mapping and reverse mapping of client_pointer<->real_pointer */
- void pointer_mapping_insert(device_ptr client_pointer, device_ptr real_pointer)
- {
- pair<PtrMap::iterator,bool> mapins;
-
- /* insert mapping from client pointer to our real device pointer */
- mapins = ptr_map.insert(PtrMap::value_type(client_pointer, real_pointer));
- assert(mapins.second);
-
- /* insert reverse mapping from real our device pointer to client pointer */
- mapins = ptr_imap.insert(PtrMap::value_type(real_pointer, client_pointer));
- assert(mapins.second);
- }
-
- device_ptr device_ptr_from_client_pointer(device_ptr client_pointer)
- {
- PtrMap::iterator i = ptr_map.find(client_pointer);
- assert(i != ptr_map.end());
- return i->second;
- }
-
- device_ptr device_ptr_from_client_pointer_erase(device_ptr client_pointer)
- {
- PtrMap::iterator i = ptr_map.find(client_pointer);
- assert(i != ptr_map.end());
-
- device_ptr result = i->second;
-
- /* erase the mapping */
- ptr_map.erase(i);
-
- /* erase the reverse mapping */
- PtrMap::iterator irev = ptr_imap.find(result);
- assert(irev != ptr_imap.end());
- ptr_imap.erase(irev);
-
- /* erase the data vector */
- DataMap::iterator idata = mem_data.find(client_pointer);
- assert(idata != mem_data.end());
- mem_data.erase(idata);
-
- return result;
- }
-
- /* note that the lock must be already acquired upon entry.
- * This is necessary because the caller often peeks at
- * the header and delegates control to here when it doesn't
- * specifically handle the current RPC.
- * The lock must be unlocked before returning */
- void process(RPCReceive& rcv, thread_scoped_lock &lock)
- {
- if(rcv.name == "mem_alloc") {
- string name;
- network_device_memory mem(device);
- rcv.read(mem, name);
- lock.unlock();
-
- /* Allocate host side data buffer. */
- size_t data_size = mem.memory_size();
- device_ptr client_pointer = mem.device_pointer;
-
- DataVector &data_v = data_vector_insert(client_pointer, data_size);
- mem.host_pointer = (data_size)? (void*)&(data_v[0]): 0;
-
- /* Perform the allocation on the actual device. */
- device->mem_alloc(mem);
-
- /* Store a mapping to/from client_pointer and real device pointer. */
- pointer_mapping_insert(client_pointer, mem.device_pointer);
- }
- else if(rcv.name == "mem_copy_to") {
- string name;
- network_device_memory mem(device);
- rcv.read(mem, name);
- lock.unlock();
-
- size_t data_size = mem.memory_size();
- device_ptr client_pointer = mem.device_pointer;
-
- if(client_pointer) {
- /* Lookup existing host side data buffer. */
- DataVector &data_v = data_vector_find(client_pointer);
- mem.host_pointer = (void*)&data_v[0];
-
- /* Translate the client pointer to a real device pointer. */
- mem.device_pointer = device_ptr_from_client_pointer(client_pointer);
- }
- else {
- /* Allocate host side data buffer. */
- DataVector &data_v = data_vector_insert(client_pointer, data_size);
- mem.host_pointer = (data_size)? (void*)&(data_v[0]): 0;
- }
-
- /* Copy data from network into memory buffer. */
- rcv.read_buffer((uint8_t*)mem.host_pointer, data_size);
-
- /* Copy the data from the memory buffer to the device buffer. */
- device->mem_copy_to(mem);
-
- if(!client_pointer) {
- /* Store a mapping to/from client_pointer and real device pointer. */
- pointer_mapping_insert(client_pointer, mem.device_pointer);
- }
- }
- else if(rcv.name == "mem_copy_from") {
- string name;
- network_device_memory mem(device);
- int y, w, h, elem;
-
- rcv.read(mem, name);
- rcv.read(y);
- rcv.read(w);
- rcv.read(h);
- rcv.read(elem);
-
- device_ptr client_pointer = mem.device_pointer;
- mem.device_pointer = device_ptr_from_client_pointer(client_pointer);
-
- DataVector &data_v = data_vector_find(client_pointer);
-
- mem.host_pointer = (device_ptr)&(data_v[0]);
-
- device->mem_copy_from(mem, y, w, h, elem);
-
- size_t data_size = mem.memory_size();
-
- RPCSend snd(socket, &error_func, "mem_copy_from");
- snd.write();
- snd.write_buffer((uint8_t*)mem.host_pointer, data_size);
- lock.unlock();
- }
- else if(rcv.name == "mem_zero") {
- string name;
- network_device_memory mem(device);
- rcv.read(mem, name);
- lock.unlock();
-
- size_t data_size = mem.memory_size();
- device_ptr client_pointer = mem.device_pointer;
-
- if(client_pointer) {
- /* Lookup existing host side data buffer. */
- DataVector &data_v = data_vector_find(client_pointer);
- mem.host_pointer = (void*)&data_v[0];
-
- /* Translate the client pointer to a real device pointer. */
- mem.device_pointer = device_ptr_from_client_pointer(client_pointer);
- }
- else {
- /* Allocate host side data buffer. */
- DataVector &data_v = data_vector_insert(client_pointer, data_size);
- mem.host_pointer = (void*)? (device_ptr)&(data_v[0]): 0;
- }
-
- /* Zero memory. */
- device->mem_zero(mem);
-
- if(!client_pointer) {
- /* Store a mapping to/from client_pointer and real device pointer. */
- pointer_mapping_insert(client_pointer, mem.device_pointer);
- }
- }
- else if(rcv.name == "mem_free") {
- string name;
- network_device_memory mem(device);
-
- rcv.read(mem, name);
- lock.unlock();
-
- device_ptr client_pointer = mem.device_pointer;
-
- mem.device_pointer = device_ptr_from_client_pointer_erase(client_pointer);
-
- device->mem_free(mem);
- }
- else if(rcv.name == "const_copy_to") {
- string name_string;
- size_t size;
-
- rcv.read(name_string);
- rcv.read(size);
-
- vector<char> host_vector(size);
- rcv.read_buffer(&host_vector[0], size);
- lock.unlock();
-
- device->const_copy_to(name_string.c_str(), &host_vector[0], size);
- }
- else if(rcv.name == "load_kernels") {
- DeviceRequestedFeatures requested_features;
- rcv.read(requested_features.experimental);
- rcv.read(requested_features.max_closure);
- rcv.read(requested_features.max_nodes_group);
- rcv.read(requested_features.nodes_features);
-
- bool result;
- result = device->load_kernels(requested_features);
- RPCSend snd(socket, &error_func, "load_kernels");
- snd.add(result);
- snd.write();
- lock.unlock();
- }
- else if(rcv.name == "task_add") {
- DeviceTask task;
-
- rcv.read(task);
- lock.unlock();
-
- if(task.buffer)
- task.buffer = device_ptr_from_client_pointer(task.buffer);
-
- if(task.rgba_half)
- task.rgba_half = device_ptr_from_client_pointer(task.rgba_half);
-
- if(task.rgba_byte)
- task.rgba_byte = device_ptr_from_client_pointer(task.rgba_byte);
-
- if(task.shader_input)
- task.shader_input = device_ptr_from_client_pointer(task.shader_input);
-
- if(task.shader_output)
- task.shader_output = device_ptr_from_client_pointer(task.shader_output);
-
- task.acquire_tile = function_bind(&DeviceServer::task_acquire_tile, this, _1, _2);
- task.release_tile = function_bind(&DeviceServer::task_release_tile, this, _1);
- task.update_progress_sample = function_bind(&DeviceServer::task_update_progress_sample, this);
- task.update_tile_sample = function_bind(&DeviceServer::task_update_tile_sample, this, _1);
- task.get_cancel = function_bind(&DeviceServer::task_get_cancel, this);
-
- device->task_add(task);
- }
- else if(rcv.name == "task_wait") {
- lock.unlock();
-
- blocked_waiting = true;
- device->task_wait();
- blocked_waiting = false;
-
- lock.lock();
- RPCSend snd(socket, &error_func, "task_wait_done");
- snd.write();
- lock.unlock();
- }
- else if(rcv.name == "task_cancel") {
- lock.unlock();
- device->task_cancel();
- }
- else if(rcv.name == "acquire_tile") {
- AcquireEntry entry;
- entry.name = rcv.name;
- rcv.read(entry.tile);
- acquire_queue.push_back(entry);
- lock.unlock();
- }
- else if(rcv.name == "acquire_tile_none") {
- AcquireEntry entry;
- entry.name = rcv.name;
- acquire_queue.push_back(entry);
- lock.unlock();
- }
- else if(rcv.name == "release_tile") {
- AcquireEntry entry;
- entry.name = rcv.name;
- acquire_queue.push_back(entry);
- lock.unlock();
- }
- else {
- cout << "Error: unexpected RPC receive call \"" + rcv.name + "\"\n";
- lock.unlock();
- }
- }
-
- bool task_acquire_tile(Device *, RenderTile& tile)
- {
- thread_scoped_lock acquire_lock(acquire_mutex);
-
- bool result = false;
-
- RPCSend snd(socket, &error_func, "acquire_tile");
- snd.write();
-
- do {
- if(blocked_waiting)
- listen_step();
-
- /* todo: avoid busy wait loop */
- thread_scoped_lock lock(rpc_lock);
-
- if(!acquire_queue.empty()) {
- AcquireEntry entry = acquire_queue.front();
- acquire_queue.pop_front();
-
- if(entry.name == "acquire_tile") {
- tile = entry.tile;
-
- if(tile.buffer) tile.buffer = ptr_map[tile.buffer];
-
- result = true;
- break;
- }
- else if(entry.name == "acquire_tile_none") {
- break;
- }
- else {
- cout << "Error: unexpected acquire RPC receive call \"" + entry.name + "\"\n";
- }
- }
- } while(acquire_queue.empty() && !stop && !have_error());
-
- return result;
- }
-
- void task_update_progress_sample()
- {
- ; /* skip */
- }
-
- void task_update_tile_sample(RenderTile&)
- {
- ; /* skip */
- }
-
- void task_release_tile(RenderTile& tile)
- {
- thread_scoped_lock acquire_lock(acquire_mutex);
-
- if(tile.buffer) tile.buffer = ptr_imap[tile.buffer];
-
- {
- thread_scoped_lock lock(rpc_lock);
- RPCSend snd(socket, &error_func, "release_tile");
- snd.add(tile);
- snd.write();
- lock.unlock();
- }
-
- do {
- if(blocked_waiting)
- listen_step();
-
- /* todo: avoid busy wait loop */
- thread_scoped_lock lock(rpc_lock);
-
- if(!acquire_queue.empty()) {
- AcquireEntry entry = acquire_queue.front();
- acquire_queue.pop_front();
-
- if(entry.name == "release_tile") {
- lock.unlock();
- break;
- }
- else {
- cout << "Error: unexpected release RPC receive call \"" + entry.name + "\"\n";
- }
- }
- } while(acquire_queue.empty() && !stop);
- }
-
- bool task_get_cancel()
- {
- return false;
- }
-
- /* properties */
- Device *device;
- tcp::socket& socket;
-
- /* mapping of remote to local pointer */
- PtrMap ptr_map;
- PtrMap ptr_imap;
- DataMap mem_data;
-
- struct AcquireEntry {
- string name;
- RenderTile tile;
- };
-
- thread_mutex acquire_mutex;
- list<AcquireEntry> acquire_queue;
-
- bool stop;
- bool blocked_waiting;
-private:
- NetworkError error_func;
-
- /* todo: free memory and device (osl) on network error */
-
+ public:
+ thread_mutex rpc_lock;
+
+ void network_error(const string &message)
+ {
+ error_func.network_error(message);
+ }
+
+ bool have_error()
+ {
+ return error_func.have_error();
+ }
+
+ DeviceServer(Device *device_, tcp::socket &socket_)
+ : device(device_), socket(socket_), stop(false), blocked_waiting(false)
+ {
+ error_func = NetworkError();
+ }
+
+ void listen()
+ {
+ /* receive remote function calls */
+ for (;;) {
+ listen_step();
+
+ if (stop)
+ break;
+ }
+ }
+
+ protected:
+ void listen_step()
+ {
+ thread_scoped_lock lock(rpc_lock);
+ RPCReceive rcv(socket, &error_func);
+
+ if (rcv.name == "stop")
+ stop = true;
+ else
+ process(rcv, lock);
+ }
+
+ /* create a memory buffer for a device buffer and insert it into mem_data */
+ DataVector &data_vector_insert(device_ptr client_pointer, size_t data_size)
+ {
+ /* create a new DataVector and insert it into mem_data */
+ pair<DataMap::iterator, bool> data_ins = mem_data.insert(
+ DataMap::value_type(client_pointer, DataVector()));
+
+ /* make sure it was a unique insertion */
+ assert(data_ins.second);
+
+ /* get a reference to the inserted vector */
+ DataVector &data_v = data_ins.first->second;
+
+ /* size the vector */
+ data_v.resize(data_size);
+
+ return data_v;
+ }
+
+ DataVector &data_vector_find(device_ptr client_pointer)
+ {
+ DataMap::iterator i = mem_data.find(client_pointer);
+ assert(i != mem_data.end());
+ return i->second;
+ }
+
+ /* setup mapping and reverse mapping of client_pointer<->real_pointer */
+ void pointer_mapping_insert(device_ptr client_pointer, device_ptr real_pointer)
+ {
+ pair<PtrMap::iterator, bool> mapins;
+
+ /* insert mapping from client pointer to our real device pointer */
+ mapins = ptr_map.insert(PtrMap::value_type(client_pointer, real_pointer));
+ assert(mapins.second);
+
+ /* insert reverse mapping from real our device pointer to client pointer */
+ mapins = ptr_imap.insert(PtrMap::value_type(real_pointer, client_pointer));
+ assert(mapins.second);
+ }
+
+ device_ptr device_ptr_from_client_pointer(device_ptr client_pointer)
+ {
+ PtrMap::iterator i = ptr_map.find(client_pointer);
+ assert(i != ptr_map.end());
+ return i->second;
+ }
+
+ device_ptr device_ptr_from_client_pointer_erase(device_ptr client_pointer)
+ {
+ PtrMap::iterator i = ptr_map.find(client_pointer);
+ assert(i != ptr_map.end());
+
+ device_ptr result = i->second;
+
+ /* erase the mapping */
+ ptr_map.erase(i);
+
+ /* erase the reverse mapping */
+ PtrMap::iterator irev = ptr_imap.find(result);
+ assert(irev != ptr_imap.end());
+ ptr_imap.erase(irev);
+
+ /* erase the data vector */
+ DataMap::iterator idata = mem_data.find(client_pointer);
+ assert(idata != mem_data.end());
+ mem_data.erase(idata);
+
+ return result;
+ }
+
+ /* note that the lock must be already acquired upon entry.
+ * This is necessary because the caller often peeks at
+ * the header and delegates control to here when it doesn't
+ * specifically handle the current RPC.
+ * The lock must be unlocked before returning */
+ void process(RPCReceive &rcv, thread_scoped_lock &lock)
+ {
+ if (rcv.name == "mem_alloc") {
+ string name;
+ network_device_memory mem(device);
+ rcv.read(mem, name);
+ lock.unlock();
+
+ /* Allocate host side data buffer. */
+ size_t data_size = mem.memory_size();
+ device_ptr client_pointer = mem.device_pointer;
+
+ DataVector &data_v = data_vector_insert(client_pointer, data_size);
+ mem.host_pointer = (data_size) ? (void *)&(data_v[0]) : 0;
+
+ /* Perform the allocation on the actual device. */
+ device->mem_alloc(mem);
+
+ /* Store a mapping to/from client_pointer and real device pointer. */
+ pointer_mapping_insert(client_pointer, mem.device_pointer);
+ }
+ else if (rcv.name == "mem_copy_to") {
+ string name;
+ network_device_memory mem(device);
+ rcv.read(mem, name);
+ lock.unlock();
+
+ size_t data_size = mem.memory_size();
+ device_ptr client_pointer = mem.device_pointer;
+
+ if (client_pointer) {
+ /* Lookup existing host side data buffer. */
+ DataVector &data_v = data_vector_find(client_pointer);
+ mem.host_pointer = (void *)&data_v[0];
+
+ /* Translate the client pointer to a real device pointer. */
+ mem.device_pointer = device_ptr_from_client_pointer(client_pointer);
+ }
+ else {
+ /* Allocate host side data buffer. */
+ DataVector &data_v = data_vector_insert(client_pointer, data_size);
+ mem.host_pointer = (data_size) ? (void *)&(data_v[0]) : 0;
+ }
+
+ /* Copy data from network into memory buffer. */
+ rcv.read_buffer((uint8_t *)mem.host_pointer, data_size);
+
+ /* Copy the data from the memory buffer to the device buffer. */
+ device->mem_copy_to(mem);
+
+ if (!client_pointer) {
+ /* Store a mapping to/from client_pointer and real device pointer. */
+ pointer_mapping_insert(client_pointer, mem.device_pointer);
+ }
+ }
+ else if (rcv.name == "mem_copy_from") {
+ string name;
+ network_device_memory mem(device);
+ int y, w, h, elem;
+
+ rcv.read(mem, name);
+ rcv.read(y);
+ rcv.read(w);
+ rcv.read(h);
+ rcv.read(elem);
+
+ device_ptr client_pointer = mem.device_pointer;
+ mem.device_pointer = device_ptr_from_client_pointer(client_pointer);
+
+ DataVector &data_v = data_vector_find(client_pointer);
+
+ mem.host_pointer = (device_ptr) & (data_v[0]);
+
+ device->mem_copy_from(mem, y, w, h, elem);
+
+ size_t data_size = mem.memory_size();
+
+ RPCSend snd(socket, &error_func, "mem_copy_from");
+ snd.write();
+ snd.write_buffer((uint8_t *)mem.host_pointer, data_size);
+ lock.unlock();
+ }
+ else if (rcv.name == "mem_zero") {
+ string name;
+ network_device_memory mem(device);
+ rcv.read(mem, name);
+ lock.unlock();
+
+ size_t data_size = mem.memory_size();
+ device_ptr client_pointer = mem.device_pointer;
+
+ if (client_pointer) {
+ /* Lookup existing host side data buffer. */
+ DataVector &data_v = data_vector_find(client_pointer);
+ mem.host_pointer = (void *)&data_v[0];
+
+ /* Translate the client pointer to a real device pointer. */
+ mem.device_pointer = device_ptr_from_client_pointer(client_pointer);
+ }
+ else {
+ /* Allocate host side data buffer. */
+ DataVector &data_v = data_vector_insert(client_pointer, data_size);
+ mem.host_pointer = (void *) ? (device_ptr) & (data_v[0]) : 0;
+ }
+
+ /* Zero memory. */
+ device->mem_zero(mem);
+
+ if (!client_pointer) {
+ /* Store a mapping to/from client_pointer and real device pointer. */
+ pointer_mapping_insert(client_pointer, mem.device_pointer);
+ }
+ }
+ else if (rcv.name == "mem_free") {
+ string name;
+ network_device_memory mem(device);
+
+ rcv.read(mem, name);
+ lock.unlock();
+
+ device_ptr client_pointer = mem.device_pointer;
+
+ mem.device_pointer = device_ptr_from_client_pointer_erase(client_pointer);
+
+ device->mem_free(mem);
+ }
+ else if (rcv.name == "const_copy_to") {
+ string name_string;
+ size_t size;
+
+ rcv.read(name_string);
+ rcv.read(size);
+
+ vector<char> host_vector(size);
+ rcv.read_buffer(&host_vector[0], size);
+ lock.unlock();
+
+ device->const_copy_to(name_string.c_str(), &host_vector[0], size);
+ }
+ else if (rcv.name == "load_kernels") {
+ DeviceRequestedFeatures requested_features;
+ rcv.read(requested_features.experimental);
+ rcv.read(requested_features.max_closure);
+ rcv.read(requested_features.max_nodes_group);
+ rcv.read(requested_features.nodes_features);
+
+ bool result;
+ result = device->load_kernels(requested_features);
+ RPCSend snd(socket, &error_func, "load_kernels");
+ snd.add(result);
+ snd.write();
+ lock.unlock();
+ }
+ else if (rcv.name == "task_add") {
+ DeviceTask task;
+
+ rcv.read(task);
+ lock.unlock();
+
+ if (task.buffer)
+ task.buffer = device_ptr_from_client_pointer(task.buffer);
+
+ if (task.rgba_half)
+ task.rgba_half = device_ptr_from_client_pointer(task.rgba_half);
+
+ if (task.rgba_byte)
+ task.rgba_byte = device_ptr_from_client_pointer(task.rgba_byte);
+
+ if (task.shader_input)
+ task.shader_input = device_ptr_from_client_pointer(task.shader_input);
+
+ if (task.shader_output)
+ task.shader_output = device_ptr_from_client_pointer(task.shader_output);
+
+ task.acquire_tile = function_bind(&DeviceServer::task_acquire_tile, this, _1, _2);
+ task.release_tile = function_bind(&DeviceServer::task_release_tile, this, _1);
+ task.update_progress_sample = function_bind(&DeviceServer::task_update_progress_sample,
+ this);
+ task.update_tile_sample = function_bind(&DeviceServer::task_update_tile_sample, this, _1);
+ task.get_cancel = function_bind(&DeviceServer::task_get_cancel, this);
+
+ device->task_add(task);
+ }
+ else if (rcv.name == "task_wait") {
+ lock.unlock();
+
+ blocked_waiting = true;
+ device->task_wait();
+ blocked_waiting = false;
+
+ lock.lock();
+ RPCSend snd(socket, &error_func, "task_wait_done");
+ snd.write();
+ lock.unlock();
+ }
+ else if (rcv.name == "task_cancel") {
+ lock.unlock();
+ device->task_cancel();
+ }
+ else if (rcv.name == "acquire_tile") {
+ AcquireEntry entry;
+ entry.name = rcv.name;
+ rcv.read(entry.tile);
+ acquire_queue.push_back(entry);
+ lock.unlock();
+ }
+ else if (rcv.name == "acquire_tile_none") {
+ AcquireEntry entry;
+ entry.name = rcv.name;
+ acquire_queue.push_back(entry);
+ lock.unlock();
+ }
+ else if (rcv.name == "release_tile") {
+ AcquireEntry entry;
+ entry.name = rcv.name;
+ acquire_queue.push_back(entry);
+ lock.unlock();
+ }
+ else {
+ cout << "Error: unexpected RPC receive call \"" + rcv.name + "\"\n";
+ lock.unlock();
+ }
+ }
+
+ bool task_acquire_tile(Device *, RenderTile &tile)
+ {
+ thread_scoped_lock acquire_lock(acquire_mutex);
+
+ bool result = false;
+
+ RPCSend snd(socket, &error_func, "acquire_tile");
+ snd.write();
+
+ do {
+ if (blocked_waiting)
+ listen_step();
+
+ /* todo: avoid busy wait loop */
+ thread_scoped_lock lock(rpc_lock);
+
+ if (!acquire_queue.empty()) {
+ AcquireEntry entry = acquire_queue.front();
+ acquire_queue.pop_front();
+
+ if (entry.name == "acquire_tile") {
+ tile = entry.tile;
+
+ if (tile.buffer)
+ tile.buffer = ptr_map[tile.buffer];
+
+ result = true;
+ break;
+ }
+ else if (entry.name == "acquire_tile_none") {
+ break;
+ }
+ else {
+ cout << "Error: unexpected acquire RPC receive call \"" + entry.name + "\"\n";
+ }
+ }
+ } while (acquire_queue.empty() && !stop && !have_error());
+
+ return result;
+ }
+
+ void task_update_progress_sample()
+ {
+ ; /* skip */
+ }
+
+ void task_update_tile_sample(RenderTile &)
+ {
+ ; /* skip */
+ }
+
+ void task_release_tile(RenderTile &tile)
+ {
+ thread_scoped_lock acquire_lock(acquire_mutex);
+
+ if (tile.buffer)
+ tile.buffer = ptr_imap[tile.buffer];
+
+ {
+ thread_scoped_lock lock(rpc_lock);
+ RPCSend snd(socket, &error_func, "release_tile");
+ snd.add(tile);
+ snd.write();
+ lock.unlock();
+ }
+
+ do {
+ if (blocked_waiting)
+ listen_step();
+
+ /* todo: avoid busy wait loop */
+ thread_scoped_lock lock(rpc_lock);
+
+ if (!acquire_queue.empty()) {
+ AcquireEntry entry = acquire_queue.front();
+ acquire_queue.pop_front();
+
+ if (entry.name == "release_tile") {
+ lock.unlock();
+ break;
+ }
+ else {
+ cout << "Error: unexpected release RPC receive call \"" + entry.name + "\"\n";
+ }
+ }
+ } while (acquire_queue.empty() && !stop);
+ }
+
+ bool task_get_cancel()
+ {
+ return false;
+ }
+
+ /* properties */
+ Device *device;
+ tcp::socket &socket;
+
+ /* mapping of remote to local pointer */
+ PtrMap ptr_map;
+ PtrMap ptr_imap;
+ DataMap mem_data;
+
+ struct AcquireEntry {
+ string name;
+ RenderTile tile;
+ };
+
+ thread_mutex acquire_mutex;
+ list<AcquireEntry> acquire_queue;
+
+ bool stop;
+ bool blocked_waiting;
+
+ private:
+ NetworkError error_func;
+
+ /* todo: free memory and device (osl) on network error */
};
void Device::server_run()
{
- try {
- /* starts thread that responds to discovery requests */
- ServerDiscovery discovery;
-
- for(;;) {
- /* accept connection */
- boost::asio::io_service io_service;
- tcp::acceptor acceptor(io_service, tcp::endpoint(tcp::v4(), SERVER_PORT));
-
- tcp::socket socket(io_service);
- acceptor.accept(socket);
-
- string remote_address = socket.remote_endpoint().address().to_string();
- printf("Connected to remote client at: %s\n", remote_address.c_str());
-
- DeviceServer server(this, socket);
- server.listen();
-
- printf("Disconnected.\n");
- }
- }
- catch(exception& e) {
- fprintf(stderr, "Network server exception: %s\n", e.what());
- }
+ try {
+ /* starts thread that responds to discovery requests */
+ ServerDiscovery discovery;
+
+ for (;;) {
+ /* accept connection */
+ boost::asio::io_service io_service;
+ tcp::acceptor acceptor(io_service, tcp::endpoint(tcp::v4(), SERVER_PORT));
+
+ tcp::socket socket(io_service);
+ acceptor.accept(socket);
+
+ string remote_address = socket.remote_endpoint().address().to_string();
+ printf("Connected to remote client at: %s\n", remote_address.c_str());
+
+ DeviceServer server(this, socket);
+ server.listen();
+
+ printf("Disconnected.\n");
+ }
+ }
+ catch (exception &e) {
+ fprintf(stderr, "Network server exception: %s\n", e.what());
+ }
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/device/device_network.h b/intern/cycles/device/device_network.h
index 67626ae177f..5b69b815cc6 100644
--- a/intern/cycles/device/device_network.h
+++ b/intern/cycles/device/device_network.h
@@ -19,35 +19,35 @@
#ifdef WITH_NETWORK
-#include <boost/archive/text_iarchive.hpp>
-#include <boost/archive/text_oarchive.hpp>
-#include <boost/archive/binary_iarchive.hpp>
-#include <boost/archive/binary_oarchive.hpp>
-#include <boost/array.hpp>
-#include <boost/asio.hpp>
-#include <boost/bind.hpp>
-#include <boost/serialization/vector.hpp>
-#include <boost/thread.hpp>
-
-#include <iostream>
-#include <sstream>
-#include <deque>
-
-#include "render/buffers.h"
-
-#include "util/util_foreach.h"
-#include "util/util_list.h"
-#include "util/util_map.h"
-#include "util/util_param.h"
-#include "util/util_string.h"
+# include <boost/archive/text_iarchive.hpp>
+# include <boost/archive/text_oarchive.hpp>
+# include <boost/archive/binary_iarchive.hpp>
+# include <boost/archive/binary_oarchive.hpp>
+# include <boost/array.hpp>
+# include <boost/asio.hpp>
+# include <boost/bind.hpp>
+# include <boost/serialization/vector.hpp>
+# include <boost/thread.hpp>
+
+# include <iostream>
+# include <sstream>
+# include <deque>
+
+# include "render/buffers.h"
+
+# include "util/util_foreach.h"
+# include "util/util_list.h"
+# include "util/util_map.h"
+# include "util/util_param.h"
+# include "util/util_string.h"
CCL_NAMESPACE_BEGIN
-using std::cout;
using std::cerr;
+using std::cout;
+using std::exception;
using std::hex;
using std::setw;
-using std::exception;
using boost::asio::ip::tcp;
@@ -56,436 +56,435 @@ static const int DISCOVER_PORT = 5121;
static const string DISCOVER_REQUEST_MSG = "REQUEST_RENDER_SERVER_IP";
static const string DISCOVER_REPLY_MSG = "REPLY_RENDER_SERVER_IP";
-#if 0
+# if 0
typedef boost::archive::text_oarchive o_archive;
typedef boost::archive::text_iarchive i_archive;
-#else
+# else
typedef boost::archive::binary_oarchive o_archive;
typedef boost::archive::binary_iarchive i_archive;
-#endif
+# endif
/* Serialization of device memory */
-class network_device_memory : public device_memory
-{
-public:
- network_device_memory(Device *device)
- : device_memory(device, "", MEM_READ_ONLY)
- {
- }
+class network_device_memory : public device_memory {
+ public:
+ network_device_memory(Device *device) : device_memory(device, "", MEM_READ_ONLY)
+ {
+ }
- ~network_device_memory()
- {
- device_pointer = 0;
- };
+ ~network_device_memory()
+ {
+ device_pointer = 0;
+ };
- vector<char> local_data;
+ vector<char> local_data;
};
/* Common netowrk error function / object for both DeviceNetwork and DeviceServer*/
class NetworkError {
-public:
- NetworkError() {
- error = "";
- error_count = 0;
- }
-
- ~NetworkError() {}
-
- void network_error(const string& message) {
- error = message;
- error_count += 1;
- }
-
- bool have_error() {
- return true ? error_count > 0 : false;
- }
-
-private:
- string error;
- int error_count;
+ public:
+ NetworkError()
+ {
+ error = "";
+ error_count = 0;
+ }
+
+ ~NetworkError()
+ {
+ }
+
+ void network_error(const string &message)
+ {
+ error = message;
+ error_count += 1;
+ }
+
+ bool have_error()
+ {
+ return true ? error_count > 0 : false;
+ }
+
+ private:
+ string error;
+ int error_count;
};
-
/* Remote procedure call Send */
class RPCSend {
-public:
- RPCSend(tcp::socket& socket_, NetworkError* e, const string& name_ = "")
- : name(name_), socket(socket_), archive(archive_stream), sent(false)
- {
- archive & name_;
- error_func = e;
- fprintf(stderr, "rpc send %s\n", name.c_str());
- }
-
- ~RPCSend()
- {
- }
-
- void add(const device_memory& mem)
- {
- archive & mem.data_type & mem.data_elements & mem.data_size;
- archive & mem.data_width & mem.data_height & mem.data_depth & mem.device_pointer;
- archive & mem.type & string(mem.name);
- archive & mem.interpolation & mem.extension;
- archive & mem.device_pointer;
- }
-
- template<typename T> void add(const T& data)
- {
- archive & data;
- }
-
- void add(const DeviceTask& task)
- {
- int type = (int)task.type;
- archive & type & task.x & task.y & task.w & task.h;
- archive & task.rgba_byte & task.rgba_half & task.buffer & task.sample & task.num_samples;
- archive & task.offset & task.stride;
- archive & task.shader_input & task.shader_output & task.shader_eval_type;
- archive & task.shader_x & task.shader_w;
- archive & task.need_finish_queue;
- }
-
- void add(const RenderTile& tile)
- {
- archive & tile.x & tile.y & tile.w & tile.h;
- archive & tile.start_sample & tile.num_samples & tile.sample;
- archive & tile.resolution & tile.offset & tile.stride;
- archive & tile.buffer;
- }
-
- void write()
- {
- boost::system::error_code error;
-
- /* get string from stream */
- string archive_str = archive_stream.str();
-
- /* first send fixed size header with size of following data */
- ostringstream header_stream;
- header_stream << setw(8) << hex << archive_str.size();
- string header_str = header_stream.str();
-
- boost::asio::write(socket,
- boost::asio::buffer(header_str),
- boost::asio::transfer_all(), error);
-
- if(error.value())
- error_func->network_error(error.message());
-
- /* then send actual data */
- boost::asio::write(socket,
- boost::asio::buffer(archive_str),
- boost::asio::transfer_all(), error);
-
- if(error.value())
- error_func->network_error(error.message());
-
- sent = true;
- }
-
- void write_buffer(void *buffer, size_t size)
- {
- boost::system::error_code error;
-
- boost::asio::write(socket,
- boost::asio::buffer(buffer, size),
- boost::asio::transfer_all(), error);
-
- if(error.value())
- error_func->network_error(error.message());
- }
-
-protected:
- string name;
- tcp::socket& socket;
- ostringstream archive_stream;
- o_archive archive;
- bool sent;
- NetworkError *error_func;
+ public:
+ RPCSend(tcp::socket &socket_, NetworkError *e, const string &name_ = "")
+ : name(name_), socket(socket_), archive(archive_stream), sent(false)
+ {
+ archive &name_;
+ error_func = e;
+ fprintf(stderr, "rpc send %s\n", name.c_str());
+ }
+
+ ~RPCSend()
+ {
+ }
+
+ void add(const device_memory &mem)
+ {
+ archive &mem.data_type &mem.data_elements &mem.data_size;
+ archive &mem.data_width &mem.data_height &mem.data_depth &mem.device_pointer;
+ archive &mem.type &string(mem.name);
+ archive &mem.interpolation &mem.extension;
+ archive &mem.device_pointer;
+ }
+
+ template<typename T> void add(const T &data)
+ {
+ archive &data;
+ }
+
+ void add(const DeviceTask &task)
+ {
+ int type = (int)task.type;
+ archive &type &task.x &task.y &task.w &task.h;
+ archive &task.rgba_byte &task.rgba_half &task.buffer &task.sample &task.num_samples;
+ archive &task.offset &task.stride;
+ archive &task.shader_input &task.shader_output &task.shader_eval_type;
+ archive &task.shader_x &task.shader_w;
+ archive &task.need_finish_queue;
+ }
+
+ void add(const RenderTile &tile)
+ {
+ archive &tile.x &tile.y &tile.w &tile.h;
+ archive &tile.start_sample &tile.num_samples &tile.sample;
+ archive &tile.resolution &tile.offset &tile.stride;
+ archive &tile.buffer;
+ }
+
+ void write()
+ {
+ boost::system::error_code error;
+
+ /* get string from stream */
+ string archive_str = archive_stream.str();
+
+ /* first send fixed size header with size of following data */
+ ostringstream header_stream;
+ header_stream << setw(8) << hex << archive_str.size();
+ string header_str = header_stream.str();
+
+ boost::asio::write(
+ socket, boost::asio::buffer(header_str), boost::asio::transfer_all(), error);
+
+ if (error.value())
+ error_func->network_error(error.message());
+
+ /* then send actual data */
+ boost::asio::write(
+ socket, boost::asio::buffer(archive_str), boost::asio::transfer_all(), error);
+
+ if (error.value())
+ error_func->network_error(error.message());
+
+ sent = true;
+ }
+
+ void write_buffer(void *buffer, size_t size)
+ {
+ boost::system::error_code error;
+
+ boost::asio::write(
+ socket, boost::asio::buffer(buffer, size), boost::asio::transfer_all(), error);
+
+ if (error.value())
+ error_func->network_error(error.message());
+ }
+
+ protected:
+ string name;
+ tcp::socket &socket;
+ ostringstream archive_stream;
+ o_archive archive;
+ bool sent;
+ NetworkError *error_func;
};
/* Remote procedure call Receive */
class RPCReceive {
-public:
- RPCReceive(tcp::socket& socket_, NetworkError* e )
- : socket(socket_), archive_stream(NULL), archive(NULL)
- {
- error_func = e;
- /* read head with fixed size */
- vector<char> header(8);
- boost::system::error_code error;
- size_t len = boost::asio::read(socket, boost::asio::buffer(header), error);
-
- if(error.value()) {
- error_func->network_error(error.message());
- }
-
- /* verify if we got something */
- if(len == header.size()) {
- /* decode header */
- string header_str(&header[0], header.size());
- istringstream header_stream(header_str);
-
- size_t data_size;
-
- if((header_stream >> hex >> data_size)) {
-
- vector<char> data(data_size);
- size_t len = boost::asio::read(socket, boost::asio::buffer(data), error);
-
- if(error.value())
- error_func->network_error(error.message());
-
-
- if(len == data_size) {
- archive_str = (data.size())? string(&data[0], data.size()): string("");
-
- archive_stream = new istringstream(archive_str);
- archive = new i_archive(*archive_stream);
-
- *archive & name;
- fprintf(stderr, "rpc receive %s\n", name.c_str());
- }
- else {
- error_func->network_error("Network receive error: data size doesn't match header");
- }
- }
- else {
- error_func->network_error("Network receive error: can't decode data size from header");
- }
- }
- else {
- error_func->network_error("Network receive error: invalid header size");
- }
- }
-
- ~RPCReceive()
- {
- delete archive;
- delete archive_stream;
- }
-
- void read(network_device_memory& mem, string& name)
- {
- *archive & mem.data_type & mem.data_elements & mem.data_size;
- *archive & mem.data_width & mem.data_height & mem.data_depth & mem.device_pointer;
- *archive & mem.type & name;
- *archive & mem.interpolation & mem.extension;
- *archive & mem.device_pointer;
-
- mem.name = name.c_str();
- mem.host_pointer = 0;
-
- /* Can't transfer OpenGL texture over network. */
- if(mem.type == MEM_PIXELS) {
- mem.type = MEM_READ_WRITE;
- }
- }
-
- template<typename T> void read(T& data)
- {
- *archive & data;
- }
-
- void read_buffer(void *buffer, size_t size)
- {
- boost::system::error_code error;
- size_t len = boost::asio::read(socket, boost::asio::buffer(buffer, size), error);
-
- if(error.value()) {
- error_func->network_error(error.message());
- }
-
- if(len != size)
- cout << "Network receive error: buffer size doesn't match expected size\n";
- }
-
- void read(DeviceTask& task)
- {
- int type;
-
- *archive & type & task.x & task.y & task.w & task.h;
- *archive & task.rgba_byte & task.rgba_half & task.buffer & task.sample & task.num_samples;
- *archive & task.offset & task.stride;
- *archive & task.shader_input & task.shader_output & task.shader_eval_type;
- *archive & task.shader_x & task.shader_w;
- *archive & task.need_finish_queue;
-
- task.type = (DeviceTask::Type)type;
- }
-
- void read(RenderTile& tile)
- {
- *archive & tile.x & tile.y & tile.w & tile.h;
- *archive & tile.start_sample & tile.num_samples & tile.sample;
- *archive & tile.resolution & tile.offset & tile.stride;
- *archive & tile.buffer;
-
- tile.buffers = NULL;
- }
-
- string name;
-
-protected:
- tcp::socket& socket;
- string archive_str;
- istringstream *archive_stream;
- i_archive *archive;
- NetworkError *error_func;
+ public:
+ RPCReceive(tcp::socket &socket_, NetworkError *e)
+ : socket(socket_), archive_stream(NULL), archive(NULL)
+ {
+ error_func = e;
+ /* read head with fixed size */
+ vector<char> header(8);
+ boost::system::error_code error;
+ size_t len = boost::asio::read(socket, boost::asio::buffer(header), error);
+
+ if (error.value()) {
+ error_func->network_error(error.message());
+ }
+
+ /* verify if we got something */
+ if (len == header.size()) {
+ /* decode header */
+ string header_str(&header[0], header.size());
+ istringstream header_stream(header_str);
+
+ size_t data_size;
+
+ if ((header_stream >> hex >> data_size)) {
+
+ vector<char> data(data_size);
+ size_t len = boost::asio::read(socket, boost::asio::buffer(data), error);
+
+ if (error.value())
+ error_func->network_error(error.message());
+
+ if (len == data_size) {
+ archive_str = (data.size()) ? string(&data[0], data.size()) : string("");
+
+ archive_stream = new istringstream(archive_str);
+ archive = new i_archive(*archive_stream);
+
+ *archive &name;
+ fprintf(stderr, "rpc receive %s\n", name.c_str());
+ }
+ else {
+ error_func->network_error("Network receive error: data size doesn't match header");
+ }
+ }
+ else {
+ error_func->network_error("Network receive error: can't decode data size from header");
+ }
+ }
+ else {
+ error_func->network_error("Network receive error: invalid header size");
+ }
+ }
+
+ ~RPCReceive()
+ {
+ delete archive;
+ delete archive_stream;
+ }
+
+ void read(network_device_memory &mem, string &name)
+ {
+ *archive &mem.data_type &mem.data_elements &mem.data_size;
+ *archive &mem.data_width &mem.data_height &mem.data_depth &mem.device_pointer;
+ *archive &mem.type &name;
+ *archive &mem.interpolation &mem.extension;
+ *archive &mem.device_pointer;
+
+ mem.name = name.c_str();
+ mem.host_pointer = 0;
+
+ /* Can't transfer OpenGL texture over network. */
+ if (mem.type == MEM_PIXELS) {
+ mem.type = MEM_READ_WRITE;
+ }
+ }
+
+ template<typename T> void read(T &data)
+ {
+ *archive &data;
+ }
+
+ void read_buffer(void *buffer, size_t size)
+ {
+ boost::system::error_code error;
+ size_t len = boost::asio::read(socket, boost::asio::buffer(buffer, size), error);
+
+ if (error.value()) {
+ error_func->network_error(error.message());
+ }
+
+ if (len != size)
+ cout << "Network receive error: buffer size doesn't match expected size\n";
+ }
+
+ void read(DeviceTask &task)
+ {
+ int type;
+
+ *archive &type &task.x &task.y &task.w &task.h;
+ *archive &task.rgba_byte &task.rgba_half &task.buffer &task.sample &task.num_samples;
+ *archive &task.offset &task.stride;
+ *archive &task.shader_input &task.shader_output &task.shader_eval_type;
+ *archive &task.shader_x &task.shader_w;
+ *archive &task.need_finish_queue;
+
+ task.type = (DeviceTask::Type)type;
+ }
+
+ void read(RenderTile &tile)
+ {
+ *archive &tile.x &tile.y &tile.w &tile.h;
+ *archive &tile.start_sample &tile.num_samples &tile.sample;
+ *archive &tile.resolution &tile.offset &tile.stride;
+ *archive &tile.buffer;
+
+ tile.buffers = NULL;
+ }
+
+ string name;
+
+ protected:
+ tcp::socket &socket;
+ string archive_str;
+ istringstream *archive_stream;
+ i_archive *archive;
+ NetworkError *error_func;
};
/* Server auto discovery */
class ServerDiscovery {
-public:
- explicit ServerDiscovery(bool discover = false)
- : listen_socket(io_service), collect_servers(false)
- {
- /* setup listen socket */
- listen_endpoint.address(boost::asio::ip::address_v4::any());
- listen_endpoint.port(DISCOVER_PORT);
-
- listen_socket.open(listen_endpoint.protocol());
-
- boost::asio::socket_base::reuse_address option(true);
- listen_socket.set_option(option);
-
- listen_socket.bind(listen_endpoint);
-
- /* setup receive callback */
- async_receive();
-
- /* start server discovery */
- if(discover) {
- collect_servers = true;
- servers.clear();
-
- broadcast_message(DISCOVER_REQUEST_MSG);
- }
-
- /* start thread */
- work = new boost::asio::io_service::work(io_service);
- thread = new boost::thread(boost::bind(&boost::asio::io_service::run, &io_service));
- }
-
- ~ServerDiscovery()
- {
- io_service.stop();
- thread->join();
- delete thread;
- delete work;
- }
-
- vector<string> get_server_list()
- {
- vector<string> result;
-
- mutex.lock();
- result = vector<string>(servers.begin(), servers.end());
- mutex.unlock();
-
- return result;
- }
-
-private:
- void handle_receive_from(const boost::system::error_code& error, size_t size)
- {
- if(error) {
- cout << "Server discovery receive error: " << error.message() << "\n";
- return;
- }
-
- if(size > 0) {
- string msg = string(receive_buffer, size);
-
- /* handle incoming message */
- if(collect_servers) {
- if(msg == DISCOVER_REPLY_MSG) {
- string address = receive_endpoint.address().to_string();
-
- mutex.lock();
-
- /* add address if it's not already in the list */
- bool found = std::find(servers.begin(), servers.end(),
- address) != servers.end();
-
- if(!found)
- servers.push_back(address);
-
- mutex.unlock();
- }
- }
- else {
- /* reply to request */
- if(msg == DISCOVER_REQUEST_MSG)
- broadcast_message(DISCOVER_REPLY_MSG);
- }
- }
-
- async_receive();
- }
-
- void async_receive()
- {
- listen_socket.async_receive_from(
- boost::asio::buffer(receive_buffer), receive_endpoint,
- boost::bind(&ServerDiscovery::handle_receive_from, this,
- boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred));
- }
-
- void broadcast_message(const string& msg)
- {
- /* setup broadcast socket */
- boost::asio::ip::udp::socket socket(io_service);
-
- socket.open(boost::asio::ip::udp::v4());
-
- boost::asio::socket_base::broadcast option(true);
- socket.set_option(option);
-
- boost::asio::ip::udp::endpoint broadcast_endpoint(
- boost::asio::ip::address::from_string("255.255.255.255"), DISCOVER_PORT);
-
- /* broadcast message */
- socket.send_to(boost::asio::buffer(msg), broadcast_endpoint);
- }
-
- /* network service and socket */
- boost::asio::io_service io_service;
- boost::asio::ip::udp::endpoint listen_endpoint;
- boost::asio::ip::udp::socket listen_socket;
-
- /* threading */
- boost::thread *thread;
- boost::asio::io_service::work *work;
- boost::mutex mutex;
-
- /* buffer and endpoint for receiving messages */
- char receive_buffer[256];
- boost::asio::ip::udp::endpoint receive_endpoint;
-
- // os, version, devices, status, host name, group name, ip as far as fields go
- struct ServerInfo {
- string cycles_version;
- string os;
- int device_count;
- string status;
- string host_name;
- string group_name;
- string host_addr;
- };
-
- /* collection of server addresses in list */
- bool collect_servers;
- vector<string> servers;
+ public:
+ explicit ServerDiscovery(bool discover = false)
+ : listen_socket(io_service), collect_servers(false)
+ {
+ /* setup listen socket */
+ listen_endpoint.address(boost::asio::ip::address_v4::any());
+ listen_endpoint.port(DISCOVER_PORT);
+
+ listen_socket.open(listen_endpoint.protocol());
+
+ boost::asio::socket_base::reuse_address option(true);
+ listen_socket.set_option(option);
+
+ listen_socket.bind(listen_endpoint);
+
+ /* setup receive callback */
+ async_receive();
+
+ /* start server discovery */
+ if (discover) {
+ collect_servers = true;
+ servers.clear();
+
+ broadcast_message(DISCOVER_REQUEST_MSG);
+ }
+
+ /* start thread */
+ work = new boost::asio::io_service::work(io_service);
+ thread = new boost::thread(boost::bind(&boost::asio::io_service::run, &io_service));
+ }
+
+ ~ServerDiscovery()
+ {
+ io_service.stop();
+ thread->join();
+ delete thread;
+ delete work;
+ }
+
+ vector<string> get_server_list()
+ {
+ vector<string> result;
+
+ mutex.lock();
+ result = vector<string>(servers.begin(), servers.end());
+ mutex.unlock();
+
+ return result;
+ }
+
+ private:
+ void handle_receive_from(const boost::system::error_code &error, size_t size)
+ {
+ if (error) {
+ cout << "Server discovery receive error: " << error.message() << "\n";
+ return;
+ }
+
+ if (size > 0) {
+ string msg = string(receive_buffer, size);
+
+ /* handle incoming message */
+ if (collect_servers) {
+ if (msg == DISCOVER_REPLY_MSG) {
+ string address = receive_endpoint.address().to_string();
+
+ mutex.lock();
+
+ /* add address if it's not already in the list */
+ bool found = std::find(servers.begin(), servers.end(), address) != servers.end();
+
+ if (!found)
+ servers.push_back(address);
+
+ mutex.unlock();
+ }
+ }
+ else {
+ /* reply to request */
+ if (msg == DISCOVER_REQUEST_MSG)
+ broadcast_message(DISCOVER_REPLY_MSG);
+ }
+ }
+
+ async_receive();
+ }
+
+ void async_receive()
+ {
+ listen_socket.async_receive_from(boost::asio::buffer(receive_buffer),
+ receive_endpoint,
+ boost::bind(&ServerDiscovery::handle_receive_from,
+ this,
+ boost::asio::placeholders::error,
+ boost::asio::placeholders::bytes_transferred));
+ }
+
+ void broadcast_message(const string &msg)
+ {
+ /* setup broadcast socket */
+ boost::asio::ip::udp::socket socket(io_service);
+
+ socket.open(boost::asio::ip::udp::v4());
+
+ boost::asio::socket_base::broadcast option(true);
+ socket.set_option(option);
+
+ boost::asio::ip::udp::endpoint broadcast_endpoint(
+ boost::asio::ip::address::from_string("255.255.255.255"), DISCOVER_PORT);
+
+ /* broadcast message */
+ socket.send_to(boost::asio::buffer(msg), broadcast_endpoint);
+ }
+
+ /* network service and socket */
+ boost::asio::io_service io_service;
+ boost::asio::ip::udp::endpoint listen_endpoint;
+ boost::asio::ip::udp::socket listen_socket;
+
+ /* threading */
+ boost::thread *thread;
+ boost::asio::io_service::work *work;
+ boost::mutex mutex;
+
+ /* buffer and endpoint for receiving messages */
+ char receive_buffer[256];
+ boost::asio::ip::udp::endpoint receive_endpoint;
+
+ // os, version, devices, status, host name, group name, ip as far as fields go
+ struct ServerInfo {
+ string cycles_version;
+ string os;
+ int device_count;
+ string status;
+ string host_name;
+ string group_name;
+ string host_addr;
+ };
+
+ /* collection of server addresses in list */
+ bool collect_servers;
+ vector<string> servers;
};
CCL_NAMESPACE_END
#endif
-#endif /* __DEVICE_NETWORK_H__ */
+#endif /* __DEVICE_NETWORK_H__ */
diff --git a/intern/cycles/device/device_opencl.cpp b/intern/cycles/device/device_opencl.cpp
index 4cefaa217f1..99a8d2438d6 100644
--- a/intern/cycles/device/device_opencl.cpp
+++ b/intern/cycles/device/device_opencl.cpp
@@ -16,218 +16,211 @@
#ifdef WITH_OPENCL
-#include "device/opencl/opencl.h"
+# include "device/opencl/opencl.h"
-#include "device/device_intern.h"
+# include "device/device_intern.h"
-#include "util/util_foreach.h"
-#include "util/util_logging.h"
-#include "util/util_set.h"
-#include "util/util_string.h"
+# include "util/util_foreach.h"
+# include "util/util_logging.h"
+# include "util/util_set.h"
+# include "util/util_string.h"
CCL_NAMESPACE_BEGIN
-Device *device_opencl_create(DeviceInfo& info, Stats &stats, Profiler &profiler, bool background)
+Device *device_opencl_create(DeviceInfo &info, Stats &stats, Profiler &profiler, bool background)
{
- return opencl_create_split_device(info, stats, profiler, background);
+ return opencl_create_split_device(info, stats, profiler, background);
}
bool device_opencl_init()
{
- static bool initialized = false;
- static bool result = false;
-
- if(initialized)
- return result;
-
- initialized = true;
-
- if(OpenCLInfo::device_type() != 0) {
- int clew_result = clewInit();
- if(clew_result == CLEW_SUCCESS) {
- VLOG(1) << "CLEW initialization succeeded.";
- result = true;
- }
- else {
- VLOG(1) << "CLEW initialization failed: "
- << ((clew_result == CLEW_ERROR_ATEXIT_FAILED)
- ? "Error setting up atexit() handler"
- : "Error opening the library");
- }
- }
- else {
- VLOG(1) << "Skip initializing CLEW, platform is force disabled.";
- result = false;
- }
-
- return result;
+ static bool initialized = false;
+ static bool result = false;
+
+ if (initialized)
+ return result;
+
+ initialized = true;
+
+ if (OpenCLInfo::device_type() != 0) {
+ int clew_result = clewInit();
+ if (clew_result == CLEW_SUCCESS) {
+ VLOG(1) << "CLEW initialization succeeded.";
+ result = true;
+ }
+ else {
+ VLOG(1) << "CLEW initialization failed: "
+ << ((clew_result == CLEW_ERROR_ATEXIT_FAILED) ? "Error setting up atexit() handler" :
+ "Error opening the library");
+ }
+ }
+ else {
+ VLOG(1) << "Skip initializing CLEW, platform is force disabled.";
+ result = false;
+ }
+
+ return result;
}
-
static cl_int device_opencl_get_num_platforms_safe(cl_uint *num_platforms)
{
-#ifdef _WIN32
- __try {
- return clGetPlatformIDs(0, NULL, num_platforms);
- }
- __except(EXCEPTION_EXECUTE_HANDLER) {
- /* Ignore crashes inside the OpenCL driver and hope we can
- * survive even with corrupted OpenCL installs. */
- fprintf(stderr, "Cycles OpenCL: driver crashed, continuing without OpenCL.\n");
- }
-
- *num_platforms = 0;
- return CL_DEVICE_NOT_FOUND;
-#else
- return clGetPlatformIDs(0, NULL, num_platforms);
-#endif
+# ifdef _WIN32
+ __try {
+ return clGetPlatformIDs(0, NULL, num_platforms);
+ }
+ __except (EXCEPTION_EXECUTE_HANDLER) {
+ /* Ignore crashes inside the OpenCL driver and hope we can
+ * survive even with corrupted OpenCL installs. */
+ fprintf(stderr, "Cycles OpenCL: driver crashed, continuing without OpenCL.\n");
+ }
+
+ *num_platforms = 0;
+ return CL_DEVICE_NOT_FOUND;
+# else
+ return clGetPlatformIDs(0, NULL, num_platforms);
+# endif
}
-void device_opencl_info(vector<DeviceInfo>& devices)
+void device_opencl_info(vector<DeviceInfo> &devices)
{
- cl_uint num_platforms = 0;
- device_opencl_get_num_platforms_safe(&num_platforms);
- if(num_platforms == 0) {
- return;
- }
-
- vector<OpenCLPlatformDevice> usable_devices;
- OpenCLInfo::get_usable_devices(&usable_devices);
- /* Devices are numbered consecutively across platforms. */
- int num_devices = 0;
- set<string> unique_ids;
- foreach(OpenCLPlatformDevice& platform_device, usable_devices) {
- /* Compute unique ID for persistent user preferences. */
- const string& platform_name = platform_device.platform_name;
- const string& device_name = platform_device.device_name;
- string hardware_id = platform_device.hardware_id;
- if(hardware_id == "") {
- hardware_id = string_printf("ID_%d", num_devices);
- }
- string id = string("OPENCL_") + platform_name + "_" + device_name + "_" + hardware_id;
-
- /* Hardware ID might not be unique, add device number in that case. */
- if(unique_ids.find(id) != unique_ids.end()) {
- id += string_printf("_ID_%d", num_devices);
- }
- unique_ids.insert(id);
-
- /* Create DeviceInfo. */
- DeviceInfo info;
- info.type = DEVICE_OPENCL;
- info.description = string_remove_trademark(string(device_name));
- info.num = num_devices;
- /* We don't know if it's used for display, but assume it is. */
- info.display_device = true;
- info.use_split_kernel = true;
- info.has_volume_decoupled = false;
- info.id = id;
-
- /* Check OpenCL extensions */
- info.has_half_images = platform_device.device_extensions.find("cl_khr_fp16") != string::npos;
-
- devices.push_back(info);
- num_devices++;
- }
+ cl_uint num_platforms = 0;
+ device_opencl_get_num_platforms_safe(&num_platforms);
+ if (num_platforms == 0) {
+ return;
+ }
+
+ vector<OpenCLPlatformDevice> usable_devices;
+ OpenCLInfo::get_usable_devices(&usable_devices);
+ /* Devices are numbered consecutively across platforms. */
+ int num_devices = 0;
+ set<string> unique_ids;
+ foreach (OpenCLPlatformDevice &platform_device, usable_devices) {
+ /* Compute unique ID for persistent user preferences. */
+ const string &platform_name = platform_device.platform_name;
+ const string &device_name = platform_device.device_name;
+ string hardware_id = platform_device.hardware_id;
+ if (hardware_id == "") {
+ hardware_id = string_printf("ID_%d", num_devices);
+ }
+ string id = string("OPENCL_") + platform_name + "_" + device_name + "_" + hardware_id;
+
+ /* Hardware ID might not be unique, add device number in that case. */
+ if (unique_ids.find(id) != unique_ids.end()) {
+ id += string_printf("_ID_%d", num_devices);
+ }
+ unique_ids.insert(id);
+
+ /* Create DeviceInfo. */
+ DeviceInfo info;
+ info.type = DEVICE_OPENCL;
+ info.description = string_remove_trademark(string(device_name));
+ info.num = num_devices;
+ /* We don't know if it's used for display, but assume it is. */
+ info.display_device = true;
+ info.use_split_kernel = true;
+ info.has_volume_decoupled = false;
+ info.id = id;
+
+ /* Check OpenCL extensions */
+ info.has_half_images = platform_device.device_extensions.find("cl_khr_fp16") != string::npos;
+
+ devices.push_back(info);
+ num_devices++;
+ }
}
string device_opencl_capabilities()
{
- if(OpenCLInfo::device_type() == 0) {
- return "All OpenCL devices are forced to be OFF";
- }
- string result = "";
- string error_msg = ""; /* Only used by opencl_assert(), but in the future
- * it could also be nicely reported to the console.
- */
- cl_uint num_platforms = 0;
- opencl_assert(device_opencl_get_num_platforms_safe(&num_platforms));
- if(num_platforms == 0) {
- return "No OpenCL platforms found\n";
- }
- result += string_printf("Number of platforms: %u\n", num_platforms);
-
- vector<cl_platform_id> platform_ids;
- platform_ids.resize(num_platforms);
- opencl_assert(clGetPlatformIDs(num_platforms, &platform_ids[0], NULL));
-
- typedef char cl_string[1024];
-
-#define APPEND_INFO(func, id, name, what, type) \
- do { \
- type data; \
- memset(&data, 0, sizeof(data)); \
- opencl_assert(func(id, what, sizeof(data), &data, NULL)); \
- result += string_printf("%s: %s\n", name, to_string(data).c_str()); \
- } while(false)
-#define APPEND_STRING_EXTENSION_INFO(func, id, name, what) \
- do { \
- char data[1024] = "\0"; \
- size_t length = 0; \
- if(func(id, what, sizeof(data), &data, &length) == CL_SUCCESS) { \
- if(length != 0 && data[0] != '\0') { \
- result += string_printf("%s: %s\n", name, data); \
- } \
- } \
- } while(false)
-#define APPEND_PLATFORM_INFO(id, name, what, type) \
- APPEND_INFO(clGetPlatformInfo, id, "\tPlatform " name, what, type)
-#define APPEND_DEVICE_INFO(id, name, what, type) \
- APPEND_INFO(clGetDeviceInfo, id, "\t\t\tDevice " name, what, type)
-#define APPEND_DEVICE_STRING_EXTENSION_INFO(id, name, what) \
- APPEND_STRING_EXTENSION_INFO(clGetDeviceInfo, id, "\t\t\tDevice " name, what)
-
- vector<cl_device_id> device_ids;
- for(cl_uint platform = 0; platform < num_platforms; ++platform) {
- cl_platform_id platform_id = platform_ids[platform];
-
- result += string_printf("Platform #%u\n", platform);
-
- APPEND_PLATFORM_INFO(platform_id, "Name", CL_PLATFORM_NAME, cl_string);
- APPEND_PLATFORM_INFO(platform_id, "Vendor", CL_PLATFORM_VENDOR, cl_string);
- APPEND_PLATFORM_INFO(platform_id, "Version", CL_PLATFORM_VERSION, cl_string);
- APPEND_PLATFORM_INFO(platform_id, "Profile", CL_PLATFORM_PROFILE, cl_string);
- APPEND_PLATFORM_INFO(platform_id, "Extensions", CL_PLATFORM_EXTENSIONS, cl_string);
-
- cl_uint num_devices = 0;
- opencl_assert(clGetDeviceIDs(platform_ids[platform],
- CL_DEVICE_TYPE_ALL,
- 0,
- NULL,
- &num_devices));
- result += string_printf("\tNumber of devices: %u\n", num_devices);
-
- device_ids.resize(num_devices);
- opencl_assert(clGetDeviceIDs(platform_ids[platform],
- CL_DEVICE_TYPE_ALL,
- num_devices,
- &device_ids[0],
- NULL));
- for(cl_uint device = 0; device < num_devices; ++device) {
- cl_device_id device_id = device_ids[device];
-
- result += string_printf("\t\tDevice: #%u\n", device);
-
- APPEND_DEVICE_INFO(device_id, "Name", CL_DEVICE_NAME, cl_string);
- APPEND_DEVICE_STRING_EXTENSION_INFO(device_id, "Board Name", CL_DEVICE_BOARD_NAME_AMD);
- APPEND_DEVICE_INFO(device_id, "Vendor", CL_DEVICE_VENDOR, cl_string);
- APPEND_DEVICE_INFO(device_id, "OpenCL C Version", CL_DEVICE_OPENCL_C_VERSION, cl_string);
- APPEND_DEVICE_INFO(device_id, "Profile", CL_DEVICE_PROFILE, cl_string);
- APPEND_DEVICE_INFO(device_id, "Version", CL_DEVICE_VERSION, cl_string);
- APPEND_DEVICE_INFO(device_id, "Extensions", CL_DEVICE_EXTENSIONS, cl_string);
- APPEND_DEVICE_INFO(device_id, "Max clock frequency (MHz)", CL_DEVICE_MAX_CLOCK_FREQUENCY, cl_uint);
- APPEND_DEVICE_INFO(device_id, "Max compute units", CL_DEVICE_MAX_COMPUTE_UNITS, cl_uint);
- APPEND_DEVICE_INFO(device_id, "Max work group size", CL_DEVICE_MAX_WORK_GROUP_SIZE, size_t);
- }
- }
-
-#undef APPEND_STRING_INFO
-#undef APPEND_PLATFORM_STRING_INFO
-#undef APPEND_DEVICE_STRING_INFO
-
- return result;
+ if (OpenCLInfo::device_type() == 0) {
+ return "All OpenCL devices are forced to be OFF";
+ }
+ string result = "";
+ string error_msg = ""; /* Only used by opencl_assert(), but in the future
+ * it could also be nicely reported to the console.
+ */
+ cl_uint num_platforms = 0;
+ opencl_assert(device_opencl_get_num_platforms_safe(&num_platforms));
+ if (num_platforms == 0) {
+ return "No OpenCL platforms found\n";
+ }
+ result += string_printf("Number of platforms: %u\n", num_platforms);
+
+ vector<cl_platform_id> platform_ids;
+ platform_ids.resize(num_platforms);
+ opencl_assert(clGetPlatformIDs(num_platforms, &platform_ids[0], NULL));
+
+ typedef char cl_string[1024];
+
+# define APPEND_INFO(func, id, name, what, type) \
+ do { \
+ type data; \
+ memset(&data, 0, sizeof(data)); \
+ opencl_assert(func(id, what, sizeof(data), &data, NULL)); \
+ result += string_printf("%s: %s\n", name, to_string(data).c_str()); \
+ } while (false)
+# define APPEND_STRING_EXTENSION_INFO(func, id, name, what) \
+ do { \
+ char data[1024] = "\0"; \
+ size_t length = 0; \
+ if (func(id, what, sizeof(data), &data, &length) == CL_SUCCESS) { \
+ if (length != 0 && data[0] != '\0') { \
+ result += string_printf("%s: %s\n", name, data); \
+ } \
+ } \
+ } while (false)
+# define APPEND_PLATFORM_INFO(id, name, what, type) \
+ APPEND_INFO(clGetPlatformInfo, id, "\tPlatform " name, what, type)
+# define APPEND_DEVICE_INFO(id, name, what, type) \
+ APPEND_INFO(clGetDeviceInfo, id, "\t\t\tDevice " name, what, type)
+# define APPEND_DEVICE_STRING_EXTENSION_INFO(id, name, what) \
+ APPEND_STRING_EXTENSION_INFO(clGetDeviceInfo, id, "\t\t\tDevice " name, what)
+
+ vector<cl_device_id> device_ids;
+ for (cl_uint platform = 0; platform < num_platforms; ++platform) {
+ cl_platform_id platform_id = platform_ids[platform];
+
+ result += string_printf("Platform #%u\n", platform);
+
+ APPEND_PLATFORM_INFO(platform_id, "Name", CL_PLATFORM_NAME, cl_string);
+ APPEND_PLATFORM_INFO(platform_id, "Vendor", CL_PLATFORM_VENDOR, cl_string);
+ APPEND_PLATFORM_INFO(platform_id, "Version", CL_PLATFORM_VERSION, cl_string);
+ APPEND_PLATFORM_INFO(platform_id, "Profile", CL_PLATFORM_PROFILE, cl_string);
+ APPEND_PLATFORM_INFO(platform_id, "Extensions", CL_PLATFORM_EXTENSIONS, cl_string);
+
+ cl_uint num_devices = 0;
+ opencl_assert(
+ clGetDeviceIDs(platform_ids[platform], CL_DEVICE_TYPE_ALL, 0, NULL, &num_devices));
+ result += string_printf("\tNumber of devices: %u\n", num_devices);
+
+ device_ids.resize(num_devices);
+ opencl_assert(clGetDeviceIDs(
+ platform_ids[platform], CL_DEVICE_TYPE_ALL, num_devices, &device_ids[0], NULL));
+ for (cl_uint device = 0; device < num_devices; ++device) {
+ cl_device_id device_id = device_ids[device];
+
+ result += string_printf("\t\tDevice: #%u\n", device);
+
+ APPEND_DEVICE_INFO(device_id, "Name", CL_DEVICE_NAME, cl_string);
+ APPEND_DEVICE_STRING_EXTENSION_INFO(device_id, "Board Name", CL_DEVICE_BOARD_NAME_AMD);
+ APPEND_DEVICE_INFO(device_id, "Vendor", CL_DEVICE_VENDOR, cl_string);
+ APPEND_DEVICE_INFO(device_id, "OpenCL C Version", CL_DEVICE_OPENCL_C_VERSION, cl_string);
+ APPEND_DEVICE_INFO(device_id, "Profile", CL_DEVICE_PROFILE, cl_string);
+ APPEND_DEVICE_INFO(device_id, "Version", CL_DEVICE_VERSION, cl_string);
+ APPEND_DEVICE_INFO(device_id, "Extensions", CL_DEVICE_EXTENSIONS, cl_string);
+ APPEND_DEVICE_INFO(
+ device_id, "Max clock frequency (MHz)", CL_DEVICE_MAX_CLOCK_FREQUENCY, cl_uint);
+ APPEND_DEVICE_INFO(device_id, "Max compute units", CL_DEVICE_MAX_COMPUTE_UNITS, cl_uint);
+ APPEND_DEVICE_INFO(device_id, "Max work group size", CL_DEVICE_MAX_WORK_GROUP_SIZE, size_t);
+ }
+ }
+
+# undef APPEND_STRING_INFO
+# undef APPEND_PLATFORM_STRING_INFO
+# undef APPEND_DEVICE_STRING_INFO
+
+ return result;
}
CCL_NAMESPACE_END
-#endif /* WITH_OPENCL */
+#endif /* WITH_OPENCL */
diff --git a/intern/cycles/device/device_split_kernel.cpp b/intern/cycles/device/device_split_kernel.cpp
index ee566e57918..42e597a34d7 100644
--- a/intern/cycles/device/device_split_kernel.cpp
+++ b/intern/cycles/device/device_split_kernel.cpp
@@ -27,299 +27,304 @@ CCL_NAMESPACE_BEGIN
static const double alpha = 0.1; /* alpha for rolling average */
DeviceSplitKernel::DeviceSplitKernel(Device *device)
-: device(device),
- split_data(device, "split_data"),
- ray_state(device, "ray_state", MEM_READ_WRITE),
- queue_index(device, "queue_index"),
- use_queues_flag(device, "use_queues_flag"),
- work_pool_wgs(device, "work_pool_wgs"),
- kernel_data_initialized(false)
+ : device(device),
+ split_data(device, "split_data"),
+ ray_state(device, "ray_state", MEM_READ_WRITE),
+ queue_index(device, "queue_index"),
+ use_queues_flag(device, "use_queues_flag"),
+ work_pool_wgs(device, "work_pool_wgs"),
+ kernel_data_initialized(false)
{
- avg_time_per_sample = 0.0;
-
- kernel_path_init = NULL;
- kernel_scene_intersect = NULL;
- kernel_lamp_emission = NULL;
- 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;
- kernel_direct_lighting = NULL;
- kernel_shadow_blocked_ao = NULL;
- kernel_shadow_blocked_dl = NULL;
- kernel_enqueue_inactive = NULL;
- kernel_next_iteration_setup = NULL;
- kernel_indirect_subsurface = NULL;
- kernel_buffer_update = NULL;
+ avg_time_per_sample = 0.0;
+
+ kernel_path_init = NULL;
+ kernel_scene_intersect = NULL;
+ kernel_lamp_emission = NULL;
+ 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;
+ kernel_direct_lighting = NULL;
+ kernel_shadow_blocked_ao = NULL;
+ kernel_shadow_blocked_dl = NULL;
+ kernel_enqueue_inactive = NULL;
+ kernel_next_iteration_setup = NULL;
+ kernel_indirect_subsurface = NULL;
+ kernel_buffer_update = NULL;
}
DeviceSplitKernel::~DeviceSplitKernel()
{
- split_data.free();
- ray_state.free();
- use_queues_flag.free();
- queue_index.free();
- work_pool_wgs.free();
-
- delete kernel_path_init;
- delete kernel_scene_intersect;
- delete kernel_lamp_emission;
- 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;
- delete kernel_direct_lighting;
- delete kernel_shadow_blocked_ao;
- delete kernel_shadow_blocked_dl;
- delete kernel_enqueue_inactive;
- delete kernel_next_iteration_setup;
- delete kernel_indirect_subsurface;
- delete kernel_buffer_update;
+ split_data.free();
+ ray_state.free();
+ use_queues_flag.free();
+ queue_index.free();
+ work_pool_wgs.free();
+
+ delete kernel_path_init;
+ delete kernel_scene_intersect;
+ delete kernel_lamp_emission;
+ 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;
+ delete kernel_direct_lighting;
+ delete kernel_shadow_blocked_ao;
+ delete kernel_shadow_blocked_dl;
+ delete kernel_enqueue_inactive;
+ delete kernel_next_iteration_setup;
+ delete kernel_indirect_subsurface;
+ delete kernel_buffer_update;
}
-bool DeviceSplitKernel::load_kernels(const DeviceRequestedFeatures& requested_features)
+bool DeviceSplitKernel::load_kernels(const DeviceRequestedFeatures &requested_features)
{
#define LOAD_KERNEL(name) \
- kernel_##name = get_split_kernel_function(#name, requested_features); \
- if(!kernel_##name) { \
- device->set_error(string("Split kernel error: failed to load kernel_") + #name); \
- return false; \
- }
-
- LOAD_KERNEL(path_init);
- LOAD_KERNEL(scene_intersect);
- LOAD_KERNEL(lamp_emission);
- if (requested_features.use_volume) {
- 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);
- LOAD_KERNEL(direct_lighting);
- LOAD_KERNEL(shadow_blocked_ao);
- LOAD_KERNEL(shadow_blocked_dl);
- LOAD_KERNEL(enqueue_inactive);
- LOAD_KERNEL(next_iteration_setup);
- LOAD_KERNEL(indirect_subsurface);
- LOAD_KERNEL(buffer_update);
+ kernel_##name = get_split_kernel_function(#name, requested_features); \
+ if (!kernel_##name) { \
+ device->set_error(string("Split kernel error: failed to load kernel_") + #name); \
+ return false; \
+ }
+
+ LOAD_KERNEL(path_init);
+ LOAD_KERNEL(scene_intersect);
+ LOAD_KERNEL(lamp_emission);
+ if (requested_features.use_volume) {
+ 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);
+ LOAD_KERNEL(direct_lighting);
+ LOAD_KERNEL(shadow_blocked_ao);
+ LOAD_KERNEL(shadow_blocked_dl);
+ LOAD_KERNEL(enqueue_inactive);
+ LOAD_KERNEL(next_iteration_setup);
+ LOAD_KERNEL(indirect_subsurface);
+ LOAD_KERNEL(buffer_update);
#undef LOAD_KERNEL
- /* Re-initialiaze kernel-dependent data when kernels change. */
- kernel_data_initialized = false;
+ /* Re-initialiaze kernel-dependent data when kernels change. */
+ kernel_data_initialized = false;
- return true;
+ return true;
}
-size_t DeviceSplitKernel::max_elements_for_max_buffer_size(device_memory& kg, device_memory& data, uint64_t max_buffer_size)
+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;
+ 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;
}
bool DeviceSplitKernel::path_trace(DeviceTask *task,
- RenderTile& tile,
- device_memory& kgbuffer,
- device_memory& kernel_data)
+ RenderTile &tile,
+ device_memory &kgbuffer,
+ device_memory &kernel_data)
{
- if(device->have_error()) {
- return false;
- }
+ if (device->have_error()) {
+ return false;
+ }
- /* Allocate all required global memory once. */
- if(!kernel_data_initialized) {
- kernel_data_initialized = true;
+ /* Allocate all required global memory once. */
+ if (!kernel_data_initialized) {
+ kernel_data_initialized = true;
- /* Set local size */
- int2 lsize = split_kernel_local_size();
- local_size[0] = lsize[0];
- local_size[1] = lsize[1];
+ /* Set local size */
+ int2 lsize = split_kernel_local_size();
+ local_size[0] = lsize[0];
+ local_size[1] = lsize[1];
- /* Set global size */
- int2 gsize = split_kernel_global_size(kgbuffer, kernel_data, task);
+ /* Set global size */
+ int2 gsize = split_kernel_global_size(kgbuffer, kernel_data, task);
- /* Make sure that set work size is a multiple of local
- * work size dimensions.
- */
- global_size[0] = round_up(gsize[0], local_size[0]);
- global_size[1] = round_up(gsize[1], local_size[1]);
+ /* Make sure that set work size is a multiple of local
+ * work size dimensions.
+ */
+ global_size[0] = round_up(gsize[0], local_size[0]);
+ global_size[1] = round_up(gsize[1], local_size[1]);
- int num_global_elements = global_size[0] * global_size[1];
- assert(num_global_elements % WORK_POOL_SIZE == 0);
+ int num_global_elements = global_size[0] * global_size[1];
+ assert(num_global_elements % WORK_POOL_SIZE == 0);
- /* Calculate max groups */
+ /* Calculate max groups */
- /* Denotes the maximum work groups possible w.r.t. current requested tile size. */
- unsigned int work_pool_size = (device->info.type == DEVICE_CPU) ? WORK_POOL_SIZE_CPU : WORK_POOL_SIZE_GPU;
- unsigned int max_work_groups = num_global_elements / work_pool_size + 1;
+ /* Denotes the maximum work groups possible w.r.t. current requested tile size. */
+ unsigned int work_pool_size = (device->info.type == DEVICE_CPU) ? WORK_POOL_SIZE_CPU :
+ WORK_POOL_SIZE_GPU;
+ unsigned int max_work_groups = num_global_elements / work_pool_size + 1;
- /* Allocate work_pool_wgs memory. */
- work_pool_wgs.alloc_to_device(max_work_groups);
- queue_index.alloc_to_device(NUM_QUEUES);
- use_queues_flag.alloc_to_device(1);
- split_data.alloc_to_device(state_buffer_size(kgbuffer, kernel_data, num_global_elements));
- ray_state.alloc(num_global_elements);
- }
+ /* Allocate work_pool_wgs memory. */
+ work_pool_wgs.alloc_to_device(max_work_groups);
+ queue_index.alloc_to_device(NUM_QUEUES);
+ use_queues_flag.alloc_to_device(1);
+ split_data.alloc_to_device(state_buffer_size(kgbuffer, kernel_data, num_global_elements));
+ ray_state.alloc(num_global_elements);
+ }
- /* Number of elements in the global state buffer */
- int num_global_elements = global_size[0] * global_size[1];
+ /* Number of elements in the global state buffer */
+ int num_global_elements = global_size[0] * global_size[1];
#define ENQUEUE_SPLIT_KERNEL(name, global_size, local_size) \
- if(device->have_error()) { \
- return false; \
- } \
- if(!kernel_##name->enqueue(KernelDimensions(global_size, local_size), kgbuffer, kernel_data)) { \
- return false; \
- }
-
- tile.sample = tile.start_sample;
-
- /* for exponential increase between tile updates */
- int time_multiplier = 1;
-
- while(tile.sample < tile.start_sample + tile.num_samples) {
- /* to keep track of how long it takes to run a number of samples */
- double start_time = time_dt();
-
- /* initial guess to start rolling average */
- const int initial_num_samples = 1;
- /* approx number of samples per second */
- int samples_per_second = (avg_time_per_sample > 0.0) ?
- int(double(time_multiplier) / avg_time_per_sample) + 1 : initial_num_samples;
-
- RenderTile subtile = tile;
- subtile.start_sample = tile.sample;
- subtile.num_samples = min(samples_per_second, tile.start_sample + tile.num_samples - tile.sample);
-
- if(device->have_error()) {
- return false;
- }
-
- /* reset state memory here as global size for data_init
- * kernel might not be large enough to do in kernel
- */
- work_pool_wgs.zero_to_device();
- split_data.zero_to_device();
- ray_state.zero_to_device();
-
- if(!enqueue_split_kernel_data_init(KernelDimensions(global_size, local_size),
- subtile,
- num_global_elements,
- kgbuffer,
- kernel_data,
- split_data,
- ray_state,
- queue_index,
- use_queues_flag,
- work_pool_wgs))
- {
- return false;
- }
-
- ENQUEUE_SPLIT_KERNEL(path_init, global_size, local_size);
-
- bool activeRaysAvailable = true;
- double cancel_time = DBL_MAX;
-
- while(activeRaysAvailable) {
- /* Do path-iteration in host [Enqueue Path-iteration kernels. */
- for(int PathIter = 0; PathIter < 16; PathIter++) {
- ENQUEUE_SPLIT_KERNEL(scene_intersect, global_size, local_size);
- ENQUEUE_SPLIT_KERNEL(lamp_emission, global_size, local_size);
- if (kernel_do_volume) {
- 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);
- ENQUEUE_SPLIT_KERNEL(enqueue_inactive, global_size, local_size);
- ENQUEUE_SPLIT_KERNEL(next_iteration_setup, global_size, local_size);
- ENQUEUE_SPLIT_KERNEL(indirect_subsurface, global_size, local_size);
- ENQUEUE_SPLIT_KERNEL(queue_enqueue, global_size, local_size);
- ENQUEUE_SPLIT_KERNEL(buffer_update, global_size, local_size);
-
- if(task->get_cancel() && cancel_time == DBL_MAX) {
- /* Wait up to twice as many seconds for current samples to finish
- * to avoid artifacts in render result from ending too soon.
- */
- cancel_time = time_dt() + 2.0 * time_multiplier;
- }
-
- if(time_dt() > cancel_time) {
- return true;
- }
- }
-
- /* Decide if we should exit path-iteration in host. */
- ray_state.copy_from_device(0, global_size[0] * global_size[1], 1);
-
- activeRaysAvailable = false;
-
- for(int rayStateIter = 0; rayStateIter < global_size[0] * global_size[1]; ++rayStateIter) {
- if(!IS_STATE(ray_state.data(), rayStateIter, RAY_INACTIVE)) {
- if(IS_STATE(ray_state.data(), rayStateIter, RAY_INVALID)) {
- /* Something went wrong, abort to avoid looping endlessly. */
- device->set_error("Split kernel error: invalid ray state");
- return false;
- }
-
- /* Not all rays are RAY_INACTIVE. */
- activeRaysAvailable = true;
- break;
- }
- }
-
- if(time_dt() > cancel_time) {
- return true;
- }
- }
-
- double time_per_sample = ((time_dt()-start_time) / subtile.num_samples);
-
- if(avg_time_per_sample == 0.0) {
- /* start rolling average */
- avg_time_per_sample = time_per_sample;
- }
- else {
- avg_time_per_sample = alpha*time_per_sample + (1.0-alpha)*avg_time_per_sample;
- }
+ if (device->have_error()) { \
+ return false; \
+ } \
+ if (!kernel_##name->enqueue( \
+ KernelDimensions(global_size, local_size), kgbuffer, kernel_data)) { \
+ return false; \
+ }
+
+ tile.sample = tile.start_sample;
+
+ /* for exponential increase between tile updates */
+ int time_multiplier = 1;
+
+ while (tile.sample < tile.start_sample + tile.num_samples) {
+ /* to keep track of how long it takes to run a number of samples */
+ double start_time = time_dt();
+
+ /* initial guess to start rolling average */
+ const int initial_num_samples = 1;
+ /* approx number of samples per second */
+ int samples_per_second = (avg_time_per_sample > 0.0) ?
+ int(double(time_multiplier) / avg_time_per_sample) + 1 :
+ initial_num_samples;
+
+ RenderTile subtile = tile;
+ subtile.start_sample = tile.sample;
+ subtile.num_samples = min(samples_per_second,
+ tile.start_sample + tile.num_samples - tile.sample);
+
+ if (device->have_error()) {
+ return false;
+ }
+
+ /* reset state memory here as global size for data_init
+ * kernel might not be large enough to do in kernel
+ */
+ work_pool_wgs.zero_to_device();
+ split_data.zero_to_device();
+ ray_state.zero_to_device();
+
+ if (!enqueue_split_kernel_data_init(KernelDimensions(global_size, local_size),
+ subtile,
+ num_global_elements,
+ kgbuffer,
+ kernel_data,
+ split_data,
+ ray_state,
+ queue_index,
+ use_queues_flag,
+ work_pool_wgs)) {
+ return false;
+ }
+
+ ENQUEUE_SPLIT_KERNEL(path_init, global_size, local_size);
+
+ bool activeRaysAvailable = true;
+ double cancel_time = DBL_MAX;
+
+ while (activeRaysAvailable) {
+ /* Do path-iteration in host [Enqueue Path-iteration kernels. */
+ for (int PathIter = 0; PathIter < 16; PathIter++) {
+ ENQUEUE_SPLIT_KERNEL(scene_intersect, global_size, local_size);
+ ENQUEUE_SPLIT_KERNEL(lamp_emission, global_size, local_size);
+ if (kernel_do_volume) {
+ 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);
+ ENQUEUE_SPLIT_KERNEL(enqueue_inactive, global_size, local_size);
+ ENQUEUE_SPLIT_KERNEL(next_iteration_setup, global_size, local_size);
+ ENQUEUE_SPLIT_KERNEL(indirect_subsurface, global_size, local_size);
+ ENQUEUE_SPLIT_KERNEL(queue_enqueue, global_size, local_size);
+ ENQUEUE_SPLIT_KERNEL(buffer_update, global_size, local_size);
+
+ if (task->get_cancel() && cancel_time == DBL_MAX) {
+ /* Wait up to twice as many seconds for current samples to finish
+ * to avoid artifacts in render result from ending too soon.
+ */
+ cancel_time = time_dt() + 2.0 * time_multiplier;
+ }
+
+ if (time_dt() > cancel_time) {
+ return true;
+ }
+ }
+
+ /* Decide if we should exit path-iteration in host. */
+ ray_state.copy_from_device(0, global_size[0] * global_size[1], 1);
+
+ activeRaysAvailable = false;
+
+ for (int rayStateIter = 0; rayStateIter < global_size[0] * global_size[1]; ++rayStateIter) {
+ if (!IS_STATE(ray_state.data(), rayStateIter, RAY_INACTIVE)) {
+ if (IS_STATE(ray_state.data(), rayStateIter, RAY_INVALID)) {
+ /* Something went wrong, abort to avoid looping endlessly. */
+ device->set_error("Split kernel error: invalid ray state");
+ return false;
+ }
+
+ /* Not all rays are RAY_INACTIVE. */
+ activeRaysAvailable = true;
+ break;
+ }
+ }
+
+ if (time_dt() > cancel_time) {
+ return true;
+ }
+ }
+
+ double time_per_sample = ((time_dt() - start_time) / subtile.num_samples);
+
+ if (avg_time_per_sample == 0.0) {
+ /* start rolling average */
+ avg_time_per_sample = time_per_sample;
+ }
+ else {
+ avg_time_per_sample = alpha * time_per_sample + (1.0 - alpha) * avg_time_per_sample;
+ }
#undef ENQUEUE_SPLIT_KERNEL
- tile.sample += subtile.num_samples;
- task->update_progress(&tile, tile.w*tile.h*subtile.num_samples);
+ tile.sample += subtile.num_samples;
+ task->update_progress(&tile, tile.w * tile.h * subtile.num_samples);
- time_multiplier = min(time_multiplier << 1, 10);
+ time_multiplier = min(time_multiplier << 1, 10);
- if(task->get_cancel()) {
- return true;
- }
- }
+ if (task->get_cancel()) {
+ return true;
+ }
+ }
- return true;
+ return true;
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/device/device_split_kernel.h b/intern/cycles/device/device_split_kernel.h
index 622733b843f..c9fb2ac844f 100644
--- a/intern/cycles/device/device_split_kernel.h
+++ b/intern/cycles/device/device_split_kernel.h
@@ -27,106 +27,115 @@ CCL_NAMESPACE_BEGIN
* Since some bytes may be needed for aligning chunks of memory;
* This is the amount of memory that we dedicate for that purpose.
*/
-#define DATA_ALLOCATION_MEM_FACTOR 5000000 //5MB
+#define DATA_ALLOCATION_MEM_FACTOR 5000000 //5MB
/* Types used for split kernel */
class KernelDimensions {
-public:
- size_t global_size[2];
- size_t local_size[2];
-
- KernelDimensions(size_t global_size_[2], size_t local_size_[2])
- {
- memcpy(global_size, global_size_, sizeof(global_size));
- memcpy(local_size, local_size_, sizeof(local_size));
- }
+ public:
+ size_t global_size[2];
+ size_t local_size[2];
+
+ KernelDimensions(size_t global_size_[2], size_t local_size_[2])
+ {
+ memcpy(global_size, global_size_, sizeof(global_size));
+ memcpy(local_size, local_size_, sizeof(local_size));
+ }
};
class SplitKernelFunction {
-public:
- virtual ~SplitKernelFunction() {}
+ public:
+ virtual ~SplitKernelFunction()
+ {
+ }
- /* enqueue the kernel, returns false if there is an error */
- virtual bool enqueue(const KernelDimensions& dim, device_memory& kg, device_memory& data) = 0;
+ /* enqueue the kernel, returns false if there is an error */
+ virtual bool enqueue(const KernelDimensions &dim, device_memory &kg, device_memory &data) = 0;
};
class DeviceSplitKernel {
-private:
- Device *device;
-
- SplitKernelFunction *kernel_path_init;
- SplitKernelFunction *kernel_scene_intersect;
- SplitKernelFunction *kernel_lamp_emission;
- 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;
- SplitKernelFunction *kernel_direct_lighting;
- SplitKernelFunction *kernel_shadow_blocked_ao;
- SplitKernelFunction *kernel_shadow_blocked_dl;
- SplitKernelFunction *kernel_enqueue_inactive;
- SplitKernelFunction *kernel_next_iteration_setup;
- SplitKernelFunction *kernel_indirect_subsurface;
- SplitKernelFunction *kernel_buffer_update;
-
- /* Global memory variables [porting]; These memory is used for
- * co-operation between different kernels; Data written by one
- * kernel will be available to another kernel via this global
- * memory.
- */
- device_only_memory<uchar> split_data;
- device_vector<uchar> ray_state;
- device_only_memory<int> queue_index; /* Array of size num_queues that tracks the size of each queue. */
-
- /* Flag to make sceneintersect and lampemission kernel use queues. */
- device_only_memory<char> use_queues_flag;
-
- /* Approximate time it takes to complete one sample */
- double avg_time_per_sample;
-
- /* Work pool with respect to each work group. */
- device_only_memory<unsigned int> work_pool_wgs;
-
- /* Cached kernel-dependent data, initialized once. */
- bool kernel_data_initialized;
- size_t local_size[2];
- size_t global_size[2];
-
-public:
- explicit DeviceSplitKernel(Device* device);
- virtual ~DeviceSplitKernel();
-
- bool load_kernels(const DeviceRequestedFeatures& requested_features);
- bool path_trace(DeviceTask *task,
- RenderTile& rtile,
- device_memory& kgbuffer,
- device_memory& kernel_data);
-
- virtual uint64_t state_buffer_size(device_memory& kg, device_memory& data, size_t num_threads) = 0;
- size_t max_elements_for_max_buffer_size(device_memory& kg, device_memory& data, uint64_t max_buffer_size);
-
- virtual bool enqueue_split_kernel_data_init(const KernelDimensions& dim,
- RenderTile& rtile,
- int num_global_elements,
- device_memory& kernel_globals,
- device_memory& kernel_data_,
- device_memory& split_data,
- device_memory& ray_state,
- device_memory& queue_index,
- device_memory& use_queues_flag,
- device_memory& work_pool_wgs) = 0;
-
- virtual SplitKernelFunction* get_split_kernel_function(const string& kernel_name,
- const DeviceRequestedFeatures&) = 0;
- virtual int2 split_kernel_local_size() = 0;
- virtual int2 split_kernel_global_size(device_memory& kg, device_memory& data, DeviceTask *task) = 0;
+ private:
+ Device *device;
+
+ SplitKernelFunction *kernel_path_init;
+ SplitKernelFunction *kernel_scene_intersect;
+ SplitKernelFunction *kernel_lamp_emission;
+ 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;
+ SplitKernelFunction *kernel_direct_lighting;
+ SplitKernelFunction *kernel_shadow_blocked_ao;
+ SplitKernelFunction *kernel_shadow_blocked_dl;
+ SplitKernelFunction *kernel_enqueue_inactive;
+ SplitKernelFunction *kernel_next_iteration_setup;
+ SplitKernelFunction *kernel_indirect_subsurface;
+ SplitKernelFunction *kernel_buffer_update;
+
+ /* Global memory variables [porting]; These memory is used for
+ * co-operation between different kernels; Data written by one
+ * kernel will be available to another kernel via this global
+ * memory.
+ */
+ device_only_memory<uchar> split_data;
+ device_vector<uchar> ray_state;
+ device_only_memory<int>
+ queue_index; /* Array of size num_queues that tracks the size of each queue. */
+
+ /* Flag to make sceneintersect and lampemission kernel use queues. */
+ device_only_memory<char> use_queues_flag;
+
+ /* Approximate time it takes to complete one sample */
+ double avg_time_per_sample;
+
+ /* Work pool with respect to each work group. */
+ device_only_memory<unsigned int> work_pool_wgs;
+
+ /* Cached kernel-dependent data, initialized once. */
+ bool kernel_data_initialized;
+ size_t local_size[2];
+ size_t global_size[2];
+
+ public:
+ explicit DeviceSplitKernel(Device *device);
+ virtual ~DeviceSplitKernel();
+
+ bool load_kernels(const DeviceRequestedFeatures &requested_features);
+ bool path_trace(DeviceTask *task,
+ RenderTile &rtile,
+ device_memory &kgbuffer,
+ device_memory &kernel_data);
+
+ virtual uint64_t state_buffer_size(device_memory &kg,
+ device_memory &data,
+ size_t num_threads) = 0;
+ size_t max_elements_for_max_buffer_size(device_memory &kg,
+ device_memory &data,
+ uint64_t max_buffer_size);
+
+ virtual bool enqueue_split_kernel_data_init(const KernelDimensions &dim,
+ RenderTile &rtile,
+ int num_global_elements,
+ device_memory &kernel_globals,
+ device_memory &kernel_data_,
+ device_memory &split_data,
+ device_memory &ray_state,
+ device_memory &queue_index,
+ device_memory &use_queues_flag,
+ device_memory &work_pool_wgs) = 0;
+
+ virtual SplitKernelFunction *get_split_kernel_function(const string &kernel_name,
+ const DeviceRequestedFeatures &) = 0;
+ virtual int2 split_kernel_local_size() = 0;
+ virtual int2 split_kernel_global_size(device_memory &kg,
+ device_memory &data,
+ DeviceTask *task) = 0;
};
CCL_NAMESPACE_END
-#endif /* __DEVICE_SPLIT_KERNEL_H__ */
+#endif /* __DEVICE_SPLIT_KERNEL_H__ */
diff --git a/intern/cycles/device/device_task.cpp b/intern/cycles/device/device_task.cpp
index 8310863886c..376ad06a734 100644
--- a/intern/cycles/device/device_task.cpp
+++ b/intern/cycles/device/device_task.cpp
@@ -29,100 +29,111 @@ CCL_NAMESPACE_BEGIN
/* Device Task */
DeviceTask::DeviceTask(Type type_)
-: type(type_), x(0), y(0), w(0), h(0), rgba_byte(0), rgba_half(0), buffer(0),
- sample(0), num_samples(1),
- shader_input(0), shader_output(0),
- shader_eval_type(0), shader_filter(0), shader_x(0), shader_w(0)
+ : type(type_),
+ x(0),
+ y(0),
+ w(0),
+ h(0),
+ rgba_byte(0),
+ rgba_half(0),
+ buffer(0),
+ sample(0),
+ num_samples(1),
+ shader_input(0),
+ shader_output(0),
+ shader_eval_type(0),
+ shader_filter(0),
+ shader_x(0),
+ shader_w(0)
{
- last_update_time = time_dt();
+ last_update_time = time_dt();
}
int DeviceTask::get_subtask_count(int num, int max_size)
{
- if(max_size != 0) {
- int max_size_num;
-
- if(type == SHADER) {
- max_size_num = (shader_w + max_size - 1)/max_size;
- }
- else {
- max_size = max(1, max_size/w);
- max_size_num = (h + max_size - 1)/max_size;
- }
-
- num = max(max_size_num, num);
- }
-
- if(type == SHADER) {
- num = min(shader_w, num);
- }
- else if(type == RENDER) {
- }
- else {
- num = min(h, num);
- }
-
- return num;
+ if (max_size != 0) {
+ int max_size_num;
+
+ if (type == SHADER) {
+ max_size_num = (shader_w + max_size - 1) / max_size;
+ }
+ else {
+ max_size = max(1, max_size / w);
+ max_size_num = (h + max_size - 1) / max_size;
+ }
+
+ num = max(max_size_num, num);
+ }
+
+ if (type == SHADER) {
+ num = min(shader_w, num);
+ }
+ else if (type == RENDER) {
+ }
+ else {
+ num = min(h, num);
+ }
+
+ return num;
}
-void DeviceTask::split(list<DeviceTask>& tasks, int num, int max_size)
+void DeviceTask::split(list<DeviceTask> &tasks, int num, int max_size)
{
- num = get_subtask_count(num, max_size);
-
- if(type == SHADER) {
- for(int i = 0; i < num; i++) {
- int tx = shader_x + (shader_w/num)*i;
- int tw = (i == num-1)? shader_w - i*(shader_w/num): shader_w/num;
-
- DeviceTask task = *this;
-
- task.shader_x = tx;
- task.shader_w = tw;
-
- tasks.push_back(task);
- }
- }
- else if(type == RENDER) {
- for(int i = 0; i < num; i++)
- tasks.push_back(*this);
- }
- else {
- for(int i = 0; i < num; i++) {
- int ty = y + (h/num)*i;
- int th = (i == num-1)? h - i*(h/num): h/num;
-
- DeviceTask task = *this;
-
- task.y = ty;
- task.h = th;
-
- tasks.push_back(task);
- }
- }
+ num = get_subtask_count(num, max_size);
+
+ if (type == SHADER) {
+ for (int i = 0; i < num; i++) {
+ int tx = shader_x + (shader_w / num) * i;
+ int tw = (i == num - 1) ? shader_w - i * (shader_w / num) : shader_w / num;
+
+ DeviceTask task = *this;
+
+ task.shader_x = tx;
+ task.shader_w = tw;
+
+ tasks.push_back(task);
+ }
+ }
+ else if (type == RENDER) {
+ for (int i = 0; i < num; i++)
+ tasks.push_back(*this);
+ }
+ else {
+ for (int i = 0; i < num; i++) {
+ int ty = y + (h / num) * i;
+ int th = (i == num - 1) ? h - i * (h / num) : h / num;
+
+ DeviceTask task = *this;
+
+ task.y = ty;
+ task.h = th;
+
+ tasks.push_back(task);
+ }
+ }
}
void DeviceTask::update_progress(RenderTile *rtile, int pixel_samples)
{
- if((type != RENDER) &&
- (type != SHADER))
- return;
-
- if(update_progress_sample) {
- if(pixel_samples == -1) {
- pixel_samples = shader_w;
- }
- update_progress_sample(pixel_samples, rtile? rtile->sample : 0);
- }
-
- if(update_tile_sample) {
- double current_time = time_dt();
-
- if(current_time - last_update_time >= 1.0) {
- update_tile_sample(*rtile);
-
- last_update_time = current_time;
- }
- }
+ if ((type != RENDER) && (type != SHADER))
+ return;
+
+ if (update_progress_sample) {
+ if (pixel_samples == -1) {
+ pixel_samples = shader_w;
+ }
+ update_progress_sample(pixel_samples, rtile ? rtile->sample : 0);
+ }
+
+ if (update_tile_sample) {
+ double current_time = time_dt();
+
+ if (current_time - last_update_time >= 1.0) {
+ update_tile_sample(*rtile);
+
+ last_update_time = current_time;
+ }
+ }
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/device/device_task.h b/intern/cycles/device/device_task.h
index f1fd4246868..5cc2e5e25db 100644
--- a/intern/cycles/device/device_task.h
+++ b/intern/cycles/device/device_task.h
@@ -33,87 +33,88 @@ class RenderTile;
class Tile;
class DenoiseParams {
-public:
- /* Pixel radius for neighbouring pixels to take into account. */
- int radius;
- /* Controls neighbor pixel weighting for the denoising filter. */
- float strength;
- /* Preserve more or less detail based on feature passes. */
- float feature_strength;
- /* When removing pixels that don't carry information, use a relative threshold instead of an absolute one. */
- bool relative_pca;
- /* How many frames before and after the current center frame are included. */
- int neighbor_frames;
- /* Clamp the input to the range of +-1e8. Should be enough for any legitimate data. */
- bool clamp_input;
-
- DenoiseParams()
- {
- radius = 8;
- strength = 0.5f;
- feature_strength = 0.5f;
- relative_pca = false;
- neighbor_frames = 2;
- clamp_input = true;
- }
+ public:
+ /* Pixel radius for neighbouring pixels to take into account. */
+ int radius;
+ /* Controls neighbor pixel weighting for the denoising filter. */
+ float strength;
+ /* Preserve more or less detail based on feature passes. */
+ float feature_strength;
+ /* When removing pixels that don't carry information, use a relative threshold instead of an absolute one. */
+ bool relative_pca;
+ /* How many frames before and after the current center frame are included. */
+ int neighbor_frames;
+ /* Clamp the input to the range of +-1e8. Should be enough for any legitimate data. */
+ bool clamp_input;
+
+ DenoiseParams()
+ {
+ radius = 8;
+ strength = 0.5f;
+ feature_strength = 0.5f;
+ relative_pca = false;
+ neighbor_frames = 2;
+ clamp_input = true;
+ }
};
class DeviceTask : public Task {
-public:
- typedef enum { RENDER, FILM_CONVERT, SHADER } Type;
- Type type;
-
- int x, y, w, h;
- device_ptr rgba_byte;
- device_ptr rgba_half;
- device_ptr buffer;
- int sample;
- int num_samples;
- int offset, stride;
-
- device_ptr shader_input;
- device_ptr shader_output;
- int shader_eval_type;
- int shader_filter;
- int shader_x, shader_w;
-
- int passes_size;
-
- explicit DeviceTask(Type type = RENDER);
-
- int get_subtask_count(int num, int max_size = 0);
- void split(list<DeviceTask>& tasks, int num, int max_size = 0);
-
- void update_progress(RenderTile *rtile, int pixel_samples = -1);
-
- function<bool(Device *device, RenderTile&)> acquire_tile;
- function<void(long, int)> update_progress_sample;
- function<void(RenderTile&)> update_tile_sample;
- function<void(RenderTile&)> release_tile;
- function<bool()> get_cancel;
- function<void(RenderTile*, Device*)> map_neighbor_tiles;
- function<void(RenderTile*, Device*)> unmap_neighbor_tiles;
-
- DenoiseParams denoising;
- bool denoising_from_render;
- vector<int> denoising_frames;
-
- bool denoising_do_filter;
- bool denoising_write_passes;
-
- int pass_stride;
- int frame_stride;
- int target_pass_stride;
- int pass_denoising_data;
- int pass_denoising_clean;
-
- bool need_finish_queue;
- bool integrator_branched;
- int2 requested_tile_size;
-protected:
- double last_update_time;
+ public:
+ typedef enum { RENDER, FILM_CONVERT, SHADER } Type;
+ Type type;
+
+ int x, y, w, h;
+ device_ptr rgba_byte;
+ device_ptr rgba_half;
+ device_ptr buffer;
+ int sample;
+ int num_samples;
+ int offset, stride;
+
+ device_ptr shader_input;
+ device_ptr shader_output;
+ int shader_eval_type;
+ int shader_filter;
+ int shader_x, shader_w;
+
+ int passes_size;
+
+ explicit DeviceTask(Type type = RENDER);
+
+ int get_subtask_count(int num, int max_size = 0);
+ void split(list<DeviceTask> &tasks, int num, int max_size = 0);
+
+ void update_progress(RenderTile *rtile, int pixel_samples = -1);
+
+ function<bool(Device *device, RenderTile &)> acquire_tile;
+ function<void(long, int)> update_progress_sample;
+ function<void(RenderTile &)> update_tile_sample;
+ function<void(RenderTile &)> release_tile;
+ function<bool()> get_cancel;
+ function<void(RenderTile *, Device *)> map_neighbor_tiles;
+ function<void(RenderTile *, Device *)> unmap_neighbor_tiles;
+
+ DenoiseParams denoising;
+ bool denoising_from_render;
+ vector<int> denoising_frames;
+
+ bool denoising_do_filter;
+ bool denoising_write_passes;
+
+ int pass_stride;
+ int frame_stride;
+ int target_pass_stride;
+ int pass_denoising_data;
+ int pass_denoising_clean;
+
+ bool need_finish_queue;
+ bool integrator_branched;
+ int2 requested_tile_size;
+
+ protected:
+ double last_update_time;
};
CCL_NAMESPACE_END
-#endif /* __DEVICE_TASK_H__ */
+#endif /* __DEVICE_TASK_H__ */
diff --git a/intern/cycles/device/opencl/memory_manager.cpp b/intern/cycles/device/opencl/memory_manager.cpp
index 9cb105982aa..f85aadce1c2 100644
--- a/intern/cycles/device/opencl/memory_manager.cpp
+++ b/intern/cycles/device/opencl/memory_manager.cpp
@@ -16,241 +16,246 @@
#ifdef WITH_OPENCL
-#include "util/util_foreach.h"
+# include "util/util_foreach.h"
-#include "device/opencl/opencl.h"
-#include "device/opencl/memory_manager.h"
+# include "device/opencl/opencl.h"
+# include "device/opencl/memory_manager.h"
CCL_NAMESPACE_BEGIN
-void MemoryManager::DeviceBuffer::add_allocation(Allocation& allocation)
+void MemoryManager::DeviceBuffer::add_allocation(Allocation &allocation)
{
- allocations.push_back(&allocation);
+ allocations.push_back(&allocation);
}
void MemoryManager::DeviceBuffer::update_device_memory(OpenCLDevice *device)
{
- bool need_realloc = false;
-
- /* Calculate total size and remove any freed. */
- size_t total_size = 0;
-
- for(int i = allocations.size()-1; i >= 0; i--) {
- Allocation* allocation = allocations[i];
-
- /* Remove allocations that have been freed. */
- if(!allocation->mem || allocation->mem->memory_size() == 0) {
- allocation->device_buffer = NULL;
- allocation->size = 0;
-
- allocations.erase(allocations.begin()+i);
-
- need_realloc = true;
-
- continue;
- }
-
- /* Get actual size for allocation. */
- size_t alloc_size = align_up(allocation->mem->memory_size(), 16);
-
- if(allocation->size != alloc_size) {
- /* Allocation is either new or resized. */
- allocation->size = alloc_size;
- allocation->needs_copy_to_device = true;
-
- need_realloc = true;
- }
-
- total_size += alloc_size;
- }
-
- if(need_realloc) {
- cl_ulong max_buffer_size;
- clGetDeviceInfo(device->cdDevice, CL_DEVICE_MAX_MEM_ALLOC_SIZE, sizeof(cl_ulong), &max_buffer_size, NULL);
-
- if(total_size > max_buffer_size) {
- device->set_error("Scene too complex to fit in available memory.");
- return;
- }
-
- device_only_memory<uchar> *new_buffer =
- new device_only_memory<uchar>(device, "memory manager buffer");
-
- new_buffer->alloc_to_device(total_size);
-
- size_t offset = 0;
-
- foreach(Allocation* allocation, allocations) {
- if(allocation->needs_copy_to_device) {
- /* Copy from host to device. */
- opencl_device_assert(device, clEnqueueWriteBuffer(device->cqCommandQueue,
- CL_MEM_PTR(new_buffer->device_pointer),
- CL_FALSE,
- offset,
- allocation->mem->memory_size(),
- allocation->mem->host_pointer,
- 0, NULL, NULL
- ));
-
- allocation->needs_copy_to_device = false;
- }
- else {
- /* Fast copy from memory already on device. */
- opencl_device_assert(device, clEnqueueCopyBuffer(device->cqCommandQueue,
- CL_MEM_PTR(buffer->device_pointer),
- CL_MEM_PTR(new_buffer->device_pointer),
- allocation->desc.offset,
- offset,
- allocation->mem->memory_size(),
- 0, NULL, NULL
- ));
- }
-
- allocation->desc.offset = offset;
- offset += allocation->size;
- }
-
- delete buffer;
-
- buffer = new_buffer;
- }
- else {
- assert(total_size == buffer->data_size);
-
- size_t offset = 0;
-
- foreach(Allocation* allocation, allocations) {
- if(allocation->needs_copy_to_device) {
- /* Copy from host to device. */
- opencl_device_assert(device, clEnqueueWriteBuffer(device->cqCommandQueue,
- CL_MEM_PTR(buffer->device_pointer),
- CL_FALSE,
- offset,
- allocation->mem->memory_size(),
- allocation->mem->host_pointer,
- 0, NULL, NULL
- ));
-
- allocation->needs_copy_to_device = false;
- }
-
- offset += allocation->size;
- }
- }
-
- /* Not really necessary, but seems to improve responsiveness for some reason. */
- clFinish(device->cqCommandQueue);
+ bool need_realloc = false;
+
+ /* Calculate total size and remove any freed. */
+ size_t total_size = 0;
+
+ for (int i = allocations.size() - 1; i >= 0; i--) {
+ Allocation *allocation = allocations[i];
+
+ /* Remove allocations that have been freed. */
+ if (!allocation->mem || allocation->mem->memory_size() == 0) {
+ allocation->device_buffer = NULL;
+ allocation->size = 0;
+
+ allocations.erase(allocations.begin() + i);
+
+ need_realloc = true;
+
+ continue;
+ }
+
+ /* Get actual size for allocation. */
+ size_t alloc_size = align_up(allocation->mem->memory_size(), 16);
+
+ if (allocation->size != alloc_size) {
+ /* Allocation is either new or resized. */
+ allocation->size = alloc_size;
+ allocation->needs_copy_to_device = true;
+
+ need_realloc = true;
+ }
+
+ total_size += alloc_size;
+ }
+
+ if (need_realloc) {
+ cl_ulong max_buffer_size;
+ clGetDeviceInfo(
+ device->cdDevice, CL_DEVICE_MAX_MEM_ALLOC_SIZE, sizeof(cl_ulong), &max_buffer_size, NULL);
+
+ if (total_size > max_buffer_size) {
+ device->set_error("Scene too complex to fit in available memory.");
+ return;
+ }
+
+ device_only_memory<uchar> *new_buffer = new device_only_memory<uchar>(device,
+ "memory manager buffer");
+
+ new_buffer->alloc_to_device(total_size);
+
+ size_t offset = 0;
+
+ foreach (Allocation *allocation, allocations) {
+ if (allocation->needs_copy_to_device) {
+ /* Copy from host to device. */
+ opencl_device_assert(device,
+ clEnqueueWriteBuffer(device->cqCommandQueue,
+ CL_MEM_PTR(new_buffer->device_pointer),
+ CL_FALSE,
+ offset,
+ allocation->mem->memory_size(),
+ allocation->mem->host_pointer,
+ 0,
+ NULL,
+ NULL));
+
+ allocation->needs_copy_to_device = false;
+ }
+ else {
+ /* Fast copy from memory already on device. */
+ opencl_device_assert(device,
+ clEnqueueCopyBuffer(device->cqCommandQueue,
+ CL_MEM_PTR(buffer->device_pointer),
+ CL_MEM_PTR(new_buffer->device_pointer),
+ allocation->desc.offset,
+ offset,
+ allocation->mem->memory_size(),
+ 0,
+ NULL,
+ NULL));
+ }
+
+ allocation->desc.offset = offset;
+ offset += allocation->size;
+ }
+
+ delete buffer;
+
+ buffer = new_buffer;
+ }
+ else {
+ assert(total_size == buffer->data_size);
+
+ size_t offset = 0;
+
+ foreach (Allocation *allocation, allocations) {
+ if (allocation->needs_copy_to_device) {
+ /* Copy from host to device. */
+ opencl_device_assert(device,
+ clEnqueueWriteBuffer(device->cqCommandQueue,
+ CL_MEM_PTR(buffer->device_pointer),
+ CL_FALSE,
+ offset,
+ allocation->mem->memory_size(),
+ allocation->mem->host_pointer,
+ 0,
+ NULL,
+ NULL));
+
+ allocation->needs_copy_to_device = false;
+ }
+
+ offset += allocation->size;
+ }
+ }
+
+ /* Not really necessary, but seems to improve responsiveness for some reason. */
+ clFinish(device->cqCommandQueue);
}
void MemoryManager::DeviceBuffer::free(OpenCLDevice *)
{
- buffer->free();
+ buffer->free();
}
-MemoryManager::DeviceBuffer* MemoryManager::smallest_device_buffer()
+MemoryManager::DeviceBuffer *MemoryManager::smallest_device_buffer()
{
- DeviceBuffer* smallest = device_buffers;
+ DeviceBuffer *smallest = device_buffers;
- foreach(DeviceBuffer& device_buffer, device_buffers) {
- if(device_buffer.size < smallest->size) {
- smallest = &device_buffer;
- }
- }
+ foreach (DeviceBuffer &device_buffer, device_buffers) {
+ if (device_buffer.size < smallest->size) {
+ smallest = &device_buffer;
+ }
+ }
- return smallest;
+ return smallest;
}
-MemoryManager::MemoryManager(OpenCLDevice *device)
-: device(device), need_update(false)
+MemoryManager::MemoryManager(OpenCLDevice *device) : device(device), need_update(false)
{
- foreach(DeviceBuffer& device_buffer, device_buffers) {
- device_buffer.buffer =
- new device_only_memory<uchar>(device, "memory manager buffer");
- }
+ foreach (DeviceBuffer &device_buffer, device_buffers) {
+ device_buffer.buffer = new device_only_memory<uchar>(device, "memory manager buffer");
+ }
}
void MemoryManager::free()
{
- foreach(DeviceBuffer& device_buffer, device_buffers) {
- device_buffer.free(device);
- }
+ foreach (DeviceBuffer &device_buffer, device_buffers) {
+ device_buffer.free(device);
+ }
}
-void MemoryManager::alloc(const char *name, device_memory& mem)
+void MemoryManager::alloc(const char *name, device_memory &mem)
{
- Allocation& allocation = allocations[name];
+ Allocation &allocation = allocations[name];
- allocation.mem = &mem;
- allocation.needs_copy_to_device = true;
+ allocation.mem = &mem;
+ allocation.needs_copy_to_device = true;
- if(!allocation.device_buffer) {
- DeviceBuffer* device_buffer = smallest_device_buffer();
- allocation.device_buffer = device_buffer;
+ if (!allocation.device_buffer) {
+ DeviceBuffer *device_buffer = smallest_device_buffer();
+ allocation.device_buffer = device_buffer;
- allocation.desc.device_buffer = device_buffer - device_buffers;
+ allocation.desc.device_buffer = device_buffer - device_buffers;
- device_buffer->add_allocation(allocation);
+ device_buffer->add_allocation(allocation);
- device_buffer->size += mem.memory_size();
- }
+ device_buffer->size += mem.memory_size();
+ }
- need_update = true;
+ need_update = true;
}
-bool MemoryManager::free(device_memory& mem)
+bool MemoryManager::free(device_memory &mem)
{
- foreach(AllocationsMap::value_type& value, allocations) {
- Allocation& allocation = value.second;
- if(allocation.mem == &mem) {
+ foreach (AllocationsMap::value_type &value, allocations) {
+ Allocation &allocation = value.second;
+ if (allocation.mem == &mem) {
- allocation.device_buffer->size -= mem.memory_size();
+ allocation.device_buffer->size -= mem.memory_size();
- allocation.mem = NULL;
- allocation.needs_copy_to_device = false;
+ allocation.mem = NULL;
+ allocation.needs_copy_to_device = false;
- need_update = true;
- return true;
- }
- }
+ need_update = true;
+ return true;
+ }
+ }
- return false;
+ return false;
}
MemoryManager::BufferDescriptor MemoryManager::get_descriptor(string name)
{
- update_device_memory();
+ update_device_memory();
- Allocation& allocation = allocations[name];
- return allocation.desc;
+ Allocation &allocation = allocations[name];
+ return allocation.desc;
}
void MemoryManager::update_device_memory()
{
- if(!need_update) {
- return;
- }
+ if (!need_update) {
+ return;
+ }
- need_update = false;
+ need_update = false;
- foreach(DeviceBuffer& device_buffer, device_buffers) {
- device_buffer.update_device_memory(device);
- }
+ foreach (DeviceBuffer &device_buffer, device_buffers) {
+ device_buffer.update_device_memory(device);
+ }
}
void MemoryManager::set_kernel_arg_buffers(cl_kernel kernel, cl_uint *narg)
{
- update_device_memory();
-
- foreach(DeviceBuffer& device_buffer, device_buffers) {
- if(device_buffer.buffer->device_pointer) {
- device->kernel_set_args(kernel, (*narg)++, *device_buffer.buffer);
- }
- else {
- device->kernel_set_args(kernel, (*narg)++, device->null_mem);
- }
- }
+ update_device_memory();
+
+ foreach (DeviceBuffer &device_buffer, device_buffers) {
+ if (device_buffer.buffer->device_pointer) {
+ device->kernel_set_args(kernel, (*narg)++, *device_buffer.buffer);
+ }
+ else {
+ device->kernel_set_args(kernel, (*narg)++, device->null_mem);
+ }
+ }
}
CCL_NAMESPACE_END
-#endif /* WITH_OPENCL */
+#endif /* WITH_OPENCL */
diff --git a/intern/cycles/device/opencl/memory_manager.h b/intern/cycles/device/opencl/memory_manager.h
index 8fcc4440369..2fbc97a0756 100644
--- a/intern/cycles/device/opencl/memory_manager.h
+++ b/intern/cycles/device/opencl/memory_manager.h
@@ -29,78 +29,77 @@ CCL_NAMESPACE_BEGIN
class OpenCLDevice;
class MemoryManager {
-public:
- static const int NUM_DEVICE_BUFFERS = 8;
+ public:
+ static const int NUM_DEVICE_BUFFERS = 8;
- struct BufferDescriptor {
- uint device_buffer;
- cl_ulong offset;
- };
+ struct BufferDescriptor {
+ uint device_buffer;
+ cl_ulong offset;
+ };
-private:
- struct DeviceBuffer;
+ private:
+ struct DeviceBuffer;
- struct Allocation {
- device_memory *mem;
+ struct Allocation {
+ device_memory *mem;
- DeviceBuffer *device_buffer;
- size_t size; /* Size of actual allocation, may be larger than requested. */
+ DeviceBuffer *device_buffer;
+ size_t size; /* Size of actual allocation, may be larger than requested. */
- BufferDescriptor desc;
+ BufferDescriptor desc;
- bool needs_copy_to_device;
+ bool needs_copy_to_device;
- Allocation() : mem(NULL), device_buffer(NULL), size(0), needs_copy_to_device(false)
- {
- }
- };
+ Allocation() : mem(NULL), device_buffer(NULL), size(0), needs_copy_to_device(false)
+ {
+ }
+ };
- struct DeviceBuffer {
- device_only_memory<uchar> *buffer;
- vector<Allocation*> allocations;
- size_t size; /* Size of all allocations. */
+ struct DeviceBuffer {
+ device_only_memory<uchar> *buffer;
+ vector<Allocation *> allocations;
+ size_t size; /* Size of all allocations. */
- DeviceBuffer()
- : buffer(NULL), size(0)
- {
- }
+ DeviceBuffer() : buffer(NULL), size(0)
+ {
+ }
- ~DeviceBuffer()
- {
- delete buffer;
- buffer = NULL;
- }
+ ~DeviceBuffer()
+ {
+ delete buffer;
+ buffer = NULL;
+ }
- void add_allocation(Allocation& allocation);
+ void add_allocation(Allocation &allocation);
- void update_device_memory(OpenCLDevice *device);
+ void update_device_memory(OpenCLDevice *device);
- void free(OpenCLDevice *device);
- };
+ void free(OpenCLDevice *device);
+ };
- OpenCLDevice *device;
+ OpenCLDevice *device;
- DeviceBuffer device_buffers[NUM_DEVICE_BUFFERS];
+ DeviceBuffer device_buffers[NUM_DEVICE_BUFFERS];
- typedef unordered_map<string, Allocation> AllocationsMap;
- AllocationsMap allocations;
+ typedef unordered_map<string, Allocation> AllocationsMap;
+ AllocationsMap allocations;
- bool need_update;
+ bool need_update;
- DeviceBuffer* smallest_device_buffer();
+ DeviceBuffer *smallest_device_buffer();
-public:
- MemoryManager(OpenCLDevice *device);
+ public:
+ MemoryManager(OpenCLDevice *device);
- void free(); /* Free all memory. */
+ void free(); /* Free all memory. */
- void alloc(const char *name, device_memory& mem);
- bool free(device_memory& mem);
+ void alloc(const char *name, device_memory &mem);
+ bool free(device_memory &mem);
- BufferDescriptor get_descriptor(string name);
+ BufferDescriptor get_descriptor(string name);
- void update_device_memory();
- void set_kernel_arg_buffers(cl_kernel kernel, cl_uint *narg);
+ void update_device_memory();
+ void set_kernel_arg_buffers(cl_kernel kernel, cl_uint *narg);
};
CCL_NAMESPACE_END
diff --git a/intern/cycles/device/opencl/opencl.h b/intern/cycles/device/opencl/opencl.h
index 89761293638..e7bafa0b8a8 100644
--- a/intern/cycles/device/opencl/opencl.h
+++ b/intern/cycles/device/opencl/opencl.h
@@ -16,645 +16,641 @@
#ifdef WITH_OPENCL
-#include "device/device.h"
-#include "device/device_denoising.h"
-#include "device/device_split_kernel.h"
+# include "device/device.h"
+# include "device/device_denoising.h"
+# include "device/device_split_kernel.h"
-#include "util/util_map.h"
-#include "util/util_param.h"
-#include "util/util_string.h"
+# include "util/util_map.h"
+# include "util/util_param.h"
+# include "util/util_string.h"
-#include "clew.h"
+# include "clew.h"
-#include "device/opencl/memory_manager.h"
+# include "device/opencl/memory_manager.h"
CCL_NAMESPACE_BEGIN
/* Disable workarounds, seems to be working fine on latest drivers. */
-#define CYCLES_DISABLE_DRIVER_WORKAROUNDS
+# define CYCLES_DISABLE_DRIVER_WORKAROUNDS
/* Define CYCLES_DISABLE_DRIVER_WORKAROUNDS to disable workaounds for testing */
-#ifndef CYCLES_DISABLE_DRIVER_WORKAROUNDS
+# ifndef CYCLES_DISABLE_DRIVER_WORKAROUNDS
/* 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) \
- CLEW_GET_FUN(__clewEnqueueNDRangeKernel)(a, b, c, d, e, f, g, h, i); \
- clFinish(a);
+# undef clEnqueueNDRangeKernel
+# define clEnqueueNDRangeKernel(a, b, c, d, e, f, g, h, i) \
+ 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) \
- CLEW_GET_FUN(__clewEnqueueWriteBuffer)(a, b, c, d, e, f, g, h, i); \
- clFinish(a);
+# undef clEnqueueWriteBuffer
+# define clEnqueueWriteBuffer(a, b, c, d, e, f, g, h, i) \
+ 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) \
- CLEW_GET_FUN(__clewEnqueueReadBuffer)(a, b, c, d, e, f, g, h, i); \
- clFinish(a);
-#endif /* CYCLES_DISABLE_DRIVER_WORKAROUNDS */
+# undef clEnqueueReadBuffer
+# define clEnqueueReadBuffer(a, b, c, d, e, f, g, h, i) \
+ CLEW_GET_FUN(__clewEnqueueReadBuffer)(a, b, c, d, e, f, g, h, i); \
+ clFinish(a);
+# endif /* CYCLES_DISABLE_DRIVER_WORKAROUNDS */
-#define CL_MEM_PTR(p) ((cl_mem)(uintptr_t)(p))
+# define CL_MEM_PTR(p) ((cl_mem)(uintptr_t)(p))
struct OpenCLPlatformDevice {
- OpenCLPlatformDevice(cl_platform_id platform_id,
- const string& platform_name,
- cl_device_id device_id,
- cl_device_type device_type,
- const string& device_name,
- const string& hardware_id,
- const string& device_extensions)
- : platform_id(platform_id),
- platform_name(platform_name),
- device_id(device_id),
- device_type(device_type),
- device_name(device_name),
- hardware_id(hardware_id),
- device_extensions(device_extensions) {}
- cl_platform_id platform_id;
- string platform_name;
- cl_device_id device_id;
- cl_device_type device_type;
- string device_name;
- string hardware_id;
- string device_extensions;
+ OpenCLPlatformDevice(cl_platform_id platform_id,
+ const string &platform_name,
+ cl_device_id device_id,
+ cl_device_type device_type,
+ const string &device_name,
+ const string &hardware_id,
+ const string &device_extensions)
+ : platform_id(platform_id),
+ platform_name(platform_name),
+ device_id(device_id),
+ device_type(device_type),
+ device_name(device_name),
+ hardware_id(hardware_id),
+ device_extensions(device_extensions)
+ {
+ }
+ cl_platform_id platform_id;
+ string platform_name;
+ cl_device_id device_id;
+ cl_device_type device_type;
+ string device_name;
+ string hardware_id;
+ string device_extensions;
};
/* Contains all static OpenCL helper functions. */
-class OpenCLInfo
-{
-public:
- static cl_device_type device_type();
- static bool use_debug();
- static bool device_supported(const string& platform_name,
- const cl_device_id device_id);
- static bool platform_version_check(cl_platform_id platform,
- string *error = NULL);
- static bool device_version_check(cl_device_id device,
- string *error = NULL);
- static string get_hardware_id(const string& platform_name,
- cl_device_id device_id);
- static void get_usable_devices(vector<OpenCLPlatformDevice> *usable_devices,
- bool force_all = false);
-
- /* ** Some handy shortcuts to low level cl*GetInfo() functions. ** */
-
- /* Platform information. */
- static bool get_num_platforms(cl_uint *num_platforms, cl_int *error = NULL);
- static cl_uint get_num_platforms();
-
- static bool get_platforms(vector<cl_platform_id> *platform_ids,
- cl_int *error = NULL);
- static vector<cl_platform_id> get_platforms();
-
- static bool get_platform_name(cl_platform_id platform_id,
- string *platform_name);
- static string get_platform_name(cl_platform_id platform_id);
-
- static bool get_num_platform_devices(cl_platform_id platform_id,
- cl_device_type device_type,
- cl_uint *num_devices,
- cl_int *error = NULL);
- static cl_uint get_num_platform_devices(cl_platform_id platform_id,
- cl_device_type device_type);
-
- static bool get_platform_devices(cl_platform_id platform_id,
- cl_device_type device_type,
- vector<cl_device_id> *device_ids,
- cl_int* error = NULL);
- static vector<cl_device_id> get_platform_devices(cl_platform_id platform_id,
- cl_device_type device_type);
-
- /* Device information. */
- static bool get_device_name(cl_device_id device_id,
- string *device_name,
- cl_int* error = NULL);
-
- static string get_device_name(cl_device_id device_id);
-
- static bool get_device_extensions(cl_device_id device_id,
- string *device_extensions,
- cl_int* error = NULL);
-
- static string get_device_extensions(cl_device_id device_id);
-
- static bool get_device_type(cl_device_id device_id,
- cl_device_type *device_type,
- cl_int* error = NULL);
- static cl_device_type get_device_type(cl_device_id device_id);
-
- static bool get_driver_version(cl_device_id device_id,
- int *major,
- int *minor,
- cl_int* error = NULL);
-
- static int mem_sub_ptr_alignment(cl_device_id device_id);
-
- /* Get somewhat more readable device name.
- * Main difference is AMD OpenCL here which only gives code name
- * for the regular device name. This will give more sane device
- * name using some extensions.
- */
- static string get_readable_device_name(cl_device_id device_id);
+class OpenCLInfo {
+ public:
+ static cl_device_type device_type();
+ static bool use_debug();
+ static bool device_supported(const string &platform_name, const cl_device_id device_id);
+ static bool platform_version_check(cl_platform_id platform, string *error = NULL);
+ static bool device_version_check(cl_device_id device, string *error = NULL);
+ static string get_hardware_id(const string &platform_name, cl_device_id device_id);
+ static void get_usable_devices(vector<OpenCLPlatformDevice> *usable_devices,
+ bool force_all = false);
+
+ /* ** Some handy shortcuts to low level cl*GetInfo() functions. ** */
+
+ /* Platform information. */
+ static bool get_num_platforms(cl_uint *num_platforms, cl_int *error = NULL);
+ static cl_uint get_num_platforms();
+
+ static bool get_platforms(vector<cl_platform_id> *platform_ids, cl_int *error = NULL);
+ static vector<cl_platform_id> get_platforms();
+
+ static bool get_platform_name(cl_platform_id platform_id, string *platform_name);
+ static string get_platform_name(cl_platform_id platform_id);
+
+ static bool get_num_platform_devices(cl_platform_id platform_id,
+ cl_device_type device_type,
+ cl_uint *num_devices,
+ cl_int *error = NULL);
+ static cl_uint get_num_platform_devices(cl_platform_id platform_id, cl_device_type device_type);
+
+ static bool get_platform_devices(cl_platform_id platform_id,
+ cl_device_type device_type,
+ vector<cl_device_id> *device_ids,
+ cl_int *error = NULL);
+ static vector<cl_device_id> get_platform_devices(cl_platform_id platform_id,
+ cl_device_type device_type);
+
+ /* Device information. */
+ static bool get_device_name(cl_device_id device_id, string *device_name, cl_int *error = NULL);
+
+ static string get_device_name(cl_device_id device_id);
+
+ static bool get_device_extensions(cl_device_id device_id,
+ string *device_extensions,
+ cl_int *error = NULL);
+
+ static string get_device_extensions(cl_device_id device_id);
+
+ static bool get_device_type(cl_device_id device_id,
+ cl_device_type *device_type,
+ cl_int *error = NULL);
+ static cl_device_type get_device_type(cl_device_id device_id);
+
+ static bool get_driver_version(cl_device_id device_id,
+ int *major,
+ int *minor,
+ cl_int *error = NULL);
+
+ static int mem_sub_ptr_alignment(cl_device_id device_id);
+
+ /* Get somewhat more readable device name.
+ * Main difference is AMD OpenCL here which only gives code name
+ * for the regular device name. This will give more sane device
+ * name using some extensions.
+ */
+ static string get_readable_device_name(cl_device_id device_id);
};
/* Thread safe cache for contexts and programs.
*/
-class OpenCLCache
-{
- struct Slot
- {
- struct ProgramEntry
- {
- ProgramEntry();
- ProgramEntry(const ProgramEntry& rhs);
- ~ProgramEntry();
- cl_program program;
- thread_mutex *mutex;
- };
-
- Slot();
- Slot(const Slot& rhs);
- ~Slot();
-
- thread_mutex *context_mutex;
- cl_context context;
- typedef map<ustring, ProgramEntry> EntryMap;
- EntryMap programs;
-
- };
-
- /* key is combination of platform ID and device ID */
- typedef pair<cl_platform_id, cl_device_id> PlatformDevicePair;
-
- /* map of Slot objects */
- typedef map<PlatformDevicePair, Slot> CacheMap;
- CacheMap cache;
-
- /* MD5 hash of the kernel source. */
- string kernel_md5;
-
- thread_mutex cache_lock;
- thread_mutex kernel_md5_lock;
-
- /* lazy instantiate */
- static OpenCLCache& global_instance();
-
-public:
-
- enum ProgramName {
- OCL_DEV_BASE_PROGRAM,
- OCL_DEV_MEGAKERNEL_PROGRAM,
- };
-
- /* Lookup context in the cache. If this returns NULL, slot_locker
- * will be holding a lock for the cache. slot_locker should refer to a
- * default constructed thread_scoped_lock. */
- static cl_context get_context(cl_platform_id platform,
- cl_device_id device,
- thread_scoped_lock& slot_locker);
- /* Same as above. */
- static cl_program get_program(cl_platform_id platform,
- cl_device_id device,
- ustring key,
- thread_scoped_lock& slot_locker);
-
- /* Store context in the cache. You MUST have tried to get the item before storing to it. */
- static void store_context(cl_platform_id platform,
- cl_device_id device,
- cl_context context,
- thread_scoped_lock& slot_locker);
- /* Same as above. */
- static void store_program(cl_platform_id platform,
- cl_device_id device,
- cl_program program,
- ustring key,
- thread_scoped_lock& slot_locker);
-
- static string get_kernel_md5();
+class OpenCLCache {
+ struct Slot {
+ struct ProgramEntry {
+ ProgramEntry();
+ ProgramEntry(const ProgramEntry &rhs);
+ ~ProgramEntry();
+ cl_program program;
+ thread_mutex *mutex;
+ };
+
+ Slot();
+ Slot(const Slot &rhs);
+ ~Slot();
+
+ thread_mutex *context_mutex;
+ cl_context context;
+ typedef map<ustring, ProgramEntry> EntryMap;
+ EntryMap programs;
+ };
+
+ /* key is combination of platform ID and device ID */
+ typedef pair<cl_platform_id, cl_device_id> PlatformDevicePair;
+
+ /* map of Slot objects */
+ typedef map<PlatformDevicePair, Slot> CacheMap;
+ CacheMap cache;
+
+ /* MD5 hash of the kernel source. */
+ string kernel_md5;
+
+ thread_mutex cache_lock;
+ thread_mutex kernel_md5_lock;
+
+ /* lazy instantiate */
+ static OpenCLCache &global_instance();
+
+ public:
+ enum ProgramName {
+ OCL_DEV_BASE_PROGRAM,
+ OCL_DEV_MEGAKERNEL_PROGRAM,
+ };
+
+ /* Lookup context in the cache. If this returns NULL, slot_locker
+ * will be holding a lock for the cache. slot_locker should refer to a
+ * default constructed thread_scoped_lock. */
+ static cl_context get_context(cl_platform_id platform,
+ cl_device_id device,
+ thread_scoped_lock &slot_locker);
+ /* Same as above. */
+ static cl_program get_program(cl_platform_id platform,
+ cl_device_id device,
+ ustring key,
+ thread_scoped_lock &slot_locker);
+
+ /* Store context in the cache. You MUST have tried to get the item before storing to it. */
+ static void store_context(cl_platform_id platform,
+ cl_device_id device,
+ cl_context context,
+ thread_scoped_lock &slot_locker);
+ /* Same as above. */
+ static void store_program(cl_platform_id platform,
+ cl_device_id device,
+ cl_program program,
+ ustring key,
+ thread_scoped_lock &slot_locker);
+
+ static string get_kernel_md5();
};
-#define opencl_device_assert(device, stmt) \
- { \
- cl_int err = stmt; \
- \
- if(err != CL_SUCCESS) { \
- string message = string_printf("OpenCL error: %s in %s (%s:%d)", clewErrorString(err), #stmt, __FILE__, __LINE__); \
- if((device)->error_message() == "") \
- (device)->set_error(message); \
- fprintf(stderr, "%s\n", message.c_str()); \
- } \
- } (void) 0
-
-#define opencl_assert(stmt) \
- { \
- cl_int err = stmt; \
- \
- if(err != CL_SUCCESS) { \
- string message = string_printf("OpenCL error: %s in %s (%s:%d)", clewErrorString(err), #stmt, __FILE__, __LINE__); \
- if(error_msg == "") \
- error_msg = message; \
- fprintf(stderr, "%s\n", message.c_str()); \
- } \
- } (void) 0
-
-class OpenCLDevice : public Device
-{
-public:
- DedicatedTaskPool task_pool;
-
- /* Task pool for required kernels (base, AO kernels during foreground rendering) */
- TaskPool load_required_kernel_task_pool;
- /* Task pool for optional kernels (feature kernels during foreground rendering) */
- TaskPool load_kernel_task_pool;
- cl_context cxContext;
- cl_command_queue cqCommandQueue;
- cl_platform_id cpPlatform;
- cl_device_id cdDevice;
- cl_int ciErr;
- int device_num;
- bool use_preview_kernels;
-
- class OpenCLProgram {
- public:
- OpenCLProgram() : loaded(false), needs_compiling(true), program(NULL), device(NULL) {}
- OpenCLProgram(OpenCLDevice *device,
- const string& program_name,
- const string& kernel_name,
- const string& kernel_build_options,
- bool use_stdout = true);
- ~OpenCLProgram();
-
- void add_kernel(ustring name);
-
- /* Try to load the program from device cache or disk */
- bool load();
- /* Compile the kernel (first separate, failback to local) */
- void compile();
- /* Create the OpenCL kernels after loading or compiling */
- void create_kernels();
-
- bool is_loaded() const { return loaded; }
- const string& get_log() const { return log; }
- void report_error();
-
- /* Wait until this kernel is available to be used
- * It will return true when the kernel is available.
- * It will return false when the kernel is not available
- * or could not be loaded. */
- bool wait_for_availability();
-
- cl_kernel operator()();
- cl_kernel operator()(ustring name);
-
- void release();
-
- private:
- bool build_kernel(const string *debug_src);
- /* Build the program by calling the own process.
- * This is required for multithreaded OpenCL compilation, since most Frameworks serialize
- * build calls internally if they come from the same process.
- * If that is not supported, this function just returns false.
- */
- bool compile_separate(const string& clbin);
- /* Build the program by calling OpenCL directly. */
- bool compile_kernel(const string *debug_src);
- /* Loading and saving the program from/to disk. */
- bool load_binary(const string& clbin, const string *debug_src = NULL);
- bool save_binary(const string& clbin);
-
- void add_log(const string& msg, bool is_debug);
- void add_error(const string& msg);
-
- bool loaded;
- bool needs_compiling;
-
- cl_program program;
- OpenCLDevice *device;
-
- /* Used for the OpenCLCache key. */
- string program_name;
-
- string kernel_file, kernel_build_options, device_md5;
-
- bool use_stdout;
- string log, error_msg;
- string compile_output;
-
- map<ustring, cl_kernel> kernels;
- };
-
- /* Container for all types of split programs. */
- class OpenCLSplitPrograms {
- public:
- OpenCLDevice *device;
- OpenCLProgram program_split;
- OpenCLProgram program_lamp_emission;
- OpenCLProgram program_do_volume;
- OpenCLProgram program_indirect_background;
- OpenCLProgram program_shader_eval;
- OpenCLProgram program_holdout_emission_blurring_pathtermination_ao;
- OpenCLProgram program_subsurface_scatter;
- OpenCLProgram program_direct_lighting;
- OpenCLProgram program_shadow_blocked_ao;
- OpenCLProgram program_shadow_blocked_dl;
-
- OpenCLSplitPrograms(OpenCLDevice *device);
- ~OpenCLSplitPrograms();
-
- /* Load the kernels and put the created kernels in the given `programs`
- * paramter. */
- void load_kernels(vector<OpenCLProgram*> &programs,
- const DeviceRequestedFeatures& requested_features,
- bool is_preview=false);
- };
-
- DeviceSplitKernel *split_kernel;
-
- OpenCLProgram base_program;
- OpenCLProgram bake_program;
- OpenCLProgram displace_program;
- OpenCLProgram background_program;
- OpenCLProgram denoising_program;
-
- OpenCLSplitPrograms kernel_programs;
- OpenCLSplitPrograms preview_programs;
-
- typedef map<string, device_vector<uchar>*> ConstMemMap;
- typedef map<string, device_ptr> MemMap;
-
- ConstMemMap const_mem_map;
- MemMap mem_map;
- device_ptr null_mem;
-
- bool device_initialized;
- string platform_name;
- string device_name;
-
- bool opencl_error(cl_int err);
- void opencl_error(const string& message);
- void opencl_assert_err(cl_int err, const char* where);
-
- OpenCLDevice(DeviceInfo& info, Stats &stats, Profiler &profiler, bool background);
- ~OpenCLDevice();
-
- static void CL_CALLBACK context_notify_callback(const char *err_info,
- const void * /*private_info*/, size_t /*cb*/, void *user_data);
-
- bool opencl_version_check();
- OpenCLSplitPrograms* get_split_programs();
-
- string device_md5_hash(string kernel_custom_build_options = "");
- bool load_kernels(const DeviceRequestedFeatures& requested_features);
- void load_required_kernels(const DeviceRequestedFeatures& requested_features);
- void load_preview_kernels();
-
- bool wait_for_availability(const DeviceRequestedFeatures& requested_features);
- DeviceKernelStatus get_active_kernel_switch_state();
-
- /* Get the name of the opencl program for the given kernel */
- const string get_opencl_program_name(const string& kernel_name);
- /* Get the program file name to compile (*.cl) for the given kernel */
- const string get_opencl_program_filename(const string& kernel_name);
- string get_build_options(const DeviceRequestedFeatures& requested_features,
- const string& opencl_program_name,
- bool preview_kernel=false);
- /* Enable the default features to reduce recompilation events */
- void enable_default_features(DeviceRequestedFeatures& features);
-
- void mem_alloc(device_memory& mem);
- void mem_copy_to(device_memory& mem);
- void mem_copy_from(device_memory& mem, int y, int w, int h, int elem);
- void mem_zero(device_memory& mem);
- void mem_free(device_memory& mem);
-
- int mem_sub_ptr_alignment();
-
- void const_copy_to(const char *name, void *host, size_t size);
- void tex_alloc(device_memory& mem);
- void tex_free(device_memory& mem);
-
- size_t global_size_round_up(int group_size, int global_size);
- void enqueue_kernel(cl_kernel kernel, size_t w, size_t h,
- bool x_workgroups = false,
- size_t max_workgroup_size = -1);
- void set_kernel_arg_mem(cl_kernel kernel, cl_uint *narg, const char *name);
- void set_kernel_arg_buffers(cl_kernel kernel, cl_uint *narg);
-
- void film_convert(DeviceTask& task, device_ptr buffer, device_ptr rgba_byte, device_ptr rgba_half);
- void shader(DeviceTask& task);
-
- void denoise(RenderTile& tile, DenoisingTask& denoising);
-
- class OpenCLDeviceTask : public DeviceTask {
- public:
- OpenCLDeviceTask(OpenCLDevice *device, DeviceTask& task)
- : DeviceTask(task)
- {
- run = function_bind(&OpenCLDevice::thread_run,
- device,
- this);
- }
- };
-
- int get_split_task_count(DeviceTask& /*task*/)
- {
- return 1;
- }
-
- void task_add(DeviceTask& task)
- {
- task_pool.push(new OpenCLDeviceTask(this, task));
- }
-
- void task_wait()
- {
- task_pool.wait();
- }
-
- void task_cancel()
- {
- task_pool.cancel();
- }
-
- void thread_run(DeviceTask *task);
-
- virtual BVHLayoutMask get_bvh_layout_mask() const {
- return BVH_LAYOUT_BVH2;
- }
-
- virtual bool show_samples() const {
- return true;
- }
-
-
-protected:
- string kernel_build_options(const string *debug_src = NULL);
-
- void mem_zero_kernel(device_ptr ptr, size_t size);
-
- bool denoising_non_local_means(device_ptr image_ptr,
- device_ptr guide_ptr,
- device_ptr variance_ptr,
- device_ptr out_ptr,
- DenoisingTask *task);
- bool denoising_construct_transform(DenoisingTask *task);
- bool denoising_accumulate(device_ptr color_ptr,
- device_ptr color_variance_ptr,
- device_ptr scale_ptr,
- int frame,
- DenoisingTask *task);
- bool denoising_solve(device_ptr output_ptr,
- DenoisingTask *task);
- bool denoising_combine_halves(device_ptr a_ptr,
- device_ptr b_ptr,
- device_ptr mean_ptr,
- device_ptr variance_ptr,
- int r, int4 rect,
- DenoisingTask *task);
- bool denoising_divide_shadow(device_ptr a_ptr,
- device_ptr b_ptr,
- device_ptr sample_variance_ptr,
- device_ptr sv_variance_ptr,
- device_ptr buffer_variance_ptr,
- DenoisingTask *task);
- bool denoising_get_feature(int mean_offset,
- int variance_offset,
- device_ptr mean_ptr,
- device_ptr variance_ptr,
- float scale,
- DenoisingTask *task);
- bool denoising_write_feature(int to_offset,
- device_ptr from_ptr,
- device_ptr buffer_ptr,
- DenoisingTask *task);
- bool denoising_detect_outliers(device_ptr image_ptr,
- device_ptr variance_ptr,
- device_ptr depth_ptr,
- device_ptr output_ptr,
- DenoisingTask *task);
-
- device_ptr mem_alloc_sub_ptr(device_memory& mem, int offset, int size);
- void mem_free_sub_ptr(device_ptr ptr);
-
- class ArgumentWrapper {
- public:
- ArgumentWrapper() : size(0), pointer(NULL)
- {
- }
-
- ArgumentWrapper(device_memory& argument) : size(sizeof(void*)),
- pointer((void*)(&argument.device_pointer))
- {
- }
-
- template<typename T>
- ArgumentWrapper(device_vector<T>& argument) : size(sizeof(void*)),
- pointer((void*)(&argument.device_pointer))
- {
- }
-
- template<typename T>
- ArgumentWrapper(device_only_memory<T>& argument) : size(sizeof(void*)),
- pointer((void*)(&argument.device_pointer))
- {
- }
- template<typename T>
- ArgumentWrapper(T& argument) : size(sizeof(argument)),
- pointer(&argument)
- {
- }
-
- ArgumentWrapper(int argument) : size(sizeof(int)),
- int_value(argument),
- pointer(&int_value)
- {
- }
-
- ArgumentWrapper(float argument) : size(sizeof(float)),
- float_value(argument),
- pointer(&float_value)
- {
- }
-
- size_t size;
- int int_value;
- float float_value;
- void *pointer;
- };
-
- /* TODO(sergey): In the future we can use variadic templates, once
- * C++0x is allowed. Should allow to clean this up a bit.
- */
- int kernel_set_args(cl_kernel kernel,
- int start_argument_index,
- const ArgumentWrapper& arg1 = ArgumentWrapper(),
- const ArgumentWrapper& arg2 = ArgumentWrapper(),
- const ArgumentWrapper& arg3 = ArgumentWrapper(),
- const ArgumentWrapper& arg4 = ArgumentWrapper(),
- const ArgumentWrapper& arg5 = ArgumentWrapper(),
- const ArgumentWrapper& arg6 = ArgumentWrapper(),
- const ArgumentWrapper& arg7 = ArgumentWrapper(),
- const ArgumentWrapper& arg8 = ArgumentWrapper(),
- const ArgumentWrapper& arg9 = ArgumentWrapper(),
- const ArgumentWrapper& arg10 = ArgumentWrapper(),
- const ArgumentWrapper& arg11 = ArgumentWrapper(),
- const ArgumentWrapper& arg12 = ArgumentWrapper(),
- const ArgumentWrapper& arg13 = ArgumentWrapper(),
- const ArgumentWrapper& arg14 = ArgumentWrapper(),
- const ArgumentWrapper& arg15 = ArgumentWrapper(),
- const ArgumentWrapper& arg16 = ArgumentWrapper(),
- const ArgumentWrapper& arg17 = ArgumentWrapper(),
- const ArgumentWrapper& arg18 = ArgumentWrapper(),
- const ArgumentWrapper& arg19 = ArgumentWrapper(),
- const ArgumentWrapper& arg20 = ArgumentWrapper(),
- const ArgumentWrapper& arg21 = ArgumentWrapper(),
- const ArgumentWrapper& arg22 = ArgumentWrapper(),
- const ArgumentWrapper& arg23 = ArgumentWrapper(),
- const ArgumentWrapper& arg24 = ArgumentWrapper(),
- const ArgumentWrapper& arg25 = ArgumentWrapper(),
- const ArgumentWrapper& arg26 = ArgumentWrapper(),
- const ArgumentWrapper& arg27 = ArgumentWrapper(),
- const ArgumentWrapper& arg28 = ArgumentWrapper(),
- const ArgumentWrapper& arg29 = ArgumentWrapper(),
- const ArgumentWrapper& arg30 = ArgumentWrapper(),
- const ArgumentWrapper& arg31 = ArgumentWrapper(),
- const ArgumentWrapper& arg32 = ArgumentWrapper(),
- const ArgumentWrapper& arg33 = ArgumentWrapper());
-
- void release_kernel_safe(cl_kernel kernel);
- void release_mem_object_safe(cl_mem mem);
- void release_program_safe(cl_program program);
-
- /* ** Those guys are for workign around some compiler-specific bugs ** */
-
- cl_program load_cached_kernel(
- ustring key,
- thread_scoped_lock& cache_locker);
-
- void store_cached_kernel(
- cl_program program,
- ustring key,
- thread_scoped_lock& cache_locker);
-
-private:
- MemoryManager memory_manager;
- friend class MemoryManager;
-
- static_assert_align(TextureInfo, 16);
- device_vector<TextureInfo> texture_info;
-
- typedef map<string, device_memory*> TexturesMap;
- TexturesMap textures;
-
- bool textures_need_update;
-
-protected:
- void flush_texture_buffers();
-
- friend class OpenCLSplitKernel;
- friend class OpenCLSplitKernelFunction;
+# define opencl_device_assert(device, stmt) \
+ { \
+ cl_int err = stmt; \
+\
+ if (err != CL_SUCCESS) { \
+ string message = string_printf( \
+ "OpenCL error: %s in %s (%s:%d)", clewErrorString(err), #stmt, __FILE__, __LINE__); \
+ if ((device)->error_message() == "") \
+ (device)->set_error(message); \
+ fprintf(stderr, "%s\n", message.c_str()); \
+ } \
+ } \
+ (void)0
+
+# define opencl_assert(stmt) \
+ { \
+ cl_int err = stmt; \
+\
+ if (err != CL_SUCCESS) { \
+ string message = string_printf( \
+ "OpenCL error: %s in %s (%s:%d)", clewErrorString(err), #stmt, __FILE__, __LINE__); \
+ if (error_msg == "") \
+ error_msg = message; \
+ fprintf(stderr, "%s\n", message.c_str()); \
+ } \
+ } \
+ (void)0
+
+class OpenCLDevice : public Device {
+ public:
+ DedicatedTaskPool task_pool;
+
+ /* Task pool for required kernels (base, AO kernels during foreground rendering) */
+ TaskPool load_required_kernel_task_pool;
+ /* Task pool for optional kernels (feature kernels during foreground rendering) */
+ TaskPool load_kernel_task_pool;
+ cl_context cxContext;
+ cl_command_queue cqCommandQueue;
+ cl_platform_id cpPlatform;
+ cl_device_id cdDevice;
+ cl_int ciErr;
+ int device_num;
+ bool use_preview_kernels;
+
+ class OpenCLProgram {
+ public:
+ OpenCLProgram() : loaded(false), needs_compiling(true), program(NULL), device(NULL)
+ {
+ }
+ OpenCLProgram(OpenCLDevice *device,
+ const string &program_name,
+ const string &kernel_name,
+ const string &kernel_build_options,
+ bool use_stdout = true);
+ ~OpenCLProgram();
+
+ void add_kernel(ustring name);
+
+ /* Try to load the program from device cache or disk */
+ bool load();
+ /* Compile the kernel (first separate, failback to local) */
+ void compile();
+ /* Create the OpenCL kernels after loading or compiling */
+ void create_kernels();
+
+ bool is_loaded() const
+ {
+ return loaded;
+ }
+ const string &get_log() const
+ {
+ return log;
+ }
+ void report_error();
+
+ /* Wait until this kernel is available to be used
+ * It will return true when the kernel is available.
+ * It will return false when the kernel is not available
+ * or could not be loaded. */
+ bool wait_for_availability();
+
+ cl_kernel operator()();
+ cl_kernel operator()(ustring name);
+
+ void release();
+
+ private:
+ bool build_kernel(const string *debug_src);
+ /* Build the program by calling the own process.
+ * This is required for multithreaded OpenCL compilation, since most Frameworks serialize
+ * build calls internally if they come from the same process.
+ * If that is not supported, this function just returns false.
+ */
+ bool compile_separate(const string &clbin);
+ /* Build the program by calling OpenCL directly. */
+ bool compile_kernel(const string *debug_src);
+ /* Loading and saving the program from/to disk. */
+ bool load_binary(const string &clbin, const string *debug_src = NULL);
+ bool save_binary(const string &clbin);
+
+ void add_log(const string &msg, bool is_debug);
+ void add_error(const string &msg);
+
+ bool loaded;
+ bool needs_compiling;
+
+ cl_program program;
+ OpenCLDevice *device;
+
+ /* Used for the OpenCLCache key. */
+ string program_name;
+
+ string kernel_file, kernel_build_options, device_md5;
+
+ bool use_stdout;
+ string log, error_msg;
+ string compile_output;
+
+ map<ustring, cl_kernel> kernels;
+ };
+
+ /* Container for all types of split programs. */
+ class OpenCLSplitPrograms {
+ public:
+ OpenCLDevice *device;
+ OpenCLProgram program_split;
+ OpenCLProgram program_lamp_emission;
+ OpenCLProgram program_do_volume;
+ OpenCLProgram program_indirect_background;
+ OpenCLProgram program_shader_eval;
+ OpenCLProgram program_holdout_emission_blurring_pathtermination_ao;
+ OpenCLProgram program_subsurface_scatter;
+ OpenCLProgram program_direct_lighting;
+ OpenCLProgram program_shadow_blocked_ao;
+ OpenCLProgram program_shadow_blocked_dl;
+
+ OpenCLSplitPrograms(OpenCLDevice *device);
+ ~OpenCLSplitPrograms();
+
+ /* Load the kernels and put the created kernels in the given `programs`
+ * paramter. */
+ void load_kernels(vector<OpenCLProgram *> &programs,
+ const DeviceRequestedFeatures &requested_features,
+ bool is_preview = false);
+ };
+
+ DeviceSplitKernel *split_kernel;
+
+ OpenCLProgram base_program;
+ OpenCLProgram bake_program;
+ OpenCLProgram displace_program;
+ OpenCLProgram background_program;
+ OpenCLProgram denoising_program;
+
+ OpenCLSplitPrograms kernel_programs;
+ OpenCLSplitPrograms preview_programs;
+
+ typedef map<string, device_vector<uchar> *> ConstMemMap;
+ typedef map<string, device_ptr> MemMap;
+
+ ConstMemMap const_mem_map;
+ MemMap mem_map;
+ device_ptr null_mem;
+
+ bool device_initialized;
+ string platform_name;
+ string device_name;
+
+ bool opencl_error(cl_int err);
+ void opencl_error(const string &message);
+ void opencl_assert_err(cl_int err, const char *where);
+
+ OpenCLDevice(DeviceInfo &info, Stats &stats, Profiler &profiler, bool background);
+ ~OpenCLDevice();
+
+ static void CL_CALLBACK context_notify_callback(const char *err_info,
+ const void * /*private_info*/,
+ size_t /*cb*/,
+ void *user_data);
+
+ bool opencl_version_check();
+ OpenCLSplitPrograms *get_split_programs();
+
+ string device_md5_hash(string kernel_custom_build_options = "");
+ bool load_kernels(const DeviceRequestedFeatures &requested_features);
+ void load_required_kernels(const DeviceRequestedFeatures &requested_features);
+ void load_preview_kernels();
+
+ bool wait_for_availability(const DeviceRequestedFeatures &requested_features);
+ DeviceKernelStatus get_active_kernel_switch_state();
+
+ /* Get the name of the opencl program for the given kernel */
+ const string get_opencl_program_name(const string &kernel_name);
+ /* Get the program file name to compile (*.cl) for the given kernel */
+ const string get_opencl_program_filename(const string &kernel_name);
+ string get_build_options(const DeviceRequestedFeatures &requested_features,
+ const string &opencl_program_name,
+ bool preview_kernel = false);
+ /* Enable the default features to reduce recompilation events */
+ void enable_default_features(DeviceRequestedFeatures &features);
+
+ void mem_alloc(device_memory &mem);
+ void mem_copy_to(device_memory &mem);
+ void mem_copy_from(device_memory &mem, int y, int w, int h, int elem);
+ void mem_zero(device_memory &mem);
+ void mem_free(device_memory &mem);
+
+ int mem_sub_ptr_alignment();
+
+ void const_copy_to(const char *name, void *host, size_t size);
+ void tex_alloc(device_memory &mem);
+ void tex_free(device_memory &mem);
+
+ size_t global_size_round_up(int group_size, int global_size);
+ void enqueue_kernel(cl_kernel kernel,
+ size_t w,
+ size_t h,
+ bool x_workgroups = false,
+ size_t max_workgroup_size = -1);
+ void set_kernel_arg_mem(cl_kernel kernel, cl_uint *narg, const char *name);
+ void set_kernel_arg_buffers(cl_kernel kernel, cl_uint *narg);
+
+ void film_convert(DeviceTask &task,
+ device_ptr buffer,
+ device_ptr rgba_byte,
+ device_ptr rgba_half);
+ void shader(DeviceTask &task);
+
+ void denoise(RenderTile &tile, DenoisingTask &denoising);
+
+ class OpenCLDeviceTask : public DeviceTask {
+ public:
+ OpenCLDeviceTask(OpenCLDevice *device, DeviceTask &task) : DeviceTask(task)
+ {
+ run = function_bind(&OpenCLDevice::thread_run, device, this);
+ }
+ };
+
+ int get_split_task_count(DeviceTask & /*task*/)
+ {
+ return 1;
+ }
+
+ void task_add(DeviceTask &task)
+ {
+ task_pool.push(new OpenCLDeviceTask(this, task));
+ }
+
+ void task_wait()
+ {
+ task_pool.wait();
+ }
+
+ void task_cancel()
+ {
+ task_pool.cancel();
+ }
+
+ void thread_run(DeviceTask *task);
+
+ virtual BVHLayoutMask get_bvh_layout_mask() const
+ {
+ return BVH_LAYOUT_BVH2;
+ }
+
+ virtual bool show_samples() const
+ {
+ return true;
+ }
+
+ protected:
+ string kernel_build_options(const string *debug_src = NULL);
+
+ void mem_zero_kernel(device_ptr ptr, size_t size);
+
+ bool denoising_non_local_means(device_ptr image_ptr,
+ device_ptr guide_ptr,
+ device_ptr variance_ptr,
+ device_ptr out_ptr,
+ DenoisingTask *task);
+ bool denoising_construct_transform(DenoisingTask *task);
+ bool denoising_accumulate(device_ptr color_ptr,
+ device_ptr color_variance_ptr,
+ device_ptr scale_ptr,
+ int frame,
+ DenoisingTask *task);
+ bool denoising_solve(device_ptr output_ptr, DenoisingTask *task);
+ bool denoising_combine_halves(device_ptr a_ptr,
+ device_ptr b_ptr,
+ device_ptr mean_ptr,
+ device_ptr variance_ptr,
+ int r,
+ int4 rect,
+ DenoisingTask *task);
+ bool denoising_divide_shadow(device_ptr a_ptr,
+ device_ptr b_ptr,
+ device_ptr sample_variance_ptr,
+ device_ptr sv_variance_ptr,
+ device_ptr buffer_variance_ptr,
+ DenoisingTask *task);
+ bool denoising_get_feature(int mean_offset,
+ int variance_offset,
+ device_ptr mean_ptr,
+ device_ptr variance_ptr,
+ float scale,
+ DenoisingTask *task);
+ bool denoising_write_feature(int to_offset,
+ device_ptr from_ptr,
+ device_ptr buffer_ptr,
+ DenoisingTask *task);
+ bool denoising_detect_outliers(device_ptr image_ptr,
+ device_ptr variance_ptr,
+ device_ptr depth_ptr,
+ device_ptr output_ptr,
+ DenoisingTask *task);
+
+ device_ptr mem_alloc_sub_ptr(device_memory &mem, int offset, int size);
+ void mem_free_sub_ptr(device_ptr ptr);
+
+ class ArgumentWrapper {
+ public:
+ ArgumentWrapper() : size(0), pointer(NULL)
+ {
+ }
+
+ ArgumentWrapper(device_memory &argument)
+ : size(sizeof(void *)), pointer((void *)(&argument.device_pointer))
+ {
+ }
+
+ template<typename T>
+ ArgumentWrapper(device_vector<T> &argument)
+ : size(sizeof(void *)), pointer((void *)(&argument.device_pointer))
+ {
+ }
+
+ template<typename T>
+ ArgumentWrapper(device_only_memory<T> &argument)
+ : size(sizeof(void *)), pointer((void *)(&argument.device_pointer))
+ {
+ }
+ template<typename T> ArgumentWrapper(T &argument) : size(sizeof(argument)), pointer(&argument)
+ {
+ }
+
+ ArgumentWrapper(int argument) : size(sizeof(int)), int_value(argument), pointer(&int_value)
+ {
+ }
+
+ ArgumentWrapper(float argument)
+ : size(sizeof(float)), float_value(argument), pointer(&float_value)
+ {
+ }
+
+ size_t size;
+ int int_value;
+ float float_value;
+ void *pointer;
+ };
+
+ /* TODO(sergey): In the future we can use variadic templates, once
+ * C++0x is allowed. Should allow to clean this up a bit.
+ */
+ int kernel_set_args(cl_kernel kernel,
+ int start_argument_index,
+ const ArgumentWrapper &arg1 = ArgumentWrapper(),
+ const ArgumentWrapper &arg2 = ArgumentWrapper(),
+ const ArgumentWrapper &arg3 = ArgumentWrapper(),
+ const ArgumentWrapper &arg4 = ArgumentWrapper(),
+ const ArgumentWrapper &arg5 = ArgumentWrapper(),
+ const ArgumentWrapper &arg6 = ArgumentWrapper(),
+ const ArgumentWrapper &arg7 = ArgumentWrapper(),
+ const ArgumentWrapper &arg8 = ArgumentWrapper(),
+ const ArgumentWrapper &arg9 = ArgumentWrapper(),
+ const ArgumentWrapper &arg10 = ArgumentWrapper(),
+ const ArgumentWrapper &arg11 = ArgumentWrapper(),
+ const ArgumentWrapper &arg12 = ArgumentWrapper(),
+ const ArgumentWrapper &arg13 = ArgumentWrapper(),
+ const ArgumentWrapper &arg14 = ArgumentWrapper(),
+ const ArgumentWrapper &arg15 = ArgumentWrapper(),
+ const ArgumentWrapper &arg16 = ArgumentWrapper(),
+ const ArgumentWrapper &arg17 = ArgumentWrapper(),
+ const ArgumentWrapper &arg18 = ArgumentWrapper(),
+ const ArgumentWrapper &arg19 = ArgumentWrapper(),
+ const ArgumentWrapper &arg20 = ArgumentWrapper(),
+ const ArgumentWrapper &arg21 = ArgumentWrapper(),
+ const ArgumentWrapper &arg22 = ArgumentWrapper(),
+ const ArgumentWrapper &arg23 = ArgumentWrapper(),
+ const ArgumentWrapper &arg24 = ArgumentWrapper(),
+ const ArgumentWrapper &arg25 = ArgumentWrapper(),
+ const ArgumentWrapper &arg26 = ArgumentWrapper(),
+ const ArgumentWrapper &arg27 = ArgumentWrapper(),
+ const ArgumentWrapper &arg28 = ArgumentWrapper(),
+ const ArgumentWrapper &arg29 = ArgumentWrapper(),
+ const ArgumentWrapper &arg30 = ArgumentWrapper(),
+ const ArgumentWrapper &arg31 = ArgumentWrapper(),
+ const ArgumentWrapper &arg32 = ArgumentWrapper(),
+ const ArgumentWrapper &arg33 = ArgumentWrapper());
+
+ void release_kernel_safe(cl_kernel kernel);
+ void release_mem_object_safe(cl_mem mem);
+ void release_program_safe(cl_program program);
+
+ /* ** Those guys are for workign around some compiler-specific bugs ** */
+
+ cl_program load_cached_kernel(ustring key, thread_scoped_lock &cache_locker);
+
+ void store_cached_kernel(cl_program program, ustring key, thread_scoped_lock &cache_locker);
+
+ private:
+ MemoryManager memory_manager;
+ friend class MemoryManager;
+
+ static_assert_align(TextureInfo, 16);
+ device_vector<TextureInfo> texture_info;
+
+ typedef map<string, device_memory *> TexturesMap;
+ TexturesMap textures;
+
+ bool textures_need_update;
+
+ protected:
+ void flush_texture_buffers();
+
+ friend class OpenCLSplitKernel;
+ friend class OpenCLSplitKernelFunction;
};
-Device *opencl_create_split_device(DeviceInfo& info, Stats& stats, Profiler &profiler, bool background);
+Device *opencl_create_split_device(DeviceInfo &info,
+ Stats &stats,
+ Profiler &profiler,
+ bool background);
CCL_NAMESPACE_END
diff --git a/intern/cycles/device/opencl/opencl_split.cpp b/intern/cycles/device/opencl/opencl_split.cpp
index 489d10b7087..70b1a643044 100644
--- a/intern/cycles/device/opencl/opencl_split.cpp
+++ b/intern/cycles/device/opencl/opencl_split.cpp
@@ -16,273 +16,278 @@
#ifdef WITH_OPENCL
-#include "device/opencl/opencl.h"
+# include "device/opencl/opencl.h"
-#include "kernel/kernel_types.h"
-#include "kernel/split/kernel_split_data_types.h"
+# include "kernel/kernel_types.h"
+# include "kernel/split/kernel_split_data_types.h"
-#include "util/util_algorithm.h"
-#include "util/util_debug.h"
-#include "util/util_foreach.h"
-#include "util/util_logging.h"
-#include "util/util_md5.h"
-#include "util/util_path.h"
-#include "util/util_time.h"
+# include "util/util_algorithm.h"
+# include "util/util_debug.h"
+# include "util/util_foreach.h"
+# include "util/util_logging.h"
+# include "util/util_md5.h"
+# include "util/util_path.h"
+# include "util/util_time.h"
CCL_NAMESPACE_BEGIN
struct texture_slot_t {
- texture_slot_t(const string& name, int slot)
- : name(name),
- slot(slot) {
- }
- string name;
- int slot;
+ texture_slot_t(const string &name, int slot) : name(name), slot(slot)
+ {
+ }
+ string name;
+ int slot;
};
static const string NON_SPLIT_KERNELS =
- "denoising "
- "base "
- "background "
- "displace ";
+ "denoising "
+ "base "
+ "background "
+ "displace ";
static const string SPLIT_BUNDLE_KERNELS =
- "data_init "
- "path_init "
- "state_buffer_size "
- "scene_intersect "
- "queue_enqueue "
- "shader_setup "
- "shader_sort "
- "enqueue_inactive "
- "next_iteration_setup "
- "indirect_subsurface "
- "buffer_update";
-
-const string OpenCLDevice::get_opencl_program_name(const string& kernel_name)
+ "data_init "
+ "path_init "
+ "state_buffer_size "
+ "scene_intersect "
+ "queue_enqueue "
+ "shader_setup "
+ "shader_sort "
+ "enqueue_inactive "
+ "next_iteration_setup "
+ "indirect_subsurface "
+ "buffer_update";
+
+const string OpenCLDevice::get_opencl_program_name(const string &kernel_name)
{
- if (NON_SPLIT_KERNELS.find(kernel_name) != std::string::npos) {
- return kernel_name;
- }
- else if (SPLIT_BUNDLE_KERNELS.find(kernel_name) != std::string::npos) {
- return "split_bundle";
- }
- else {
- return "split_" + kernel_name;
- }
+ if (NON_SPLIT_KERNELS.find(kernel_name) != std::string::npos) {
+ return kernel_name;
+ }
+ else if (SPLIT_BUNDLE_KERNELS.find(kernel_name) != std::string::npos) {
+ return "split_bundle";
+ }
+ else {
+ return "split_" + kernel_name;
+ }
}
-const string OpenCLDevice::get_opencl_program_filename(const string& kernel_name)
+const string OpenCLDevice::get_opencl_program_filename(const string &kernel_name)
{
- if (kernel_name == "denoising") {
- return "filter.cl";
- }
- else if (SPLIT_BUNDLE_KERNELS.find(kernel_name) != std::string::npos) {
- return "kernel_split_bundle.cl";
- }
- else {
- return "kernel_" + kernel_name + ".cl";
- }
+ if (kernel_name == "denoising") {
+ return "filter.cl";
+ }
+ else if (SPLIT_BUNDLE_KERNELS.find(kernel_name) != std::string::npos) {
+ return "kernel_split_bundle.cl";
+ }
+ else {
+ return "kernel_" + kernel_name + ".cl";
+ }
}
/* Enable features that we always want to compile to reduce recompilation events */
-void OpenCLDevice::enable_default_features(DeviceRequestedFeatures& features)
+void OpenCLDevice::enable_default_features(DeviceRequestedFeatures &features)
{
- features.use_transparent = true;
- features.use_shadow_tricks = true;
- features.use_principled = true;
- features.use_denoising = true;
-
- if (!background)
- {
- features.max_nodes_group = NODE_GROUP_LEVEL_MAX;
- features.nodes_features = NODE_FEATURE_ALL;
- features.use_hair = true;
- features.use_subsurface = true;
- features.use_camera_motion = false;
- features.use_object_motion = false;
- }
+ features.use_transparent = true;
+ features.use_shadow_tricks = true;
+ features.use_principled = true;
+ features.use_denoising = true;
+
+ if (!background) {
+ features.max_nodes_group = NODE_GROUP_LEVEL_MAX;
+ features.nodes_features = NODE_FEATURE_ALL;
+ features.use_hair = true;
+ features.use_subsurface = true;
+ features.use_camera_motion = false;
+ features.use_object_motion = false;
+ }
}
-string OpenCLDevice::get_build_options(const DeviceRequestedFeatures& requested_features, const string& opencl_program_name, bool preview_kernel)
+string OpenCLDevice::get_build_options(const DeviceRequestedFeatures &requested_features,
+ const string &opencl_program_name,
+ bool preview_kernel)
{
- /* first check for non-split kernel programs */
- if (opencl_program_name == "base" || opencl_program_name == "denoising") {
- return "";
- }
- else if (opencl_program_name == "bake") {
- /* Note: get_build_options for bake is only requested when baking is enabled.
- * displace and background are always requested.
- * `__SPLIT_KERNEL__` must not be present in the compile directives for bake */
- DeviceRequestedFeatures features(requested_features);
- enable_default_features(features);
- features.use_denoising = false;
- features.use_object_motion = false;
- features.use_camera_motion = false;
- features.use_hair = true;
- features.use_subsurface = true;
- features.max_nodes_group = NODE_GROUP_LEVEL_MAX;
- features.nodes_features = NODE_FEATURE_ALL;
- features.use_integrator_branched = false;
- return features.get_build_options();
- }
- else if (opencl_program_name == "displace") {
- /* As displacement does not use any nodes from the Shading group (eg BSDF).
- * We disable all features that are related to shading. */
- DeviceRequestedFeatures features(requested_features);
- enable_default_features(features);
- features.use_denoising = false;
- features.use_object_motion = false;
- features.use_camera_motion = false;
- features.use_baking = false;
- features.use_transparent = false;
- features.use_shadow_tricks = false;
- features.use_subsurface = false;
- features.use_volume = false;
- features.nodes_features &= ~NODE_FEATURE_VOLUME;
- features.use_denoising = false;
- features.use_principled = false;
- features.use_integrator_branched = false;
- return features.get_build_options();
- }
- else if (opencl_program_name == "background") {
- /* Background uses Background shading
- * It is save to disable shadow features, subsurface and volumetric. */
- DeviceRequestedFeatures features(requested_features);
- enable_default_features(features);
- features.use_baking = false;
- features.use_object_motion = false;
- features.use_camera_motion = false;
- features.use_transparent = false;
- features.use_shadow_tricks = false;
- features.use_denoising = false;
- /* NOTE: currently possible to use surface nodes like `Hair Info`, `Bump` node.
- * Perhaps we should remove them in UI as it does not make any sense when
- * rendering background. */
- features.nodes_features &= ~NODE_FEATURE_VOLUME;
- features.use_subsurface = false;
- features.use_volume = false;
- features.use_shader_raytrace = false;
- features.use_patch_evaluation = false;
- features.use_integrator_branched = false;
- return features.get_build_options();
- }
-
- string build_options = "-D__SPLIT_KERNEL__ ";
- /* Set compute device build option. */
- cl_device_type device_type;
- OpenCLInfo::get_device_type(this->cdDevice, &device_type, &this->ciErr);
- assert(this->ciErr == CL_SUCCESS);
- if(device_type == CL_DEVICE_TYPE_GPU) {
- build_options += "-D__COMPUTE_DEVICE_GPU__ ";
- }
-
- DeviceRequestedFeatures nofeatures;
- enable_default_features(nofeatures);
-
- /* Add program specific optimized compile directives */
- if (preview_kernel) {
- DeviceRequestedFeatures preview_features;
- preview_features.use_hair = true;
- build_options += "-D__KERNEL_AO_PREVIEW__ ";
- build_options += preview_features.get_build_options();
- }
- else if (opencl_program_name == "split_do_volume" && !requested_features.use_volume) {
- build_options += nofeatures.get_build_options();
- }
- else {
- DeviceRequestedFeatures features(requested_features);
- enable_default_features(features);
-
- /* Always turn off baking at this point. Baking is only usefull when building the bake kernel.
- * this also makes sure that the kernels that are build during baking can be reused
- * when not doing any baking. */
- features.use_baking = false;
-
- /* Do not vary on shaders when program doesn't do any shading.
- * We have bundled them in a single program. */
- if (opencl_program_name == "split_bundle") {
- features.max_nodes_group = 0;
- features.nodes_features = 0;
- features.use_shader_raytrace = false;
- }
-
- /* No specific settings, just add the regular ones */
- build_options += features.get_build_options();
- }
-
- return build_options;
+ /* first check for non-split kernel programs */
+ if (opencl_program_name == "base" || opencl_program_name == "denoising") {
+ return "";
+ }
+ else if (opencl_program_name == "bake") {
+ /* Note: get_build_options for bake is only requested when baking is enabled.
+ * displace and background are always requested.
+ * `__SPLIT_KERNEL__` must not be present in the compile directives for bake */
+ DeviceRequestedFeatures features(requested_features);
+ enable_default_features(features);
+ features.use_denoising = false;
+ features.use_object_motion = false;
+ features.use_camera_motion = false;
+ features.use_hair = true;
+ features.use_subsurface = true;
+ features.max_nodes_group = NODE_GROUP_LEVEL_MAX;
+ features.nodes_features = NODE_FEATURE_ALL;
+ features.use_integrator_branched = false;
+ return features.get_build_options();
+ }
+ else if (opencl_program_name == "displace") {
+ /* As displacement does not use any nodes from the Shading group (eg BSDF).
+ * We disable all features that are related to shading. */
+ DeviceRequestedFeatures features(requested_features);
+ enable_default_features(features);
+ features.use_denoising = false;
+ features.use_object_motion = false;
+ features.use_camera_motion = false;
+ features.use_baking = false;
+ features.use_transparent = false;
+ features.use_shadow_tricks = false;
+ features.use_subsurface = false;
+ features.use_volume = false;
+ features.nodes_features &= ~NODE_FEATURE_VOLUME;
+ features.use_denoising = false;
+ features.use_principled = false;
+ features.use_integrator_branched = false;
+ return features.get_build_options();
+ }
+ else if (opencl_program_name == "background") {
+ /* Background uses Background shading
+ * It is save to disable shadow features, subsurface and volumetric. */
+ DeviceRequestedFeatures features(requested_features);
+ enable_default_features(features);
+ features.use_baking = false;
+ features.use_object_motion = false;
+ features.use_camera_motion = false;
+ features.use_transparent = false;
+ features.use_shadow_tricks = false;
+ features.use_denoising = false;
+ /* NOTE: currently possible to use surface nodes like `Hair Info`, `Bump` node.
+ * Perhaps we should remove them in UI as it does not make any sense when
+ * rendering background. */
+ features.nodes_features &= ~NODE_FEATURE_VOLUME;
+ features.use_subsurface = false;
+ features.use_volume = false;
+ features.use_shader_raytrace = false;
+ features.use_patch_evaluation = false;
+ features.use_integrator_branched = false;
+ return features.get_build_options();
+ }
+
+ string build_options = "-D__SPLIT_KERNEL__ ";
+ /* Set compute device build option. */
+ cl_device_type device_type;
+ OpenCLInfo::get_device_type(this->cdDevice, &device_type, &this->ciErr);
+ assert(this->ciErr == CL_SUCCESS);
+ if (device_type == CL_DEVICE_TYPE_GPU) {
+ build_options += "-D__COMPUTE_DEVICE_GPU__ ";
+ }
+
+ DeviceRequestedFeatures nofeatures;
+ enable_default_features(nofeatures);
+
+ /* Add program specific optimized compile directives */
+ if (preview_kernel) {
+ DeviceRequestedFeatures preview_features;
+ preview_features.use_hair = true;
+ build_options += "-D__KERNEL_AO_PREVIEW__ ";
+ build_options += preview_features.get_build_options();
+ }
+ else if (opencl_program_name == "split_do_volume" && !requested_features.use_volume) {
+ build_options += nofeatures.get_build_options();
+ }
+ else {
+ DeviceRequestedFeatures features(requested_features);
+ enable_default_features(features);
+
+ /* Always turn off baking at this point. Baking is only usefull when building the bake kernel.
+ * this also makes sure that the kernels that are build during baking can be reused
+ * when not doing any baking. */
+ features.use_baking = false;
+
+ /* Do not vary on shaders when program doesn't do any shading.
+ * We have bundled them in a single program. */
+ if (opencl_program_name == "split_bundle") {
+ features.max_nodes_group = 0;
+ features.nodes_features = 0;
+ features.use_shader_raytrace = false;
+ }
+
+ /* No specific settings, just add the regular ones */
+ build_options += features.get_build_options();
+ }
+
+ return build_options;
}
OpenCLDevice::OpenCLSplitPrograms::OpenCLSplitPrograms(OpenCLDevice *device_)
{
- device = device_;
+ device = device_;
}
OpenCLDevice::OpenCLSplitPrograms::~OpenCLSplitPrograms()
{
- program_split.release();
- program_lamp_emission.release();
- program_do_volume.release();
- program_indirect_background.release();
- program_shader_eval.release();
- program_holdout_emission_blurring_pathtermination_ao.release();
- program_subsurface_scatter.release();
- program_direct_lighting.release();
- program_shadow_blocked_ao.release();
- program_shadow_blocked_dl.release();
+ program_split.release();
+ program_lamp_emission.release();
+ program_do_volume.release();
+ program_indirect_background.release();
+ program_shader_eval.release();
+ program_holdout_emission_blurring_pathtermination_ao.release();
+ program_subsurface_scatter.release();
+ program_direct_lighting.release();
+ program_shadow_blocked_ao.release();
+ program_shadow_blocked_dl.release();
}
-void OpenCLDevice::OpenCLSplitPrograms::load_kernels(vector<OpenCLProgram*> &programs, const DeviceRequestedFeatures& requested_features, bool is_preview)
+void OpenCLDevice::OpenCLSplitPrograms::load_kernels(
+ vector<OpenCLProgram *> &programs,
+ const DeviceRequestedFeatures &requested_features,
+ bool is_preview)
{
- if (!requested_features.use_baking) {
-#define ADD_SPLIT_KERNEL_BUNDLE_PROGRAM(kernel_name) program_split.add_kernel(ustring("path_trace_"#kernel_name));
-#define ADD_SPLIT_KERNEL_PROGRAM(kernel_name) \
- const string program_name_##kernel_name = "split_"#kernel_name; \
- program_##kernel_name = \
- OpenCLDevice::OpenCLProgram(device, \
- program_name_##kernel_name, \
- "kernel_"#kernel_name".cl", \
- device->get_build_options(requested_features, program_name_##kernel_name, is_preview)); \
- program_##kernel_name.add_kernel(ustring("path_trace_"#kernel_name)); \
- programs.push_back(&program_##kernel_name);
-
- /* Ordered with most complex kernels first, to reduce overall compile time. */
- ADD_SPLIT_KERNEL_PROGRAM(subsurface_scatter);
- if (requested_features.use_volume || is_preview) {
- ADD_SPLIT_KERNEL_PROGRAM(do_volume);
- }
- ADD_SPLIT_KERNEL_PROGRAM(shadow_blocked_dl);
- ADD_SPLIT_KERNEL_PROGRAM(shadow_blocked_ao);
- ADD_SPLIT_KERNEL_PROGRAM(holdout_emission_blurring_pathtermination_ao);
- ADD_SPLIT_KERNEL_PROGRAM(lamp_emission);
- ADD_SPLIT_KERNEL_PROGRAM(direct_lighting);
- ADD_SPLIT_KERNEL_PROGRAM(indirect_background);
- ADD_SPLIT_KERNEL_PROGRAM(shader_eval);
-
- /* Quick kernels bundled in a single program to reduce overhead of starting
- * Blender processes. */
- program_split = OpenCLDevice::OpenCLProgram(device,
- "split_bundle" ,
- "kernel_split_bundle.cl",
- device->get_build_options(requested_features, "split_bundle", is_preview));
-
- ADD_SPLIT_KERNEL_BUNDLE_PROGRAM(data_init);
- ADD_SPLIT_KERNEL_BUNDLE_PROGRAM(state_buffer_size);
- ADD_SPLIT_KERNEL_BUNDLE_PROGRAM(path_init);
- ADD_SPLIT_KERNEL_BUNDLE_PROGRAM(scene_intersect);
- ADD_SPLIT_KERNEL_BUNDLE_PROGRAM(queue_enqueue);
- ADD_SPLIT_KERNEL_BUNDLE_PROGRAM(shader_setup);
- ADD_SPLIT_KERNEL_BUNDLE_PROGRAM(shader_sort);
- ADD_SPLIT_KERNEL_BUNDLE_PROGRAM(enqueue_inactive);
- ADD_SPLIT_KERNEL_BUNDLE_PROGRAM(next_iteration_setup);
- ADD_SPLIT_KERNEL_BUNDLE_PROGRAM(indirect_subsurface);
- ADD_SPLIT_KERNEL_BUNDLE_PROGRAM(buffer_update);
- programs.push_back(&program_split);
-
-#undef ADD_SPLIT_KERNEL_PROGRAM
-#undef ADD_SPLIT_KERNEL_BUNDLE_PROGRAM
- }
+ if (!requested_features.use_baking) {
+# define ADD_SPLIT_KERNEL_BUNDLE_PROGRAM(kernel_name) \
+ program_split.add_kernel(ustring("path_trace_" #kernel_name));
+# define ADD_SPLIT_KERNEL_PROGRAM(kernel_name) \
+ const string program_name_##kernel_name = "split_" #kernel_name; \
+ program_##kernel_name = OpenCLDevice::OpenCLProgram( \
+ device, \
+ program_name_##kernel_name, \
+ "kernel_" #kernel_name ".cl", \
+ device->get_build_options(requested_features, program_name_##kernel_name, is_preview)); \
+ program_##kernel_name.add_kernel(ustring("path_trace_" #kernel_name)); \
+ programs.push_back(&program_##kernel_name);
+
+ /* Ordered with most complex kernels first, to reduce overall compile time. */
+ ADD_SPLIT_KERNEL_PROGRAM(subsurface_scatter);
+ if (requested_features.use_volume || is_preview) {
+ ADD_SPLIT_KERNEL_PROGRAM(do_volume);
+ }
+ ADD_SPLIT_KERNEL_PROGRAM(shadow_blocked_dl);
+ ADD_SPLIT_KERNEL_PROGRAM(shadow_blocked_ao);
+ ADD_SPLIT_KERNEL_PROGRAM(holdout_emission_blurring_pathtermination_ao);
+ ADD_SPLIT_KERNEL_PROGRAM(lamp_emission);
+ ADD_SPLIT_KERNEL_PROGRAM(direct_lighting);
+ ADD_SPLIT_KERNEL_PROGRAM(indirect_background);
+ ADD_SPLIT_KERNEL_PROGRAM(shader_eval);
+
+ /* Quick kernels bundled in a single program to reduce overhead of starting
+ * Blender processes. */
+ program_split = OpenCLDevice::OpenCLProgram(
+ device,
+ "split_bundle",
+ "kernel_split_bundle.cl",
+ device->get_build_options(requested_features, "split_bundle", is_preview));
+
+ ADD_SPLIT_KERNEL_BUNDLE_PROGRAM(data_init);
+ ADD_SPLIT_KERNEL_BUNDLE_PROGRAM(state_buffer_size);
+ ADD_SPLIT_KERNEL_BUNDLE_PROGRAM(path_init);
+ ADD_SPLIT_KERNEL_BUNDLE_PROGRAM(scene_intersect);
+ ADD_SPLIT_KERNEL_BUNDLE_PROGRAM(queue_enqueue);
+ ADD_SPLIT_KERNEL_BUNDLE_PROGRAM(shader_setup);
+ ADD_SPLIT_KERNEL_BUNDLE_PROGRAM(shader_sort);
+ ADD_SPLIT_KERNEL_BUNDLE_PROGRAM(enqueue_inactive);
+ ADD_SPLIT_KERNEL_BUNDLE_PROGRAM(next_iteration_setup);
+ ADD_SPLIT_KERNEL_BUNDLE_PROGRAM(indirect_subsurface);
+ ADD_SPLIT_KERNEL_BUNDLE_PROGRAM(buffer_update);
+ programs.push_back(&program_split);
+
+# undef ADD_SPLIT_KERNEL_PROGRAM
+# undef ADD_SPLIT_KERNEL_BUNDLE_PROGRAM
+ }
}
namespace {
@@ -291,1126 +296,1108 @@ namespace {
* fetch its size.
*/
typedef struct KernelGlobalsDummy {
- ccl_constant KernelData *data;
- ccl_global char *buffers[8];
+ ccl_constant KernelData *data;
+ ccl_global char *buffers[8];
-#define KERNEL_TEX(type, name) \
- TextureInfo name;
+# define KERNEL_TEX(type, name) TextureInfo name;
# include "kernel/kernel_textures.h"
-#undef KERNEL_TEX
- SplitData split_data;
- SplitParams split_param_data;
+# undef KERNEL_TEX
+ SplitData split_data;
+ SplitParams split_param_data;
} KernelGlobalsDummy;
} // namespace
-
struct CachedSplitMemory {
- int id;
- device_memory *split_data;
- device_memory *ray_state;
- device_memory *queue_index;
- device_memory *use_queues_flag;
- device_memory *work_pools;
- device_ptr *buffer;
+ int id;
+ device_memory *split_data;
+ device_memory *ray_state;
+ device_memory *queue_index;
+ device_memory *use_queues_flag;
+ device_memory *work_pools;
+ device_ptr *buffer;
};
class OpenCLSplitKernelFunction : public SplitKernelFunction {
-public:
- OpenCLDevice* device;
- OpenCLDevice::OpenCLProgram program;
- CachedSplitMemory& cached_memory;
- int cached_id;
-
- OpenCLSplitKernelFunction(OpenCLDevice* device, CachedSplitMemory& cached_memory) :
- device(device), cached_memory(cached_memory), cached_id(cached_memory.id-1)
- {
- }
-
- ~OpenCLSplitKernelFunction()
- {
- program.release();
- }
-
- virtual bool enqueue(const KernelDimensions& dim, device_memory& kg, device_memory& data)
- {
- if(cached_id != cached_memory.id) {
- cl_uint start_arg_index =
- device->kernel_set_args(program(),
- 0,
- kg,
- data,
- *cached_memory.split_data,
- *cached_memory.ray_state);
-
- device->set_kernel_arg_buffers(program(), &start_arg_index);
-
- start_arg_index +=
- device->kernel_set_args(program(),
- start_arg_index,
- *cached_memory.queue_index,
- *cached_memory.use_queues_flag,
- *cached_memory.work_pools,
- *cached_memory.buffer);
-
- cached_id = cached_memory.id;
- }
-
- device->ciErr = clEnqueueNDRangeKernel(device->cqCommandQueue,
- program(),
- 2,
- NULL,
- dim.global_size,
- dim.local_size,
- 0,
- NULL,
- NULL);
-
- device->opencl_assert_err(device->ciErr, "clEnqueueNDRangeKernel");
-
- if(device->ciErr != CL_SUCCESS) {
- string message = string_printf("OpenCL error: %s in clEnqueueNDRangeKernel()",
- clewErrorString(device->ciErr));
- device->opencl_error(message);
- return false;
- }
-
- return true;
- }
+ public:
+ OpenCLDevice *device;
+ OpenCLDevice::OpenCLProgram program;
+ CachedSplitMemory &cached_memory;
+ int cached_id;
+
+ OpenCLSplitKernelFunction(OpenCLDevice *device, CachedSplitMemory &cached_memory)
+ : device(device), cached_memory(cached_memory), cached_id(cached_memory.id - 1)
+ {
+ }
+
+ ~OpenCLSplitKernelFunction()
+ {
+ program.release();
+ }
+
+ virtual bool enqueue(const KernelDimensions &dim, device_memory &kg, device_memory &data)
+ {
+ if (cached_id != cached_memory.id) {
+ cl_uint start_arg_index = device->kernel_set_args(
+ program(), 0, kg, data, *cached_memory.split_data, *cached_memory.ray_state);
+
+ device->set_kernel_arg_buffers(program(), &start_arg_index);
+
+ start_arg_index += device->kernel_set_args(program(),
+ start_arg_index,
+ *cached_memory.queue_index,
+ *cached_memory.use_queues_flag,
+ *cached_memory.work_pools,
+ *cached_memory.buffer);
+
+ cached_id = cached_memory.id;
+ }
+
+ device->ciErr = clEnqueueNDRangeKernel(device->cqCommandQueue,
+ program(),
+ 2,
+ NULL,
+ dim.global_size,
+ dim.local_size,
+ 0,
+ NULL,
+ NULL);
+
+ device->opencl_assert_err(device->ciErr, "clEnqueueNDRangeKernel");
+
+ if (device->ciErr != CL_SUCCESS) {
+ string message = string_printf("OpenCL error: %s in clEnqueueNDRangeKernel()",
+ clewErrorString(device->ciErr));
+ device->opencl_error(message);
+ return false;
+ }
+
+ return true;
+ }
};
class OpenCLSplitKernel : public DeviceSplitKernel {
- OpenCLDevice *device;
- CachedSplitMemory cached_memory;
-public:
- explicit OpenCLSplitKernel(OpenCLDevice *device) : DeviceSplitKernel(device), device(device) {
- }
-
- virtual SplitKernelFunction* get_split_kernel_function(const string& kernel_name,
- const DeviceRequestedFeatures& requested_features)
- {
- OpenCLSplitKernelFunction* kernel = new OpenCLSplitKernelFunction(device, cached_memory);
-
- const string program_name = device->get_opencl_program_name(kernel_name);
- kernel->program =
- OpenCLDevice::OpenCLProgram(device,
- program_name,
- device->get_opencl_program_filename(kernel_name),
- device->get_build_options(requested_features,
- program_name,
- device->use_preview_kernels));
-
- kernel->program.add_kernel(ustring("path_trace_" + kernel_name));
- kernel->program.load();
-
- if(!kernel->program.is_loaded()) {
- delete kernel;
- return NULL;
- }
-
- return kernel;
- }
-
- virtual uint64_t state_buffer_size(device_memory& kg, device_memory& data, size_t num_threads)
- {
- device_vector<uint64_t> size_buffer(device, "size_buffer", MEM_READ_WRITE);
- size_buffer.alloc(1);
- size_buffer.zero_to_device();
-
- uint threads = num_threads;
- OpenCLDevice::OpenCLSplitPrograms *programs = device->get_split_programs();
- cl_kernel kernel_state_buffer_size = programs->program_split(ustring("path_trace_state_buffer_size"));
- device->kernel_set_args(kernel_state_buffer_size, 0, kg, data, threads, size_buffer);
-
- size_t global_size = 64;
- device->ciErr = clEnqueueNDRangeKernel(device->cqCommandQueue,
- kernel_state_buffer_size,
- 1,
- NULL,
- &global_size,
- NULL,
- 0,
- NULL,
- NULL);
-
- device->opencl_assert_err(device->ciErr, "clEnqueueNDRangeKernel");
-
- size_buffer.copy_from_device(0, 1, 1);
- size_t size = size_buffer[0];
- size_buffer.free();
-
- if(device->ciErr != CL_SUCCESS) {
- string message = string_printf("OpenCL error: %s in clEnqueueNDRangeKernel()",
- clewErrorString(device->ciErr));
- device->opencl_error(message);
- return 0;
- }
-
- return size;
- }
-
- virtual bool enqueue_split_kernel_data_init(const KernelDimensions& dim,
- RenderTile& rtile,
- int num_global_elements,
- device_memory& kernel_globals,
- device_memory& kernel_data,
- device_memory& split_data,
- device_memory& ray_state,
- device_memory& queue_index,
- device_memory& use_queues_flag,
- device_memory& work_pool_wgs
- )
- {
- cl_int dQueue_size = dim.global_size[0] * dim.global_size[1];
-
- /* Set the range of samples to be processed for every ray in
- * path-regeneration logic.
- */
- cl_int start_sample = rtile.start_sample;
- cl_int end_sample = rtile.start_sample + rtile.num_samples;
-
- OpenCLDevice::OpenCLSplitPrograms *programs = device->get_split_programs();
- cl_kernel kernel_data_init = programs->program_split(ustring("path_trace_data_init"));
-
- cl_uint start_arg_index =
- device->kernel_set_args(kernel_data_init,
- 0,
- kernel_globals,
- kernel_data,
- split_data,
- num_global_elements,
- ray_state);
-
- device->set_kernel_arg_buffers(kernel_data_init, &start_arg_index);
-
- start_arg_index +=
- device->kernel_set_args(kernel_data_init,
- start_arg_index,
- start_sample,
- end_sample,
- rtile.x,
- rtile.y,
- rtile.w,
- rtile.h,
- rtile.offset,
- rtile.stride,
- queue_index,
- dQueue_size,
- use_queues_flag,
- work_pool_wgs,
- rtile.num_samples,
- rtile.buffer);
-
- /* Enqueue ckPathTraceKernel_data_init kernel. */
- device->ciErr = clEnqueueNDRangeKernel(device->cqCommandQueue,
- kernel_data_init,
- 2,
- NULL,
- dim.global_size,
- dim.local_size,
- 0,
- NULL,
- NULL);
-
- device->opencl_assert_err(device->ciErr, "clEnqueueNDRangeKernel");
-
- if(device->ciErr != CL_SUCCESS) {
- string message = string_printf("OpenCL error: %s in clEnqueueNDRangeKernel()",
- clewErrorString(device->ciErr));
- device->opencl_error(message);
- return false;
- }
-
- cached_memory.split_data = &split_data;
- cached_memory.ray_state = &ray_state;
- cached_memory.queue_index = &queue_index;
- cached_memory.use_queues_flag = &use_queues_flag;
- cached_memory.work_pools = &work_pool_wgs;
- cached_memory.buffer = &rtile.buffer;
- cached_memory.id++;
-
- return true;
- }
-
- virtual int2 split_kernel_local_size()
- {
- return make_int2(64, 1);
- }
-
- virtual int2 split_kernel_global_size(device_memory& kg, device_memory& data, DeviceTask * /*task*/)
- {
- cl_device_type type = OpenCLInfo::get_device_type(device->cdDevice);
- /* Use small global size on CPU devices as it seems to be much faster. */
- if(type == CL_DEVICE_TYPE_CPU) {
- VLOG(1) << "Global size: (64, 64).";
- return make_int2(64, 64);
- }
-
- cl_ulong max_buffer_size;
- clGetDeviceInfo(device->cdDevice, CL_DEVICE_MAX_MEM_ALLOC_SIZE, sizeof(cl_ulong), &max_buffer_size, NULL);
-
- if(DebugFlags().opencl.mem_limit) {
- max_buffer_size = min(max_buffer_size,
- cl_ulong(DebugFlags().opencl.mem_limit - device->stats.mem_used));
- }
-
- VLOG(1) << "Maximum device allocation size: "
- << string_human_readable_number(max_buffer_size) << " bytes. ("
- << string_human_readable_size(max_buffer_size) << ").";
-
- /* Limit to 2gb, as we shouldn't need more than that and some devices may support much more. */
- max_buffer_size = min(max_buffer_size / 2, (cl_ulong)2l*1024*1024*1024);
-
- size_t num_elements = max_elements_for_max_buffer_size(kg, data, max_buffer_size);
- int2 global_size = make_int2(max(round_down((int)sqrt(num_elements), 64), 64), (int)sqrt(num_elements));
- VLOG(1) << "Global size: " << global_size << ".";
- return global_size;
- }
+ OpenCLDevice *device;
+ CachedSplitMemory cached_memory;
+
+ public:
+ explicit OpenCLSplitKernel(OpenCLDevice *device) : DeviceSplitKernel(device), device(device)
+ {
+ }
+
+ virtual SplitKernelFunction *get_split_kernel_function(
+ const string &kernel_name, const DeviceRequestedFeatures &requested_features)
+ {
+ OpenCLSplitKernelFunction *kernel = new OpenCLSplitKernelFunction(device, cached_memory);
+
+ const string program_name = device->get_opencl_program_name(kernel_name);
+ kernel->program = OpenCLDevice::OpenCLProgram(
+ device,
+ program_name,
+ device->get_opencl_program_filename(kernel_name),
+ device->get_build_options(requested_features, program_name, device->use_preview_kernels));
+
+ kernel->program.add_kernel(ustring("path_trace_" + kernel_name));
+ kernel->program.load();
+
+ if (!kernel->program.is_loaded()) {
+ delete kernel;
+ return NULL;
+ }
+
+ return kernel;
+ }
+
+ virtual uint64_t state_buffer_size(device_memory &kg, device_memory &data, size_t num_threads)
+ {
+ device_vector<uint64_t> size_buffer(device, "size_buffer", MEM_READ_WRITE);
+ size_buffer.alloc(1);
+ size_buffer.zero_to_device();
+
+ uint threads = num_threads;
+ OpenCLDevice::OpenCLSplitPrograms *programs = device->get_split_programs();
+ cl_kernel kernel_state_buffer_size = programs->program_split(
+ ustring("path_trace_state_buffer_size"));
+ device->kernel_set_args(kernel_state_buffer_size, 0, kg, data, threads, size_buffer);
+
+ size_t global_size = 64;
+ device->ciErr = clEnqueueNDRangeKernel(device->cqCommandQueue,
+ kernel_state_buffer_size,
+ 1,
+ NULL,
+ &global_size,
+ NULL,
+ 0,
+ NULL,
+ NULL);
+
+ device->opencl_assert_err(device->ciErr, "clEnqueueNDRangeKernel");
+
+ size_buffer.copy_from_device(0, 1, 1);
+ size_t size = size_buffer[0];
+ size_buffer.free();
+
+ if (device->ciErr != CL_SUCCESS) {
+ string message = string_printf("OpenCL error: %s in clEnqueueNDRangeKernel()",
+ clewErrorString(device->ciErr));
+ device->opencl_error(message);
+ return 0;
+ }
+
+ return size;
+ }
+
+ virtual bool enqueue_split_kernel_data_init(const KernelDimensions &dim,
+ RenderTile &rtile,
+ int num_global_elements,
+ device_memory &kernel_globals,
+ device_memory &kernel_data,
+ device_memory &split_data,
+ device_memory &ray_state,
+ device_memory &queue_index,
+ device_memory &use_queues_flag,
+ device_memory &work_pool_wgs)
+ {
+ cl_int dQueue_size = dim.global_size[0] * dim.global_size[1];
+
+ /* Set the range of samples to be processed for every ray in
+ * path-regeneration logic.
+ */
+ cl_int start_sample = rtile.start_sample;
+ cl_int end_sample = rtile.start_sample + rtile.num_samples;
+
+ OpenCLDevice::OpenCLSplitPrograms *programs = device->get_split_programs();
+ cl_kernel kernel_data_init = programs->program_split(ustring("path_trace_data_init"));
+
+ cl_uint start_arg_index = device->kernel_set_args(kernel_data_init,
+ 0,
+ kernel_globals,
+ kernel_data,
+ split_data,
+ num_global_elements,
+ ray_state);
+
+ device->set_kernel_arg_buffers(kernel_data_init, &start_arg_index);
+
+ start_arg_index += device->kernel_set_args(kernel_data_init,
+ start_arg_index,
+ start_sample,
+ end_sample,
+ rtile.x,
+ rtile.y,
+ rtile.w,
+ rtile.h,
+ rtile.offset,
+ rtile.stride,
+ queue_index,
+ dQueue_size,
+ use_queues_flag,
+ work_pool_wgs,
+ rtile.num_samples,
+ rtile.buffer);
+
+ /* Enqueue ckPathTraceKernel_data_init kernel. */
+ device->ciErr = clEnqueueNDRangeKernel(device->cqCommandQueue,
+ kernel_data_init,
+ 2,
+ NULL,
+ dim.global_size,
+ dim.local_size,
+ 0,
+ NULL,
+ NULL);
+
+ device->opencl_assert_err(device->ciErr, "clEnqueueNDRangeKernel");
+
+ if (device->ciErr != CL_SUCCESS) {
+ string message = string_printf("OpenCL error: %s in clEnqueueNDRangeKernel()",
+ clewErrorString(device->ciErr));
+ device->opencl_error(message);
+ return false;
+ }
+
+ cached_memory.split_data = &split_data;
+ cached_memory.ray_state = &ray_state;
+ cached_memory.queue_index = &queue_index;
+ cached_memory.use_queues_flag = &use_queues_flag;
+ cached_memory.work_pools = &work_pool_wgs;
+ cached_memory.buffer = &rtile.buffer;
+ cached_memory.id++;
+
+ return true;
+ }
+
+ virtual int2 split_kernel_local_size()
+ {
+ return make_int2(64, 1);
+ }
+
+ virtual int2 split_kernel_global_size(device_memory &kg,
+ device_memory &data,
+ DeviceTask * /*task*/)
+ {
+ cl_device_type type = OpenCLInfo::get_device_type(device->cdDevice);
+ /* Use small global size on CPU devices as it seems to be much faster. */
+ if (type == CL_DEVICE_TYPE_CPU) {
+ VLOG(1) << "Global size: (64, 64).";
+ return make_int2(64, 64);
+ }
+
+ cl_ulong max_buffer_size;
+ clGetDeviceInfo(
+ device->cdDevice, CL_DEVICE_MAX_MEM_ALLOC_SIZE, sizeof(cl_ulong), &max_buffer_size, NULL);
+
+ if (DebugFlags().opencl.mem_limit) {
+ max_buffer_size = min(max_buffer_size,
+ cl_ulong(DebugFlags().opencl.mem_limit - device->stats.mem_used));
+ }
+
+ VLOG(1) << "Maximum device allocation size: " << string_human_readable_number(max_buffer_size)
+ << " bytes. (" << string_human_readable_size(max_buffer_size) << ").";
+
+ /* Limit to 2gb, as we shouldn't need more than that and some devices may support much more. */
+ max_buffer_size = min(max_buffer_size / 2, (cl_ulong)2l * 1024 * 1024 * 1024);
+
+ size_t num_elements = max_elements_for_max_buffer_size(kg, data, max_buffer_size);
+ int2 global_size = make_int2(max(round_down((int)sqrt(num_elements), 64), 64),
+ (int)sqrt(num_elements));
+ VLOG(1) << "Global size: " << global_size << ".";
+ return global_size;
+ }
};
bool OpenCLDevice::opencl_error(cl_int err)
{
- if(err != CL_SUCCESS) {
- string message = string_printf("OpenCL error (%d): %s", err, clewErrorString(err));
- if(error_msg == "")
- error_msg = message;
- fprintf(stderr, "%s\n", message.c_str());
- return true;
- }
-
- return false;
+ if (err != CL_SUCCESS) {
+ string message = string_printf("OpenCL error (%d): %s", err, clewErrorString(err));
+ if (error_msg == "")
+ error_msg = message;
+ fprintf(stderr, "%s\n", message.c_str());
+ return true;
+ }
+
+ return false;
}
-void OpenCLDevice::opencl_error(const string& message)
+void OpenCLDevice::opencl_error(const string &message)
{
- if(error_msg == "")
- error_msg = message;
- fprintf(stderr, "%s\n", message.c_str());
+ if (error_msg == "")
+ error_msg = message;
+ fprintf(stderr, "%s\n", message.c_str());
}
-void OpenCLDevice::opencl_assert_err(cl_int err, const char* where)
+void OpenCLDevice::opencl_assert_err(cl_int err, const char *where)
{
- if(err != CL_SUCCESS) {
- string message = string_printf("OpenCL error (%d): %s in %s", err, clewErrorString(err), where);
- if(error_msg == "")
- error_msg = message;
- fprintf(stderr, "%s\n", message.c_str());
-#ifndef NDEBUG
- abort();
-#endif
- }
+ if (err != CL_SUCCESS) {
+ string message = string_printf(
+ "OpenCL error (%d): %s in %s", err, clewErrorString(err), where);
+ if (error_msg == "")
+ error_msg = message;
+ fprintf(stderr, "%s\n", message.c_str());
+# ifndef NDEBUG
+ abort();
+# endif
+ }
}
-OpenCLDevice::OpenCLDevice(DeviceInfo& info, Stats &stats, Profiler &profiler, bool background)
-: Device(info, stats, profiler, background),
- kernel_programs(this),
- preview_programs(this),
- memory_manager(this),
- texture_info(this, "__texture_info", MEM_TEXTURE)
+OpenCLDevice::OpenCLDevice(DeviceInfo &info, Stats &stats, Profiler &profiler, bool background)
+ : Device(info, stats, profiler, background),
+ kernel_programs(this),
+ preview_programs(this),
+ memory_manager(this),
+ texture_info(this, "__texture_info", MEM_TEXTURE)
{
- cpPlatform = NULL;
- cdDevice = NULL;
- cxContext = NULL;
- cqCommandQueue = NULL;
- null_mem = 0;
- device_initialized = false;
- textures_need_update = true;
- use_preview_kernels = !background;
-
- vector<OpenCLPlatformDevice> usable_devices;
- OpenCLInfo::get_usable_devices(&usable_devices);
- if(usable_devices.size() == 0) {
- opencl_error("OpenCL: no devices found.");
- return;
- }
- assert(info.num < usable_devices.size());
- OpenCLPlatformDevice& platform_device = usable_devices[info.num];
- device_num = info.num;
- cpPlatform = platform_device.platform_id;
- cdDevice = platform_device.device_id;
- platform_name = platform_device.platform_name;
- device_name = platform_device.device_name;
- VLOG(2) << "Creating new Cycles device for OpenCL platform "
- << platform_name << ", device "
- << device_name << ".";
-
- {
- /* try to use cached context */
- thread_scoped_lock cache_locker;
- cxContext = OpenCLCache::get_context(cpPlatform, cdDevice, cache_locker);
-
- if(cxContext == NULL) {
- /* create context properties array to specify platform */
- const cl_context_properties context_props[] = {
- CL_CONTEXT_PLATFORM, (cl_context_properties)cpPlatform,
- 0, 0
- };
-
- /* create context */
- cxContext = clCreateContext(context_props, 1, &cdDevice,
- context_notify_callback, cdDevice, &ciErr);
-
- if(opencl_error(ciErr)) {
- opencl_error("OpenCL: clCreateContext failed");
- return;
- }
-
- /* cache it */
- OpenCLCache::store_context(cpPlatform, cdDevice, cxContext, cache_locker);
- }
- }
-
- cqCommandQueue = clCreateCommandQueue(cxContext, cdDevice, 0, &ciErr);
- if(opencl_error(ciErr)) {
- opencl_error("OpenCL: Error creating command queue");
- return;
- }
-
- null_mem = (device_ptr)clCreateBuffer(cxContext, CL_MEM_READ_ONLY, 1, NULL, &ciErr);
- if(opencl_error(ciErr)) {
- opencl_error("OpenCL: Error creating memory buffer for NULL");
- return;
- }
-
- /* Allocate this right away so that texture_info is placed at offset 0 in the device memory buffers */
- texture_info.resize(1);
- memory_manager.alloc("texture_info", texture_info);
-
- device_initialized = true;
-
- split_kernel = new OpenCLSplitKernel(this);
- if (!background) {
- load_preview_kernels();
- }
+ cpPlatform = NULL;
+ cdDevice = NULL;
+ cxContext = NULL;
+ cqCommandQueue = NULL;
+ null_mem = 0;
+ device_initialized = false;
+ textures_need_update = true;
+ use_preview_kernels = !background;
+
+ vector<OpenCLPlatformDevice> usable_devices;
+ OpenCLInfo::get_usable_devices(&usable_devices);
+ if (usable_devices.size() == 0) {
+ opencl_error("OpenCL: no devices found.");
+ return;
+ }
+ assert(info.num < usable_devices.size());
+ OpenCLPlatformDevice &platform_device = usable_devices[info.num];
+ device_num = info.num;
+ cpPlatform = platform_device.platform_id;
+ cdDevice = platform_device.device_id;
+ platform_name = platform_device.platform_name;
+ device_name = platform_device.device_name;
+ VLOG(2) << "Creating new Cycles device for OpenCL platform " << platform_name << ", device "
+ << device_name << ".";
+
+ {
+ /* try to use cached context */
+ thread_scoped_lock cache_locker;
+ cxContext = OpenCLCache::get_context(cpPlatform, cdDevice, cache_locker);
+
+ if (cxContext == NULL) {
+ /* create context properties array to specify platform */
+ const cl_context_properties context_props[] = {
+ CL_CONTEXT_PLATFORM, (cl_context_properties)cpPlatform, 0, 0};
+
+ /* create context */
+ cxContext = clCreateContext(
+ context_props, 1, &cdDevice, context_notify_callback, cdDevice, &ciErr);
+
+ if (opencl_error(ciErr)) {
+ opencl_error("OpenCL: clCreateContext failed");
+ return;
+ }
+
+ /* cache it */
+ OpenCLCache::store_context(cpPlatform, cdDevice, cxContext, cache_locker);
+ }
+ }
+
+ cqCommandQueue = clCreateCommandQueue(cxContext, cdDevice, 0, &ciErr);
+ if (opencl_error(ciErr)) {
+ opencl_error("OpenCL: Error creating command queue");
+ return;
+ }
+
+ null_mem = (device_ptr)clCreateBuffer(cxContext, CL_MEM_READ_ONLY, 1, NULL, &ciErr);
+ if (opencl_error(ciErr)) {
+ opencl_error("OpenCL: Error creating memory buffer for NULL");
+ return;
+ }
+
+ /* Allocate this right away so that texture_info is placed at offset 0 in the device memory buffers */
+ texture_info.resize(1);
+ memory_manager.alloc("texture_info", texture_info);
+
+ device_initialized = true;
+
+ split_kernel = new OpenCLSplitKernel(this);
+ if (!background) {
+ load_preview_kernels();
+ }
}
OpenCLDevice::~OpenCLDevice()
{
- task_pool.stop();
- load_required_kernel_task_pool.stop();
- load_kernel_task_pool.stop();
+ task_pool.stop();
+ load_required_kernel_task_pool.stop();
+ load_kernel_task_pool.stop();
- memory_manager.free();
+ memory_manager.free();
- if(null_mem)
- clReleaseMemObject(CL_MEM_PTR(null_mem));
+ if (null_mem)
+ clReleaseMemObject(CL_MEM_PTR(null_mem));
- ConstMemMap::iterator mt;
- for(mt = const_mem_map.begin(); mt != const_mem_map.end(); mt++) {
- delete mt->second;
- }
+ ConstMemMap::iterator mt;
+ for (mt = const_mem_map.begin(); mt != const_mem_map.end(); mt++) {
+ delete mt->second;
+ }
- base_program.release();
- bake_program.release();
- displace_program.release();
- background_program.release();
- denoising_program.release();
+ base_program.release();
+ bake_program.release();
+ displace_program.release();
+ background_program.release();
+ denoising_program.release();
- if(cqCommandQueue)
- clReleaseCommandQueue(cqCommandQueue);
- if(cxContext)
- clReleaseContext(cxContext);
+ if (cqCommandQueue)
+ clReleaseCommandQueue(cqCommandQueue);
+ if (cxContext)
+ clReleaseContext(cxContext);
- delete split_kernel;
+ delete split_kernel;
}
void CL_CALLBACK OpenCLDevice::context_notify_callback(const char *err_info,
- const void * /*private_info*/, size_t /*cb*/, void *user_data)
+ const void * /*private_info*/,
+ size_t /*cb*/,
+ void *user_data)
{
- string device_name = OpenCLInfo::get_device_name((cl_device_id)user_data);
- fprintf(stderr, "OpenCL error (%s): %s\n", device_name.c_str(), err_info);
+ string device_name = OpenCLInfo::get_device_name((cl_device_id)user_data);
+ fprintf(stderr, "OpenCL error (%s): %s\n", device_name.c_str(), err_info);
}
bool OpenCLDevice::opencl_version_check()
{
- string error;
- if(!OpenCLInfo::platform_version_check(cpPlatform, &error)) {
- opencl_error(error);
- return false;
- }
- if(!OpenCLInfo::device_version_check(cdDevice, &error)) {
- opencl_error(error);
- return false;
- }
- return true;
+ string error;
+ if (!OpenCLInfo::platform_version_check(cpPlatform, &error)) {
+ opencl_error(error);
+ return false;
+ }
+ if (!OpenCLInfo::device_version_check(cdDevice, &error)) {
+ opencl_error(error);
+ return false;
+ }
+ return true;
}
string OpenCLDevice::device_md5_hash(string kernel_custom_build_options)
{
- MD5Hash md5;
- char version[256], driver[256], name[256], vendor[256];
+ MD5Hash md5;
+ char version[256], driver[256], name[256], vendor[256];
- clGetPlatformInfo(cpPlatform, CL_PLATFORM_VENDOR, sizeof(vendor), &vendor, NULL);
- clGetDeviceInfo(cdDevice, CL_DEVICE_VERSION, sizeof(version), &version, NULL);
- clGetDeviceInfo(cdDevice, CL_DEVICE_NAME, sizeof(name), &name, NULL);
- clGetDeviceInfo(cdDevice, CL_DRIVER_VERSION, sizeof(driver), &driver, NULL);
+ clGetPlatformInfo(cpPlatform, CL_PLATFORM_VENDOR, sizeof(vendor), &vendor, NULL);
+ clGetDeviceInfo(cdDevice, CL_DEVICE_VERSION, sizeof(version), &version, NULL);
+ clGetDeviceInfo(cdDevice, CL_DEVICE_NAME, sizeof(name), &name, NULL);
+ clGetDeviceInfo(cdDevice, CL_DRIVER_VERSION, sizeof(driver), &driver, NULL);
- md5.append((uint8_t*)vendor, strlen(vendor));
- md5.append((uint8_t*)version, strlen(version));
- md5.append((uint8_t*)name, strlen(name));
- md5.append((uint8_t*)driver, strlen(driver));
+ md5.append((uint8_t *)vendor, strlen(vendor));
+ md5.append((uint8_t *)version, strlen(version));
+ md5.append((uint8_t *)name, strlen(name));
+ md5.append((uint8_t *)driver, strlen(driver));
- string options = kernel_build_options();
- options += kernel_custom_build_options;
- md5.append((uint8_t*)options.c_str(), options.size());
+ string options = kernel_build_options();
+ options += kernel_custom_build_options;
+ md5.append((uint8_t *)options.c_str(), options.size());
- return md5.get_hex();
+ return md5.get_hex();
}
-bool OpenCLDevice::load_kernels(const DeviceRequestedFeatures& requested_features)
+bool OpenCLDevice::load_kernels(const DeviceRequestedFeatures &requested_features)
{
- VLOG(2) << "Loading kernels for platform " << platform_name
- << ", device " << device_name << ".";
- /* Verify if device was initialized. */
- if(!device_initialized) {
- fprintf(stderr, "OpenCL: failed to initialize device.\n");
- return false;
- }
-
- /* Verify we have right opencl version. */
- if(!opencl_version_check())
- return false;
-
- load_required_kernels(requested_features);
-
- vector<OpenCLProgram*> programs;
- kernel_programs.load_kernels(programs, requested_features, false);
-
- if (!requested_features.use_baking && requested_features.use_denoising) {
- denoising_program = OpenCLProgram(this, "denoising", "filter.cl", get_build_options(requested_features, "denoising"));
- denoising_program.add_kernel(ustring("filter_divide_shadow"));
- denoising_program.add_kernel(ustring("filter_get_feature"));
- denoising_program.add_kernel(ustring("filter_write_feature"));
- denoising_program.add_kernel(ustring("filter_detect_outliers"));
- denoising_program.add_kernel(ustring("filter_combine_halves"));
- denoising_program.add_kernel(ustring("filter_construct_transform"));
- denoising_program.add_kernel(ustring("filter_nlm_calc_difference"));
- denoising_program.add_kernel(ustring("filter_nlm_blur"));
- denoising_program.add_kernel(ustring("filter_nlm_calc_weight"));
- denoising_program.add_kernel(ustring("filter_nlm_update_output"));
- denoising_program.add_kernel(ustring("filter_nlm_normalize"));
- denoising_program.add_kernel(ustring("filter_nlm_construct_gramian"));
- denoising_program.add_kernel(ustring("filter_finalize"));
- programs.push_back(&denoising_program);
- }
-
- load_required_kernel_task_pool.wait_work();
-
- /* Parallel compilation of Cycles kernels, this launches multiple
- * processes to workaround OpenCL frameworks serializing the calls
- * internally within a single process. */
- foreach(OpenCLProgram *program, programs) {
- if (!program->load()) {
- load_kernel_task_pool.push(function_bind(&OpenCLProgram::compile, program));
- }
- }
- return true;
+ VLOG(2) << "Loading kernels for platform " << platform_name << ", device " << device_name << ".";
+ /* Verify if device was initialized. */
+ if (!device_initialized) {
+ fprintf(stderr, "OpenCL: failed to initialize device.\n");
+ return false;
+ }
+
+ /* Verify we have right opencl version. */
+ if (!opencl_version_check())
+ return false;
+
+ load_required_kernels(requested_features);
+
+ vector<OpenCLProgram *> programs;
+ kernel_programs.load_kernels(programs, requested_features, false);
+
+ if (!requested_features.use_baking && requested_features.use_denoising) {
+ denoising_program = OpenCLProgram(
+ this, "denoising", "filter.cl", get_build_options(requested_features, "denoising"));
+ denoising_program.add_kernel(ustring("filter_divide_shadow"));
+ denoising_program.add_kernel(ustring("filter_get_feature"));
+ denoising_program.add_kernel(ustring("filter_write_feature"));
+ denoising_program.add_kernel(ustring("filter_detect_outliers"));
+ denoising_program.add_kernel(ustring("filter_combine_halves"));
+ denoising_program.add_kernel(ustring("filter_construct_transform"));
+ denoising_program.add_kernel(ustring("filter_nlm_calc_difference"));
+ denoising_program.add_kernel(ustring("filter_nlm_blur"));
+ denoising_program.add_kernel(ustring("filter_nlm_calc_weight"));
+ denoising_program.add_kernel(ustring("filter_nlm_update_output"));
+ denoising_program.add_kernel(ustring("filter_nlm_normalize"));
+ denoising_program.add_kernel(ustring("filter_nlm_construct_gramian"));
+ denoising_program.add_kernel(ustring("filter_finalize"));
+ programs.push_back(&denoising_program);
+ }
+
+ load_required_kernel_task_pool.wait_work();
+
+ /* Parallel compilation of Cycles kernels, this launches multiple
+ * processes to workaround OpenCL frameworks serializing the calls
+ * internally within a single process. */
+ foreach (OpenCLProgram *program, programs) {
+ if (!program->load()) {
+ load_kernel_task_pool.push(function_bind(&OpenCLProgram::compile, program));
+ }
+ }
+ return true;
}
-void OpenCLDevice::load_required_kernels(const DeviceRequestedFeatures& requested_features)
+void OpenCLDevice::load_required_kernels(const DeviceRequestedFeatures &requested_features)
{
- vector<OpenCLProgram*> programs;
- base_program = OpenCLProgram(this, "base", "kernel_base.cl", get_build_options(requested_features, "base"));
- base_program.add_kernel(ustring("convert_to_byte"));
- base_program.add_kernel(ustring("convert_to_half_float"));
- base_program.add_kernel(ustring("zero_buffer"));
- programs.push_back(&base_program);
-
- if (requested_features.use_true_displacement) {
- displace_program = OpenCLProgram(this, "displace", "kernel_displace.cl", get_build_options(requested_features, "displace"));
- displace_program.add_kernel(ustring("displace"));
- programs.push_back(&displace_program);
- }
-
- if (requested_features.use_background_light) {
- background_program = OpenCLProgram(this, "background", "kernel_background.cl", get_build_options(requested_features, "background"));
- background_program.add_kernel(ustring("background"));
- programs.push_back(&background_program);
- }
-
- if (requested_features.use_baking) {
- bake_program = OpenCLProgram(this, "bake", "kernel_bake.cl", get_build_options(requested_features, "bake"));
- bake_program.add_kernel(ustring("bake"));
- programs.push_back(&bake_program);
- }
-
- foreach(OpenCLProgram *program, programs) {
- if (!program->load()) {
- load_required_kernel_task_pool.push(function_bind(&OpenCLProgram::compile, program));
- }
- }
+ vector<OpenCLProgram *> programs;
+ base_program = OpenCLProgram(
+ this, "base", "kernel_base.cl", get_build_options(requested_features, "base"));
+ base_program.add_kernel(ustring("convert_to_byte"));
+ base_program.add_kernel(ustring("convert_to_half_float"));
+ base_program.add_kernel(ustring("zero_buffer"));
+ programs.push_back(&base_program);
+
+ if (requested_features.use_true_displacement) {
+ displace_program = OpenCLProgram(
+ this, "displace", "kernel_displace.cl", get_build_options(requested_features, "displace"));
+ displace_program.add_kernel(ustring("displace"));
+ programs.push_back(&displace_program);
+ }
+
+ if (requested_features.use_background_light) {
+ background_program = OpenCLProgram(this,
+ "background",
+ "kernel_background.cl",
+ get_build_options(requested_features, "background"));
+ background_program.add_kernel(ustring("background"));
+ programs.push_back(&background_program);
+ }
+
+ if (requested_features.use_baking) {
+ bake_program = OpenCLProgram(
+ this, "bake", "kernel_bake.cl", get_build_options(requested_features, "bake"));
+ bake_program.add_kernel(ustring("bake"));
+ programs.push_back(&bake_program);
+ }
+
+ foreach (OpenCLProgram *program, programs) {
+ if (!program->load()) {
+ load_required_kernel_task_pool.push(function_bind(&OpenCLProgram::compile, program));
+ }
+ }
}
void OpenCLDevice::load_preview_kernels()
{
- DeviceRequestedFeatures no_features;
- vector<OpenCLProgram*> programs;
- preview_programs.load_kernels(programs, no_features, true);
-
- foreach(OpenCLProgram *program, programs) {
- if (!program->load()) {
- load_required_kernel_task_pool.push(function_bind(&OpenCLProgram::compile, program));
- }
- }
+ DeviceRequestedFeatures no_features;
+ vector<OpenCLProgram *> programs;
+ preview_programs.load_kernels(programs, no_features, true);
+
+ foreach (OpenCLProgram *program, programs) {
+ if (!program->load()) {
+ load_required_kernel_task_pool.push(function_bind(&OpenCLProgram::compile, program));
+ }
+ }
}
-bool OpenCLDevice::wait_for_availability(const DeviceRequestedFeatures& requested_features)
+bool OpenCLDevice::wait_for_availability(const DeviceRequestedFeatures &requested_features)
{
- if (background) {
- load_kernel_task_pool.wait_work();
- use_preview_kernels = false;
- }
- else {
- /* We use a device setting to determine to load preview kernels or not
- * Better to check on device level than per kernel as mixing preview and
- * non-preview kernels does not work due to different data types */
- if (use_preview_kernels) {
- use_preview_kernels = !load_kernel_task_pool.finished();
- }
- }
- return split_kernel->load_kernels(requested_features);
+ if (background) {
+ load_kernel_task_pool.wait_work();
+ use_preview_kernels = false;
+ }
+ else {
+ /* We use a device setting to determine to load preview kernels or not
+ * Better to check on device level than per kernel as mixing preview and
+ * non-preview kernels does not work due to different data types */
+ if (use_preview_kernels) {
+ use_preview_kernels = !load_kernel_task_pool.finished();
+ }
+ }
+ return split_kernel->load_kernels(requested_features);
}
-OpenCLDevice::OpenCLSplitPrograms* OpenCLDevice::get_split_programs()
+OpenCLDevice::OpenCLSplitPrograms *OpenCLDevice::get_split_programs()
{
- return use_preview_kernels?&preview_programs:&kernel_programs;
+ return use_preview_kernels ? &preview_programs : &kernel_programs;
}
DeviceKernelStatus OpenCLDevice::get_active_kernel_switch_state()
{
- /* Do not switch kernels for background renderings
- * We do foreground rendering but use the preview kernels
- * Check for the optimized kernels
- *
- * This works also the other way around, where we are using
- * optimized kernels but new ones are being compiled due
- * to other features that are needed */
- if (background) {
- /* The if-statements below would find the same result,
- * But as the `finished` method uses a mutex we added
- * this as an early exit */
- return DEVICE_KERNEL_USING_FEATURE_KERNEL;
- }
-
- bool other_kernels_finished = load_kernel_task_pool.finished();
- if (use_preview_kernels) {
- if (other_kernels_finished) {
- return DEVICE_KERNEL_FEATURE_KERNEL_AVAILABLE;
- }
- else {
- return DEVICE_KERNEL_WAITING_FOR_FEATURE_KERNEL;
- }
- }
- else {
- if (other_kernels_finished) {
- return DEVICE_KERNEL_USING_FEATURE_KERNEL;
- }
- else {
- return DEVICE_KERNEL_FEATURE_KERNEL_INVALID;
- }
- }
+ /* Do not switch kernels for background renderings
+ * We do foreground rendering but use the preview kernels
+ * Check for the optimized kernels
+ *
+ * This works also the other way around, where we are using
+ * optimized kernels but new ones are being compiled due
+ * to other features that are needed */
+ if (background) {
+ /* The if-statements below would find the same result,
+ * But as the `finished` method uses a mutex we added
+ * this as an early exit */
+ return DEVICE_KERNEL_USING_FEATURE_KERNEL;
+ }
+
+ bool other_kernels_finished = load_kernel_task_pool.finished();
+ if (use_preview_kernels) {
+ if (other_kernels_finished) {
+ return DEVICE_KERNEL_FEATURE_KERNEL_AVAILABLE;
+ }
+ else {
+ return DEVICE_KERNEL_WAITING_FOR_FEATURE_KERNEL;
+ }
+ }
+ else {
+ if (other_kernels_finished) {
+ return DEVICE_KERNEL_USING_FEATURE_KERNEL;
+ }
+ else {
+ return DEVICE_KERNEL_FEATURE_KERNEL_INVALID;
+ }
+ }
}
-void OpenCLDevice::mem_alloc(device_memory& mem)
+void OpenCLDevice::mem_alloc(device_memory &mem)
{
- if(mem.name) {
- VLOG(1) << "Buffer allocate: " << mem.name << ", "
- << string_human_readable_number(mem.memory_size()) << " bytes. ("
- << string_human_readable_size(mem.memory_size()) << ")";
- }
-
- size_t size = mem.memory_size();
-
- /* check there is enough memory available for the allocation */
- cl_ulong max_alloc_size = 0;
- clGetDeviceInfo(cdDevice, CL_DEVICE_MAX_MEM_ALLOC_SIZE, sizeof(cl_ulong), &max_alloc_size, NULL);
-
- if(DebugFlags().opencl.mem_limit) {
- max_alloc_size = min(max_alloc_size,
- cl_ulong(DebugFlags().opencl.mem_limit - stats.mem_used));
- }
-
- if(size > max_alloc_size) {
- string error = "Scene too complex to fit in available memory.";
- if(mem.name != NULL) {
- error += string_printf(" (allocating buffer %s failed.)", mem.name);
- }
- set_error(error);
-
- return;
- }
-
- cl_mem_flags mem_flag;
- void *mem_ptr = NULL;
-
- if(mem.type == MEM_READ_ONLY || mem.type == MEM_TEXTURE)
- mem_flag = CL_MEM_READ_ONLY;
- else
- mem_flag = CL_MEM_READ_WRITE;
-
- /* Zero-size allocation might be invoked by render, but not really
- * supported by OpenCL. Using NULL as device pointer also doesn't really
- * work for some reason, so for the time being we'll use special case
- * will null_mem buffer.
- */
- if(size != 0) {
- mem.device_pointer = (device_ptr)clCreateBuffer(cxContext,
- mem_flag,
- size,
- mem_ptr,
- &ciErr);
- opencl_assert_err(ciErr, "clCreateBuffer");
- }
- else {
- mem.device_pointer = null_mem;
- }
-
- stats.mem_alloc(size);
- mem.device_size = size;
+ if (mem.name) {
+ VLOG(1) << "Buffer allocate: " << mem.name << ", "
+ << string_human_readable_number(mem.memory_size()) << " bytes. ("
+ << string_human_readable_size(mem.memory_size()) << ")";
+ }
+
+ size_t size = mem.memory_size();
+
+ /* check there is enough memory available for the allocation */
+ cl_ulong max_alloc_size = 0;
+ clGetDeviceInfo(cdDevice, CL_DEVICE_MAX_MEM_ALLOC_SIZE, sizeof(cl_ulong), &max_alloc_size, NULL);
+
+ if (DebugFlags().opencl.mem_limit) {
+ max_alloc_size = min(max_alloc_size, cl_ulong(DebugFlags().opencl.mem_limit - stats.mem_used));
+ }
+
+ if (size > max_alloc_size) {
+ string error = "Scene too complex to fit in available memory.";
+ if (mem.name != NULL) {
+ error += string_printf(" (allocating buffer %s failed.)", mem.name);
+ }
+ set_error(error);
+
+ return;
+ }
+
+ cl_mem_flags mem_flag;
+ void *mem_ptr = NULL;
+
+ if (mem.type == MEM_READ_ONLY || mem.type == MEM_TEXTURE)
+ mem_flag = CL_MEM_READ_ONLY;
+ else
+ mem_flag = CL_MEM_READ_WRITE;
+
+ /* Zero-size allocation might be invoked by render, but not really
+ * supported by OpenCL. Using NULL as device pointer also doesn't really
+ * work for some reason, so for the time being we'll use special case
+ * will null_mem buffer.
+ */
+ if (size != 0) {
+ mem.device_pointer = (device_ptr)clCreateBuffer(cxContext, mem_flag, size, mem_ptr, &ciErr);
+ opencl_assert_err(ciErr, "clCreateBuffer");
+ }
+ else {
+ mem.device_pointer = null_mem;
+ }
+
+ stats.mem_alloc(size);
+ mem.device_size = size;
}
-void OpenCLDevice::mem_copy_to(device_memory& mem)
+void OpenCLDevice::mem_copy_to(device_memory &mem)
{
- if(mem.type == MEM_TEXTURE) {
- tex_free(mem);
- tex_alloc(mem);
- }
- else {
- if(!mem.device_pointer) {
- mem_alloc(mem);
- }
-
- /* this is blocking */
- size_t size = mem.memory_size();
- if(size != 0) {
- opencl_assert(clEnqueueWriteBuffer(cqCommandQueue,
- CL_MEM_PTR(mem.device_pointer),
- CL_TRUE,
- 0,
- size,
- mem.host_pointer,
- 0,
- NULL, NULL));
- }
- }
+ if (mem.type == MEM_TEXTURE) {
+ tex_free(mem);
+ tex_alloc(mem);
+ }
+ else {
+ if (!mem.device_pointer) {
+ mem_alloc(mem);
+ }
+
+ /* this is blocking */
+ size_t size = mem.memory_size();
+ if (size != 0) {
+ opencl_assert(clEnqueueWriteBuffer(cqCommandQueue,
+ CL_MEM_PTR(mem.device_pointer),
+ CL_TRUE,
+ 0,
+ size,
+ mem.host_pointer,
+ 0,
+ NULL,
+ NULL));
+ }
+ }
}
-void OpenCLDevice::mem_copy_from(device_memory& mem, int y, int w, int h, int elem)
+void OpenCLDevice::mem_copy_from(device_memory &mem, int y, int w, int h, int elem)
{
- size_t offset = elem*y*w;
- size_t size = elem*w*h;
- assert(size != 0);
- opencl_assert(clEnqueueReadBuffer(cqCommandQueue,
- CL_MEM_PTR(mem.device_pointer),
- CL_TRUE,
- offset,
- size,
- (uchar*)mem.host_pointer + offset,
- 0,
- NULL, NULL));
+ size_t offset = elem * y * w;
+ size_t size = elem * w * h;
+ assert(size != 0);
+ opencl_assert(clEnqueueReadBuffer(cqCommandQueue,
+ CL_MEM_PTR(mem.device_pointer),
+ CL_TRUE,
+ offset,
+ size,
+ (uchar *)mem.host_pointer + offset,
+ 0,
+ NULL,
+ NULL));
}
void OpenCLDevice::mem_zero_kernel(device_ptr mem, size_t size)
{
- base_program.wait_for_availability();
- cl_kernel ckZeroBuffer = base_program(ustring("zero_buffer"));
-
- size_t global_size[] = {1024, 1024};
- size_t num_threads = global_size[0] * global_size[1];
-
- cl_mem d_buffer = CL_MEM_PTR(mem);
- cl_ulong d_offset = 0;
- cl_ulong d_size = 0;
-
- while(d_offset < size) {
- d_size = std::min<cl_ulong>(num_threads*sizeof(float4), size - d_offset);
-
- kernel_set_args(ckZeroBuffer, 0, d_buffer, d_size, d_offset);
-
- ciErr = clEnqueueNDRangeKernel(cqCommandQueue,
- ckZeroBuffer,
- 2,
- NULL,
- global_size,
- NULL,
- 0,
- NULL,
- NULL);
- opencl_assert_err(ciErr, "clEnqueueNDRangeKernel");
-
- d_offset += d_size;
- }
+ base_program.wait_for_availability();
+ cl_kernel ckZeroBuffer = base_program(ustring("zero_buffer"));
+
+ size_t global_size[] = {1024, 1024};
+ size_t num_threads = global_size[0] * global_size[1];
+
+ cl_mem d_buffer = CL_MEM_PTR(mem);
+ cl_ulong d_offset = 0;
+ cl_ulong d_size = 0;
+
+ while (d_offset < size) {
+ d_size = std::min<cl_ulong>(num_threads * sizeof(float4), size - d_offset);
+
+ kernel_set_args(ckZeroBuffer, 0, d_buffer, d_size, d_offset);
+
+ ciErr = clEnqueueNDRangeKernel(
+ cqCommandQueue, ckZeroBuffer, 2, NULL, global_size, NULL, 0, NULL, NULL);
+ opencl_assert_err(ciErr, "clEnqueueNDRangeKernel");
+
+ d_offset += d_size;
+ }
}
-void OpenCLDevice::mem_zero(device_memory& mem)
+void OpenCLDevice::mem_zero(device_memory &mem)
{
- if(!mem.device_pointer) {
- mem_alloc(mem);
- }
-
- if(mem.device_pointer) {
- if(base_program.is_loaded()) {
- mem_zero_kernel(mem.device_pointer, mem.memory_size());
- }
-
- if(mem.host_pointer) {
- memset(mem.host_pointer, 0, mem.memory_size());
- }
-
- if(!base_program.is_loaded()) {
- void* zero = mem.host_pointer;
-
- if(!mem.host_pointer) {
- zero = util_aligned_malloc(mem.memory_size(), 16);
- memset(zero, 0, mem.memory_size());
- }
-
- opencl_assert(clEnqueueWriteBuffer(cqCommandQueue,
- CL_MEM_PTR(mem.device_pointer),
- CL_TRUE,
- 0,
- mem.memory_size(),
- zero,
- 0,
- NULL, NULL));
-
- if(!mem.host_pointer) {
- util_aligned_free(zero);
- }
- }
- }
+ if (!mem.device_pointer) {
+ mem_alloc(mem);
+ }
+
+ if (mem.device_pointer) {
+ if (base_program.is_loaded()) {
+ mem_zero_kernel(mem.device_pointer, mem.memory_size());
+ }
+
+ if (mem.host_pointer) {
+ memset(mem.host_pointer, 0, mem.memory_size());
+ }
+
+ if (!base_program.is_loaded()) {
+ void *zero = mem.host_pointer;
+
+ if (!mem.host_pointer) {
+ zero = util_aligned_malloc(mem.memory_size(), 16);
+ memset(zero, 0, mem.memory_size());
+ }
+
+ opencl_assert(clEnqueueWriteBuffer(cqCommandQueue,
+ CL_MEM_PTR(mem.device_pointer),
+ CL_TRUE,
+ 0,
+ mem.memory_size(),
+ zero,
+ 0,
+ NULL,
+ NULL));
+
+ if (!mem.host_pointer) {
+ util_aligned_free(zero);
+ }
+ }
+ }
}
-void OpenCLDevice::mem_free(device_memory& mem)
+void OpenCLDevice::mem_free(device_memory &mem)
{
- if(mem.type == MEM_TEXTURE) {
- tex_free(mem);
- }
- else {
- if(mem.device_pointer) {
- if(mem.device_pointer != null_mem) {
- opencl_assert(clReleaseMemObject(CL_MEM_PTR(mem.device_pointer)));
- }
- mem.device_pointer = 0;
-
- stats.mem_free(mem.device_size);
- mem.device_size = 0;
- }
- }
+ if (mem.type == MEM_TEXTURE) {
+ tex_free(mem);
+ }
+ else {
+ if (mem.device_pointer) {
+ if (mem.device_pointer != null_mem) {
+ opencl_assert(clReleaseMemObject(CL_MEM_PTR(mem.device_pointer)));
+ }
+ mem.device_pointer = 0;
+
+ stats.mem_free(mem.device_size);
+ mem.device_size = 0;
+ }
+ }
}
int OpenCLDevice::mem_sub_ptr_alignment()
{
- return OpenCLInfo::mem_sub_ptr_alignment(cdDevice);
+ return OpenCLInfo::mem_sub_ptr_alignment(cdDevice);
}
-device_ptr OpenCLDevice::mem_alloc_sub_ptr(device_memory& mem, int offset, int size)
+device_ptr OpenCLDevice::mem_alloc_sub_ptr(device_memory &mem, int offset, int size)
{
- cl_mem_flags mem_flag;
- if(mem.type == MEM_READ_ONLY || mem.type == MEM_TEXTURE)
- mem_flag = CL_MEM_READ_ONLY;
- else
- mem_flag = CL_MEM_READ_WRITE;
-
- cl_buffer_region info;
- info.origin = mem.memory_elements_size(offset);
- info.size = mem.memory_elements_size(size);
-
- device_ptr sub_buf = (device_ptr) clCreateSubBuffer(CL_MEM_PTR(mem.device_pointer),
- mem_flag,
- CL_BUFFER_CREATE_TYPE_REGION,
- &info,
- &ciErr);
- opencl_assert_err(ciErr, "clCreateSubBuffer");
- return sub_buf;
+ cl_mem_flags mem_flag;
+ if (mem.type == MEM_READ_ONLY || mem.type == MEM_TEXTURE)
+ mem_flag = CL_MEM_READ_ONLY;
+ else
+ mem_flag = CL_MEM_READ_WRITE;
+
+ cl_buffer_region info;
+ info.origin = mem.memory_elements_size(offset);
+ info.size = mem.memory_elements_size(size);
+
+ device_ptr sub_buf = (device_ptr)clCreateSubBuffer(
+ CL_MEM_PTR(mem.device_pointer), mem_flag, CL_BUFFER_CREATE_TYPE_REGION, &info, &ciErr);
+ opencl_assert_err(ciErr, "clCreateSubBuffer");
+ return sub_buf;
}
void OpenCLDevice::mem_free_sub_ptr(device_ptr device_pointer)
{
- if(device_pointer && device_pointer != null_mem) {
- opencl_assert(clReleaseMemObject(CL_MEM_PTR(device_pointer)));
- }
+ if (device_pointer && device_pointer != null_mem) {
+ opencl_assert(clReleaseMemObject(CL_MEM_PTR(device_pointer)));
+ }
}
void OpenCLDevice::const_copy_to(const char *name, void *host, size_t size)
{
- ConstMemMap::iterator i = const_mem_map.find(name);
- device_vector<uchar> *data;
-
- if(i == const_mem_map.end()) {
- data = new device_vector<uchar>(this, name, MEM_READ_ONLY);
- data->alloc(size);
- const_mem_map.insert(ConstMemMap::value_type(name, data));
- }
- else {
- data = i->second;
- }
-
- memcpy(data->data(), host, size);
- data->copy_to_device();
+ ConstMemMap::iterator i = const_mem_map.find(name);
+ device_vector<uchar> *data;
+
+ if (i == const_mem_map.end()) {
+ data = new device_vector<uchar>(this, name, MEM_READ_ONLY);
+ data->alloc(size);
+ const_mem_map.insert(ConstMemMap::value_type(name, data));
+ }
+ else {
+ data = i->second;
+ }
+
+ memcpy(data->data(), host, size);
+ data->copy_to_device();
}
-void OpenCLDevice::tex_alloc(device_memory& mem)
+void OpenCLDevice::tex_alloc(device_memory &mem)
{
- VLOG(1) << "Texture allocate: " << mem.name << ", "
- << string_human_readable_number(mem.memory_size()) << " bytes. ("
- << string_human_readable_size(mem.memory_size()) << ")";
-
- memory_manager.alloc(mem.name, mem);
- /* Set the pointer to non-null to keep code that inspects its value from thinking its unallocated. */
- mem.device_pointer = 1;
- textures[mem.name] = &mem;
- textures_need_update = true;
+ VLOG(1) << "Texture allocate: " << mem.name << ", "
+ << string_human_readable_number(mem.memory_size()) << " bytes. ("
+ << string_human_readable_size(mem.memory_size()) << ")";
+
+ memory_manager.alloc(mem.name, mem);
+ /* Set the pointer to non-null to keep code that inspects its value from thinking its unallocated. */
+ mem.device_pointer = 1;
+ textures[mem.name] = &mem;
+ textures_need_update = true;
}
-void OpenCLDevice::tex_free(device_memory& mem)
+void OpenCLDevice::tex_free(device_memory &mem)
{
- if(mem.device_pointer) {
- mem.device_pointer = 0;
-
- if(memory_manager.free(mem)) {
- textures_need_update = true;
- }
-
- foreach(TexturesMap::value_type& value, textures) {
- if(value.second == &mem) {
- textures.erase(value.first);
- break;
- }
- }
- }
+ if (mem.device_pointer) {
+ mem.device_pointer = 0;
+
+ if (memory_manager.free(mem)) {
+ textures_need_update = true;
+ }
+
+ foreach (TexturesMap::value_type &value, textures) {
+ if (value.second == &mem) {
+ textures.erase(value.first);
+ break;
+ }
+ }
+ }
}
size_t OpenCLDevice::global_size_round_up(int group_size, int global_size)
{
- int r = global_size % group_size;
- return global_size + ((r == 0)? 0: group_size - r);
+ int r = global_size % group_size;
+ return global_size + ((r == 0) ? 0 : group_size - r);
}
-void OpenCLDevice::enqueue_kernel(cl_kernel kernel, size_t w, size_t h, bool x_workgroups, size_t max_workgroup_size)
+void OpenCLDevice::enqueue_kernel(
+ cl_kernel kernel, size_t w, size_t h, bool x_workgroups, size_t max_workgroup_size)
{
- size_t workgroup_size, max_work_items[3];
-
- clGetKernelWorkGroupInfo(kernel, cdDevice,
- CL_KERNEL_WORK_GROUP_SIZE, sizeof(size_t), &workgroup_size, NULL);
- clGetDeviceInfo(cdDevice,
- CL_DEVICE_MAX_WORK_ITEM_SIZES, sizeof(size_t)*3, max_work_items, NULL);
-
- if(max_workgroup_size > 0 && workgroup_size > max_workgroup_size) {
- workgroup_size = max_workgroup_size;
- }
-
- /* Try to divide evenly over 2 dimensions. */
- size_t local_size[2];
- if(x_workgroups) {
- local_size[0] = workgroup_size;
- local_size[1] = 1;
- }
- else {
- size_t sqrt_workgroup_size = max((size_t)sqrt((double)workgroup_size), 1);
- local_size[0] = local_size[1] = sqrt_workgroup_size;
- }
-
- /* Some implementations have max size 1 on 2nd dimension. */
- if(local_size[1] > max_work_items[1]) {
- local_size[0] = workgroup_size/max_work_items[1];
- local_size[1] = max_work_items[1];
- }
-
- size_t global_size[2] = {global_size_round_up(local_size[0], w),
- global_size_round_up(local_size[1], h)};
-
- /* Vertical size of 1 is coming from bake/shade kernels where we should
- * not round anything up because otherwise we'll either be doing too
- * much work per pixel (if we don't check global ID on Y axis) or will
- * be checking for global ID to always have Y of 0.
- */
- if(h == 1) {
- global_size[h] = 1;
- }
-
- /* run kernel */
- opencl_assert(clEnqueueNDRangeKernel(cqCommandQueue, kernel, 2, NULL, global_size, NULL, 0, NULL, NULL));
- opencl_assert(clFlush(cqCommandQueue));
+ size_t workgroup_size, max_work_items[3];
+
+ clGetKernelWorkGroupInfo(
+ kernel, cdDevice, CL_KERNEL_WORK_GROUP_SIZE, sizeof(size_t), &workgroup_size, NULL);
+ clGetDeviceInfo(
+ cdDevice, CL_DEVICE_MAX_WORK_ITEM_SIZES, sizeof(size_t) * 3, max_work_items, NULL);
+
+ if (max_workgroup_size > 0 && workgroup_size > max_workgroup_size) {
+ workgroup_size = max_workgroup_size;
+ }
+
+ /* Try to divide evenly over 2 dimensions. */
+ size_t local_size[2];
+ if (x_workgroups) {
+ local_size[0] = workgroup_size;
+ local_size[1] = 1;
+ }
+ else {
+ size_t sqrt_workgroup_size = max((size_t)sqrt((double)workgroup_size), 1);
+ local_size[0] = local_size[1] = sqrt_workgroup_size;
+ }
+
+ /* Some implementations have max size 1 on 2nd dimension. */
+ if (local_size[1] > max_work_items[1]) {
+ local_size[0] = workgroup_size / max_work_items[1];
+ local_size[1] = max_work_items[1];
+ }
+
+ size_t global_size[2] = {global_size_round_up(local_size[0], w),
+ global_size_round_up(local_size[1], h)};
+
+ /* Vertical size of 1 is coming from bake/shade kernels where we should
+ * not round anything up because otherwise we'll either be doing too
+ * much work per pixel (if we don't check global ID on Y axis) or will
+ * be checking for global ID to always have Y of 0.
+ */
+ if (h == 1) {
+ global_size[h] = 1;
+ }
+
+ /* run kernel */
+ opencl_assert(
+ clEnqueueNDRangeKernel(cqCommandQueue, kernel, 2, NULL, global_size, NULL, 0, NULL, NULL));
+ opencl_assert(clFlush(cqCommandQueue));
}
void OpenCLDevice::set_kernel_arg_mem(cl_kernel kernel, cl_uint *narg, const char *name)
{
- cl_mem ptr;
-
- MemMap::iterator i = mem_map.find(name);
- if(i != mem_map.end()) {
- ptr = CL_MEM_PTR(i->second);
- }
- else {
- /* work around NULL not working, even though the spec says otherwise */
- ptr = CL_MEM_PTR(null_mem);
- }
-
- opencl_assert(clSetKernelArg(kernel, (*narg)++, sizeof(ptr), (void*)&ptr));
+ cl_mem ptr;
+
+ MemMap::iterator i = mem_map.find(name);
+ if (i != mem_map.end()) {
+ ptr = CL_MEM_PTR(i->second);
+ }
+ else {
+ /* work around NULL not working, even though the spec says otherwise */
+ ptr = CL_MEM_PTR(null_mem);
+ }
+
+ opencl_assert(clSetKernelArg(kernel, (*narg)++, sizeof(ptr), (void *)&ptr));
}
void OpenCLDevice::set_kernel_arg_buffers(cl_kernel kernel, cl_uint *narg)
{
- flush_texture_buffers();
+ flush_texture_buffers();
- memory_manager.set_kernel_arg_buffers(kernel, narg);
+ memory_manager.set_kernel_arg_buffers(kernel, narg);
}
void OpenCLDevice::flush_texture_buffers()
{
- if(!textures_need_update) {
- return;
- }
- textures_need_update = false;
-
- /* Setup slots for textures. */
- int num_slots = 0;
-
- vector<texture_slot_t> texture_slots;
-
-#define KERNEL_TEX(type, name) \
- if(textures.find(#name) != textures.end()) { \
- texture_slots.push_back(texture_slot_t(#name, num_slots)); \
- } \
- num_slots++;
-#include "kernel/kernel_textures.h"
-
- int num_data_slots = num_slots;
-
- foreach(TexturesMap::value_type& tex, textures) {
- string name = tex.first;
-
- if(string_startswith(name, "__tex_image")) {
- int pos = name.rfind("_");
- int id = atoi(name.data() + pos + 1);
- texture_slots.push_back(texture_slot_t(name,
- num_data_slots + id));
- num_slots = max(num_slots, num_data_slots + id + 1);
- }
- }
-
- /* Realloc texture descriptors buffer. */
- memory_manager.free(texture_info);
- texture_info.resize(num_slots);
- memory_manager.alloc("texture_info", texture_info);
-
- /* Fill in descriptors */
- foreach(texture_slot_t& slot, texture_slots) {
- TextureInfo& info = texture_info[slot.slot];
-
- MemoryManager::BufferDescriptor desc = memory_manager.get_descriptor(slot.name);
- info.data = desc.offset;
- info.cl_buffer = desc.device_buffer;
-
- if(string_startswith(slot.name, "__tex_image")) {
- device_memory *mem = textures[slot.name];
-
- info.width = mem->data_width;
- info.height = mem->data_height;
- info.depth = mem->data_depth;
-
- info.interpolation = mem->interpolation;
- info.extension = mem->extension;
- }
- }
-
- /* Force write of descriptors. */
- memory_manager.free(texture_info);
- memory_manager.alloc("texture_info", texture_info);
-}
+ if (!textures_need_update) {
+ return;
+ }
+ textures_need_update = false;
+
+ /* Setup slots for textures. */
+ int num_slots = 0;
+
+ vector<texture_slot_t> texture_slots;
+
+# define KERNEL_TEX(type, name) \
+ if (textures.find(#name) != textures.end()) { \
+ texture_slots.push_back(texture_slot_t(#name, num_slots)); \
+ } \
+ num_slots++;
+# include "kernel/kernel_textures.h"
+
+ int num_data_slots = num_slots;
+
+ foreach (TexturesMap::value_type &tex, textures) {
+ string name = tex.first;
+
+ if (string_startswith(name, "__tex_image")) {
+ int pos = name.rfind("_");
+ int id = atoi(name.data() + pos + 1);
+ texture_slots.push_back(texture_slot_t(name, num_data_slots + id));
+ num_slots = max(num_slots, num_data_slots + id + 1);
+ }
+ }
+
+ /* Realloc texture descriptors buffer. */
+ memory_manager.free(texture_info);
+ texture_info.resize(num_slots);
+ memory_manager.alloc("texture_info", texture_info);
+
+ /* Fill in descriptors */
+ foreach (texture_slot_t &slot, texture_slots) {
+ TextureInfo &info = texture_info[slot.slot];
+
+ MemoryManager::BufferDescriptor desc = memory_manager.get_descriptor(slot.name);
+ info.data = desc.offset;
+ info.cl_buffer = desc.device_buffer;
+ if (string_startswith(slot.name, "__tex_image")) {
+ device_memory *mem = textures[slot.name];
+
+ info.width = mem->data_width;
+ info.height = mem->data_height;
+ info.depth = mem->data_depth;
+
+ info.interpolation = mem->interpolation;
+ info.extension = mem->extension;
+ }
+ }
+
+ /* Force write of descriptors. */
+ memory_manager.free(texture_info);
+ memory_manager.alloc("texture_info", texture_info);
+}
void OpenCLDevice::thread_run(DeviceTask *task)
{
- flush_texture_buffers();
-
- if(task->type == DeviceTask::FILM_CONVERT) {
- film_convert(*task, task->buffer, task->rgba_byte, task->rgba_half);
- }
- else if(task->type == DeviceTask::SHADER) {
- shader(*task);
- }
- else if(task->type == DeviceTask::RENDER) {
- RenderTile tile;
- DenoisingTask denoising(this, *task);
-
- /* Allocate buffer for kernel globals */
- device_only_memory<KernelGlobalsDummy> kgbuffer(this, "kernel_globals");
- kgbuffer.alloc_to_device(1);
-
- /* Keep rendering tiles until done. */
- while(task->acquire_tile(this, tile)) {
- if(tile.task == RenderTile::PATH_TRACE) {
- assert(tile.task == RenderTile::PATH_TRACE);
- scoped_timer timer(&tile.buffers->render_time);
-
- split_kernel->path_trace(task,
- tile,
- kgbuffer,
- *const_mem_map["__data"]);
-
- /* Complete kernel execution before release tile. */
- /* This helps in multi-device render;
- * The device that reaches the critical-section function
- * release_tile waits (stalling other devices from entering
- * release_tile) for all kernels to complete. If device1 (a
- * slow-render device) reaches release_tile first then it would
- * stall device2 (a fast-render device) from proceeding to render
- * next tile.
- */
- clFinish(cqCommandQueue);
- }
- else if(tile.task == RenderTile::DENOISE) {
- tile.sample = tile.start_sample + tile.num_samples;
- denoise(tile, denoising);
- task->update_progress(&tile, tile.w*tile.h);
- }
-
- task->release_tile(tile);
- }
-
- kgbuffer.free();
- }
+ flush_texture_buffers();
+
+ if (task->type == DeviceTask::FILM_CONVERT) {
+ film_convert(*task, task->buffer, task->rgba_byte, task->rgba_half);
+ }
+ else if (task->type == DeviceTask::SHADER) {
+ shader(*task);
+ }
+ else if (task->type == DeviceTask::RENDER) {
+ RenderTile tile;
+ DenoisingTask denoising(this, *task);
+
+ /* Allocate buffer for kernel globals */
+ device_only_memory<KernelGlobalsDummy> kgbuffer(this, "kernel_globals");
+ kgbuffer.alloc_to_device(1);
+
+ /* Keep rendering tiles until done. */
+ while (task->acquire_tile(this, tile)) {
+ if (tile.task == RenderTile::PATH_TRACE) {
+ assert(tile.task == RenderTile::PATH_TRACE);
+ scoped_timer timer(&tile.buffers->render_time);
+
+ split_kernel->path_trace(task, tile, kgbuffer, *const_mem_map["__data"]);
+
+ /* Complete kernel execution before release tile. */
+ /* This helps in multi-device render;
+ * The device that reaches the critical-section function
+ * release_tile waits (stalling other devices from entering
+ * release_tile) for all kernels to complete. If device1 (a
+ * slow-render device) reaches release_tile first then it would
+ * stall device2 (a fast-render device) from proceeding to render
+ * next tile.
+ */
+ clFinish(cqCommandQueue);
+ }
+ else if (tile.task == RenderTile::DENOISE) {
+ tile.sample = tile.start_sample + tile.num_samples;
+ denoise(tile, denoising);
+ task->update_progress(&tile, tile.w * tile.h);
+ }
+
+ task->release_tile(tile);
+ }
+
+ kgbuffer.free();
+ }
}
-void OpenCLDevice::film_convert(DeviceTask& task, device_ptr buffer, device_ptr rgba_byte, device_ptr rgba_half)
+void OpenCLDevice::film_convert(DeviceTask &task,
+ device_ptr buffer,
+ device_ptr rgba_byte,
+ device_ptr rgba_half)
{
- /* cast arguments to cl types */
- cl_mem d_data = CL_MEM_PTR(const_mem_map["__data"]->device_pointer);
- cl_mem d_rgba = (rgba_byte)? CL_MEM_PTR(rgba_byte): CL_MEM_PTR(rgba_half);
- cl_mem d_buffer = CL_MEM_PTR(buffer);
- cl_int d_x = task.x;
- cl_int d_y = task.y;
- cl_int d_w = task.w;
- cl_int d_h = task.h;
- cl_float d_sample_scale = 1.0f/(task.sample + 1);
- cl_int d_offset = task.offset;
- cl_int d_stride = task.stride;
-
-
- cl_kernel ckFilmConvertKernel = (rgba_byte)? base_program(ustring("convert_to_byte")): base_program(ustring("convert_to_half_float"));
-
- cl_uint start_arg_index =
- kernel_set_args(ckFilmConvertKernel,
- 0,
- d_data,
- d_rgba,
- d_buffer);
-
- set_kernel_arg_buffers(ckFilmConvertKernel, &start_arg_index);
-
- start_arg_index += kernel_set_args(ckFilmConvertKernel,
- start_arg_index,
- d_sample_scale,
- d_x,
- d_y,
- d_w,
- d_h,
- d_offset,
- d_stride);
-
- enqueue_kernel(ckFilmConvertKernel, d_w, d_h);
+ /* cast arguments to cl types */
+ cl_mem d_data = CL_MEM_PTR(const_mem_map["__data"]->device_pointer);
+ cl_mem d_rgba = (rgba_byte) ? CL_MEM_PTR(rgba_byte) : CL_MEM_PTR(rgba_half);
+ cl_mem d_buffer = CL_MEM_PTR(buffer);
+ cl_int d_x = task.x;
+ cl_int d_y = task.y;
+ cl_int d_w = task.w;
+ cl_int d_h = task.h;
+ cl_float d_sample_scale = 1.0f / (task.sample + 1);
+ cl_int d_offset = task.offset;
+ cl_int d_stride = task.stride;
+
+ cl_kernel ckFilmConvertKernel = (rgba_byte) ? base_program(ustring("convert_to_byte")) :
+ base_program(ustring("convert_to_half_float"));
+
+ cl_uint start_arg_index = kernel_set_args(ckFilmConvertKernel, 0, d_data, d_rgba, d_buffer);
+
+ set_kernel_arg_buffers(ckFilmConvertKernel, &start_arg_index);
+
+ start_arg_index += kernel_set_args(ckFilmConvertKernel,
+ start_arg_index,
+ d_sample_scale,
+ d_x,
+ d_y,
+ d_w,
+ d_h,
+ d_offset,
+ d_stride);
+
+ enqueue_kernel(ckFilmConvertKernel, d_w, d_h);
}
bool OpenCLDevice::denoising_non_local_means(device_ptr image_ptr,
@@ -1419,123 +1406,119 @@ bool OpenCLDevice::denoising_non_local_means(device_ptr image_ptr,
device_ptr out_ptr,
DenoisingTask *task)
{
- int stride = task->buffer.stride;
- int w = task->buffer.width;
- int h = task->buffer.h;
- int r = task->nlm_state.r;
- int f = task->nlm_state.f;
- float a = task->nlm_state.a;
- float k_2 = task->nlm_state.k_2;
-
- int pass_stride = task->buffer.pass_stride;
- int num_shifts = (2*r+1)*(2*r+1);
- int channel_offset = task->nlm_state.is_color? task->buffer.pass_stride : 0;
-
- device_sub_ptr difference(task->buffer.temporary_mem, 0, pass_stride*num_shifts);
- device_sub_ptr blurDifference(task->buffer.temporary_mem, pass_stride*num_shifts, pass_stride*num_shifts);
- device_sub_ptr weightAccum(task->buffer.temporary_mem, 2*pass_stride*num_shifts, pass_stride);
- cl_mem weightAccum_mem = CL_MEM_PTR(*weightAccum);
- cl_mem difference_mem = CL_MEM_PTR(*difference);
- cl_mem blurDifference_mem = CL_MEM_PTR(*blurDifference);
-
- cl_mem image_mem = CL_MEM_PTR(image_ptr);
- cl_mem guide_mem = CL_MEM_PTR(guide_ptr);
- cl_mem variance_mem = CL_MEM_PTR(variance_ptr);
- cl_mem out_mem = CL_MEM_PTR(out_ptr);
- cl_mem scale_mem = NULL;
-
- mem_zero_kernel(*weightAccum, sizeof(float)*pass_stride);
- mem_zero_kernel(out_ptr, sizeof(float)*pass_stride);
-
- cl_kernel ckNLMCalcDifference = denoising_program(ustring("filter_nlm_calc_difference"));
- cl_kernel ckNLMBlur = denoising_program(ustring("filter_nlm_blur"));
- cl_kernel ckNLMCalcWeight = denoising_program(ustring("filter_nlm_calc_weight"));
- cl_kernel ckNLMUpdateOutput = denoising_program(ustring("filter_nlm_update_output"));
- cl_kernel ckNLMNormalize = denoising_program(ustring("filter_nlm_normalize"));
-
- kernel_set_args(ckNLMCalcDifference, 0,
- guide_mem,
- variance_mem,
- scale_mem,
- difference_mem,
- w, h, stride,
- pass_stride,
- r, channel_offset,
- 0, a, k_2);
- kernel_set_args(ckNLMBlur, 0,
- difference_mem,
- blurDifference_mem,
- w, h, stride,
- pass_stride,
- r, f);
- kernel_set_args(ckNLMCalcWeight, 0,
- blurDifference_mem,
- difference_mem,
- w, h, stride,
- pass_stride,
- r, f);
- kernel_set_args(ckNLMUpdateOutput, 0,
- blurDifference_mem,
- image_mem,
- out_mem,
- weightAccum_mem,
- w, h, stride,
- pass_stride,
- channel_offset,
- r, f);
-
- enqueue_kernel(ckNLMCalcDifference, w*h, num_shifts, true);
- enqueue_kernel(ckNLMBlur, w*h, num_shifts, true);
- enqueue_kernel(ckNLMCalcWeight, w*h, num_shifts, true);
- enqueue_kernel(ckNLMBlur, w*h, num_shifts, true);
- enqueue_kernel(ckNLMUpdateOutput, w*h, num_shifts, true);
-
- kernel_set_args(ckNLMNormalize, 0,
- out_mem, weightAccum_mem, w, h, stride);
- enqueue_kernel(ckNLMNormalize, w, h);
-
- return true;
+ int stride = task->buffer.stride;
+ int w = task->buffer.width;
+ int h = task->buffer.h;
+ int r = task->nlm_state.r;
+ int f = task->nlm_state.f;
+ float a = task->nlm_state.a;
+ float k_2 = task->nlm_state.k_2;
+
+ int pass_stride = task->buffer.pass_stride;
+ int num_shifts = (2 * r + 1) * (2 * r + 1);
+ int channel_offset = task->nlm_state.is_color ? task->buffer.pass_stride : 0;
+
+ device_sub_ptr difference(task->buffer.temporary_mem, 0, pass_stride * num_shifts);
+ device_sub_ptr blurDifference(
+ task->buffer.temporary_mem, pass_stride * num_shifts, pass_stride * num_shifts);
+ device_sub_ptr weightAccum(
+ task->buffer.temporary_mem, 2 * pass_stride * num_shifts, pass_stride);
+ cl_mem weightAccum_mem = CL_MEM_PTR(*weightAccum);
+ cl_mem difference_mem = CL_MEM_PTR(*difference);
+ cl_mem blurDifference_mem = CL_MEM_PTR(*blurDifference);
+
+ cl_mem image_mem = CL_MEM_PTR(image_ptr);
+ cl_mem guide_mem = CL_MEM_PTR(guide_ptr);
+ cl_mem variance_mem = CL_MEM_PTR(variance_ptr);
+ cl_mem out_mem = CL_MEM_PTR(out_ptr);
+ cl_mem scale_mem = NULL;
+
+ mem_zero_kernel(*weightAccum, sizeof(float) * pass_stride);
+ mem_zero_kernel(out_ptr, sizeof(float) * pass_stride);
+
+ cl_kernel ckNLMCalcDifference = denoising_program(ustring("filter_nlm_calc_difference"));
+ cl_kernel ckNLMBlur = denoising_program(ustring("filter_nlm_blur"));
+ cl_kernel ckNLMCalcWeight = denoising_program(ustring("filter_nlm_calc_weight"));
+ cl_kernel ckNLMUpdateOutput = denoising_program(ustring("filter_nlm_update_output"));
+ cl_kernel ckNLMNormalize = denoising_program(ustring("filter_nlm_normalize"));
+
+ kernel_set_args(ckNLMCalcDifference,
+ 0,
+ guide_mem,
+ variance_mem,
+ scale_mem,
+ difference_mem,
+ w,
+ h,
+ stride,
+ pass_stride,
+ r,
+ channel_offset,
+ 0,
+ a,
+ k_2);
+ kernel_set_args(
+ ckNLMBlur, 0, difference_mem, blurDifference_mem, w, h, stride, pass_stride, r, f);
+ kernel_set_args(
+ ckNLMCalcWeight, 0, blurDifference_mem, difference_mem, w, h, stride, pass_stride, r, f);
+ kernel_set_args(ckNLMUpdateOutput,
+ 0,
+ blurDifference_mem,
+ image_mem,
+ out_mem,
+ weightAccum_mem,
+ w,
+ h,
+ stride,
+ pass_stride,
+ channel_offset,
+ r,
+ f);
+
+ enqueue_kernel(ckNLMCalcDifference, w * h, num_shifts, true);
+ enqueue_kernel(ckNLMBlur, w * h, num_shifts, true);
+ enqueue_kernel(ckNLMCalcWeight, w * h, num_shifts, true);
+ enqueue_kernel(ckNLMBlur, w * h, num_shifts, true);
+ enqueue_kernel(ckNLMUpdateOutput, w * h, num_shifts, true);
+
+ kernel_set_args(ckNLMNormalize, 0, out_mem, weightAccum_mem, w, h, stride);
+ enqueue_kernel(ckNLMNormalize, w, h);
+
+ return true;
}
bool OpenCLDevice::denoising_construct_transform(DenoisingTask *task)
{
- cl_mem buffer_mem = CL_MEM_PTR(task->buffer.mem.device_pointer);
- cl_mem transform_mem = CL_MEM_PTR(task->storage.transform.device_pointer);
- cl_mem rank_mem = CL_MEM_PTR(task->storage.rank.device_pointer);
- cl_mem tile_info_mem = CL_MEM_PTR(task->tile_info_mem.device_pointer);
-
- char use_time = task->buffer.use_time? 1 : 0;
-
- cl_kernel ckFilterConstructTransform = denoising_program(ustring("filter_construct_transform"));
-
- int arg_ofs = kernel_set_args(ckFilterConstructTransform, 0,
- buffer_mem,
- tile_info_mem);
- cl_mem buffers[9];
- for(int i = 0; i < 9; i++) {
- buffers[i] = CL_MEM_PTR(task->tile_info->buffers[i]);
- arg_ofs += kernel_set_args(ckFilterConstructTransform,
- arg_ofs,
- buffers[i]);
- }
- kernel_set_args(ckFilterConstructTransform,
- arg_ofs,
- transform_mem,
- rank_mem,
- task->filter_area,
- task->rect,
- task->buffer.pass_stride,
- task->buffer.frame_stride,
- use_time,
- task->radius,
- task->pca_threshold);
-
- enqueue_kernel(ckFilterConstructTransform,
- task->storage.w,
- task->storage.h,
- 256);
-
- return true;
+ cl_mem buffer_mem = CL_MEM_PTR(task->buffer.mem.device_pointer);
+ cl_mem transform_mem = CL_MEM_PTR(task->storage.transform.device_pointer);
+ cl_mem rank_mem = CL_MEM_PTR(task->storage.rank.device_pointer);
+ cl_mem tile_info_mem = CL_MEM_PTR(task->tile_info_mem.device_pointer);
+
+ char use_time = task->buffer.use_time ? 1 : 0;
+
+ cl_kernel ckFilterConstructTransform = denoising_program(ustring("filter_construct_transform"));
+
+ int arg_ofs = kernel_set_args(ckFilterConstructTransform, 0, buffer_mem, tile_info_mem);
+ cl_mem buffers[9];
+ for (int i = 0; i < 9; i++) {
+ buffers[i] = CL_MEM_PTR(task->tile_info->buffers[i]);
+ arg_ofs += kernel_set_args(ckFilterConstructTransform, arg_ofs, buffers[i]);
+ }
+ kernel_set_args(ckFilterConstructTransform,
+ arg_ofs,
+ transform_mem,
+ rank_mem,
+ task->filter_area,
+ task->rect,
+ task->buffer.pass_stride,
+ task->buffer.frame_stride,
+ use_time,
+ task->radius,
+ task->pca_threshold);
+
+ enqueue_kernel(ckFilterConstructTransform, task->storage.w, task->storage.h, 256);
+
+ return true;
}
bool OpenCLDevice::denoising_accumulate(device_ptr color_ptr,
@@ -1544,136 +1527,130 @@ bool OpenCLDevice::denoising_accumulate(device_ptr color_ptr,
int frame,
DenoisingTask *task)
{
- cl_mem color_mem = CL_MEM_PTR(color_ptr);
- cl_mem color_variance_mem = CL_MEM_PTR(color_variance_ptr);
- cl_mem scale_mem = CL_MEM_PTR(scale_ptr);
-
- cl_mem buffer_mem = CL_MEM_PTR(task->buffer.mem.device_pointer);
- cl_mem transform_mem = CL_MEM_PTR(task->storage.transform.device_pointer);
- cl_mem rank_mem = CL_MEM_PTR(task->storage.rank.device_pointer);
- cl_mem XtWX_mem = CL_MEM_PTR(task->storage.XtWX.device_pointer);
- cl_mem XtWY_mem = CL_MEM_PTR(task->storage.XtWY.device_pointer);
-
- cl_kernel ckNLMCalcDifference = denoising_program(ustring("filter_nlm_calc_difference"));
- cl_kernel ckNLMBlur = denoising_program(ustring("filter_nlm_blur"));
- cl_kernel ckNLMCalcWeight = denoising_program(ustring("filter_nlm_calc_weight"));
- cl_kernel ckNLMConstructGramian = denoising_program(ustring("filter_nlm_construct_gramian"));
-
- int w = task->reconstruction_state.source_w;
- int h = task->reconstruction_state.source_h;
- int stride = task->buffer.stride;
- int frame_offset = frame * task->buffer.frame_stride;
- int t = task->tile_info->frames[frame];
- char use_time = task->buffer.use_time? 1 : 0;
-
- int r = task->radius;
- int pass_stride = task->buffer.pass_stride;
- int num_shifts = (2*r+1)*(2*r+1);
-
- device_sub_ptr difference(task->buffer.temporary_mem, 0, pass_stride*num_shifts);
- device_sub_ptr blurDifference(task->buffer.temporary_mem, pass_stride*num_shifts, pass_stride*num_shifts);
- cl_mem difference_mem = CL_MEM_PTR(*difference);
- cl_mem blurDifference_mem = CL_MEM_PTR(*blurDifference);
-
- kernel_set_args(ckNLMCalcDifference, 0,
- color_mem,
- color_variance_mem,
- scale_mem,
- difference_mem,
- w, h, stride,
- pass_stride,
- r,
- pass_stride,
- frame_offset,
- 1.0f, task->nlm_k_2);
- kernel_set_args(ckNLMBlur, 0,
- difference_mem,
- blurDifference_mem,
- w, h, stride,
- pass_stride,
- r, 4);
- kernel_set_args(ckNLMCalcWeight, 0,
- blurDifference_mem,
- difference_mem,
- w, h, stride,
- pass_stride,
- r, 4);
- kernel_set_args(ckNLMConstructGramian, 0,
- t,
- blurDifference_mem,
- buffer_mem,
- transform_mem,
- rank_mem,
- XtWX_mem,
- XtWY_mem,
- task->reconstruction_state.filter_window,
- w, h, stride,
- pass_stride,
- r, 4,
- frame_offset,
- use_time);
-
- enqueue_kernel(ckNLMCalcDifference, w*h, num_shifts, true);
- enqueue_kernel(ckNLMBlur, w*h, num_shifts, true);
- enqueue_kernel(ckNLMCalcWeight, w*h, num_shifts, true);
- enqueue_kernel(ckNLMBlur, w*h, num_shifts, true);
- enqueue_kernel(ckNLMConstructGramian, w*h, num_shifts, true, 256);
-
- return true;
+ cl_mem color_mem = CL_MEM_PTR(color_ptr);
+ cl_mem color_variance_mem = CL_MEM_PTR(color_variance_ptr);
+ cl_mem scale_mem = CL_MEM_PTR(scale_ptr);
+
+ cl_mem buffer_mem = CL_MEM_PTR(task->buffer.mem.device_pointer);
+ cl_mem transform_mem = CL_MEM_PTR(task->storage.transform.device_pointer);
+ cl_mem rank_mem = CL_MEM_PTR(task->storage.rank.device_pointer);
+ cl_mem XtWX_mem = CL_MEM_PTR(task->storage.XtWX.device_pointer);
+ cl_mem XtWY_mem = CL_MEM_PTR(task->storage.XtWY.device_pointer);
+
+ cl_kernel ckNLMCalcDifference = denoising_program(ustring("filter_nlm_calc_difference"));
+ cl_kernel ckNLMBlur = denoising_program(ustring("filter_nlm_blur"));
+ cl_kernel ckNLMCalcWeight = denoising_program(ustring("filter_nlm_calc_weight"));
+ cl_kernel ckNLMConstructGramian = denoising_program(ustring("filter_nlm_construct_gramian"));
+
+ int w = task->reconstruction_state.source_w;
+ int h = task->reconstruction_state.source_h;
+ int stride = task->buffer.stride;
+ int frame_offset = frame * task->buffer.frame_stride;
+ int t = task->tile_info->frames[frame];
+ char use_time = task->buffer.use_time ? 1 : 0;
+
+ int r = task->radius;
+ int pass_stride = task->buffer.pass_stride;
+ int num_shifts = (2 * r + 1) * (2 * r + 1);
+
+ device_sub_ptr difference(task->buffer.temporary_mem, 0, pass_stride * num_shifts);
+ device_sub_ptr blurDifference(
+ task->buffer.temporary_mem, pass_stride * num_shifts, pass_stride * num_shifts);
+ cl_mem difference_mem = CL_MEM_PTR(*difference);
+ cl_mem blurDifference_mem = CL_MEM_PTR(*blurDifference);
+
+ kernel_set_args(ckNLMCalcDifference,
+ 0,
+ color_mem,
+ color_variance_mem,
+ scale_mem,
+ difference_mem,
+ w,
+ h,
+ stride,
+ pass_stride,
+ r,
+ pass_stride,
+ frame_offset,
+ 1.0f,
+ task->nlm_k_2);
+ kernel_set_args(
+ ckNLMBlur, 0, difference_mem, blurDifference_mem, w, h, stride, pass_stride, r, 4);
+ kernel_set_args(
+ ckNLMCalcWeight, 0, blurDifference_mem, difference_mem, w, h, stride, pass_stride, r, 4);
+ kernel_set_args(ckNLMConstructGramian,
+ 0,
+ t,
+ blurDifference_mem,
+ buffer_mem,
+ transform_mem,
+ rank_mem,
+ XtWX_mem,
+ XtWY_mem,
+ task->reconstruction_state.filter_window,
+ w,
+ h,
+ stride,
+ pass_stride,
+ r,
+ 4,
+ frame_offset,
+ use_time);
+
+ enqueue_kernel(ckNLMCalcDifference, w * h, num_shifts, true);
+ enqueue_kernel(ckNLMBlur, w * h, num_shifts, true);
+ enqueue_kernel(ckNLMCalcWeight, w * h, num_shifts, true);
+ enqueue_kernel(ckNLMBlur, w * h, num_shifts, true);
+ enqueue_kernel(ckNLMConstructGramian, w * h, num_shifts, true, 256);
+
+ return true;
}
-bool OpenCLDevice::denoising_solve(device_ptr output_ptr,
- DenoisingTask *task)
+bool OpenCLDevice::denoising_solve(device_ptr output_ptr, DenoisingTask *task)
{
- cl_kernel ckFinalize = denoising_program(ustring("filter_finalize"));
-
- cl_mem output_mem = CL_MEM_PTR(output_ptr);
- cl_mem rank_mem = CL_MEM_PTR(task->storage.rank.device_pointer);
- cl_mem XtWX_mem = CL_MEM_PTR(task->storage.XtWX.device_pointer);
- cl_mem XtWY_mem = CL_MEM_PTR(task->storage.XtWY.device_pointer);
-
- int w = task->reconstruction_state.source_w;
- int h = task->reconstruction_state.source_h;
-
- kernel_set_args(ckFinalize, 0,
- output_mem,
- rank_mem,
- XtWX_mem,
- XtWY_mem,
- task->filter_area,
- task->reconstruction_state.buffer_params,
- task->render_buffer.samples);
- enqueue_kernel(ckFinalize, w, h);
-
- return true;
+ cl_kernel ckFinalize = denoising_program(ustring("filter_finalize"));
+
+ cl_mem output_mem = CL_MEM_PTR(output_ptr);
+ cl_mem rank_mem = CL_MEM_PTR(task->storage.rank.device_pointer);
+ cl_mem XtWX_mem = CL_MEM_PTR(task->storage.XtWX.device_pointer);
+ cl_mem XtWY_mem = CL_MEM_PTR(task->storage.XtWY.device_pointer);
+
+ int w = task->reconstruction_state.source_w;
+ int h = task->reconstruction_state.source_h;
+
+ kernel_set_args(ckFinalize,
+ 0,
+ output_mem,
+ rank_mem,
+ XtWX_mem,
+ XtWY_mem,
+ task->filter_area,
+ task->reconstruction_state.buffer_params,
+ task->render_buffer.samples);
+ enqueue_kernel(ckFinalize, w, h);
+
+ return true;
}
bool OpenCLDevice::denoising_combine_halves(device_ptr a_ptr,
device_ptr b_ptr,
device_ptr mean_ptr,
device_ptr variance_ptr,
- int r, int4 rect,
+ int r,
+ int4 rect,
DenoisingTask *task)
{
- cl_mem a_mem = CL_MEM_PTR(a_ptr);
- cl_mem b_mem = CL_MEM_PTR(b_ptr);
- cl_mem mean_mem = CL_MEM_PTR(mean_ptr);
- cl_mem variance_mem = CL_MEM_PTR(variance_ptr);
-
- cl_kernel ckFilterCombineHalves = denoising_program(ustring("filter_combine_halves"));
-
- kernel_set_args(ckFilterCombineHalves, 0,
- mean_mem,
- variance_mem,
- a_mem,
- b_mem,
- rect,
- r);
- enqueue_kernel(ckFilterCombineHalves,
- task->rect.z-task->rect.x,
- task->rect.w-task->rect.y);
-
- return true;
+ cl_mem a_mem = CL_MEM_PTR(a_ptr);
+ cl_mem b_mem = CL_MEM_PTR(b_ptr);
+ cl_mem mean_mem = CL_MEM_PTR(mean_ptr);
+ cl_mem variance_mem = CL_MEM_PTR(variance_ptr);
+
+ cl_kernel ckFilterCombineHalves = denoising_program(ustring("filter_combine_halves"));
+
+ kernel_set_args(ckFilterCombineHalves, 0, mean_mem, variance_mem, a_mem, b_mem, rect, r);
+ enqueue_kernel(ckFilterCombineHalves, task->rect.z - task->rect.x, task->rect.w - task->rect.y);
+
+ return true;
}
bool OpenCLDevice::denoising_divide_shadow(device_ptr a_ptr,
@@ -1683,39 +1660,36 @@ bool OpenCLDevice::denoising_divide_shadow(device_ptr a_ptr,
device_ptr buffer_variance_ptr,
DenoisingTask *task)
{
- cl_mem a_mem = CL_MEM_PTR(a_ptr);
- cl_mem b_mem = CL_MEM_PTR(b_ptr);
- cl_mem sample_variance_mem = CL_MEM_PTR(sample_variance_ptr);
- cl_mem sv_variance_mem = CL_MEM_PTR(sv_variance_ptr);
- cl_mem buffer_variance_mem = CL_MEM_PTR(buffer_variance_ptr);
-
- cl_mem tile_info_mem = CL_MEM_PTR(task->tile_info_mem.device_pointer);
-
- cl_kernel ckFilterDivideShadow = denoising_program(ustring("filter_divide_shadow"));
-
- int arg_ofs = kernel_set_args(ckFilterDivideShadow, 0,
- task->render_buffer.samples,
- tile_info_mem);
- cl_mem buffers[9];
- for(int i = 0; i < 9; i++) {
- buffers[i] = CL_MEM_PTR(task->tile_info->buffers[i]);
- arg_ofs += kernel_set_args(ckFilterDivideShadow, arg_ofs,
- buffers[i]);
- }
- kernel_set_args(ckFilterDivideShadow, arg_ofs,
- a_mem,
- b_mem,
- sample_variance_mem,
- sv_variance_mem,
- buffer_variance_mem,
- task->rect,
- task->render_buffer.pass_stride,
- task->render_buffer.offset);
- enqueue_kernel(ckFilterDivideShadow,
- task->rect.z-task->rect.x,
- task->rect.w-task->rect.y);
-
- return true;
+ cl_mem a_mem = CL_MEM_PTR(a_ptr);
+ cl_mem b_mem = CL_MEM_PTR(b_ptr);
+ cl_mem sample_variance_mem = CL_MEM_PTR(sample_variance_ptr);
+ cl_mem sv_variance_mem = CL_MEM_PTR(sv_variance_ptr);
+ cl_mem buffer_variance_mem = CL_MEM_PTR(buffer_variance_ptr);
+
+ cl_mem tile_info_mem = CL_MEM_PTR(task->tile_info_mem.device_pointer);
+
+ cl_kernel ckFilterDivideShadow = denoising_program(ustring("filter_divide_shadow"));
+
+ int arg_ofs = kernel_set_args(
+ ckFilterDivideShadow, 0, task->render_buffer.samples, tile_info_mem);
+ cl_mem buffers[9];
+ for (int i = 0; i < 9; i++) {
+ buffers[i] = CL_MEM_PTR(task->tile_info->buffers[i]);
+ arg_ofs += kernel_set_args(ckFilterDivideShadow, arg_ofs, buffers[i]);
+ }
+ kernel_set_args(ckFilterDivideShadow,
+ arg_ofs,
+ a_mem,
+ b_mem,
+ sample_variance_mem,
+ sv_variance_mem,
+ buffer_variance_mem,
+ task->rect,
+ task->render_buffer.pass_stride,
+ task->render_buffer.offset);
+ enqueue_kernel(ckFilterDivideShadow, task->rect.z - task->rect.x, task->rect.w - task->rect.y);
+
+ return true;
}
bool OpenCLDevice::denoising_get_feature(int mean_offset,
@@ -1725,36 +1699,32 @@ bool OpenCLDevice::denoising_get_feature(int mean_offset,
float scale,
DenoisingTask *task)
{
- cl_mem mean_mem = CL_MEM_PTR(mean_ptr);
- cl_mem variance_mem = CL_MEM_PTR(variance_ptr);
-
- cl_mem tile_info_mem = CL_MEM_PTR(task->tile_info_mem.device_pointer);
-
- cl_kernel ckFilterGetFeature = denoising_program(ustring("filter_get_feature"));
-
- int arg_ofs = kernel_set_args(ckFilterGetFeature, 0,
- task->render_buffer.samples,
- tile_info_mem);
- cl_mem buffers[9];
- for(int i = 0; i < 9; i++) {
- buffers[i] = CL_MEM_PTR(task->tile_info->buffers[i]);
- arg_ofs += kernel_set_args(ckFilterGetFeature, arg_ofs,
- buffers[i]);
- }
- kernel_set_args(ckFilterGetFeature, arg_ofs,
- mean_offset,
- variance_offset,
- mean_mem,
- variance_mem,
- scale,
- task->rect,
- task->render_buffer.pass_stride,
- task->render_buffer.offset);
- enqueue_kernel(ckFilterGetFeature,
- task->rect.z-task->rect.x,
- task->rect.w-task->rect.y);
-
- return true;
+ cl_mem mean_mem = CL_MEM_PTR(mean_ptr);
+ cl_mem variance_mem = CL_MEM_PTR(variance_ptr);
+
+ cl_mem tile_info_mem = CL_MEM_PTR(task->tile_info_mem.device_pointer);
+
+ cl_kernel ckFilterGetFeature = denoising_program(ustring("filter_get_feature"));
+
+ int arg_ofs = kernel_set_args(ckFilterGetFeature, 0, task->render_buffer.samples, tile_info_mem);
+ cl_mem buffers[9];
+ for (int i = 0; i < 9; i++) {
+ buffers[i] = CL_MEM_PTR(task->tile_info->buffers[i]);
+ arg_ofs += kernel_set_args(ckFilterGetFeature, arg_ofs, buffers[i]);
+ }
+ kernel_set_args(ckFilterGetFeature,
+ arg_ofs,
+ mean_offset,
+ variance_offset,
+ mean_mem,
+ variance_mem,
+ scale,
+ task->rect,
+ task->render_buffer.pass_stride,
+ task->render_buffer.offset);
+ enqueue_kernel(ckFilterGetFeature, task->rect.z - task->rect.x, task->rect.w - task->rect.y);
+
+ return true;
}
bool OpenCLDevice::denoising_write_feature(int out_offset,
@@ -1762,24 +1732,23 @@ bool OpenCLDevice::denoising_write_feature(int out_offset,
device_ptr buffer_ptr,
DenoisingTask *task)
{
- cl_mem from_mem = CL_MEM_PTR(from_ptr);
- cl_mem buffer_mem = CL_MEM_PTR(buffer_ptr);
-
- cl_kernel ckFilterWriteFeature = denoising_program(ustring("filter_write_feature"));
-
- kernel_set_args(ckFilterWriteFeature, 0,
- task->render_buffer.samples,
- task->reconstruction_state.buffer_params,
- task->filter_area,
- from_mem,
- buffer_mem,
- out_offset,
- task->rect);
- enqueue_kernel(ckFilterWriteFeature,
- task->filter_area.z,
- task->filter_area.w);
-
- return true;
+ cl_mem from_mem = CL_MEM_PTR(from_ptr);
+ cl_mem buffer_mem = CL_MEM_PTR(buffer_ptr);
+
+ cl_kernel ckFilterWriteFeature = denoising_program(ustring("filter_write_feature"));
+
+ kernel_set_args(ckFilterWriteFeature,
+ 0,
+ task->render_buffer.samples,
+ task->reconstruction_state.buffer_params,
+ task->filter_area,
+ from_mem,
+ buffer_mem,
+ out_offset,
+ task->rect);
+ enqueue_kernel(ckFilterWriteFeature, task->filter_area.z, task->filter_area.w);
+
+ return true;
}
bool OpenCLDevice::denoising_detect_outliers(device_ptr image_ptr,
@@ -1788,155 +1757,155 @@ bool OpenCLDevice::denoising_detect_outliers(device_ptr image_ptr,
device_ptr output_ptr,
DenoisingTask *task)
{
- cl_mem image_mem = CL_MEM_PTR(image_ptr);
- cl_mem variance_mem = CL_MEM_PTR(variance_ptr);
- cl_mem depth_mem = CL_MEM_PTR(depth_ptr);
- cl_mem output_mem = CL_MEM_PTR(output_ptr);
-
- cl_kernel ckFilterDetectOutliers = denoising_program(ustring("filter_detect_outliers"));
-
- kernel_set_args(ckFilterDetectOutliers, 0,
- image_mem,
- variance_mem,
- depth_mem,
- output_mem,
- task->rect,
- task->buffer.pass_stride);
- enqueue_kernel(ckFilterDetectOutliers,
- task->rect.z-task->rect.x,
- task->rect.w-task->rect.y);
-
- return true;
+ cl_mem image_mem = CL_MEM_PTR(image_ptr);
+ cl_mem variance_mem = CL_MEM_PTR(variance_ptr);
+ cl_mem depth_mem = CL_MEM_PTR(depth_ptr);
+ cl_mem output_mem = CL_MEM_PTR(output_ptr);
+
+ cl_kernel ckFilterDetectOutliers = denoising_program(ustring("filter_detect_outliers"));
+
+ kernel_set_args(ckFilterDetectOutliers,
+ 0,
+ image_mem,
+ variance_mem,
+ depth_mem,
+ output_mem,
+ task->rect,
+ task->buffer.pass_stride);
+ enqueue_kernel(ckFilterDetectOutliers, task->rect.z - task->rect.x, task->rect.w - task->rect.y);
+
+ return true;
}
-void OpenCLDevice::denoise(RenderTile &rtile, DenoisingTask& denoising)
+void OpenCLDevice::denoise(RenderTile &rtile, DenoisingTask &denoising)
{
- denoising.functions.construct_transform = function_bind(&OpenCLDevice::denoising_construct_transform, this, &denoising);
- denoising.functions.accumulate = function_bind(&OpenCLDevice::denoising_accumulate, this, _1, _2, _3, _4, &denoising);
- denoising.functions.solve = function_bind(&OpenCLDevice::denoising_solve, this, _1, &denoising);
- denoising.functions.divide_shadow = function_bind(&OpenCLDevice::denoising_divide_shadow, this, _1, _2, _3, _4, _5, &denoising);
- denoising.functions.non_local_means = function_bind(&OpenCLDevice::denoising_non_local_means, this, _1, _2, _3, _4, &denoising);
- denoising.functions.combine_halves = function_bind(&OpenCLDevice::denoising_combine_halves, this, _1, _2, _3, _4, _5, _6, &denoising);
- denoising.functions.get_feature = function_bind(&OpenCLDevice::denoising_get_feature, this, _1, _2, _3, _4, _5, &denoising);
- denoising.functions.write_feature = function_bind(&OpenCLDevice::denoising_write_feature, this, _1, _2, _3, &denoising);
- denoising.functions.detect_outliers = function_bind(&OpenCLDevice::denoising_detect_outliers, this, _1, _2, _3, _4, &denoising);
-
- denoising.filter_area = make_int4(rtile.x, rtile.y, rtile.w, rtile.h);
- denoising.render_buffer.samples = rtile.sample;
- denoising.buffer.gpu_temporary_mem = true;
-
- denoising.run_denoising(&rtile);
+ denoising.functions.construct_transform = function_bind(
+ &OpenCLDevice::denoising_construct_transform, this, &denoising);
+ denoising.functions.accumulate = function_bind(
+ &OpenCLDevice::denoising_accumulate, this, _1, _2, _3, _4, &denoising);
+ denoising.functions.solve = function_bind(&OpenCLDevice::denoising_solve, this, _1, &denoising);
+ denoising.functions.divide_shadow = function_bind(
+ &OpenCLDevice::denoising_divide_shadow, this, _1, _2, _3, _4, _5, &denoising);
+ denoising.functions.non_local_means = function_bind(
+ &OpenCLDevice::denoising_non_local_means, this, _1, _2, _3, _4, &denoising);
+ denoising.functions.combine_halves = function_bind(
+ &OpenCLDevice::denoising_combine_halves, this, _1, _2, _3, _4, _5, _6, &denoising);
+ denoising.functions.get_feature = function_bind(
+ &OpenCLDevice::denoising_get_feature, this, _1, _2, _3, _4, _5, &denoising);
+ denoising.functions.write_feature = function_bind(
+ &OpenCLDevice::denoising_write_feature, this, _1, _2, _3, &denoising);
+ denoising.functions.detect_outliers = function_bind(
+ &OpenCLDevice::denoising_detect_outliers, this, _1, _2, _3, _4, &denoising);
+
+ denoising.filter_area = make_int4(rtile.x, rtile.y, rtile.w, rtile.h);
+ denoising.render_buffer.samples = rtile.sample;
+ denoising.buffer.gpu_temporary_mem = true;
+
+ denoising.run_denoising(&rtile);
}
-void OpenCLDevice::shader(DeviceTask& task)
+void OpenCLDevice::shader(DeviceTask &task)
{
- /* cast arguments to cl types */
- cl_mem d_data = CL_MEM_PTR(const_mem_map["__data"]->device_pointer);
- cl_mem d_input = CL_MEM_PTR(task.shader_input);
- cl_mem d_output = CL_MEM_PTR(task.shader_output);
- cl_int d_shader_eval_type = task.shader_eval_type;
- cl_int d_shader_filter = task.shader_filter;
- cl_int d_shader_x = task.shader_x;
- cl_int d_shader_w = task.shader_w;
- cl_int d_offset = task.offset;
-
- OpenCLDevice::OpenCLProgram *program = &background_program;
- if(task.shader_eval_type >= SHADER_EVAL_BAKE) {
- program = &bake_program;
- }
- else if(task.shader_eval_type == SHADER_EVAL_DISPLACE) {
- program = &displace_program;
- }
- program->wait_for_availability();
- cl_kernel kernel = (*program)();
-
- cl_uint start_arg_index =
- kernel_set_args(kernel,
- 0,
- d_data,
- d_input,
- d_output);
-
- set_kernel_arg_buffers(kernel, &start_arg_index);
-
- start_arg_index += kernel_set_args(kernel,
- start_arg_index,
- d_shader_eval_type);
- if(task.shader_eval_type >= SHADER_EVAL_BAKE) {
- start_arg_index += kernel_set_args(kernel,
- start_arg_index,
- d_shader_filter);
- }
- start_arg_index += kernel_set_args(kernel,
- start_arg_index,
- d_shader_x,
- d_shader_w,
- d_offset);
-
- for(int sample = 0; sample < task.num_samples; sample++) {
-
- if(task.get_cancel())
- break;
-
- kernel_set_args(kernel, start_arg_index, sample);
-
- enqueue_kernel(kernel, task.shader_w, 1);
-
- clFinish(cqCommandQueue);
-
- task.update_progress(NULL);
- }
+ /* cast arguments to cl types */
+ cl_mem d_data = CL_MEM_PTR(const_mem_map["__data"]->device_pointer);
+ cl_mem d_input = CL_MEM_PTR(task.shader_input);
+ cl_mem d_output = CL_MEM_PTR(task.shader_output);
+ cl_int d_shader_eval_type = task.shader_eval_type;
+ cl_int d_shader_filter = task.shader_filter;
+ cl_int d_shader_x = task.shader_x;
+ cl_int d_shader_w = task.shader_w;
+ cl_int d_offset = task.offset;
+
+ OpenCLDevice::OpenCLProgram *program = &background_program;
+ if (task.shader_eval_type >= SHADER_EVAL_BAKE) {
+ program = &bake_program;
+ }
+ else if (task.shader_eval_type == SHADER_EVAL_DISPLACE) {
+ program = &displace_program;
+ }
+ program->wait_for_availability();
+ cl_kernel kernel = (*program)();
+
+ cl_uint start_arg_index = kernel_set_args(kernel, 0, d_data, d_input, d_output);
+
+ set_kernel_arg_buffers(kernel, &start_arg_index);
+
+ start_arg_index += kernel_set_args(kernel, start_arg_index, d_shader_eval_type);
+ if (task.shader_eval_type >= SHADER_EVAL_BAKE) {
+ start_arg_index += kernel_set_args(kernel, start_arg_index, d_shader_filter);
+ }
+ start_arg_index += kernel_set_args(kernel, start_arg_index, d_shader_x, d_shader_w, d_offset);
+
+ for (int sample = 0; sample < task.num_samples; sample++) {
+
+ if (task.get_cancel())
+ break;
+
+ kernel_set_args(kernel, start_arg_index, sample);
+
+ enqueue_kernel(kernel, task.shader_w, 1);
+
+ clFinish(cqCommandQueue);
+
+ task.update_progress(NULL);
+ }
}
string OpenCLDevice::kernel_build_options(const string *debug_src)
{
- string build_options = "-cl-no-signed-zeros -cl-mad-enable ";
-
- if(platform_name == "NVIDIA CUDA") {
- build_options += "-D__KERNEL_OPENCL_NVIDIA__ "
- "-cl-nv-maxrregcount=32 "
- "-cl-nv-verbose ";
-
- uint compute_capability_major, compute_capability_minor;
- clGetDeviceInfo(cdDevice, CL_DEVICE_COMPUTE_CAPABILITY_MAJOR_NV,
- sizeof(cl_uint), &compute_capability_major, NULL);
- clGetDeviceInfo(cdDevice, CL_DEVICE_COMPUTE_CAPABILITY_MINOR_NV,
- sizeof(cl_uint), &compute_capability_minor, NULL);
-
- build_options += string_printf("-D__COMPUTE_CAPABILITY__=%u ",
- compute_capability_major * 100 +
- compute_capability_minor * 10);
- }
-
- else if(platform_name == "Apple")
- build_options += "-D__KERNEL_OPENCL_APPLE__ ";
-
- else if(platform_name == "AMD Accelerated Parallel Processing")
- build_options += "-D__KERNEL_OPENCL_AMD__ ";
-
- else if(platform_name == "Intel(R) OpenCL") {
- build_options += "-D__KERNEL_OPENCL_INTEL_CPU__ ";
-
- /* Options for gdb source level kernel debugging.
- * this segfaults on linux currently.
- */
- if(OpenCLInfo::use_debug() && debug_src)
- build_options += "-g -s \"" + *debug_src + "\" ";
- }
-
- if(info.has_half_images) {
- build_options += "-D__KERNEL_CL_KHR_FP16__ ";
- }
-
- if(OpenCLInfo::use_debug()) {
- build_options += "-D__KERNEL_OPENCL_DEBUG__ ";
- }
-
-#ifdef WITH_CYCLES_DEBUG
- build_options += "-D__KERNEL_DEBUG__ ";
-#endif
-
- return build_options;
+ string build_options = "-cl-no-signed-zeros -cl-mad-enable ";
+
+ if (platform_name == "NVIDIA CUDA") {
+ build_options +=
+ "-D__KERNEL_OPENCL_NVIDIA__ "
+ "-cl-nv-maxrregcount=32 "
+ "-cl-nv-verbose ";
+
+ uint compute_capability_major, compute_capability_minor;
+ clGetDeviceInfo(cdDevice,
+ CL_DEVICE_COMPUTE_CAPABILITY_MAJOR_NV,
+ sizeof(cl_uint),
+ &compute_capability_major,
+ NULL);
+ clGetDeviceInfo(cdDevice,
+ CL_DEVICE_COMPUTE_CAPABILITY_MINOR_NV,
+ sizeof(cl_uint),
+ &compute_capability_minor,
+ NULL);
+
+ build_options += string_printf("-D__COMPUTE_CAPABILITY__=%u ",
+ compute_capability_major * 100 + compute_capability_minor * 10);
+ }
+
+ else if (platform_name == "Apple")
+ build_options += "-D__KERNEL_OPENCL_APPLE__ ";
+
+ else if (platform_name == "AMD Accelerated Parallel Processing")
+ build_options += "-D__KERNEL_OPENCL_AMD__ ";
+
+ else if (platform_name == "Intel(R) OpenCL") {
+ build_options += "-D__KERNEL_OPENCL_INTEL_CPU__ ";
+
+ /* Options for gdb source level kernel debugging.
+ * this segfaults on linux currently.
+ */
+ if (OpenCLInfo::use_debug() && debug_src)
+ build_options += "-g -s \"" + *debug_src + "\" ";
+ }
+
+ if (info.has_half_images) {
+ build_options += "-D__KERNEL_CL_KHR_FP16__ ";
+ }
+
+ if (OpenCLInfo::use_debug()) {
+ build_options += "-D__KERNEL_OPENCL_DEBUG__ ";
+ }
+
+# ifdef WITH_CYCLES_DEBUG
+ build_options += "-D__KERNEL_DEBUG__ ";
+# endif
+
+ return build_options;
}
/* TODO(sergey): In the future we can use variadic templates, once
@@ -1944,137 +1913,130 @@ string OpenCLDevice::kernel_build_options(const string *debug_src)
*/
int OpenCLDevice::kernel_set_args(cl_kernel kernel,
int start_argument_index,
- const ArgumentWrapper& arg1,
- const ArgumentWrapper& arg2,
- const ArgumentWrapper& arg3,
- const ArgumentWrapper& arg4,
- const ArgumentWrapper& arg5,
- const ArgumentWrapper& arg6,
- const ArgumentWrapper& arg7,
- const ArgumentWrapper& arg8,
- const ArgumentWrapper& arg9,
- const ArgumentWrapper& arg10,
- const ArgumentWrapper& arg11,
- const ArgumentWrapper& arg12,
- const ArgumentWrapper& arg13,
- const ArgumentWrapper& arg14,
- const ArgumentWrapper& arg15,
- const ArgumentWrapper& arg16,
- const ArgumentWrapper& arg17,
- const ArgumentWrapper& arg18,
- const ArgumentWrapper& arg19,
- const ArgumentWrapper& arg20,
- const ArgumentWrapper& arg21,
- const ArgumentWrapper& arg22,
- const ArgumentWrapper& arg23,
- const ArgumentWrapper& arg24,
- const ArgumentWrapper& arg25,
- const ArgumentWrapper& arg26,
- const ArgumentWrapper& arg27,
- const ArgumentWrapper& arg28,
- const ArgumentWrapper& arg29,
- const ArgumentWrapper& arg30,
- const ArgumentWrapper& arg31,
- const ArgumentWrapper& arg32,
- const ArgumentWrapper& arg33)
+ const ArgumentWrapper &arg1,
+ const ArgumentWrapper &arg2,
+ const ArgumentWrapper &arg3,
+ const ArgumentWrapper &arg4,
+ const ArgumentWrapper &arg5,
+ const ArgumentWrapper &arg6,
+ const ArgumentWrapper &arg7,
+ const ArgumentWrapper &arg8,
+ const ArgumentWrapper &arg9,
+ const ArgumentWrapper &arg10,
+ const ArgumentWrapper &arg11,
+ const ArgumentWrapper &arg12,
+ const ArgumentWrapper &arg13,
+ const ArgumentWrapper &arg14,
+ const ArgumentWrapper &arg15,
+ const ArgumentWrapper &arg16,
+ const ArgumentWrapper &arg17,
+ const ArgumentWrapper &arg18,
+ const ArgumentWrapper &arg19,
+ const ArgumentWrapper &arg20,
+ const ArgumentWrapper &arg21,
+ const ArgumentWrapper &arg22,
+ const ArgumentWrapper &arg23,
+ const ArgumentWrapper &arg24,
+ const ArgumentWrapper &arg25,
+ const ArgumentWrapper &arg26,
+ const ArgumentWrapper &arg27,
+ const ArgumentWrapper &arg28,
+ const ArgumentWrapper &arg29,
+ const ArgumentWrapper &arg30,
+ const ArgumentWrapper &arg31,
+ const ArgumentWrapper &arg32,
+ const ArgumentWrapper &arg33)
{
- int current_arg_index = 0;
-#define FAKE_VARARG_HANDLE_ARG(arg) \
- do { \
- if(arg.pointer != NULL) { \
- opencl_assert(clSetKernelArg( \
- kernel, \
- start_argument_index + current_arg_index, \
- arg.size, arg.pointer)); \
- ++current_arg_index; \
- } \
- else { \
- return current_arg_index; \
- } \
- } while(false)
- FAKE_VARARG_HANDLE_ARG(arg1);
- FAKE_VARARG_HANDLE_ARG(arg2);
- FAKE_VARARG_HANDLE_ARG(arg3);
- FAKE_VARARG_HANDLE_ARG(arg4);
- FAKE_VARARG_HANDLE_ARG(arg5);
- FAKE_VARARG_HANDLE_ARG(arg6);
- FAKE_VARARG_HANDLE_ARG(arg7);
- FAKE_VARARG_HANDLE_ARG(arg8);
- FAKE_VARARG_HANDLE_ARG(arg9);
- FAKE_VARARG_HANDLE_ARG(arg10);
- FAKE_VARARG_HANDLE_ARG(arg11);
- FAKE_VARARG_HANDLE_ARG(arg12);
- FAKE_VARARG_HANDLE_ARG(arg13);
- FAKE_VARARG_HANDLE_ARG(arg14);
- FAKE_VARARG_HANDLE_ARG(arg15);
- FAKE_VARARG_HANDLE_ARG(arg16);
- FAKE_VARARG_HANDLE_ARG(arg17);
- FAKE_VARARG_HANDLE_ARG(arg18);
- FAKE_VARARG_HANDLE_ARG(arg19);
- FAKE_VARARG_HANDLE_ARG(arg20);
- FAKE_VARARG_HANDLE_ARG(arg21);
- FAKE_VARARG_HANDLE_ARG(arg22);
- FAKE_VARARG_HANDLE_ARG(arg23);
- FAKE_VARARG_HANDLE_ARG(arg24);
- FAKE_VARARG_HANDLE_ARG(arg25);
- FAKE_VARARG_HANDLE_ARG(arg26);
- FAKE_VARARG_HANDLE_ARG(arg27);
- FAKE_VARARG_HANDLE_ARG(arg28);
- FAKE_VARARG_HANDLE_ARG(arg29);
- FAKE_VARARG_HANDLE_ARG(arg30);
- FAKE_VARARG_HANDLE_ARG(arg31);
- FAKE_VARARG_HANDLE_ARG(arg32);
- FAKE_VARARG_HANDLE_ARG(arg33);
-#undef FAKE_VARARG_HANDLE_ARG
- return current_arg_index;
+ int current_arg_index = 0;
+# define FAKE_VARARG_HANDLE_ARG(arg) \
+ do { \
+ if (arg.pointer != NULL) { \
+ opencl_assert(clSetKernelArg( \
+ kernel, start_argument_index + current_arg_index, arg.size, arg.pointer)); \
+ ++current_arg_index; \
+ } \
+ else { \
+ return current_arg_index; \
+ } \
+ } while (false)
+ FAKE_VARARG_HANDLE_ARG(arg1);
+ FAKE_VARARG_HANDLE_ARG(arg2);
+ FAKE_VARARG_HANDLE_ARG(arg3);
+ FAKE_VARARG_HANDLE_ARG(arg4);
+ FAKE_VARARG_HANDLE_ARG(arg5);
+ FAKE_VARARG_HANDLE_ARG(arg6);
+ FAKE_VARARG_HANDLE_ARG(arg7);
+ FAKE_VARARG_HANDLE_ARG(arg8);
+ FAKE_VARARG_HANDLE_ARG(arg9);
+ FAKE_VARARG_HANDLE_ARG(arg10);
+ FAKE_VARARG_HANDLE_ARG(arg11);
+ FAKE_VARARG_HANDLE_ARG(arg12);
+ FAKE_VARARG_HANDLE_ARG(arg13);
+ FAKE_VARARG_HANDLE_ARG(arg14);
+ FAKE_VARARG_HANDLE_ARG(arg15);
+ FAKE_VARARG_HANDLE_ARG(arg16);
+ FAKE_VARARG_HANDLE_ARG(arg17);
+ FAKE_VARARG_HANDLE_ARG(arg18);
+ FAKE_VARARG_HANDLE_ARG(arg19);
+ FAKE_VARARG_HANDLE_ARG(arg20);
+ FAKE_VARARG_HANDLE_ARG(arg21);
+ FAKE_VARARG_HANDLE_ARG(arg22);
+ FAKE_VARARG_HANDLE_ARG(arg23);
+ FAKE_VARARG_HANDLE_ARG(arg24);
+ FAKE_VARARG_HANDLE_ARG(arg25);
+ FAKE_VARARG_HANDLE_ARG(arg26);
+ FAKE_VARARG_HANDLE_ARG(arg27);
+ FAKE_VARARG_HANDLE_ARG(arg28);
+ FAKE_VARARG_HANDLE_ARG(arg29);
+ FAKE_VARARG_HANDLE_ARG(arg30);
+ FAKE_VARARG_HANDLE_ARG(arg31);
+ FAKE_VARARG_HANDLE_ARG(arg32);
+ FAKE_VARARG_HANDLE_ARG(arg33);
+# undef FAKE_VARARG_HANDLE_ARG
+ return current_arg_index;
}
void OpenCLDevice::release_kernel_safe(cl_kernel kernel)
{
- if(kernel) {
- clReleaseKernel(kernel);
- }
+ if (kernel) {
+ clReleaseKernel(kernel);
+ }
}
void OpenCLDevice::release_mem_object_safe(cl_mem mem)
{
- if(mem != NULL) {
- clReleaseMemObject(mem);
- }
+ if (mem != NULL) {
+ clReleaseMemObject(mem);
+ }
}
void OpenCLDevice::release_program_safe(cl_program program)
{
- if(program) {
- clReleaseProgram(program);
- }
+ if (program) {
+ clReleaseProgram(program);
+ }
}
/* ** Those guys are for workign around some compiler-specific bugs ** */
-cl_program OpenCLDevice::load_cached_kernel(ustring key,
- thread_scoped_lock& cache_locker)
+cl_program OpenCLDevice::load_cached_kernel(ustring key, thread_scoped_lock &cache_locker)
{
- return OpenCLCache::get_program(cpPlatform,
- cdDevice,
- key,
- cache_locker);
+ return OpenCLCache::get_program(cpPlatform, cdDevice, key, cache_locker);
}
void OpenCLDevice::store_cached_kernel(cl_program program,
ustring key,
- thread_scoped_lock& cache_locker)
+ thread_scoped_lock &cache_locker)
{
- OpenCLCache::store_program(cpPlatform,
- cdDevice,
- program,
- key,
- cache_locker);
+ OpenCLCache::store_program(cpPlatform, cdDevice, program, key, cache_locker);
}
-Device *opencl_create_split_device(DeviceInfo& info, Stats& stats, Profiler &profiler, bool background)
+Device *opencl_create_split_device(DeviceInfo &info,
+ Stats &stats,
+ Profiler &profiler,
+ bool background)
{
- return new OpenCLDevice(info, stats, profiler, background);
+ return new OpenCLDevice(info, stats, profiler, background);
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/device/opencl/opencl_util.cpp b/intern/cycles/device/opencl/opencl_util.cpp
index 5a1e12af8ab..cc40ad42b06 100644
--- a/intern/cycles/device/opencl/opencl_util.cpp
+++ b/intern/cycles/device/opencl/opencl_util.cpp
@@ -16,1059 +16,1017 @@
#ifdef WITH_OPENCL
-#include "device/opencl/opencl.h"
-#include "device/device_intern.h"
+# include "device/opencl/opencl.h"
+# include "device/device_intern.h"
-#include "util/util_debug.h"
-#include "util/util_logging.h"
-#include "util/util_md5.h"
-#include "util/util_path.h"
-#include "util/util_time.h"
-#include "util/util_system.h"
+# include "util/util_debug.h"
+# include "util/util_logging.h"
+# include "util/util_md5.h"
+# include "util/util_path.h"
+# include "util/util_time.h"
+# include "util/util_system.h"
using std::cerr;
using std::endl;
CCL_NAMESPACE_BEGIN
-OpenCLCache::Slot::ProgramEntry::ProgramEntry()
- : program(NULL),
- mutex(NULL)
+OpenCLCache::Slot::ProgramEntry::ProgramEntry() : program(NULL), mutex(NULL)
{
}
-OpenCLCache::Slot::ProgramEntry::ProgramEntry(const ProgramEntry& rhs)
- : program(rhs.program),
- mutex(NULL)
+OpenCLCache::Slot::ProgramEntry::ProgramEntry(const ProgramEntry &rhs)
+ : program(rhs.program), mutex(NULL)
{
}
OpenCLCache::Slot::ProgramEntry::~ProgramEntry()
{
- delete mutex;
+ delete mutex;
}
-OpenCLCache::Slot::Slot()
- : context_mutex(NULL),
- context(NULL)
+OpenCLCache::Slot::Slot() : context_mutex(NULL), context(NULL)
{
}
-OpenCLCache::Slot::Slot(const Slot& rhs)
- : context_mutex(NULL),
- context(NULL),
- programs(rhs.programs)
+OpenCLCache::Slot::Slot(const Slot &rhs)
+ : context_mutex(NULL), context(NULL), programs(rhs.programs)
{
}
OpenCLCache::Slot::~Slot()
{
- delete context_mutex;
+ delete context_mutex;
}
-OpenCLCache& OpenCLCache::global_instance()
+OpenCLCache &OpenCLCache::global_instance()
{
- static OpenCLCache instance;
- return instance;
+ static OpenCLCache instance;
+ return instance;
}
cl_context OpenCLCache::get_context(cl_platform_id platform,
cl_device_id device,
- thread_scoped_lock& slot_locker)
+ thread_scoped_lock &slot_locker)
{
- assert(platform != NULL);
+ assert(platform != NULL);
- OpenCLCache& self = global_instance();
+ OpenCLCache &self = global_instance();
- thread_scoped_lock cache_lock(self.cache_lock);
+ thread_scoped_lock cache_lock(self.cache_lock);
- pair<CacheMap::iterator,bool> ins = self.cache.insert(
- CacheMap::value_type(PlatformDevicePair(platform, device), Slot()));
+ pair<CacheMap::iterator, bool> ins = self.cache.insert(
+ CacheMap::value_type(PlatformDevicePair(platform, device), Slot()));
- Slot &slot = ins.first->second;
+ Slot &slot = ins.first->second;
- /* create slot lock only while holding cache lock */
- if(!slot.context_mutex)
- slot.context_mutex = new thread_mutex;
+ /* create slot lock only while holding cache lock */
+ if (!slot.context_mutex)
+ slot.context_mutex = new thread_mutex;
- /* need to unlock cache before locking slot, to allow store to complete */
- cache_lock.unlock();
+ /* need to unlock cache before locking slot, to allow store to complete */
+ cache_lock.unlock();
- /* lock the slot */
- slot_locker = thread_scoped_lock(*slot.context_mutex);
+ /* lock the slot */
+ slot_locker = thread_scoped_lock(*slot.context_mutex);
- /* If the thing isn't cached */
- if(slot.context == NULL) {
- /* return with the caller's lock holder holding the slot lock */
- return NULL;
- }
+ /* If the thing isn't cached */
+ if (slot.context == NULL) {
+ /* return with the caller's lock holder holding the slot lock */
+ return NULL;
+ }
- /* the item was already cached, release the slot lock */
- slot_locker.unlock();
+ /* the item was already cached, release the slot lock */
+ slot_locker.unlock();
- cl_int ciErr = clRetainContext(slot.context);
- assert(ciErr == CL_SUCCESS);
- (void) ciErr;
+ cl_int ciErr = clRetainContext(slot.context);
+ assert(ciErr == CL_SUCCESS);
+ (void)ciErr;
- return slot.context;
+ return slot.context;
}
cl_program OpenCLCache::get_program(cl_platform_id platform,
cl_device_id device,
ustring key,
- thread_scoped_lock& slot_locker)
+ thread_scoped_lock &slot_locker)
{
- assert(platform != NULL);
+ assert(platform != NULL);
- OpenCLCache& self = global_instance();
+ OpenCLCache &self = global_instance();
- thread_scoped_lock cache_lock(self.cache_lock);
+ thread_scoped_lock cache_lock(self.cache_lock);
- pair<CacheMap::iterator,bool> ins = self.cache.insert(
- CacheMap::value_type(PlatformDevicePair(platform, device), Slot()));
+ pair<CacheMap::iterator, bool> ins = self.cache.insert(
+ CacheMap::value_type(PlatformDevicePair(platform, device), Slot()));
- Slot &slot = ins.first->second;
+ Slot &slot = ins.first->second;
- pair<Slot::EntryMap::iterator,bool> ins2 = slot.programs.insert(
- Slot::EntryMap::value_type(key, Slot::ProgramEntry()));
+ pair<Slot::EntryMap::iterator, bool> ins2 = slot.programs.insert(
+ Slot::EntryMap::value_type(key, Slot::ProgramEntry()));
- Slot::ProgramEntry &entry = ins2.first->second;
+ Slot::ProgramEntry &entry = ins2.first->second;
- /* create slot lock only while holding cache lock */
- if(!entry.mutex)
- entry.mutex = new thread_mutex;
+ /* create slot lock only while holding cache lock */
+ if (!entry.mutex)
+ entry.mutex = new thread_mutex;
- /* need to unlock cache before locking slot, to allow store to complete */
- cache_lock.unlock();
+ /* need to unlock cache before locking slot, to allow store to complete */
+ cache_lock.unlock();
- /* lock the slot */
- slot_locker = thread_scoped_lock(*entry.mutex);
+ /* lock the slot */
+ slot_locker = thread_scoped_lock(*entry.mutex);
- /* If the thing isn't cached */
- if(entry.program == NULL) {
- /* return with the caller's lock holder holding the slot lock */
- return NULL;
- }
+ /* If the thing isn't cached */
+ if (entry.program == NULL) {
+ /* return with the caller's lock holder holding the slot lock */
+ return NULL;
+ }
- /* the item was already cached, release the slot lock */
- slot_locker.unlock();
+ /* the item was already cached, release the slot lock */
+ slot_locker.unlock();
- cl_int ciErr = clRetainProgram(entry.program);
- assert(ciErr == CL_SUCCESS);
- (void) ciErr;
+ cl_int ciErr = clRetainProgram(entry.program);
+ assert(ciErr == CL_SUCCESS);
+ (void)ciErr;
- return entry.program;
+ return entry.program;
}
void OpenCLCache::store_context(cl_platform_id platform,
cl_device_id device,
cl_context context,
- thread_scoped_lock& slot_locker)
+ thread_scoped_lock &slot_locker)
{
- assert(platform != NULL);
- assert(device != NULL);
- assert(context != NULL);
+ assert(platform != NULL);
+ assert(device != NULL);
+ assert(context != NULL);
- OpenCLCache &self = global_instance();
+ OpenCLCache &self = global_instance();
- thread_scoped_lock cache_lock(self.cache_lock);
- CacheMap::iterator i = self.cache.find(PlatformDevicePair(platform, device));
- cache_lock.unlock();
+ thread_scoped_lock cache_lock(self.cache_lock);
+ CacheMap::iterator i = self.cache.find(PlatformDevicePair(platform, device));
+ cache_lock.unlock();
- Slot &slot = i->second;
+ Slot &slot = i->second;
- /* sanity check */
- assert(i != self.cache.end());
- assert(slot.context == NULL);
+ /* sanity check */
+ assert(i != self.cache.end());
+ assert(slot.context == NULL);
- slot.context = context;
+ slot.context = context;
- /* unlock the slot */
- slot_locker.unlock();
+ /* unlock the slot */
+ slot_locker.unlock();
- /* increment reference count in OpenCL.
- * The caller is going to release the object when done with it. */
- cl_int ciErr = clRetainContext(context);
- assert(ciErr == CL_SUCCESS);
- (void) ciErr;
+ /* increment reference count in OpenCL.
+ * The caller is going to release the object when done with it. */
+ cl_int ciErr = clRetainContext(context);
+ assert(ciErr == CL_SUCCESS);
+ (void)ciErr;
}
void OpenCLCache::store_program(cl_platform_id platform,
cl_device_id device,
cl_program program,
ustring key,
- thread_scoped_lock& slot_locker)
+ thread_scoped_lock &slot_locker)
{
- assert(platform != NULL);
- assert(device != NULL);
- assert(program != NULL);
+ assert(platform != NULL);
+ assert(device != NULL);
+ assert(program != NULL);
- OpenCLCache &self = global_instance();
+ OpenCLCache &self = global_instance();
- thread_scoped_lock cache_lock(self.cache_lock);
+ thread_scoped_lock cache_lock(self.cache_lock);
- CacheMap::iterator i = self.cache.find(PlatformDevicePair(platform, device));
- assert(i != self.cache.end());
- Slot &slot = i->second;
+ CacheMap::iterator i = self.cache.find(PlatformDevicePair(platform, device));
+ assert(i != self.cache.end());
+ Slot &slot = i->second;
- Slot::EntryMap::iterator i2 = slot.programs.find(key);
- assert(i2 != slot.programs.end());
- Slot::ProgramEntry &entry = i2->second;
+ Slot::EntryMap::iterator i2 = slot.programs.find(key);
+ assert(i2 != slot.programs.end());
+ Slot::ProgramEntry &entry = i2->second;
- assert(entry.program == NULL);
+ assert(entry.program == NULL);
- cache_lock.unlock();
+ cache_lock.unlock();
- entry.program = program;
+ entry.program = program;
- /* unlock the slot */
- slot_locker.unlock();
+ /* unlock the slot */
+ slot_locker.unlock();
- /* Increment reference count in OpenCL.
- * The caller is going to release the object when done with it.
- */
- cl_int ciErr = clRetainProgram(program);
- assert(ciErr == CL_SUCCESS);
- (void) ciErr;
+ /* Increment reference count in OpenCL.
+ * The caller is going to release the object when done with it.
+ */
+ cl_int ciErr = clRetainProgram(program);
+ assert(ciErr == CL_SUCCESS);
+ (void)ciErr;
}
string OpenCLCache::get_kernel_md5()
{
- OpenCLCache &self = global_instance();
- thread_scoped_lock lock(self.kernel_md5_lock);
+ OpenCLCache &self = global_instance();
+ thread_scoped_lock lock(self.kernel_md5_lock);
- if(self.kernel_md5.empty()) {
- self.kernel_md5 = path_files_md5_hash(path_get("source"));
- }
- return self.kernel_md5;
+ if (self.kernel_md5.empty()) {
+ self.kernel_md5 = path_files_md5_hash(path_get("source"));
+ }
+ return self.kernel_md5;
}
-static string get_program_source(const string& kernel_file)
+static string get_program_source(const string &kernel_file)
{
- string source = "#include \"kernel/kernels/opencl/" + kernel_file + "\"\n";
- /* We compile kernels consisting of many files. unfortunately OpenCL
- * kernel caches do not seem to recognize changes in included files.
- * so we force recompile on changes by adding the md5 hash of all files.
- */
- source = path_source_replace_includes(source, path_get("source"));
- source += "\n// " + util_md5_string(source) + "\n";
- return source;
+ string source = "#include \"kernel/kernels/opencl/" + kernel_file + "\"\n";
+ /* We compile kernels consisting of many files. unfortunately OpenCL
+ * kernel caches do not seem to recognize changes in included files.
+ * so we force recompile on changes by adding the md5 hash of all files.
+ */
+ source = path_source_replace_includes(source, path_get("source"));
+ source += "\n// " + util_md5_string(source) + "\n";
+ return source;
}
OpenCLDevice::OpenCLProgram::OpenCLProgram(OpenCLDevice *device,
- const string& program_name,
- const string& kernel_file,
- const string& kernel_build_options,
- bool use_stdout)
- : device(device),
- program_name(program_name),
- kernel_file(kernel_file),
- kernel_build_options(kernel_build_options),
- use_stdout(use_stdout)
+ const string &program_name,
+ const string &kernel_file,
+ const string &kernel_build_options,
+ bool use_stdout)
+ : device(device),
+ program_name(program_name),
+ kernel_file(kernel_file),
+ kernel_build_options(kernel_build_options),
+ use_stdout(use_stdout)
{
- loaded = false;
- needs_compiling = true;
- program = NULL;
+ loaded = false;
+ needs_compiling = true;
+ program = NULL;
}
OpenCLDevice::OpenCLProgram::~OpenCLProgram()
{
- release();
+ release();
}
void OpenCLDevice::OpenCLProgram::release()
{
- for(map<ustring, cl_kernel>::iterator kernel = kernels.begin(); kernel != kernels.end(); ++kernel) {
- if(kernel->second) {
- clReleaseKernel(kernel->second);
- kernel->second = NULL;
- }
- }
- if(program) {
- clReleaseProgram(program);
- program = NULL;
- }
+ for (map<ustring, cl_kernel>::iterator kernel = kernels.begin(); kernel != kernels.end();
+ ++kernel) {
+ if (kernel->second) {
+ clReleaseKernel(kernel->second);
+ kernel->second = NULL;
+ }
+ }
+ if (program) {
+ clReleaseProgram(program);
+ program = NULL;
+ }
}
-void OpenCLDevice::OpenCLProgram::add_log(const string& msg, bool debug)
+void OpenCLDevice::OpenCLProgram::add_log(const string &msg, bool debug)
{
- if(!use_stdout) {
- log += msg + "\n";
- }
- else if(!debug) {
- printf("%s\n", msg.c_str());
- fflush(stdout);
- }
- else {
- VLOG(2) << msg;
- }
+ if (!use_stdout) {
+ log += msg + "\n";
+ }
+ else if (!debug) {
+ printf("%s\n", msg.c_str());
+ fflush(stdout);
+ }
+ else {
+ VLOG(2) << msg;
+ }
}
-void OpenCLDevice::OpenCLProgram::add_error(const string& msg)
+void OpenCLDevice::OpenCLProgram::add_error(const string &msg)
{
- if(use_stdout) {
- fprintf(stderr, "%s\n", msg.c_str());
- }
- if(error_msg == "") {
- error_msg += "\n";
- }
- error_msg += msg;
+ if (use_stdout) {
+ fprintf(stderr, "%s\n", msg.c_str());
+ }
+ if (error_msg == "") {
+ error_msg += "\n";
+ }
+ error_msg += msg;
}
void OpenCLDevice::OpenCLProgram::add_kernel(ustring name)
{
- if(!kernels.count(name)) {
- kernels[name] = NULL;
- }
+ if (!kernels.count(name)) {
+ kernels[name] = NULL;
+ }
}
bool OpenCLDevice::OpenCLProgram::build_kernel(const string *debug_src)
{
- string build_options;
- build_options = device->kernel_build_options(debug_src) + kernel_build_options;
+ string build_options;
+ build_options = device->kernel_build_options(debug_src) + kernel_build_options;
- VLOG(1) << "Build options passed to clBuildProgram: '"
- << build_options << "'.";
- cl_int ciErr = clBuildProgram(program, 0, NULL, build_options.c_str(), NULL, NULL);
+ VLOG(1) << "Build options passed to clBuildProgram: '" << build_options << "'.";
+ cl_int ciErr = clBuildProgram(program, 0, NULL, build_options.c_str(), NULL, NULL);
- /* show warnings even if build is successful */
- size_t ret_val_size = 0;
+ /* show warnings even if build is successful */
+ size_t ret_val_size = 0;
- clGetProgramBuildInfo(program, device->cdDevice, CL_PROGRAM_BUILD_LOG, 0, NULL, &ret_val_size);
+ clGetProgramBuildInfo(program, device->cdDevice, CL_PROGRAM_BUILD_LOG, 0, NULL, &ret_val_size);
- if(ciErr != CL_SUCCESS) {
- add_error(string("OpenCL build failed with error ") + clewErrorString(ciErr) + ", errors in console.");
- }
+ if (ciErr != CL_SUCCESS) {
+ add_error(string("OpenCL build failed with error ") + clewErrorString(ciErr) +
+ ", errors in console.");
+ }
- if(ret_val_size > 1) {
- vector<char> build_log(ret_val_size + 1);
- clGetProgramBuildInfo(program, device->cdDevice, CL_PROGRAM_BUILD_LOG, ret_val_size, &build_log[0], NULL);
+ if (ret_val_size > 1) {
+ vector<char> build_log(ret_val_size + 1);
+ clGetProgramBuildInfo(
+ program, device->cdDevice, CL_PROGRAM_BUILD_LOG, ret_val_size, &build_log[0], NULL);
- build_log[ret_val_size] = '\0';
- /* Skip meaningless empty output from the NVidia compiler. */
- if(!(ret_val_size == 2 && build_log[0] == '\n')) {
- add_log(string("OpenCL program ") + program_name + " build output: " + string(&build_log[0]), ciErr == CL_SUCCESS);
- }
- }
+ build_log[ret_val_size] = '\0';
+ /* Skip meaningless empty output from the NVidia compiler. */
+ if (!(ret_val_size == 2 && build_log[0] == '\n')) {
+ add_log(string("OpenCL program ") + program_name + " build output: " + string(&build_log[0]),
+ ciErr == CL_SUCCESS);
+ }
+ }
- return (ciErr == CL_SUCCESS);
+ return (ciErr == CL_SUCCESS);
}
bool OpenCLDevice::OpenCLProgram::compile_kernel(const string *debug_src)
{
- string source = get_program_source(kernel_file);
+ string source = get_program_source(kernel_file);
- if(debug_src) {
- path_write_text(*debug_src, source);
- }
+ if (debug_src) {
+ path_write_text(*debug_src, source);
+ }
- size_t source_len = source.size();
- const char *source_str = source.c_str();
- cl_int ciErr;
+ size_t source_len = source.size();
+ const char *source_str = source.c_str();
+ cl_int ciErr;
- program = clCreateProgramWithSource(device->cxContext,
- 1,
- &source_str,
- &source_len,
- &ciErr);
+ program = clCreateProgramWithSource(device->cxContext, 1, &source_str, &source_len, &ciErr);
- if(ciErr != CL_SUCCESS) {
- add_error(string("OpenCL program creation failed: ") + clewErrorString(ciErr));
- return false;
- }
+ if (ciErr != CL_SUCCESS) {
+ add_error(string("OpenCL program creation failed: ") + clewErrorString(ciErr));
+ return false;
+ }
- double starttime = time_dt();
- add_log(string("Cycles: compiling OpenCL program ") + program_name + "...", false);
- add_log(string("Build flags: ") + kernel_build_options, true);
+ double starttime = time_dt();
+ add_log(string("Cycles: compiling OpenCL program ") + program_name + "...", false);
+ add_log(string("Build flags: ") + kernel_build_options, true);
- if(!build_kernel(debug_src))
- return false;
+ if (!build_kernel(debug_src))
+ return false;
- double elapsed = time_dt() - starttime;
- add_log(string_printf("Kernel compilation of %s finished in %.2lfs.", program_name.c_str(), elapsed), false);
+ double elapsed = time_dt() - starttime;
+ add_log(
+ string_printf("Kernel compilation of %s finished in %.2lfs.", program_name.c_str(), elapsed),
+ false);
- return true;
+ return true;
}
-static void escape_python_string(string& str)
+static void escape_python_string(string &str)
{
- /* Escape string to be passed as a Python raw string with '' quotes'. */
- string_replace(str, "'", "\'");
+ /* Escape string to be passed as a Python raw string with '' quotes'. */
+ string_replace(str, "'", "\'");
}
-bool OpenCLDevice::OpenCLProgram::compile_separate(const string& clbin)
+bool OpenCLDevice::OpenCLProgram::compile_separate(const string &clbin)
{
- vector<string> args;
- args.push_back("--background");
- args.push_back("--factory-startup");
- args.push_back("--python-expr");
-
- int device_platform_id = device->device_num;
- string device_name = device->device_name;
- string platform_name = device->platform_name;
- string build_options = device->kernel_build_options(NULL) + kernel_build_options;
- string kernel_file_escaped = kernel_file;
- string clbin_escaped = clbin;
-
- escape_python_string(device_name);
- escape_python_string(platform_name);
- escape_python_string(build_options);
- escape_python_string(kernel_file_escaped);
- escape_python_string(clbin_escaped);
-
- args.push_back(
- string_printf(
- "import _cycles; _cycles.opencl_compile(r'%d', r'%s', r'%s', r'%s', r'%s', r'%s')",
- device_platform_id,
- device_name.c_str(),
- platform_name.c_str(),
- build_options.c_str(),
- kernel_file_escaped.c_str(),
- clbin_escaped.c_str()));
-
- double starttime = time_dt();
- add_log(string("Cycles: compiling OpenCL program ") + program_name + "...", false);
- add_log(string("Build flags: ") + kernel_build_options, true);
- if(!system_call_self(args) || !path_exists(clbin)) {
- return false;
- }
-
- double elapsed = time_dt() - starttime;
- add_log(string_printf("Kernel compilation of %s finished in %.2lfs.", program_name.c_str(), elapsed), false);
-
- return load_binary(clbin);
+ vector<string> args;
+ args.push_back("--background");
+ args.push_back("--factory-startup");
+ args.push_back("--python-expr");
+
+ int device_platform_id = device->device_num;
+ string device_name = device->device_name;
+ string platform_name = device->platform_name;
+ string build_options = device->kernel_build_options(NULL) + kernel_build_options;
+ string kernel_file_escaped = kernel_file;
+ string clbin_escaped = clbin;
+
+ escape_python_string(device_name);
+ escape_python_string(platform_name);
+ escape_python_string(build_options);
+ escape_python_string(kernel_file_escaped);
+ escape_python_string(clbin_escaped);
+
+ args.push_back(string_printf(
+ "import _cycles; _cycles.opencl_compile(r'%d', r'%s', r'%s', r'%s', r'%s', r'%s')",
+ device_platform_id,
+ device_name.c_str(),
+ platform_name.c_str(),
+ build_options.c_str(),
+ kernel_file_escaped.c_str(),
+ clbin_escaped.c_str()));
+
+ double starttime = time_dt();
+ add_log(string("Cycles: compiling OpenCL program ") + program_name + "...", false);
+ add_log(string("Build flags: ") + kernel_build_options, true);
+ if (!system_call_self(args) || !path_exists(clbin)) {
+ return false;
+ }
+
+ double elapsed = time_dt() - starttime;
+ add_log(
+ string_printf("Kernel compilation of %s finished in %.2lfs.", program_name.c_str(), elapsed),
+ false);
+
+ return load_binary(clbin);
}
/* Compile opencl kernel. This method is called from the _cycles Python
* module compile kernels. Parameters must match function above. */
-bool device_opencl_compile_kernel(const vector<string>& parameters)
+bool device_opencl_compile_kernel(const vector<string> &parameters)
{
- int device_platform_id = std::stoi(parameters[0]);
- const string& device_name = parameters[1];
- const string& platform_name = parameters[2];
- const string& build_options = parameters[3];
- const string& kernel_file = parameters[4];
- const string& binary_path = parameters[5];
-
- if(clewInit() != CLEW_SUCCESS) {
- return false;
- }
-
- vector<OpenCLPlatformDevice> usable_devices;
- OpenCLInfo::get_usable_devices(&usable_devices);
- if(device_platform_id >= usable_devices.size()) {
- return false;
- }
-
- OpenCLPlatformDevice& platform_device = usable_devices[device_platform_id];
- if(platform_device.platform_name != platform_name ||
- platform_device.device_name != device_name)
- {
- return false;
- }
-
- cl_platform_id platform = platform_device.platform_id;
- cl_device_id device = platform_device.device_id;
- const cl_context_properties context_props[] = {
- CL_CONTEXT_PLATFORM, (cl_context_properties) platform,
- 0, 0
- };
-
- cl_int err;
- cl_context context = clCreateContext(context_props, 1, &device, NULL, NULL, &err);
- if(err != CL_SUCCESS) {
- return false;
- }
-
- string source = get_program_source(kernel_file);
- size_t source_len = source.size();
- const char *source_str = source.c_str();
- cl_program program = clCreateProgramWithSource(context, 1, &source_str, &source_len, &err);
- bool result = false;
-
- if(err == CL_SUCCESS) {
- err = clBuildProgram(program, 0, NULL, build_options.c_str(), NULL, NULL);
-
- if(err == CL_SUCCESS) {
- size_t size = 0;
- clGetProgramInfo(program, CL_PROGRAM_BINARY_SIZES, sizeof(size_t), &size, NULL);
- if(size > 0) {
- vector<uint8_t> binary(size);
- uint8_t *bytes = &binary[0];
- clGetProgramInfo(program, CL_PROGRAM_BINARIES, sizeof(uint8_t*), &bytes, NULL);
- result = path_write_binary(binary_path, binary);
- }
- }
- clReleaseProgram(program);
- }
-
- clReleaseContext(context);
-
- return result;
+ int device_platform_id = std::stoi(parameters[0]);
+ const string &device_name = parameters[1];
+ const string &platform_name = parameters[2];
+ const string &build_options = parameters[3];
+ const string &kernel_file = parameters[4];
+ const string &binary_path = parameters[5];
+
+ if (clewInit() != CLEW_SUCCESS) {
+ return false;
+ }
+
+ vector<OpenCLPlatformDevice> usable_devices;
+ OpenCLInfo::get_usable_devices(&usable_devices);
+ if (device_platform_id >= usable_devices.size()) {
+ return false;
+ }
+
+ OpenCLPlatformDevice &platform_device = usable_devices[device_platform_id];
+ if (platform_device.platform_name != platform_name ||
+ platform_device.device_name != device_name) {
+ return false;
+ }
+
+ cl_platform_id platform = platform_device.platform_id;
+ cl_device_id device = platform_device.device_id;
+ const cl_context_properties context_props[] = {
+ CL_CONTEXT_PLATFORM, (cl_context_properties)platform, 0, 0};
+
+ cl_int err;
+ cl_context context = clCreateContext(context_props, 1, &device, NULL, NULL, &err);
+ if (err != CL_SUCCESS) {
+ return false;
+ }
+
+ string source = get_program_source(kernel_file);
+ size_t source_len = source.size();
+ const char *source_str = source.c_str();
+ cl_program program = clCreateProgramWithSource(context, 1, &source_str, &source_len, &err);
+ bool result = false;
+
+ if (err == CL_SUCCESS) {
+ err = clBuildProgram(program, 0, NULL, build_options.c_str(), NULL, NULL);
+
+ if (err == CL_SUCCESS) {
+ size_t size = 0;
+ clGetProgramInfo(program, CL_PROGRAM_BINARY_SIZES, sizeof(size_t), &size, NULL);
+ if (size > 0) {
+ vector<uint8_t> binary(size);
+ uint8_t *bytes = &binary[0];
+ clGetProgramInfo(program, CL_PROGRAM_BINARIES, sizeof(uint8_t *), &bytes, NULL);
+ result = path_write_binary(binary_path, binary);
+ }
+ }
+ clReleaseProgram(program);
+ }
+
+ clReleaseContext(context);
+
+ return result;
}
-bool OpenCLDevice::OpenCLProgram::load_binary(const string& clbin,
- const string *debug_src)
+bool OpenCLDevice::OpenCLProgram::load_binary(const string &clbin, const string *debug_src)
{
- /* read binary into memory */
- vector<uint8_t> binary;
+ /* read binary into memory */
+ vector<uint8_t> binary;
- if(!path_read_binary(clbin, binary)) {
- add_error(string_printf("OpenCL failed to read cached binary %s.", clbin.c_str()));
- return false;
- }
+ if (!path_read_binary(clbin, binary)) {
+ add_error(string_printf("OpenCL failed to read cached binary %s.", clbin.c_str()));
+ return false;
+ }
- /* create program */
- cl_int status, ciErr;
- size_t size = binary.size();
- const uint8_t *bytes = &binary[0];
+ /* create program */
+ cl_int status, ciErr;
+ size_t size = binary.size();
+ const uint8_t *bytes = &binary[0];
- program = clCreateProgramWithBinary(device->cxContext, 1, &device->cdDevice,
- &size, &bytes, &status, &ciErr);
+ program = clCreateProgramWithBinary(
+ device->cxContext, 1, &device->cdDevice, &size, &bytes, &status, &ciErr);
- if(status != CL_SUCCESS || ciErr != CL_SUCCESS) {
- add_error(string("OpenCL failed create program from cached binary ") + clbin + ": "
- + clewErrorString(status) + " " + clewErrorString(ciErr));
- return false;
- }
+ if (status != CL_SUCCESS || ciErr != CL_SUCCESS) {
+ add_error(string("OpenCL failed create program from cached binary ") + clbin + ": " +
+ clewErrorString(status) + " " + clewErrorString(ciErr));
+ return false;
+ }
- if(!build_kernel(debug_src))
- return false;
+ if (!build_kernel(debug_src))
+ return false;
- return true;
+ return true;
}
-bool OpenCLDevice::OpenCLProgram::save_binary(const string& clbin)
+bool OpenCLDevice::OpenCLProgram::save_binary(const string &clbin)
{
- size_t size = 0;
- clGetProgramInfo(program, CL_PROGRAM_BINARY_SIZES, sizeof(size_t), &size, NULL);
+ size_t size = 0;
+ clGetProgramInfo(program, CL_PROGRAM_BINARY_SIZES, sizeof(size_t), &size, NULL);
- if(!size)
- return false;
+ if (!size)
+ return false;
- vector<uint8_t> binary(size);
- uint8_t *bytes = &binary[0];
+ vector<uint8_t> binary(size);
+ uint8_t *bytes = &binary[0];
- clGetProgramInfo(program, CL_PROGRAM_BINARIES, sizeof(uint8_t*), &bytes, NULL);
+ clGetProgramInfo(program, CL_PROGRAM_BINARIES, sizeof(uint8_t *), &bytes, NULL);
- return path_write_binary(clbin, binary);
+ return path_write_binary(clbin, binary);
}
bool OpenCLDevice::OpenCLProgram::load()
{
- loaded = false;
- string device_md5 = device->device_md5_hash(kernel_build_options);
-
- /* Try to use cached kernel. */
- thread_scoped_lock cache_locker;
- ustring cache_key(program_name + device_md5);
- program = device->load_cached_kernel(cache_key,
- cache_locker);
- if (!program) {
- add_log(string("OpenCL program ") + program_name + " not found in cache.", true);
-
- /* need to create source to get md5 */
- string source = get_program_source(kernel_file);
-
- string basename = "cycles_kernel_" + program_name + "_" + device_md5 + "_" + util_md5_string(source);
- basename = path_cache_get(path_join("kernels", basename));
- string clbin = basename + ".clbin";
-
- /* If binary kernel exists already, try use it. */
- if(path_exists(clbin) && load_binary(clbin)) {
- /* Kernel loaded from binary, nothing to do. */
- add_log(string("Loaded program from ") + clbin + ".", true);
-
- /* Cache the program. */
- device->store_cached_kernel(program,
- cache_key,
- cache_locker);
- }
- else {
- add_log(string("OpenCL program ") + program_name + " not found on disk.", true);
- cache_locker.unlock();
- }
- }
-
- if (program) {
- create_kernels();
- loaded = true;
- needs_compiling = false;
- }
-
- return loaded;
+ loaded = false;
+ string device_md5 = device->device_md5_hash(kernel_build_options);
+
+ /* Try to use cached kernel. */
+ thread_scoped_lock cache_locker;
+ ustring cache_key(program_name + device_md5);
+ program = device->load_cached_kernel(cache_key, cache_locker);
+ if (!program) {
+ add_log(string("OpenCL program ") + program_name + " not found in cache.", true);
+
+ /* need to create source to get md5 */
+ string source = get_program_source(kernel_file);
+
+ string basename = "cycles_kernel_" + program_name + "_" + device_md5 + "_" +
+ util_md5_string(source);
+ basename = path_cache_get(path_join("kernels", basename));
+ string clbin = basename + ".clbin";
+
+ /* If binary kernel exists already, try use it. */
+ if (path_exists(clbin) && load_binary(clbin)) {
+ /* Kernel loaded from binary, nothing to do. */
+ add_log(string("Loaded program from ") + clbin + ".", true);
+
+ /* Cache the program. */
+ device->store_cached_kernel(program, cache_key, cache_locker);
+ }
+ else {
+ add_log(string("OpenCL program ") + program_name + " not found on disk.", true);
+ cache_locker.unlock();
+ }
+ }
+
+ if (program) {
+ create_kernels();
+ loaded = true;
+ needs_compiling = false;
+ }
+
+ return loaded;
}
void OpenCLDevice::OpenCLProgram::compile()
{
- assert(device);
-
- string device_md5 = device->device_md5_hash(kernel_build_options);
-
- /* Try to use cached kernel. */
- thread_scoped_lock cache_locker;
- ustring cache_key(program_name + device_md5);
- program = device->load_cached_kernel(cache_key,
- cache_locker);
-
- if (!program)
- {
-
- add_log(string("OpenCL program ") + program_name + " not found in cache.", true);
-
- /* need to create source to get md5 */
- string source = get_program_source(kernel_file);
-
- string basename = "cycles_kernel_" + program_name + "_" + device_md5 + "_" + util_md5_string(source);
- basename = path_cache_get(path_join("kernels", basename));
- string clbin = basename + ".clbin";
-
- /* path to preprocessed source for debugging */
- string clsrc, *debug_src = NULL;
-
- if(OpenCLInfo::use_debug()) {
- clsrc = basename + ".cl";
- debug_src = &clsrc;
- }
-
- /* If binary kernel exists already, try use it. */
- if(compile_separate(clbin)) {
- add_log(string("Built and loaded program from ") + clbin + ".", true);
- loaded = true;
- }
- else {
- add_log(string("Separate-process building of ") + clbin + " failed, will fall back to regular building.", true);
-
- /* If does not exist or loading binary failed, compile kernel. */
- if(!compile_kernel(debug_src)) {
- needs_compiling = false;
- return;
- }
-
- /* Save binary for reuse. */
- if(!save_binary(clbin)) {
- add_log(string("Saving compiled OpenCL kernel to ") + clbin + " failed!", true);
- }
- }
-
- /* Cache the program. */
- device->store_cached_kernel(program,
- cache_key,
- cache_locker);
- }
-
- create_kernels();
- needs_compiling = false;
- loaded = true;
+ assert(device);
+
+ string device_md5 = device->device_md5_hash(kernel_build_options);
+
+ /* Try to use cached kernel. */
+ thread_scoped_lock cache_locker;
+ ustring cache_key(program_name + device_md5);
+ program = device->load_cached_kernel(cache_key, cache_locker);
+
+ if (!program) {
+
+ add_log(string("OpenCL program ") + program_name + " not found in cache.", true);
+
+ /* need to create source to get md5 */
+ string source = get_program_source(kernel_file);
+
+ string basename = "cycles_kernel_" + program_name + "_" + device_md5 + "_" +
+ util_md5_string(source);
+ basename = path_cache_get(path_join("kernels", basename));
+ string clbin = basename + ".clbin";
+
+ /* path to preprocessed source for debugging */
+ string clsrc, *debug_src = NULL;
+
+ if (OpenCLInfo::use_debug()) {
+ clsrc = basename + ".cl";
+ debug_src = &clsrc;
+ }
+
+ /* If binary kernel exists already, try use it. */
+ if (compile_separate(clbin)) {
+ add_log(string("Built and loaded program from ") + clbin + ".", true);
+ loaded = true;
+ }
+ else {
+ add_log(string("Separate-process building of ") + clbin +
+ " failed, will fall back to regular building.",
+ true);
+
+ /* If does not exist or loading binary failed, compile kernel. */
+ if (!compile_kernel(debug_src)) {
+ needs_compiling = false;
+ return;
+ }
+
+ /* Save binary for reuse. */
+ if (!save_binary(clbin)) {
+ add_log(string("Saving compiled OpenCL kernel to ") + clbin + " failed!", true);
+ }
+ }
+
+ /* Cache the program. */
+ device->store_cached_kernel(program, cache_key, cache_locker);
+ }
+
+ create_kernels();
+ needs_compiling = false;
+ loaded = true;
}
void OpenCLDevice::OpenCLProgram::create_kernels()
{
- for(map<ustring, cl_kernel>::iterator kernel = kernels.begin(); kernel != kernels.end(); ++kernel) {
- assert(kernel->second == NULL);
- cl_int ciErr;
- string name = "kernel_ocl_" + kernel->first.string();
- kernel->second = clCreateKernel(program, name.c_str(), &ciErr);
- if(device->opencl_error(ciErr)) {
- add_error(string("Error getting kernel ") + name + " from program " + program_name + ": " + clewErrorString(ciErr));
- return;
- }
- }
+ for (map<ustring, cl_kernel>::iterator kernel = kernels.begin(); kernel != kernels.end();
+ ++kernel) {
+ assert(kernel->second == NULL);
+ cl_int ciErr;
+ string name = "kernel_ocl_" + kernel->first.string();
+ kernel->second = clCreateKernel(program, name.c_str(), &ciErr);
+ if (device->opencl_error(ciErr)) {
+ add_error(string("Error getting kernel ") + name + " from program " + program_name + ": " +
+ clewErrorString(ciErr));
+ return;
+ }
+ }
}
bool OpenCLDevice::OpenCLProgram::wait_for_availability()
{
- add_log(string("Waiting for availability of ") + program_name + ".", true);
- while (needs_compiling) {
- time_sleep(0.1);
- }
- return loaded;
+ add_log(string("Waiting for availability of ") + program_name + ".", true);
+ while (needs_compiling) {
+ time_sleep(0.1);
+ }
+ return loaded;
}
void OpenCLDevice::OpenCLProgram::report_error()
{
- /* If loaded is true, there was no error. */
- if(loaded) return;
- /* if use_stdout is true, the error was already reported. */
- if(use_stdout) return;
-
- cerr << error_msg << endl;
- if(!compile_output.empty()) {
- cerr << "OpenCL kernel build output for " << program_name << ":" << endl;
- cerr << compile_output << endl;
- }
+ /* If loaded is true, there was no error. */
+ if (loaded)
+ return;
+ /* if use_stdout is true, the error was already reported. */
+ if (use_stdout)
+ return;
+
+ cerr << error_msg << endl;
+ if (!compile_output.empty()) {
+ cerr << "OpenCL kernel build output for " << program_name << ":" << endl;
+ cerr << compile_output << endl;
+ }
}
cl_kernel OpenCLDevice::OpenCLProgram::operator()()
{
- assert(kernels.size() == 1);
- return kernels.begin()->second;
+ assert(kernels.size() == 1);
+ return kernels.begin()->second;
}
cl_kernel OpenCLDevice::OpenCLProgram::operator()(ustring name)
{
- assert(kernels.count(name));
- return kernels[name];
+ assert(kernels.count(name));
+ return kernels[name];
}
cl_device_type OpenCLInfo::device_type()
{
- switch(DebugFlags().opencl.device_type)
- {
- case DebugFlags::OpenCL::DEVICE_NONE:
- return 0;
- case DebugFlags::OpenCL::DEVICE_ALL:
- return CL_DEVICE_TYPE_ALL;
- case DebugFlags::OpenCL::DEVICE_DEFAULT:
- return CL_DEVICE_TYPE_DEFAULT;
- case DebugFlags::OpenCL::DEVICE_CPU:
- return CL_DEVICE_TYPE_CPU;
- case DebugFlags::OpenCL::DEVICE_GPU:
- return CL_DEVICE_TYPE_GPU;
- case DebugFlags::OpenCL::DEVICE_ACCELERATOR:
- return CL_DEVICE_TYPE_ACCELERATOR;
- default:
- return CL_DEVICE_TYPE_ALL;
- }
+ switch (DebugFlags().opencl.device_type) {
+ case DebugFlags::OpenCL::DEVICE_NONE:
+ return 0;
+ case DebugFlags::OpenCL::DEVICE_ALL:
+ return CL_DEVICE_TYPE_ALL;
+ case DebugFlags::OpenCL::DEVICE_DEFAULT:
+ return CL_DEVICE_TYPE_DEFAULT;
+ case DebugFlags::OpenCL::DEVICE_CPU:
+ return CL_DEVICE_TYPE_CPU;
+ case DebugFlags::OpenCL::DEVICE_GPU:
+ return CL_DEVICE_TYPE_GPU;
+ case DebugFlags::OpenCL::DEVICE_ACCELERATOR:
+ return CL_DEVICE_TYPE_ACCELERATOR;
+ default:
+ return CL_DEVICE_TYPE_ALL;
+ }
}
bool OpenCLInfo::use_debug()
{
- return DebugFlags().opencl.debug;
+ return DebugFlags().opencl.debug;
}
-bool OpenCLInfo::device_supported(const string& platform_name,
- const cl_device_id device_id)
+bool OpenCLInfo::device_supported(const string &platform_name, const cl_device_id device_id)
{
- cl_device_type device_type;
- if(!get_device_type(device_id, &device_type)) {
- return false;
- }
- string device_name;
- if(!get_device_name(device_id, &device_name)) {
- return false;
- }
-
- int driver_major = 0;
- int driver_minor = 0;
- if(!get_driver_version(device_id, &driver_major, &driver_minor)) {
- return false;
- }
- VLOG(3) << "OpenCL driver version " << driver_major << "." << driver_minor;
-
- /* It is possible tyo have Iris GPU on AMD/Apple OpenCL framework
- * (aka, it will not be on Intel framework). This isn't supported
- * and needs an explicit blacklist.
- */
- if(strstr(device_name.c_str(), "Iris")) {
- return false;
- }
- if(platform_name == "AMD Accelerated Parallel Processing" &&
- device_type == CL_DEVICE_TYPE_GPU)
- {
- if(driver_major < 2236) {
- VLOG(1) << "AMD driver version " << driver_major << "." << driver_minor << " not supported.";
- return false;
- }
- const char *blacklist[] = {
- /* GCN 1 */
- "Tahiti", "Pitcairn", "Capeverde", "Oland", "Hainan",
- NULL
- };
- for(int i = 0; blacklist[i] != NULL; i++) {
- if(device_name == blacklist[i]) {
- VLOG(1) << "AMD device " << device_name << " not supported";
- return false;
- }
- }
- return true;
- }
- if(platform_name == "Apple" && device_type == CL_DEVICE_TYPE_GPU) {
- return false;
- }
- return false;
+ cl_device_type device_type;
+ if (!get_device_type(device_id, &device_type)) {
+ return false;
+ }
+ string device_name;
+ if (!get_device_name(device_id, &device_name)) {
+ return false;
+ }
+
+ int driver_major = 0;
+ int driver_minor = 0;
+ if (!get_driver_version(device_id, &driver_major, &driver_minor)) {
+ return false;
+ }
+ VLOG(3) << "OpenCL driver version " << driver_major << "." << driver_minor;
+
+ /* It is possible tyo have Iris GPU on AMD/Apple OpenCL framework
+ * (aka, it will not be on Intel framework). This isn't supported
+ * and needs an explicit blacklist.
+ */
+ if (strstr(device_name.c_str(), "Iris")) {
+ return false;
+ }
+ if (platform_name == "AMD Accelerated Parallel Processing" &&
+ device_type == CL_DEVICE_TYPE_GPU) {
+ if (driver_major < 2236) {
+ VLOG(1) << "AMD driver version " << driver_major << "." << driver_minor << " not supported.";
+ return false;
+ }
+ const char *blacklist[] = {/* GCN 1 */
+ "Tahiti",
+ "Pitcairn",
+ "Capeverde",
+ "Oland",
+ "Hainan",
+ NULL};
+ for (int i = 0; blacklist[i] != NULL; i++) {
+ if (device_name == blacklist[i]) {
+ VLOG(1) << "AMD device " << device_name << " not supported";
+ return false;
+ }
+ }
+ return true;
+ }
+ if (platform_name == "Apple" && device_type == CL_DEVICE_TYPE_GPU) {
+ return false;
+ }
+ return false;
}
-bool OpenCLInfo::platform_version_check(cl_platform_id platform,
- string *error)
+bool OpenCLInfo::platform_version_check(cl_platform_id platform, string *error)
{
- const int req_major = 1, req_minor = 1;
- int major, minor;
- char version[256];
- clGetPlatformInfo(platform,
- CL_PLATFORM_VERSION,
- sizeof(version),
- &version,
- NULL);
- if(sscanf(version, "OpenCL %d.%d", &major, &minor) < 2) {
- if(error != NULL) {
- *error = string_printf("OpenCL: failed to parse platform version string (%s).", version);
- }
- return false;
- }
- if(!((major == req_major && minor >= req_minor) || (major > req_major))) {
- if(error != NULL) {
- *error = string_printf("OpenCL: platform version 1.1 or later required, found %d.%d", major, minor);
- }
- return false;
- }
- if(error != NULL) {
- *error = "";
- }
- return true;
+ const int req_major = 1, req_minor = 1;
+ int major, minor;
+ char version[256];
+ clGetPlatformInfo(platform, CL_PLATFORM_VERSION, sizeof(version), &version, NULL);
+ if (sscanf(version, "OpenCL %d.%d", &major, &minor) < 2) {
+ if (error != NULL) {
+ *error = string_printf("OpenCL: failed to parse platform version string (%s).", version);
+ }
+ return false;
+ }
+ if (!((major == req_major && minor >= req_minor) || (major > req_major))) {
+ if (error != NULL) {
+ *error = string_printf(
+ "OpenCL: platform version 1.1 or later required, found %d.%d", major, minor);
+ }
+ return false;
+ }
+ if (error != NULL) {
+ *error = "";
+ }
+ return true;
}
-bool OpenCLInfo::device_version_check(cl_device_id device,
- string *error)
+bool OpenCLInfo::device_version_check(cl_device_id device, string *error)
{
- const int req_major = 1, req_minor = 1;
- int major, minor;
- char version[256];
- clGetDeviceInfo(device,
- CL_DEVICE_OPENCL_C_VERSION,
- sizeof(version),
- &version,
- NULL);
- if(sscanf(version, "OpenCL C %d.%d", &major, &minor) < 2) {
- if(error != NULL) {
- *error = string_printf("OpenCL: failed to parse OpenCL C version string (%s).", version);
- }
- return false;
- }
- if(!((major == req_major && minor >= req_minor) || (major > req_major))) {
- if(error != NULL) {
- *error = string_printf("OpenCL: C version 1.1 or later required, found %d.%d", major, minor);
- }
- return false;
- }
- if(error != NULL) {
- *error = "";
- }
- return true;
+ const int req_major = 1, req_minor = 1;
+ int major, minor;
+ char version[256];
+ clGetDeviceInfo(device, CL_DEVICE_OPENCL_C_VERSION, sizeof(version), &version, NULL);
+ if (sscanf(version, "OpenCL C %d.%d", &major, &minor) < 2) {
+ if (error != NULL) {
+ *error = string_printf("OpenCL: failed to parse OpenCL C version string (%s).", version);
+ }
+ return false;
+ }
+ if (!((major == req_major && minor >= req_minor) || (major > req_major))) {
+ if (error != NULL) {
+ *error = string_printf("OpenCL: C version 1.1 or later required, found %d.%d", major, minor);
+ }
+ return false;
+ }
+ if (error != NULL) {
+ *error = "";
+ }
+ return true;
}
-string OpenCLInfo::get_hardware_id(const string& platform_name, cl_device_id device_id)
+string OpenCLInfo::get_hardware_id(const string &platform_name, cl_device_id device_id)
{
- if(platform_name == "AMD Accelerated Parallel Processing" || platform_name == "Apple") {
- /* Use cl_amd_device_topology extension. */
- cl_char topology[24];
- if(clGetDeviceInfo(device_id, 0x4037, sizeof(topology), topology, NULL) == CL_SUCCESS && topology[0] == 1) {
- return string_printf("%02x:%02x.%01x",
- (unsigned int)topology[21],
- (unsigned int)topology[22],
- (unsigned int)topology[23]);
- }
- }
- else if(platform_name == "NVIDIA CUDA") {
- /* Use two undocumented options of the cl_nv_device_attribute_query extension. */
- cl_int bus_id, slot_id;
- if(clGetDeviceInfo(device_id, 0x4008, sizeof(cl_int), &bus_id, NULL) == CL_SUCCESS &&
- clGetDeviceInfo(device_id, 0x4009, sizeof(cl_int), &slot_id, NULL) == CL_SUCCESS) {
- return string_printf("%02x:%02x.%01x",
- (unsigned int)(bus_id),
- (unsigned int)(slot_id >> 3),
- (unsigned int)(slot_id & 0x7));
- }
- }
- /* No general way to get a hardware ID from OpenCL => give up. */
- return "";
+ if (platform_name == "AMD Accelerated Parallel Processing" || platform_name == "Apple") {
+ /* Use cl_amd_device_topology extension. */
+ cl_char topology[24];
+ if (clGetDeviceInfo(device_id, 0x4037, sizeof(topology), topology, NULL) == CL_SUCCESS &&
+ topology[0] == 1) {
+ return string_printf("%02x:%02x.%01x",
+ (unsigned int)topology[21],
+ (unsigned int)topology[22],
+ (unsigned int)topology[23]);
+ }
+ }
+ else if (platform_name == "NVIDIA CUDA") {
+ /* Use two undocumented options of the cl_nv_device_attribute_query extension. */
+ cl_int bus_id, slot_id;
+ if (clGetDeviceInfo(device_id, 0x4008, sizeof(cl_int), &bus_id, NULL) == CL_SUCCESS &&
+ clGetDeviceInfo(device_id, 0x4009, sizeof(cl_int), &slot_id, NULL) == CL_SUCCESS) {
+ return string_printf("%02x:%02x.%01x",
+ (unsigned int)(bus_id),
+ (unsigned int)(slot_id >> 3),
+ (unsigned int)(slot_id & 0x7));
+ }
+ }
+ /* No general way to get a hardware ID from OpenCL => give up. */
+ return "";
}
-void OpenCLInfo::get_usable_devices(vector<OpenCLPlatformDevice> *usable_devices,
- bool force_all)
+void OpenCLInfo::get_usable_devices(vector<OpenCLPlatformDevice> *usable_devices, bool force_all)
{
- const cl_device_type device_type = OpenCLInfo::device_type();
- static bool first_time = true;
-#define FIRST_VLOG(severity) if(first_time) VLOG(severity)
-
- usable_devices->clear();
-
- if(device_type == 0) {
- FIRST_VLOG(2) << "OpenCL devices are forced to be disabled.";
- first_time = false;
- return;
- }
-
- cl_int error;
- vector<cl_device_id> device_ids;
- vector<cl_platform_id> platform_ids;
-
- /* Get platforms. */
- if(!get_platforms(&platform_ids, &error)) {
- FIRST_VLOG(2) << "Error fetching platforms:"
- << string(clewErrorString(error));
- first_time = false;
- return;
- }
- if(platform_ids.size() == 0) {
- FIRST_VLOG(2) << "No OpenCL platforms were found.";
- first_time = false;
- return;
- }
- /* Devices are numbered consecutively across platforms. */
- for(int platform = 0; platform < platform_ids.size(); platform++) {
- cl_platform_id platform_id = platform_ids[platform];
- string platform_name;
- if(!get_platform_name(platform_id, &platform_name)) {
- FIRST_VLOG(2) << "Failed to get platform name, ignoring.";
- continue;
- }
- FIRST_VLOG(2) << "Enumerating devices for platform "
- << platform_name << ".";
- if(!platform_version_check(platform_id)) {
- FIRST_VLOG(2) << "Ignoring platform " << platform_name
- << " due to too old compiler version.";
- continue;
- }
- if(!get_platform_devices(platform_id,
- device_type,
- &device_ids,
- &error))
- {
- FIRST_VLOG(2) << "Ignoring platform " << platform_name
- << ", failed to fetch of devices: "
- << string(clewErrorString(error));
- continue;
- }
- if(device_ids.size() == 0) {
- FIRST_VLOG(2) << "Ignoring platform " << platform_name
- << ", it has no devices.";
- continue;
- }
- for(int num = 0; num < device_ids.size(); num++) {
- const cl_device_id device_id = device_ids[num];
- string device_name;
- if(!get_device_name(device_id, &device_name, &error)) {
- FIRST_VLOG(2) << "Failed to fetch device name: "
- << string(clewErrorString(error))
- << ", ignoring.";
- continue;
- }
- if(!device_version_check(device_id)) {
- FIRST_VLOG(2) << "Ignoring device " << device_name
- << " due to old compiler version.";
- continue;
- }
- if(force_all ||
- device_supported(platform_name, device_id))
- {
- cl_device_type device_type;
- if(!get_device_type(device_id, &device_type, &error)) {
- FIRST_VLOG(2) << "Ignoring device " << device_name
- << ", failed to fetch device type:"
- << string(clewErrorString(error));
- continue;
- }
- string readable_device_name =
- get_readable_device_name(device_id);
- if(readable_device_name != device_name) {
- FIRST_VLOG(2) << "Using more readable device name: "
- << readable_device_name;
- }
- FIRST_VLOG(2) << "Adding new device "
- << readable_device_name << ".";
- string hardware_id = get_hardware_id(platform_name, device_id);
- string device_extensions = get_device_extensions(device_id);
- usable_devices->push_back(OpenCLPlatformDevice(
- platform_id,
- platform_name,
- device_id,
- device_type,
- readable_device_name,
- hardware_id,
- device_extensions));
- }
- else {
- FIRST_VLOG(2) << "Ignoring device " << device_name
- << ", not officially supported yet.";
- }
- }
- }
- first_time = false;
+ const cl_device_type device_type = OpenCLInfo::device_type();
+ static bool first_time = true;
+# define FIRST_VLOG(severity) \
+ if (first_time) \
+ VLOG(severity)
+
+ usable_devices->clear();
+
+ if (device_type == 0) {
+ FIRST_VLOG(2) << "OpenCL devices are forced to be disabled.";
+ first_time = false;
+ return;
+ }
+
+ cl_int error;
+ vector<cl_device_id> device_ids;
+ vector<cl_platform_id> platform_ids;
+
+ /* Get platforms. */
+ if (!get_platforms(&platform_ids, &error)) {
+ FIRST_VLOG(2) << "Error fetching platforms:" << string(clewErrorString(error));
+ first_time = false;
+ return;
+ }
+ if (platform_ids.size() == 0) {
+ FIRST_VLOG(2) << "No OpenCL platforms were found.";
+ first_time = false;
+ return;
+ }
+ /* Devices are numbered consecutively across platforms. */
+ for (int platform = 0; platform < platform_ids.size(); platform++) {
+ cl_platform_id platform_id = platform_ids[platform];
+ string platform_name;
+ if (!get_platform_name(platform_id, &platform_name)) {
+ FIRST_VLOG(2) << "Failed to get platform name, ignoring.";
+ continue;
+ }
+ FIRST_VLOG(2) << "Enumerating devices for platform " << platform_name << ".";
+ if (!platform_version_check(platform_id)) {
+ FIRST_VLOG(2) << "Ignoring platform " << platform_name
+ << " due to too old compiler version.";
+ continue;
+ }
+ if (!get_platform_devices(platform_id, device_type, &device_ids, &error)) {
+ FIRST_VLOG(2) << "Ignoring platform " << platform_name
+ << ", failed to fetch of devices: " << string(clewErrorString(error));
+ continue;
+ }
+ if (device_ids.size() == 0) {
+ FIRST_VLOG(2) << "Ignoring platform " << platform_name << ", it has no devices.";
+ continue;
+ }
+ for (int num = 0; num < device_ids.size(); num++) {
+ const cl_device_id device_id = device_ids[num];
+ string device_name;
+ if (!get_device_name(device_id, &device_name, &error)) {
+ FIRST_VLOG(2) << "Failed to fetch device name: " << string(clewErrorString(error))
+ << ", ignoring.";
+ continue;
+ }
+ if (!device_version_check(device_id)) {
+ FIRST_VLOG(2) << "Ignoring device " << device_name << " due to old compiler version.";
+ continue;
+ }
+ if (force_all || device_supported(platform_name, device_id)) {
+ cl_device_type device_type;
+ if (!get_device_type(device_id, &device_type, &error)) {
+ FIRST_VLOG(2) << "Ignoring device " << device_name
+ << ", failed to fetch device type:" << string(clewErrorString(error));
+ continue;
+ }
+ string readable_device_name = get_readable_device_name(device_id);
+ if (readable_device_name != device_name) {
+ FIRST_VLOG(2) << "Using more readable device name: " << readable_device_name;
+ }
+ FIRST_VLOG(2) << "Adding new device " << readable_device_name << ".";
+ string hardware_id = get_hardware_id(platform_name, device_id);
+ string device_extensions = get_device_extensions(device_id);
+ usable_devices->push_back(OpenCLPlatformDevice(platform_id,
+ platform_name,
+ device_id,
+ device_type,
+ readable_device_name,
+ hardware_id,
+ device_extensions));
+ }
+ else {
+ FIRST_VLOG(2) << "Ignoring device " << device_name << ", not officially supported yet.";
+ }
+ }
+ }
+ first_time = false;
}
-bool OpenCLInfo::get_platforms(vector<cl_platform_id> *platform_ids,
- cl_int *error)
+bool OpenCLInfo::get_platforms(vector<cl_platform_id> *platform_ids, cl_int *error)
{
- /* Reset from possible previous state. */
- platform_ids->resize(0);
- cl_uint num_platforms;
- if(!get_num_platforms(&num_platforms, error)) {
- return false;
- }
- /* Get actual platforms. */
- cl_int err;
- platform_ids->resize(num_platforms);
- if((err = clGetPlatformIDs(num_platforms,
- &platform_ids->at(0),
- NULL)) != CL_SUCCESS) {
- if(error != NULL) {
- *error = err;
- }
- return false;
- }
- if(error != NULL) {
- *error = CL_SUCCESS;
- }
- return true;
+ /* Reset from possible previous state. */
+ platform_ids->resize(0);
+ cl_uint num_platforms;
+ if (!get_num_platforms(&num_platforms, error)) {
+ return false;
+ }
+ /* Get actual platforms. */
+ cl_int err;
+ platform_ids->resize(num_platforms);
+ if ((err = clGetPlatformIDs(num_platforms, &platform_ids->at(0), NULL)) != CL_SUCCESS) {
+ if (error != NULL) {
+ *error = err;
+ }
+ return false;
+ }
+ if (error != NULL) {
+ *error = CL_SUCCESS;
+ }
+ return true;
}
vector<cl_platform_id> OpenCLInfo::get_platforms()
{
- vector<cl_platform_id> platform_ids;
- get_platforms(&platform_ids);
- return platform_ids;
+ vector<cl_platform_id> platform_ids;
+ get_platforms(&platform_ids);
+ return platform_ids;
}
bool OpenCLInfo::get_num_platforms(cl_uint *num_platforms, cl_int *error)
{
- cl_int err;
- if((err = clGetPlatformIDs(0, NULL, num_platforms)) != CL_SUCCESS) {
- if(error != NULL) {
- *error = err;
- }
- *num_platforms = 0;
- return false;
- }
- if(error != NULL) {
- *error = CL_SUCCESS;
- }
- return true;
+ cl_int err;
+ if ((err = clGetPlatformIDs(0, NULL, num_platforms)) != CL_SUCCESS) {
+ if (error != NULL) {
+ *error = err;
+ }
+ *num_platforms = 0;
+ return false;
+ }
+ if (error != NULL) {
+ *error = CL_SUCCESS;
+ }
+ return true;
}
cl_uint OpenCLInfo::get_num_platforms()
{
- cl_uint num_platforms;
- if(!get_num_platforms(&num_platforms)) {
- return 0;
- }
- return num_platforms;
+ cl_uint num_platforms;
+ if (!get_num_platforms(&num_platforms)) {
+ return 0;
+ }
+ return num_platforms;
}
-bool OpenCLInfo::get_platform_name(cl_platform_id platform_id,
- string *platform_name)
+bool OpenCLInfo::get_platform_name(cl_platform_id platform_id, string *platform_name)
{
- char buffer[256];
- if(clGetPlatformInfo(platform_id,
- CL_PLATFORM_NAME,
- sizeof(buffer),
- &buffer,
- NULL) != CL_SUCCESS)
- {
- *platform_name = "";
- return false;
- }
- *platform_name = buffer;
- return true;
+ char buffer[256];
+ if (clGetPlatformInfo(platform_id, CL_PLATFORM_NAME, sizeof(buffer), &buffer, NULL) !=
+ CL_SUCCESS) {
+ *platform_name = "";
+ return false;
+ }
+ *platform_name = buffer;
+ return true;
}
string OpenCLInfo::get_platform_name(cl_platform_id platform_id)
{
- string platform_name;
- if(!get_platform_name(platform_id, &platform_name)) {
- return "";
- }
- return platform_name;
+ string platform_name;
+ if (!get_platform_name(platform_id, &platform_name)) {
+ return "";
+ }
+ return platform_name;
}
bool OpenCLInfo::get_num_platform_devices(cl_platform_id platform_id,
@@ -1076,266 +1034,222 @@ bool OpenCLInfo::get_num_platform_devices(cl_platform_id platform_id,
cl_uint *num_devices,
cl_int *error)
{
- cl_int err;
- if((err = clGetDeviceIDs(platform_id,
- device_type,
- 0,
- NULL,
- num_devices)) != CL_SUCCESS)
- {
- if(error != NULL) {
- *error = err;
- }
- *num_devices = 0;
- return false;
- }
- if(error != NULL) {
- *error = CL_SUCCESS;
- }
- return true;
+ cl_int err;
+ if ((err = clGetDeviceIDs(platform_id, device_type, 0, NULL, num_devices)) != CL_SUCCESS) {
+ if (error != NULL) {
+ *error = err;
+ }
+ *num_devices = 0;
+ return false;
+ }
+ if (error != NULL) {
+ *error = CL_SUCCESS;
+ }
+ return true;
}
cl_uint OpenCLInfo::get_num_platform_devices(cl_platform_id platform_id,
cl_device_type device_type)
{
- cl_uint num_devices;
- if(!get_num_platform_devices(platform_id,
- device_type,
- &num_devices))
- {
- return 0;
- }
- return num_devices;
+ cl_uint num_devices;
+ if (!get_num_platform_devices(platform_id, device_type, &num_devices)) {
+ return 0;
+ }
+ return num_devices;
}
bool OpenCLInfo::get_platform_devices(cl_platform_id platform_id,
cl_device_type device_type,
vector<cl_device_id> *device_ids,
- cl_int* error)
+ cl_int *error)
{
- /* Reset from possible previous state. */
- device_ids->resize(0);
- /* Get number of devices to pre-allocate memory. */
- cl_uint num_devices;
- if(!get_num_platform_devices(platform_id,
- device_type,
- &num_devices,
- error))
- {
- return false;
- }
- /* Get actual device list. */
- device_ids->resize(num_devices);
- cl_int err;
- if((err = clGetDeviceIDs(platform_id,
- device_type,
- num_devices,
- &device_ids->at(0),
- NULL)) != CL_SUCCESS)
- {
- if(error != NULL) {
- *error = err;
- }
- return false;
- }
- if(error != NULL) {
- *error = CL_SUCCESS;
- }
- return true;
+ /* Reset from possible previous state. */
+ device_ids->resize(0);
+ /* Get number of devices to pre-allocate memory. */
+ cl_uint num_devices;
+ if (!get_num_platform_devices(platform_id, device_type, &num_devices, error)) {
+ return false;
+ }
+ /* Get actual device list. */
+ device_ids->resize(num_devices);
+ cl_int err;
+ if ((err = clGetDeviceIDs(platform_id, device_type, num_devices, &device_ids->at(0), NULL)) !=
+ CL_SUCCESS) {
+ if (error != NULL) {
+ *error = err;
+ }
+ return false;
+ }
+ if (error != NULL) {
+ *error = CL_SUCCESS;
+ }
+ return true;
}
vector<cl_device_id> OpenCLInfo::get_platform_devices(cl_platform_id platform_id,
cl_device_type device_type)
{
- vector<cl_device_id> devices;
- get_platform_devices(platform_id, device_type, &devices);
- return devices;
+ vector<cl_device_id> devices;
+ get_platform_devices(platform_id, device_type, &devices);
+ return devices;
}
-bool OpenCLInfo::get_device_name(cl_device_id device_id,
- string *device_name,
- cl_int* error)
+bool OpenCLInfo::get_device_name(cl_device_id device_id, string *device_name, cl_int *error)
{
- char buffer[1024];
- cl_int err;
- if((err = clGetDeviceInfo(device_id,
- CL_DEVICE_NAME,
- sizeof(buffer),
- &buffer,
- NULL)) != CL_SUCCESS)
- {
- if(error != NULL) {
- *error = err;
- }
- *device_name = "";
- return false;
- }
- if(error != NULL) {
- *error = CL_SUCCESS;
- }
- *device_name = buffer;
- return true;
+ char buffer[1024];
+ cl_int err;
+ if ((err = clGetDeviceInfo(device_id, CL_DEVICE_NAME, sizeof(buffer), &buffer, NULL)) !=
+ CL_SUCCESS) {
+ if (error != NULL) {
+ *error = err;
+ }
+ *device_name = "";
+ return false;
+ }
+ if (error != NULL) {
+ *error = CL_SUCCESS;
+ }
+ *device_name = buffer;
+ return true;
}
string OpenCLInfo::get_device_name(cl_device_id device_id)
{
- string device_name;
- if(!get_device_name(device_id, &device_name)) {
- return "";
- }
- return device_name;
+ string device_name;
+ if (!get_device_name(device_id, &device_name)) {
+ return "";
+ }
+ return device_name;
}
bool OpenCLInfo::get_device_extensions(cl_device_id device_id,
- string *device_extensions,
- cl_int* error)
+ string *device_extensions,
+ cl_int *error)
{
- char buffer[1024];
- cl_int err;
- if((err = clGetDeviceInfo(device_id,
- CL_DEVICE_EXTENSIONS,
- sizeof(buffer),
- &buffer,
- NULL)) != CL_SUCCESS)
- {
- if(error != NULL) {
- *error = err;
- }
- *device_extensions = "";
- return false;
- }
- if(error != NULL) {
- *error = CL_SUCCESS;
- }
- *device_extensions = buffer;
- return true;
+ char buffer[1024];
+ cl_int err;
+ if ((err = clGetDeviceInfo(device_id, CL_DEVICE_EXTENSIONS, sizeof(buffer), &buffer, NULL)) !=
+ CL_SUCCESS) {
+ if (error != NULL) {
+ *error = err;
+ }
+ *device_extensions = "";
+ return false;
+ }
+ if (error != NULL) {
+ *error = CL_SUCCESS;
+ }
+ *device_extensions = buffer;
+ return true;
}
string OpenCLInfo::get_device_extensions(cl_device_id device_id)
{
- string device_extensions;
- if(!get_device_extensions(device_id, &device_extensions)) {
- return "";
- }
- return device_extensions;
+ string device_extensions;
+ if (!get_device_extensions(device_id, &device_extensions)) {
+ return "";
+ }
+ return device_extensions;
}
bool OpenCLInfo::get_device_type(cl_device_id device_id,
cl_device_type *device_type,
- cl_int* error)
+ cl_int *error)
{
- cl_int err;
- if((err = clGetDeviceInfo(device_id,
- CL_DEVICE_TYPE,
- sizeof(cl_device_type),
- device_type,
- NULL)) != CL_SUCCESS)
- {
- if(error != NULL) {
- *error = err;
- }
- *device_type = 0;
- return false;
- }
- if(error != NULL) {
- *error = CL_SUCCESS;
- }
- return true;
+ cl_int err;
+ if ((err = clGetDeviceInfo(
+ device_id, CL_DEVICE_TYPE, sizeof(cl_device_type), device_type, NULL)) != CL_SUCCESS) {
+ if (error != NULL) {
+ *error = err;
+ }
+ *device_type = 0;
+ return false;
+ }
+ if (error != NULL) {
+ *error = CL_SUCCESS;
+ }
+ return true;
}
cl_device_type OpenCLInfo::get_device_type(cl_device_id device_id)
{
- cl_device_type device_type;
- if(!get_device_type(device_id, &device_type)) {
- return 0;
- }
- return device_type;
+ cl_device_type device_type;
+ if (!get_device_type(device_id, &device_type)) {
+ return 0;
+ }
+ return device_type;
}
string OpenCLInfo::get_readable_device_name(cl_device_id device_id)
{
- string name = "";
- char board_name[1024];
- size_t length = 0;
- if(clGetDeviceInfo(device_id,
- CL_DEVICE_BOARD_NAME_AMD,
- sizeof(board_name),
- &board_name,
- &length) == CL_SUCCESS)
- {
- if(length != 0 && board_name[0] != '\0') {
- name = board_name;
- }
- }
-
- /* Fallback to standard device name API. */
- if(name.empty()) {
- name = get_device_name(device_id);
- }
-
- /* Special exception for AMD Vega, need to be able to tell
- * Vega 56 from 64 apart.
- */
- if(name == "Radeon RX Vega") {
- cl_int max_compute_units = 0;
- if(clGetDeviceInfo(device_id,
- CL_DEVICE_MAX_COMPUTE_UNITS,
- sizeof(max_compute_units),
- &max_compute_units,
- NULL) == CL_SUCCESS)
- {
- name += " " + to_string(max_compute_units);
- }
- }
-
- /* Distinguish from our native CPU device. */
- if(get_device_type(device_id) & CL_DEVICE_TYPE_CPU) {
- name += " (OpenCL)";
- }
-
- return name;
+ string name = "";
+ char board_name[1024];
+ size_t length = 0;
+ if (clGetDeviceInfo(
+ device_id, CL_DEVICE_BOARD_NAME_AMD, sizeof(board_name), &board_name, &length) ==
+ CL_SUCCESS) {
+ if (length != 0 && board_name[0] != '\0') {
+ name = board_name;
+ }
+ }
+
+ /* Fallback to standard device name API. */
+ if (name.empty()) {
+ name = get_device_name(device_id);
+ }
+
+ /* Special exception for AMD Vega, need to be able to tell
+ * Vega 56 from 64 apart.
+ */
+ if (name == "Radeon RX Vega") {
+ cl_int max_compute_units = 0;
+ if (clGetDeviceInfo(device_id,
+ CL_DEVICE_MAX_COMPUTE_UNITS,
+ sizeof(max_compute_units),
+ &max_compute_units,
+ NULL) == CL_SUCCESS) {
+ name += " " + to_string(max_compute_units);
+ }
+ }
+
+ /* Distinguish from our native CPU device. */
+ if (get_device_type(device_id) & CL_DEVICE_TYPE_CPU) {
+ name += " (OpenCL)";
+ }
+
+ return name;
}
-bool OpenCLInfo::get_driver_version(cl_device_id device_id,
- int *major,
- int *minor,
- cl_int* error)
+bool OpenCLInfo::get_driver_version(cl_device_id device_id, int *major, int *minor, cl_int *error)
{
- char buffer[1024];
- cl_int err;
- if((err = clGetDeviceInfo(device_id,
- CL_DRIVER_VERSION,
- sizeof(buffer),
- &buffer,
- NULL)) != CL_SUCCESS)
- {
- if(error != NULL) {
- *error = err;
- }
- return false;
- }
- if(error != NULL) {
- *error = CL_SUCCESS;
- }
- if(sscanf(buffer, "%d.%d", major, minor) < 2) {
- VLOG(1) << string_printf("OpenCL: failed to parse driver version string (%s).", buffer);
- return false;
- }
- return true;
+ char buffer[1024];
+ cl_int err;
+ if ((err = clGetDeviceInfo(device_id, CL_DRIVER_VERSION, sizeof(buffer), &buffer, NULL)) !=
+ CL_SUCCESS) {
+ if (error != NULL) {
+ *error = err;
+ }
+ return false;
+ }
+ if (error != NULL) {
+ *error = CL_SUCCESS;
+ }
+ if (sscanf(buffer, "%d.%d", major, minor) < 2) {
+ VLOG(1) << string_printf("OpenCL: failed to parse driver version string (%s).", buffer);
+ return false;
+ }
+ return true;
}
int OpenCLInfo::mem_sub_ptr_alignment(cl_device_id device_id)
{
- int base_align_bits;
- if(clGetDeviceInfo(device_id,
- CL_DEVICE_MEM_BASE_ADDR_ALIGN,
- sizeof(int),
- &base_align_bits,
- NULL) == CL_SUCCESS)
- {
- return base_align_bits/8;
- }
- return 1;
+ int base_align_bits;
+ if (clGetDeviceInfo(
+ device_id, CL_DEVICE_MEM_BASE_ADDR_ALIGN, sizeof(int), &base_align_bits, NULL) ==
+ CL_SUCCESS) {
+ return base_align_bits / 8;
+ }
+ return 1;
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/doc/license/CMakeLists.txt b/intern/cycles/doc/license/CMakeLists.txt
index 2f8fe92ad5c..2d8651b6ea1 100644
--- a/intern/cycles/doc/license/CMakeLists.txt
+++ b/intern/cycles/doc/license/CMakeLists.txt
@@ -1,11 +1,11 @@
set(LICENSES
- Apache_2.0.txt
- ILM.txt
- NVidia.txt
- OSL.txt
- Sobol.txt
- readme.txt
+ Apache_2.0.txt
+ ILM.txt
+ NVidia.txt
+ OSL.txt
+ Sobol.txt
+ readme.txt
)
delayed_install(${CMAKE_CURRENT_SOURCE_DIR} "${LICENSES}" ${CYCLES_INSTALL_PATH}/license)
diff --git a/intern/cycles/graph/CMakeLists.txt b/intern/cycles/graph/CMakeLists.txt
index bd2b2728a29..c6c46941598 100644
--- a/intern/cycles/graph/CMakeLists.txt
+++ b/intern/cycles/graph/CMakeLists.txt
@@ -1,19 +1,19 @@
set(INC
- ..
+ ..
)
set(SRC
- node.cpp
- node_type.cpp
- node_xml.cpp
+ node.cpp
+ node_type.cpp
+ node_xml.cpp
)
set(SRC_HEADERS
- node.h
- node_enum.h
- node_type.h
- node_xml.h
+ node.h
+ node_enum.h
+ node_type.h
+ node_xml.h
)
set(LIB
diff --git a/intern/cycles/graph/node.cpp b/intern/cycles/graph/node.cpp
index 19fe0a168ea..fc7daaeeaa6 100644
--- a/intern/cycles/graph/node.cpp
+++ b/intern/cycles/graph/node.cpp
@@ -26,550 +26,645 @@ CCL_NAMESPACE_BEGIN
/* Node Type */
-Node::Node(const NodeType *type_, ustring name_)
-: name(name_), type(type_)
+Node::Node(const NodeType *type_, ustring name_) : name(name_), type(type_)
{
- assert(type);
+ assert(type);
- /* assign non-empty name, convenient for debugging */
- if(name.empty()) {
- name = type->name;
- }
+ /* assign non-empty name, convenient for debugging */
+ if (name.empty()) {
+ name = type->name;
+ }
- /* initialize default values */
- foreach(const SocketType& socket, type->inputs) {
- set_default_value(socket);
- }
+ /* initialize default values */
+ foreach (const SocketType &socket, type->inputs) {
+ set_default_value(socket);
+ }
}
Node::~Node()
{
}
-template<typename T>
-static T& get_socket_value(const Node *node, const SocketType& socket)
+template<typename T> static T &get_socket_value(const Node *node, const SocketType &socket)
{
- return (T&)*(((char*)node) + socket.struct_offset);
+ return (T &)*(((char *)node) + socket.struct_offset);
}
#ifndef NDEBUG
-static bool is_socket_float3(const SocketType& socket)
+static bool is_socket_float3(const SocketType &socket)
{
- return socket.type == SocketType::COLOR ||
- socket.type == SocketType::POINT ||
- socket.type == SocketType::VECTOR ||
- socket.type == SocketType::NORMAL;
+ return socket.type == SocketType::COLOR || socket.type == SocketType::POINT ||
+ socket.type == SocketType::VECTOR || socket.type == SocketType::NORMAL;
}
-static bool is_socket_array_float3(const SocketType& socket)
+static bool is_socket_array_float3(const SocketType &socket)
{
- return socket.type == SocketType::COLOR_ARRAY ||
- socket.type == SocketType::POINT_ARRAY ||
- socket.type == SocketType::VECTOR_ARRAY ||
- socket.type == SocketType::NORMAL_ARRAY;
+ return socket.type == SocketType::COLOR_ARRAY || socket.type == SocketType::POINT_ARRAY ||
+ socket.type == SocketType::VECTOR_ARRAY || socket.type == SocketType::NORMAL_ARRAY;
}
#endif
/* set values */
-void Node::set(const SocketType& input, bool value)
+void Node::set(const SocketType &input, bool value)
{
- assert(input.type == SocketType::BOOLEAN);
- get_socket_value<bool>(this, input) = value;
+ assert(input.type == SocketType::BOOLEAN);
+ get_socket_value<bool>(this, input) = value;
}
-void Node::set(const SocketType& input, int value)
+void Node::set(const SocketType &input, int value)
{
- assert((input.type == SocketType::INT || input.type == SocketType::ENUM));
- get_socket_value<int>(this, input) = value;
+ assert((input.type == SocketType::INT || input.type == SocketType::ENUM));
+ get_socket_value<int>(this, input) = value;
}
-void Node::set(const SocketType& input, uint value)
+void Node::set(const SocketType &input, uint value)
{
- assert(input.type == SocketType::UINT);
- get_socket_value<uint>(this, input) = value;
+ assert(input.type == SocketType::UINT);
+ get_socket_value<uint>(this, input) = value;
}
-void Node::set(const SocketType& input, float value)
+void Node::set(const SocketType &input, float value)
{
- assert(input.type == SocketType::FLOAT);
- get_socket_value<float>(this, input) = value;
+ assert(input.type == SocketType::FLOAT);
+ get_socket_value<float>(this, input) = value;
}
-void Node::set(const SocketType& input, float2 value)
+void Node::set(const SocketType &input, float2 value)
{
- assert(input.type == SocketType::FLOAT);
- get_socket_value<float2>(this, input) = value;
+ assert(input.type == SocketType::FLOAT);
+ get_socket_value<float2>(this, input) = value;
}
-void Node::set(const SocketType& input, float3 value)
+void Node::set(const SocketType &input, float3 value)
{
- assert(is_socket_float3(input));
- get_socket_value<float3>(this, input) = value;
+ assert(is_socket_float3(input));
+ get_socket_value<float3>(this, input) = value;
}
-void Node::set(const SocketType& input, const char *value)
+void Node::set(const SocketType &input, const char *value)
{
- set(input, ustring(value));
+ set(input, ustring(value));
}
-void Node::set(const SocketType& input, ustring value)
+void Node::set(const SocketType &input, ustring value)
{
- if(input.type == SocketType::STRING) {
- get_socket_value<ustring>(this, input) = value;
- }
- else if(input.type == SocketType::ENUM) {
- const NodeEnum& enm = *input.enum_values;
- if(enm.exists(value)) {
- get_socket_value<int>(this, input) = enm[value];
- }
- else {
- assert(0);
- }
- }
- else {
- assert(0);
- }
+ if (input.type == SocketType::STRING) {
+ get_socket_value<ustring>(this, input) = value;
+ }
+ else if (input.type == SocketType::ENUM) {
+ const NodeEnum &enm = *input.enum_values;
+ if (enm.exists(value)) {
+ get_socket_value<int>(this, input) = enm[value];
+ }
+ else {
+ assert(0);
+ }
+ }
+ else {
+ assert(0);
+ }
}
-void Node::set(const SocketType& input, const Transform& value)
+void Node::set(const SocketType &input, const Transform &value)
{
- assert(input.type == SocketType::TRANSFORM);
- get_socket_value<Transform>(this, input) = value;
+ assert(input.type == SocketType::TRANSFORM);
+ get_socket_value<Transform>(this, input) = value;
}
-void Node::set(const SocketType& input, Node *value)
+void Node::set(const SocketType &input, Node *value)
{
- assert(input.type == SocketType::TRANSFORM);
- get_socket_value<Node*>(this, input) = value;
+ assert(input.type == SocketType::TRANSFORM);
+ get_socket_value<Node *>(this, input) = value;
}
/* set array values */
-void Node::set(const SocketType& input, array<bool>& value)
+void Node::set(const SocketType &input, array<bool> &value)
{
- assert(input.type == SocketType::BOOLEAN_ARRAY);
- get_socket_value<array<bool> >(this, input).steal_data(value);
+ assert(input.type == SocketType::BOOLEAN_ARRAY);
+ get_socket_value<array<bool>>(this, input).steal_data(value);
}
-void Node::set(const SocketType& input, array<int>& value)
+void Node::set(const SocketType &input, array<int> &value)
{
- assert(input.type == SocketType::INT_ARRAY);
- get_socket_value<array<int> >(this, input).steal_data(value);
+ assert(input.type == SocketType::INT_ARRAY);
+ get_socket_value<array<int>>(this, input).steal_data(value);
}
-void Node::set(const SocketType& input, array<float>& value)
+void Node::set(const SocketType &input, array<float> &value)
{
- assert(input.type == SocketType::FLOAT_ARRAY);
- get_socket_value<array<float> >(this, input).steal_data(value);
+ assert(input.type == SocketType::FLOAT_ARRAY);
+ get_socket_value<array<float>>(this, input).steal_data(value);
}
-void Node::set(const SocketType& input, array<float2>& value)
+void Node::set(const SocketType &input, array<float2> &value)
{
- assert(input.type == SocketType::FLOAT_ARRAY);
- get_socket_value<array<float2> >(this, input).steal_data(value);
+ assert(input.type == SocketType::FLOAT_ARRAY);
+ get_socket_value<array<float2>>(this, input).steal_data(value);
}
-void Node::set(const SocketType& input, array<float3>& value)
+void Node::set(const SocketType &input, array<float3> &value)
{
- assert(is_socket_array_float3(input));
- get_socket_value<array<float3> >(this, input).steal_data(value);
+ assert(is_socket_array_float3(input));
+ get_socket_value<array<float3>>(this, input).steal_data(value);
}
-void Node::set(const SocketType& input, array<ustring>& value)
+void Node::set(const SocketType &input, array<ustring> &value)
{
- assert(input.type == SocketType::STRING_ARRAY);
- get_socket_value<array<ustring> >(this, input).steal_data(value);
+ assert(input.type == SocketType::STRING_ARRAY);
+ get_socket_value<array<ustring>>(this, input).steal_data(value);
}
-void Node::set(const SocketType& input, array<Transform>& value)
+void Node::set(const SocketType &input, array<Transform> &value)
{
- assert(input.type == SocketType::TRANSFORM_ARRAY);
- get_socket_value<array<Transform> >(this, input).steal_data(value);
+ assert(input.type == SocketType::TRANSFORM_ARRAY);
+ get_socket_value<array<Transform>>(this, input).steal_data(value);
}
-void Node::set(const SocketType& input, array<Node*>& value)
+void Node::set(const SocketType &input, array<Node *> &value)
{
- assert(input.type == SocketType::TRANSFORM_ARRAY);
- get_socket_value<array<Node*> >(this, input).steal_data(value);
+ assert(input.type == SocketType::TRANSFORM_ARRAY);
+ get_socket_value<array<Node *>>(this, input).steal_data(value);
}
/* get values */
-bool Node::get_bool(const SocketType& input) const
+bool Node::get_bool(const SocketType &input) const
{
- assert(input.type == SocketType::BOOLEAN);
- return get_socket_value<bool>(this, input);
+ assert(input.type == SocketType::BOOLEAN);
+ return get_socket_value<bool>(this, input);
}
-int Node::get_int(const SocketType& input) const
+int Node::get_int(const SocketType &input) const
{
- assert(input.type == SocketType::INT || input.type == SocketType::ENUM);
- return get_socket_value<int>(this, input);
+ assert(input.type == SocketType::INT || input.type == SocketType::ENUM);
+ return get_socket_value<int>(this, input);
}
-uint Node::get_uint(const SocketType& input) const
+uint Node::get_uint(const SocketType &input) const
{
- assert(input.type == SocketType::UINT);
- return get_socket_value<uint>(this, input);
+ assert(input.type == SocketType::UINT);
+ return get_socket_value<uint>(this, input);
}
-float Node::get_float(const SocketType& input) const
+float Node::get_float(const SocketType &input) const
{
- assert(input.type == SocketType::FLOAT);
- return get_socket_value<float>(this, input);
+ assert(input.type == SocketType::FLOAT);
+ return get_socket_value<float>(this, input);
}
-float2 Node::get_float2(const SocketType& input) const
+float2 Node::get_float2(const SocketType &input) const
{
- assert(input.type == SocketType::FLOAT);
- return get_socket_value<float2>(this, input);
+ assert(input.type == SocketType::FLOAT);
+ return get_socket_value<float2>(this, input);
}
-float3 Node::get_float3(const SocketType& input) const
+float3 Node::get_float3(const SocketType &input) const
{
- assert(is_socket_float3(input));
- return get_socket_value<float3>(this, input);
+ assert(is_socket_float3(input));
+ return get_socket_value<float3>(this, input);
}
-ustring Node::get_string(const SocketType& input) const
+ustring Node::get_string(const SocketType &input) const
{
- if(input.type == SocketType::STRING) {
- return get_socket_value<ustring>(this, input);
- }
- else if(input.type == SocketType::ENUM) {
- const NodeEnum& enm = *input.enum_values;
- int intvalue = get_socket_value<int>(this, input);
- return (enm.exists(intvalue)) ? enm[intvalue] : ustring();
- }
- else {
- assert(0);
- return ustring();
- }
+ if (input.type == SocketType::STRING) {
+ return get_socket_value<ustring>(this, input);
+ }
+ else if (input.type == SocketType::ENUM) {
+ const NodeEnum &enm = *input.enum_values;
+ int intvalue = get_socket_value<int>(this, input);
+ return (enm.exists(intvalue)) ? enm[intvalue] : ustring();
+ }
+ else {
+ assert(0);
+ return ustring();
+ }
}
-Transform Node::get_transform(const SocketType& input) const
+Transform Node::get_transform(const SocketType &input) const
{
- assert(input.type == SocketType::TRANSFORM);
- return get_socket_value<Transform>(this, input);
+ assert(input.type == SocketType::TRANSFORM);
+ return get_socket_value<Transform>(this, input);
}
-Node *Node::get_node(const SocketType& input) const
+Node *Node::get_node(const SocketType &input) const
{
- assert(input.type == SocketType::NODE);
- return get_socket_value<Node*>(this, input);
+ assert(input.type == SocketType::NODE);
+ return get_socket_value<Node *>(this, input);
}
/* get array values */
-const array<bool>& Node::get_bool_array(const SocketType& input) const
+const array<bool> &Node::get_bool_array(const SocketType &input) const
{
- assert(input.type == SocketType::BOOLEAN_ARRAY);
- return get_socket_value<array<bool> >(this, input);
+ assert(input.type == SocketType::BOOLEAN_ARRAY);
+ return get_socket_value<array<bool>>(this, input);
}
-const array<int>& Node::get_int_array(const SocketType& input) const
+const array<int> &Node::get_int_array(const SocketType &input) const
{
- assert(input.type == SocketType::INT_ARRAY);
- return get_socket_value<array<int> >(this, input);
+ assert(input.type == SocketType::INT_ARRAY);
+ return get_socket_value<array<int>>(this, input);
}
-const array<float>& Node::get_float_array(const SocketType& input) const
+const array<float> &Node::get_float_array(const SocketType &input) const
{
- assert(input.type == SocketType::FLOAT_ARRAY);
- return get_socket_value<array<float> >(this, input);
+ assert(input.type == SocketType::FLOAT_ARRAY);
+ return get_socket_value<array<float>>(this, input);
}
-const array<float2>& Node::get_float2_array(const SocketType& input) const
+const array<float2> &Node::get_float2_array(const SocketType &input) const
{
- assert(input.type == SocketType::FLOAT_ARRAY);
- return get_socket_value<array<float2> >(this, input);
+ assert(input.type == SocketType::FLOAT_ARRAY);
+ return get_socket_value<array<float2>>(this, input);
}
-const array<float3>& Node::get_float3_array(const SocketType& input) const
+const array<float3> &Node::get_float3_array(const SocketType &input) const
{
- assert(is_socket_array_float3(input));
- return get_socket_value<array<float3> >(this, input);
+ assert(is_socket_array_float3(input));
+ return get_socket_value<array<float3>>(this, input);
}
-const array<ustring>& Node::get_string_array(const SocketType& input) const
+const array<ustring> &Node::get_string_array(const SocketType &input) const
{
- assert(input.type == SocketType::STRING_ARRAY);
- return get_socket_value<array<ustring> >(this, input);
+ assert(input.type == SocketType::STRING_ARRAY);
+ return get_socket_value<array<ustring>>(this, input);
}
-const array<Transform>& Node::get_transform_array(const SocketType& input) const
+const array<Transform> &Node::get_transform_array(const SocketType &input) const
{
- assert(input.type == SocketType::TRANSFORM_ARRAY);
- return get_socket_value<array<Transform> >(this, input);
+ assert(input.type == SocketType::TRANSFORM_ARRAY);
+ return get_socket_value<array<Transform>>(this, input);
}
-const array<Node*>& Node::get_node_array(const SocketType& input) const
+const array<Node *> &Node::get_node_array(const SocketType &input) const
{
- assert(input.type == SocketType::NODE_ARRAY);
- return get_socket_value<array<Node*> >(this, input);
+ assert(input.type == SocketType::NODE_ARRAY);
+ return get_socket_value<array<Node *>>(this, input);
}
/* generic value operations */
-bool Node::has_default_value(const SocketType& input) const
+bool Node::has_default_value(const SocketType &input) const
{
- const void *src = input.default_value;
- void *dst = &get_socket_value<char>(this, input);
- return memcmp(dst, src, input.size()) == 0;
+ const void *src = input.default_value;
+ void *dst = &get_socket_value<char>(this, input);
+ return memcmp(dst, src, input.size()) == 0;
}
-void Node::set_default_value(const SocketType& socket)
+void Node::set_default_value(const SocketType &socket)
{
- const void *src = socket.default_value;
- void *dst = ((char*)this) + socket.struct_offset;
- memcpy(dst, src, socket.size());
+ const void *src = socket.default_value;
+ void *dst = ((char *)this) + socket.struct_offset;
+ memcpy(dst, src, socket.size());
}
template<typename T>
-static void copy_array(const Node *node, const SocketType& socket, const Node *other, const SocketType& other_socket)
-{
- const array<T>* src = (const array<T>*)(((char*)other) + other_socket.struct_offset);
- array<T>* dst = (array<T>*)(((char*)node) + socket.struct_offset);
- *dst = *src;
-}
-
-void Node::copy_value(const SocketType& socket, const Node& other, const SocketType& other_socket)
-{
- assert(socket.type == other_socket.type);
-
- if(socket.is_array()) {
- switch(socket.type) {
- case SocketType::BOOLEAN_ARRAY: copy_array<bool>(this, socket, &other, other_socket); break;
- case SocketType::FLOAT_ARRAY: copy_array<float>(this, socket, &other, other_socket); break;
- case SocketType::INT_ARRAY: copy_array<int>(this, socket, &other, other_socket); break;
- case SocketType::COLOR_ARRAY: copy_array<float3>(this, socket, &other, other_socket); break;
- case SocketType::VECTOR_ARRAY: copy_array<float3>(this, socket, &other, other_socket); break;
- case SocketType::POINT_ARRAY: copy_array<float3>(this, socket, &other, other_socket); break;
- case SocketType::NORMAL_ARRAY: copy_array<float3>(this, socket, &other, other_socket); break;
- case SocketType::POINT2_ARRAY: copy_array<float2>(this, socket, &other, other_socket); break;
- case SocketType::STRING_ARRAY: copy_array<ustring>(this, socket, &other, other_socket); break;
- case SocketType::TRANSFORM_ARRAY: copy_array<Transform>(this, socket, &other, other_socket); break;
- case SocketType::NODE_ARRAY: copy_array<void*>(this, socket, &other, other_socket); break;
- default: assert(0); break;
- }
- }
- else {
- const void *src = ((char*)&other) + other_socket.struct_offset;
- void *dst = ((char*)this) + socket.struct_offset;
- memcpy(dst, src, socket.size());
- }
+static void copy_array(const Node *node,
+ const SocketType &socket,
+ const Node *other,
+ const SocketType &other_socket)
+{
+ const array<T> *src = (const array<T> *)(((char *)other) + other_socket.struct_offset);
+ array<T> *dst = (array<T> *)(((char *)node) + socket.struct_offset);
+ *dst = *src;
+}
+
+void Node::copy_value(const SocketType &socket, const Node &other, const SocketType &other_socket)
+{
+ assert(socket.type == other_socket.type);
+
+ if (socket.is_array()) {
+ switch (socket.type) {
+ case SocketType::BOOLEAN_ARRAY:
+ copy_array<bool>(this, socket, &other, other_socket);
+ break;
+ case SocketType::FLOAT_ARRAY:
+ copy_array<float>(this, socket, &other, other_socket);
+ break;
+ case SocketType::INT_ARRAY:
+ copy_array<int>(this, socket, &other, other_socket);
+ break;
+ case SocketType::COLOR_ARRAY:
+ copy_array<float3>(this, socket, &other, other_socket);
+ break;
+ case SocketType::VECTOR_ARRAY:
+ copy_array<float3>(this, socket, &other, other_socket);
+ break;
+ case SocketType::POINT_ARRAY:
+ copy_array<float3>(this, socket, &other, other_socket);
+ break;
+ case SocketType::NORMAL_ARRAY:
+ copy_array<float3>(this, socket, &other, other_socket);
+ break;
+ case SocketType::POINT2_ARRAY:
+ copy_array<float2>(this, socket, &other, other_socket);
+ break;
+ case SocketType::STRING_ARRAY:
+ copy_array<ustring>(this, socket, &other, other_socket);
+ break;
+ case SocketType::TRANSFORM_ARRAY:
+ copy_array<Transform>(this, socket, &other, other_socket);
+ break;
+ case SocketType::NODE_ARRAY:
+ copy_array<void *>(this, socket, &other, other_socket);
+ break;
+ default:
+ assert(0);
+ break;
+ }
+ }
+ else {
+ const void *src = ((char *)&other) + other_socket.struct_offset;
+ void *dst = ((char *)this) + socket.struct_offset;
+ memcpy(dst, src, socket.size());
+ }
}
template<typename T>
-static bool is_array_equal(const Node *node, const Node *other, const SocketType& socket)
+static bool is_array_equal(const Node *node, const Node *other, const SocketType &socket)
{
- const array<T>* a = (const array<T>*)(((char*)node) + socket.struct_offset);
- const array<T>* b = (const array<T>*)(((char*)other) + socket.struct_offset);
- return *a == *b;
+ const array<T> *a = (const array<T> *)(((char *)node) + socket.struct_offset);
+ const array<T> *b = (const array<T> *)(((char *)other) + socket.struct_offset);
+ return *a == *b;
}
template<typename T>
-static bool is_value_equal(const Node *node, const Node *other, const SocketType& socket)
-{
- const T *a = (const T*)(((char*)node) + socket.struct_offset);
- const T *b = (const T*)(((char*)other) + socket.struct_offset);
- return *a == *b;
-}
-
-bool Node::equals_value(const Node& other, const SocketType& socket) const
-{
- switch(socket.type) {
- case SocketType::BOOLEAN: return is_value_equal<bool>(this, &other, socket);
- case SocketType::FLOAT: return is_value_equal<float>(this, &other, socket);
- case SocketType::INT: return is_value_equal<int>(this, &other, socket);
- case SocketType::UINT: return is_value_equal<uint>(this, &other, socket);
- case SocketType::COLOR: return is_value_equal<float3>(this, &other, socket);
- case SocketType::VECTOR: return is_value_equal<float3>(this, &other, socket);
- case SocketType::POINT: return is_value_equal<float3>(this, &other, socket);
- case SocketType::NORMAL: return is_value_equal<float3>(this, &other, socket);
- case SocketType::POINT2: return is_value_equal<float2>(this, &other, socket);
- case SocketType::CLOSURE: return true;
- case SocketType::STRING: return is_value_equal<ustring>(this, &other, socket);
- case SocketType::ENUM: return is_value_equal<int>(this, &other, socket);
- case SocketType::TRANSFORM: return is_value_equal<Transform>(this, &other, socket);
- case SocketType::NODE: return is_value_equal<void*>(this, &other, socket);
-
- case SocketType::BOOLEAN_ARRAY: return is_array_equal<bool>(this, &other, socket);
- case SocketType::FLOAT_ARRAY: return is_array_equal<float>(this, &other, socket);
- case SocketType::INT_ARRAY: return is_array_equal<int>(this, &other, socket);
- case SocketType::COLOR_ARRAY: return is_array_equal<float3>(this, &other, socket);
- case SocketType::VECTOR_ARRAY: return is_array_equal<float3>(this, &other, socket);
- case SocketType::POINT_ARRAY: return is_array_equal<float3>(this, &other, socket);
- case SocketType::NORMAL_ARRAY: return is_array_equal<float3>(this, &other, socket);
- case SocketType::POINT2_ARRAY: return is_array_equal<float2>(this, &other, socket);
- case SocketType::STRING_ARRAY: return is_array_equal<ustring>(this, &other, socket);
- case SocketType::TRANSFORM_ARRAY: return is_array_equal<Transform>(this, &other, socket);
- case SocketType::NODE_ARRAY: return is_array_equal<void*>(this, &other, socket);
-
- case SocketType::UNDEFINED: return true;
- }
-
- return true;
+static bool is_value_equal(const Node *node, const Node *other, const SocketType &socket)
+{
+ const T *a = (const T *)(((char *)node) + socket.struct_offset);
+ const T *b = (const T *)(((char *)other) + socket.struct_offset);
+ return *a == *b;
+}
+
+bool Node::equals_value(const Node &other, const SocketType &socket) const
+{
+ switch (socket.type) {
+ case SocketType::BOOLEAN:
+ return is_value_equal<bool>(this, &other, socket);
+ case SocketType::FLOAT:
+ return is_value_equal<float>(this, &other, socket);
+ case SocketType::INT:
+ return is_value_equal<int>(this, &other, socket);
+ case SocketType::UINT:
+ return is_value_equal<uint>(this, &other, socket);
+ case SocketType::COLOR:
+ return is_value_equal<float3>(this, &other, socket);
+ case SocketType::VECTOR:
+ return is_value_equal<float3>(this, &other, socket);
+ case SocketType::POINT:
+ return is_value_equal<float3>(this, &other, socket);
+ case SocketType::NORMAL:
+ return is_value_equal<float3>(this, &other, socket);
+ case SocketType::POINT2:
+ return is_value_equal<float2>(this, &other, socket);
+ case SocketType::CLOSURE:
+ return true;
+ case SocketType::STRING:
+ return is_value_equal<ustring>(this, &other, socket);
+ case SocketType::ENUM:
+ return is_value_equal<int>(this, &other, socket);
+ case SocketType::TRANSFORM:
+ return is_value_equal<Transform>(this, &other, socket);
+ case SocketType::NODE:
+ return is_value_equal<void *>(this, &other, socket);
+
+ case SocketType::BOOLEAN_ARRAY:
+ return is_array_equal<bool>(this, &other, socket);
+ case SocketType::FLOAT_ARRAY:
+ return is_array_equal<float>(this, &other, socket);
+ case SocketType::INT_ARRAY:
+ return is_array_equal<int>(this, &other, socket);
+ case SocketType::COLOR_ARRAY:
+ return is_array_equal<float3>(this, &other, socket);
+ case SocketType::VECTOR_ARRAY:
+ return is_array_equal<float3>(this, &other, socket);
+ case SocketType::POINT_ARRAY:
+ return is_array_equal<float3>(this, &other, socket);
+ case SocketType::NORMAL_ARRAY:
+ return is_array_equal<float3>(this, &other, socket);
+ case SocketType::POINT2_ARRAY:
+ return is_array_equal<float2>(this, &other, socket);
+ case SocketType::STRING_ARRAY:
+ return is_array_equal<ustring>(this, &other, socket);
+ case SocketType::TRANSFORM_ARRAY:
+ return is_array_equal<Transform>(this, &other, socket);
+ case SocketType::NODE_ARRAY:
+ return is_array_equal<void *>(this, &other, socket);
+
+ case SocketType::UNDEFINED:
+ return true;
+ }
+
+ return true;
}
/* equals */
-bool Node::equals(const Node& other) const
+bool Node::equals(const Node &other) const
{
- assert(type == other.type);
+ assert(type == other.type);
- foreach(const SocketType& socket, type->inputs) {
- if(!equals_value(other, socket))
- return false;
- }
+ foreach (const SocketType &socket, type->inputs) {
+ if (!equals_value(other, socket))
+ return false;
+ }
- return true;
+ return true;
}
/* Hash */
namespace {
-template<typename T>
-void value_hash(const Node *node, const SocketType& socket, MD5Hash& md5)
+template<typename T> void value_hash(const Node *node, const SocketType &socket, MD5Hash &md5)
{
- md5.append(((uint8_t*)node) + socket.struct_offset, socket.size());
+ md5.append(((uint8_t *)node) + socket.struct_offset, socket.size());
}
-void float3_hash(const Node *node, const SocketType& socket, MD5Hash& md5)
+void float3_hash(const Node *node, const SocketType &socket, MD5Hash &md5)
{
- /* Don't compare 4th element used for padding. */
- md5.append(((uint8_t*)node) + socket.struct_offset, sizeof(float) * 3);
+ /* Don't compare 4th element used for padding. */
+ md5.append(((uint8_t *)node) + socket.struct_offset, sizeof(float) * 3);
}
-template<typename T>
-void array_hash(const Node *node, const SocketType& socket, MD5Hash& md5)
+template<typename T> void array_hash(const Node *node, const SocketType &socket, MD5Hash &md5)
{
- const array<T>& a = *(const array<T>*)(((char*)node) + socket.struct_offset);
- for(size_t i = 0; i < a.size(); i++) {
- md5.append((uint8_t*)&a[i], sizeof(T));
- }
+ const array<T> &a = *(const array<T> *)(((char *)node) + socket.struct_offset);
+ for (size_t i = 0; i < a.size(); i++) {
+ md5.append((uint8_t *)&a[i], sizeof(T));
+ }
}
-void float3_array_hash(const Node *node, const SocketType& socket, MD5Hash& md5)
+void float3_array_hash(const Node *node, const SocketType &socket, MD5Hash &md5)
{
- /* Don't compare 4th element used for padding. */
- const array<float3>& a = *(const array<float3>*)(((char*)node) + socket.struct_offset);
- for(size_t i = 0; i < a.size(); i++) {
- md5.append((uint8_t*)&a[i], sizeof(float) * 3);
- }
+ /* Don't compare 4th element used for padding. */
+ const array<float3> &a = *(const array<float3> *)(((char *)node) + socket.struct_offset);
+ for (size_t i = 0; i < a.size(); i++) {
+ md5.append((uint8_t *)&a[i], sizeof(float) * 3);
+ }
}
} // namespace
-void Node::hash(MD5Hash& md5)
-{
- md5.append(type->name.string());
-
- foreach(const SocketType& socket, type->inputs) {
- md5.append(socket.name.string());
-
- switch(socket.type) {
- case SocketType::BOOLEAN: value_hash<bool>(this, socket, md5); break;
- case SocketType::FLOAT: value_hash<float>(this, socket, md5); break;
- case SocketType::INT: value_hash<int>(this, socket, md5); break;
- case SocketType::UINT: value_hash<uint>(this, socket, md5); break;
- case SocketType::COLOR: float3_hash(this, socket, md5); break;
- case SocketType::VECTOR: float3_hash(this, socket, md5); break;
- case SocketType::POINT: float3_hash(this, socket, md5); break;
- case SocketType::NORMAL: float3_hash(this, socket, md5); break;
- case SocketType::POINT2: value_hash<float2>(this, socket, md5); break;
- case SocketType::CLOSURE: break;
- case SocketType::STRING: value_hash<ustring>(this, socket, md5); break;
- case SocketType::ENUM: value_hash<int>(this, socket, md5); break;
- case SocketType::TRANSFORM: value_hash<Transform>(this, socket, md5); break;
- case SocketType::NODE: value_hash<void*>(this, socket, md5); break;
-
- case SocketType::BOOLEAN_ARRAY: array_hash<bool>(this, socket, md5); break;
- case SocketType::FLOAT_ARRAY: array_hash<float>(this, socket, md5); break;
- case SocketType::INT_ARRAY: array_hash<int>(this, socket, md5); break;
- case SocketType::COLOR_ARRAY: float3_array_hash(this, socket, md5); break;
- case SocketType::VECTOR_ARRAY: float3_array_hash(this, socket, md5); break;
- case SocketType::POINT_ARRAY: float3_array_hash(this, socket, md5); break;
- case SocketType::NORMAL_ARRAY: float3_array_hash(this, socket, md5); break;
- case SocketType::POINT2_ARRAY: array_hash<float2>(this, socket, md5); break;
- case SocketType::STRING_ARRAY: array_hash<ustring>(this, socket, md5); break;
- case SocketType::TRANSFORM_ARRAY: array_hash<Transform>(this, socket, md5); break;
- case SocketType::NODE_ARRAY: array_hash<void*>(this, socket, md5); break;
-
- case SocketType::UNDEFINED: break;
- }
- }
+void Node::hash(MD5Hash &md5)
+{
+ md5.append(type->name.string());
+
+ foreach (const SocketType &socket, type->inputs) {
+ md5.append(socket.name.string());
+
+ switch (socket.type) {
+ case SocketType::BOOLEAN:
+ value_hash<bool>(this, socket, md5);
+ break;
+ case SocketType::FLOAT:
+ value_hash<float>(this, socket, md5);
+ break;
+ case SocketType::INT:
+ value_hash<int>(this, socket, md5);
+ break;
+ case SocketType::UINT:
+ value_hash<uint>(this, socket, md5);
+ break;
+ case SocketType::COLOR:
+ float3_hash(this, socket, md5);
+ break;
+ case SocketType::VECTOR:
+ float3_hash(this, socket, md5);
+ break;
+ case SocketType::POINT:
+ float3_hash(this, socket, md5);
+ break;
+ case SocketType::NORMAL:
+ float3_hash(this, socket, md5);
+ break;
+ case SocketType::POINT2:
+ value_hash<float2>(this, socket, md5);
+ break;
+ case SocketType::CLOSURE:
+ break;
+ case SocketType::STRING:
+ value_hash<ustring>(this, socket, md5);
+ break;
+ case SocketType::ENUM:
+ value_hash<int>(this, socket, md5);
+ break;
+ case SocketType::TRANSFORM:
+ value_hash<Transform>(this, socket, md5);
+ break;
+ case SocketType::NODE:
+ value_hash<void *>(this, socket, md5);
+ break;
+
+ case SocketType::BOOLEAN_ARRAY:
+ array_hash<bool>(this, socket, md5);
+ break;
+ case SocketType::FLOAT_ARRAY:
+ array_hash<float>(this, socket, md5);
+ break;
+ case SocketType::INT_ARRAY:
+ array_hash<int>(this, socket, md5);
+ break;
+ case SocketType::COLOR_ARRAY:
+ float3_array_hash(this, socket, md5);
+ break;
+ case SocketType::VECTOR_ARRAY:
+ float3_array_hash(this, socket, md5);
+ break;
+ case SocketType::POINT_ARRAY:
+ float3_array_hash(this, socket, md5);
+ break;
+ case SocketType::NORMAL_ARRAY:
+ float3_array_hash(this, socket, md5);
+ break;
+ case SocketType::POINT2_ARRAY:
+ array_hash<float2>(this, socket, md5);
+ break;
+ case SocketType::STRING_ARRAY:
+ array_hash<ustring>(this, socket, md5);
+ break;
+ case SocketType::TRANSFORM_ARRAY:
+ array_hash<Transform>(this, socket, md5);
+ break;
+ case SocketType::NODE_ARRAY:
+ array_hash<void *>(this, socket, md5);
+ break;
+
+ case SocketType::UNDEFINED:
+ break;
+ }
+ }
}
namespace {
-template<typename T>
-size_t array_size_in_bytes(const Node *node, const SocketType& socket)
+template<typename T> size_t array_size_in_bytes(const Node *node, const SocketType &socket)
{
- const array<T>& a = *(const array<T>*)(((char*)node) + socket.struct_offset);
- return a.size() * sizeof(T);
+ const array<T> &a = *(const array<T> *)(((char *)node) + socket.struct_offset);
+ return a.size() * sizeof(T);
}
} // namespace
size_t Node::get_total_size_in_bytes() const
{
- size_t total_size = 0;
- foreach(const SocketType& socket, type->inputs) {
- switch(socket.type) {
- case SocketType::BOOLEAN:
- case SocketType::FLOAT:
- case SocketType::INT:
- case SocketType::UINT:
- case SocketType::COLOR:
- case SocketType::VECTOR:
- case SocketType::POINT:
- case SocketType::NORMAL:
- case SocketType::POINT2:
- case SocketType::CLOSURE:
- case SocketType::STRING:
- case SocketType::ENUM:
- case SocketType::TRANSFORM:
- case SocketType::NODE:
- total_size += socket.size();
- break;
-
- case SocketType::BOOLEAN_ARRAY:
- total_size += array_size_in_bytes<bool>(this, socket);
- break;
- case SocketType::FLOAT_ARRAY:
- total_size += array_size_in_bytes<float>(this, socket);
- break;
- case SocketType::INT_ARRAY:
- total_size += array_size_in_bytes<int>(this, socket);
- break;
- case SocketType::COLOR_ARRAY:
- total_size += array_size_in_bytes<float3>(this, socket);
- break;
- case SocketType::VECTOR_ARRAY:
- total_size += array_size_in_bytes<float3>(this, socket);
- break;
- case SocketType::POINT_ARRAY:
- total_size += array_size_in_bytes<float3>(this, socket);
- break;
- case SocketType::NORMAL_ARRAY:
- total_size += array_size_in_bytes<float3>(this, socket);
- break;
- case SocketType::POINT2_ARRAY:
- total_size += array_size_in_bytes<float2>(this, socket);
- break;
- case SocketType::STRING_ARRAY:
- total_size += array_size_in_bytes<ustring>(this, socket);
- break;
- case SocketType::TRANSFORM_ARRAY:
- total_size += array_size_in_bytes<Transform>(this, socket);
- break;
- case SocketType::NODE_ARRAY:
- total_size += array_size_in_bytes<void*>(this, socket);
- break;
-
- case SocketType::UNDEFINED: break;
- }
- }
- return total_size;
+ size_t total_size = 0;
+ foreach (const SocketType &socket, type->inputs) {
+ switch (socket.type) {
+ case SocketType::BOOLEAN:
+ case SocketType::FLOAT:
+ case SocketType::INT:
+ case SocketType::UINT:
+ case SocketType::COLOR:
+ case SocketType::VECTOR:
+ case SocketType::POINT:
+ case SocketType::NORMAL:
+ case SocketType::POINT2:
+ case SocketType::CLOSURE:
+ case SocketType::STRING:
+ case SocketType::ENUM:
+ case SocketType::TRANSFORM:
+ case SocketType::NODE:
+ total_size += socket.size();
+ break;
+
+ case SocketType::BOOLEAN_ARRAY:
+ total_size += array_size_in_bytes<bool>(this, socket);
+ break;
+ case SocketType::FLOAT_ARRAY:
+ total_size += array_size_in_bytes<float>(this, socket);
+ break;
+ case SocketType::INT_ARRAY:
+ total_size += array_size_in_bytes<int>(this, socket);
+ break;
+ case SocketType::COLOR_ARRAY:
+ total_size += array_size_in_bytes<float3>(this, socket);
+ break;
+ case SocketType::VECTOR_ARRAY:
+ total_size += array_size_in_bytes<float3>(this, socket);
+ break;
+ case SocketType::POINT_ARRAY:
+ total_size += array_size_in_bytes<float3>(this, socket);
+ break;
+ case SocketType::NORMAL_ARRAY:
+ total_size += array_size_in_bytes<float3>(this, socket);
+ break;
+ case SocketType::POINT2_ARRAY:
+ total_size += array_size_in_bytes<float2>(this, socket);
+ break;
+ case SocketType::STRING_ARRAY:
+ total_size += array_size_in_bytes<ustring>(this, socket);
+ break;
+ case SocketType::TRANSFORM_ARRAY:
+ total_size += array_size_in_bytes<Transform>(this, socket);
+ break;
+ case SocketType::NODE_ARRAY:
+ total_size += array_size_in_bytes<void *>(this, socket);
+ break;
+
+ case SocketType::UNDEFINED:
+ break;
+ }
+ }
+ return total_size;
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/graph/node.h b/intern/cycles/graph/node.h
index d50a3786139..226c49b387a 100644
--- a/intern/cycles/graph/node.h
+++ b/intern/cycles/graph/node.h
@@ -31,72 +31,71 @@ struct Transform;
/* Node */
-struct Node
-{
- explicit Node(const NodeType *type, ustring name = ustring());
- virtual ~Node();
-
- /* set values */
- void set(const SocketType& input, bool value);
- void set(const SocketType& input, int value);
- void set(const SocketType& input, uint value);
- void set(const SocketType& input, float value);
- void set(const SocketType& input, float2 value);
- void set(const SocketType& input, float3 value);
- void set(const SocketType& input, const char *value);
- void set(const SocketType& input, ustring value);
- void set(const SocketType& input, const Transform& value);
- void set(const SocketType& input, Node *value);
-
- /* set array values. the memory from the input array will taken over
- * by the node and the input array will be empty after return */
- void set(const SocketType& input, array<bool>& value);
- void set(const SocketType& input, array<int>& value);
- void set(const SocketType& input, array<float>& value);
- void set(const SocketType& input, array<float2>& value);
- void set(const SocketType& input, array<float3>& value);
- void set(const SocketType& input, array<ustring>& value);
- void set(const SocketType& input, array<Transform>& value);
- void set(const SocketType& input, array<Node*>& value);
-
- /* get values */
- bool get_bool(const SocketType& input) const;
- int get_int(const SocketType& input) const;
- uint get_uint(const SocketType& input) const;
- float get_float(const SocketType& input) const;
- float2 get_float2(const SocketType& input) const;
- float3 get_float3(const SocketType& input) const;
- ustring get_string(const SocketType& input) const;
- Transform get_transform(const SocketType& input) const;
- Node *get_node(const SocketType& input) const;
-
- /* get array values */
- const array<bool>& get_bool_array(const SocketType& input) const;
- const array<int>& get_int_array(const SocketType& input) const;
- const array<float>& get_float_array(const SocketType& input) const;
- const array<float2>& get_float2_array(const SocketType& input) const;
- const array<float3>& get_float3_array(const SocketType& input) const;
- const array<ustring>& get_string_array(const SocketType& input) const;
- const array<Transform>& get_transform_array(const SocketType& input) const;
- const array<Node*>& get_node_array(const SocketType& input) const;
-
- /* generic values operations */
- bool has_default_value(const SocketType& input) const;
- void set_default_value(const SocketType& input);
- bool equals_value(const Node& other, const SocketType& input) const;
- void copy_value(const SocketType& input, const Node& other, const SocketType& other_input);
-
- /* equals */
- bool equals(const Node& other) const;
-
- /* compute hash of node and its socket values */
- void hash(MD5Hash& md5);
-
- /* Get total size of this node. */
- size_t get_total_size_in_bytes() const;
-
- ustring name;
- const NodeType *type;
+struct Node {
+ explicit Node(const NodeType *type, ustring name = ustring());
+ virtual ~Node();
+
+ /* set values */
+ void set(const SocketType &input, bool value);
+ void set(const SocketType &input, int value);
+ void set(const SocketType &input, uint value);
+ void set(const SocketType &input, float value);
+ void set(const SocketType &input, float2 value);
+ void set(const SocketType &input, float3 value);
+ void set(const SocketType &input, const char *value);
+ void set(const SocketType &input, ustring value);
+ void set(const SocketType &input, const Transform &value);
+ void set(const SocketType &input, Node *value);
+
+ /* set array values. the memory from the input array will taken over
+ * by the node and the input array will be empty after return */
+ void set(const SocketType &input, array<bool> &value);
+ void set(const SocketType &input, array<int> &value);
+ void set(const SocketType &input, array<float> &value);
+ void set(const SocketType &input, array<float2> &value);
+ void set(const SocketType &input, array<float3> &value);
+ void set(const SocketType &input, array<ustring> &value);
+ void set(const SocketType &input, array<Transform> &value);
+ void set(const SocketType &input, array<Node *> &value);
+
+ /* get values */
+ bool get_bool(const SocketType &input) const;
+ int get_int(const SocketType &input) const;
+ uint get_uint(const SocketType &input) const;
+ float get_float(const SocketType &input) const;
+ float2 get_float2(const SocketType &input) const;
+ float3 get_float3(const SocketType &input) const;
+ ustring get_string(const SocketType &input) const;
+ Transform get_transform(const SocketType &input) const;
+ Node *get_node(const SocketType &input) const;
+
+ /* get array values */
+ const array<bool> &get_bool_array(const SocketType &input) const;
+ const array<int> &get_int_array(const SocketType &input) const;
+ const array<float> &get_float_array(const SocketType &input) const;
+ const array<float2> &get_float2_array(const SocketType &input) const;
+ const array<float3> &get_float3_array(const SocketType &input) const;
+ const array<ustring> &get_string_array(const SocketType &input) const;
+ const array<Transform> &get_transform_array(const SocketType &input) const;
+ const array<Node *> &get_node_array(const SocketType &input) const;
+
+ /* generic values operations */
+ bool has_default_value(const SocketType &input) const;
+ void set_default_value(const SocketType &input);
+ bool equals_value(const Node &other, const SocketType &input) const;
+ void copy_value(const SocketType &input, const Node &other, const SocketType &other_input);
+
+ /* equals */
+ bool equals(const Node &other) const;
+
+ /* compute hash of node and its socket values */
+ void hash(MD5Hash &md5);
+
+ /* Get total size of this node. */
+ size_t get_total_size_in_bytes() const;
+
+ ustring name;
+ const NodeType *type;
};
CCL_NAMESPACE_END
diff --git a/intern/cycles/graph/node_enum.h b/intern/cycles/graph/node_enum.h
index 705aec9a918..d3ed0928a4f 100644
--- a/intern/cycles/graph/node_enum.h
+++ b/intern/cycles/graph/node_enum.h
@@ -26,25 +26,50 @@ CCL_NAMESPACE_BEGIN
* Utility class for enum values. */
struct NodeEnum {
- bool empty() const { return left.empty(); }
- void insert(const char *x, int y) {
- left[ustring(x)] = y;
- right[y] = ustring(x);
- }
+ bool empty() const
+ {
+ return left.empty();
+ }
+ void insert(const char *x, int y)
+ {
+ left[ustring(x)] = y;
+ right[y] = ustring(x);
+ }
- bool exists(ustring x) const { return left.find(x) != left.end(); }
- bool exists(int y) const { return right.find(y) != right.end(); }
+ bool exists(ustring x) const
+ {
+ return left.find(x) != left.end();
+ }
+ bool exists(int y) const
+ {
+ return right.find(y) != right.end();
+ }
- int operator[](const char *x) const { return left.find(ustring(x))->second; }
- int operator[](ustring x) const { return left.find(x)->second; }
- ustring operator[](int y) const { return right.find(y)->second; }
+ int operator[](const char *x) const
+ {
+ return left.find(ustring(x))->second;
+ }
+ int operator[](ustring x) const
+ {
+ return left.find(x)->second;
+ }
+ ustring operator[](int y) const
+ {
+ return right.find(y)->second;
+ }
- unordered_map<ustring, int, ustringHash>::const_iterator begin() const { return left.begin(); }
- unordered_map<ustring, int, ustringHash>::const_iterator end() const { return left.end(); }
+ unordered_map<ustring, int, ustringHash>::const_iterator begin() const
+ {
+ return left.begin();
+ }
+ unordered_map<ustring, int, ustringHash>::const_iterator end() const
+ {
+ return left.end();
+ }
-private:
- unordered_map<ustring, int, ustringHash> left;
- unordered_map<int, ustring> right;
+ private:
+ unordered_map<ustring, int, ustringHash> left;
+ unordered_map<int, ustring> right;
};
CCL_NAMESPACE_END
diff --git a/intern/cycles/graph/node_type.cpp b/intern/cycles/graph/node_type.cpp
index e045777e969..f46d4e48026 100644
--- a/intern/cycles/graph/node_type.cpp
+++ b/intern/cycles/graph/node_type.cpp
@@ -24,107 +24,118 @@ CCL_NAMESPACE_BEGIN
size_t SocketType::size() const
{
- return size(type);
+ return size(type);
}
bool SocketType::is_array() const
{
- return (type >= BOOLEAN_ARRAY);
+ return (type >= BOOLEAN_ARRAY);
}
size_t SocketType::size(Type type)
{
- switch(type)
- {
- case UNDEFINED: return 0;
-
- case BOOLEAN: return sizeof(bool);
- case FLOAT: return sizeof(float);
- case INT: return sizeof(int);
- case UINT: return sizeof(uint);
- case COLOR: return sizeof(float3);
- case VECTOR: return sizeof(float3);
- case POINT: return sizeof(float3);
- case NORMAL: return sizeof(float3);
- case POINT2: return sizeof(float2);
- case CLOSURE: return 0;
- case STRING: return sizeof(ustring);
- case ENUM: return sizeof(int);
- case TRANSFORM: return sizeof(Transform);
- case NODE: return sizeof(void*);
-
- case BOOLEAN_ARRAY: return sizeof(array<bool>);
- case FLOAT_ARRAY: return sizeof(array<float>);
- case INT_ARRAY: return sizeof(array<int>);
- case COLOR_ARRAY: return sizeof(array<float3>);
- case VECTOR_ARRAY: return sizeof(array<float3>);
- case POINT_ARRAY: return sizeof(array<float3>);
- case NORMAL_ARRAY: return sizeof(array<float3>);
- case POINT2_ARRAY: return sizeof(array<float2>);
- case STRING_ARRAY: return sizeof(array<ustring>);
- case TRANSFORM_ARRAY: return sizeof(array<Transform>);
- case NODE_ARRAY: return sizeof(array<void*>);
- }
-
- assert(0);
- return 0;
+ switch (type) {
+ case UNDEFINED:
+ return 0;
+
+ case BOOLEAN:
+ return sizeof(bool);
+ case FLOAT:
+ return sizeof(float);
+ case INT:
+ return sizeof(int);
+ case UINT:
+ return sizeof(uint);
+ case COLOR:
+ return sizeof(float3);
+ case VECTOR:
+ return sizeof(float3);
+ case POINT:
+ return sizeof(float3);
+ case NORMAL:
+ return sizeof(float3);
+ case POINT2:
+ return sizeof(float2);
+ case CLOSURE:
+ return 0;
+ case STRING:
+ return sizeof(ustring);
+ case ENUM:
+ return sizeof(int);
+ case TRANSFORM:
+ return sizeof(Transform);
+ case NODE:
+ return sizeof(void *);
+
+ case BOOLEAN_ARRAY:
+ return sizeof(array<bool>);
+ case FLOAT_ARRAY:
+ return sizeof(array<float>);
+ case INT_ARRAY:
+ return sizeof(array<int>);
+ case COLOR_ARRAY:
+ return sizeof(array<float3>);
+ case VECTOR_ARRAY:
+ return sizeof(array<float3>);
+ case POINT_ARRAY:
+ return sizeof(array<float3>);
+ case NORMAL_ARRAY:
+ return sizeof(array<float3>);
+ case POINT2_ARRAY:
+ return sizeof(array<float2>);
+ case STRING_ARRAY:
+ return sizeof(array<ustring>);
+ case TRANSFORM_ARRAY:
+ return sizeof(array<Transform>);
+ case NODE_ARRAY:
+ return sizeof(array<void *>);
+ }
+
+ assert(0);
+ return 0;
}
size_t SocketType::max_size()
{
- return sizeof(Transform);
+ return sizeof(Transform);
}
void *SocketType::zero_default_value()
{
- static Transform zero_transform = {{0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}};
- return &zero_transform;
+ static Transform zero_transform = {{0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}};
+ return &zero_transform;
}
ustring SocketType::type_name(Type type)
{
- static ustring names[] = {
- ustring("undefined"),
-
- ustring("boolean"),
- ustring("float"),
- ustring("int"),
- ustring("uint"),
- ustring("color"),
- ustring("vector"),
- ustring("point"),
- ustring("normal"),
- ustring("point2"),
- ustring("closure"),
- ustring("string"),
- ustring("enum"),
- ustring("transform"),
- ustring("node"),
-
- ustring("array_boolean"),
- ustring("array_float"),
- ustring("array_int"),
- ustring("array_color"),
- ustring("array_vector"),
- ustring("array_point"),
- ustring("array_normal"),
- ustring("array_point2"),
- ustring("array_string"),
- ustring("array_transform"),
- ustring("array_node")};
-
- return names[(int)type];
+ static ustring names[] = {ustring("undefined"),
+
+ ustring("boolean"), ustring("float"),
+ ustring("int"), ustring("uint"),
+ ustring("color"), ustring("vector"),
+ ustring("point"), ustring("normal"),
+ ustring("point2"), ustring("closure"),
+ ustring("string"), ustring("enum"),
+ ustring("transform"), ustring("node"),
+
+ ustring("array_boolean"), ustring("array_float"),
+ ustring("array_int"), ustring("array_color"),
+ ustring("array_vector"), ustring("array_point"),
+ ustring("array_normal"), ustring("array_point2"),
+ ustring("array_string"), ustring("array_transform"),
+ ustring("array_node")};
+
+ return names[(int)type];
}
bool SocketType::is_float3(Type type)
{
- return (type == COLOR || type == VECTOR || type == POINT || type == NORMAL);
+ return (type == COLOR || type == VECTOR || type == POINT || type == NORMAL);
}
/* Node Type */
-NodeType::NodeType(Type type_)
-: type(type_)
+NodeType::NodeType(Type type_) : type(type_)
{
}
@@ -132,88 +143,94 @@ NodeType::~NodeType()
{
}
-void NodeType::register_input(ustring name, ustring ui_name, SocketType::Type type, int struct_offset,
- const void *default_value, const NodeEnum *enum_values,
- const NodeType **node_type, int flags, int extra_flags)
+void NodeType::register_input(ustring name,
+ ustring ui_name,
+ SocketType::Type type,
+ int struct_offset,
+ const void *default_value,
+ const NodeEnum *enum_values,
+ const NodeType **node_type,
+ int flags,
+ int extra_flags)
{
- SocketType socket;
- socket.name = name;
- socket.ui_name = ui_name;
- socket.type = type;
- socket.struct_offset = struct_offset;
- socket.default_value = default_value;
- socket.enum_values = enum_values;
- socket.node_type = node_type;
- socket.flags = flags | extra_flags;
- inputs.push_back(socket);
+ SocketType socket;
+ socket.name = name;
+ socket.ui_name = ui_name;
+ socket.type = type;
+ socket.struct_offset = struct_offset;
+ socket.default_value = default_value;
+ socket.enum_values = enum_values;
+ socket.node_type = node_type;
+ socket.flags = flags | extra_flags;
+ inputs.push_back(socket);
}
void NodeType::register_output(ustring name, ustring ui_name, SocketType::Type type)
{
- SocketType socket;
- socket.name = name;
- socket.ui_name = ui_name;
- socket.type = type;
- socket.struct_offset = 0;
- socket.default_value = NULL;
- socket.enum_values = NULL;
- socket.node_type = NULL;
- socket.flags = SocketType::LINKABLE;
- outputs.push_back(socket);
+ SocketType socket;
+ socket.name = name;
+ socket.ui_name = ui_name;
+ socket.type = type;
+ socket.struct_offset = 0;
+ socket.default_value = NULL;
+ socket.enum_values = NULL;
+ socket.node_type = NULL;
+ socket.flags = SocketType::LINKABLE;
+ outputs.push_back(socket);
}
const SocketType *NodeType::find_input(ustring name) const
{
- foreach(const SocketType& socket, inputs) {
- if(socket.name == name) {
- return &socket;
- }
- }
+ foreach (const SocketType &socket, inputs) {
+ if (socket.name == name) {
+ return &socket;
+ }
+ }
- return NULL;
+ return NULL;
}
const SocketType *NodeType::find_output(ustring name) const
{
- foreach(const SocketType& socket, outputs) {
- if(socket.name == name) {
- return &socket;
- }
- }
+ foreach (const SocketType &socket, outputs) {
+ if (socket.name == name) {
+ return &socket;
+ }
+ }
- return NULL;
+ return NULL;
}
/* Node Type Registry */
-unordered_map<ustring, NodeType, ustringHash>& NodeType::types()
+unordered_map<ustring, NodeType, ustringHash> &NodeType::types()
{
- static unordered_map<ustring, NodeType, ustringHash> _types;
- return _types;
+ static unordered_map<ustring, NodeType, ustringHash> _types;
+ return _types;
}
NodeType *NodeType::add(const char *name_, CreateFunc create_, Type type_)
{
- ustring name(name_);
+ ustring name(name_);
- if(types().find(name) != types().end()) {
- fprintf(stderr, "Node type %s registered twice!\n", name_);
- assert(0);
- return NULL;
- }
+ if (types().find(name) != types().end()) {
+ fprintf(stderr, "Node type %s registered twice!\n", name_);
+ assert(0);
+ return NULL;
+ }
- types()[name] = NodeType(type_);
+ types()[name] = NodeType(type_);
- NodeType *type = &types()[name];
- type->name = name;
- type->create = create_;
- return type;
+ NodeType *type = &types()[name];
+ type->name = name;
+ type->create = create_;
+ return type;
}
const NodeType *NodeType::find(ustring name)
{
- unordered_map<ustring, NodeType, ustringHash>::iterator it = types().find(name);
- return (it == types().end()) ? NULL : &it->second;
+ unordered_map<ustring, NodeType, ustringHash>::iterator it = types().find(name);
+ return (it == types().end()) ? NULL : &it->second;
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/graph/node_type.h b/intern/cycles/graph/node_type.h
index 7d6abae2314..e9496a42658 100644
--- a/intern/cycles/graph/node_type.h
+++ b/intern/cycles/graph/node_type.h
@@ -30,236 +30,349 @@ struct NodeType;
/* Socket Type */
-struct SocketType
-{
- enum Type
- {
- UNDEFINED,
+struct SocketType {
+ enum Type {
+ UNDEFINED,
- BOOLEAN,
- FLOAT,
- INT,
- UINT,
- COLOR,
- VECTOR,
- POINT,
- NORMAL,
- POINT2,
- CLOSURE,
- STRING,
- ENUM,
- TRANSFORM,
- NODE,
+ BOOLEAN,
+ FLOAT,
+ INT,
+ UINT,
+ COLOR,
+ VECTOR,
+ POINT,
+ NORMAL,
+ POINT2,
+ CLOSURE,
+ STRING,
+ ENUM,
+ TRANSFORM,
+ NODE,
- BOOLEAN_ARRAY,
- FLOAT_ARRAY,
- INT_ARRAY,
- COLOR_ARRAY,
- VECTOR_ARRAY,
- POINT_ARRAY,
- NORMAL_ARRAY,
- POINT2_ARRAY,
- STRING_ARRAY,
- TRANSFORM_ARRAY,
- NODE_ARRAY,
- };
+ BOOLEAN_ARRAY,
+ FLOAT_ARRAY,
+ INT_ARRAY,
+ COLOR_ARRAY,
+ VECTOR_ARRAY,
+ POINT_ARRAY,
+ NORMAL_ARRAY,
+ POINT2_ARRAY,
+ STRING_ARRAY,
+ TRANSFORM_ARRAY,
+ NODE_ARRAY,
+ };
- enum Flags {
- LINKABLE = (1 << 0),
- ANIMATABLE = (1 << 1),
+ enum Flags {
+ LINKABLE = (1 << 0),
+ ANIMATABLE = (1 << 1),
- SVM_INTERNAL = (1 << 2),
- OSL_INTERNAL = (1 << 3),
- INTERNAL = (1 << 2) | (1 << 3),
+ SVM_INTERNAL = (1 << 2),
+ OSL_INTERNAL = (1 << 3),
+ INTERNAL = (1 << 2) | (1 << 3),
- LINK_TEXTURE_GENERATED = (1 << 4),
- LINK_TEXTURE_NORMAL = (1 << 5),
- LINK_TEXTURE_UV = (1 << 6),
- LINK_INCOMING = (1 << 7),
- LINK_NORMAL = (1 << 8),
- LINK_POSITION = (1 << 9),
- LINK_TANGENT = (1 << 10),
- DEFAULT_LINK_MASK = (1 << 4) | (1 << 5) | (1 << 6) | (1 << 7) | (1 << 8) | (1 << 9) | (1 << 10)
- };
+ LINK_TEXTURE_GENERATED = (1 << 4),
+ LINK_TEXTURE_NORMAL = (1 << 5),
+ LINK_TEXTURE_UV = (1 << 6),
+ LINK_INCOMING = (1 << 7),
+ LINK_NORMAL = (1 << 8),
+ LINK_POSITION = (1 << 9),
+ LINK_TANGENT = (1 << 10),
+ DEFAULT_LINK_MASK = (1 << 4) | (1 << 5) | (1 << 6) | (1 << 7) | (1 << 8) | (1 << 9) | (1 << 10)
+ };
- ustring name;
- Type type;
- int struct_offset;
- const void *default_value;
- const NodeEnum *enum_values;
- const NodeType **node_type;
- int flags;
- ustring ui_name;
+ ustring name;
+ Type type;
+ int struct_offset;
+ const void *default_value;
+ const NodeEnum *enum_values;
+ const NodeType **node_type;
+ int flags;
+ ustring ui_name;
- size_t size() const;
- bool is_array() const;
- static size_t size(Type type);
- static size_t max_size();
- static ustring type_name(Type type);
- static void *zero_default_value();
- static bool is_float3(Type type);
+ size_t size() const;
+ bool is_array() const;
+ static size_t size(Type type);
+ static size_t max_size();
+ static ustring type_name(Type type);
+ static void *zero_default_value();
+ static bool is_float3(Type type);
};
/* Node Type */
-struct NodeType
-{
- enum Type {
- NONE,
- SHADER
- };
+struct NodeType {
+ enum Type { NONE, SHADER };
- explicit NodeType(Type type = NONE);
- ~NodeType();
+ explicit NodeType(Type type = NONE);
+ ~NodeType();
- void register_input(ustring name, ustring ui_name, SocketType::Type type,
- int struct_offset, const void *default_value,
- const NodeEnum *enum_values = NULL,
- const NodeType **node_type = NULL,
- int flags = 0, int extra_flags = 0);
- void register_output(ustring name, ustring ui_name, SocketType::Type type);
+ void register_input(ustring name,
+ ustring ui_name,
+ SocketType::Type type,
+ int struct_offset,
+ const void *default_value,
+ const NodeEnum *enum_values = NULL,
+ const NodeType **node_type = NULL,
+ int flags = 0,
+ int extra_flags = 0);
+ void register_output(ustring name, ustring ui_name, SocketType::Type type);
- const SocketType *find_input(ustring name) const;
- const SocketType *find_output(ustring name) const;
+ const SocketType *find_input(ustring name) const;
+ const SocketType *find_output(ustring name) const;
- typedef Node *(*CreateFunc)(const NodeType *type);
+ typedef Node *(*CreateFunc)(const NodeType *type);
- ustring name;
- Type type;
- vector<SocketType, std::allocator<SocketType> > inputs;
- vector<SocketType, std::allocator<SocketType> > outputs;
- CreateFunc create;
+ ustring name;
+ Type type;
+ vector<SocketType, std::allocator<SocketType>> inputs;
+ vector<SocketType, std::allocator<SocketType>> outputs;
+ CreateFunc create;
- static NodeType *add(const char *name, CreateFunc create, Type type = NONE);
- static const NodeType *find(ustring name);
- static unordered_map<ustring, NodeType, ustringHash>& types();
+ static NodeType *add(const char *name, CreateFunc create, Type type = NONE);
+ static const NodeType *find(ustring name);
+ static unordered_map<ustring, NodeType, ustringHash> &types();
};
/* Node Definition Macros */
-#define NODE_DECLARE \
-template<typename T> \
-static const NodeType *register_type(); \
-static Node *create(const NodeType *type); \
-static const NodeType *node_type;
+#define NODE_DECLARE \
+ template<typename T> static const NodeType *register_type(); \
+ static Node *create(const NodeType *type); \
+ static const NodeType *node_type;
-#define NODE_DEFINE(structname) \
-const NodeType *structname::node_type = structname::register_type<structname>(); \
-Node *structname::create(const NodeType*) { return new structname(); } \
-template<typename T> \
-const NodeType *structname::register_type()
+#define NODE_DEFINE(structname) \
+ const NodeType *structname::node_type = structname::register_type<structname>(); \
+ Node *structname::create(const NodeType *) \
+ { \
+ return new structname(); \
+ } \
+ template<typename T> const NodeType *structname::register_type()
/* Sock Definition Macros */
#define SOCKET_OFFSETOF(T, name) (((char *)&(((T *)1)->name)) - (char *)1)
#define SOCKET_SIZEOF(T, name) (sizeof(((T *)1)->name))
#define SOCKET_DEFINE(name, ui_name, default_value, datatype, TYPE, flags, ...) \
- { \
- static datatype defval = default_value; \
- CHECK_TYPE(((T *)1)->name, datatype); \
- type->register_input(ustring(#name), ustring(ui_name), TYPE, SOCKET_OFFSETOF(T, name), &defval, NULL, NULL, flags, ##__VA_ARGS__); \
- }
+ { \
+ static datatype defval = default_value; \
+ CHECK_TYPE(((T *)1)->name, datatype); \
+ type->register_input(ustring(#name), \
+ ustring(ui_name), \
+ TYPE, \
+ SOCKET_OFFSETOF(T, name), \
+ &defval, \
+ NULL, \
+ NULL, \
+ flags, \
+ ##__VA_ARGS__); \
+ }
#define SOCKET_BOOLEAN(name, ui_name, default_value, ...) \
- SOCKET_DEFINE(name, ui_name, default_value, bool, SocketType::BOOLEAN, 0, ##__VA_ARGS__)
+ SOCKET_DEFINE(name, ui_name, default_value, bool, SocketType::BOOLEAN, 0, ##__VA_ARGS__)
#define SOCKET_INT(name, ui_name, default_value, ...) \
- SOCKET_DEFINE(name, ui_name, default_value, int, SocketType::INT, 0, ##__VA_ARGS__)
+ SOCKET_DEFINE(name, ui_name, default_value, int, SocketType::INT, 0, ##__VA_ARGS__)
#define SOCKET_UINT(name, ui_name, default_value, ...) \
- SOCKET_DEFINE(name, ui_name, default_value, uint, SocketType::UINT, 0, ##__VA_ARGS__)
+ SOCKET_DEFINE(name, ui_name, default_value, uint, SocketType::UINT, 0, ##__VA_ARGS__)
#define SOCKET_FLOAT(name, ui_name, default_value, ...) \
- SOCKET_DEFINE(name, ui_name, default_value, float, SocketType::FLOAT, 0, ##__VA_ARGS__)
+ SOCKET_DEFINE(name, ui_name, default_value, float, SocketType::FLOAT, 0, ##__VA_ARGS__)
#define SOCKET_COLOR(name, ui_name, default_value, ...) \
- SOCKET_DEFINE(name, ui_name, default_value, float3, SocketType::COLOR, 0, ##__VA_ARGS__)
+ SOCKET_DEFINE(name, ui_name, default_value, float3, SocketType::COLOR, 0, ##__VA_ARGS__)
#define SOCKET_VECTOR(name, ui_name, default_value, ...) \
- SOCKET_DEFINE(name, ui_name, default_value, float3, SocketType::VECTOR, 0, ##__VA_ARGS__)
+ SOCKET_DEFINE(name, ui_name, default_value, float3, SocketType::VECTOR, 0, ##__VA_ARGS__)
#define SOCKET_POINT(name, ui_name, default_value, ...) \
- SOCKET_DEFINE(name, ui_name, default_value, float3, SocketType::POINT, 0, ##__VA_ARGS__)
+ SOCKET_DEFINE(name, ui_name, default_value, float3, SocketType::POINT, 0, ##__VA_ARGS__)
#define SOCKET_NORMAL(name, ui_name, default_value, ...) \
- SOCKET_DEFINE(name, ui_name, default_value, float3, SocketType::NORMAL, 0, ##__VA_ARGS__)
+ SOCKET_DEFINE(name, ui_name, default_value, float3, SocketType::NORMAL, 0, ##__VA_ARGS__)
#define SOCKET_POINT2(name, ui_name, default_value, ...) \
- SOCKET_DEFINE(name, ui_name, default_value, float2, SocketType::POINT2, 0, ##__VA_ARGS__)
+ SOCKET_DEFINE(name, ui_name, default_value, float2, SocketType::POINT2, 0, ##__VA_ARGS__)
#define SOCKET_STRING(name, ui_name, default_value, ...) \
- SOCKET_DEFINE(name, ui_name, default_value, ustring, SocketType::STRING, 0, ##__VA_ARGS__)
+ SOCKET_DEFINE(name, ui_name, default_value, ustring, SocketType::STRING, 0, ##__VA_ARGS__)
#define SOCKET_TRANSFORM(name, ui_name, default_value, ...) \
- SOCKET_DEFINE(name, ui_name, default_value, Transform, SocketType::TRANSFORM, 0, ##__VA_ARGS__)
+ SOCKET_DEFINE(name, ui_name, default_value, Transform, SocketType::TRANSFORM, 0, ##__VA_ARGS__)
#define SOCKET_ENUM(name, ui_name, values, default_value, ...) \
- { \
- static int defval = default_value; \
- assert(SOCKET_SIZEOF(T, name) == sizeof(int)); \
- type->register_input(ustring(#name), ustring(ui_name), SocketType::ENUM, SOCKET_OFFSETOF(T, name), &defval, &values, NULL, ##__VA_ARGS__); \
- }
+ { \
+ static int defval = default_value; \
+ assert(SOCKET_SIZEOF(T, name) == sizeof(int)); \
+ type->register_input(ustring(#name), \
+ ustring(ui_name), \
+ SocketType::ENUM, \
+ SOCKET_OFFSETOF(T, name), \
+ &defval, \
+ &values, \
+ NULL, \
+ ##__VA_ARGS__); \
+ }
#define SOCKET_NODE(name, ui_name, node_type, ...) \
- { \
- static Node *defval = NULL; \
- assert(SOCKET_SIZEOF(T, name) == sizeof(Node*)); \
- type->register_input(ustring(#name), ustring(ui_name), SocketType::NODE, SOCKET_OFFSETOF(T, name), &defval, NULL, node_type, ##__VA_ARGS__); \
- }
+ { \
+ static Node *defval = NULL; \
+ assert(SOCKET_SIZEOF(T, name) == sizeof(Node *)); \
+ type->register_input(ustring(#name), \
+ ustring(ui_name), \
+ SocketType::NODE, \
+ SOCKET_OFFSETOF(T, name), \
+ &defval, \
+ NULL, \
+ node_type, \
+ ##__VA_ARGS__); \
+ }
#define SOCKET_BOOLEAN_ARRAY(name, ui_name, default_value, ...) \
- SOCKET_DEFINE(name, ui_name, default_value, array<bool>, SocketType::BOOLEAN_ARRAY, 0, ##__VA_ARGS__)
+ SOCKET_DEFINE( \
+ name, ui_name, default_value, array<bool>, SocketType::BOOLEAN_ARRAY, 0, ##__VA_ARGS__)
#define SOCKET_INT_ARRAY(name, ui_name, default_value, ...) \
- SOCKET_DEFINE(name, ui_name, default_value, array<int>, SocketType::INT_ARRAY, 0, ##__VA_ARGS__)
+ SOCKET_DEFINE(name, ui_name, default_value, array<int>, SocketType::INT_ARRAY, 0, ##__VA_ARGS__)
#define SOCKET_FLOAT_ARRAY(name, ui_name, default_value, ...) \
- SOCKET_DEFINE(name, ui_name, default_value, array<float>, SocketType::FLOAT_ARRAY, 0, ##__VA_ARGS__)
+ SOCKET_DEFINE( \
+ name, ui_name, default_value, array<float>, SocketType::FLOAT_ARRAY, 0, ##__VA_ARGS__)
#define SOCKET_COLOR_ARRAY(name, ui_name, default_value, ...) \
- SOCKET_DEFINE(name, ui_name, default_value, array<float3>, SocketType::COLOR_ARRAY, 0, ##__VA_ARGS__)
+ SOCKET_DEFINE( \
+ name, ui_name, default_value, array<float3>, SocketType::COLOR_ARRAY, 0, ##__VA_ARGS__)
#define SOCKET_VECTOR_ARRAY(name, ui_name, default_value, ...) \
- SOCKET_DEFINE(name, ui_name, default_value, array<float3>, SocketType::VECTOR_ARRAY, 0, ##__VA_ARGS__)
+ SOCKET_DEFINE( \
+ name, ui_name, default_value, array<float3>, SocketType::VECTOR_ARRAY, 0, ##__VA_ARGS__)
#define SOCKET_POINT_ARRAY(name, ui_name, default_value, ...) \
- SOCKET_DEFINE(name, ui_name, default_value, array<float3>, SocketType::POINT_ARRAY, 0, ##__VA_ARGS__)
+ SOCKET_DEFINE( \
+ name, ui_name, default_value, array<float3>, SocketType::POINT_ARRAY, 0, ##__VA_ARGS__)
#define SOCKET_NORMAL_ARRAY(name, ui_name, default_value, ...) \
- SOCKET_DEFINE(name, ui_name, default_value, array<float3>, SocketType::NORMAL_ARRAY, 0, ##__VA_ARGS__)
+ SOCKET_DEFINE( \
+ name, ui_name, default_value, array<float3>, SocketType::NORMAL_ARRAY, 0, ##__VA_ARGS__)
#define SOCKET_POINT2_ARRAY(name, ui_name, default_value, ...) \
- SOCKET_DEFINE(name, ui_name, default_value, array<float2>, SocketType::POINT2_ARRAY, 0, ##__VA_ARGS__)
+ SOCKET_DEFINE( \
+ name, ui_name, default_value, array<float2>, SocketType::POINT2_ARRAY, 0, ##__VA_ARGS__)
#define SOCKET_STRING_ARRAY(name, ui_name, default_value, ...) \
- SOCKET_DEFINE(name, ui_name, default_value, array<ustring>, SocketType::STRING_ARRAY, 0, ##__VA_ARGS__)
+ SOCKET_DEFINE( \
+ name, ui_name, default_value, array<ustring>, SocketType::STRING_ARRAY, 0, ##__VA_ARGS__)
#define SOCKET_TRANSFORM_ARRAY(name, ui_name, default_value, ...) \
- SOCKET_DEFINE(name, ui_name, default_value, array<Transform>, SocketType::TRANSFORM_ARRAY, 0, ##__VA_ARGS__)
+ SOCKET_DEFINE(name, \
+ ui_name, \
+ default_value, \
+ array<Transform>, \
+ SocketType::TRANSFORM_ARRAY, \
+ 0, \
+ ##__VA_ARGS__)
#define SOCKET_NODE_ARRAY(name, ui_name, node_type, ...) \
- { \
- static Node *defval = NULL; \
- assert(SOCKET_SIZEOF(T, name) == sizeof(Node*)); \
- type->register_input(ustring(#name), ustring(ui_name), SocketType::NODE_ARRAY, SOCKET_OFFSETOF(T, name), &defval, NULL, node_type, ##__VA_ARGS__); \
- }
+ { \
+ static Node *defval = NULL; \
+ assert(SOCKET_SIZEOF(T, name) == sizeof(Node *)); \
+ type->register_input(ustring(#name), \
+ ustring(ui_name), \
+ SocketType::NODE_ARRAY, \
+ SOCKET_OFFSETOF(T, name), \
+ &defval, \
+ NULL, \
+ node_type, \
+ ##__VA_ARGS__); \
+ }
#define SOCKET_IN_BOOLEAN(name, ui_name, default_value, ...) \
- SOCKET_DEFINE(name, ui_name, default_value, bool, SocketType::BOOLEAN, SocketType::LINKABLE, ##__VA_ARGS__)
+ SOCKET_DEFINE(name, \
+ ui_name, \
+ default_value, \
+ bool, \
+ SocketType::BOOLEAN, \
+ SocketType::LINKABLE, \
+ ##__VA_ARGS__)
#define SOCKET_IN_INT(name, ui_name, default_value, ...) \
- SOCKET_DEFINE(name, ui_name, default_value, int, SocketType::INT, SocketType::LINKABLE, ##__VA_ARGS__)
+ SOCKET_DEFINE( \
+ name, ui_name, default_value, int, SocketType::INT, SocketType::LINKABLE, ##__VA_ARGS__)
#define SOCKET_IN_FLOAT(name, ui_name, default_value, ...) \
- SOCKET_DEFINE(name, ui_name, default_value, float, SocketType::FLOAT, SocketType::LINKABLE, ##__VA_ARGS__)
+ SOCKET_DEFINE(name, \
+ ui_name, \
+ default_value, \
+ float, \
+ SocketType::FLOAT, \
+ SocketType::LINKABLE, \
+ ##__VA_ARGS__)
#define SOCKET_IN_COLOR(name, ui_name, default_value, ...) \
- SOCKET_DEFINE(name, ui_name, default_value, float3, SocketType::COLOR, SocketType::LINKABLE, ##__VA_ARGS__)
+ SOCKET_DEFINE(name, \
+ ui_name, \
+ default_value, \
+ float3, \
+ SocketType::COLOR, \
+ SocketType::LINKABLE, \
+ ##__VA_ARGS__)
#define SOCKET_IN_VECTOR(name, ui_name, default_value, ...) \
- SOCKET_DEFINE(name, ui_name, default_value, float3, SocketType::VECTOR, SocketType::LINKABLE, ##__VA_ARGS__)
+ SOCKET_DEFINE(name, \
+ ui_name, \
+ default_value, \
+ float3, \
+ SocketType::VECTOR, \
+ SocketType::LINKABLE, \
+ ##__VA_ARGS__)
#define SOCKET_IN_POINT(name, ui_name, default_value, ...) \
- SOCKET_DEFINE(name, ui_name, default_value, float3, SocketType::POINT, SocketType::LINKABLE, ##__VA_ARGS__)
+ SOCKET_DEFINE(name, \
+ ui_name, \
+ default_value, \
+ float3, \
+ SocketType::POINT, \
+ SocketType::LINKABLE, \
+ ##__VA_ARGS__)
#define SOCKET_IN_NORMAL(name, ui_name, default_value, ...) \
- SOCKET_DEFINE(name, ui_name, default_value, float3, SocketType::NORMAL, SocketType::LINKABLE, ##__VA_ARGS__)
+ SOCKET_DEFINE(name, \
+ ui_name, \
+ default_value, \
+ float3, \
+ SocketType::NORMAL, \
+ SocketType::LINKABLE, \
+ ##__VA_ARGS__)
#define SOCKET_IN_STRING(name, ui_name, default_value, ...) \
- SOCKET_DEFINE(name, ui_name, default_value, ustring, SocketType::STRING, SocketType::LINKABLE, ##__VA_ARGS__)
+ SOCKET_DEFINE(name, \
+ ui_name, \
+ default_value, \
+ ustring, \
+ SocketType::STRING, \
+ SocketType::LINKABLE, \
+ ##__VA_ARGS__)
#define SOCKET_IN_CLOSURE(name, ui_name, ...) \
- type->register_input(ustring(#name), ustring(ui_name), SocketType::CLOSURE, 0, NULL, NULL, NULL, SocketType::LINKABLE, ##__VA_ARGS__)
+ type->register_input(ustring(#name), \
+ ustring(ui_name), \
+ SocketType::CLOSURE, \
+ 0, \
+ NULL, \
+ NULL, \
+ NULL, \
+ SocketType::LINKABLE, \
+ ##__VA_ARGS__)
#define SOCKET_OUT_BOOLEAN(name, ui_name) \
- { type->register_output(ustring(#name), ustring(ui_name), SocketType::BOOLEAN); }
+ { \
+ type->register_output(ustring(#name), ustring(ui_name), SocketType::BOOLEAN); \
+ }
#define SOCKET_OUT_INT(name, ui_name) \
- { type->register_output(ustring(#name), ustring(ui_name), SocketType::INT); }
+ { \
+ type->register_output(ustring(#name), ustring(ui_name), SocketType::INT); \
+ }
#define SOCKET_OUT_FLOAT(name, ui_name) \
- { type->register_output(ustring(#name), ustring(ui_name), SocketType::FLOAT); }
+ { \
+ type->register_output(ustring(#name), ustring(ui_name), SocketType::FLOAT); \
+ }
#define SOCKET_OUT_COLOR(name, ui_name) \
- { type->register_output(ustring(#name), ustring(ui_name), SocketType::COLOR); }
+ { \
+ type->register_output(ustring(#name), ustring(ui_name), SocketType::COLOR); \
+ }
#define SOCKET_OUT_VECTOR(name, ui_name) \
- { type->register_output(ustring(#name), ustring(ui_name), SocketType::VECTOR); }
+ { \
+ type->register_output(ustring(#name), ustring(ui_name), SocketType::VECTOR); \
+ }
#define SOCKET_OUT_POINT(name, ui_name) \
- { type->register_output(ustring(#name), ustring(ui_name), SocketType::POINT); }
+ { \
+ type->register_output(ustring(#name), ustring(ui_name), SocketType::POINT); \
+ }
#define SOCKET_OUT_NORMAL(name, ui_name) \
- { type->register_output(ustring(#name), ustring(ui_name), SocketType::NORMAL); }
+ { \
+ type->register_output(ustring(#name), ustring(ui_name), SocketType::NORMAL); \
+ }
#define SOCKET_OUT_CLOSURE(name, ui_name) \
- { type->register_output(ustring(#name), ustring(ui_name), SocketType::CLOSURE); }
+ { \
+ type->register_output(ustring(#name), ustring(ui_name), SocketType::CLOSURE); \
+ }
#define SOCKET_OUT_STRING(name, ui_name) \
- { type->register_output(ustring(#name), ustring(ui_name), SocketType::STRING); }
+ { \
+ type->register_output(ustring(#name), ustring(ui_name), SocketType::STRING); \
+ }
#define SOCKET_OUT_ENUM(name, ui_name) \
- { type->register_output(ustring(#name), ustring(ui_name), SocketType::ENUM); }
+ { \
+ type->register_output(ustring(#name), ustring(ui_name), SocketType::ENUM); \
+ }
CCL_NAMESPACE_END
diff --git a/intern/cycles/graph/node_xml.cpp b/intern/cycles/graph/node_xml.cpp
index f228da282e9..a96970cc904 100644
--- a/intern/cycles/graph/node_xml.cpp
+++ b/intern/cycles/graph/node_xml.cpp
@@ -24,437 +24,409 @@ CCL_NAMESPACE_BEGIN
static bool xml_read_boolean(const char *value)
{
- return string_iequals(value, "true") || (atoi(value) != 0);
+ return string_iequals(value, "true") || (atoi(value) != 0);
}
static const char *xml_write_boolean(bool value)
{
- return (value) ? "true" : "false";
+ return (value) ? "true" : "false";
}
template<int VECTOR_SIZE, typename T>
-static void xml_read_float_array(T& value, xml_attribute attr)
+static void xml_read_float_array(T &value, xml_attribute attr)
{
- vector<string> tokens;
- string_split(tokens, attr.value());
+ vector<string> tokens;
+ string_split(tokens, attr.value());
- if(tokens.size() % VECTOR_SIZE != 0) {
- return;
- }
+ if (tokens.size() % VECTOR_SIZE != 0) {
+ return;
+ }
- value.resize(tokens.size() / VECTOR_SIZE);
- for(size_t i = 0; i < value.size(); i++) {
- float *value_float = (float*)&value[i];
+ value.resize(tokens.size() / VECTOR_SIZE);
+ for (size_t i = 0; i < value.size(); i++) {
+ float *value_float = (float *)&value[i];
- for(size_t j = 0; j < VECTOR_SIZE; j++)
- value_float[j] = (float)atof(tokens[i * VECTOR_SIZE + j].c_str());
- }
+ for (size_t j = 0; j < VECTOR_SIZE; j++)
+ value_float[j] = (float)atof(tokens[i * VECTOR_SIZE + j].c_str());
+ }
}
-void xml_read_node(XMLReader& reader, Node *node, xml_node xml_node)
+void xml_read_node(XMLReader &reader, Node *node, xml_node xml_node)
{
- xml_attribute name_attr = xml_node.attribute("name");
- if(name_attr) {
- node->name = ustring(name_attr.value());
- }
+ xml_attribute name_attr = xml_node.attribute("name");
+ if (name_attr) {
+ node->name = ustring(name_attr.value());
+ }
- foreach(const SocketType& socket, node->type->inputs) {
- if(socket.type == SocketType::CLOSURE || socket.type == SocketType::UNDEFINED) {
- continue;
- }
- if(socket.flags & SocketType::INTERNAL) {
- continue;
- }
+ foreach (const SocketType &socket, node->type->inputs) {
+ if (socket.type == SocketType::CLOSURE || socket.type == SocketType::UNDEFINED) {
+ continue;
+ }
+ if (socket.flags & SocketType::INTERNAL) {
+ continue;
+ }
- xml_attribute attr = xml_node.attribute(socket.name.c_str());
+ xml_attribute attr = xml_node.attribute(socket.name.c_str());
- if(!attr) {
- continue;
- }
+ if (!attr) {
+ continue;
+ }
- switch(socket.type)
- {
- case SocketType::BOOLEAN:
- {
- node->set(socket, xml_read_boolean(attr.value()));
- break;
- }
- case SocketType::BOOLEAN_ARRAY:
- {
- vector<string> tokens;
- string_split(tokens, attr.value());
+ switch (socket.type) {
+ case SocketType::BOOLEAN: {
+ node->set(socket, xml_read_boolean(attr.value()));
+ break;
+ }
+ case SocketType::BOOLEAN_ARRAY: {
+ vector<string> tokens;
+ string_split(tokens, attr.value());
- array<bool> value;
- value.resize(tokens.size());
- for(size_t i = 0; i < value.size(); i++)
- value[i] = xml_read_boolean(tokens[i].c_str());
- node->set(socket, value);
- break;
- }
- case SocketType::FLOAT:
- {
- node->set(socket, (float)atof(attr.value()));
- break;
- }
- case SocketType::FLOAT_ARRAY:
- {
- array<float> value;
- xml_read_float_array<1>(value, attr);
- node->set(socket, value);
- break;
- }
- case SocketType::INT:
- {
- node->set(socket, (int)atoi(attr.value()));
- break;
- }
- case SocketType::UINT:
- {
- node->set(socket, (uint)atoi(attr.value()));
- break;
- }
- case SocketType::INT_ARRAY:
- {
- vector<string> tokens;
- string_split(tokens, attr.value());
+ array<bool> value;
+ value.resize(tokens.size());
+ for (size_t i = 0; i < value.size(); i++)
+ value[i] = xml_read_boolean(tokens[i].c_str());
+ node->set(socket, value);
+ break;
+ }
+ case SocketType::FLOAT: {
+ node->set(socket, (float)atof(attr.value()));
+ break;
+ }
+ case SocketType::FLOAT_ARRAY: {
+ array<float> value;
+ xml_read_float_array<1>(value, attr);
+ node->set(socket, value);
+ break;
+ }
+ case SocketType::INT: {
+ node->set(socket, (int)atoi(attr.value()));
+ break;
+ }
+ case SocketType::UINT: {
+ node->set(socket, (uint)atoi(attr.value()));
+ break;
+ }
+ case SocketType::INT_ARRAY: {
+ vector<string> tokens;
+ string_split(tokens, attr.value());
- array<int> value;
- value.resize(tokens.size());
- for(size_t i = 0; i < value.size(); i++) {
- value[i] = (int)atoi(attr.value());
- }
- node->set(socket, value);
- break;
- }
- case SocketType::COLOR:
- case SocketType::VECTOR:
- case SocketType::POINT:
- case SocketType::NORMAL:
- {
- array<float3> value;
- xml_read_float_array<3>(value, attr);
- if(value.size() == 1) {
- node->set(socket, value[0]);
- }
- break;
- }
- case SocketType::COLOR_ARRAY:
- case SocketType::VECTOR_ARRAY:
- case SocketType::POINT_ARRAY:
- case SocketType::NORMAL_ARRAY:
- {
- array<float3> value;
- xml_read_float_array<3>(value, attr);
- node->set(socket, value);
- break;
- }
- case SocketType::POINT2:
- {
- array<float2> value;
- xml_read_float_array<2>(value, attr);
- if(value.size() == 1) {
- node->set(socket, value[0]);
- }
- break;
- }
- case SocketType::POINT2_ARRAY:
- {
- array<float2> value;
- xml_read_float_array<2>(value, attr);
- node->set(socket, value);
- break;
- }
- case SocketType::STRING:
- {
- node->set(socket, attr.value());
- break;
- }
- case SocketType::ENUM:
- {
- ustring value(attr.value());
- if(socket.enum_values->exists(value)) {
- node->set(socket, value);
- }
- else {
- fprintf(stderr, "Unknown value \"%s\" for attribute \"%s\".\n", value.c_str(), socket.name.c_str());
- }
- break;
- }
- case SocketType::STRING_ARRAY:
- {
- vector<string> tokens;
- string_split(tokens, attr.value());
+ array<int> value;
+ value.resize(tokens.size());
+ for (size_t i = 0; i < value.size(); i++) {
+ value[i] = (int)atoi(attr.value());
+ }
+ node->set(socket, value);
+ break;
+ }
+ case SocketType::COLOR:
+ case SocketType::VECTOR:
+ case SocketType::POINT:
+ case SocketType::NORMAL: {
+ array<float3> value;
+ xml_read_float_array<3>(value, attr);
+ if (value.size() == 1) {
+ node->set(socket, value[0]);
+ }
+ break;
+ }
+ case SocketType::COLOR_ARRAY:
+ case SocketType::VECTOR_ARRAY:
+ case SocketType::POINT_ARRAY:
+ case SocketType::NORMAL_ARRAY: {
+ array<float3> value;
+ xml_read_float_array<3>(value, attr);
+ node->set(socket, value);
+ break;
+ }
+ case SocketType::POINT2: {
+ array<float2> value;
+ xml_read_float_array<2>(value, attr);
+ if (value.size() == 1) {
+ node->set(socket, value[0]);
+ }
+ break;
+ }
+ case SocketType::POINT2_ARRAY: {
+ array<float2> value;
+ xml_read_float_array<2>(value, attr);
+ node->set(socket, value);
+ break;
+ }
+ case SocketType::STRING: {
+ node->set(socket, attr.value());
+ break;
+ }
+ case SocketType::ENUM: {
+ ustring value(attr.value());
+ if (socket.enum_values->exists(value)) {
+ node->set(socket, value);
+ }
+ else {
+ fprintf(stderr,
+ "Unknown value \"%s\" for attribute \"%s\".\n",
+ value.c_str(),
+ socket.name.c_str());
+ }
+ break;
+ }
+ case SocketType::STRING_ARRAY: {
+ vector<string> tokens;
+ string_split(tokens, attr.value());
- array<ustring> value;
- value.resize(tokens.size());
- for(size_t i = 0; i < value.size(); i++) {
- value[i] = ustring(tokens[i]);
- }
- node->set(socket, value);
- break;
- }
- case SocketType::TRANSFORM:
- {
- array<Transform> value;
- xml_read_float_array<12>(value, attr);
- if(value.size() == 1) {
- node->set(socket, value[0]);
- }
- break;
- }
- case SocketType::TRANSFORM_ARRAY:
- {
- array<Transform> value;
- xml_read_float_array<12>(value, attr);
- node->set(socket, value);
- break;
- }
- case SocketType::NODE:
- {
- ustring value(attr.value());
- map<ustring, Node*>::iterator it = reader.node_map.find(value);
- if(it != reader.node_map.end())
- {
- Node *value_node = it->second;
- if(value_node->type == *(socket.node_type))
- node->set(socket, it->second);
- }
- break;
- }
- case SocketType::NODE_ARRAY:
- {
- vector<string> tokens;
- string_split(tokens, attr.value());
+ array<ustring> value;
+ value.resize(tokens.size());
+ for (size_t i = 0; i < value.size(); i++) {
+ value[i] = ustring(tokens[i]);
+ }
+ node->set(socket, value);
+ break;
+ }
+ case SocketType::TRANSFORM: {
+ array<Transform> value;
+ xml_read_float_array<12>(value, attr);
+ if (value.size() == 1) {
+ node->set(socket, value[0]);
+ }
+ break;
+ }
+ case SocketType::TRANSFORM_ARRAY: {
+ array<Transform> value;
+ xml_read_float_array<12>(value, attr);
+ node->set(socket, value);
+ break;
+ }
+ case SocketType::NODE: {
+ ustring value(attr.value());
+ map<ustring, Node *>::iterator it = reader.node_map.find(value);
+ if (it != reader.node_map.end()) {
+ Node *value_node = it->second;
+ if (value_node->type == *(socket.node_type))
+ node->set(socket, it->second);
+ }
+ break;
+ }
+ case SocketType::NODE_ARRAY: {
+ vector<string> tokens;
+ string_split(tokens, attr.value());
- array<Node*> value;
- value.resize(tokens.size());
- for(size_t i = 0; i < value.size(); i++)
- {
- map<ustring, Node*>::iterator it = reader.node_map.find(ustring(tokens[i]));
- if(it != reader.node_map.end())
- {
- Node *value_node = it->second;
- value[i] = (value_node->type == *(socket.node_type)) ? value_node : NULL;
- }
- else
- {
- value[i] = NULL;
- }
- }
- node->set(socket, value);
- break;
- }
- case SocketType::CLOSURE:
- case SocketType::UNDEFINED:
- break;
- }
- }
+ array<Node *> value;
+ value.resize(tokens.size());
+ for (size_t i = 0; i < value.size(); i++) {
+ map<ustring, Node *>::iterator it = reader.node_map.find(ustring(tokens[i]));
+ if (it != reader.node_map.end()) {
+ Node *value_node = it->second;
+ value[i] = (value_node->type == *(socket.node_type)) ? value_node : NULL;
+ }
+ else {
+ value[i] = NULL;
+ }
+ }
+ node->set(socket, value);
+ break;
+ }
+ case SocketType::CLOSURE:
+ case SocketType::UNDEFINED:
+ break;
+ }
+ }
- if(!node->name.empty())
- reader.node_map[node->name] = node;
+ if (!node->name.empty())
+ reader.node_map[node->name] = node;
}
xml_node xml_write_node(Node *node, xml_node xml_root)
{
- xml_node xml_node = xml_root.append_child(node->type->name.c_str());
+ xml_node xml_node = xml_root.append_child(node->type->name.c_str());
- xml_node.append_attribute("name") = node->name.c_str();
+ xml_node.append_attribute("name") = node->name.c_str();
- foreach(const SocketType& socket, node->type->inputs) {
- if(socket.type == SocketType::CLOSURE || socket.type == SocketType::UNDEFINED) {
- continue;
- }
- if(socket.flags & SocketType::INTERNAL) {
- continue;
- }
- if(node->has_default_value(socket)) {
- continue;
- }
+ foreach (const SocketType &socket, node->type->inputs) {
+ if (socket.type == SocketType::CLOSURE || socket.type == SocketType::UNDEFINED) {
+ continue;
+ }
+ if (socket.flags & SocketType::INTERNAL) {
+ continue;
+ }
+ if (node->has_default_value(socket)) {
+ continue;
+ }
- xml_attribute attr = xml_node.append_attribute(socket.name.c_str());
+ xml_attribute attr = xml_node.append_attribute(socket.name.c_str());
- switch(socket.type)
- {
- case SocketType::BOOLEAN:
- {
- attr = xml_write_boolean(node->get_bool(socket));
- break;
- }
- case SocketType::BOOLEAN_ARRAY:
- {
- std::stringstream ss;
- const array<bool>& value = node->get_bool_array(socket);
- for(size_t i = 0; i < value.size(); i++) {
- ss << xml_write_boolean(value[i]);
- if(i != value.size() - 1)
- ss << " ";
- }
- attr = ss.str().c_str();
- break;
- }
- case SocketType::FLOAT:
- {
- attr = (double)node->get_float(socket);
- break;
- }
- case SocketType::FLOAT_ARRAY:
- {
- std::stringstream ss;
- const array<float>& value = node->get_float_array(socket);
- for(size_t i = 0; i < value.size(); i++) {
- ss << value[i];
- if(i != value.size() - 1) {
- ss << " ";
- }
- }
- attr = ss.str().c_str();
- break;
- }
- case SocketType::INT:
- {
- attr = node->get_int(socket);
- break;
- }
- case SocketType::UINT:
- {
- attr = node->get_uint(socket);
- break;
- }
- case SocketType::INT_ARRAY:
- {
- std::stringstream ss;
- const array<int>& value = node->get_int_array(socket);
- for(size_t i = 0; i < value.size(); i++) {
- ss << value[i];
- if(i != value.size() - 1) {
- ss << " ";
- }
- }
- attr = ss.str().c_str();
- break;
- }
- case SocketType::COLOR:
- case SocketType::VECTOR:
- case SocketType::POINT:
- case SocketType::NORMAL:
- {
- float3 value = node->get_float3(socket);
- attr = string_printf("%g %g %g", (double)value.x, (double)value.y, (double)value.z).c_str();
- break;
- }
- case SocketType::COLOR_ARRAY:
- case SocketType::VECTOR_ARRAY:
- case SocketType::POINT_ARRAY:
- case SocketType::NORMAL_ARRAY:
- {
- std::stringstream ss;
- const array<float3>& value = node->get_float3_array(socket);
- for(size_t i = 0; i < value.size(); i++) {
- ss << string_printf("%g %g %g", (double)value[i].x, (double)value[i].y, (double)value[i].z);
- if(i != value.size() - 1) {
- ss << " ";
- }
- }
- attr = ss.str().c_str();
- break;
- }
- case SocketType::POINT2:
- {
- float2 value = node->get_float2(socket);
- attr = string_printf("%g %g", (double)value.x, (double)value.y).c_str();
- break;
- }
- case SocketType::POINT2_ARRAY:
- {
- std::stringstream ss;
- const array<float2>& value = node->get_float2_array(socket);
- for(size_t i = 0; i < value.size(); i++) {
- ss << string_printf("%g %g", (double)value[i].x, (double)value[i].y);
- if(i != value.size() - 1) {
- ss << " ";
- }
- }
- attr = ss.str().c_str();
- break;
- }
- case SocketType::STRING:
- case SocketType::ENUM:
- {
- attr = node->get_string(socket).c_str();
- break;
- }
- case SocketType::STRING_ARRAY:
- {
- std::stringstream ss;
- const array<ustring>& value = node->get_string_array(socket);
- for(size_t i = 0; i < value.size(); i++) {
- ss << value[i];
- if(i != value.size() - 1) {
- ss << " ";
- }
- }
- attr = ss.str().c_str();
- break;
- }
- case SocketType::TRANSFORM:
- {
- Transform tfm = node->get_transform(socket);
- std::stringstream ss;
- for(int i = 0; i < 3; i++) {
- ss << string_printf("%g %g %g %g ", (double)tfm[i][0], (double)tfm[i][1], (double)tfm[i][2], (double)tfm[i][3]);
- }
- ss << string_printf("%g %g %g %g", 0.0, 0.0, 0.0, 1.0);
- attr = ss.str().c_str();
- break;
- }
- case SocketType::TRANSFORM_ARRAY:
- {
- std::stringstream ss;
- const array<Transform>& value = node->get_transform_array(socket);
- for(size_t j = 0; j < value.size(); j++) {
- const Transform& tfm = value[j];
+ switch (socket.type) {
+ case SocketType::BOOLEAN: {
+ attr = xml_write_boolean(node->get_bool(socket));
+ break;
+ }
+ case SocketType::BOOLEAN_ARRAY: {
+ std::stringstream ss;
+ const array<bool> &value = node->get_bool_array(socket);
+ for (size_t i = 0; i < value.size(); i++) {
+ ss << xml_write_boolean(value[i]);
+ if (i != value.size() - 1)
+ ss << " ";
+ }
+ attr = ss.str().c_str();
+ break;
+ }
+ case SocketType::FLOAT: {
+ attr = (double)node->get_float(socket);
+ break;
+ }
+ case SocketType::FLOAT_ARRAY: {
+ std::stringstream ss;
+ const array<float> &value = node->get_float_array(socket);
+ for (size_t i = 0; i < value.size(); i++) {
+ ss << value[i];
+ if (i != value.size() - 1) {
+ ss << " ";
+ }
+ }
+ attr = ss.str().c_str();
+ break;
+ }
+ case SocketType::INT: {
+ attr = node->get_int(socket);
+ break;
+ }
+ case SocketType::UINT: {
+ attr = node->get_uint(socket);
+ break;
+ }
+ case SocketType::INT_ARRAY: {
+ std::stringstream ss;
+ const array<int> &value = node->get_int_array(socket);
+ for (size_t i = 0; i < value.size(); i++) {
+ ss << value[i];
+ if (i != value.size() - 1) {
+ ss << " ";
+ }
+ }
+ attr = ss.str().c_str();
+ break;
+ }
+ case SocketType::COLOR:
+ case SocketType::VECTOR:
+ case SocketType::POINT:
+ case SocketType::NORMAL: {
+ float3 value = node->get_float3(socket);
+ attr =
+ string_printf("%g %g %g", (double)value.x, (double)value.y, (double)value.z).c_str();
+ break;
+ }
+ case SocketType::COLOR_ARRAY:
+ case SocketType::VECTOR_ARRAY:
+ case SocketType::POINT_ARRAY:
+ case SocketType::NORMAL_ARRAY: {
+ std::stringstream ss;
+ const array<float3> &value = node->get_float3_array(socket);
+ for (size_t i = 0; i < value.size(); i++) {
+ ss << string_printf(
+ "%g %g %g", (double)value[i].x, (double)value[i].y, (double)value[i].z);
+ if (i != value.size() - 1) {
+ ss << " ";
+ }
+ }
+ attr = ss.str().c_str();
+ break;
+ }
+ case SocketType::POINT2: {
+ float2 value = node->get_float2(socket);
+ attr = string_printf("%g %g", (double)value.x, (double)value.y).c_str();
+ break;
+ }
+ case SocketType::POINT2_ARRAY: {
+ std::stringstream ss;
+ const array<float2> &value = node->get_float2_array(socket);
+ for (size_t i = 0; i < value.size(); i++) {
+ ss << string_printf("%g %g", (double)value[i].x, (double)value[i].y);
+ if (i != value.size() - 1) {
+ ss << " ";
+ }
+ }
+ attr = ss.str().c_str();
+ break;
+ }
+ case SocketType::STRING:
+ case SocketType::ENUM: {
+ attr = node->get_string(socket).c_str();
+ break;
+ }
+ case SocketType::STRING_ARRAY: {
+ std::stringstream ss;
+ const array<ustring> &value = node->get_string_array(socket);
+ for (size_t i = 0; i < value.size(); i++) {
+ ss << value[i];
+ if (i != value.size() - 1) {
+ ss << " ";
+ }
+ }
+ attr = ss.str().c_str();
+ break;
+ }
+ case SocketType::TRANSFORM: {
+ Transform tfm = node->get_transform(socket);
+ std::stringstream ss;
+ for (int i = 0; i < 3; i++) {
+ ss << string_printf("%g %g %g %g ",
+ (double)tfm[i][0],
+ (double)tfm[i][1],
+ (double)tfm[i][2],
+ (double)tfm[i][3]);
+ }
+ ss << string_printf("%g %g %g %g", 0.0, 0.0, 0.0, 1.0);
+ attr = ss.str().c_str();
+ break;
+ }
+ case SocketType::TRANSFORM_ARRAY: {
+ std::stringstream ss;
+ const array<Transform> &value = node->get_transform_array(socket);
+ for (size_t j = 0; j < value.size(); j++) {
+ const Transform &tfm = value[j];
- for(int i = 0; i < 3; i++) {
- ss << string_printf("%g %g %g %g ", (double)tfm[i][0], (double)tfm[i][1], (double)tfm[i][2], (double)tfm[i][3]);
- }
- ss << string_printf("%g %g %g %g", 0.0, 0.0, 0.0, 1.0);
- if(j != value.size() - 1) {
- ss << " ";
- }
- }
- attr = ss.str().c_str();
- break;
- }
- case SocketType::NODE:
- {
- Node *value = node->get_node(socket);
- if(value) {
- attr = value->name.c_str();
- }
- break;
- }
- case SocketType::NODE_ARRAY:
- {
- std::stringstream ss;
- const array<Node*>& value = node->get_node_array(socket);
- for(size_t i = 0; i < value.size(); i++) {
- if(value[i]) {
- ss << value[i]->name.c_str();
- }
- if(i != value.size() - 1) {
- ss << " ";
- }
- }
- attr = ss.str().c_str();
- break;
- }
- case SocketType::CLOSURE:
- case SocketType::UNDEFINED:
- break;
- }
- }
+ for (int i = 0; i < 3; i++) {
+ ss << string_printf("%g %g %g %g ",
+ (double)tfm[i][0],
+ (double)tfm[i][1],
+ (double)tfm[i][2],
+ (double)tfm[i][3]);
+ }
+ ss << string_printf("%g %g %g %g", 0.0, 0.0, 0.0, 1.0);
+ if (j != value.size() - 1) {
+ ss << " ";
+ }
+ }
+ attr = ss.str().c_str();
+ break;
+ }
+ case SocketType::NODE: {
+ Node *value = node->get_node(socket);
+ if (value) {
+ attr = value->name.c_str();
+ }
+ break;
+ }
+ case SocketType::NODE_ARRAY: {
+ std::stringstream ss;
+ const array<Node *> &value = node->get_node_array(socket);
+ for (size_t i = 0; i < value.size(); i++) {
+ if (value[i]) {
+ ss << value[i]->name.c_str();
+ }
+ if (i != value.size() - 1) {
+ ss << " ";
+ }
+ }
+ attr = ss.str().c_str();
+ break;
+ }
+ case SocketType::CLOSURE:
+ case SocketType::UNDEFINED:
+ break;
+ }
+ }
- return xml_node;
+ return xml_node;
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/graph/node_xml.h b/intern/cycles/graph/node_xml.h
index 5fecf40f96c..15bbf5d5621 100644
--- a/intern/cycles/graph/node_xml.h
+++ b/intern/cycles/graph/node_xml.h
@@ -25,10 +25,10 @@
CCL_NAMESPACE_BEGIN
struct XMLReader {
- map<ustring, Node*> node_map;
+ map<ustring, Node *> node_map;
};
-void xml_read_node(XMLReader& reader, Node *node, xml_node xml_node);
+void xml_read_node(XMLReader &reader, Node *node, xml_node xml_node);
xml_node xml_write_node(Node *node, xml_node xml_root);
CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/CMakeLists.txt b/intern/cycles/kernel/CMakeLists.txt
index 01552dff9bb..8a8fee108ae 100644
--- a/intern/cycles/kernel/CMakeLists.txt
+++ b/intern/cycles/kernel/CMakeLists.txt
@@ -1,7 +1,7 @@
remove_extra_strict_flags()
set(INC
- ..
+ ..
)
set(INC_SYS
@@ -9,328 +9,328 @@ set(INC_SYS
)
set(SRC_CPU_KERNELS
- kernels/cpu/kernel.cpp
- kernels/cpu/kernel_sse2.cpp
- kernels/cpu/kernel_sse3.cpp
- kernels/cpu/kernel_sse41.cpp
- kernels/cpu/kernel_avx.cpp
- kernels/cpu/kernel_avx2.cpp
- kernels/cpu/kernel_split.cpp
- kernels/cpu/kernel_split_sse2.cpp
- kernels/cpu/kernel_split_sse3.cpp
- kernels/cpu/kernel_split_sse41.cpp
- kernels/cpu/kernel_split_avx.cpp
- kernels/cpu/kernel_split_avx2.cpp
- kernels/cpu/filter.cpp
- kernels/cpu/filter_sse2.cpp
- kernels/cpu/filter_sse3.cpp
- kernels/cpu/filter_sse41.cpp
- kernels/cpu/filter_avx.cpp
- kernels/cpu/filter_avx2.cpp
+ kernels/cpu/kernel.cpp
+ kernels/cpu/kernel_sse2.cpp
+ kernels/cpu/kernel_sse3.cpp
+ kernels/cpu/kernel_sse41.cpp
+ kernels/cpu/kernel_avx.cpp
+ kernels/cpu/kernel_avx2.cpp
+ kernels/cpu/kernel_split.cpp
+ kernels/cpu/kernel_split_sse2.cpp
+ kernels/cpu/kernel_split_sse3.cpp
+ kernels/cpu/kernel_split_sse41.cpp
+ kernels/cpu/kernel_split_avx.cpp
+ kernels/cpu/kernel_split_avx2.cpp
+ kernels/cpu/filter.cpp
+ kernels/cpu/filter_sse2.cpp
+ kernels/cpu/filter_sse3.cpp
+ kernels/cpu/filter_sse41.cpp
+ kernels/cpu/filter_avx.cpp
+ kernels/cpu/filter_avx2.cpp
)
set(SRC_CUDA_KERNELS
- kernels/cuda/kernel.cu
- kernels/cuda/kernel_split.cu
- kernels/cuda/filter.cu
+ kernels/cuda/kernel.cu
+ kernels/cuda/kernel_split.cu
+ kernels/cuda/filter.cu
)
set(SRC_OPENCL_KERNELS
- kernels/opencl/kernel_bake.cl
- kernels/opencl/kernel_base.cl
- kernels/opencl/kernel_displace.cl
- kernels/opencl/kernel_background.cl
- kernels/opencl/kernel_state_buffer_size.cl
- kernels/opencl/kernel_split_bundle.cl
- kernels/opencl/kernel_data_init.cl
- kernels/opencl/kernel_path_init.cl
- kernels/opencl/kernel_queue_enqueue.cl
- kernels/opencl/kernel_scene_intersect.cl
- 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
- kernels/opencl/kernel_direct_lighting.cl
- kernels/opencl/kernel_shadow_blocked_ao.cl
- kernels/opencl/kernel_shadow_blocked_dl.cl
- kernels/opencl/kernel_enqueue_inactive.cl
- kernels/opencl/kernel_next_iteration_setup.cl
- kernels/opencl/kernel_indirect_subsurface.cl
- kernels/opencl/kernel_buffer_update.cl
- kernels/opencl/filter.cl
+ kernels/opencl/kernel_bake.cl
+ kernels/opencl/kernel_base.cl
+ kernels/opencl/kernel_displace.cl
+ kernels/opencl/kernel_background.cl
+ kernels/opencl/kernel_state_buffer_size.cl
+ kernels/opencl/kernel_split_bundle.cl
+ kernels/opencl/kernel_data_init.cl
+ kernels/opencl/kernel_path_init.cl
+ kernels/opencl/kernel_queue_enqueue.cl
+ kernels/opencl/kernel_scene_intersect.cl
+ 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
+ kernels/opencl/kernel_direct_lighting.cl
+ kernels/opencl/kernel_shadow_blocked_ao.cl
+ kernels/opencl/kernel_shadow_blocked_dl.cl
+ kernels/opencl/kernel_enqueue_inactive.cl
+ kernels/opencl/kernel_next_iteration_setup.cl
+ kernels/opencl/kernel_indirect_subsurface.cl
+ kernels/opencl/kernel_buffer_update.cl
+ kernels/opencl/filter.cl
)
set(SRC_BVH_HEADERS
- bvh/bvh.h
- bvh/bvh_nodes.h
- bvh/bvh_shadow_all.h
- bvh/bvh_local.h
- bvh/bvh_traversal.h
- bvh/bvh_types.h
- bvh/bvh_volume.h
- bvh/bvh_volume_all.h
- bvh/qbvh_nodes.h
- bvh/qbvh_shadow_all.h
- bvh/qbvh_local.h
- bvh/qbvh_traversal.h
- bvh/qbvh_volume.h
- bvh/qbvh_volume_all.h
- bvh/obvh_nodes.h
- bvh/obvh_shadow_all.h
- bvh/obvh_local.h
- bvh/obvh_traversal.h
- bvh/obvh_volume.h
- bvh/obvh_volume_all.h
- bvh/bvh_embree.h
+ bvh/bvh.h
+ bvh/bvh_nodes.h
+ bvh/bvh_shadow_all.h
+ bvh/bvh_local.h
+ bvh/bvh_traversal.h
+ bvh/bvh_types.h
+ bvh/bvh_volume.h
+ bvh/bvh_volume_all.h
+ bvh/qbvh_nodes.h
+ bvh/qbvh_shadow_all.h
+ bvh/qbvh_local.h
+ bvh/qbvh_traversal.h
+ bvh/qbvh_volume.h
+ bvh/qbvh_volume_all.h
+ bvh/obvh_nodes.h
+ bvh/obvh_shadow_all.h
+ bvh/obvh_local.h
+ bvh/obvh_traversal.h
+ bvh/obvh_volume.h
+ bvh/obvh_volume_all.h
+ bvh/bvh_embree.h
)
set(SRC_HEADERS
- kernel_accumulate.h
- kernel_bake.h
- kernel_camera.h
- kernel_color.h
- kernel_compat_cpu.h
- kernel_compat_cuda.h
- kernel_compat_opencl.h
- kernel_differential.h
- kernel_emission.h
- kernel_film.h
- kernel_globals.h
- kernel_id_passes.h
- kernel_jitter.h
- kernel_light.h
- kernel_math.h
- kernel_montecarlo.h
- kernel_passes.h
- kernel_path.h
- kernel_path_branched.h
- kernel_path_common.h
- kernel_path_state.h
- kernel_path_surface.h
- kernel_path_subsurface.h
- kernel_path_volume.h
- kernel_profiling.h
- kernel_projection.h
- kernel_queues.h
- kernel_random.h
- kernel_shader.h
- kernel_shadow.h
- kernel_subsurface.h
- kernel_textures.h
- kernel_types.h
- kernel_volume.h
- kernel_work_stealing.h
+ kernel_accumulate.h
+ kernel_bake.h
+ kernel_camera.h
+ kernel_color.h
+ kernel_compat_cpu.h
+ kernel_compat_cuda.h
+ kernel_compat_opencl.h
+ kernel_differential.h
+ kernel_emission.h
+ kernel_film.h
+ kernel_globals.h
+ kernel_id_passes.h
+ kernel_jitter.h
+ kernel_light.h
+ kernel_math.h
+ kernel_montecarlo.h
+ kernel_passes.h
+ kernel_path.h
+ kernel_path_branched.h
+ kernel_path_common.h
+ kernel_path_state.h
+ kernel_path_surface.h
+ kernel_path_subsurface.h
+ kernel_path_volume.h
+ kernel_profiling.h
+ kernel_projection.h
+ kernel_queues.h
+ kernel_random.h
+ kernel_shader.h
+ kernel_shadow.h
+ kernel_subsurface.h
+ kernel_textures.h
+ kernel_types.h
+ kernel_volume.h
+ kernel_work_stealing.h
)
set(SRC_KERNELS_CPU_HEADERS
- kernel.h
- kernels/cpu/kernel_cpu.h
- kernels/cpu/kernel_cpu_impl.h
- kernels/cpu/kernel_cpu_image.h
- kernels/cpu/filter_cpu.h
- kernels/cpu/filter_cpu_impl.h
+ kernel.h
+ kernels/cpu/kernel_cpu.h
+ kernels/cpu/kernel_cpu_impl.h
+ kernels/cpu/kernel_cpu_image.h
+ kernels/cpu/filter_cpu.h
+ kernels/cpu/filter_cpu_impl.h
)
set(SRC_KERNELS_CUDA_HEADERS
- kernels/cuda/kernel_config.h
- kernels/cuda/kernel_cuda_image.h
+ kernels/cuda/kernel_config.h
+ kernels/cuda/kernel_cuda_image.h
)
set(SRC_KERNELS_OPENCL_HEADERS
- kernels/opencl/kernel_split_function.h
- kernels/opencl/kernel_opencl_image.h
+ kernels/opencl/kernel_split_function.h
+ kernels/opencl/kernel_opencl_image.h
)
set(SRC_CLOSURE_HEADERS
- closure/alloc.h
- closure/bsdf.h
- closure/bsdf_ashikhmin_velvet.h
- closure/bsdf_diffuse.h
- closure/bsdf_diffuse_ramp.h
- closure/bsdf_microfacet.h
- closure/bsdf_microfacet_multi.h
- closure/bsdf_microfacet_multi_impl.h
- closure/bsdf_oren_nayar.h
- closure/bsdf_phong_ramp.h
- closure/bsdf_reflection.h
- closure/bsdf_refraction.h
- closure/bsdf_toon.h
- closure/bsdf_transparent.h
- closure/bsdf_util.h
- closure/bsdf_ashikhmin_shirley.h
- closure/bsdf_hair.h
- closure/bssrdf.h
- closure/emissive.h
- closure/volume.h
- closure/bsdf_principled_diffuse.h
- closure/bsdf_principled_sheen.h
+ closure/alloc.h
+ closure/bsdf.h
+ closure/bsdf_ashikhmin_velvet.h
+ closure/bsdf_diffuse.h
+ closure/bsdf_diffuse_ramp.h
+ closure/bsdf_microfacet.h
+ closure/bsdf_microfacet_multi.h
+ closure/bsdf_microfacet_multi_impl.h
+ closure/bsdf_oren_nayar.h
+ closure/bsdf_phong_ramp.h
+ closure/bsdf_reflection.h
+ closure/bsdf_refraction.h
+ closure/bsdf_toon.h
+ closure/bsdf_transparent.h
+ closure/bsdf_util.h
+ closure/bsdf_ashikhmin_shirley.h
+ closure/bsdf_hair.h
+ closure/bssrdf.h
+ closure/emissive.h
+ closure/volume.h
+ closure/bsdf_principled_diffuse.h
+ closure/bsdf_principled_sheen.h
closure/bsdf_hair_principled.h
)
set(SRC_SVM_HEADERS
- svm/svm.h
- svm/svm_ao.h
- svm/svm_attribute.h
- svm/svm_bevel.h
- svm/svm_blackbody.h
- svm/svm_bump.h
- svm/svm_camera.h
- svm/svm_closure.h
- svm/svm_convert.h
- svm/svm_checker.h
- svm/svm_color_util.h
- svm/svm_brick.h
- svm/svm_displace.h
- svm/svm_fresnel.h
- svm/svm_wireframe.h
- svm/svm_wavelength.h
- svm/svm_gamma.h
- svm/svm_brightness.h
- svm/svm_geometry.h
- svm/svm_gradient.h
- svm/svm_hsv.h
- svm/svm_ies.h
- svm/svm_image.h
- svm/svm_invert.h
- svm/svm_light_path.h
- svm/svm_magic.h
- svm/svm_mapping.h
- svm/svm_math.h
- svm/svm_math_util.h
- svm/svm_mix.h
- svm/svm_musgrave.h
- svm/svm_noise.h
- svm/svm_noisetex.h
- svm/svm_normal.h
- svm/svm_ramp.h
- svm/svm_ramp_util.h
- svm/svm_sepcomb_hsv.h
- svm/svm_sepcomb_vector.h
- svm/svm_sky.h
- svm/svm_tex_coord.h
- svm/svm_texture.h
- svm/svm_types.h
- svm/svm_value.h
- svm/svm_vector_transform.h
- svm/svm_voronoi.h
- svm/svm_voxel.h
- svm/svm_wave.h
+ svm/svm.h
+ svm/svm_ao.h
+ svm/svm_attribute.h
+ svm/svm_bevel.h
+ svm/svm_blackbody.h
+ svm/svm_bump.h
+ svm/svm_camera.h
+ svm/svm_closure.h
+ svm/svm_convert.h
+ svm/svm_checker.h
+ svm/svm_color_util.h
+ svm/svm_brick.h
+ svm/svm_displace.h
+ svm/svm_fresnel.h
+ svm/svm_wireframe.h
+ svm/svm_wavelength.h
+ svm/svm_gamma.h
+ svm/svm_brightness.h
+ svm/svm_geometry.h
+ svm/svm_gradient.h
+ svm/svm_hsv.h
+ svm/svm_ies.h
+ svm/svm_image.h
+ svm/svm_invert.h
+ svm/svm_light_path.h
+ svm/svm_magic.h
+ svm/svm_mapping.h
+ svm/svm_math.h
+ svm/svm_math_util.h
+ svm/svm_mix.h
+ svm/svm_musgrave.h
+ svm/svm_noise.h
+ svm/svm_noisetex.h
+ svm/svm_normal.h
+ svm/svm_ramp.h
+ svm/svm_ramp_util.h
+ svm/svm_sepcomb_hsv.h
+ svm/svm_sepcomb_vector.h
+ svm/svm_sky.h
+ svm/svm_tex_coord.h
+ svm/svm_texture.h
+ svm/svm_types.h
+ svm/svm_value.h
+ svm/svm_vector_transform.h
+ svm/svm_voronoi.h
+ svm/svm_voxel.h
+ svm/svm_wave.h
)
set(SRC_GEOM_HEADERS
- geom/geom.h
- geom/geom_attribute.h
- geom/geom_curve.h
- geom/geom_curve_intersect.h
- geom/geom_motion_curve.h
- geom/geom_motion_triangle.h
- geom/geom_motion_triangle_intersect.h
- geom/geom_motion_triangle_shader.h
- geom/geom_object.h
- geom/geom_patch.h
- geom/geom_primitive.h
- geom/geom_subd_triangle.h
- geom/geom_triangle.h
- geom/geom_triangle_intersect.h
- geom/geom_volume.h
+ geom/geom.h
+ geom/geom_attribute.h
+ geom/geom_curve.h
+ geom/geom_curve_intersect.h
+ geom/geom_motion_curve.h
+ geom/geom_motion_triangle.h
+ geom/geom_motion_triangle_intersect.h
+ geom/geom_motion_triangle_shader.h
+ geom/geom_object.h
+ geom/geom_patch.h
+ geom/geom_primitive.h
+ geom/geom_subd_triangle.h
+ geom/geom_triangle.h
+ geom/geom_triangle_intersect.h
+ geom/geom_volume.h
)
set(SRC_FILTER_HEADERS
- filter/filter.h
- filter/filter_defines.h
- filter/filter_features.h
- filter/filter_features_sse.h
- filter/filter_kernel.h
- filter/filter_nlm_cpu.h
- filter/filter_nlm_gpu.h
- filter/filter_prefilter.h
- filter/filter_reconstruction.h
- filter/filter_transform.h
- filter/filter_transform_gpu.h
- filter/filter_transform_sse.h
+ filter/filter.h
+ filter/filter_defines.h
+ filter/filter_features.h
+ filter/filter_features_sse.h
+ filter/filter_kernel.h
+ filter/filter_nlm_cpu.h
+ filter/filter_nlm_gpu.h
+ filter/filter_prefilter.h
+ filter/filter_reconstruction.h
+ filter/filter_transform.h
+ filter/filter_transform_gpu.h
+ filter/filter_transform_sse.h
)
set(SRC_UTIL_HEADERS
- ../util/util_atomic.h
- ../util/util_color.h
- ../util/util_defines.h
- ../util/util_half.h
- ../util/util_hash.h
- ../util/util_math.h
- ../util/util_math_fast.h
- ../util/util_math_intersect.h
- ../util/util_math_float2.h
- ../util/util_math_float3.h
- ../util/util_math_float4.h
- ../util/util_math_int2.h
- ../util/util_math_int3.h
- ../util/util_math_int4.h
- ../util/util_math_matrix.h
- ../util/util_projection.h
- ../util/util_rect.h
- ../util/util_static_assert.h
- ../util/util_transform.h
- ../util/util_texture.h
- ../util/util_types.h
- ../util/util_types_float2.h
- ../util/util_types_float2_impl.h
- ../util/util_types_float3.h
- ../util/util_types_float3_impl.h
- ../util/util_types_float4.h
- ../util/util_types_float4_impl.h
- ../util/util_types_float8.h
- ../util/util_types_float8_impl.h
- ../util/util_types_int2.h
- ../util/util_types_int2_impl.h
- ../util/util_types_int3.h
- ../util/util_types_int3_impl.h
- ../util/util_types_int4.h
- ../util/util_types_int4_impl.h
- ../util/util_types_uchar2.h
- ../util/util_types_uchar2_impl.h
- ../util/util_types_uchar3.h
- ../util/util_types_uchar3_impl.h
- ../util/util_types_uchar4.h
- ../util/util_types_uchar4_impl.h
- ../util/util_types_uint2.h
- ../util/util_types_uint2_impl.h
- ../util/util_types_uint3.h
- ../util/util_types_uint3_impl.h
- ../util/util_types_uint4.h
- ../util/util_types_uint4_impl.h
- ../util/util_types_ushort4.h
- ../util/util_types_vector3.h
- ../util/util_types_vector3_impl.h
+ ../util/util_atomic.h
+ ../util/util_color.h
+ ../util/util_defines.h
+ ../util/util_half.h
+ ../util/util_hash.h
+ ../util/util_math.h
+ ../util/util_math_fast.h
+ ../util/util_math_intersect.h
+ ../util/util_math_float2.h
+ ../util/util_math_float3.h
+ ../util/util_math_float4.h
+ ../util/util_math_int2.h
+ ../util/util_math_int3.h
+ ../util/util_math_int4.h
+ ../util/util_math_matrix.h
+ ../util/util_projection.h
+ ../util/util_rect.h
+ ../util/util_static_assert.h
+ ../util/util_transform.h
+ ../util/util_texture.h
+ ../util/util_types.h
+ ../util/util_types_float2.h
+ ../util/util_types_float2_impl.h
+ ../util/util_types_float3.h
+ ../util/util_types_float3_impl.h
+ ../util/util_types_float4.h
+ ../util/util_types_float4_impl.h
+ ../util/util_types_float8.h
+ ../util/util_types_float8_impl.h
+ ../util/util_types_int2.h
+ ../util/util_types_int2_impl.h
+ ../util/util_types_int3.h
+ ../util/util_types_int3_impl.h
+ ../util/util_types_int4.h
+ ../util/util_types_int4_impl.h
+ ../util/util_types_uchar2.h
+ ../util/util_types_uchar2_impl.h
+ ../util/util_types_uchar3.h
+ ../util/util_types_uchar3_impl.h
+ ../util/util_types_uchar4.h
+ ../util/util_types_uchar4_impl.h
+ ../util/util_types_uint2.h
+ ../util/util_types_uint2_impl.h
+ ../util/util_types_uint3.h
+ ../util/util_types_uint3_impl.h
+ ../util/util_types_uint4.h
+ ../util/util_types_uint4_impl.h
+ ../util/util_types_ushort4.h
+ ../util/util_types_vector3.h
+ ../util/util_types_vector3_impl.h
)
set(SRC_SPLIT_HEADERS
- split/kernel_branched.h
- split/kernel_buffer_update.h
- split/kernel_data_init.h
- split/kernel_direct_lighting.h
- split/kernel_do_volume.h
- split/kernel_enqueue_inactive.h
- split/kernel_holdout_emission_blurring_pathtermination_ao.h
- split/kernel_indirect_background.h
- split/kernel_indirect_subsurface.h
- split/kernel_lamp_emission.h
- split/kernel_next_iteration_setup.h
- 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
- split/kernel_split_common.h
- split/kernel_split_data.h
- split/kernel_split_data_types.h
- split/kernel_subsurface_scatter.h
+ split/kernel_branched.h
+ split/kernel_buffer_update.h
+ split/kernel_data_init.h
+ split/kernel_direct_lighting.h
+ split/kernel_do_volume.h
+ split/kernel_enqueue_inactive.h
+ split/kernel_holdout_emission_blurring_pathtermination_ao.h
+ split/kernel_indirect_background.h
+ split/kernel_indirect_subsurface.h
+ split/kernel_lamp_emission.h
+ split/kernel_next_iteration_setup.h
+ 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
+ split/kernel_split_common.h
+ split/kernel_split_data.h
+ split/kernel_split_data_types.h
+ split/kernel_subsurface_scatter.h
)
set(LIB
@@ -340,145 +340,145 @@ set(LIB
# CUDA module
if(WITH_CYCLES_CUDA_BINARIES)
- # 64 bit only
- set(CUDA_BITS 64)
-
- # CUDA version
- execute_process(COMMAND ${CUDA_NVCC_EXECUTABLE} "--version" OUTPUT_VARIABLE NVCC_OUT)
- string(REGEX REPLACE ".*release ([0-9]+)\\.([0-9]+).*" "\\1" CUDA_VERSION_MAJOR "${NVCC_OUT}")
- string(REGEX REPLACE ".*release ([0-9]+)\\.([0-9]+).*" "\\2" CUDA_VERSION_MINOR "${NVCC_OUT}")
- set(CUDA_VERSION "${CUDA_VERSION_MAJOR}${CUDA_VERSION_MINOR}")
-
- # warn for other versions
- if(CUDA_VERSION MATCHES "101")
- else()
- message(WARNING
- "CUDA version ${CUDA_VERSION_MAJOR}.${CUDA_VERSION_MINOR} detected, "
- "build may succeed but only CUDA 10.1 is officially supported")
- endif()
-
- # build for each arch
- set(cuda_sources kernels/cuda/kernel.cu kernels/cuda/kernel_split.cu
- ${SRC_HEADERS}
- ${SRC_KERNELS_CUDA_HEADERS}
- ${SRC_BVH_HEADERS}
- ${SRC_SVM_HEADERS}
- ${SRC_GEOM_HEADERS}
- ${SRC_CLOSURE_HEADERS}
- ${SRC_UTIL_HEADERS}
- )
- set(cuda_filter_sources kernels/cuda/filter.cu
- ${SRC_HEADERS}
- ${SRC_KERNELS_CUDA_HEADERS}
- ${SRC_FILTER_HEADERS}
- ${SRC_UTIL_HEADERS}
- )
- set(cuda_cubins)
-
- macro(CYCLES_CUDA_KERNEL_ADD arch prev_arch name flags sources experimental)
- set(cuda_cubin ${name}_${arch}.cubin)
-
- set(kernel_sources ${sources})
- if(NOT ${prev_arch} STREQUAL "none")
- set(kernel_sources ${kernel_sources} ${name}_${prev_arch}.cubin)
- endif()
-
- set(cuda_kernel_src "/kernels/cuda/${name}.cu")
-
- set(cuda_flags
- -D CCL_NAMESPACE_BEGIN=
- -D CCL_NAMESPACE_END=
- -D NVCC
- -m ${CUDA_BITS}
- -I ${CMAKE_CURRENT_SOURCE_DIR}/..
- -I ${CMAKE_CURRENT_SOURCE_DIR}/kernels/cuda
- --use_fast_math
- -o ${CMAKE_CURRENT_BINARY_DIR}/${cuda_cubin})
-
- if(${experimental})
- set(cuda_flags ${cuda_flags} -D __KERNEL_EXPERIMENTAL__)
- set(name ${name}_experimental)
- endif()
-
- if(WITH_CYCLES_DEBUG)
- set(cuda_flags ${cuda_flags} -D __KERNEL_DEBUG__)
- endif()
-
- if(WITH_CYCLES_CUBIN_COMPILER)
- string(SUBSTRING ${arch} 3 -1 CUDA_ARCH)
-
- # Needed to find libnvrtc-builtins.so. Can't do it from inside
- # cycles_cubin_cc since the env variable is read before main()
- if(APPLE)
- set(CUBIN_CC_ENV ${CMAKE_COMMAND}
- -E env DYLD_LIBRARY_PATH="${CUDA_TOOLKIT_ROOT_DIR}/lib")
- elseif(UNIX)
- set(CUBIN_CC_ENV ${CMAKE_COMMAND}
- -E env LD_LIBRARY_PATH="${CUDA_TOOLKIT_ROOT_DIR}/lib64")
- endif()
-
- add_custom_command(
- OUTPUT ${cuda_cubin}
- COMMAND ${CUBIN_CC_ENV}
- "$<TARGET_FILE:cycles_cubin_cc>"
- -target ${CUDA_ARCH}
- -i ${CMAKE_CURRENT_SOURCE_DIR}${cuda_kernel_src}
- ${cuda_flags}
- -v
- -cuda-toolkit-dir "${CUDA_TOOLKIT_ROOT_DIR}"
- DEPENDS ${kernel_sources} cycles_cubin_cc)
- else()
- add_custom_command(
- OUTPUT ${cuda_cubin}
- COMMAND ${CUDA_NVCC_EXECUTABLE}
- -arch=${arch}
- ${CUDA_NVCC_FLAGS}
- --cubin
- ${CMAKE_CURRENT_SOURCE_DIR}${cuda_kernel_src}
- --ptxas-options="-v"
- ${cuda_flags}
- DEPENDS ${kernel_sources})
- endif()
- delayed_install("${CMAKE_CURRENT_BINARY_DIR}" "${cuda_cubin}" ${CYCLES_INSTALL_PATH}/lib)
- list(APPEND cuda_cubins ${cuda_cubin})
-
- unset(cuda_debug_flags)
- endmacro()
-
- set(prev_arch "none")
- foreach(arch ${CYCLES_CUDA_BINARIES_ARCH})
- if(${arch} MATCHES "sm_2.")
- message(STATUS "CUDA binaries for ${arch} are no longer supported, skipped.")
- elseif(${arch} MATCHES "sm_7." AND ${CUDA_VERSION} LESS 100)
- message(STATUS "CUDA binaries for ${arch} require CUDA 10.0+, skipped.")
- else()
- # Compile regular kernel
- CYCLES_CUDA_KERNEL_ADD(${arch} ${prev_arch} filter "" "${cuda_filter_sources}" FALSE)
- CYCLES_CUDA_KERNEL_ADD(${arch} ${prev_arch} kernel "" "${cuda_sources}" FALSE)
-
- if(WITH_CYCLES_CUDA_SPLIT_KERNEL_BINARIES)
- # Compile split kernel
- CYCLES_CUDA_KERNEL_ADD(${arch} ${prev_arch} kernel_split "-D __SPLIT__" "${cuda_sources}" FALSE)
- endif()
-
- if(WITH_CYCLES_CUDA_BUILD_SERIAL)
- set(prev_arch ${arch})
- endif()
- endif()
- endforeach()
-
- add_custom_target(cycles_kernel_cuda ALL DEPENDS ${cuda_cubins})
- cycles_set_solution_folder(cycles_kernel_cuda)
+ # 64 bit only
+ set(CUDA_BITS 64)
+
+ # CUDA version
+ execute_process(COMMAND ${CUDA_NVCC_EXECUTABLE} "--version" OUTPUT_VARIABLE NVCC_OUT)
+ string(REGEX REPLACE ".*release ([0-9]+)\\.([0-9]+).*" "\\1" CUDA_VERSION_MAJOR "${NVCC_OUT}")
+ string(REGEX REPLACE ".*release ([0-9]+)\\.([0-9]+).*" "\\2" CUDA_VERSION_MINOR "${NVCC_OUT}")
+ set(CUDA_VERSION "${CUDA_VERSION_MAJOR}${CUDA_VERSION_MINOR}")
+
+ # warn for other versions
+ if(CUDA_VERSION MATCHES "101")
+ else()
+ message(WARNING
+ "CUDA version ${CUDA_VERSION_MAJOR}.${CUDA_VERSION_MINOR} detected, "
+ "build may succeed but only CUDA 10.1 is officially supported")
+ endif()
+
+ # build for each arch
+ set(cuda_sources kernels/cuda/kernel.cu kernels/cuda/kernel_split.cu
+ ${SRC_HEADERS}
+ ${SRC_KERNELS_CUDA_HEADERS}
+ ${SRC_BVH_HEADERS}
+ ${SRC_SVM_HEADERS}
+ ${SRC_GEOM_HEADERS}
+ ${SRC_CLOSURE_HEADERS}
+ ${SRC_UTIL_HEADERS}
+ )
+ set(cuda_filter_sources kernels/cuda/filter.cu
+ ${SRC_HEADERS}
+ ${SRC_KERNELS_CUDA_HEADERS}
+ ${SRC_FILTER_HEADERS}
+ ${SRC_UTIL_HEADERS}
+ )
+ set(cuda_cubins)
+
+ macro(CYCLES_CUDA_KERNEL_ADD arch prev_arch name flags sources experimental)
+ set(cuda_cubin ${name}_${arch}.cubin)
+
+ set(kernel_sources ${sources})
+ if(NOT ${prev_arch} STREQUAL "none")
+ set(kernel_sources ${kernel_sources} ${name}_${prev_arch}.cubin)
+ endif()
+
+ set(cuda_kernel_src "/kernels/cuda/${name}.cu")
+
+ set(cuda_flags
+ -D CCL_NAMESPACE_BEGIN=
+ -D CCL_NAMESPACE_END=
+ -D NVCC
+ -m ${CUDA_BITS}
+ -I ${CMAKE_CURRENT_SOURCE_DIR}/..
+ -I ${CMAKE_CURRENT_SOURCE_DIR}/kernels/cuda
+ --use_fast_math
+ -o ${CMAKE_CURRENT_BINARY_DIR}/${cuda_cubin})
+
+ if(${experimental})
+ set(cuda_flags ${cuda_flags} -D __KERNEL_EXPERIMENTAL__)
+ set(name ${name}_experimental)
+ endif()
+
+ if(WITH_CYCLES_DEBUG)
+ set(cuda_flags ${cuda_flags} -D __KERNEL_DEBUG__)
+ endif()
+
+ if(WITH_CYCLES_CUBIN_COMPILER)
+ string(SUBSTRING ${arch} 3 -1 CUDA_ARCH)
+
+ # Needed to find libnvrtc-builtins.so. Can't do it from inside
+ # cycles_cubin_cc since the env variable is read before main()
+ if(APPLE)
+ set(CUBIN_CC_ENV ${CMAKE_COMMAND}
+ -E env DYLD_LIBRARY_PATH="${CUDA_TOOLKIT_ROOT_DIR}/lib")
+ elseif(UNIX)
+ set(CUBIN_CC_ENV ${CMAKE_COMMAND}
+ -E env LD_LIBRARY_PATH="${CUDA_TOOLKIT_ROOT_DIR}/lib64")
+ endif()
+
+ add_custom_command(
+ OUTPUT ${cuda_cubin}
+ COMMAND ${CUBIN_CC_ENV}
+ "$<TARGET_FILE:cycles_cubin_cc>"
+ -target ${CUDA_ARCH}
+ -i ${CMAKE_CURRENT_SOURCE_DIR}${cuda_kernel_src}
+ ${cuda_flags}
+ -v
+ -cuda-toolkit-dir "${CUDA_TOOLKIT_ROOT_DIR}"
+ DEPENDS ${kernel_sources} cycles_cubin_cc)
+ else()
+ add_custom_command(
+ OUTPUT ${cuda_cubin}
+ COMMAND ${CUDA_NVCC_EXECUTABLE}
+ -arch=${arch}
+ ${CUDA_NVCC_FLAGS}
+ --cubin
+ ${CMAKE_CURRENT_SOURCE_DIR}${cuda_kernel_src}
+ --ptxas-options="-v"
+ ${cuda_flags}
+ DEPENDS ${kernel_sources})
+ endif()
+ delayed_install("${CMAKE_CURRENT_BINARY_DIR}" "${cuda_cubin}" ${CYCLES_INSTALL_PATH}/lib)
+ list(APPEND cuda_cubins ${cuda_cubin})
+
+ unset(cuda_debug_flags)
+ endmacro()
+
+ set(prev_arch "none")
+ foreach(arch ${CYCLES_CUDA_BINARIES_ARCH})
+ if(${arch} MATCHES "sm_2.")
+ message(STATUS "CUDA binaries for ${arch} are no longer supported, skipped.")
+ elseif(${arch} MATCHES "sm_7." AND ${CUDA_VERSION} LESS 100)
+ message(STATUS "CUDA binaries for ${arch} require CUDA 10.0+, skipped.")
+ else()
+ # Compile regular kernel
+ CYCLES_CUDA_KERNEL_ADD(${arch} ${prev_arch} filter "" "${cuda_filter_sources}" FALSE)
+ CYCLES_CUDA_KERNEL_ADD(${arch} ${prev_arch} kernel "" "${cuda_sources}" FALSE)
+
+ if(WITH_CYCLES_CUDA_SPLIT_KERNEL_BINARIES)
+ # Compile split kernel
+ CYCLES_CUDA_KERNEL_ADD(${arch} ${prev_arch} kernel_split "-D __SPLIT__" "${cuda_sources}" FALSE)
+ endif()
+
+ if(WITH_CYCLES_CUDA_BUILD_SERIAL)
+ set(prev_arch ${arch})
+ endif()
+ endif()
+ endforeach()
+
+ add_custom_target(cycles_kernel_cuda ALL DEPENDS ${cuda_cubins})
+ cycles_set_solution_folder(cycles_kernel_cuda)
endif()
# OSL module
if(WITH_CYCLES_OSL)
- list(APPEND LIB
- cycles_kernel_osl
- )
- add_subdirectory(osl)
- add_subdirectory(shaders)
+ list(APPEND LIB
+ cycles_kernel_osl
+ )
+ add_subdirectory(osl)
+ add_subdirectory(shaders)
endif()
# CPU module
@@ -491,56 +491,56 @@ set_source_files_properties(kernels/cpu/kernel_split.cpp PROPERTIES COMPILE_FLAG
set_source_files_properties(kernels/cpu/filter.cpp PROPERTIES COMPILE_FLAGS "${CYCLES_KERNEL_FLAGS}")
if(CXX_HAS_SSE)
- set_source_files_properties(kernels/cpu/kernel_sse2.cpp PROPERTIES COMPILE_FLAGS "${CYCLES_SSE2_KERNEL_FLAGS}")
- set_source_files_properties(kernels/cpu/kernel_sse3.cpp PROPERTIES COMPILE_FLAGS "${CYCLES_SSE3_KERNEL_FLAGS}")
- set_source_files_properties(kernels/cpu/kernel_sse41.cpp PROPERTIES COMPILE_FLAGS "${CYCLES_SSE41_KERNEL_FLAGS}")
- set_source_files_properties(kernels/cpu/kernel_split_sse2.cpp PROPERTIES COMPILE_FLAGS "${CYCLES_SSE2_KERNEL_FLAGS}")
- set_source_files_properties(kernels/cpu/kernel_split_sse3.cpp PROPERTIES COMPILE_FLAGS "${CYCLES_SSE3_KERNEL_FLAGS}")
- set_source_files_properties(kernels/cpu/kernel_split_sse41.cpp PROPERTIES COMPILE_FLAGS "${CYCLES_SSE41_KERNEL_FLAGS}")
- set_source_files_properties(kernels/cpu/filter_sse2.cpp PROPERTIES COMPILE_FLAGS "${CYCLES_SSE2_KERNEL_FLAGS}")
- set_source_files_properties(kernels/cpu/filter_sse3.cpp PROPERTIES COMPILE_FLAGS "${CYCLES_SSE3_KERNEL_FLAGS}")
- set_source_files_properties(kernels/cpu/filter_sse41.cpp PROPERTIES COMPILE_FLAGS "${CYCLES_SSE41_KERNEL_FLAGS}")
+ set_source_files_properties(kernels/cpu/kernel_sse2.cpp PROPERTIES COMPILE_FLAGS "${CYCLES_SSE2_KERNEL_FLAGS}")
+ set_source_files_properties(kernels/cpu/kernel_sse3.cpp PROPERTIES COMPILE_FLAGS "${CYCLES_SSE3_KERNEL_FLAGS}")
+ set_source_files_properties(kernels/cpu/kernel_sse41.cpp PROPERTIES COMPILE_FLAGS "${CYCLES_SSE41_KERNEL_FLAGS}")
+ set_source_files_properties(kernels/cpu/kernel_split_sse2.cpp PROPERTIES COMPILE_FLAGS "${CYCLES_SSE2_KERNEL_FLAGS}")
+ set_source_files_properties(kernels/cpu/kernel_split_sse3.cpp PROPERTIES COMPILE_FLAGS "${CYCLES_SSE3_KERNEL_FLAGS}")
+ set_source_files_properties(kernels/cpu/kernel_split_sse41.cpp PROPERTIES COMPILE_FLAGS "${CYCLES_SSE41_KERNEL_FLAGS}")
+ set_source_files_properties(kernels/cpu/filter_sse2.cpp PROPERTIES COMPILE_FLAGS "${CYCLES_SSE2_KERNEL_FLAGS}")
+ set_source_files_properties(kernels/cpu/filter_sse3.cpp PROPERTIES COMPILE_FLAGS "${CYCLES_SSE3_KERNEL_FLAGS}")
+ set_source_files_properties(kernels/cpu/filter_sse41.cpp PROPERTIES COMPILE_FLAGS "${CYCLES_SSE41_KERNEL_FLAGS}")
endif()
if(CXX_HAS_AVX)
- set_source_files_properties(kernels/cpu/kernel_avx.cpp PROPERTIES COMPILE_FLAGS "${CYCLES_AVX_KERNEL_FLAGS}")
- set_source_files_properties(kernels/cpu/kernel_split_avx.cpp PROPERTIES COMPILE_FLAGS "${CYCLES_AVX_KERNEL_FLAGS}")
- set_source_files_properties(kernels/cpu/filter_avx.cpp PROPERTIES COMPILE_FLAGS "${CYCLES_AVX_KERNEL_FLAGS}")
+ set_source_files_properties(kernels/cpu/kernel_avx.cpp PROPERTIES COMPILE_FLAGS "${CYCLES_AVX_KERNEL_FLAGS}")
+ set_source_files_properties(kernels/cpu/kernel_split_avx.cpp PROPERTIES COMPILE_FLAGS "${CYCLES_AVX_KERNEL_FLAGS}")
+ set_source_files_properties(kernels/cpu/filter_avx.cpp PROPERTIES COMPILE_FLAGS "${CYCLES_AVX_KERNEL_FLAGS}")
endif()
if(CXX_HAS_AVX2)
- set_source_files_properties(kernels/cpu/kernel_avx2.cpp PROPERTIES COMPILE_FLAGS "${CYCLES_AVX2_KERNEL_FLAGS}")
- set_source_files_properties(kernels/cpu/kernel_split_avx2.cpp PROPERTIES COMPILE_FLAGS "${CYCLES_AVX2_KERNEL_FLAGS}")
- set_source_files_properties(kernels/cpu/filter_avx2.cpp PROPERTIES COMPILE_FLAGS "${CYCLES_AVX2_KERNEL_FLAGS}")
+ set_source_files_properties(kernels/cpu/kernel_avx2.cpp PROPERTIES COMPILE_FLAGS "${CYCLES_AVX2_KERNEL_FLAGS}")
+ set_source_files_properties(kernels/cpu/kernel_split_avx2.cpp PROPERTIES COMPILE_FLAGS "${CYCLES_AVX2_KERNEL_FLAGS}")
+ set_source_files_properties(kernels/cpu/filter_avx2.cpp PROPERTIES COMPILE_FLAGS "${CYCLES_AVX2_KERNEL_FLAGS}")
endif()
cycles_add_library(cycles_kernel "${LIB}"
- ${SRC_CPU_KERNELS}
- ${SRC_CUDA_KERNELS}
- ${SRC_OPENCL_KERNELS}
- ${SRC_HEADERS}
- ${SRC_KERNELS_CPU_HEADERS}
- ${SRC_KERNELS_CUDA_HEADERS}
- ${SRC_KERNELS_OPENCL_HEADERS}
- ${SRC_BVH_HEADERS}
- ${SRC_CLOSURE_HEADERS}
- ${SRC_FILTER_HEADERS}
- ${SRC_SVM_HEADERS}
- ${SRC_GEOM_HEADERS}
- ${SRC_SPLIT_HEADERS}
+ ${SRC_CPU_KERNELS}
+ ${SRC_CUDA_KERNELS}
+ ${SRC_OPENCL_KERNELS}
+ ${SRC_HEADERS}
+ ${SRC_KERNELS_CPU_HEADERS}
+ ${SRC_KERNELS_CUDA_HEADERS}
+ ${SRC_KERNELS_OPENCL_HEADERS}
+ ${SRC_BVH_HEADERS}
+ ${SRC_CLOSURE_HEADERS}
+ ${SRC_FILTER_HEADERS}
+ ${SRC_SVM_HEADERS}
+ ${SRC_GEOM_HEADERS}
+ ${SRC_SPLIT_HEADERS}
)
if(WITH_CYCLES_CUDA)
- add_dependencies(cycles_kernel cycles_kernel_cuda)
+ add_dependencies(cycles_kernel cycles_kernel_cuda)
endif()
# OpenCL kernel
#set(KERNEL_PREPROCESSED ${CMAKE_CURRENT_BINARY_DIR}/kernel_preprocessed.cl)
#add_custom_command(
-# OUTPUT ${KERNEL_PREPROCESSED}
-# COMMAND gcc -x c++ -E ${CMAKE_CURRENT_SOURCE_DIR}/kernel.cl -I ${CMAKE_CURRENT_SOURCE_DIR}/../util/ -DCCL_NAMESPACE_BEGIN= -DCCL_NAMESPACE_END= -o ${KERNEL_PREPROCESSED}
-# DEPENDS ${SRC_KERNEL} ${SRC_UTIL_HEADERS})
+# OUTPUT ${KERNEL_PREPROCESSED}
+# COMMAND gcc -x c++ -E ${CMAKE_CURRENT_SOURCE_DIR}/kernel.cl -I ${CMAKE_CURRENT_SOURCE_DIR}/../util/ -DCCL_NAMESPACE_BEGIN= -DCCL_NAMESPACE_END= -o ${KERNEL_PREPROCESSED}
+# DEPENDS ${SRC_KERNEL} ${SRC_UTIL_HEADERS})
#add_custom_target(cycles_kernel_preprocess ALL DEPENDS ${KERNEL_PREPROCESSED})
#delayed_install(${CMAKE_CURRENT_SOURCE_DIR} "${KERNEL_PREPROCESSED}" ${CYCLES_INSTALL_PATH}/kernel)
diff --git a/intern/cycles/kernel/bvh/bvh.h b/intern/cycles/kernel/bvh/bvh.h
index e5f807833f3..13e72ed299f 100644
--- a/intern/cycles/kernel/bvh/bvh.h
+++ b/intern/cycles/kernel/bvh/bvh.h
@@ -57,19 +57,19 @@ CCL_NAMESPACE_BEGIN
#if defined(__HAIR__)
# define BVH_FUNCTION_NAME bvh_intersect_hair
-# define BVH_FUNCTION_FEATURES BVH_INSTANCING|BVH_HAIR|BVH_HAIR_MINIMUM_WIDTH
+# define BVH_FUNCTION_FEATURES BVH_INSTANCING | BVH_HAIR | BVH_HAIR_MINIMUM_WIDTH
# include "kernel/bvh/bvh_traversal.h"
#endif
#if defined(__OBJECT_MOTION__)
# define BVH_FUNCTION_NAME bvh_intersect_motion
-# define BVH_FUNCTION_FEATURES BVH_INSTANCING|BVH_MOTION
+# define BVH_FUNCTION_FEATURES BVH_INSTANCING | BVH_MOTION
# include "kernel/bvh/bvh_traversal.h"
#endif
#if defined(__HAIR__) && defined(__OBJECT_MOTION__)
# define BVH_FUNCTION_NAME bvh_intersect_hair_motion
-# define BVH_FUNCTION_FEATURES BVH_INSTANCING|BVH_HAIR|BVH_HAIR_MINIMUM_WIDTH|BVH_MOTION
+# define BVH_FUNCTION_FEATURES BVH_INSTANCING | BVH_HAIR | BVH_HAIR_MINIMUM_WIDTH | BVH_MOTION
# include "kernel/bvh/bvh_traversal.h"
#endif
@@ -82,10 +82,10 @@ CCL_NAMESPACE_BEGIN
# if defined(__OBJECT_MOTION__)
# define BVH_FUNCTION_NAME bvh_intersect_local_motion
-# define BVH_FUNCTION_FEATURES BVH_MOTION|BVH_HAIR
+# define BVH_FUNCTION_FEATURES BVH_MOTION | BVH_HAIR
# include "kernel/bvh/bvh_local.h"
# endif
-#endif /* __BVH_LOCAL__ */
+#endif /* __BVH_LOCAL__ */
/* Volume BVH traversal */
@@ -96,16 +96,16 @@ CCL_NAMESPACE_BEGIN
# if defined(__INSTANCING__)
# define BVH_FUNCTION_NAME bvh_intersect_volume_instancing
-# define BVH_FUNCTION_FEATURES BVH_INSTANCING|BVH_HAIR
+# define BVH_FUNCTION_FEATURES BVH_INSTANCING | BVH_HAIR
# include "kernel/bvh/bvh_volume.h"
# endif
# if defined(__OBJECT_MOTION__)
# define BVH_FUNCTION_NAME bvh_intersect_volume_motion
-# define BVH_FUNCTION_FEATURES BVH_INSTANCING|BVH_MOTION|BVH_HAIR
+# define BVH_FUNCTION_FEATURES BVH_INSTANCING | BVH_MOTION | BVH_HAIR
# include "kernel/bvh/bvh_volume.h"
# endif
-#endif /* __VOLUME__ */
+#endif /* __VOLUME__ */
/* Record all intersections - Shadow BVH traversal */
@@ -122,22 +122,22 @@ CCL_NAMESPACE_BEGIN
# if defined(__HAIR__)
# define BVH_FUNCTION_NAME bvh_intersect_shadow_all_hair
-# define BVH_FUNCTION_FEATURES BVH_INSTANCING|BVH_HAIR
+# define BVH_FUNCTION_FEATURES BVH_INSTANCING | BVH_HAIR
# include "kernel/bvh/bvh_shadow_all.h"
# endif
# if defined(__OBJECT_MOTION__)
# define BVH_FUNCTION_NAME bvh_intersect_shadow_all_motion
-# define BVH_FUNCTION_FEATURES BVH_INSTANCING|BVH_MOTION
+# define BVH_FUNCTION_FEATURES BVH_INSTANCING | BVH_MOTION
# include "kernel/bvh/bvh_shadow_all.h"
# endif
# if defined(__HAIR__) && defined(__OBJECT_MOTION__)
# define BVH_FUNCTION_NAME bvh_intersect_shadow_all_hair_motion
-# define BVH_FUNCTION_FEATURES BVH_INSTANCING|BVH_HAIR|BVH_MOTION
+# define BVH_FUNCTION_FEATURES BVH_INSTANCING | BVH_HAIR | BVH_MOTION
# include "kernel/bvh/bvh_shadow_all.h"
# endif
-#endif /* __SHADOW_RECORD_ALL__ */
+#endif /* __SHADOW_RECORD_ALL__ */
/* Record all intersections - Volume BVH traversal */
@@ -148,16 +148,16 @@ CCL_NAMESPACE_BEGIN
# if defined(__INSTANCING__)
# define BVH_FUNCTION_NAME bvh_intersect_volume_all_instancing
-# define BVH_FUNCTION_FEATURES BVH_INSTANCING|BVH_HAIR
+# define BVH_FUNCTION_FEATURES BVH_INSTANCING | BVH_HAIR
# include "kernel/bvh/bvh_volume_all.h"
# endif
# if defined(__OBJECT_MOTION__)
# define BVH_FUNCTION_NAME bvh_intersect_volume_all_motion
-# define BVH_FUNCTION_FEATURES BVH_INSTANCING|BVH_MOTION|BVH_HAIR
+# define BVH_FUNCTION_FEATURES BVH_INSTANCING | BVH_MOTION | BVH_HAIR
# include "kernel/bvh/bvh_volume_all.h"
# endif
-#endif /* __VOLUME_RECORD_ALL__ */
+#endif /* __VOLUME_RECORD_ALL__ */
#undef BVH_FEATURE
#undef BVH_NAME_JOIN
@@ -166,15 +166,15 @@ CCL_NAMESPACE_BEGIN
ccl_device_inline bool scene_intersect_valid(const Ray *ray)
{
- /* NOTE: Due to some vectorization code non-finite origin point might
- * cause lots of false-positive intersections which will overflow traversal
- * stack.
- * This code is a quick way to perform early output, to avoid crashes in
- * such cases.
- * From production scenes so far it seems it's enough to test first element
- * only.
- */
- return isfinite(ray->P.x);
+ /* NOTE: Due to some vectorization code non-finite origin point might
+ * cause lots of false-positive intersections which will overflow traversal
+ * stack.
+ * This code is a quick way to perform early output, to avoid crashes in
+ * such cases.
+ * From production scenes so far it seems it's enough to test first element
+ * only.
+ */
+ return isfinite(ray->P.x);
}
/* Note: ray is passed by value to work around a possible CUDA compiler bug. */
@@ -186,59 +186,60 @@ ccl_device_intersect bool scene_intersect(KernelGlobals *kg,
float difl,
float extmax)
{
- PROFILING_INIT(kg, PROFILING_INTERSECT);
+ PROFILING_INIT(kg, PROFILING_INTERSECT);
- if(!scene_intersect_valid(&ray)) {
- return false;
- }
+ if (!scene_intersect_valid(&ray)) {
+ return false;
+ }
#ifdef __EMBREE__
- if(kernel_data.bvh.scene) {
- isect->t = ray.t;
- CCLIntersectContext ctx(kg, CCLIntersectContext::RAY_REGULAR);
- IntersectContext rtc_ctx(&ctx);
- RTCRayHit ray_hit;
- kernel_embree_setup_rayhit(ray, ray_hit, visibility);
- rtcIntersect1(kernel_data.bvh.scene, &rtc_ctx.context, &ray_hit);
- if(ray_hit.hit.geomID != RTC_INVALID_GEOMETRY_ID && ray_hit.hit.primID != RTC_INVALID_GEOMETRY_ID) {
- kernel_embree_convert_hit(kg, &ray_hit.ray, &ray_hit.hit, isect);
- return true;
- }
- return false;
- }
-#endif /* __EMBREE__ */
+ if (kernel_data.bvh.scene) {
+ isect->t = ray.t;
+ CCLIntersectContext ctx(kg, CCLIntersectContext::RAY_REGULAR);
+ IntersectContext rtc_ctx(&ctx);
+ RTCRayHit ray_hit;
+ kernel_embree_setup_rayhit(ray, ray_hit, visibility);
+ rtcIntersect1(kernel_data.bvh.scene, &rtc_ctx.context, &ray_hit);
+ if (ray_hit.hit.geomID != RTC_INVALID_GEOMETRY_ID &&
+ ray_hit.hit.primID != RTC_INVALID_GEOMETRY_ID) {
+ kernel_embree_convert_hit(kg, &ray_hit.ray, &ray_hit.hit, isect);
+ return true;
+ }
+ return false;
+ }
+#endif /* __EMBREE__ */
#ifdef __OBJECT_MOTION__
- if(kernel_data.bvh.have_motion) {
+ if (kernel_data.bvh.have_motion) {
# ifdef __HAIR__
- if(kernel_data.bvh.have_curves)
- return bvh_intersect_hair_motion(kg, &ray, isect, visibility, lcg_state, difl, extmax);
-# endif /* __HAIR__ */
+ if (kernel_data.bvh.have_curves)
+ return bvh_intersect_hair_motion(kg, &ray, isect, visibility, lcg_state, difl, extmax);
+# endif /* __HAIR__ */
- return bvh_intersect_motion(kg, &ray, isect, visibility);
- }
-#endif /* __OBJECT_MOTION__ */
+ return bvh_intersect_motion(kg, &ray, isect, visibility);
+ }
+#endif /* __OBJECT_MOTION__ */
#ifdef __HAIR__
- if(kernel_data.bvh.have_curves)
- return bvh_intersect_hair(kg, &ray, isect, visibility, lcg_state, difl, extmax);
-#endif /* __HAIR__ */
+ if (kernel_data.bvh.have_curves)
+ return bvh_intersect_hair(kg, &ray, isect, visibility, lcg_state, difl, extmax);
+#endif /* __HAIR__ */
#ifdef __KERNEL_CPU__
# ifdef __INSTANCING__
- if(kernel_data.bvh.have_instancing)
- return bvh_intersect_instancing(kg, &ray, isect, visibility);
-# endif /* __INSTANCING__ */
+ if (kernel_data.bvh.have_instancing)
+ return bvh_intersect_instancing(kg, &ray, isect, visibility);
+# endif /* __INSTANCING__ */
- return bvh_intersect(kg, &ray, isect, visibility);
-#else /* __KERNEL_CPU__ */
+ return bvh_intersect(kg, &ray, isect, visibility);
+#else /* __KERNEL_CPU__ */
# ifdef __INSTANCING__
- return bvh_intersect_instancing(kg, &ray, isect, visibility);
+ return bvh_intersect_instancing(kg, &ray, isect, visibility);
# else
- return bvh_intersect(kg, &ray, isect, visibility);
-# endif /* __INSTANCING__ */
+ return bvh_intersect(kg, &ray, isect, visibility);
+# endif /* __INSTANCING__ */
-#endif /* __KERNEL_CPU__ */
+#endif /* __KERNEL_CPU__ */
}
#ifdef __BVH_LOCAL__
@@ -250,77 +251,61 @@ ccl_device_intersect bool scene_intersect_local(KernelGlobals *kg,
uint *lcg_state,
int max_hits)
{
- PROFILING_INIT(kg, PROFILING_INTERSECT_LOCAL);
+ PROFILING_INIT(kg, PROFILING_INTERSECT_LOCAL);
- if(!scene_intersect_valid(&ray)) {
- local_isect->num_hits = 0;
- return false;
- }
-#ifdef __EMBREE__
- if(kernel_data.bvh.scene) {
- CCLIntersectContext ctx(kg, CCLIntersectContext::RAY_SSS);
- ctx.lcg_state = lcg_state;
- ctx.max_hits = max_hits;
- ctx.ss_isect = local_isect;
- local_isect->num_hits = 0;
- ctx.sss_object_id = local_object;
- IntersectContext rtc_ctx(&ctx);
- RTCRay rtc_ray;
- kernel_embree_setup_ray(ray, rtc_ray, PATH_RAY_ALL_VISIBILITY);
-
- /* Get the Embree scene for this intersection. */
- RTCGeometry geom = rtcGetGeometry(kernel_data.bvh.scene, local_object * 2);
- if(geom) {
- float3 P = ray.P;
- float3 dir = ray.D;
- float3 idir = ray.D;
- const int object_flag = kernel_tex_fetch(__object_flag, local_object);
- if(!(object_flag & SD_OBJECT_TRANSFORM_APPLIED)) {
- Transform ob_itfm;
- rtc_ray.tfar = bvh_instance_motion_push(kg,
- local_object,
- &ray,
- &P,
- &dir,
- &idir,
- ray.t,
- &ob_itfm);
- /* bvh_instance_motion_push() returns the inverse transform but
- * it's not needed here. */
- (void) ob_itfm;
-
- rtc_ray.org_x = P.x;
- rtc_ray.org_y = P.y;
- rtc_ray.org_z = P.z;
- rtc_ray.dir_x = dir.x;
- rtc_ray.dir_y = dir.y;
- rtc_ray.dir_z = dir.z;
- }
- RTCScene scene = (RTCScene)rtcGetGeometryUserData(geom);
- if(scene) {
- rtcOccluded1(scene, &rtc_ctx.context, &rtc_ray);
- }
- }
-
- return local_isect->num_hits > 0;
- }
-#endif /* __EMBREE__ */
-#ifdef __OBJECT_MOTION__
- if(kernel_data.bvh.have_motion) {
- return bvh_intersect_local_motion(kg,
- &ray,
- local_isect,
- local_object,
- lcg_state,
- max_hits);
- }
-#endif /* __OBJECT_MOTION__ */
- return bvh_intersect_local(kg,
- &ray,
- local_isect,
- local_object,
- lcg_state,
- max_hits);
+ if (!scene_intersect_valid(&ray)) {
+ local_isect->num_hits = 0;
+ return false;
+ }
+# ifdef __EMBREE__
+ if (kernel_data.bvh.scene) {
+ CCLIntersectContext ctx(kg, CCLIntersectContext::RAY_SSS);
+ ctx.lcg_state = lcg_state;
+ ctx.max_hits = max_hits;
+ ctx.ss_isect = local_isect;
+ local_isect->num_hits = 0;
+ ctx.sss_object_id = local_object;
+ IntersectContext rtc_ctx(&ctx);
+ RTCRay rtc_ray;
+ kernel_embree_setup_ray(ray, rtc_ray, PATH_RAY_ALL_VISIBILITY);
+
+ /* Get the Embree scene for this intersection. */
+ RTCGeometry geom = rtcGetGeometry(kernel_data.bvh.scene, local_object * 2);
+ if (geom) {
+ float3 P = ray.P;
+ float3 dir = ray.D;
+ float3 idir = ray.D;
+ const int object_flag = kernel_tex_fetch(__object_flag, local_object);
+ if (!(object_flag & SD_OBJECT_TRANSFORM_APPLIED)) {
+ Transform ob_itfm;
+ rtc_ray.tfar = bvh_instance_motion_push(
+ kg, local_object, &ray, &P, &dir, &idir, ray.t, &ob_itfm);
+ /* bvh_instance_motion_push() returns the inverse transform but
+ * it's not needed here. */
+ (void)ob_itfm;
+
+ rtc_ray.org_x = P.x;
+ rtc_ray.org_y = P.y;
+ rtc_ray.org_z = P.z;
+ rtc_ray.dir_x = dir.x;
+ rtc_ray.dir_y = dir.y;
+ rtc_ray.dir_z = dir.z;
+ }
+ RTCScene scene = (RTCScene)rtcGetGeometryUserData(geom);
+ if (scene) {
+ rtcOccluded1(scene, &rtc_ctx.context, &rtc_ray);
+ }
+ }
+
+ return local_isect->num_hits > 0;
+ }
+# endif /* __EMBREE__ */
+# ifdef __OBJECT_MOTION__
+ if (kernel_data.bvh.have_motion) {
+ return bvh_intersect_local_motion(kg, &ray, local_isect, local_object, lcg_state, max_hits);
+ }
+# endif /* __OBJECT_MOTION__ */
+ return bvh_intersect_local(kg, &ray, local_isect, local_object, lcg_state, max_hits);
}
#endif
@@ -332,82 +317,57 @@ ccl_device_intersect bool scene_intersect_shadow_all(KernelGlobals *kg,
uint max_hits,
uint *num_hits)
{
- PROFILING_INIT(kg, PROFILING_INTERSECT_SHADOW_ALL);
+ PROFILING_INIT(kg, PROFILING_INTERSECT_SHADOW_ALL);
- if(!scene_intersect_valid(ray)) {
- *num_hits = 0;
- return false;
- }
+ if (!scene_intersect_valid(ray)) {
+ *num_hits = 0;
+ return false;
+ }
# ifdef __EMBREE__
- if(kernel_data.bvh.scene) {
- CCLIntersectContext ctx(kg, CCLIntersectContext::RAY_SHADOW_ALL);
- ctx.isect_s = isect;
- ctx.max_hits = max_hits;
- ctx.num_hits = 0;
- IntersectContext rtc_ctx(&ctx);
- RTCRay rtc_ray;
- kernel_embree_setup_ray(*ray, rtc_ray, PATH_RAY_SHADOW);
- rtcOccluded1(kernel_data.bvh.scene, &rtc_ctx.context, &rtc_ray);
-
- if(ctx.num_hits > max_hits) {
- return true;
- }
- *num_hits = ctx.num_hits;
- return rtc_ray.tfar == -INFINITY;
- }
+ if (kernel_data.bvh.scene) {
+ CCLIntersectContext ctx(kg, CCLIntersectContext::RAY_SHADOW_ALL);
+ ctx.isect_s = isect;
+ ctx.max_hits = max_hits;
+ ctx.num_hits = 0;
+ IntersectContext rtc_ctx(&ctx);
+ RTCRay rtc_ray;
+ kernel_embree_setup_ray(*ray, rtc_ray, PATH_RAY_SHADOW);
+ rtcOccluded1(kernel_data.bvh.scene, &rtc_ctx.context, &rtc_ray);
+
+ if (ctx.num_hits > max_hits) {
+ return true;
+ }
+ *num_hits = ctx.num_hits;
+ return rtc_ray.tfar == -INFINITY;
+ }
# endif
# ifdef __OBJECT_MOTION__
- if(kernel_data.bvh.have_motion) {
+ if (kernel_data.bvh.have_motion) {
# ifdef __HAIR__
- if(kernel_data.bvh.have_curves) {
- return bvh_intersect_shadow_all_hair_motion(kg,
- ray,
- isect,
- visibility,
- max_hits,
- num_hits);
- }
-# endif /* __HAIR__ */
-
- return bvh_intersect_shadow_all_motion(kg,
- ray,
- isect,
- visibility,
- max_hits,
- num_hits);
- }
-# endif /* __OBJECT_MOTION__ */
+ if (kernel_data.bvh.have_curves) {
+ return bvh_intersect_shadow_all_hair_motion(kg, ray, isect, visibility, max_hits, num_hits);
+ }
+# endif /* __HAIR__ */
+
+ return bvh_intersect_shadow_all_motion(kg, ray, isect, visibility, max_hits, num_hits);
+ }
+# endif /* __OBJECT_MOTION__ */
# ifdef __HAIR__
- if(kernel_data.bvh.have_curves) {
- return bvh_intersect_shadow_all_hair(kg,
- ray,
- isect,
- visibility,
- max_hits,
- num_hits);
- }
-# endif /* __HAIR__ */
+ if (kernel_data.bvh.have_curves) {
+ return bvh_intersect_shadow_all_hair(kg, ray, isect, visibility, max_hits, num_hits);
+ }
+# endif /* __HAIR__ */
# ifdef __INSTANCING__
- if(kernel_data.bvh.have_instancing) {
- return bvh_intersect_shadow_all_instancing(kg,
- ray,
- isect,
- visibility,
- max_hits,
- num_hits);
- }
-# endif /* __INSTANCING__ */
-
- return bvh_intersect_shadow_all(kg,
- ray,
- isect,
- visibility,
- max_hits,
- num_hits);
+ if (kernel_data.bvh.have_instancing) {
+ return bvh_intersect_shadow_all_instancing(kg, ray, isect, visibility, max_hits, num_hits);
+ }
+# endif /* __INSTANCING__ */
+
+ return bvh_intersect_shadow_all(kg, ray, isect, visibility, max_hits, num_hits);
}
-#endif /* __SHADOW_RECORD_ALL__ */
+#endif /* __SHADOW_RECORD_ALL__ */
#ifdef __VOLUME__
ccl_device_intersect bool scene_intersect_volume(KernelGlobals *kg,
@@ -415,31 +375,31 @@ ccl_device_intersect bool scene_intersect_volume(KernelGlobals *kg,
Intersection *isect,
const uint visibility)
{
- PROFILING_INIT(kg, PROFILING_INTERSECT_VOLUME);
+ PROFILING_INIT(kg, PROFILING_INTERSECT_VOLUME);
- if(!scene_intersect_valid(ray)) {
- return false;
- }
+ if (!scene_intersect_valid(ray)) {
+ return false;
+ }
# ifdef __OBJECT_MOTION__
- if(kernel_data.bvh.have_motion) {
- return bvh_intersect_volume_motion(kg, ray, isect, visibility);
- }
-# endif /* __OBJECT_MOTION__ */
+ if (kernel_data.bvh.have_motion) {
+ return bvh_intersect_volume_motion(kg, ray, isect, visibility);
+ }
+# endif /* __OBJECT_MOTION__ */
# ifdef __KERNEL_CPU__
# ifdef __INSTANCING__
- if(kernel_data.bvh.have_instancing)
- return bvh_intersect_volume_instancing(kg, ray, isect, visibility);
-# endif /* __INSTANCING__ */
- return bvh_intersect_volume(kg, ray, isect, visibility);
-# else /* __KERNEL_CPU__ */
+ if (kernel_data.bvh.have_instancing)
+ return bvh_intersect_volume_instancing(kg, ray, isect, visibility);
+# endif /* __INSTANCING__ */
+ return bvh_intersect_volume(kg, ray, isect, visibility);
+# else /* __KERNEL_CPU__ */
# ifdef __INSTANCING__
- return bvh_intersect_volume_instancing(kg, ray, isect, visibility);
+ return bvh_intersect_volume_instancing(kg, ray, isect, visibility);
# else
- return bvh_intersect_volume(kg, ray, isect, visibility);
-# endif /* __INSTANCING__ */
-# endif /* __KERNEL_CPU__ */
+ return bvh_intersect_volume(kg, ray, isect, visibility);
+# endif /* __INSTANCING__ */
+# endif /* __KERNEL_CPU__ */
}
-#endif /* __VOLUME__ */
+#endif /* __VOLUME__ */
#ifdef __VOLUME_RECORD_ALL__
ccl_device_intersect uint scene_intersect_volume_all(KernelGlobals *kg,
@@ -448,37 +408,36 @@ ccl_device_intersect uint scene_intersect_volume_all(KernelGlobals *kg,
const uint max_hits,
const uint visibility)
{
- PROFILING_INIT(kg, PROFILING_INTERSECT_VOLUME_ALL);
+ PROFILING_INIT(kg, PROFILING_INTERSECT_VOLUME_ALL);
- if(!scene_intersect_valid(ray)) {
- return false;
- }
+ if (!scene_intersect_valid(ray)) {
+ return false;
+ }
# ifdef __EMBREE__
- if(kernel_data.bvh.scene) {
- CCLIntersectContext ctx(kg, CCLIntersectContext::RAY_VOLUME_ALL);
- ctx.isect_s = isect;
- ctx.max_hits = max_hits;
- ctx.num_hits = 0;
- IntersectContext rtc_ctx(&ctx);
- RTCRay rtc_ray;
- kernel_embree_setup_ray(*ray, rtc_ray, visibility);
- rtcOccluded1(kernel_data.bvh.scene, &rtc_ctx.context, &rtc_ray);
- return rtc_ray.tfar == -INFINITY;
- }
+ if (kernel_data.bvh.scene) {
+ CCLIntersectContext ctx(kg, CCLIntersectContext::RAY_VOLUME_ALL);
+ ctx.isect_s = isect;
+ ctx.max_hits = max_hits;
+ ctx.num_hits = 0;
+ IntersectContext rtc_ctx(&ctx);
+ RTCRay rtc_ray;
+ kernel_embree_setup_ray(*ray, rtc_ray, visibility);
+ rtcOccluded1(kernel_data.bvh.scene, &rtc_ctx.context, &rtc_ray);
+ return rtc_ray.tfar == -INFINITY;
+ }
# endif
# ifdef __OBJECT_MOTION__
- if(kernel_data.bvh.have_motion) {
- return bvh_intersect_volume_all_motion(kg, ray, isect, max_hits, visibility);
- }
-# endif /* __OBJECT_MOTION__ */
+ if (kernel_data.bvh.have_motion) {
+ return bvh_intersect_volume_all_motion(kg, ray, isect, max_hits, visibility);
+ }
+# endif /* __OBJECT_MOTION__ */
# ifdef __INSTANCING__
- if(kernel_data.bvh.have_instancing)
- return bvh_intersect_volume_all_instancing(kg, ray, isect, max_hits, visibility);
-# endif /* __INSTANCING__ */
- return bvh_intersect_volume_all(kg, ray, isect, max_hits, visibility);
+ if (kernel_data.bvh.have_instancing)
+ return bvh_intersect_volume_all_instancing(kg, ray, isect, max_hits, visibility);
+# endif /* __INSTANCING__ */
+ return bvh_intersect_volume_all(kg, ray, isect, max_hits, visibility);
}
-#endif /* __VOLUME_RECORD_ALL__ */
-
+#endif /* __VOLUME_RECORD_ALL__ */
/* Ray offset to avoid self intersection.
*
@@ -488,48 +447,48 @@ ccl_device_intersect uint scene_intersect_volume_all(KernelGlobals *kg,
ccl_device_inline float3 ray_offset(float3 P, float3 Ng)
{
#ifdef __INTERSECTION_REFINE__
- const float epsilon_f = 1e-5f;
- /* ideally this should match epsilon_f, but instancing and motion blur
- * precision makes it problematic */
- const float epsilon_test = 1.0f;
- const int epsilon_i = 32;
-
- float3 res;
-
- /* x component */
- if(fabsf(P.x) < epsilon_test) {
- res.x = P.x + Ng.x*epsilon_f;
- }
- else {
- uint ix = __float_as_uint(P.x);
- ix += ((ix ^ __float_as_uint(Ng.x)) >> 31)? -epsilon_i: epsilon_i;
- res.x = __uint_as_float(ix);
- }
-
- /* y component */
- if(fabsf(P.y) < epsilon_test) {
- res.y = P.y + Ng.y*epsilon_f;
- }
- else {
- uint iy = __float_as_uint(P.y);
- iy += ((iy ^ __float_as_uint(Ng.y)) >> 31)? -epsilon_i: epsilon_i;
- res.y = __uint_as_float(iy);
- }
-
- /* z component */
- if(fabsf(P.z) < epsilon_test) {
- res.z = P.z + Ng.z*epsilon_f;
- }
- else {
- uint iz = __float_as_uint(P.z);
- iz += ((iz ^ __float_as_uint(Ng.z)) >> 31)? -epsilon_i: epsilon_i;
- res.z = __uint_as_float(iz);
- }
-
- return res;
+ const float epsilon_f = 1e-5f;
+ /* ideally this should match epsilon_f, but instancing and motion blur
+ * precision makes it problematic */
+ const float epsilon_test = 1.0f;
+ const int epsilon_i = 32;
+
+ float3 res;
+
+ /* x component */
+ if (fabsf(P.x) < epsilon_test) {
+ res.x = P.x + Ng.x * epsilon_f;
+ }
+ else {
+ uint ix = __float_as_uint(P.x);
+ ix += ((ix ^ __float_as_uint(Ng.x)) >> 31) ? -epsilon_i : epsilon_i;
+ res.x = __uint_as_float(ix);
+ }
+
+ /* y component */
+ if (fabsf(P.y) < epsilon_test) {
+ res.y = P.y + Ng.y * epsilon_f;
+ }
+ else {
+ uint iy = __float_as_uint(P.y);
+ iy += ((iy ^ __float_as_uint(Ng.y)) >> 31) ? -epsilon_i : epsilon_i;
+ res.y = __uint_as_float(iy);
+ }
+
+ /* z component */
+ if (fabsf(P.z) < epsilon_test) {
+ res.z = P.z + Ng.z * epsilon_f;
+ }
+ else {
+ uint iz = __float_as_uint(P.z);
+ iz += ((iz ^ __float_as_uint(Ng.z)) >> 31) ? -epsilon_i : epsilon_i;
+ res.z = __uint_as_float(iz);
+ }
+
+ return res;
#else
- const float epsilon_f = 1e-4f;
- return P + epsilon_f*Ng;
+ const float epsilon_f = 1e-4f;
+ return P + epsilon_f * Ng;
#endif
}
@@ -537,40 +496,40 @@ ccl_device_inline float3 ray_offset(float3 P, float3 Ng)
/* ToDo: Move to another file? */
ccl_device int intersections_compare(const void *a, const void *b)
{
- const Intersection *isect_a = (const Intersection*)a;
- const Intersection *isect_b = (const Intersection*)b;
-
- if(isect_a->t < isect_b->t)
- return -1;
- else if(isect_a->t > isect_b->t)
- return 1;
- else
- return 0;
+ const Intersection *isect_a = (const Intersection *)a;
+ const Intersection *isect_b = (const Intersection *)b;
+
+ if (isect_a->t < isect_b->t)
+ return -1;
+ else if (isect_a->t > isect_b->t)
+ return 1;
+ else
+ return 0;
}
#endif
#if defined(__SHADOW_RECORD_ALL__)
ccl_device_inline void sort_intersections(Intersection *hits, uint num_hits)
{
-#ifdef __KERNEL_GPU__
- /* Use bubble sort which has more friendly memory pattern on GPU. */
- bool swapped;
- do {
- swapped = false;
- for(int j = 0; j < num_hits - 1; ++j) {
- if(hits[j].t > hits[j + 1].t) {
- struct Intersection tmp = hits[j];
- hits[j] = hits[j + 1];
- hits[j + 1] = tmp;
- swapped = true;
- }
- }
- --num_hits;
- } while(swapped);
-#else
- qsort(hits, num_hits, sizeof(Intersection), intersections_compare);
-#endif
+# ifdef __KERNEL_GPU__
+ /* Use bubble sort which has more friendly memory pattern on GPU. */
+ bool swapped;
+ do {
+ swapped = false;
+ for (int j = 0; j < num_hits - 1; ++j) {
+ if (hits[j].t > hits[j + 1].t) {
+ struct Intersection tmp = hits[j];
+ hits[j] = hits[j + 1];
+ hits[j + 1] = tmp;
+ swapped = true;
+ }
+ }
+ --num_hits;
+ } while (swapped);
+# else
+ qsort(hits, num_hits, sizeof(Intersection), intersections_compare);
+# endif
}
-#endif /* __SHADOW_RECORD_ALL__ | __VOLUME_RECORD_ALL__ */
+#endif /* __SHADOW_RECORD_ALL__ | __VOLUME_RECORD_ALL__ */
CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/bvh/bvh_embree.h b/intern/cycles/kernel/bvh/bvh_embree.h
index bfc911a1e76..661bba54fd4 100644
--- a/intern/cycles/kernel/bvh/bvh_embree.h
+++ b/intern/cycles/kernel/bvh/bvh_embree.h
@@ -24,103 +24,120 @@
CCL_NAMESPACE_BEGIN
-struct CCLIntersectContext {
- typedef enum {
- RAY_REGULAR = 0,
- RAY_SHADOW_ALL = 1,
- RAY_SSS = 2,
- RAY_VOLUME_ALL = 3,
+struct CCLIntersectContext {
+ typedef enum {
+ RAY_REGULAR = 0,
+ RAY_SHADOW_ALL = 1,
+ RAY_SSS = 2,
+ RAY_VOLUME_ALL = 3,
- } RayType;
+ } RayType;
- KernelGlobals *kg;
- RayType type;
+ KernelGlobals *kg;
+ RayType type;
- /* for shadow rays */
- Intersection *isect_s;
- int max_hits;
- int num_hits;
+ /* for shadow rays */
+ Intersection *isect_s;
+ int max_hits;
+ int num_hits;
- /* for SSS Rays: */
- LocalIntersection *ss_isect;
- int sss_object_id;
- uint *lcg_state;
+ /* for SSS Rays: */
+ LocalIntersection *ss_isect;
+ int sss_object_id;
+ uint *lcg_state;
- CCLIntersectContext(KernelGlobals *kg_, RayType type_)
- {
- kg = kg_;
- type = type_;
- max_hits = 1;
- num_hits = 0;
- isect_s = NULL;
- ss_isect = NULL;
- sss_object_id = -1;
- lcg_state = NULL;
- }
+ CCLIntersectContext(KernelGlobals *kg_, RayType type_)
+ {
+ kg = kg_;
+ type = type_;
+ max_hits = 1;
+ num_hits = 0;
+ isect_s = NULL;
+ ss_isect = NULL;
+ sss_object_id = -1;
+ lcg_state = NULL;
+ }
};
-class IntersectContext
-{
-public:
- IntersectContext(CCLIntersectContext* ctx)
- {
- rtcInitIntersectContext(&context);
- userRayExt = ctx;
- }
- RTCIntersectContext context;
- CCLIntersectContext* userRayExt;
+class IntersectContext {
+ public:
+ IntersectContext(CCLIntersectContext *ctx)
+ {
+ rtcInitIntersectContext(&context);
+ userRayExt = ctx;
+ }
+ RTCIntersectContext context;
+ CCLIntersectContext *userRayExt;
};
-ccl_device_inline void kernel_embree_setup_ray(const Ray& ray, RTCRay& rtc_ray, const uint visibility)
+ccl_device_inline void kernel_embree_setup_ray(const Ray &ray,
+ RTCRay &rtc_ray,
+ const uint visibility)
{
- rtc_ray.org_x = ray.P.x;
- rtc_ray.org_y = ray.P.y;
- rtc_ray.org_z = ray.P.z;
- rtc_ray.dir_x = ray.D.x;
- rtc_ray.dir_y = ray.D.y;
- rtc_ray.dir_z = ray.D.z;
- rtc_ray.tnear = 0.0f;
- rtc_ray.tfar = ray.t;
- rtc_ray.time = ray.time;
- rtc_ray.mask = visibility;
+ rtc_ray.org_x = ray.P.x;
+ rtc_ray.org_y = ray.P.y;
+ rtc_ray.org_z = ray.P.z;
+ rtc_ray.dir_x = ray.D.x;
+ rtc_ray.dir_y = ray.D.y;
+ rtc_ray.dir_z = ray.D.z;
+ rtc_ray.tnear = 0.0f;
+ rtc_ray.tfar = ray.t;
+ rtc_ray.time = ray.time;
+ rtc_ray.mask = visibility;
}
-ccl_device_inline void kernel_embree_setup_rayhit(const Ray& ray, RTCRayHit& rayhit, const uint visibility)
+ccl_device_inline void kernel_embree_setup_rayhit(const Ray &ray,
+ RTCRayHit &rayhit,
+ const uint visibility)
{
- kernel_embree_setup_ray(ray, rayhit.ray, visibility);
- rayhit.hit.geomID = RTC_INVALID_GEOMETRY_ID;
- rayhit.hit.primID = RTC_INVALID_GEOMETRY_ID;
+ kernel_embree_setup_ray(ray, rayhit.ray, visibility);
+ rayhit.hit.geomID = RTC_INVALID_GEOMETRY_ID;
+ rayhit.hit.primID = RTC_INVALID_GEOMETRY_ID;
}
-ccl_device_inline void kernel_embree_convert_hit(KernelGlobals *kg, const RTCRay *ray, const RTCHit *hit, Intersection *isect)
+ccl_device_inline void kernel_embree_convert_hit(KernelGlobals *kg,
+ const RTCRay *ray,
+ const RTCHit *hit,
+ Intersection *isect)
{
- bool is_hair = hit->geomID & 1;
- isect->u = is_hair ? hit->u : 1.0f - hit->v - hit->u;
- isect->v = is_hair ? hit->v : hit->u;
- isect->t = ray->tfar;
- isect->Ng = make_float3(hit->Ng_x, hit->Ng_y, hit->Ng_z);
- if(hit->instID[0] != RTC_INVALID_GEOMETRY_ID) {
- RTCScene inst_scene = (RTCScene)rtcGetGeometryUserData(rtcGetGeometry(kernel_data.bvh.scene, hit->instID[0]));
- isect->prim = hit->primID + (intptr_t)rtcGetGeometryUserData(rtcGetGeometry(inst_scene, hit->geomID)) + kernel_tex_fetch(__object_node, hit->instID[0]/2);
- isect->object = hit->instID[0]/2;
- }
- else {
- isect->prim = hit->primID + (intptr_t)rtcGetGeometryUserData(rtcGetGeometry(kernel_data.bvh.scene, hit->geomID));
- isect->object = OBJECT_NONE;
- }
- isect->type = kernel_tex_fetch(__prim_type, isect->prim);
+ bool is_hair = hit->geomID & 1;
+ isect->u = is_hair ? hit->u : 1.0f - hit->v - hit->u;
+ isect->v = is_hair ? hit->v : hit->u;
+ isect->t = ray->tfar;
+ isect->Ng = make_float3(hit->Ng_x, hit->Ng_y, hit->Ng_z);
+ if (hit->instID[0] != RTC_INVALID_GEOMETRY_ID) {
+ RTCScene inst_scene = (RTCScene)rtcGetGeometryUserData(
+ rtcGetGeometry(kernel_data.bvh.scene, hit->instID[0]));
+ isect->prim = hit->primID +
+ (intptr_t)rtcGetGeometryUserData(rtcGetGeometry(inst_scene, hit->geomID)) +
+ kernel_tex_fetch(__object_node, hit->instID[0] / 2);
+ isect->object = hit->instID[0] / 2;
+ }
+ else {
+ isect->prim = hit->primID + (intptr_t)rtcGetGeometryUserData(
+ rtcGetGeometry(kernel_data.bvh.scene, hit->geomID));
+ isect->object = OBJECT_NONE;
+ }
+ isect->type = kernel_tex_fetch(__prim_type, isect->prim);
}
-ccl_device_inline void kernel_embree_convert_local_hit(KernelGlobals *kg, const RTCRay *ray, const RTCHit *hit, Intersection *isect, int local_object_id)
+ccl_device_inline void kernel_embree_convert_local_hit(KernelGlobals *kg,
+ const RTCRay *ray,
+ const RTCHit *hit,
+ Intersection *isect,
+ int local_object_id)
{
- isect->u = 1.0f - hit->v - hit->u;
- isect->v = hit->u;
- isect->t = ray->tfar;
- isect->Ng = make_float3(hit->Ng_x, hit->Ng_y, hit->Ng_z);
- RTCScene inst_scene = (RTCScene)rtcGetGeometryUserData(rtcGetGeometry(kernel_data.bvh.scene, local_object_id * 2));
- isect->prim = hit->primID + (intptr_t)rtcGetGeometryUserData(rtcGetGeometry(inst_scene, hit->geomID)) + kernel_tex_fetch(__object_node, local_object_id);
- isect->object = local_object_id;
- isect->type = kernel_tex_fetch(__prim_type, isect->prim);
+ isect->u = 1.0f - hit->v - hit->u;
+ isect->v = hit->u;
+ isect->t = ray->tfar;
+ isect->Ng = make_float3(hit->Ng_x, hit->Ng_y, hit->Ng_z);
+ RTCScene inst_scene = (RTCScene)rtcGetGeometryUserData(
+ rtcGetGeometry(kernel_data.bvh.scene, local_object_id * 2));
+ isect->prim = hit->primID +
+ (intptr_t)rtcGetGeometryUserData(rtcGetGeometry(inst_scene, hit->geomID)) +
+ kernel_tex_fetch(__object_node, local_object_id);
+ isect->object = local_object_id;
+ isect->type = kernel_tex_fetch(__prim_type, isect->prim);
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/bvh/bvh_local.h b/intern/cycles/kernel/bvh/bvh_local.h
index 3bdc9293a6c..7a069ef1108 100644
--- a/intern/cycles/kernel/bvh/bvh_local.h
+++ b/intern/cycles/kernel/bvh/bvh_local.h
@@ -43,208 +43,201 @@ ccl_device
#else
ccl_device_inline
#endif
-bool BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg,
- const Ray *ray,
- LocalIntersection *local_isect,
- int local_object,
- uint *lcg_state,
- int max_hits)
+ bool BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg,
+ const Ray *ray,
+ LocalIntersection *local_isect,
+ int local_object,
+ uint *lcg_state,
+ int max_hits)
{
- /* todo:
- * - test if pushing distance on the stack helps (for non shadow rays)
- * - separate version for shadow rays
- * - likely and unlikely for if() statements
- * - test restrict attribute for pointers
- */
+ /* todo:
+ * - test if pushing distance on the stack helps (for non shadow rays)
+ * - separate version for shadow rays
+ * - likely and unlikely for if() statements
+ * - test restrict attribute for pointers
+ */
- /* traversal stack in CUDA thread-local memory */
- int traversal_stack[BVH_STACK_SIZE];
- traversal_stack[0] = ENTRYPOINT_SENTINEL;
+ /* traversal stack in CUDA thread-local memory */
+ int traversal_stack[BVH_STACK_SIZE];
+ traversal_stack[0] = ENTRYPOINT_SENTINEL;
- /* traversal variables in registers */
- int stack_ptr = 0;
- int node_addr = kernel_tex_fetch(__object_node, local_object);
+ /* traversal variables in registers */
+ int stack_ptr = 0;
+ int node_addr = kernel_tex_fetch(__object_node, local_object);
- /* ray parameters in registers */
- float3 P = ray->P;
- float3 dir = bvh_clamp_direction(ray->D);
- float3 idir = bvh_inverse_direction(dir);
- int object = OBJECT_NONE;
- float isect_t = ray->t;
+ /* ray parameters in registers */
+ float3 P = ray->P;
+ float3 dir = bvh_clamp_direction(ray->D);
+ float3 idir = bvh_inverse_direction(dir);
+ int object = OBJECT_NONE;
+ float isect_t = ray->t;
- if(local_isect != NULL) {
- local_isect->num_hits = 0;
- }
- kernel_assert((local_isect == NULL) == (max_hits == 0));
+ if (local_isect != NULL) {
+ local_isect->num_hits = 0;
+ }
+ kernel_assert((local_isect == NULL) == (max_hits == 0));
- const int object_flag = kernel_tex_fetch(__object_flag, local_object);
- if(!(object_flag & SD_OBJECT_TRANSFORM_APPLIED)) {
+ const int object_flag = kernel_tex_fetch(__object_flag, local_object);
+ if (!(object_flag & SD_OBJECT_TRANSFORM_APPLIED)) {
#if BVH_FEATURE(BVH_MOTION)
- Transform ob_itfm;
- isect_t = bvh_instance_motion_push(kg,
- local_object,
- ray,
- &P,
- &dir,
- &idir,
- isect_t,
- &ob_itfm);
+ Transform ob_itfm;
+ isect_t = bvh_instance_motion_push(kg, local_object, ray, &P, &dir, &idir, isect_t, &ob_itfm);
#else
- isect_t = bvh_instance_push(kg, local_object, ray, &P, &dir, &idir, isect_t);
+ isect_t = bvh_instance_push(kg, local_object, ray, &P, &dir, &idir, isect_t);
#endif
- object = local_object;
- }
+ object = local_object;
+ }
#if defined(__KERNEL_SSE2__)
- const shuffle_swap_t shuf_identity = shuffle_swap_identity();
- const shuffle_swap_t shuf_swap = shuffle_swap_swap();
+ const shuffle_swap_t shuf_identity = shuffle_swap_identity();
+ const shuffle_swap_t shuf_swap = shuffle_swap_swap();
- const ssef pn = cast(ssei(0, 0, 0x80000000, 0x80000000));
- ssef Psplat[3], idirsplat[3];
+ const ssef pn = cast(ssei(0, 0, 0x80000000, 0x80000000));
+ ssef Psplat[3], idirsplat[3];
# if BVH_FEATURE(BVH_HAIR)
- ssef tnear(0.0f), tfar(isect_t);
+ ssef tnear(0.0f), tfar(isect_t);
# endif
- shuffle_swap_t shufflexyz[3];
+ shuffle_swap_t shufflexyz[3];
- Psplat[0] = ssef(P.x);
- Psplat[1] = ssef(P.y);
- Psplat[2] = ssef(P.z);
+ Psplat[0] = ssef(P.x);
+ Psplat[1] = ssef(P.y);
+ Psplat[2] = ssef(P.z);
- ssef tsplat(0.0f, 0.0f, -isect_t, -isect_t);
+ ssef tsplat(0.0f, 0.0f, -isect_t, -isect_t);
- gen_idirsplat_swap(pn, shuf_identity, shuf_swap, idir, idirsplat, shufflexyz);
+ gen_idirsplat_swap(pn, shuf_identity, shuf_swap, idir, idirsplat, shufflexyz);
#endif
- /* traversal loop */
- do {
- do {
- /* traverse internal nodes */
- while(node_addr >= 0 && node_addr != ENTRYPOINT_SENTINEL) {
- int node_addr_child1, traverse_mask;
- float dist[2];
- float4 cnodes = kernel_tex_fetch(__bvh_nodes, node_addr+0);
+ /* traversal loop */
+ do {
+ do {
+ /* traverse internal nodes */
+ while (node_addr >= 0 && node_addr != ENTRYPOINT_SENTINEL) {
+ int node_addr_child1, traverse_mask;
+ float dist[2];
+ float4 cnodes = kernel_tex_fetch(__bvh_nodes, node_addr + 0);
#if !defined(__KERNEL_SSE2__)
- traverse_mask = NODE_INTERSECT(kg,
- P,
+ traverse_mask = NODE_INTERSECT(kg,
+ P,
# if BVH_FEATURE(BVH_HAIR)
- dir,
+ dir,
# endif
- idir,
- isect_t,
- node_addr,
- PATH_RAY_ALL_VISIBILITY,
- dist);
+ idir,
+ isect_t,
+ node_addr,
+ PATH_RAY_ALL_VISIBILITY,
+ dist);
#else // __KERNEL_SSE2__
- traverse_mask = NODE_INTERSECT(kg,
- P,
- dir,
+ traverse_mask = NODE_INTERSECT(kg,
+ P,
+ dir,
# if BVH_FEATURE(BVH_HAIR)
- tnear,
- tfar,
+ tnear,
+ tfar,
# endif
- tsplat,
- Psplat,
- idirsplat,
- shufflexyz,
- node_addr,
- PATH_RAY_ALL_VISIBILITY,
- dist);
+ tsplat,
+ Psplat,
+ idirsplat,
+ shufflexyz,
+ node_addr,
+ PATH_RAY_ALL_VISIBILITY,
+ dist);
#endif // __KERNEL_SSE2__
- node_addr = __float_as_int(cnodes.z);
- node_addr_child1 = __float_as_int(cnodes.w);
+ node_addr = __float_as_int(cnodes.z);
+ node_addr_child1 = __float_as_int(cnodes.w);
- if(traverse_mask == 3) {
- /* Both children were intersected, push the farther one. */
- bool is_closest_child1 = (dist[1] < dist[0]);
- if(is_closest_child1) {
- int tmp = node_addr;
- node_addr = node_addr_child1;
- node_addr_child1 = tmp;
- }
+ if (traverse_mask == 3) {
+ /* Both children were intersected, push the farther one. */
+ bool is_closest_child1 = (dist[1] < dist[0]);
+ if (is_closest_child1) {
+ int tmp = node_addr;
+ node_addr = node_addr_child1;
+ node_addr_child1 = tmp;
+ }
- ++stack_ptr;
- kernel_assert(stack_ptr < BVH_STACK_SIZE);
- traversal_stack[stack_ptr] = node_addr_child1;
- }
- else {
- /* One child was intersected. */
- if(traverse_mask == 2) {
- node_addr = node_addr_child1;
- }
- else if(traverse_mask == 0) {
- /* Neither child was intersected. */
- node_addr = traversal_stack[stack_ptr];
- --stack_ptr;
- }
- }
- }
+ ++stack_ptr;
+ kernel_assert(stack_ptr < BVH_STACK_SIZE);
+ traversal_stack[stack_ptr] = node_addr_child1;
+ }
+ else {
+ /* One child was intersected. */
+ if (traverse_mask == 2) {
+ node_addr = node_addr_child1;
+ }
+ else if (traverse_mask == 0) {
+ /* Neither child was intersected. */
+ node_addr = traversal_stack[stack_ptr];
+ --stack_ptr;
+ }
+ }
+ }
- /* if node is leaf, fetch triangle list */
- if(node_addr < 0) {
- float4 leaf = kernel_tex_fetch(__bvh_leaf_nodes, (-node_addr-1));
- int prim_addr = __float_as_int(leaf.x);
+ /* if node is leaf, fetch triangle list */
+ if (node_addr < 0) {
+ float4 leaf = kernel_tex_fetch(__bvh_leaf_nodes, (-node_addr - 1));
+ int prim_addr = __float_as_int(leaf.x);
- const int prim_addr2 = __float_as_int(leaf.y);
- const uint type = __float_as_int(leaf.w);
+ const int prim_addr2 = __float_as_int(leaf.y);
+ const uint type = __float_as_int(leaf.w);
- /* pop */
- node_addr = traversal_stack[stack_ptr];
- --stack_ptr;
+ /* pop */
+ node_addr = traversal_stack[stack_ptr];
+ --stack_ptr;
- /* primitive intersection */
- switch(type & PRIMITIVE_ALL) {
- case PRIMITIVE_TRIANGLE: {
- /* intersect ray against primitive */
- for(; prim_addr < prim_addr2; prim_addr++) {
- kernel_assert(kernel_tex_fetch(__prim_type, prim_addr) == type);
- if(triangle_intersect_local(kg,
- local_isect,
- P,
- dir,
- object,
- local_object,
- prim_addr,
- isect_t,
- lcg_state,
- max_hits)) {
- return true;
- }
- }
- break;
- }
+ /* primitive intersection */
+ switch (type & PRIMITIVE_ALL) {
+ case PRIMITIVE_TRIANGLE: {
+ /* intersect ray against primitive */
+ for (; prim_addr < prim_addr2; prim_addr++) {
+ kernel_assert(kernel_tex_fetch(__prim_type, prim_addr) == type);
+ if (triangle_intersect_local(kg,
+ local_isect,
+ P,
+ dir,
+ object,
+ local_object,
+ prim_addr,
+ isect_t,
+ lcg_state,
+ max_hits)) {
+ return true;
+ }
+ }
+ break;
+ }
#if BVH_FEATURE(BVH_MOTION)
- case PRIMITIVE_MOTION_TRIANGLE: {
- /* intersect ray against primitive */
- for(; prim_addr < prim_addr2; prim_addr++) {
- kernel_assert(kernel_tex_fetch(__prim_type, prim_addr) == type);
- if(motion_triangle_intersect_local(kg,
- local_isect,
- P,
- dir,
- ray->time,
- object,
- local_object,
- prim_addr,
- isect_t,
- lcg_state,
- max_hits)) {
- return true;
- }
- }
- break;
- }
+ case PRIMITIVE_MOTION_TRIANGLE: {
+ /* intersect ray against primitive */
+ for (; prim_addr < prim_addr2; prim_addr++) {
+ kernel_assert(kernel_tex_fetch(__prim_type, prim_addr) == type);
+ if (motion_triangle_intersect_local(kg,
+ local_isect,
+ P,
+ dir,
+ ray->time,
+ object,
+ local_object,
+ prim_addr,
+ isect_t,
+ lcg_state,
+ max_hits)) {
+ return true;
+ }
+ }
+ break;
+ }
#endif
- default: {
- break;
- }
- }
- }
- } while(node_addr != ENTRYPOINT_SENTINEL);
- } while(node_addr != ENTRYPOINT_SENTINEL);
+ default: {
+ break;
+ }
+ }
+ }
+ } while (node_addr != ENTRYPOINT_SENTINEL);
+ } while (node_addr != ENTRYPOINT_SENTINEL);
- return false;
+ return false;
}
ccl_device_inline bool BVH_FUNCTION_NAME(KernelGlobals *kg,
@@ -254,35 +247,20 @@ ccl_device_inline bool BVH_FUNCTION_NAME(KernelGlobals *kg,
uint *lcg_state,
int max_hits)
{
- switch(kernel_data.bvh.bvh_layout) {
+ switch (kernel_data.bvh.bvh_layout) {
#ifdef __KERNEL_AVX2__
- case BVH_LAYOUT_BVH8:
- return BVH_FUNCTION_FULL_NAME(OBVH)(kg,
- ray,
- local_isect,
- local_object,
- lcg_state,
- max_hits);
+ case BVH_LAYOUT_BVH8:
+ return BVH_FUNCTION_FULL_NAME(OBVH)(kg, ray, local_isect, local_object, lcg_state, max_hits);
#endif
#ifdef __QBVH__
- case BVH_LAYOUT_BVH4:
- return BVH_FUNCTION_FULL_NAME(QBVH)(kg,
- ray,
- local_isect,
- local_object,
- lcg_state,
- max_hits);
+ case BVH_LAYOUT_BVH4:
+ return BVH_FUNCTION_FULL_NAME(QBVH)(kg, ray, local_isect, local_object, lcg_state, max_hits);
#endif
- case BVH_LAYOUT_BVH2:
- return BVH_FUNCTION_FULL_NAME(BVH)(kg,
- ray,
- local_isect,
- local_object,
- lcg_state,
- max_hits);
- }
- kernel_assert(!"Should not happen");
- return false;
+ case BVH_LAYOUT_BVH2:
+ return BVH_FUNCTION_FULL_NAME(BVH)(kg, ray, local_isect, local_object, lcg_state, max_hits);
+ }
+ kernel_assert(!"Should not happen");
+ return false;
}
#undef BVH_FUNCTION_NAME
diff --git a/intern/cycles/kernel/bvh/bvh_nodes.h b/intern/cycles/kernel/bvh/bvh_nodes.h
index 060b3934a41..042630121c8 100644
--- a/intern/cycles/kernel/bvh/bvh_nodes.h
+++ b/intern/cycles/kernel/bvh/bvh_nodes.h
@@ -20,12 +20,12 @@ ccl_device_forceinline Transform bvh_unaligned_node_fetch_space(KernelGlobals *k
int node_addr,
int child)
{
- Transform space;
- const int child_addr = node_addr + child * 3;
- space.x = kernel_tex_fetch(__bvh_nodes, child_addr+1);
- space.y = kernel_tex_fetch(__bvh_nodes, child_addr+2);
- space.z = kernel_tex_fetch(__bvh_nodes, child_addr+3);
- return space;
+ Transform space;
+ const int child_addr = node_addr + child * 3;
+ space.x = kernel_tex_fetch(__bvh_nodes, child_addr + 1);
+ space.y = kernel_tex_fetch(__bvh_nodes, child_addr + 2);
+ space.z = kernel_tex_fetch(__bvh_nodes, child_addr + 3);
+ return space;
}
#if !defined(__KERNEL_SSE2__)
@@ -38,42 +38,41 @@ ccl_device_forceinline int bvh_aligned_node_intersect(KernelGlobals *kg,
float dist[2])
{
- /* fetch node data */
- float4 cnodes = kernel_tex_fetch(__bvh_nodes, node_addr+0);
- float4 node0 = kernel_tex_fetch(__bvh_nodes, node_addr+1);
- float4 node1 = kernel_tex_fetch(__bvh_nodes, node_addr+2);
- float4 node2 = kernel_tex_fetch(__bvh_nodes, node_addr+3);
-
- /* intersect ray against child nodes */
- float c0lox = (node0.x - P.x) * idir.x;
- float c0hix = (node0.z - P.x) * idir.x;
- float c0loy = (node1.x - P.y) * idir.y;
- float c0hiy = (node1.z - P.y) * idir.y;
- float c0loz = (node2.x - P.z) * idir.z;
- float c0hiz = (node2.z - P.z) * idir.z;
- float c0min = max4(0.0f, min(c0lox, c0hix), min(c0loy, c0hiy), min(c0loz, c0hiz));
- float c0max = min4(t, max(c0lox, c0hix), max(c0loy, c0hiy), max(c0loz, c0hiz));
-
- float c1lox = (node0.y - P.x) * idir.x;
- float c1hix = (node0.w - P.x) * idir.x;
- float c1loy = (node1.y - P.y) * idir.y;
- float c1hiy = (node1.w - P.y) * idir.y;
- float c1loz = (node2.y - P.z) * idir.z;
- float c1hiz = (node2.w - P.z) * idir.z;
- float c1min = max4(0.0f, min(c1lox, c1hix), min(c1loy, c1hiy), min(c1loz, c1hiz));
- float c1max = min4(t, max(c1lox, c1hix), max(c1loy, c1hiy), max(c1loz, c1hiz));
-
- dist[0] = c0min;
- dist[1] = c1min;
-
-#ifdef __VISIBILITY_FLAG__
- /* this visibility test gives a 5% performance hit, how to solve? */
- return (((c0max >= c0min) && (__float_as_uint(cnodes.x) & visibility))? 1: 0) |
- (((c1max >= c1min) && (__float_as_uint(cnodes.y) & visibility))? 2: 0);
-#else
- return ((c0max >= c0min)? 1: 0) |
- ((c1max >= c1min)? 2: 0);
-#endif
+ /* fetch node data */
+ float4 cnodes = kernel_tex_fetch(__bvh_nodes, node_addr + 0);
+ float4 node0 = kernel_tex_fetch(__bvh_nodes, node_addr + 1);
+ float4 node1 = kernel_tex_fetch(__bvh_nodes, node_addr + 2);
+ float4 node2 = kernel_tex_fetch(__bvh_nodes, node_addr + 3);
+
+ /* intersect ray against child nodes */
+ float c0lox = (node0.x - P.x) * idir.x;
+ float c0hix = (node0.z - P.x) * idir.x;
+ float c0loy = (node1.x - P.y) * idir.y;
+ float c0hiy = (node1.z - P.y) * idir.y;
+ float c0loz = (node2.x - P.z) * idir.z;
+ float c0hiz = (node2.z - P.z) * idir.z;
+ float c0min = max4(0.0f, min(c0lox, c0hix), min(c0loy, c0hiy), min(c0loz, c0hiz));
+ float c0max = min4(t, max(c0lox, c0hix), max(c0loy, c0hiy), max(c0loz, c0hiz));
+
+ float c1lox = (node0.y - P.x) * idir.x;
+ float c1hix = (node0.w - P.x) * idir.x;
+ float c1loy = (node1.y - P.y) * idir.y;
+ float c1hiy = (node1.w - P.y) * idir.y;
+ float c1loz = (node2.y - P.z) * idir.z;
+ float c1hiz = (node2.w - P.z) * idir.z;
+ float c1min = max4(0.0f, min(c1lox, c1hix), min(c1loy, c1hiy), min(c1loz, c1hiz));
+ float c1max = min4(t, max(c1lox, c1hix), max(c1loy, c1hiy), max(c1loz, c1hiz));
+
+ dist[0] = c0min;
+ dist[1] = c1min;
+
+# ifdef __VISIBILITY_FLAG__
+ /* this visibility test gives a 5% performance hit, how to solve? */
+ return (((c0max >= c0min) && (__float_as_uint(cnodes.x) & visibility)) ? 1 : 0) |
+ (((c1max >= c1min) && (__float_as_uint(cnodes.y) & visibility)) ? 2 : 0);
+# else
+ return ((c0max >= c0min) ? 1 : 0) | ((c1max >= c1min) ? 2 : 0);
+# endif
}
ccl_device_forceinline int bvh_aligned_node_intersect_robust(KernelGlobals *kg,
@@ -87,118 +86,115 @@ ccl_device_forceinline int bvh_aligned_node_intersect_robust(KernelGlobals *kg,
float dist[2])
{
- /* fetch node data */
- float4 cnodes = kernel_tex_fetch(__bvh_nodes, node_addr+0);
- float4 node0 = kernel_tex_fetch(__bvh_nodes, node_addr+1);
- float4 node1 = kernel_tex_fetch(__bvh_nodes, node_addr+2);
- float4 node2 = kernel_tex_fetch(__bvh_nodes, node_addr+3);
-
- /* intersect ray against child nodes */
- float c0lox = (node0.x - P.x) * idir.x;
- float c0hix = (node0.z - P.x) * idir.x;
- float c0loy = (node1.x - P.y) * idir.y;
- float c0hiy = (node1.z - P.y) * idir.y;
- float c0loz = (node2.x - P.z) * idir.z;
- float c0hiz = (node2.z - P.z) * idir.z;
- float c0min = max4(0.0f, min(c0lox, c0hix), min(c0loy, c0hiy), min(c0loz, c0hiz));
- float c0max = min4(t, max(c0lox, c0hix), max(c0loy, c0hiy), max(c0loz, c0hiz));
-
- float c1lox = (node0.y - P.x) * idir.x;
- float c1hix = (node0.w - P.x) * idir.x;
- float c1loy = (node1.y - P.y) * idir.y;
- float c1hiy = (node1.w - P.y) * idir.y;
- float c1loz = (node2.y - P.z) * idir.z;
- float c1hiz = (node2.w - P.z) * idir.z;
- float c1min = max4(0.0f, min(c1lox, c1hix), min(c1loy, c1hiy), min(c1loz, c1hiz));
- float c1max = min4(t, max(c1lox, c1hix), max(c1loy, c1hiy), max(c1loz, c1hiz));
-
- if(difl != 0.0f) {
- float hdiff = 1.0f + difl;
- float ldiff = 1.0f - difl;
- if(__float_as_int(cnodes.z) & PATH_RAY_CURVE) {
- c0min = max(ldiff * c0min, c0min - extmax);
- c0max = min(hdiff * c0max, c0max + extmax);
- }
- if(__float_as_int(cnodes.w) & PATH_RAY_CURVE) {
- c1min = max(ldiff * c1min, c1min - extmax);
- c1max = min(hdiff * c1max, c1max + extmax);
- }
- }
-
- dist[0] = c0min;
- dist[1] = c1min;
-
-#ifdef __VISIBILITY_FLAG__
- /* this visibility test gives a 5% performance hit, how to solve? */
- return (((c0max >= c0min) && (__float_as_uint(cnodes.x) & visibility))? 1: 0) |
- (((c1max >= c1min) && (__float_as_uint(cnodes.y) & visibility))? 2: 0);
-#else
- return ((c0max >= c0min)? 1: 0) |
- ((c1max >= c1min)? 2: 0);
-#endif
+ /* fetch node data */
+ float4 cnodes = kernel_tex_fetch(__bvh_nodes, node_addr + 0);
+ float4 node0 = kernel_tex_fetch(__bvh_nodes, node_addr + 1);
+ float4 node1 = kernel_tex_fetch(__bvh_nodes, node_addr + 2);
+ float4 node2 = kernel_tex_fetch(__bvh_nodes, node_addr + 3);
+
+ /* intersect ray against child nodes */
+ float c0lox = (node0.x - P.x) * idir.x;
+ float c0hix = (node0.z - P.x) * idir.x;
+ float c0loy = (node1.x - P.y) * idir.y;
+ float c0hiy = (node1.z - P.y) * idir.y;
+ float c0loz = (node2.x - P.z) * idir.z;
+ float c0hiz = (node2.z - P.z) * idir.z;
+ float c0min = max4(0.0f, min(c0lox, c0hix), min(c0loy, c0hiy), min(c0loz, c0hiz));
+ float c0max = min4(t, max(c0lox, c0hix), max(c0loy, c0hiy), max(c0loz, c0hiz));
+
+ float c1lox = (node0.y - P.x) * idir.x;
+ float c1hix = (node0.w - P.x) * idir.x;
+ float c1loy = (node1.y - P.y) * idir.y;
+ float c1hiy = (node1.w - P.y) * idir.y;
+ float c1loz = (node2.y - P.z) * idir.z;
+ float c1hiz = (node2.w - P.z) * idir.z;
+ float c1min = max4(0.0f, min(c1lox, c1hix), min(c1loy, c1hiy), min(c1loz, c1hiz));
+ float c1max = min4(t, max(c1lox, c1hix), max(c1loy, c1hiy), max(c1loz, c1hiz));
+
+ if (difl != 0.0f) {
+ float hdiff = 1.0f + difl;
+ float ldiff = 1.0f - difl;
+ if (__float_as_int(cnodes.z) & PATH_RAY_CURVE) {
+ c0min = max(ldiff * c0min, c0min - extmax);
+ c0max = min(hdiff * c0max, c0max + extmax);
+ }
+ if (__float_as_int(cnodes.w) & PATH_RAY_CURVE) {
+ c1min = max(ldiff * c1min, c1min - extmax);
+ c1max = min(hdiff * c1max, c1max + extmax);
+ }
+ }
+
+ dist[0] = c0min;
+ dist[1] = c1min;
+
+# ifdef __VISIBILITY_FLAG__
+ /* this visibility test gives a 5% performance hit, how to solve? */
+ return (((c0max >= c0min) && (__float_as_uint(cnodes.x) & visibility)) ? 1 : 0) |
+ (((c1max >= c1min) && (__float_as_uint(cnodes.y) & visibility)) ? 2 : 0);
+# else
+ return ((c0max >= c0min) ? 1 : 0) | ((c1max >= c1min) ? 2 : 0);
+# endif
}
-ccl_device_forceinline bool bvh_unaligned_node_intersect_child(
- KernelGlobals *kg,
- const float3 P,
- const float3 dir,
- const float t,
- int node_addr,
- int child,
- float dist[2])
+ccl_device_forceinline bool bvh_unaligned_node_intersect_child(KernelGlobals *kg,
+ const float3 P,
+ const float3 dir,
+ const float t,
+ int node_addr,
+ int child,
+ float dist[2])
{
- Transform space = bvh_unaligned_node_fetch_space(kg, node_addr, child);
- float3 aligned_dir = transform_direction(&space, dir);
- float3 aligned_P = transform_point(&space, P);
- float3 nrdir = -bvh_inverse_direction(aligned_dir);
- float3 lower_xyz = aligned_P * nrdir;
- float3 upper_xyz = lower_xyz - nrdir;
- const float near_x = min(lower_xyz.x, upper_xyz.x);
- const float near_y = min(lower_xyz.y, upper_xyz.y);
- const float near_z = min(lower_xyz.z, upper_xyz.z);
- const float far_x = max(lower_xyz.x, upper_xyz.x);
- const float far_y = max(lower_xyz.y, upper_xyz.y);
- const float far_z = max(lower_xyz.z, upper_xyz.z);
- const float tnear = max4(0.0f, near_x, near_y, near_z);
- const float tfar = min4(t, far_x, far_y, far_z);
- *dist = tnear;
- return tnear <= tfar;
+ Transform space = bvh_unaligned_node_fetch_space(kg, node_addr, child);
+ float3 aligned_dir = transform_direction(&space, dir);
+ float3 aligned_P = transform_point(&space, P);
+ float3 nrdir = -bvh_inverse_direction(aligned_dir);
+ float3 lower_xyz = aligned_P * nrdir;
+ float3 upper_xyz = lower_xyz - nrdir;
+ const float near_x = min(lower_xyz.x, upper_xyz.x);
+ const float near_y = min(lower_xyz.y, upper_xyz.y);
+ const float near_z = min(lower_xyz.z, upper_xyz.z);
+ const float far_x = max(lower_xyz.x, upper_xyz.x);
+ const float far_y = max(lower_xyz.y, upper_xyz.y);
+ const float far_z = max(lower_xyz.z, upper_xyz.z);
+ const float tnear = max4(0.0f, near_x, near_y, near_z);
+ const float tfar = min4(t, far_x, far_y, far_z);
+ *dist = tnear;
+ return tnear <= tfar;
}
-ccl_device_forceinline bool bvh_unaligned_node_intersect_child_robust(
- KernelGlobals *kg,
- const float3 P,
- const float3 dir,
- const float t,
- const float difl,
- int node_addr,
- int child,
- float dist[2])
+ccl_device_forceinline bool bvh_unaligned_node_intersect_child_robust(KernelGlobals *kg,
+ const float3 P,
+ const float3 dir,
+ const float t,
+ const float difl,
+ int node_addr,
+ int child,
+ float dist[2])
{
- Transform space = bvh_unaligned_node_fetch_space(kg, node_addr, child);
- float3 aligned_dir = transform_direction(&space, dir);
- float3 aligned_P = transform_point(&space, P);
- float3 nrdir = -bvh_inverse_direction(aligned_dir);
- float3 tLowerXYZ = aligned_P * nrdir;
- float3 tUpperXYZ = tLowerXYZ - nrdir;
- const float near_x = min(tLowerXYZ.x, tUpperXYZ.x);
- const float near_y = min(tLowerXYZ.y, tUpperXYZ.y);
- const float near_z = min(tLowerXYZ.z, tUpperXYZ.z);
- const float far_x = max(tLowerXYZ.x, tUpperXYZ.x);
- const float far_y = max(tLowerXYZ.y, tUpperXYZ.y);
- const float far_z = max(tLowerXYZ.z, tUpperXYZ.z);
- const float tnear = max4(0.0f, near_x, near_y, near_z);
- const float tfar = min4(t, far_x, far_y, far_z);
- *dist = tnear;
- if(difl != 0.0f) {
- /* TODO(sergey): Same as for QBVH, needs a proper use. */
- const float round_down = 1.0f - difl;
- const float round_up = 1.0f + difl;
- return round_down*tnear <= round_up*tfar;
- }
- else {
- return tnear <= tfar;
- }
+ Transform space = bvh_unaligned_node_fetch_space(kg, node_addr, child);
+ float3 aligned_dir = transform_direction(&space, dir);
+ float3 aligned_P = transform_point(&space, P);
+ float3 nrdir = -bvh_inverse_direction(aligned_dir);
+ float3 tLowerXYZ = aligned_P * nrdir;
+ float3 tUpperXYZ = tLowerXYZ - nrdir;
+ const float near_x = min(tLowerXYZ.x, tUpperXYZ.x);
+ const float near_y = min(tLowerXYZ.y, tUpperXYZ.y);
+ const float near_z = min(tLowerXYZ.z, tUpperXYZ.z);
+ const float far_x = max(tLowerXYZ.x, tUpperXYZ.x);
+ const float far_y = max(tLowerXYZ.y, tUpperXYZ.y);
+ const float far_z = max(tLowerXYZ.z, tUpperXYZ.z);
+ const float tnear = max4(0.0f, near_x, near_y, near_z);
+ const float tfar = min4(t, far_x, far_y, far_z);
+ *dist = tnear;
+ if (difl != 0.0f) {
+ /* TODO(sergey): Same as for QBVH, needs a proper use. */
+ const float round_down = 1.0f - difl;
+ const float round_up = 1.0f + difl;
+ return round_down * tnear <= round_up * tfar;
+ }
+ else {
+ return tnear <= tfar;
+ }
}
ccl_device_forceinline int bvh_unaligned_node_intersect(KernelGlobals *kg,
@@ -210,25 +206,25 @@ ccl_device_forceinline int bvh_unaligned_node_intersect(KernelGlobals *kg,
const uint visibility,
float dist[2])
{
- int mask = 0;
- float4 cnodes = kernel_tex_fetch(__bvh_nodes, node_addr+0);
- if(bvh_unaligned_node_intersect_child(kg, P, dir, t, node_addr, 0, &dist[0])) {
-#ifdef __VISIBILITY_FLAG__
- if((__float_as_uint(cnodes.x) & visibility))
-#endif
- {
- mask |= 1;
- }
- }
- if(bvh_unaligned_node_intersect_child(kg, P, dir, t, node_addr, 1, &dist[1])) {
-#ifdef __VISIBILITY_FLAG__
- if((__float_as_uint(cnodes.y) & visibility))
-#endif
- {
- mask |= 2;
- }
- }
- return mask;
+ int mask = 0;
+ float4 cnodes = kernel_tex_fetch(__bvh_nodes, node_addr + 0);
+ if (bvh_unaligned_node_intersect_child(kg, P, dir, t, node_addr, 0, &dist[0])) {
+# ifdef __VISIBILITY_FLAG__
+ if ((__float_as_uint(cnodes.x) & visibility))
+# endif
+ {
+ mask |= 1;
+ }
+ }
+ if (bvh_unaligned_node_intersect_child(kg, P, dir, t, node_addr, 1, &dist[1])) {
+# ifdef __VISIBILITY_FLAG__
+ if ((__float_as_uint(cnodes.y) & visibility))
+# endif
+ {
+ mask |= 2;
+ }
+ }
+ return mask;
}
ccl_device_forceinline int bvh_unaligned_node_intersect_robust(KernelGlobals *kg,
@@ -242,25 +238,25 @@ ccl_device_forceinline int bvh_unaligned_node_intersect_robust(KernelGlobals *kg
const uint visibility,
float dist[2])
{
- int mask = 0;
- float4 cnodes = kernel_tex_fetch(__bvh_nodes, node_addr+0);
- if(bvh_unaligned_node_intersect_child_robust(kg, P, dir, t, difl, node_addr, 0, &dist[0])) {
-#ifdef __VISIBILITY_FLAG__
- if((__float_as_uint(cnodes.x) & visibility))
-#endif
- {
- mask |= 1;
- }
- }
- if(bvh_unaligned_node_intersect_child_robust(kg, P, dir, t, difl, node_addr, 1, &dist[1])) {
-#ifdef __VISIBILITY_FLAG__
- if((__float_as_uint(cnodes.y) & visibility))
-#endif
- {
- mask |= 2;
- }
- }
- return mask;
+ int mask = 0;
+ float4 cnodes = kernel_tex_fetch(__bvh_nodes, node_addr + 0);
+ if (bvh_unaligned_node_intersect_child_robust(kg, P, dir, t, difl, node_addr, 0, &dist[0])) {
+# ifdef __VISIBILITY_FLAG__
+ if ((__float_as_uint(cnodes.x) & visibility))
+# endif
+ {
+ mask |= 1;
+ }
+ }
+ if (bvh_unaligned_node_intersect_child_robust(kg, P, dir, t, difl, node_addr, 1, &dist[1])) {
+# ifdef __VISIBILITY_FLAG__
+ if ((__float_as_uint(cnodes.y) & visibility))
+# endif
+ {
+ mask |= 2;
+ }
+ }
+ return mask;
}
ccl_device_forceinline int bvh_node_intersect(KernelGlobals *kg,
@@ -272,26 +268,13 @@ ccl_device_forceinline int bvh_node_intersect(KernelGlobals *kg,
const uint visibility,
float dist[2])
{
- float4 node = kernel_tex_fetch(__bvh_nodes, node_addr);
- if(__float_as_uint(node.x) & PATH_RAY_NODE_UNALIGNED) {
- return bvh_unaligned_node_intersect(kg,
- P,
- dir,
- idir,
- t,
- node_addr,
- visibility,
- dist);
- }
- else {
- return bvh_aligned_node_intersect(kg,
- P,
- idir,
- t,
- node_addr,
- visibility,
- dist);
- }
+ float4 node = kernel_tex_fetch(__bvh_nodes, node_addr);
+ if (__float_as_uint(node.x) & PATH_RAY_NODE_UNALIGNED) {
+ return bvh_unaligned_node_intersect(kg, P, dir, idir, t, node_addr, visibility, dist);
+ }
+ else {
+ return bvh_aligned_node_intersect(kg, P, idir, t, node_addr, visibility, dist);
+ }
}
ccl_device_forceinline int bvh_node_intersect_robust(KernelGlobals *kg,
@@ -305,279 +288,244 @@ ccl_device_forceinline int bvh_node_intersect_robust(KernelGlobals *kg,
const uint visibility,
float dist[2])
{
- float4 node = kernel_tex_fetch(__bvh_nodes, node_addr);
- if(__float_as_uint(node.x) & PATH_RAY_NODE_UNALIGNED) {
- return bvh_unaligned_node_intersect_robust(kg,
- P,
- dir,
- idir,
- t,
- difl,
- extmax,
- node_addr,
- visibility,
- dist);
- }
- else {
- return bvh_aligned_node_intersect_robust(kg,
- P,
- idir,
- t,
- difl,
- extmax,
- node_addr,
- visibility,
- dist);
- }
+ float4 node = kernel_tex_fetch(__bvh_nodes, node_addr);
+ if (__float_as_uint(node.x) & PATH_RAY_NODE_UNALIGNED) {
+ return bvh_unaligned_node_intersect_robust(
+ kg, P, dir, idir, t, difl, extmax, node_addr, visibility, dist);
+ }
+ else {
+ return bvh_aligned_node_intersect_robust(
+ kg, P, idir, t, difl, extmax, node_addr, visibility, dist);
+ }
}
-#else /* !defined(__KERNEL_SSE2__) */
-
-int ccl_device_forceinline bvh_aligned_node_intersect(
- KernelGlobals *kg,
- const float3& P,
- const float3& dir,
- const ssef& tsplat,
- const ssef Psplat[3],
- const ssef idirsplat[3],
- const shuffle_swap_t shufflexyz[3],
- const int node_addr,
- const uint visibility,
- float dist[2])
+#else /* !defined(__KERNEL_SSE2__) */
+
+int ccl_device_forceinline bvh_aligned_node_intersect(KernelGlobals *kg,
+ const float3 &P,
+ const float3 &dir,
+ const ssef &tsplat,
+ const ssef Psplat[3],
+ const ssef idirsplat[3],
+ const shuffle_swap_t shufflexyz[3],
+ const int node_addr,
+ const uint visibility,
+ float dist[2])
{
- /* Intersect two child bounding boxes, SSE3 version adapted from Embree */
- const ssef pn = cast(ssei(0, 0, 0x80000000, 0x80000000));
+ /* Intersect two child bounding boxes, SSE3 version adapted from Embree */
+ const ssef pn = cast(ssei(0, 0, 0x80000000, 0x80000000));
- /* fetch node data */
- const ssef *bvh_nodes = (ssef*)kg->__bvh_nodes.data + node_addr;
+ /* fetch node data */
+ const ssef *bvh_nodes = (ssef *)kg->__bvh_nodes.data + node_addr;
- /* intersect ray against child nodes */
- const ssef tminmaxx = (shuffle_swap(bvh_nodes[1], shufflexyz[0]) - Psplat[0]) * idirsplat[0];
- const ssef tminmaxy = (shuffle_swap(bvh_nodes[2], shufflexyz[1]) - Psplat[1]) * idirsplat[1];
- const ssef tminmaxz = (shuffle_swap(bvh_nodes[3], shufflexyz[2]) - Psplat[2]) * idirsplat[2];
+ /* intersect ray against child nodes */
+ const ssef tminmaxx = (shuffle_swap(bvh_nodes[1], shufflexyz[0]) - Psplat[0]) * idirsplat[0];
+ const ssef tminmaxy = (shuffle_swap(bvh_nodes[2], shufflexyz[1]) - Psplat[1]) * idirsplat[1];
+ const ssef tminmaxz = (shuffle_swap(bvh_nodes[3], shufflexyz[2]) - Psplat[2]) * idirsplat[2];
- /* calculate { c0min, c1min, -c0max, -c1max} */
- ssef minmax = max(max(tminmaxx, tminmaxy), max(tminmaxz, tsplat));
- const ssef tminmax = minmax ^ pn;
- const sseb lrhit = tminmax <= shuffle<2, 3, 0, 1>(tminmax);
+ /* calculate { c0min, c1min, -c0max, -c1max} */
+ ssef minmax = max(max(tminmaxx, tminmaxy), max(tminmaxz, tsplat));
+ const ssef tminmax = minmax ^ pn;
+ const sseb lrhit = tminmax <= shuffle<2, 3, 0, 1>(tminmax);
- dist[0] = tminmax[0];
- dist[1] = tminmax[1];
+ dist[0] = tminmax[0];
+ dist[1] = tminmax[1];
- int mask = movemask(lrhit);
+ int mask = movemask(lrhit);
# ifdef __VISIBILITY_FLAG__
- /* this visibility test gives a 5% performance hit, how to solve? */
- float4 cnodes = kernel_tex_fetch(__bvh_nodes, node_addr+0);
- int cmask = (((mask & 1) && (__float_as_uint(cnodes.x) & visibility))? 1: 0) |
- (((mask & 2) && (__float_as_uint(cnodes.y) & visibility))? 2: 0);
- return cmask;
+ /* this visibility test gives a 5% performance hit, how to solve? */
+ float4 cnodes = kernel_tex_fetch(__bvh_nodes, node_addr + 0);
+ int cmask = (((mask & 1) && (__float_as_uint(cnodes.x) & visibility)) ? 1 : 0) |
+ (((mask & 2) && (__float_as_uint(cnodes.y) & visibility)) ? 2 : 0);
+ return cmask;
# else
- return mask & 3;
+ return mask & 3;
# endif
}
-ccl_device_forceinline int bvh_aligned_node_intersect_robust(
- KernelGlobals *kg,
- const float3& P,
- const float3& dir,
- const ssef& tsplat,
- const ssef Psplat[3],
- const ssef idirsplat[3],
- const shuffle_swap_t shufflexyz[3],
- const float difl,
- const float extmax,
- const int nodeAddr,
- const uint visibility,
- float dist[2])
+ccl_device_forceinline int bvh_aligned_node_intersect_robust(KernelGlobals *kg,
+ const float3 &P,
+ const float3 &dir,
+ const ssef &tsplat,
+ const ssef Psplat[3],
+ const ssef idirsplat[3],
+ const shuffle_swap_t shufflexyz[3],
+ const float difl,
+ const float extmax,
+ const int nodeAddr,
+ const uint visibility,
+ float dist[2])
{
- /* Intersect two child bounding boxes, SSE3 version adapted from Embree */
- const ssef pn = cast(ssei(0, 0, 0x80000000, 0x80000000));
-
- /* fetch node data */
- const ssef *bvh_nodes = (ssef*)kg->__bvh_nodes.data + nodeAddr;
-
- /* intersect ray against child nodes */
- const ssef tminmaxx = (shuffle_swap(bvh_nodes[1], shufflexyz[0]) - Psplat[0]) * idirsplat[0];
- const ssef tminmaxy = (shuffle_swap(bvh_nodes[2], shufflexyz[1]) - Psplat[1]) * idirsplat[1];
- const ssef tminmaxz = (shuffle_swap(bvh_nodes[3], shufflexyz[2]) - Psplat[2]) * idirsplat[2];
-
- /* calculate { c0min, c1min, -c0max, -c1max} */
- ssef minmax = max(max(tminmaxx, tminmaxy), max(tminmaxz, tsplat));
- const ssef tminmax = minmax ^ pn;
-
- if(difl != 0.0f) {
- float4 cnodes = kernel_tex_fetch(__bvh_nodes, nodeAddr+0);
- float4 *tminmaxview = (float4*)&tminmax;
- float& c0min = tminmaxview->x, &c1min = tminmaxview->y;
- float& c0max = tminmaxview->z, &c1max = tminmaxview->w;
- float hdiff = 1.0f + difl;
- float ldiff = 1.0f - difl;
- if(__float_as_int(cnodes.x) & PATH_RAY_CURVE) {
- c0min = max(ldiff * c0min, c0min - extmax);
- c0max = min(hdiff * c0max, c0max + extmax);
- }
- if(__float_as_int(cnodes.y) & PATH_RAY_CURVE) {
- c1min = max(ldiff * c1min, c1min - extmax);
- c1max = min(hdiff * c1max, c1max + extmax);
- }
- }
-
- const sseb lrhit = tminmax <= shuffle<2, 3, 0, 1>(tminmax);
-
- dist[0] = tminmax[0];
- dist[1] = tminmax[1];
-
- int mask = movemask(lrhit);
+ /* Intersect two child bounding boxes, SSE3 version adapted from Embree */
+ const ssef pn = cast(ssei(0, 0, 0x80000000, 0x80000000));
+
+ /* fetch node data */
+ const ssef *bvh_nodes = (ssef *)kg->__bvh_nodes.data + nodeAddr;
+
+ /* intersect ray against child nodes */
+ const ssef tminmaxx = (shuffle_swap(bvh_nodes[1], shufflexyz[0]) - Psplat[0]) * idirsplat[0];
+ const ssef tminmaxy = (shuffle_swap(bvh_nodes[2], shufflexyz[1]) - Psplat[1]) * idirsplat[1];
+ const ssef tminmaxz = (shuffle_swap(bvh_nodes[3], shufflexyz[2]) - Psplat[2]) * idirsplat[2];
+
+ /* calculate { c0min, c1min, -c0max, -c1max} */
+ ssef minmax = max(max(tminmaxx, tminmaxy), max(tminmaxz, tsplat));
+ const ssef tminmax = minmax ^ pn;
+
+ if (difl != 0.0f) {
+ float4 cnodes = kernel_tex_fetch(__bvh_nodes, nodeAddr + 0);
+ float4 *tminmaxview = (float4 *)&tminmax;
+ float &c0min = tminmaxview->x, &c1min = tminmaxview->y;
+ float &c0max = tminmaxview->z, &c1max = tminmaxview->w;
+ float hdiff = 1.0f + difl;
+ float ldiff = 1.0f - difl;
+ if (__float_as_int(cnodes.x) & PATH_RAY_CURVE) {
+ c0min = max(ldiff * c0min, c0min - extmax);
+ c0max = min(hdiff * c0max, c0max + extmax);
+ }
+ if (__float_as_int(cnodes.y) & PATH_RAY_CURVE) {
+ c1min = max(ldiff * c1min, c1min - extmax);
+ c1max = min(hdiff * c1max, c1max + extmax);
+ }
+ }
+
+ const sseb lrhit = tminmax <= shuffle<2, 3, 0, 1>(tminmax);
+
+ dist[0] = tminmax[0];
+ dist[1] = tminmax[1];
+
+ int mask = movemask(lrhit);
# ifdef __VISIBILITY_FLAG__
- /* this visibility test gives a 5% performance hit, how to solve? */
- float4 cnodes = kernel_tex_fetch(__bvh_nodes, nodeAddr+0);
- int cmask = (((mask & 1) && (__float_as_uint(cnodes.x) & visibility))? 1: 0) |
- (((mask & 2) && (__float_as_uint(cnodes.y) & visibility))? 2: 0);
- return cmask;
+ /* this visibility test gives a 5% performance hit, how to solve? */
+ float4 cnodes = kernel_tex_fetch(__bvh_nodes, nodeAddr + 0);
+ int cmask = (((mask & 1) && (__float_as_uint(cnodes.x) & visibility)) ? 1 : 0) |
+ (((mask & 2) && (__float_as_uint(cnodes.y) & visibility)) ? 2 : 0);
+ return cmask;
# else
- return mask & 3;
+ return mask & 3;
# endif
}
ccl_device_forceinline int bvh_unaligned_node_intersect(KernelGlobals *kg,
const float3 P,
const float3 dir,
- const ssef& isect_near,
- const ssef& isect_far,
+ const ssef &isect_near,
+ const ssef &isect_far,
const int node_addr,
const uint visibility,
float dist[2])
{
- Transform space0 = bvh_unaligned_node_fetch_space(kg, node_addr, 0);
- Transform space1 = bvh_unaligned_node_fetch_space(kg, node_addr, 1);
-
- float3 aligned_dir0 = transform_direction(&space0, dir),
- aligned_dir1 = transform_direction(&space1, dir);
- float3 aligned_P0 = transform_point(&space0, P),
- aligned_P1 = transform_point(&space1, P);
- float3 nrdir0 = -bvh_inverse_direction(aligned_dir0),
- nrdir1 = -bvh_inverse_direction(aligned_dir1);
-
- ssef lower_x = ssef(aligned_P0.x * nrdir0.x,
- aligned_P1.x * nrdir1.x,
- 0.0f, 0.0f),
- lower_y = ssef(aligned_P0.y * nrdir0.y,
- aligned_P1.y * nrdir1.y,
- 0.0f,
- 0.0f),
- lower_z = ssef(aligned_P0.z * nrdir0.z,
- aligned_P1.z * nrdir1.z,
- 0.0f,
- 0.0f);
-
- ssef upper_x = lower_x - ssef(nrdir0.x, nrdir1.x, 0.0f, 0.0f),
- upper_y = lower_y - ssef(nrdir0.y, nrdir1.y, 0.0f, 0.0f),
- upper_z = lower_z - ssef(nrdir0.z, nrdir1.z, 0.0f, 0.0f);
-
- ssef tnear_x = min(lower_x, upper_x);
- ssef tnear_y = min(lower_y, upper_y);
- ssef tnear_z = min(lower_z, upper_z);
- ssef tfar_x = max(lower_x, upper_x);
- ssef tfar_y = max(lower_y, upper_y);
- ssef tfar_z = max(lower_z, upper_z);
-
- const ssef tnear = max4(isect_near, tnear_x, tnear_y, tnear_z);
- const ssef tfar = min4(isect_far, tfar_x, tfar_y, tfar_z);
- sseb vmask = tnear <= tfar;
- dist[0] = tnear.f[0];
- dist[1] = tnear.f[1];
-
- int mask = (int)movemask(vmask);
+ Transform space0 = bvh_unaligned_node_fetch_space(kg, node_addr, 0);
+ Transform space1 = bvh_unaligned_node_fetch_space(kg, node_addr, 1);
+
+ float3 aligned_dir0 = transform_direction(&space0, dir),
+ aligned_dir1 = transform_direction(&space1, dir);
+ float3 aligned_P0 = transform_point(&space0, P), aligned_P1 = transform_point(&space1, P);
+ float3 nrdir0 = -bvh_inverse_direction(aligned_dir0),
+ nrdir1 = -bvh_inverse_direction(aligned_dir1);
+
+ ssef lower_x = ssef(aligned_P0.x * nrdir0.x, aligned_P1.x * nrdir1.x, 0.0f, 0.0f),
+ lower_y = ssef(aligned_P0.y * nrdir0.y, aligned_P1.y * nrdir1.y, 0.0f, 0.0f),
+ lower_z = ssef(aligned_P0.z * nrdir0.z, aligned_P1.z * nrdir1.z, 0.0f, 0.0f);
+
+ ssef upper_x = lower_x - ssef(nrdir0.x, nrdir1.x, 0.0f, 0.0f),
+ upper_y = lower_y - ssef(nrdir0.y, nrdir1.y, 0.0f, 0.0f),
+ upper_z = lower_z - ssef(nrdir0.z, nrdir1.z, 0.0f, 0.0f);
+
+ ssef tnear_x = min(lower_x, upper_x);
+ ssef tnear_y = min(lower_y, upper_y);
+ ssef tnear_z = min(lower_z, upper_z);
+ ssef tfar_x = max(lower_x, upper_x);
+ ssef tfar_y = max(lower_y, upper_y);
+ ssef tfar_z = max(lower_z, upper_z);
+
+ const ssef tnear = max4(isect_near, tnear_x, tnear_y, tnear_z);
+ const ssef tfar = min4(isect_far, tfar_x, tfar_y, tfar_z);
+ sseb vmask = tnear <= tfar;
+ dist[0] = tnear.f[0];
+ dist[1] = tnear.f[1];
+
+ int mask = (int)movemask(vmask);
# ifdef __VISIBILITY_FLAG__
- /* this visibility test gives a 5% performance hit, how to solve? */
- float4 cnodes = kernel_tex_fetch(__bvh_nodes, node_addr+0);
- int cmask = (((mask & 1) && (__float_as_uint(cnodes.x) & visibility))? 1: 0) |
- (((mask & 2) && (__float_as_uint(cnodes.y) & visibility))? 2: 0);
- return cmask;
+ /* this visibility test gives a 5% performance hit, how to solve? */
+ float4 cnodes = kernel_tex_fetch(__bvh_nodes, node_addr + 0);
+ int cmask = (((mask & 1) && (__float_as_uint(cnodes.x) & visibility)) ? 1 : 0) |
+ (((mask & 2) && (__float_as_uint(cnodes.y) & visibility)) ? 2 : 0);
+ return cmask;
# else
- return mask & 3;
+ return mask & 3;
# endif
}
ccl_device_forceinline int bvh_unaligned_node_intersect_robust(KernelGlobals *kg,
const float3 P,
const float3 dir,
- const ssef& isect_near,
- const ssef& isect_far,
+ const ssef &isect_near,
+ const ssef &isect_far,
const float difl,
const int node_addr,
const uint visibility,
float dist[2])
{
- Transform space0 = bvh_unaligned_node_fetch_space(kg, node_addr, 0);
- Transform space1 = bvh_unaligned_node_fetch_space(kg, node_addr, 1);
-
- float3 aligned_dir0 = transform_direction(&space0, dir),
- aligned_dir1 = transform_direction(&space1, dir);
- float3 aligned_P0 = transform_point(&space0, P),
- aligned_P1 = transform_point(&space1, P);
- float3 nrdir0 = -bvh_inverse_direction(aligned_dir0),
- nrdir1 = -bvh_inverse_direction(aligned_dir1);
-
- ssef lower_x = ssef(aligned_P0.x * nrdir0.x,
- aligned_P1.x * nrdir1.x,
- 0.0f, 0.0f),
- lower_y = ssef(aligned_P0.y * nrdir0.y,
- aligned_P1.y * nrdir1.y,
- 0.0f,
- 0.0f),
- lower_z = ssef(aligned_P0.z * nrdir0.z,
- aligned_P1.z * nrdir1.z,
- 0.0f,
- 0.0f);
-
- ssef upper_x = lower_x - ssef(nrdir0.x, nrdir1.x, 0.0f, 0.0f),
- upper_y = lower_y - ssef(nrdir0.y, nrdir1.y, 0.0f, 0.0f),
- upper_z = lower_z - ssef(nrdir0.z, nrdir1.z, 0.0f, 0.0f);
-
- ssef tnear_x = min(lower_x, upper_x);
- ssef tnear_y = min(lower_y, upper_y);
- ssef tnear_z = min(lower_z, upper_z);
- ssef tfar_x = max(lower_x, upper_x);
- ssef tfar_y = max(lower_y, upper_y);
- ssef tfar_z = max(lower_z, upper_z);
-
- const ssef tnear = max4(isect_near, tnear_x, tnear_y, tnear_z);
- const ssef tfar = min4(isect_far, tfar_x, tfar_y, tfar_z);
- sseb vmask;
- if(difl != 0.0f) {
- const float round_down = 1.0f - difl;
- const float round_up = 1.0f + difl;
- vmask = round_down*tnear <= round_up*tfar;
- }
- else {
- vmask = tnear <= tfar;
- }
-
- dist[0] = tnear.f[0];
- dist[1] = tnear.f[1];
-
- int mask = (int)movemask(vmask);
+ Transform space0 = bvh_unaligned_node_fetch_space(kg, node_addr, 0);
+ Transform space1 = bvh_unaligned_node_fetch_space(kg, node_addr, 1);
+
+ float3 aligned_dir0 = transform_direction(&space0, dir),
+ aligned_dir1 = transform_direction(&space1, dir);
+ float3 aligned_P0 = transform_point(&space0, P), aligned_P1 = transform_point(&space1, P);
+ float3 nrdir0 = -bvh_inverse_direction(aligned_dir0),
+ nrdir1 = -bvh_inverse_direction(aligned_dir1);
+
+ ssef lower_x = ssef(aligned_P0.x * nrdir0.x, aligned_P1.x * nrdir1.x, 0.0f, 0.0f),
+ lower_y = ssef(aligned_P0.y * nrdir0.y, aligned_P1.y * nrdir1.y, 0.0f, 0.0f),
+ lower_z = ssef(aligned_P0.z * nrdir0.z, aligned_P1.z * nrdir1.z, 0.0f, 0.0f);
+
+ ssef upper_x = lower_x - ssef(nrdir0.x, nrdir1.x, 0.0f, 0.0f),
+ upper_y = lower_y - ssef(nrdir0.y, nrdir1.y, 0.0f, 0.0f),
+ upper_z = lower_z - ssef(nrdir0.z, nrdir1.z, 0.0f, 0.0f);
+
+ ssef tnear_x = min(lower_x, upper_x);
+ ssef tnear_y = min(lower_y, upper_y);
+ ssef tnear_z = min(lower_z, upper_z);
+ ssef tfar_x = max(lower_x, upper_x);
+ ssef tfar_y = max(lower_y, upper_y);
+ ssef tfar_z = max(lower_z, upper_z);
+
+ const ssef tnear = max4(isect_near, tnear_x, tnear_y, tnear_z);
+ const ssef tfar = min4(isect_far, tfar_x, tfar_y, tfar_z);
+ sseb vmask;
+ if (difl != 0.0f) {
+ const float round_down = 1.0f - difl;
+ const float round_up = 1.0f + difl;
+ vmask = round_down * tnear <= round_up * tfar;
+ }
+ else {
+ vmask = tnear <= tfar;
+ }
+
+ dist[0] = tnear.f[0];
+ dist[1] = tnear.f[1];
+
+ int mask = (int)movemask(vmask);
# ifdef __VISIBILITY_FLAG__
- /* this visibility test gives a 5% performance hit, how to solve? */
- float4 cnodes = kernel_tex_fetch(__bvh_nodes, node_addr+0);
- int cmask = (((mask & 1) && (__float_as_uint(cnodes.x) & visibility))? 1: 0) |
- (((mask & 2) && (__float_as_uint(cnodes.y) & visibility))? 2: 0);
- return cmask;
+ /* this visibility test gives a 5% performance hit, how to solve? */
+ float4 cnodes = kernel_tex_fetch(__bvh_nodes, node_addr + 0);
+ int cmask = (((mask & 1) && (__float_as_uint(cnodes.x) & visibility)) ? 1 : 0) |
+ (((mask & 2) && (__float_as_uint(cnodes.y) & visibility)) ? 2 : 0);
+ return cmask;
# else
- return mask & 3;
+ return mask & 3;
# endif
}
ccl_device_forceinline int bvh_node_intersect(KernelGlobals *kg,
- const float3& P,
- const float3& dir,
- const ssef& isect_near,
- const ssef& isect_far,
- const ssef& tsplat,
+ const float3 &P,
+ const float3 &dir,
+ const ssef &isect_near,
+ const ssef &isect_far,
+ const ssef &tsplat,
const ssef Psplat[3],
const ssef idirsplat[3],
const shuffle_swap_t shufflexyz[3],
@@ -585,37 +533,23 @@ ccl_device_forceinline int bvh_node_intersect(KernelGlobals *kg,
const uint visibility,
float dist[2])
{
- float4 node = kernel_tex_fetch(__bvh_nodes, node_addr);
- if(__float_as_uint(node.x) & PATH_RAY_NODE_UNALIGNED) {
- return bvh_unaligned_node_intersect(kg,
- P,
- dir,
- isect_near,
- isect_far,
- node_addr,
- visibility,
- dist);
- }
- else {
- return bvh_aligned_node_intersect(kg,
- P,
- dir,
- tsplat,
- Psplat,
- idirsplat,
- shufflexyz,
- node_addr,
- visibility,
- dist);
- }
+ float4 node = kernel_tex_fetch(__bvh_nodes, node_addr);
+ if (__float_as_uint(node.x) & PATH_RAY_NODE_UNALIGNED) {
+ return bvh_unaligned_node_intersect(
+ kg, P, dir, isect_near, isect_far, node_addr, visibility, dist);
+ }
+ else {
+ return bvh_aligned_node_intersect(
+ kg, P, dir, tsplat, Psplat, idirsplat, shufflexyz, node_addr, visibility, dist);
+ }
}
ccl_device_forceinline int bvh_node_intersect_robust(KernelGlobals *kg,
- const float3& P,
- const float3& dir,
- const ssef& isect_near,
- const ssef& isect_far,
- const ssef& tsplat,
+ const float3 &P,
+ const float3 &dir,
+ const ssef &isect_near,
+ const ssef &isect_far,
+ const ssef &tsplat,
const ssef Psplat[3],
const ssef idirsplat[3],
const shuffle_swap_t shufflexyz[3],
@@ -625,31 +559,24 @@ ccl_device_forceinline int bvh_node_intersect_robust(KernelGlobals *kg,
const uint visibility,
float dist[2])
{
- float4 node = kernel_tex_fetch(__bvh_nodes, node_addr);
- if(__float_as_uint(node.x) & PATH_RAY_NODE_UNALIGNED) {
- return bvh_unaligned_node_intersect_robust(kg,
- P,
- dir,
- isect_near,
- isect_far,
- difl,
- node_addr,
- visibility,
- dist);
- }
- else {
- return bvh_aligned_node_intersect_robust(kg,
- P,
- dir,
- tsplat,
- Psplat,
- idirsplat,
- shufflexyz,
- difl,
- extmax,
- node_addr,
- visibility,
- dist);
- }
+ float4 node = kernel_tex_fetch(__bvh_nodes, node_addr);
+ if (__float_as_uint(node.x) & PATH_RAY_NODE_UNALIGNED) {
+ return bvh_unaligned_node_intersect_robust(
+ kg, P, dir, isect_near, isect_far, difl, node_addr, visibility, dist);
+ }
+ else {
+ return bvh_aligned_node_intersect_robust(kg,
+ P,
+ dir,
+ tsplat,
+ Psplat,
+ idirsplat,
+ shufflexyz,
+ difl,
+ extmax,
+ node_addr,
+ visibility,
+ dist);
+ }
}
-#endif /* !defined(__KERNEL_SSE2__) */
+#endif /* !defined(__KERNEL_SSE2__) */
diff --git a/intern/cycles/kernel/bvh/bvh_shadow_all.h b/intern/cycles/kernel/bvh/bvh_shadow_all.h
index d8e089711ee..b362779549c 100644
--- a/intern/cycles/kernel/bvh/bvh_shadow_all.h
+++ b/intern/cycles/kernel/bvh/bvh_shadow_all.h
@@ -19,9 +19,9 @@
#ifdef __QBVH__
# include "kernel/bvh/qbvh_shadow_all.h"
-#ifdef __KERNEL_AVX2__
-# include "kernel/bvh/obvh_shadow_all.h"
-#endif
+# ifdef __KERNEL_AVX2__
+# include "kernel/bvh/obvh_shadow_all.h"
+# endif
#endif
#if BVH_FEATURE(BVH_HAIR)
@@ -44,350 +44,340 @@ ccl_device
#else
ccl_device_inline
#endif
-bool BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg,
- const Ray *ray,
- Intersection *isect_array,
- const uint visibility,
- const uint max_hits,
- uint *num_hits)
+ bool BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg,
+ const Ray *ray,
+ Intersection *isect_array,
+ const uint visibility,
+ const uint max_hits,
+ uint *num_hits)
{
- /* todo:
- * - likely and unlikely for if() statements
- * - test restrict attribute for pointers
- */
-
- /* traversal stack in CUDA thread-local memory */
- int traversal_stack[BVH_STACK_SIZE];
- traversal_stack[0] = ENTRYPOINT_SENTINEL;
-
- /* traversal variables in registers */
- int stack_ptr = 0;
- int node_addr = kernel_data.bvh.root;
-
- /* ray parameters in registers */
- const float tmax = ray->t;
- float3 P = ray->P;
- float3 dir = bvh_clamp_direction(ray->D);
- float3 idir = bvh_inverse_direction(dir);
- int object = OBJECT_NONE;
- float isect_t = tmax;
+ /* todo:
+ * - likely and unlikely for if() statements
+ * - test restrict attribute for pointers
+ */
+
+ /* traversal stack in CUDA thread-local memory */
+ int traversal_stack[BVH_STACK_SIZE];
+ traversal_stack[0] = ENTRYPOINT_SENTINEL;
+
+ /* traversal variables in registers */
+ int stack_ptr = 0;
+ int node_addr = kernel_data.bvh.root;
+
+ /* ray parameters in registers */
+ const float tmax = ray->t;
+ float3 P = ray->P;
+ float3 dir = bvh_clamp_direction(ray->D);
+ float3 idir = bvh_inverse_direction(dir);
+ int object = OBJECT_NONE;
+ float isect_t = tmax;
#if BVH_FEATURE(BVH_MOTION)
- Transform ob_itfm;
+ Transform ob_itfm;
#endif
#if BVH_FEATURE(BVH_INSTANCING)
- int num_hits_in_instance = 0;
+ int num_hits_in_instance = 0;
#endif
- *num_hits = 0;
- isect_array->t = tmax;
+ *num_hits = 0;
+ isect_array->t = tmax;
#if defined(__KERNEL_SSE2__)
- const shuffle_swap_t shuf_identity = shuffle_swap_identity();
- const shuffle_swap_t shuf_swap = shuffle_swap_swap();
+ const shuffle_swap_t shuf_identity = shuffle_swap_identity();
+ const shuffle_swap_t shuf_swap = shuffle_swap_swap();
- const ssef pn = cast(ssei(0, 0, 0x80000000, 0x80000000));
- ssef Psplat[3], idirsplat[3];
+ const ssef pn = cast(ssei(0, 0, 0x80000000, 0x80000000));
+ ssef Psplat[3], idirsplat[3];
# if BVH_FEATURE(BVH_HAIR)
- ssef tnear(0.0f), tfar(isect_t);
+ ssef tnear(0.0f), tfar(isect_t);
# endif
- shuffle_swap_t shufflexyz[3];
+ shuffle_swap_t shufflexyz[3];
- Psplat[0] = ssef(P.x);
- Psplat[1] = ssef(P.y);
- Psplat[2] = ssef(P.z);
+ Psplat[0] = ssef(P.x);
+ Psplat[1] = ssef(P.y);
+ Psplat[2] = ssef(P.z);
- ssef tsplat(0.0f, 0.0f, -isect_t, -isect_t);
+ ssef tsplat(0.0f, 0.0f, -isect_t, -isect_t);
- gen_idirsplat_swap(pn, shuf_identity, shuf_swap, idir, idirsplat, shufflexyz);
-#endif /* __KERNEL_SSE2__ */
+ gen_idirsplat_swap(pn, shuf_identity, shuf_swap, idir, idirsplat, shufflexyz);
+#endif /* __KERNEL_SSE2__ */
- /* traversal loop */
- do {
- do {
- /* traverse internal nodes */
- while(node_addr >= 0 && node_addr != ENTRYPOINT_SENTINEL) {
- int node_addr_child1, traverse_mask;
- float dist[2];
- float4 cnodes = kernel_tex_fetch(__bvh_nodes, node_addr+0);
+ /* traversal loop */
+ do {
+ do {
+ /* traverse internal nodes */
+ while (node_addr >= 0 && node_addr != ENTRYPOINT_SENTINEL) {
+ int node_addr_child1, traverse_mask;
+ float dist[2];
+ float4 cnodes = kernel_tex_fetch(__bvh_nodes, node_addr + 0);
#if !defined(__KERNEL_SSE2__)
- traverse_mask = NODE_INTERSECT(kg,
- P,
+ traverse_mask = NODE_INTERSECT(kg,
+ P,
# if BVH_FEATURE(BVH_HAIR)
- dir,
+ dir,
# endif
- idir,
- isect_t,
- node_addr,
- visibility,
- dist);
+ idir,
+ isect_t,
+ node_addr,
+ visibility,
+ dist);
#else // __KERNEL_SSE2__
- traverse_mask = NODE_INTERSECT(kg,
- P,
- dir,
+ traverse_mask = NODE_INTERSECT(kg,
+ P,
+ dir,
# if BVH_FEATURE(BVH_HAIR)
- tnear,
- tfar,
+ tnear,
+ tfar,
# endif
- tsplat,
- Psplat,
- idirsplat,
- shufflexyz,
- node_addr,
- visibility,
- dist);
+ tsplat,
+ Psplat,
+ idirsplat,
+ shufflexyz,
+ node_addr,
+ visibility,
+ dist);
#endif // __KERNEL_SSE2__
- node_addr = __float_as_int(cnodes.z);
- node_addr_child1 = __float_as_int(cnodes.w);
-
- if(traverse_mask == 3) {
- /* Both children were intersected, push the farther one. */
- bool is_closest_child1 = (dist[1] < dist[0]);
- if(is_closest_child1) {
- int tmp = node_addr;
- node_addr = node_addr_child1;
- node_addr_child1 = tmp;
- }
-
- ++stack_ptr;
- kernel_assert(stack_ptr < BVH_STACK_SIZE);
- traversal_stack[stack_ptr] = node_addr_child1;
- }
- else {
- /* One child was intersected. */
- if(traverse_mask == 2) {
- node_addr = node_addr_child1;
- }
- else if(traverse_mask == 0) {
- /* Neither child was intersected. */
- node_addr = traversal_stack[stack_ptr];
- --stack_ptr;
- }
- }
- }
-
- /* if node is leaf, fetch triangle list */
- if(node_addr < 0) {
- float4 leaf = kernel_tex_fetch(__bvh_leaf_nodes, (-node_addr-1));
- int prim_addr = __float_as_int(leaf.x);
+ node_addr = __float_as_int(cnodes.z);
+ node_addr_child1 = __float_as_int(cnodes.w);
+
+ if (traverse_mask == 3) {
+ /* Both children were intersected, push the farther one. */
+ bool is_closest_child1 = (dist[1] < dist[0]);
+ if (is_closest_child1) {
+ int tmp = node_addr;
+ node_addr = node_addr_child1;
+ node_addr_child1 = tmp;
+ }
+
+ ++stack_ptr;
+ kernel_assert(stack_ptr < BVH_STACK_SIZE);
+ traversal_stack[stack_ptr] = node_addr_child1;
+ }
+ else {
+ /* One child was intersected. */
+ if (traverse_mask == 2) {
+ node_addr = node_addr_child1;
+ }
+ else if (traverse_mask == 0) {
+ /* Neither child was intersected. */
+ node_addr = traversal_stack[stack_ptr];
+ --stack_ptr;
+ }
+ }
+ }
+
+ /* if node is leaf, fetch triangle list */
+ if (node_addr < 0) {
+ float4 leaf = kernel_tex_fetch(__bvh_leaf_nodes, (-node_addr - 1));
+ int prim_addr = __float_as_int(leaf.x);
#if BVH_FEATURE(BVH_INSTANCING)
- if(prim_addr >= 0) {
+ if (prim_addr >= 0) {
#endif
- const int prim_addr2 = __float_as_int(leaf.y);
- const uint type = __float_as_int(leaf.w);
- const uint p_type = type & PRIMITIVE_ALL;
-
- /* pop */
- node_addr = traversal_stack[stack_ptr];
- --stack_ptr;
-
- /* primitive intersection */
- while(prim_addr < prim_addr2) {
- kernel_assert((kernel_tex_fetch(__prim_type, prim_addr) & PRIMITIVE_ALL) == p_type);
- bool hit;
-
- /* todo: specialized intersect functions which don't fill in
- * isect unless needed and check SD_HAS_TRANSPARENT_SHADOW?
- * might give a few % performance improvement */
-
- switch(p_type) {
- case PRIMITIVE_TRIANGLE: {
- hit = triangle_intersect(kg,
- isect_array,
- P,
- dir,
- visibility,
- object,
- prim_addr);
- break;
- }
+ const int prim_addr2 = __float_as_int(leaf.y);
+ const uint type = __float_as_int(leaf.w);
+ const uint p_type = type & PRIMITIVE_ALL;
+
+ /* pop */
+ node_addr = traversal_stack[stack_ptr];
+ --stack_ptr;
+
+ /* primitive intersection */
+ while (prim_addr < prim_addr2) {
+ kernel_assert((kernel_tex_fetch(__prim_type, prim_addr) & PRIMITIVE_ALL) == p_type);
+ bool hit;
+
+ /* todo: specialized intersect functions which don't fill in
+ * isect unless needed and check SD_HAS_TRANSPARENT_SHADOW?
+ * might give a few % performance improvement */
+
+ switch (p_type) {
+ case PRIMITIVE_TRIANGLE: {
+ hit = triangle_intersect(kg, isect_array, P, dir, visibility, object, prim_addr);
+ break;
+ }
#if BVH_FEATURE(BVH_MOTION)
- case PRIMITIVE_MOTION_TRIANGLE: {
- hit = motion_triangle_intersect(kg,
- isect_array,
- P,
- dir,
- ray->time,
- visibility,
- object,
- prim_addr);
- break;
- }
+ case PRIMITIVE_MOTION_TRIANGLE: {
+ hit = motion_triangle_intersect(
+ kg, isect_array, P, dir, ray->time, visibility, object, prim_addr);
+ break;
+ }
#endif
#if BVH_FEATURE(BVH_HAIR)
- case PRIMITIVE_CURVE:
- case PRIMITIVE_MOTION_CURVE: {
- const uint curve_type = kernel_tex_fetch(__prim_type, prim_addr);
- if(kernel_data.curve.curveflags & CURVE_KN_INTERPOLATE) {
- hit = cardinal_curve_intersect(kg,
- isect_array,
- P,
- dir,
- visibility,
- object,
- prim_addr,
- ray->time,
- curve_type,
- NULL,
- 0, 0);
- }
- else {
- hit = curve_intersect(kg,
- isect_array,
- P,
- dir,
- visibility,
- object,
- prim_addr,
- ray->time,
- curve_type,
- NULL,
- 0, 0);
- }
- break;
- }
+ case PRIMITIVE_CURVE:
+ case PRIMITIVE_MOTION_CURVE: {
+ const uint curve_type = kernel_tex_fetch(__prim_type, prim_addr);
+ if (kernel_data.curve.curveflags & CURVE_KN_INTERPOLATE) {
+ hit = cardinal_curve_intersect(kg,
+ isect_array,
+ P,
+ dir,
+ visibility,
+ object,
+ prim_addr,
+ ray->time,
+ curve_type,
+ NULL,
+ 0,
+ 0);
+ }
+ else {
+ hit = curve_intersect(kg,
+ isect_array,
+ P,
+ dir,
+ visibility,
+ object,
+ prim_addr,
+ ray->time,
+ curve_type,
+ NULL,
+ 0,
+ 0);
+ }
+ break;
+ }
#endif
- default: {
- hit = false;
- break;
- }
- }
+ default: {
+ hit = false;
+ break;
+ }
+ }
- /* shadow ray early termination */
- if(hit) {
- /* detect if this surface has a shader with transparent shadows */
+ /* shadow ray early termination */
+ if (hit) {
+ /* detect if this surface has a shader with transparent shadows */
- /* todo: optimize so primitive visibility flag indicates if
- * the primitive has a transparent shadow shader? */
- int prim = kernel_tex_fetch(__prim_index, isect_array->prim);
- int shader = 0;
+ /* todo: optimize so primitive visibility flag indicates if
+ * the primitive has a transparent shadow shader? */
+ int prim = kernel_tex_fetch(__prim_index, isect_array->prim);
+ int shader = 0;
#ifdef __HAIR__
- if(kernel_tex_fetch(__prim_type, isect_array->prim) & PRIMITIVE_ALL_TRIANGLE)
+ if (kernel_tex_fetch(__prim_type, isect_array->prim) & PRIMITIVE_ALL_TRIANGLE)
#endif
- {
- shader = kernel_tex_fetch(__tri_shader, prim);
- }
+ {
+ shader = kernel_tex_fetch(__tri_shader, prim);
+ }
#ifdef __HAIR__
- else {
- float4 str = kernel_tex_fetch(__curves, prim);
- shader = __float_as_int(str.z);
- }
+ else {
+ float4 str = kernel_tex_fetch(__curves, prim);
+ shader = __float_as_int(str.z);
+ }
#endif
- int flag = kernel_tex_fetch(__shaders, (shader & SHADER_MASK)).flags;
-
- /* if no transparent shadows, all light is blocked */
- if(!(flag & SD_HAS_TRANSPARENT_SHADOW)) {
- return true;
- }
- /* if maximum number of hits reached, block all light */
- else if(*num_hits == max_hits) {
- return true;
- }
-
- /* move on to next entry in intersections array */
- isect_array++;
- (*num_hits)++;
+ int flag = kernel_tex_fetch(__shaders, (shader & SHADER_MASK)).flags;
+
+ /* if no transparent shadows, all light is blocked */
+ if (!(flag & SD_HAS_TRANSPARENT_SHADOW)) {
+ return true;
+ }
+ /* if maximum number of hits reached, block all light */
+ else if (*num_hits == max_hits) {
+ return true;
+ }
+
+ /* move on to next entry in intersections array */
+ isect_array++;
+ (*num_hits)++;
#if BVH_FEATURE(BVH_INSTANCING)
- num_hits_in_instance++;
+ num_hits_in_instance++;
#endif
- isect_array->t = isect_t;
- }
+ isect_array->t = isect_t;
+ }
- prim_addr++;
- }
- }
+ prim_addr++;
+ }
+ }
#if BVH_FEATURE(BVH_INSTANCING)
- else {
- /* instance push */
- object = kernel_tex_fetch(__prim_object, -prim_addr-1);
+ else {
+ /* instance push */
+ object = kernel_tex_fetch(__prim_object, -prim_addr - 1);
# if BVH_FEATURE(BVH_MOTION)
- isect_t = bvh_instance_motion_push(kg, object, ray, &P, &dir, &idir, isect_t, &ob_itfm);
+ isect_t = bvh_instance_motion_push(kg, object, ray, &P, &dir, &idir, isect_t, &ob_itfm);
# else
- isect_t = bvh_instance_push(kg, object, ray, &P, &dir, &idir, isect_t);
+ isect_t = bvh_instance_push(kg, object, ray, &P, &dir, &idir, isect_t);
# endif
- num_hits_in_instance = 0;
- isect_array->t = isect_t;
+ num_hits_in_instance = 0;
+ isect_array->t = isect_t;
# if defined(__KERNEL_SSE2__)
- Psplat[0] = ssef(P.x);
- Psplat[1] = ssef(P.y);
- Psplat[2] = ssef(P.z);
+ Psplat[0] = ssef(P.x);
+ Psplat[1] = ssef(P.y);
+ Psplat[2] = ssef(P.z);
- tsplat = ssef(0.0f, 0.0f, -isect_t, -isect_t);
+ tsplat = ssef(0.0f, 0.0f, -isect_t, -isect_t);
# if BVH_FEATURE(BVH_HAIR)
- tfar = ssef(isect_t);
+ tfar = ssef(isect_t);
# endif
- gen_idirsplat_swap(pn, shuf_identity, shuf_swap, idir, idirsplat, shufflexyz);
+ gen_idirsplat_swap(pn, shuf_identity, shuf_swap, idir, idirsplat, shufflexyz);
# endif
- ++stack_ptr;
- kernel_assert(stack_ptr < BVH_STACK_SIZE);
- traversal_stack[stack_ptr] = ENTRYPOINT_SENTINEL;
+ ++stack_ptr;
+ kernel_assert(stack_ptr < BVH_STACK_SIZE);
+ traversal_stack[stack_ptr] = ENTRYPOINT_SENTINEL;
- node_addr = kernel_tex_fetch(__object_node, object);
- }
- }
-#endif /* FEATURE(BVH_INSTANCING) */
- } while(node_addr != ENTRYPOINT_SENTINEL);
+ node_addr = kernel_tex_fetch(__object_node, object);
+ }
+ }
+#endif /* FEATURE(BVH_INSTANCING) */
+ } while (node_addr != ENTRYPOINT_SENTINEL);
#if BVH_FEATURE(BVH_INSTANCING)
- if(stack_ptr >= 0) {
- kernel_assert(object != OBJECT_NONE);
+ if (stack_ptr >= 0) {
+ kernel_assert(object != OBJECT_NONE);
- /* Instance pop. */
- if(num_hits_in_instance) {
- float t_fac;
+ /* Instance pop. */
+ if (num_hits_in_instance) {
+ float t_fac;
# if BVH_FEATURE(BVH_MOTION)
- bvh_instance_motion_pop_factor(kg, object, ray, &P, &dir, &idir, &t_fac, &ob_itfm);
+ bvh_instance_motion_pop_factor(kg, object, ray, &P, &dir, &idir, &t_fac, &ob_itfm);
# else
- bvh_instance_pop_factor(kg, object, ray, &P, &dir, &idir, &t_fac);
+ bvh_instance_pop_factor(kg, object, ray, &P, &dir, &idir, &t_fac);
# endif
- /* scale isect->t to adjust for instancing */
- for(int i = 0; i < num_hits_in_instance; i++) {
- (isect_array-i-1)->t *= t_fac;
- }
- }
- else {
+ /* scale isect->t to adjust for instancing */
+ for (int i = 0; i < num_hits_in_instance; i++) {
+ (isect_array - i - 1)->t *= t_fac;
+ }
+ }
+ else {
# if BVH_FEATURE(BVH_MOTION)
- bvh_instance_motion_pop(kg, object, ray, &P, &dir, &idir, FLT_MAX, &ob_itfm);
+ bvh_instance_motion_pop(kg, object, ray, &P, &dir, &idir, FLT_MAX, &ob_itfm);
# else
- bvh_instance_pop(kg, object, ray, &P, &dir, &idir, FLT_MAX);
+ bvh_instance_pop(kg, object, ray, &P, &dir, &idir, FLT_MAX);
# endif
- }
+ }
- isect_t = tmax;
- isect_array->t = isect_t;
+ isect_t = tmax;
+ isect_array->t = isect_t;
# if defined(__KERNEL_SSE2__)
- Psplat[0] = ssef(P.x);
- Psplat[1] = ssef(P.y);
- Psplat[2] = ssef(P.z);
+ Psplat[0] = ssef(P.x);
+ Psplat[1] = ssef(P.y);
+ Psplat[2] = ssef(P.z);
- tsplat = ssef(0.0f, 0.0f, -isect_t, -isect_t);
+ tsplat = ssef(0.0f, 0.0f, -isect_t, -isect_t);
# if BVH_FEATURE(BVH_HAIR)
- tfar = ssef(isect_t);
+ tfar = ssef(isect_t);
# endif
- gen_idirsplat_swap(pn, shuf_identity, shuf_swap, idir, idirsplat, shufflexyz);
+ gen_idirsplat_swap(pn, shuf_identity, shuf_swap, idir, idirsplat, shufflexyz);
# endif
- object = OBJECT_NONE;
- node_addr = traversal_stack[stack_ptr];
- --stack_ptr;
- }
-#endif /* FEATURE(BVH_INSTANCING) */
- } while(node_addr != ENTRYPOINT_SENTINEL);
+ object = OBJECT_NONE;
+ node_addr = traversal_stack[stack_ptr];
+ --stack_ptr;
+ }
+#endif /* FEATURE(BVH_INSTANCING) */
+ } while (node_addr != ENTRYPOINT_SENTINEL);
- return false;
+ return false;
}
ccl_device_inline bool BVH_FUNCTION_NAME(KernelGlobals *kg,
@@ -397,35 +387,20 @@ ccl_device_inline bool BVH_FUNCTION_NAME(KernelGlobals *kg,
const uint max_hits,
uint *num_hits)
{
- switch(kernel_data.bvh.bvh_layout) {
+ switch (kernel_data.bvh.bvh_layout) {
#ifdef __KERNEL_AVX2__
- case BVH_LAYOUT_BVH8:
- return BVH_FUNCTION_FULL_NAME(OBVH)(kg,
- ray,
- isect_array,
- visibility,
- max_hits,
- num_hits);
+ case BVH_LAYOUT_BVH8:
+ return BVH_FUNCTION_FULL_NAME(OBVH)(kg, ray, isect_array, visibility, max_hits, num_hits);
#endif
#ifdef __QBVH__
- case BVH_LAYOUT_BVH4:
- return BVH_FUNCTION_FULL_NAME(QBVH)(kg,
- ray,
- isect_array,
- visibility,
- max_hits,
- num_hits);
+ case BVH_LAYOUT_BVH4:
+ return BVH_FUNCTION_FULL_NAME(QBVH)(kg, ray, isect_array, visibility, max_hits, num_hits);
#endif
- case BVH_LAYOUT_BVH2:
- return BVH_FUNCTION_FULL_NAME(BVH)(kg,
- ray,
- isect_array,
- visibility,
- max_hits,
- num_hits);
- }
- kernel_assert(!"Should not happen");
- return false;
+ case BVH_LAYOUT_BVH2:
+ return BVH_FUNCTION_FULL_NAME(BVH)(kg, ray, isect_array, visibility, max_hits, num_hits);
+ }
+ kernel_assert(!"Should not happen");
+ return false;
}
#undef BVH_FUNCTION_NAME
diff --git a/intern/cycles/kernel/bvh/bvh_traversal.h b/intern/cycles/kernel/bvh/bvh_traversal.h
index 76d4cab663d..34a06d003bb 100644
--- a/intern/cycles/kernel/bvh/bvh_traversal.h
+++ b/intern/cycles/kernel/bvh/bvh_traversal.h
@@ -47,374 +47,362 @@ ccl_device_noinline bool BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg,
Intersection *isect,
const uint visibility
#if BVH_FEATURE(BVH_HAIR_MINIMUM_WIDTH)
- , uint *lcg_state,
+ ,
+ uint *lcg_state,
float difl,
float extmax
#endif
- )
+)
{
- /* todo:
- * - test if pushing distance on the stack helps (for non shadow rays)
- * - separate version for shadow rays
- * - likely and unlikely for if() statements
- * - test restrict attribute for pointers
- */
-
- /* traversal stack in CUDA thread-local memory */
- int traversal_stack[BVH_STACK_SIZE];
- traversal_stack[0] = ENTRYPOINT_SENTINEL;
-
- /* traversal variables in registers */
- int stack_ptr = 0;
- int node_addr = kernel_data.bvh.root;
-
- /* ray parameters in registers */
- float3 P = ray->P;
- float3 dir = bvh_clamp_direction(ray->D);
- float3 idir = bvh_inverse_direction(dir);
- int object = OBJECT_NONE;
+ /* todo:
+ * - test if pushing distance on the stack helps (for non shadow rays)
+ * - separate version for shadow rays
+ * - likely and unlikely for if() statements
+ * - test restrict attribute for pointers
+ */
+
+ /* traversal stack in CUDA thread-local memory */
+ int traversal_stack[BVH_STACK_SIZE];
+ traversal_stack[0] = ENTRYPOINT_SENTINEL;
+
+ /* traversal variables in registers */
+ int stack_ptr = 0;
+ int node_addr = kernel_data.bvh.root;
+
+ /* ray parameters in registers */
+ float3 P = ray->P;
+ float3 dir = bvh_clamp_direction(ray->D);
+ float3 idir = bvh_inverse_direction(dir);
+ int object = OBJECT_NONE;
#if BVH_FEATURE(BVH_MOTION)
- Transform ob_itfm;
+ Transform ob_itfm;
#endif
- isect->t = ray->t;
- isect->u = 0.0f;
- isect->v = 0.0f;
- isect->prim = PRIM_NONE;
- isect->object = OBJECT_NONE;
+ isect->t = ray->t;
+ isect->u = 0.0f;
+ isect->v = 0.0f;
+ isect->prim = PRIM_NONE;
+ isect->object = OBJECT_NONE;
- BVH_DEBUG_INIT();
+ BVH_DEBUG_INIT();
#if defined(__KERNEL_SSE2__)
- const shuffle_swap_t shuf_identity = shuffle_swap_identity();
- const shuffle_swap_t shuf_swap = shuffle_swap_swap();
+ const shuffle_swap_t shuf_identity = shuffle_swap_identity();
+ const shuffle_swap_t shuf_swap = shuffle_swap_swap();
- const ssef pn = cast(ssei(0, 0, 0x80000000, 0x80000000));
- ssef Psplat[3], idirsplat[3];
+ const ssef pn = cast(ssei(0, 0, 0x80000000, 0x80000000));
+ ssef Psplat[3], idirsplat[3];
# if BVH_FEATURE(BVH_HAIR)
- ssef tnear(0.0f), tfar(isect->t);
+ ssef tnear(0.0f), tfar(isect->t);
# endif
- shuffle_swap_t shufflexyz[3];
+ shuffle_swap_t shufflexyz[3];
- Psplat[0] = ssef(P.x);
- Psplat[1] = ssef(P.y);
- Psplat[2] = ssef(P.z);
+ Psplat[0] = ssef(P.x);
+ Psplat[1] = ssef(P.y);
+ Psplat[2] = ssef(P.z);
- ssef tsplat(0.0f, 0.0f, -isect->t, -isect->t);
+ ssef tsplat(0.0f, 0.0f, -isect->t, -isect->t);
- gen_idirsplat_swap(pn, shuf_identity, shuf_swap, idir, idirsplat, shufflexyz);
+ gen_idirsplat_swap(pn, shuf_identity, shuf_swap, idir, idirsplat, shufflexyz);
#endif
- /* traversal loop */
- do {
- do {
- /* traverse internal nodes */
- while(node_addr >= 0 && node_addr != ENTRYPOINT_SENTINEL) {
- int node_addr_child1, traverse_mask;
- float dist[2];
- float4 cnodes = kernel_tex_fetch(__bvh_nodes, node_addr+0);
+ /* traversal loop */
+ do {
+ do {
+ /* traverse internal nodes */
+ while (node_addr >= 0 && node_addr != ENTRYPOINT_SENTINEL) {
+ int node_addr_child1, traverse_mask;
+ float dist[2];
+ float4 cnodes = kernel_tex_fetch(__bvh_nodes, node_addr + 0);
#if !defined(__KERNEL_SSE2__)
# if BVH_FEATURE(BVH_HAIR_MINIMUM_WIDTH)
- if(difl != 0.0f) {
- traverse_mask = NODE_INTERSECT_ROBUST(kg,
- P,
+ if (difl != 0.0f) {
+ traverse_mask = NODE_INTERSECT_ROBUST(kg,
+ P,
# if BVH_FEATURE(BVH_HAIR)
- dir,
+ dir,
# endif
- idir,
- isect->t,
- difl,
- extmax,
- node_addr,
- visibility,
- dist);
- }
- else
+ idir,
+ isect->t,
+ difl,
+ extmax,
+ node_addr,
+ visibility,
+ dist);
+ }
+ else
# endif
- {
- traverse_mask = NODE_INTERSECT(kg,
- P,
-# if BVH_FEATURE(BVH_HAIR)
- dir,
-# endif
- idir,
- isect->t,
- node_addr,
- visibility,
- dist);
- }
+ {
+ traverse_mask = NODE_INTERSECT(kg,
+ P,
+# if BVH_FEATURE(BVH_HAIR)
+ dir,
+# endif
+ idir,
+ isect->t,
+ node_addr,
+ visibility,
+ dist);
+ }
#else // __KERNEL_SSE2__
# if BVH_FEATURE(BVH_HAIR_MINIMUM_WIDTH)
- if(difl != 0.0f) {
- traverse_mask = NODE_INTERSECT_ROBUST(kg,
- P,
- dir,
+ if (difl != 0.0f) {
+ traverse_mask = NODE_INTERSECT_ROBUST(kg,
+ P,
+ dir,
# if BVH_FEATURE(BVH_HAIR)
- tnear,
- tfar,
+ tnear,
+ tfar,
# endif
- tsplat,
- Psplat,
- idirsplat,
- shufflexyz,
- difl,
- extmax,
- node_addr,
- visibility,
- dist);
- }
- else
+ tsplat,
+ Psplat,
+ idirsplat,
+ shufflexyz,
+ difl,
+ extmax,
+ node_addr,
+ visibility,
+ dist);
+ }
+ else
# endif
- {
- traverse_mask = NODE_INTERSECT(kg,
- P,
- dir,
-# if BVH_FEATURE(BVH_HAIR)
- tnear,
- tfar,
-# endif
- tsplat,
- Psplat,
- idirsplat,
- shufflexyz,
- node_addr,
- visibility,
- dist);
- }
+ {
+ traverse_mask = NODE_INTERSECT(kg,
+ P,
+ dir,
+# if BVH_FEATURE(BVH_HAIR)
+ tnear,
+ tfar,
+# endif
+ tsplat,
+ Psplat,
+ idirsplat,
+ shufflexyz,
+ node_addr,
+ visibility,
+ dist);
+ }
#endif // __KERNEL_SSE2__
- node_addr = __float_as_int(cnodes.z);
- node_addr_child1 = __float_as_int(cnodes.w);
-
- if(traverse_mask == 3) {
- /* Both children were intersected, push the farther one. */
- bool is_closest_child1 = (dist[1] < dist[0]);
- if(is_closest_child1) {
- int tmp = node_addr;
- node_addr = node_addr_child1;
- node_addr_child1 = tmp;
- }
-
- ++stack_ptr;
- kernel_assert(stack_ptr < BVH_STACK_SIZE);
- traversal_stack[stack_ptr] = node_addr_child1;
- }
- else {
- /* One child was intersected. */
- if(traverse_mask == 2) {
- node_addr = node_addr_child1;
- }
- else if(traverse_mask == 0) {
- /* Neither child was intersected. */
- node_addr = traversal_stack[stack_ptr];
- --stack_ptr;
- }
- }
- BVH_DEBUG_NEXT_NODE();
- }
-
- /* if node is leaf, fetch triangle list */
- if(node_addr < 0) {
- float4 leaf = kernel_tex_fetch(__bvh_leaf_nodes, (-node_addr-1));
- int prim_addr = __float_as_int(leaf.x);
+ node_addr = __float_as_int(cnodes.z);
+ node_addr_child1 = __float_as_int(cnodes.w);
+
+ if (traverse_mask == 3) {
+ /* Both children were intersected, push the farther one. */
+ bool is_closest_child1 = (dist[1] < dist[0]);
+ if (is_closest_child1) {
+ int tmp = node_addr;
+ node_addr = node_addr_child1;
+ node_addr_child1 = tmp;
+ }
+
+ ++stack_ptr;
+ kernel_assert(stack_ptr < BVH_STACK_SIZE);
+ traversal_stack[stack_ptr] = node_addr_child1;
+ }
+ else {
+ /* One child was intersected. */
+ if (traverse_mask == 2) {
+ node_addr = node_addr_child1;
+ }
+ else if (traverse_mask == 0) {
+ /* Neither child was intersected. */
+ node_addr = traversal_stack[stack_ptr];
+ --stack_ptr;
+ }
+ }
+ BVH_DEBUG_NEXT_NODE();
+ }
+
+ /* if node is leaf, fetch triangle list */
+ if (node_addr < 0) {
+ float4 leaf = kernel_tex_fetch(__bvh_leaf_nodes, (-node_addr - 1));
+ int prim_addr = __float_as_int(leaf.x);
#if BVH_FEATURE(BVH_INSTANCING)
- if(prim_addr >= 0) {
+ if (prim_addr >= 0) {
#endif
- const int prim_addr2 = __float_as_int(leaf.y);
- const uint type = __float_as_int(leaf.w);
-
- /* pop */
- node_addr = traversal_stack[stack_ptr];
- --stack_ptr;
-
- /* primitive intersection */
- switch(type & PRIMITIVE_ALL) {
- case PRIMITIVE_TRIANGLE: {
- for(; prim_addr < prim_addr2; prim_addr++) {
- BVH_DEBUG_NEXT_INTERSECTION();
- kernel_assert(kernel_tex_fetch(__prim_type, prim_addr) == type);
- if(triangle_intersect(kg,
- isect,
- P,
- dir,
- visibility,
- object,
- prim_addr))
- {
- /* shadow ray early termination */
+ const int prim_addr2 = __float_as_int(leaf.y);
+ const uint type = __float_as_int(leaf.w);
+
+ /* pop */
+ node_addr = traversal_stack[stack_ptr];
+ --stack_ptr;
+
+ /* primitive intersection */
+ switch (type & PRIMITIVE_ALL) {
+ case PRIMITIVE_TRIANGLE: {
+ for (; prim_addr < prim_addr2; prim_addr++) {
+ BVH_DEBUG_NEXT_INTERSECTION();
+ kernel_assert(kernel_tex_fetch(__prim_type, prim_addr) == type);
+ if (triangle_intersect(kg, isect, P, dir, visibility, object, prim_addr)) {
+ /* shadow ray early termination */
#if defined(__KERNEL_SSE2__)
- if(visibility & PATH_RAY_SHADOW_OPAQUE)
- return true;
- tsplat = ssef(0.0f, 0.0f, -isect->t, -isect->t);
+ if (visibility & PATH_RAY_SHADOW_OPAQUE)
+ return true;
+ tsplat = ssef(0.0f, 0.0f, -isect->t, -isect->t);
# if BVH_FEATURE(BVH_HAIR)
- tfar = ssef(isect->t);
+ tfar = ssef(isect->t);
# endif
#else
- if(visibility & PATH_RAY_SHADOW_OPAQUE)
- return true;
+ if (visibility & PATH_RAY_SHADOW_OPAQUE)
+ return true;
#endif
- }
- }
- break;
- }
+ }
+ }
+ break;
+ }
#if BVH_FEATURE(BVH_MOTION)
- case PRIMITIVE_MOTION_TRIANGLE: {
- for(; prim_addr < prim_addr2; prim_addr++) {
- BVH_DEBUG_NEXT_INTERSECTION();
- kernel_assert(kernel_tex_fetch(__prim_type, prim_addr) == type);
- if(motion_triangle_intersect(kg,
- isect,
- P,
- dir,
- ray->time,
- visibility,
- object,
- prim_addr))
- {
- /* shadow ray early termination */
+ case PRIMITIVE_MOTION_TRIANGLE: {
+ for (; prim_addr < prim_addr2; prim_addr++) {
+ BVH_DEBUG_NEXT_INTERSECTION();
+ kernel_assert(kernel_tex_fetch(__prim_type, prim_addr) == type);
+ if (motion_triangle_intersect(
+ kg, isect, P, dir, ray->time, visibility, object, prim_addr)) {
+ /* shadow ray early termination */
# if defined(__KERNEL_SSE2__)
- if(visibility & PATH_RAY_SHADOW_OPAQUE)
- return true;
- tsplat = ssef(0.0f, 0.0f, -isect->t, -isect->t);
+ if (visibility & PATH_RAY_SHADOW_OPAQUE)
+ return true;
+ tsplat = ssef(0.0f, 0.0f, -isect->t, -isect->t);
# if BVH_FEATURE(BVH_HAIR)
- tfar = ssef(isect->t);
+ tfar = ssef(isect->t);
# endif
# else
- if(visibility & PATH_RAY_SHADOW_OPAQUE)
- return true;
+ if (visibility & PATH_RAY_SHADOW_OPAQUE)
+ return true;
# endif
- }
- }
- break;
- }
-#endif /* BVH_FEATURE(BVH_MOTION) */
+ }
+ }
+ break;
+ }
+#endif /* BVH_FEATURE(BVH_MOTION) */
#if BVH_FEATURE(BVH_HAIR)
- case PRIMITIVE_CURVE:
- case PRIMITIVE_MOTION_CURVE: {
- for(; prim_addr < prim_addr2; prim_addr++) {
- BVH_DEBUG_NEXT_INTERSECTION();
- const uint curve_type = kernel_tex_fetch(__prim_type, prim_addr);
- kernel_assert((curve_type & PRIMITIVE_ALL) == (type & PRIMITIVE_ALL));
- bool hit;
- if(kernel_data.curve.curveflags & CURVE_KN_INTERPOLATE) {
- hit = cardinal_curve_intersect(kg,
- isect,
- P,
- dir,
- visibility,
- object,
- prim_addr,
- ray->time,
- curve_type,
- lcg_state,
- difl,
- extmax);
- }
- else {
- hit = curve_intersect(kg,
- isect,
- P,
- dir,
- visibility,
- object,
- prim_addr,
- ray->time,
- curve_type,
- lcg_state,
- difl,
- extmax);
- }
- if(hit) {
- /* shadow ray early termination */
+ case PRIMITIVE_CURVE:
+ case PRIMITIVE_MOTION_CURVE: {
+ for (; prim_addr < prim_addr2; prim_addr++) {
+ BVH_DEBUG_NEXT_INTERSECTION();
+ const uint curve_type = kernel_tex_fetch(__prim_type, prim_addr);
+ kernel_assert((curve_type & PRIMITIVE_ALL) == (type & PRIMITIVE_ALL));
+ bool hit;
+ if (kernel_data.curve.curveflags & CURVE_KN_INTERPOLATE) {
+ hit = cardinal_curve_intersect(kg,
+ isect,
+ P,
+ dir,
+ visibility,
+ object,
+ prim_addr,
+ ray->time,
+ curve_type,
+ lcg_state,
+ difl,
+ extmax);
+ }
+ else {
+ hit = curve_intersect(kg,
+ isect,
+ P,
+ dir,
+ visibility,
+ object,
+ prim_addr,
+ ray->time,
+ curve_type,
+ lcg_state,
+ difl,
+ extmax);
+ }
+ if (hit) {
+ /* shadow ray early termination */
# if defined(__KERNEL_SSE2__)
- if(visibility & PATH_RAY_SHADOW_OPAQUE)
- return true;
- tsplat = ssef(0.0f, 0.0f, -isect->t, -isect->t);
+ if (visibility & PATH_RAY_SHADOW_OPAQUE)
+ return true;
+ tsplat = ssef(0.0f, 0.0f, -isect->t, -isect->t);
# if BVH_FEATURE(BVH_HAIR)
- tfar = ssef(isect->t);
+ tfar = ssef(isect->t);
# endif
# else
- if(visibility & PATH_RAY_SHADOW_OPAQUE)
- return true;
+ if (visibility & PATH_RAY_SHADOW_OPAQUE)
+ return true;
# endif
- }
- }
- break;
- }
-#endif /* BVH_FEATURE(BVH_HAIR) */
- }
- }
+ }
+ }
+ break;
+ }
+#endif /* BVH_FEATURE(BVH_HAIR) */
+ }
+ }
#if BVH_FEATURE(BVH_INSTANCING)
- else {
- /* instance push */
- object = kernel_tex_fetch(__prim_object, -prim_addr-1);
+ else {
+ /* instance push */
+ object = kernel_tex_fetch(__prim_object, -prim_addr - 1);
# if BVH_FEATURE(BVH_MOTION)
- isect->t = bvh_instance_motion_push(kg, object, ray, &P, &dir, &idir, isect->t, &ob_itfm);
+ isect->t = bvh_instance_motion_push(
+ kg, object, ray, &P, &dir, &idir, isect->t, &ob_itfm);
# else
- isect->t = bvh_instance_push(kg, object, ray, &P, &dir, &idir, isect->t);
+ isect->t = bvh_instance_push(kg, object, ray, &P, &dir, &idir, isect->t);
# endif
# if defined(__KERNEL_SSE2__)
- Psplat[0] = ssef(P.x);
- Psplat[1] = ssef(P.y);
- Psplat[2] = ssef(P.z);
+ Psplat[0] = ssef(P.x);
+ Psplat[1] = ssef(P.y);
+ Psplat[2] = ssef(P.z);
- tsplat = ssef(0.0f, 0.0f, -isect->t, -isect->t);
+ tsplat = ssef(0.0f, 0.0f, -isect->t, -isect->t);
# if BVH_FEATURE(BVH_HAIR)
- tfar = ssef(isect->t);
+ tfar = ssef(isect->t);
# endif
- gen_idirsplat_swap(pn, shuf_identity, shuf_swap, idir, idirsplat, shufflexyz);
+ gen_idirsplat_swap(pn, shuf_identity, shuf_swap, idir, idirsplat, shufflexyz);
# endif
- ++stack_ptr;
- kernel_assert(stack_ptr < BVH_STACK_SIZE);
- traversal_stack[stack_ptr] = ENTRYPOINT_SENTINEL;
+ ++stack_ptr;
+ kernel_assert(stack_ptr < BVH_STACK_SIZE);
+ traversal_stack[stack_ptr] = ENTRYPOINT_SENTINEL;
- node_addr = kernel_tex_fetch(__object_node, object);
+ node_addr = kernel_tex_fetch(__object_node, object);
- BVH_DEBUG_NEXT_INSTANCE();
- }
- }
-#endif /* FEATURE(BVH_INSTANCING) */
- } while(node_addr != ENTRYPOINT_SENTINEL);
+ BVH_DEBUG_NEXT_INSTANCE();
+ }
+ }
+#endif /* FEATURE(BVH_INSTANCING) */
+ } while (node_addr != ENTRYPOINT_SENTINEL);
#if BVH_FEATURE(BVH_INSTANCING)
- if(stack_ptr >= 0) {
- kernel_assert(object != OBJECT_NONE);
+ if (stack_ptr >= 0) {
+ kernel_assert(object != OBJECT_NONE);
- /* instance pop */
+ /* instance pop */
# if BVH_FEATURE(BVH_MOTION)
- isect->t = bvh_instance_motion_pop(kg, object, ray, &P, &dir, &idir, isect->t, &ob_itfm);
+ isect->t = bvh_instance_motion_pop(kg, object, ray, &P, &dir, &idir, isect->t, &ob_itfm);
# else
- isect->t = bvh_instance_pop(kg, object, ray, &P, &dir, &idir, isect->t);
+ isect->t = bvh_instance_pop(kg, object, ray, &P, &dir, &idir, isect->t);
# endif
# if defined(__KERNEL_SSE2__)
- Psplat[0] = ssef(P.x);
- Psplat[1] = ssef(P.y);
- Psplat[2] = ssef(P.z);
+ Psplat[0] = ssef(P.x);
+ Psplat[1] = ssef(P.y);
+ Psplat[2] = ssef(P.z);
- tsplat = ssef(0.0f, 0.0f, -isect->t, -isect->t);
+ tsplat = ssef(0.0f, 0.0f, -isect->t, -isect->t);
# if BVH_FEATURE(BVH_HAIR)
- tfar = ssef(isect->t);
+ tfar = ssef(isect->t);
# endif
- gen_idirsplat_swap(pn, shuf_identity, shuf_swap, idir, idirsplat, shufflexyz);
+ gen_idirsplat_swap(pn, shuf_identity, shuf_swap, idir, idirsplat, shufflexyz);
# endif
- object = OBJECT_NONE;
- node_addr = traversal_stack[stack_ptr];
- --stack_ptr;
- }
-#endif /* FEATURE(BVH_INSTANCING) */
- } while(node_addr != ENTRYPOINT_SENTINEL);
+ object = OBJECT_NONE;
+ node_addr = traversal_stack[stack_ptr];
+ --stack_ptr;
+ }
+#endif /* FEATURE(BVH_INSTANCING) */
+ } while (node_addr != ENTRYPOINT_SENTINEL);
- return (isect->prim != PRIM_NONE);
+ return (isect->prim != PRIM_NONE);
}
ccl_device_inline bool BVH_FUNCTION_NAME(KernelGlobals *kg,
@@ -422,53 +410,57 @@ ccl_device_inline bool BVH_FUNCTION_NAME(KernelGlobals *kg,
Intersection *isect,
const uint visibility
#if BVH_FEATURE(BVH_HAIR_MINIMUM_WIDTH)
- , uint *lcg_state,
+ ,
+ uint *lcg_state,
float difl,
float extmax
#endif
- )
+)
{
- switch(kernel_data.bvh.bvh_layout) {
+ switch (kernel_data.bvh.bvh_layout) {
#ifdef __KERNEL_AVX2__
- case BVH_LAYOUT_BVH8:
- return BVH_FUNCTION_FULL_NAME(OBVH)(kg,
- ray,
- isect,
- visibility
+ case BVH_LAYOUT_BVH8:
+ return BVH_FUNCTION_FULL_NAME(OBVH)(kg,
+ ray,
+ isect,
+ visibility
# if BVH_FEATURE(BVH_HAIR_MINIMUM_WIDTH)
- , lcg_state,
- difl,
- extmax
+ ,
+ lcg_state,
+ difl,
+ extmax
# endif
- );
+ );
#endif
#ifdef __QBVH__
- case BVH_LAYOUT_BVH4:
- return BVH_FUNCTION_FULL_NAME(QBVH)(kg,
- ray,
- isect,
- visibility
+ case BVH_LAYOUT_BVH4:
+ return BVH_FUNCTION_FULL_NAME(QBVH)(kg,
+ ray,
+ isect,
+ visibility
# if BVH_FEATURE(BVH_HAIR_MINIMUM_WIDTH)
- , lcg_state,
- difl,
- extmax
+ ,
+ lcg_state,
+ difl,
+ extmax
# endif
- );
-#endif /* __QBVH__ */
- case BVH_LAYOUT_BVH2:
- return BVH_FUNCTION_FULL_NAME(BVH)(kg,
- ray,
- isect,
- visibility
+ );
+#endif /* __QBVH__ */
+ case BVH_LAYOUT_BVH2:
+ return BVH_FUNCTION_FULL_NAME(BVH)(kg,
+ ray,
+ isect,
+ visibility
#if BVH_FEATURE(BVH_HAIR_MINIMUM_WIDTH)
- , lcg_state,
- difl,
- extmax
+ ,
+ lcg_state,
+ difl,
+ extmax
#endif
- );
- }
- kernel_assert(!"Should not happen");
- return false;
+ );
+ }
+ kernel_assert(!"Should not happen");
+ return false;
}
#undef BVH_FUNCTION_NAME
diff --git a/intern/cycles/kernel/bvh/bvh_types.h b/intern/cycles/kernel/bvh/bvh_types.h
index 4ca0dc2225e..16f3b03f842 100644
--- a/intern/cycles/kernel/bvh/bvh_types.h
+++ b/intern/cycles/kernel/bvh/bvh_types.h
@@ -35,13 +35,13 @@ CCL_NAMESPACE_BEGIN
#define BVH_OSTACK_SIZE 768
/* BVH intersection function variations */
-#define BVH_INSTANCING 1
-#define BVH_MOTION 2
-#define BVH_HAIR 4
-#define BVH_HAIR_MINIMUM_WIDTH 8
+#define BVH_INSTANCING 1
+#define BVH_MOTION 2
+#define BVH_HAIR 4
+#define BVH_HAIR_MINIMUM_WIDTH 8
-#define BVH_NAME_JOIN(x,y) x ## _ ## y
-#define BVH_NAME_EVAL(x,y) BVH_NAME_JOIN(x,y)
+#define BVH_NAME_JOIN(x, y) x##_##y
+#define BVH_NAME_EVAL(x, y) BVH_NAME_JOIN(x, y)
#define BVH_FUNCTION_FULL_NAME(prefix) BVH_NAME_EVAL(prefix, BVH_FUNCTION_NAME)
#define BVH_FEATURE(f) (((BVH_FUNCTION_FEATURES) & (f)) != 0)
@@ -49,30 +49,30 @@ CCL_NAMESPACE_BEGIN
/* Debugging heleprs */
#ifdef __KERNEL_DEBUG__
# define BVH_DEBUG_INIT() \
- do { \
- isect->num_traversed_nodes = 0; \
- isect->num_traversed_instances = 0; \
- isect->num_intersections = 0; \
- } while(0)
+ do { \
+ isect->num_traversed_nodes = 0; \
+ isect->num_traversed_instances = 0; \
+ isect->num_intersections = 0; \
+ } while (0)
# define BVH_DEBUG_NEXT_NODE() \
- do { \
- ++isect->num_traversed_nodes; \
- } while(0)
+ do { \
+ ++isect->num_traversed_nodes; \
+ } while (0)
# define BVH_DEBUG_NEXT_INTERSECTION() \
- do { \
- ++isect->num_intersections; \
- } while(0)
+ do { \
+ ++isect->num_intersections; \
+ } while (0)
# define BVH_DEBUG_NEXT_INSTANCE() \
- do { \
- ++isect->num_traversed_instances; \
- } while(0)
-#else /* __KERNEL_DEBUG__ */
+ do { \
+ ++isect->num_traversed_instances; \
+ } while (0)
+#else /* __KERNEL_DEBUG__ */
# define BVH_DEBUG_INIT()
# define BVH_DEBUG_NEXT_NODE()
# define BVH_DEBUG_NEXT_INTERSECTION()
# define BVH_DEBUG_NEXT_INSTANCE()
-#endif /* __KERNEL_DEBUG__ */
+#endif /* __KERNEL_DEBUG__ */
CCL_NAMESPACE_END
-#endif /* __BVH_TYPES__ */
+#endif /* __BVH_TYPES__ */
diff --git a/intern/cycles/kernel/bvh/bvh_volume.h b/intern/cycles/kernel/bvh/bvh_volume.h
index b8257e3493e..c83b0d783f4 100644
--- a/intern/cycles/kernel/bvh/bvh_volume.h
+++ b/intern/cycles/kernel/bvh/bvh_volume.h
@@ -19,9 +19,9 @@
#ifdef __QBVH__
# include "kernel/bvh/qbvh_volume.h"
-#ifdef __KERNEL_AVX2__
-# include "kernel/bvh/obvh_volume.h"
-#endif
+# ifdef __KERNEL_AVX2__
+# include "kernel/bvh/obvh_volume.h"
+# endif
#endif
#if BVH_FEATURE(BVH_HAIR)
@@ -43,267 +43,260 @@ ccl_device
#else
ccl_device_inline
#endif
-bool BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg,
- const Ray *ray,
- Intersection *isect,
- const uint visibility)
+ bool BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg,
+ const Ray *ray,
+ Intersection *isect,
+ const uint visibility)
{
- /* todo:
- * - test if pushing distance on the stack helps (for non shadow rays)
- * - separate version for shadow rays
- * - likely and unlikely for if() statements
- * - test restrict attribute for pointers
- */
-
- /* traversal stack in CUDA thread-local memory */
- int traversal_stack[BVH_STACK_SIZE];
- traversal_stack[0] = ENTRYPOINT_SENTINEL;
-
- /* traversal variables in registers */
- int stack_ptr = 0;
- int node_addr = kernel_data.bvh.root;
-
- /* ray parameters in registers */
- float3 P = ray->P;
- float3 dir = bvh_clamp_direction(ray->D);
- float3 idir = bvh_inverse_direction(dir);
- int object = OBJECT_NONE;
+ /* todo:
+ * - test if pushing distance on the stack helps (for non shadow rays)
+ * - separate version for shadow rays
+ * - likely and unlikely for if() statements
+ * - test restrict attribute for pointers
+ */
+
+ /* traversal stack in CUDA thread-local memory */
+ int traversal_stack[BVH_STACK_SIZE];
+ traversal_stack[0] = ENTRYPOINT_SENTINEL;
+
+ /* traversal variables in registers */
+ int stack_ptr = 0;
+ int node_addr = kernel_data.bvh.root;
+
+ /* ray parameters in registers */
+ float3 P = ray->P;
+ float3 dir = bvh_clamp_direction(ray->D);
+ float3 idir = bvh_inverse_direction(dir);
+ int object = OBJECT_NONE;
#if BVH_FEATURE(BVH_MOTION)
- Transform ob_itfm;
+ Transform ob_itfm;
#endif
- isect->t = ray->t;
- isect->u = 0.0f;
- isect->v = 0.0f;
- isect->prim = PRIM_NONE;
- isect->object = OBJECT_NONE;
+ isect->t = ray->t;
+ isect->u = 0.0f;
+ isect->v = 0.0f;
+ isect->prim = PRIM_NONE;
+ isect->object = OBJECT_NONE;
#if defined(__KERNEL_SSE2__)
- const shuffle_swap_t shuf_identity = shuffle_swap_identity();
- const shuffle_swap_t shuf_swap = shuffle_swap_swap();
+ const shuffle_swap_t shuf_identity = shuffle_swap_identity();
+ const shuffle_swap_t shuf_swap = shuffle_swap_swap();
- const ssef pn = cast(ssei(0, 0, 0x80000000, 0x80000000));
- ssef Psplat[3], idirsplat[3];
+ const ssef pn = cast(ssei(0, 0, 0x80000000, 0x80000000));
+ ssef Psplat[3], idirsplat[3];
# if BVH_FEATURE(BVH_HAIR)
- ssef tnear(0.0f), tfar(isect->t);
+ ssef tnear(0.0f), tfar(isect->t);
# endif
- shuffle_swap_t shufflexyz[3];
+ shuffle_swap_t shufflexyz[3];
- Psplat[0] = ssef(P.x);
- Psplat[1] = ssef(P.y);
- Psplat[2] = ssef(P.z);
+ Psplat[0] = ssef(P.x);
+ Psplat[1] = ssef(P.y);
+ Psplat[2] = ssef(P.z);
- ssef tsplat(0.0f, 0.0f, -isect->t, -isect->t);
+ ssef tsplat(0.0f, 0.0f, -isect->t, -isect->t);
- gen_idirsplat_swap(pn, shuf_identity, shuf_swap, idir, idirsplat, shufflexyz);
+ gen_idirsplat_swap(pn, shuf_identity, shuf_swap, idir, idirsplat, shufflexyz);
#endif
- /* traversal loop */
- do {
- do {
- /* traverse internal nodes */
- while(node_addr >= 0 && node_addr != ENTRYPOINT_SENTINEL) {
- int node_addr_child1, traverse_mask;
- float dist[2];
- float4 cnodes = kernel_tex_fetch(__bvh_nodes, node_addr+0);
+ /* traversal loop */
+ do {
+ do {
+ /* traverse internal nodes */
+ while (node_addr >= 0 && node_addr != ENTRYPOINT_SENTINEL) {
+ int node_addr_child1, traverse_mask;
+ float dist[2];
+ float4 cnodes = kernel_tex_fetch(__bvh_nodes, node_addr + 0);
#if !defined(__KERNEL_SSE2__)
- traverse_mask = NODE_INTERSECT(kg,
- P,
+ traverse_mask = NODE_INTERSECT(kg,
+ P,
# if BVH_FEATURE(BVH_HAIR)
- dir,
+ dir,
# endif
- idir,
- isect->t,
- node_addr,
- visibility,
- dist);
+ idir,
+ isect->t,
+ node_addr,
+ visibility,
+ dist);
#else // __KERNEL_SSE2__
- traverse_mask = NODE_INTERSECT(kg,
- P,
- dir,
+ traverse_mask = NODE_INTERSECT(kg,
+ P,
+ dir,
# if BVH_FEATURE(BVH_HAIR)
- tnear,
- tfar,
+ tnear,
+ tfar,
# endif
- tsplat,
- Psplat,
- idirsplat,
- shufflexyz,
- node_addr,
- visibility,
- dist);
+ tsplat,
+ Psplat,
+ idirsplat,
+ shufflexyz,
+ node_addr,
+ visibility,
+ dist);
#endif // __KERNEL_SSE2__
- node_addr = __float_as_int(cnodes.z);
- node_addr_child1 = __float_as_int(cnodes.w);
-
- if(traverse_mask == 3) {
- /* Both children were intersected, push the farther one. */
- bool is_closest_child1 = (dist[1] < dist[0]);
- if(is_closest_child1) {
- int tmp = node_addr;
- node_addr = node_addr_child1;
- node_addr_child1 = tmp;
- }
-
- ++stack_ptr;
- kernel_assert(stack_ptr < BVH_STACK_SIZE);
- traversal_stack[stack_ptr] = node_addr_child1;
- }
- else {
- /* One child was intersected. */
- if(traverse_mask == 2) {
- node_addr = node_addr_child1;
- }
- else if(traverse_mask == 0) {
- /* Neither child was intersected. */
- node_addr = traversal_stack[stack_ptr];
- --stack_ptr;
- }
- }
- }
-
- /* if node is leaf, fetch triangle list */
- if(node_addr < 0) {
- float4 leaf = kernel_tex_fetch(__bvh_leaf_nodes, (-node_addr-1));
- int prim_addr = __float_as_int(leaf.x);
+ node_addr = __float_as_int(cnodes.z);
+ node_addr_child1 = __float_as_int(cnodes.w);
+
+ if (traverse_mask == 3) {
+ /* Both children were intersected, push the farther one. */
+ bool is_closest_child1 = (dist[1] < dist[0]);
+ if (is_closest_child1) {
+ int tmp = node_addr;
+ node_addr = node_addr_child1;
+ node_addr_child1 = tmp;
+ }
+
+ ++stack_ptr;
+ kernel_assert(stack_ptr < BVH_STACK_SIZE);
+ traversal_stack[stack_ptr] = node_addr_child1;
+ }
+ else {
+ /* One child was intersected. */
+ if (traverse_mask == 2) {
+ node_addr = node_addr_child1;
+ }
+ else if (traverse_mask == 0) {
+ /* Neither child was intersected. */
+ node_addr = traversal_stack[stack_ptr];
+ --stack_ptr;
+ }
+ }
+ }
+
+ /* if node is leaf, fetch triangle list */
+ if (node_addr < 0) {
+ float4 leaf = kernel_tex_fetch(__bvh_leaf_nodes, (-node_addr - 1));
+ int prim_addr = __float_as_int(leaf.x);
#if BVH_FEATURE(BVH_INSTANCING)
- if(prim_addr >= 0) {
+ if (prim_addr >= 0) {
#endif
- const int prim_addr2 = __float_as_int(leaf.y);
- const uint type = __float_as_int(leaf.w);
-
- /* pop */
- node_addr = traversal_stack[stack_ptr];
- --stack_ptr;
-
- /* primitive intersection */
- switch(type & PRIMITIVE_ALL) {
- case PRIMITIVE_TRIANGLE: {
- /* intersect ray against primitive */
- for(; prim_addr < prim_addr2; prim_addr++) {
- kernel_assert(kernel_tex_fetch(__prim_type, prim_addr) == type);
- /* only primitives from volume object */
- uint tri_object = (object == OBJECT_NONE)? kernel_tex_fetch(__prim_object, prim_addr): object;
- int object_flag = kernel_tex_fetch(__object_flag, tri_object);
- if((object_flag & SD_OBJECT_HAS_VOLUME) == 0) {
- continue;
- }
- triangle_intersect(kg,
- isect,
- P,
- dir,
- visibility,
- object,
- prim_addr);
- }
- break;
- }
+ const int prim_addr2 = __float_as_int(leaf.y);
+ const uint type = __float_as_int(leaf.w);
+
+ /* pop */
+ node_addr = traversal_stack[stack_ptr];
+ --stack_ptr;
+
+ /* primitive intersection */
+ switch (type & PRIMITIVE_ALL) {
+ case PRIMITIVE_TRIANGLE: {
+ /* intersect ray against primitive */
+ for (; prim_addr < prim_addr2; prim_addr++) {
+ kernel_assert(kernel_tex_fetch(__prim_type, prim_addr) == type);
+ /* only primitives from volume object */
+ uint tri_object = (object == OBJECT_NONE) ?
+ kernel_tex_fetch(__prim_object, prim_addr) :
+ object;
+ int object_flag = kernel_tex_fetch(__object_flag, tri_object);
+ if ((object_flag & SD_OBJECT_HAS_VOLUME) == 0) {
+ continue;
+ }
+ triangle_intersect(kg, isect, P, dir, visibility, object, prim_addr);
+ }
+ break;
+ }
#if BVH_FEATURE(BVH_MOTION)
- case PRIMITIVE_MOTION_TRIANGLE: {
- /* intersect ray against primitive */
- for(; prim_addr < prim_addr2; prim_addr++) {
- kernel_assert(kernel_tex_fetch(__prim_type, prim_addr) == type);
- /* only primitives from volume object */
- uint tri_object = (object == OBJECT_NONE)? kernel_tex_fetch(__prim_object, prim_addr): object;
- int object_flag = kernel_tex_fetch(__object_flag, tri_object);
- if((object_flag & SD_OBJECT_HAS_VOLUME) == 0) {
- continue;
- }
- motion_triangle_intersect(kg,
- isect,
- P,
- dir,
- ray->time,
- visibility,
- object,
- prim_addr);
- }
- break;
- }
+ case PRIMITIVE_MOTION_TRIANGLE: {
+ /* intersect ray against primitive */
+ for (; prim_addr < prim_addr2; prim_addr++) {
+ kernel_assert(kernel_tex_fetch(__prim_type, prim_addr) == type);
+ /* only primitives from volume object */
+ uint tri_object = (object == OBJECT_NONE) ?
+ kernel_tex_fetch(__prim_object, prim_addr) :
+ object;
+ int object_flag = kernel_tex_fetch(__object_flag, tri_object);
+ if ((object_flag & SD_OBJECT_HAS_VOLUME) == 0) {
+ continue;
+ }
+ motion_triangle_intersect(
+ kg, isect, P, dir, ray->time, visibility, object, prim_addr);
+ }
+ break;
+ }
#endif
- default: {
- break;
- }
- }
- }
+ default: {
+ break;
+ }
+ }
+ }
#if BVH_FEATURE(BVH_INSTANCING)
- else {
- /* instance push */
- object = kernel_tex_fetch(__prim_object, -prim_addr-1);
- int object_flag = kernel_tex_fetch(__object_flag, object);
- if(object_flag & SD_OBJECT_HAS_VOLUME) {
+ else {
+ /* instance push */
+ object = kernel_tex_fetch(__prim_object, -prim_addr - 1);
+ int object_flag = kernel_tex_fetch(__object_flag, object);
+ if (object_flag & SD_OBJECT_HAS_VOLUME) {
# if BVH_FEATURE(BVH_MOTION)
- isect->t = bvh_instance_motion_push(kg, object, ray, &P, &dir, &idir, isect->t, &ob_itfm);
+ isect->t = bvh_instance_motion_push(
+ kg, object, ray, &P, &dir, &idir, isect->t, &ob_itfm);
# else
- isect->t = bvh_instance_push(kg, object, ray, &P, &dir, &idir, isect->t);
+ isect->t = bvh_instance_push(kg, object, ray, &P, &dir, &idir, isect->t);
# endif
# if defined(__KERNEL_SSE2__)
- Psplat[0] = ssef(P.x);
- Psplat[1] = ssef(P.y);
- Psplat[2] = ssef(P.z);
+ Psplat[0] = ssef(P.x);
+ Psplat[1] = ssef(P.y);
+ Psplat[2] = ssef(P.z);
- tsplat = ssef(0.0f, 0.0f, -isect->t, -isect->t);
+ tsplat = ssef(0.0f, 0.0f, -isect->t, -isect->t);
# if BVH_FEATURE(BVH_HAIR)
- tfar = ssef(isect->t);
+ tfar = ssef(isect->t);
# endif
- gen_idirsplat_swap(pn, shuf_identity, shuf_swap, idir, idirsplat, shufflexyz);
+ gen_idirsplat_swap(pn, shuf_identity, shuf_swap, idir, idirsplat, shufflexyz);
# endif
- ++stack_ptr;
- kernel_assert(stack_ptr < BVH_STACK_SIZE);
- traversal_stack[stack_ptr] = ENTRYPOINT_SENTINEL;
-
- node_addr = kernel_tex_fetch(__object_node, object);
- }
- else {
- /* pop */
- object = OBJECT_NONE;
- node_addr = traversal_stack[stack_ptr];
- --stack_ptr;
- }
- }
- }
-#endif /* FEATURE(BVH_INSTANCING) */
- } while(node_addr != ENTRYPOINT_SENTINEL);
+ ++stack_ptr;
+ kernel_assert(stack_ptr < BVH_STACK_SIZE);
+ traversal_stack[stack_ptr] = ENTRYPOINT_SENTINEL;
+
+ node_addr = kernel_tex_fetch(__object_node, object);
+ }
+ else {
+ /* pop */
+ object = OBJECT_NONE;
+ node_addr = traversal_stack[stack_ptr];
+ --stack_ptr;
+ }
+ }
+ }
+#endif /* FEATURE(BVH_INSTANCING) */
+ } while (node_addr != ENTRYPOINT_SENTINEL);
#if BVH_FEATURE(BVH_INSTANCING)
- if(stack_ptr >= 0) {
- kernel_assert(object != OBJECT_NONE);
+ if (stack_ptr >= 0) {
+ kernel_assert(object != OBJECT_NONE);
- /* instance pop */
+ /* instance pop */
# if BVH_FEATURE(BVH_MOTION)
- isect->t = bvh_instance_motion_pop(kg, object, ray, &P, &dir, &idir, isect->t, &ob_itfm);
+ isect->t = bvh_instance_motion_pop(kg, object, ray, &P, &dir, &idir, isect->t, &ob_itfm);
# else
- isect->t = bvh_instance_pop(kg, object, ray, &P, &dir, &idir, isect->t);
+ isect->t = bvh_instance_pop(kg, object, ray, &P, &dir, &idir, isect->t);
# endif
# if defined(__KERNEL_SSE2__)
- Psplat[0] = ssef(P.x);
- Psplat[1] = ssef(P.y);
- Psplat[2] = ssef(P.z);
+ Psplat[0] = ssef(P.x);
+ Psplat[1] = ssef(P.y);
+ Psplat[2] = ssef(P.z);
- tsplat = ssef(0.0f, 0.0f, -isect->t, -isect->t);
+ tsplat = ssef(0.0f, 0.0f, -isect->t, -isect->t);
# if BVH_FEATURE(BVH_HAIR)
- tfar = ssef(isect->t);
+ tfar = ssef(isect->t);
# endif
- gen_idirsplat_swap(pn, shuf_identity, shuf_swap, idir, idirsplat, shufflexyz);
+ gen_idirsplat_swap(pn, shuf_identity, shuf_swap, idir, idirsplat, shufflexyz);
# endif
- object = OBJECT_NONE;
- node_addr = traversal_stack[stack_ptr];
- --stack_ptr;
- }
-#endif /* FEATURE(BVH_MOTION) */
- } while(node_addr != ENTRYPOINT_SENTINEL);
+ object = OBJECT_NONE;
+ node_addr = traversal_stack[stack_ptr];
+ --stack_ptr;
+ }
+#endif /* FEATURE(BVH_MOTION) */
+ } while (node_addr != ENTRYPOINT_SENTINEL);
- return (isect->prim != PRIM_NONE);
+ return (isect->prim != PRIM_NONE);
}
ccl_device_inline bool BVH_FUNCTION_NAME(KernelGlobals *kg,
@@ -311,29 +304,20 @@ ccl_device_inline bool BVH_FUNCTION_NAME(KernelGlobals *kg,
Intersection *isect,
const uint visibility)
{
- switch(kernel_data.bvh.bvh_layout) {
+ switch (kernel_data.bvh.bvh_layout) {
#ifdef __KERNEL_AVX2__
- case BVH_LAYOUT_BVH8:
- return BVH_FUNCTION_FULL_NAME(OBVH)(kg,
- ray,
- isect,
- visibility);
+ case BVH_LAYOUT_BVH8:
+ return BVH_FUNCTION_FULL_NAME(OBVH)(kg, ray, isect, visibility);
#endif
#ifdef __QBVH__
- case BVH_LAYOUT_BVH4:
- return BVH_FUNCTION_FULL_NAME(QBVH)(kg,
- ray,
- isect,
- visibility);
+ case BVH_LAYOUT_BVH4:
+ return BVH_FUNCTION_FULL_NAME(QBVH)(kg, ray, isect, visibility);
#endif
- case BVH_LAYOUT_BVH2:
- return BVH_FUNCTION_FULL_NAME(BVH)(kg,
- ray,
- isect,
- visibility);
- }
- kernel_assert(!"Should not happen");
- return false;
+ case BVH_LAYOUT_BVH2:
+ return BVH_FUNCTION_FULL_NAME(BVH)(kg, ray, isect, visibility);
+ }
+ kernel_assert(!"Should not happen");
+ return false;
}
#undef BVH_FUNCTION_NAME
diff --git a/intern/cycles/kernel/bvh/bvh_volume_all.h b/intern/cycles/kernel/bvh/bvh_volume_all.h
index f3ca4058460..ae8c4d12e8a 100644
--- a/intern/cycles/kernel/bvh/bvh_volume_all.h
+++ b/intern/cycles/kernel/bvh/bvh_volume_all.h
@@ -19,9 +19,9 @@
#ifdef __QBVH__
# include "kernel/bvh/qbvh_volume_all.h"
-#ifdef __KERNEL_AVX2__
-# include "kernel/bvh/obvh_volume_all.h"
-#endif
+# ifdef __KERNEL_AVX2__
+# include "kernel/bvh/obvh_volume_all.h"
+# endif
#endif
#if BVH_FEATURE(BVH_HAIR)
@@ -43,342 +43,337 @@ ccl_device
#else
ccl_device_inline
#endif
-uint BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg,
- const Ray *ray,
- Intersection *isect_array,
- const uint max_hits,
- const uint visibility)
+ uint BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg,
+ const Ray *ray,
+ Intersection *isect_array,
+ const uint max_hits,
+ const uint visibility)
{
- /* todo:
- * - test if pushing distance on the stack helps (for non shadow rays)
- * - separate version for shadow rays
- * - likely and unlikely for if() statements
- * - test restrict attribute for pointers
- */
-
- /* traversal stack in CUDA thread-local memory */
- int traversal_stack[BVH_STACK_SIZE];
- traversal_stack[0] = ENTRYPOINT_SENTINEL;
-
- /* traversal variables in registers */
- int stack_ptr = 0;
- int node_addr = kernel_data.bvh.root;
-
- /* ray parameters in registers */
- const float tmax = ray->t;
- float3 P = ray->P;
- float3 dir = bvh_clamp_direction(ray->D);
- float3 idir = bvh_inverse_direction(dir);
- int object = OBJECT_NONE;
- float isect_t = tmax;
+ /* todo:
+ * - test if pushing distance on the stack helps (for non shadow rays)
+ * - separate version for shadow rays
+ * - likely and unlikely for if() statements
+ * - test restrict attribute for pointers
+ */
+
+ /* traversal stack in CUDA thread-local memory */
+ int traversal_stack[BVH_STACK_SIZE];
+ traversal_stack[0] = ENTRYPOINT_SENTINEL;
+
+ /* traversal variables in registers */
+ int stack_ptr = 0;
+ int node_addr = kernel_data.bvh.root;
+
+ /* ray parameters in registers */
+ const float tmax = ray->t;
+ float3 P = ray->P;
+ float3 dir = bvh_clamp_direction(ray->D);
+ float3 idir = bvh_inverse_direction(dir);
+ int object = OBJECT_NONE;
+ float isect_t = tmax;
#if BVH_FEATURE(BVH_MOTION)
- Transform ob_itfm;
+ Transform ob_itfm;
#endif
#if BVH_FEATURE(BVH_INSTANCING)
- int num_hits_in_instance = 0;
+ int num_hits_in_instance = 0;
#endif
- uint num_hits = 0;
- isect_array->t = tmax;
+ uint num_hits = 0;
+ isect_array->t = tmax;
#if defined(__KERNEL_SSE2__)
- const shuffle_swap_t shuf_identity = shuffle_swap_identity();
- const shuffle_swap_t shuf_swap = shuffle_swap_swap();
+ const shuffle_swap_t shuf_identity = shuffle_swap_identity();
+ const shuffle_swap_t shuf_swap = shuffle_swap_swap();
- const ssef pn = cast(ssei(0, 0, 0x80000000, 0x80000000));
- ssef Psplat[3], idirsplat[3];
+ const ssef pn = cast(ssei(0, 0, 0x80000000, 0x80000000));
+ ssef Psplat[3], idirsplat[3];
# if BVH_FEATURE(BVH_HAIR)
- ssef tnear(0.0f), tfar(isect_t);
+ ssef tnear(0.0f), tfar(isect_t);
# endif
- shuffle_swap_t shufflexyz[3];
+ shuffle_swap_t shufflexyz[3];
- Psplat[0] = ssef(P.x);
- Psplat[1] = ssef(P.y);
- Psplat[2] = ssef(P.z);
+ Psplat[0] = ssef(P.x);
+ Psplat[1] = ssef(P.y);
+ Psplat[2] = ssef(P.z);
- ssef tsplat(0.0f, 0.0f, -isect_t, -isect_t);
+ ssef tsplat(0.0f, 0.0f, -isect_t, -isect_t);
- gen_idirsplat_swap(pn, shuf_identity, shuf_swap, idir, idirsplat, shufflexyz);
-#endif /* __KERNEL_SSE2__ */
+ gen_idirsplat_swap(pn, shuf_identity, shuf_swap, idir, idirsplat, shufflexyz);
+#endif /* __KERNEL_SSE2__ */
- /* traversal loop */
- do {
- do {
- /* traverse internal nodes */
- while(node_addr >= 0 && node_addr != ENTRYPOINT_SENTINEL) {
- int node_addr_child1, traverse_mask;
- float dist[2];
- float4 cnodes = kernel_tex_fetch(__bvh_nodes, node_addr+0);
+ /* traversal loop */
+ do {
+ do {
+ /* traverse internal nodes */
+ while (node_addr >= 0 && node_addr != ENTRYPOINT_SENTINEL) {
+ int node_addr_child1, traverse_mask;
+ float dist[2];
+ float4 cnodes = kernel_tex_fetch(__bvh_nodes, node_addr + 0);
#if !defined(__KERNEL_SSE2__)
- traverse_mask = NODE_INTERSECT(kg,
- P,
+ traverse_mask = NODE_INTERSECT(kg,
+ P,
# if BVH_FEATURE(BVH_HAIR)
- dir,
+ dir,
# endif
- idir,
- isect_t,
- node_addr,
- visibility,
- dist);
+ idir,
+ isect_t,
+ node_addr,
+ visibility,
+ dist);
#else // __KERNEL_SSE2__
- traverse_mask = NODE_INTERSECT(kg,
- P,
- dir,
+ traverse_mask = NODE_INTERSECT(kg,
+ P,
+ dir,
# if BVH_FEATURE(BVH_HAIR)
- tnear,
- tfar,
+ tnear,
+ tfar,
# endif
- tsplat,
- Psplat,
- idirsplat,
- shufflexyz,
- node_addr,
- visibility,
- dist);
+ tsplat,
+ Psplat,
+ idirsplat,
+ shufflexyz,
+ node_addr,
+ visibility,
+ dist);
#endif // __KERNEL_SSE2__
- node_addr = __float_as_int(cnodes.z);
- node_addr_child1 = __float_as_int(cnodes.w);
-
- if(traverse_mask == 3) {
- /* Both children were intersected, push the farther one. */
- bool is_closest_child1 = (dist[1] < dist[0]);
- if(is_closest_child1) {
- int tmp = node_addr;
- node_addr = node_addr_child1;
- node_addr_child1 = tmp;
- }
-
- ++stack_ptr;
- kernel_assert(stack_ptr < BVH_STACK_SIZE);
- traversal_stack[stack_ptr] = node_addr_child1;
- }
- else {
- /* One child was intersected. */
- if(traverse_mask == 2) {
- node_addr = node_addr_child1;
- }
- else if(traverse_mask == 0) {
- /* Neither child was intersected. */
- node_addr = traversal_stack[stack_ptr];
- --stack_ptr;
- }
- }
- }
-
- /* if node is leaf, fetch triangle list */
- if(node_addr < 0) {
- float4 leaf = kernel_tex_fetch(__bvh_leaf_nodes, (-node_addr-1));
- int prim_addr = __float_as_int(leaf.x);
+ node_addr = __float_as_int(cnodes.z);
+ node_addr_child1 = __float_as_int(cnodes.w);
+
+ if (traverse_mask == 3) {
+ /* Both children were intersected, push the farther one. */
+ bool is_closest_child1 = (dist[1] < dist[0]);
+ if (is_closest_child1) {
+ int tmp = node_addr;
+ node_addr = node_addr_child1;
+ node_addr_child1 = tmp;
+ }
+
+ ++stack_ptr;
+ kernel_assert(stack_ptr < BVH_STACK_SIZE);
+ traversal_stack[stack_ptr] = node_addr_child1;
+ }
+ else {
+ /* One child was intersected. */
+ if (traverse_mask == 2) {
+ node_addr = node_addr_child1;
+ }
+ else if (traverse_mask == 0) {
+ /* Neither child was intersected. */
+ node_addr = traversal_stack[stack_ptr];
+ --stack_ptr;
+ }
+ }
+ }
+
+ /* if node is leaf, fetch triangle list */
+ if (node_addr < 0) {
+ float4 leaf = kernel_tex_fetch(__bvh_leaf_nodes, (-node_addr - 1));
+ int prim_addr = __float_as_int(leaf.x);
#if BVH_FEATURE(BVH_INSTANCING)
- if(prim_addr >= 0) {
+ if (prim_addr >= 0) {
#endif
- const int prim_addr2 = __float_as_int(leaf.y);
- const uint type = __float_as_int(leaf.w);
- bool hit;
-
- /* pop */
- node_addr = traversal_stack[stack_ptr];
- --stack_ptr;
-
- /* primitive intersection */
- switch(type & PRIMITIVE_ALL) {
- case PRIMITIVE_TRIANGLE: {
- /* intersect ray against primitive */
- for(; prim_addr < prim_addr2; prim_addr++) {
- kernel_assert(kernel_tex_fetch(__prim_type, prim_addr) == type);
- /* only primitives from volume object */
- uint tri_object = (object == OBJECT_NONE)? kernel_tex_fetch(__prim_object, prim_addr): object;
- int object_flag = kernel_tex_fetch(__object_flag, tri_object);
- if((object_flag & SD_OBJECT_HAS_VOLUME) == 0) {
- continue;
- }
- hit = triangle_intersect(kg,
- isect_array,
- P,
- dir,
- visibility,
- object,
- prim_addr);
- if(hit) {
- /* Move on to next entry in intersections array. */
- isect_array++;
- num_hits++;
+ const int prim_addr2 = __float_as_int(leaf.y);
+ const uint type = __float_as_int(leaf.w);
+ bool hit;
+
+ /* pop */
+ node_addr = traversal_stack[stack_ptr];
+ --stack_ptr;
+
+ /* primitive intersection */
+ switch (type & PRIMITIVE_ALL) {
+ case PRIMITIVE_TRIANGLE: {
+ /* intersect ray against primitive */
+ for (; prim_addr < prim_addr2; prim_addr++) {
+ kernel_assert(kernel_tex_fetch(__prim_type, prim_addr) == type);
+ /* only primitives from volume object */
+ uint tri_object = (object == OBJECT_NONE) ?
+ kernel_tex_fetch(__prim_object, prim_addr) :
+ object;
+ int object_flag = kernel_tex_fetch(__object_flag, tri_object);
+ if ((object_flag & SD_OBJECT_HAS_VOLUME) == 0) {
+ continue;
+ }
+ hit = triangle_intersect(kg, isect_array, P, dir, visibility, object, prim_addr);
+ if (hit) {
+ /* Move on to next entry in intersections array. */
+ isect_array++;
+ num_hits++;
#if BVH_FEATURE(BVH_INSTANCING)
- num_hits_in_instance++;
+ num_hits_in_instance++;
#endif
- isect_array->t = isect_t;
- if(num_hits == max_hits) {
+ isect_array->t = isect_t;
+ if (num_hits == max_hits) {
#if BVH_FEATURE(BVH_INSTANCING)
- if(object != OBJECT_NONE) {
+ if (object != OBJECT_NONE) {
# if BVH_FEATURE(BVH_MOTION)
- float t_fac = 1.0f / len(transform_direction(&ob_itfm, dir));
+ float t_fac = 1.0f / len(transform_direction(&ob_itfm, dir));
# else
- Transform itfm = object_fetch_transform(kg, object, OBJECT_INVERSE_TRANSFORM);
- float t_fac = 1.0f / len(transform_direction(&itfm, dir));
+ Transform itfm = object_fetch_transform(
+ kg, object, OBJECT_INVERSE_TRANSFORM);
+ float t_fac = 1.0f / len(transform_direction(&itfm, dir));
# endif
- for(int i = 0; i < num_hits_in_instance; i++) {
- (isect_array-i-1)->t *= t_fac;
- }
- }
-#endif /* BVH_FEATURE(BVH_INSTANCING) */
- return num_hits;
- }
- }
- }
- break;
- }
+ for (int i = 0; i < num_hits_in_instance; i++) {
+ (isect_array - i - 1)->t *= t_fac;
+ }
+ }
+#endif /* BVH_FEATURE(BVH_INSTANCING) */
+ return num_hits;
+ }
+ }
+ }
+ break;
+ }
#if BVH_FEATURE(BVH_MOTION)
- case PRIMITIVE_MOTION_TRIANGLE: {
- /* intersect ray against primitive */
- for(; prim_addr < prim_addr2; prim_addr++) {
- kernel_assert(kernel_tex_fetch(__prim_type, prim_addr) == type);
- /* only primitives from volume object */
- uint tri_object = (object == OBJECT_NONE)? kernel_tex_fetch(__prim_object, prim_addr): object;
- int object_flag = kernel_tex_fetch(__object_flag, tri_object);
- if((object_flag & SD_OBJECT_HAS_VOLUME) == 0) {
- continue;
- }
- hit = motion_triangle_intersect(kg,
- isect_array,
- P,
- dir,
- ray->time,
- visibility,
- object,
- prim_addr);
- if(hit) {
- /* Move on to next entry in intersections array. */
- isect_array++;
- num_hits++;
+ case PRIMITIVE_MOTION_TRIANGLE: {
+ /* intersect ray against primitive */
+ for (; prim_addr < prim_addr2; prim_addr++) {
+ kernel_assert(kernel_tex_fetch(__prim_type, prim_addr) == type);
+ /* only primitives from volume object */
+ uint tri_object = (object == OBJECT_NONE) ?
+ kernel_tex_fetch(__prim_object, prim_addr) :
+ object;
+ int object_flag = kernel_tex_fetch(__object_flag, tri_object);
+ if ((object_flag & SD_OBJECT_HAS_VOLUME) == 0) {
+ continue;
+ }
+ hit = motion_triangle_intersect(
+ kg, isect_array, P, dir, ray->time, visibility, object, prim_addr);
+ if (hit) {
+ /* Move on to next entry in intersections array. */
+ isect_array++;
+ num_hits++;
# if BVH_FEATURE(BVH_INSTANCING)
- num_hits_in_instance++;
+ num_hits_in_instance++;
# endif
- isect_array->t = isect_t;
- if(num_hits == max_hits) {
+ isect_array->t = isect_t;
+ if (num_hits == max_hits) {
# if BVH_FEATURE(BVH_INSTANCING)
- if(object != OBJECT_NONE) {
+ if (object != OBJECT_NONE) {
# if BVH_FEATURE(BVH_MOTION)
- float t_fac = 1.0f / len(transform_direction(&ob_itfm, dir));
+ float t_fac = 1.0f / len(transform_direction(&ob_itfm, dir));
# else
- Transform itfm = object_fetch_transform(kg, object, OBJECT_INVERSE_TRANSFORM);
- float t_fac = 1.0f / len(transform_direction(&itfm, dir));
+ Transform itfm = object_fetch_transform(
+ kg, object, OBJECT_INVERSE_TRANSFORM);
+ float t_fac = 1.0f / len(transform_direction(&itfm, dir));
# endif
- for(int i = 0; i < num_hits_in_instance; i++) {
- (isect_array-i-1)->t *= t_fac;
- }
- }
-# endif /* BVH_FEATURE(BVH_INSTANCING) */
- return num_hits;
- }
- }
- }
- break;
- }
-#endif /* BVH_MOTION */
- default: {
- break;
- }
- }
- }
+ for (int i = 0; i < num_hits_in_instance; i++) {
+ (isect_array - i - 1)->t *= t_fac;
+ }
+ }
+# endif /* BVH_FEATURE(BVH_INSTANCING) */
+ return num_hits;
+ }
+ }
+ }
+ break;
+ }
+#endif /* BVH_MOTION */
+ default: {
+ break;
+ }
+ }
+ }
#if BVH_FEATURE(BVH_INSTANCING)
- else {
- /* instance push */
- object = kernel_tex_fetch(__prim_object, -prim_addr-1);
- int object_flag = kernel_tex_fetch(__object_flag, object);
- if(object_flag & SD_OBJECT_HAS_VOLUME) {
+ else {
+ /* instance push */
+ object = kernel_tex_fetch(__prim_object, -prim_addr - 1);
+ int object_flag = kernel_tex_fetch(__object_flag, object);
+ if (object_flag & SD_OBJECT_HAS_VOLUME) {
# if BVH_FEATURE(BVH_MOTION)
- isect_t = bvh_instance_motion_push(kg, object, ray, &P, &dir, &idir, isect_t, &ob_itfm);
+ isect_t = bvh_instance_motion_push(
+ kg, object, ray, &P, &dir, &idir, isect_t, &ob_itfm);
# else
- isect_t = bvh_instance_push(kg, object, ray, &P, &dir, &idir, isect_t);
+ isect_t = bvh_instance_push(kg, object, ray, &P, &dir, &idir, isect_t);
# endif
- num_hits_in_instance = 0;
- isect_array->t = isect_t;
+ num_hits_in_instance = 0;
+ isect_array->t = isect_t;
# if defined(__KERNEL_SSE2__)
- Psplat[0] = ssef(P.x);
- Psplat[1] = ssef(P.y);
- Psplat[2] = ssef(P.z);
+ Psplat[0] = ssef(P.x);
+ Psplat[1] = ssef(P.y);
+ Psplat[2] = ssef(P.z);
- tsplat = ssef(0.0f, 0.0f, -isect_t, -isect_t);
+ tsplat = ssef(0.0f, 0.0f, -isect_t, -isect_t);
# if BVH_FEATURE(BVH_HAIR)
- tfar = ssef(isect_t);
+ tfar = ssef(isect_t);
# endif
- gen_idirsplat_swap(pn, shuf_identity, shuf_swap, idir, idirsplat, shufflexyz);
+ gen_idirsplat_swap(pn, shuf_identity, shuf_swap, idir, idirsplat, shufflexyz);
# endif
- ++stack_ptr;
- kernel_assert(stack_ptr < BVH_STACK_SIZE);
- traversal_stack[stack_ptr] = ENTRYPOINT_SENTINEL;
-
- node_addr = kernel_tex_fetch(__object_node, object);
- }
- else {
- /* pop */
- object = OBJECT_NONE;
- node_addr = traversal_stack[stack_ptr];
- --stack_ptr;
- }
- }
- }
-#endif /* FEATURE(BVH_INSTANCING) */
- } while(node_addr != ENTRYPOINT_SENTINEL);
+ ++stack_ptr;
+ kernel_assert(stack_ptr < BVH_STACK_SIZE);
+ traversal_stack[stack_ptr] = ENTRYPOINT_SENTINEL;
+
+ node_addr = kernel_tex_fetch(__object_node, object);
+ }
+ else {
+ /* pop */
+ object = OBJECT_NONE;
+ node_addr = traversal_stack[stack_ptr];
+ --stack_ptr;
+ }
+ }
+ }
+#endif /* FEATURE(BVH_INSTANCING) */
+ } while (node_addr != ENTRYPOINT_SENTINEL);
#if BVH_FEATURE(BVH_INSTANCING)
- if(stack_ptr >= 0) {
- kernel_assert(object != OBJECT_NONE);
+ if (stack_ptr >= 0) {
+ kernel_assert(object != OBJECT_NONE);
- /* Instance pop. */
- if(num_hits_in_instance) {
- float t_fac;
+ /* Instance pop. */
+ if (num_hits_in_instance) {
+ float t_fac;
# if BVH_FEATURE(BVH_MOTION)
- bvh_instance_motion_pop_factor(kg, object, ray, &P, &dir, &idir, &t_fac, &ob_itfm);
+ bvh_instance_motion_pop_factor(kg, object, ray, &P, &dir, &idir, &t_fac, &ob_itfm);
# else
- bvh_instance_pop_factor(kg, object, ray, &P, &dir, &idir, &t_fac);
+ bvh_instance_pop_factor(kg, object, ray, &P, &dir, &idir, &t_fac);
# endif
- /* Scale isect->t to adjust for instancing. */
- for(int i = 0; i < num_hits_in_instance; i++) {
- (isect_array-i-1)->t *= t_fac;
- }
- }
- else {
+ /* Scale isect->t to adjust for instancing. */
+ for (int i = 0; i < num_hits_in_instance; i++) {
+ (isect_array - i - 1)->t *= t_fac;
+ }
+ }
+ else {
# if BVH_FEATURE(BVH_MOTION)
- bvh_instance_motion_pop(kg, object, ray, &P, &dir, &idir, FLT_MAX, &ob_itfm);
+ bvh_instance_motion_pop(kg, object, ray, &P, &dir, &idir, FLT_MAX, &ob_itfm);
# else
- bvh_instance_pop(kg, object, ray, &P, &dir, &idir, FLT_MAX);
+ bvh_instance_pop(kg, object, ray, &P, &dir, &idir, FLT_MAX);
# endif
- }
+ }
- isect_t = tmax;
- isect_array->t = isect_t;
+ isect_t = tmax;
+ isect_array->t = isect_t;
# if defined(__KERNEL_SSE2__)
- Psplat[0] = ssef(P.x);
- Psplat[1] = ssef(P.y);
- Psplat[2] = ssef(P.z);
+ Psplat[0] = ssef(P.x);
+ Psplat[1] = ssef(P.y);
+ Psplat[2] = ssef(P.z);
- tsplat = ssef(0.0f, 0.0f, -isect_t, -isect_t);
+ tsplat = ssef(0.0f, 0.0f, -isect_t, -isect_t);
# if BVH_FEATURE(BVH_HAIR)
- tfar = ssef(isect_t);
+ tfar = ssef(isect_t);
# endif
- gen_idirsplat_swap(pn, shuf_identity, shuf_swap, idir, idirsplat, shufflexyz);
+ gen_idirsplat_swap(pn, shuf_identity, shuf_swap, idir, idirsplat, shufflexyz);
# endif
- object = OBJECT_NONE;
- node_addr = traversal_stack[stack_ptr];
- --stack_ptr;
- }
-#endif /* FEATURE(BVH_INSTANCING) */
- } while(node_addr != ENTRYPOINT_SENTINEL);
+ object = OBJECT_NONE;
+ node_addr = traversal_stack[stack_ptr];
+ --stack_ptr;
+ }
+#endif /* FEATURE(BVH_INSTANCING) */
+ } while (node_addr != ENTRYPOINT_SENTINEL);
- return num_hits;
+ return num_hits;
}
ccl_device_inline uint BVH_FUNCTION_NAME(KernelGlobals *kg,
@@ -387,32 +382,20 @@ ccl_device_inline uint BVH_FUNCTION_NAME(KernelGlobals *kg,
const uint max_hits,
const uint visibility)
{
- switch(kernel_data.bvh.bvh_layout) {
+ switch (kernel_data.bvh.bvh_layout) {
#ifdef __KERNEL_AVX2__
- case BVH_LAYOUT_BVH8:
- return BVH_FUNCTION_FULL_NAME(OBVH)(kg,
- ray,
- isect_array,
- max_hits,
- visibility);
+ case BVH_LAYOUT_BVH8:
+ return BVH_FUNCTION_FULL_NAME(OBVH)(kg, ray, isect_array, max_hits, visibility);
#endif
#ifdef __QBVH__
- case BVH_LAYOUT_BVH4:
- return BVH_FUNCTION_FULL_NAME(QBVH)(kg,
- ray,
- isect_array,
- max_hits,
- visibility);
+ case BVH_LAYOUT_BVH4:
+ return BVH_FUNCTION_FULL_NAME(QBVH)(kg, ray, isect_array, max_hits, visibility);
#endif
- case BVH_LAYOUT_BVH2:
- return BVH_FUNCTION_FULL_NAME(BVH)(kg,
- ray,
- isect_array,
- max_hits,
- visibility);
- }
- kernel_assert(!"Should not happen");
- return 0;
+ case BVH_LAYOUT_BVH2:
+ return BVH_FUNCTION_FULL_NAME(BVH)(kg, ray, isect_array, max_hits, visibility);
+ }
+ kernel_assert(!"Should not happen");
+ return 0;
}
#undef BVH_FUNCTION_NAME
diff --git a/intern/cycles/kernel/bvh/obvh_local.h b/intern/cycles/kernel/bvh/obvh_local.h
index f449cefb335..e6bb548bc5b 100644
--- a/intern/cycles/kernel/bvh/obvh_local.h
+++ b/intern/cycles/kernel/bvh/obvh_local.h
@@ -34,372 +34,365 @@ ccl_device bool BVH_FUNCTION_FULL_NAME(OBVH)(KernelGlobals *kg,
uint *lcg_state,
int max_hits)
{
- /* Traversal stack in CUDA thread-local memory. */
- OBVHStackItem traversal_stack[BVH_OSTACK_SIZE];
- traversal_stack[0].addr = ENTRYPOINT_SENTINEL;
+ /* Traversal stack in CUDA thread-local memory. */
+ OBVHStackItem traversal_stack[BVH_OSTACK_SIZE];
+ traversal_stack[0].addr = ENTRYPOINT_SENTINEL;
- /* Traversal variables in registers. */
- int stack_ptr = 0;
- int node_addr = kernel_tex_fetch(__object_node, local_object);
+ /* Traversal variables in registers. */
+ int stack_ptr = 0;
+ int node_addr = kernel_tex_fetch(__object_node, local_object);
- /* Ray parameters in registers. */
- float3 P = ray->P;
- float3 dir = bvh_clamp_direction(ray->D);
- float3 idir = bvh_inverse_direction(dir);
- int object = OBJECT_NONE;
- float isect_t = ray->t;
+ /* Ray parameters in registers. */
+ float3 P = ray->P;
+ float3 dir = bvh_clamp_direction(ray->D);
+ float3 idir = bvh_inverse_direction(dir);
+ int object = OBJECT_NONE;
+ float isect_t = ray->t;
- if(local_isect != NULL) {
- local_isect->num_hits = 0;
- }
- kernel_assert((local_isect == NULL) == (max_hits == 0));
+ if (local_isect != NULL) {
+ local_isect->num_hits = 0;
+ }
+ kernel_assert((local_isect == NULL) == (max_hits == 0));
- const int object_flag = kernel_tex_fetch(__object_flag, local_object);
- if(!(object_flag & SD_OBJECT_TRANSFORM_APPLIED)) {
+ const int object_flag = kernel_tex_fetch(__object_flag, local_object);
+ if (!(object_flag & SD_OBJECT_TRANSFORM_APPLIED)) {
#if BVH_FEATURE(BVH_MOTION)
- Transform ob_itfm;
- isect_t = bvh_instance_motion_push(kg,
- local_object,
- ray,
- &P,
- &dir,
- &idir,
- isect_t,
- &ob_itfm);
+ Transform ob_itfm;
+ isect_t = bvh_instance_motion_push(kg, local_object, ray, &P, &dir, &idir, isect_t, &ob_itfm);
#else
- isect_t = bvh_instance_push(kg, local_object, ray, &P, &dir, &idir, isect_t);
+ isect_t = bvh_instance_push(kg, local_object, ray, &P, &dir, &idir, isect_t);
#endif
- object = local_object;
- }
+ object = local_object;
+ }
- avxf tnear(0.0f), tfar(isect_t);
+ avxf tnear(0.0f), tfar(isect_t);
#if BVH_FEATURE(BVH_HAIR)
- avx3f dir4(avxf(dir.x), avxf(dir.y), avxf(dir.z));
+ avx3f dir4(avxf(dir.x), avxf(dir.y), avxf(dir.z));
#endif
- avx3f idir4(avxf(idir.x), avxf(idir.y), avxf(idir.z));
+ avx3f idir4(avxf(idir.x), avxf(idir.y), avxf(idir.z));
#ifdef __KERNEL_AVX2__
- float3 P_idir = P*idir;
- avx3f P_idir4(P_idir.x, P_idir.y, P_idir.z);
+ float3 P_idir = P * idir;
+ avx3f P_idir4(P_idir.x, P_idir.y, P_idir.z);
#endif
#if BVH_FEATURE(BVH_HAIR) || !defined(__KERNEL_AVX2__)
- avx3f org4(avxf(P.x), avxf(P.y), avxf(P.z));
+ avx3f org4(avxf(P.x), avxf(P.y), avxf(P.z));
#endif
- /* Offsets to select the side that becomes the lower or upper bound. */
- int near_x, near_y, near_z;
- int far_x, far_y, far_z;
- obvh_near_far_idx_calc(idir,
- &near_x, &near_y, &near_z,
- &far_x, &far_y, &far_z);
+ /* Offsets to select the side that becomes the lower or upper bound. */
+ int near_x, near_y, near_z;
+ int far_x, far_y, far_z;
+ obvh_near_far_idx_calc(idir, &near_x, &near_y, &near_z, &far_x, &far_y, &far_z);
- /* Traversal loop. */
- do {
- do {
- /* Traverse internal nodes. */
- while(node_addr >= 0 && node_addr != ENTRYPOINT_SENTINEL) {
- avxf dist;
- int child_mask = NODE_INTERSECT(kg,
- tnear,
- tfar,
+ /* Traversal loop. */
+ do {
+ do {
+ /* Traverse internal nodes. */
+ while (node_addr >= 0 && node_addr != ENTRYPOINT_SENTINEL) {
+ avxf dist;
+ int child_mask = NODE_INTERSECT(kg,
+ tnear,
+ tfar,
#ifdef __KERNEL_AVX2__
- P_idir4,
+ P_idir4,
#endif
#if BVH_FEATURE(BVH_HAIR) || !defined(__KERNEL_AVX2__)
- org4,
+ org4,
#endif
#if BVH_FEATURE(BVH_HAIR)
- dir4,
+ dir4,
#endif
- idir4,
- near_x, near_y, near_z,
- far_x, far_y, far_z,
- node_addr,
- &dist);
+ idir4,
+ near_x,
+ near_y,
+ near_z,
+ far_x,
+ far_y,
+ far_z,
+ node_addr,
+ &dist);
- if(child_mask != 0) {
- float4 inodes = kernel_tex_fetch(__bvh_nodes, node_addr+0);
- avxf cnodes;
+ if (child_mask != 0) {
+ float4 inodes = kernel_tex_fetch(__bvh_nodes, node_addr + 0);
+ avxf cnodes;
#if BVH_FEATURE(BVH_HAIR)
- if(__float_as_uint(inodes.x) & PATH_RAY_NODE_UNALIGNED) {
- cnodes = kernel_tex_fetch_avxf(__bvh_nodes, node_addr+26);
- }
- else
+ if (__float_as_uint(inodes.x) & PATH_RAY_NODE_UNALIGNED) {
+ cnodes = kernel_tex_fetch_avxf(__bvh_nodes, node_addr + 26);
+ }
+ else
#endif
- {
- cnodes = kernel_tex_fetch_avxf(__bvh_nodes, node_addr+14);
- }
+ {
+ cnodes = kernel_tex_fetch_avxf(__bvh_nodes, node_addr + 14);
+ }
- /* One child is hit, continue with that child. */
- int r = __bscf(child_mask);
- if(child_mask == 0) {
- node_addr = __float_as_int(cnodes[r]);
- continue;
- }
+ /* One child is hit, continue with that child. */
+ int r = __bscf(child_mask);
+ if (child_mask == 0) {
+ node_addr = __float_as_int(cnodes[r]);
+ continue;
+ }
- /* Two children are hit, push far child, and continue with
- * closer child.
- */
- int c0 = __float_as_int(cnodes[r]);
- float d0 = ((float*)&dist)[r];
- r = __bscf(child_mask);
- int c1 = __float_as_int(cnodes[r]);
- float d1 = ((float*)&dist)[r];
- if(child_mask == 0) {
- if(d1 < d0) {
- node_addr = c1;
- ++stack_ptr;
- kernel_assert(stack_ptr < BVH_OSTACK_SIZE);
- traversal_stack[stack_ptr].addr = c0;
- traversal_stack[stack_ptr].dist = d0;
- continue;
- }
- else {
- node_addr = c0;
- ++stack_ptr;
- kernel_assert(stack_ptr < BVH_OSTACK_SIZE);
- traversal_stack[stack_ptr].addr = c1;
- traversal_stack[stack_ptr].dist = d1;
- continue;
- }
- }
+ /* Two children are hit, push far child, and continue with
+ * closer child.
+ */
+ int c0 = __float_as_int(cnodes[r]);
+ float d0 = ((float *)&dist)[r];
+ r = __bscf(child_mask);
+ int c1 = __float_as_int(cnodes[r]);
+ float d1 = ((float *)&dist)[r];
+ if (child_mask == 0) {
+ if (d1 < d0) {
+ node_addr = c1;
+ ++stack_ptr;
+ kernel_assert(stack_ptr < BVH_OSTACK_SIZE);
+ traversal_stack[stack_ptr].addr = c0;
+ traversal_stack[stack_ptr].dist = d0;
+ continue;
+ }
+ else {
+ node_addr = c0;
+ ++stack_ptr;
+ kernel_assert(stack_ptr < BVH_OSTACK_SIZE);
+ traversal_stack[stack_ptr].addr = c1;
+ traversal_stack[stack_ptr].dist = d1;
+ continue;
+ }
+ }
- /* Here starts the slow path for 3 or 4 hit children. We push
- * all nodes onto the stack to sort them there.
- */
- ++stack_ptr;
- kernel_assert(stack_ptr < BVH_OSTACK_SIZE);
- traversal_stack[stack_ptr].addr = c1;
- traversal_stack[stack_ptr].dist = d1;
- ++stack_ptr;
- kernel_assert(stack_ptr < BVH_OSTACK_SIZE);
- traversal_stack[stack_ptr].addr = c0;
- traversal_stack[stack_ptr].dist = d0;
+ /* Here starts the slow path for 3 or 4 hit children. We push
+ * all nodes onto the stack to sort them there.
+ */
+ ++stack_ptr;
+ kernel_assert(stack_ptr < BVH_OSTACK_SIZE);
+ traversal_stack[stack_ptr].addr = c1;
+ traversal_stack[stack_ptr].dist = d1;
+ ++stack_ptr;
+ kernel_assert(stack_ptr < BVH_OSTACK_SIZE);
+ traversal_stack[stack_ptr].addr = c0;
+ traversal_stack[stack_ptr].dist = d0;
- /* Three children are hit, push all onto stack and sort 3
- * stack items, continue with closest child.
- */
- r = __bscf(child_mask);
- int c2 = __float_as_int(cnodes[r]);
- float d2 = ((float*)&dist)[r];
- if(child_mask == 0) {
- ++stack_ptr;
- kernel_assert(stack_ptr < BVH_OSTACK_SIZE);
- traversal_stack[stack_ptr].addr = c2;
- traversal_stack[stack_ptr].dist = d2;
- obvh_stack_sort(&traversal_stack[stack_ptr],
- &traversal_stack[stack_ptr - 1],
- &traversal_stack[stack_ptr - 2]);
- node_addr = traversal_stack[stack_ptr].addr;
- --stack_ptr;
- continue;
- }
+ /* Three children are hit, push all onto stack and sort 3
+ * stack items, continue with closest child.
+ */
+ r = __bscf(child_mask);
+ int c2 = __float_as_int(cnodes[r]);
+ float d2 = ((float *)&dist)[r];
+ if (child_mask == 0) {
+ ++stack_ptr;
+ kernel_assert(stack_ptr < BVH_OSTACK_SIZE);
+ traversal_stack[stack_ptr].addr = c2;
+ traversal_stack[stack_ptr].dist = d2;
+ obvh_stack_sort(&traversal_stack[stack_ptr],
+ &traversal_stack[stack_ptr - 1],
+ &traversal_stack[stack_ptr - 2]);
+ node_addr = traversal_stack[stack_ptr].addr;
+ --stack_ptr;
+ continue;
+ }
- /* Four children are hit, push all onto stack and sort 4
- * stack items, continue with closest child.
- */
- r = __bscf(child_mask);
- int c3 = __float_as_int(cnodes[r]);
- float d3 = ((float*)&dist)[r];
- if(child_mask == 0) {
- ++stack_ptr;
- kernel_assert(stack_ptr < BVH_OSTACK_SIZE);
- traversal_stack[stack_ptr].addr = c3;
- traversal_stack[stack_ptr].dist = d3;
- ++stack_ptr;
- kernel_assert(stack_ptr < BVH_OSTACK_SIZE);
- traversal_stack[stack_ptr].addr = c2;
- traversal_stack[stack_ptr].dist = d2;
- obvh_stack_sort(&traversal_stack[stack_ptr],
- &traversal_stack[stack_ptr - 1],
- &traversal_stack[stack_ptr - 2],
- &traversal_stack[stack_ptr - 3]);
- node_addr = traversal_stack[stack_ptr].addr;
- --stack_ptr;
- continue;
- }
+ /* Four children are hit, push all onto stack and sort 4
+ * stack items, continue with closest child.
+ */
+ r = __bscf(child_mask);
+ int c3 = __float_as_int(cnodes[r]);
+ float d3 = ((float *)&dist)[r];
+ if (child_mask == 0) {
+ ++stack_ptr;
+ kernel_assert(stack_ptr < BVH_OSTACK_SIZE);
+ traversal_stack[stack_ptr].addr = c3;
+ traversal_stack[stack_ptr].dist = d3;
+ ++stack_ptr;
+ kernel_assert(stack_ptr < BVH_OSTACK_SIZE);
+ traversal_stack[stack_ptr].addr = c2;
+ traversal_stack[stack_ptr].dist = d2;
+ obvh_stack_sort(&traversal_stack[stack_ptr],
+ &traversal_stack[stack_ptr - 1],
+ &traversal_stack[stack_ptr - 2],
+ &traversal_stack[stack_ptr - 3]);
+ node_addr = traversal_stack[stack_ptr].addr;
+ --stack_ptr;
+ continue;
+ }
- ++stack_ptr;
- kernel_assert(stack_ptr < BVH_OSTACK_SIZE);
- traversal_stack[stack_ptr].addr = c3;
- traversal_stack[stack_ptr].dist = d3;
- ++stack_ptr;
- kernel_assert(stack_ptr < BVH_OSTACK_SIZE);
- traversal_stack[stack_ptr].addr = c2;
- traversal_stack[stack_ptr].dist = d2;
+ ++stack_ptr;
+ kernel_assert(stack_ptr < BVH_OSTACK_SIZE);
+ traversal_stack[stack_ptr].addr = c3;
+ traversal_stack[stack_ptr].dist = d3;
+ ++stack_ptr;
+ kernel_assert(stack_ptr < BVH_OSTACK_SIZE);
+ traversal_stack[stack_ptr].addr = c2;
+ traversal_stack[stack_ptr].dist = d2;
- /* Five children are hit, push all onto stack and sort 5
- * stack items, continue with closest child
- */
- r = __bscf(child_mask);
- int c4 = __float_as_int(cnodes[r]);
- float d4 = ((float*)&dist)[r];
- if(child_mask == 0) {
- ++stack_ptr;
- kernel_assert(stack_ptr < BVH_OSTACK_SIZE);
- traversal_stack[stack_ptr].addr = c4;
- traversal_stack[stack_ptr].dist = d4;
- obvh_stack_sort(&traversal_stack[stack_ptr],
- &traversal_stack[stack_ptr - 1],
- &traversal_stack[stack_ptr - 2],
- &traversal_stack[stack_ptr - 3],
- &traversal_stack[stack_ptr - 4]);
- node_addr = traversal_stack[stack_ptr].addr;
- --stack_ptr;
- continue;
- }
- /* Six children are hit, push all onto stack and sort 6
- * stack items, continue with closest child.
- */
- r = __bscf(child_mask);
- int c5 = __float_as_int(cnodes[r]);
- float d5 = ((float*)&dist)[r];
- if(child_mask == 0) {
- ++stack_ptr;
- kernel_assert(stack_ptr < BVH_OSTACK_SIZE);
- traversal_stack[stack_ptr].addr = c5;
- traversal_stack[stack_ptr].dist = d5;
- ++stack_ptr;
- kernel_assert(stack_ptr < BVH_OSTACK_SIZE);
- traversal_stack[stack_ptr].addr = c4;
- traversal_stack[stack_ptr].dist = d4;
- obvh_stack_sort(&traversal_stack[stack_ptr],
- &traversal_stack[stack_ptr - 1],
- &traversal_stack[stack_ptr - 2],
- &traversal_stack[stack_ptr - 3],
- &traversal_stack[stack_ptr - 4],
- &traversal_stack[stack_ptr - 5]);
- node_addr = traversal_stack[stack_ptr].addr;
- --stack_ptr;
- continue;
- }
+ /* Five children are hit, push all onto stack and sort 5
+ * stack items, continue with closest child
+ */
+ r = __bscf(child_mask);
+ int c4 = __float_as_int(cnodes[r]);
+ float d4 = ((float *)&dist)[r];
+ if (child_mask == 0) {
+ ++stack_ptr;
+ kernel_assert(stack_ptr < BVH_OSTACK_SIZE);
+ traversal_stack[stack_ptr].addr = c4;
+ traversal_stack[stack_ptr].dist = d4;
+ obvh_stack_sort(&traversal_stack[stack_ptr],
+ &traversal_stack[stack_ptr - 1],
+ &traversal_stack[stack_ptr - 2],
+ &traversal_stack[stack_ptr - 3],
+ &traversal_stack[stack_ptr - 4]);
+ node_addr = traversal_stack[stack_ptr].addr;
+ --stack_ptr;
+ continue;
+ }
+ /* Six children are hit, push all onto stack and sort 6
+ * stack items, continue with closest child.
+ */
+ r = __bscf(child_mask);
+ int c5 = __float_as_int(cnodes[r]);
+ float d5 = ((float *)&dist)[r];
+ if (child_mask == 0) {
+ ++stack_ptr;
+ kernel_assert(stack_ptr < BVH_OSTACK_SIZE);
+ traversal_stack[stack_ptr].addr = c5;
+ traversal_stack[stack_ptr].dist = d5;
+ ++stack_ptr;
+ kernel_assert(stack_ptr < BVH_OSTACK_SIZE);
+ traversal_stack[stack_ptr].addr = c4;
+ traversal_stack[stack_ptr].dist = d4;
+ obvh_stack_sort(&traversal_stack[stack_ptr],
+ &traversal_stack[stack_ptr - 1],
+ &traversal_stack[stack_ptr - 2],
+ &traversal_stack[stack_ptr - 3],
+ &traversal_stack[stack_ptr - 4],
+ &traversal_stack[stack_ptr - 5]);
+ node_addr = traversal_stack[stack_ptr].addr;
+ --stack_ptr;
+ continue;
+ }
- ++stack_ptr;
- kernel_assert(stack_ptr < BVH_OSTACK_SIZE);
- traversal_stack[stack_ptr].addr = c5;
- traversal_stack[stack_ptr].dist = d5;
- ++stack_ptr;
- kernel_assert(stack_ptr < BVH_OSTACK_SIZE);
- traversal_stack[stack_ptr].addr = c4;
- traversal_stack[stack_ptr].dist = d4;
+ ++stack_ptr;
+ kernel_assert(stack_ptr < BVH_OSTACK_SIZE);
+ traversal_stack[stack_ptr].addr = c5;
+ traversal_stack[stack_ptr].dist = d5;
+ ++stack_ptr;
+ kernel_assert(stack_ptr < BVH_OSTACK_SIZE);
+ traversal_stack[stack_ptr].addr = c4;
+ traversal_stack[stack_ptr].dist = d4;
- /* Seven children are hit, push all onto stack and sort 7
- * stack items, continue with closest child.
- */
- r = __bscf(child_mask);
- int c6 = __float_as_int(cnodes[r]);
- float d6 = ((float*)&dist)[r];
- if(child_mask == 0) {
- ++stack_ptr;
- kernel_assert(stack_ptr < BVH_OSTACK_SIZE);
- traversal_stack[stack_ptr].addr = c6;
- traversal_stack[stack_ptr].dist = d6;
- obvh_stack_sort(&traversal_stack[stack_ptr],
- &traversal_stack[stack_ptr - 1],
- &traversal_stack[stack_ptr - 2],
- &traversal_stack[stack_ptr - 3],
- &traversal_stack[stack_ptr - 4],
- &traversal_stack[stack_ptr - 5],
- &traversal_stack[stack_ptr - 6]);
- node_addr = traversal_stack[stack_ptr].addr;
- --stack_ptr;
- continue;
- }
- /* Eight children are hit, push all onto stack and sort 8
- * stack items, continue with closest child.
- */
- r = __bscf(child_mask);
- int c7 = __float_as_int(cnodes[r]);
- float d7 = ((float*)&dist)[r];
- ++stack_ptr;
- kernel_assert(stack_ptr < BVH_OSTACK_SIZE);
- traversal_stack[stack_ptr].addr = c7;
- traversal_stack[stack_ptr].dist = d7;
- ++stack_ptr;
- kernel_assert(stack_ptr < BVH_OSTACK_SIZE);
- traversal_stack[stack_ptr].addr = c6;
- traversal_stack[stack_ptr].dist = d6;
- obvh_stack_sort(&traversal_stack[stack_ptr],
- &traversal_stack[stack_ptr - 1],
- &traversal_stack[stack_ptr - 2],
- &traversal_stack[stack_ptr - 3],
- &traversal_stack[stack_ptr - 4],
- &traversal_stack[stack_ptr - 5],
- &traversal_stack[stack_ptr - 6],
- &traversal_stack[stack_ptr - 7]);
- node_addr = traversal_stack[stack_ptr].addr;
- --stack_ptr;
- continue;
- }
+ /* Seven children are hit, push all onto stack and sort 7
+ * stack items, continue with closest child.
+ */
+ r = __bscf(child_mask);
+ int c6 = __float_as_int(cnodes[r]);
+ float d6 = ((float *)&dist)[r];
+ if (child_mask == 0) {
+ ++stack_ptr;
+ kernel_assert(stack_ptr < BVH_OSTACK_SIZE);
+ traversal_stack[stack_ptr].addr = c6;
+ traversal_stack[stack_ptr].dist = d6;
+ obvh_stack_sort(&traversal_stack[stack_ptr],
+ &traversal_stack[stack_ptr - 1],
+ &traversal_stack[stack_ptr - 2],
+ &traversal_stack[stack_ptr - 3],
+ &traversal_stack[stack_ptr - 4],
+ &traversal_stack[stack_ptr - 5],
+ &traversal_stack[stack_ptr - 6]);
+ node_addr = traversal_stack[stack_ptr].addr;
+ --stack_ptr;
+ continue;
+ }
+ /* Eight children are hit, push all onto stack and sort 8
+ * stack items, continue with closest child.
+ */
+ r = __bscf(child_mask);
+ int c7 = __float_as_int(cnodes[r]);
+ float d7 = ((float *)&dist)[r];
+ ++stack_ptr;
+ kernel_assert(stack_ptr < BVH_OSTACK_SIZE);
+ traversal_stack[stack_ptr].addr = c7;
+ traversal_stack[stack_ptr].dist = d7;
+ ++stack_ptr;
+ kernel_assert(stack_ptr < BVH_OSTACK_SIZE);
+ traversal_stack[stack_ptr].addr = c6;
+ traversal_stack[stack_ptr].dist = d6;
+ obvh_stack_sort(&traversal_stack[stack_ptr],
+ &traversal_stack[stack_ptr - 1],
+ &traversal_stack[stack_ptr - 2],
+ &traversal_stack[stack_ptr - 3],
+ &traversal_stack[stack_ptr - 4],
+ &traversal_stack[stack_ptr - 5],
+ &traversal_stack[stack_ptr - 6],
+ &traversal_stack[stack_ptr - 7]);
+ node_addr = traversal_stack[stack_ptr].addr;
+ --stack_ptr;
+ continue;
+ }
- node_addr = traversal_stack[stack_ptr].addr;
- --stack_ptr;
- }
+ node_addr = traversal_stack[stack_ptr].addr;
+ --stack_ptr;
+ }
- /* If node is leaf, fetch triangle list. */
- if(node_addr < 0) {
- float4 leaf = kernel_tex_fetch(__bvh_leaf_nodes, (-node_addr-1));
- int prim_addr = __float_as_int(leaf.x);
+ /* If node is leaf, fetch triangle list. */
+ if (node_addr < 0) {
+ float4 leaf = kernel_tex_fetch(__bvh_leaf_nodes, (-node_addr - 1));
+ int prim_addr = __float_as_int(leaf.x);
- int prim_addr2 = __float_as_int(leaf.y);
- const uint type = __float_as_int(leaf.w);
+ int prim_addr2 = __float_as_int(leaf.y);
+ const uint type = __float_as_int(leaf.w);
- /* Pop. */
- node_addr = traversal_stack[stack_ptr].addr;
- --stack_ptr;
+ /* Pop. */
+ node_addr = traversal_stack[stack_ptr].addr;
+ --stack_ptr;
- /* Primitive intersection. */
- switch(type & PRIMITIVE_ALL) {
- case PRIMITIVE_TRIANGLE: {
- /* Intersect ray against primitive, */
- for(; prim_addr < prim_addr2; prim_addr++) {
- kernel_assert(kernel_tex_fetch(__prim_type, prim_addr) == type);
- if(triangle_intersect_local(kg,
- local_isect,
- P,
- dir,
- object,
- local_object,
- prim_addr,
- isect_t,
- lcg_state,
- max_hits))
- {
- return true;
- }
- }
- break;
- }
+ /* Primitive intersection. */
+ switch (type & PRIMITIVE_ALL) {
+ case PRIMITIVE_TRIANGLE: {
+ /* Intersect ray against primitive, */
+ for (; prim_addr < prim_addr2; prim_addr++) {
+ kernel_assert(kernel_tex_fetch(__prim_type, prim_addr) == type);
+ if (triangle_intersect_local(kg,
+ local_isect,
+ P,
+ dir,
+ object,
+ local_object,
+ prim_addr,
+ isect_t,
+ lcg_state,
+ max_hits)) {
+ return true;
+ }
+ }
+ break;
+ }
#if BVH_FEATURE(BVH_MOTION)
- case PRIMITIVE_MOTION_TRIANGLE: {
- /* Intersect ray against primitive. */
- for(; prim_addr < prim_addr2; prim_addr++) {
- kernel_assert(kernel_tex_fetch(__prim_type, prim_addr) == type);
- if(motion_triangle_intersect_local(kg,
- local_isect,
- P,
- dir,
- ray->time,
- object,
- local_object,
- prim_addr,
- isect_t,
- lcg_state,
- max_hits))
- {
- return true;
- }
- }
- break;
- }
+ case PRIMITIVE_MOTION_TRIANGLE: {
+ /* Intersect ray against primitive. */
+ for (; prim_addr < prim_addr2; prim_addr++) {
+ kernel_assert(kernel_tex_fetch(__prim_type, prim_addr) == type);
+ if (motion_triangle_intersect_local(kg,
+ local_isect,
+ P,
+ dir,
+ ray->time,
+ object,
+ local_object,
+ prim_addr,
+ isect_t,
+ lcg_state,
+ max_hits)) {
+ return true;
+ }
+ }
+ break;
+ }
#endif
- default:
- break;
- }
- }
- } while(node_addr != ENTRYPOINT_SENTINEL);
- } while(node_addr != ENTRYPOINT_SENTINEL);
- return false;
+ default:
+ break;
+ }
+ }
+ } while (node_addr != ENTRYPOINT_SENTINEL);
+ } while (node_addr != ENTRYPOINT_SENTINEL);
+ return false;
}
#undef NODE_INTERSECT
diff --git a/intern/cycles/kernel/bvh/obvh_nodes.h b/intern/cycles/kernel/bvh/obvh_nodes.h
index 93f35f6dffb..6831562cade 100644
--- a/intern/cycles/kernel/bvh/obvh_nodes.h
+++ b/intern/cycles/kernel/bvh/obvh_nodes.h
@@ -17,11 +17,11 @@
*/
struct OBVHStackItem {
- int addr;
- float dist;
+ int addr;
+ float dist;
};
-ccl_device_inline void obvh_near_far_idx_calc(const float3& idir,
+ccl_device_inline void obvh_near_far_idx_calc(const float3 &idir,
int *ccl_restrict near_x,
int *ccl_restrict near_y,
int *ccl_restrict near_z,
@@ -31,41 +31,73 @@ ccl_device_inline void obvh_near_far_idx_calc(const float3& idir,
{
#ifdef __KERNEL_SSE__
- *near_x = 0; *far_x = 1;
- *near_y = 2; *far_y = 3;
- *near_z = 4; *far_z = 5;
-
- const size_t mask = movemask(ssef(idir.m128));
-
- const int mask_x = mask & 1;
- const int mask_y = (mask & 2) >> 1;
- const int mask_z = (mask & 4) >> 2;
-
- *near_x += mask_x; *far_x -= mask_x;
- *near_y += mask_y; *far_y -= mask_y;
- *near_z += mask_z; *far_z -= mask_z;
+ *near_x = 0;
+ *far_x = 1;
+ *near_y = 2;
+ *far_y = 3;
+ *near_z = 4;
+ *far_z = 5;
+
+ const size_t mask = movemask(ssef(idir.m128));
+
+ const int mask_x = mask & 1;
+ const int mask_y = (mask & 2) >> 1;
+ const int mask_z = (mask & 4) >> 2;
+
+ *near_x += mask_x;
+ *far_x -= mask_x;
+ *near_y += mask_y;
+ *far_y -= mask_y;
+ *near_z += mask_z;
+ *far_z -= mask_z;
#else
- if(idir.x >= 0.0f) { *near_x = 0; *far_x = 1; } else { *near_x = 1; *far_x = 0; }
- if(idir.y >= 0.0f) { *near_y = 2; *far_y = 3; } else { *near_y = 3; *far_y = 2; }
- if(idir.z >= 0.0f) { *near_z = 4; *far_z = 5; } else { *near_z = 5; *far_z = 4; }
+ if (idir.x >= 0.0f) {
+ *near_x = 0;
+ *far_x = 1;
+ }
+ else {
+ *near_x = 1;
+ *far_x = 0;
+ }
+ if (idir.y >= 0.0f) {
+ *near_y = 2;
+ *far_y = 3;
+ }
+ else {
+ *near_y = 3;
+ *far_y = 2;
+ }
+ if (idir.z >= 0.0f) {
+ *near_z = 4;
+ *far_z = 5;
+ }
+ else {
+ *near_z = 5;
+ *far_z = 4;
+ }
#endif
}
-ccl_device_inline void obvh_item_swap(OBVHStackItem *ccl_restrict a,
- OBVHStackItem *ccl_restrict b)
+ccl_device_inline void obvh_item_swap(OBVHStackItem *ccl_restrict a, OBVHStackItem *ccl_restrict b)
{
- OBVHStackItem tmp = *a;
- *a = *b;
- *b = tmp;
+ OBVHStackItem tmp = *a;
+ *a = *b;
+ *b = tmp;
}
ccl_device_inline void obvh_stack_sort(OBVHStackItem *ccl_restrict s1,
OBVHStackItem *ccl_restrict s2,
OBVHStackItem *ccl_restrict s3)
{
- if(s2->dist < s1->dist) { obvh_item_swap(s2, s1); }
- if(s3->dist < s2->dist) { obvh_item_swap(s3, s2); }
- if(s2->dist < s1->dist) { obvh_item_swap(s2, s1); }
+ if (s2->dist < s1->dist) {
+ obvh_item_swap(s2, s1);
+ }
+ if (s3->dist < s2->dist) {
+ obvh_item_swap(s3, s2);
+ }
+ if (s2->dist < s1->dist) {
+ obvh_item_swap(s2, s1);
+ }
}
ccl_device_inline void obvh_stack_sort(OBVHStackItem *ccl_restrict s1,
@@ -73,11 +105,21 @@ ccl_device_inline void obvh_stack_sort(OBVHStackItem *ccl_restrict s1,
OBVHStackItem *ccl_restrict s3,
OBVHStackItem *ccl_restrict s4)
{
- if(s2->dist < s1->dist) { obvh_item_swap(s2, s1); }
- if(s4->dist < s3->dist) { obvh_item_swap(s4, s3); }
- if(s3->dist < s1->dist) { obvh_item_swap(s3, s1); }
- if(s4->dist < s2->dist) { obvh_item_swap(s4, s2); }
- if(s3->dist < s2->dist) { obvh_item_swap(s3, s2); }
+ if (s2->dist < s1->dist) {
+ obvh_item_swap(s2, s1);
+ }
+ if (s4->dist < s3->dist) {
+ obvh_item_swap(s4, s3);
+ }
+ if (s3->dist < s1->dist) {
+ obvh_item_swap(s3, s1);
+ }
+ if (s4->dist < s2->dist) {
+ obvh_item_swap(s4, s2);
+ }
+ if (s3->dist < s2->dist) {
+ obvh_item_swap(s3, s2);
+ }
}
ccl_device_inline void obvh_stack_sort(OBVHStackItem *ccl_restrict s1,
@@ -86,19 +128,19 @@ ccl_device_inline void obvh_stack_sort(OBVHStackItem *ccl_restrict s1,
OBVHStackItem *ccl_restrict s4,
OBVHStackItem *ccl_restrict s5)
{
- obvh_stack_sort(s1, s2, s3, s4);
- if(s5->dist < s4->dist) {
- obvh_item_swap(s4, s5);
- if(s4->dist < s3->dist) {
- obvh_item_swap(s3, s4);
- if(s3->dist < s2->dist) {
- obvh_item_swap(s2, s3);
- if(s2->dist < s1->dist) {
- obvh_item_swap(s1, s2);
- }
- }
- }
- }
+ obvh_stack_sort(s1, s2, s3, s4);
+ if (s5->dist < s4->dist) {
+ obvh_item_swap(s4, s5);
+ if (s4->dist < s3->dist) {
+ obvh_item_swap(s3, s4);
+ if (s3->dist < s2->dist) {
+ obvh_item_swap(s2, s3);
+ if (s2->dist < s1->dist) {
+ obvh_item_swap(s1, s2);
+ }
+ }
+ }
+ }
}
ccl_device_inline void obvh_stack_sort(OBVHStackItem *ccl_restrict s1,
@@ -108,22 +150,22 @@ ccl_device_inline void obvh_stack_sort(OBVHStackItem *ccl_restrict s1,
OBVHStackItem *ccl_restrict s5,
OBVHStackItem *ccl_restrict s6)
{
- obvh_stack_sort(s1, s2, s3, s4, s5);
- if(s6->dist < s5->dist) {
- obvh_item_swap(s5, s6);
- if(s5->dist < s4->dist) {
- obvh_item_swap(s4, s5);
- if(s4->dist < s3->dist) {
- obvh_item_swap(s3, s4);
- if(s3->dist < s2->dist) {
- obvh_item_swap(s2, s3);
- if(s2->dist < s1->dist) {
- obvh_item_swap(s1, s2);
- }
- }
- }
- }
- }
+ obvh_stack_sort(s1, s2, s3, s4, s5);
+ if (s6->dist < s5->dist) {
+ obvh_item_swap(s5, s6);
+ if (s5->dist < s4->dist) {
+ obvh_item_swap(s4, s5);
+ if (s4->dist < s3->dist) {
+ obvh_item_swap(s3, s4);
+ if (s3->dist < s2->dist) {
+ obvh_item_swap(s2, s3);
+ if (s2->dist < s1->dist) {
+ obvh_item_swap(s1, s2);
+ }
+ }
+ }
+ }
+ }
}
ccl_device_inline void obvh_stack_sort(OBVHStackItem *ccl_restrict s1,
@@ -134,25 +176,25 @@ ccl_device_inline void obvh_stack_sort(OBVHStackItem *ccl_restrict s1,
OBVHStackItem *ccl_restrict s6,
OBVHStackItem *ccl_restrict s7)
{
- obvh_stack_sort(s1, s2, s3, s4, s5, s6);
- if(s7->dist < s6->dist) {
- obvh_item_swap(s6, s7);
- if(s6->dist < s5->dist) {
- obvh_item_swap(s5, s6);
- if(s5->dist < s4->dist) {
- obvh_item_swap(s4, s5);
- if(s4->dist < s3->dist) {
- obvh_item_swap(s3, s4);
- if(s3->dist < s2->dist) {
- obvh_item_swap(s2, s3);
- if(s2->dist < s1->dist) {
- obvh_item_swap(s1, s2);
- }
- }
- }
- }
- }
- }
+ obvh_stack_sort(s1, s2, s3, s4, s5, s6);
+ if (s7->dist < s6->dist) {
+ obvh_item_swap(s6, s7);
+ if (s6->dist < s5->dist) {
+ obvh_item_swap(s5, s6);
+ if (s5->dist < s4->dist) {
+ obvh_item_swap(s4, s5);
+ if (s4->dist < s3->dist) {
+ obvh_item_swap(s3, s4);
+ if (s3->dist < s2->dist) {
+ obvh_item_swap(s2, s3);
+ if (s2->dist < s1->dist) {
+ obvh_item_swap(s1, s2);
+ }
+ }
+ }
+ }
+ }
+ }
}
ccl_device_inline void obvh_stack_sort(OBVHStackItem *ccl_restrict s1,
@@ -164,41 +206,41 @@ ccl_device_inline void obvh_stack_sort(OBVHStackItem *ccl_restrict s1,
OBVHStackItem *ccl_restrict s7,
OBVHStackItem *ccl_restrict s8)
{
- obvh_stack_sort(s1, s2, s3, s4, s5, s6, s7);
- if(s8->dist < s7->dist) {
- obvh_item_swap(s7, s8);
- if(s7->dist < s6->dist) {
- obvh_item_swap(s6, s7);
- if(s6->dist < s5->dist) {
- obvh_item_swap(s5, s6);
- if(s5->dist < s4->dist) {
- obvh_item_swap(s4, s5);
- if(s4->dist < s3->dist) {
- obvh_item_swap(s3, s4);
- if(s3->dist < s2->dist) {
- obvh_item_swap(s2, s3);
- if(s2->dist < s1->dist) {
- obvh_item_swap(s1, s2);
- }
- }
- }
- }
- }
- }
- }
+ obvh_stack_sort(s1, s2, s3, s4, s5, s6, s7);
+ if (s8->dist < s7->dist) {
+ obvh_item_swap(s7, s8);
+ if (s7->dist < s6->dist) {
+ obvh_item_swap(s6, s7);
+ if (s6->dist < s5->dist) {
+ obvh_item_swap(s5, s6);
+ if (s5->dist < s4->dist) {
+ obvh_item_swap(s4, s5);
+ if (s4->dist < s3->dist) {
+ obvh_item_swap(s3, s4);
+ if (s3->dist < s2->dist) {
+ obvh_item_swap(s2, s3);
+ if (s2->dist < s1->dist) {
+ obvh_item_swap(s1, s2);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
}
/* Axis-aligned nodes intersection */
ccl_device_inline int obvh_aligned_node_intersect(KernelGlobals *ccl_restrict kg,
- const avxf& isect_near,
- const avxf& isect_far,
+ const avxf &isect_near,
+ const avxf &isect_far,
#ifdef __KERNEL_AVX2__
- const avx3f& org_idir,
+ const avx3f &org_idir,
#else
- const avx3f& org,
+ const avx3f &org,
#endif
- const avx3f& idir,
+ const avx3f &idir,
const int near_x,
const int near_y,
const int near_z,
@@ -208,213 +250,216 @@ ccl_device_inline int obvh_aligned_node_intersect(KernelGlobals *ccl_restrict kg
const int node_addr,
avxf *ccl_restrict dist)
{
- const int offset = node_addr + 2;
+ const int offset = node_addr + 2;
#ifdef __KERNEL_AVX2__
- const avxf tnear_x = msub(kernel_tex_fetch_avxf(__bvh_nodes, offset+near_x*2), idir.x, org_idir.x);
- const avxf tnear_y = msub(kernel_tex_fetch_avxf(__bvh_nodes, offset+near_y*2), idir.y, org_idir.y);
- const avxf tnear_z = msub(kernel_tex_fetch_avxf(__bvh_nodes, offset+near_z*2), idir.z, org_idir.z);
- const avxf tfar_x = msub(kernel_tex_fetch_avxf(__bvh_nodes, offset+far_x*2), idir.x, org_idir.x);
- const avxf tfar_y = msub(kernel_tex_fetch_avxf(__bvh_nodes, offset+far_y*2), idir.y, org_idir.y);
- const avxf tfar_z = msub(kernel_tex_fetch_avxf(__bvh_nodes, offset+far_z*2), idir.z, org_idir.z);
-
- const avxf tnear = max4(tnear_x, tnear_y, tnear_z, isect_near);
- const avxf tfar = min4(tfar_x, tfar_y, tfar_z, isect_far);
- const avxb vmask = tnear <= tfar;
- int mask = (int)movemask(vmask);
- *dist = tnear;
- return mask;
+ const avxf tnear_x = msub(
+ kernel_tex_fetch_avxf(__bvh_nodes, offset + near_x * 2), idir.x, org_idir.x);
+ const avxf tnear_y = msub(
+ kernel_tex_fetch_avxf(__bvh_nodes, offset + near_y * 2), idir.y, org_idir.y);
+ const avxf tnear_z = msub(
+ kernel_tex_fetch_avxf(__bvh_nodes, offset + near_z * 2), idir.z, org_idir.z);
+ const avxf tfar_x = msub(
+ kernel_tex_fetch_avxf(__bvh_nodes, offset + far_x * 2), idir.x, org_idir.x);
+ const avxf tfar_y = msub(
+ kernel_tex_fetch_avxf(__bvh_nodes, offset + far_y * 2), idir.y, org_idir.y);
+ const avxf tfar_z = msub(
+ kernel_tex_fetch_avxf(__bvh_nodes, offset + far_z * 2), idir.z, org_idir.z);
+
+ const avxf tnear = max4(tnear_x, tnear_y, tnear_z, isect_near);
+ const avxf tfar = min4(tfar_x, tfar_y, tfar_z, isect_far);
+ const avxb vmask = tnear <= tfar;
+ int mask = (int)movemask(vmask);
+ *dist = tnear;
+ return mask;
#else
- return 0;
+ return 0;
#endif
}
-ccl_device_inline int obvh_aligned_node_intersect_robust(
- KernelGlobals *ccl_restrict kg,
- const avxf& isect_near,
- const avxf& isect_far,
+ccl_device_inline int obvh_aligned_node_intersect_robust(KernelGlobals *ccl_restrict kg,
+ const avxf &isect_near,
+ const avxf &isect_far,
#ifdef __KERNEL_AVX2__
- const avx3f& P_idir,
+ const avx3f &P_idir,
#else
- const avx3f& P,
+ const avx3f &P,
#endif
- const avx3f& idir,
- const int near_x,
- const int near_y,
- const int near_z,
- const int far_x,
- const int far_y,
- const int far_z,
- const int node_addr,
- const float difl,
- avxf *ccl_restrict dist)
+ const avx3f &idir,
+ const int near_x,
+ const int near_y,
+ const int near_z,
+ const int far_x,
+ const int far_y,
+ const int far_z,
+ const int node_addr,
+ const float difl,
+ avxf *ccl_restrict dist)
{
- const int offset = node_addr + 2;
+ const int offset = node_addr + 2;
#ifdef __KERNEL_AVX2__
- const avxf tnear_x = msub(kernel_tex_fetch_avxf(__bvh_nodes, offset + near_x * 2), idir.x, P_idir.x);
- const avxf tfar_x = msub(kernel_tex_fetch_avxf(__bvh_nodes, offset + far_x * 2), idir.x, P_idir.x);
- const avxf tnear_y = msub(kernel_tex_fetch_avxf(__bvh_nodes, offset + near_y * 2), idir.y, P_idir.y);
- const avxf tfar_y = msub(kernel_tex_fetch_avxf(__bvh_nodes, offset + far_y * 2), idir.y, P_idir.y);
- const avxf tnear_z = msub(kernel_tex_fetch_avxf(__bvh_nodes, offset + near_z * 2), idir.z, P_idir.z);
- const avxf tfar_z = msub(kernel_tex_fetch_avxf(__bvh_nodes, offset + far_z * 2), idir.z, P_idir.z);
-
- const float round_down = 1.0f - difl;
- const float round_up = 1.0f + difl;
- const avxf tnear = max4(tnear_x, tnear_y, tnear_z, isect_near);
- const avxf tfar = min4(tfar_x, tfar_y, tfar_z, isect_far);
- const avxb vmask = round_down*tnear <= round_up*tfar;
- int mask = (int)movemask(vmask);
- *dist = tnear;
- return mask;
+ const avxf tnear_x = msub(
+ kernel_tex_fetch_avxf(__bvh_nodes, offset + near_x * 2), idir.x, P_idir.x);
+ const avxf tfar_x = msub(
+ kernel_tex_fetch_avxf(__bvh_nodes, offset + far_x * 2), idir.x, P_idir.x);
+ const avxf tnear_y = msub(
+ kernel_tex_fetch_avxf(__bvh_nodes, offset + near_y * 2), idir.y, P_idir.y);
+ const avxf tfar_y = msub(
+ kernel_tex_fetch_avxf(__bvh_nodes, offset + far_y * 2), idir.y, P_idir.y);
+ const avxf tnear_z = msub(
+ kernel_tex_fetch_avxf(__bvh_nodes, offset + near_z * 2), idir.z, P_idir.z);
+ const avxf tfar_z = msub(
+ kernel_tex_fetch_avxf(__bvh_nodes, offset + far_z * 2), idir.z, P_idir.z);
+
+ const float round_down = 1.0f - difl;
+ const float round_up = 1.0f + difl;
+ const avxf tnear = max4(tnear_x, tnear_y, tnear_z, isect_near);
+ const avxf tfar = min4(tfar_x, tfar_y, tfar_z, isect_far);
+ const avxb vmask = round_down * tnear <= round_up * tfar;
+ int mask = (int)movemask(vmask);
+ *dist = tnear;
+ return mask;
#else
- return 0;
+ return 0;
#endif
}
/* Unaligned nodes intersection */
-ccl_device_inline int obvh_unaligned_node_intersect(
- KernelGlobals *ccl_restrict kg,
- const avxf& isect_near,
- const avxf& isect_far,
+ccl_device_inline int obvh_unaligned_node_intersect(KernelGlobals *ccl_restrict kg,
+ const avxf &isect_near,
+ const avxf &isect_far,
#ifdef __KERNEL_AVX2__
- const avx3f& org_idir,
+ const avx3f &org_idir,
#endif
- const avx3f& org,
- const avx3f& dir,
- const avx3f& idir,
- const int near_x,
- const int near_y,
- const int near_z,
- const int far_x,
- const int far_y,
- const int far_z,
- const int node_addr,
- avxf *ccl_restrict dist)
+ const avx3f &org,
+ const avx3f &dir,
+ const avx3f &idir,
+ const int near_x,
+ const int near_y,
+ const int near_z,
+ const int far_x,
+ const int far_y,
+ const int far_z,
+ const int node_addr,
+ avxf *ccl_restrict dist)
{
- const int offset = node_addr;
- const avxf tfm_x_x = kernel_tex_fetch_avxf(__bvh_nodes, offset+2);
- const avxf tfm_x_y = kernel_tex_fetch_avxf(__bvh_nodes, offset+4);
- const avxf tfm_x_z = kernel_tex_fetch_avxf(__bvh_nodes, offset+6);
-
- const avxf tfm_y_x = kernel_tex_fetch_avxf(__bvh_nodes, offset+8);
- const avxf tfm_y_y = kernel_tex_fetch_avxf(__bvh_nodes, offset+10);
- const avxf tfm_y_z = kernel_tex_fetch_avxf(__bvh_nodes, offset+12);
-
- const avxf tfm_z_x = kernel_tex_fetch_avxf(__bvh_nodes, offset+14);
- const avxf tfm_z_y = kernel_tex_fetch_avxf(__bvh_nodes, offset+16);
- const avxf tfm_z_z = kernel_tex_fetch_avxf(__bvh_nodes, offset+18);
-
- const avxf tfm_t_x = kernel_tex_fetch_avxf(__bvh_nodes, offset+20);
- const avxf tfm_t_y = kernel_tex_fetch_avxf(__bvh_nodes, offset+22);
- const avxf tfm_t_z = kernel_tex_fetch_avxf(__bvh_nodes, offset+24);
-
- const avxf aligned_dir_x = dir.x*tfm_x_x + dir.y*tfm_x_y + dir.z*tfm_x_z,
- aligned_dir_y = dir.x*tfm_y_x + dir.y*tfm_y_y + dir.z*tfm_y_z,
- aligned_dir_z = dir.x*tfm_z_x + dir.y*tfm_z_y + dir.z*tfm_z_z;
-
- const avxf aligned_P_x = org.x*tfm_x_x + org.y*tfm_x_y + org.z*tfm_x_z + tfm_t_x,
- aligned_P_y = org.x*tfm_y_x + org.y*tfm_y_y + org.z*tfm_y_z + tfm_t_y,
- aligned_P_z = org.x*tfm_z_x + org.y*tfm_z_y + org.z*tfm_z_z + tfm_t_z;
-
- const avxf neg_one(-1.0f);
- const avxf nrdir_x = neg_one / aligned_dir_x,
- nrdir_y = neg_one / aligned_dir_y,
- nrdir_z = neg_one / aligned_dir_z;
-
- const avxf tlower_x = aligned_P_x * nrdir_x,
- tlower_y = aligned_P_y * nrdir_y,
- tlower_z = aligned_P_z * nrdir_z;
-
- const avxf tupper_x = tlower_x - nrdir_x,
- tupper_y = tlower_y - nrdir_y,
- tupper_z = tlower_z - nrdir_z;
-
- const avxf tnear_x = min(tlower_x, tupper_x);
- const avxf tnear_y = min(tlower_y, tupper_y);
- const avxf tnear_z = min(tlower_z, tupper_z);
- const avxf tfar_x = max(tlower_x, tupper_x);
- const avxf tfar_y = max(tlower_y, tupper_y);
- const avxf tfar_z = max(tlower_z, tupper_z);
- const avxf tnear = max4(isect_near, tnear_x, tnear_y, tnear_z);
- const avxf tfar = min4(isect_far, tfar_x, tfar_y, tfar_z);
- const avxb vmask = tnear <= tfar;
- *dist = tnear;
- return movemask(vmask);
+ const int offset = node_addr;
+ const avxf tfm_x_x = kernel_tex_fetch_avxf(__bvh_nodes, offset + 2);
+ const avxf tfm_x_y = kernel_tex_fetch_avxf(__bvh_nodes, offset + 4);
+ const avxf tfm_x_z = kernel_tex_fetch_avxf(__bvh_nodes, offset + 6);
+
+ const avxf tfm_y_x = kernel_tex_fetch_avxf(__bvh_nodes, offset + 8);
+ const avxf tfm_y_y = kernel_tex_fetch_avxf(__bvh_nodes, offset + 10);
+ const avxf tfm_y_z = kernel_tex_fetch_avxf(__bvh_nodes, offset + 12);
+
+ const avxf tfm_z_x = kernel_tex_fetch_avxf(__bvh_nodes, offset + 14);
+ const avxf tfm_z_y = kernel_tex_fetch_avxf(__bvh_nodes, offset + 16);
+ const avxf tfm_z_z = kernel_tex_fetch_avxf(__bvh_nodes, offset + 18);
+
+ const avxf tfm_t_x = kernel_tex_fetch_avxf(__bvh_nodes, offset + 20);
+ const avxf tfm_t_y = kernel_tex_fetch_avxf(__bvh_nodes, offset + 22);
+ const avxf tfm_t_z = kernel_tex_fetch_avxf(__bvh_nodes, offset + 24);
+
+ const avxf aligned_dir_x = dir.x * tfm_x_x + dir.y * tfm_x_y + dir.z * tfm_x_z,
+ aligned_dir_y = dir.x * tfm_y_x + dir.y * tfm_y_y + dir.z * tfm_y_z,
+ aligned_dir_z = dir.x * tfm_z_x + dir.y * tfm_z_y + dir.z * tfm_z_z;
+
+ const avxf aligned_P_x = org.x * tfm_x_x + org.y * tfm_x_y + org.z * tfm_x_z + tfm_t_x,
+ aligned_P_y = org.x * tfm_y_x + org.y * tfm_y_y + org.z * tfm_y_z + tfm_t_y,
+ aligned_P_z = org.x * tfm_z_x + org.y * tfm_z_y + org.z * tfm_z_z + tfm_t_z;
+
+ const avxf neg_one(-1.0f);
+ const avxf nrdir_x = neg_one / aligned_dir_x, nrdir_y = neg_one / aligned_dir_y,
+ nrdir_z = neg_one / aligned_dir_z;
+
+ const avxf tlower_x = aligned_P_x * nrdir_x, tlower_y = aligned_P_y * nrdir_y,
+ tlower_z = aligned_P_z * nrdir_z;
+
+ const avxf tupper_x = tlower_x - nrdir_x, tupper_y = tlower_y - nrdir_y,
+ tupper_z = tlower_z - nrdir_z;
+
+ const avxf tnear_x = min(tlower_x, tupper_x);
+ const avxf tnear_y = min(tlower_y, tupper_y);
+ const avxf tnear_z = min(tlower_z, tupper_z);
+ const avxf tfar_x = max(tlower_x, tupper_x);
+ const avxf tfar_y = max(tlower_y, tupper_y);
+ const avxf tfar_z = max(tlower_z, tupper_z);
+ const avxf tnear = max4(isect_near, tnear_x, tnear_y, tnear_z);
+ const avxf tfar = min4(isect_far, tfar_x, tfar_y, tfar_z);
+ const avxb vmask = tnear <= tfar;
+ *dist = tnear;
+ return movemask(vmask);
}
-ccl_device_inline int obvh_unaligned_node_intersect_robust(
- KernelGlobals *ccl_restrict kg,
- const avxf& isect_near,
- const avxf& isect_far,
+ccl_device_inline int obvh_unaligned_node_intersect_robust(KernelGlobals *ccl_restrict kg,
+ const avxf &isect_near,
+ const avxf &isect_far,
#ifdef __KERNEL_AVX2__
- const avx3f& P_idir,
+ const avx3f &P_idir,
#endif
- const avx3f& P,
- const avx3f& dir,
- const avx3f& idir,
- const int near_x,
- const int near_y,
- const int near_z,
- const int far_x,
- const int far_y,
- const int far_z,
- const int node_addr,
- const float difl,
- avxf *ccl_restrict dist)
+ const avx3f &P,
+ const avx3f &dir,
+ const avx3f &idir,
+ const int near_x,
+ const int near_y,
+ const int near_z,
+ const int far_x,
+ const int far_y,
+ const int far_z,
+ const int node_addr,
+ const float difl,
+ avxf *ccl_restrict dist)
{
- const int offset = node_addr;
- const avxf tfm_x_x = kernel_tex_fetch_avxf(__bvh_nodes, offset+2);
- const avxf tfm_x_y = kernel_tex_fetch_avxf(__bvh_nodes, offset+4);
- const avxf tfm_x_z = kernel_tex_fetch_avxf(__bvh_nodes, offset+6);
-
- const avxf tfm_y_x = kernel_tex_fetch_avxf(__bvh_nodes, offset+8);
- const avxf tfm_y_y = kernel_tex_fetch_avxf(__bvh_nodes, offset+10);
- const avxf tfm_y_z = kernel_tex_fetch_avxf(__bvh_nodes, offset+12);
-
- const avxf tfm_z_x = kernel_tex_fetch_avxf(__bvh_nodes, offset+14);
- const avxf tfm_z_y = kernel_tex_fetch_avxf(__bvh_nodes, offset+16);
- const avxf tfm_z_z = kernel_tex_fetch_avxf(__bvh_nodes, offset+18);
-
- const avxf tfm_t_x = kernel_tex_fetch_avxf(__bvh_nodes, offset+20);
- const avxf tfm_t_y = kernel_tex_fetch_avxf(__bvh_nodes, offset+22);
- const avxf tfm_t_z = kernel_tex_fetch_avxf(__bvh_nodes, offset+24);
-
- const avxf aligned_dir_x = dir.x*tfm_x_x + dir.y*tfm_x_y + dir.z*tfm_x_z,
- aligned_dir_y = dir.x*tfm_y_x + dir.y*tfm_y_y + dir.z*tfm_y_z,
- aligned_dir_z = dir.x*tfm_z_x + dir.y*tfm_z_y + dir.z*tfm_z_z;
-
- const avxf aligned_P_x = P.x*tfm_x_x + P.y*tfm_x_y + P.z*tfm_x_z + tfm_t_x,
- aligned_P_y = P.x*tfm_y_x + P.y*tfm_y_y + P.z*tfm_y_z + tfm_t_y,
- aligned_P_z = P.x*tfm_z_x + P.y*tfm_z_y + P.z*tfm_z_z + tfm_t_z;
-
- const avxf neg_one(-1.0f);
- const avxf nrdir_x = neg_one / aligned_dir_x,
- nrdir_y = neg_one / aligned_dir_y,
- nrdir_z = neg_one / aligned_dir_z;
-
- const avxf tlower_x = aligned_P_x * nrdir_x,
- tlower_y = aligned_P_y * nrdir_y,
- tlower_z = aligned_P_z * nrdir_z;
-
- const avxf tupper_x = tlower_x - nrdir_x,
- tupper_y = tlower_y - nrdir_y,
- tupper_z = tlower_z - nrdir_z;
-
- const float round_down = 1.0f - difl;
- const float round_up = 1.0f + difl;
-
- const avxf tnear_x = min(tlower_x, tupper_x);
- const avxf tnear_y = min(tlower_y, tupper_y);
- const avxf tnear_z = min(tlower_z, tupper_z);
- const avxf tfar_x = max(tlower_x, tupper_x);
- const avxf tfar_y = max(tlower_y, tupper_y);
- const avxf tfar_z = max(tlower_z, tupper_z);
-
- const avxf tnear = max4(isect_near, tnear_x, tnear_y, tnear_z);
- const avxf tfar = min4(isect_far, tfar_x, tfar_y, tfar_z);
- const avxb vmask = round_down*tnear <= round_up*tfar;
- *dist = tnear;
- return movemask(vmask);
+ const int offset = node_addr;
+ const avxf tfm_x_x = kernel_tex_fetch_avxf(__bvh_nodes, offset + 2);
+ const avxf tfm_x_y = kernel_tex_fetch_avxf(__bvh_nodes, offset + 4);
+ const avxf tfm_x_z = kernel_tex_fetch_avxf(__bvh_nodes, offset + 6);
+
+ const avxf tfm_y_x = kernel_tex_fetch_avxf(__bvh_nodes, offset + 8);
+ const avxf tfm_y_y = kernel_tex_fetch_avxf(__bvh_nodes, offset + 10);
+ const avxf tfm_y_z = kernel_tex_fetch_avxf(__bvh_nodes, offset + 12);
+
+ const avxf tfm_z_x = kernel_tex_fetch_avxf(__bvh_nodes, offset + 14);
+ const avxf tfm_z_y = kernel_tex_fetch_avxf(__bvh_nodes, offset + 16);
+ const avxf tfm_z_z = kernel_tex_fetch_avxf(__bvh_nodes, offset + 18);
+
+ const avxf tfm_t_x = kernel_tex_fetch_avxf(__bvh_nodes, offset + 20);
+ const avxf tfm_t_y = kernel_tex_fetch_avxf(__bvh_nodes, offset + 22);
+ const avxf tfm_t_z = kernel_tex_fetch_avxf(__bvh_nodes, offset + 24);
+
+ const avxf aligned_dir_x = dir.x * tfm_x_x + dir.y * tfm_x_y + dir.z * tfm_x_z,
+ aligned_dir_y = dir.x * tfm_y_x + dir.y * tfm_y_y + dir.z * tfm_y_z,
+ aligned_dir_z = dir.x * tfm_z_x + dir.y * tfm_z_y + dir.z * tfm_z_z;
+
+ const avxf aligned_P_x = P.x * tfm_x_x + P.y * tfm_x_y + P.z * tfm_x_z + tfm_t_x,
+ aligned_P_y = P.x * tfm_y_x + P.y * tfm_y_y + P.z * tfm_y_z + tfm_t_y,
+ aligned_P_z = P.x * tfm_z_x + P.y * tfm_z_y + P.z * tfm_z_z + tfm_t_z;
+
+ const avxf neg_one(-1.0f);
+ const avxf nrdir_x = neg_one / aligned_dir_x, nrdir_y = neg_one / aligned_dir_y,
+ nrdir_z = neg_one / aligned_dir_z;
+
+ const avxf tlower_x = aligned_P_x * nrdir_x, tlower_y = aligned_P_y * nrdir_y,
+ tlower_z = aligned_P_z * nrdir_z;
+
+ const avxf tupper_x = tlower_x - nrdir_x, tupper_y = tlower_y - nrdir_y,
+ tupper_z = tlower_z - nrdir_z;
+
+ const float round_down = 1.0f - difl;
+ const float round_up = 1.0f + difl;
+
+ const avxf tnear_x = min(tlower_x, tupper_x);
+ const avxf tnear_y = min(tlower_y, tupper_y);
+ const avxf tnear_z = min(tlower_z, tupper_z);
+ const avxf tfar_x = max(tlower_x, tupper_x);
+ const avxf tfar_y = max(tlower_y, tupper_y);
+ const avxf tfar_z = max(tlower_z, tupper_z);
+
+ const avxf tnear = max4(isect_near, tnear_x, tnear_y, tnear_z);
+ const avxf tfar = min4(isect_far, tfar_x, tfar_y, tfar_z);
+ const avxb vmask = round_down * tnear <= round_up * tfar;
+ *dist = tnear;
+ return movemask(vmask);
}
/* Intersectors wrappers.
@@ -422,111 +467,125 @@ ccl_device_inline int obvh_unaligned_node_intersect_robust(
* They'll check node type and call appropriate intersection code.
*/
-ccl_device_inline int obvh_node_intersect(
- KernelGlobals *ccl_restrict kg,
- const avxf& isect_near,
- const avxf& isect_far,
+ccl_device_inline int obvh_node_intersect(KernelGlobals *ccl_restrict kg,
+ const avxf &isect_near,
+ const avxf &isect_far,
#ifdef __KERNEL_AVX2__
- const avx3f& org_idir,
+ const avx3f &org_idir,
#endif
- const avx3f& org,
- const avx3f& dir,
- const avx3f& idir,
- const int near_x,
- const int near_y,
- const int near_z,
- const int far_x,
- const int far_y,
- const int far_z,
- const int node_addr,
- avxf *ccl_restrict dist)
+ const avx3f &org,
+ const avx3f &dir,
+ const avx3f &idir,
+ const int near_x,
+ const int near_y,
+ const int near_z,
+ const int far_x,
+ const int far_y,
+ const int far_z,
+ const int node_addr,
+ avxf *ccl_restrict dist)
{
- const int offset = node_addr;
- const float4 node = kernel_tex_fetch(__bvh_nodes, offset);
- if(__float_as_uint(node.x) & PATH_RAY_NODE_UNALIGNED) {
- return obvh_unaligned_node_intersect(kg,
- isect_near,
- isect_far,
+ const int offset = node_addr;
+ const float4 node = kernel_tex_fetch(__bvh_nodes, offset);
+ if (__float_as_uint(node.x) & PATH_RAY_NODE_UNALIGNED) {
+ return obvh_unaligned_node_intersect(kg,
+ isect_near,
+ isect_far,
#ifdef __KERNEL_AVX2__
- org_idir,
+ org_idir,
#endif
- org,
- dir,
- idir,
- near_x, near_y, near_z,
- far_x, far_y, far_z,
- node_addr,
- dist);
- }
- else {
- return obvh_aligned_node_intersect(kg,
- isect_near,
- isect_far,
+ org,
+ dir,
+ idir,
+ near_x,
+ near_y,
+ near_z,
+ far_x,
+ far_y,
+ far_z,
+ node_addr,
+ dist);
+ }
+ else {
+ return obvh_aligned_node_intersect(kg,
+ isect_near,
+ isect_far,
#ifdef __KERNEL_AVX2__
- org_idir,
+ org_idir,
#else
- org,
+ org,
#endif
- idir,
- near_x, near_y, near_z,
- far_x, far_y, far_z,
- node_addr,
- dist);
- }
+ idir,
+ near_x,
+ near_y,
+ near_z,
+ far_x,
+ far_y,
+ far_z,
+ node_addr,
+ dist);
+ }
}
-ccl_device_inline int obvh_node_intersect_robust(
- KernelGlobals *ccl_restrict kg,
- const avxf& isect_near,
- const avxf& isect_far,
+ccl_device_inline int obvh_node_intersect_robust(KernelGlobals *ccl_restrict kg,
+ const avxf &isect_near,
+ const avxf &isect_far,
#ifdef __KERNEL_AVX2__
- const avx3f& P_idir,
+ const avx3f &P_idir,
#endif
- const avx3f& P,
- const avx3f& dir,
- const avx3f& idir,
- const int near_x,
- const int near_y,
- const int near_z,
- const int far_x,
- const int far_y,
- const int far_z,
- const int node_addr,
- const float difl,
- avxf *ccl_restrict dist)
+ const avx3f &P,
+ const avx3f &dir,
+ const avx3f &idir,
+ const int near_x,
+ const int near_y,
+ const int near_z,
+ const int far_x,
+ const int far_y,
+ const int far_z,
+ const int node_addr,
+ const float difl,
+ avxf *ccl_restrict dist)
{
- const int offset = node_addr;
- const float4 node = kernel_tex_fetch(__bvh_nodes, offset);
- if(__float_as_uint(node.x) & PATH_RAY_NODE_UNALIGNED) {
- return obvh_unaligned_node_intersect_robust(kg,
- isect_near,
- isect_far,
+ const int offset = node_addr;
+ const float4 node = kernel_tex_fetch(__bvh_nodes, offset);
+ if (__float_as_uint(node.x) & PATH_RAY_NODE_UNALIGNED) {
+ return obvh_unaligned_node_intersect_robust(kg,
+ isect_near,
+ isect_far,
#ifdef __KERNEL_AVX2__
- P_idir,
+ P_idir,
#endif
- P,
- dir,
- idir,
- near_x, near_y, near_z,
- far_x, far_y, far_z,
- node_addr,
- difl,
- dist);
- }
- else {
- return obvh_aligned_node_intersect_robust(kg,
- isect_near,
- isect_far,
+ P,
+ dir,
+ idir,
+ near_x,
+ near_y,
+ near_z,
+ far_x,
+ far_y,
+ far_z,
+ node_addr,
+ difl,
+ dist);
+ }
+ else {
+ return obvh_aligned_node_intersect_robust(kg,
+ isect_near,
+ isect_far,
#ifdef __KERNEL_AVX2__
- P_idir,
+ P_idir,
#else
- P,
+ P,
#endif
- idir,
- near_x, near_y, near_z,
- far_x, far_y, far_z,
- node_addr,
- difl,
- dist);
- }
+ idir,
+ near_x,
+ near_y,
+ near_z,
+ far_x,
+ far_y,
+ far_z,
+ node_addr,
+ difl,
+ dist);
+ }
}
diff --git a/intern/cycles/kernel/bvh/obvh_shadow_all.h b/intern/cycles/kernel/bvh/obvh_shadow_all.h
index 10d5422c31c..98efb003788 100644
--- a/intern/cycles/kernel/bvh/obvh_shadow_all.h
+++ b/intern/cycles/kernel/bvh/obvh_shadow_all.h
@@ -36,645 +36,635 @@ ccl_device bool BVH_FUNCTION_FULL_NAME(OBVH)(KernelGlobals *kg,
const uint max_hits,
uint *num_hits)
{
- /* TODO(sergey):
- * - Test if pushing distance on the stack helps.
- * - Likely and unlikely for if() statements.
- * - Test restrict attribute for pointers.
- */
-
- /* Traversal stack in CUDA thread-local memory. */
- OBVHStackItem traversal_stack[BVH_OSTACK_SIZE];
- traversal_stack[0].addr = ENTRYPOINT_SENTINEL;
-
- /* Traversal variables in registers. */
- int stack_ptr = 0;
- int node_addr = kernel_data.bvh.root;
-
- /* Ray parameters in registers. */
- const float tmax = ray->t;
- float3 P = ray->P;
- float3 dir = bvh_clamp_direction(ray->D);
- float3 idir = bvh_inverse_direction(dir);
- int object = OBJECT_NONE;
- float isect_t = tmax;
+ /* TODO(sergey):
+ * - Test if pushing distance on the stack helps.
+ * - Likely and unlikely for if() statements.
+ * - Test restrict attribute for pointers.
+ */
+
+ /* Traversal stack in CUDA thread-local memory. */
+ OBVHStackItem traversal_stack[BVH_OSTACK_SIZE];
+ traversal_stack[0].addr = ENTRYPOINT_SENTINEL;
+
+ /* Traversal variables in registers. */
+ int stack_ptr = 0;
+ int node_addr = kernel_data.bvh.root;
+
+ /* Ray parameters in registers. */
+ const float tmax = ray->t;
+ float3 P = ray->P;
+ float3 dir = bvh_clamp_direction(ray->D);
+ float3 idir = bvh_inverse_direction(dir);
+ int object = OBJECT_NONE;
+ float isect_t = tmax;
#if BVH_FEATURE(BVH_MOTION)
- Transform ob_itfm;
+ Transform ob_itfm;
#endif
- *num_hits = 0;
- isect_array->t = tmax;
+ *num_hits = 0;
+ isect_array->t = tmax;
#if BVH_FEATURE(BVH_INSTANCING)
- int num_hits_in_instance = 0;
+ int num_hits_in_instance = 0;
#endif
- avxf tnear(0.0f), tfar(isect_t);
+ avxf tnear(0.0f), tfar(isect_t);
#if BVH_FEATURE(BVH_HAIR)
- avx3f dir4(avxf(dir.x), avxf(dir.y), avxf(dir.z));
+ avx3f dir4(avxf(dir.x), avxf(dir.y), avxf(dir.z));
#endif
- avx3f idir4(avxf(idir.x), avxf(idir.y), avxf(idir.z));
+ avx3f idir4(avxf(idir.x), avxf(idir.y), avxf(idir.z));
#ifdef __KERNEL_AVX2__
- float3 P_idir = P*idir;
- avx3f P_idir4(P_idir.x, P_idir.y, P_idir.z);
+ float3 P_idir = P * idir;
+ avx3f P_idir4(P_idir.x, P_idir.y, P_idir.z);
#endif
#if BVH_FEATURE(BVH_HAIR) || !defined(__KERNEL_AVX2__)
- avx3f org4(avxf(P.x), avxf(P.y), avxf(P.z));
+ avx3f org4(avxf(P.x), avxf(P.y), avxf(P.z));
#endif
- /* Offsets to select the side that becomes the lower or upper bound. */
- int near_x, near_y, near_z;
- int far_x, far_y, far_z;
- obvh_near_far_idx_calc(idir,
- &near_x, &near_y, &near_z,
- &far_x, &far_y, &far_z);
-
- /* Traversal loop. */
- do {
- do {
- /* Traverse internal nodes. */
- while(node_addr >= 0 && node_addr != ENTRYPOINT_SENTINEL) {
- float4 inodes = kernel_tex_fetch(__bvh_nodes, node_addr+0);
- (void) inodes;
-
- if(false
+ /* Offsets to select the side that becomes the lower or upper bound. */
+ int near_x, near_y, near_z;
+ int far_x, far_y, far_z;
+ obvh_near_far_idx_calc(idir, &near_x, &near_y, &near_z, &far_x, &far_y, &far_z);
+
+ /* Traversal loop. */
+ do {
+ do {
+ /* Traverse internal nodes. */
+ while (node_addr >= 0 && node_addr != ENTRYPOINT_SENTINEL) {
+ float4 inodes = kernel_tex_fetch(__bvh_nodes, node_addr + 0);
+ (void)inodes;
+
+ if (false
#ifdef __VISIBILITY_FLAG__
- || ((__float_as_uint(inodes.x) & PATH_RAY_SHADOW) == 0)
+ || ((__float_as_uint(inodes.x) & PATH_RAY_SHADOW) == 0)
#endif
#if BVH_FEATURE(BVH_MOTION)
- || UNLIKELY(ray->time < inodes.y)
- || UNLIKELY(ray->time > inodes.z)
+ || UNLIKELY(ray->time < inodes.y) || UNLIKELY(ray->time > inodes.z)
#endif
- ) {
- /* Pop. */
- node_addr = traversal_stack[stack_ptr].addr;
- --stack_ptr;
- continue;
- }
-
- avxf dist;
- int child_mask = NODE_INTERSECT(kg,
- tnear,
- tfar,
+ ) {
+ /* Pop. */
+ node_addr = traversal_stack[stack_ptr].addr;
+ --stack_ptr;
+ continue;
+ }
+
+ avxf dist;
+ int child_mask = NODE_INTERSECT(kg,
+ tnear,
+ tfar,
#ifdef __KERNEL_AVX2__
- P_idir4,
+ P_idir4,
#endif
#if BVH_FEATURE(BVH_HAIR) || !defined(__KERNEL_AVX2__)
-//#if !defined(__KERNEL_AVX2__)
- org4,
+ //#if !defined(__KERNEL_AVX2__)
+ org4,
#endif
#if BVH_FEATURE(BVH_HAIR)
- dir4,
+ dir4,
#endif
- idir4,
- near_x, near_y, near_z,
- far_x, far_y, far_z,
- node_addr,
- &dist);
-
- if(child_mask != 0) {
- avxf cnodes;
+ idir4,
+ near_x,
+ near_y,
+ near_z,
+ far_x,
+ far_y,
+ far_z,
+ node_addr,
+ &dist);
+
+ if (child_mask != 0) {
+ avxf cnodes;
#if BVH_FEATURE(BVH_HAIR)
- if(__float_as_uint(inodes.x) & PATH_RAY_NODE_UNALIGNED) {
- cnodes = kernel_tex_fetch_avxf(__bvh_nodes, node_addr+26);
- }
- else
+ if (__float_as_uint(inodes.x) & PATH_RAY_NODE_UNALIGNED) {
+ cnodes = kernel_tex_fetch_avxf(__bvh_nodes, node_addr + 26);
+ }
+ else
#endif
- {
- cnodes = kernel_tex_fetch_avxf(__bvh_nodes, node_addr+14);
- }
-
- /* One child is hit, continue with that child. */
- int r = __bscf(child_mask);
- if(child_mask == 0) {
- node_addr = __float_as_int(cnodes[r]);
- continue;
- }
-
- /* Two children are hit, push far child, and continue with
- * closer child.
- */
- int c0 = __float_as_int(cnodes[r]);
- float d0 = ((float*)&dist)[r];
- r = __bscf(child_mask);
- int c1 = __float_as_int(cnodes[r]);
- float d1 = ((float*)&dist)[r];
- if(child_mask == 0) {
- if(d1 < d0) {
- node_addr = c1;
- ++stack_ptr;
- kernel_assert(stack_ptr < BVH_OSTACK_SIZE);
- traversal_stack[stack_ptr].addr = c0;
- traversal_stack[stack_ptr].dist = d0;
- continue;
- }
- else {
- node_addr = c0;
- ++stack_ptr;
- kernel_assert(stack_ptr < BVH_OSTACK_SIZE);
- traversal_stack[stack_ptr].addr = c1;
- traversal_stack[stack_ptr].dist = d1;
- continue;
- }
- }
-
- /* Here starts the slow path for 3 or 4 hit children. We push
- * all nodes onto the stack to sort them there.
- */
- ++stack_ptr;
- kernel_assert(stack_ptr < BVH_OSTACK_SIZE);
- traversal_stack[stack_ptr].addr = c1;
- traversal_stack[stack_ptr].dist = d1;
- ++stack_ptr;
- kernel_assert(stack_ptr < BVH_OSTACK_SIZE);
- traversal_stack[stack_ptr].addr = c0;
- traversal_stack[stack_ptr].dist = d0;
-
- /* Three children are hit, push all onto stack and sort 3
- * stack items, continue with closest child.
- */
- r = __bscf(child_mask);
- int c2 = __float_as_int(cnodes[r]);
- float d2 = ((float*)&dist)[r];
- if(child_mask == 0) {
- ++stack_ptr;
- kernel_assert(stack_ptr < BVH_OSTACK_SIZE);
- traversal_stack[stack_ptr].addr = c2;
- traversal_stack[stack_ptr].dist = d2;
- obvh_stack_sort(&traversal_stack[stack_ptr],
- &traversal_stack[stack_ptr - 1],
- &traversal_stack[stack_ptr - 2]);
- node_addr = traversal_stack[stack_ptr].addr;
- --stack_ptr;
- continue;
- }
-
- /* Four children are hit, push all onto stack and sort 4
- * stack items, continue with closest child.
- */
- r = __bscf(child_mask);
- int c3 = __float_as_int(cnodes[r]);
- float d3 = ((float*)&dist)[r];
- if(child_mask == 0) {
- ++stack_ptr;
- kernel_assert(stack_ptr < BVH_OSTACK_SIZE);
- traversal_stack[stack_ptr].addr = c3;
- traversal_stack[stack_ptr].dist = d3;
- ++stack_ptr;
- kernel_assert(stack_ptr < BVH_OSTACK_SIZE);
- traversal_stack[stack_ptr].addr = c2;
- traversal_stack[stack_ptr].dist = d2;
- obvh_stack_sort(&traversal_stack[stack_ptr],
- &traversal_stack[stack_ptr - 1],
- &traversal_stack[stack_ptr - 2],
- &traversal_stack[stack_ptr - 3]);
- node_addr = traversal_stack[stack_ptr].addr;
- --stack_ptr;
- continue;
- }
-
- ++stack_ptr;
- kernel_assert(stack_ptr < BVH_OSTACK_SIZE);
- traversal_stack[stack_ptr].addr = c3;
- traversal_stack[stack_ptr].dist = d3;
- ++stack_ptr;
- kernel_assert(stack_ptr < BVH_OSTACK_SIZE);
- traversal_stack[stack_ptr].addr = c2;
- traversal_stack[stack_ptr].dist = d2;
-
- /* Five children are hit, push all onto stack and sort 5
- * stack items, continue with closest child
- */
- r = __bscf(child_mask);
- int c4 = __float_as_int(cnodes[r]);
- float d4 = ((float*)&dist)[r];
- if(child_mask == 0) {
- ++stack_ptr;
- kernel_assert(stack_ptr < BVH_OSTACK_SIZE);
- traversal_stack[stack_ptr].addr = c4;
- traversal_stack[stack_ptr].dist = d4;
- obvh_stack_sort(&traversal_stack[stack_ptr],
- &traversal_stack[stack_ptr - 1],
- &traversal_stack[stack_ptr - 2],
- &traversal_stack[stack_ptr - 3],
- &traversal_stack[stack_ptr - 4]);
- node_addr = traversal_stack[stack_ptr].addr;
- --stack_ptr;
- continue;
- }
-
- /* Six children are hit, push all onto stack and sort 6
- * stack items, continue with closest child.
- */
- r = __bscf(child_mask);
- int c5 = __float_as_int(cnodes[r]);
- float d5 = ((float*)&dist)[r];
- if(child_mask == 0) {
- ++stack_ptr;
- kernel_assert(stack_ptr < BVH_OSTACK_SIZE);
- traversal_stack[stack_ptr].addr = c5;
- traversal_stack[stack_ptr].dist = d5;
- ++stack_ptr;
- kernel_assert(stack_ptr < BVH_OSTACK_SIZE);
- traversal_stack[stack_ptr].addr = c4;
- traversal_stack[stack_ptr].dist = d4;
- obvh_stack_sort(&traversal_stack[stack_ptr],
- &traversal_stack[stack_ptr - 1],
- &traversal_stack[stack_ptr - 2],
- &traversal_stack[stack_ptr - 3],
- &traversal_stack[stack_ptr - 4],
- &traversal_stack[stack_ptr - 5]);
- node_addr = traversal_stack[stack_ptr].addr;
- --stack_ptr;
- continue;
- }
-
- ++stack_ptr;
- kernel_assert(stack_ptr < BVH_OSTACK_SIZE);
- traversal_stack[stack_ptr].addr = c5;
- traversal_stack[stack_ptr].dist = d5;
- ++stack_ptr;
- kernel_assert(stack_ptr < BVH_OSTACK_SIZE);
- traversal_stack[stack_ptr].addr = c4;
- traversal_stack[stack_ptr].dist = d4;
-
- /* Seven children are hit, push all onto stack and sort 7
- * stack items, continue with closest child.
- */
- r = __bscf(child_mask);
- int c6 = __float_as_int(cnodes[r]);
- float d6 = ((float*)&dist)[r];
- if(child_mask == 0) {
- ++stack_ptr;
- kernel_assert(stack_ptr < BVH_OSTACK_SIZE);
- traversal_stack[stack_ptr].addr = c6;
- traversal_stack[stack_ptr].dist = d6;
- obvh_stack_sort(&traversal_stack[stack_ptr],
- &traversal_stack[stack_ptr - 1],
- &traversal_stack[stack_ptr - 2],
- &traversal_stack[stack_ptr - 3],
- &traversal_stack[stack_ptr - 4],
- &traversal_stack[stack_ptr - 5],
- &traversal_stack[stack_ptr - 6]);
- node_addr = traversal_stack[stack_ptr].addr;
- --stack_ptr;
- continue;
- }
-
- /* Eight children are hit, push all onto stack and sort 8
- * stack items, continue with closest child.
- */
- r = __bscf(child_mask);
- int c7 = __float_as_int(cnodes[r]);
- float d7 = ((float*)&dist)[r];
- ++stack_ptr;
- kernel_assert(stack_ptr < BVH_OSTACK_SIZE);
- traversal_stack[stack_ptr].addr = c7;
- traversal_stack[stack_ptr].dist = d7;
- ++stack_ptr;
- kernel_assert(stack_ptr < BVH_OSTACK_SIZE);
- traversal_stack[stack_ptr].addr = c6;
- traversal_stack[stack_ptr].dist = d6;
- obvh_stack_sort(&traversal_stack[stack_ptr],
- &traversal_stack[stack_ptr - 1],
- &traversal_stack[stack_ptr - 2],
- &traversal_stack[stack_ptr - 3],
- &traversal_stack[stack_ptr - 4],
- &traversal_stack[stack_ptr - 5],
- &traversal_stack[stack_ptr - 6],
- &traversal_stack[stack_ptr - 7]);
- node_addr = traversal_stack[stack_ptr].addr;
- --stack_ptr;
- continue;
- }
-
- node_addr = traversal_stack[stack_ptr].addr;
- --stack_ptr;
- }
-
- /* If node is leaf, fetch triangle list. */
- if(node_addr < 0) {
- float4 leaf = kernel_tex_fetch(__bvh_leaf_nodes, (-node_addr-1));
+ {
+ cnodes = kernel_tex_fetch_avxf(__bvh_nodes, node_addr + 14);
+ }
+
+ /* One child is hit, continue with that child. */
+ int r = __bscf(child_mask);
+ if (child_mask == 0) {
+ node_addr = __float_as_int(cnodes[r]);
+ continue;
+ }
+
+ /* Two children are hit, push far child, and continue with
+ * closer child.
+ */
+ int c0 = __float_as_int(cnodes[r]);
+ float d0 = ((float *)&dist)[r];
+ r = __bscf(child_mask);
+ int c1 = __float_as_int(cnodes[r]);
+ float d1 = ((float *)&dist)[r];
+ if (child_mask == 0) {
+ if (d1 < d0) {
+ node_addr = c1;
+ ++stack_ptr;
+ kernel_assert(stack_ptr < BVH_OSTACK_SIZE);
+ traversal_stack[stack_ptr].addr = c0;
+ traversal_stack[stack_ptr].dist = d0;
+ continue;
+ }
+ else {
+ node_addr = c0;
+ ++stack_ptr;
+ kernel_assert(stack_ptr < BVH_OSTACK_SIZE);
+ traversal_stack[stack_ptr].addr = c1;
+ traversal_stack[stack_ptr].dist = d1;
+ continue;
+ }
+ }
+
+ /* Here starts the slow path for 3 or 4 hit children. We push
+ * all nodes onto the stack to sort them there.
+ */
+ ++stack_ptr;
+ kernel_assert(stack_ptr < BVH_OSTACK_SIZE);
+ traversal_stack[stack_ptr].addr = c1;
+ traversal_stack[stack_ptr].dist = d1;
+ ++stack_ptr;
+ kernel_assert(stack_ptr < BVH_OSTACK_SIZE);
+ traversal_stack[stack_ptr].addr = c0;
+ traversal_stack[stack_ptr].dist = d0;
+
+ /* Three children are hit, push all onto stack and sort 3
+ * stack items, continue with closest child.
+ */
+ r = __bscf(child_mask);
+ int c2 = __float_as_int(cnodes[r]);
+ float d2 = ((float *)&dist)[r];
+ if (child_mask == 0) {
+ ++stack_ptr;
+ kernel_assert(stack_ptr < BVH_OSTACK_SIZE);
+ traversal_stack[stack_ptr].addr = c2;
+ traversal_stack[stack_ptr].dist = d2;
+ obvh_stack_sort(&traversal_stack[stack_ptr],
+ &traversal_stack[stack_ptr - 1],
+ &traversal_stack[stack_ptr - 2]);
+ node_addr = traversal_stack[stack_ptr].addr;
+ --stack_ptr;
+ continue;
+ }
+
+ /* Four children are hit, push all onto stack and sort 4
+ * stack items, continue with closest child.
+ */
+ r = __bscf(child_mask);
+ int c3 = __float_as_int(cnodes[r]);
+ float d3 = ((float *)&dist)[r];
+ if (child_mask == 0) {
+ ++stack_ptr;
+ kernel_assert(stack_ptr < BVH_OSTACK_SIZE);
+ traversal_stack[stack_ptr].addr = c3;
+ traversal_stack[stack_ptr].dist = d3;
+ ++stack_ptr;
+ kernel_assert(stack_ptr < BVH_OSTACK_SIZE);
+ traversal_stack[stack_ptr].addr = c2;
+ traversal_stack[stack_ptr].dist = d2;
+ obvh_stack_sort(&traversal_stack[stack_ptr],
+ &traversal_stack[stack_ptr - 1],
+ &traversal_stack[stack_ptr - 2],
+ &traversal_stack[stack_ptr - 3]);
+ node_addr = traversal_stack[stack_ptr].addr;
+ --stack_ptr;
+ continue;
+ }
+
+ ++stack_ptr;
+ kernel_assert(stack_ptr < BVH_OSTACK_SIZE);
+ traversal_stack[stack_ptr].addr = c3;
+ traversal_stack[stack_ptr].dist = d3;
+ ++stack_ptr;
+ kernel_assert(stack_ptr < BVH_OSTACK_SIZE);
+ traversal_stack[stack_ptr].addr = c2;
+ traversal_stack[stack_ptr].dist = d2;
+
+ /* Five children are hit, push all onto stack and sort 5
+ * stack items, continue with closest child
+ */
+ r = __bscf(child_mask);
+ int c4 = __float_as_int(cnodes[r]);
+ float d4 = ((float *)&dist)[r];
+ if (child_mask == 0) {
+ ++stack_ptr;
+ kernel_assert(stack_ptr < BVH_OSTACK_SIZE);
+ traversal_stack[stack_ptr].addr = c4;
+ traversal_stack[stack_ptr].dist = d4;
+ obvh_stack_sort(&traversal_stack[stack_ptr],
+ &traversal_stack[stack_ptr - 1],
+ &traversal_stack[stack_ptr - 2],
+ &traversal_stack[stack_ptr - 3],
+ &traversal_stack[stack_ptr - 4]);
+ node_addr = traversal_stack[stack_ptr].addr;
+ --stack_ptr;
+ continue;
+ }
+
+ /* Six children are hit, push all onto stack and sort 6
+ * stack items, continue with closest child.
+ */
+ r = __bscf(child_mask);
+ int c5 = __float_as_int(cnodes[r]);
+ float d5 = ((float *)&dist)[r];
+ if (child_mask == 0) {
+ ++stack_ptr;
+ kernel_assert(stack_ptr < BVH_OSTACK_SIZE);
+ traversal_stack[stack_ptr].addr = c5;
+ traversal_stack[stack_ptr].dist = d5;
+ ++stack_ptr;
+ kernel_assert(stack_ptr < BVH_OSTACK_SIZE);
+ traversal_stack[stack_ptr].addr = c4;
+ traversal_stack[stack_ptr].dist = d4;
+ obvh_stack_sort(&traversal_stack[stack_ptr],
+ &traversal_stack[stack_ptr - 1],
+ &traversal_stack[stack_ptr - 2],
+ &traversal_stack[stack_ptr - 3],
+ &traversal_stack[stack_ptr - 4],
+ &traversal_stack[stack_ptr - 5]);
+ node_addr = traversal_stack[stack_ptr].addr;
+ --stack_ptr;
+ continue;
+ }
+
+ ++stack_ptr;
+ kernel_assert(stack_ptr < BVH_OSTACK_SIZE);
+ traversal_stack[stack_ptr].addr = c5;
+ traversal_stack[stack_ptr].dist = d5;
+ ++stack_ptr;
+ kernel_assert(stack_ptr < BVH_OSTACK_SIZE);
+ traversal_stack[stack_ptr].addr = c4;
+ traversal_stack[stack_ptr].dist = d4;
+
+ /* Seven children are hit, push all onto stack and sort 7
+ * stack items, continue with closest child.
+ */
+ r = __bscf(child_mask);
+ int c6 = __float_as_int(cnodes[r]);
+ float d6 = ((float *)&dist)[r];
+ if (child_mask == 0) {
+ ++stack_ptr;
+ kernel_assert(stack_ptr < BVH_OSTACK_SIZE);
+ traversal_stack[stack_ptr].addr = c6;
+ traversal_stack[stack_ptr].dist = d6;
+ obvh_stack_sort(&traversal_stack[stack_ptr],
+ &traversal_stack[stack_ptr - 1],
+ &traversal_stack[stack_ptr - 2],
+ &traversal_stack[stack_ptr - 3],
+ &traversal_stack[stack_ptr - 4],
+ &traversal_stack[stack_ptr - 5],
+ &traversal_stack[stack_ptr - 6]);
+ node_addr = traversal_stack[stack_ptr].addr;
+ --stack_ptr;
+ continue;
+ }
+
+ /* Eight children are hit, push all onto stack and sort 8
+ * stack items, continue with closest child.
+ */
+ r = __bscf(child_mask);
+ int c7 = __float_as_int(cnodes[r]);
+ float d7 = ((float *)&dist)[r];
+ ++stack_ptr;
+ kernel_assert(stack_ptr < BVH_OSTACK_SIZE);
+ traversal_stack[stack_ptr].addr = c7;
+ traversal_stack[stack_ptr].dist = d7;
+ ++stack_ptr;
+ kernel_assert(stack_ptr < BVH_OSTACK_SIZE);
+ traversal_stack[stack_ptr].addr = c6;
+ traversal_stack[stack_ptr].dist = d6;
+ obvh_stack_sort(&traversal_stack[stack_ptr],
+ &traversal_stack[stack_ptr - 1],
+ &traversal_stack[stack_ptr - 2],
+ &traversal_stack[stack_ptr - 3],
+ &traversal_stack[stack_ptr - 4],
+ &traversal_stack[stack_ptr - 5],
+ &traversal_stack[stack_ptr - 6],
+ &traversal_stack[stack_ptr - 7]);
+ node_addr = traversal_stack[stack_ptr].addr;
+ --stack_ptr;
+ continue;
+ }
+
+ node_addr = traversal_stack[stack_ptr].addr;
+ --stack_ptr;
+ }
+
+ /* If node is leaf, fetch triangle list. */
+ if (node_addr < 0) {
+ float4 leaf = kernel_tex_fetch(__bvh_leaf_nodes, (-node_addr - 1));
#ifdef __VISIBILITY_FLAG__
- if((__float_as_uint(leaf.z) & PATH_RAY_SHADOW) == 0) {
- /* Pop. */
- node_addr = traversal_stack[stack_ptr].addr;
- --stack_ptr;
- continue;
- }
+ if ((__float_as_uint(leaf.z) & PATH_RAY_SHADOW) == 0) {
+ /* Pop. */
+ node_addr = traversal_stack[stack_ptr].addr;
+ --stack_ptr;
+ continue;
+ }
#endif
- int prim_addr = __float_as_int(leaf.x);
+ int prim_addr = __float_as_int(leaf.x);
#if BVH_FEATURE(BVH_INSTANCING)
- if(prim_addr >= 0) {
+ if (prim_addr >= 0) {
#endif
- int prim_addr2 = __float_as_int(leaf.y);
- const uint type = __float_as_int(leaf.w);
- const uint p_type = type & PRIMITIVE_ALL;
-
- /* Pop. */
- node_addr = traversal_stack[stack_ptr].addr;
- --stack_ptr;
-
- /* Primitive intersection. */
- if(p_type == PRIMITIVE_TRIANGLE) {
- int prim_count = prim_addr2 - prim_addr;
- if(prim_count < 3) {
- while(prim_addr < prim_addr2) {
- kernel_assert((kernel_tex_fetch(__prim_type, prim_addr) & PRIMITIVE_ALL) == p_type);
- int hit = triangle_intersect(kg,
- isect_array,
- P,
- dir,
- PATH_RAY_SHADOW,
- object,
- prim_addr);
- /* Shadow ray early termination. */
- if(hit) {
- /* detect if this surface has a shader with transparent shadows */
-
- /* todo: optimize so primitive visibility flag indicates if
- * the primitive has a transparent shadow shader? */
- int prim = kernel_tex_fetch(__prim_index, isect_array->prim);
- int shader = 0;
+ int prim_addr2 = __float_as_int(leaf.y);
+ const uint type = __float_as_int(leaf.w);
+ const uint p_type = type & PRIMITIVE_ALL;
+
+ /* Pop. */
+ node_addr = traversal_stack[stack_ptr].addr;
+ --stack_ptr;
+
+ /* Primitive intersection. */
+ if (p_type == PRIMITIVE_TRIANGLE) {
+ int prim_count = prim_addr2 - prim_addr;
+ if (prim_count < 3) {
+ while (prim_addr < prim_addr2) {
+ kernel_assert((kernel_tex_fetch(__prim_type, prim_addr) & PRIMITIVE_ALL) ==
+ p_type);
+ int hit = triangle_intersect(
+ kg, isect_array, P, dir, PATH_RAY_SHADOW, object, prim_addr);
+ /* Shadow ray early termination. */
+ if (hit) {
+ /* detect if this surface has a shader with transparent shadows */
+
+ /* todo: optimize so primitive visibility flag indicates if
+ * the primitive has a transparent shadow shader? */
+ int prim = kernel_tex_fetch(__prim_index, isect_array->prim);
+ int shader = 0;
#ifdef __HAIR__
- if(kernel_tex_fetch(__prim_type, isect_array->prim) & PRIMITIVE_ALL_TRIANGLE)
+ if (kernel_tex_fetch(__prim_type, isect_array->prim) & PRIMITIVE_ALL_TRIANGLE)
#endif
- {
- shader = kernel_tex_fetch(__tri_shader, prim);
- }
+ {
+ shader = kernel_tex_fetch(__tri_shader, prim);
+ }
#ifdef __HAIR__
- else {
- float4 str = kernel_tex_fetch(__curves, prim);
- shader = __float_as_int(str.z);
- }
+ else {
+ float4 str = kernel_tex_fetch(__curves, prim);
+ shader = __float_as_int(str.z);
+ }
#endif
- int flag = kernel_tex_fetch(__shaders, (shader & SHADER_MASK)).flags;
-
- /* if no transparent shadows, all light is blocked */
- if(!(flag & SD_HAS_TRANSPARENT_SHADOW)) {
- return true;
- }
- /* if maximum number of hits reached, block all light */
- else if(*num_hits == max_hits) {
- return true;
- }
-
- /* move on to next entry in intersections array */
- isect_array++;
- (*num_hits)++;
+ int flag = kernel_tex_fetch(__shaders, (shader & SHADER_MASK)).flags;
+
+ /* if no transparent shadows, all light is blocked */
+ if (!(flag & SD_HAS_TRANSPARENT_SHADOW)) {
+ return true;
+ }
+ /* if maximum number of hits reached, block all light */
+ else if (*num_hits == max_hits) {
+ return true;
+ }
+
+ /* move on to next entry in intersections array */
+ isect_array++;
+ (*num_hits)++;
#if BVH_FEATURE(BVH_INSTANCING)
- num_hits_in_instance++;
+ num_hits_in_instance++;
#endif
- isect_array->t = isect_t;
- }
+ isect_array->t = isect_t;
+ }
- prim_addr++;
- } //while
- } else {
- kernel_assert((kernel_tex_fetch(__prim_type, (prim_addr)) & PRIMITIVE_ALL) == p_type);
+ prim_addr++;
+ } //while
+ }
+ else {
+ kernel_assert((kernel_tex_fetch(__prim_type, (prim_addr)) & PRIMITIVE_ALL) ==
+ p_type);
#if BVH_FEATURE(BVH_INSTANCING)
- int* nhiptr = &num_hits_in_instance;
+ int *nhiptr = &num_hits_in_instance;
#else
- int nhi= 0;
- int *nhiptr = &nhi;
+ int nhi = 0;
+ int *nhiptr = &nhi;
#endif
- int result = triangle_intersect8(kg,
- &isect_array,
- P,
- dir,
- PATH_RAY_SHADOW,
- object,
- prim_addr,
- prim_count,
- num_hits,
- max_hits,
- nhiptr,
- isect_t);
- if(result == 2) {
- return true;
- }
- } // prim_count
- } // PRIMITIVE_TRIANGLE
- else {
- while(prim_addr < prim_addr2) {
- kernel_assert((kernel_tex_fetch(__prim_type, prim_addr) & PRIMITIVE_ALL) == p_type);
+ int result = triangle_intersect8(kg,
+ &isect_array,
+ P,
+ dir,
+ PATH_RAY_SHADOW,
+ object,
+ prim_addr,
+ prim_count,
+ num_hits,
+ max_hits,
+ nhiptr,
+ isect_t);
+ if (result == 2) {
+ return true;
+ }
+ } // prim_count
+ } // PRIMITIVE_TRIANGLE
+ else {
+ while (prim_addr < prim_addr2) {
+ kernel_assert((kernel_tex_fetch(__prim_type, prim_addr) & PRIMITIVE_ALL) == p_type);
#ifdef __SHADOW_TRICKS__
- uint tri_object = (object == OBJECT_NONE)
- ? kernel_tex_fetch(__prim_object, prim_addr)
- : object;
- if(tri_object == skip_object) {
- ++prim_addr;
- continue;
- }
+ uint tri_object = (object == OBJECT_NONE) ?
+ kernel_tex_fetch(__prim_object, prim_addr) :
+ object;
+ if (tri_object == skip_object) {
+ ++prim_addr;
+ continue;
+ }
#endif
- bool hit;
+ bool hit;
- /* todo: specialized intersect functions which don't fill in
- * isect unless needed and check SD_HAS_TRANSPARENT_SHADOW?
- * might give a few % performance improvement */
+ /* todo: specialized intersect functions which don't fill in
+ * isect unless needed and check SD_HAS_TRANSPARENT_SHADOW?
+ * might give a few % performance improvement */
- switch(p_type) {
+ switch (p_type) {
#if BVH_FEATURE(BVH_MOTION)
- case PRIMITIVE_MOTION_TRIANGLE: {
- hit = motion_triangle_intersect(kg,
- isect_array,
- P,
- dir,
- ray->time,
- PATH_RAY_SHADOW,
- object,
- prim_addr);
- break;
- }
+ case PRIMITIVE_MOTION_TRIANGLE: {
+ hit = motion_triangle_intersect(
+ kg, isect_array, P, dir, ray->time, PATH_RAY_SHADOW, object, prim_addr);
+ break;
+ }
#endif
#if BVH_FEATURE(BVH_HAIR)
- case PRIMITIVE_CURVE:
- case PRIMITIVE_MOTION_CURVE: {
- const uint curve_type = kernel_tex_fetch(__prim_type, prim_addr);
- if(kernel_data.curve.curveflags & CURVE_KN_INTERPOLATE) {
- hit = cardinal_curve_intersect(kg,
- isect_array,
- P,
- dir,
- PATH_RAY_SHADOW,
- object,
- prim_addr,
- ray->time,
- curve_type,
- NULL,
- 0, 0);
- }
- else {
- hit = curve_intersect(kg,
- isect_array,
- P,
- dir,
- PATH_RAY_SHADOW,
- object,
- prim_addr,
- ray->time,
- curve_type,
- NULL,
- 0, 0);
- }
- break;
- }
+ case PRIMITIVE_CURVE:
+ case PRIMITIVE_MOTION_CURVE: {
+ const uint curve_type = kernel_tex_fetch(__prim_type, prim_addr);
+ if (kernel_data.curve.curveflags & CURVE_KN_INTERPOLATE) {
+ hit = cardinal_curve_intersect(kg,
+ isect_array,
+ P,
+ dir,
+ PATH_RAY_SHADOW,
+ object,
+ prim_addr,
+ ray->time,
+ curve_type,
+ NULL,
+ 0,
+ 0);
+ }
+ else {
+ hit = curve_intersect(kg,
+ isect_array,
+ P,
+ dir,
+ PATH_RAY_SHADOW,
+ object,
+ prim_addr,
+ ray->time,
+ curve_type,
+ NULL,
+ 0,
+ 0);
+ }
+ break;
+ }
#endif
- default: {
- hit = false;
- break;
- }
- }
+ default: {
+ hit = false;
+ break;
+ }
+ }
- /* Shadow ray early termination. */
- if(hit) {
- /* detect if this surface has a shader with transparent shadows */
+ /* Shadow ray early termination. */
+ if (hit) {
+ /* detect if this surface has a shader with transparent shadows */
- /* todo: optimize so primitive visibility flag indicates if
- * the primitive has a transparent shadow shader? */
- int prim = kernel_tex_fetch(__prim_index, isect_array->prim);
- int shader = 0;
+ /* todo: optimize so primitive visibility flag indicates if
+ * the primitive has a transparent shadow shader? */
+ int prim = kernel_tex_fetch(__prim_index, isect_array->prim);
+ int shader = 0;
#ifdef __HAIR__
- if(kernel_tex_fetch(__prim_type, isect_array->prim) & PRIMITIVE_ALL_TRIANGLE)
+ if (kernel_tex_fetch(__prim_type, isect_array->prim) & PRIMITIVE_ALL_TRIANGLE)
#endif
- {
- shader = kernel_tex_fetch(__tri_shader, prim);
- }
+ {
+ shader = kernel_tex_fetch(__tri_shader, prim);
+ }
#ifdef __HAIR__
- else {
- float4 str = kernel_tex_fetch(__curves, prim);
- shader = __float_as_int(str.z);
- }
+ else {
+ float4 str = kernel_tex_fetch(__curves, prim);
+ shader = __float_as_int(str.z);
+ }
#endif
- int flag = kernel_tex_fetch(__shaders, (shader & SHADER_MASK)).flags;
-
- /* if no transparent shadows, all light is blocked */
- if(!(flag & SD_HAS_TRANSPARENT_SHADOW)) {
- return true;
- }
- /* if maximum number of hits reached, block all light */
- else if(*num_hits == max_hits) {
- return true;
- }
-
- /* move on to next entry in intersections array */
- isect_array++;
- (*num_hits)++;
+ int flag = kernel_tex_fetch(__shaders, (shader & SHADER_MASK)).flags;
+
+ /* if no transparent shadows, all light is blocked */
+ if (!(flag & SD_HAS_TRANSPARENT_SHADOW)) {
+ return true;
+ }
+ /* if maximum number of hits reached, block all light */
+ else if (*num_hits == max_hits) {
+ return true;
+ }
+
+ /* move on to next entry in intersections array */
+ isect_array++;
+ (*num_hits)++;
#if BVH_FEATURE(BVH_INSTANCING)
- num_hits_in_instance++;
+ num_hits_in_instance++;
#endif
- isect_array->t = isect_t;
- }
+ isect_array->t = isect_t;
+ }
- prim_addr++;
- }//while prim
- }
- }
+ prim_addr++;
+ } //while prim
+ }
+ }
#if BVH_FEATURE(BVH_INSTANCING)
- else {
- /* Instance push. */
- object = kernel_tex_fetch(__prim_object, -prim_addr-1);
+ else {
+ /* Instance push. */
+ object = kernel_tex_fetch(__prim_object, -prim_addr - 1);
# if BVH_FEATURE(BVH_MOTION)
- isect_t = bvh_instance_motion_push(kg, object, ray, &P, &dir, &idir, isect_t, &ob_itfm);
+ isect_t = bvh_instance_motion_push(kg, object, ray, &P, &dir, &idir, isect_t, &ob_itfm);
# else
- isect_t = bvh_instance_push(kg, object, ray, &P, &dir, &idir, isect_t);
+ isect_t = bvh_instance_push(kg, object, ray, &P, &dir, &idir, isect_t);
# endif
- num_hits_in_instance = 0;
- isect_array->t = isect_t;
+ num_hits_in_instance = 0;
+ isect_array->t = isect_t;
- obvh_near_far_idx_calc(idir,
- &near_x, &near_y, &near_z,
- &far_x, &far_y, &far_z);
- tfar = avxf(isect_t);
+ obvh_near_far_idx_calc(idir, &near_x, &near_y, &near_z, &far_x, &far_y, &far_z);
+ tfar = avxf(isect_t);
# if BVH_FEATURE(BVH_HAIR)
- dir4 = avx3f(avxf(dir.x), avxf(dir.y), avxf(dir.z));
+ dir4 = avx3f(avxf(dir.x), avxf(dir.y), avxf(dir.z));
# endif
- idir4 = avx3f(avxf(idir.x), avxf(idir.y), avxf(idir.z));
+ idir4 = avx3f(avxf(idir.x), avxf(idir.y), avxf(idir.z));
# ifdef __KERNEL_AVX2__
- P_idir = P*idir;
- P_idir4 = avx3f(P_idir.x, P_idir.y, P_idir.z);
+ P_idir = P * idir;
+ P_idir4 = avx3f(P_idir.x, P_idir.y, P_idir.z);
# endif
# if BVH_FEATURE(BVH_HAIR) || !defined(__KERNEL_AVX2__)
- org4 = avx3f(avxf(P.x), avxf(P.y), avxf(P.z));
+ org4 = avx3f(avxf(P.x), avxf(P.y), avxf(P.z));
# endif
- ++stack_ptr;
- kernel_assert(stack_ptr < BVH_OSTACK_SIZE);
- traversal_stack[stack_ptr].addr = ENTRYPOINT_SENTINEL;
-
- node_addr = kernel_tex_fetch(__object_node, object);
+ ++stack_ptr;
+ kernel_assert(stack_ptr < BVH_OSTACK_SIZE);
+ traversal_stack[stack_ptr].addr = ENTRYPOINT_SENTINEL;
- }
- }
-#endif /* FEATURE(BVH_INSTANCING) */
- } while(node_addr != ENTRYPOINT_SENTINEL);
+ node_addr = kernel_tex_fetch(__object_node, object);
+ }
+ }
+#endif /* FEATURE(BVH_INSTANCING) */
+ } while (node_addr != ENTRYPOINT_SENTINEL);
#if BVH_FEATURE(BVH_INSTANCING)
- if(stack_ptr >= 0) {
- kernel_assert(object != OBJECT_NONE);
+ if (stack_ptr >= 0) {
+ kernel_assert(object != OBJECT_NONE);
- /* Instance pop. */
- if(num_hits_in_instance) {
- float t_fac;
+ /* Instance pop. */
+ if (num_hits_in_instance) {
+ float t_fac;
# if BVH_FEATURE(BVH_MOTION)
- bvh_instance_motion_pop_factor(kg, object, ray, &P, &dir, &idir, &t_fac, &ob_itfm);
+ bvh_instance_motion_pop_factor(kg, object, ray, &P, &dir, &idir, &t_fac, &ob_itfm);
# else
- bvh_instance_pop_factor(kg, object, ray, &P, &dir, &idir, &t_fac);
+ bvh_instance_pop_factor(kg, object, ray, &P, &dir, &idir, &t_fac);
# endif
- /* Scale isect->t to adjust for instancing. */
- for(int i = 0; i < num_hits_in_instance; i++) {
- (isect_array-i-1)->t *= t_fac;
- }
- }
- else {
+ /* Scale isect->t to adjust for instancing. */
+ for (int i = 0; i < num_hits_in_instance; i++) {
+ (isect_array - i - 1)->t *= t_fac;
+ }
+ }
+ else {
# if BVH_FEATURE(BVH_MOTION)
- bvh_instance_motion_pop(kg, object, ray, &P, &dir, &idir, FLT_MAX, &ob_itfm);
+ bvh_instance_motion_pop(kg, object, ray, &P, &dir, &idir, FLT_MAX, &ob_itfm);
# else
- bvh_instance_pop(kg, object, ray, &P, &dir, &idir, FLT_MAX);
+ bvh_instance_pop(kg, object, ray, &P, &dir, &idir, FLT_MAX);
# endif
- }
+ }
- isect_t = tmax;
- isect_array->t = isect_t;
+ isect_t = tmax;
+ isect_array->t = isect_t;
- obvh_near_far_idx_calc(idir,
- &near_x, &near_y, &near_z,
- &far_x, &far_y, &far_z);
- tfar = avxf(isect_t);
+ obvh_near_far_idx_calc(idir, &near_x, &near_y, &near_z, &far_x, &far_y, &far_z);
+ tfar = avxf(isect_t);
# if BVH_FEATURE(BVH_HAIR)
- dir4 = avx3f(avxf(dir.x), avxf(dir.y), avxf(dir.z));
+ dir4 = avx3f(avxf(dir.x), avxf(dir.y), avxf(dir.z));
# endif
- idir4 = avx3f(avxf(idir.x), avxf(idir.y), avxf(idir.z));
+ idir4 = avx3f(avxf(idir.x), avxf(idir.y), avxf(idir.z));
# ifdef __KERNEL_AVX2__
- P_idir = P*idir;
- P_idir4 = avx3f(P_idir.x, P_idir.y, P_idir.z);
+ P_idir = P * idir;
+ P_idir4 = avx3f(P_idir.x, P_idir.y, P_idir.z);
# endif
# if BVH_FEATURE(BVH_HAIR) || !defined(__KERNEL_AVX2__)
- org4 = avx3f(avxf(P.x), avxf(P.y), avxf(P.z));
+ org4 = avx3f(avxf(P.x), avxf(P.y), avxf(P.z));
# endif
- object = OBJECT_NONE;
- node_addr = traversal_stack[stack_ptr].addr;
- --stack_ptr;
- }
-#endif /* FEATURE(BVH_INSTANCING) */
- } while(node_addr != ENTRYPOINT_SENTINEL);
+ object = OBJECT_NONE;
+ node_addr = traversal_stack[stack_ptr].addr;
+ --stack_ptr;
+ }
+#endif /* FEATURE(BVH_INSTANCING) */
+ } while (node_addr != ENTRYPOINT_SENTINEL);
- return false;
+ return false;
}
#undef NODE_INTERSECT
diff --git a/intern/cycles/kernel/bvh/obvh_traversal.h b/intern/cycles/kernel/bvh/obvh_traversal.h
index 5df7a3be515..86b1de48aaa 100644
--- a/intern/cycles/kernel/bvh/obvh_traversal.h
+++ b/intern/cycles/kernel/bvh/obvh_traversal.h
@@ -37,598 +37,583 @@ ccl_device bool BVH_FUNCTION_FULL_NAME(OBVH)(KernelGlobals *kg,
Intersection *isect,
const uint visibility
#if BVH_FEATURE(BVH_HAIR_MINIMUM_WIDTH)
- ,uint *lcg_state,
+ ,
+ uint *lcg_state,
float difl,
float extmax
#endif
- )
+)
{
- /* Traversal stack in CUDA thread-local memory. */
- OBVHStackItem traversal_stack[BVH_OSTACK_SIZE];
- traversal_stack[0].addr = ENTRYPOINT_SENTINEL;
- traversal_stack[0].dist = -FLT_MAX;
-
- /* Traversal variables in registers. */
- int stack_ptr = 0;
- int node_addr = kernel_data.bvh.root;
- float node_dist = -FLT_MAX;
-
- /* Ray parameters in registers. */
- float3 P = ray->P;
- float3 dir = bvh_clamp_direction(ray->D);
- float3 idir = bvh_inverse_direction(dir);
- int object = OBJECT_NONE;
+ /* Traversal stack in CUDA thread-local memory. */
+ OBVHStackItem traversal_stack[BVH_OSTACK_SIZE];
+ traversal_stack[0].addr = ENTRYPOINT_SENTINEL;
+ traversal_stack[0].dist = -FLT_MAX;
+
+ /* Traversal variables in registers. */
+ int stack_ptr = 0;
+ int node_addr = kernel_data.bvh.root;
+ float node_dist = -FLT_MAX;
+
+ /* Ray parameters in registers. */
+ float3 P = ray->P;
+ float3 dir = bvh_clamp_direction(ray->D);
+ float3 idir = bvh_inverse_direction(dir);
+ int object = OBJECT_NONE;
#if BVH_FEATURE(BVH_MOTION)
- Transform ob_itfm;
+ Transform ob_itfm;
#endif
- isect->t = ray->t;
- isect->u = 0.0f;
- isect->v = 0.0f;
- isect->prim = PRIM_NONE;
- isect->object = OBJECT_NONE;
+ isect->t = ray->t;
+ isect->u = 0.0f;
+ isect->v = 0.0f;
+ isect->prim = PRIM_NONE;
+ isect->object = OBJECT_NONE;
- BVH_DEBUG_INIT();
- avxf tnear(0.0f), tfar(ray->t);
+ BVH_DEBUG_INIT();
+ avxf tnear(0.0f), tfar(ray->t);
#if BVH_FEATURE(BVH_HAIR)
- avx3f dir4(avxf(dir.x), avxf(dir.y), avxf(dir.z));
+ avx3f dir4(avxf(dir.x), avxf(dir.y), avxf(dir.z));
#endif
- avx3f idir4(avxf(idir.x), avxf(idir.y), avxf(idir.z));
+ avx3f idir4(avxf(idir.x), avxf(idir.y), avxf(idir.z));
#ifdef __KERNEL_AVX2__
- float3 P_idir = P*idir;
- avx3f P_idir4 = avx3f(P_idir.x, P_idir.y, P_idir.z);
+ float3 P_idir = P * idir;
+ avx3f P_idir4 = avx3f(P_idir.x, P_idir.y, P_idir.z);
#endif
#if BVH_FEATURE(BVH_HAIR) || !defined(__KERNEL_AVX2__)
- avx3f org4 = avx3f(avxf(P.x), avxf(P.y), avxf(P.z));
+ avx3f org4 = avx3f(avxf(P.x), avxf(P.y), avxf(P.z));
#endif
- /* Offsets to select the side that becomes the lower or upper bound. */
- int near_x, near_y, near_z;
- int far_x, far_y, far_z;
- obvh_near_far_idx_calc(idir,
- &near_x, &near_y, &near_z,
- &far_x, &far_y, &far_z);
- /* Traversal loop. */
- do {
- do {
- /* Traverse internal nodes. */
- while(node_addr >= 0 && node_addr != ENTRYPOINT_SENTINEL) {
- float4 inodes = kernel_tex_fetch(__bvh_nodes, node_addr+0);
- (void) inodes;
-
- if(UNLIKELY(node_dist > isect->t)
+ /* Offsets to select the side that becomes the lower or upper bound. */
+ int near_x, near_y, near_z;
+ int far_x, far_y, far_z;
+ obvh_near_far_idx_calc(idir, &near_x, &near_y, &near_z, &far_x, &far_y, &far_z);
+ /* Traversal loop. */
+ do {
+ do {
+ /* Traverse internal nodes. */
+ while (node_addr >= 0 && node_addr != ENTRYPOINT_SENTINEL) {
+ float4 inodes = kernel_tex_fetch(__bvh_nodes, node_addr + 0);
+ (void)inodes;
+
+ if (UNLIKELY(node_dist > isect->t)
#if BVH_FEATURE(BVH_MOTION)
- || UNLIKELY(ray->time < inodes.y)
- || UNLIKELY(ray->time > inodes.z)
+ || UNLIKELY(ray->time < inodes.y) || UNLIKELY(ray->time > inodes.z)
#endif
#ifdef __VISIBILITY_FLAG__
- || (__float_as_uint(inodes.x) & visibility) == 0
+ || (__float_as_uint(inodes.x) & visibility) == 0
#endif
- )
- {
- /* Pop. */
- node_addr = traversal_stack[stack_ptr].addr;
- node_dist = traversal_stack[stack_ptr].dist;
- --stack_ptr;
- continue;
- }
+ ) {
+ /* Pop. */
+ node_addr = traversal_stack[stack_ptr].addr;
+ node_dist = traversal_stack[stack_ptr].dist;
+ --stack_ptr;
+ continue;
+ }
- int child_mask;
- avxf dist;
+ int child_mask;
+ avxf dist;
- BVH_DEBUG_NEXT_NODE();
+ BVH_DEBUG_NEXT_NODE();
#if BVH_FEATURE(BVH_HAIR_MINIMUM_WIDTH)
- if(difl != 0.0f) {
- /* NOTE: We extend all the child BB instead of fetching
- * and checking visibility flags for each of the,
- *
- * Need to test if doing opposite would be any faster.
- */
- child_mask = NODE_INTERSECT_ROBUST(kg,
- tnear,
- tfar,
+ if (difl != 0.0f) {
+ /* NOTE: We extend all the child BB instead of fetching
+ * and checking visibility flags for each of the,
+ *
+ * Need to test if doing opposite would be any faster.
+ */
+ child_mask = NODE_INTERSECT_ROBUST(kg,
+ tnear,
+ tfar,
# ifdef __KERNEL_AVX2__
- P_idir4,
+ P_idir4,
# endif
# if BVH_FEATURE(BVH_HAIR) || !defined(__KERNEL_AVX2__)
- org4,
+ org4,
# endif
# if BVH_FEATURE(BVH_HAIR)
- dir4,
+ dir4,
# endif
- idir4,
- near_x, near_y, near_z,
- far_x, far_y, far_z,
- node_addr,
- difl,
- &dist);
- }
- else
-#endif /* BVH_HAIR_MINIMUM_WIDTH */
- {
- child_mask = NODE_INTERSECT(kg,
- tnear,
- tfar,
+ idir4,
+ near_x,
+ near_y,
+ near_z,
+ far_x,
+ far_y,
+ far_z,
+ node_addr,
+ difl,
+ &dist);
+ }
+ else
+#endif /* BVH_HAIR_MINIMUM_WIDTH */
+ {
+ child_mask = NODE_INTERSECT(kg,
+ tnear,
+ tfar,
#ifdef __KERNEL_AVX2__
- P_idir4,
+ P_idir4,
#endif
#if BVH_FEATURE(BVH_HAIR) || !defined(__KERNEL_AVX2__)
- org4,
+ org4,
#endif
#if BVH_FEATURE(BVH_HAIR)
- dir4,
+ dir4,
#endif
- idir4,
- near_x, near_y, near_z,
- far_x, far_y, far_z,
- node_addr,
- &dist);
- }
-
- if(child_mask != 0) {
- avxf cnodes;
- /* TODO(sergey): Investigate whether moving cnodes upwards
- * gives a speedup (will be different cache pattern but will
- * avoid extra check here).
- */
+ idir4,
+ near_x,
+ near_y,
+ near_z,
+ far_x,
+ far_y,
+ far_z,
+ node_addr,
+ &dist);
+ }
+
+ if (child_mask != 0) {
+ avxf cnodes;
+ /* TODO(sergey): Investigate whether moving cnodes upwards
+ * gives a speedup (will be different cache pattern but will
+ * avoid extra check here).
+ */
#if BVH_FEATURE(BVH_HAIR)
- if(__float_as_uint(inodes.x) & PATH_RAY_NODE_UNALIGNED) {
- cnodes = kernel_tex_fetch_avxf(__bvh_nodes, node_addr+26);
- }
- else
+ if (__float_as_uint(inodes.x) & PATH_RAY_NODE_UNALIGNED) {
+ cnodes = kernel_tex_fetch_avxf(__bvh_nodes, node_addr + 26);
+ }
+ else
#endif
- {
- cnodes = kernel_tex_fetch_avxf(__bvh_nodes, node_addr+14);
- }
-
- /* One child is hit, continue with that child. */
- int r = __bscf(child_mask);
- float d0 = ((float*)&dist)[r];
- if(child_mask == 0) {
- node_addr = __float_as_int(cnodes[r]);
- node_dist = d0;
- continue;
- }
-
- /* Two children are hit, push far child, and continue with
- * closer child.
- */
- int c0 = __float_as_int(cnodes[r]);
- r = __bscf(child_mask);
- int c1 = __float_as_int(cnodes[r]);
- float d1 = ((float*)&dist)[r];
- if(child_mask == 0) {
- if(d1 < d0) {
- node_addr = c1;
- node_dist = d1;
- ++stack_ptr;
- kernel_assert(stack_ptr < BVH_OSTACK_SIZE);
- traversal_stack[stack_ptr].addr = c0;
- traversal_stack[stack_ptr].dist = d0;
- continue;
- }
- else {
- node_addr = c0;
- node_dist = d0;
- ++stack_ptr;
- kernel_assert(stack_ptr < BVH_OSTACK_SIZE);
- traversal_stack[stack_ptr].addr = c1;
- traversal_stack[stack_ptr].dist = d1;
- continue;
- }
- }
-
- /* Here starts the slow path for 3 or 4 hit children. We push
- * all nodes onto the stack to sort them there.
- */
- ++stack_ptr;
- kernel_assert(stack_ptr < BVH_OSTACK_SIZE);
- traversal_stack[stack_ptr].addr = c1;
- traversal_stack[stack_ptr].dist = d1;
- ++stack_ptr;
- kernel_assert(stack_ptr < BVH_OSTACK_SIZE);
- traversal_stack[stack_ptr].addr = c0;
- traversal_stack[stack_ptr].dist = d0;
-
- /* Three children are hit, push all onto stack and sort 3
- * stack items, continue with closest child.
- */
- r = __bscf(child_mask);
- int c2 = __float_as_int(cnodes[r]);
- float d2 = ((float*)&dist)[r];
- if(child_mask == 0) {
- ++stack_ptr;
- kernel_assert(stack_ptr < BVH_OSTACK_SIZE);
- traversal_stack[stack_ptr].addr = c2;
- traversal_stack[stack_ptr].dist = d2;
- obvh_stack_sort(&traversal_stack[stack_ptr],
- &traversal_stack[stack_ptr - 1],
- &traversal_stack[stack_ptr - 2]);
- node_addr = traversal_stack[stack_ptr].addr;
- node_dist = traversal_stack[stack_ptr].dist;
- --stack_ptr;
- continue;
- }
-
- /* Four children are hit, push all onto stack and sort 4
- * stack items, continue with closest child.
- */
- r = __bscf(child_mask);
- int c3 = __float_as_int(cnodes[r]);
- float d3 = ((float*)&dist)[r];
- if(child_mask == 0) {
- ++stack_ptr;
- kernel_assert(stack_ptr < BVH_OSTACK_SIZE);
- traversal_stack[stack_ptr].addr = c3;
- traversal_stack[stack_ptr].dist = d3;
- ++stack_ptr;
- kernel_assert(stack_ptr < BVH_OSTACK_SIZE);
- traversal_stack[stack_ptr].addr = c2;
- traversal_stack[stack_ptr].dist = d2;
- obvh_stack_sort(&traversal_stack[stack_ptr],
- &traversal_stack[stack_ptr - 1],
- &traversal_stack[stack_ptr - 2],
- &traversal_stack[stack_ptr - 3]);
- node_addr = traversal_stack[stack_ptr].addr;
- node_dist = traversal_stack[stack_ptr].dist;
- --stack_ptr;
- continue;
- }
-
- ++stack_ptr;
- kernel_assert(stack_ptr < BVH_OSTACK_SIZE);
- traversal_stack[stack_ptr].addr = c3;
- traversal_stack[stack_ptr].dist = d3;
- ++stack_ptr;
- kernel_assert(stack_ptr < BVH_OSTACK_SIZE);
- traversal_stack[stack_ptr].addr = c2;
- traversal_stack[stack_ptr].dist = d2;
-
- /* Five children are hit, push all onto stack and sort 5
- * stack items, continue with closest child.
- */
- r = __bscf(child_mask);
- int c4 = __float_as_int(cnodes[r]);
- float d4 = ((float*)&dist)[r];
- if(child_mask == 0) {
- ++stack_ptr;
- kernel_assert(stack_ptr < BVH_OSTACK_SIZE);
- traversal_stack[stack_ptr].addr = c4;
- traversal_stack[stack_ptr].dist = d4;
- obvh_stack_sort(&traversal_stack[stack_ptr],
- &traversal_stack[stack_ptr - 1],
- &traversal_stack[stack_ptr - 2],
- &traversal_stack[stack_ptr - 3],
- &traversal_stack[stack_ptr - 4]);
- node_addr = traversal_stack[stack_ptr].addr;
- node_dist = traversal_stack[stack_ptr].dist;
- --stack_ptr;
- continue;
- }
-
- /* Six children are hit, push all onto stack and sort 6
- * stack items, continue with closest child.
- */
- r = __bscf(child_mask);
- int c5 = __float_as_int(cnodes[r]);
- float d5 = ((float*)&dist)[r];
- if(child_mask == 0) {
- ++stack_ptr;
- kernel_assert(stack_ptr < BVH_OSTACK_SIZE);
- traversal_stack[stack_ptr].addr = c5;
- traversal_stack[stack_ptr].dist = d5;
- ++stack_ptr;
- kernel_assert(stack_ptr < BVH_OSTACK_SIZE);
- traversal_stack[stack_ptr].addr = c4;
- traversal_stack[stack_ptr].dist = d4;
- obvh_stack_sort(&traversal_stack[stack_ptr],
- &traversal_stack[stack_ptr - 1],
- &traversal_stack[stack_ptr - 2],
- &traversal_stack[stack_ptr - 3],
- &traversal_stack[stack_ptr - 4],
- &traversal_stack[stack_ptr - 5]);
- node_addr = traversal_stack[stack_ptr].addr;
- node_dist = traversal_stack[stack_ptr].dist;
- --stack_ptr;
- continue;
- }
-
- ++stack_ptr;
- kernel_assert(stack_ptr < BVH_OSTACK_SIZE);
- traversal_stack[stack_ptr].addr = c5;
- traversal_stack[stack_ptr].dist = d5;
- ++stack_ptr;
- kernel_assert(stack_ptr < BVH_OSTACK_SIZE);
- traversal_stack[stack_ptr].addr = c4;
- traversal_stack[stack_ptr].dist = d4;
-
- /* Seven children are hit, push all onto stack and sort 7
- * stack items, continue with closest child.
- */
- r = __bscf(child_mask);
- int c6 = __float_as_int(cnodes[r]);
- float d6 = ((float*)&dist)[r];
- if(child_mask == 0) {
- ++stack_ptr;
- kernel_assert(stack_ptr < BVH_OSTACK_SIZE);
- traversal_stack[stack_ptr].addr = c6;
- traversal_stack[stack_ptr].dist = d6;
- obvh_stack_sort(&traversal_stack[stack_ptr],
- &traversal_stack[stack_ptr - 1],
- &traversal_stack[stack_ptr - 2],
- &traversal_stack[stack_ptr - 3],
- &traversal_stack[stack_ptr - 4],
- &traversal_stack[stack_ptr - 5],
- &traversal_stack[stack_ptr - 6]);
- node_addr = traversal_stack[stack_ptr].addr;
- node_dist = traversal_stack[stack_ptr].dist;
- --stack_ptr;
- continue;
- }
-
- /* Eight children are hit, push all onto stack and sort 8
- * stack items, continue with closest child.
- */
- r = __bscf(child_mask);
- int c7 = __float_as_int(cnodes[r]);
- float d7 = ((float*)&dist)[r];
- ++stack_ptr;
- kernel_assert(stack_ptr < BVH_OSTACK_SIZE);
- traversal_stack[stack_ptr].addr = c7;
- traversal_stack[stack_ptr].dist = d7;
- ++stack_ptr;
- kernel_assert(stack_ptr < BVH_OSTACK_SIZE);
- traversal_stack[stack_ptr].addr = c6;
- traversal_stack[stack_ptr].dist = d6;
- obvh_stack_sort(&traversal_stack[stack_ptr],
- &traversal_stack[stack_ptr - 1],
- &traversal_stack[stack_ptr - 2],
- &traversal_stack[stack_ptr - 3],
- &traversal_stack[stack_ptr - 4],
- &traversal_stack[stack_ptr - 5],
- &traversal_stack[stack_ptr - 6],
- &traversal_stack[stack_ptr - 7]);
- node_addr = traversal_stack[stack_ptr].addr;
- node_dist = traversal_stack[stack_ptr].dist;
- --stack_ptr;
- continue;
- }
-
-
- node_addr = traversal_stack[stack_ptr].addr;
- node_dist = traversal_stack[stack_ptr].dist;
- --stack_ptr;
- }
-
- /* If node is leaf, fetch triangle list. */
- if(node_addr < 0) {
- float4 leaf = kernel_tex_fetch(__bvh_leaf_nodes, (-node_addr-1));
+ {
+ cnodes = kernel_tex_fetch_avxf(__bvh_nodes, node_addr + 14);
+ }
+
+ /* One child is hit, continue with that child. */
+ int r = __bscf(child_mask);
+ float d0 = ((float *)&dist)[r];
+ if (child_mask == 0) {
+ node_addr = __float_as_int(cnodes[r]);
+ node_dist = d0;
+ continue;
+ }
+
+ /* Two children are hit, push far child, and continue with
+ * closer child.
+ */
+ int c0 = __float_as_int(cnodes[r]);
+ r = __bscf(child_mask);
+ int c1 = __float_as_int(cnodes[r]);
+ float d1 = ((float *)&dist)[r];
+ if (child_mask == 0) {
+ if (d1 < d0) {
+ node_addr = c1;
+ node_dist = d1;
+ ++stack_ptr;
+ kernel_assert(stack_ptr < BVH_OSTACK_SIZE);
+ traversal_stack[stack_ptr].addr = c0;
+ traversal_stack[stack_ptr].dist = d0;
+ continue;
+ }
+ else {
+ node_addr = c0;
+ node_dist = d0;
+ ++stack_ptr;
+ kernel_assert(stack_ptr < BVH_OSTACK_SIZE);
+ traversal_stack[stack_ptr].addr = c1;
+ traversal_stack[stack_ptr].dist = d1;
+ continue;
+ }
+ }
+
+ /* Here starts the slow path for 3 or 4 hit children. We push
+ * all nodes onto the stack to sort them there.
+ */
+ ++stack_ptr;
+ kernel_assert(stack_ptr < BVH_OSTACK_SIZE);
+ traversal_stack[stack_ptr].addr = c1;
+ traversal_stack[stack_ptr].dist = d1;
+ ++stack_ptr;
+ kernel_assert(stack_ptr < BVH_OSTACK_SIZE);
+ traversal_stack[stack_ptr].addr = c0;
+ traversal_stack[stack_ptr].dist = d0;
+
+ /* Three children are hit, push all onto stack and sort 3
+ * stack items, continue with closest child.
+ */
+ r = __bscf(child_mask);
+ int c2 = __float_as_int(cnodes[r]);
+ float d2 = ((float *)&dist)[r];
+ if (child_mask == 0) {
+ ++stack_ptr;
+ kernel_assert(stack_ptr < BVH_OSTACK_SIZE);
+ traversal_stack[stack_ptr].addr = c2;
+ traversal_stack[stack_ptr].dist = d2;
+ obvh_stack_sort(&traversal_stack[stack_ptr],
+ &traversal_stack[stack_ptr - 1],
+ &traversal_stack[stack_ptr - 2]);
+ node_addr = traversal_stack[stack_ptr].addr;
+ node_dist = traversal_stack[stack_ptr].dist;
+ --stack_ptr;
+ continue;
+ }
+
+ /* Four children are hit, push all onto stack and sort 4
+ * stack items, continue with closest child.
+ */
+ r = __bscf(child_mask);
+ int c3 = __float_as_int(cnodes[r]);
+ float d3 = ((float *)&dist)[r];
+ if (child_mask == 0) {
+ ++stack_ptr;
+ kernel_assert(stack_ptr < BVH_OSTACK_SIZE);
+ traversal_stack[stack_ptr].addr = c3;
+ traversal_stack[stack_ptr].dist = d3;
+ ++stack_ptr;
+ kernel_assert(stack_ptr < BVH_OSTACK_SIZE);
+ traversal_stack[stack_ptr].addr = c2;
+ traversal_stack[stack_ptr].dist = d2;
+ obvh_stack_sort(&traversal_stack[stack_ptr],
+ &traversal_stack[stack_ptr - 1],
+ &traversal_stack[stack_ptr - 2],
+ &traversal_stack[stack_ptr - 3]);
+ node_addr = traversal_stack[stack_ptr].addr;
+ node_dist = traversal_stack[stack_ptr].dist;
+ --stack_ptr;
+ continue;
+ }
+
+ ++stack_ptr;
+ kernel_assert(stack_ptr < BVH_OSTACK_SIZE);
+ traversal_stack[stack_ptr].addr = c3;
+ traversal_stack[stack_ptr].dist = d3;
+ ++stack_ptr;
+ kernel_assert(stack_ptr < BVH_OSTACK_SIZE);
+ traversal_stack[stack_ptr].addr = c2;
+ traversal_stack[stack_ptr].dist = d2;
+
+ /* Five children are hit, push all onto stack and sort 5
+ * stack items, continue with closest child.
+ */
+ r = __bscf(child_mask);
+ int c4 = __float_as_int(cnodes[r]);
+ float d4 = ((float *)&dist)[r];
+ if (child_mask == 0) {
+ ++stack_ptr;
+ kernel_assert(stack_ptr < BVH_OSTACK_SIZE);
+ traversal_stack[stack_ptr].addr = c4;
+ traversal_stack[stack_ptr].dist = d4;
+ obvh_stack_sort(&traversal_stack[stack_ptr],
+ &traversal_stack[stack_ptr - 1],
+ &traversal_stack[stack_ptr - 2],
+ &traversal_stack[stack_ptr - 3],
+ &traversal_stack[stack_ptr - 4]);
+ node_addr = traversal_stack[stack_ptr].addr;
+ node_dist = traversal_stack[stack_ptr].dist;
+ --stack_ptr;
+ continue;
+ }
+
+ /* Six children are hit, push all onto stack and sort 6
+ * stack items, continue with closest child.
+ */
+ r = __bscf(child_mask);
+ int c5 = __float_as_int(cnodes[r]);
+ float d5 = ((float *)&dist)[r];
+ if (child_mask == 0) {
+ ++stack_ptr;
+ kernel_assert(stack_ptr < BVH_OSTACK_SIZE);
+ traversal_stack[stack_ptr].addr = c5;
+ traversal_stack[stack_ptr].dist = d5;
+ ++stack_ptr;
+ kernel_assert(stack_ptr < BVH_OSTACK_SIZE);
+ traversal_stack[stack_ptr].addr = c4;
+ traversal_stack[stack_ptr].dist = d4;
+ obvh_stack_sort(&traversal_stack[stack_ptr],
+ &traversal_stack[stack_ptr - 1],
+ &traversal_stack[stack_ptr - 2],
+ &traversal_stack[stack_ptr - 3],
+ &traversal_stack[stack_ptr - 4],
+ &traversal_stack[stack_ptr - 5]);
+ node_addr = traversal_stack[stack_ptr].addr;
+ node_dist = traversal_stack[stack_ptr].dist;
+ --stack_ptr;
+ continue;
+ }
+
+ ++stack_ptr;
+ kernel_assert(stack_ptr < BVH_OSTACK_SIZE);
+ traversal_stack[stack_ptr].addr = c5;
+ traversal_stack[stack_ptr].dist = d5;
+ ++stack_ptr;
+ kernel_assert(stack_ptr < BVH_OSTACK_SIZE);
+ traversal_stack[stack_ptr].addr = c4;
+ traversal_stack[stack_ptr].dist = d4;
+
+ /* Seven children are hit, push all onto stack and sort 7
+ * stack items, continue with closest child.
+ */
+ r = __bscf(child_mask);
+ int c6 = __float_as_int(cnodes[r]);
+ float d6 = ((float *)&dist)[r];
+ if (child_mask == 0) {
+ ++stack_ptr;
+ kernel_assert(stack_ptr < BVH_OSTACK_SIZE);
+ traversal_stack[stack_ptr].addr = c6;
+ traversal_stack[stack_ptr].dist = d6;
+ obvh_stack_sort(&traversal_stack[stack_ptr],
+ &traversal_stack[stack_ptr - 1],
+ &traversal_stack[stack_ptr - 2],
+ &traversal_stack[stack_ptr - 3],
+ &traversal_stack[stack_ptr - 4],
+ &traversal_stack[stack_ptr - 5],
+ &traversal_stack[stack_ptr - 6]);
+ node_addr = traversal_stack[stack_ptr].addr;
+ node_dist = traversal_stack[stack_ptr].dist;
+ --stack_ptr;
+ continue;
+ }
+
+ /* Eight children are hit, push all onto stack and sort 8
+ * stack items, continue with closest child.
+ */
+ r = __bscf(child_mask);
+ int c7 = __float_as_int(cnodes[r]);
+ float d7 = ((float *)&dist)[r];
+ ++stack_ptr;
+ kernel_assert(stack_ptr < BVH_OSTACK_SIZE);
+ traversal_stack[stack_ptr].addr = c7;
+ traversal_stack[stack_ptr].dist = d7;
+ ++stack_ptr;
+ kernel_assert(stack_ptr < BVH_OSTACK_SIZE);
+ traversal_stack[stack_ptr].addr = c6;
+ traversal_stack[stack_ptr].dist = d6;
+ obvh_stack_sort(&traversal_stack[stack_ptr],
+ &traversal_stack[stack_ptr - 1],
+ &traversal_stack[stack_ptr - 2],
+ &traversal_stack[stack_ptr - 3],
+ &traversal_stack[stack_ptr - 4],
+ &traversal_stack[stack_ptr - 5],
+ &traversal_stack[stack_ptr - 6],
+ &traversal_stack[stack_ptr - 7]);
+ node_addr = traversal_stack[stack_ptr].addr;
+ node_dist = traversal_stack[stack_ptr].dist;
+ --stack_ptr;
+ continue;
+ }
+
+ node_addr = traversal_stack[stack_ptr].addr;
+ node_dist = traversal_stack[stack_ptr].dist;
+ --stack_ptr;
+ }
+
+ /* If node is leaf, fetch triangle list. */
+ if (node_addr < 0) {
+ float4 leaf = kernel_tex_fetch(__bvh_leaf_nodes, (-node_addr - 1));
#ifdef __VISIBILITY_FLAG__
- if(UNLIKELY((node_dist > isect->t) ||
- ((__float_as_uint(leaf.z) & visibility) == 0)))
+ if (UNLIKELY((node_dist > isect->t) || ((__float_as_uint(leaf.z) & visibility) == 0)))
#else
- if(UNLIKELY((node_dist > isect->t)))
+ if (UNLIKELY((node_dist > isect->t)))
#endif
- {
- /* Pop. */
- node_addr = traversal_stack[stack_ptr].addr;
- node_dist = traversal_stack[stack_ptr].dist;
- --stack_ptr;
- continue;
- }
- int prim_addr = __float_as_int(leaf.x);
+ {
+ /* Pop. */
+ node_addr = traversal_stack[stack_ptr].addr;
+ node_dist = traversal_stack[stack_ptr].dist;
+ --stack_ptr;
+ continue;
+ }
+ int prim_addr = __float_as_int(leaf.x);
#if BVH_FEATURE(BVH_INSTANCING)
- if(prim_addr >= 0) {
+ if (prim_addr >= 0) {
#endif
- int prim_addr2 = __float_as_int(leaf.y);
- const uint type = __float_as_int(leaf.w);
-
- /* Pop. */
- node_addr = traversal_stack[stack_ptr].addr;
- node_dist = traversal_stack[stack_ptr].dist;
- --stack_ptr;
-
- /* Primitive intersection. */
- switch(type & PRIMITIVE_ALL) {
- case PRIMITIVE_TRIANGLE: {
- int prim_count = prim_addr2 - prim_addr;
- if(prim_count < 3) {
- for(; prim_addr < prim_addr2; prim_addr++) {
- BVH_DEBUG_NEXT_INTERSECTION();
- kernel_assert(kernel_tex_fetch(__prim_type, prim_addr) == type);
- if(triangle_intersect(kg,
- isect,
- P,
- dir,
- visibility,
- object,
- prim_addr))
- {
- tfar = avxf(isect->t);
- /* Shadow ray early termination. */
- if(visibility == PATH_RAY_SHADOW_OPAQUE) {
- return true;
- }
- }
- }//for
- }
- else {
- kernel_assert(kernel_tex_fetch(__prim_type, prim_addr) == type);
- if(triangle_intersect8(kg,
- &isect,
- P,
- dir,
- visibility,
- object,
- prim_addr,
- prim_count,
- 0,
- 0,
- NULL,
- 0.0f))
- {
- tfar = avxf(isect->t);
- if(visibility == PATH_RAY_SHADOW_OPAQUE) {
- return true;
- }
- }
- }//prim count
- break;
- }
+ int prim_addr2 = __float_as_int(leaf.y);
+ const uint type = __float_as_int(leaf.w);
+
+ /* Pop. */
+ node_addr = traversal_stack[stack_ptr].addr;
+ node_dist = traversal_stack[stack_ptr].dist;
+ --stack_ptr;
+
+ /* Primitive intersection. */
+ switch (type & PRIMITIVE_ALL) {
+ case PRIMITIVE_TRIANGLE: {
+ int prim_count = prim_addr2 - prim_addr;
+ if (prim_count < 3) {
+ for (; prim_addr < prim_addr2; prim_addr++) {
+ BVH_DEBUG_NEXT_INTERSECTION();
+ kernel_assert(kernel_tex_fetch(__prim_type, prim_addr) == type);
+ if (triangle_intersect(kg, isect, P, dir, visibility, object, prim_addr)) {
+ tfar = avxf(isect->t);
+ /* Shadow ray early termination. */
+ if (visibility == PATH_RAY_SHADOW_OPAQUE) {
+ return true;
+ }
+ }
+ } //for
+ }
+ else {
+ kernel_assert(kernel_tex_fetch(__prim_type, prim_addr) == type);
+ if (triangle_intersect8(kg,
+ &isect,
+ P,
+ dir,
+ visibility,
+ object,
+ prim_addr,
+ prim_count,
+ 0,
+ 0,
+ NULL,
+ 0.0f)) {
+ tfar = avxf(isect->t);
+ if (visibility == PATH_RAY_SHADOW_OPAQUE) {
+ return true;
+ }
+ }
+ } //prim count
+ break;
+ }
#if BVH_FEATURE(BVH_MOTION)
- case PRIMITIVE_MOTION_TRIANGLE: {
- for(; prim_addr < prim_addr2; prim_addr++) {
- BVH_DEBUG_NEXT_INTERSECTION();
- kernel_assert(kernel_tex_fetch(__prim_type, prim_addr) == type);
- if(motion_triangle_intersect(kg,
- isect,
- P,
- dir,
- ray->time,
- visibility,
- object,
- prim_addr))
- {
- tfar = avxf(isect->t);
- /* Shadow ray early termination. */
- if(visibility == PATH_RAY_SHADOW_OPAQUE) {
- return true;
- }
- }
- }
- break;
- }
-#endif /* BVH_FEATURE(BVH_MOTION) */
+ case PRIMITIVE_MOTION_TRIANGLE: {
+ for (; prim_addr < prim_addr2; prim_addr++) {
+ BVH_DEBUG_NEXT_INTERSECTION();
+ kernel_assert(kernel_tex_fetch(__prim_type, prim_addr) == type);
+ if (motion_triangle_intersect(
+ kg, isect, P, dir, ray->time, visibility, object, prim_addr)) {
+ tfar = avxf(isect->t);
+ /* Shadow ray early termination. */
+ if (visibility == PATH_RAY_SHADOW_OPAQUE) {
+ return true;
+ }
+ }
+ }
+ break;
+ }
+#endif /* BVH_FEATURE(BVH_MOTION) */
#if BVH_FEATURE(BVH_HAIR)
- case PRIMITIVE_CURVE:
- case PRIMITIVE_MOTION_CURVE: {
- for(; prim_addr < prim_addr2; prim_addr++) {
- BVH_DEBUG_NEXT_INTERSECTION();
- const uint curve_type = kernel_tex_fetch(__prim_type, prim_addr);
- kernel_assert((curve_type & PRIMITIVE_ALL) == (type & PRIMITIVE_ALL));
- bool hit;
- if(kernel_data.curve.curveflags & CURVE_KN_INTERPOLATE) {
- hit = cardinal_curve_intersect(kg,
- isect,
- P,
- dir,
- visibility,
- object,
- prim_addr,
- ray->time,
- curve_type,
- lcg_state,
- difl,
- extmax);
- }
- else {
- hit = curve_intersect(kg,
- isect,
- P,
- dir,
- visibility,
- object,
- prim_addr,
- ray->time,
- curve_type,
- lcg_state,
- difl,
- extmax);
- }
- if(hit) {
- tfar = avxf(isect->t);
- /* Shadow ray early termination. */
- if(visibility == PATH_RAY_SHADOW_OPAQUE) {
- return true;
- }
- }
- }
- break;
- }
-#endif /* BVH_FEATURE(BVH_HAIR) */
- }
- }
+ case PRIMITIVE_CURVE:
+ case PRIMITIVE_MOTION_CURVE: {
+ for (; prim_addr < prim_addr2; prim_addr++) {
+ BVH_DEBUG_NEXT_INTERSECTION();
+ const uint curve_type = kernel_tex_fetch(__prim_type, prim_addr);
+ kernel_assert((curve_type & PRIMITIVE_ALL) == (type & PRIMITIVE_ALL));
+ bool hit;
+ if (kernel_data.curve.curveflags & CURVE_KN_INTERPOLATE) {
+ hit = cardinal_curve_intersect(kg,
+ isect,
+ P,
+ dir,
+ visibility,
+ object,
+ prim_addr,
+ ray->time,
+ curve_type,
+ lcg_state,
+ difl,
+ extmax);
+ }
+ else {
+ hit = curve_intersect(kg,
+ isect,
+ P,
+ dir,
+ visibility,
+ object,
+ prim_addr,
+ ray->time,
+ curve_type,
+ lcg_state,
+ difl,
+ extmax);
+ }
+ if (hit) {
+ tfar = avxf(isect->t);
+ /* Shadow ray early termination. */
+ if (visibility == PATH_RAY_SHADOW_OPAQUE) {
+ return true;
+ }
+ }
+ }
+ break;
+ }
+#endif /* BVH_FEATURE(BVH_HAIR) */
+ }
+ }
#if BVH_FEATURE(BVH_INSTANCING)
- else {
- /* Instance push. */
- object = kernel_tex_fetch(__prim_object, -prim_addr-1);
+ else {
+ /* Instance push. */
+ object = kernel_tex_fetch(__prim_object, -prim_addr - 1);
# if BVH_FEATURE(BVH_MOTION)
- qbvh_instance_motion_push(kg, object, ray, &P, &dir, &idir, &isect->t, &node_dist, &ob_itfm);
+ qbvh_instance_motion_push(
+ kg, object, ray, &P, &dir, &idir, &isect->t, &node_dist, &ob_itfm);
# else
- qbvh_instance_push(kg, object, ray, &P, &dir, &idir, &isect->t, &node_dist);
+ qbvh_instance_push(kg, object, ray, &P, &dir, &idir, &isect->t, &node_dist);
# endif
- obvh_near_far_idx_calc(idir,
- &near_x, &near_y, &near_z,
- &far_x, &far_y, &far_z);
- tfar = avxf(isect->t);
+ obvh_near_far_idx_calc(idir, &near_x, &near_y, &near_z, &far_x, &far_y, &far_z);
+ tfar = avxf(isect->t);
# if BVH_FEATURE(BVH_HAIR)
- dir4 = avx3f(avxf(dir.x), avxf(dir.y), avxf(dir.z));
+ dir4 = avx3f(avxf(dir.x), avxf(dir.y), avxf(dir.z));
# endif
- idir4 = avx3f(avxf(idir.x), avxf(idir.y), avxf(idir.z));
+ idir4 = avx3f(avxf(idir.x), avxf(idir.y), avxf(idir.z));
# ifdef __KERNEL_AVX2__
- P_idir = P*idir;
- P_idir4 = avx3f(P_idir.x, P_idir.y, P_idir.z);
+ P_idir = P * idir;
+ P_idir4 = avx3f(P_idir.x, P_idir.y, P_idir.z);
# endif
# if BVH_FEATURE(BVH_HAIR) || !defined(__KERNEL_AVX2__)
- org4 = avx3f(avxf(P.x), avxf(P.y), avxf(P.z));
+ org4 = avx3f(avxf(P.x), avxf(P.y), avxf(P.z));
# endif
- ++stack_ptr;
- kernel_assert(stack_ptr < BVH_OSTACK_SIZE);
- traversal_stack[stack_ptr].addr = ENTRYPOINT_SENTINEL;
- traversal_stack[stack_ptr].dist = -FLT_MAX;
+ ++stack_ptr;
+ kernel_assert(stack_ptr < BVH_OSTACK_SIZE);
+ traversal_stack[stack_ptr].addr = ENTRYPOINT_SENTINEL;
+ traversal_stack[stack_ptr].dist = -FLT_MAX;
- node_addr = kernel_tex_fetch(__object_node, object);
+ node_addr = kernel_tex_fetch(__object_node, object);
- BVH_DEBUG_NEXT_INSTANCE();
- }
- }
-#endif /* FEATURE(BVH_INSTANCING) */
- } while(node_addr != ENTRYPOINT_SENTINEL);
+ BVH_DEBUG_NEXT_INSTANCE();
+ }
+ }
+#endif /* FEATURE(BVH_INSTANCING) */
+ } while (node_addr != ENTRYPOINT_SENTINEL);
#if BVH_FEATURE(BVH_INSTANCING)
- if(stack_ptr >= 0) {
- kernel_assert(object != OBJECT_NONE);
+ if (stack_ptr >= 0) {
+ kernel_assert(object != OBJECT_NONE);
- /* Instance pop. */
+ /* Instance pop. */
# if BVH_FEATURE(BVH_MOTION)
- isect->t = bvh_instance_motion_pop(kg, object, ray, &P, &dir, &idir, isect->t, &ob_itfm);
+ isect->t = bvh_instance_motion_pop(kg, object, ray, &P, &dir, &idir, isect->t, &ob_itfm);
# else
- isect->t = bvh_instance_pop(kg, object, ray, &P, &dir, &idir, isect->t);
+ isect->t = bvh_instance_pop(kg, object, ray, &P, &dir, &idir, isect->t);
# endif
- obvh_near_far_idx_calc(idir,
- &near_x, &near_y, &near_z,
- &far_x, &far_y, &far_z);
- tfar = avxf(isect->t);
+ obvh_near_far_idx_calc(idir, &near_x, &near_y, &near_z, &far_x, &far_y, &far_z);
+ tfar = avxf(isect->t);
# if BVH_FEATURE(BVH_HAIR)
- dir4 = avx3f(avxf(dir.x), avxf(dir.y), avxf(dir.z));
+ dir4 = avx3f(avxf(dir.x), avxf(dir.y), avxf(dir.z));
# endif
- idir4 = avx3f(avxf(idir.x), avxf(idir.y), avxf(idir.z));
+ idir4 = avx3f(avxf(idir.x), avxf(idir.y), avxf(idir.z));
# ifdef __KERNEL_AVX2__
- P_idir = P*idir;
- P_idir4 = avx3f(P_idir.x, P_idir.y, P_idir.z);
+ P_idir = P * idir;
+ P_idir4 = avx3f(P_idir.x, P_idir.y, P_idir.z);
# endif
# if BVH_FEATURE(BVH_HAIR) || !defined(__KERNEL_AVX2__)
- org4 = avx3f(avxf(P.x), avxf(P.y), avxf(P.z));
+ org4 = avx3f(avxf(P.x), avxf(P.y), avxf(P.z));
# endif
- object = OBJECT_NONE;
- node_addr = traversal_stack[stack_ptr].addr;
- node_dist = traversal_stack[stack_ptr].dist;
- --stack_ptr;
- }
-#endif /* FEATURE(BVH_INSTANCING) */
- } while(node_addr != ENTRYPOINT_SENTINEL);
+ object = OBJECT_NONE;
+ node_addr = traversal_stack[stack_ptr].addr;
+ node_dist = traversal_stack[stack_ptr].dist;
+ --stack_ptr;
+ }
+#endif /* FEATURE(BVH_INSTANCING) */
+ } while (node_addr != ENTRYPOINT_SENTINEL);
- return (isect->prim != PRIM_NONE);
+ return (isect->prim != PRIM_NONE);
}
#undef NODE_INTERSECT
diff --git a/intern/cycles/kernel/bvh/obvh_volume.h b/intern/cycles/kernel/bvh/obvh_volume.h
index e66d499dccc..fb41ae783ab 100644
--- a/intern/cycles/kernel/bvh/obvh_volume.h
+++ b/intern/cycles/kernel/bvh/obvh_volume.h
@@ -33,444 +33,448 @@ ccl_device bool BVH_FUNCTION_FULL_NAME(OBVH)(KernelGlobals *kg,
Intersection *isect,
const uint visibility)
{
- /* Traversal stack in CUDA thread-local memory. */
- OBVHStackItem traversal_stack[BVH_OSTACK_SIZE];
- traversal_stack[0].addr = ENTRYPOINT_SENTINEL;
+ /* Traversal stack in CUDA thread-local memory. */
+ OBVHStackItem traversal_stack[BVH_OSTACK_SIZE];
+ traversal_stack[0].addr = ENTRYPOINT_SENTINEL;
- /* Traversal variables in registers. */
- int stack_ptr = 0;
- int node_addr = kernel_data.bvh.root;
+ /* Traversal variables in registers. */
+ int stack_ptr = 0;
+ int node_addr = kernel_data.bvh.root;
- /* Ray parameters in registers. */
- float3 P = ray->P;
- float3 dir = bvh_clamp_direction(ray->D);
- float3 idir = bvh_inverse_direction(dir);
- int object = OBJECT_NONE;
+ /* Ray parameters in registers. */
+ float3 P = ray->P;
+ float3 dir = bvh_clamp_direction(ray->D);
+ float3 idir = bvh_inverse_direction(dir);
+ int object = OBJECT_NONE;
#if BVH_FEATURE(BVH_MOTION)
- Transform ob_itfm;
+ Transform ob_itfm;
#endif
- isect->t = ray->t;
- isect->u = 0.0f;
- isect->v = 0.0f;
- isect->prim = PRIM_NONE;
- isect->object = OBJECT_NONE;
+ isect->t = ray->t;
+ isect->u = 0.0f;
+ isect->v = 0.0f;
+ isect->prim = PRIM_NONE;
+ isect->object = OBJECT_NONE;
- avxf tnear(0.0f), tfar(ray->t);
+ avxf tnear(0.0f), tfar(ray->t);
#if BVH_FEATURE(BVH_HAIR)
- avx3f dir4(avxf(dir.x), avxf(dir.y), avxf(dir.z));
+ avx3f dir4(avxf(dir.x), avxf(dir.y), avxf(dir.z));
#endif
- avx3f idir4(avxf(idir.x), avxf(idir.y), avxf(idir.z));
+ avx3f idir4(avxf(idir.x), avxf(idir.y), avxf(idir.z));
#ifdef __KERNEL_AVX2__
- float3 P_idir = P*idir;
- avx3f P_idir4(P_idir.x, P_idir.y, P_idir.z);
+ float3 P_idir = P * idir;
+ avx3f P_idir4(P_idir.x, P_idir.y, P_idir.z);
#endif
#if BVH_FEATURE(BVH_HAIR) || !defined(__KERNEL_AVX2__)
- avx3f org4(avxf(P.x), avxf(P.y), avxf(P.z));
+ avx3f org4(avxf(P.x), avxf(P.y), avxf(P.z));
#endif
- /* Offsets to select the side that becomes the lower or upper bound. */
- int near_x, near_y, near_z;
- int far_x, far_y, far_z;
- obvh_near_far_idx_calc(idir,
- &near_x, &near_y, &near_z,
- &far_x, &far_y, &far_z);
+ /* Offsets to select the side that becomes the lower or upper bound. */
+ int near_x, near_y, near_z;
+ int far_x, far_y, far_z;
+ obvh_near_far_idx_calc(idir, &near_x, &near_y, &near_z, &far_x, &far_y, &far_z);
- /* Traversal loop. */
- do {
- do {
- /* Traverse internal nodes. */
- while(node_addr >= 0 && node_addr != ENTRYPOINT_SENTINEL) {
- float4 inodes = kernel_tex_fetch(__bvh_nodes, node_addr+0);
+ /* Traversal loop. */
+ do {
+ do {
+ /* Traverse internal nodes. */
+ while (node_addr >= 0 && node_addr != ENTRYPOINT_SENTINEL) {
+ float4 inodes = kernel_tex_fetch(__bvh_nodes, node_addr + 0);
#ifdef __VISIBILITY_FLAG__
- if((__float_as_uint(inodes.x) & visibility) == 0) {
- /* Pop. */
- node_addr = traversal_stack[stack_ptr].addr;
- --stack_ptr;
- continue;
- }
+ if ((__float_as_uint(inodes.x) & visibility) == 0) {
+ /* Pop. */
+ node_addr = traversal_stack[stack_ptr].addr;
+ --stack_ptr;
+ continue;
+ }
#endif
- avxf dist;
- int child_mask = NODE_INTERSECT(kg,
- tnear,
- tfar,
+ avxf dist;
+ int child_mask = NODE_INTERSECT(kg,
+ tnear,
+ tfar,
#ifdef __KERNEL_AVX2__
- P_idir4,
+ P_idir4,
#endif
#if BVH_FEATURE(BVH_HAIR) || !defined(__KERNEL_AVX2__)
- org4,
+ org4,
#endif
#if BVH_FEATURE(BVH_HAIR)
- dir4,
+ dir4,
#endif
- idir4,
- near_x, near_y, near_z,
- far_x, far_y, far_z,
- node_addr,
- &dist);
-
- if(child_mask != 0) {
- avxf cnodes;
+ idir4,
+ near_x,
+ near_y,
+ near_z,
+ far_x,
+ far_y,
+ far_z,
+ node_addr,
+ &dist);
+
+ if (child_mask != 0) {
+ avxf cnodes;
#if BVH_FEATURE(BVH_HAIR)
- if(__float_as_uint(inodes.x) & PATH_RAY_NODE_UNALIGNED) {
- cnodes = kernel_tex_fetch_avxf(__bvh_nodes, node_addr+26);
- }
- else
+ if (__float_as_uint(inodes.x) & PATH_RAY_NODE_UNALIGNED) {
+ cnodes = kernel_tex_fetch_avxf(__bvh_nodes, node_addr + 26);
+ }
+ else
#endif
- {
- cnodes = kernel_tex_fetch_avxf(__bvh_nodes, node_addr+14);
- }
-
- /* One child is hit, continue with that child. */
- int r = __bscf(child_mask);
- if(child_mask == 0) {
- node_addr = __float_as_int(cnodes[r]);
- continue;
- }
-
- /* Two children are hit, push far child, and continue with
- * closer child.
- */
- int c0 = __float_as_int(cnodes[r]);
- float d0 = ((float*)&dist)[r];
- r = __bscf(child_mask);
- int c1 = __float_as_int(cnodes[r]);
- float d1 = ((float*)&dist)[r];
- if(child_mask == 0) {
- if(d1 < d0) {
- node_addr = c1;
- ++stack_ptr;
- kernel_assert(stack_ptr < BVH_OSTACK_SIZE);
- traversal_stack[stack_ptr].addr = c0;
- traversal_stack[stack_ptr].dist = d0;
- continue;
- }
- else {
- node_addr = c0;
- ++stack_ptr;
- kernel_assert(stack_ptr < BVH_OSTACK_SIZE);
- traversal_stack[stack_ptr].addr = c1;
- traversal_stack[stack_ptr].dist = d1;
- continue;
- }
- }
-
- /* Here starts the slow path for 3 or 4 hit children. We push
- * all nodes onto the stack to sort them there.
- */
- ++stack_ptr;
- kernel_assert(stack_ptr < BVH_OSTACK_SIZE);
- traversal_stack[stack_ptr].addr = c1;
- traversal_stack[stack_ptr].dist = d1;
- ++stack_ptr;
- kernel_assert(stack_ptr < BVH_OSTACK_SIZE);
- traversal_stack[stack_ptr].addr = c0;
- traversal_stack[stack_ptr].dist = d0;
-
- /* Three children are hit, push all onto stack and sort 3
- * stack items, continue with closest child.
- */
- r = __bscf(child_mask);
- int c2 = __float_as_int(cnodes[r]);
- float d2 = ((float*)&dist)[r];
- if(child_mask == 0) {
- ++stack_ptr;
- kernel_assert(stack_ptr < BVH_OSTACK_SIZE);
- traversal_stack[stack_ptr].addr = c2;
- traversal_stack[stack_ptr].dist = d2;
- obvh_stack_sort(&traversal_stack[stack_ptr],
- &traversal_stack[stack_ptr - 1],
- &traversal_stack[stack_ptr - 2]);
- node_addr = traversal_stack[stack_ptr].addr;
- --stack_ptr;
- continue;
- }
-
- /* Four children are hit, push all onto stack and sort 4
- * stack items, continue with closest child.
- */
- r = __bscf(child_mask);
- int c3 = __float_as_int(cnodes[r]);
- float d3 = ((float*)&dist)[r];
- if(child_mask == 0) {
- ++stack_ptr;
- kernel_assert(stack_ptr < BVH_OSTACK_SIZE);
- traversal_stack[stack_ptr].addr = c3;
- traversal_stack[stack_ptr].dist = d3;
- ++stack_ptr;
- kernel_assert(stack_ptr < BVH_OSTACK_SIZE);
- traversal_stack[stack_ptr].addr = c2;
- traversal_stack[stack_ptr].dist = d2;
- obvh_stack_sort(&traversal_stack[stack_ptr],
- &traversal_stack[stack_ptr - 1],
- &traversal_stack[stack_ptr - 2],
- &traversal_stack[stack_ptr - 3]);
- node_addr = traversal_stack[stack_ptr].addr;
- --stack_ptr;
- continue;
- }
-
- ++stack_ptr;
- kernel_assert(stack_ptr < BVH_OSTACK_SIZE);
- traversal_stack[stack_ptr].addr = c3;
- traversal_stack[stack_ptr].dist = d3;
- ++stack_ptr;
- kernel_assert(stack_ptr < BVH_OSTACK_SIZE);
- traversal_stack[stack_ptr].addr = c2;
- traversal_stack[stack_ptr].dist = d2;
-
- /* Five children are hit, push all onto stack and sort 5
- * stack items, continue with closest child
- */
- r = __bscf(child_mask);
- int c4 = __float_as_int(cnodes[r]);
- float d4 = ((float*)&dist)[r];
- if(child_mask == 0) {
- ++stack_ptr;
- kernel_assert(stack_ptr < BVH_OSTACK_SIZE);
- traversal_stack[stack_ptr].addr = c4;
- traversal_stack[stack_ptr].dist = d4;
- obvh_stack_sort(&traversal_stack[stack_ptr],
- &traversal_stack[stack_ptr - 1],
- &traversal_stack[stack_ptr - 2],
- &traversal_stack[stack_ptr - 3],
- &traversal_stack[stack_ptr - 4]);
- node_addr = traversal_stack[stack_ptr].addr;
- --stack_ptr;
- continue;
- }
-
- /* Six children are hit, push all onto stack and sort 6
- * stack items, continue with closest child.
- */
- r = __bscf(child_mask);
- int c5 = __float_as_int(cnodes[r]);
- float d5 = ((float*)&dist)[r];
- if(child_mask == 0) {
- ++stack_ptr;
- kernel_assert(stack_ptr < BVH_OSTACK_SIZE);
- traversal_stack[stack_ptr].addr = c5;
- traversal_stack[stack_ptr].dist = d5;
- ++stack_ptr;
- kernel_assert(stack_ptr < BVH_OSTACK_SIZE);
- traversal_stack[stack_ptr].addr = c4;
- traversal_stack[stack_ptr].dist = d4;
- obvh_stack_sort(&traversal_stack[stack_ptr],
- &traversal_stack[stack_ptr - 1],
- &traversal_stack[stack_ptr - 2],
- &traversal_stack[stack_ptr - 3],
- &traversal_stack[stack_ptr - 4],
- &traversal_stack[stack_ptr - 5]);
- node_addr = traversal_stack[stack_ptr].addr;
- --stack_ptr;
- continue;
- }
-
- ++stack_ptr;
- kernel_assert(stack_ptr < BVH_OSTACK_SIZE);
- traversal_stack[stack_ptr].addr = c5;
- traversal_stack[stack_ptr].dist = d5;
- ++stack_ptr;
- kernel_assert(stack_ptr < BVH_OSTACK_SIZE);
- traversal_stack[stack_ptr].addr = c4;
- traversal_stack[stack_ptr].dist = d4;
-
- /* Seven children are hit, push all onto stack and sort 7
- * stack items, continue with closest child.
- */
- r = __bscf(child_mask);
- int c6 = __float_as_int(cnodes[r]);
- float d6 = ((float*)&dist)[r];
- if(child_mask == 0) {
- ++stack_ptr;
- kernel_assert(stack_ptr < BVH_OSTACK_SIZE);
- traversal_stack[stack_ptr].addr = c6;
- traversal_stack[stack_ptr].dist = d6;
- obvh_stack_sort(&traversal_stack[stack_ptr],
- &traversal_stack[stack_ptr - 1],
- &traversal_stack[stack_ptr - 2],
- &traversal_stack[stack_ptr - 3],
- &traversal_stack[stack_ptr - 4],
- &traversal_stack[stack_ptr - 5],
- &traversal_stack[stack_ptr - 6]);
- node_addr = traversal_stack[stack_ptr].addr;
- --stack_ptr;
- continue;
- }
-
- /* Eight children are hit, push all onto stack and sort 8
- * stack items, continue with closest child.
- */
- r = __bscf(child_mask);
- int c7 = __float_as_int(cnodes[r]);
- float d7 = ((float*)&dist)[r];
- ++stack_ptr;
- kernel_assert(stack_ptr < BVH_OSTACK_SIZE);
- traversal_stack[stack_ptr].addr = c7;
- traversal_stack[stack_ptr].dist = d7;
- ++stack_ptr;
- kernel_assert(stack_ptr < BVH_OSTACK_SIZE);
- traversal_stack[stack_ptr].addr = c6;
- traversal_stack[stack_ptr].dist = d6;
- obvh_stack_sort(&traversal_stack[stack_ptr],
- &traversal_stack[stack_ptr - 1],
- &traversal_stack[stack_ptr - 2],
- &traversal_stack[stack_ptr - 3],
- &traversal_stack[stack_ptr - 4],
- &traversal_stack[stack_ptr - 5],
- &traversal_stack[stack_ptr - 6],
- &traversal_stack[stack_ptr - 7]);
- node_addr = traversal_stack[stack_ptr].addr;
- --stack_ptr;
- continue;
- }
-
- node_addr = traversal_stack[stack_ptr].addr;
- --stack_ptr;
- }
-
- /* If node is leaf, fetch triangle list. */
- if(node_addr < 0) {
- float4 leaf = kernel_tex_fetch(__bvh_leaf_nodes, (-node_addr-1));
-
- if((__float_as_uint(leaf.z) & visibility) == 0) {
- /* Pop. */
- node_addr = traversal_stack[stack_ptr].addr;
- --stack_ptr;
- continue;
- }
-
- int prim_addr = __float_as_int(leaf.x);
+ {
+ cnodes = kernel_tex_fetch_avxf(__bvh_nodes, node_addr + 14);
+ }
+
+ /* One child is hit, continue with that child. */
+ int r = __bscf(child_mask);
+ if (child_mask == 0) {
+ node_addr = __float_as_int(cnodes[r]);
+ continue;
+ }
+
+ /* Two children are hit, push far child, and continue with
+ * closer child.
+ */
+ int c0 = __float_as_int(cnodes[r]);
+ float d0 = ((float *)&dist)[r];
+ r = __bscf(child_mask);
+ int c1 = __float_as_int(cnodes[r]);
+ float d1 = ((float *)&dist)[r];
+ if (child_mask == 0) {
+ if (d1 < d0) {
+ node_addr = c1;
+ ++stack_ptr;
+ kernel_assert(stack_ptr < BVH_OSTACK_SIZE);
+ traversal_stack[stack_ptr].addr = c0;
+ traversal_stack[stack_ptr].dist = d0;
+ continue;
+ }
+ else {
+ node_addr = c0;
+ ++stack_ptr;
+ kernel_assert(stack_ptr < BVH_OSTACK_SIZE);
+ traversal_stack[stack_ptr].addr = c1;
+ traversal_stack[stack_ptr].dist = d1;
+ continue;
+ }
+ }
+
+ /* Here starts the slow path for 3 or 4 hit children. We push
+ * all nodes onto the stack to sort them there.
+ */
+ ++stack_ptr;
+ kernel_assert(stack_ptr < BVH_OSTACK_SIZE);
+ traversal_stack[stack_ptr].addr = c1;
+ traversal_stack[stack_ptr].dist = d1;
+ ++stack_ptr;
+ kernel_assert(stack_ptr < BVH_OSTACK_SIZE);
+ traversal_stack[stack_ptr].addr = c0;
+ traversal_stack[stack_ptr].dist = d0;
+
+ /* Three children are hit, push all onto stack and sort 3
+ * stack items, continue with closest child.
+ */
+ r = __bscf(child_mask);
+ int c2 = __float_as_int(cnodes[r]);
+ float d2 = ((float *)&dist)[r];
+ if (child_mask == 0) {
+ ++stack_ptr;
+ kernel_assert(stack_ptr < BVH_OSTACK_SIZE);
+ traversal_stack[stack_ptr].addr = c2;
+ traversal_stack[stack_ptr].dist = d2;
+ obvh_stack_sort(&traversal_stack[stack_ptr],
+ &traversal_stack[stack_ptr - 1],
+ &traversal_stack[stack_ptr - 2]);
+ node_addr = traversal_stack[stack_ptr].addr;
+ --stack_ptr;
+ continue;
+ }
+
+ /* Four children are hit, push all onto stack and sort 4
+ * stack items, continue with closest child.
+ */
+ r = __bscf(child_mask);
+ int c3 = __float_as_int(cnodes[r]);
+ float d3 = ((float *)&dist)[r];
+ if (child_mask == 0) {
+ ++stack_ptr;
+ kernel_assert(stack_ptr < BVH_OSTACK_SIZE);
+ traversal_stack[stack_ptr].addr = c3;
+ traversal_stack[stack_ptr].dist = d3;
+ ++stack_ptr;
+ kernel_assert(stack_ptr < BVH_OSTACK_SIZE);
+ traversal_stack[stack_ptr].addr = c2;
+ traversal_stack[stack_ptr].dist = d2;
+ obvh_stack_sort(&traversal_stack[stack_ptr],
+ &traversal_stack[stack_ptr - 1],
+ &traversal_stack[stack_ptr - 2],
+ &traversal_stack[stack_ptr - 3]);
+ node_addr = traversal_stack[stack_ptr].addr;
+ --stack_ptr;
+ continue;
+ }
+
+ ++stack_ptr;
+ kernel_assert(stack_ptr < BVH_OSTACK_SIZE);
+ traversal_stack[stack_ptr].addr = c3;
+ traversal_stack[stack_ptr].dist = d3;
+ ++stack_ptr;
+ kernel_assert(stack_ptr < BVH_OSTACK_SIZE);
+ traversal_stack[stack_ptr].addr = c2;
+ traversal_stack[stack_ptr].dist = d2;
+
+ /* Five children are hit, push all onto stack and sort 5
+ * stack items, continue with closest child
+ */
+ r = __bscf(child_mask);
+ int c4 = __float_as_int(cnodes[r]);
+ float d4 = ((float *)&dist)[r];
+ if (child_mask == 0) {
+ ++stack_ptr;
+ kernel_assert(stack_ptr < BVH_OSTACK_SIZE);
+ traversal_stack[stack_ptr].addr = c4;
+ traversal_stack[stack_ptr].dist = d4;
+ obvh_stack_sort(&traversal_stack[stack_ptr],
+ &traversal_stack[stack_ptr - 1],
+ &traversal_stack[stack_ptr - 2],
+ &traversal_stack[stack_ptr - 3],
+ &traversal_stack[stack_ptr - 4]);
+ node_addr = traversal_stack[stack_ptr].addr;
+ --stack_ptr;
+ continue;
+ }
+
+ /* Six children are hit, push all onto stack and sort 6
+ * stack items, continue with closest child.
+ */
+ r = __bscf(child_mask);
+ int c5 = __float_as_int(cnodes[r]);
+ float d5 = ((float *)&dist)[r];
+ if (child_mask == 0) {
+ ++stack_ptr;
+ kernel_assert(stack_ptr < BVH_OSTACK_SIZE);
+ traversal_stack[stack_ptr].addr = c5;
+ traversal_stack[stack_ptr].dist = d5;
+ ++stack_ptr;
+ kernel_assert(stack_ptr < BVH_OSTACK_SIZE);
+ traversal_stack[stack_ptr].addr = c4;
+ traversal_stack[stack_ptr].dist = d4;
+ obvh_stack_sort(&traversal_stack[stack_ptr],
+ &traversal_stack[stack_ptr - 1],
+ &traversal_stack[stack_ptr - 2],
+ &traversal_stack[stack_ptr - 3],
+ &traversal_stack[stack_ptr - 4],
+ &traversal_stack[stack_ptr - 5]);
+ node_addr = traversal_stack[stack_ptr].addr;
+ --stack_ptr;
+ continue;
+ }
+
+ ++stack_ptr;
+ kernel_assert(stack_ptr < BVH_OSTACK_SIZE);
+ traversal_stack[stack_ptr].addr = c5;
+ traversal_stack[stack_ptr].dist = d5;
+ ++stack_ptr;
+ kernel_assert(stack_ptr < BVH_OSTACK_SIZE);
+ traversal_stack[stack_ptr].addr = c4;
+ traversal_stack[stack_ptr].dist = d4;
+
+ /* Seven children are hit, push all onto stack and sort 7
+ * stack items, continue with closest child.
+ */
+ r = __bscf(child_mask);
+ int c6 = __float_as_int(cnodes[r]);
+ float d6 = ((float *)&dist)[r];
+ if (child_mask == 0) {
+ ++stack_ptr;
+ kernel_assert(stack_ptr < BVH_OSTACK_SIZE);
+ traversal_stack[stack_ptr].addr = c6;
+ traversal_stack[stack_ptr].dist = d6;
+ obvh_stack_sort(&traversal_stack[stack_ptr],
+ &traversal_stack[stack_ptr - 1],
+ &traversal_stack[stack_ptr - 2],
+ &traversal_stack[stack_ptr - 3],
+ &traversal_stack[stack_ptr - 4],
+ &traversal_stack[stack_ptr - 5],
+ &traversal_stack[stack_ptr - 6]);
+ node_addr = traversal_stack[stack_ptr].addr;
+ --stack_ptr;
+ continue;
+ }
+
+ /* Eight children are hit, push all onto stack and sort 8
+ * stack items, continue with closest child.
+ */
+ r = __bscf(child_mask);
+ int c7 = __float_as_int(cnodes[r]);
+ float d7 = ((float *)&dist)[r];
+ ++stack_ptr;
+ kernel_assert(stack_ptr < BVH_OSTACK_SIZE);
+ traversal_stack[stack_ptr].addr = c7;
+ traversal_stack[stack_ptr].dist = d7;
+ ++stack_ptr;
+ kernel_assert(stack_ptr < BVH_OSTACK_SIZE);
+ traversal_stack[stack_ptr].addr = c6;
+ traversal_stack[stack_ptr].dist = d6;
+ obvh_stack_sort(&traversal_stack[stack_ptr],
+ &traversal_stack[stack_ptr - 1],
+ &traversal_stack[stack_ptr - 2],
+ &traversal_stack[stack_ptr - 3],
+ &traversal_stack[stack_ptr - 4],
+ &traversal_stack[stack_ptr - 5],
+ &traversal_stack[stack_ptr - 6],
+ &traversal_stack[stack_ptr - 7]);
+ node_addr = traversal_stack[stack_ptr].addr;
+ --stack_ptr;
+ continue;
+ }
+
+ node_addr = traversal_stack[stack_ptr].addr;
+ --stack_ptr;
+ }
+
+ /* If node is leaf, fetch triangle list. */
+ if (node_addr < 0) {
+ float4 leaf = kernel_tex_fetch(__bvh_leaf_nodes, (-node_addr - 1));
+
+ if ((__float_as_uint(leaf.z) & visibility) == 0) {
+ /* Pop. */
+ node_addr = traversal_stack[stack_ptr].addr;
+ --stack_ptr;
+ continue;
+ }
+
+ int prim_addr = __float_as_int(leaf.x);
#if BVH_FEATURE(BVH_INSTANCING)
- if(prim_addr >= 0) {
+ if (prim_addr >= 0) {
#endif
- int prim_addr2 = __float_as_int(leaf.y);
- const uint type = __float_as_int(leaf.w);
- const uint p_type = type & PRIMITIVE_ALL;
-
- /* Pop. */
- node_addr = traversal_stack[stack_ptr].addr;
- --stack_ptr;
-
- /* Primitive intersection. */
- switch(p_type) {
- case PRIMITIVE_TRIANGLE: {
- for(; prim_addr < prim_addr2; prim_addr++) {
- kernel_assert(kernel_tex_fetch(__prim_type, prim_addr) == type);
- /* Only primitives from volume object. */
- uint tri_object = (object == OBJECT_NONE)? kernel_tex_fetch(__prim_object, prim_addr): object;
- int object_flag = kernel_tex_fetch(__object_flag, tri_object);
- if((object_flag & SD_OBJECT_HAS_VOLUME) == 0) {
- continue;
- }
- /* Intersect ray against primitive. */
- triangle_intersect(kg, isect, P, dir, visibility, object, prim_addr);
- }
- break;
- }
+ int prim_addr2 = __float_as_int(leaf.y);
+ const uint type = __float_as_int(leaf.w);
+ const uint p_type = type & PRIMITIVE_ALL;
+
+ /* Pop. */
+ node_addr = traversal_stack[stack_ptr].addr;
+ --stack_ptr;
+
+ /* Primitive intersection. */
+ switch (p_type) {
+ case PRIMITIVE_TRIANGLE: {
+ for (; prim_addr < prim_addr2; prim_addr++) {
+ kernel_assert(kernel_tex_fetch(__prim_type, prim_addr) == type);
+ /* Only primitives from volume object. */
+ uint tri_object = (object == OBJECT_NONE) ?
+ kernel_tex_fetch(__prim_object, prim_addr) :
+ object;
+ int object_flag = kernel_tex_fetch(__object_flag, tri_object);
+ if ((object_flag & SD_OBJECT_HAS_VOLUME) == 0) {
+ continue;
+ }
+ /* Intersect ray against primitive. */
+ triangle_intersect(kg, isect, P, dir, visibility, object, prim_addr);
+ }
+ break;
+ }
#if BVH_FEATURE(BVH_MOTION)
- case PRIMITIVE_MOTION_TRIANGLE: {
- for(; prim_addr < prim_addr2; prim_addr++) {
- kernel_assert(kernel_tex_fetch(__prim_type, prim_addr) == type);
- /* Only primitives from volume object. */
- uint tri_object = (object == OBJECT_NONE)? kernel_tex_fetch(__prim_object, prim_addr): object;
- int object_flag = kernel_tex_fetch(__object_flag, tri_object);
- if((object_flag & SD_OBJECT_HAS_VOLUME) == 0) {
- continue;
- }
- /* Intersect ray against primitive. */
- motion_triangle_intersect(kg, isect, P, dir, ray->time, visibility, object, prim_addr);
- }
- break;
- }
+ case PRIMITIVE_MOTION_TRIANGLE: {
+ for (; prim_addr < prim_addr2; prim_addr++) {
+ kernel_assert(kernel_tex_fetch(__prim_type, prim_addr) == type);
+ /* Only primitives from volume object. */
+ uint tri_object = (object == OBJECT_NONE) ?
+ kernel_tex_fetch(__prim_object, prim_addr) :
+ object;
+ int object_flag = kernel_tex_fetch(__object_flag, tri_object);
+ if ((object_flag & SD_OBJECT_HAS_VOLUME) == 0) {
+ continue;
+ }
+ /* Intersect ray against primitive. */
+ motion_triangle_intersect(
+ kg, isect, P, dir, ray->time, visibility, object, prim_addr);
+ }
+ break;
+ }
#endif
- }
- }
+ }
+ }
#if BVH_FEATURE(BVH_INSTANCING)
- else {
- /* Instance push. */
- object = kernel_tex_fetch(__prim_object, -prim_addr-1);
- int object_flag = kernel_tex_fetch(__object_flag, object);
- if(object_flag & SD_OBJECT_HAS_VOLUME) {
+ else {
+ /* Instance push. */
+ object = kernel_tex_fetch(__prim_object, -prim_addr - 1);
+ int object_flag = kernel_tex_fetch(__object_flag, object);
+ if (object_flag & SD_OBJECT_HAS_VOLUME) {
# if BVH_FEATURE(BVH_MOTION)
- isect->t = bvh_instance_motion_push(kg, object, ray, &P, &dir, &idir, isect->t, &ob_itfm);
+ isect->t = bvh_instance_motion_push(
+ kg, object, ray, &P, &dir, &idir, isect->t, &ob_itfm);
# else
- isect->t = bvh_instance_push(kg, object, ray, &P, &dir, &idir, isect->t);
+ isect->t = bvh_instance_push(kg, object, ray, &P, &dir, &idir, isect->t);
# endif
- obvh_near_far_idx_calc(idir,
- &near_x, &near_y, &near_z,
- &far_x, &far_y, &far_z);
- tfar = avxf(isect->t);
+ obvh_near_far_idx_calc(idir, &near_x, &near_y, &near_z, &far_x, &far_y, &far_z);
+ tfar = avxf(isect->t);
# if BVH_FEATURE(BVH_HAIR)
- dir4 = avx3f(avxf(dir.x), avxf(dir.y), avxf(dir.z));
+ dir4 = avx3f(avxf(dir.x), avxf(dir.y), avxf(dir.z));
# endif
- idir4 = avx3f(avxf(idir.x), avxf(idir.y), avxf(idir.z));
+ idir4 = avx3f(avxf(idir.x), avxf(idir.y), avxf(idir.z));
# ifdef __KERNEL_AVX2__
- P_idir = P*idir;
- P_idir4 = avx3f(P_idir.x, P_idir.y, P_idir.z);
+ P_idir = P * idir;
+ P_idir4 = avx3f(P_idir.x, P_idir.y, P_idir.z);
# endif
# if BVH_FEATURE(BVH_HAIR) || !defined(__KERNEL_AVX2__)
- org4 = avx3f(avxf(P.x), avxf(P.y), avxf(P.z));
+ org4 = avx3f(avxf(P.x), avxf(P.y), avxf(P.z));
# endif
- ++stack_ptr;
- kernel_assert(stack_ptr < BVH_OSTACK_SIZE);
- traversal_stack[stack_ptr].addr = ENTRYPOINT_SENTINEL;
-
- node_addr = kernel_tex_fetch(__object_node, object);
- }
- else {
- /* Pop. */
- object = OBJECT_NONE;
- node_addr = traversal_stack[stack_ptr].addr;
- --stack_ptr;
- }
- }
- }
-#endif /* FEATURE(BVH_INSTANCING) */
- } while(node_addr != ENTRYPOINT_SENTINEL);
+ ++stack_ptr;
+ kernel_assert(stack_ptr < BVH_OSTACK_SIZE);
+ traversal_stack[stack_ptr].addr = ENTRYPOINT_SENTINEL;
+
+ node_addr = kernel_tex_fetch(__object_node, object);
+ }
+ else {
+ /* Pop. */
+ object = OBJECT_NONE;
+ node_addr = traversal_stack[stack_ptr].addr;
+ --stack_ptr;
+ }
+ }
+ }
+#endif /* FEATURE(BVH_INSTANCING) */
+ } while (node_addr != ENTRYPOINT_SENTINEL);
#if BVH_FEATURE(BVH_INSTANCING)
- if(stack_ptr >= 0) {
- kernel_assert(object != OBJECT_NONE);
+ if (stack_ptr >= 0) {
+ kernel_assert(object != OBJECT_NONE);
- /* Instance pop. */
+ /* Instance pop. */
# if BVH_FEATURE(BVH_MOTION)
- isect->t = bvh_instance_motion_pop(kg, object, ray, &P, &dir, &idir, isect->t, &ob_itfm);
+ isect->t = bvh_instance_motion_pop(kg, object, ray, &P, &dir, &idir, isect->t, &ob_itfm);
# else
- isect->t = bvh_instance_pop(kg, object, ray, &P, &dir, &idir, isect->t);
+ isect->t = bvh_instance_pop(kg, object, ray, &P, &dir, &idir, isect->t);
# endif
- obvh_near_far_idx_calc(idir,
- &near_x, &near_y, &near_z,
- &far_x, &far_y, &far_z);
- tfar = avxf(isect->t);
+ obvh_near_far_idx_calc(idir, &near_x, &near_y, &near_z, &far_x, &far_y, &far_z);
+ tfar = avxf(isect->t);
# if BVH_FEATURE(BVH_HAIR)
- dir4 = avx3f(avxf(dir.x), avxf(dir.y), avxf(dir.z));
+ dir4 = avx3f(avxf(dir.x), avxf(dir.y), avxf(dir.z));
# endif
- idir4 = avx3f(avxf(idir.x), avxf(idir.y), avxf(idir.z));
+ idir4 = avx3f(avxf(idir.x), avxf(idir.y), avxf(idir.z));
# ifdef __KERNEL_AVX2__
- P_idir = P*idir;
- P_idir4 = avx3f(P_idir.x, P_idir.y, P_idir.z);
+ P_idir = P * idir;
+ P_idir4 = avx3f(P_idir.x, P_idir.y, P_idir.z);
# endif
# if BVH_FEATURE(BVH_HAIR) || !defined(__KERNEL_AVX2__)
- org4 = avx3f(avxf(P.x), avxf(P.y), avxf(P.z));
+ org4 = avx3f(avxf(P.x), avxf(P.y), avxf(P.z));
# endif
- object = OBJECT_NONE;
- node_addr = traversal_stack[stack_ptr].addr;
- --stack_ptr;
- }
-#endif /* FEATURE(BVH_INSTANCING) */
- } while(node_addr != ENTRYPOINT_SENTINEL);
+ object = OBJECT_NONE;
+ node_addr = traversal_stack[stack_ptr].addr;
+ --stack_ptr;
+ }
+#endif /* FEATURE(BVH_INSTANCING) */
+ } while (node_addr != ENTRYPOINT_SENTINEL);
- return (isect->prim != PRIM_NONE);
+ return (isect->prim != PRIM_NONE);
}
#undef NODE_INTERSECT
diff --git a/intern/cycles/kernel/bvh/obvh_volume_all.h b/intern/cycles/kernel/bvh/obvh_volume_all.h
index 5476f79712a..56e2afd4a11 100644
--- a/intern/cycles/kernel/bvh/obvh_volume_all.h
+++ b/intern/cycles/kernel/bvh/obvh_volume_all.h
@@ -34,514 +34,518 @@ ccl_device uint BVH_FUNCTION_FULL_NAME(OBVH)(KernelGlobals *kg,
const uint max_hits,
const uint visibility)
{
- /* Traversal stack in CUDA thread-local memory. */
- OBVHStackItem traversal_stack[BVH_OSTACK_SIZE];
- traversal_stack[0].addr = ENTRYPOINT_SENTINEL;
-
- /* Traversal variables in registers. */
- int stack_ptr = 0;
- int node_addr = kernel_data.bvh.root;
-
- /* Ray parameters in registers. */
- const float tmax = ray->t;
- float3 P = ray->P;
- float3 dir = bvh_clamp_direction(ray->D);
- float3 idir = bvh_inverse_direction(dir);
- int object = OBJECT_NONE;
- float isect_t = tmax;
+ /* Traversal stack in CUDA thread-local memory. */
+ OBVHStackItem traversal_stack[BVH_OSTACK_SIZE];
+ traversal_stack[0].addr = ENTRYPOINT_SENTINEL;
+
+ /* Traversal variables in registers. */
+ int stack_ptr = 0;
+ int node_addr = kernel_data.bvh.root;
+
+ /* Ray parameters in registers. */
+ const float tmax = ray->t;
+ float3 P = ray->P;
+ float3 dir = bvh_clamp_direction(ray->D);
+ float3 idir = bvh_inverse_direction(dir);
+ int object = OBJECT_NONE;
+ float isect_t = tmax;
#if BVH_FEATURE(BVH_MOTION)
- Transform ob_itfm;
+ Transform ob_itfm;
#endif
- uint num_hits = 0;
- isect_array->t = tmax;
+ uint num_hits = 0;
+ isect_array->t = tmax;
#if BVH_FEATURE(BVH_INSTANCING)
- int num_hits_in_instance = 0;
+ int num_hits_in_instance = 0;
#endif
- avxf tnear(0.0f), tfar(isect_t);
+ avxf tnear(0.0f), tfar(isect_t);
#if BVH_FEATURE(BVH_HAIR)
- avx3f dir4(avxf(dir.x), avxf(dir.y), avxf(dir.z));
+ avx3f dir4(avxf(dir.x), avxf(dir.y), avxf(dir.z));
#endif
- avx3f idir4(avxf(idir.x), avxf(idir.y), avxf(idir.z));
+ avx3f idir4(avxf(idir.x), avxf(idir.y), avxf(idir.z));
#ifdef __KERNEL_AVX2__
- float3 P_idir = P*idir;
- avx3f P_idir4(P_idir.x, P_idir.y, P_idir.z);
+ float3 P_idir = P * idir;
+ avx3f P_idir4(P_idir.x, P_idir.y, P_idir.z);
#endif
#if BVH_FEATURE(BVH_HAIR) || !defined(__KERNEL_AVX2__)
- avx3f org4(avxf(P.x), avxf(P.y), avxf(P.z));
+ avx3f org4(avxf(P.x), avxf(P.y), avxf(P.z));
#endif
- /* Offsets to select the side that becomes the lower or upper bound. */
- int near_x, near_y, near_z;
- int far_x, far_y, far_z;
- obvh_near_far_idx_calc(idir,
- &near_x, &near_y, &near_z,
- &far_x, &far_y, &far_z);
+ /* Offsets to select the side that becomes the lower or upper bound. */
+ int near_x, near_y, near_z;
+ int far_x, far_y, far_z;
+ obvh_near_far_idx_calc(idir, &near_x, &near_y, &near_z, &far_x, &far_y, &far_z);
- /* Traversal loop. */
- do {
- do {
- /* Traverse internal nodes. */
- while(node_addr >= 0 && node_addr != ENTRYPOINT_SENTINEL) {
- float4 inodes = kernel_tex_fetch(__bvh_nodes, node_addr+0);
+ /* Traversal loop. */
+ do {
+ do {
+ /* Traverse internal nodes. */
+ while (node_addr >= 0 && node_addr != ENTRYPOINT_SENTINEL) {
+ float4 inodes = kernel_tex_fetch(__bvh_nodes, node_addr + 0);
#ifdef __VISIBILITY_FLAG__
- if((__float_as_uint(inodes.x) & visibility) == 0) {
- /* Pop. */
- node_addr = traversal_stack[stack_ptr].addr;
- --stack_ptr;
- continue;
- }
+ if ((__float_as_uint(inodes.x) & visibility) == 0) {
+ /* Pop. */
+ node_addr = traversal_stack[stack_ptr].addr;
+ --stack_ptr;
+ continue;
+ }
#endif
- avxf dist;
- int child_mask = NODE_INTERSECT(kg,
- tnear,
- tfar,
+ avxf dist;
+ int child_mask = NODE_INTERSECT(kg,
+ tnear,
+ tfar,
#ifdef __KERNEL_AVX2__
- P_idir4,
+ P_idir4,
#endif
#if BVH_FEATURE(BVH_HAIR) || !defined(__KERNEL_AVX2__)
- org4,
+ org4,
#endif
#if BVH_FEATURE(BVH_HAIR)
- dir4,
+ dir4,
#endif
- idir4,
- near_x, near_y, near_z,
- far_x, far_y, far_z,
- node_addr,
- &dist);
-
- if(child_mask != 0) {
- avxf cnodes;
+ idir4,
+ near_x,
+ near_y,
+ near_z,
+ far_x,
+ far_y,
+ far_z,
+ node_addr,
+ &dist);
+
+ if (child_mask != 0) {
+ avxf cnodes;
#if BVH_FEATURE(BVH_HAIR)
- if(__float_as_uint(inodes.x) & PATH_RAY_NODE_UNALIGNED) {
- cnodes = kernel_tex_fetch_avxf(__bvh_nodes, node_addr+26);
- }
- else
+ if (__float_as_uint(inodes.x) & PATH_RAY_NODE_UNALIGNED) {
+ cnodes = kernel_tex_fetch_avxf(__bvh_nodes, node_addr + 26);
+ }
+ else
#endif
- {
- cnodes = kernel_tex_fetch_avxf(__bvh_nodes, node_addr+14);
- }
-
- /* One child is hit, continue with that child. */
- int r = __bscf(child_mask);
- if(child_mask == 0) {
- node_addr = __float_as_int(cnodes[r]);
- continue;
- }
-
- /* Two children are hit, push far child, and continue with
- * closer child.
- */
- int c0 = __float_as_int(cnodes[r]);
- float d0 = ((float*)&dist)[r];
- r = __bscf(child_mask);
- int c1 = __float_as_int(cnodes[r]);
- float d1 = ((float*)&dist)[r];
- if(child_mask == 0) {
- if(d1 < d0) {
- node_addr = c1;
- ++stack_ptr;
- kernel_assert(stack_ptr < BVH_OSTACK_SIZE);
- traversal_stack[stack_ptr].addr = c0;
- traversal_stack[stack_ptr].dist = d0;
- continue;
- }
- else {
- node_addr = c0;
- ++stack_ptr;
- kernel_assert(stack_ptr < BVH_OSTACK_SIZE);
- traversal_stack[stack_ptr].addr = c1;
- traversal_stack[stack_ptr].dist = d1;
- continue;
- }
- }
-
- /* Here starts the slow path for 3 or 4 hit children. We push
- * all nodes onto the stack to sort them there.
- */
- ++stack_ptr;
- kernel_assert(stack_ptr < BVH_OSTACK_SIZE);
- traversal_stack[stack_ptr].addr = c1;
- traversal_stack[stack_ptr].dist = d1;
- ++stack_ptr;
- kernel_assert(stack_ptr < BVH_OSTACK_SIZE);
- traversal_stack[stack_ptr].addr = c0;
- traversal_stack[stack_ptr].dist = d0;
-
- /* Three children are hit, push all onto stack and sort 3
- * stack items, continue with closest child.
- */
- r = __bscf(child_mask);
- int c2 = __float_as_int(cnodes[r]);
- float d2 = ((float*)&dist)[r];
- if(child_mask == 0) {
- ++stack_ptr;
- kernel_assert(stack_ptr < BVH_OSTACK_SIZE);
- traversal_stack[stack_ptr].addr = c2;
- traversal_stack[stack_ptr].dist = d2;
- obvh_stack_sort(&traversal_stack[stack_ptr],
- &traversal_stack[stack_ptr - 1],
- &traversal_stack[stack_ptr - 2]);
- node_addr = traversal_stack[stack_ptr].addr;
- --stack_ptr;
- continue;
- }
-
- /* Four children are hit, push all onto stack and sort 4
- * stack items, continue with closest child.
- */
- r = __bscf(child_mask);
- int c3 = __float_as_int(cnodes[r]);
- float d3 = ((float*)&dist)[r];
- if(child_mask == 0) {
- ++stack_ptr;
- kernel_assert(stack_ptr < BVH_OSTACK_SIZE);
- traversal_stack[stack_ptr].addr = c3;
- traversal_stack[stack_ptr].dist = d3;
- ++stack_ptr;
- kernel_assert(stack_ptr < BVH_OSTACK_SIZE);
- traversal_stack[stack_ptr].addr = c2;
- traversal_stack[stack_ptr].dist = d2;
- obvh_stack_sort(&traversal_stack[stack_ptr],
- &traversal_stack[stack_ptr - 1],
- &traversal_stack[stack_ptr - 2],
- &traversal_stack[stack_ptr - 3]);
- node_addr = traversal_stack[stack_ptr].addr;
- --stack_ptr;
- continue;
- }
-
- ++stack_ptr;
- kernel_assert(stack_ptr < BVH_OSTACK_SIZE);
- traversal_stack[stack_ptr].addr = c3;
- traversal_stack[stack_ptr].dist = d3;
- ++stack_ptr;
- kernel_assert(stack_ptr < BVH_OSTACK_SIZE);
- traversal_stack[stack_ptr].addr = c2;
- traversal_stack[stack_ptr].dist = d2;
-
- /* Five children are hit, push all onto stack and sort 5
- * stack items, continue with closest child.
- */
- r = __bscf(child_mask);
- int c4 = __float_as_int(cnodes[r]);
- float d4 = ((float*)&dist)[r];
- if(child_mask == 0) {
- ++stack_ptr;
- kernel_assert(stack_ptr < BVH_OSTACK_SIZE);
- traversal_stack[stack_ptr].addr = c4;
- traversal_stack[stack_ptr].dist = d4;
- obvh_stack_sort(&traversal_stack[stack_ptr],
- &traversal_stack[stack_ptr - 1],
- &traversal_stack[stack_ptr - 2],
- &traversal_stack[stack_ptr - 3],
- &traversal_stack[stack_ptr - 4]);
- node_addr = traversal_stack[stack_ptr].addr;
- --stack_ptr;
- continue;
- }
-
- /* Six children are hit, push all onto stack and sort 6
- * stack items, continue with closest child.
- */
- r = __bscf(child_mask);
- int c5 = __float_as_int(cnodes[r]);
- float d5 = ((float*)&dist)[r];
- if(child_mask == 0) {
- ++stack_ptr;
- kernel_assert(stack_ptr < BVH_OSTACK_SIZE);
- traversal_stack[stack_ptr].addr = c5;
- traversal_stack[stack_ptr].dist = d5;
- ++stack_ptr;
- kernel_assert(stack_ptr < BVH_OSTACK_SIZE);
- traversal_stack[stack_ptr].addr = c4;
- traversal_stack[stack_ptr].dist = d4;
- obvh_stack_sort(&traversal_stack[stack_ptr],
- &traversal_stack[stack_ptr - 1],
- &traversal_stack[stack_ptr - 2],
- &traversal_stack[stack_ptr - 3],
- &traversal_stack[stack_ptr - 4],
- &traversal_stack[stack_ptr - 5]);
- node_addr = traversal_stack[stack_ptr].addr;
- --stack_ptr;
- continue;
- }
-
- ++stack_ptr;
- kernel_assert(stack_ptr < BVH_OSTACK_SIZE);
- traversal_stack[stack_ptr].addr = c5;
- traversal_stack[stack_ptr].dist = d5;
- ++stack_ptr;
- kernel_assert(stack_ptr < BVH_OSTACK_SIZE);
- traversal_stack[stack_ptr].addr = c4;
- traversal_stack[stack_ptr].dist = d4;
-
- /* Seven children are hit, push all onto stack and sort 7
- * stack items, continue with closest child.
- */
- r = __bscf(child_mask);
- int c6 = __float_as_int(cnodes[r]);
- float d6 = ((float*)&dist)[r];
- if(child_mask == 0) {
- ++stack_ptr;
- kernel_assert(stack_ptr < BVH_OSTACK_SIZE);
- traversal_stack[stack_ptr].addr = c6;
- traversal_stack[stack_ptr].dist = d6;
- obvh_stack_sort(&traversal_stack[stack_ptr],
- &traversal_stack[stack_ptr - 1],
- &traversal_stack[stack_ptr - 2],
- &traversal_stack[stack_ptr - 3],
- &traversal_stack[stack_ptr - 4],
- &traversal_stack[stack_ptr - 5],
- &traversal_stack[stack_ptr - 6]);
- node_addr = traversal_stack[stack_ptr].addr;
- --stack_ptr;
- continue;
- }
-
- /* Eight children are hit, push all onto stack and sort 8
- * stack items, continue with closest child.
- */
- r = __bscf(child_mask);
- int c7 = __float_as_int(cnodes[r]);
- float d7 = ((float*)&dist)[r];
- ++stack_ptr;
- kernel_assert(stack_ptr < BVH_OSTACK_SIZE);
- traversal_stack[stack_ptr].addr = c7;
- traversal_stack[stack_ptr].dist = d7;
- ++stack_ptr;
- kernel_assert(stack_ptr < BVH_OSTACK_SIZE);
- traversal_stack[stack_ptr].addr = c6;
- traversal_stack[stack_ptr].dist = d6;
- obvh_stack_sort(&traversal_stack[stack_ptr],
- &traversal_stack[stack_ptr - 1],
- &traversal_stack[stack_ptr - 2],
- &traversal_stack[stack_ptr - 3],
- &traversal_stack[stack_ptr - 4],
- &traversal_stack[stack_ptr - 5],
- &traversal_stack[stack_ptr - 6],
- &traversal_stack[stack_ptr - 7]);
- node_addr = traversal_stack[stack_ptr].addr;
- --stack_ptr;
- continue;
- }
-
- node_addr = traversal_stack[stack_ptr].addr;
- --stack_ptr;
- }
-
- /* If node is leaf, fetch triangle list. */
- if(node_addr < 0) {
- float4 leaf = kernel_tex_fetch(__bvh_leaf_nodes, (-node_addr-1));
-
- if((__float_as_uint(leaf.z) & visibility) == 0) {
- /* Pop. */
- node_addr = traversal_stack[stack_ptr].addr;
- --stack_ptr;
- continue;
- }
-
- int prim_addr = __float_as_int(leaf.x);
+ {
+ cnodes = kernel_tex_fetch_avxf(__bvh_nodes, node_addr + 14);
+ }
+
+ /* One child is hit, continue with that child. */
+ int r = __bscf(child_mask);
+ if (child_mask == 0) {
+ node_addr = __float_as_int(cnodes[r]);
+ continue;
+ }
+
+ /* Two children are hit, push far child, and continue with
+ * closer child.
+ */
+ int c0 = __float_as_int(cnodes[r]);
+ float d0 = ((float *)&dist)[r];
+ r = __bscf(child_mask);
+ int c1 = __float_as_int(cnodes[r]);
+ float d1 = ((float *)&dist)[r];
+ if (child_mask == 0) {
+ if (d1 < d0) {
+ node_addr = c1;
+ ++stack_ptr;
+ kernel_assert(stack_ptr < BVH_OSTACK_SIZE);
+ traversal_stack[stack_ptr].addr = c0;
+ traversal_stack[stack_ptr].dist = d0;
+ continue;
+ }
+ else {
+ node_addr = c0;
+ ++stack_ptr;
+ kernel_assert(stack_ptr < BVH_OSTACK_SIZE);
+ traversal_stack[stack_ptr].addr = c1;
+ traversal_stack[stack_ptr].dist = d1;
+ continue;
+ }
+ }
+
+ /* Here starts the slow path for 3 or 4 hit children. We push
+ * all nodes onto the stack to sort them there.
+ */
+ ++stack_ptr;
+ kernel_assert(stack_ptr < BVH_OSTACK_SIZE);
+ traversal_stack[stack_ptr].addr = c1;
+ traversal_stack[stack_ptr].dist = d1;
+ ++stack_ptr;
+ kernel_assert(stack_ptr < BVH_OSTACK_SIZE);
+ traversal_stack[stack_ptr].addr = c0;
+ traversal_stack[stack_ptr].dist = d0;
+
+ /* Three children are hit, push all onto stack and sort 3
+ * stack items, continue with closest child.
+ */
+ r = __bscf(child_mask);
+ int c2 = __float_as_int(cnodes[r]);
+ float d2 = ((float *)&dist)[r];
+ if (child_mask == 0) {
+ ++stack_ptr;
+ kernel_assert(stack_ptr < BVH_OSTACK_SIZE);
+ traversal_stack[stack_ptr].addr = c2;
+ traversal_stack[stack_ptr].dist = d2;
+ obvh_stack_sort(&traversal_stack[stack_ptr],
+ &traversal_stack[stack_ptr - 1],
+ &traversal_stack[stack_ptr - 2]);
+ node_addr = traversal_stack[stack_ptr].addr;
+ --stack_ptr;
+ continue;
+ }
+
+ /* Four children are hit, push all onto stack and sort 4
+ * stack items, continue with closest child.
+ */
+ r = __bscf(child_mask);
+ int c3 = __float_as_int(cnodes[r]);
+ float d3 = ((float *)&dist)[r];
+ if (child_mask == 0) {
+ ++stack_ptr;
+ kernel_assert(stack_ptr < BVH_OSTACK_SIZE);
+ traversal_stack[stack_ptr].addr = c3;
+ traversal_stack[stack_ptr].dist = d3;
+ ++stack_ptr;
+ kernel_assert(stack_ptr < BVH_OSTACK_SIZE);
+ traversal_stack[stack_ptr].addr = c2;
+ traversal_stack[stack_ptr].dist = d2;
+ obvh_stack_sort(&traversal_stack[stack_ptr],
+ &traversal_stack[stack_ptr - 1],
+ &traversal_stack[stack_ptr - 2],
+ &traversal_stack[stack_ptr - 3]);
+ node_addr = traversal_stack[stack_ptr].addr;
+ --stack_ptr;
+ continue;
+ }
+
+ ++stack_ptr;
+ kernel_assert(stack_ptr < BVH_OSTACK_SIZE);
+ traversal_stack[stack_ptr].addr = c3;
+ traversal_stack[stack_ptr].dist = d3;
+ ++stack_ptr;
+ kernel_assert(stack_ptr < BVH_OSTACK_SIZE);
+ traversal_stack[stack_ptr].addr = c2;
+ traversal_stack[stack_ptr].dist = d2;
+
+ /* Five children are hit, push all onto stack and sort 5
+ * stack items, continue with closest child.
+ */
+ r = __bscf(child_mask);
+ int c4 = __float_as_int(cnodes[r]);
+ float d4 = ((float *)&dist)[r];
+ if (child_mask == 0) {
+ ++stack_ptr;
+ kernel_assert(stack_ptr < BVH_OSTACK_SIZE);
+ traversal_stack[stack_ptr].addr = c4;
+ traversal_stack[stack_ptr].dist = d4;
+ obvh_stack_sort(&traversal_stack[stack_ptr],
+ &traversal_stack[stack_ptr - 1],
+ &traversal_stack[stack_ptr - 2],
+ &traversal_stack[stack_ptr - 3],
+ &traversal_stack[stack_ptr - 4]);
+ node_addr = traversal_stack[stack_ptr].addr;
+ --stack_ptr;
+ continue;
+ }
+
+ /* Six children are hit, push all onto stack and sort 6
+ * stack items, continue with closest child.
+ */
+ r = __bscf(child_mask);
+ int c5 = __float_as_int(cnodes[r]);
+ float d5 = ((float *)&dist)[r];
+ if (child_mask == 0) {
+ ++stack_ptr;
+ kernel_assert(stack_ptr < BVH_OSTACK_SIZE);
+ traversal_stack[stack_ptr].addr = c5;
+ traversal_stack[stack_ptr].dist = d5;
+ ++stack_ptr;
+ kernel_assert(stack_ptr < BVH_OSTACK_SIZE);
+ traversal_stack[stack_ptr].addr = c4;
+ traversal_stack[stack_ptr].dist = d4;
+ obvh_stack_sort(&traversal_stack[stack_ptr],
+ &traversal_stack[stack_ptr - 1],
+ &traversal_stack[stack_ptr - 2],
+ &traversal_stack[stack_ptr - 3],
+ &traversal_stack[stack_ptr - 4],
+ &traversal_stack[stack_ptr - 5]);
+ node_addr = traversal_stack[stack_ptr].addr;
+ --stack_ptr;
+ continue;
+ }
+
+ ++stack_ptr;
+ kernel_assert(stack_ptr < BVH_OSTACK_SIZE);
+ traversal_stack[stack_ptr].addr = c5;
+ traversal_stack[stack_ptr].dist = d5;
+ ++stack_ptr;
+ kernel_assert(stack_ptr < BVH_OSTACK_SIZE);
+ traversal_stack[stack_ptr].addr = c4;
+ traversal_stack[stack_ptr].dist = d4;
+
+ /* Seven children are hit, push all onto stack and sort 7
+ * stack items, continue with closest child.
+ */
+ r = __bscf(child_mask);
+ int c6 = __float_as_int(cnodes[r]);
+ float d6 = ((float *)&dist)[r];
+ if (child_mask == 0) {
+ ++stack_ptr;
+ kernel_assert(stack_ptr < BVH_OSTACK_SIZE);
+ traversal_stack[stack_ptr].addr = c6;
+ traversal_stack[stack_ptr].dist = d6;
+ obvh_stack_sort(&traversal_stack[stack_ptr],
+ &traversal_stack[stack_ptr - 1],
+ &traversal_stack[stack_ptr - 2],
+ &traversal_stack[stack_ptr - 3],
+ &traversal_stack[stack_ptr - 4],
+ &traversal_stack[stack_ptr - 5],
+ &traversal_stack[stack_ptr - 6]);
+ node_addr = traversal_stack[stack_ptr].addr;
+ --stack_ptr;
+ continue;
+ }
+
+ /* Eight children are hit, push all onto stack and sort 8
+ * stack items, continue with closest child.
+ */
+ r = __bscf(child_mask);
+ int c7 = __float_as_int(cnodes[r]);
+ float d7 = ((float *)&dist)[r];
+ ++stack_ptr;
+ kernel_assert(stack_ptr < BVH_OSTACK_SIZE);
+ traversal_stack[stack_ptr].addr = c7;
+ traversal_stack[stack_ptr].dist = d7;
+ ++stack_ptr;
+ kernel_assert(stack_ptr < BVH_OSTACK_SIZE);
+ traversal_stack[stack_ptr].addr = c6;
+ traversal_stack[stack_ptr].dist = d6;
+ obvh_stack_sort(&traversal_stack[stack_ptr],
+ &traversal_stack[stack_ptr - 1],
+ &traversal_stack[stack_ptr - 2],
+ &traversal_stack[stack_ptr - 3],
+ &traversal_stack[stack_ptr - 4],
+ &traversal_stack[stack_ptr - 5],
+ &traversal_stack[stack_ptr - 6],
+ &traversal_stack[stack_ptr - 7]);
+ node_addr = traversal_stack[stack_ptr].addr;
+ --stack_ptr;
+ continue;
+ }
+
+ node_addr = traversal_stack[stack_ptr].addr;
+ --stack_ptr;
+ }
+
+ /* If node is leaf, fetch triangle list. */
+ if (node_addr < 0) {
+ float4 leaf = kernel_tex_fetch(__bvh_leaf_nodes, (-node_addr - 1));
+
+ if ((__float_as_uint(leaf.z) & visibility) == 0) {
+ /* Pop. */
+ node_addr = traversal_stack[stack_ptr].addr;
+ --stack_ptr;
+ continue;
+ }
+
+ int prim_addr = __float_as_int(leaf.x);
#if BVH_FEATURE(BVH_INSTANCING)
- if(prim_addr >= 0) {
+ if (prim_addr >= 0) {
#endif
- int prim_addr2 = __float_as_int(leaf.y);
- const uint type = __float_as_int(leaf.w);
- const uint p_type = type & PRIMITIVE_ALL;
- bool hit;
-
- /* Pop. */
- node_addr = traversal_stack[stack_ptr].addr;
- --stack_ptr;
-
- /* Primitive intersection. */
- switch(p_type) {
- case PRIMITIVE_TRIANGLE: {
- for(; prim_addr < prim_addr2; prim_addr++) {
- kernel_assert(kernel_tex_fetch(__prim_type, prim_addr) == type);
- /* Only primitives from volume object. */
- uint tri_object = (object == OBJECT_NONE)? kernel_tex_fetch(__prim_object, prim_addr): object;
- int object_flag = kernel_tex_fetch(__object_flag, tri_object);
- if((object_flag & SD_OBJECT_HAS_VOLUME) == 0) {
- continue;
- }
- /* Intersect ray against primitive. */
- hit = triangle_intersect(kg, isect_array, P, dir, visibility, object, prim_addr);
- if(hit) {
- /* Move on to next entry in intersections array. */
- isect_array++;
- num_hits++;
+ int prim_addr2 = __float_as_int(leaf.y);
+ const uint type = __float_as_int(leaf.w);
+ const uint p_type = type & PRIMITIVE_ALL;
+ bool hit;
+
+ /* Pop. */
+ node_addr = traversal_stack[stack_ptr].addr;
+ --stack_ptr;
+
+ /* Primitive intersection. */
+ switch (p_type) {
+ case PRIMITIVE_TRIANGLE: {
+ for (; prim_addr < prim_addr2; prim_addr++) {
+ kernel_assert(kernel_tex_fetch(__prim_type, prim_addr) == type);
+ /* Only primitives from volume object. */
+ uint tri_object = (object == OBJECT_NONE) ?
+ kernel_tex_fetch(__prim_object, prim_addr) :
+ object;
+ int object_flag = kernel_tex_fetch(__object_flag, tri_object);
+ if ((object_flag & SD_OBJECT_HAS_VOLUME) == 0) {
+ continue;
+ }
+ /* Intersect ray against primitive. */
+ hit = triangle_intersect(kg, isect_array, P, dir, visibility, object, prim_addr);
+ if (hit) {
+ /* Move on to next entry in intersections array. */
+ isect_array++;
+ num_hits++;
#if BVH_FEATURE(BVH_INSTANCING)
- num_hits_in_instance++;
+ num_hits_in_instance++;
#endif
- isect_array->t = isect_t;
- if(num_hits == max_hits) {
+ isect_array->t = isect_t;
+ if (num_hits == max_hits) {
#if BVH_FEATURE(BVH_INSTANCING)
# if BVH_FEATURE(BVH_MOTION)
- float t_fac = 1.0f / len(transform_direction(&ob_itfm, dir));
+ float t_fac = 1.0f / len(transform_direction(&ob_itfm, dir));
# else
- Transform itfm = object_fetch_transform(kg, object, OBJECT_INVERSE_TRANSFORM);
- float t_fac = 1.0f / len(transform_direction(&itfm, dir));
+ Transform itfm = object_fetch_transform(kg, object, OBJECT_INVERSE_TRANSFORM);
+ float t_fac = 1.0f / len(transform_direction(&itfm, dir));
# endif
- for(int i = 0; i < num_hits_in_instance; i++) {
- (isect_array-i-1)->t *= t_fac;
- }
-#endif /* BVH_FEATURE(BVH_INSTANCING) */
- return num_hits;
- }
- }
- }
- break;
- }
+ for (int i = 0; i < num_hits_in_instance; i++) {
+ (isect_array - i - 1)->t *= t_fac;
+ }
+#endif /* BVH_FEATURE(BVH_INSTANCING) */
+ return num_hits;
+ }
+ }
+ }
+ break;
+ }
#if BVH_FEATURE(BVH_MOTION)
- case PRIMITIVE_MOTION_TRIANGLE: {
- for(; prim_addr < prim_addr2; prim_addr++) {
- kernel_assert(kernel_tex_fetch(__prim_type, prim_addr) == type);
- /* Only primitives from volume object. */
- uint tri_object = (object == OBJECT_NONE)? kernel_tex_fetch(__prim_object, prim_addr): object;
- int object_flag = kernel_tex_fetch(__object_flag, tri_object);
- if((object_flag & SD_OBJECT_HAS_VOLUME) == 0) {
- continue;
- }
- /* Intersect ray against primitive. */
- hit = motion_triangle_intersect(kg, isect_array, P, dir, ray->time, visibility, object, prim_addr);
- if(hit) {
- /* Move on to next entry in intersections array. */
- isect_array++;
- num_hits++;
+ case PRIMITIVE_MOTION_TRIANGLE: {
+ for (; prim_addr < prim_addr2; prim_addr++) {
+ kernel_assert(kernel_tex_fetch(__prim_type, prim_addr) == type);
+ /* Only primitives from volume object. */
+ uint tri_object = (object == OBJECT_NONE) ?
+ kernel_tex_fetch(__prim_object, prim_addr) :
+ object;
+ int object_flag = kernel_tex_fetch(__object_flag, tri_object);
+ if ((object_flag & SD_OBJECT_HAS_VOLUME) == 0) {
+ continue;
+ }
+ /* Intersect ray against primitive. */
+ hit = motion_triangle_intersect(
+ kg, isect_array, P, dir, ray->time, visibility, object, prim_addr);
+ if (hit) {
+ /* Move on to next entry in intersections array. */
+ isect_array++;
+ num_hits++;
# if BVH_FEATURE(BVH_INSTANCING)
- num_hits_in_instance++;
+ num_hits_in_instance++;
# endif
- isect_array->t = isect_t;
- if(num_hits == max_hits) {
+ isect_array->t = isect_t;
+ if (num_hits == max_hits) {
# if BVH_FEATURE(BVH_INSTANCING)
# if BVH_FEATURE(BVH_MOTION)
- float t_fac = 1.0f / len(transform_direction(&ob_itfm, dir));
+ float t_fac = 1.0f / len(transform_direction(&ob_itfm, dir));
# else
- Transform itfm = object_fetch_transform(kg, object, OBJECT_INVERSE_TRANSFORM);
- float t_fac = 1.0f / len(transform_direction(&itfm, dir));
+ Transform itfm = object_fetch_transform(kg, object, OBJECT_INVERSE_TRANSFORM);
+ float t_fac = 1.0f / len(transform_direction(&itfm, dir));
# endif
- for(int i = 0; i < num_hits_in_instance; i++) {
- (isect_array-i-1)->t *= t_fac;
- }
-# endif /* BVH_FEATURE(BVH_INSTANCING) */
- return num_hits;
- }
- }
- }
- break;
- }
+ for (int i = 0; i < num_hits_in_instance; i++) {
+ (isect_array - i - 1)->t *= t_fac;
+ }
+# endif /* BVH_FEATURE(BVH_INSTANCING) */
+ return num_hits;
+ }
+ }
+ }
+ break;
+ }
#endif
- }
- }
+ }
+ }
#if BVH_FEATURE(BVH_INSTANCING)
- else {
- /* Instance push. */
- object = kernel_tex_fetch(__prim_object, -prim_addr-1);
- int object_flag = kernel_tex_fetch(__object_flag, object);
- if(object_flag & SD_OBJECT_HAS_VOLUME) {
+ else {
+ /* Instance push. */
+ object = kernel_tex_fetch(__prim_object, -prim_addr - 1);
+ int object_flag = kernel_tex_fetch(__object_flag, object);
+ if (object_flag & SD_OBJECT_HAS_VOLUME) {
# if BVH_FEATURE(BVH_MOTION)
- isect_t = bvh_instance_motion_push(kg, object, ray, &P, &dir, &idir, isect_t, &ob_itfm);
+ isect_t = bvh_instance_motion_push(
+ kg, object, ray, &P, &dir, &idir, isect_t, &ob_itfm);
# else
- isect_t = bvh_instance_push(kg, object, ray, &P, &dir, &idir, isect_t);
+ isect_t = bvh_instance_push(kg, object, ray, &P, &dir, &idir, isect_t);
# endif
- obvh_near_far_idx_calc(idir,
- &near_x, &near_y, &near_z,
- &far_x, &far_y, &far_z);
- tfar = avxf(isect_t);
- idir4 = avx3f(avxf(idir.x), avxf(idir.y), avxf(idir.z));
+ obvh_near_far_idx_calc(idir, &near_x, &near_y, &near_z, &far_x, &far_y, &far_z);
+ tfar = avxf(isect_t);
+ idir4 = avx3f(avxf(idir.x), avxf(idir.y), avxf(idir.z));
# if BVH_FEATURE(BVH_HAIR)
- dir4 = avx3f(avxf(dir.x), avxf(dir.y), avxf(dir.z));
+ dir4 = avx3f(avxf(dir.x), avxf(dir.y), avxf(dir.z));
# endif
# ifdef __KERNEL_AVX2__
- P_idir = P*idir;
- P_idir4 = avx3f(P_idir.x, P_idir.y, P_idir.z);
+ P_idir = P * idir;
+ P_idir4 = avx3f(P_idir.x, P_idir.y, P_idir.z);
# endif
# if BVH_FEATURE(BVH_HAIR) || !defined(__KERNEL_AVX2__)
- org4 = avx3f(avxf(P.x), avxf(P.y), avxf(P.z));
+ org4 = avx3f(avxf(P.x), avxf(P.y), avxf(P.z));
# endif
- num_hits_in_instance = 0;
- isect_array->t = isect_t;
-
- ++stack_ptr;
- kernel_assert(stack_ptr < BVH_OSTACK_SIZE);
- traversal_stack[stack_ptr].addr = ENTRYPOINT_SENTINEL;
-
- node_addr = kernel_tex_fetch(__object_node, object);
- }
- else {
- /* Pop. */
- object = OBJECT_NONE;
- node_addr = traversal_stack[stack_ptr].addr;
- --stack_ptr;
- }
- }
- }
-#endif /* FEATURE(BVH_INSTANCING) */
- } while(node_addr != ENTRYPOINT_SENTINEL);
+ num_hits_in_instance = 0;
+ isect_array->t = isect_t;
+
+ ++stack_ptr;
+ kernel_assert(stack_ptr < BVH_OSTACK_SIZE);
+ traversal_stack[stack_ptr].addr = ENTRYPOINT_SENTINEL;
+
+ node_addr = kernel_tex_fetch(__object_node, object);
+ }
+ else {
+ /* Pop. */
+ object = OBJECT_NONE;
+ node_addr = traversal_stack[stack_ptr].addr;
+ --stack_ptr;
+ }
+ }
+ }
+#endif /* FEATURE(BVH_INSTANCING) */
+ } while (node_addr != ENTRYPOINT_SENTINEL);
#if BVH_FEATURE(BVH_INSTANCING)
- if(stack_ptr >= 0) {
- kernel_assert(object != OBJECT_NONE);
+ if (stack_ptr >= 0) {
+ kernel_assert(object != OBJECT_NONE);
- /* Instance pop. */
- if(num_hits_in_instance) {
- float t_fac;
+ /* Instance pop. */
+ if (num_hits_in_instance) {
+ float t_fac;
# if BVH_FEATURE(BVH_MOTION)
- bvh_instance_motion_pop_factor(kg, object, ray, &P, &dir, &idir, &t_fac, &ob_itfm);
+ bvh_instance_motion_pop_factor(kg, object, ray, &P, &dir, &idir, &t_fac, &ob_itfm);
# else
- bvh_instance_pop_factor(kg, object, ray, &P, &dir, &idir, &t_fac);
+ bvh_instance_pop_factor(kg, object, ray, &P, &dir, &idir, &t_fac);
# endif
- /* Scale isect->t to adjust for instancing. */
- for(int i = 0; i < num_hits_in_instance; i++) {
- (isect_array-i-1)->t *= t_fac;
- }
- }
- else {
+ /* Scale isect->t to adjust for instancing. */
+ for (int i = 0; i < num_hits_in_instance; i++) {
+ (isect_array - i - 1)->t *= t_fac;
+ }
+ }
+ else {
# if BVH_FEATURE(BVH_MOTION)
- bvh_instance_motion_pop(kg, object, ray, &P, &dir, &idir, FLT_MAX, &ob_itfm);
+ bvh_instance_motion_pop(kg, object, ray, &P, &dir, &idir, FLT_MAX, &ob_itfm);
# else
- bvh_instance_pop(kg, object, ray, &P, &dir, &idir, FLT_MAX);
+ bvh_instance_pop(kg, object, ray, &P, &dir, &idir, FLT_MAX);
# endif
- }
+ }
- isect_t = tmax;
- isect_array->t = isect_t;
+ isect_t = tmax;
+ isect_array->t = isect_t;
- obvh_near_far_idx_calc(idir,
- &near_x, &near_y, &near_z,
- &far_x, &far_y, &far_z);
- tfar = avxf(isect_t);
+ obvh_near_far_idx_calc(idir, &near_x, &near_y, &near_z, &far_x, &far_y, &far_z);
+ tfar = avxf(isect_t);
# if BVH_FEATURE(BVH_HAIR)
- dir4 = avx3f(avxf(dir.x), avxf(dir.y), avxf(dir.z));
+ dir4 = avx3f(avxf(dir.x), avxf(dir.y), avxf(dir.z));
# endif
- idir4 = avx3f(avxf(idir.x), avxf(idir.y), avxf(idir.z));
+ idir4 = avx3f(avxf(idir.x), avxf(idir.y), avxf(idir.z));
# ifdef __KERNEL_AVX2__
- P_idir = P*idir;
- P_idir4 = avx3f(P_idir.x, P_idir.y, P_idir.z);
+ P_idir = P * idir;
+ P_idir4 = avx3f(P_idir.x, P_idir.y, P_idir.z);
# endif
# if BVH_FEATURE(BVH_HAIR) || !defined(__KERNEL_AVX2__)
- org4 = avx3f(avxf(P.x), avxf(P.y), avxf(P.z));
+ org4 = avx3f(avxf(P.x), avxf(P.y), avxf(P.z));
# endif
- object = OBJECT_NONE;
- node_addr = traversal_stack[stack_ptr].addr;
- --stack_ptr;
- }
-#endif /* FEATURE(BVH_INSTANCING) */
- } while(node_addr != ENTRYPOINT_SENTINEL);
+ object = OBJECT_NONE;
+ node_addr = traversal_stack[stack_ptr].addr;
+ --stack_ptr;
+ }
+#endif /* FEATURE(BVH_INSTANCING) */
+ } while (node_addr != ENTRYPOINT_SENTINEL);
- return num_hits;
+ return num_hits;
}
#undef NODE_INTERSECT
diff --git a/intern/cycles/kernel/bvh/qbvh_local.h b/intern/cycles/kernel/bvh/qbvh_local.h
index 661182e31b3..b21f79bd3a0 100644
--- a/intern/cycles/kernel/bvh/qbvh_local.h
+++ b/intern/cycles/kernel/bvh/qbvh_local.h
@@ -35,262 +35,257 @@ ccl_device bool BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg,
uint *lcg_state,
int max_hits)
{
- /* TODO(sergey):
- * - Test if pushing distance on the stack helps (for non shadow rays).
- * - Separate version for shadow rays.
- * - Likely and unlikely for if() statements.
- * - SSE for hair.
- * - Test restrict attribute for pointers.
- */
+ /* TODO(sergey):
+ * - Test if pushing distance on the stack helps (for non shadow rays).
+ * - Separate version for shadow rays.
+ * - Likely and unlikely for if() statements.
+ * - SSE for hair.
+ * - Test restrict attribute for pointers.
+ */
- /* Traversal stack in CUDA thread-local memory. */
- QBVHStackItem traversal_stack[BVH_QSTACK_SIZE];
- traversal_stack[0].addr = ENTRYPOINT_SENTINEL;
+ /* Traversal stack in CUDA thread-local memory. */
+ QBVHStackItem traversal_stack[BVH_QSTACK_SIZE];
+ traversal_stack[0].addr = ENTRYPOINT_SENTINEL;
- /* Traversal variables in registers. */
- int stack_ptr = 0;
- int node_addr = kernel_tex_fetch(__object_node, local_object);
+ /* Traversal variables in registers. */
+ int stack_ptr = 0;
+ int node_addr = kernel_tex_fetch(__object_node, local_object);
- /* Ray parameters in registers. */
- float3 P = ray->P;
- float3 dir = bvh_clamp_direction(ray->D);
- float3 idir = bvh_inverse_direction(dir);
- int object = OBJECT_NONE;
- float isect_t = ray->t;
+ /* Ray parameters in registers. */
+ float3 P = ray->P;
+ float3 dir = bvh_clamp_direction(ray->D);
+ float3 idir = bvh_inverse_direction(dir);
+ int object = OBJECT_NONE;
+ float isect_t = ray->t;
- if(local_isect != NULL) {
- local_isect->num_hits = 0;
- }
- kernel_assert((local_isect == NULL) == (max_hits == 0));
+ if (local_isect != NULL) {
+ local_isect->num_hits = 0;
+ }
+ kernel_assert((local_isect == NULL) == (max_hits == 0));
- const int object_flag = kernel_tex_fetch(__object_flag, local_object);
- if(!(object_flag & SD_OBJECT_TRANSFORM_APPLIED)) {
+ const int object_flag = kernel_tex_fetch(__object_flag, local_object);
+ if (!(object_flag & SD_OBJECT_TRANSFORM_APPLIED)) {
#if BVH_FEATURE(BVH_MOTION)
- Transform ob_itfm;
- isect_t = bvh_instance_motion_push(kg,
- local_object,
- ray,
- &P,
- &dir,
- &idir,
- isect_t,
- &ob_itfm);
+ Transform ob_itfm;
+ isect_t = bvh_instance_motion_push(kg, local_object, ray, &P, &dir, &idir, isect_t, &ob_itfm);
#else
- isect_t = bvh_instance_push(kg, local_object, ray, &P, &dir, &idir, isect_t);
+ isect_t = bvh_instance_push(kg, local_object, ray, &P, &dir, &idir, isect_t);
#endif
- object = local_object;
- }
+ object = local_object;
+ }
- ssef tnear(0.0f), tfar(isect_t);
+ ssef tnear(0.0f), tfar(isect_t);
#if BVH_FEATURE(BVH_HAIR)
- sse3f dir4(ssef(dir.x), ssef(dir.y), ssef(dir.z));
+ sse3f dir4(ssef(dir.x), ssef(dir.y), ssef(dir.z));
#endif
- sse3f idir4(ssef(idir.x), ssef(idir.y), ssef(idir.z));
+ sse3f idir4(ssef(idir.x), ssef(idir.y), ssef(idir.z));
#ifdef __KERNEL_AVX2__
- float3 P_idir = P*idir;
- sse3f P_idir4(P_idir.x, P_idir.y, P_idir.z);
+ float3 P_idir = P * idir;
+ sse3f P_idir4(P_idir.x, P_idir.y, P_idir.z);
#endif
#if BVH_FEATURE(BVH_HAIR) || !defined(__KERNEL_AVX2__)
- sse3f org4(ssef(P.x), ssef(P.y), ssef(P.z));
+ sse3f org4(ssef(P.x), ssef(P.y), ssef(P.z));
#endif
- /* Offsets to select the side that becomes the lower or upper bound. */
- int near_x, near_y, near_z;
- int far_x, far_y, far_z;
- qbvh_near_far_idx_calc(idir,
- &near_x, &near_y, &near_z,
- &far_x, &far_y, &far_z);
+ /* Offsets to select the side that becomes the lower or upper bound. */
+ int near_x, near_y, near_z;
+ int far_x, far_y, far_z;
+ qbvh_near_far_idx_calc(idir, &near_x, &near_y, &near_z, &far_x, &far_y, &far_z);
- /* Traversal loop. */
- do {
- do {
- /* Traverse internal nodes. */
- while(node_addr >= 0 && node_addr != ENTRYPOINT_SENTINEL) {
- ssef dist;
- int child_mask = NODE_INTERSECT(kg,
- tnear,
- tfar,
+ /* Traversal loop. */
+ do {
+ do {
+ /* Traverse internal nodes. */
+ while (node_addr >= 0 && node_addr != ENTRYPOINT_SENTINEL) {
+ ssef dist;
+ int child_mask = NODE_INTERSECT(kg,
+ tnear,
+ tfar,
#ifdef __KERNEL_AVX2__
- P_idir4,
+ P_idir4,
#endif
#if BVH_FEATURE(BVH_HAIR) || !defined(__KERNEL_AVX2__)
- org4,
+ org4,
#endif
#if BVH_FEATURE(BVH_HAIR)
- dir4,
+ dir4,
#endif
- idir4,
- near_x, near_y, near_z,
- far_x, far_y, far_z,
- node_addr,
- &dist);
+ idir4,
+ near_x,
+ near_y,
+ near_z,
+ far_x,
+ far_y,
+ far_z,
+ node_addr,
+ &dist);
- if(child_mask != 0) {
- float4 inodes = kernel_tex_fetch(__bvh_nodes, node_addr+0);
- float4 cnodes;
+ if (child_mask != 0) {
+ float4 inodes = kernel_tex_fetch(__bvh_nodes, node_addr + 0);
+ float4 cnodes;
#if BVH_FEATURE(BVH_HAIR)
- if(__float_as_uint(inodes.x) & PATH_RAY_NODE_UNALIGNED) {
- cnodes = kernel_tex_fetch(__bvh_nodes, node_addr+13);
- }
- else
+ if (__float_as_uint(inodes.x) & PATH_RAY_NODE_UNALIGNED) {
+ cnodes = kernel_tex_fetch(__bvh_nodes, node_addr + 13);
+ }
+ else
#endif
- {
- cnodes = kernel_tex_fetch(__bvh_nodes, node_addr+7);
- }
+ {
+ cnodes = kernel_tex_fetch(__bvh_nodes, node_addr + 7);
+ }
- /* One child is hit, continue with that child. */
- int r = __bscf(child_mask);
- if(child_mask == 0) {
- node_addr = __float_as_int(cnodes[r]);
- continue;
- }
+ /* One child is hit, continue with that child. */
+ int r = __bscf(child_mask);
+ if (child_mask == 0) {
+ node_addr = __float_as_int(cnodes[r]);
+ continue;
+ }
- /* Two children are hit, push far child, and continue with
- * closer child.
- */
- int c0 = __float_as_int(cnodes[r]);
- float d0 = ((float*)&dist)[r];
- r = __bscf(child_mask);
- int c1 = __float_as_int(cnodes[r]);
- float d1 = ((float*)&dist)[r];
- if(child_mask == 0) {
- if(d1 < d0) {
- node_addr = c1;
- ++stack_ptr;
- kernel_assert(stack_ptr < BVH_QSTACK_SIZE);
- traversal_stack[stack_ptr].addr = c0;
- traversal_stack[stack_ptr].dist = d0;
- continue;
- }
- else {
- node_addr = c0;
- ++stack_ptr;
- kernel_assert(stack_ptr < BVH_QSTACK_SIZE);
- traversal_stack[stack_ptr].addr = c1;
- traversal_stack[stack_ptr].dist = d1;
- continue;
- }
- }
+ /* Two children are hit, push far child, and continue with
+ * closer child.
+ */
+ int c0 = __float_as_int(cnodes[r]);
+ float d0 = ((float *)&dist)[r];
+ r = __bscf(child_mask);
+ int c1 = __float_as_int(cnodes[r]);
+ float d1 = ((float *)&dist)[r];
+ if (child_mask == 0) {
+ if (d1 < d0) {
+ node_addr = c1;
+ ++stack_ptr;
+ kernel_assert(stack_ptr < BVH_QSTACK_SIZE);
+ traversal_stack[stack_ptr].addr = c0;
+ traversal_stack[stack_ptr].dist = d0;
+ continue;
+ }
+ else {
+ node_addr = c0;
+ ++stack_ptr;
+ kernel_assert(stack_ptr < BVH_QSTACK_SIZE);
+ traversal_stack[stack_ptr].addr = c1;
+ traversal_stack[stack_ptr].dist = d1;
+ continue;
+ }
+ }
- /* Here starts the slow path for 3 or 4 hit children. We push
- * all nodes onto the stack to sort them there.
- */
- ++stack_ptr;
- kernel_assert(stack_ptr < BVH_QSTACK_SIZE);
- traversal_stack[stack_ptr].addr = c1;
- traversal_stack[stack_ptr].dist = d1;
- ++stack_ptr;
- kernel_assert(stack_ptr < BVH_QSTACK_SIZE);
- traversal_stack[stack_ptr].addr = c0;
- traversal_stack[stack_ptr].dist = d0;
+ /* Here starts the slow path for 3 or 4 hit children. We push
+ * all nodes onto the stack to sort them there.
+ */
+ ++stack_ptr;
+ kernel_assert(stack_ptr < BVH_QSTACK_SIZE);
+ traversal_stack[stack_ptr].addr = c1;
+ traversal_stack[stack_ptr].dist = d1;
+ ++stack_ptr;
+ kernel_assert(stack_ptr < BVH_QSTACK_SIZE);
+ traversal_stack[stack_ptr].addr = c0;
+ traversal_stack[stack_ptr].dist = d0;
- /* Three children are hit, push all onto stack and sort 3
- * stack items, continue with closest child.
- */
- r = __bscf(child_mask);
- int c2 = __float_as_int(cnodes[r]);
- float d2 = ((float*)&dist)[r];
- if(child_mask == 0) {
- ++stack_ptr;
- kernel_assert(stack_ptr < BVH_QSTACK_SIZE);
- traversal_stack[stack_ptr].addr = c2;
- traversal_stack[stack_ptr].dist = d2;
- qbvh_stack_sort(&traversal_stack[stack_ptr],
- &traversal_stack[stack_ptr - 1],
- &traversal_stack[stack_ptr - 2]);
- node_addr = traversal_stack[stack_ptr].addr;
- --stack_ptr;
- continue;
- }
+ /* Three children are hit, push all onto stack and sort 3
+ * stack items, continue with closest child.
+ */
+ r = __bscf(child_mask);
+ int c2 = __float_as_int(cnodes[r]);
+ float d2 = ((float *)&dist)[r];
+ if (child_mask == 0) {
+ ++stack_ptr;
+ kernel_assert(stack_ptr < BVH_QSTACK_SIZE);
+ traversal_stack[stack_ptr].addr = c2;
+ traversal_stack[stack_ptr].dist = d2;
+ qbvh_stack_sort(&traversal_stack[stack_ptr],
+ &traversal_stack[stack_ptr - 1],
+ &traversal_stack[stack_ptr - 2]);
+ node_addr = traversal_stack[stack_ptr].addr;
+ --stack_ptr;
+ continue;
+ }
- /* Four children are hit, push all onto stack and sort 4
- * stack items, continue with closest child.
- */
- r = __bscf(child_mask);
- int c3 = __float_as_int(cnodes[r]);
- float d3 = ((float*)&dist)[r];
- ++stack_ptr;
- kernel_assert(stack_ptr < BVH_QSTACK_SIZE);
- traversal_stack[stack_ptr].addr = c3;
- traversal_stack[stack_ptr].dist = d3;
- ++stack_ptr;
- kernel_assert(stack_ptr < BVH_QSTACK_SIZE);
- traversal_stack[stack_ptr].addr = c2;
- traversal_stack[stack_ptr].dist = d2;
- qbvh_stack_sort(&traversal_stack[stack_ptr],
- &traversal_stack[stack_ptr - 1],
- &traversal_stack[stack_ptr - 2],
- &traversal_stack[stack_ptr - 3]);
- }
+ /* Four children are hit, push all onto stack and sort 4
+ * stack items, continue with closest child.
+ */
+ r = __bscf(child_mask);
+ int c3 = __float_as_int(cnodes[r]);
+ float d3 = ((float *)&dist)[r];
+ ++stack_ptr;
+ kernel_assert(stack_ptr < BVH_QSTACK_SIZE);
+ traversal_stack[stack_ptr].addr = c3;
+ traversal_stack[stack_ptr].dist = d3;
+ ++stack_ptr;
+ kernel_assert(stack_ptr < BVH_QSTACK_SIZE);
+ traversal_stack[stack_ptr].addr = c2;
+ traversal_stack[stack_ptr].dist = d2;
+ qbvh_stack_sort(&traversal_stack[stack_ptr],
+ &traversal_stack[stack_ptr - 1],
+ &traversal_stack[stack_ptr - 2],
+ &traversal_stack[stack_ptr - 3]);
+ }
- node_addr = traversal_stack[stack_ptr].addr;
- --stack_ptr;
- }
+ node_addr = traversal_stack[stack_ptr].addr;
+ --stack_ptr;
+ }
- /* If node is leaf, fetch triangle list. */
- if(node_addr < 0) {
- float4 leaf = kernel_tex_fetch(__bvh_leaf_nodes, (-node_addr-1));
- int prim_addr = __float_as_int(leaf.x);
+ /* If node is leaf, fetch triangle list. */
+ if (node_addr < 0) {
+ float4 leaf = kernel_tex_fetch(__bvh_leaf_nodes, (-node_addr - 1));
+ int prim_addr = __float_as_int(leaf.x);
- int prim_addr2 = __float_as_int(leaf.y);
- const uint type = __float_as_int(leaf.w);
+ int prim_addr2 = __float_as_int(leaf.y);
+ const uint type = __float_as_int(leaf.w);
- /* Pop. */
- node_addr = traversal_stack[stack_ptr].addr;
- --stack_ptr;
+ /* Pop. */
+ node_addr = traversal_stack[stack_ptr].addr;
+ --stack_ptr;
- /* Primitive intersection. */
- switch(type & PRIMITIVE_ALL) {
- case PRIMITIVE_TRIANGLE: {
- /* Intersect ray against primitive, */
- for(; prim_addr < prim_addr2; prim_addr++) {
- kernel_assert(kernel_tex_fetch(__prim_type, prim_addr) == type);
- if(triangle_intersect_local(kg,
- local_isect,
- P,
- dir,
- object,
- local_object,
- prim_addr,
- isect_t,
- lcg_state,
- max_hits)) {
- return true;
- }
- }
- break;
- }
+ /* Primitive intersection. */
+ switch (type & PRIMITIVE_ALL) {
+ case PRIMITIVE_TRIANGLE: {
+ /* Intersect ray against primitive, */
+ for (; prim_addr < prim_addr2; prim_addr++) {
+ kernel_assert(kernel_tex_fetch(__prim_type, prim_addr) == type);
+ if (triangle_intersect_local(kg,
+ local_isect,
+ P,
+ dir,
+ object,
+ local_object,
+ prim_addr,
+ isect_t,
+ lcg_state,
+ max_hits)) {
+ return true;
+ }
+ }
+ break;
+ }
#if BVH_FEATURE(BVH_MOTION)
- case PRIMITIVE_MOTION_TRIANGLE: {
- /* Intersect ray against primitive. */
- for(; prim_addr < prim_addr2; prim_addr++) {
- kernel_assert(kernel_tex_fetch(__prim_type, prim_addr) == type);
- if(motion_triangle_intersect_local(kg,
- local_isect,
- P,
- dir,
- ray->time,
- object,
- local_object,
- prim_addr,
- isect_t,
- lcg_state,
- max_hits)) {
- return true;
- }
- }
- break;
- }
+ case PRIMITIVE_MOTION_TRIANGLE: {
+ /* Intersect ray against primitive. */
+ for (; prim_addr < prim_addr2; prim_addr++) {
+ kernel_assert(kernel_tex_fetch(__prim_type, prim_addr) == type);
+ if (motion_triangle_intersect_local(kg,
+ local_isect,
+ P,
+ dir,
+ ray->time,
+ object,
+ local_object,
+ prim_addr,
+ isect_t,
+ lcg_state,
+ max_hits)) {
+ return true;
+ }
+ }
+ break;
+ }
#endif
- default:
- break;
- }
- }
- } while(node_addr != ENTRYPOINT_SENTINEL);
- } while(node_addr != ENTRYPOINT_SENTINEL);
+ default:
+ break;
+ }
+ }
+ } while (node_addr != ENTRYPOINT_SENTINEL);
+ } while (node_addr != ENTRYPOINT_SENTINEL);
- return false;
+ return false;
}
#undef NODE_INTERSECT
diff --git a/intern/cycles/kernel/bvh/qbvh_nodes.h b/intern/cycles/kernel/bvh/qbvh_nodes.h
index 2e622af1758..7c1d8c8c72e 100644
--- a/intern/cycles/kernel/bvh/qbvh_nodes.h
+++ b/intern/cycles/kernel/bvh/qbvh_nodes.h
@@ -17,11 +17,11 @@
*/
struct QBVHStackItem {
- int addr;
- float dist;
+ int addr;
+ float dist;
};
-ccl_device_inline void qbvh_near_far_idx_calc(const float3& idir,
+ccl_device_inline void qbvh_near_far_idx_calc(const float3 &idir,
int *ccl_restrict near_x,
int *ccl_restrict near_y,
int *ccl_restrict near_z,
@@ -31,44 +31,76 @@ ccl_device_inline void qbvh_near_far_idx_calc(const float3& idir,
{
#ifdef __KERNEL_SSE__
- *near_x = 0; *far_x = 1;
- *near_y = 2; *far_y = 3;
- *near_z = 4; *far_z = 5;
-
- const size_t mask = movemask(ssef(idir.m128));
-
- const int mask_x = mask & 1;
- const int mask_y = (mask & 2) >> 1;
- const int mask_z = (mask & 4) >> 2;
-
- *near_x += mask_x; *far_x -= mask_x;
- *near_y += mask_y; *far_y -= mask_y;
- *near_z += mask_z; *far_z -= mask_z;
+ *near_x = 0;
+ *far_x = 1;
+ *near_y = 2;
+ *far_y = 3;
+ *near_z = 4;
+ *far_z = 5;
+
+ const size_t mask = movemask(ssef(idir.m128));
+
+ const int mask_x = mask & 1;
+ const int mask_y = (mask & 2) >> 1;
+ const int mask_z = (mask & 4) >> 2;
+
+ *near_x += mask_x;
+ *far_x -= mask_x;
+ *near_y += mask_y;
+ *far_y -= mask_y;
+ *near_z += mask_z;
+ *far_z -= mask_z;
#else
- if(idir.x >= 0.0f) { *near_x = 0; *far_x = 1; } else { *near_x = 1; *far_x = 0; }
- if(idir.y >= 0.0f) { *near_y = 2; *far_y = 3; } else { *near_y = 3; *far_y = 2; }
- if(idir.z >= 0.0f) { *near_z = 4; *far_z = 5; } else { *near_z = 5; *far_z = 4; }
+ if (idir.x >= 0.0f) {
+ *near_x = 0;
+ *far_x = 1;
+ }
+ else {
+ *near_x = 1;
+ *far_x = 0;
+ }
+ if (idir.y >= 0.0f) {
+ *near_y = 2;
+ *far_y = 3;
+ }
+ else {
+ *near_y = 3;
+ *far_y = 2;
+ }
+ if (idir.z >= 0.0f) {
+ *near_z = 4;
+ *far_z = 5;
+ }
+ else {
+ *near_z = 5;
+ *far_z = 4;
+ }
#endif
}
/* TOOD(sergey): Investigate if using intrinsics helps for both
* stack item swap and float comparison.
*/
-ccl_device_inline void qbvh_item_swap(QBVHStackItem *ccl_restrict a,
- QBVHStackItem *ccl_restrict b)
+ccl_device_inline void qbvh_item_swap(QBVHStackItem *ccl_restrict a, QBVHStackItem *ccl_restrict b)
{
- QBVHStackItem tmp = *a;
- *a = *b;
- *b = tmp;
+ QBVHStackItem tmp = *a;
+ *a = *b;
+ *b = tmp;
}
ccl_device_inline void qbvh_stack_sort(QBVHStackItem *ccl_restrict s1,
QBVHStackItem *ccl_restrict s2,
QBVHStackItem *ccl_restrict s3)
{
- if(s2->dist < s1->dist) { qbvh_item_swap(s2, s1); }
- if(s3->dist < s2->dist) { qbvh_item_swap(s3, s2); }
- if(s2->dist < s1->dist) { qbvh_item_swap(s2, s1); }
+ if (s2->dist < s1->dist) {
+ qbvh_item_swap(s2, s1);
+ }
+ if (s3->dist < s2->dist) {
+ qbvh_item_swap(s3, s2);
+ }
+ if (s2->dist < s1->dist) {
+ qbvh_item_swap(s2, s1);
+ }
}
ccl_device_inline void qbvh_stack_sort(QBVHStackItem *ccl_restrict s1,
@@ -76,279 +108,283 @@ ccl_device_inline void qbvh_stack_sort(QBVHStackItem *ccl_restrict s1,
QBVHStackItem *ccl_restrict s3,
QBVHStackItem *ccl_restrict s4)
{
- if(s2->dist < s1->dist) { qbvh_item_swap(s2, s1); }
- if(s4->dist < s3->dist) { qbvh_item_swap(s4, s3); }
- if(s3->dist < s1->dist) { qbvh_item_swap(s3, s1); }
- if(s4->dist < s2->dist) { qbvh_item_swap(s4, s2); }
- if(s3->dist < s2->dist) { qbvh_item_swap(s3, s2); }
+ if (s2->dist < s1->dist) {
+ qbvh_item_swap(s2, s1);
+ }
+ if (s4->dist < s3->dist) {
+ qbvh_item_swap(s4, s3);
+ }
+ if (s3->dist < s1->dist) {
+ qbvh_item_swap(s3, s1);
+ }
+ if (s4->dist < s2->dist) {
+ qbvh_item_swap(s4, s2);
+ }
+ if (s3->dist < s2->dist) {
+ qbvh_item_swap(s3, s2);
+ }
}
/* Axis-aligned nodes intersection */
//ccl_device_inline int qbvh_aligned_node_intersect(KernelGlobals *ccl_restrict kg,
static int qbvh_aligned_node_intersect(KernelGlobals *ccl_restrict kg,
- const ssef& isect_near,
- const ssef& isect_far,
+ const ssef &isect_near,
+ const ssef &isect_far,
#ifdef __KERNEL_AVX2__
- const sse3f& org_idir,
+ const sse3f &org_idir,
#else
- const sse3f& org,
+ const sse3f &org,
#endif
- const sse3f& idir,
- const int near_x,
- const int near_y,
- const int near_z,
- const int far_x,
- const int far_y,
- const int far_z,
- const int node_addr,
- ssef *ccl_restrict dist)
+ const sse3f &idir,
+ const int near_x,
+ const int near_y,
+ const int near_z,
+ const int far_x,
+ const int far_y,
+ const int far_z,
+ const int node_addr,
+ ssef *ccl_restrict dist)
{
- const int offset = node_addr + 1;
+ const int offset = node_addr + 1;
#ifdef __KERNEL_AVX2__
- const ssef tnear_x = msub(kernel_tex_fetch_ssef(__bvh_nodes, offset+near_x), idir.x, org_idir.x);
- const ssef tnear_y = msub(kernel_tex_fetch_ssef(__bvh_nodes, offset+near_y), idir.y, org_idir.y);
- const ssef tnear_z = msub(kernel_tex_fetch_ssef(__bvh_nodes, offset+near_z), idir.z, org_idir.z);
- const ssef tfar_x = msub(kernel_tex_fetch_ssef(__bvh_nodes, offset+far_x), idir.x, org_idir.x);
- const ssef tfar_y = msub(kernel_tex_fetch_ssef(__bvh_nodes, offset+far_y), idir.y, org_idir.y);
- const ssef tfar_z = msub(kernel_tex_fetch_ssef(__bvh_nodes, offset+far_z), idir.z, org_idir.z);
+ const ssef tnear_x = msub(
+ kernel_tex_fetch_ssef(__bvh_nodes, offset + near_x), idir.x, org_idir.x);
+ const ssef tnear_y = msub(
+ kernel_tex_fetch_ssef(__bvh_nodes, offset + near_y), idir.y, org_idir.y);
+ const ssef tnear_z = msub(
+ kernel_tex_fetch_ssef(__bvh_nodes, offset + near_z), idir.z, org_idir.z);
+ const ssef tfar_x = msub(kernel_tex_fetch_ssef(__bvh_nodes, offset + far_x), idir.x, org_idir.x);
+ const ssef tfar_y = msub(kernel_tex_fetch_ssef(__bvh_nodes, offset + far_y), idir.y, org_idir.y);
+ const ssef tfar_z = msub(kernel_tex_fetch_ssef(__bvh_nodes, offset + far_z), idir.z, org_idir.z);
#else
- const ssef tnear_x = (kernel_tex_fetch_ssef(__bvh_nodes, offset+near_x) - org.x) * idir.x;
- const ssef tnear_y = (kernel_tex_fetch_ssef(__bvh_nodes, offset+near_y) - org.y) * idir.y;
- const ssef tnear_z = (kernel_tex_fetch_ssef(__bvh_nodes, offset+near_z) - org.z) * idir.z;
- const ssef tfar_x = (kernel_tex_fetch_ssef(__bvh_nodes, offset+far_x) - org.x) * idir.x;
- const ssef tfar_y = (kernel_tex_fetch_ssef(__bvh_nodes, offset+far_y) - org.y) * idir.y;
- const ssef tfar_z = (kernel_tex_fetch_ssef(__bvh_nodes, offset+far_z) - org.z) * idir.z;
+ const ssef tnear_x = (kernel_tex_fetch_ssef(__bvh_nodes, offset + near_x) - org.x) * idir.x;
+ const ssef tnear_y = (kernel_tex_fetch_ssef(__bvh_nodes, offset + near_y) - org.y) * idir.y;
+ const ssef tnear_z = (kernel_tex_fetch_ssef(__bvh_nodes, offset + near_z) - org.z) * idir.z;
+ const ssef tfar_x = (kernel_tex_fetch_ssef(__bvh_nodes, offset + far_x) - org.x) * idir.x;
+ const ssef tfar_y = (kernel_tex_fetch_ssef(__bvh_nodes, offset + far_y) - org.y) * idir.y;
+ const ssef tfar_z = (kernel_tex_fetch_ssef(__bvh_nodes, offset + far_z) - org.z) * idir.z;
#endif
#ifdef __KERNEL_SSE41__
- const ssef tnear = maxi(maxi(tnear_x, tnear_y), maxi(tnear_z, isect_near));
- const ssef tfar = mini(mini(tfar_x, tfar_y), mini(tfar_z, isect_far));
- const sseb vmask = cast(tnear) > cast(tfar);
- int mask = (int)movemask(vmask)^0xf;
+ const ssef tnear = maxi(maxi(tnear_x, tnear_y), maxi(tnear_z, isect_near));
+ const ssef tfar = mini(mini(tfar_x, tfar_y), mini(tfar_z, isect_far));
+ const sseb vmask = cast(tnear) > cast(tfar);
+ int mask = (int)movemask(vmask) ^ 0xf;
#else
- const ssef tnear = max4(isect_near, tnear_x, tnear_y, tnear_z);
- const ssef tfar = min4(isect_far, tfar_x, tfar_y, tfar_z);
- const sseb vmask = tnear <= tfar;
- int mask = (int)movemask(vmask);
+ const ssef tnear = max4(isect_near, tnear_x, tnear_y, tnear_z);
+ const ssef tfar = min4(isect_far, tfar_x, tfar_y, tfar_z);
+ const sseb vmask = tnear <= tfar;
+ int mask = (int)movemask(vmask);
#endif
- *dist = tnear;
- return mask;
+ *dist = tnear;
+ return mask;
}
-ccl_device_inline int qbvh_aligned_node_intersect_robust(
- KernelGlobals *ccl_restrict kg,
- const ssef& isect_near,
- const ssef& isect_far,
+ccl_device_inline int qbvh_aligned_node_intersect_robust(KernelGlobals *ccl_restrict kg,
+ const ssef &isect_near,
+ const ssef &isect_far,
#ifdef __KERNEL_AVX2__
- const sse3f& P_idir,
+ const sse3f &P_idir,
#else
- const sse3f& P,
+ const sse3f &P,
#endif
- const sse3f& idir,
- const int near_x,
- const int near_y,
- const int near_z,
- const int far_x,
- const int far_y,
- const int far_z,
- const int node_addr,
- const float difl,
- ssef *ccl_restrict dist)
+ const sse3f &idir,
+ const int near_x,
+ const int near_y,
+ const int near_z,
+ const int far_x,
+ const int far_y,
+ const int far_z,
+ const int node_addr,
+ const float difl,
+ ssef *ccl_restrict dist)
{
- const int offset = node_addr + 1;
+ const int offset = node_addr + 1;
#ifdef __KERNEL_AVX2__
- const ssef tnear_x = msub(kernel_tex_fetch_ssef(__bvh_nodes, offset+near_x), idir.x, P_idir.x);
- const ssef tnear_y = msub(kernel_tex_fetch_ssef(__bvh_nodes, offset+near_y), idir.y, P_idir.y);
- const ssef tnear_z = msub(kernel_tex_fetch_ssef(__bvh_nodes, offset+near_z), idir.z, P_idir.z);
- const ssef tfar_x = msub(kernel_tex_fetch_ssef(__bvh_nodes, offset+far_x), idir.x, P_idir.x);
- const ssef tfar_y = msub(kernel_tex_fetch_ssef(__bvh_nodes, offset+far_y), idir.y, P_idir.y);
- const ssef tfar_z = msub(kernel_tex_fetch_ssef(__bvh_nodes, offset+far_z), idir.z, P_idir.z);
+ const ssef tnear_x = msub(kernel_tex_fetch_ssef(__bvh_nodes, offset + near_x), idir.x, P_idir.x);
+ const ssef tnear_y = msub(kernel_tex_fetch_ssef(__bvh_nodes, offset + near_y), idir.y, P_idir.y);
+ const ssef tnear_z = msub(kernel_tex_fetch_ssef(__bvh_nodes, offset + near_z), idir.z, P_idir.z);
+ const ssef tfar_x = msub(kernel_tex_fetch_ssef(__bvh_nodes, offset + far_x), idir.x, P_idir.x);
+ const ssef tfar_y = msub(kernel_tex_fetch_ssef(__bvh_nodes, offset + far_y), idir.y, P_idir.y);
+ const ssef tfar_z = msub(kernel_tex_fetch_ssef(__bvh_nodes, offset + far_z), idir.z, P_idir.z);
#else
- const ssef tnear_x = (kernel_tex_fetch_ssef(__bvh_nodes, offset+near_x) - P.x) * idir.x;
- const ssef tnear_y = (kernel_tex_fetch_ssef(__bvh_nodes, offset+near_y) - P.y) * idir.y;
- const ssef tnear_z = (kernel_tex_fetch_ssef(__bvh_nodes, offset+near_z) - P.z) * idir.z;
- const ssef tfar_x = (kernel_tex_fetch_ssef(__bvh_nodes, offset+far_x) - P.x) * idir.x;
- const ssef tfar_y = (kernel_tex_fetch_ssef(__bvh_nodes, offset+far_y) - P.y) * idir.y;
- const ssef tfar_z = (kernel_tex_fetch_ssef(__bvh_nodes, offset+far_z) - P.z) * idir.z;
+ const ssef tnear_x = (kernel_tex_fetch_ssef(__bvh_nodes, offset + near_x) - P.x) * idir.x;
+ const ssef tnear_y = (kernel_tex_fetch_ssef(__bvh_nodes, offset + near_y) - P.y) * idir.y;
+ const ssef tnear_z = (kernel_tex_fetch_ssef(__bvh_nodes, offset + near_z) - P.z) * idir.z;
+ const ssef tfar_x = (kernel_tex_fetch_ssef(__bvh_nodes, offset + far_x) - P.x) * idir.x;
+ const ssef tfar_y = (kernel_tex_fetch_ssef(__bvh_nodes, offset + far_y) - P.y) * idir.y;
+ const ssef tfar_z = (kernel_tex_fetch_ssef(__bvh_nodes, offset + far_z) - P.z) * idir.z;
#endif
- const float round_down = 1.0f - difl;
- const float round_up = 1.0f + difl;
- const ssef tnear = max4(isect_near, tnear_x, tnear_y, tnear_z);
- const ssef tfar = min4(isect_far, tfar_x, tfar_y, tfar_z);
- const sseb vmask = round_down*tnear <= round_up*tfar;
- *dist = tnear;
- return (int)movemask(vmask);
+ const float round_down = 1.0f - difl;
+ const float round_up = 1.0f + difl;
+ const ssef tnear = max4(isect_near, tnear_x, tnear_y, tnear_z);
+ const ssef tfar = min4(isect_far, tfar_x, tfar_y, tfar_z);
+ const sseb vmask = round_down * tnear <= round_up * tfar;
+ *dist = tnear;
+ return (int)movemask(vmask);
}
/* Unaligned nodes intersection */
-ccl_device_inline int qbvh_unaligned_node_intersect(
- KernelGlobals *ccl_restrict kg,
- const ssef& isect_near,
- const ssef& isect_far,
+ccl_device_inline int qbvh_unaligned_node_intersect(KernelGlobals *ccl_restrict kg,
+ const ssef &isect_near,
+ const ssef &isect_far,
#ifdef __KERNEL_AVX2__
- const sse3f& org_idir,
+ const sse3f &org_idir,
#endif
- const sse3f& org,
- const sse3f& dir,
- const sse3f& idir,
- const int near_x,
- const int near_y,
- const int near_z,
- const int far_x,
- const int far_y,
- const int far_z,
- const int node_addr,
- ssef *ccl_restrict dist)
+ const sse3f &org,
+ const sse3f &dir,
+ const sse3f &idir,
+ const int near_x,
+ const int near_y,
+ const int near_z,
+ const int far_x,
+ const int far_y,
+ const int far_z,
+ const int node_addr,
+ ssef *ccl_restrict dist)
{
- const int offset = node_addr;
- const ssef tfm_x_x = kernel_tex_fetch_ssef(__bvh_nodes, offset+1);
- const ssef tfm_x_y = kernel_tex_fetch_ssef(__bvh_nodes, offset+2);
- const ssef tfm_x_z = kernel_tex_fetch_ssef(__bvh_nodes, offset+3);
+ const int offset = node_addr;
+ const ssef tfm_x_x = kernel_tex_fetch_ssef(__bvh_nodes, offset + 1);
+ const ssef tfm_x_y = kernel_tex_fetch_ssef(__bvh_nodes, offset + 2);
+ const ssef tfm_x_z = kernel_tex_fetch_ssef(__bvh_nodes, offset + 3);
- const ssef tfm_y_x = kernel_tex_fetch_ssef(__bvh_nodes, offset+4);
- const ssef tfm_y_y = kernel_tex_fetch_ssef(__bvh_nodes, offset+5);
- const ssef tfm_y_z = kernel_tex_fetch_ssef(__bvh_nodes, offset+6);
+ const ssef tfm_y_x = kernel_tex_fetch_ssef(__bvh_nodes, offset + 4);
+ const ssef tfm_y_y = kernel_tex_fetch_ssef(__bvh_nodes, offset + 5);
+ const ssef tfm_y_z = kernel_tex_fetch_ssef(__bvh_nodes, offset + 6);
- const ssef tfm_z_x = kernel_tex_fetch_ssef(__bvh_nodes, offset+7);
- const ssef tfm_z_y = kernel_tex_fetch_ssef(__bvh_nodes, offset+8);
- const ssef tfm_z_z = kernel_tex_fetch_ssef(__bvh_nodes, offset+9);
+ const ssef tfm_z_x = kernel_tex_fetch_ssef(__bvh_nodes, offset + 7);
+ const ssef tfm_z_y = kernel_tex_fetch_ssef(__bvh_nodes, offset + 8);
+ const ssef tfm_z_z = kernel_tex_fetch_ssef(__bvh_nodes, offset + 9);
- const ssef tfm_t_x = kernel_tex_fetch_ssef(__bvh_nodes, offset+10);
- const ssef tfm_t_y = kernel_tex_fetch_ssef(__bvh_nodes, offset+11);
- const ssef tfm_t_z = kernel_tex_fetch_ssef(__bvh_nodes, offset+12);
+ const ssef tfm_t_x = kernel_tex_fetch_ssef(__bvh_nodes, offset + 10);
+ const ssef tfm_t_y = kernel_tex_fetch_ssef(__bvh_nodes, offset + 11);
+ const ssef tfm_t_z = kernel_tex_fetch_ssef(__bvh_nodes, offset + 12);
- const ssef aligned_dir_x = dir.x*tfm_x_x + dir.y*tfm_x_y + dir.z*tfm_x_z,
- aligned_dir_y = dir.x*tfm_y_x + dir.y*tfm_y_y + dir.z*tfm_y_z,
- aligned_dir_z = dir.x*tfm_z_x + dir.y*tfm_z_y + dir.z*tfm_z_z;
+ const ssef aligned_dir_x = dir.x * tfm_x_x + dir.y * tfm_x_y + dir.z * tfm_x_z,
+ aligned_dir_y = dir.x * tfm_y_x + dir.y * tfm_y_y + dir.z * tfm_y_z,
+ aligned_dir_z = dir.x * tfm_z_x + dir.y * tfm_z_y + dir.z * tfm_z_z;
- const ssef aligned_P_x = org.x*tfm_x_x + org.y*tfm_x_y + org.z*tfm_x_z + tfm_t_x,
- aligned_P_y = org.x*tfm_y_x + org.y*tfm_y_y + org.z*tfm_y_z + tfm_t_y,
- aligned_P_z = org.x*tfm_z_x + org.y*tfm_z_y + org.z*tfm_z_z + tfm_t_z;
+ const ssef aligned_P_x = org.x * tfm_x_x + org.y * tfm_x_y + org.z * tfm_x_z + tfm_t_x,
+ aligned_P_y = org.x * tfm_y_x + org.y * tfm_y_y + org.z * tfm_y_z + tfm_t_y,
+ aligned_P_z = org.x * tfm_z_x + org.y * tfm_z_y + org.z * tfm_z_z + tfm_t_z;
- const ssef neg_one(-1.0f, -1.0f, -1.0f, -1.0f);
- const ssef nrdir_x = neg_one / aligned_dir_x,
- nrdir_y = neg_one / aligned_dir_y,
- nrdir_z = neg_one / aligned_dir_z;
+ const ssef neg_one(-1.0f, -1.0f, -1.0f, -1.0f);
+ const ssef nrdir_x = neg_one / aligned_dir_x, nrdir_y = neg_one / aligned_dir_y,
+ nrdir_z = neg_one / aligned_dir_z;
- const ssef tlower_x = aligned_P_x * nrdir_x,
- tlower_y = aligned_P_y * nrdir_y,
- tlower_z = aligned_P_z * nrdir_z;
+ const ssef tlower_x = aligned_P_x * nrdir_x, tlower_y = aligned_P_y * nrdir_y,
+ tlower_z = aligned_P_z * nrdir_z;
- const ssef tupper_x = tlower_x - nrdir_x,
- tupper_y = tlower_y - nrdir_y,
- tupper_z = tlower_z - nrdir_z;
+ const ssef tupper_x = tlower_x - nrdir_x, tupper_y = tlower_y - nrdir_y,
+ tupper_z = tlower_z - nrdir_z;
#ifdef __KERNEL_SSE41__
- const ssef tnear_x = mini(tlower_x, tupper_x);
- const ssef tnear_y = mini(tlower_y, tupper_y);
- const ssef tnear_z = mini(tlower_z, tupper_z);
- const ssef tfar_x = maxi(tlower_x, tupper_x);
- const ssef tfar_y = maxi(tlower_y, tupper_y);
- const ssef tfar_z = maxi(tlower_z, tupper_z);
- const ssef tnear = max4(isect_near, tnear_x, tnear_y, tnear_z);
- const ssef tfar = min4(isect_far, tfar_x, tfar_y, tfar_z);
- const sseb vmask = tnear <= tfar;
- *dist = tnear;
- return movemask(vmask);
+ const ssef tnear_x = mini(tlower_x, tupper_x);
+ const ssef tnear_y = mini(tlower_y, tupper_y);
+ const ssef tnear_z = mini(tlower_z, tupper_z);
+ const ssef tfar_x = maxi(tlower_x, tupper_x);
+ const ssef tfar_y = maxi(tlower_y, tupper_y);
+ const ssef tfar_z = maxi(tlower_z, tupper_z);
+ const ssef tnear = max4(isect_near, tnear_x, tnear_y, tnear_z);
+ const ssef tfar = min4(isect_far, tfar_x, tfar_y, tfar_z);
+ const sseb vmask = tnear <= tfar;
+ *dist = tnear;
+ return movemask(vmask);
#else
- const ssef tnear_x = min(tlower_x, tupper_x);
- const ssef tnear_y = min(tlower_y, tupper_y);
- const ssef tnear_z = min(tlower_z, tupper_z);
- const ssef tfar_x = max(tlower_x, tupper_x);
- const ssef tfar_y = max(tlower_y, tupper_y);
- const ssef tfar_z = max(tlower_z, tupper_z);
- const ssef tnear = max4(isect_near, tnear_x, tnear_y, tnear_z);
- const ssef tfar = min4(isect_far, tfar_x, tfar_y, tfar_z);
- const sseb vmask = tnear <= tfar;
- *dist = tnear;
- return movemask(vmask);
+ const ssef tnear_x = min(tlower_x, tupper_x);
+ const ssef tnear_y = min(tlower_y, tupper_y);
+ const ssef tnear_z = min(tlower_z, tupper_z);
+ const ssef tfar_x = max(tlower_x, tupper_x);
+ const ssef tfar_y = max(tlower_y, tupper_y);
+ const ssef tfar_z = max(tlower_z, tupper_z);
+ const ssef tnear = max4(isect_near, tnear_x, tnear_y, tnear_z);
+ const ssef tfar = min4(isect_far, tfar_x, tfar_y, tfar_z);
+ const sseb vmask = tnear <= tfar;
+ *dist = tnear;
+ return movemask(vmask);
#endif
}
-ccl_device_inline int qbvh_unaligned_node_intersect_robust(
- KernelGlobals *ccl_restrict kg,
- const ssef& isect_near,
- const ssef& isect_far,
+ccl_device_inline int qbvh_unaligned_node_intersect_robust(KernelGlobals *ccl_restrict kg,
+ const ssef &isect_near,
+ const ssef &isect_far,
#ifdef __KERNEL_AVX2__
- const sse3f& P_idir,
+ const sse3f &P_idir,
#endif
- const sse3f& P,
- const sse3f& dir,
- const sse3f& idir,
- const int near_x,
- const int near_y,
- const int near_z,
- const int far_x,
- const int far_y,
- const int far_z,
- const int node_addr,
- const float difl,
- ssef *ccl_restrict dist)
+ const sse3f &P,
+ const sse3f &dir,
+ const sse3f &idir,
+ const int near_x,
+ const int near_y,
+ const int near_z,
+ const int far_x,
+ const int far_y,
+ const int far_z,
+ const int node_addr,
+ const float difl,
+ ssef *ccl_restrict dist)
{
- const int offset = node_addr;
- const ssef tfm_x_x = kernel_tex_fetch_ssef(__bvh_nodes, offset+1);
- const ssef tfm_x_y = kernel_tex_fetch_ssef(__bvh_nodes, offset+2);
- const ssef tfm_x_z = kernel_tex_fetch_ssef(__bvh_nodes, offset+3);
+ const int offset = node_addr;
+ const ssef tfm_x_x = kernel_tex_fetch_ssef(__bvh_nodes, offset + 1);
+ const ssef tfm_x_y = kernel_tex_fetch_ssef(__bvh_nodes, offset + 2);
+ const ssef tfm_x_z = kernel_tex_fetch_ssef(__bvh_nodes, offset + 3);
- const ssef tfm_y_x = kernel_tex_fetch_ssef(__bvh_nodes, offset+4);
- const ssef tfm_y_y = kernel_tex_fetch_ssef(__bvh_nodes, offset+5);
- const ssef tfm_y_z = kernel_tex_fetch_ssef(__bvh_nodes, offset+6);
+ const ssef tfm_y_x = kernel_tex_fetch_ssef(__bvh_nodes, offset + 4);
+ const ssef tfm_y_y = kernel_tex_fetch_ssef(__bvh_nodes, offset + 5);
+ const ssef tfm_y_z = kernel_tex_fetch_ssef(__bvh_nodes, offset + 6);
- const ssef tfm_z_x = kernel_tex_fetch_ssef(__bvh_nodes, offset+7);
- const ssef tfm_z_y = kernel_tex_fetch_ssef(__bvh_nodes, offset+8);
- const ssef tfm_z_z = kernel_tex_fetch_ssef(__bvh_nodes, offset+9);
+ const ssef tfm_z_x = kernel_tex_fetch_ssef(__bvh_nodes, offset + 7);
+ const ssef tfm_z_y = kernel_tex_fetch_ssef(__bvh_nodes, offset + 8);
+ const ssef tfm_z_z = kernel_tex_fetch_ssef(__bvh_nodes, offset + 9);
- const ssef tfm_t_x = kernel_tex_fetch_ssef(__bvh_nodes, offset+10);
- const ssef tfm_t_y = kernel_tex_fetch_ssef(__bvh_nodes, offset+11);
- const ssef tfm_t_z = kernel_tex_fetch_ssef(__bvh_nodes, offset+12);
+ const ssef tfm_t_x = kernel_tex_fetch_ssef(__bvh_nodes, offset + 10);
+ const ssef tfm_t_y = kernel_tex_fetch_ssef(__bvh_nodes, offset + 11);
+ const ssef tfm_t_z = kernel_tex_fetch_ssef(__bvh_nodes, offset + 12);
- const ssef aligned_dir_x = dir.x*tfm_x_x + dir.y*tfm_x_y + dir.z*tfm_x_z,
- aligned_dir_y = dir.x*tfm_y_x + dir.y*tfm_y_y + dir.z*tfm_y_z,
- aligned_dir_z = dir.x*tfm_z_x + dir.y*tfm_z_y + dir.z*tfm_z_z;
+ const ssef aligned_dir_x = dir.x * tfm_x_x + dir.y * tfm_x_y + dir.z * tfm_x_z,
+ aligned_dir_y = dir.x * tfm_y_x + dir.y * tfm_y_y + dir.z * tfm_y_z,
+ aligned_dir_z = dir.x * tfm_z_x + dir.y * tfm_z_y + dir.z * tfm_z_z;
- const ssef aligned_P_x = P.x*tfm_x_x + P.y*tfm_x_y + P.z*tfm_x_z + tfm_t_x,
- aligned_P_y = P.x*tfm_y_x + P.y*tfm_y_y + P.z*tfm_y_z + tfm_t_y,
- aligned_P_z = P.x*tfm_z_x + P.y*tfm_z_y + P.z*tfm_z_z + tfm_t_z;
+ const ssef aligned_P_x = P.x * tfm_x_x + P.y * tfm_x_y + P.z * tfm_x_z + tfm_t_x,
+ aligned_P_y = P.x * tfm_y_x + P.y * tfm_y_y + P.z * tfm_y_z + tfm_t_y,
+ aligned_P_z = P.x * tfm_z_x + P.y * tfm_z_y + P.z * tfm_z_z + tfm_t_z;
- const ssef neg_one(-1.0f, -1.0f, -1.0f, -1.0f);
- const ssef nrdir_x = neg_one / aligned_dir_x,
- nrdir_y = neg_one / aligned_dir_y,
- nrdir_z = neg_one / aligned_dir_z;
+ const ssef neg_one(-1.0f, -1.0f, -1.0f, -1.0f);
+ const ssef nrdir_x = neg_one / aligned_dir_x, nrdir_y = neg_one / aligned_dir_y,
+ nrdir_z = neg_one / aligned_dir_z;
- const ssef tlower_x = aligned_P_x * nrdir_x,
- tlower_y = aligned_P_y * nrdir_y,
- tlower_z = aligned_P_z * nrdir_z;
+ const ssef tlower_x = aligned_P_x * nrdir_x, tlower_y = aligned_P_y * nrdir_y,
+ tlower_z = aligned_P_z * nrdir_z;
- const ssef tupper_x = tlower_x - nrdir_x,
- tupper_y = tlower_y - nrdir_y,
- tupper_z = tlower_z - nrdir_z;
+ const ssef tupper_x = tlower_x - nrdir_x, tupper_y = tlower_y - nrdir_y,
+ tupper_z = tlower_z - nrdir_z;
- const float round_down = 1.0f - difl;
- const float round_up = 1.0f + difl;
+ const float round_down = 1.0f - difl;
+ const float round_up = 1.0f + difl;
#ifdef __KERNEL_SSE41__
- const ssef tnear_x = mini(tlower_x, tupper_x);
- const ssef tnear_y = mini(tlower_y, tupper_y);
- const ssef tnear_z = mini(tlower_z, tupper_z);
- const ssef tfar_x = maxi(tlower_x, tupper_x);
- const ssef tfar_y = maxi(tlower_y, tupper_y);
- const ssef tfar_z = maxi(tlower_z, tupper_z);
+ const ssef tnear_x = mini(tlower_x, tupper_x);
+ const ssef tnear_y = mini(tlower_y, tupper_y);
+ const ssef tnear_z = mini(tlower_z, tupper_z);
+ const ssef tfar_x = maxi(tlower_x, tupper_x);
+ const ssef tfar_y = maxi(tlower_y, tupper_y);
+ const ssef tfar_z = maxi(tlower_z, tupper_z);
#else
- const ssef tnear_x = min(tlower_x, tupper_x);
- const ssef tnear_y = min(tlower_y, tupper_y);
- const ssef tnear_z = min(tlower_z, tupper_z);
- const ssef tfar_x = max(tlower_x, tupper_x);
- const ssef tfar_y = max(tlower_y, tupper_y);
- const ssef tfar_z = max(tlower_z, tupper_z);
+ const ssef tnear_x = min(tlower_x, tupper_x);
+ const ssef tnear_y = min(tlower_y, tupper_y);
+ const ssef tnear_z = min(tlower_z, tupper_z);
+ const ssef tfar_x = max(tlower_x, tupper_x);
+ const ssef tfar_y = max(tlower_y, tupper_y);
+ const ssef tfar_z = max(tlower_z, tupper_z);
#endif
- const ssef tnear = max4(isect_near, tnear_x, tnear_y, tnear_z);
- const ssef tfar = min4(isect_far, tfar_x, tfar_y, tfar_z);
- const sseb vmask = round_down*tnear <= round_up*tfar;
- *dist = tnear;
- return movemask(vmask);
+ const ssef tnear = max4(isect_near, tnear_x, tnear_y, tnear_z);
+ const ssef tfar = min4(isect_far, tfar_x, tfar_y, tfar_z);
+ const sseb vmask = round_down * tnear <= round_up * tfar;
+ *dist = tnear;
+ return movemask(vmask);
}
/* Intersectors wrappers.
@@ -356,111 +392,125 @@ ccl_device_inline int qbvh_unaligned_node_intersect_robust(
* They'll check node type and call appropriate intersection code.
*/
-ccl_device_inline int qbvh_node_intersect(
- KernelGlobals *ccl_restrict kg,
- const ssef& isect_near,
- const ssef& isect_far,
+ccl_device_inline int qbvh_node_intersect(KernelGlobals *ccl_restrict kg,
+ const ssef &isect_near,
+ const ssef &isect_far,
#ifdef __KERNEL_AVX2__
- const sse3f& org_idir,
+ const sse3f &org_idir,
#endif
- const sse3f& org,
- const sse3f& dir,
- const sse3f& idir,
- const int near_x,
- const int near_y,
- const int near_z,
- const int far_x,
- const int far_y,
- const int far_z,
- const int node_addr,
- ssef *ccl_restrict dist)
+ const sse3f &org,
+ const sse3f &dir,
+ const sse3f &idir,
+ const int near_x,
+ const int near_y,
+ const int near_z,
+ const int far_x,
+ const int far_y,
+ const int far_z,
+ const int node_addr,
+ ssef *ccl_restrict dist)
{
- const int offset = node_addr;
- const float4 node = kernel_tex_fetch(__bvh_nodes, offset);
- if(__float_as_uint(node.x) & PATH_RAY_NODE_UNALIGNED) {
- return qbvh_unaligned_node_intersect(kg,
- isect_near,
- isect_far,
+ const int offset = node_addr;
+ const float4 node = kernel_tex_fetch(__bvh_nodes, offset);
+ if (__float_as_uint(node.x) & PATH_RAY_NODE_UNALIGNED) {
+ return qbvh_unaligned_node_intersect(kg,
+ isect_near,
+ isect_far,
#ifdef __KERNEL_AVX2__
- org_idir,
+ org_idir,
#endif
- org,
- dir,
- idir,
- near_x, near_y, near_z,
- far_x, far_y, far_z,
- node_addr,
- dist);
- }
- else {
- return qbvh_aligned_node_intersect(kg,
- isect_near,
- isect_far,
+ org,
+ dir,
+ idir,
+ near_x,
+ near_y,
+ near_z,
+ far_x,
+ far_y,
+ far_z,
+ node_addr,
+ dist);
+ }
+ else {
+ return qbvh_aligned_node_intersect(kg,
+ isect_near,
+ isect_far,
#ifdef __KERNEL_AVX2__
- org_idir,
+ org_idir,
#else
- org,
+ org,
#endif
- idir,
- near_x, near_y, near_z,
- far_x, far_y, far_z,
- node_addr,
- dist);
- }
+ idir,
+ near_x,
+ near_y,
+ near_z,
+ far_x,
+ far_y,
+ far_z,
+ node_addr,
+ dist);
+ }
}
-ccl_device_inline int qbvh_node_intersect_robust(
- KernelGlobals *ccl_restrict kg,
- const ssef& isect_near,
- const ssef& isect_far,
+ccl_device_inline int qbvh_node_intersect_robust(KernelGlobals *ccl_restrict kg,
+ const ssef &isect_near,
+ const ssef &isect_far,
#ifdef __KERNEL_AVX2__
- const sse3f& P_idir,
+ const sse3f &P_idir,
#endif
- const sse3f& P,
- const sse3f& dir,
- const sse3f& idir,
- const int near_x,
- const int near_y,
- const int near_z,
- const int far_x,
- const int far_y,
- const int far_z,
- const int node_addr,
- const float difl,
- ssef *ccl_restrict dist)
+ const sse3f &P,
+ const sse3f &dir,
+ const sse3f &idir,
+ const int near_x,
+ const int near_y,
+ const int near_z,
+ const int far_x,
+ const int far_y,
+ const int far_z,
+ const int node_addr,
+ const float difl,
+ ssef *ccl_restrict dist)
{
- const int offset = node_addr;
- const float4 node = kernel_tex_fetch(__bvh_nodes, offset);
- if(__float_as_uint(node.x) & PATH_RAY_NODE_UNALIGNED) {
- return qbvh_unaligned_node_intersect_robust(kg,
- isect_near,
- isect_far,
+ const int offset = node_addr;
+ const float4 node = kernel_tex_fetch(__bvh_nodes, offset);
+ if (__float_as_uint(node.x) & PATH_RAY_NODE_UNALIGNED) {
+ return qbvh_unaligned_node_intersect_robust(kg,
+ isect_near,
+ isect_far,
#ifdef __KERNEL_AVX2__
- P_idir,
+ P_idir,
#endif
- P,
- dir,
- idir,
- near_x, near_y, near_z,
- far_x, far_y, far_z,
- node_addr,
- difl,
- dist);
- }
- else {
- return qbvh_aligned_node_intersect_robust(kg,
- isect_near,
- isect_far,
+ P,
+ dir,
+ idir,
+ near_x,
+ near_y,
+ near_z,
+ far_x,
+ far_y,
+ far_z,
+ node_addr,
+ difl,
+ dist);
+ }
+ else {
+ return qbvh_aligned_node_intersect_robust(kg,
+ isect_near,
+ isect_far,
#ifdef __KERNEL_AVX2__
- P_idir,
+ P_idir,
#else
- P,
+ P,
#endif
- idir,
- near_x, near_y, near_z,
- far_x, far_y, far_z,
- node_addr,
- difl,
- dist);
- }
+ idir,
+ near_x,
+ near_y,
+ near_z,
+ far_x,
+ far_y,
+ far_z,
+ node_addr,
+ difl,
+ dist);
+ }
}
diff --git a/intern/cycles/kernel/bvh/qbvh_shadow_all.h b/intern/cycles/kernel/bvh/qbvh_shadow_all.h
index dd977fb9e74..49e607bfbd0 100644
--- a/intern/cycles/kernel/bvh/qbvh_shadow_all.h
+++ b/intern/cycles/kernel/bvh/qbvh_shadow_all.h
@@ -36,439 +36,424 @@ ccl_device bool BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg,
const uint max_hits,
uint *num_hits)
{
- /* TODO(sergey):
- * - Test if pushing distance on the stack helps.
- * - Likely and unlikely for if() statements.
- * - Test restrict attribute for pointers.
- */
-
- /* Traversal stack in CUDA thread-local memory. */
- QBVHStackItem traversal_stack[BVH_QSTACK_SIZE];
- traversal_stack[0].addr = ENTRYPOINT_SENTINEL;
-
- /* Traversal variables in registers. */
- int stack_ptr = 0;
- int node_addr = kernel_data.bvh.root;
-
- /* Ray parameters in registers. */
- const float tmax = ray->t;
- float3 P = ray->P;
- float3 dir = bvh_clamp_direction(ray->D);
- float3 idir = bvh_inverse_direction(dir);
- int object = OBJECT_NONE;
- float isect_t = tmax;
+ /* TODO(sergey):
+ * - Test if pushing distance on the stack helps.
+ * - Likely and unlikely for if() statements.
+ * - Test restrict attribute for pointers.
+ */
+
+ /* Traversal stack in CUDA thread-local memory. */
+ QBVHStackItem traversal_stack[BVH_QSTACK_SIZE];
+ traversal_stack[0].addr = ENTRYPOINT_SENTINEL;
+
+ /* Traversal variables in registers. */
+ int stack_ptr = 0;
+ int node_addr = kernel_data.bvh.root;
+
+ /* Ray parameters in registers. */
+ const float tmax = ray->t;
+ float3 P = ray->P;
+ float3 dir = bvh_clamp_direction(ray->D);
+ float3 idir = bvh_inverse_direction(dir);
+ int object = OBJECT_NONE;
+ float isect_t = tmax;
#if BVH_FEATURE(BVH_MOTION)
- Transform ob_itfm;
+ Transform ob_itfm;
#endif
- *num_hits = 0;
- isect_array->t = tmax;
-
+ *num_hits = 0;
+ isect_array->t = tmax;
#if BVH_FEATURE(BVH_INSTANCING)
- int num_hits_in_instance = 0;
+ int num_hits_in_instance = 0;
#endif
- ssef tnear(0.0f), tfar(isect_t);
+ ssef tnear(0.0f), tfar(isect_t);
#if BVH_FEATURE(BVH_HAIR)
- sse3f dir4(ssef(dir.x), ssef(dir.y), ssef(dir.z));
+ sse3f dir4(ssef(dir.x), ssef(dir.y), ssef(dir.z));
#endif
- sse3f idir4(ssef(idir.x), ssef(idir.y), ssef(idir.z));
+ sse3f idir4(ssef(idir.x), ssef(idir.y), ssef(idir.z));
#ifdef __KERNEL_AVX2__
- float3 P_idir = P*idir;
- sse3f P_idir4(P_idir.x, P_idir.y, P_idir.z);
+ float3 P_idir = P * idir;
+ sse3f P_idir4(P_idir.x, P_idir.y, P_idir.z);
#endif
#if BVH_FEATURE(BVH_HAIR) || !defined(__KERNEL_AVX2__)
- sse3f org4(ssef(P.x), ssef(P.y), ssef(P.z));
+ sse3f org4(ssef(P.x), ssef(P.y), ssef(P.z));
#endif
- /* Offsets to select the side that becomes the lower or upper bound. */
- int near_x, near_y, near_z;
- int far_x, far_y, far_z;
- qbvh_near_far_idx_calc(idir,
- &near_x, &near_y, &near_z,
- &far_x, &far_y, &far_z);
-
- /* Traversal loop. */
- do {
- do {
- /* Traverse internal nodes. */
- while(node_addr >= 0 && node_addr != ENTRYPOINT_SENTINEL) {
- float4 inodes = kernel_tex_fetch(__bvh_nodes, node_addr+0);
- (void) inodes;
-
- if(false
+ /* Offsets to select the side that becomes the lower or upper bound. */
+ int near_x, near_y, near_z;
+ int far_x, far_y, far_z;
+ qbvh_near_far_idx_calc(idir, &near_x, &near_y, &near_z, &far_x, &far_y, &far_z);
+
+ /* Traversal loop. */
+ do {
+ do {
+ /* Traverse internal nodes. */
+ while (node_addr >= 0 && node_addr != ENTRYPOINT_SENTINEL) {
+ float4 inodes = kernel_tex_fetch(__bvh_nodes, node_addr + 0);
+ (void)inodes;
+
+ if (false
#ifdef __VISIBILITY_FLAG__
- || ((__float_as_uint(inodes.x) & visibility) == 0)
+ || ((__float_as_uint(inodes.x) & visibility) == 0)
#endif
#if BVH_FEATURE(BVH_MOTION)
- || UNLIKELY(ray->time < inodes.y)
- || UNLIKELY(ray->time > inodes.z)
+ || UNLIKELY(ray->time < inodes.y) || UNLIKELY(ray->time > inodes.z)
#endif
- ) {
- /* Pop. */
- node_addr = traversal_stack[stack_ptr].addr;
- --stack_ptr;
- continue;
- }
-
- ssef dist;
- int child_mask = NODE_INTERSECT(kg,
- tnear,
- tfar,
+ ) {
+ /* Pop. */
+ node_addr = traversal_stack[stack_ptr].addr;
+ --stack_ptr;
+ continue;
+ }
+
+ ssef dist;
+ int child_mask = NODE_INTERSECT(kg,
+ tnear,
+ tfar,
#ifdef __KERNEL_AVX2__
- P_idir4,
+ P_idir4,
#endif
#if BVH_FEATURE(BVH_HAIR) || !defined(__KERNEL_AVX2__)
- org4,
+ org4,
#endif
#if BVH_FEATURE(BVH_HAIR)
- dir4,
+ dir4,
#endif
- idir4,
- near_x, near_y, near_z,
- far_x, far_y, far_z,
- node_addr,
- &dist);
-
- if(child_mask != 0) {
- float4 cnodes;
+ idir4,
+ near_x,
+ near_y,
+ near_z,
+ far_x,
+ far_y,
+ far_z,
+ node_addr,
+ &dist);
+
+ if (child_mask != 0) {
+ float4 cnodes;
#if BVH_FEATURE(BVH_HAIR)
- if(__float_as_uint(inodes.x) & PATH_RAY_NODE_UNALIGNED) {
- cnodes = kernel_tex_fetch(__bvh_nodes, node_addr+13);
- }
- else
+ if (__float_as_uint(inodes.x) & PATH_RAY_NODE_UNALIGNED) {
+ cnodes = kernel_tex_fetch(__bvh_nodes, node_addr + 13);
+ }
+ else
#endif
- {
- cnodes = kernel_tex_fetch(__bvh_nodes, node_addr+7);
- }
-
- /* One child is hit, continue with that child. */
- int r = __bscf(child_mask);
- if(child_mask == 0) {
- node_addr = __float_as_int(cnodes[r]);
- continue;
- }
-
- /* Two children are hit, push far child, and continue with
- * closer child.
- */
- int c0 = __float_as_int(cnodes[r]);
- float d0 = ((float*)&dist)[r];
- r = __bscf(child_mask);
- int c1 = __float_as_int(cnodes[r]);
- float d1 = ((float*)&dist)[r];
- if(child_mask == 0) {
- if(d1 < d0) {
- node_addr = c1;
- ++stack_ptr;
- kernel_assert(stack_ptr < BVH_QSTACK_SIZE);
- traversal_stack[stack_ptr].addr = c0;
- traversal_stack[stack_ptr].dist = d0;
- continue;
- }
- else {
- node_addr = c0;
- ++stack_ptr;
- kernel_assert(stack_ptr < BVH_QSTACK_SIZE);
- traversal_stack[stack_ptr].addr = c1;
- traversal_stack[stack_ptr].dist = d1;
- continue;
- }
- }
-
- /* Here starts the slow path for 3 or 4 hit children. We push
- * all nodes onto the stack to sort them there.
- */
- ++stack_ptr;
- kernel_assert(stack_ptr < BVH_QSTACK_SIZE);
- traversal_stack[stack_ptr].addr = c1;
- traversal_stack[stack_ptr].dist = d1;
- ++stack_ptr;
- kernel_assert(stack_ptr < BVH_QSTACK_SIZE);
- traversal_stack[stack_ptr].addr = c0;
- traversal_stack[stack_ptr].dist = d0;
-
- /* Three children are hit, push all onto stack and sort 3
- * stack items, continue with closest child.
- */
- r = __bscf(child_mask);
- int c2 = __float_as_int(cnodes[r]);
- float d2 = ((float*)&dist)[r];
- if(child_mask == 0) {
- ++stack_ptr;
- kernel_assert(stack_ptr < BVH_QSTACK_SIZE);
- traversal_stack[stack_ptr].addr = c2;
- traversal_stack[stack_ptr].dist = d2;
- qbvh_stack_sort(&traversal_stack[stack_ptr],
- &traversal_stack[stack_ptr - 1],
- &traversal_stack[stack_ptr - 2]);
- node_addr = traversal_stack[stack_ptr].addr;
- --stack_ptr;
- continue;
- }
-
- /* Four children are hit, push all onto stack and sort 4
- * stack items, continue with closest child.
- */
- r = __bscf(child_mask);
- int c3 = __float_as_int(cnodes[r]);
- float d3 = ((float*)&dist)[r];
- ++stack_ptr;
- kernel_assert(stack_ptr < BVH_QSTACK_SIZE);
- traversal_stack[stack_ptr].addr = c3;
- traversal_stack[stack_ptr].dist = d3;
- ++stack_ptr;
- kernel_assert(stack_ptr < BVH_QSTACK_SIZE);
- traversal_stack[stack_ptr].addr = c2;
- traversal_stack[stack_ptr].dist = d2;
- qbvh_stack_sort(&traversal_stack[stack_ptr],
- &traversal_stack[stack_ptr - 1],
- &traversal_stack[stack_ptr - 2],
- &traversal_stack[stack_ptr - 3]);
- }
-
- node_addr = traversal_stack[stack_ptr].addr;
- --stack_ptr;
- }
-
- /* If node is leaf, fetch triangle list. */
- if(node_addr < 0) {
- float4 leaf = kernel_tex_fetch(__bvh_leaf_nodes, (-node_addr-1));
+ {
+ cnodes = kernel_tex_fetch(__bvh_nodes, node_addr + 7);
+ }
+
+ /* One child is hit, continue with that child. */
+ int r = __bscf(child_mask);
+ if (child_mask == 0) {
+ node_addr = __float_as_int(cnodes[r]);
+ continue;
+ }
+
+ /* Two children are hit, push far child, and continue with
+ * closer child.
+ */
+ int c0 = __float_as_int(cnodes[r]);
+ float d0 = ((float *)&dist)[r];
+ r = __bscf(child_mask);
+ int c1 = __float_as_int(cnodes[r]);
+ float d1 = ((float *)&dist)[r];
+ if (child_mask == 0) {
+ if (d1 < d0) {
+ node_addr = c1;
+ ++stack_ptr;
+ kernel_assert(stack_ptr < BVH_QSTACK_SIZE);
+ traversal_stack[stack_ptr].addr = c0;
+ traversal_stack[stack_ptr].dist = d0;
+ continue;
+ }
+ else {
+ node_addr = c0;
+ ++stack_ptr;
+ kernel_assert(stack_ptr < BVH_QSTACK_SIZE);
+ traversal_stack[stack_ptr].addr = c1;
+ traversal_stack[stack_ptr].dist = d1;
+ continue;
+ }
+ }
+
+ /* Here starts the slow path for 3 or 4 hit children. We push
+ * all nodes onto the stack to sort them there.
+ */
+ ++stack_ptr;
+ kernel_assert(stack_ptr < BVH_QSTACK_SIZE);
+ traversal_stack[stack_ptr].addr = c1;
+ traversal_stack[stack_ptr].dist = d1;
+ ++stack_ptr;
+ kernel_assert(stack_ptr < BVH_QSTACK_SIZE);
+ traversal_stack[stack_ptr].addr = c0;
+ traversal_stack[stack_ptr].dist = d0;
+
+ /* Three children are hit, push all onto stack and sort 3
+ * stack items, continue with closest child.
+ */
+ r = __bscf(child_mask);
+ int c2 = __float_as_int(cnodes[r]);
+ float d2 = ((float *)&dist)[r];
+ if (child_mask == 0) {
+ ++stack_ptr;
+ kernel_assert(stack_ptr < BVH_QSTACK_SIZE);
+ traversal_stack[stack_ptr].addr = c2;
+ traversal_stack[stack_ptr].dist = d2;
+ qbvh_stack_sort(&traversal_stack[stack_ptr],
+ &traversal_stack[stack_ptr - 1],
+ &traversal_stack[stack_ptr - 2]);
+ node_addr = traversal_stack[stack_ptr].addr;
+ --stack_ptr;
+ continue;
+ }
+
+ /* Four children are hit, push all onto stack and sort 4
+ * stack items, continue with closest child.
+ */
+ r = __bscf(child_mask);
+ int c3 = __float_as_int(cnodes[r]);
+ float d3 = ((float *)&dist)[r];
+ ++stack_ptr;
+ kernel_assert(stack_ptr < BVH_QSTACK_SIZE);
+ traversal_stack[stack_ptr].addr = c3;
+ traversal_stack[stack_ptr].dist = d3;
+ ++stack_ptr;
+ kernel_assert(stack_ptr < BVH_QSTACK_SIZE);
+ traversal_stack[stack_ptr].addr = c2;
+ traversal_stack[stack_ptr].dist = d2;
+ qbvh_stack_sort(&traversal_stack[stack_ptr],
+ &traversal_stack[stack_ptr - 1],
+ &traversal_stack[stack_ptr - 2],
+ &traversal_stack[stack_ptr - 3]);
+ }
+
+ node_addr = traversal_stack[stack_ptr].addr;
+ --stack_ptr;
+ }
+
+ /* If node is leaf, fetch triangle list. */
+ if (node_addr < 0) {
+ float4 leaf = kernel_tex_fetch(__bvh_leaf_nodes, (-node_addr - 1));
#ifdef __VISIBILITY_FLAG__
- if((__float_as_uint(leaf.z) & visibility) == 0) {
- /* Pop. */
- node_addr = traversal_stack[stack_ptr].addr;
- --stack_ptr;
- continue;
- }
+ if ((__float_as_uint(leaf.z) & visibility) == 0) {
+ /* Pop. */
+ node_addr = traversal_stack[stack_ptr].addr;
+ --stack_ptr;
+ continue;
+ }
#endif
- int prim_addr = __float_as_int(leaf.x);
+ int prim_addr = __float_as_int(leaf.x);
#if BVH_FEATURE(BVH_INSTANCING)
- if(prim_addr >= 0) {
+ if (prim_addr >= 0) {
#endif
- int prim_addr2 = __float_as_int(leaf.y);
- const uint type = __float_as_int(leaf.w);
- const uint p_type = type & PRIMITIVE_ALL;
-
- /* Pop. */
- node_addr = traversal_stack[stack_ptr].addr;
- --stack_ptr;
-
- /* Primitive intersection. */
- while(prim_addr < prim_addr2) {
- kernel_assert((kernel_tex_fetch(__prim_type, prim_addr) & PRIMITIVE_ALL) == p_type);
- bool hit;
-
- /* todo: specialized intersect functions which don't fill in
- * isect unless needed and check SD_HAS_TRANSPARENT_SHADOW?
- * might give a few % performance improvement */
-
- switch(p_type) {
- case PRIMITIVE_TRIANGLE: {
- hit = triangle_intersect(kg,
- isect_array,
- P,
- dir,
- visibility,
- object,
- prim_addr);
- break;
- }
+ int prim_addr2 = __float_as_int(leaf.y);
+ const uint type = __float_as_int(leaf.w);
+ const uint p_type = type & PRIMITIVE_ALL;
+
+ /* Pop. */
+ node_addr = traversal_stack[stack_ptr].addr;
+ --stack_ptr;
+
+ /* Primitive intersection. */
+ while (prim_addr < prim_addr2) {
+ kernel_assert((kernel_tex_fetch(__prim_type, prim_addr) & PRIMITIVE_ALL) == p_type);
+ bool hit;
+
+ /* todo: specialized intersect functions which don't fill in
+ * isect unless needed and check SD_HAS_TRANSPARENT_SHADOW?
+ * might give a few % performance improvement */
+
+ switch (p_type) {
+ case PRIMITIVE_TRIANGLE: {
+ hit = triangle_intersect(kg, isect_array, P, dir, visibility, object, prim_addr);
+ break;
+ }
#if BVH_FEATURE(BVH_MOTION)
- case PRIMITIVE_MOTION_TRIANGLE: {
- hit = motion_triangle_intersect(kg,
- isect_array,
- P,
- dir,
- ray->time,
- visibility,
- object,
- prim_addr);
- break;
- }
+ case PRIMITIVE_MOTION_TRIANGLE: {
+ hit = motion_triangle_intersect(
+ kg, isect_array, P, dir, ray->time, visibility, object, prim_addr);
+ break;
+ }
#endif
#if BVH_FEATURE(BVH_HAIR)
- case PRIMITIVE_CURVE:
- case PRIMITIVE_MOTION_CURVE: {
- const uint curve_type = kernel_tex_fetch(__prim_type, prim_addr);
- if(kernel_data.curve.curveflags & CURVE_KN_INTERPOLATE) {
- hit = cardinal_curve_intersect(kg,
- isect_array,
- P,
- dir,
- visibility,
- object,
- prim_addr,
- ray->time,
- curve_type,
- NULL,
- 0, 0);
- }
- else {
- hit = curve_intersect(kg,
- isect_array,
- P,
- dir,
- visibility,
- object,
- prim_addr,
- ray->time,
- curve_type,
- NULL,
- 0, 0);
- }
- break;
- }
+ case PRIMITIVE_CURVE:
+ case PRIMITIVE_MOTION_CURVE: {
+ const uint curve_type = kernel_tex_fetch(__prim_type, prim_addr);
+ if (kernel_data.curve.curveflags & CURVE_KN_INTERPOLATE) {
+ hit = cardinal_curve_intersect(kg,
+ isect_array,
+ P,
+ dir,
+ visibility,
+ object,
+ prim_addr,
+ ray->time,
+ curve_type,
+ NULL,
+ 0,
+ 0);
+ }
+ else {
+ hit = curve_intersect(kg,
+ isect_array,
+ P,
+ dir,
+ visibility,
+ object,
+ prim_addr,
+ ray->time,
+ curve_type,
+ NULL,
+ 0,
+ 0);
+ }
+ break;
+ }
#endif
- default: {
- hit = false;
- break;
- }
- }
+ default: {
+ hit = false;
+ break;
+ }
+ }
- /* Shadow ray early termination. */
- if(hit) {
- /* detect if this surface has a shader with transparent shadows */
+ /* Shadow ray early termination. */
+ if (hit) {
+ /* detect if this surface has a shader with transparent shadows */
- /* todo: optimize so primitive visibility flag indicates if
- * the primitive has a transparent shadow shader? */
- int prim = kernel_tex_fetch(__prim_index, isect_array->prim);
- int shader = 0;
+ /* todo: optimize so primitive visibility flag indicates if
+ * the primitive has a transparent shadow shader? */
+ int prim = kernel_tex_fetch(__prim_index, isect_array->prim);
+ int shader = 0;
#ifdef __HAIR__
- if(kernel_tex_fetch(__prim_type, isect_array->prim) & PRIMITIVE_ALL_TRIANGLE)
+ if (kernel_tex_fetch(__prim_type, isect_array->prim) & PRIMITIVE_ALL_TRIANGLE)
#endif
- {
- shader = kernel_tex_fetch(__tri_shader, prim);
- }
+ {
+ shader = kernel_tex_fetch(__tri_shader, prim);
+ }
#ifdef __HAIR__
- else {
- float4 str = kernel_tex_fetch(__curves, prim);
- shader = __float_as_int(str.z);
- }
+ else {
+ float4 str = kernel_tex_fetch(__curves, prim);
+ shader = __float_as_int(str.z);
+ }
#endif
- int flag = kernel_tex_fetch(__shaders, (shader & SHADER_MASK)).flags;
-
- /* if no transparent shadows, all light is blocked */
- if(!(flag & SD_HAS_TRANSPARENT_SHADOW)) {
- return true;
- }
- /* if maximum number of hits reached, block all light */
- else if(*num_hits == max_hits) {
- return true;
- }
-
- /* move on to next entry in intersections array */
- isect_array++;
- (*num_hits)++;
+ int flag = kernel_tex_fetch(__shaders, (shader & SHADER_MASK)).flags;
+
+ /* if no transparent shadows, all light is blocked */
+ if (!(flag & SD_HAS_TRANSPARENT_SHADOW)) {
+ return true;
+ }
+ /* if maximum number of hits reached, block all light */
+ else if (*num_hits == max_hits) {
+ return true;
+ }
+
+ /* move on to next entry in intersections array */
+ isect_array++;
+ (*num_hits)++;
#if BVH_FEATURE(BVH_INSTANCING)
- num_hits_in_instance++;
+ num_hits_in_instance++;
#endif
- isect_array->t = isect_t;
- }
+ isect_array->t = isect_t;
+ }
- prim_addr++;
- }
- }
+ prim_addr++;
+ }
+ }
#if BVH_FEATURE(BVH_INSTANCING)
- else {
- /* Instance push. */
- object = kernel_tex_fetch(__prim_object, -prim_addr-1);
+ else {
+ /* Instance push. */
+ object = kernel_tex_fetch(__prim_object, -prim_addr - 1);
# if BVH_FEATURE(BVH_MOTION)
- isect_t = bvh_instance_motion_push(kg, object, ray, &P, &dir, &idir, isect_t, &ob_itfm);
+ isect_t = bvh_instance_motion_push(kg, object, ray, &P, &dir, &idir, isect_t, &ob_itfm);
# else
- isect_t = bvh_instance_push(kg, object, ray, &P, &dir, &idir, isect_t);
+ isect_t = bvh_instance_push(kg, object, ray, &P, &dir, &idir, isect_t);
# endif
- num_hits_in_instance = 0;
- isect_array->t = isect_t;
+ num_hits_in_instance = 0;
+ isect_array->t = isect_t;
- qbvh_near_far_idx_calc(idir,
- &near_x, &near_y, &near_z,
- &far_x, &far_y, &far_z);
- tfar = ssef(isect_t);
+ qbvh_near_far_idx_calc(idir, &near_x, &near_y, &near_z, &far_x, &far_y, &far_z);
+ tfar = ssef(isect_t);
# if BVH_FEATURE(BVH_HAIR)
- dir4 = sse3f(ssef(dir.x), ssef(dir.y), ssef(dir.z));
+ dir4 = sse3f(ssef(dir.x), ssef(dir.y), ssef(dir.z));
# endif
- idir4 = sse3f(ssef(idir.x), ssef(idir.y), ssef(idir.z));
+ idir4 = sse3f(ssef(idir.x), ssef(idir.y), ssef(idir.z));
# ifdef __KERNEL_AVX2__
- P_idir = P*idir;
- P_idir4 = sse3f(P_idir.x, P_idir.y, P_idir.z);
+ P_idir = P * idir;
+ P_idir4 = sse3f(P_idir.x, P_idir.y, P_idir.z);
# endif
# if BVH_FEATURE(BVH_HAIR) || !defined(__KERNEL_AVX2__)
- org4 = sse3f(ssef(P.x), ssef(P.y), ssef(P.z));
+ org4 = sse3f(ssef(P.x), ssef(P.y), ssef(P.z));
# endif
- ++stack_ptr;
- kernel_assert(stack_ptr < BVH_QSTACK_SIZE);
- traversal_stack[stack_ptr].addr = ENTRYPOINT_SENTINEL;
-
- node_addr = kernel_tex_fetch(__object_node, object);
+ ++stack_ptr;
+ kernel_assert(stack_ptr < BVH_QSTACK_SIZE);
+ traversal_stack[stack_ptr].addr = ENTRYPOINT_SENTINEL;
- }
- }
-#endif /* FEATURE(BVH_INSTANCING) */
- } while(node_addr != ENTRYPOINT_SENTINEL);
+ node_addr = kernel_tex_fetch(__object_node, object);
+ }
+ }
+#endif /* FEATURE(BVH_INSTANCING) */
+ } while (node_addr != ENTRYPOINT_SENTINEL);
#if BVH_FEATURE(BVH_INSTANCING)
- if(stack_ptr >= 0) {
- kernel_assert(object != OBJECT_NONE);
+ if (stack_ptr >= 0) {
+ kernel_assert(object != OBJECT_NONE);
- /* Instance pop. */
- if(num_hits_in_instance) {
- float t_fac;
+ /* Instance pop. */
+ if (num_hits_in_instance) {
+ float t_fac;
# if BVH_FEATURE(BVH_MOTION)
- bvh_instance_motion_pop_factor(kg, object, ray, &P, &dir, &idir, &t_fac, &ob_itfm);
+ bvh_instance_motion_pop_factor(kg, object, ray, &P, &dir, &idir, &t_fac, &ob_itfm);
# else
- bvh_instance_pop_factor(kg, object, ray, &P, &dir, &idir, &t_fac);
+ bvh_instance_pop_factor(kg, object, ray, &P, &dir, &idir, &t_fac);
# endif
- /* Scale isect->t to adjust for instancing. */
- for(int i = 0; i < num_hits_in_instance; i++) {
- (isect_array-i-1)->t *= t_fac;
- }
- }
- else {
+ /* Scale isect->t to adjust for instancing. */
+ for (int i = 0; i < num_hits_in_instance; i++) {
+ (isect_array - i - 1)->t *= t_fac;
+ }
+ }
+ else {
# if BVH_FEATURE(BVH_MOTION)
- bvh_instance_motion_pop(kg, object, ray, &P, &dir, &idir, FLT_MAX, &ob_itfm);
+ bvh_instance_motion_pop(kg, object, ray, &P, &dir, &idir, FLT_MAX, &ob_itfm);
# else
- bvh_instance_pop(kg, object, ray, &P, &dir, &idir, FLT_MAX);
+ bvh_instance_pop(kg, object, ray, &P, &dir, &idir, FLT_MAX);
# endif
- }
+ }
- isect_t = tmax;
- isect_array->t = isect_t;
+ isect_t = tmax;
+ isect_array->t = isect_t;
- qbvh_near_far_idx_calc(idir,
- &near_x, &near_y, &near_z,
- &far_x, &far_y, &far_z);
- tfar = ssef(isect_t);
+ qbvh_near_far_idx_calc(idir, &near_x, &near_y, &near_z, &far_x, &far_y, &far_z);
+ tfar = ssef(isect_t);
# if BVH_FEATURE(BVH_HAIR)
- dir4 = sse3f(ssef(dir.x), ssef(dir.y), ssef(dir.z));
+ dir4 = sse3f(ssef(dir.x), ssef(dir.y), ssef(dir.z));
# endif
- idir4 = sse3f(ssef(idir.x), ssef(idir.y), ssef(idir.z));
+ idir4 = sse3f(ssef(idir.x), ssef(idir.y), ssef(idir.z));
# ifdef __KERNEL_AVX2__
- P_idir = P*idir;
- P_idir4 = sse3f(P_idir.x, P_idir.y, P_idir.z);
+ P_idir = P * idir;
+ P_idir4 = sse3f(P_idir.x, P_idir.y, P_idir.z);
# endif
# if BVH_FEATURE(BVH_HAIR) || !defined(__KERNEL_AVX2__)
- org4 = sse3f(ssef(P.x), ssef(P.y), ssef(P.z));
+ org4 = sse3f(ssef(P.x), ssef(P.y), ssef(P.z));
# endif
- object = OBJECT_NONE;
- node_addr = traversal_stack[stack_ptr].addr;
- --stack_ptr;
- }
-#endif /* FEATURE(BVH_INSTANCING) */
- } while(node_addr != ENTRYPOINT_SENTINEL);
+ object = OBJECT_NONE;
+ node_addr = traversal_stack[stack_ptr].addr;
+ --stack_ptr;
+ }
+#endif /* FEATURE(BVH_INSTANCING) */
+ } while (node_addr != ENTRYPOINT_SENTINEL);
- return false;
+ return false;
}
#undef NODE_INTERSECT
diff --git a/intern/cycles/kernel/bvh/qbvh_traversal.h b/intern/cycles/kernel/bvh/qbvh_traversal.h
index 40cd57aad34..9ee0f7b5933 100644
--- a/intern/cycles/kernel/bvh/qbvh_traversal.h
+++ b/intern/cycles/kernel/bvh/qbvh_traversal.h
@@ -37,457 +37,446 @@ ccl_device bool BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg,
Intersection *isect,
const uint visibility
#if BVH_FEATURE(BVH_HAIR_MINIMUM_WIDTH)
- ,uint *lcg_state,
+ ,
+ uint *lcg_state,
float difl,
float extmax
#endif
- )
+)
{
- /* TODO(sergey):
- * - Test if pushing distance on the stack helps (for non shadow rays).
- * - Separate version for shadow rays.
- * - Likely and unlikely for if() statements.
- * - Test restrict attribute for pointers.
- */
-
- /* Traversal stack in CUDA thread-local memory. */
- QBVHStackItem traversal_stack[BVH_QSTACK_SIZE];
- traversal_stack[0].addr = ENTRYPOINT_SENTINEL;
- traversal_stack[0].dist = -FLT_MAX;
-
- /* Traversal variables in registers. */
- int stack_ptr = 0;
- int node_addr = kernel_data.bvh.root;
- float node_dist = -FLT_MAX;
-
- /* Ray parameters in registers. */
- float3 P = ray->P;
- float3 dir = bvh_clamp_direction(ray->D);
- float3 idir = bvh_inverse_direction(dir);
- int object = OBJECT_NONE;
+ /* TODO(sergey):
+ * - Test if pushing distance on the stack helps (for non shadow rays).
+ * - Separate version for shadow rays.
+ * - Likely and unlikely for if() statements.
+ * - Test restrict attribute for pointers.
+ */
+
+ /* Traversal stack in CUDA thread-local memory. */
+ QBVHStackItem traversal_stack[BVH_QSTACK_SIZE];
+ traversal_stack[0].addr = ENTRYPOINT_SENTINEL;
+ traversal_stack[0].dist = -FLT_MAX;
+
+ /* Traversal variables in registers. */
+ int stack_ptr = 0;
+ int node_addr = kernel_data.bvh.root;
+ float node_dist = -FLT_MAX;
+
+ /* Ray parameters in registers. */
+ float3 P = ray->P;
+ float3 dir = bvh_clamp_direction(ray->D);
+ float3 idir = bvh_inverse_direction(dir);
+ int object = OBJECT_NONE;
#if BVH_FEATURE(BVH_MOTION)
- Transform ob_itfm;
+ Transform ob_itfm;
#endif
- isect->t = ray->t;
- isect->u = 0.0f;
- isect->v = 0.0f;
- isect->prim = PRIM_NONE;
- isect->object = OBJECT_NONE;
+ isect->t = ray->t;
+ isect->u = 0.0f;
+ isect->v = 0.0f;
+ isect->prim = PRIM_NONE;
+ isect->object = OBJECT_NONE;
- BVH_DEBUG_INIT();
+ BVH_DEBUG_INIT();
- ssef tnear(0.0f), tfar(ray->t);
+ ssef tnear(0.0f), tfar(ray->t);
#if BVH_FEATURE(BVH_HAIR)
- sse3f dir4(ssef(dir.x), ssef(dir.y), ssef(dir.z));
+ sse3f dir4(ssef(dir.x), ssef(dir.y), ssef(dir.z));
#endif
- sse3f idir4(ssef(idir.x), ssef(idir.y), ssef(idir.z));
+ sse3f idir4(ssef(idir.x), ssef(idir.y), ssef(idir.z));
#ifdef __KERNEL_AVX2__
- float3 P_idir = P*idir;
- sse3f P_idir4 = sse3f(P_idir.x, P_idir.y, P_idir.z);
+ float3 P_idir = P * idir;
+ sse3f P_idir4 = sse3f(P_idir.x, P_idir.y, P_idir.z);
#endif
#if BVH_FEATURE(BVH_HAIR) || !defined(__KERNEL_AVX2__)
- sse3f org4 = sse3f(ssef(P.x), ssef(P.y), ssef(P.z));
+ sse3f org4 = sse3f(ssef(P.x), ssef(P.y), ssef(P.z));
#endif
- /* Offsets to select the side that becomes the lower or upper bound. */
- int near_x, near_y, near_z;
- int far_x, far_y, far_z;
- qbvh_near_far_idx_calc(idir,
- &near_x, &near_y, &near_z,
- &far_x, &far_y, &far_z);
-
- /* Traversal loop. */
- do {
- do {
- /* Traverse internal nodes. */
- while(node_addr >= 0 && node_addr != ENTRYPOINT_SENTINEL) {
- float4 inodes = kernel_tex_fetch(__bvh_nodes, node_addr+0);
- (void) inodes;
-
- if(UNLIKELY(node_dist > isect->t)
+ /* Offsets to select the side that becomes the lower or upper bound. */
+ int near_x, near_y, near_z;
+ int far_x, far_y, far_z;
+ qbvh_near_far_idx_calc(idir, &near_x, &near_y, &near_z, &far_x, &far_y, &far_z);
+
+ /* Traversal loop. */
+ do {
+ do {
+ /* Traverse internal nodes. */
+ while (node_addr >= 0 && node_addr != ENTRYPOINT_SENTINEL) {
+ float4 inodes = kernel_tex_fetch(__bvh_nodes, node_addr + 0);
+ (void)inodes;
+
+ if (UNLIKELY(node_dist > isect->t)
#if BVH_FEATURE(BVH_MOTION)
- || UNLIKELY(ray->time < inodes.y)
- || UNLIKELY(ray->time > inodes.z)
+ || UNLIKELY(ray->time < inodes.y) || UNLIKELY(ray->time > inodes.z)
#endif
#ifdef __VISIBILITY_FLAG__
- || (__float_as_uint(inodes.x) & visibility) == 0
+ || (__float_as_uint(inodes.x) & visibility) == 0
#endif
- )
- {
- /* Pop. */
- node_addr = traversal_stack[stack_ptr].addr;
- node_dist = traversal_stack[stack_ptr].dist;
- --stack_ptr;
- continue;
- }
+ ) {
+ /* Pop. */
+ node_addr = traversal_stack[stack_ptr].addr;
+ node_dist = traversal_stack[stack_ptr].dist;
+ --stack_ptr;
+ continue;
+ }
- int child_mask;
- ssef dist;
+ int child_mask;
+ ssef dist;
- BVH_DEBUG_NEXT_NODE();
+ BVH_DEBUG_NEXT_NODE();
#if BVH_FEATURE(BVH_HAIR_MINIMUM_WIDTH)
- if(difl != 0.0f) {
- /* NOTE: We extend all the child BB instead of fetching
- * and checking visibility flags for each of the,
- *
- * Need to test if doing opposite would be any faster.
- */
- child_mask = NODE_INTERSECT_ROBUST(kg,
- tnear,
- tfar,
+ if (difl != 0.0f) {
+ /* NOTE: We extend all the child BB instead of fetching
+ * and checking visibility flags for each of the,
+ *
+ * Need to test if doing opposite would be any faster.
+ */
+ child_mask = NODE_INTERSECT_ROBUST(kg,
+ tnear,
+ tfar,
# ifdef __KERNEL_AVX2__
- P_idir4,
+ P_idir4,
# endif
# if BVH_FEATURE(BVH_HAIR) || !defined(__KERNEL_AVX2__)
- org4,
+ org4,
# endif
# if BVH_FEATURE(BVH_HAIR)
- dir4,
+ dir4,
# endif
- idir4,
- near_x, near_y, near_z,
- far_x, far_y, far_z,
- node_addr,
- difl,
- &dist);
- }
- else
-#endif /* BVH_HAIR_MINIMUM_WIDTH */
- {
- child_mask = NODE_INTERSECT(kg,
- tnear,
- tfar,
+ idir4,
+ near_x,
+ near_y,
+ near_z,
+ far_x,
+ far_y,
+ far_z,
+ node_addr,
+ difl,
+ &dist);
+ }
+ else
+#endif /* BVH_HAIR_MINIMUM_WIDTH */
+ {
+ child_mask = NODE_INTERSECT(kg,
+ tnear,
+ tfar,
#ifdef __KERNEL_AVX2__
- P_idir4,
+ P_idir4,
#endif
#if BVH_FEATURE(BVH_HAIR) || !defined(__KERNEL_AVX2__)
- org4,
+ org4,
#endif
#if BVH_FEATURE(BVH_HAIR)
- dir4,
+ dir4,
#endif
- idir4,
- near_x, near_y, near_z,
- far_x, far_y, far_z,
- node_addr,
- &dist);
- }
-
- if(child_mask != 0) {
- float4 cnodes;
- /* TODO(sergey): Investigate whether moving cnodes upwards
- * gives a speedup (will be different cache pattern but will
- * avoid extra check here).
- */
+ idir4,
+ near_x,
+ near_y,
+ near_z,
+ far_x,
+ far_y,
+ far_z,
+ node_addr,
+ &dist);
+ }
+
+ if (child_mask != 0) {
+ float4 cnodes;
+ /* TODO(sergey): Investigate whether moving cnodes upwards
+ * gives a speedup (will be different cache pattern but will
+ * avoid extra check here).
+ */
#if BVH_FEATURE(BVH_HAIR)
- if(__float_as_uint(inodes.x) & PATH_RAY_NODE_UNALIGNED) {
- cnodes = kernel_tex_fetch(__bvh_nodes, node_addr+13);
- }
- else
+ if (__float_as_uint(inodes.x) & PATH_RAY_NODE_UNALIGNED) {
+ cnodes = kernel_tex_fetch(__bvh_nodes, node_addr + 13);
+ }
+ else
#endif
- {
- cnodes = kernel_tex_fetch(__bvh_nodes, node_addr+7);
- }
-
- /* One child is hit, continue with that child. */
- int r = __bscf(child_mask);
- float d0 = ((float*)&dist)[r];
- if(child_mask == 0) {
- node_addr = __float_as_int(cnodes[r]);
- node_dist = d0;
- continue;
- }
-
- /* Two children are hit, push far child, and continue with
- * closer child.
- */
- int c0 = __float_as_int(cnodes[r]);
- r = __bscf(child_mask);
- int c1 = __float_as_int(cnodes[r]);
- float d1 = ((float*)&dist)[r];
- if(child_mask == 0) {
- if(d1 < d0) {
- node_addr = c1;
- node_dist = d1;
- ++stack_ptr;
- kernel_assert(stack_ptr < BVH_QSTACK_SIZE);
- traversal_stack[stack_ptr].addr = c0;
- traversal_stack[stack_ptr].dist = d0;
- continue;
- }
- else {
- node_addr = c0;
- node_dist = d0;
- ++stack_ptr;
- kernel_assert(stack_ptr < BVH_QSTACK_SIZE);
- traversal_stack[stack_ptr].addr = c1;
- traversal_stack[stack_ptr].dist = d1;
- continue;
- }
- }
-
- /* Here starts the slow path for 3 or 4 hit children. We push
- * all nodes onto the stack to sort them there.
- */
- ++stack_ptr;
- kernel_assert(stack_ptr < BVH_QSTACK_SIZE);
- traversal_stack[stack_ptr].addr = c1;
- traversal_stack[stack_ptr].dist = d1;
- ++stack_ptr;
- kernel_assert(stack_ptr < BVH_QSTACK_SIZE);
- traversal_stack[stack_ptr].addr = c0;
- traversal_stack[stack_ptr].dist = d0;
-
- /* Three children are hit, push all onto stack and sort 3
- * stack items, continue with closest child.
- */
- r = __bscf(child_mask);
- int c2 = __float_as_int(cnodes[r]);
- float d2 = ((float*)&dist)[r];
- if(child_mask == 0) {
- ++stack_ptr;
- kernel_assert(stack_ptr < BVH_QSTACK_SIZE);
- traversal_stack[stack_ptr].addr = c2;
- traversal_stack[stack_ptr].dist = d2;
- qbvh_stack_sort(&traversal_stack[stack_ptr],
- &traversal_stack[stack_ptr - 1],
- &traversal_stack[stack_ptr - 2]);
- node_addr = traversal_stack[stack_ptr].addr;
- node_dist = traversal_stack[stack_ptr].dist;
- --stack_ptr;
- continue;
- }
-
- /* Four children are hit, push all onto stack and sort 4
- * stack items, continue with closest child.
- */
- r = __bscf(child_mask);
- int c3 = __float_as_int(cnodes[r]);
- float d3 = ((float*)&dist)[r];
- ++stack_ptr;
- kernel_assert(stack_ptr < BVH_QSTACK_SIZE);
- traversal_stack[stack_ptr].addr = c3;
- traversal_stack[stack_ptr].dist = d3;
- ++stack_ptr;
- kernel_assert(stack_ptr < BVH_QSTACK_SIZE);
- traversal_stack[stack_ptr].addr = c2;
- traversal_stack[stack_ptr].dist = d2;
- qbvh_stack_sort(&traversal_stack[stack_ptr],
- &traversal_stack[stack_ptr - 1],
- &traversal_stack[stack_ptr - 2],
- &traversal_stack[stack_ptr - 3]);
- }
-
- node_addr = traversal_stack[stack_ptr].addr;
- node_dist = traversal_stack[stack_ptr].dist;
- --stack_ptr;
- }
-
- /* If node is leaf, fetch triangle list. */
- if(node_addr < 0) {
- float4 leaf = kernel_tex_fetch(__bvh_leaf_nodes, (-node_addr-1));
+ {
+ cnodes = kernel_tex_fetch(__bvh_nodes, node_addr + 7);
+ }
+
+ /* One child is hit, continue with that child. */
+ int r = __bscf(child_mask);
+ float d0 = ((float *)&dist)[r];
+ if (child_mask == 0) {
+ node_addr = __float_as_int(cnodes[r]);
+ node_dist = d0;
+ continue;
+ }
+
+ /* Two children are hit, push far child, and continue with
+ * closer child.
+ */
+ int c0 = __float_as_int(cnodes[r]);
+ r = __bscf(child_mask);
+ int c1 = __float_as_int(cnodes[r]);
+ float d1 = ((float *)&dist)[r];
+ if (child_mask == 0) {
+ if (d1 < d0) {
+ node_addr = c1;
+ node_dist = d1;
+ ++stack_ptr;
+ kernel_assert(stack_ptr < BVH_QSTACK_SIZE);
+ traversal_stack[stack_ptr].addr = c0;
+ traversal_stack[stack_ptr].dist = d0;
+ continue;
+ }
+ else {
+ node_addr = c0;
+ node_dist = d0;
+ ++stack_ptr;
+ kernel_assert(stack_ptr < BVH_QSTACK_SIZE);
+ traversal_stack[stack_ptr].addr = c1;
+ traversal_stack[stack_ptr].dist = d1;
+ continue;
+ }
+ }
+
+ /* Here starts the slow path for 3 or 4 hit children. We push
+ * all nodes onto the stack to sort them there.
+ */
+ ++stack_ptr;
+ kernel_assert(stack_ptr < BVH_QSTACK_SIZE);
+ traversal_stack[stack_ptr].addr = c1;
+ traversal_stack[stack_ptr].dist = d1;
+ ++stack_ptr;
+ kernel_assert(stack_ptr < BVH_QSTACK_SIZE);
+ traversal_stack[stack_ptr].addr = c0;
+ traversal_stack[stack_ptr].dist = d0;
+
+ /* Three children are hit, push all onto stack and sort 3
+ * stack items, continue with closest child.
+ */
+ r = __bscf(child_mask);
+ int c2 = __float_as_int(cnodes[r]);
+ float d2 = ((float *)&dist)[r];
+ if (child_mask == 0) {
+ ++stack_ptr;
+ kernel_assert(stack_ptr < BVH_QSTACK_SIZE);
+ traversal_stack[stack_ptr].addr = c2;
+ traversal_stack[stack_ptr].dist = d2;
+ qbvh_stack_sort(&traversal_stack[stack_ptr],
+ &traversal_stack[stack_ptr - 1],
+ &traversal_stack[stack_ptr - 2]);
+ node_addr = traversal_stack[stack_ptr].addr;
+ node_dist = traversal_stack[stack_ptr].dist;
+ --stack_ptr;
+ continue;
+ }
+
+ /* Four children are hit, push all onto stack and sort 4
+ * stack items, continue with closest child.
+ */
+ r = __bscf(child_mask);
+ int c3 = __float_as_int(cnodes[r]);
+ float d3 = ((float *)&dist)[r];
+ ++stack_ptr;
+ kernel_assert(stack_ptr < BVH_QSTACK_SIZE);
+ traversal_stack[stack_ptr].addr = c3;
+ traversal_stack[stack_ptr].dist = d3;
+ ++stack_ptr;
+ kernel_assert(stack_ptr < BVH_QSTACK_SIZE);
+ traversal_stack[stack_ptr].addr = c2;
+ traversal_stack[stack_ptr].dist = d2;
+ qbvh_stack_sort(&traversal_stack[stack_ptr],
+ &traversal_stack[stack_ptr - 1],
+ &traversal_stack[stack_ptr - 2],
+ &traversal_stack[stack_ptr - 3]);
+ }
+
+ node_addr = traversal_stack[stack_ptr].addr;
+ node_dist = traversal_stack[stack_ptr].dist;
+ --stack_ptr;
+ }
+
+ /* If node is leaf, fetch triangle list. */
+ if (node_addr < 0) {
+ float4 leaf = kernel_tex_fetch(__bvh_leaf_nodes, (-node_addr - 1));
#ifdef __VISIBILITY_FLAG__
- if(UNLIKELY((node_dist > isect->t) ||
- ((__float_as_uint(leaf.z) & visibility) == 0)))
+ if (UNLIKELY((node_dist > isect->t) || ((__float_as_uint(leaf.z) & visibility) == 0)))
#else
- if(UNLIKELY((node_dist > isect->t)))
+ if (UNLIKELY((node_dist > isect->t)))
#endif
- {
- /* Pop. */
- node_addr = traversal_stack[stack_ptr].addr;
- node_dist = traversal_stack[stack_ptr].dist;
- --stack_ptr;
- continue;
- }
+ {
+ /* Pop. */
+ node_addr = traversal_stack[stack_ptr].addr;
+ node_dist = traversal_stack[stack_ptr].dist;
+ --stack_ptr;
+ continue;
+ }
- int prim_addr = __float_as_int(leaf.x);
+ int prim_addr = __float_as_int(leaf.x);
#if BVH_FEATURE(BVH_INSTANCING)
- if(prim_addr >= 0) {
+ if (prim_addr >= 0) {
#endif
- int prim_addr2 = __float_as_int(leaf.y);
- const uint type = __float_as_int(leaf.w);
-
- /* Pop. */
- node_addr = traversal_stack[stack_ptr].addr;
- node_dist = traversal_stack[stack_ptr].dist;
- --stack_ptr;
-
- /* Primitive intersection. */
- switch(type & PRIMITIVE_ALL) {
- case PRIMITIVE_TRIANGLE: {
- for(; prim_addr < prim_addr2; prim_addr++) {
- BVH_DEBUG_NEXT_INTERSECTION();
- kernel_assert(kernel_tex_fetch(__prim_type, prim_addr) == type);
- if(triangle_intersect(kg,
- isect,
- P,
- dir,
- visibility,
- object,
- prim_addr)) {
- tfar = ssef(isect->t);
- /* Shadow ray early termination. */
- if(visibility & PATH_RAY_SHADOW_OPAQUE) {
- return true;
- }
- }
- }
- break;
- }
+ int prim_addr2 = __float_as_int(leaf.y);
+ const uint type = __float_as_int(leaf.w);
+
+ /* Pop. */
+ node_addr = traversal_stack[stack_ptr].addr;
+ node_dist = traversal_stack[stack_ptr].dist;
+ --stack_ptr;
+
+ /* Primitive intersection. */
+ switch (type & PRIMITIVE_ALL) {
+ case PRIMITIVE_TRIANGLE: {
+ for (; prim_addr < prim_addr2; prim_addr++) {
+ BVH_DEBUG_NEXT_INTERSECTION();
+ kernel_assert(kernel_tex_fetch(__prim_type, prim_addr) == type);
+ if (triangle_intersect(kg, isect, P, dir, visibility, object, prim_addr)) {
+ tfar = ssef(isect->t);
+ /* Shadow ray early termination. */
+ if (visibility & PATH_RAY_SHADOW_OPAQUE) {
+ return true;
+ }
+ }
+ }
+ break;
+ }
#if BVH_FEATURE(BVH_MOTION)
- case PRIMITIVE_MOTION_TRIANGLE: {
- for(; prim_addr < prim_addr2; prim_addr++) {
- BVH_DEBUG_NEXT_INTERSECTION();
- kernel_assert(kernel_tex_fetch(__prim_type, prim_addr) == type);
- if(motion_triangle_intersect(kg,
- isect,
- P,
- dir,
- ray->time,
- visibility,
- object,
- prim_addr)) {
- tfar = ssef(isect->t);
- /* Shadow ray early termination. */
- if(visibility & PATH_RAY_SHADOW_OPAQUE) {
- return true;
- }
- }
- }
- break;
- }
-#endif /* BVH_FEATURE(BVH_MOTION) */
+ case PRIMITIVE_MOTION_TRIANGLE: {
+ for (; prim_addr < prim_addr2; prim_addr++) {
+ BVH_DEBUG_NEXT_INTERSECTION();
+ kernel_assert(kernel_tex_fetch(__prim_type, prim_addr) == type);
+ if (motion_triangle_intersect(
+ kg, isect, P, dir, ray->time, visibility, object, prim_addr)) {
+ tfar = ssef(isect->t);
+ /* Shadow ray early termination. */
+ if (visibility & PATH_RAY_SHADOW_OPAQUE) {
+ return true;
+ }
+ }
+ }
+ break;
+ }
+#endif /* BVH_FEATURE(BVH_MOTION) */
#if BVH_FEATURE(BVH_HAIR)
- case PRIMITIVE_CURVE:
- case PRIMITIVE_MOTION_CURVE: {
- for(; prim_addr < prim_addr2; prim_addr++) {
- BVH_DEBUG_NEXT_INTERSECTION();
- const uint curve_type = kernel_tex_fetch(__prim_type, prim_addr);
- kernel_assert((curve_type & PRIMITIVE_ALL) == (type & PRIMITIVE_ALL));
- bool hit;
- if(kernel_data.curve.curveflags & CURVE_KN_INTERPOLATE) {
- hit = cardinal_curve_intersect(kg,
- isect,
- P,
- dir,
- visibility,
- object,
- prim_addr,
- ray->time,
- curve_type,
- lcg_state,
- difl,
- extmax);
- }
- else {
- hit = curve_intersect(kg,
- isect,
- P,
- dir,
- visibility,
- object,
- prim_addr,
- ray->time,
- curve_type,
- lcg_state,
- difl,
- extmax);
- }
- if(hit) {
- tfar = ssef(isect->t);
- /* Shadow ray early termination. */
- if(visibility & PATH_RAY_SHADOW_OPAQUE) {
- return true;
- }
- }
- }
- break;
- }
-#endif /* BVH_FEATURE(BVH_HAIR) */
- }
- }
+ case PRIMITIVE_CURVE:
+ case PRIMITIVE_MOTION_CURVE: {
+ for (; prim_addr < prim_addr2; prim_addr++) {
+ BVH_DEBUG_NEXT_INTERSECTION();
+ const uint curve_type = kernel_tex_fetch(__prim_type, prim_addr);
+ kernel_assert((curve_type & PRIMITIVE_ALL) == (type & PRIMITIVE_ALL));
+ bool hit;
+ if (kernel_data.curve.curveflags & CURVE_KN_INTERPOLATE) {
+ hit = cardinal_curve_intersect(kg,
+ isect,
+ P,
+ dir,
+ visibility,
+ object,
+ prim_addr,
+ ray->time,
+ curve_type,
+ lcg_state,
+ difl,
+ extmax);
+ }
+ else {
+ hit = curve_intersect(kg,
+ isect,
+ P,
+ dir,
+ visibility,
+ object,
+ prim_addr,
+ ray->time,
+ curve_type,
+ lcg_state,
+ difl,
+ extmax);
+ }
+ if (hit) {
+ tfar = ssef(isect->t);
+ /* Shadow ray early termination. */
+ if (visibility & PATH_RAY_SHADOW_OPAQUE) {
+ return true;
+ }
+ }
+ }
+ break;
+ }
+#endif /* BVH_FEATURE(BVH_HAIR) */
+ }
+ }
#if BVH_FEATURE(BVH_INSTANCING)
- else {
- /* Instance push. */
- object = kernel_tex_fetch(__prim_object, -prim_addr-1);
+ else {
+ /* Instance push. */
+ object = kernel_tex_fetch(__prim_object, -prim_addr - 1);
# if BVH_FEATURE(BVH_MOTION)
- qbvh_instance_motion_push(kg, object, ray, &P, &dir, &idir, &isect->t, &node_dist, &ob_itfm);
+ qbvh_instance_motion_push(
+ kg, object, ray, &P, &dir, &idir, &isect->t, &node_dist, &ob_itfm);
# else
- qbvh_instance_push(kg, object, ray, &P, &dir, &idir, &isect->t, &node_dist);
+ qbvh_instance_push(kg, object, ray, &P, &dir, &idir, &isect->t, &node_dist);
# endif
- qbvh_near_far_idx_calc(idir,
- &near_x, &near_y, &near_z,
- &far_x, &far_y, &far_z);
- tfar = ssef(isect->t);
+ qbvh_near_far_idx_calc(idir, &near_x, &near_y, &near_z, &far_x, &far_y, &far_z);
+ tfar = ssef(isect->t);
# if BVH_FEATURE(BVH_HAIR)
- dir4 = sse3f(ssef(dir.x), ssef(dir.y), ssef(dir.z));
+ dir4 = sse3f(ssef(dir.x), ssef(dir.y), ssef(dir.z));
# endif
- idir4 = sse3f(ssef(idir.x), ssef(idir.y), ssef(idir.z));
+ idir4 = sse3f(ssef(idir.x), ssef(idir.y), ssef(idir.z));
# ifdef __KERNEL_AVX2__
- P_idir = P*idir;
- P_idir4 = sse3f(P_idir.x, P_idir.y, P_idir.z);
+ P_idir = P * idir;
+ P_idir4 = sse3f(P_idir.x, P_idir.y, P_idir.z);
# endif
# if BVH_FEATURE(BVH_HAIR) || !defined(__KERNEL_AVX2__)
- org4 = sse3f(ssef(P.x), ssef(P.y), ssef(P.z));
+ org4 = sse3f(ssef(P.x), ssef(P.y), ssef(P.z));
# endif
- ++stack_ptr;
- kernel_assert(stack_ptr < BVH_QSTACK_SIZE);
- traversal_stack[stack_ptr].addr = ENTRYPOINT_SENTINEL;
- traversal_stack[stack_ptr].dist = -FLT_MAX;
+ ++stack_ptr;
+ kernel_assert(stack_ptr < BVH_QSTACK_SIZE);
+ traversal_stack[stack_ptr].addr = ENTRYPOINT_SENTINEL;
+ traversal_stack[stack_ptr].dist = -FLT_MAX;
- node_addr = kernel_tex_fetch(__object_node, object);
+ node_addr = kernel_tex_fetch(__object_node, object);
- BVH_DEBUG_NEXT_INSTANCE();
- }
- }
-#endif /* FEATURE(BVH_INSTANCING) */
- } while(node_addr != ENTRYPOINT_SENTINEL);
+ BVH_DEBUG_NEXT_INSTANCE();
+ }
+ }
+#endif /* FEATURE(BVH_INSTANCING) */
+ } while (node_addr != ENTRYPOINT_SENTINEL);
#if BVH_FEATURE(BVH_INSTANCING)
- if(stack_ptr >= 0) {
- kernel_assert(object != OBJECT_NONE);
+ if (stack_ptr >= 0) {
+ kernel_assert(object != OBJECT_NONE);
- /* Instance pop. */
+ /* Instance pop. */
# if BVH_FEATURE(BVH_MOTION)
- isect->t = bvh_instance_motion_pop(kg, object, ray, &P, &dir, &idir, isect->t, &ob_itfm);
+ isect->t = bvh_instance_motion_pop(kg, object, ray, &P, &dir, &idir, isect->t, &ob_itfm);
# else
- isect->t = bvh_instance_pop(kg, object, ray, &P, &dir, &idir, isect->t);
+ isect->t = bvh_instance_pop(kg, object, ray, &P, &dir, &idir, isect->t);
# endif
- qbvh_near_far_idx_calc(idir,
- &near_x, &near_y, &near_z,
- &far_x, &far_y, &far_z);
- tfar = ssef(isect->t);
+ qbvh_near_far_idx_calc(idir, &near_x, &near_y, &near_z, &far_x, &far_y, &far_z);
+ tfar = ssef(isect->t);
# if BVH_FEATURE(BVH_HAIR)
- dir4 = sse3f(ssef(dir.x), ssef(dir.y), ssef(dir.z));
+ dir4 = sse3f(ssef(dir.x), ssef(dir.y), ssef(dir.z));
# endif
- idir4 = sse3f(ssef(idir.x), ssef(idir.y), ssef(idir.z));
+ idir4 = sse3f(ssef(idir.x), ssef(idir.y), ssef(idir.z));
# ifdef __KERNEL_AVX2__
- P_idir = P*idir;
- P_idir4 = sse3f(P_idir.x, P_idir.y, P_idir.z);
+ P_idir = P * idir;
+ P_idir4 = sse3f(P_idir.x, P_idir.y, P_idir.z);
# endif
# if BVH_FEATURE(BVH_HAIR) || !defined(__KERNEL_AVX2__)
- org4 = sse3f(ssef(P.x), ssef(P.y), ssef(P.z));
+ org4 = sse3f(ssef(P.x), ssef(P.y), ssef(P.z));
# endif
- object = OBJECT_NONE;
- node_addr = traversal_stack[stack_ptr].addr;
- node_dist = traversal_stack[stack_ptr].dist;
- --stack_ptr;
- }
-#endif /* FEATURE(BVH_INSTANCING) */
- } while(node_addr != ENTRYPOINT_SENTINEL);
+ object = OBJECT_NONE;
+ node_addr = traversal_stack[stack_ptr].addr;
+ node_dist = traversal_stack[stack_ptr].dist;
+ --stack_ptr;
+ }
+#endif /* FEATURE(BVH_INSTANCING) */
+ } while (node_addr != ENTRYPOINT_SENTINEL);
- return (isect->prim != PRIM_NONE);
+ return (isect->prim != PRIM_NONE);
}
#undef NODE_INTERSECT
diff --git a/intern/cycles/kernel/bvh/qbvh_volume.h b/intern/cycles/kernel/bvh/qbvh_volume.h
index 6790bfa6c83..e4eaed04467 100644
--- a/intern/cycles/kernel/bvh/qbvh_volume.h
+++ b/intern/cycles/kernel/bvh/qbvh_volume.h
@@ -33,331 +33,335 @@ ccl_device bool BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg,
Intersection *isect,
const uint visibility)
{
- /* TODO(sergey):
- * - Test if pushing distance on the stack helps.
- * - Likely and unlikely for if() statements.
- * - Test restrict attribute for pointers.
- */
-
- /* Traversal stack in CUDA thread-local memory. */
- QBVHStackItem traversal_stack[BVH_QSTACK_SIZE];
- traversal_stack[0].addr = ENTRYPOINT_SENTINEL;
-
- /* Traversal variables in registers. */
- int stack_ptr = 0;
- int node_addr = kernel_data.bvh.root;
-
- /* Ray parameters in registers. */
- float3 P = ray->P;
- float3 dir = bvh_clamp_direction(ray->D);
- float3 idir = bvh_inverse_direction(dir);
- int object = OBJECT_NONE;
+ /* TODO(sergey):
+ * - Test if pushing distance on the stack helps.
+ * - Likely and unlikely for if() statements.
+ * - Test restrict attribute for pointers.
+ */
+
+ /* Traversal stack in CUDA thread-local memory. */
+ QBVHStackItem traversal_stack[BVH_QSTACK_SIZE];
+ traversal_stack[0].addr = ENTRYPOINT_SENTINEL;
+
+ /* Traversal variables in registers. */
+ int stack_ptr = 0;
+ int node_addr = kernel_data.bvh.root;
+
+ /* Ray parameters in registers. */
+ float3 P = ray->P;
+ float3 dir = bvh_clamp_direction(ray->D);
+ float3 idir = bvh_inverse_direction(dir);
+ int object = OBJECT_NONE;
#if BVH_FEATURE(BVH_MOTION)
- Transform ob_itfm;
+ Transform ob_itfm;
#endif
- isect->t = ray->t;
- isect->u = 0.0f;
- isect->v = 0.0f;
- isect->prim = PRIM_NONE;
- isect->object = OBJECT_NONE;
+ isect->t = ray->t;
+ isect->u = 0.0f;
+ isect->v = 0.0f;
+ isect->prim = PRIM_NONE;
+ isect->object = OBJECT_NONE;
- ssef tnear(0.0f), tfar(ray->t);
+ ssef tnear(0.0f), tfar(ray->t);
#if BVH_FEATURE(BVH_HAIR)
- sse3f dir4(ssef(dir.x), ssef(dir.y), ssef(dir.z));
+ sse3f dir4(ssef(dir.x), ssef(dir.y), ssef(dir.z));
#endif
- sse3f idir4(ssef(idir.x), ssef(idir.y), ssef(idir.z));
+ sse3f idir4(ssef(idir.x), ssef(idir.y), ssef(idir.z));
#ifdef __KERNEL_AVX2__
- float3 P_idir = P*idir;
- sse3f P_idir4(P_idir.x, P_idir.y, P_idir.z);
+ float3 P_idir = P * idir;
+ sse3f P_idir4(P_idir.x, P_idir.y, P_idir.z);
#endif
#if BVH_FEATURE(BVH_HAIR) || !defined(__KERNEL_AVX2__)
- sse3f org4(ssef(P.x), ssef(P.y), ssef(P.z));
+ sse3f org4(ssef(P.x), ssef(P.y), ssef(P.z));
#endif
- /* Offsets to select the side that becomes the lower or upper bound. */
- int near_x, near_y, near_z;
- int far_x, far_y, far_z;
- qbvh_near_far_idx_calc(idir,
- &near_x, &near_y, &near_z,
- &far_x, &far_y, &far_z);
+ /* Offsets to select the side that becomes the lower or upper bound. */
+ int near_x, near_y, near_z;
+ int far_x, far_y, far_z;
+ qbvh_near_far_idx_calc(idir, &near_x, &near_y, &near_z, &far_x, &far_y, &far_z);
- /* Traversal loop. */
- do {
- do {
- /* Traverse internal nodes. */
- while(node_addr >= 0 && node_addr != ENTRYPOINT_SENTINEL) {
- float4 inodes = kernel_tex_fetch(__bvh_nodes, node_addr+0);
+ /* Traversal loop. */
+ do {
+ do {
+ /* Traverse internal nodes. */
+ while (node_addr >= 0 && node_addr != ENTRYPOINT_SENTINEL) {
+ float4 inodes = kernel_tex_fetch(__bvh_nodes, node_addr + 0);
#ifdef __VISIBILITY_FLAG__
- if((__float_as_uint(inodes.x) & visibility) == 0) {
- /* Pop. */
- node_addr = traversal_stack[stack_ptr].addr;
- --stack_ptr;
- continue;
- }
+ if ((__float_as_uint(inodes.x) & visibility) == 0) {
+ /* Pop. */
+ node_addr = traversal_stack[stack_ptr].addr;
+ --stack_ptr;
+ continue;
+ }
#endif
- ssef dist;
- int child_mask = NODE_INTERSECT(kg,
- tnear,
- tfar,
+ ssef dist;
+ int child_mask = NODE_INTERSECT(kg,
+ tnear,
+ tfar,
#ifdef __KERNEL_AVX2__
- P_idir4,
+ P_idir4,
#endif
#if BVH_FEATURE(BVH_HAIR) || !defined(__KERNEL_AVX2__)
- org4,
+ org4,
#endif
#if BVH_FEATURE(BVH_HAIR)
- dir4,
+ dir4,
#endif
- idir4,
- near_x, near_y, near_z,
- far_x, far_y, far_z,
- node_addr,
- &dist);
-
- if(child_mask != 0) {
- float4 cnodes;
+ idir4,
+ near_x,
+ near_y,
+ near_z,
+ far_x,
+ far_y,
+ far_z,
+ node_addr,
+ &dist);
+
+ if (child_mask != 0) {
+ float4 cnodes;
#if BVH_FEATURE(BVH_HAIR)
- if(__float_as_uint(inodes.x) & PATH_RAY_NODE_UNALIGNED) {
- cnodes = kernel_tex_fetch(__bvh_nodes, node_addr+13);
- }
- else
+ if (__float_as_uint(inodes.x) & PATH_RAY_NODE_UNALIGNED) {
+ cnodes = kernel_tex_fetch(__bvh_nodes, node_addr + 13);
+ }
+ else
#endif
- {
- cnodes = kernel_tex_fetch(__bvh_nodes, node_addr+7);
- }
-
- /* One child is hit, continue with that child. */
- int r = __bscf(child_mask);
- if(child_mask == 0) {
- node_addr = __float_as_int(cnodes[r]);
- continue;
- }
-
- /* Two children are hit, push far child, and continue with
- * closer child.
- */
- int c0 = __float_as_int(cnodes[r]);
- float d0 = ((float*)&dist)[r];
- r = __bscf(child_mask);
- int c1 = __float_as_int(cnodes[r]);
- float d1 = ((float*)&dist)[r];
- if(child_mask == 0) {
- if(d1 < d0) {
- node_addr = c1;
- ++stack_ptr;
- kernel_assert(stack_ptr < BVH_QSTACK_SIZE);
- traversal_stack[stack_ptr].addr = c0;
- traversal_stack[stack_ptr].dist = d0;
- continue;
- }
- else {
- node_addr = c0;
- ++stack_ptr;
- kernel_assert(stack_ptr < BVH_QSTACK_SIZE);
- traversal_stack[stack_ptr].addr = c1;
- traversal_stack[stack_ptr].dist = d1;
- continue;
- }
- }
-
- /* Here starts the slow path for 3 or 4 hit children. We push
- * all nodes onto the stack to sort them there.
- */
- ++stack_ptr;
- kernel_assert(stack_ptr < BVH_QSTACK_SIZE);
- traversal_stack[stack_ptr].addr = c1;
- traversal_stack[stack_ptr].dist = d1;
- ++stack_ptr;
- kernel_assert(stack_ptr < BVH_QSTACK_SIZE);
- traversal_stack[stack_ptr].addr = c0;
- traversal_stack[stack_ptr].dist = d0;
-
- /* Three children are hit, push all onto stack and sort 3
- * stack items, continue with closest child.
- */
- r = __bscf(child_mask);
- int c2 = __float_as_int(cnodes[r]);
- float d2 = ((float*)&dist)[r];
- if(child_mask == 0) {
- ++stack_ptr;
- kernel_assert(stack_ptr < BVH_QSTACK_SIZE);
- traversal_stack[stack_ptr].addr = c2;
- traversal_stack[stack_ptr].dist = d2;
- qbvh_stack_sort(&traversal_stack[stack_ptr],
- &traversal_stack[stack_ptr - 1],
- &traversal_stack[stack_ptr - 2]);
- node_addr = traversal_stack[stack_ptr].addr;
- --stack_ptr;
- continue;
- }
-
- /* Four children are hit, push all onto stack and sort 4
- * stack items, continue with closest child.
- */
- r = __bscf(child_mask);
- int c3 = __float_as_int(cnodes[r]);
- float d3 = ((float*)&dist)[r];
- ++stack_ptr;
- kernel_assert(stack_ptr < BVH_QSTACK_SIZE);
- traversal_stack[stack_ptr].addr = c3;
- traversal_stack[stack_ptr].dist = d3;
- ++stack_ptr;
- kernel_assert(stack_ptr < BVH_QSTACK_SIZE);
- traversal_stack[stack_ptr].addr = c2;
- traversal_stack[stack_ptr].dist = d2;
- qbvh_stack_sort(&traversal_stack[stack_ptr],
- &traversal_stack[stack_ptr - 1],
- &traversal_stack[stack_ptr - 2],
- &traversal_stack[stack_ptr - 3]);
- }
-
- node_addr = traversal_stack[stack_ptr].addr;
- --stack_ptr;
- }
-
- /* If node is leaf, fetch triangle list. */
- if(node_addr < 0) {
- float4 leaf = kernel_tex_fetch(__bvh_leaf_nodes, (-node_addr-1));
-
- if((__float_as_uint(leaf.z) & visibility) == 0) {
- /* Pop. */
- node_addr = traversal_stack[stack_ptr].addr;
- --stack_ptr;
- continue;
- }
-
- int prim_addr = __float_as_int(leaf.x);
+ {
+ cnodes = kernel_tex_fetch(__bvh_nodes, node_addr + 7);
+ }
+
+ /* One child is hit, continue with that child. */
+ int r = __bscf(child_mask);
+ if (child_mask == 0) {
+ node_addr = __float_as_int(cnodes[r]);
+ continue;
+ }
+
+ /* Two children are hit, push far child, and continue with
+ * closer child.
+ */
+ int c0 = __float_as_int(cnodes[r]);
+ float d0 = ((float *)&dist)[r];
+ r = __bscf(child_mask);
+ int c1 = __float_as_int(cnodes[r]);
+ float d1 = ((float *)&dist)[r];
+ if (child_mask == 0) {
+ if (d1 < d0) {
+ node_addr = c1;
+ ++stack_ptr;
+ kernel_assert(stack_ptr < BVH_QSTACK_SIZE);
+ traversal_stack[stack_ptr].addr = c0;
+ traversal_stack[stack_ptr].dist = d0;
+ continue;
+ }
+ else {
+ node_addr = c0;
+ ++stack_ptr;
+ kernel_assert(stack_ptr < BVH_QSTACK_SIZE);
+ traversal_stack[stack_ptr].addr = c1;
+ traversal_stack[stack_ptr].dist = d1;
+ continue;
+ }
+ }
+
+ /* Here starts the slow path for 3 or 4 hit children. We push
+ * all nodes onto the stack to sort them there.
+ */
+ ++stack_ptr;
+ kernel_assert(stack_ptr < BVH_QSTACK_SIZE);
+ traversal_stack[stack_ptr].addr = c1;
+ traversal_stack[stack_ptr].dist = d1;
+ ++stack_ptr;
+ kernel_assert(stack_ptr < BVH_QSTACK_SIZE);
+ traversal_stack[stack_ptr].addr = c0;
+ traversal_stack[stack_ptr].dist = d0;
+
+ /* Three children are hit, push all onto stack and sort 3
+ * stack items, continue with closest child.
+ */
+ r = __bscf(child_mask);
+ int c2 = __float_as_int(cnodes[r]);
+ float d2 = ((float *)&dist)[r];
+ if (child_mask == 0) {
+ ++stack_ptr;
+ kernel_assert(stack_ptr < BVH_QSTACK_SIZE);
+ traversal_stack[stack_ptr].addr = c2;
+ traversal_stack[stack_ptr].dist = d2;
+ qbvh_stack_sort(&traversal_stack[stack_ptr],
+ &traversal_stack[stack_ptr - 1],
+ &traversal_stack[stack_ptr - 2]);
+ node_addr = traversal_stack[stack_ptr].addr;
+ --stack_ptr;
+ continue;
+ }
+
+ /* Four children are hit, push all onto stack and sort 4
+ * stack items, continue with closest child.
+ */
+ r = __bscf(child_mask);
+ int c3 = __float_as_int(cnodes[r]);
+ float d3 = ((float *)&dist)[r];
+ ++stack_ptr;
+ kernel_assert(stack_ptr < BVH_QSTACK_SIZE);
+ traversal_stack[stack_ptr].addr = c3;
+ traversal_stack[stack_ptr].dist = d3;
+ ++stack_ptr;
+ kernel_assert(stack_ptr < BVH_QSTACK_SIZE);
+ traversal_stack[stack_ptr].addr = c2;
+ traversal_stack[stack_ptr].dist = d2;
+ qbvh_stack_sort(&traversal_stack[stack_ptr],
+ &traversal_stack[stack_ptr - 1],
+ &traversal_stack[stack_ptr - 2],
+ &traversal_stack[stack_ptr - 3]);
+ }
+
+ node_addr = traversal_stack[stack_ptr].addr;
+ --stack_ptr;
+ }
+
+ /* If node is leaf, fetch triangle list. */
+ if (node_addr < 0) {
+ float4 leaf = kernel_tex_fetch(__bvh_leaf_nodes, (-node_addr - 1));
+
+ if ((__float_as_uint(leaf.z) & visibility) == 0) {
+ /* Pop. */
+ node_addr = traversal_stack[stack_ptr].addr;
+ --stack_ptr;
+ continue;
+ }
+
+ int prim_addr = __float_as_int(leaf.x);
#if BVH_FEATURE(BVH_INSTANCING)
- if(prim_addr >= 0) {
+ if (prim_addr >= 0) {
#endif
- int prim_addr2 = __float_as_int(leaf.y);
- const uint type = __float_as_int(leaf.w);
- const uint p_type = type & PRIMITIVE_ALL;
-
- /* Pop. */
- node_addr = traversal_stack[stack_ptr].addr;
- --stack_ptr;
-
- /* Primitive intersection. */
- switch(p_type) {
- case PRIMITIVE_TRIANGLE: {
- for(; prim_addr < prim_addr2; prim_addr++) {
- kernel_assert(kernel_tex_fetch(__prim_type, prim_addr) == type);
- /* Only primitives from volume object. */
- uint tri_object = (object == OBJECT_NONE)? kernel_tex_fetch(__prim_object, prim_addr): object;
- int object_flag = kernel_tex_fetch(__object_flag, tri_object);
- if((object_flag & SD_OBJECT_HAS_VOLUME) == 0) {
- continue;
- }
- /* Intersect ray against primitive. */
- triangle_intersect(kg, isect, P, dir, visibility, object, prim_addr);
- }
- break;
- }
+ int prim_addr2 = __float_as_int(leaf.y);
+ const uint type = __float_as_int(leaf.w);
+ const uint p_type = type & PRIMITIVE_ALL;
+
+ /* Pop. */
+ node_addr = traversal_stack[stack_ptr].addr;
+ --stack_ptr;
+
+ /* Primitive intersection. */
+ switch (p_type) {
+ case PRIMITIVE_TRIANGLE: {
+ for (; prim_addr < prim_addr2; prim_addr++) {
+ kernel_assert(kernel_tex_fetch(__prim_type, prim_addr) == type);
+ /* Only primitives from volume object. */
+ uint tri_object = (object == OBJECT_NONE) ?
+ kernel_tex_fetch(__prim_object, prim_addr) :
+ object;
+ int object_flag = kernel_tex_fetch(__object_flag, tri_object);
+ if ((object_flag & SD_OBJECT_HAS_VOLUME) == 0) {
+ continue;
+ }
+ /* Intersect ray against primitive. */
+ triangle_intersect(kg, isect, P, dir, visibility, object, prim_addr);
+ }
+ break;
+ }
#if BVH_FEATURE(BVH_MOTION)
- case PRIMITIVE_MOTION_TRIANGLE: {
- for(; prim_addr < prim_addr2; prim_addr++) {
- kernel_assert(kernel_tex_fetch(__prim_type, prim_addr) == type);
- /* Only primitives from volume object. */
- uint tri_object = (object == OBJECT_NONE)? kernel_tex_fetch(__prim_object, prim_addr): object;
- int object_flag = kernel_tex_fetch(__object_flag, tri_object);
- if((object_flag & SD_OBJECT_HAS_VOLUME) == 0) {
- continue;
- }
- /* Intersect ray against primitive. */
- motion_triangle_intersect(kg, isect, P, dir, ray->time, visibility, object, prim_addr);
- }
- break;
- }
+ case PRIMITIVE_MOTION_TRIANGLE: {
+ for (; prim_addr < prim_addr2; prim_addr++) {
+ kernel_assert(kernel_tex_fetch(__prim_type, prim_addr) == type);
+ /* Only primitives from volume object. */
+ uint tri_object = (object == OBJECT_NONE) ?
+ kernel_tex_fetch(__prim_object, prim_addr) :
+ object;
+ int object_flag = kernel_tex_fetch(__object_flag, tri_object);
+ if ((object_flag & SD_OBJECT_HAS_VOLUME) == 0) {
+ continue;
+ }
+ /* Intersect ray against primitive. */
+ motion_triangle_intersect(
+ kg, isect, P, dir, ray->time, visibility, object, prim_addr);
+ }
+ break;
+ }
#endif
- }
- }
+ }
+ }
#if BVH_FEATURE(BVH_INSTANCING)
- else {
- /* Instance push. */
- object = kernel_tex_fetch(__prim_object, -prim_addr-1);
- int object_flag = kernel_tex_fetch(__object_flag, object);
- if(object_flag & SD_OBJECT_HAS_VOLUME) {
+ else {
+ /* Instance push. */
+ object = kernel_tex_fetch(__prim_object, -prim_addr - 1);
+ int object_flag = kernel_tex_fetch(__object_flag, object);
+ if (object_flag & SD_OBJECT_HAS_VOLUME) {
# if BVH_FEATURE(BVH_MOTION)
- isect->t = bvh_instance_motion_push(kg, object, ray, &P, &dir, &idir, isect->t, &ob_itfm);
+ isect->t = bvh_instance_motion_push(
+ kg, object, ray, &P, &dir, &idir, isect->t, &ob_itfm);
# else
- isect->t = bvh_instance_push(kg, object, ray, &P, &dir, &idir, isect->t);
+ isect->t = bvh_instance_push(kg, object, ray, &P, &dir, &idir, isect->t);
# endif
- qbvh_near_far_idx_calc(idir,
- &near_x, &near_y, &near_z,
- &far_x, &far_y, &far_z);
- tfar = ssef(isect->t);
+ qbvh_near_far_idx_calc(idir, &near_x, &near_y, &near_z, &far_x, &far_y, &far_z);
+ tfar = ssef(isect->t);
# if BVH_FEATURE(BVH_HAIR)
- dir4 = sse3f(ssef(dir.x), ssef(dir.y), ssef(dir.z));
+ dir4 = sse3f(ssef(dir.x), ssef(dir.y), ssef(dir.z));
# endif
- idir4 = sse3f(ssef(idir.x), ssef(idir.y), ssef(idir.z));
+ idir4 = sse3f(ssef(idir.x), ssef(idir.y), ssef(idir.z));
# ifdef __KERNEL_AVX2__
- P_idir = P*idir;
- P_idir4 = sse3f(P_idir.x, P_idir.y, P_idir.z);
+ P_idir = P * idir;
+ P_idir4 = sse3f(P_idir.x, P_idir.y, P_idir.z);
# endif
# if BVH_FEATURE(BVH_HAIR) || !defined(__KERNEL_AVX2__)
- org4 = sse3f(ssef(P.x), ssef(P.y), ssef(P.z));
+ org4 = sse3f(ssef(P.x), ssef(P.y), ssef(P.z));
# endif
- ++stack_ptr;
- kernel_assert(stack_ptr < BVH_QSTACK_SIZE);
- traversal_stack[stack_ptr].addr = ENTRYPOINT_SENTINEL;
-
- node_addr = kernel_tex_fetch(__object_node, object);
- }
- else {
- /* Pop. */
- object = OBJECT_NONE;
- node_addr = traversal_stack[stack_ptr].addr;
- --stack_ptr;
- }
- }
- }
-#endif /* FEATURE(BVH_INSTANCING) */
- } while(node_addr != ENTRYPOINT_SENTINEL);
+ ++stack_ptr;
+ kernel_assert(stack_ptr < BVH_QSTACK_SIZE);
+ traversal_stack[stack_ptr].addr = ENTRYPOINT_SENTINEL;
+
+ node_addr = kernel_tex_fetch(__object_node, object);
+ }
+ else {
+ /* Pop. */
+ object = OBJECT_NONE;
+ node_addr = traversal_stack[stack_ptr].addr;
+ --stack_ptr;
+ }
+ }
+ }
+#endif /* FEATURE(BVH_INSTANCING) */
+ } while (node_addr != ENTRYPOINT_SENTINEL);
#if BVH_FEATURE(BVH_INSTANCING)
- if(stack_ptr >= 0) {
- kernel_assert(object != OBJECT_NONE);
+ if (stack_ptr >= 0) {
+ kernel_assert(object != OBJECT_NONE);
- /* Instance pop. */
+ /* Instance pop. */
# if BVH_FEATURE(BVH_MOTION)
- isect->t = bvh_instance_motion_pop(kg, object, ray, &P, &dir, &idir, isect->t, &ob_itfm);
+ isect->t = bvh_instance_motion_pop(kg, object, ray, &P, &dir, &idir, isect->t, &ob_itfm);
# else
- isect->t = bvh_instance_pop(kg, object, ray, &P, &dir, &idir, isect->t);
+ isect->t = bvh_instance_pop(kg, object, ray, &P, &dir, &idir, isect->t);
# endif
- qbvh_near_far_idx_calc(idir,
- &near_x, &near_y, &near_z,
- &far_x, &far_y, &far_z);
- tfar = ssef(isect->t);
+ qbvh_near_far_idx_calc(idir, &near_x, &near_y, &near_z, &far_x, &far_y, &far_z);
+ tfar = ssef(isect->t);
# if BVH_FEATURE(BVH_HAIR)
- dir4 = sse3f(ssef(dir.x), ssef(dir.y), ssef(dir.z));
+ dir4 = sse3f(ssef(dir.x), ssef(dir.y), ssef(dir.z));
# endif
- idir4 = sse3f(ssef(idir.x), ssef(idir.y), ssef(idir.z));
+ idir4 = sse3f(ssef(idir.x), ssef(idir.y), ssef(idir.z));
# ifdef __KERNEL_AVX2__
- P_idir = P*idir;
- P_idir4 = sse3f(P_idir.x, P_idir.y, P_idir.z);
+ P_idir = P * idir;
+ P_idir4 = sse3f(P_idir.x, P_idir.y, P_idir.z);
# endif
# if BVH_FEATURE(BVH_HAIR) || !defined(__KERNEL_AVX2__)
- org4 = sse3f(ssef(P.x), ssef(P.y), ssef(P.z));
+ org4 = sse3f(ssef(P.x), ssef(P.y), ssef(P.z));
# endif
- object = OBJECT_NONE;
- node_addr = traversal_stack[stack_ptr].addr;
- --stack_ptr;
- }
-#endif /* FEATURE(BVH_INSTANCING) */
- } while(node_addr != ENTRYPOINT_SENTINEL);
+ object = OBJECT_NONE;
+ node_addr = traversal_stack[stack_ptr].addr;
+ --stack_ptr;
+ }
+#endif /* FEATURE(BVH_INSTANCING) */
+ } while (node_addr != ENTRYPOINT_SENTINEL);
- return (isect->prim != PRIM_NONE);
+ return (isect->prim != PRIM_NONE);
}
#undef NODE_INTERSECT
diff --git a/intern/cycles/kernel/bvh/qbvh_volume_all.h b/intern/cycles/kernel/bvh/qbvh_volume_all.h
index 63d79b6fe34..eddc48c487e 100644
--- a/intern/cycles/kernel/bvh/qbvh_volume_all.h
+++ b/intern/cycles/kernel/bvh/qbvh_volume_all.h
@@ -34,405 +34,411 @@ ccl_device uint BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg,
const uint max_hits,
const uint visibility)
{
- /* TODO(sergey):
- * - Test if pushing distance on the stack helps.
- * - Likely and unlikely for if() statements.
- * - Test restrict attribute for pointers.
- */
-
- /* Traversal stack in CUDA thread-local memory. */
- QBVHStackItem traversal_stack[BVH_QSTACK_SIZE];
- traversal_stack[0].addr = ENTRYPOINT_SENTINEL;
-
- /* Traversal variables in registers. */
- int stack_ptr = 0;
- int node_addr = kernel_data.bvh.root;
-
- /* Ray parameters in registers. */
- const float tmax = ray->t;
- float3 P = ray->P;
- float3 dir = bvh_clamp_direction(ray->D);
- float3 idir = bvh_inverse_direction(dir);
- int object = OBJECT_NONE;
- float isect_t = tmax;
+ /* TODO(sergey):
+ * - Test if pushing distance on the stack helps.
+ * - Likely and unlikely for if() statements.
+ * - Test restrict attribute for pointers.
+ */
+
+ /* Traversal stack in CUDA thread-local memory. */
+ QBVHStackItem traversal_stack[BVH_QSTACK_SIZE];
+ traversal_stack[0].addr = ENTRYPOINT_SENTINEL;
+
+ /* Traversal variables in registers. */
+ int stack_ptr = 0;
+ int node_addr = kernel_data.bvh.root;
+
+ /* Ray parameters in registers. */
+ const float tmax = ray->t;
+ float3 P = ray->P;
+ float3 dir = bvh_clamp_direction(ray->D);
+ float3 idir = bvh_inverse_direction(dir);
+ int object = OBJECT_NONE;
+ float isect_t = tmax;
#if BVH_FEATURE(BVH_MOTION)
- Transform ob_itfm;
+ Transform ob_itfm;
#endif
- uint num_hits = 0;
- isect_array->t = tmax;
+ uint num_hits = 0;
+ isect_array->t = tmax;
#if BVH_FEATURE(BVH_INSTANCING)
- int num_hits_in_instance = 0;
+ int num_hits_in_instance = 0;
#endif
- ssef tnear(0.0f), tfar(isect_t);
+ ssef tnear(0.0f), tfar(isect_t);
#if BVH_FEATURE(BVH_HAIR)
- sse3f dir4(ssef(dir.x), ssef(dir.y), ssef(dir.z));
+ sse3f dir4(ssef(dir.x), ssef(dir.y), ssef(dir.z));
#endif
- sse3f idir4(ssef(idir.x), ssef(idir.y), ssef(idir.z));
+ sse3f idir4(ssef(idir.x), ssef(idir.y), ssef(idir.z));
#ifdef __KERNEL_AVX2__
- float3 P_idir = P*idir;
- sse3f P_idir4(P_idir.x, P_idir.y, P_idir.z);
+ float3 P_idir = P * idir;
+ sse3f P_idir4(P_idir.x, P_idir.y, P_idir.z);
#endif
#if BVH_FEATURE(BVH_HAIR) || !defined(__KERNEL_AVX2__)
- sse3f org4(ssef(P.x), ssef(P.y), ssef(P.z));
+ sse3f org4(ssef(P.x), ssef(P.y), ssef(P.z));
#endif
- /* Offsets to select the side that becomes the lower or upper bound. */
- int near_x, near_y, near_z;
- int far_x, far_y, far_z;
- qbvh_near_far_idx_calc(idir,
- &near_x, &near_y, &near_z,
- &far_x, &far_y, &far_z);
+ /* Offsets to select the side that becomes the lower or upper bound. */
+ int near_x, near_y, near_z;
+ int far_x, far_y, far_z;
+ qbvh_near_far_idx_calc(idir, &near_x, &near_y, &near_z, &far_x, &far_y, &far_z);
- /* Traversal loop. */
- do {
- do {
- /* Traverse internal nodes. */
- while(node_addr >= 0 && node_addr != ENTRYPOINT_SENTINEL) {
- float4 inodes = kernel_tex_fetch(__bvh_nodes, node_addr+0);
+ /* Traversal loop. */
+ do {
+ do {
+ /* Traverse internal nodes. */
+ while (node_addr >= 0 && node_addr != ENTRYPOINT_SENTINEL) {
+ float4 inodes = kernel_tex_fetch(__bvh_nodes, node_addr + 0);
#ifdef __VISIBILITY_FLAG__
- if((__float_as_uint(inodes.x) & visibility) == 0) {
- /* Pop. */
- node_addr = traversal_stack[stack_ptr].addr;
- --stack_ptr;
- continue;
- }
+ if ((__float_as_uint(inodes.x) & visibility) == 0) {
+ /* Pop. */
+ node_addr = traversal_stack[stack_ptr].addr;
+ --stack_ptr;
+ continue;
+ }
#endif
- ssef dist;
- int child_mask = NODE_INTERSECT(kg,
- tnear,
- tfar,
+ ssef dist;
+ int child_mask = NODE_INTERSECT(kg,
+ tnear,
+ tfar,
#ifdef __KERNEL_AVX2__
- P_idir4,
+ P_idir4,
#endif
#if BVH_FEATURE(BVH_HAIR) || !defined(__KERNEL_AVX2__)
- org4,
+ org4,
#endif
#if BVH_FEATURE(BVH_HAIR)
- dir4,
+ dir4,
#endif
- idir4,
- near_x, near_y, near_z,
- far_x, far_y, far_z,
- node_addr,
- &dist);
-
- if(child_mask != 0) {
- float4 cnodes;
+ idir4,
+ near_x,
+ near_y,
+ near_z,
+ far_x,
+ far_y,
+ far_z,
+ node_addr,
+ &dist);
+
+ if (child_mask != 0) {
+ float4 cnodes;
#if BVH_FEATURE(BVH_HAIR)
- if(__float_as_uint(inodes.x) & PATH_RAY_NODE_UNALIGNED) {
- cnodes = kernel_tex_fetch(__bvh_nodes, node_addr+13);
- }
- else
+ if (__float_as_uint(inodes.x) & PATH_RAY_NODE_UNALIGNED) {
+ cnodes = kernel_tex_fetch(__bvh_nodes, node_addr + 13);
+ }
+ else
#endif
- {
- cnodes = kernel_tex_fetch(__bvh_nodes, node_addr+7);
- }
-
- /* One child is hit, continue with that child. */
- int r = __bscf(child_mask);
- if(child_mask == 0) {
- node_addr = __float_as_int(cnodes[r]);
- continue;
- }
-
- /* Two children are hit, push far child, and continue with
- * closer child.
- */
- int c0 = __float_as_int(cnodes[r]);
- float d0 = ((float*)&dist)[r];
- r = __bscf(child_mask);
- int c1 = __float_as_int(cnodes[r]);
- float d1 = ((float*)&dist)[r];
- if(child_mask == 0) {
- if(d1 < d0) {
- node_addr = c1;
- ++stack_ptr;
- kernel_assert(stack_ptr < BVH_QSTACK_SIZE);
- traversal_stack[stack_ptr].addr = c0;
- traversal_stack[stack_ptr].dist = d0;
- continue;
- }
- else {
- node_addr = c0;
- ++stack_ptr;
- kernel_assert(stack_ptr < BVH_QSTACK_SIZE);
- traversal_stack[stack_ptr].addr = c1;
- traversal_stack[stack_ptr].dist = d1;
- continue;
- }
- }
-
- /* Here starts the slow path for 3 or 4 hit children. We push
- * all nodes onto the stack to sort them there.
- */
- ++stack_ptr;
- kernel_assert(stack_ptr < BVH_QSTACK_SIZE);
- traversal_stack[stack_ptr].addr = c1;
- traversal_stack[stack_ptr].dist = d1;
- ++stack_ptr;
- kernel_assert(stack_ptr < BVH_QSTACK_SIZE);
- traversal_stack[stack_ptr].addr = c0;
- traversal_stack[stack_ptr].dist = d0;
-
- /* Three children are hit, push all onto stack and sort 3
- * stack items, continue with closest child.
- */
- r = __bscf(child_mask);
- int c2 = __float_as_int(cnodes[r]);
- float d2 = ((float*)&dist)[r];
- if(child_mask == 0) {
- ++stack_ptr;
- kernel_assert(stack_ptr < BVH_QSTACK_SIZE);
- traversal_stack[stack_ptr].addr = c2;
- traversal_stack[stack_ptr].dist = d2;
- qbvh_stack_sort(&traversal_stack[stack_ptr],
- &traversal_stack[stack_ptr - 1],
- &traversal_stack[stack_ptr - 2]);
- node_addr = traversal_stack[stack_ptr].addr;
- --stack_ptr;
- continue;
- }
-
- /* Four children are hit, push all onto stack and sort 4
- * stack items, continue with closest child.
- */
- r = __bscf(child_mask);
- int c3 = __float_as_int(cnodes[r]);
- float d3 = ((float*)&dist)[r];
- ++stack_ptr;
- kernel_assert(stack_ptr < BVH_QSTACK_SIZE);
- traversal_stack[stack_ptr].addr = c3;
- traversal_stack[stack_ptr].dist = d3;
- ++stack_ptr;
- kernel_assert(stack_ptr < BVH_QSTACK_SIZE);
- traversal_stack[stack_ptr].addr = c2;
- traversal_stack[stack_ptr].dist = d2;
- qbvh_stack_sort(&traversal_stack[stack_ptr],
- &traversal_stack[stack_ptr - 1],
- &traversal_stack[stack_ptr - 2],
- &traversal_stack[stack_ptr - 3]);
- }
-
- node_addr = traversal_stack[stack_ptr].addr;
- --stack_ptr;
- }
-
- /* If node is leaf, fetch triangle list. */
- if(node_addr < 0) {
- float4 leaf = kernel_tex_fetch(__bvh_leaf_nodes, (-node_addr-1));
-
- if((__float_as_uint(leaf.z) & visibility) == 0) {
- /* Pop. */
- node_addr = traversal_stack[stack_ptr].addr;
- --stack_ptr;
- continue;
- }
-
- int prim_addr = __float_as_int(leaf.x);
+ {
+ cnodes = kernel_tex_fetch(__bvh_nodes, node_addr + 7);
+ }
+
+ /* One child is hit, continue with that child. */
+ int r = __bscf(child_mask);
+ if (child_mask == 0) {
+ node_addr = __float_as_int(cnodes[r]);
+ continue;
+ }
+
+ /* Two children are hit, push far child, and continue with
+ * closer child.
+ */
+ int c0 = __float_as_int(cnodes[r]);
+ float d0 = ((float *)&dist)[r];
+ r = __bscf(child_mask);
+ int c1 = __float_as_int(cnodes[r]);
+ float d1 = ((float *)&dist)[r];
+ if (child_mask == 0) {
+ if (d1 < d0) {
+ node_addr = c1;
+ ++stack_ptr;
+ kernel_assert(stack_ptr < BVH_QSTACK_SIZE);
+ traversal_stack[stack_ptr].addr = c0;
+ traversal_stack[stack_ptr].dist = d0;
+ continue;
+ }
+ else {
+ node_addr = c0;
+ ++stack_ptr;
+ kernel_assert(stack_ptr < BVH_QSTACK_SIZE);
+ traversal_stack[stack_ptr].addr = c1;
+ traversal_stack[stack_ptr].dist = d1;
+ continue;
+ }
+ }
+
+ /* Here starts the slow path for 3 or 4 hit children. We push
+ * all nodes onto the stack to sort them there.
+ */
+ ++stack_ptr;
+ kernel_assert(stack_ptr < BVH_QSTACK_SIZE);
+ traversal_stack[stack_ptr].addr = c1;
+ traversal_stack[stack_ptr].dist = d1;
+ ++stack_ptr;
+ kernel_assert(stack_ptr < BVH_QSTACK_SIZE);
+ traversal_stack[stack_ptr].addr = c0;
+ traversal_stack[stack_ptr].dist = d0;
+
+ /* Three children are hit, push all onto stack and sort 3
+ * stack items, continue with closest child.
+ */
+ r = __bscf(child_mask);
+ int c2 = __float_as_int(cnodes[r]);
+ float d2 = ((float *)&dist)[r];
+ if (child_mask == 0) {
+ ++stack_ptr;
+ kernel_assert(stack_ptr < BVH_QSTACK_SIZE);
+ traversal_stack[stack_ptr].addr = c2;
+ traversal_stack[stack_ptr].dist = d2;
+ qbvh_stack_sort(&traversal_stack[stack_ptr],
+ &traversal_stack[stack_ptr - 1],
+ &traversal_stack[stack_ptr - 2]);
+ node_addr = traversal_stack[stack_ptr].addr;
+ --stack_ptr;
+ continue;
+ }
+
+ /* Four children are hit, push all onto stack and sort 4
+ * stack items, continue with closest child.
+ */
+ r = __bscf(child_mask);
+ int c3 = __float_as_int(cnodes[r]);
+ float d3 = ((float *)&dist)[r];
+ ++stack_ptr;
+ kernel_assert(stack_ptr < BVH_QSTACK_SIZE);
+ traversal_stack[stack_ptr].addr = c3;
+ traversal_stack[stack_ptr].dist = d3;
+ ++stack_ptr;
+ kernel_assert(stack_ptr < BVH_QSTACK_SIZE);
+ traversal_stack[stack_ptr].addr = c2;
+ traversal_stack[stack_ptr].dist = d2;
+ qbvh_stack_sort(&traversal_stack[stack_ptr],
+ &traversal_stack[stack_ptr - 1],
+ &traversal_stack[stack_ptr - 2],
+ &traversal_stack[stack_ptr - 3]);
+ }
+
+ node_addr = traversal_stack[stack_ptr].addr;
+ --stack_ptr;
+ }
+
+ /* If node is leaf, fetch triangle list. */
+ if (node_addr < 0) {
+ float4 leaf = kernel_tex_fetch(__bvh_leaf_nodes, (-node_addr - 1));
+
+ if ((__float_as_uint(leaf.z) & visibility) == 0) {
+ /* Pop. */
+ node_addr = traversal_stack[stack_ptr].addr;
+ --stack_ptr;
+ continue;
+ }
+
+ int prim_addr = __float_as_int(leaf.x);
#if BVH_FEATURE(BVH_INSTANCING)
- if(prim_addr >= 0) {
+ if (prim_addr >= 0) {
#endif
- int prim_addr2 = __float_as_int(leaf.y);
- const uint type = __float_as_int(leaf.w);
- const uint p_type = type & PRIMITIVE_ALL;
- bool hit;
-
- /* Pop. */
- node_addr = traversal_stack[stack_ptr].addr;
- --stack_ptr;
-
- /* Primitive intersection. */
- switch(p_type) {
- case PRIMITIVE_TRIANGLE: {
- for(; prim_addr < prim_addr2; prim_addr++) {
- kernel_assert(kernel_tex_fetch(__prim_type, prim_addr) == type);
- /* Only primitives from volume object. */
- uint tri_object = (object == OBJECT_NONE)? kernel_tex_fetch(__prim_object, prim_addr): object;
- int object_flag = kernel_tex_fetch(__object_flag, tri_object);
- if((object_flag & SD_OBJECT_HAS_VOLUME) == 0) {
- continue;
- }
- /* Intersect ray against primitive. */
- hit = triangle_intersect(kg, isect_array, P, dir, visibility, object, prim_addr);
- if(hit) {
- /* Move on to next entry in intersections array. */
- isect_array++;
- num_hits++;
+ int prim_addr2 = __float_as_int(leaf.y);
+ const uint type = __float_as_int(leaf.w);
+ const uint p_type = type & PRIMITIVE_ALL;
+ bool hit;
+
+ /* Pop. */
+ node_addr = traversal_stack[stack_ptr].addr;
+ --stack_ptr;
+
+ /* Primitive intersection. */
+ switch (p_type) {
+ case PRIMITIVE_TRIANGLE: {
+ for (; prim_addr < prim_addr2; prim_addr++) {
+ kernel_assert(kernel_tex_fetch(__prim_type, prim_addr) == type);
+ /* Only primitives from volume object. */
+ uint tri_object = (object == OBJECT_NONE) ?
+ kernel_tex_fetch(__prim_object, prim_addr) :
+ object;
+ int object_flag = kernel_tex_fetch(__object_flag, tri_object);
+ if ((object_flag & SD_OBJECT_HAS_VOLUME) == 0) {
+ continue;
+ }
+ /* Intersect ray against primitive. */
+ hit = triangle_intersect(kg, isect_array, P, dir, visibility, object, prim_addr);
+ if (hit) {
+ /* Move on to next entry in intersections array. */
+ isect_array++;
+ num_hits++;
#if BVH_FEATURE(BVH_INSTANCING)
- num_hits_in_instance++;
+ num_hits_in_instance++;
#endif
- isect_array->t = isect_t;
- if(num_hits == max_hits) {
+ isect_array->t = isect_t;
+ if (num_hits == max_hits) {
#if BVH_FEATURE(BVH_INSTANCING)
- if(object != OBJECT_NONE) {
+ if (object != OBJECT_NONE) {
# if BVH_FEATURE(BVH_MOTION)
- float t_fac = 1.0f / len(transform_direction(&ob_itfm, dir));
+ float t_fac = 1.0f / len(transform_direction(&ob_itfm, dir));
# else
- Transform itfm = object_fetch_transform(kg, object, OBJECT_INVERSE_TRANSFORM);
- float t_fac = 1.0f / len(transform_direction(&itfm, dir));
+ Transform itfm = object_fetch_transform(
+ kg, object, OBJECT_INVERSE_TRANSFORM);
+ float t_fac = 1.0f / len(transform_direction(&itfm, dir));
# endif
- for(int i = 0; i < num_hits_in_instance; i++) {
- (isect_array-i-1)->t *= t_fac;
- }
- }
-#endif /* BVH_FEATURE(BVH_INSTANCING) */
- return num_hits;
- }
- }
- }
- break;
- }
+ for (int i = 0; i < num_hits_in_instance; i++) {
+ (isect_array - i - 1)->t *= t_fac;
+ }
+ }
+#endif /* BVH_FEATURE(BVH_INSTANCING) */
+ return num_hits;
+ }
+ }
+ }
+ break;
+ }
#if BVH_FEATURE(BVH_MOTION)
- case PRIMITIVE_MOTION_TRIANGLE: {
- for(; prim_addr < prim_addr2; prim_addr++) {
- kernel_assert(kernel_tex_fetch(__prim_type, prim_addr) == type);
- /* Only primitives from volume object. */
- uint tri_object = (object == OBJECT_NONE)? kernel_tex_fetch(__prim_object, prim_addr): object;
- int object_flag = kernel_tex_fetch(__object_flag, tri_object);
- if((object_flag & SD_OBJECT_HAS_VOLUME) == 0) {
- continue;
- }
- /* Intersect ray against primitive. */
- hit = motion_triangle_intersect(kg, isect_array, P, dir, ray->time, visibility, object, prim_addr);
- if(hit) {
- /* Move on to next entry in intersections array. */
- isect_array++;
- num_hits++;
+ case PRIMITIVE_MOTION_TRIANGLE: {
+ for (; prim_addr < prim_addr2; prim_addr++) {
+ kernel_assert(kernel_tex_fetch(__prim_type, prim_addr) == type);
+ /* Only primitives from volume object. */
+ uint tri_object = (object == OBJECT_NONE) ?
+ kernel_tex_fetch(__prim_object, prim_addr) :
+ object;
+ int object_flag = kernel_tex_fetch(__object_flag, tri_object);
+ if ((object_flag & SD_OBJECT_HAS_VOLUME) == 0) {
+ continue;
+ }
+ /* Intersect ray against primitive. */
+ hit = motion_triangle_intersect(
+ kg, isect_array, P, dir, ray->time, visibility, object, prim_addr);
+ if (hit) {
+ /* Move on to next entry in intersections array. */
+ isect_array++;
+ num_hits++;
# if BVH_FEATURE(BVH_INSTANCING)
- num_hits_in_instance++;
+ num_hits_in_instance++;
# endif
- isect_array->t = isect_t;
- if(num_hits == max_hits) {
+ isect_array->t = isect_t;
+ if (num_hits == max_hits) {
# if BVH_FEATURE(BVH_INSTANCING)
- if(object != OBJECT_NONE) {
+ if (object != OBJECT_NONE) {
# if BVH_FEATURE(BVH_MOTION)
- float t_fac = 1.0f / len(transform_direction(&ob_itfm, dir));
+ float t_fac = 1.0f / len(transform_direction(&ob_itfm, dir));
# else
- Transform itfm = object_fetch_transform(kg, object, OBJECT_INVERSE_TRANSFORM);
- float t_fac = 1.0f / len(transform_direction(&itfm, dir));
+ Transform itfm = object_fetch_transform(
+ kg, object, OBJECT_INVERSE_TRANSFORM);
+ float t_fac = 1.0f / len(transform_direction(&itfm, dir));
# endif
- for(int i = 0; i < num_hits_in_instance; i++) {
- (isect_array-i-1)->t *= t_fac;
- }
- }
-# endif /* BVH_FEATURE(BVH_INSTANCING) */
- return num_hits;
- }
- }
- }
- break;
- }
+ for (int i = 0; i < num_hits_in_instance; i++) {
+ (isect_array - i - 1)->t *= t_fac;
+ }
+ }
+# endif /* BVH_FEATURE(BVH_INSTANCING) */
+ return num_hits;
+ }
+ }
+ }
+ break;
+ }
#endif
- }
- }
+ }
+ }
#if BVH_FEATURE(BVH_INSTANCING)
- else {
- /* Instance push. */
- object = kernel_tex_fetch(__prim_object, -prim_addr-1);
- int object_flag = kernel_tex_fetch(__object_flag, object);
- if(object_flag & SD_OBJECT_HAS_VOLUME) {
+ else {
+ /* Instance push. */
+ object = kernel_tex_fetch(__prim_object, -prim_addr - 1);
+ int object_flag = kernel_tex_fetch(__object_flag, object);
+ if (object_flag & SD_OBJECT_HAS_VOLUME) {
# if BVH_FEATURE(BVH_MOTION)
- isect_t = bvh_instance_motion_push(kg, object, ray, &P, &dir, &idir, isect_t, &ob_itfm);
+ isect_t = bvh_instance_motion_push(
+ kg, object, ray, &P, &dir, &idir, isect_t, &ob_itfm);
# else
- isect_t = bvh_instance_push(kg, object, ray, &P, &dir, &idir, isect_t);
+ isect_t = bvh_instance_push(kg, object, ray, &P, &dir, &idir, isect_t);
# endif
- qbvh_near_far_idx_calc(idir,
- &near_x, &near_y, &near_z,
- &far_x, &far_y, &far_z);
- tfar = ssef(isect_t);
- idir4 = sse3f(ssef(idir.x), ssef(idir.y), ssef(idir.z));
+ qbvh_near_far_idx_calc(idir, &near_x, &near_y, &near_z, &far_x, &far_y, &far_z);
+ tfar = ssef(isect_t);
+ idir4 = sse3f(ssef(idir.x), ssef(idir.y), ssef(idir.z));
# if BVH_FEATURE(BVH_HAIR)
- dir4 = sse3f(ssef(dir.x), ssef(dir.y), ssef(dir.z));
+ dir4 = sse3f(ssef(dir.x), ssef(dir.y), ssef(dir.z));
# endif
# ifdef __KERNEL_AVX2__
- P_idir = P*idir;
- P_idir4 = sse3f(P_idir.x, P_idir.y, P_idir.z);
+ P_idir = P * idir;
+ P_idir4 = sse3f(P_idir.x, P_idir.y, P_idir.z);
# endif
# if BVH_FEATURE(BVH_HAIR) || !defined(__KERNEL_AVX2__)
- org4 = sse3f(ssef(P.x), ssef(P.y), ssef(P.z));
+ org4 = sse3f(ssef(P.x), ssef(P.y), ssef(P.z));
# endif
- num_hits_in_instance = 0;
- isect_array->t = isect_t;
-
- ++stack_ptr;
- kernel_assert(stack_ptr < BVH_QSTACK_SIZE);
- traversal_stack[stack_ptr].addr = ENTRYPOINT_SENTINEL;
-
- node_addr = kernel_tex_fetch(__object_node, object);
- }
- else {
- /* Pop. */
- object = OBJECT_NONE;
- node_addr = traversal_stack[stack_ptr].addr;
- --stack_ptr;
- }
- }
- }
-#endif /* FEATURE(BVH_INSTANCING) */
- } while(node_addr != ENTRYPOINT_SENTINEL);
+ num_hits_in_instance = 0;
+ isect_array->t = isect_t;
+
+ ++stack_ptr;
+ kernel_assert(stack_ptr < BVH_QSTACK_SIZE);
+ traversal_stack[stack_ptr].addr = ENTRYPOINT_SENTINEL;
+
+ node_addr = kernel_tex_fetch(__object_node, object);
+ }
+ else {
+ /* Pop. */
+ object = OBJECT_NONE;
+ node_addr = traversal_stack[stack_ptr].addr;
+ --stack_ptr;
+ }
+ }
+ }
+#endif /* FEATURE(BVH_INSTANCING) */
+ } while (node_addr != ENTRYPOINT_SENTINEL);
#if BVH_FEATURE(BVH_INSTANCING)
- if(stack_ptr >= 0) {
- kernel_assert(object != OBJECT_NONE);
+ if (stack_ptr >= 0) {
+ kernel_assert(object != OBJECT_NONE);
- /* Instance pop. */
- if(num_hits_in_instance) {
- float t_fac;
+ /* Instance pop. */
+ if (num_hits_in_instance) {
+ float t_fac;
# if BVH_FEATURE(BVH_MOTION)
- bvh_instance_motion_pop_factor(kg, object, ray, &P, &dir, &idir, &t_fac, &ob_itfm);
+ bvh_instance_motion_pop_factor(kg, object, ray, &P, &dir, &idir, &t_fac, &ob_itfm);
# else
- bvh_instance_pop_factor(kg, object, ray, &P, &dir, &idir, &t_fac);
+ bvh_instance_pop_factor(kg, object, ray, &P, &dir, &idir, &t_fac);
# endif
- /* Scale isect->t to adjust for instancing. */
- for(int i = 0; i < num_hits_in_instance; i++) {
- (isect_array-i-1)->t *= t_fac;
- }
- }
- else {
+ /* Scale isect->t to adjust for instancing. */
+ for (int i = 0; i < num_hits_in_instance; i++) {
+ (isect_array - i - 1)->t *= t_fac;
+ }
+ }
+ else {
# if BVH_FEATURE(BVH_MOTION)
- bvh_instance_motion_pop(kg, object, ray, &P, &dir, &idir, FLT_MAX, &ob_itfm);
+ bvh_instance_motion_pop(kg, object, ray, &P, &dir, &idir, FLT_MAX, &ob_itfm);
# else
- bvh_instance_pop(kg, object, ray, &P, &dir, &idir, FLT_MAX);
+ bvh_instance_pop(kg, object, ray, &P, &dir, &idir, FLT_MAX);
# endif
- }
+ }
- isect_t = tmax;
- isect_array->t = isect_t;
+ isect_t = tmax;
+ isect_array->t = isect_t;
- qbvh_near_far_idx_calc(idir,
- &near_x, &near_y, &near_z,
- &far_x, &far_y, &far_z);
- tfar = ssef(isect_t);
+ qbvh_near_far_idx_calc(idir, &near_x, &near_y, &near_z, &far_x, &far_y, &far_z);
+ tfar = ssef(isect_t);
# if BVH_FEATURE(BVH_HAIR)
- dir4 = sse3f(ssef(dir.x), ssef(dir.y), ssef(dir.z));
+ dir4 = sse3f(ssef(dir.x), ssef(dir.y), ssef(dir.z));
# endif
- idir4 = sse3f(ssef(idir.x), ssef(idir.y), ssef(idir.z));
+ idir4 = sse3f(ssef(idir.x), ssef(idir.y), ssef(idir.z));
# ifdef __KERNEL_AVX2__
- P_idir = P*idir;
- P_idir4 = sse3f(P_idir.x, P_idir.y, P_idir.z);
+ P_idir = P * idir;
+ P_idir4 = sse3f(P_idir.x, P_idir.y, P_idir.z);
# endif
# if BVH_FEATURE(BVH_HAIR) || !defined(__KERNEL_AVX2__)
- org4 = sse3f(ssef(P.x), ssef(P.y), ssef(P.z));
+ org4 = sse3f(ssef(P.x), ssef(P.y), ssef(P.z));
# endif
- object = OBJECT_NONE;
- node_addr = traversal_stack[stack_ptr].addr;
- --stack_ptr;
- }
-#endif /* FEATURE(BVH_INSTANCING) */
- } while(node_addr != ENTRYPOINT_SENTINEL);
+ object = OBJECT_NONE;
+ node_addr = traversal_stack[stack_ptr].addr;
+ --stack_ptr;
+ }
+#endif /* FEATURE(BVH_INSTANCING) */
+ } while (node_addr != ENTRYPOINT_SENTINEL);
- return num_hits;
+ return num_hits;
}
#undef NODE_INTERSECT
diff --git a/intern/cycles/kernel/closure/alloc.h b/intern/cycles/kernel/closure/alloc.h
index acccba9ecec..341d1e16eb1 100644
--- a/intern/cycles/kernel/closure/alloc.h
+++ b/intern/cycles/kernel/closure/alloc.h
@@ -18,69 +18,72 @@ CCL_NAMESPACE_BEGIN
ccl_device ShaderClosure *closure_alloc(ShaderData *sd, int size, ClosureType type, float3 weight)
{
- kernel_assert(size <= sizeof(ShaderClosure));
+ kernel_assert(size <= sizeof(ShaderClosure));
- if(sd->num_closure_left == 0)
- return NULL;
+ if (sd->num_closure_left == 0)
+ return NULL;
- ShaderClosure *sc = &sd->closure[sd->num_closure];
+ ShaderClosure *sc = &sd->closure[sd->num_closure];
- sc->type = type;
- sc->weight = weight;
+ sc->type = type;
+ sc->weight = weight;
- sd->num_closure++;
- sd->num_closure_left--;
+ sd->num_closure++;
+ sd->num_closure_left--;
- return sc;
+ return sc;
}
ccl_device ccl_addr_space void *closure_alloc_extra(ShaderData *sd, int size)
{
- /* Allocate extra space for closure that need more parameters. We allocate
- * in chunks of sizeof(ShaderClosure) starting from the end of the closure
- * array.
- *
- * This lets us keep the same fast array iteration over closures, as we
- * found linked list iteration and iteration with skipping to be slower. */
- int num_extra = ((size + sizeof(ShaderClosure) - 1) / sizeof(ShaderClosure));
-
- if(num_extra > sd->num_closure_left) {
- /* Remove previous closure if it was allocated. */
- sd->num_closure--;
- sd->num_closure_left++;
- return NULL;
- }
-
- sd->num_closure_left -= num_extra;
- return (ccl_addr_space void*)(sd->closure + sd->num_closure + sd->num_closure_left);
+ /* Allocate extra space for closure that need more parameters. We allocate
+ * in chunks of sizeof(ShaderClosure) starting from the end of the closure
+ * array.
+ *
+ * This lets us keep the same fast array iteration over closures, as we
+ * found linked list iteration and iteration with skipping to be slower. */
+ int num_extra = ((size + sizeof(ShaderClosure) - 1) / sizeof(ShaderClosure));
+
+ if (num_extra > sd->num_closure_left) {
+ /* Remove previous closure if it was allocated. */
+ sd->num_closure--;
+ sd->num_closure_left++;
+ return NULL;
+ }
+
+ sd->num_closure_left -= num_extra;
+ return (ccl_addr_space void *)(sd->closure + sd->num_closure + sd->num_closure_left);
}
ccl_device_inline ShaderClosure *bsdf_alloc(ShaderData *sd, int size, float3 weight)
{
- ShaderClosure *sc = closure_alloc(sd, size, CLOSURE_NONE_ID, weight);
+ ShaderClosure *sc = closure_alloc(sd, size, CLOSURE_NONE_ID, weight);
- if(sc == NULL)
- return NULL;
+ if (sc == NULL)
+ return NULL;
- float sample_weight = fabsf(average(weight));
- sc->sample_weight = sample_weight;
- return (sample_weight >= CLOSURE_WEIGHT_CUTOFF) ? sc : NULL;
+ float sample_weight = fabsf(average(weight));
+ sc->sample_weight = sample_weight;
+ return (sample_weight >= CLOSURE_WEIGHT_CUTOFF) ? sc : NULL;
}
#ifdef __OSL__
-ccl_device_inline ShaderClosure *bsdf_alloc_osl(ShaderData *sd, int size, float3 weight, void *data)
+ccl_device_inline ShaderClosure *bsdf_alloc_osl(ShaderData *sd,
+ int size,
+ float3 weight,
+ void *data)
{
- ShaderClosure *sc = closure_alloc(sd, size, CLOSURE_NONE_ID, weight);
+ ShaderClosure *sc = closure_alloc(sd, size, CLOSURE_NONE_ID, weight);
- if(!sc)
- return NULL;
+ if (!sc)
+ return NULL;
- memcpy((void *)sc, data, size);
+ memcpy((void *)sc, data, size);
- float sample_weight = fabsf(average(weight));
- sc->weight = weight;
- sc->sample_weight = sample_weight;
- return (sample_weight >= CLOSURE_WEIGHT_CUTOFF) ? sc : NULL;
+ float sample_weight = fabsf(average(weight));
+ sc->weight = weight;
+ sc->sample_weight = sample_weight;
+ return (sample_weight >= CLOSURE_WEIGHT_CUTOFF) ? sc : NULL;
}
#endif
diff --git a/intern/cycles/kernel/closure/bsdf.h b/intern/cycles/kernel/closure/bsdf.h
index 3a9629ea9d7..5e26f90a878 100644
--- a/intern/cycles/kernel/closure/bsdf.h
+++ b/intern/cycles/kernel/closure/bsdf.h
@@ -39,38 +39,38 @@ CCL_NAMESPACE_BEGIN
* 0 for singular closures and 1 otherwise. */
ccl_device_inline float bsdf_get_specular_roughness_squared(const ShaderClosure *sc)
{
- if(CLOSURE_IS_BSDF_SINGULAR(sc->type)) {
- return 0.0f;
- }
+ if (CLOSURE_IS_BSDF_SINGULAR(sc->type)) {
+ return 0.0f;
+ }
- if(CLOSURE_IS_BSDF_MICROFACET(sc->type)) {
- MicrofacetBsdf *bsdf = (MicrofacetBsdf*)sc;
- return bsdf->alpha_x*bsdf->alpha_y;
- }
+ if (CLOSURE_IS_BSDF_MICROFACET(sc->type)) {
+ MicrofacetBsdf *bsdf = (MicrofacetBsdf *)sc;
+ return bsdf->alpha_x * bsdf->alpha_y;
+ }
- return 1.0f;
+ return 1.0f;
}
ccl_device_inline float bsdf_get_roughness_squared(const ShaderClosure *sc)
{
- /* This version includes diffuse, mainly for baking Principled BSDF
- * where specular and metallic zero otherwise does not bake the
- * specified roughness parameter. */
- if(sc->type == CLOSURE_BSDF_OREN_NAYAR_ID) {
- OrenNayarBsdf *bsdf = (OrenNayarBsdf*)sc;
- return sqr(sqr(bsdf->roughness));
- }
+ /* This version includes diffuse, mainly for baking Principled BSDF
+ * where specular and metallic zero otherwise does not bake the
+ * specified roughness parameter. */
+ if (sc->type == CLOSURE_BSDF_OREN_NAYAR_ID) {
+ OrenNayarBsdf *bsdf = (OrenNayarBsdf *)sc;
+ return sqr(sqr(bsdf->roughness));
+ }
- if(sc->type == CLOSURE_BSDF_PRINCIPLED_DIFFUSE_ID) {
- PrincipledDiffuseBsdf *bsdf = (PrincipledDiffuseBsdf*)sc;
- return sqr(sqr(bsdf->roughness));
- }
+ if (sc->type == CLOSURE_BSDF_PRINCIPLED_DIFFUSE_ID) {
+ PrincipledDiffuseBsdf *bsdf = (PrincipledDiffuseBsdf *)sc;
+ return sqr(sqr(bsdf->roughness));
+ }
- if(CLOSURE_IS_BSDF_DIFFUSE(sc->type)) {
- return 0.0f;
- }
+ if (CLOSURE_IS_BSDF_DIFFUSE(sc->type)) {
+ return 0.0f;
+ }
- return bsdf_get_specular_roughness_squared(sc);
+ return bsdf_get_specular_roughness_squared(sc);
}
ccl_device_inline int bsdf_sample(KernelGlobals *kg,
@@ -83,133 +83,349 @@ ccl_device_inline int bsdf_sample(KernelGlobals *kg,
differential3 *domega_in,
float *pdf)
{
- int label;
+ int label;
- switch(sc->type) {
- case CLOSURE_BSDF_DIFFUSE_ID:
- case CLOSURE_BSDF_BSSRDF_ID:
- label = bsdf_diffuse_sample(sc, sd->Ng, sd->I, sd->dI.dx, sd->dI.dy, randu, randv,
- eval, omega_in, &domega_in->dx, &domega_in->dy, pdf);
- break;
+ switch (sc->type) {
+ case CLOSURE_BSDF_DIFFUSE_ID:
+ case CLOSURE_BSDF_BSSRDF_ID:
+ label = bsdf_diffuse_sample(sc,
+ sd->Ng,
+ sd->I,
+ sd->dI.dx,
+ sd->dI.dy,
+ randu,
+ randv,
+ eval,
+ omega_in,
+ &domega_in->dx,
+ &domega_in->dy,
+ pdf);
+ break;
#ifdef __SVM__
- case CLOSURE_BSDF_OREN_NAYAR_ID:
- label = bsdf_oren_nayar_sample(sc, sd->Ng, sd->I, sd->dI.dx, sd->dI.dy, randu, randv,
- eval, omega_in, &domega_in->dx, &domega_in->dy, pdf);
- break;
-#ifdef __OSL__
- case CLOSURE_BSDF_PHONG_RAMP_ID:
- label = bsdf_phong_ramp_sample(sc, sd->Ng, sd->I, sd->dI.dx, sd->dI.dy, randu, randv,
- eval, omega_in, &domega_in->dx, &domega_in->dy, pdf);
- break;
- case CLOSURE_BSDF_DIFFUSE_RAMP_ID:
- label = bsdf_diffuse_ramp_sample(sc, sd->Ng, sd->I, sd->dI.dx, sd->dI.dy, randu, randv,
- eval, omega_in, &domega_in->dx, &domega_in->dy, pdf);
- break;
-#endif
- case CLOSURE_BSDF_TRANSLUCENT_ID:
- label = bsdf_translucent_sample(sc, sd->Ng, sd->I, sd->dI.dx, sd->dI.dy, randu, randv,
- eval, omega_in, &domega_in->dx, &domega_in->dy, pdf);
- break;
- case CLOSURE_BSDF_REFLECTION_ID:
- label = bsdf_reflection_sample(sc, sd->Ng, sd->I, sd->dI.dx, sd->dI.dy, randu, randv,
- eval, omega_in, &domega_in->dx, &domega_in->dy, pdf);
- break;
- case CLOSURE_BSDF_REFRACTION_ID:
- label = bsdf_refraction_sample(sc, sd->Ng, sd->I, sd->dI.dx, sd->dI.dy, randu, randv,
- eval, omega_in, &domega_in->dx, &domega_in->dy, pdf);
- break;
- case CLOSURE_BSDF_TRANSPARENT_ID:
- label = bsdf_transparent_sample(sc, sd->Ng, sd->I, sd->dI.dx, sd->dI.dy, randu, randv,
- eval, omega_in, &domega_in->dx, &domega_in->dy, pdf);
- break;
- case CLOSURE_BSDF_MICROFACET_GGX_ID:
- case CLOSURE_BSDF_MICROFACET_GGX_FRESNEL_ID:
- case CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_ID:
- case CLOSURE_BSDF_MICROFACET_GGX_ANISO_ID:
- case CLOSURE_BSDF_MICROFACET_GGX_ANISO_FRESNEL_ID:
- case CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID:
- label = bsdf_microfacet_ggx_sample(kg, sc, sd->Ng, sd->I, sd->dI.dx, sd->dI.dy, randu, randv,
- eval, omega_in, &domega_in->dx, &domega_in->dy, pdf);
- break;
- case CLOSURE_BSDF_MICROFACET_MULTI_GGX_ID:
- case CLOSURE_BSDF_MICROFACET_MULTI_GGX_FRESNEL_ID:
- label = bsdf_microfacet_multi_ggx_sample(kg, sc, sd->Ng, sd->I, sd->dI.dx, sd->dI.dy, randu, randv,
- eval, omega_in, &domega_in->dx, &domega_in->dy, pdf, &sd->lcg_state);
- break;
- case CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID:
- case CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_FRESNEL_ID:
- label = bsdf_microfacet_multi_ggx_glass_sample(kg, sc, sd->Ng, sd->I, sd->dI.dx, sd->dI.dy, randu, randv,
- eval, omega_in, &domega_in->dx, &domega_in->dy, pdf, &sd->lcg_state);
- break;
- case CLOSURE_BSDF_MICROFACET_BECKMANN_ID:
- case CLOSURE_BSDF_MICROFACET_BECKMANN_ANISO_ID:
- case CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID:
- label = bsdf_microfacet_beckmann_sample(kg, sc, sd->Ng, sd->I, sd->dI.dx, sd->dI.dy, randu, randv,
- eval, omega_in, &domega_in->dx, &domega_in->dy, pdf);
- break;
- case CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ID:
- case CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ANISO_ID:
- label = bsdf_ashikhmin_shirley_sample(sc, sd->Ng, sd->I, sd->dI.dx, sd->dI.dy, randu, randv,
- eval, omega_in, &domega_in->dx, &domega_in->dy, pdf);
- break;
- case CLOSURE_BSDF_ASHIKHMIN_VELVET_ID:
- label = bsdf_ashikhmin_velvet_sample(sc, sd->Ng, sd->I, sd->dI.dx, sd->dI.dy, randu, randv,
- eval, omega_in, &domega_in->dx, &domega_in->dy, pdf);
- break;
- case CLOSURE_BSDF_DIFFUSE_TOON_ID:
- label = bsdf_diffuse_toon_sample(sc, sd->Ng, sd->I, sd->dI.dx, sd->dI.dy, randu, randv,
- eval, omega_in, &domega_in->dx, &domega_in->dy, pdf);
- break;
- case CLOSURE_BSDF_GLOSSY_TOON_ID:
- label = bsdf_glossy_toon_sample(sc, sd->Ng, sd->I, sd->dI.dx, sd->dI.dy, randu, randv,
- eval, omega_in, &domega_in->dx, &domega_in->dy, pdf);
- break;
- case CLOSURE_BSDF_HAIR_REFLECTION_ID:
- label = bsdf_hair_reflection_sample(sc, sd->Ng, sd->I, sd->dI.dx, sd->dI.dy, randu, randv,
- eval, omega_in, &domega_in->dx, &domega_in->dy, pdf);
- break;
- case CLOSURE_BSDF_HAIR_TRANSMISSION_ID:
- label = bsdf_hair_transmission_sample(sc, sd->Ng, sd->I, sd->dI.dx, sd->dI.dy, randu, randv,
- eval, omega_in, &domega_in->dx, &domega_in->dy, pdf);
- break;
- case CLOSURE_BSDF_HAIR_PRINCIPLED_ID:
- label = bsdf_principled_hair_sample(kg, sc, sd, randu, randv,
- eval, omega_in, &domega_in->dx, &domega_in->dy, pdf);
- break;
-#ifdef __PRINCIPLED__
- case CLOSURE_BSDF_PRINCIPLED_DIFFUSE_ID:
- case CLOSURE_BSDF_BSSRDF_PRINCIPLED_ID:
- label = bsdf_principled_diffuse_sample(sc, sd->Ng, sd->I, sd->dI.dx, sd->dI.dy, randu, randv,
- eval, omega_in, &domega_in->dx, &domega_in->dy, pdf);
- break;
- case CLOSURE_BSDF_PRINCIPLED_SHEEN_ID:
- label = bsdf_principled_sheen_sample(sc, sd->Ng, sd->I, sd->dI.dx, sd->dI.dy, randu, randv,
- eval, omega_in, &domega_in->dx, &domega_in->dy, pdf);
- break;
-#endif /* __PRINCIPLED__ */
+ case CLOSURE_BSDF_OREN_NAYAR_ID:
+ label = bsdf_oren_nayar_sample(sc,
+ sd->Ng,
+ sd->I,
+ sd->dI.dx,
+ sd->dI.dy,
+ randu,
+ randv,
+ eval,
+ omega_in,
+ &domega_in->dx,
+ &domega_in->dy,
+ pdf);
+ break;
+# ifdef __OSL__
+ case CLOSURE_BSDF_PHONG_RAMP_ID:
+ label = bsdf_phong_ramp_sample(sc,
+ sd->Ng,
+ sd->I,
+ sd->dI.dx,
+ sd->dI.dy,
+ randu,
+ randv,
+ eval,
+ omega_in,
+ &domega_in->dx,
+ &domega_in->dy,
+ pdf);
+ break;
+ case CLOSURE_BSDF_DIFFUSE_RAMP_ID:
+ label = bsdf_diffuse_ramp_sample(sc,
+ sd->Ng,
+ sd->I,
+ sd->dI.dx,
+ sd->dI.dy,
+ randu,
+ randv,
+ eval,
+ omega_in,
+ &domega_in->dx,
+ &domega_in->dy,
+ pdf);
+ break;
+# endif
+ case CLOSURE_BSDF_TRANSLUCENT_ID:
+ label = bsdf_translucent_sample(sc,
+ sd->Ng,
+ sd->I,
+ sd->dI.dx,
+ sd->dI.dy,
+ randu,
+ randv,
+ eval,
+ omega_in,
+ &domega_in->dx,
+ &domega_in->dy,
+ pdf);
+ break;
+ case CLOSURE_BSDF_REFLECTION_ID:
+ label = bsdf_reflection_sample(sc,
+ sd->Ng,
+ sd->I,
+ sd->dI.dx,
+ sd->dI.dy,
+ randu,
+ randv,
+ eval,
+ omega_in,
+ &domega_in->dx,
+ &domega_in->dy,
+ pdf);
+ break;
+ case CLOSURE_BSDF_REFRACTION_ID:
+ label = bsdf_refraction_sample(sc,
+ sd->Ng,
+ sd->I,
+ sd->dI.dx,
+ sd->dI.dy,
+ randu,
+ randv,
+ eval,
+ omega_in,
+ &domega_in->dx,
+ &domega_in->dy,
+ pdf);
+ break;
+ case CLOSURE_BSDF_TRANSPARENT_ID:
+ label = bsdf_transparent_sample(sc,
+ sd->Ng,
+ sd->I,
+ sd->dI.dx,
+ sd->dI.dy,
+ randu,
+ randv,
+ eval,
+ omega_in,
+ &domega_in->dx,
+ &domega_in->dy,
+ pdf);
+ break;
+ case CLOSURE_BSDF_MICROFACET_GGX_ID:
+ case CLOSURE_BSDF_MICROFACET_GGX_FRESNEL_ID:
+ case CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_ID:
+ case CLOSURE_BSDF_MICROFACET_GGX_ANISO_ID:
+ case CLOSURE_BSDF_MICROFACET_GGX_ANISO_FRESNEL_ID:
+ case CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID:
+ label = bsdf_microfacet_ggx_sample(kg,
+ sc,
+ sd->Ng,
+ sd->I,
+ sd->dI.dx,
+ sd->dI.dy,
+ randu,
+ randv,
+ eval,
+ omega_in,
+ &domega_in->dx,
+ &domega_in->dy,
+ pdf);
+ break;
+ case CLOSURE_BSDF_MICROFACET_MULTI_GGX_ID:
+ case CLOSURE_BSDF_MICROFACET_MULTI_GGX_FRESNEL_ID:
+ label = bsdf_microfacet_multi_ggx_sample(kg,
+ sc,
+ sd->Ng,
+ sd->I,
+ sd->dI.dx,
+ sd->dI.dy,
+ randu,
+ randv,
+ eval,
+ omega_in,
+ &domega_in->dx,
+ &domega_in->dy,
+ pdf,
+ &sd->lcg_state);
+ break;
+ case CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID:
+ case CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_FRESNEL_ID:
+ label = bsdf_microfacet_multi_ggx_glass_sample(kg,
+ sc,
+ sd->Ng,
+ sd->I,
+ sd->dI.dx,
+ sd->dI.dy,
+ randu,
+ randv,
+ eval,
+ omega_in,
+ &domega_in->dx,
+ &domega_in->dy,
+ pdf,
+ &sd->lcg_state);
+ break;
+ case CLOSURE_BSDF_MICROFACET_BECKMANN_ID:
+ case CLOSURE_BSDF_MICROFACET_BECKMANN_ANISO_ID:
+ case CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID:
+ label = bsdf_microfacet_beckmann_sample(kg,
+ sc,
+ sd->Ng,
+ sd->I,
+ sd->dI.dx,
+ sd->dI.dy,
+ randu,
+ randv,
+ eval,
+ omega_in,
+ &domega_in->dx,
+ &domega_in->dy,
+ pdf);
+ break;
+ case CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ID:
+ case CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ANISO_ID:
+ label = bsdf_ashikhmin_shirley_sample(sc,
+ sd->Ng,
+ sd->I,
+ sd->dI.dx,
+ sd->dI.dy,
+ randu,
+ randv,
+ eval,
+ omega_in,
+ &domega_in->dx,
+ &domega_in->dy,
+ pdf);
+ break;
+ case CLOSURE_BSDF_ASHIKHMIN_VELVET_ID:
+ label = bsdf_ashikhmin_velvet_sample(sc,
+ sd->Ng,
+ sd->I,
+ sd->dI.dx,
+ sd->dI.dy,
+ randu,
+ randv,
+ eval,
+ omega_in,
+ &domega_in->dx,
+ &domega_in->dy,
+ pdf);
+ break;
+ case CLOSURE_BSDF_DIFFUSE_TOON_ID:
+ label = bsdf_diffuse_toon_sample(sc,
+ sd->Ng,
+ sd->I,
+ sd->dI.dx,
+ sd->dI.dy,
+ randu,
+ randv,
+ eval,
+ omega_in,
+ &domega_in->dx,
+ &domega_in->dy,
+ pdf);
+ break;
+ case CLOSURE_BSDF_GLOSSY_TOON_ID:
+ label = bsdf_glossy_toon_sample(sc,
+ sd->Ng,
+ sd->I,
+ sd->dI.dx,
+ sd->dI.dy,
+ randu,
+ randv,
+ eval,
+ omega_in,
+ &domega_in->dx,
+ &domega_in->dy,
+ pdf);
+ break;
+ case CLOSURE_BSDF_HAIR_REFLECTION_ID:
+ label = bsdf_hair_reflection_sample(sc,
+ sd->Ng,
+ sd->I,
+ sd->dI.dx,
+ sd->dI.dy,
+ randu,
+ randv,
+ eval,
+ omega_in,
+ &domega_in->dx,
+ &domega_in->dy,
+ pdf);
+ break;
+ case CLOSURE_BSDF_HAIR_TRANSMISSION_ID:
+ label = bsdf_hair_transmission_sample(sc,
+ sd->Ng,
+ sd->I,
+ sd->dI.dx,
+ sd->dI.dy,
+ randu,
+ randv,
+ eval,
+ omega_in,
+ &domega_in->dx,
+ &domega_in->dy,
+ pdf);
+ break;
+ case CLOSURE_BSDF_HAIR_PRINCIPLED_ID:
+ label = bsdf_principled_hair_sample(
+ kg, sc, sd, randu, randv, eval, omega_in, &domega_in->dx, &domega_in->dy, pdf);
+ break;
+# ifdef __PRINCIPLED__
+ case CLOSURE_BSDF_PRINCIPLED_DIFFUSE_ID:
+ case CLOSURE_BSDF_BSSRDF_PRINCIPLED_ID:
+ label = bsdf_principled_diffuse_sample(sc,
+ sd->Ng,
+ sd->I,
+ sd->dI.dx,
+ sd->dI.dy,
+ randu,
+ randv,
+ eval,
+ omega_in,
+ &domega_in->dx,
+ &domega_in->dy,
+ pdf);
+ break;
+ case CLOSURE_BSDF_PRINCIPLED_SHEEN_ID:
+ label = bsdf_principled_sheen_sample(sc,
+ sd->Ng,
+ sd->I,
+ sd->dI.dx,
+ sd->dI.dy,
+ randu,
+ randv,
+ eval,
+ omega_in,
+ &domega_in->dx,
+ &domega_in->dy,
+ pdf);
+ break;
+# endif /* __PRINCIPLED__ */
#endif
#ifdef __VOLUME__
- case CLOSURE_VOLUME_HENYEY_GREENSTEIN_ID:
- label = volume_henyey_greenstein_sample(sc, sd->I, sd->dI.dx, sd->dI.dy, randu, randv, eval, omega_in, &domega_in->dx, &domega_in->dy, pdf);
- break;
+ case CLOSURE_VOLUME_HENYEY_GREENSTEIN_ID:
+ label = volume_henyey_greenstein_sample(sc,
+ sd->I,
+ sd->dI.dx,
+ sd->dI.dy,
+ randu,
+ randv,
+ eval,
+ omega_in,
+ &domega_in->dx,
+ &domega_in->dy,
+ pdf);
+ break;
#endif
- default:
- label = LABEL_NONE;
- break;
- }
+ default:
+ label = LABEL_NONE;
+ break;
+ }
- /* Test if BSDF sample should be treated as transparent for background. */
- if(label & LABEL_TRANSMIT) {
- float threshold_squared = kernel_data.background.transparent_roughness_squared_threshold;
+ /* Test if BSDF sample should be treated as transparent for background. */
+ if (label & LABEL_TRANSMIT) {
+ float threshold_squared = kernel_data.background.transparent_roughness_squared_threshold;
- if(threshold_squared >= 0.0f) {
- if(bsdf_get_specular_roughness_squared(sc) <= threshold_squared) {
- label |= LABEL_TRANSMIT_TRANSPARENT;
- }
- }
- }
+ if (threshold_squared >= 0.0f) {
+ if (bsdf_get_specular_roughness_squared(sc) <= threshold_squared) {
+ label |= LABEL_TRANSMIT_TRANSPARENT;
+ }
+ }
+ }
- return label;
+ return label;
}
#ifndef __KERNEL_CUDA__
@@ -217,285 +433,288 @@ ccl_device
#else
ccl_device_inline
#endif
-float3 bsdf_eval(KernelGlobals *kg,
- ShaderData *sd,
- const ShaderClosure *sc,
- const float3 omega_in,
- float *pdf)
+ float3
+ bsdf_eval(KernelGlobals *kg,
+ ShaderData *sd,
+ const ShaderClosure *sc,
+ const float3 omega_in,
+ float *pdf)
{
- float3 eval;
+ float3 eval;
- if(dot(sd->Ng, omega_in) >= 0.0f) {
- switch(sc->type) {
- case CLOSURE_BSDF_DIFFUSE_ID:
- case CLOSURE_BSDF_BSSRDF_ID:
- eval = bsdf_diffuse_eval_reflect(sc, sd->I, omega_in, pdf);
- break;
+ if (dot(sd->Ng, omega_in) >= 0.0f) {
+ switch (sc->type) {
+ case CLOSURE_BSDF_DIFFUSE_ID:
+ case CLOSURE_BSDF_BSSRDF_ID:
+ eval = bsdf_diffuse_eval_reflect(sc, sd->I, omega_in, pdf);
+ break;
#ifdef __SVM__
- case CLOSURE_BSDF_OREN_NAYAR_ID:
- eval = bsdf_oren_nayar_eval_reflect(sc, sd->I, omega_in, pdf);
- break;
-#ifdef __OSL__
- case CLOSURE_BSDF_PHONG_RAMP_ID:
- eval = bsdf_phong_ramp_eval_reflect(sc, sd->I, omega_in, pdf);
- break;
- case CLOSURE_BSDF_DIFFUSE_RAMP_ID:
- eval = bsdf_diffuse_ramp_eval_reflect(sc, sd->I, omega_in, pdf);
- break;
-#endif
- case CLOSURE_BSDF_TRANSLUCENT_ID:
- eval = bsdf_translucent_eval_reflect(sc, sd->I, omega_in, pdf);
- break;
- case CLOSURE_BSDF_REFLECTION_ID:
- eval = bsdf_reflection_eval_reflect(sc, sd->I, omega_in, pdf);
- break;
- case CLOSURE_BSDF_REFRACTION_ID:
- eval = bsdf_refraction_eval_reflect(sc, sd->I, omega_in, pdf);
- break;
- case CLOSURE_BSDF_TRANSPARENT_ID:
- eval = bsdf_transparent_eval_reflect(sc, sd->I, omega_in, pdf);
- break;
- case CLOSURE_BSDF_MICROFACET_GGX_ID:
- case CLOSURE_BSDF_MICROFACET_GGX_FRESNEL_ID:
- case CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_ID:
- case CLOSURE_BSDF_MICROFACET_GGX_ANISO_ID:
- case CLOSURE_BSDF_MICROFACET_GGX_ANISO_FRESNEL_ID:
- case CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID:
- eval = bsdf_microfacet_ggx_eval_reflect(sc, sd->I, omega_in, pdf);
- break;
- case CLOSURE_BSDF_MICROFACET_MULTI_GGX_ID:
- case CLOSURE_BSDF_MICROFACET_MULTI_GGX_FRESNEL_ID:
- eval = bsdf_microfacet_multi_ggx_eval_reflect(sc, sd->I, omega_in, pdf, &sd->lcg_state);
- break;
- case CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID:
- case CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_FRESNEL_ID:
- eval = bsdf_microfacet_multi_ggx_glass_eval_reflect(sc, sd->I, omega_in, pdf, &sd->lcg_state);
- break;
- case CLOSURE_BSDF_MICROFACET_BECKMANN_ID:
- case CLOSURE_BSDF_MICROFACET_BECKMANN_ANISO_ID:
- case CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID:
- eval = bsdf_microfacet_beckmann_eval_reflect(sc, sd->I, omega_in, pdf);
- break;
- case CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ID:
- case CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ANISO_ID:
- eval = bsdf_ashikhmin_shirley_eval_reflect(sc, sd->I, omega_in, pdf);
- break;
- case CLOSURE_BSDF_ASHIKHMIN_VELVET_ID:
- eval = bsdf_ashikhmin_velvet_eval_reflect(sc, sd->I, omega_in, pdf);
- break;
- case CLOSURE_BSDF_DIFFUSE_TOON_ID:
- eval = bsdf_diffuse_toon_eval_reflect(sc, sd->I, omega_in, pdf);
- break;
- case CLOSURE_BSDF_GLOSSY_TOON_ID:
- eval = bsdf_glossy_toon_eval_reflect(sc, sd->I, omega_in, pdf);
- break;
- case CLOSURE_BSDF_HAIR_PRINCIPLED_ID:
- eval = bsdf_principled_hair_eval(kg, sd, sc, omega_in, pdf);
- break;
- case CLOSURE_BSDF_HAIR_REFLECTION_ID:
- eval = bsdf_hair_reflection_eval_reflect(sc, sd->I, omega_in, pdf);
- break;
- case CLOSURE_BSDF_HAIR_TRANSMISSION_ID:
- eval = bsdf_hair_transmission_eval_reflect(sc, sd->I, omega_in, pdf);
- break;
-#ifdef __PRINCIPLED__
- case CLOSURE_BSDF_PRINCIPLED_DIFFUSE_ID:
- case CLOSURE_BSDF_BSSRDF_PRINCIPLED_ID:
- eval = bsdf_principled_diffuse_eval_reflect(sc, sd->I, omega_in, pdf);
- break;
- case CLOSURE_BSDF_PRINCIPLED_SHEEN_ID:
- eval = bsdf_principled_sheen_eval_reflect(sc, sd->I, omega_in, pdf);
- break;
-#endif /* __PRINCIPLED__ */
+ case CLOSURE_BSDF_OREN_NAYAR_ID:
+ eval = bsdf_oren_nayar_eval_reflect(sc, sd->I, omega_in, pdf);
+ break;
+# ifdef __OSL__
+ case CLOSURE_BSDF_PHONG_RAMP_ID:
+ eval = bsdf_phong_ramp_eval_reflect(sc, sd->I, omega_in, pdf);
+ break;
+ case CLOSURE_BSDF_DIFFUSE_RAMP_ID:
+ eval = bsdf_diffuse_ramp_eval_reflect(sc, sd->I, omega_in, pdf);
+ break;
+# endif
+ case CLOSURE_BSDF_TRANSLUCENT_ID:
+ eval = bsdf_translucent_eval_reflect(sc, sd->I, omega_in, pdf);
+ break;
+ case CLOSURE_BSDF_REFLECTION_ID:
+ eval = bsdf_reflection_eval_reflect(sc, sd->I, omega_in, pdf);
+ break;
+ case CLOSURE_BSDF_REFRACTION_ID:
+ eval = bsdf_refraction_eval_reflect(sc, sd->I, omega_in, pdf);
+ break;
+ case CLOSURE_BSDF_TRANSPARENT_ID:
+ eval = bsdf_transparent_eval_reflect(sc, sd->I, omega_in, pdf);
+ break;
+ case CLOSURE_BSDF_MICROFACET_GGX_ID:
+ case CLOSURE_BSDF_MICROFACET_GGX_FRESNEL_ID:
+ case CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_ID:
+ case CLOSURE_BSDF_MICROFACET_GGX_ANISO_ID:
+ case CLOSURE_BSDF_MICROFACET_GGX_ANISO_FRESNEL_ID:
+ case CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID:
+ eval = bsdf_microfacet_ggx_eval_reflect(sc, sd->I, omega_in, pdf);
+ break;
+ case CLOSURE_BSDF_MICROFACET_MULTI_GGX_ID:
+ case CLOSURE_BSDF_MICROFACET_MULTI_GGX_FRESNEL_ID:
+ eval = bsdf_microfacet_multi_ggx_eval_reflect(sc, sd->I, omega_in, pdf, &sd->lcg_state);
+ break;
+ case CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID:
+ case CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_FRESNEL_ID:
+ eval = bsdf_microfacet_multi_ggx_glass_eval_reflect(
+ sc, sd->I, omega_in, pdf, &sd->lcg_state);
+ break;
+ case CLOSURE_BSDF_MICROFACET_BECKMANN_ID:
+ case CLOSURE_BSDF_MICROFACET_BECKMANN_ANISO_ID:
+ case CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID:
+ eval = bsdf_microfacet_beckmann_eval_reflect(sc, sd->I, omega_in, pdf);
+ break;
+ case CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ID:
+ case CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ANISO_ID:
+ eval = bsdf_ashikhmin_shirley_eval_reflect(sc, sd->I, omega_in, pdf);
+ break;
+ case CLOSURE_BSDF_ASHIKHMIN_VELVET_ID:
+ eval = bsdf_ashikhmin_velvet_eval_reflect(sc, sd->I, omega_in, pdf);
+ break;
+ case CLOSURE_BSDF_DIFFUSE_TOON_ID:
+ eval = bsdf_diffuse_toon_eval_reflect(sc, sd->I, omega_in, pdf);
+ break;
+ case CLOSURE_BSDF_GLOSSY_TOON_ID:
+ eval = bsdf_glossy_toon_eval_reflect(sc, sd->I, omega_in, pdf);
+ break;
+ case CLOSURE_BSDF_HAIR_PRINCIPLED_ID:
+ eval = bsdf_principled_hair_eval(kg, sd, sc, omega_in, pdf);
+ break;
+ case CLOSURE_BSDF_HAIR_REFLECTION_ID:
+ eval = bsdf_hair_reflection_eval_reflect(sc, sd->I, omega_in, pdf);
+ break;
+ case CLOSURE_BSDF_HAIR_TRANSMISSION_ID:
+ eval = bsdf_hair_transmission_eval_reflect(sc, sd->I, omega_in, pdf);
+ break;
+# ifdef __PRINCIPLED__
+ case CLOSURE_BSDF_PRINCIPLED_DIFFUSE_ID:
+ case CLOSURE_BSDF_BSSRDF_PRINCIPLED_ID:
+ eval = bsdf_principled_diffuse_eval_reflect(sc, sd->I, omega_in, pdf);
+ break;
+ case CLOSURE_BSDF_PRINCIPLED_SHEEN_ID:
+ eval = bsdf_principled_sheen_eval_reflect(sc, sd->I, omega_in, pdf);
+ break;
+# endif /* __PRINCIPLED__ */
#endif
#ifdef __VOLUME__
- case CLOSURE_VOLUME_HENYEY_GREENSTEIN_ID:
- eval = volume_henyey_greenstein_eval_phase(sc, sd->I, omega_in, pdf);
- break;
+ case CLOSURE_VOLUME_HENYEY_GREENSTEIN_ID:
+ eval = volume_henyey_greenstein_eval_phase(sc, sd->I, omega_in, pdf);
+ break;
#endif
- default:
- eval = make_float3(0.0f, 0.0f, 0.0f);
- break;
- }
- }
- else {
- switch(sc->type) {
- case CLOSURE_BSDF_DIFFUSE_ID:
- case CLOSURE_BSDF_BSSRDF_ID:
- eval = bsdf_diffuse_eval_transmit(sc, sd->I, omega_in, pdf);
- break;
+ default:
+ eval = make_float3(0.0f, 0.0f, 0.0f);
+ break;
+ }
+ }
+ else {
+ switch (sc->type) {
+ case CLOSURE_BSDF_DIFFUSE_ID:
+ case CLOSURE_BSDF_BSSRDF_ID:
+ eval = bsdf_diffuse_eval_transmit(sc, sd->I, omega_in, pdf);
+ break;
#ifdef __SVM__
- case CLOSURE_BSDF_OREN_NAYAR_ID:
- eval = bsdf_oren_nayar_eval_transmit(sc, sd->I, omega_in, pdf);
- break;
- case CLOSURE_BSDF_TRANSLUCENT_ID:
- eval = bsdf_translucent_eval_transmit(sc, sd->I, omega_in, pdf);
- break;
- case CLOSURE_BSDF_REFLECTION_ID:
- eval = bsdf_reflection_eval_transmit(sc, sd->I, omega_in, pdf);
- break;
- case CLOSURE_BSDF_REFRACTION_ID:
- eval = bsdf_refraction_eval_transmit(sc, sd->I, omega_in, pdf);
- break;
- case CLOSURE_BSDF_TRANSPARENT_ID:
- eval = bsdf_transparent_eval_transmit(sc, sd->I, omega_in, pdf);
- break;
- case CLOSURE_BSDF_MICROFACET_GGX_ID:
- case CLOSURE_BSDF_MICROFACET_GGX_FRESNEL_ID:
- case CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_ID:
- case CLOSURE_BSDF_MICROFACET_GGX_ANISO_ID:
- case CLOSURE_BSDF_MICROFACET_GGX_ANISO_FRESNEL_ID:
- case CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID:
- eval = bsdf_microfacet_ggx_eval_transmit(sc, sd->I, omega_in, pdf);
- break;
- case CLOSURE_BSDF_MICROFACET_MULTI_GGX_ID:
- case CLOSURE_BSDF_MICROFACET_MULTI_GGX_FRESNEL_ID:
- eval = bsdf_microfacet_multi_ggx_eval_transmit(sc, sd->I, omega_in, pdf, &sd->lcg_state);
- break;
- case CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID:
- case CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_FRESNEL_ID:
- eval = bsdf_microfacet_multi_ggx_glass_eval_transmit(sc, sd->I, omega_in, pdf, &sd->lcg_state);
- break;
- case CLOSURE_BSDF_MICROFACET_BECKMANN_ID:
- case CLOSURE_BSDF_MICROFACET_BECKMANN_ANISO_ID:
- case CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID:
- eval = bsdf_microfacet_beckmann_eval_transmit(sc, sd->I, omega_in, pdf);
- break;
- case CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ID:
- case CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ANISO_ID:
- eval = bsdf_ashikhmin_shirley_eval_transmit(sc, sd->I, omega_in, pdf);
- break;
- case CLOSURE_BSDF_ASHIKHMIN_VELVET_ID:
- eval = bsdf_ashikhmin_velvet_eval_transmit(sc, sd->I, omega_in, pdf);
- break;
- case CLOSURE_BSDF_DIFFUSE_TOON_ID:
- eval = bsdf_diffuse_toon_eval_transmit(sc, sd->I, omega_in, pdf);
- break;
- case CLOSURE_BSDF_GLOSSY_TOON_ID:
- eval = bsdf_glossy_toon_eval_transmit(sc, sd->I, omega_in, pdf);
- break;
- case CLOSURE_BSDF_HAIR_PRINCIPLED_ID:
- eval = bsdf_principled_hair_eval(kg, sd, sc, omega_in, pdf);
- break;
- case CLOSURE_BSDF_HAIR_REFLECTION_ID:
- eval = bsdf_hair_reflection_eval_transmit(sc, sd->I, omega_in, pdf);
- break;
- case CLOSURE_BSDF_HAIR_TRANSMISSION_ID:
- eval = bsdf_hair_transmission_eval_transmit(sc, sd->I, omega_in, pdf);
- break;
-#ifdef __PRINCIPLED__
- case CLOSURE_BSDF_PRINCIPLED_DIFFUSE_ID:
- case CLOSURE_BSDF_BSSRDF_PRINCIPLED_ID:
- eval = bsdf_principled_diffuse_eval_transmit(sc, sd->I, omega_in, pdf);
- break;
- case CLOSURE_BSDF_PRINCIPLED_SHEEN_ID:
- eval = bsdf_principled_sheen_eval_transmit(sc, sd->I, omega_in, pdf);
- break;
-#endif /* __PRINCIPLED__ */
+ case CLOSURE_BSDF_OREN_NAYAR_ID:
+ eval = bsdf_oren_nayar_eval_transmit(sc, sd->I, omega_in, pdf);
+ break;
+ case CLOSURE_BSDF_TRANSLUCENT_ID:
+ eval = bsdf_translucent_eval_transmit(sc, sd->I, omega_in, pdf);
+ break;
+ case CLOSURE_BSDF_REFLECTION_ID:
+ eval = bsdf_reflection_eval_transmit(sc, sd->I, omega_in, pdf);
+ break;
+ case CLOSURE_BSDF_REFRACTION_ID:
+ eval = bsdf_refraction_eval_transmit(sc, sd->I, omega_in, pdf);
+ break;
+ case CLOSURE_BSDF_TRANSPARENT_ID:
+ eval = bsdf_transparent_eval_transmit(sc, sd->I, omega_in, pdf);
+ break;
+ case CLOSURE_BSDF_MICROFACET_GGX_ID:
+ case CLOSURE_BSDF_MICROFACET_GGX_FRESNEL_ID:
+ case CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_ID:
+ case CLOSURE_BSDF_MICROFACET_GGX_ANISO_ID:
+ case CLOSURE_BSDF_MICROFACET_GGX_ANISO_FRESNEL_ID:
+ case CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID:
+ eval = bsdf_microfacet_ggx_eval_transmit(sc, sd->I, omega_in, pdf);
+ break;
+ case CLOSURE_BSDF_MICROFACET_MULTI_GGX_ID:
+ case CLOSURE_BSDF_MICROFACET_MULTI_GGX_FRESNEL_ID:
+ eval = bsdf_microfacet_multi_ggx_eval_transmit(sc, sd->I, omega_in, pdf, &sd->lcg_state);
+ break;
+ case CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID:
+ case CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_FRESNEL_ID:
+ eval = bsdf_microfacet_multi_ggx_glass_eval_transmit(
+ sc, sd->I, omega_in, pdf, &sd->lcg_state);
+ break;
+ case CLOSURE_BSDF_MICROFACET_BECKMANN_ID:
+ case CLOSURE_BSDF_MICROFACET_BECKMANN_ANISO_ID:
+ case CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID:
+ eval = bsdf_microfacet_beckmann_eval_transmit(sc, sd->I, omega_in, pdf);
+ break;
+ case CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ID:
+ case CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ANISO_ID:
+ eval = bsdf_ashikhmin_shirley_eval_transmit(sc, sd->I, omega_in, pdf);
+ break;
+ case CLOSURE_BSDF_ASHIKHMIN_VELVET_ID:
+ eval = bsdf_ashikhmin_velvet_eval_transmit(sc, sd->I, omega_in, pdf);
+ break;
+ case CLOSURE_BSDF_DIFFUSE_TOON_ID:
+ eval = bsdf_diffuse_toon_eval_transmit(sc, sd->I, omega_in, pdf);
+ break;
+ case CLOSURE_BSDF_GLOSSY_TOON_ID:
+ eval = bsdf_glossy_toon_eval_transmit(sc, sd->I, omega_in, pdf);
+ break;
+ case CLOSURE_BSDF_HAIR_PRINCIPLED_ID:
+ eval = bsdf_principled_hair_eval(kg, sd, sc, omega_in, pdf);
+ break;
+ case CLOSURE_BSDF_HAIR_REFLECTION_ID:
+ eval = bsdf_hair_reflection_eval_transmit(sc, sd->I, omega_in, pdf);
+ break;
+ case CLOSURE_BSDF_HAIR_TRANSMISSION_ID:
+ eval = bsdf_hair_transmission_eval_transmit(sc, sd->I, omega_in, pdf);
+ break;
+# ifdef __PRINCIPLED__
+ case CLOSURE_BSDF_PRINCIPLED_DIFFUSE_ID:
+ case CLOSURE_BSDF_BSSRDF_PRINCIPLED_ID:
+ eval = bsdf_principled_diffuse_eval_transmit(sc, sd->I, omega_in, pdf);
+ break;
+ case CLOSURE_BSDF_PRINCIPLED_SHEEN_ID:
+ eval = bsdf_principled_sheen_eval_transmit(sc, sd->I, omega_in, pdf);
+ break;
+# endif /* __PRINCIPLED__ */
#endif
#ifdef __VOLUME__
- case CLOSURE_VOLUME_HENYEY_GREENSTEIN_ID:
- eval = volume_henyey_greenstein_eval_phase(sc, sd->I, omega_in, pdf);
- break;
+ case CLOSURE_VOLUME_HENYEY_GREENSTEIN_ID:
+ eval = volume_henyey_greenstein_eval_phase(sc, sd->I, omega_in, pdf);
+ break;
#endif
- default:
- eval = make_float3(0.0f, 0.0f, 0.0f);
- break;
- }
- }
+ default:
+ eval = make_float3(0.0f, 0.0f, 0.0f);
+ break;
+ }
+ }
- return eval;
+ return eval;
}
ccl_device void bsdf_blur(KernelGlobals *kg, ShaderClosure *sc, float roughness)
{
- /* ToDo: do we want to blur volume closures? */
+ /* ToDo: do we want to blur volume closures? */
#ifdef __SVM__
- switch(sc->type) {
- case CLOSURE_BSDF_MICROFACET_MULTI_GGX_ID:
- case CLOSURE_BSDF_MICROFACET_MULTI_GGX_FRESNEL_ID:
- case CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID:
- case CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_FRESNEL_ID:
- bsdf_microfacet_multi_ggx_blur(sc, roughness);
- break;
- case CLOSURE_BSDF_MICROFACET_GGX_ID:
- case CLOSURE_BSDF_MICROFACET_GGX_FRESNEL_ID:
- case CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_ID:
- case CLOSURE_BSDF_MICROFACET_GGX_ANISO_ID:
- case CLOSURE_BSDF_MICROFACET_GGX_ANISO_FRESNEL_ID:
- case CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID:
- bsdf_microfacet_ggx_blur(sc, roughness);
- break;
- case CLOSURE_BSDF_MICROFACET_BECKMANN_ID:
- case CLOSURE_BSDF_MICROFACET_BECKMANN_ANISO_ID:
- case CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID:
- bsdf_microfacet_beckmann_blur(sc, roughness);
- break;
- case CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ID:
- case CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ANISO_ID:
- bsdf_ashikhmin_shirley_blur(sc, roughness);
- break;
- case CLOSURE_BSDF_HAIR_PRINCIPLED_ID:
- bsdf_principled_hair_blur(sc, roughness);
- break;
- default:
- break;
- }
+ switch (sc->type) {
+ case CLOSURE_BSDF_MICROFACET_MULTI_GGX_ID:
+ case CLOSURE_BSDF_MICROFACET_MULTI_GGX_FRESNEL_ID:
+ case CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID:
+ case CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_FRESNEL_ID:
+ bsdf_microfacet_multi_ggx_blur(sc, roughness);
+ break;
+ case CLOSURE_BSDF_MICROFACET_GGX_ID:
+ case CLOSURE_BSDF_MICROFACET_GGX_FRESNEL_ID:
+ case CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_ID:
+ case CLOSURE_BSDF_MICROFACET_GGX_ANISO_ID:
+ case CLOSURE_BSDF_MICROFACET_GGX_ANISO_FRESNEL_ID:
+ case CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID:
+ bsdf_microfacet_ggx_blur(sc, roughness);
+ break;
+ case CLOSURE_BSDF_MICROFACET_BECKMANN_ID:
+ case CLOSURE_BSDF_MICROFACET_BECKMANN_ANISO_ID:
+ case CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID:
+ bsdf_microfacet_beckmann_blur(sc, roughness);
+ break;
+ case CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ID:
+ case CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ANISO_ID:
+ bsdf_ashikhmin_shirley_blur(sc, roughness);
+ break;
+ case CLOSURE_BSDF_HAIR_PRINCIPLED_ID:
+ bsdf_principled_hair_blur(sc, roughness);
+ break;
+ default:
+ break;
+ }
#endif
}
ccl_device bool bsdf_merge(ShaderClosure *a, ShaderClosure *b)
{
#ifdef __SVM__
- switch(a->type) {
- case CLOSURE_BSDF_TRANSPARENT_ID:
- return true;
- case CLOSURE_BSDF_DIFFUSE_ID:
- case CLOSURE_BSDF_BSSRDF_ID:
- case CLOSURE_BSDF_TRANSLUCENT_ID:
- return bsdf_diffuse_merge(a, b);
- case CLOSURE_BSDF_OREN_NAYAR_ID:
- return bsdf_oren_nayar_merge(a, b);
- case CLOSURE_BSDF_REFLECTION_ID:
- case CLOSURE_BSDF_REFRACTION_ID:
- case CLOSURE_BSDF_MICROFACET_GGX_ID:
- case CLOSURE_BSDF_MICROFACET_GGX_FRESNEL_ID:
- case CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_ID:
- case CLOSURE_BSDF_MICROFACET_GGX_ANISO_ID:
- case CLOSURE_BSDF_MICROFACET_GGX_ANISO_FRESNEL_ID:
- case CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID:
- case CLOSURE_BSDF_MICROFACET_MULTI_GGX_ID:
- case CLOSURE_BSDF_MICROFACET_MULTI_GGX_FRESNEL_ID:
- case CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID:
- case CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_FRESNEL_ID:
- case CLOSURE_BSDF_MICROFACET_BECKMANN_ID:
- case CLOSURE_BSDF_MICROFACET_BECKMANN_ANISO_ID:
- case CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID:
- case CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ID:
- case CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ANISO_ID:
- return bsdf_microfacet_merge(a, b);
- case CLOSURE_BSDF_ASHIKHMIN_VELVET_ID:
- return bsdf_ashikhmin_velvet_merge(a, b);
- case CLOSURE_BSDF_DIFFUSE_TOON_ID:
- case CLOSURE_BSDF_GLOSSY_TOON_ID:
- return bsdf_toon_merge(a, b);
- case CLOSURE_BSDF_HAIR_REFLECTION_ID:
- case CLOSURE_BSDF_HAIR_TRANSMISSION_ID:
- return bsdf_hair_merge(a, b);
-#ifdef __PRINCIPLED__
- case CLOSURE_BSDF_PRINCIPLED_DIFFUSE_ID:
- case CLOSURE_BSDF_BSSRDF_PRINCIPLED_ID:
- return bsdf_principled_diffuse_merge(a, b);
-#endif
-#ifdef __VOLUME__
- case CLOSURE_VOLUME_HENYEY_GREENSTEIN_ID:
- return volume_henyey_greenstein_merge(a, b);
-#endif
- default:
- return false;
- }
+ switch (a->type) {
+ case CLOSURE_BSDF_TRANSPARENT_ID:
+ return true;
+ case CLOSURE_BSDF_DIFFUSE_ID:
+ case CLOSURE_BSDF_BSSRDF_ID:
+ case CLOSURE_BSDF_TRANSLUCENT_ID:
+ return bsdf_diffuse_merge(a, b);
+ case CLOSURE_BSDF_OREN_NAYAR_ID:
+ return bsdf_oren_nayar_merge(a, b);
+ case CLOSURE_BSDF_REFLECTION_ID:
+ case CLOSURE_BSDF_REFRACTION_ID:
+ case CLOSURE_BSDF_MICROFACET_GGX_ID:
+ case CLOSURE_BSDF_MICROFACET_GGX_FRESNEL_ID:
+ case CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_ID:
+ case CLOSURE_BSDF_MICROFACET_GGX_ANISO_ID:
+ case CLOSURE_BSDF_MICROFACET_GGX_ANISO_FRESNEL_ID:
+ case CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID:
+ case CLOSURE_BSDF_MICROFACET_MULTI_GGX_ID:
+ case CLOSURE_BSDF_MICROFACET_MULTI_GGX_FRESNEL_ID:
+ case CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID:
+ case CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_FRESNEL_ID:
+ case CLOSURE_BSDF_MICROFACET_BECKMANN_ID:
+ case CLOSURE_BSDF_MICROFACET_BECKMANN_ANISO_ID:
+ case CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID:
+ case CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ID:
+ case CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ANISO_ID:
+ return bsdf_microfacet_merge(a, b);
+ case CLOSURE_BSDF_ASHIKHMIN_VELVET_ID:
+ return bsdf_ashikhmin_velvet_merge(a, b);
+ case CLOSURE_BSDF_DIFFUSE_TOON_ID:
+ case CLOSURE_BSDF_GLOSSY_TOON_ID:
+ return bsdf_toon_merge(a, b);
+ case CLOSURE_BSDF_HAIR_REFLECTION_ID:
+ case CLOSURE_BSDF_HAIR_TRANSMISSION_ID:
+ return bsdf_hair_merge(a, b);
+# ifdef __PRINCIPLED__
+ case CLOSURE_BSDF_PRINCIPLED_DIFFUSE_ID:
+ case CLOSURE_BSDF_BSSRDF_PRINCIPLED_ID:
+ return bsdf_principled_diffuse_merge(a, b);
+# endif
+# ifdef __VOLUME__
+ case CLOSURE_VOLUME_HENYEY_GREENSTEIN_ID:
+ return volume_henyey_greenstein_merge(a, b);
+# endif
+ default:
+ return false;
+ }
#else
- return false;
+ return false;
#endif
}
diff --git a/intern/cycles/kernel/closure/bsdf_ashikhmin_shirley.h b/intern/cycles/kernel/closure/bsdf_ashikhmin_shirley.h
index 4e7425bd800..b3b1c37748d 100644
--- a/intern/cycles/kernel/closure/bsdf_ashikhmin_shirley.h
+++ b/intern/cycles/kernel/closure/bsdf_ashikhmin_shirley.h
@@ -33,203 +33,226 @@ CCL_NAMESPACE_BEGIN
ccl_device int bsdf_ashikhmin_shirley_setup(MicrofacetBsdf *bsdf)
{
- bsdf->alpha_x = clamp(bsdf->alpha_x, 1e-4f, 1.0f);
- bsdf->alpha_y = bsdf->alpha_x;
+ bsdf->alpha_x = clamp(bsdf->alpha_x, 1e-4f, 1.0f);
+ bsdf->alpha_y = bsdf->alpha_x;
- bsdf->type = CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ID;
- return SD_BSDF|SD_BSDF_HAS_EVAL;
+ bsdf->type = CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ID;
+ return SD_BSDF | SD_BSDF_HAS_EVAL;
}
ccl_device int bsdf_ashikhmin_shirley_aniso_setup(MicrofacetBsdf *bsdf)
{
- bsdf->alpha_x = clamp(bsdf->alpha_x, 1e-4f, 1.0f);
- bsdf->alpha_y = clamp(bsdf->alpha_y, 1e-4f, 1.0f);
+ bsdf->alpha_x = clamp(bsdf->alpha_x, 1e-4f, 1.0f);
+ bsdf->alpha_y = clamp(bsdf->alpha_y, 1e-4f, 1.0f);
- bsdf->type = CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ANISO_ID;
- return SD_BSDF|SD_BSDF_HAS_EVAL;
+ bsdf->type = CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ANISO_ID;
+ return SD_BSDF | SD_BSDF_HAS_EVAL;
}
ccl_device void bsdf_ashikhmin_shirley_blur(ShaderClosure *sc, float roughness)
{
- MicrofacetBsdf *bsdf = (MicrofacetBsdf*)sc;
+ MicrofacetBsdf *bsdf = (MicrofacetBsdf *)sc;
- bsdf->alpha_x = fmaxf(roughness, bsdf->alpha_x);
- bsdf->alpha_y = fmaxf(roughness, bsdf->alpha_y);
+ bsdf->alpha_x = fmaxf(roughness, bsdf->alpha_x);
+ bsdf->alpha_y = fmaxf(roughness, bsdf->alpha_y);
}
ccl_device_inline float bsdf_ashikhmin_shirley_roughness_to_exponent(float roughness)
{
- return 2.0f / (roughness*roughness) - 2.0f;
+ return 2.0f / (roughness * roughness) - 2.0f;
}
-ccl_device_forceinline float3 bsdf_ashikhmin_shirley_eval_reflect(
- const ShaderClosure *sc,
- const float3 I,
- const float3 omega_in,
- float *pdf)
+ccl_device_forceinline float3 bsdf_ashikhmin_shirley_eval_reflect(const ShaderClosure *sc,
+ const float3 I,
+ const float3 omega_in,
+ float *pdf)
{
- const MicrofacetBsdf *bsdf = (const MicrofacetBsdf*)sc;
- float3 N = bsdf->N;
-
- float NdotI = dot(N, I); /* in Cycles/OSL convention I is omega_out */
- float NdotO = dot(N, omega_in); /* and consequently we use for O omaga_in ;) */
-
- float out = 0.0f;
-
- if(fmaxf(bsdf->alpha_x, bsdf->alpha_y) <= 1e-4f)
- return make_float3(0.0f, 0.0f, 0.0f);
-
- if(NdotI > 0.0f && NdotO > 0.0f) {
- NdotI = fmaxf(NdotI, 1e-6f);
- NdotO = fmaxf(NdotO, 1e-6f);
- float3 H = normalize(omega_in + I);
- float HdotI = fmaxf(fabsf(dot(H, I)), 1e-6f);
- float HdotN = fmaxf(dot(H, N), 1e-6f);
-
- float pump = 1.0f / fmaxf(1e-6f, (HdotI*fmaxf(NdotO, NdotI))); /* pump from original paper (first derivative disc., but cancels the HdotI in the pdf nicely) */
- /*float pump = 1.0f / fmaxf(1e-4f, ((NdotO + NdotI) * (NdotO*NdotI))); */ /* pump from d-brdf paper */
-
- float n_x = bsdf_ashikhmin_shirley_roughness_to_exponent(bsdf->alpha_x);
- float n_y = bsdf_ashikhmin_shirley_roughness_to_exponent(bsdf->alpha_y);
-
- if(n_x == n_y) {
- /* isotropic */
- float e = n_x;
- float lobe = powf(HdotN, e);
- float norm = (n_x + 1.0f) / (8.0f * M_PI_F);
-
- out = NdotO * norm * lobe * pump;
- *pdf = norm * lobe / HdotI; /* this is p_h / 4(H.I) (conversion from 'wh measure' to 'wi measure', eq. 8 in paper) */
- }
- else {
- /* anisotropic */
- float3 X, Y;
- make_orthonormals_tangent(N, bsdf->T, &X, &Y);
-
- float HdotX = dot(H, X);
- float HdotY = dot(H, Y);
- float lobe;
- if(HdotN < 1.0f) {
- float e = (n_x * HdotX*HdotX + n_y * HdotY*HdotY) / (1.0f - HdotN*HdotN);
- lobe = powf(HdotN, e);
- }
- else {
- lobe = 1.0f;
- }
- float norm = sqrtf((n_x + 1.0f)*(n_y + 1.0f)) / (8.0f * M_PI_F);
-
- out = NdotO * norm * lobe * pump;
- *pdf = norm * lobe / HdotI;
- }
- }
-
- return make_float3(out, out, out);
+ const MicrofacetBsdf *bsdf = (const MicrofacetBsdf *)sc;
+ float3 N = bsdf->N;
+
+ float NdotI = dot(N, I); /* in Cycles/OSL convention I is omega_out */
+ float NdotO = dot(N, omega_in); /* and consequently we use for O omaga_in ;) */
+
+ float out = 0.0f;
+
+ if (fmaxf(bsdf->alpha_x, bsdf->alpha_y) <= 1e-4f)
+ return make_float3(0.0f, 0.0f, 0.0f);
+
+ if (NdotI > 0.0f && NdotO > 0.0f) {
+ NdotI = fmaxf(NdotI, 1e-6f);
+ NdotO = fmaxf(NdotO, 1e-6f);
+ float3 H = normalize(omega_in + I);
+ float HdotI = fmaxf(fabsf(dot(H, I)), 1e-6f);
+ float HdotN = fmaxf(dot(H, N), 1e-6f);
+
+ float pump =
+ 1.0f /
+ fmaxf(
+ 1e-6f,
+ (HdotI *
+ fmaxf(
+ NdotO,
+ NdotI))); /* pump from original paper (first derivative disc., but cancels the HdotI in the pdf nicely) */
+ /*float pump = 1.0f / fmaxf(1e-4f, ((NdotO + NdotI) * (NdotO*NdotI))); */ /* pump from d-brdf paper */
+
+ float n_x = bsdf_ashikhmin_shirley_roughness_to_exponent(bsdf->alpha_x);
+ float n_y = bsdf_ashikhmin_shirley_roughness_to_exponent(bsdf->alpha_y);
+
+ if (n_x == n_y) {
+ /* isotropic */
+ float e = n_x;
+ float lobe = powf(HdotN, e);
+ float norm = (n_x + 1.0f) / (8.0f * M_PI_F);
+
+ out = NdotO * norm * lobe * pump;
+ *pdf =
+ norm * lobe /
+ HdotI; /* this is p_h / 4(H.I) (conversion from 'wh measure' to 'wi measure', eq. 8 in paper) */
+ }
+ else {
+ /* anisotropic */
+ float3 X, Y;
+ make_orthonormals_tangent(N, bsdf->T, &X, &Y);
+
+ float HdotX = dot(H, X);
+ float HdotY = dot(H, Y);
+ float lobe;
+ if (HdotN < 1.0f) {
+ float e = (n_x * HdotX * HdotX + n_y * HdotY * HdotY) / (1.0f - HdotN * HdotN);
+ lobe = powf(HdotN, e);
+ }
+ else {
+ lobe = 1.0f;
+ }
+ float norm = sqrtf((n_x + 1.0f) * (n_y + 1.0f)) / (8.0f * M_PI_F);
+
+ out = NdotO * norm * lobe * pump;
+ *pdf = norm * lobe / HdotI;
+ }
+ }
+
+ return make_float3(out, out, out);
}
-ccl_device float3 bsdf_ashikhmin_shirley_eval_transmit(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf)
+ccl_device float3 bsdf_ashikhmin_shirley_eval_transmit(const ShaderClosure *sc,
+ const float3 I,
+ const float3 omega_in,
+ float *pdf)
{
- return make_float3(0.0f, 0.0f, 0.0f);
+ return make_float3(0.0f, 0.0f, 0.0f);
}
-ccl_device_inline void bsdf_ashikhmin_shirley_sample_first_quadrant(float n_x, float n_y, float randu, float randv, float *phi, float *cos_theta)
+ccl_device_inline void bsdf_ashikhmin_shirley_sample_first_quadrant(
+ float n_x, float n_y, float randu, float randv, float *phi, float *cos_theta)
{
- *phi = atanf(sqrtf((n_x + 1.0f) / (n_y + 1.0f)) * tanf(M_PI_2_F * randu));
- float cos_phi = cosf(*phi);
- float sin_phi = sinf(*phi);
- *cos_theta = powf(randv, 1.0f / (n_x * cos_phi*cos_phi + n_y * sin_phi*sin_phi + 1.0f));
+ *phi = atanf(sqrtf((n_x + 1.0f) / (n_y + 1.0f)) * tanf(M_PI_2_F * randu));
+ float cos_phi = cosf(*phi);
+ float sin_phi = sinf(*phi);
+ *cos_theta = powf(randv, 1.0f / (n_x * cos_phi * cos_phi + n_y * sin_phi * sin_phi + 1.0f));
}
-ccl_device int bsdf_ashikhmin_shirley_sample(const ShaderClosure *sc, float3 Ng, float3 I, float3 dIdx, float3 dIdy, float randu, float randv, float3 *eval, float3 *omega_in, float3 *domega_in_dx, float3 *domega_in_dy, float *pdf)
+ccl_device int bsdf_ashikhmin_shirley_sample(const ShaderClosure *sc,
+ float3 Ng,
+ float3 I,
+ float3 dIdx,
+ float3 dIdy,
+ float randu,
+ float randv,
+ float3 *eval,
+ float3 *omega_in,
+ float3 *domega_in_dx,
+ float3 *domega_in_dy,
+ float *pdf)
{
- const MicrofacetBsdf *bsdf = (const MicrofacetBsdf*)sc;
- float3 N = bsdf->N;
- int label = LABEL_REFLECT | LABEL_GLOSSY;
-
- float NdotI = dot(N, I);
- if(NdotI > 0.0f) {
-
- float n_x = bsdf_ashikhmin_shirley_roughness_to_exponent(bsdf->alpha_x);
- float n_y = bsdf_ashikhmin_shirley_roughness_to_exponent(bsdf->alpha_y);
-
- /* get x,y basis on the surface for anisotropy */
- float3 X, Y;
-
- if(n_x == n_y)
- make_orthonormals(N, &X, &Y);
- else
- make_orthonormals_tangent(N, bsdf->T, &X, &Y);
-
- /* sample spherical coords for h in tangent space */
- float phi;
- float cos_theta;
- if(n_x == n_y) {
- /* isotropic sampling */
- phi = M_2PI_F * randu;
- cos_theta = powf(randv, 1.0f / (n_x + 1.0f));
- }
- else {
- /* anisotropic sampling */
- if(randu < 0.25f) { /* first quadrant */
- float remapped_randu = 4.0f * randu;
- bsdf_ashikhmin_shirley_sample_first_quadrant(n_x, n_y, remapped_randu, randv, &phi, &cos_theta);
- }
- else if(randu < 0.5f) { /* second quadrant */
- float remapped_randu = 4.0f * (.5f - randu);
- bsdf_ashikhmin_shirley_sample_first_quadrant(n_x, n_y, remapped_randu, randv, &phi, &cos_theta);
- phi = M_PI_F - phi;
- }
- else if(randu < 0.75f) { /* third quadrant */
- float remapped_randu = 4.0f * (randu - 0.5f);
- bsdf_ashikhmin_shirley_sample_first_quadrant(n_x, n_y, remapped_randu, randv, &phi, &cos_theta);
- phi = M_PI_F + phi;
- }
- else { /* fourth quadrant */
- float remapped_randu = 4.0f * (1.0f - randu);
- bsdf_ashikhmin_shirley_sample_first_quadrant(n_x, n_y, remapped_randu, randv, &phi, &cos_theta);
- phi = 2.0f * M_PI_F - phi;
- }
- }
-
- /* get half vector in tangent space */
- float sin_theta = sqrtf(fmaxf(0.0f, 1.0f - cos_theta*cos_theta));
- float cos_phi = cosf(phi);
- float sin_phi = sinf(phi); /* no sqrt(1-cos^2) here b/c it causes artifacts */
- float3 h = make_float3(
- sin_theta * cos_phi,
- sin_theta * sin_phi,
- cos_theta
- );
-
- /* half vector to world space */
- float3 H = h.x*X + h.y*Y + h.z*N;
- float HdotI = dot(H, I);
- if(HdotI < 0.0f) H = -H;
-
- /* reflect I on H to get omega_in */
- *omega_in = -I + (2.0f * HdotI) * H;
-
- if(fmaxf(bsdf->alpha_x, bsdf->alpha_y) <= 1e-4f) {
- /* Some high number for MIS. */
- *pdf = 1e6f;
- *eval = make_float3(1e6f, 1e6f, 1e6f);
- label = LABEL_REFLECT | LABEL_SINGULAR;
- }
- else {
- /* leave the rest to eval_reflect */
- *eval = bsdf_ashikhmin_shirley_eval_reflect(sc, I, *omega_in, pdf);
- }
+ const MicrofacetBsdf *bsdf = (const MicrofacetBsdf *)sc;
+ float3 N = bsdf->N;
+ int label = LABEL_REFLECT | LABEL_GLOSSY;
+
+ float NdotI = dot(N, I);
+ if (NdotI > 0.0f) {
+
+ float n_x = bsdf_ashikhmin_shirley_roughness_to_exponent(bsdf->alpha_x);
+ float n_y = bsdf_ashikhmin_shirley_roughness_to_exponent(bsdf->alpha_y);
+
+ /* get x,y basis on the surface for anisotropy */
+ float3 X, Y;
+
+ if (n_x == n_y)
+ make_orthonormals(N, &X, &Y);
+ else
+ make_orthonormals_tangent(N, bsdf->T, &X, &Y);
+
+ /* sample spherical coords for h in tangent space */
+ float phi;
+ float cos_theta;
+ if (n_x == n_y) {
+ /* isotropic sampling */
+ phi = M_2PI_F * randu;
+ cos_theta = powf(randv, 1.0f / (n_x + 1.0f));
+ }
+ else {
+ /* anisotropic sampling */
+ if (randu < 0.25f) { /* first quadrant */
+ float remapped_randu = 4.0f * randu;
+ bsdf_ashikhmin_shirley_sample_first_quadrant(
+ n_x, n_y, remapped_randu, randv, &phi, &cos_theta);
+ }
+ else if (randu < 0.5f) { /* second quadrant */
+ float remapped_randu = 4.0f * (.5f - randu);
+ bsdf_ashikhmin_shirley_sample_first_quadrant(
+ n_x, n_y, remapped_randu, randv, &phi, &cos_theta);
+ phi = M_PI_F - phi;
+ }
+ else if (randu < 0.75f) { /* third quadrant */
+ float remapped_randu = 4.0f * (randu - 0.5f);
+ bsdf_ashikhmin_shirley_sample_first_quadrant(
+ n_x, n_y, remapped_randu, randv, &phi, &cos_theta);
+ phi = M_PI_F + phi;
+ }
+ else { /* fourth quadrant */
+ float remapped_randu = 4.0f * (1.0f - randu);
+ bsdf_ashikhmin_shirley_sample_first_quadrant(
+ n_x, n_y, remapped_randu, randv, &phi, &cos_theta);
+ phi = 2.0f * M_PI_F - phi;
+ }
+ }
+
+ /* get half vector in tangent space */
+ float sin_theta = sqrtf(fmaxf(0.0f, 1.0f - cos_theta * cos_theta));
+ float cos_phi = cosf(phi);
+ float sin_phi = sinf(phi); /* no sqrt(1-cos^2) here b/c it causes artifacts */
+ float3 h = make_float3(sin_theta * cos_phi, sin_theta * sin_phi, cos_theta);
+
+ /* half vector to world space */
+ float3 H = h.x * X + h.y * Y + h.z * N;
+ float HdotI = dot(H, I);
+ if (HdotI < 0.0f)
+ H = -H;
+
+ /* reflect I on H to get omega_in */
+ *omega_in = -I + (2.0f * HdotI) * H;
+
+ if (fmaxf(bsdf->alpha_x, bsdf->alpha_y) <= 1e-4f) {
+ /* Some high number for MIS. */
+ *pdf = 1e6f;
+ *eval = make_float3(1e6f, 1e6f, 1e6f);
+ label = LABEL_REFLECT | LABEL_SINGULAR;
+ }
+ else {
+ /* leave the rest to eval_reflect */
+ *eval = bsdf_ashikhmin_shirley_eval_reflect(sc, I, *omega_in, pdf);
+ }
#ifdef __RAY_DIFFERENTIALS__
- /* just do the reflection thing for now */
- *domega_in_dx = (2.0f * dot(N, dIdx)) * N - dIdx;
- *domega_in_dy = (2.0f * dot(N, dIdy)) * N - dIdy;
+ /* just do the reflection thing for now */
+ *domega_in_dx = (2.0f * dot(N, dIdx)) * N - dIdx;
+ *domega_in_dy = (2.0f * dot(N, dIdy)) * N - dIdy;
#endif
- }
+ }
- return label;
+ return label;
}
-
CCL_NAMESPACE_END
-#endif /* __BSDF_ASHIKHMIN_SHIRLEY_H__ */
+#endif /* __BSDF_ASHIKHMIN_SHIRLEY_H__ */
diff --git a/intern/cycles/kernel/closure/bsdf_ashikhmin_velvet.h b/intern/cycles/kernel/closure/bsdf_ashikhmin_velvet.h
index 80fd9ba2b37..8122bcc1424 100644
--- a/intern/cycles/kernel/closure/bsdf_ashikhmin_velvet.h
+++ b/intern/cycles/kernel/closure/bsdf_ashikhmin_velvet.h
@@ -36,126 +36,142 @@
CCL_NAMESPACE_BEGIN
typedef ccl_addr_space struct VelvetBsdf {
- SHADER_CLOSURE_BASE;
+ SHADER_CLOSURE_BASE;
- float sigma;
- float invsigma2;
+ float sigma;
+ float invsigma2;
} VelvetBsdf;
ccl_device int bsdf_ashikhmin_velvet_setup(VelvetBsdf *bsdf)
{
- float sigma = fmaxf(bsdf->sigma, 0.01f);
- bsdf->invsigma2 = 1.0f/(sigma * sigma);
+ float sigma = fmaxf(bsdf->sigma, 0.01f);
+ bsdf->invsigma2 = 1.0f / (sigma * sigma);
- bsdf->type = CLOSURE_BSDF_ASHIKHMIN_VELVET_ID;
+ bsdf->type = CLOSURE_BSDF_ASHIKHMIN_VELVET_ID;
- return SD_BSDF|SD_BSDF_HAS_EVAL;
+ return SD_BSDF | SD_BSDF_HAS_EVAL;
}
ccl_device bool bsdf_ashikhmin_velvet_merge(const ShaderClosure *a, const ShaderClosure *b)
{
- const VelvetBsdf *bsdf_a = (const VelvetBsdf*)a;
- const VelvetBsdf *bsdf_b = (const VelvetBsdf*)b;
+ const VelvetBsdf *bsdf_a = (const VelvetBsdf *)a;
+ const VelvetBsdf *bsdf_b = (const VelvetBsdf *)b;
- return (isequal_float3(bsdf_a->N, bsdf_b->N)) &&
- (bsdf_a->sigma == bsdf_b->sigma);
+ return (isequal_float3(bsdf_a->N, bsdf_b->N)) && (bsdf_a->sigma == bsdf_b->sigma);
}
-ccl_device float3 bsdf_ashikhmin_velvet_eval_reflect(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf)
+ccl_device float3 bsdf_ashikhmin_velvet_eval_reflect(const ShaderClosure *sc,
+ const float3 I,
+ const float3 omega_in,
+ float *pdf)
{
- const VelvetBsdf *bsdf = (const VelvetBsdf*)sc;
- float m_invsigma2 = bsdf->invsigma2;
- float3 N = bsdf->N;
+ const VelvetBsdf *bsdf = (const VelvetBsdf *)sc;
+ float m_invsigma2 = bsdf->invsigma2;
+ float3 N = bsdf->N;
- float cosNO = dot(N, I);
- float cosNI = dot(N, omega_in);
- if(cosNO > 0 && cosNI > 0) {
- float3 H = normalize(omega_in + I);
+ float cosNO = dot(N, I);
+ float cosNI = dot(N, omega_in);
+ if (cosNO > 0 && cosNI > 0) {
+ float3 H = normalize(omega_in + I);
- float cosNH = dot(N, H);
- float cosHO = fabsf(dot(I, H));
+ float cosNH = dot(N, H);
+ float cosHO = fabsf(dot(I, H));
- if(!(fabsf(cosNH) < 1.0f-1e-5f && cosHO > 1e-5f))
- return make_float3(0.0f, 0.0f, 0.0f);
+ if (!(fabsf(cosNH) < 1.0f - 1e-5f && cosHO > 1e-5f))
+ return make_float3(0.0f, 0.0f, 0.0f);
- float cosNHdivHO = cosNH / cosHO;
- cosNHdivHO = fmaxf(cosNHdivHO, 1e-5f);
+ float cosNHdivHO = cosNH / cosHO;
+ cosNHdivHO = fmaxf(cosNHdivHO, 1e-5f);
- float fac1 = 2 * fabsf(cosNHdivHO * cosNO);
- float fac2 = 2 * fabsf(cosNHdivHO * cosNI);
+ float fac1 = 2 * fabsf(cosNHdivHO * cosNO);
+ float fac2 = 2 * fabsf(cosNHdivHO * cosNI);
- float sinNH2 = 1 - cosNH * cosNH;
- float sinNH4 = sinNH2 * sinNH2;
- float cotangent2 = (cosNH * cosNH) / sinNH2;
+ float sinNH2 = 1 - cosNH * cosNH;
+ float sinNH4 = sinNH2 * sinNH2;
+ float cotangent2 = (cosNH * cosNH) / sinNH2;
- float D = expf(-cotangent2 * m_invsigma2) * m_invsigma2 * M_1_PI_F / sinNH4;
- float G = min(1.0f, min(fac1, fac2)); // TODO: derive G from D analytically
+ float D = expf(-cotangent2 * m_invsigma2) * m_invsigma2 * M_1_PI_F / sinNH4;
+ float G = min(1.0f, min(fac1, fac2)); // TODO: derive G from D analytically
- float out = 0.25f * (D * G) / cosNO;
+ float out = 0.25f * (D * G) / cosNO;
- *pdf = 0.5f * M_1_PI_F;
- return make_float3(out, out, out);
- }
+ *pdf = 0.5f * M_1_PI_F;
+ return make_float3(out, out, out);
+ }
- return make_float3(0.0f, 0.0f, 0.0f);
+ return make_float3(0.0f, 0.0f, 0.0f);
}
-ccl_device float3 bsdf_ashikhmin_velvet_eval_transmit(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf)
+ccl_device float3 bsdf_ashikhmin_velvet_eval_transmit(const ShaderClosure *sc,
+ const float3 I,
+ const float3 omega_in,
+ float *pdf)
{
- return make_float3(0.0f, 0.0f, 0.0f);
+ return make_float3(0.0f, 0.0f, 0.0f);
}
-ccl_device int bsdf_ashikhmin_velvet_sample(const ShaderClosure *sc, float3 Ng, float3 I, float3 dIdx, float3 dIdy, float randu, float randv, float3 *eval, float3 *omega_in, float3 *domega_in_dx, float3 *domega_in_dy, float *pdf)
+ccl_device int bsdf_ashikhmin_velvet_sample(const ShaderClosure *sc,
+ float3 Ng,
+ float3 I,
+ float3 dIdx,
+ float3 dIdy,
+ float randu,
+ float randv,
+ float3 *eval,
+ float3 *omega_in,
+ float3 *domega_in_dx,
+ float3 *domega_in_dy,
+ float *pdf)
{
- const VelvetBsdf *bsdf = (const VelvetBsdf*)sc;
- float m_invsigma2 = bsdf->invsigma2;
- float3 N = bsdf->N;
+ const VelvetBsdf *bsdf = (const VelvetBsdf *)sc;
+ float m_invsigma2 = bsdf->invsigma2;
+ float3 N = bsdf->N;
- // we are viewing the surface from above - send a ray out with uniform
- // distribution over the hemisphere
- sample_uniform_hemisphere(N, randu, randv, omega_in, pdf);
+ // we are viewing the surface from above - send a ray out with uniform
+ // distribution over the hemisphere
+ sample_uniform_hemisphere(N, randu, randv, omega_in, pdf);
- if(dot(Ng, *omega_in) > 0) {
- float3 H = normalize(*omega_in + I);
+ if (dot(Ng, *omega_in) > 0) {
+ float3 H = normalize(*omega_in + I);
- float cosNI = dot(N, *omega_in);
- float cosNO = dot(N, I);
- float cosNH = dot(N, H);
- float cosHO = fabsf(dot(I, H));
+ float cosNI = dot(N, *omega_in);
+ float cosNO = dot(N, I);
+ float cosNH = dot(N, H);
+ float cosHO = fabsf(dot(I, H));
- if(fabsf(cosNO) > 1e-5f && fabsf(cosNH) < 1.0f-1e-5f && cosHO > 1e-5f) {
- float cosNHdivHO = cosNH / cosHO;
- cosNHdivHO = fmaxf(cosNHdivHO, 1e-5f);
+ if (fabsf(cosNO) > 1e-5f && fabsf(cosNH) < 1.0f - 1e-5f && cosHO > 1e-5f) {
+ float cosNHdivHO = cosNH / cosHO;
+ cosNHdivHO = fmaxf(cosNHdivHO, 1e-5f);
- float fac1 = 2 * fabsf(cosNHdivHO * cosNO);
- float fac2 = 2 * fabsf(cosNHdivHO * cosNI);
+ float fac1 = 2 * fabsf(cosNHdivHO * cosNO);
+ float fac2 = 2 * fabsf(cosNHdivHO * cosNI);
- float sinNH2 = 1 - cosNH * cosNH;
- float sinNH4 = sinNH2 * sinNH2;
- float cotangent2 = (cosNH * cosNH) / sinNH2;
+ float sinNH2 = 1 - cosNH * cosNH;
+ float sinNH4 = sinNH2 * sinNH2;
+ float cotangent2 = (cosNH * cosNH) / sinNH2;
- float D = expf(-cotangent2 * m_invsigma2) * m_invsigma2 * M_1_PI_F / sinNH4;
- float G = min(1.0f, min(fac1, fac2)); // TODO: derive G from D analytically
+ float D = expf(-cotangent2 * m_invsigma2) * m_invsigma2 * M_1_PI_F / sinNH4;
+ float G = min(1.0f, min(fac1, fac2)); // TODO: derive G from D analytically
- float power = 0.25f * (D * G) / cosNO;
+ float power = 0.25f * (D * G) / cosNO;
- *eval = make_float3(power, power, power);
+ *eval = make_float3(power, power, power);
#ifdef __RAY_DIFFERENTIALS__
- // TODO: find a better approximation for the retroreflective bounce
- *domega_in_dx = (2 * dot(N, dIdx)) * N - dIdx;
- *domega_in_dy = (2 * dot(N, dIdy)) * N - dIdy;
+ // TODO: find a better approximation for the retroreflective bounce
+ *domega_in_dx = (2 * dot(N, dIdx)) * N - dIdx;
+ *domega_in_dy = (2 * dot(N, dIdy)) * N - dIdy;
#endif
- }
- else
- *pdf = 0.0f;
- }
- else
- *pdf = 0.0f;
-
- return LABEL_REFLECT|LABEL_DIFFUSE;
+ }
+ else
+ *pdf = 0.0f;
+ }
+ else
+ *pdf = 0.0f;
+
+ return LABEL_REFLECT | LABEL_DIFFUSE;
}
CCL_NAMESPACE_END
-#endif /* __BSDF_ASHIKHMIN_VELVET_H__ */
+#endif /* __BSDF_ASHIKHMIN_VELVET_H__ */
diff --git a/intern/cycles/kernel/closure/bsdf_diffuse.h b/intern/cycles/kernel/closure/bsdf_diffuse.h
index 946c460a70e..76b50548455 100644
--- a/intern/cycles/kernel/closure/bsdf_diffuse.h
+++ b/intern/cycles/kernel/closure/bsdf_diffuse.h
@@ -36,107 +36,141 @@
CCL_NAMESPACE_BEGIN
typedef ccl_addr_space struct DiffuseBsdf {
- SHADER_CLOSURE_BASE;
+ SHADER_CLOSURE_BASE;
} DiffuseBsdf;
/* DIFFUSE */
ccl_device int bsdf_diffuse_setup(DiffuseBsdf *bsdf)
{
- bsdf->type = CLOSURE_BSDF_DIFFUSE_ID;
- return SD_BSDF|SD_BSDF_HAS_EVAL;
+ bsdf->type = CLOSURE_BSDF_DIFFUSE_ID;
+ return SD_BSDF | SD_BSDF_HAS_EVAL;
}
ccl_device bool bsdf_diffuse_merge(const ShaderClosure *a, const ShaderClosure *b)
{
- const DiffuseBsdf *bsdf_a = (const DiffuseBsdf*)a;
- const DiffuseBsdf *bsdf_b = (const DiffuseBsdf*)b;
+ const DiffuseBsdf *bsdf_a = (const DiffuseBsdf *)a;
+ const DiffuseBsdf *bsdf_b = (const DiffuseBsdf *)b;
- return (isequal_float3(bsdf_a->N, bsdf_b->N));
+ return (isequal_float3(bsdf_a->N, bsdf_b->N));
}
-ccl_device float3 bsdf_diffuse_eval_reflect(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf)
+ccl_device float3 bsdf_diffuse_eval_reflect(const ShaderClosure *sc,
+ const float3 I,
+ const float3 omega_in,
+ float *pdf)
{
- const DiffuseBsdf *bsdf = (const DiffuseBsdf*)sc;
- float3 N = bsdf->N;
+ const DiffuseBsdf *bsdf = (const DiffuseBsdf *)sc;
+ float3 N = bsdf->N;
- float cos_pi = fmaxf(dot(N, omega_in), 0.0f) * M_1_PI_F;
- *pdf = cos_pi;
- return make_float3(cos_pi, cos_pi, cos_pi);
+ float cos_pi = fmaxf(dot(N, omega_in), 0.0f) * M_1_PI_F;
+ *pdf = cos_pi;
+ return make_float3(cos_pi, cos_pi, cos_pi);
}
-ccl_device float3 bsdf_diffuse_eval_transmit(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf)
+ccl_device float3 bsdf_diffuse_eval_transmit(const ShaderClosure *sc,
+ const float3 I,
+ const float3 omega_in,
+ float *pdf)
{
- return make_float3(0.0f, 0.0f, 0.0f);
+ return make_float3(0.0f, 0.0f, 0.0f);
}
-ccl_device int bsdf_diffuse_sample(const ShaderClosure *sc, float3 Ng, float3 I, float3 dIdx, float3 dIdy, float randu, float randv, float3 *eval, float3 *omega_in, float3 *domega_in_dx, float3 *domega_in_dy, float *pdf)
+ccl_device int bsdf_diffuse_sample(const ShaderClosure *sc,
+ float3 Ng,
+ float3 I,
+ float3 dIdx,
+ float3 dIdy,
+ float randu,
+ float randv,
+ float3 *eval,
+ float3 *omega_in,
+ float3 *domega_in_dx,
+ float3 *domega_in_dy,
+ float *pdf)
{
- const DiffuseBsdf *bsdf = (const DiffuseBsdf*)sc;
- float3 N = bsdf->N;
+ const DiffuseBsdf *bsdf = (const DiffuseBsdf *)sc;
+ float3 N = bsdf->N;
- // distribution over the hemisphere
- sample_cos_hemisphere(N, randu, randv, omega_in, pdf);
+ // distribution over the hemisphere
+ sample_cos_hemisphere(N, randu, randv, omega_in, pdf);
- if(dot(Ng, *omega_in) > 0.0f) {
- *eval = make_float3(*pdf, *pdf, *pdf);
+ if (dot(Ng, *omega_in) > 0.0f) {
+ *eval = make_float3(*pdf, *pdf, *pdf);
#ifdef __RAY_DIFFERENTIALS__
- // TODO: find a better approximation for the diffuse bounce
- *domega_in_dx = (2 * dot(N, dIdx)) * N - dIdx;
- *domega_in_dy = (2 * dot(N, dIdy)) * N - dIdy;
+ // TODO: find a better approximation for the diffuse bounce
+ *domega_in_dx = (2 * dot(N, dIdx)) * N - dIdx;
+ *domega_in_dy = (2 * dot(N, dIdy)) * N - dIdy;
#endif
- }
- else
- *pdf = 0.0f;
+ }
+ else
+ *pdf = 0.0f;
- return LABEL_REFLECT|LABEL_DIFFUSE;
+ return LABEL_REFLECT | LABEL_DIFFUSE;
}
/* TRANSLUCENT */
ccl_device int bsdf_translucent_setup(DiffuseBsdf *bsdf)
{
- bsdf->type = CLOSURE_BSDF_TRANSLUCENT_ID;
- return SD_BSDF|SD_BSDF_HAS_EVAL;
+ bsdf->type = CLOSURE_BSDF_TRANSLUCENT_ID;
+ return SD_BSDF | SD_BSDF_HAS_EVAL;
}
-ccl_device float3 bsdf_translucent_eval_reflect(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf)
+ccl_device float3 bsdf_translucent_eval_reflect(const ShaderClosure *sc,
+ const float3 I,
+ const float3 omega_in,
+ float *pdf)
{
- return make_float3(0.0f, 0.0f, 0.0f);
+ return make_float3(0.0f, 0.0f, 0.0f);
}
-ccl_device float3 bsdf_translucent_eval_transmit(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf)
+ccl_device float3 bsdf_translucent_eval_transmit(const ShaderClosure *sc,
+ const float3 I,
+ const float3 omega_in,
+ float *pdf)
{
- const DiffuseBsdf *bsdf = (const DiffuseBsdf*)sc;
- float3 N = bsdf->N;
+ const DiffuseBsdf *bsdf = (const DiffuseBsdf *)sc;
+ float3 N = bsdf->N;
- float cos_pi = fmaxf(-dot(N, omega_in), 0.0f) * M_1_PI_F;
- *pdf = cos_pi;
- return make_float3 (cos_pi, cos_pi, cos_pi);
+ float cos_pi = fmaxf(-dot(N, omega_in), 0.0f) * M_1_PI_F;
+ *pdf = cos_pi;
+ return make_float3(cos_pi, cos_pi, cos_pi);
}
-ccl_device int bsdf_translucent_sample(const ShaderClosure *sc, float3 Ng, float3 I, float3 dIdx, float3 dIdy, float randu, float randv, float3 *eval, float3 *omega_in, float3 *domega_in_dx, float3 *domega_in_dy, float *pdf)
+ccl_device int bsdf_translucent_sample(const ShaderClosure *sc,
+ float3 Ng,
+ float3 I,
+ float3 dIdx,
+ float3 dIdy,
+ float randu,
+ float randv,
+ float3 *eval,
+ float3 *omega_in,
+ float3 *domega_in_dx,
+ float3 *domega_in_dy,
+ float *pdf)
{
- const DiffuseBsdf *bsdf = (const DiffuseBsdf*)sc;
- float3 N = bsdf->N;
-
- // we are viewing the surface from the right side - send a ray out with cosine
- // distribution over the hemisphere
- sample_cos_hemisphere (-N, randu, randv, omega_in, pdf);
- if(dot(Ng, *omega_in) < 0) {
- *eval = make_float3(*pdf, *pdf, *pdf);
+ const DiffuseBsdf *bsdf = (const DiffuseBsdf *)sc;
+ float3 N = bsdf->N;
+
+ // we are viewing the surface from the right side - send a ray out with cosine
+ // distribution over the hemisphere
+ sample_cos_hemisphere(-N, randu, randv, omega_in, pdf);
+ if (dot(Ng, *omega_in) < 0) {
+ *eval = make_float3(*pdf, *pdf, *pdf);
#ifdef __RAY_DIFFERENTIALS__
- // TODO: find a better approximation for the diffuse bounce
- *domega_in_dx = -((2 * dot(N, dIdx)) * N - dIdx);
- *domega_in_dy = -((2 * dot(N, dIdy)) * N - dIdy);
+ // TODO: find a better approximation for the diffuse bounce
+ *domega_in_dx = -((2 * dot(N, dIdx)) * N - dIdx);
+ *domega_in_dy = -((2 * dot(N, dIdy)) * N - dIdy);
#endif
- }
- else {
- *pdf = 0;
- }
- return LABEL_TRANSMIT|LABEL_DIFFUSE;
+ }
+ else {
+ *pdf = 0;
+ }
+ return LABEL_TRANSMIT | LABEL_DIFFUSE;
}
CCL_NAMESPACE_END
-#endif /* __BSDF_DIFFUSE_H__ */
+#endif /* __BSDF_DIFFUSE_H__ */
diff --git a/intern/cycles/kernel/closure/bsdf_diffuse_ramp.h b/intern/cycles/kernel/closure/bsdf_diffuse_ramp.h
index ca33a5b275c..9d13eb8d4e0 100644
--- a/intern/cycles/kernel/closure/bsdf_diffuse_ramp.h
+++ b/intern/cycles/kernel/closure/bsdf_diffuse_ramp.h
@@ -38,73 +38,90 @@ CCL_NAMESPACE_BEGIN
#ifdef __OSL__
typedef ccl_addr_space struct DiffuseRampBsdf {
- SHADER_CLOSURE_BASE;
+ SHADER_CLOSURE_BASE;
- float3 *colors;
+ float3 *colors;
} DiffuseRampBsdf;
ccl_device float3 bsdf_diffuse_ramp_get_color(const float3 colors[8], float pos)
{
- int MAXCOLORS = 8;
-
- float npos = pos * (float)(MAXCOLORS - 1);
- int ipos = float_to_int(npos);
- if(ipos < 0)
- return colors[0];
- if(ipos >= (MAXCOLORS - 1))
- return colors[MAXCOLORS - 1];
- float offset = npos - (float)ipos;
- return colors[ipos] * (1.0f - offset) + colors[ipos+1] * offset;
+ int MAXCOLORS = 8;
+
+ float npos = pos * (float)(MAXCOLORS - 1);
+ int ipos = float_to_int(npos);
+ if (ipos < 0)
+ return colors[0];
+ if (ipos >= (MAXCOLORS - 1))
+ return colors[MAXCOLORS - 1];
+ float offset = npos - (float)ipos;
+ return colors[ipos] * (1.0f - offset) + colors[ipos + 1] * offset;
}
ccl_device int bsdf_diffuse_ramp_setup(DiffuseRampBsdf *bsdf)
{
- bsdf->type = CLOSURE_BSDF_DIFFUSE_RAMP_ID;
- return SD_BSDF|SD_BSDF_HAS_EVAL;
+ bsdf->type = CLOSURE_BSDF_DIFFUSE_RAMP_ID;
+ return SD_BSDF | SD_BSDF_HAS_EVAL;
}
ccl_device void bsdf_diffuse_ramp_blur(ShaderClosure *sc, float roughness)
{
}
-ccl_device float3 bsdf_diffuse_ramp_eval_reflect(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf)
+ccl_device float3 bsdf_diffuse_ramp_eval_reflect(const ShaderClosure *sc,
+ const float3 I,
+ const float3 omega_in,
+ float *pdf)
{
- const DiffuseRampBsdf *bsdf = (const DiffuseRampBsdf*)sc;
- float3 N = bsdf->N;
+ const DiffuseRampBsdf *bsdf = (const DiffuseRampBsdf *)sc;
+ float3 N = bsdf->N;
- float cos_pi = fmaxf(dot(N, omega_in), 0.0f);
- *pdf = cos_pi * M_1_PI_F;
- return bsdf_diffuse_ramp_get_color(bsdf->colors, cos_pi) * M_1_PI_F;
+ float cos_pi = fmaxf(dot(N, omega_in), 0.0f);
+ *pdf = cos_pi * M_1_PI_F;
+ return bsdf_diffuse_ramp_get_color(bsdf->colors, cos_pi) * M_1_PI_F;
}
-ccl_device float3 bsdf_diffuse_ramp_eval_transmit(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf)
+ccl_device float3 bsdf_diffuse_ramp_eval_transmit(const ShaderClosure *sc,
+ const float3 I,
+ const float3 omega_in,
+ float *pdf)
{
- return make_float3(0.0f, 0.0f, 0.0f);
+ return make_float3(0.0f, 0.0f, 0.0f);
}
-ccl_device int bsdf_diffuse_ramp_sample(const ShaderClosure *sc, float3 Ng, float3 I, float3 dIdx, float3 dIdy, float randu, float randv, float3 *eval, float3 *omega_in, float3 *domega_in_dx, float3 *domega_in_dy, float *pdf)
+ccl_device int bsdf_diffuse_ramp_sample(const ShaderClosure *sc,
+ float3 Ng,
+ float3 I,
+ float3 dIdx,
+ float3 dIdy,
+ float randu,
+ float randv,
+ float3 *eval,
+ float3 *omega_in,
+ float3 *domega_in_dx,
+ float3 *domega_in_dy,
+ float *pdf)
{
- const DiffuseRampBsdf *bsdf = (const DiffuseRampBsdf*)sc;
- float3 N = bsdf->N;
-
- // distribution over the hemisphere
- sample_cos_hemisphere(N, randu, randv, omega_in, pdf);
-
- if(dot(Ng, *omega_in) > 0.0f) {
- *eval = bsdf_diffuse_ramp_get_color(bsdf->colors, *pdf * M_PI_F) * M_1_PI_F;
-#ifdef __RAY_DIFFERENTIALS__
- *domega_in_dx = (2 * dot(N, dIdx)) * N - dIdx;
- *domega_in_dy = (2 * dot(N, dIdy)) * N - dIdy;
-#endif
- }
- else
- *pdf = 0.0f;
-
- return LABEL_REFLECT|LABEL_DIFFUSE;
+ const DiffuseRampBsdf *bsdf = (const DiffuseRampBsdf *)sc;
+ float3 N = bsdf->N;
+
+ // distribution over the hemisphere
+ sample_cos_hemisphere(N, randu, randv, omega_in, pdf);
+
+ if (dot(Ng, *omega_in) > 0.0f) {
+ *eval = bsdf_diffuse_ramp_get_color(bsdf->colors, *pdf * M_PI_F) * M_1_PI_F;
+# ifdef __RAY_DIFFERENTIALS__
+ *domega_in_dx = (2 * dot(N, dIdx)) * N - dIdx;
+ *domega_in_dy = (2 * dot(N, dIdy)) * N - dIdy;
+# endif
+ }
+ else
+ *pdf = 0.0f;
+
+ return LABEL_REFLECT | LABEL_DIFFUSE;
}
-#endif /* __OSL__ */
+#endif /* __OSL__ */
CCL_NAMESPACE_END
-#endif /* __BSDF_DIFFUSE_RAMP_H__ */
+#endif /* __BSDF_DIFFUSE_RAMP_H__ */
diff --git a/intern/cycles/kernel/closure/bsdf_hair.h b/intern/cycles/kernel/closure/bsdf_hair.h
index e1a0cfaa3f5..6b2a9a97d30 100644
--- a/intern/cycles/kernel/closure/bsdf_hair.h
+++ b/intern/cycles/kernel/closure/bsdf_hair.h
@@ -36,245 +36,276 @@
CCL_NAMESPACE_BEGIN
typedef ccl_addr_space struct HairBsdf {
- SHADER_CLOSURE_BASE;
+ SHADER_CLOSURE_BASE;
- float3 T;
- float roughness1;
- float roughness2;
- float offset;
+ float3 T;
+ float roughness1;
+ float roughness2;
+ float offset;
} HairBsdf;
ccl_device int bsdf_hair_reflection_setup(HairBsdf *bsdf)
{
- bsdf->type = CLOSURE_BSDF_HAIR_REFLECTION_ID;
- bsdf->roughness1 = clamp(bsdf->roughness1, 0.001f, 1.0f);
- bsdf->roughness2 = clamp(bsdf->roughness2, 0.001f, 1.0f);
- return SD_BSDF|SD_BSDF_HAS_EVAL;
+ bsdf->type = CLOSURE_BSDF_HAIR_REFLECTION_ID;
+ bsdf->roughness1 = clamp(bsdf->roughness1, 0.001f, 1.0f);
+ bsdf->roughness2 = clamp(bsdf->roughness2, 0.001f, 1.0f);
+ return SD_BSDF | SD_BSDF_HAS_EVAL;
}
ccl_device int bsdf_hair_transmission_setup(HairBsdf *bsdf)
{
- bsdf->type = CLOSURE_BSDF_HAIR_TRANSMISSION_ID;
- bsdf->roughness1 = clamp(bsdf->roughness1, 0.001f, 1.0f);
- bsdf->roughness2 = clamp(bsdf->roughness2, 0.001f, 1.0f);
- return SD_BSDF|SD_BSDF_HAS_EVAL;
+ bsdf->type = CLOSURE_BSDF_HAIR_TRANSMISSION_ID;
+ bsdf->roughness1 = clamp(bsdf->roughness1, 0.001f, 1.0f);
+ bsdf->roughness2 = clamp(bsdf->roughness2, 0.001f, 1.0f);
+ return SD_BSDF | SD_BSDF_HAS_EVAL;
}
ccl_device bool bsdf_hair_merge(const ShaderClosure *a, const ShaderClosure *b)
{
- const HairBsdf *bsdf_a = (const HairBsdf*)a;
- const HairBsdf *bsdf_b = (const HairBsdf*)b;
+ const HairBsdf *bsdf_a = (const HairBsdf *)a;
+ const HairBsdf *bsdf_b = (const HairBsdf *)b;
- return (isequal_float3(bsdf_a->T, bsdf_b->T)) &&
- (bsdf_a->roughness1 == bsdf_b->roughness1) &&
- (bsdf_a->roughness2 == bsdf_b->roughness2) &&
- (bsdf_a->offset == bsdf_b->offset);
+ return (isequal_float3(bsdf_a->T, bsdf_b->T)) && (bsdf_a->roughness1 == bsdf_b->roughness1) &&
+ (bsdf_a->roughness2 == bsdf_b->roughness2) && (bsdf_a->offset == bsdf_b->offset);
}
-ccl_device float3 bsdf_hair_reflection_eval_reflect(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf)
+ccl_device float3 bsdf_hair_reflection_eval_reflect(const ShaderClosure *sc,
+ const float3 I,
+ const float3 omega_in,
+ float *pdf)
{
- const HairBsdf *bsdf = (const HairBsdf*)sc;
- float offset = bsdf->offset;
- float3 Tg = bsdf->T;
- float roughness1 = bsdf->roughness1;
- float roughness2 = bsdf->roughness2;
+ const HairBsdf *bsdf = (const HairBsdf *)sc;
+ float offset = bsdf->offset;
+ float3 Tg = bsdf->T;
+ float roughness1 = bsdf->roughness1;
+ float roughness2 = bsdf->roughness2;
- float Iz = dot(Tg, I);
- float3 locy = normalize(I - Tg * Iz);
+ float Iz = dot(Tg, I);
+ float3 locy = normalize(I - Tg * Iz);
- float theta_r = M_PI_2_F - fast_acosf(Iz);
+ float theta_r = M_PI_2_F - fast_acosf(Iz);
- float omega_in_z = dot(Tg, omega_in);
- float3 omega_in_y = normalize(omega_in - Tg * omega_in_z);
+ float omega_in_z = dot(Tg, omega_in);
+ float3 omega_in_y = normalize(omega_in - Tg * omega_in_z);
- float theta_i = M_PI_2_F - fast_acosf(omega_in_z);
- float cosphi_i = dot(omega_in_y, locy);
+ float theta_i = M_PI_2_F - fast_acosf(omega_in_z);
+ float cosphi_i = dot(omega_in_y, locy);
- if(M_PI_2_F - fabsf(theta_i) < 0.001f || cosphi_i < 0.0f) {
- *pdf = 0.0f;
- return make_float3(*pdf, *pdf, *pdf);
- }
+ if (M_PI_2_F - fabsf(theta_i) < 0.001f || cosphi_i < 0.0f) {
+ *pdf = 0.0f;
+ return make_float3(*pdf, *pdf, *pdf);
+ }
- float roughness1_inv = 1.0f / roughness1;
- float roughness2_inv = 1.0f / roughness2;
- float phi_i = fast_acosf(cosphi_i) * roughness2_inv;
- phi_i = fabsf(phi_i) < M_PI_F ? phi_i : M_PI_F;
- float costheta_i = fast_cosf(theta_i);
+ float roughness1_inv = 1.0f / roughness1;
+ float roughness2_inv = 1.0f / roughness2;
+ float phi_i = fast_acosf(cosphi_i) * roughness2_inv;
+ phi_i = fabsf(phi_i) < M_PI_F ? phi_i : M_PI_F;
+ float costheta_i = fast_cosf(theta_i);
- float a_R = fast_atan2f(((M_PI_2_F + theta_r) * 0.5f - offset) * roughness1_inv, 1.0f);
- float b_R = fast_atan2f(((-M_PI_2_F + theta_r) * 0.5f - offset) * roughness1_inv, 1.0f);
+ float a_R = fast_atan2f(((M_PI_2_F + theta_r) * 0.5f - offset) * roughness1_inv, 1.0f);
+ float b_R = fast_atan2f(((-M_PI_2_F + theta_r) * 0.5f - offset) * roughness1_inv, 1.0f);
- float theta_h = (theta_i + theta_r) * 0.5f;
- float t = theta_h - offset;
+ float theta_h = (theta_i + theta_r) * 0.5f;
+ float t = theta_h - offset;
- float phi_pdf = fast_cosf(phi_i * 0.5f) * 0.25f * roughness2_inv;
- float theta_pdf = roughness1 / (2 * (t*t + roughness1*roughness1) * (a_R - b_R)* costheta_i);
- *pdf = phi_pdf * theta_pdf;
+ float phi_pdf = fast_cosf(phi_i * 0.5f) * 0.25f * roughness2_inv;
+ float theta_pdf = roughness1 /
+ (2 * (t * t + roughness1 * roughness1) * (a_R - b_R) * costheta_i);
+ *pdf = phi_pdf * theta_pdf;
- return make_float3(*pdf, *pdf, *pdf);
+ return make_float3(*pdf, *pdf, *pdf);
}
-ccl_device float3 bsdf_hair_transmission_eval_reflect(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf)
+ccl_device float3 bsdf_hair_transmission_eval_reflect(const ShaderClosure *sc,
+ const float3 I,
+ const float3 omega_in,
+ float *pdf)
{
- return make_float3(0.0f, 0.0f, 0.0f);
+ return make_float3(0.0f, 0.0f, 0.0f);
}
-
-ccl_device float3 bsdf_hair_reflection_eval_transmit(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf)
+ccl_device float3 bsdf_hair_reflection_eval_transmit(const ShaderClosure *sc,
+ const float3 I,
+ const float3 omega_in,
+ float *pdf)
{
- return make_float3(0.0f, 0.0f, 0.0f);
+ return make_float3(0.0f, 0.0f, 0.0f);
}
-ccl_device float3 bsdf_hair_transmission_eval_transmit(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf)
+ccl_device float3 bsdf_hair_transmission_eval_transmit(const ShaderClosure *sc,
+ const float3 I,
+ const float3 omega_in,
+ float *pdf)
{
- const HairBsdf *bsdf = (const HairBsdf*)sc;
- float offset = bsdf->offset;
- float3 Tg = bsdf->T;
- float roughness1 = bsdf->roughness1;
- float roughness2 = bsdf->roughness2;
- float Iz = dot(Tg, I);
- float3 locy = normalize(I - Tg * Iz);
+ const HairBsdf *bsdf = (const HairBsdf *)sc;
+ float offset = bsdf->offset;
+ float3 Tg = bsdf->T;
+ float roughness1 = bsdf->roughness1;
+ float roughness2 = bsdf->roughness2;
+ float Iz = dot(Tg, I);
+ float3 locy = normalize(I - Tg * Iz);
- float theta_r = M_PI_2_F - fast_acosf(Iz);
+ float theta_r = M_PI_2_F - fast_acosf(Iz);
- float omega_in_z = dot(Tg, omega_in);
- float3 omega_in_y = normalize(omega_in - Tg * omega_in_z);
+ float omega_in_z = dot(Tg, omega_in);
+ float3 omega_in_y = normalize(omega_in - Tg * omega_in_z);
- float theta_i = M_PI_2_F - fast_acosf(omega_in_z);
- float phi_i = fast_acosf(dot(omega_in_y, locy));
+ float theta_i = M_PI_2_F - fast_acosf(omega_in_z);
+ float phi_i = fast_acosf(dot(omega_in_y, locy));
- if(M_PI_2_F - fabsf(theta_i) < 0.001f) {
- *pdf = 0.0f;
- return make_float3(*pdf, *pdf, *pdf);
- }
+ if (M_PI_2_F - fabsf(theta_i) < 0.001f) {
+ *pdf = 0.0f;
+ return make_float3(*pdf, *pdf, *pdf);
+ }
- float costheta_i = fast_cosf(theta_i);
+ float costheta_i = fast_cosf(theta_i);
- float roughness1_inv = 1.0f / roughness1;
- float a_TT = fast_atan2f(((M_PI_2_F + theta_r)/2 - offset) * roughness1_inv, 1.0f);
- float b_TT = fast_atan2f(((-M_PI_2_F + theta_r)/2 - offset) * roughness1_inv, 1.0f);
- float c_TT = 2 * fast_atan2f(M_PI_2_F / roughness2, 1.0f);
+ float roughness1_inv = 1.0f / roughness1;
+ float a_TT = fast_atan2f(((M_PI_2_F + theta_r) / 2 - offset) * roughness1_inv, 1.0f);
+ float b_TT = fast_atan2f(((-M_PI_2_F + theta_r) / 2 - offset) * roughness1_inv, 1.0f);
+ float c_TT = 2 * fast_atan2f(M_PI_2_F / roughness2, 1.0f);
- float theta_h = (theta_i + theta_r) / 2;
- float t = theta_h - offset;
- float phi = fabsf(phi_i);
+ float theta_h = (theta_i + theta_r) / 2;
+ float t = theta_h - offset;
+ float phi = fabsf(phi_i);
- float p = M_PI_F - phi;
- float theta_pdf = roughness1 / (2 * (t*t + roughness1 * roughness1) * (a_TT - b_TT)*costheta_i);
- float phi_pdf = roughness2 / (c_TT * (p * p + roughness2 * roughness2));
+ float p = M_PI_F - phi;
+ float theta_pdf = roughness1 /
+ (2 * (t * t + roughness1 * roughness1) * (a_TT - b_TT) * costheta_i);
+ float phi_pdf = roughness2 / (c_TT * (p * p + roughness2 * roughness2));
- *pdf = phi_pdf * theta_pdf;
- return make_float3(*pdf, *pdf, *pdf);
+ *pdf = phi_pdf * theta_pdf;
+ return make_float3(*pdf, *pdf, *pdf);
}
-ccl_device int bsdf_hair_reflection_sample(const ShaderClosure *sc, float3 Ng, float3 I, float3 dIdx, float3 dIdy, float randu, float randv, float3 *eval, float3 *omega_in, float3 *domega_in_dx, float3 *domega_in_dy, float *pdf)
+ccl_device int bsdf_hair_reflection_sample(const ShaderClosure *sc,
+ float3 Ng,
+ float3 I,
+ float3 dIdx,
+ float3 dIdy,
+ float randu,
+ float randv,
+ float3 *eval,
+ float3 *omega_in,
+ float3 *domega_in_dx,
+ float3 *domega_in_dy,
+ float *pdf)
{
- const HairBsdf *bsdf = (const HairBsdf*)sc;
- float offset = bsdf->offset;
- float3 Tg = bsdf->T;
- float roughness1 = bsdf->roughness1;
- float roughness2 = bsdf->roughness2;
- float Iz = dot(Tg, I);
- float3 locy = normalize(I - Tg * Iz);
- float3 locx = cross(locy, Tg);
- float theta_r = M_PI_2_F - fast_acosf(Iz);
+ const HairBsdf *bsdf = (const HairBsdf *)sc;
+ float offset = bsdf->offset;
+ float3 Tg = bsdf->T;
+ float roughness1 = bsdf->roughness1;
+ float roughness2 = bsdf->roughness2;
+ float Iz = dot(Tg, I);
+ float3 locy = normalize(I - Tg * Iz);
+ float3 locx = cross(locy, Tg);
+ float theta_r = M_PI_2_F - fast_acosf(Iz);
- float roughness1_inv = 1.0f / roughness1;
- float a_R = fast_atan2f(((M_PI_2_F + theta_r) * 0.5f - offset) * roughness1_inv, 1.0f);
- float b_R = fast_atan2f(((-M_PI_2_F + theta_r) * 0.5f - offset) * roughness1_inv, 1.0f);
+ float roughness1_inv = 1.0f / roughness1;
+ float a_R = fast_atan2f(((M_PI_2_F + theta_r) * 0.5f - offset) * roughness1_inv, 1.0f);
+ float b_R = fast_atan2f(((-M_PI_2_F + theta_r) * 0.5f - offset) * roughness1_inv, 1.0f);
- float t = roughness1 * tanf(randu * (a_R - b_R) + b_R);
+ float t = roughness1 * tanf(randu * (a_R - b_R) + b_R);
- float theta_h = t + offset;
- float theta_i = 2 * theta_h - theta_r;
+ float theta_h = t + offset;
+ float theta_i = 2 * theta_h - theta_r;
- float costheta_i, sintheta_i;
- fast_sincosf(theta_i, &sintheta_i, &costheta_i);
+ float costheta_i, sintheta_i;
+ fast_sincosf(theta_i, &sintheta_i, &costheta_i);
- float phi = 2 * safe_asinf(1 - 2 * randv) * roughness2;
+ float phi = 2 * safe_asinf(1 - 2 * randv) * roughness2;
- float phi_pdf = fast_cosf(phi * 0.5f) * 0.25f / roughness2;
+ float phi_pdf = fast_cosf(phi * 0.5f) * 0.25f / roughness2;
- float theta_pdf = roughness1 / (2 * (t*t + roughness1*roughness1) * (a_R - b_R)*costheta_i);
+ float theta_pdf = roughness1 /
+ (2 * (t * t + roughness1 * roughness1) * (a_R - b_R) * costheta_i);
- float sinphi, cosphi;
- fast_sincosf(phi, &sinphi, &cosphi);
- *omega_in =(cosphi * costheta_i) * locy -
- (sinphi * costheta_i) * locx +
- ( sintheta_i) * Tg;
+ float sinphi, cosphi;
+ fast_sincosf(phi, &sinphi, &cosphi);
+ *omega_in = (cosphi * costheta_i) * locy - (sinphi * costheta_i) * locx + (sintheta_i)*Tg;
- //differentials - TODO: find a better approximation for the reflective bounce
+ //differentials - TODO: find a better approximation for the reflective bounce
#ifdef __RAY_DIFFERENTIALS__
- *domega_in_dx = 2 * dot(locy, dIdx) * locy - dIdx;
- *domega_in_dy = 2 * dot(locy, dIdy) * locy - dIdy;
+ *domega_in_dx = 2 * dot(locy, dIdx) * locy - dIdx;
+ *domega_in_dy = 2 * dot(locy, dIdy) * locy - dIdy;
#endif
- *pdf = fabsf(phi_pdf * theta_pdf);
- if(M_PI_2_F - fabsf(theta_i) < 0.001f)
- *pdf = 0.0f;
+ *pdf = fabsf(phi_pdf * theta_pdf);
+ if (M_PI_2_F - fabsf(theta_i) < 0.001f)
+ *pdf = 0.0f;
- *eval = make_float3(*pdf, *pdf, *pdf);
+ *eval = make_float3(*pdf, *pdf, *pdf);
- return LABEL_REFLECT|LABEL_GLOSSY;
+ return LABEL_REFLECT | LABEL_GLOSSY;
}
-ccl_device int bsdf_hair_transmission_sample(const ShaderClosure *sc, float3 Ng, float3 I, float3 dIdx, float3 dIdy, float randu, float randv, float3 *eval, float3 *omega_in, float3 *domega_in_dx, float3 *domega_in_dy, float *pdf)
+ccl_device int bsdf_hair_transmission_sample(const ShaderClosure *sc,
+ float3 Ng,
+ float3 I,
+ float3 dIdx,
+ float3 dIdy,
+ float randu,
+ float randv,
+ float3 *eval,
+ float3 *omega_in,
+ float3 *domega_in_dx,
+ float3 *domega_in_dy,
+ float *pdf)
{
- const HairBsdf *bsdf = (const HairBsdf*)sc;
- float offset = bsdf->offset;
- float3 Tg = bsdf->T;
- float roughness1 = bsdf->roughness1;
- float roughness2 = bsdf->roughness2;
- float Iz = dot(Tg, I);
- float3 locy = normalize(I - Tg * Iz);
- float3 locx = cross(locy, Tg);
- float theta_r = M_PI_2_F - fast_acosf(Iz);
-
- float roughness1_inv = 1.0f / roughness1;
- float a_TT = fast_atan2f(((M_PI_2_F + theta_r)/2 - offset) * roughness1_inv, 1.0f);
- float b_TT = fast_atan2f(((-M_PI_2_F + theta_r)/2 - offset) * roughness1_inv, 1.0f);
- float c_TT = 2 * fast_atan2f(M_PI_2_F / roughness2, 1.0f);
-
- float t = roughness1 * tanf(randu * (a_TT - b_TT) + b_TT);
-
- float theta_h = t + offset;
- float theta_i = 2 * theta_h - theta_r;
-
- float costheta_i, sintheta_i;
- fast_sincosf(theta_i, &sintheta_i, &costheta_i);
-
- float p = roughness2 * tanf(c_TT * (randv - 0.5f));
- float phi = p + M_PI_F;
- float theta_pdf = roughness1 / (2 * (t*t + roughness1*roughness1) * (a_TT - b_TT) * costheta_i);
- float phi_pdf = roughness2 / (c_TT * (p * p + roughness2 * roughness2));
-
- float sinphi, cosphi;
- fast_sincosf(phi, &sinphi, &cosphi);
- *omega_in =(cosphi * costheta_i) * locy -
- (sinphi * costheta_i) * locx +
- ( sintheta_i) * Tg;
-
- //differentials - TODO: find a better approximation for the transmission bounce
+ const HairBsdf *bsdf = (const HairBsdf *)sc;
+ float offset = bsdf->offset;
+ float3 Tg = bsdf->T;
+ float roughness1 = bsdf->roughness1;
+ float roughness2 = bsdf->roughness2;
+ float Iz = dot(Tg, I);
+ float3 locy = normalize(I - Tg * Iz);
+ float3 locx = cross(locy, Tg);
+ float theta_r = M_PI_2_F - fast_acosf(Iz);
+
+ float roughness1_inv = 1.0f / roughness1;
+ float a_TT = fast_atan2f(((M_PI_2_F + theta_r) / 2 - offset) * roughness1_inv, 1.0f);
+ float b_TT = fast_atan2f(((-M_PI_2_F + theta_r) / 2 - offset) * roughness1_inv, 1.0f);
+ float c_TT = 2 * fast_atan2f(M_PI_2_F / roughness2, 1.0f);
+
+ float t = roughness1 * tanf(randu * (a_TT - b_TT) + b_TT);
+
+ float theta_h = t + offset;
+ float theta_i = 2 * theta_h - theta_r;
+
+ float costheta_i, sintheta_i;
+ fast_sincosf(theta_i, &sintheta_i, &costheta_i);
+
+ float p = roughness2 * tanf(c_TT * (randv - 0.5f));
+ float phi = p + M_PI_F;
+ float theta_pdf = roughness1 /
+ (2 * (t * t + roughness1 * roughness1) * (a_TT - b_TT) * costheta_i);
+ float phi_pdf = roughness2 / (c_TT * (p * p + roughness2 * roughness2));
+
+ float sinphi, cosphi;
+ fast_sincosf(phi, &sinphi, &cosphi);
+ *omega_in = (cosphi * costheta_i) * locy - (sinphi * costheta_i) * locx + (sintheta_i)*Tg;
+
+ //differentials - TODO: find a better approximation for the transmission bounce
#ifdef __RAY_DIFFERENTIALS__
- *domega_in_dx = 2 * dot(locy, dIdx) * locy - dIdx;
- *domega_in_dy = 2 * dot(locy, dIdy) * locy - dIdy;
+ *domega_in_dx = 2 * dot(locy, dIdx) * locy - dIdx;
+ *domega_in_dy = 2 * dot(locy, dIdy) * locy - dIdy;
#endif
- *pdf = fabsf(phi_pdf * theta_pdf);
- if(M_PI_2_F - fabsf(theta_i) < 0.001f) {
- *pdf = 0.0f;
- }
+ *pdf = fabsf(phi_pdf * theta_pdf);
+ if (M_PI_2_F - fabsf(theta_i) < 0.001f) {
+ *pdf = 0.0f;
+ }
- *eval = make_float3(*pdf, *pdf, *pdf);
+ *eval = make_float3(*pdf, *pdf, *pdf);
- /* TODO(sergey): Should always be negative, but seems some precision issue
- * is involved here.
- */
- kernel_assert(dot(locy, *omega_in) < 1e-4f);
+ /* TODO(sergey): Should always be negative, but seems some precision issue
+ * is involved here.
+ */
+ kernel_assert(dot(locy, *omega_in) < 1e-4f);
- return LABEL_TRANSMIT|LABEL_GLOSSY;
+ return LABEL_TRANSMIT | LABEL_GLOSSY;
}
CCL_NAMESPACE_END
-#endif /* __BSDF_HAIR_H__ */
+#endif /* __BSDF_HAIR_H__ */
diff --git a/intern/cycles/kernel/closure/bsdf_hair_principled.h b/intern/cycles/kernel/closure/bsdf_hair_principled.h
index 68335ee887a..a4bba2fbf6c 100644
--- a/intern/cycles/kernel/closure/bsdf_hair_principled.h
+++ b/intern/cycles/kernel/closure/bsdf_hair_principled.h
@@ -15,251 +15,245 @@
*/
#ifdef __KERNEL_CPU__
-#include <fenv.h>
+# include <fenv.h>
#endif
#include "kernel/kernel_color.h"
#ifndef __BSDF_HAIR_PRINCIPLED_H__
-#define __BSDF_HAIR_PRINCIPLED_H__
+# define __BSDF_HAIR_PRINCIPLED_H__
CCL_NAMESPACE_BEGIN
typedef ccl_addr_space struct PrincipledHairExtra {
- /* Geometry data. */
- float4 geom;
+ /* Geometry data. */
+ float4 geom;
} PrincipledHairExtra;
typedef ccl_addr_space struct PrincipledHairBSDF {
- SHADER_CLOSURE_BASE;
-
- /* Absorption coefficient. */
- float3 sigma;
- /* Variance of the underlying logistic distribution. */
- float v;
- /* Scale factor of the underlying logistic distribution. */
- float s;
- /* Cuticle tilt angle. */
- float alpha;
- /* IOR. */
- float eta;
- /* Effective variance for the diffuse bounce only. */
- float m0_roughness;
-
- /* Extra closure. */
- PrincipledHairExtra *extra;
+ SHADER_CLOSURE_BASE;
+
+ /* Absorption coefficient. */
+ float3 sigma;
+ /* Variance of the underlying logistic distribution. */
+ float v;
+ /* Scale factor of the underlying logistic distribution. */
+ float s;
+ /* Cuticle tilt angle. */
+ float alpha;
+ /* IOR. */
+ float eta;
+ /* Effective variance for the diffuse bounce only. */
+ float m0_roughness;
+
+ /* Extra closure. */
+ PrincipledHairExtra *extra;
} PrincipledHairBSDF;
-static_assert(sizeof(ShaderClosure) >= sizeof(PrincipledHairBSDF), "PrincipledHairBSDF is too large!");
-static_assert(sizeof(ShaderClosure) >= sizeof(PrincipledHairExtra), "PrincipledHairExtra is too large!");
+static_assert(sizeof(ShaderClosure) >= sizeof(PrincipledHairBSDF),
+ "PrincipledHairBSDF is too large!");
+static_assert(sizeof(ShaderClosure) >= sizeof(PrincipledHairExtra),
+ "PrincipledHairExtra is too large!");
ccl_device_inline float cos_from_sin(const float s)
{
- return safe_sqrtf(1.0f - s*s);
+ return safe_sqrtf(1.0f - s * s);
}
/* Gives the change in direction in the normal plane for the given angles and p-th-order scattering. */
ccl_device_inline float delta_phi(int p, float gamma_o, float gamma_t)
{
- return 2.0f * p * gamma_t - 2.0f * gamma_o + p * M_PI_F;
+ return 2.0f * p * gamma_t - 2.0f * gamma_o + p * M_PI_F;
}
/* Remaps the given angle to [-pi, pi]. */
ccl_device_inline float wrap_angle(float a)
{
- while(a > M_PI_F) {
- a -= M_2PI_F;
- }
- while(a < -M_PI_F) {
- a += M_2PI_F;
- }
- return a;
+ while (a > M_PI_F) {
+ a -= M_2PI_F;
+ }
+ while (a < -M_PI_F) {
+ a += M_2PI_F;
+ }
+ return a;
}
/* Logistic distribution function. */
ccl_device_inline float logistic(float x, float s)
{
- float v = expf(-fabsf(x)/s);
- return v / (s * sqr(1.0f + v));
+ float v = expf(-fabsf(x) / s);
+ return v / (s * sqr(1.0f + v));
}
/* Logistic cumulative density function. */
ccl_device_inline float logistic_cdf(float x, float s)
{
- float arg = -x/s;
- /* expf() overflows if arg >= 89.0. */
- if(arg > 88.0f) {
- return 0.0f;
- }
- else {
- return 1.0f / (1.0f + expf(arg));
- }
+ float arg = -x / s;
+ /* expf() overflows if arg >= 89.0. */
+ if (arg > 88.0f) {
+ return 0.0f;
+ }
+ else {
+ return 1.0f / (1.0f + expf(arg));
+ }
}
/* Numerical approximation to the Bessel function of the first kind. */
ccl_device_inline float bessel_I0(float x)
{
- x = sqr(x);
- float val = 1.0f + 0.25f*x;
- float pow_x_2i = sqr(x);
- uint64_t i_fac_2 = 1;
- int pow_4_i = 16;
- for(int i = 2; i < 10; i++) {
- i_fac_2 *= i*i;
- float newval = val + pow_x_2i / (pow_4_i * i_fac_2);
- if(val == newval) {
- return val;
- }
- val = newval;
- pow_x_2i *= x;
- pow_4_i *= 4;
- }
- return val;
+ x = sqr(x);
+ float val = 1.0f + 0.25f * x;
+ float pow_x_2i = sqr(x);
+ uint64_t i_fac_2 = 1;
+ int pow_4_i = 16;
+ for (int i = 2; i < 10; i++) {
+ i_fac_2 *= i * i;
+ float newval = val + pow_x_2i / (pow_4_i * i_fac_2);
+ if (val == newval) {
+ return val;
+ }
+ val = newval;
+ pow_x_2i *= x;
+ pow_4_i *= 4;
+ }
+ return val;
}
/* Logarithm of the Bessel function of the first kind. */
ccl_device_inline float log_bessel_I0(float x)
{
- if(x > 12.0f) {
- /* log(1/x) == -log(x) iff x > 0.
- * This is only used with positive cosines */
- return x + 0.5f * (1.f / (8.0f * x) - M_LN_2PI_F - logf(x));
- }
- else {
- return logf(bessel_I0(x));
- }
+ if (x > 12.0f) {
+ /* log(1/x) == -log(x) iff x > 0.
+ * This is only used with positive cosines */
+ return x + 0.5f * (1.f / (8.0f * x) - M_LN_2PI_F - logf(x));
+ }
+ else {
+ return logf(bessel_I0(x));
+ }
}
/* Logistic distribution limited to the interval [-pi, pi]. */
ccl_device_inline float trimmed_logistic(float x, float s)
{
- /* The logistic distribution is symmetric and centered around zero,
- * so logistic_cdf(x, s) = 1 - logistic_cdf(-x, s).
- * Therefore, logistic_cdf(x, s)-logistic_cdf(-x, s) = 1 - 2*logistic_cdf(-x, s) */
- float scaling_fac = 1.0f - 2.0f*logistic_cdf(-M_PI_F, s);
- float val = logistic(x, s);
- return safe_divide(val, scaling_fac);
+ /* The logistic distribution is symmetric and centered around zero,
+ * so logistic_cdf(x, s) = 1 - logistic_cdf(-x, s).
+ * Therefore, logistic_cdf(x, s)-logistic_cdf(-x, s) = 1 - 2*logistic_cdf(-x, s) */
+ float scaling_fac = 1.0f - 2.0f * logistic_cdf(-M_PI_F, s);
+ float val = logistic(x, s);
+ return safe_divide(val, scaling_fac);
}
/* Sampling function for the trimmed logistic function. */
ccl_device_inline float sample_trimmed_logistic(float u, float s)
{
- float cdf_minuspi = logistic_cdf(-M_PI_F, s);
- float x = -s*logf(1.0f / (u*(1.0f - 2.0f*cdf_minuspi) + cdf_minuspi) - 1.0f);
- return clamp(x, -M_PI_F, M_PI_F);
+ float cdf_minuspi = logistic_cdf(-M_PI_F, s);
+ float x = -s * logf(1.0f / (u * (1.0f - 2.0f * cdf_minuspi) + cdf_minuspi) - 1.0f);
+ return clamp(x, -M_PI_F, M_PI_F);
}
/* Azimuthal scattering function Np. */
-ccl_device_inline float azimuthal_scattering(float phi,
- int p,
- float s,
- float gamma_o,
- float gamma_t)
+ccl_device_inline float azimuthal_scattering(
+ float phi, int p, float s, float gamma_o, float gamma_t)
{
- float phi_o = wrap_angle(phi - delta_phi(p, gamma_o, gamma_t));
- float val = trimmed_logistic(phi_o, s);
- return val;
+ float phi_o = wrap_angle(phi - delta_phi(p, gamma_o, gamma_t));
+ float val = trimmed_logistic(phi_o, s);
+ return val;
}
/* Longitudinal scattering function Mp. */
-ccl_device_inline float longitudinal_scattering(float sin_theta_i,
- float cos_theta_i,
- float sin_theta_o,
- float cos_theta_o,
- float v)
+ccl_device_inline float longitudinal_scattering(
+ float sin_theta_i, float cos_theta_i, float sin_theta_o, float cos_theta_o, float v)
{
- float inv_v = 1.0f/v;
- float cos_arg = cos_theta_i * cos_theta_o * inv_v;
- float sin_arg = sin_theta_i * sin_theta_o * inv_v;
- if(v <= 0.1f) {
- float i0 = log_bessel_I0(cos_arg);
- float val = expf(i0 - sin_arg - inv_v + 0.6931f + logf(0.5f*inv_v));
- return val;
- }
- else {
- float i0 = bessel_I0(cos_arg);
- float val = (expf(-sin_arg) * i0) / (sinhf(inv_v) * 2.0f * v);
- return val;
- }
+ float inv_v = 1.0f / v;
+ float cos_arg = cos_theta_i * cos_theta_o * inv_v;
+ float sin_arg = sin_theta_i * sin_theta_o * inv_v;
+ if (v <= 0.1f) {
+ float i0 = log_bessel_I0(cos_arg);
+ float val = expf(i0 - sin_arg - inv_v + 0.6931f + logf(0.5f * inv_v));
+ return val;
+ }
+ else {
+ float i0 = bessel_I0(cos_arg);
+ float val = (expf(-sin_arg) * i0) / (sinhf(inv_v) * 2.0f * v);
+ return val;
+ }
}
/* Combine the three values using their luminances. */
ccl_device_inline float4 combine_with_energy(KernelGlobals *kg, float3 c)
{
- return make_float4(c.x, c.y, c.z, linear_rgb_to_gray(kg, c));
+ return make_float4(c.x, c.y, c.z, linear_rgb_to_gray(kg, c));
}
-#ifdef __HAIR__
+# ifdef __HAIR__
/* Set up the hair closure. */
ccl_device int bsdf_principled_hair_setup(ShaderData *sd, PrincipledHairBSDF *bsdf)
{
- bsdf->type = CLOSURE_BSDF_HAIR_PRINCIPLED_ID;
- bsdf->v = clamp(bsdf->v, 0.001f, 1.0f);
- bsdf->s = clamp(bsdf->s, 0.001f, 1.0f);
- /* Apply Primary Reflection Roughness modifier. */
- bsdf->m0_roughness = clamp(bsdf->m0_roughness*bsdf->v, 0.001f, 1.0f);
-
- /* Map from roughness_u and roughness_v to variance and scale factor. */
- bsdf->v = sqr(0.726f*bsdf->v + 0.812f*sqr(bsdf->v) + 3.700f*pow20(bsdf->v));
- bsdf->s = (0.265f*bsdf->s + 1.194f*sqr(bsdf->s) + 5.372f*pow22(bsdf->s))*M_SQRT_PI_8_F;
- bsdf->m0_roughness = sqr(0.726f*bsdf->m0_roughness + 0.812f*sqr(bsdf->m0_roughness) + 3.700f*pow20(bsdf->m0_roughness));
-
- /* Compute local frame, aligned to curve tangent and ray direction. */
- float3 X = safe_normalize(sd->dPdu);
- float3 Y = safe_normalize(cross(X, sd->I));
- float3 Z = safe_normalize(cross(X, Y));
- /* TODO: the solution below works where sd->Ng is the normal
- * pointing from the center of the curve to the shading point.
- * It doesn't work for triangles, see https://developer.blender.org/T43625 */
-
- /* h -1..0..1 means the rays goes from grazing the hair, to hitting it at
- * the center, to grazing the other edge. This is the sine of the angle
- * between sd->Ng and Z, as seen from the tangent X. */
-
- /* TODO: we convert this value to a cosine later and discard the sign, so
- * we could probably save some operations. */
- float h = dot(cross(sd->Ng, X), Z);
-
- kernel_assert(fabsf(h) < 1.0f + 1e-4f);
- kernel_assert(isfinite3_safe(Y));
- kernel_assert(isfinite_safe(h));
-
- bsdf->extra->geom = make_float4(Y.x, Y.y, Y.z, h);
-
- return SD_BSDF|SD_BSDF_HAS_EVAL|SD_BSDF_NEEDS_LCG;
+ bsdf->type = CLOSURE_BSDF_HAIR_PRINCIPLED_ID;
+ bsdf->v = clamp(bsdf->v, 0.001f, 1.0f);
+ bsdf->s = clamp(bsdf->s, 0.001f, 1.0f);
+ /* Apply Primary Reflection Roughness modifier. */
+ bsdf->m0_roughness = clamp(bsdf->m0_roughness * bsdf->v, 0.001f, 1.0f);
+
+ /* Map from roughness_u and roughness_v to variance and scale factor. */
+ bsdf->v = sqr(0.726f * bsdf->v + 0.812f * sqr(bsdf->v) + 3.700f * pow20(bsdf->v));
+ bsdf->s = (0.265f * bsdf->s + 1.194f * sqr(bsdf->s) + 5.372f * pow22(bsdf->s)) * M_SQRT_PI_8_F;
+ bsdf->m0_roughness = sqr(0.726f * bsdf->m0_roughness + 0.812f * sqr(bsdf->m0_roughness) +
+ 3.700f * pow20(bsdf->m0_roughness));
+
+ /* Compute local frame, aligned to curve tangent and ray direction. */
+ float3 X = safe_normalize(sd->dPdu);
+ float3 Y = safe_normalize(cross(X, sd->I));
+ float3 Z = safe_normalize(cross(X, Y));
+ /* TODO: the solution below works where sd->Ng is the normal
+ * pointing from the center of the curve to the shading point.
+ * It doesn't work for triangles, see https://developer.blender.org/T43625 */
+
+ /* h -1..0..1 means the rays goes from grazing the hair, to hitting it at
+ * the center, to grazing the other edge. This is the sine of the angle
+ * between sd->Ng and Z, as seen from the tangent X. */
+
+ /* TODO: we convert this value to a cosine later and discard the sign, so
+ * we could probably save some operations. */
+ float h = dot(cross(sd->Ng, X), Z);
+
+ kernel_assert(fabsf(h) < 1.0f + 1e-4f);
+ kernel_assert(isfinite3_safe(Y));
+ kernel_assert(isfinite_safe(h));
+
+ bsdf->extra->geom = make_float4(Y.x, Y.y, Y.z, h);
+
+ return SD_BSDF | SD_BSDF_HAS_EVAL | SD_BSDF_NEEDS_LCG;
}
-#endif /* __HAIR__ */
+# endif /* __HAIR__ */
/* Given the Fresnel term and transmittance, generate the attenuation terms for each bounce. */
-ccl_device_inline void hair_attenuation(KernelGlobals *kg,
- float f,
- float3 T,
- float4 *Ap)
+ccl_device_inline void hair_attenuation(KernelGlobals *kg, float f, float3 T, float4 *Ap)
{
- /* Primary specular (R). */
- Ap[0] = make_float4(f, f, f, f);
+ /* Primary specular (R). */
+ Ap[0] = make_float4(f, f, f, f);
- /* Transmission (TT). */
- float3 col = sqr(1.0f - f) * T;
- Ap[1] = combine_with_energy(kg, col);
+ /* Transmission (TT). */
+ float3 col = sqr(1.0f - f) * T;
+ Ap[1] = combine_with_energy(kg, col);
- /* Secondary specular (TRT). */
- col *= T*f;
- Ap[2] = combine_with_energy(kg, col);
+ /* Secondary specular (TRT). */
+ col *= T * f;
+ Ap[2] = combine_with_energy(kg, col);
- /* Residual component (TRRT+). */
- col *= safe_divide_color(T*f, make_float3(1.0f, 1.0f, 1.0f) - T*f);
- Ap[3] = combine_with_energy(kg, col);
+ /* Residual component (TRRT+). */
+ col *= safe_divide_color(T * f, make_float3(1.0f, 1.0f, 1.0f) - T * f);
+ Ap[3] = combine_with_energy(kg, col);
- /* Normalize sampling weights. */
- float totweight = Ap[0].w + Ap[1].w + Ap[2].w + Ap[3].w;
- float fac = safe_divide(1.0f, totweight);
+ /* Normalize sampling weights. */
+ float totweight = Ap[0].w + Ap[1].w + Ap[2].w + Ap[3].w;
+ float fac = safe_divide(1.0f, totweight);
- Ap[0].w *= fac;
- Ap[1].w *= fac;
- Ap[2].w *= fac;
- Ap[3].w *= fac;
+ Ap[0].w *= fac;
+ Ap[1].w *= fac;
+ Ap[2].w *= fac;
+ Ap[3].w *= fac;
}
/* Given the tilt angle, generate the rotated theta_i for the different bounces. */
@@ -268,19 +262,19 @@ ccl_device_inline void hair_alpha_angles(float sin_theta_i,
float alpha,
float *angles)
{
- float sin_1alpha = sinf(alpha);
- float cos_1alpha = cos_from_sin(sin_1alpha);
- float sin_2alpha = 2.0f*sin_1alpha*cos_1alpha;
- float cos_2alpha = sqr(cos_1alpha) - sqr(sin_1alpha);
- float sin_4alpha = 2.0f*sin_2alpha*cos_2alpha;
- float cos_4alpha = sqr(cos_2alpha) - sqr(sin_2alpha);
-
- angles[0] = sin_theta_i*cos_2alpha + cos_theta_i*sin_2alpha;
- angles[1] = fabsf(cos_theta_i*cos_2alpha - sin_theta_i*sin_2alpha);
- angles[2] = sin_theta_i*cos_1alpha - cos_theta_i*sin_1alpha;
- angles[3] = fabsf(cos_theta_i*cos_1alpha + sin_theta_i*sin_1alpha);
- angles[4] = sin_theta_i*cos_4alpha - cos_theta_i*sin_4alpha;
- angles[5] = fabsf(cos_theta_i*cos_4alpha + sin_theta_i*sin_4alpha);
+ float sin_1alpha = sinf(alpha);
+ float cos_1alpha = cos_from_sin(sin_1alpha);
+ float sin_2alpha = 2.0f * sin_1alpha * cos_1alpha;
+ float cos_2alpha = sqr(cos_1alpha) - sqr(sin_1alpha);
+ float sin_4alpha = 2.0f * sin_2alpha * cos_2alpha;
+ float cos_4alpha = sqr(cos_2alpha) - sqr(sin_2alpha);
+
+ angles[0] = sin_theta_i * cos_2alpha + cos_theta_i * sin_2alpha;
+ angles[1] = fabsf(cos_theta_i * cos_2alpha - sin_theta_i * sin_2alpha);
+ angles[2] = sin_theta_i * cos_1alpha - cos_theta_i * sin_1alpha;
+ angles[3] = fabsf(cos_theta_i * cos_1alpha + sin_theta_i * sin_1alpha);
+ angles[4] = sin_theta_i * cos_4alpha - cos_theta_i * sin_4alpha;
+ angles[5] = fabsf(cos_theta_i * cos_4alpha + sin_theta_i * sin_4alpha);
}
/* Evaluation function for our shader. */
@@ -290,75 +284,75 @@ ccl_device float3 bsdf_principled_hair_eval(KernelGlobals *kg,
const float3 omega_in,
float *pdf)
{
- kernel_assert(isfinite3_safe(sd->P) && isfinite_safe(sd->ray_length));
+ kernel_assert(isfinite3_safe(sd->P) && isfinite_safe(sd->ray_length));
- const PrincipledHairBSDF *bsdf = (const PrincipledHairBSDF*) sc;
- float3 Y = float4_to_float3(bsdf->extra->geom);
+ const PrincipledHairBSDF *bsdf = (const PrincipledHairBSDF *)sc;
+ float3 Y = float4_to_float3(bsdf->extra->geom);
- float3 X = safe_normalize(sd->dPdu);
- kernel_assert(fabsf(dot(X, Y)) < 1e-3f);
- float3 Z = safe_normalize(cross(X, Y));
+ float3 X = safe_normalize(sd->dPdu);
+ kernel_assert(fabsf(dot(X, Y)) < 1e-3f);
+ float3 Z = safe_normalize(cross(X, Y));
- float3 wo = make_float3(dot(sd->I, X), dot(sd->I, Y), dot(sd->I, Z));
- float3 wi = make_float3(dot(omega_in, X), dot(omega_in, Y), dot(omega_in, Z));
+ float3 wo = make_float3(dot(sd->I, X), dot(sd->I, Y), dot(sd->I, Z));
+ float3 wi = make_float3(dot(omega_in, X), dot(omega_in, Y), dot(omega_in, Z));
- float sin_theta_o = wo.x;
- float cos_theta_o = cos_from_sin(sin_theta_o);
- float phi_o = atan2f(wo.z, wo.y);
+ float sin_theta_o = wo.x;
+ float cos_theta_o = cos_from_sin(sin_theta_o);
+ float phi_o = atan2f(wo.z, wo.y);
- float sin_theta_t = sin_theta_o / bsdf->eta;
- float cos_theta_t = cos_from_sin(sin_theta_t);
+ float sin_theta_t = sin_theta_o / bsdf->eta;
+ float cos_theta_t = cos_from_sin(sin_theta_t);
- float sin_gamma_o = bsdf->extra->geom.w;
- float cos_gamma_o = cos_from_sin(sin_gamma_o);
- float gamma_o = safe_asinf(sin_gamma_o);
+ float sin_gamma_o = bsdf->extra->geom.w;
+ float cos_gamma_o = cos_from_sin(sin_gamma_o);
+ float gamma_o = safe_asinf(sin_gamma_o);
- float sin_gamma_t = sin_gamma_o * cos_theta_o / sqrtf(sqr(bsdf->eta) - sqr(sin_theta_o));
- float cos_gamma_t = cos_from_sin(sin_gamma_t);
- float gamma_t = safe_asinf(sin_gamma_t);
+ float sin_gamma_t = sin_gamma_o * cos_theta_o / sqrtf(sqr(bsdf->eta) - sqr(sin_theta_o));
+ float cos_gamma_t = cos_from_sin(sin_gamma_t);
+ float gamma_t = safe_asinf(sin_gamma_t);
- float3 T = exp3(-bsdf->sigma * (2.0f * cos_gamma_t / cos_theta_t));
- float4 Ap[4];
- hair_attenuation(kg, fresnel_dielectric_cos(cos_theta_o * cos_gamma_o, bsdf->eta), T, Ap);
+ float3 T = exp3(-bsdf->sigma * (2.0f * cos_gamma_t / cos_theta_t));
+ float4 Ap[4];
+ hair_attenuation(kg, fresnel_dielectric_cos(cos_theta_o * cos_gamma_o, bsdf->eta), T, Ap);
- float sin_theta_i = wi.x;
- float cos_theta_i = cos_from_sin(sin_theta_i);
- float phi_i = atan2f(wi.z, wi.y);
+ float sin_theta_i = wi.x;
+ float cos_theta_i = cos_from_sin(sin_theta_i);
+ float phi_i = atan2f(wi.z, wi.y);
- float phi = phi_i - phi_o;
+ float phi = phi_i - phi_o;
- float angles[6];
- hair_alpha_angles(sin_theta_i, cos_theta_i, bsdf->alpha, angles);
+ float angles[6];
+ hair_alpha_angles(sin_theta_i, cos_theta_i, bsdf->alpha, angles);
- float4 F;
- float Mp, Np;
+ float4 F;
+ float Mp, Np;
- /* Primary specular (R). */
- Mp = longitudinal_scattering(angles[0], angles[1], sin_theta_o, cos_theta_o, bsdf->m0_roughness);
- Np = azimuthal_scattering(phi, 0, bsdf->s, gamma_o, gamma_t);
- F = Ap[0] * Mp * Np;
- kernel_assert(isfinite3_safe(float4_to_float3(F)));
+ /* Primary specular (R). */
+ Mp = longitudinal_scattering(angles[0], angles[1], sin_theta_o, cos_theta_o, bsdf->m0_roughness);
+ Np = azimuthal_scattering(phi, 0, bsdf->s, gamma_o, gamma_t);
+ F = Ap[0] * Mp * Np;
+ kernel_assert(isfinite3_safe(float4_to_float3(F)));
- /* Transmission (TT). */
- Mp = longitudinal_scattering(angles[2], angles[3], sin_theta_o, cos_theta_o, 0.25f*bsdf->v);
- Np = azimuthal_scattering(phi, 1, bsdf->s, gamma_o, gamma_t);
- F += Ap[1] * Mp * Np;
- kernel_assert(isfinite3_safe(float4_to_float3(F)));
+ /* Transmission (TT). */
+ Mp = longitudinal_scattering(angles[2], angles[3], sin_theta_o, cos_theta_o, 0.25f * bsdf->v);
+ Np = azimuthal_scattering(phi, 1, bsdf->s, gamma_o, gamma_t);
+ F += Ap[1] * Mp * Np;
+ kernel_assert(isfinite3_safe(float4_to_float3(F)));
- /* Secondary specular (TRT). */
- Mp = longitudinal_scattering(angles[4], angles[5], sin_theta_o, cos_theta_o, 4.0f*bsdf->v);
- Np = azimuthal_scattering(phi, 2, bsdf->s, gamma_o, gamma_t);
- F += Ap[2] * Mp * Np;
- kernel_assert(isfinite3_safe(float4_to_float3(F)));
+ /* Secondary specular (TRT). */
+ Mp = longitudinal_scattering(angles[4], angles[5], sin_theta_o, cos_theta_o, 4.0f * bsdf->v);
+ Np = azimuthal_scattering(phi, 2, bsdf->s, gamma_o, gamma_t);
+ F += Ap[2] * Mp * Np;
+ kernel_assert(isfinite3_safe(float4_to_float3(F)));
- /* Residual component (TRRT+). */
- Mp = longitudinal_scattering(sin_theta_i, cos_theta_i, sin_theta_o, cos_theta_o, 4.0f*bsdf->v);
- Np = M_1_2PI_F;
- F += Ap[3] * Mp * Np;
- kernel_assert(isfinite3_safe(float4_to_float3(F)));
+ /* Residual component (TRRT+). */
+ Mp = longitudinal_scattering(sin_theta_i, cos_theta_i, sin_theta_o, cos_theta_o, 4.0f * bsdf->v);
+ Np = M_1_2PI_F;
+ F += Ap[3] * Mp * Np;
+ kernel_assert(isfinite3_safe(float4_to_float3(F)));
- *pdf = F.w;
- return float4_to_float3(F);
+ *pdf = F.w;
+ return float4_to_float3(F);
}
/* Sampling function for the hair shader. */
@@ -373,130 +367,131 @@ ccl_device int bsdf_principled_hair_sample(KernelGlobals *kg,
float3 *domega_in_dy,
float *pdf)
{
- PrincipledHairBSDF *bsdf = (PrincipledHairBSDF*) sc;
-
- float3 Y = float4_to_float3(bsdf->extra->geom);
-
- float3 X = safe_normalize(sd->dPdu);
- kernel_assert(fabsf(dot(X, Y)) < 1e-3f);
- float3 Z = safe_normalize(cross(X, Y));
-
- float3 wo = make_float3(dot(sd->I, X), dot(sd->I, Y), dot(sd->I, Z));
-
- float2 u[2];
- u[0] = make_float2(randu, randv);
- u[1].x = lcg_step_float_addrspace(&sd->lcg_state);
- u[1].y = lcg_step_float_addrspace(&sd->lcg_state);
-
- float sin_theta_o = wo.x;
- float cos_theta_o = cos_from_sin(sin_theta_o);
- float phi_o = atan2f(wo.z, wo.y);
-
- float sin_theta_t = sin_theta_o / bsdf->eta;
- float cos_theta_t = cos_from_sin(sin_theta_t);
-
- float sin_gamma_o = bsdf->extra->geom.w;
- float cos_gamma_o = cos_from_sin(sin_gamma_o);
- float gamma_o = safe_asinf(sin_gamma_o);
-
- float sin_gamma_t = sin_gamma_o * cos_theta_o / sqrtf(sqr(bsdf->eta) - sqr(sin_theta_o));
- float cos_gamma_t = cos_from_sin(sin_gamma_t);
- float gamma_t = safe_asinf(sin_gamma_t);
-
- float3 T = exp3(-bsdf->sigma * (2.0f * cos_gamma_t / cos_theta_t));
- float4 Ap[4];
- hair_attenuation(kg, fresnel_dielectric_cos(cos_theta_o * cos_gamma_o, bsdf->eta), T, Ap);
-
- int p = 0;
- for(; p < 3; p++) {
- if(u[0].x < Ap[p].w) {
- break;
- }
- u[0].x -= Ap[p].w;
- }
-
- float v = bsdf->v;
- if(p == 1) {
- v *= 0.25f;
- }
- if(p >= 2) {
- v *= 4.0f;
- }
-
- u[1].x = max(u[1].x, 1e-5f);
- float fac = 1.0f + v*logf(u[1].x + (1.0f - u[1].x)*expf(-2.0f/v));
- float sin_theta_i = -fac * sin_theta_o + cos_from_sin(fac) * cosf(M_2PI_F * u[1].y) * cos_theta_o;
- float cos_theta_i = cos_from_sin(sin_theta_i);
-
- float angles[6];
- if(p < 3) {
- hair_alpha_angles(sin_theta_i, cos_theta_i, -bsdf->alpha, angles);
- sin_theta_i = angles[2*p];
- cos_theta_i = angles[2*p+1];
- }
-
- float phi;
- if(p < 3) {
- phi = delta_phi(p, gamma_o, gamma_t) + sample_trimmed_logistic(u[0].y, bsdf->s);
- }
- else {
- phi = M_2PI_F*u[0].y;
- }
- float phi_i = phi_o + phi;
-
- hair_alpha_angles(sin_theta_i, cos_theta_i, bsdf->alpha, angles);
-
- float4 F;
- float Mp, Np;
-
- /* Primary specular (R). */
- Mp = longitudinal_scattering(angles[0], angles[1], sin_theta_o, cos_theta_o, bsdf->m0_roughness);
- Np = azimuthal_scattering(phi, 0, bsdf->s, gamma_o, gamma_t);
- F = Ap[0] * Mp * Np;
- kernel_assert(isfinite3_safe(float4_to_float3(F)));
-
- /* Transmission (TT). */
- Mp = longitudinal_scattering(angles[2], angles[3], sin_theta_o, cos_theta_o, 0.25f*bsdf->v);
- Np = azimuthal_scattering(phi, 1, bsdf->s, gamma_o, gamma_t);
- F += Ap[1] * Mp * Np;
- kernel_assert(isfinite3_safe(float4_to_float3(F)));
-
- /* Secondary specular (TRT). */
- Mp = longitudinal_scattering(angles[4], angles[5], sin_theta_o, cos_theta_o, 4.0f*bsdf->v);
- Np = azimuthal_scattering(phi, 2, bsdf->s, gamma_o, gamma_t);
- F += Ap[2] * Mp * Np;
- kernel_assert(isfinite3_safe(float4_to_float3(F)));
-
- /* Residual component (TRRT+). */
- Mp = longitudinal_scattering(sin_theta_i, cos_theta_i, sin_theta_o, cos_theta_o, 4.0f*bsdf->v);
- Np = M_1_2PI_F;
- F += Ap[3] * Mp * Np;
- kernel_assert(isfinite3_safe(float4_to_float3(F)));
-
- *eval = float4_to_float3(F);
- *pdf = F.w;
-
- *omega_in = X*sin_theta_i + Y*cos_theta_i*cosf(phi_i) + Z*cos_theta_i*sinf(phi_i);
-
-#ifdef __RAY_DIFFERENTIALS__
- float3 N = safe_normalize(sd->I + *omega_in);
- *domega_in_dx = (2 * dot(N, sd->dI.dx)) * N - sd->dI.dx;
- *domega_in_dy = (2 * dot(N, sd->dI.dy)) * N - sd->dI.dy;
-#endif
-
- return LABEL_GLOSSY|((p == 0)? LABEL_REFLECT : LABEL_TRANSMIT);
+ PrincipledHairBSDF *bsdf = (PrincipledHairBSDF *)sc;
+
+ float3 Y = float4_to_float3(bsdf->extra->geom);
+
+ float3 X = safe_normalize(sd->dPdu);
+ kernel_assert(fabsf(dot(X, Y)) < 1e-3f);
+ float3 Z = safe_normalize(cross(X, Y));
+
+ float3 wo = make_float3(dot(sd->I, X), dot(sd->I, Y), dot(sd->I, Z));
+
+ float2 u[2];
+ u[0] = make_float2(randu, randv);
+ u[1].x = lcg_step_float_addrspace(&sd->lcg_state);
+ u[1].y = lcg_step_float_addrspace(&sd->lcg_state);
+
+ float sin_theta_o = wo.x;
+ float cos_theta_o = cos_from_sin(sin_theta_o);
+ float phi_o = atan2f(wo.z, wo.y);
+
+ float sin_theta_t = sin_theta_o / bsdf->eta;
+ float cos_theta_t = cos_from_sin(sin_theta_t);
+
+ float sin_gamma_o = bsdf->extra->geom.w;
+ float cos_gamma_o = cos_from_sin(sin_gamma_o);
+ float gamma_o = safe_asinf(sin_gamma_o);
+
+ float sin_gamma_t = sin_gamma_o * cos_theta_o / sqrtf(sqr(bsdf->eta) - sqr(sin_theta_o));
+ float cos_gamma_t = cos_from_sin(sin_gamma_t);
+ float gamma_t = safe_asinf(sin_gamma_t);
+
+ float3 T = exp3(-bsdf->sigma * (2.0f * cos_gamma_t / cos_theta_t));
+ float4 Ap[4];
+ hair_attenuation(kg, fresnel_dielectric_cos(cos_theta_o * cos_gamma_o, bsdf->eta), T, Ap);
+
+ int p = 0;
+ for (; p < 3; p++) {
+ if (u[0].x < Ap[p].w) {
+ break;
+ }
+ u[0].x -= Ap[p].w;
+ }
+
+ float v = bsdf->v;
+ if (p == 1) {
+ v *= 0.25f;
+ }
+ if (p >= 2) {
+ v *= 4.0f;
+ }
+
+ u[1].x = max(u[1].x, 1e-5f);
+ float fac = 1.0f + v * logf(u[1].x + (1.0f - u[1].x) * expf(-2.0f / v));
+ float sin_theta_i = -fac * sin_theta_o +
+ cos_from_sin(fac) * cosf(M_2PI_F * u[1].y) * cos_theta_o;
+ float cos_theta_i = cos_from_sin(sin_theta_i);
+
+ float angles[6];
+ if (p < 3) {
+ hair_alpha_angles(sin_theta_i, cos_theta_i, -bsdf->alpha, angles);
+ sin_theta_i = angles[2 * p];
+ cos_theta_i = angles[2 * p + 1];
+ }
+
+ float phi;
+ if (p < 3) {
+ phi = delta_phi(p, gamma_o, gamma_t) + sample_trimmed_logistic(u[0].y, bsdf->s);
+ }
+ else {
+ phi = M_2PI_F * u[0].y;
+ }
+ float phi_i = phi_o + phi;
+
+ hair_alpha_angles(sin_theta_i, cos_theta_i, bsdf->alpha, angles);
+
+ float4 F;
+ float Mp, Np;
+
+ /* Primary specular (R). */
+ Mp = longitudinal_scattering(angles[0], angles[1], sin_theta_o, cos_theta_o, bsdf->m0_roughness);
+ Np = azimuthal_scattering(phi, 0, bsdf->s, gamma_o, gamma_t);
+ F = Ap[0] * Mp * Np;
+ kernel_assert(isfinite3_safe(float4_to_float3(F)));
+
+ /* Transmission (TT). */
+ Mp = longitudinal_scattering(angles[2], angles[3], sin_theta_o, cos_theta_o, 0.25f * bsdf->v);
+ Np = azimuthal_scattering(phi, 1, bsdf->s, gamma_o, gamma_t);
+ F += Ap[1] * Mp * Np;
+ kernel_assert(isfinite3_safe(float4_to_float3(F)));
+
+ /* Secondary specular (TRT). */
+ Mp = longitudinal_scattering(angles[4], angles[5], sin_theta_o, cos_theta_o, 4.0f * bsdf->v);
+ Np = azimuthal_scattering(phi, 2, bsdf->s, gamma_o, gamma_t);
+ F += Ap[2] * Mp * Np;
+ kernel_assert(isfinite3_safe(float4_to_float3(F)));
+
+ /* Residual component (TRRT+). */
+ Mp = longitudinal_scattering(sin_theta_i, cos_theta_i, sin_theta_o, cos_theta_o, 4.0f * bsdf->v);
+ Np = M_1_2PI_F;
+ F += Ap[3] * Mp * Np;
+ kernel_assert(isfinite3_safe(float4_to_float3(F)));
+
+ *eval = float4_to_float3(F);
+ *pdf = F.w;
+
+ *omega_in = X * sin_theta_i + Y * cos_theta_i * cosf(phi_i) + Z * cos_theta_i * sinf(phi_i);
+
+# ifdef __RAY_DIFFERENTIALS__
+ float3 N = safe_normalize(sd->I + *omega_in);
+ *domega_in_dx = (2 * dot(N, sd->dI.dx)) * N - sd->dI.dx;
+ *domega_in_dy = (2 * dot(N, sd->dI.dy)) * N - sd->dI.dy;
+# endif
+
+ return LABEL_GLOSSY | ((p == 0) ? LABEL_REFLECT : LABEL_TRANSMIT);
}
/* Implements Filter Glossy by capping the effective roughness. */
ccl_device void bsdf_principled_hair_blur(ShaderClosure *sc, float roughness)
{
- PrincipledHairBSDF *bsdf = (PrincipledHairBSDF*)sc;
+ PrincipledHairBSDF *bsdf = (PrincipledHairBSDF *)sc;
- bsdf->v = fmaxf(roughness, bsdf->v);
- bsdf->s = fmaxf(roughness, bsdf->s);
- bsdf->m0_roughness = fmaxf(roughness, bsdf->m0_roughness);
+ bsdf->v = fmaxf(roughness, bsdf->v);
+ bsdf->s = fmaxf(roughness, bsdf->s);
+ bsdf->m0_roughness = fmaxf(roughness, bsdf->m0_roughness);
}
CCL_NAMESPACE_END
-#endif /* __BSDF_HAIR_PRINCIPLED_H__ */
+#endif /* __BSDF_HAIR_PRINCIPLED_H__ */
diff --git a/intern/cycles/kernel/closure/bsdf_microfacet.h b/intern/cycles/kernel/closure/bsdf_microfacet.h
index 32b6e50b09a..b4da3123f28 100644
--- a/intern/cycles/kernel/closure/bsdf_microfacet.h
+++ b/intern/cycles/kernel/closure/bsdf_microfacet.h
@@ -36,95 +36,98 @@
CCL_NAMESPACE_BEGIN
typedef ccl_addr_space struct MicrofacetExtra {
- float3 color, cspec0;
- float clearcoat;
+ float3 color, cspec0;
+ float clearcoat;
} MicrofacetExtra;
typedef ccl_addr_space struct MicrofacetBsdf {
- SHADER_CLOSURE_BASE;
+ SHADER_CLOSURE_BASE;
- float alpha_x, alpha_y, ior;
- MicrofacetExtra *extra;
- float3 T;
+ float alpha_x, alpha_y, ior;
+ MicrofacetExtra *extra;
+ float3 T;
} MicrofacetBsdf;
/* Beckmann and GGX microfacet importance sampling. */
-ccl_device_inline void microfacet_beckmann_sample_slopes(
- KernelGlobals *kg,
- const float cos_theta_i, const float sin_theta_i,
- float randu, float randv, float *slope_x, float *slope_y,
- float *G1i)
+ccl_device_inline void microfacet_beckmann_sample_slopes(KernelGlobals *kg,
+ const float cos_theta_i,
+ const float sin_theta_i,
+ float randu,
+ float randv,
+ float *slope_x,
+ float *slope_y,
+ float *G1i)
{
- /* special case (normal incidence) */
- if(cos_theta_i >= 0.99999f) {
- const float r = sqrtf(-logf(randu));
- const float phi = M_2PI_F * randv;
- *slope_x = r * cosf(phi);
- *slope_y = r * sinf(phi);
- *G1i = 1.0f;
- return;
- }
-
- /* precomputations */
- const float tan_theta_i = sin_theta_i/cos_theta_i;
- const float inv_a = tan_theta_i;
- const float cot_theta_i = 1.0f/tan_theta_i;
- const float erf_a = fast_erff(cot_theta_i);
- const float exp_a2 = expf(-cot_theta_i*cot_theta_i);
- const float SQRT_PI_INV = 0.56418958354f;
- const float Lambda = 0.5f*(erf_a - 1.0f) + (0.5f*SQRT_PI_INV)*(exp_a2*inv_a);
- const float G1 = 1.0f/(1.0f + Lambda); /* masking */
-
- *G1i = G1;
+ /* special case (normal incidence) */
+ if (cos_theta_i >= 0.99999f) {
+ const float r = sqrtf(-logf(randu));
+ const float phi = M_2PI_F * randv;
+ *slope_x = r * cosf(phi);
+ *slope_y = r * sinf(phi);
+ *G1i = 1.0f;
+ return;
+ }
+
+ /* precomputations */
+ const float tan_theta_i = sin_theta_i / cos_theta_i;
+ const float inv_a = tan_theta_i;
+ const float cot_theta_i = 1.0f / tan_theta_i;
+ const float erf_a = fast_erff(cot_theta_i);
+ const float exp_a2 = expf(-cot_theta_i * cot_theta_i);
+ const float SQRT_PI_INV = 0.56418958354f;
+ const float Lambda = 0.5f * (erf_a - 1.0f) + (0.5f * SQRT_PI_INV) * (exp_a2 * inv_a);
+ const float G1 = 1.0f / (1.0f + Lambda); /* masking */
+
+ *G1i = G1;
#if defined(__KERNEL_GPU__)
- /* Based on paper from Wenzel Jakob
- * An Improved Visible Normal Sampling Routine for the Beckmann Distribution
- *
- * http://www.mitsuba-renderer.org/~wenzel/files/visnormal.pdf
- *
- * Reformulation from OpenShadingLanguage which avoids using inverse
- * trigonometric functions.
- */
-
- /* Sample slope X.
- *
- * Compute a coarse approximation using the approximation:
- * exp(-ierf(x)^2) ~= 1 - x * x
- * solve y = 1 + b + K * (1 - b * b)
- */
- float K = tan_theta_i * SQRT_PI_INV;
- float y_approx = randu * (1.0f + erf_a + K * (1 - erf_a * erf_a));
- float y_exact = randu * (1.0f + erf_a + K * exp_a2);
- float b = K > 0 ? (0.5f - sqrtf(K * (K - y_approx + 1.0f) + 0.25f)) / K : y_approx - 1.0f;
-
- /* Perform newton step to refine toward the true root. */
- float inv_erf = fast_ierff(b);
- float value = 1.0f + b + K * expf(-inv_erf * inv_erf) - y_exact;
- /* Check if we are close enough already,
- * this also avoids NaNs as we get close to the root.
- */
- if(fabsf(value) > 1e-6f) {
- b -= value / (1.0f - inv_erf * tan_theta_i); /* newton step 1. */
- inv_erf = fast_ierff(b);
- value = 1.0f + b + K * expf(-inv_erf * inv_erf) - y_exact;
- b -= value / (1.0f - inv_erf * tan_theta_i); /* newton step 2. */
- /* Compute the slope from the refined value. */
- *slope_x = fast_ierff(b);
- }
- else {
- /* We are close enough already. */
- *slope_x = inv_erf;
- }
- *slope_y = fast_ierff(2.0f*randv - 1.0f);
+ /* Based on paper from Wenzel Jakob
+ * An Improved Visible Normal Sampling Routine for the Beckmann Distribution
+ *
+ * http://www.mitsuba-renderer.org/~wenzel/files/visnormal.pdf
+ *
+ * Reformulation from OpenShadingLanguage which avoids using inverse
+ * trigonometric functions.
+ */
+
+ /* Sample slope X.
+ *
+ * Compute a coarse approximation using the approximation:
+ * exp(-ierf(x)^2) ~= 1 - x * x
+ * solve y = 1 + b + K * (1 - b * b)
+ */
+ float K = tan_theta_i * SQRT_PI_INV;
+ float y_approx = randu * (1.0f + erf_a + K * (1 - erf_a * erf_a));
+ float y_exact = randu * (1.0f + erf_a + K * exp_a2);
+ float b = K > 0 ? (0.5f - sqrtf(K * (K - y_approx + 1.0f) + 0.25f)) / K : y_approx - 1.0f;
+
+ /* Perform newton step to refine toward the true root. */
+ float inv_erf = fast_ierff(b);
+ float value = 1.0f + b + K * expf(-inv_erf * inv_erf) - y_exact;
+ /* Check if we are close enough already,
+ * this also avoids NaNs as we get close to the root.
+ */
+ if (fabsf(value) > 1e-6f) {
+ b -= value / (1.0f - inv_erf * tan_theta_i); /* newton step 1. */
+ inv_erf = fast_ierff(b);
+ value = 1.0f + b + K * expf(-inv_erf * inv_erf) - y_exact;
+ b -= value / (1.0f - inv_erf * tan_theta_i); /* newton step 2. */
+ /* Compute the slope from the refined value. */
+ *slope_x = fast_ierff(b);
+ }
+ else {
+ /* We are close enough already. */
+ *slope_x = inv_erf;
+ }
+ *slope_y = fast_ierff(2.0f * randv - 1.0f);
#else
- /* Use precomputed table on CPU, it gives better perfomance. */
- int beckmann_table_offset = kernel_data.tables.beckmann_offset;
+ /* Use precomputed table on CPU, it gives better perfomance. */
+ int beckmann_table_offset = kernel_data.tables.beckmann_offset;
- *slope_x = lookup_table_read_2D(kg, randu, cos_theta_i,
- beckmann_table_offset, BECKMANN_TABLE_SIZE, BECKMANN_TABLE_SIZE);
- *slope_y = fast_ierff(2.0f*randv - 1.0f);
+ *slope_x = lookup_table_read_2D(
+ kg, randu, cos_theta_i, beckmann_table_offset, BECKMANN_TABLE_SIZE, BECKMANN_TABLE_SIZE);
+ *slope_y = fast_ierff(2.0f * randv - 1.0f);
#endif
}
@@ -134,103 +137,109 @@ ccl_device_inline void microfacet_beckmann_sample_slopes(
* E. Heitz and E. d'Eon, EGSR 2014
*/
-ccl_device_inline void microfacet_ggx_sample_slopes(
- const float cos_theta_i, const float sin_theta_i,
- float randu, float randv, float *slope_x, float *slope_y,
- float *G1i)
+ccl_device_inline void microfacet_ggx_sample_slopes(const float cos_theta_i,
+ const float sin_theta_i,
+ float randu,
+ float randv,
+ float *slope_x,
+ float *slope_y,
+ float *G1i)
{
- /* special case (normal incidence) */
- if(cos_theta_i >= 0.99999f) {
- const float r = sqrtf(randu/(1.0f - randu));
- const float phi = M_2PI_F * randv;
- *slope_x = r * cosf(phi);
- *slope_y = r * sinf(phi);
- *G1i = 1.0f;
-
- return;
- }
-
- /* precomputations */
- const float tan_theta_i = sin_theta_i/cos_theta_i;
- const float G1_inv = 0.5f * (1.0f + safe_sqrtf(1.0f + tan_theta_i*tan_theta_i));
-
- *G1i = 1.0f/G1_inv;
-
- /* sample slope_x */
- const float A = 2.0f*randu*G1_inv - 1.0f;
- const float AA = A*A;
- const float tmp = 1.0f/(AA - 1.0f);
- const float B = tan_theta_i;
- const float BB = B*B;
- const float D = safe_sqrtf(BB*(tmp*tmp) - (AA - BB)*tmp);
- const float slope_x_1 = B*tmp - D;
- const float slope_x_2 = B*tmp + D;
- *slope_x = (A < 0.0f || slope_x_2*tan_theta_i > 1.0f)? slope_x_1: slope_x_2;
-
- /* sample slope_y */
- float S;
-
- if(randv > 0.5f) {
- S = 1.0f;
- randv = 2.0f*(randv - 0.5f);
- }
- else {
- S = -1.0f;
- randv = 2.0f*(0.5f - randv);
- }
-
- const float z = (randv*(randv*(randv*0.27385f - 0.73369f) + 0.46341f)) / (randv*(randv*(randv*0.093073f + 0.309420f) - 1.000000f) + 0.597999f);
- *slope_y = S * z * safe_sqrtf(1.0f + (*slope_x)*(*slope_x));
+ /* special case (normal incidence) */
+ if (cos_theta_i >= 0.99999f) {
+ const float r = sqrtf(randu / (1.0f - randu));
+ const float phi = M_2PI_F * randv;
+ *slope_x = r * cosf(phi);
+ *slope_y = r * sinf(phi);
+ *G1i = 1.0f;
+
+ return;
+ }
+
+ /* precomputations */
+ const float tan_theta_i = sin_theta_i / cos_theta_i;
+ const float G1_inv = 0.5f * (1.0f + safe_sqrtf(1.0f + tan_theta_i * tan_theta_i));
+
+ *G1i = 1.0f / G1_inv;
+
+ /* sample slope_x */
+ const float A = 2.0f * randu * G1_inv - 1.0f;
+ const float AA = A * A;
+ const float tmp = 1.0f / (AA - 1.0f);
+ const float B = tan_theta_i;
+ const float BB = B * B;
+ const float D = safe_sqrtf(BB * (tmp * tmp) - (AA - BB) * tmp);
+ const float slope_x_1 = B * tmp - D;
+ const float slope_x_2 = B * tmp + D;
+ *slope_x = (A < 0.0f || slope_x_2 * tan_theta_i > 1.0f) ? slope_x_1 : slope_x_2;
+
+ /* sample slope_y */
+ float S;
+
+ if (randv > 0.5f) {
+ S = 1.0f;
+ randv = 2.0f * (randv - 0.5f);
+ }
+ else {
+ S = -1.0f;
+ randv = 2.0f * (0.5f - randv);
+ }
+
+ const float z = (randv * (randv * (randv * 0.27385f - 0.73369f) + 0.46341f)) /
+ (randv * (randv * (randv * 0.093073f + 0.309420f) - 1.000000f) + 0.597999f);
+ *slope_y = S * z * safe_sqrtf(1.0f + (*slope_x) * (*slope_x));
}
-ccl_device_forceinline float3 microfacet_sample_stretched(
- KernelGlobals *kg, const float3 omega_i,
- const float alpha_x, const float alpha_y,
- const float randu, const float randv,
- bool beckmann, float *G1i)
+ccl_device_forceinline float3 microfacet_sample_stretched(KernelGlobals *kg,
+ const float3 omega_i,
+ const float alpha_x,
+ const float alpha_y,
+ const float randu,
+ const float randv,
+ bool beckmann,
+ float *G1i)
{
- /* 1. stretch omega_i */
- float3 omega_i_ = make_float3(alpha_x * omega_i.x, alpha_y * omega_i.y, omega_i.z);
- omega_i_ = normalize(omega_i_);
-
- /* get polar coordinates of omega_i_ */
- float costheta_ = 1.0f;
- float sintheta_ = 0.0f;
- float cosphi_ = 1.0f;
- float sinphi_ = 0.0f;
-
- if(omega_i_.z < 0.99999f) {
- costheta_ = omega_i_.z;
- sintheta_ = safe_sqrtf(1.0f - costheta_*costheta_);
-
- float invlen = 1.0f/sintheta_;
- cosphi_ = omega_i_.x * invlen;
- sinphi_ = omega_i_.y * invlen;
- }
-
- /* 2. sample P22_{omega_i}(x_slope, y_slope, 1, 1) */
- float slope_x, slope_y;
-
- if(beckmann) {
- microfacet_beckmann_sample_slopes(kg, costheta_, sintheta_,
- randu, randv, &slope_x, &slope_y, G1i);
- }
- else {
- microfacet_ggx_sample_slopes(costheta_, sintheta_,
- randu, randv, &slope_x, &slope_y, G1i);
- }
-
- /* 3. rotate */
- float tmp = cosphi_*slope_x - sinphi_*slope_y;
- slope_y = sinphi_*slope_x + cosphi_*slope_y;
- slope_x = tmp;
-
- /* 4. unstretch */
- slope_x = alpha_x * slope_x;
- slope_y = alpha_y * slope_y;
-
- /* 5. compute normal */
- return normalize(make_float3(-slope_x, -slope_y, 1.0f));
+ /* 1. stretch omega_i */
+ float3 omega_i_ = make_float3(alpha_x * omega_i.x, alpha_y * omega_i.y, omega_i.z);
+ omega_i_ = normalize(omega_i_);
+
+ /* get polar coordinates of omega_i_ */
+ float costheta_ = 1.0f;
+ float sintheta_ = 0.0f;
+ float cosphi_ = 1.0f;
+ float sinphi_ = 0.0f;
+
+ if (omega_i_.z < 0.99999f) {
+ costheta_ = omega_i_.z;
+ sintheta_ = safe_sqrtf(1.0f - costheta_ * costheta_);
+
+ float invlen = 1.0f / sintheta_;
+ cosphi_ = omega_i_.x * invlen;
+ sinphi_ = omega_i_.y * invlen;
+ }
+
+ /* 2. sample P22_{omega_i}(x_slope, y_slope, 1, 1) */
+ float slope_x, slope_y;
+
+ if (beckmann) {
+ microfacet_beckmann_sample_slopes(
+ kg, costheta_, sintheta_, randu, randv, &slope_x, &slope_y, G1i);
+ }
+ else {
+ microfacet_ggx_sample_slopes(costheta_, sintheta_, randu, randv, &slope_x, &slope_y, G1i);
+ }
+
+ /* 3. rotate */
+ float tmp = cosphi_ * slope_x - sinphi_ * slope_y;
+ slope_y = sinphi_ * slope_x + cosphi_ * slope_y;
+ slope_x = tmp;
+
+ /* 4. unstretch */
+ slope_x = alpha_x * slope_x;
+ slope_y = alpha_y * slope_y;
+
+ /* 5. compute normal */
+ return normalize(make_float3(-slope_x, -slope_y, 1.0f));
}
/* Calculate the reflection color
@@ -240,27 +249,29 @@ ccl_device_forceinline float3 microfacet_sample_stretched(
*
* Else it is simply white
*/
-ccl_device_forceinline float3 reflection_color(const MicrofacetBsdf *bsdf, float3 L, float3 H) {
- float3 F = make_float3(1.0f, 1.0f, 1.0f);
- bool use_fresnel = (bsdf->type == CLOSURE_BSDF_MICROFACET_GGX_FRESNEL_ID
- || bsdf->type == CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_ID
- || bsdf->type == CLOSURE_BSDF_MICROFACET_GGX_ANISO_FRESNEL_ID);
+ccl_device_forceinline float3 reflection_color(const MicrofacetBsdf *bsdf, float3 L, float3 H)
+{
+ float3 F = make_float3(1.0f, 1.0f, 1.0f);
+ bool use_fresnel = (bsdf->type == CLOSURE_BSDF_MICROFACET_GGX_FRESNEL_ID ||
+ bsdf->type == CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_ID ||
+ bsdf->type == CLOSURE_BSDF_MICROFACET_GGX_ANISO_FRESNEL_ID);
- if(use_fresnel) {
- float F0 = fresnel_dielectric_cos(1.0f, bsdf->ior);
+ if (use_fresnel) {
+ float F0 = fresnel_dielectric_cos(1.0f, bsdf->ior);
- F = interpolate_fresnel_color(L, H, bsdf->ior, F0, bsdf->extra->cspec0);
- }
+ F = interpolate_fresnel_color(L, H, bsdf->ior, F0, bsdf->extra->cspec0);
+ }
- return F;
+ return F;
}
ccl_device_forceinline float D_GTR1(float NdotH, float alpha)
{
- if(alpha >= 1.0f) return M_1_PI_F;
- float alpha2 = alpha*alpha;
- float t = 1.0f + (alpha2 - 1.0f) * NdotH*NdotH;
- return (alpha2 - 1.0f) / (M_PI_F * logf(alpha2) * t);
+ if (alpha >= 1.0f)
+ return M_1_PI_F;
+ float alpha2 = alpha * alpha;
+ float t = 1.0f + (alpha2 - 1.0f) * NdotH * NdotH;
+ return (alpha2 - 1.0f) / (M_PI_F * logf(alpha2) * t);
}
/* GGX microfacet with Smith shadow-masking from:
@@ -278,483 +289,511 @@ ccl_device_forceinline float D_GTR1(float NdotH, float alpha)
ccl_device int bsdf_microfacet_ggx_setup(MicrofacetBsdf *bsdf)
{
- bsdf->extra = NULL;
+ bsdf->extra = NULL;
- bsdf->alpha_x = saturate(bsdf->alpha_x);
- bsdf->alpha_y = bsdf->alpha_x;
+ bsdf->alpha_x = saturate(bsdf->alpha_x);
+ bsdf->alpha_y = bsdf->alpha_x;
- bsdf->type = CLOSURE_BSDF_MICROFACET_GGX_ID;
+ bsdf->type = CLOSURE_BSDF_MICROFACET_GGX_ID;
- return SD_BSDF|SD_BSDF_HAS_EVAL;
+ return SD_BSDF | SD_BSDF_HAS_EVAL;
}
ccl_device int bsdf_microfacet_ggx_fresnel_setup(MicrofacetBsdf *bsdf, const ShaderData *sd)
{
- bsdf->extra->cspec0.x = saturate(bsdf->extra->cspec0.x);
- bsdf->extra->cspec0.y = saturate(bsdf->extra->cspec0.y);
- bsdf->extra->cspec0.z = saturate(bsdf->extra->cspec0.z);
+ bsdf->extra->cspec0.x = saturate(bsdf->extra->cspec0.x);
+ bsdf->extra->cspec0.y = saturate(bsdf->extra->cspec0.y);
+ bsdf->extra->cspec0.z = saturate(bsdf->extra->cspec0.z);
- float F0 = fresnel_dielectric_cos(1.0f, bsdf->ior);
- float F = average(interpolate_fresnel_color(sd->I, bsdf->N, bsdf->ior, F0, bsdf->extra->cspec0));
- bsdf->sample_weight *= F;
+ float F0 = fresnel_dielectric_cos(1.0f, bsdf->ior);
+ float F = average(interpolate_fresnel_color(sd->I, bsdf->N, bsdf->ior, F0, bsdf->extra->cspec0));
+ bsdf->sample_weight *= F;
- bsdf->alpha_x = saturate(bsdf->alpha_x);
- bsdf->alpha_y = bsdf->alpha_x;
+ bsdf->alpha_x = saturate(bsdf->alpha_x);
+ bsdf->alpha_y = bsdf->alpha_x;
- bsdf->type = CLOSURE_BSDF_MICROFACET_GGX_FRESNEL_ID;
+ bsdf->type = CLOSURE_BSDF_MICROFACET_GGX_FRESNEL_ID;
- return SD_BSDF|SD_BSDF_HAS_EVAL;
+ return SD_BSDF | SD_BSDF_HAS_EVAL;
}
ccl_device int bsdf_microfacet_ggx_clearcoat_setup(MicrofacetBsdf *bsdf, const ShaderData *sd)
{
- bsdf->extra->cspec0.x = saturate(bsdf->extra->cspec0.x);
- bsdf->extra->cspec0.y = saturate(bsdf->extra->cspec0.y);
- bsdf->extra->cspec0.z = saturate(bsdf->extra->cspec0.z);
+ bsdf->extra->cspec0.x = saturate(bsdf->extra->cspec0.x);
+ bsdf->extra->cspec0.y = saturate(bsdf->extra->cspec0.y);
+ bsdf->extra->cspec0.z = saturate(bsdf->extra->cspec0.z);
- float F0 = fresnel_dielectric_cos(1.0f, bsdf->ior);
- float F = average(interpolate_fresnel_color(sd->I, bsdf->N, bsdf->ior, F0, bsdf->extra->cspec0));
- bsdf->sample_weight *= 0.25f * bsdf->extra->clearcoat * F;
+ float F0 = fresnel_dielectric_cos(1.0f, bsdf->ior);
+ float F = average(interpolate_fresnel_color(sd->I, bsdf->N, bsdf->ior, F0, bsdf->extra->cspec0));
+ bsdf->sample_weight *= 0.25f * bsdf->extra->clearcoat * F;
- bsdf->alpha_x = saturate(bsdf->alpha_x);
- bsdf->alpha_y = bsdf->alpha_x;
+ bsdf->alpha_x = saturate(bsdf->alpha_x);
+ bsdf->alpha_y = bsdf->alpha_x;
- bsdf->type = CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_ID;
+ bsdf->type = CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_ID;
- return SD_BSDF|SD_BSDF_HAS_EVAL;
+ return SD_BSDF | SD_BSDF_HAS_EVAL;
}
ccl_device bool bsdf_microfacet_merge(const ShaderClosure *a, const ShaderClosure *b)
{
- const MicrofacetBsdf *bsdf_a = (const MicrofacetBsdf*)a;
- const MicrofacetBsdf *bsdf_b = (const MicrofacetBsdf*)b;
-
- return (isequal_float3(bsdf_a->N, bsdf_b->N)) &&
- (bsdf_a->alpha_x == bsdf_b->alpha_x) &&
- (bsdf_a->alpha_y == bsdf_b->alpha_y) &&
- (isequal_float3(bsdf_a->T, bsdf_b->T)) &&
- (bsdf_a->ior == bsdf_b->ior) &&
- ((bsdf_a->extra == NULL && bsdf_b->extra == NULL) ||
- ((bsdf_a->extra && bsdf_b->extra) &&
- (isequal_float3(bsdf_a->extra->color, bsdf_b->extra->color)) &&
- (isequal_float3(bsdf_a->extra->cspec0, bsdf_b->extra->cspec0)) &&
- (bsdf_a->extra->clearcoat == bsdf_b->extra->clearcoat)));
+ const MicrofacetBsdf *bsdf_a = (const MicrofacetBsdf *)a;
+ const MicrofacetBsdf *bsdf_b = (const MicrofacetBsdf *)b;
+
+ return (isequal_float3(bsdf_a->N, bsdf_b->N)) && (bsdf_a->alpha_x == bsdf_b->alpha_x) &&
+ (bsdf_a->alpha_y == bsdf_b->alpha_y) && (isequal_float3(bsdf_a->T, bsdf_b->T)) &&
+ (bsdf_a->ior == bsdf_b->ior) &&
+ ((bsdf_a->extra == NULL && bsdf_b->extra == NULL) ||
+ ((bsdf_a->extra && bsdf_b->extra) &&
+ (isequal_float3(bsdf_a->extra->color, bsdf_b->extra->color)) &&
+ (isequal_float3(bsdf_a->extra->cspec0, bsdf_b->extra->cspec0)) &&
+ (bsdf_a->extra->clearcoat == bsdf_b->extra->clearcoat)));
}
ccl_device int bsdf_microfacet_ggx_aniso_setup(MicrofacetBsdf *bsdf)
{
- bsdf->extra = NULL;
+ bsdf->extra = NULL;
- bsdf->alpha_x = saturate(bsdf->alpha_x);
- bsdf->alpha_y = saturate(bsdf->alpha_y);
+ bsdf->alpha_x = saturate(bsdf->alpha_x);
+ bsdf->alpha_y = saturate(bsdf->alpha_y);
- bsdf->type = CLOSURE_BSDF_MICROFACET_GGX_ANISO_ID;
+ bsdf->type = CLOSURE_BSDF_MICROFACET_GGX_ANISO_ID;
- return SD_BSDF|SD_BSDF_HAS_EVAL;
+ return SD_BSDF | SD_BSDF_HAS_EVAL;
}
ccl_device int bsdf_microfacet_ggx_aniso_fresnel_setup(MicrofacetBsdf *bsdf, const ShaderData *sd)
{
- bsdf->extra->cspec0.x = saturate(bsdf->extra->cspec0.x);
- bsdf->extra->cspec0.y = saturate(bsdf->extra->cspec0.y);
- bsdf->extra->cspec0.z = saturate(bsdf->extra->cspec0.z);
+ bsdf->extra->cspec0.x = saturate(bsdf->extra->cspec0.x);
+ bsdf->extra->cspec0.y = saturate(bsdf->extra->cspec0.y);
+ bsdf->extra->cspec0.z = saturate(bsdf->extra->cspec0.z);
- float F0 = fresnel_dielectric_cos(1.0f, bsdf->ior);
- float F = average(interpolate_fresnel_color(sd->I, bsdf->N, bsdf->ior, F0, bsdf->extra->cspec0));
- bsdf->sample_weight *= F;
+ float F0 = fresnel_dielectric_cos(1.0f, bsdf->ior);
+ float F = average(interpolate_fresnel_color(sd->I, bsdf->N, bsdf->ior, F0, bsdf->extra->cspec0));
+ bsdf->sample_weight *= F;
- bsdf->alpha_x = saturate(bsdf->alpha_x);
- bsdf->alpha_y = saturate(bsdf->alpha_y);
+ bsdf->alpha_x = saturate(bsdf->alpha_x);
+ bsdf->alpha_y = saturate(bsdf->alpha_y);
- bsdf->type = CLOSURE_BSDF_MICROFACET_GGX_ANISO_FRESNEL_ID;
+ bsdf->type = CLOSURE_BSDF_MICROFACET_GGX_ANISO_FRESNEL_ID;
- return SD_BSDF|SD_BSDF_HAS_EVAL;
+ return SD_BSDF | SD_BSDF_HAS_EVAL;
}
ccl_device int bsdf_microfacet_ggx_refraction_setup(MicrofacetBsdf *bsdf)
{
- bsdf->extra = NULL;
+ bsdf->extra = NULL;
- bsdf->alpha_x = saturate(bsdf->alpha_x);
- bsdf->alpha_y = bsdf->alpha_x;
+ bsdf->alpha_x = saturate(bsdf->alpha_x);
+ bsdf->alpha_y = bsdf->alpha_x;
- bsdf->type = CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID;
+ bsdf->type = CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID;
- return SD_BSDF|SD_BSDF_HAS_EVAL;
+ return SD_BSDF | SD_BSDF_HAS_EVAL;
}
ccl_device void bsdf_microfacet_ggx_blur(ShaderClosure *sc, float roughness)
{
- MicrofacetBsdf *bsdf = (MicrofacetBsdf*)sc;
+ MicrofacetBsdf *bsdf = (MicrofacetBsdf *)sc;
- bsdf->alpha_x = fmaxf(roughness, bsdf->alpha_x);
- bsdf->alpha_y = fmaxf(roughness, bsdf->alpha_y);
+ bsdf->alpha_x = fmaxf(roughness, bsdf->alpha_x);
+ bsdf->alpha_y = fmaxf(roughness, bsdf->alpha_y);
}
-ccl_device float3 bsdf_microfacet_ggx_eval_reflect(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf)
+ccl_device float3 bsdf_microfacet_ggx_eval_reflect(const ShaderClosure *sc,
+ const float3 I,
+ const float3 omega_in,
+ float *pdf)
{
- const MicrofacetBsdf *bsdf = (const MicrofacetBsdf*)sc;
- float alpha_x = bsdf->alpha_x;
- float alpha_y = bsdf->alpha_y;
- bool m_refractive = bsdf->type == CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID;
- float3 N = bsdf->N;
-
- if(m_refractive || alpha_x*alpha_y <= 1e-7f)
- return make_float3(0.0f, 0.0f, 0.0f);
-
- float cosNO = dot(N, I);
- float cosNI = dot(N, omega_in);
-
- if(cosNI > 0 && cosNO > 0) {
- /* get half vector */
- float3 m = normalize(omega_in + I);
- float alpha2 = alpha_x * alpha_y;
- float D, G1o, G1i;
-
- if(alpha_x == alpha_y) {
- /* isotropic
- * eq. 20: (F*G*D)/(4*in*on)
- * eq. 33: first we calculate D(m) */
- float cosThetaM = dot(N, m);
- float cosThetaM2 = cosThetaM * cosThetaM;
- float cosThetaM4 = cosThetaM2 * cosThetaM2;
- float tanThetaM2 = (1 - cosThetaM2) / cosThetaM2;
-
- if(bsdf->type == CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_ID) {
- /* use GTR1 for clearcoat */
- D = D_GTR1(cosThetaM, bsdf->alpha_x);
-
- /* the alpha value for clearcoat is a fixed 0.25 => alpha2 = 0.25 * 0.25 */
- alpha2 = 0.0625f;
- }
- else {
- /* use GTR2 otherwise */
- D = alpha2 / (M_PI_F * cosThetaM4 * (alpha2 + tanThetaM2) * (alpha2 + tanThetaM2));
- }
-
- /* eq. 34: now calculate G1(i,m) and G1(o,m) */
- G1o = 2 / (1 + safe_sqrtf(1 + alpha2 * (1 - cosNO * cosNO) / (cosNO * cosNO)));
- G1i = 2 / (1 + safe_sqrtf(1 + alpha2 * (1 - cosNI * cosNI) / (cosNI * cosNI)));
- }
- else {
- /* anisotropic */
- float3 X, Y, Z = N;
- make_orthonormals_tangent(Z, bsdf->T, &X, &Y);
-
- /* distribution */
- float3 local_m = make_float3(dot(X, m), dot(Y, m), dot(Z, m));
- float slope_x = -local_m.x/(local_m.z*alpha_x);
- float slope_y = -local_m.y/(local_m.z*alpha_y);
- float slope_len = 1 + slope_x*slope_x + slope_y*slope_y;
-
- float cosThetaM = local_m.z;
- float cosThetaM2 = cosThetaM * cosThetaM;
- float cosThetaM4 = cosThetaM2 * cosThetaM2;
-
- D = 1 / ((slope_len * slope_len) * M_PI_F * alpha2 * cosThetaM4);
-
- /* G1(i,m) and G1(o,m) */
- float tanThetaO2 = (1 - cosNO * cosNO) / (cosNO * cosNO);
- float cosPhiO = dot(I, X);
- float sinPhiO = dot(I, Y);
-
- float alphaO2 = (cosPhiO*cosPhiO)*(alpha_x*alpha_x) + (sinPhiO*sinPhiO)*(alpha_y*alpha_y);
- alphaO2 /= cosPhiO*cosPhiO + sinPhiO*sinPhiO;
-
- G1o = 2 / (1 + safe_sqrtf(1 + alphaO2 * tanThetaO2));
-
- float tanThetaI2 = (1 - cosNI * cosNI) / (cosNI * cosNI);
- float cosPhiI = dot(omega_in, X);
- float sinPhiI = dot(omega_in, Y);
-
- float alphaI2 = (cosPhiI*cosPhiI)*(alpha_x*alpha_x) + (sinPhiI*sinPhiI)*(alpha_y*alpha_y);
- alphaI2 /= cosPhiI*cosPhiI + sinPhiI*sinPhiI;
-
- G1i = 2 / (1 + safe_sqrtf(1 + alphaI2 * tanThetaI2));
- }
-
- float G = G1o * G1i;
-
- /* eq. 20 */
- float common = D * 0.25f / cosNO;
-
- float3 F = reflection_color(bsdf, omega_in, m);
- if(bsdf->type == CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_ID) {
- F *= 0.25f * bsdf->extra->clearcoat;
- }
-
- float3 out = F * G * common;
-
- /* eq. 2 in distribution of visible normals sampling
- * pm = Dw = G1o * dot(m, I) * D / dot(N, I); */
-
- /* eq. 38 - but see also:
- * eq. 17 in http://www.graphics.cornell.edu/~bjw/wardnotes.pdf
- * pdf = pm * 0.25 / dot(m, I); */
- *pdf = G1o * common;
-
- return out;
- }
-
- return make_float3(0.0f, 0.0f, 0.0f);
+ const MicrofacetBsdf *bsdf = (const MicrofacetBsdf *)sc;
+ float alpha_x = bsdf->alpha_x;
+ float alpha_y = bsdf->alpha_y;
+ bool m_refractive = bsdf->type == CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID;
+ float3 N = bsdf->N;
+
+ if (m_refractive || alpha_x * alpha_y <= 1e-7f)
+ return make_float3(0.0f, 0.0f, 0.0f);
+
+ float cosNO = dot(N, I);
+ float cosNI = dot(N, omega_in);
+
+ if (cosNI > 0 && cosNO > 0) {
+ /* get half vector */
+ float3 m = normalize(omega_in + I);
+ float alpha2 = alpha_x * alpha_y;
+ float D, G1o, G1i;
+
+ if (alpha_x == alpha_y) {
+ /* isotropic
+ * eq. 20: (F*G*D)/(4*in*on)
+ * eq. 33: first we calculate D(m) */
+ float cosThetaM = dot(N, m);
+ float cosThetaM2 = cosThetaM * cosThetaM;
+ float cosThetaM4 = cosThetaM2 * cosThetaM2;
+ float tanThetaM2 = (1 - cosThetaM2) / cosThetaM2;
+
+ if (bsdf->type == CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_ID) {
+ /* use GTR1 for clearcoat */
+ D = D_GTR1(cosThetaM, bsdf->alpha_x);
+
+ /* the alpha value for clearcoat is a fixed 0.25 => alpha2 = 0.25 * 0.25 */
+ alpha2 = 0.0625f;
+ }
+ else {
+ /* use GTR2 otherwise */
+ D = alpha2 / (M_PI_F * cosThetaM4 * (alpha2 + tanThetaM2) * (alpha2 + tanThetaM2));
+ }
+
+ /* eq. 34: now calculate G1(i,m) and G1(o,m) */
+ G1o = 2 / (1 + safe_sqrtf(1 + alpha2 * (1 - cosNO * cosNO) / (cosNO * cosNO)));
+ G1i = 2 / (1 + safe_sqrtf(1 + alpha2 * (1 - cosNI * cosNI) / (cosNI * cosNI)));
+ }
+ else {
+ /* anisotropic */
+ float3 X, Y, Z = N;
+ make_orthonormals_tangent(Z, bsdf->T, &X, &Y);
+
+ /* distribution */
+ float3 local_m = make_float3(dot(X, m), dot(Y, m), dot(Z, m));
+ float slope_x = -local_m.x / (local_m.z * alpha_x);
+ float slope_y = -local_m.y / (local_m.z * alpha_y);
+ float slope_len = 1 + slope_x * slope_x + slope_y * slope_y;
+
+ float cosThetaM = local_m.z;
+ float cosThetaM2 = cosThetaM * cosThetaM;
+ float cosThetaM4 = cosThetaM2 * cosThetaM2;
+
+ D = 1 / ((slope_len * slope_len) * M_PI_F * alpha2 * cosThetaM4);
+
+ /* G1(i,m) and G1(o,m) */
+ float tanThetaO2 = (1 - cosNO * cosNO) / (cosNO * cosNO);
+ float cosPhiO = dot(I, X);
+ float sinPhiO = dot(I, Y);
+
+ float alphaO2 = (cosPhiO * cosPhiO) * (alpha_x * alpha_x) +
+ (sinPhiO * sinPhiO) * (alpha_y * alpha_y);
+ alphaO2 /= cosPhiO * cosPhiO + sinPhiO * sinPhiO;
+
+ G1o = 2 / (1 + safe_sqrtf(1 + alphaO2 * tanThetaO2));
+
+ float tanThetaI2 = (1 - cosNI * cosNI) / (cosNI * cosNI);
+ float cosPhiI = dot(omega_in, X);
+ float sinPhiI = dot(omega_in, Y);
+
+ float alphaI2 = (cosPhiI * cosPhiI) * (alpha_x * alpha_x) +
+ (sinPhiI * sinPhiI) * (alpha_y * alpha_y);
+ alphaI2 /= cosPhiI * cosPhiI + sinPhiI * sinPhiI;
+
+ G1i = 2 / (1 + safe_sqrtf(1 + alphaI2 * tanThetaI2));
+ }
+
+ float G = G1o * G1i;
+
+ /* eq. 20 */
+ float common = D * 0.25f / cosNO;
+
+ float3 F = reflection_color(bsdf, omega_in, m);
+ if (bsdf->type == CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_ID) {
+ F *= 0.25f * bsdf->extra->clearcoat;
+ }
+
+ float3 out = F * G * common;
+
+ /* eq. 2 in distribution of visible normals sampling
+ * pm = Dw = G1o * dot(m, I) * D / dot(N, I); */
+
+ /* eq. 38 - but see also:
+ * eq. 17 in http://www.graphics.cornell.edu/~bjw/wardnotes.pdf
+ * pdf = pm * 0.25 / dot(m, I); */
+ *pdf = G1o * common;
+
+ return out;
+ }
+
+ return make_float3(0.0f, 0.0f, 0.0f);
}
-ccl_device float3 bsdf_microfacet_ggx_eval_transmit(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf)
+ccl_device float3 bsdf_microfacet_ggx_eval_transmit(const ShaderClosure *sc,
+ const float3 I,
+ const float3 omega_in,
+ float *pdf)
{
- const MicrofacetBsdf *bsdf = (const MicrofacetBsdf*)sc;
- float alpha_x = bsdf->alpha_x;
- float alpha_y = bsdf->alpha_y;
- float m_eta = bsdf->ior;
- bool m_refractive = bsdf->type == CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID;
- float3 N = bsdf->N;
+ const MicrofacetBsdf *bsdf = (const MicrofacetBsdf *)sc;
+ float alpha_x = bsdf->alpha_x;
+ float alpha_y = bsdf->alpha_y;
+ float m_eta = bsdf->ior;
+ bool m_refractive = bsdf->type == CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID;
+ float3 N = bsdf->N;
- if(!m_refractive || alpha_x*alpha_y <= 1e-7f)
- return make_float3(0.0f, 0.0f, 0.0f);
+ if (!m_refractive || alpha_x * alpha_y <= 1e-7f)
+ return make_float3(0.0f, 0.0f, 0.0f);
- float cosNO = dot(N, I);
- float cosNI = dot(N, omega_in);
+ float cosNO = dot(N, I);
+ float cosNI = dot(N, omega_in);
- if(cosNO <= 0 || cosNI >= 0)
- return make_float3(0.0f, 0.0f, 0.0f); /* vectors on same side -- not possible */
+ if (cosNO <= 0 || cosNI >= 0)
+ return make_float3(0.0f, 0.0f, 0.0f); /* vectors on same side -- not possible */
- /* compute half-vector of the refraction (eq. 16) */
- float3 ht = -(m_eta * omega_in + I);
- float3 Ht = normalize(ht);
- float cosHO = dot(Ht, I);
- float cosHI = dot(Ht, omega_in);
+ /* compute half-vector of the refraction (eq. 16) */
+ float3 ht = -(m_eta * omega_in + I);
+ float3 Ht = normalize(ht);
+ float cosHO = dot(Ht, I);
+ float cosHI = dot(Ht, omega_in);
- float D, G1o, G1i;
+ float D, G1o, G1i;
- /* eq. 33: first we calculate D(m) with m=Ht: */
- float alpha2 = alpha_x * alpha_y;
- float cosThetaM = dot(N, Ht);
- float cosThetaM2 = cosThetaM * cosThetaM;
- float tanThetaM2 = (1 - cosThetaM2) / cosThetaM2;
- float cosThetaM4 = cosThetaM2 * cosThetaM2;
- D = alpha2 / (M_PI_F * cosThetaM4 * (alpha2 + tanThetaM2) * (alpha2 + tanThetaM2));
+ /* eq. 33: first we calculate D(m) with m=Ht: */
+ float alpha2 = alpha_x * alpha_y;
+ float cosThetaM = dot(N, Ht);
+ float cosThetaM2 = cosThetaM * cosThetaM;
+ float tanThetaM2 = (1 - cosThetaM2) / cosThetaM2;
+ float cosThetaM4 = cosThetaM2 * cosThetaM2;
+ D = alpha2 / (M_PI_F * cosThetaM4 * (alpha2 + tanThetaM2) * (alpha2 + tanThetaM2));
- /* eq. 34: now calculate G1(i,m) and G1(o,m) */
- G1o = 2 / (1 + safe_sqrtf(1 + alpha2 * (1 - cosNO * cosNO) / (cosNO * cosNO)));
- G1i = 2 / (1 + safe_sqrtf(1 + alpha2 * (1 - cosNI * cosNI) / (cosNI * cosNI)));
+ /* eq. 34: now calculate G1(i,m) and G1(o,m) */
+ G1o = 2 / (1 + safe_sqrtf(1 + alpha2 * (1 - cosNO * cosNO) / (cosNO * cosNO)));
+ G1i = 2 / (1 + safe_sqrtf(1 + alpha2 * (1 - cosNI * cosNI) / (cosNI * cosNI)));
- float G = G1o * G1i;
+ float G = G1o * G1i;
- /* probability */
- float Ht2 = dot(ht, ht);
+ /* probability */
+ float Ht2 = dot(ht, ht);
- /* eq. 2 in distribution of visible normals sampling
- * pm = Dw = G1o * dot(m, I) * D / dot(N, I); */
+ /* eq. 2 in distribution of visible normals sampling
+ * pm = Dw = G1o * dot(m, I) * D / dot(N, I); */
- /* out = fabsf(cosHI * cosHO) * (m_eta * m_eta) * G * D / (cosNO * Ht2)
- * pdf = pm * (m_eta * m_eta) * fabsf(cosHI) / Ht2 */
- float common = D * (m_eta * m_eta) / (cosNO * Ht2);
- float out = G * fabsf(cosHI * cosHO) * common;
- *pdf = G1o * fabsf(cosHO * cosHI) * common;
+ /* out = fabsf(cosHI * cosHO) * (m_eta * m_eta) * G * D / (cosNO * Ht2)
+ * pdf = pm * (m_eta * m_eta) * fabsf(cosHI) / Ht2 */
+ float common = D * (m_eta * m_eta) / (cosNO * Ht2);
+ float out = G * fabsf(cosHI * cosHO) * common;
+ *pdf = G1o * fabsf(cosHO * cosHI) * common;
- return make_float3(out, out, out);
+ return make_float3(out, out, out);
}
-ccl_device int bsdf_microfacet_ggx_sample(KernelGlobals *kg, const ShaderClosure *sc, float3 Ng, float3 I, float3 dIdx, float3 dIdy, float randu, float randv, float3 *eval, float3 *omega_in, float3 *domega_in_dx, float3 *domega_in_dy, float *pdf)
+ccl_device int bsdf_microfacet_ggx_sample(KernelGlobals *kg,
+ const ShaderClosure *sc,
+ float3 Ng,
+ float3 I,
+ float3 dIdx,
+ float3 dIdy,
+ float randu,
+ float randv,
+ float3 *eval,
+ float3 *omega_in,
+ float3 *domega_in_dx,
+ float3 *domega_in_dy,
+ float *pdf)
{
- const MicrofacetBsdf *bsdf = (const MicrofacetBsdf*)sc;
- float alpha_x = bsdf->alpha_x;
- float alpha_y = bsdf->alpha_y;
- bool m_refractive = bsdf->type == CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID;
- float3 N = bsdf->N;
- int label;
-
- float cosNO = dot(N, I);
- if(cosNO > 0) {
- float3 X, Y, Z = N;
-
- if(alpha_x == alpha_y)
- make_orthonormals(Z, &X, &Y);
- else
- make_orthonormals_tangent(Z, bsdf->T, &X, &Y);
-
- /* importance sampling with distribution of visible normals. vectors are
- * transformed to local space before and after */
- float3 local_I = make_float3(dot(X, I), dot(Y, I), cosNO);
- float3 local_m;
- float G1o;
-
- local_m = microfacet_sample_stretched(kg, local_I, alpha_x, alpha_y,
- randu, randv, false, &G1o);
-
- float3 m = X*local_m.x + Y*local_m.y + Z*local_m.z;
- float cosThetaM = local_m.z;
-
- /* reflection or refraction? */
- if(!m_refractive) {
- float cosMO = dot(m, I);
- label = LABEL_REFLECT | LABEL_GLOSSY;
-
- if(cosMO > 0) {
- /* eq. 39 - compute actual reflected direction */
- *omega_in = 2 * cosMO * m - I;
-
- if(dot(Ng, *omega_in) > 0) {
- if(alpha_x*alpha_y <= 1e-7f) {
- /* some high number for MIS */
- *pdf = 1e6f;
- *eval = make_float3(1e6f, 1e6f, 1e6f);
-
- bool use_fresnel = (bsdf->type == CLOSURE_BSDF_MICROFACET_GGX_FRESNEL_ID
- || bsdf->type == CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_ID
- || bsdf->type == CLOSURE_BSDF_MICROFACET_GGX_ANISO_FRESNEL_ID);
-
- /* if fresnel is used, calculate the color with reflection_color(...) */
- if(use_fresnel) {
- *eval *= reflection_color(bsdf, *omega_in, m);
- }
-
- label = LABEL_REFLECT | LABEL_SINGULAR;
- }
- else {
- /* microfacet normal is visible to this ray */
- /* eq. 33 */
- float alpha2 = alpha_x * alpha_y;
- float D, G1i;
-
- if(alpha_x == alpha_y) {
- /* isotropic */
- float cosThetaM2 = cosThetaM * cosThetaM;
- float cosThetaM4 = cosThetaM2 * cosThetaM2;
- float tanThetaM2 = 1/(cosThetaM2) - 1;
-
- /* eval BRDF*cosNI */
- float cosNI = dot(N, *omega_in);
-
- if(bsdf->type == CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_ID) {
- /* use GTR1 for clearcoat */
- D = D_GTR1(cosThetaM, bsdf->alpha_x);
-
- /* the alpha value for clearcoat is a fixed 0.25 => alpha2 = 0.25 * 0.25 */
- alpha2 = 0.0625f;
-
- /* recalculate G1o */
- G1o = 2 / (1 + safe_sqrtf(1 + alpha2 * (1 - cosNO * cosNO) / (cosNO * cosNO)));
- }
- else {
- /* use GTR2 otherwise */
- D = alpha2 / (M_PI_F * cosThetaM4 * (alpha2 + tanThetaM2) * (alpha2 + tanThetaM2));
- }
-
- /* eq. 34: now calculate G1(i,m) */
- G1i = 2 / (1 + safe_sqrtf(1 + alpha2 * (1 - cosNI * cosNI) / (cosNI * cosNI)));
- }
- else {
- /* anisotropic distribution */
- float3 local_m = make_float3(dot(X, m), dot(Y, m), dot(Z, m));
- float slope_x = -local_m.x/(local_m.z*alpha_x);
- float slope_y = -local_m.y/(local_m.z*alpha_y);
- float slope_len = 1 + slope_x*slope_x + slope_y*slope_y;
-
- float cosThetaM = local_m.z;
- float cosThetaM2 = cosThetaM * cosThetaM;
- float cosThetaM4 = cosThetaM2 * cosThetaM2;
-
- D = 1 / ((slope_len * slope_len) * M_PI_F * alpha2 * cosThetaM4);
-
- /* calculate G1(i,m) */
- float cosNI = dot(N, *omega_in);
-
- float tanThetaI2 = (1 - cosNI * cosNI) / (cosNI * cosNI);
- float cosPhiI = dot(*omega_in, X);
- float sinPhiI = dot(*omega_in, Y);
-
- float alphaI2 = (cosPhiI*cosPhiI)*(alpha_x*alpha_x) + (sinPhiI*sinPhiI)*(alpha_y*alpha_y);
- alphaI2 /= cosPhiI*cosPhiI + sinPhiI*sinPhiI;
-
- G1i = 2 / (1 + safe_sqrtf(1 + alphaI2 * tanThetaI2));
- }
-
- /* see eval function for derivation */
- float common = (G1o * D) * 0.25f / cosNO;
- *pdf = common;
-
- float3 F = reflection_color(bsdf, *omega_in, m);
-
- *eval = G1i * common * F;
- }
-
- if(bsdf->type == CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_ID) {
- *eval *= 0.25f * bsdf->extra->clearcoat;
- }
+ const MicrofacetBsdf *bsdf = (const MicrofacetBsdf *)sc;
+ float alpha_x = bsdf->alpha_x;
+ float alpha_y = bsdf->alpha_y;
+ bool m_refractive = bsdf->type == CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID;
+ float3 N = bsdf->N;
+ int label;
+
+ float cosNO = dot(N, I);
+ if (cosNO > 0) {
+ float3 X, Y, Z = N;
+
+ if (alpha_x == alpha_y)
+ make_orthonormals(Z, &X, &Y);
+ else
+ make_orthonormals_tangent(Z, bsdf->T, &X, &Y);
+
+ /* importance sampling with distribution of visible normals. vectors are
+ * transformed to local space before and after */
+ float3 local_I = make_float3(dot(X, I), dot(Y, I), cosNO);
+ float3 local_m;
+ float G1o;
+
+ local_m = microfacet_sample_stretched(
+ kg, local_I, alpha_x, alpha_y, randu, randv, false, &G1o);
+
+ float3 m = X * local_m.x + Y * local_m.y + Z * local_m.z;
+ float cosThetaM = local_m.z;
+
+ /* reflection or refraction? */
+ if (!m_refractive) {
+ float cosMO = dot(m, I);
+ label = LABEL_REFLECT | LABEL_GLOSSY;
+
+ if (cosMO > 0) {
+ /* eq. 39 - compute actual reflected direction */
+ *omega_in = 2 * cosMO * m - I;
+
+ if (dot(Ng, *omega_in) > 0) {
+ if (alpha_x * alpha_y <= 1e-7f) {
+ /* some high number for MIS */
+ *pdf = 1e6f;
+ *eval = make_float3(1e6f, 1e6f, 1e6f);
+
+ bool use_fresnel = (bsdf->type == CLOSURE_BSDF_MICROFACET_GGX_FRESNEL_ID ||
+ bsdf->type == CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_ID ||
+ bsdf->type == CLOSURE_BSDF_MICROFACET_GGX_ANISO_FRESNEL_ID);
+
+ /* if fresnel is used, calculate the color with reflection_color(...) */
+ if (use_fresnel) {
+ *eval *= reflection_color(bsdf, *omega_in, m);
+ }
+
+ label = LABEL_REFLECT | LABEL_SINGULAR;
+ }
+ else {
+ /* microfacet normal is visible to this ray */
+ /* eq. 33 */
+ float alpha2 = alpha_x * alpha_y;
+ float D, G1i;
+
+ if (alpha_x == alpha_y) {
+ /* isotropic */
+ float cosThetaM2 = cosThetaM * cosThetaM;
+ float cosThetaM4 = cosThetaM2 * cosThetaM2;
+ float tanThetaM2 = 1 / (cosThetaM2)-1;
+
+ /* eval BRDF*cosNI */
+ float cosNI = dot(N, *omega_in);
+
+ if (bsdf->type == CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_ID) {
+ /* use GTR1 for clearcoat */
+ D = D_GTR1(cosThetaM, bsdf->alpha_x);
+
+ /* the alpha value for clearcoat is a fixed 0.25 => alpha2 = 0.25 * 0.25 */
+ alpha2 = 0.0625f;
+
+ /* recalculate G1o */
+ G1o = 2 / (1 + safe_sqrtf(1 + alpha2 * (1 - cosNO * cosNO) / (cosNO * cosNO)));
+ }
+ else {
+ /* use GTR2 otherwise */
+ D = alpha2 / (M_PI_F * cosThetaM4 * (alpha2 + tanThetaM2) * (alpha2 + tanThetaM2));
+ }
+
+ /* eq. 34: now calculate G1(i,m) */
+ G1i = 2 / (1 + safe_sqrtf(1 + alpha2 * (1 - cosNI * cosNI) / (cosNI * cosNI)));
+ }
+ else {
+ /* anisotropic distribution */
+ float3 local_m = make_float3(dot(X, m), dot(Y, m), dot(Z, m));
+ float slope_x = -local_m.x / (local_m.z * alpha_x);
+ float slope_y = -local_m.y / (local_m.z * alpha_y);
+ float slope_len = 1 + slope_x * slope_x + slope_y * slope_y;
+
+ float cosThetaM = local_m.z;
+ float cosThetaM2 = cosThetaM * cosThetaM;
+ float cosThetaM4 = cosThetaM2 * cosThetaM2;
+
+ D = 1 / ((slope_len * slope_len) * M_PI_F * alpha2 * cosThetaM4);
+
+ /* calculate G1(i,m) */
+ float cosNI = dot(N, *omega_in);
+
+ float tanThetaI2 = (1 - cosNI * cosNI) / (cosNI * cosNI);
+ float cosPhiI = dot(*omega_in, X);
+ float sinPhiI = dot(*omega_in, Y);
+
+ float alphaI2 = (cosPhiI * cosPhiI) * (alpha_x * alpha_x) +
+ (sinPhiI * sinPhiI) * (alpha_y * alpha_y);
+ alphaI2 /= cosPhiI * cosPhiI + sinPhiI * sinPhiI;
+
+ G1i = 2 / (1 + safe_sqrtf(1 + alphaI2 * tanThetaI2));
+ }
+
+ /* see eval function for derivation */
+ float common = (G1o * D) * 0.25f / cosNO;
+ *pdf = common;
+
+ float3 F = reflection_color(bsdf, *omega_in, m);
+
+ *eval = G1i * common * F;
+ }
+
+ if (bsdf->type == CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_ID) {
+ *eval *= 0.25f * bsdf->extra->clearcoat;
+ }
#ifdef __RAY_DIFFERENTIALS__
- *domega_in_dx = (2 * dot(m, dIdx)) * m - dIdx;
- *domega_in_dy = (2 * dot(m, dIdy)) * m - dIdy;
+ *domega_in_dx = (2 * dot(m, dIdx)) * m - dIdx;
+ *domega_in_dy = (2 * dot(m, dIdy)) * m - dIdy;
#endif
- }
- }
- }
- else {
- label = LABEL_TRANSMIT | LABEL_GLOSSY;
-
- /* CAUTION: the i and o variables are inverted relative to the paper
- * eq. 39 - compute actual refractive direction */
- float3 R, T;
+ }
+ }
+ }
+ else {
+ label = LABEL_TRANSMIT | LABEL_GLOSSY;
+
+ /* CAUTION: the i and o variables are inverted relative to the paper
+ * eq. 39 - compute actual refractive direction */
+ float3 R, T;
#ifdef __RAY_DIFFERENTIALS__
- float3 dRdx, dRdy, dTdx, dTdy;
+ float3 dRdx, dRdy, dTdx, dTdy;
#endif
- float m_eta = bsdf->ior, fresnel;
- bool inside;
-
- fresnel = fresnel_dielectric(m_eta, m, I, &R, &T,
+ float m_eta = bsdf->ior, fresnel;
+ bool inside;
+
+ fresnel = fresnel_dielectric(m_eta,
+ m,
+ I,
+ &R,
+ &T,
#ifdef __RAY_DIFFERENTIALS__
- dIdx, dIdy, &dRdx, &dRdy, &dTdx, &dTdy,
+ dIdx,
+ dIdy,
+ &dRdx,
+ &dRdy,
+ &dTdx,
+ &dTdy,
#endif
- &inside);
+ &inside);
- if(!inside && fresnel != 1.0f) {
+ if (!inside && fresnel != 1.0f) {
- *omega_in = T;
+ *omega_in = T;
#ifdef __RAY_DIFFERENTIALS__
- *domega_in_dx = dTdx;
- *domega_in_dy = dTdy;
+ *domega_in_dx = dTdx;
+ *domega_in_dy = dTdy;
#endif
- if(alpha_x*alpha_y <= 1e-7f || fabsf(m_eta - 1.0f) < 1e-4f) {
- /* some high number for MIS */
- *pdf = 1e6f;
- *eval = make_float3(1e6f, 1e6f, 1e6f);
- label = LABEL_TRANSMIT | LABEL_SINGULAR;
- }
- else {
- /* eq. 33 */
- float alpha2 = alpha_x * alpha_y;
- float cosThetaM2 = cosThetaM * cosThetaM;
- float cosThetaM4 = cosThetaM2 * cosThetaM2;
- float tanThetaM2 = 1/(cosThetaM2) - 1;
- float D = alpha2 / (M_PI_F * cosThetaM4 * (alpha2 + tanThetaM2) * (alpha2 + tanThetaM2));
-
- /* eval BRDF*cosNI */
- float cosNI = dot(N, *omega_in);
-
- /* eq. 34: now calculate G1(i,m) */
- float G1i = 2 / (1 + safe_sqrtf(1 + alpha2 * (1 - cosNI * cosNI) / (cosNI * cosNI)));
-
- /* eq. 21 */
- float cosHI = dot(m, *omega_in);
- float cosHO = dot(m, I);
- float Ht2 = m_eta * cosHI + cosHO;
- Ht2 *= Ht2;
-
- /* see eval function for derivation */
- float common = (G1o * D) * (m_eta * m_eta) / (cosNO * Ht2);
- float out = G1i * fabsf(cosHI * cosHO) * common;
- *pdf = cosHO * fabsf(cosHI) * common;
-
- *eval = make_float3(out, out, out);
- }
- }
- }
- }
- else {
- label = (m_refractive) ? LABEL_TRANSMIT|LABEL_GLOSSY : LABEL_REFLECT|LABEL_GLOSSY;
- }
- return label;
+ if (alpha_x * alpha_y <= 1e-7f || fabsf(m_eta - 1.0f) < 1e-4f) {
+ /* some high number for MIS */
+ *pdf = 1e6f;
+ *eval = make_float3(1e6f, 1e6f, 1e6f);
+ label = LABEL_TRANSMIT | LABEL_SINGULAR;
+ }
+ else {
+ /* eq. 33 */
+ float alpha2 = alpha_x * alpha_y;
+ float cosThetaM2 = cosThetaM * cosThetaM;
+ float cosThetaM4 = cosThetaM2 * cosThetaM2;
+ float tanThetaM2 = 1 / (cosThetaM2)-1;
+ float D = alpha2 / (M_PI_F * cosThetaM4 * (alpha2 + tanThetaM2) * (alpha2 + tanThetaM2));
+
+ /* eval BRDF*cosNI */
+ float cosNI = dot(N, *omega_in);
+
+ /* eq. 34: now calculate G1(i,m) */
+ float G1i = 2 / (1 + safe_sqrtf(1 + alpha2 * (1 - cosNI * cosNI) / (cosNI * cosNI)));
+
+ /* eq. 21 */
+ float cosHI = dot(m, *omega_in);
+ float cosHO = dot(m, I);
+ float Ht2 = m_eta * cosHI + cosHO;
+ Ht2 *= Ht2;
+
+ /* see eval function for derivation */
+ float common = (G1o * D) * (m_eta * m_eta) / (cosNO * Ht2);
+ float out = G1i * fabsf(cosHI * cosHO) * common;
+ *pdf = cosHO * fabsf(cosHI) * common;
+
+ *eval = make_float3(out, out, out);
+ }
+ }
+ }
+ }
+ else {
+ label = (m_refractive) ? LABEL_TRANSMIT | LABEL_GLOSSY : LABEL_REFLECT | LABEL_GLOSSY;
+ }
+ return label;
}
/* Beckmann microfacet with Smith shadow-masking from:
@@ -764,364 +803,392 @@ ccl_device int bsdf_microfacet_ggx_sample(KernelGlobals *kg, const ShaderClosure
ccl_device int bsdf_microfacet_beckmann_setup(MicrofacetBsdf *bsdf)
{
- bsdf->alpha_x = saturate(bsdf->alpha_x);
- bsdf->alpha_y = bsdf->alpha_x;
+ bsdf->alpha_x = saturate(bsdf->alpha_x);
+ bsdf->alpha_y = bsdf->alpha_x;
- bsdf->type = CLOSURE_BSDF_MICROFACET_BECKMANN_ID;
- return SD_BSDF|SD_BSDF_HAS_EVAL;
+ bsdf->type = CLOSURE_BSDF_MICROFACET_BECKMANN_ID;
+ return SD_BSDF | SD_BSDF_HAS_EVAL;
}
ccl_device int bsdf_microfacet_beckmann_aniso_setup(MicrofacetBsdf *bsdf)
{
- bsdf->alpha_x = saturate(bsdf->alpha_x);
- bsdf->alpha_y = saturate(bsdf->alpha_y);
+ bsdf->alpha_x = saturate(bsdf->alpha_x);
+ bsdf->alpha_y = saturate(bsdf->alpha_y);
- bsdf->type = CLOSURE_BSDF_MICROFACET_BECKMANN_ANISO_ID;
- return SD_BSDF|SD_BSDF_HAS_EVAL;
+ bsdf->type = CLOSURE_BSDF_MICROFACET_BECKMANN_ANISO_ID;
+ return SD_BSDF | SD_BSDF_HAS_EVAL;
}
ccl_device int bsdf_microfacet_beckmann_refraction_setup(MicrofacetBsdf *bsdf)
{
- bsdf->alpha_x = saturate(bsdf->alpha_x);
- bsdf->alpha_y = bsdf->alpha_x;
+ bsdf->alpha_x = saturate(bsdf->alpha_x);
+ bsdf->alpha_y = bsdf->alpha_x;
- bsdf->type = CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID;
- return SD_BSDF|SD_BSDF_HAS_EVAL;
+ bsdf->type = CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID;
+ return SD_BSDF | SD_BSDF_HAS_EVAL;
}
ccl_device void bsdf_microfacet_beckmann_blur(ShaderClosure *sc, float roughness)
{
- MicrofacetBsdf *bsdf = (MicrofacetBsdf*)sc;
+ MicrofacetBsdf *bsdf = (MicrofacetBsdf *)sc;
- bsdf->alpha_x = fmaxf(roughness, bsdf->alpha_x);
- bsdf->alpha_y = fmaxf(roughness, bsdf->alpha_y);
+ bsdf->alpha_x = fmaxf(roughness, bsdf->alpha_x);
+ bsdf->alpha_y = fmaxf(roughness, bsdf->alpha_y);
}
ccl_device_inline float bsdf_beckmann_G1(float alpha, float cos_n)
{
- cos_n *= cos_n;
- float invA = alpha * safe_sqrtf((1.0f - cos_n) / cos_n);
- if(invA < 0.625f) {
- return 1.0f;
- }
-
- float a = 1.0f / invA;
- return ((2.181f*a + 3.535f)*a) / ((2.577f*a + 2.276f)*a + 1.0f);
+ cos_n *= cos_n;
+ float invA = alpha * safe_sqrtf((1.0f - cos_n) / cos_n);
+ if (invA < 0.625f) {
+ return 1.0f;
+ }
+
+ float a = 1.0f / invA;
+ return ((2.181f * a + 3.535f) * a) / ((2.577f * a + 2.276f) * a + 1.0f);
}
-ccl_device_inline float bsdf_beckmann_aniso_G1(float alpha_x, float alpha_y, float cos_n, float cos_phi, float sin_phi)
+ccl_device_inline float bsdf_beckmann_aniso_G1(
+ float alpha_x, float alpha_y, float cos_n, float cos_phi, float sin_phi)
{
- cos_n *= cos_n;
- sin_phi *= sin_phi;
- cos_phi *= cos_phi;
- alpha_x *= alpha_x;
- alpha_y *= alpha_y;
-
- float alphaO2 = (cos_phi*alpha_x + sin_phi*alpha_y) / (cos_phi + sin_phi);
- float invA = safe_sqrtf(alphaO2 * (1 - cos_n) / cos_n);
- if(invA < 0.625f) {
- return 1.0f;
- }
-
- float a = 1.0f / invA;
- return ((2.181f*a + 3.535f)*a) / ((2.577f*a + 2.276f)*a + 1.0f);
+ cos_n *= cos_n;
+ sin_phi *= sin_phi;
+ cos_phi *= cos_phi;
+ alpha_x *= alpha_x;
+ alpha_y *= alpha_y;
+
+ float alphaO2 = (cos_phi * alpha_x + sin_phi * alpha_y) / (cos_phi + sin_phi);
+ float invA = safe_sqrtf(alphaO2 * (1 - cos_n) / cos_n);
+ if (invA < 0.625f) {
+ return 1.0f;
+ }
+
+ float a = 1.0f / invA;
+ return ((2.181f * a + 3.535f) * a) / ((2.577f * a + 2.276f) * a + 1.0f);
}
-ccl_device float3 bsdf_microfacet_beckmann_eval_reflect(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf)
+ccl_device float3 bsdf_microfacet_beckmann_eval_reflect(const ShaderClosure *sc,
+ const float3 I,
+ const float3 omega_in,
+ float *pdf)
{
- const MicrofacetBsdf *bsdf = (const MicrofacetBsdf*)sc;
- float alpha_x = bsdf->alpha_x;
- float alpha_y = bsdf->alpha_y;
- bool m_refractive = bsdf->type == CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID;
- float3 N = bsdf->N;
-
- if(m_refractive || alpha_x*alpha_y <= 1e-7f)
- return make_float3(0.0f, 0.0f, 0.0f);
-
- float cosNO = dot(N, I);
- float cosNI = dot(N, omega_in);
-
- if(cosNO > 0 && cosNI > 0) {
- /* get half vector */
- float3 m = normalize(omega_in + I);
-
- float alpha2 = alpha_x * alpha_y;
- float D, G1o, G1i;
-
- if(alpha_x == alpha_y) {
- /* isotropic
- * eq. 20: (F*G*D)/(4*in*on)
- * eq. 25: first we calculate D(m) */
- float cosThetaM = dot(N, m);
- float cosThetaM2 = cosThetaM * cosThetaM;
- float tanThetaM2 = (1 - cosThetaM2) / cosThetaM2;
- float cosThetaM4 = cosThetaM2 * cosThetaM2;
- D = expf(-tanThetaM2 / alpha2) / (M_PI_F * alpha2 * cosThetaM4);
-
- /* eq. 26, 27: now calculate G1(i,m) and G1(o,m) */
- G1o = bsdf_beckmann_G1(alpha_x, cosNO);
- G1i = bsdf_beckmann_G1(alpha_x, cosNI);
- }
- else {
- /* anisotropic */
- float3 X, Y, Z = N;
- make_orthonormals_tangent(Z, bsdf->T, &X, &Y);
-
- /* distribution */
- float3 local_m = make_float3(dot(X, m), dot(Y, m), dot(Z, m));
- float slope_x = -local_m.x/(local_m.z*alpha_x);
- float slope_y = -local_m.y/(local_m.z*alpha_y);
-
- float cosThetaM = local_m.z;
- float cosThetaM2 = cosThetaM * cosThetaM;
- float cosThetaM4 = cosThetaM2 * cosThetaM2;
-
- D = expf(-slope_x*slope_x - slope_y*slope_y) / (M_PI_F * alpha2 * cosThetaM4);
-
- /* G1(i,m) and G1(o,m) */
- G1o = bsdf_beckmann_aniso_G1(alpha_x, alpha_y, cosNO, dot(I, X), dot(I, Y));
- G1i = bsdf_beckmann_aniso_G1(alpha_x, alpha_y, cosNI, dot(omega_in, X), dot(omega_in, Y));
- }
-
- float G = G1o * G1i;
-
- /* eq. 20 */
- float common = D * 0.25f / cosNO;
- float out = G * common;
-
- /* eq. 2 in distribution of visible normals sampling
- * pm = Dw = G1o * dot(m, I) * D / dot(N, I); */
-
- /* eq. 38 - but see also:
- * eq. 17 in http://www.graphics.cornell.edu/~bjw/wardnotes.pdf
- * pdf = pm * 0.25 / dot(m, I); */
- *pdf = G1o * common;
-
- return make_float3(out, out, out);
- }
-
- return make_float3(0.0f, 0.0f, 0.0f);
+ const MicrofacetBsdf *bsdf = (const MicrofacetBsdf *)sc;
+ float alpha_x = bsdf->alpha_x;
+ float alpha_y = bsdf->alpha_y;
+ bool m_refractive = bsdf->type == CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID;
+ float3 N = bsdf->N;
+
+ if (m_refractive || alpha_x * alpha_y <= 1e-7f)
+ return make_float3(0.0f, 0.0f, 0.0f);
+
+ float cosNO = dot(N, I);
+ float cosNI = dot(N, omega_in);
+
+ if (cosNO > 0 && cosNI > 0) {
+ /* get half vector */
+ float3 m = normalize(omega_in + I);
+
+ float alpha2 = alpha_x * alpha_y;
+ float D, G1o, G1i;
+
+ if (alpha_x == alpha_y) {
+ /* isotropic
+ * eq. 20: (F*G*D)/(4*in*on)
+ * eq. 25: first we calculate D(m) */
+ float cosThetaM = dot(N, m);
+ float cosThetaM2 = cosThetaM * cosThetaM;
+ float tanThetaM2 = (1 - cosThetaM2) / cosThetaM2;
+ float cosThetaM4 = cosThetaM2 * cosThetaM2;
+ D = expf(-tanThetaM2 / alpha2) / (M_PI_F * alpha2 * cosThetaM4);
+
+ /* eq. 26, 27: now calculate G1(i,m) and G1(o,m) */
+ G1o = bsdf_beckmann_G1(alpha_x, cosNO);
+ G1i = bsdf_beckmann_G1(alpha_x, cosNI);
+ }
+ else {
+ /* anisotropic */
+ float3 X, Y, Z = N;
+ make_orthonormals_tangent(Z, bsdf->T, &X, &Y);
+
+ /* distribution */
+ float3 local_m = make_float3(dot(X, m), dot(Y, m), dot(Z, m));
+ float slope_x = -local_m.x / (local_m.z * alpha_x);
+ float slope_y = -local_m.y / (local_m.z * alpha_y);
+
+ float cosThetaM = local_m.z;
+ float cosThetaM2 = cosThetaM * cosThetaM;
+ float cosThetaM4 = cosThetaM2 * cosThetaM2;
+
+ D = expf(-slope_x * slope_x - slope_y * slope_y) / (M_PI_F * alpha2 * cosThetaM4);
+
+ /* G1(i,m) and G1(o,m) */
+ G1o = bsdf_beckmann_aniso_G1(alpha_x, alpha_y, cosNO, dot(I, X), dot(I, Y));
+ G1i = bsdf_beckmann_aniso_G1(alpha_x, alpha_y, cosNI, dot(omega_in, X), dot(omega_in, Y));
+ }
+
+ float G = G1o * G1i;
+
+ /* eq. 20 */
+ float common = D * 0.25f / cosNO;
+ float out = G * common;
+
+ /* eq. 2 in distribution of visible normals sampling
+ * pm = Dw = G1o * dot(m, I) * D / dot(N, I); */
+
+ /* eq. 38 - but see also:
+ * eq. 17 in http://www.graphics.cornell.edu/~bjw/wardnotes.pdf
+ * pdf = pm * 0.25 / dot(m, I); */
+ *pdf = G1o * common;
+
+ return make_float3(out, out, out);
+ }
+
+ return make_float3(0.0f, 0.0f, 0.0f);
}
-ccl_device float3 bsdf_microfacet_beckmann_eval_transmit(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf)
+ccl_device float3 bsdf_microfacet_beckmann_eval_transmit(const ShaderClosure *sc,
+ const float3 I,
+ const float3 omega_in,
+ float *pdf)
{
- const MicrofacetBsdf *bsdf = (const MicrofacetBsdf*)sc;
- float alpha_x = bsdf->alpha_x;
- float alpha_y = bsdf->alpha_y;
- float m_eta = bsdf->ior;
- bool m_refractive = bsdf->type == CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID;
- float3 N = bsdf->N;
-
- if(!m_refractive || alpha_x*alpha_y <= 1e-7f)
- return make_float3(0.0f, 0.0f, 0.0f);
-
- float cosNO = dot(N, I);
- float cosNI = dot(N, omega_in);
-
- if(cosNO <= 0 || cosNI >= 0)
- return make_float3(0.0f, 0.0f, 0.0f);
-
- /* compute half-vector of the refraction (eq. 16) */
- float3 ht = -(m_eta * omega_in + I);
- float3 Ht = normalize(ht);
- float cosHO = dot(Ht, I);
- float cosHI = dot(Ht, omega_in);
-
- /* eq. 25: first we calculate D(m) with m=Ht: */
- float alpha2 = alpha_x * alpha_y;
- float cosThetaM = min(dot(N, Ht), 1.0f);
- float cosThetaM2 = cosThetaM * cosThetaM;
- float tanThetaM2 = (1 - cosThetaM2) / cosThetaM2;
- float cosThetaM4 = cosThetaM2 * cosThetaM2;
- float D = expf(-tanThetaM2 / alpha2) / (M_PI_F * alpha2 * cosThetaM4);
-
- /* eq. 26, 27: now calculate G1(i,m) and G1(o,m) */
- float G1o = bsdf_beckmann_G1(alpha_x, cosNO);
- float G1i = bsdf_beckmann_G1(alpha_x, cosNI);
- float G = G1o * G1i;
-
- /* probability */
- float Ht2 = dot(ht, ht);
-
- /* eq. 2 in distribution of visible normals sampling
- * pm = Dw = G1o * dot(m, I) * D / dot(N, I); */
-
- /* out = fabsf(cosHI * cosHO) * (m_eta * m_eta) * G * D / (cosNO * Ht2)
- * pdf = pm * (m_eta * m_eta) * fabsf(cosHI) / Ht2 */
- float common = D * (m_eta * m_eta) / (cosNO * Ht2);
- float out = G * fabsf(cosHI * cosHO) * common;
- *pdf = G1o * fabsf(cosHO * cosHI) * common;
-
- return make_float3(out, out, out);
+ const MicrofacetBsdf *bsdf = (const MicrofacetBsdf *)sc;
+ float alpha_x = bsdf->alpha_x;
+ float alpha_y = bsdf->alpha_y;
+ float m_eta = bsdf->ior;
+ bool m_refractive = bsdf->type == CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID;
+ float3 N = bsdf->N;
+
+ if (!m_refractive || alpha_x * alpha_y <= 1e-7f)
+ return make_float3(0.0f, 0.0f, 0.0f);
+
+ float cosNO = dot(N, I);
+ float cosNI = dot(N, omega_in);
+
+ if (cosNO <= 0 || cosNI >= 0)
+ return make_float3(0.0f, 0.0f, 0.0f);
+
+ /* compute half-vector of the refraction (eq. 16) */
+ float3 ht = -(m_eta * omega_in + I);
+ float3 Ht = normalize(ht);
+ float cosHO = dot(Ht, I);
+ float cosHI = dot(Ht, omega_in);
+
+ /* eq. 25: first we calculate D(m) with m=Ht: */
+ float alpha2 = alpha_x * alpha_y;
+ float cosThetaM = min(dot(N, Ht), 1.0f);
+ float cosThetaM2 = cosThetaM * cosThetaM;
+ float tanThetaM2 = (1 - cosThetaM2) / cosThetaM2;
+ float cosThetaM4 = cosThetaM2 * cosThetaM2;
+ float D = expf(-tanThetaM2 / alpha2) / (M_PI_F * alpha2 * cosThetaM4);
+
+ /* eq. 26, 27: now calculate G1(i,m) and G1(o,m) */
+ float G1o = bsdf_beckmann_G1(alpha_x, cosNO);
+ float G1i = bsdf_beckmann_G1(alpha_x, cosNI);
+ float G = G1o * G1i;
+
+ /* probability */
+ float Ht2 = dot(ht, ht);
+
+ /* eq. 2 in distribution of visible normals sampling
+ * pm = Dw = G1o * dot(m, I) * D / dot(N, I); */
+
+ /* out = fabsf(cosHI * cosHO) * (m_eta * m_eta) * G * D / (cosNO * Ht2)
+ * pdf = pm * (m_eta * m_eta) * fabsf(cosHI) / Ht2 */
+ float common = D * (m_eta * m_eta) / (cosNO * Ht2);
+ float out = G * fabsf(cosHI * cosHO) * common;
+ *pdf = G1o * fabsf(cosHO * cosHI) * common;
+
+ return make_float3(out, out, out);
}
-ccl_device int bsdf_microfacet_beckmann_sample(KernelGlobals *kg, const ShaderClosure *sc, float3 Ng, float3 I, float3 dIdx, float3 dIdy, float randu, float randv, float3 *eval, float3 *omega_in, float3 *domega_in_dx, float3 *domega_in_dy, float *pdf)
+ccl_device int bsdf_microfacet_beckmann_sample(KernelGlobals *kg,
+ const ShaderClosure *sc,
+ float3 Ng,
+ float3 I,
+ float3 dIdx,
+ float3 dIdy,
+ float randu,
+ float randv,
+ float3 *eval,
+ float3 *omega_in,
+ float3 *domega_in_dx,
+ float3 *domega_in_dy,
+ float *pdf)
{
- const MicrofacetBsdf *bsdf = (const MicrofacetBsdf*)sc;
- float alpha_x = bsdf->alpha_x;
- float alpha_y = bsdf->alpha_y;
- bool m_refractive = bsdf->type == CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID;
- float3 N = bsdf->N;
- int label;
-
- float cosNO = dot(N, I);
- if(cosNO > 0) {
- float3 X, Y, Z = N;
-
- if(alpha_x == alpha_y)
- make_orthonormals(Z, &X, &Y);
- else
- make_orthonormals_tangent(Z, bsdf->T, &X, &Y);
-
- /* importance sampling with distribution of visible normals. vectors are
- * transformed to local space before and after */
- float3 local_I = make_float3(dot(X, I), dot(Y, I), cosNO);
- float3 local_m;
- float G1o;
-
- local_m = microfacet_sample_stretched(kg, local_I, alpha_x, alpha_x,
- randu, randv, true, &G1o);
-
- float3 m = X*local_m.x + Y*local_m.y + Z*local_m.z;
- float cosThetaM = local_m.z;
-
- /* reflection or refraction? */
- if(!m_refractive) {
- label = LABEL_REFLECT | LABEL_GLOSSY;
- float cosMO = dot(m, I);
-
- if(cosMO > 0) {
- /* eq. 39 - compute actual reflected direction */
- *omega_in = 2 * cosMO * m - I;
-
- if(dot(Ng, *omega_in) > 0) {
- if(alpha_x*alpha_y <= 1e-7f) {
- /* some high number for MIS */
- *pdf = 1e6f;
- *eval = make_float3(1e6f, 1e6f, 1e6f);
- label = LABEL_REFLECT | LABEL_SINGULAR;
- }
- else {
- /* microfacet normal is visible to this ray
- * eq. 25 */
- float alpha2 = alpha_x * alpha_y;
- float D, G1i;
-
- if(alpha_x == alpha_y) {
- /* istropic distribution */
- float cosThetaM2 = cosThetaM * cosThetaM;
- float cosThetaM4 = cosThetaM2 * cosThetaM2;
- float tanThetaM2 = 1/(cosThetaM2) - 1;
- D = expf(-tanThetaM2 / alpha2) / (M_PI_F * alpha2 * cosThetaM4);
-
- /* eval BRDF*cosNI */
- float cosNI = dot(N, *omega_in);
-
- /* eq. 26, 27: now calculate G1(i,m) */
- G1i = bsdf_beckmann_G1(alpha_x, cosNI);
- }
- else {
- /* anisotropic distribution */
- float3 local_m = make_float3(dot(X, m), dot(Y, m), dot(Z, m));
- float slope_x = -local_m.x/(local_m.z*alpha_x);
- float slope_y = -local_m.y/(local_m.z*alpha_y);
-
- float cosThetaM = local_m.z;
- float cosThetaM2 = cosThetaM * cosThetaM;
- float cosThetaM4 = cosThetaM2 * cosThetaM2;
-
- D = expf(-slope_x*slope_x - slope_y*slope_y) / (M_PI_F * alpha2 * cosThetaM4);
-
- /* G1(i,m) */
- G1i = bsdf_beckmann_aniso_G1(alpha_x, alpha_y, dot(*omega_in, N), dot(*omega_in, X), dot(*omega_in, Y));
- }
-
- float G = G1o * G1i;
-
- /* see eval function for derivation */
- float common = D * 0.25f / cosNO;
- float out = G * common;
- *pdf = G1o * common;
-
- *eval = make_float3(out, out, out);
- }
+ const MicrofacetBsdf *bsdf = (const MicrofacetBsdf *)sc;
+ float alpha_x = bsdf->alpha_x;
+ float alpha_y = bsdf->alpha_y;
+ bool m_refractive = bsdf->type == CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID;
+ float3 N = bsdf->N;
+ int label;
+
+ float cosNO = dot(N, I);
+ if (cosNO > 0) {
+ float3 X, Y, Z = N;
+
+ if (alpha_x == alpha_y)
+ make_orthonormals(Z, &X, &Y);
+ else
+ make_orthonormals_tangent(Z, bsdf->T, &X, &Y);
+
+ /* importance sampling with distribution of visible normals. vectors are
+ * transformed to local space before and after */
+ float3 local_I = make_float3(dot(X, I), dot(Y, I), cosNO);
+ float3 local_m;
+ float G1o;
+
+ local_m = microfacet_sample_stretched(kg, local_I, alpha_x, alpha_x, randu, randv, true, &G1o);
+
+ float3 m = X * local_m.x + Y * local_m.y + Z * local_m.z;
+ float cosThetaM = local_m.z;
+
+ /* reflection or refraction? */
+ if (!m_refractive) {
+ label = LABEL_REFLECT | LABEL_GLOSSY;
+ float cosMO = dot(m, I);
+
+ if (cosMO > 0) {
+ /* eq. 39 - compute actual reflected direction */
+ *omega_in = 2 * cosMO * m - I;
+
+ if (dot(Ng, *omega_in) > 0) {
+ if (alpha_x * alpha_y <= 1e-7f) {
+ /* some high number for MIS */
+ *pdf = 1e6f;
+ *eval = make_float3(1e6f, 1e6f, 1e6f);
+ label = LABEL_REFLECT | LABEL_SINGULAR;
+ }
+ else {
+ /* microfacet normal is visible to this ray
+ * eq. 25 */
+ float alpha2 = alpha_x * alpha_y;
+ float D, G1i;
+
+ if (alpha_x == alpha_y) {
+ /* istropic distribution */
+ float cosThetaM2 = cosThetaM * cosThetaM;
+ float cosThetaM4 = cosThetaM2 * cosThetaM2;
+ float tanThetaM2 = 1 / (cosThetaM2)-1;
+ D = expf(-tanThetaM2 / alpha2) / (M_PI_F * alpha2 * cosThetaM4);
+
+ /* eval BRDF*cosNI */
+ float cosNI = dot(N, *omega_in);
+
+ /* eq. 26, 27: now calculate G1(i,m) */
+ G1i = bsdf_beckmann_G1(alpha_x, cosNI);
+ }
+ else {
+ /* anisotropic distribution */
+ float3 local_m = make_float3(dot(X, m), dot(Y, m), dot(Z, m));
+ float slope_x = -local_m.x / (local_m.z * alpha_x);
+ float slope_y = -local_m.y / (local_m.z * alpha_y);
+
+ float cosThetaM = local_m.z;
+ float cosThetaM2 = cosThetaM * cosThetaM;
+ float cosThetaM4 = cosThetaM2 * cosThetaM2;
+
+ D = expf(-slope_x * slope_x - slope_y * slope_y) / (M_PI_F * alpha2 * cosThetaM4);
+
+ /* G1(i,m) */
+ G1i = bsdf_beckmann_aniso_G1(
+ alpha_x, alpha_y, dot(*omega_in, N), dot(*omega_in, X), dot(*omega_in, Y));
+ }
+
+ float G = G1o * G1i;
+
+ /* see eval function for derivation */
+ float common = D * 0.25f / cosNO;
+ float out = G * common;
+ *pdf = G1o * common;
+
+ *eval = make_float3(out, out, out);
+ }
#ifdef __RAY_DIFFERENTIALS__
- *domega_in_dx = (2 * dot(m, dIdx)) * m - dIdx;
- *domega_in_dy = (2 * dot(m, dIdy)) * m - dIdy;
+ *domega_in_dx = (2 * dot(m, dIdx)) * m - dIdx;
+ *domega_in_dy = (2 * dot(m, dIdy)) * m - dIdy;
#endif
- }
- }
- }
- else {
- label = LABEL_TRANSMIT | LABEL_GLOSSY;
-
- /* CAUTION: the i and o variables are inverted relative to the paper
- * eq. 39 - compute actual refractive direction */
- float3 R, T;
+ }
+ }
+ }
+ else {
+ label = LABEL_TRANSMIT | LABEL_GLOSSY;
+
+ /* CAUTION: the i and o variables are inverted relative to the paper
+ * eq. 39 - compute actual refractive direction */
+ float3 R, T;
#ifdef __RAY_DIFFERENTIALS__
- float3 dRdx, dRdy, dTdx, dTdy;
+ float3 dRdx, dRdy, dTdx, dTdy;
#endif
- float m_eta = bsdf->ior, fresnel;
- bool inside;
-
- fresnel = fresnel_dielectric(m_eta, m, I, &R, &T,
+ float m_eta = bsdf->ior, fresnel;
+ bool inside;
+
+ fresnel = fresnel_dielectric(m_eta,
+ m,
+ I,
+ &R,
+ &T,
#ifdef __RAY_DIFFERENTIALS__
- dIdx, dIdy, &dRdx, &dRdy, &dTdx, &dTdy,
+ dIdx,
+ dIdy,
+ &dRdx,
+ &dRdy,
+ &dTdx,
+ &dTdy,
#endif
- &inside);
+ &inside);
- if(!inside && fresnel != 1.0f) {
- *omega_in = T;
+ if (!inside && fresnel != 1.0f) {
+ *omega_in = T;
#ifdef __RAY_DIFFERENTIALS__
- *domega_in_dx = dTdx;
- *domega_in_dy = dTdy;
+ *domega_in_dx = dTdx;
+ *domega_in_dy = dTdy;
#endif
- if(alpha_x*alpha_y <= 1e-7f || fabsf(m_eta - 1.0f) < 1e-4f) {
- /* some high number for MIS */
- *pdf = 1e6f;
- *eval = make_float3(1e6f, 1e6f, 1e6f);
- label = LABEL_TRANSMIT | LABEL_SINGULAR;
- }
- else {
- /* eq. 33 */
- float alpha2 = alpha_x * alpha_y;
- float cosThetaM2 = cosThetaM * cosThetaM;
- float cosThetaM4 = cosThetaM2 * cosThetaM2;
- float tanThetaM2 = 1/(cosThetaM2) - 1;
- float D = expf(-tanThetaM2 / alpha2) / (M_PI_F * alpha2 * cosThetaM4);
-
- /* eval BRDF*cosNI */
- float cosNI = dot(N, *omega_in);
-
- /* eq. 26, 27: now calculate G1(i,m) */
- float G1i = bsdf_beckmann_G1(alpha_x, cosNI);
- float G = G1o * G1i;
-
- /* eq. 21 */
- float cosHI = dot(m, *omega_in);
- float cosHO = dot(m, I);
- float Ht2 = m_eta * cosHI + cosHO;
- Ht2 *= Ht2;
-
- /* see eval function for derivation */
- float common = D * (m_eta * m_eta) / (cosNO * Ht2);
- float out = G * fabsf(cosHI * cosHO) * common;
- *pdf = G1o * cosHO * fabsf(cosHI) * common;
-
- *eval = make_float3(out, out, out);
- }
- }
- }
- }
- else {
- label = (m_refractive) ? LABEL_TRANSMIT|LABEL_GLOSSY : LABEL_REFLECT|LABEL_GLOSSY;
- }
- return label;
+ if (alpha_x * alpha_y <= 1e-7f || fabsf(m_eta - 1.0f) < 1e-4f) {
+ /* some high number for MIS */
+ *pdf = 1e6f;
+ *eval = make_float3(1e6f, 1e6f, 1e6f);
+ label = LABEL_TRANSMIT | LABEL_SINGULAR;
+ }
+ else {
+ /* eq. 33 */
+ float alpha2 = alpha_x * alpha_y;
+ float cosThetaM2 = cosThetaM * cosThetaM;
+ float cosThetaM4 = cosThetaM2 * cosThetaM2;
+ float tanThetaM2 = 1 / (cosThetaM2)-1;
+ float D = expf(-tanThetaM2 / alpha2) / (M_PI_F * alpha2 * cosThetaM4);
+
+ /* eval BRDF*cosNI */
+ float cosNI = dot(N, *omega_in);
+
+ /* eq. 26, 27: now calculate G1(i,m) */
+ float G1i = bsdf_beckmann_G1(alpha_x, cosNI);
+ float G = G1o * G1i;
+
+ /* eq. 21 */
+ float cosHI = dot(m, *omega_in);
+ float cosHO = dot(m, I);
+ float Ht2 = m_eta * cosHI + cosHO;
+ Ht2 *= Ht2;
+
+ /* see eval function for derivation */
+ float common = D * (m_eta * m_eta) / (cosNO * Ht2);
+ float out = G * fabsf(cosHI * cosHO) * common;
+ *pdf = G1o * cosHO * fabsf(cosHI) * common;
+
+ *eval = make_float3(out, out, out);
+ }
+ }
+ }
+ }
+ else {
+ label = (m_refractive) ? LABEL_TRANSMIT | LABEL_GLOSSY : LABEL_REFLECT | LABEL_GLOSSY;
+ }
+ return label;
}
CCL_NAMESPACE_END
-#endif /* __BSDF_MICROFACET_H__ */
+#endif /* __BSDF_MICROFACET_H__ */
diff --git a/intern/cycles/kernel/closure/bsdf_microfacet_multi.h b/intern/cycles/kernel/closure/bsdf_microfacet_multi.h
index 2f2c35d5d1f..2cc1a9c5299 100644
--- a/intern/cycles/kernel/closure/bsdf_microfacet_multi.h
+++ b/intern/cycles/kernel/closure/bsdf_microfacet_multi.h
@@ -23,149 +23,168 @@ CCL_NAMESPACE_BEGIN
/* Isotropic GGX microfacet distribution */
ccl_device_forceinline float D_ggx(float3 wm, float alpha)
{
- wm.z *= wm.z;
- alpha *= alpha;
- float tmp = (1.0f - wm.z) + alpha * wm.z;
- return alpha / max(M_PI_F * tmp*tmp, 1e-7f);
+ wm.z *= wm.z;
+ alpha *= alpha;
+ float tmp = (1.0f - wm.z) + alpha * wm.z;
+ return alpha / max(M_PI_F * tmp * tmp, 1e-7f);
}
/* Anisotropic GGX microfacet distribution */
ccl_device_forceinline float D_ggx_aniso(const float3 wm, const float2 alpha)
{
- float slope_x = -wm.x/alpha.x;
- float slope_y = -wm.y/alpha.y;
- float tmp = wm.z*wm.z + slope_x*slope_x + slope_y*slope_y;
+ float slope_x = -wm.x / alpha.x;
+ float slope_y = -wm.y / alpha.y;
+ float tmp = wm.z * wm.z + slope_x * slope_x + slope_y * slope_y;
- return 1.0f / max(M_PI_F * tmp*tmp * alpha.x*alpha.y, 1e-7f);
+ return 1.0f / max(M_PI_F * tmp * tmp * alpha.x * alpha.y, 1e-7f);
}
/* Sample slope distribution (based on page 14 of the supplemental implementation). */
-ccl_device_forceinline float2 mf_sampleP22_11(const float cosI, const float randx, const float randy)
-{
- if(cosI > 0.9999f || fabsf(cosI) < 1e-6f) {
- const float r = sqrtf(randx / max(1.0f - randx, 1e-7f));
- const float phi = M_2PI_F * randy;
- return make_float2(r*cosf(phi), r*sinf(phi));
- }
-
- const float sinI = safe_sqrtf(1.0f - cosI*cosI);
- const float tanI = sinI/cosI;
- const float projA = 0.5f * (cosI + 1.0f);
- if(projA < 0.0001f)
- return make_float2(0.0f, 0.0f);
- const float A = 2.0f*randx*projA / cosI - 1.0f;
- float tmp = A*A-1.0f;
- if(fabsf(tmp) < 1e-7f)
- return make_float2(0.0f, 0.0f);
- tmp = 1.0f / tmp;
- const float D = safe_sqrtf(tanI*tanI*tmp*tmp - (A*A-tanI*tanI)*tmp);
-
- const float slopeX2 = tanI*tmp + D;
- const float slopeX = (A < 0.0f || slopeX2 > 1.0f/tanI)? (tanI*tmp - D) : slopeX2;
-
- float U2;
- if(randy >= 0.5f)
- U2 = 2.0f*(randy - 0.5f);
- else
- U2 = 2.0f*(0.5f - randy);
- const float z = (U2*(U2*(U2*0.27385f-0.73369f)+0.46341f)) / (U2*(U2*(U2*0.093073f+0.309420f)-1.0f)+0.597999f);
- const float slopeY = z * sqrtf(1.0f + slopeX*slopeX);
-
- if(randy >= 0.5f)
- return make_float2(slopeX, slopeY);
- else
- return make_float2(slopeX, -slopeY);
+ccl_device_forceinline float2 mf_sampleP22_11(const float cosI,
+ const float randx,
+ const float randy)
+{
+ if (cosI > 0.9999f || fabsf(cosI) < 1e-6f) {
+ const float r = sqrtf(randx / max(1.0f - randx, 1e-7f));
+ const float phi = M_2PI_F * randy;
+ return make_float2(r * cosf(phi), r * sinf(phi));
+ }
+
+ const float sinI = safe_sqrtf(1.0f - cosI * cosI);
+ const float tanI = sinI / cosI;
+ const float projA = 0.5f * (cosI + 1.0f);
+ if (projA < 0.0001f)
+ return make_float2(0.0f, 0.0f);
+ const float A = 2.0f * randx * projA / cosI - 1.0f;
+ float tmp = A * A - 1.0f;
+ if (fabsf(tmp) < 1e-7f)
+ return make_float2(0.0f, 0.0f);
+ tmp = 1.0f / tmp;
+ const float D = safe_sqrtf(tanI * tanI * tmp * tmp - (A * A - tanI * tanI) * tmp);
+
+ const float slopeX2 = tanI * tmp + D;
+ const float slopeX = (A < 0.0f || slopeX2 > 1.0f / tanI) ? (tanI * tmp - D) : slopeX2;
+
+ float U2;
+ if (randy >= 0.5f)
+ U2 = 2.0f * (randy - 0.5f);
+ else
+ U2 = 2.0f * (0.5f - randy);
+ const float z = (U2 * (U2 * (U2 * 0.27385f - 0.73369f) + 0.46341f)) /
+ (U2 * (U2 * (U2 * 0.093073f + 0.309420f) - 1.0f) + 0.597999f);
+ const float slopeY = z * sqrtf(1.0f + slopeX * slopeX);
+
+ if (randy >= 0.5f)
+ return make_float2(slopeX, slopeY);
+ else
+ return make_float2(slopeX, -slopeY);
}
/* Visible normal sampling for the GGX distribution (based on page 7 of the supplemental implementation). */
-ccl_device_forceinline float3 mf_sample_vndf(const float3 wi, const float2 alpha, const float randx, const float randy)
+ccl_device_forceinline float3 mf_sample_vndf(const float3 wi,
+ const float2 alpha,
+ const float randx,
+ const float randy)
{
- const float3 wi_11 = normalize(make_float3(alpha.x*wi.x, alpha.y*wi.y, wi.z));
- const float2 slope_11 = mf_sampleP22_11(wi_11.z, randx, randy);
+ const float3 wi_11 = normalize(make_float3(alpha.x * wi.x, alpha.y * wi.y, wi.z));
+ const float2 slope_11 = mf_sampleP22_11(wi_11.z, randx, randy);
- const float3 cossin_phi = safe_normalize(make_float3(wi_11.x, wi_11.y, 0.0f));
- const float slope_x = alpha.x*(cossin_phi.x * slope_11.x - cossin_phi.y * slope_11.y);
- const float slope_y = alpha.y*(cossin_phi.y * slope_11.x + cossin_phi.x * slope_11.y);
+ const float3 cossin_phi = safe_normalize(make_float3(wi_11.x, wi_11.y, 0.0f));
+ const float slope_x = alpha.x * (cossin_phi.x * slope_11.x - cossin_phi.y * slope_11.y);
+ const float slope_y = alpha.y * (cossin_phi.y * slope_11.x + cossin_phi.x * slope_11.y);
- kernel_assert(isfinite(slope_x));
- return normalize(make_float3(-slope_x, -slope_y, 1.0f));
+ kernel_assert(isfinite(slope_x));
+ return normalize(make_float3(-slope_x, -slope_y, 1.0f));
}
/* === Phase functions: Glossy and Glass === */
/* Phase function for reflective materials. */
-ccl_device_forceinline float3 mf_sample_phase_glossy(const float3 wi, float3 *weight, const float3 wm)
+ccl_device_forceinline float3 mf_sample_phase_glossy(const float3 wi,
+ float3 *weight,
+ const float3 wm)
{
- return -wi + 2.0f * wm * dot(wi, wm);
+ return -wi + 2.0f * wm * dot(wi, wm);
}
-ccl_device_forceinline float3 mf_eval_phase_glossy(const float3 w, const float lambda, const float3 wo, const float2 alpha)
+ccl_device_forceinline float3 mf_eval_phase_glossy(const float3 w,
+ const float lambda,
+ const float3 wo,
+ const float2 alpha)
{
- if(w.z > 0.9999f)
- return make_float3(0.0f, 0.0f, 0.0f);
+ if (w.z > 0.9999f)
+ return make_float3(0.0f, 0.0f, 0.0f);
- const float3 wh = normalize(wo - w);
- if(wh.z < 0.0f)
- return make_float3(0.0f, 0.0f, 0.0f);
+ const float3 wh = normalize(wo - w);
+ if (wh.z < 0.0f)
+ return make_float3(0.0f, 0.0f, 0.0f);
- float pArea = (w.z < -0.9999f)? 1.0f: lambda*w.z;
+ float pArea = (w.z < -0.9999f) ? 1.0f : lambda * w.z;
- const float dotW_WH = dot(-w, wh);
- if(dotW_WH < 0.0f)
- return make_float3(0.0f, 0.0f, 0.0f);
+ const float dotW_WH = dot(-w, wh);
+ if (dotW_WH < 0.0f)
+ return make_float3(0.0f, 0.0f, 0.0f);
- float phase = max(0.0f, dotW_WH) * 0.25f / max(pArea * dotW_WH, 1e-7f);
- if(alpha.x == alpha.y)
- phase *= D_ggx(wh, alpha.x);
- else
- phase *= D_ggx_aniso(wh, alpha);
+ float phase = max(0.0f, dotW_WH) * 0.25f / max(pArea * dotW_WH, 1e-7f);
+ if (alpha.x == alpha.y)
+ phase *= D_ggx(wh, alpha.x);
+ else
+ phase *= D_ggx_aniso(wh, alpha);
- return make_float3(phase, phase, phase);
+ return make_float3(phase, phase, phase);
}
/* Phase function for dielectric transmissive materials, including both reflection and refraction according to the dielectric fresnel term. */
-ccl_device_forceinline float3 mf_sample_phase_glass(const float3 wi, const float eta, const float3 wm, const float randV, bool *outside)
-{
- float cosI = dot(wi, wm);
- float f = fresnel_dielectric_cos(cosI, eta);
- if(randV < f) {
- *outside = true;
- return -wi + 2.0f * wm * cosI;
- }
- *outside = false;
- float inv_eta = 1.0f/eta;
- float cosT = -safe_sqrtf(1.0f - (1.0f - cosI*cosI) * inv_eta*inv_eta);
- return normalize(wm*(cosI*inv_eta + cosT) - wi*inv_eta);
-}
-
-ccl_device_forceinline float3 mf_eval_phase_glass(const float3 w, const float lambda, const float3 wo, const bool wo_outside, const float2 alpha, const float eta)
-{
- if(w.z > 0.9999f)
- return make_float3(0.0f, 0.0f, 0.0f);
-
- float pArea = (w.z < -0.9999f)? 1.0f: lambda*w.z;
- float v;
- if(wo_outside) {
- const float3 wh = normalize(wo - w);
- if(wh.z < 0.0f)
- return make_float3(0.0f, 0.0f, 0.0f);
-
- const float dotW_WH = dot(-w, wh);
- v = fresnel_dielectric_cos(dotW_WH, eta) * max(0.0f, dotW_WH) * D_ggx(wh, alpha.x) * 0.25f / (pArea * dotW_WH);
- }
- else {
- float3 wh = normalize(wo*eta - w);
- if(wh.z < 0.0f)
- wh = -wh;
- const float dotW_WH = dot(-w, wh), dotWO_WH = dot(wo, wh);
- if(dotW_WH < 0.0f)
- return make_float3(0.0f, 0.0f, 0.0f);
-
- float temp = dotW_WH + eta*dotWO_WH;
- v = (1.0f - fresnel_dielectric_cos(dotW_WH, eta)) * max(0.0f, dotW_WH) * max(0.0f, -dotWO_WH) * D_ggx(wh, alpha.x) / (pArea * temp * temp);
- }
-
- return make_float3(v, v, v);
+ccl_device_forceinline float3 mf_sample_phase_glass(
+ const float3 wi, const float eta, const float3 wm, const float randV, bool *outside)
+{
+ float cosI = dot(wi, wm);
+ float f = fresnel_dielectric_cos(cosI, eta);
+ if (randV < f) {
+ *outside = true;
+ return -wi + 2.0f * wm * cosI;
+ }
+ *outside = false;
+ float inv_eta = 1.0f / eta;
+ float cosT = -safe_sqrtf(1.0f - (1.0f - cosI * cosI) * inv_eta * inv_eta);
+ return normalize(wm * (cosI * inv_eta + cosT) - wi * inv_eta);
+}
+
+ccl_device_forceinline float3 mf_eval_phase_glass(const float3 w,
+ const float lambda,
+ const float3 wo,
+ const bool wo_outside,
+ const float2 alpha,
+ const float eta)
+{
+ if (w.z > 0.9999f)
+ return make_float3(0.0f, 0.0f, 0.0f);
+
+ float pArea = (w.z < -0.9999f) ? 1.0f : lambda * w.z;
+ float v;
+ if (wo_outside) {
+ const float3 wh = normalize(wo - w);
+ if (wh.z < 0.0f)
+ return make_float3(0.0f, 0.0f, 0.0f);
+
+ const float dotW_WH = dot(-w, wh);
+ v = fresnel_dielectric_cos(dotW_WH, eta) * max(0.0f, dotW_WH) * D_ggx(wh, alpha.x) * 0.25f /
+ (pArea * dotW_WH);
+ }
+ else {
+ float3 wh = normalize(wo * eta - w);
+ if (wh.z < 0.0f)
+ wh = -wh;
+ const float dotW_WH = dot(-w, wh), dotWO_WH = dot(wo, wh);
+ if (dotW_WH < 0.0f)
+ return make_float3(0.0f, 0.0f, 0.0f);
+
+ float temp = dotW_WH + eta * dotWO_WH;
+ v = (1.0f - fresnel_dielectric_cos(dotW_WH, eta)) * max(0.0f, dotW_WH) * max(0.0f, -dotWO_WH) *
+ D_ggx(wh, alpha.x) / (pArea * temp * temp);
+ }
+
+ return make_float3(v, v, v);
}
/* === Utility functions for the random walks === */
@@ -173,64 +192,65 @@ ccl_device_forceinline float3 mf_eval_phase_glass(const float3 w, const float la
/* Smith Lambda function for GGX (based on page 12 of the supplemental implementation). */
ccl_device_forceinline float mf_lambda(const float3 w, const float2 alpha)
{
- if(w.z > 0.9999f)
- return 0.0f;
- else if(w.z < -0.9999f)
- return -0.9999f;
+ if (w.z > 0.9999f)
+ return 0.0f;
+ else if (w.z < -0.9999f)
+ return -0.9999f;
- const float inv_wz2 = 1.0f / max(w.z*w.z, 1e-7f);
- const float2 wa = make_float2(w.x, w.y)*alpha;
- float v = sqrtf(1.0f + dot(wa, wa) * inv_wz2);
- if(w.z <= 0.0f)
- v = -v;
+ const float inv_wz2 = 1.0f / max(w.z * w.z, 1e-7f);
+ const float2 wa = make_float2(w.x, w.y) * alpha;
+ float v = sqrtf(1.0f + dot(wa, wa) * inv_wz2);
+ if (w.z <= 0.0f)
+ v = -v;
- return 0.5f*(v - 1.0f);
+ return 0.5f * (v - 1.0f);
}
/* Height distribution CDF (based on page 4 of the supplemental implementation). */
ccl_device_forceinline float mf_invC1(const float h)
{
- return 2.0f * saturate(h) - 1.0f;
+ return 2.0f * saturate(h) - 1.0f;
}
ccl_device_forceinline float mf_C1(const float h)
{
- return saturate(0.5f * (h + 1.0f));
+ return saturate(0.5f * (h + 1.0f));
}
/* Masking function (based on page 16 of the supplemental implementation). */
ccl_device_forceinline float mf_G1(const float3 w, const float C1, const float lambda)
{
- if(w.z > 0.9999f)
- return 1.0f;
- if(w.z < 1e-5f)
- return 0.0f;
- return powf(C1, lambda);
+ if (w.z > 0.9999f)
+ return 1.0f;
+ if (w.z < 1e-5f)
+ return 0.0f;
+ return powf(C1, lambda);
}
/* Sampling from the visible height distribution (based on page 17 of the supplemental implementation). */
-ccl_device_forceinline bool mf_sample_height(const float3 w, float *h, float *C1, float *G1, float *lambda, const float U)
-{
- if(w.z > 0.9999f)
- return false;
- if(w.z < -0.9999f) {
- *C1 *= U;
- *h = mf_invC1(*C1);
- *G1 = mf_G1(w, *C1, *lambda);
- }
- else if(fabsf(w.z) >= 0.0001f) {
- if(U > 1.0f - *G1)
- return false;
- if(*lambda >= 0.0f) {
- *C1 = 1.0f;
- }
- else {
- *C1 *= powf(1.0f-U, -1.0f / *lambda);
- }
- *h = mf_invC1(*C1);
- *G1 = mf_G1(w, *C1, *lambda);
- }
- return true;
+ccl_device_forceinline bool mf_sample_height(
+ const float3 w, float *h, float *C1, float *G1, float *lambda, const float U)
+{
+ if (w.z > 0.9999f)
+ return false;
+ if (w.z < -0.9999f) {
+ *C1 *= U;
+ *h = mf_invC1(*C1);
+ *G1 = mf_G1(w, *C1, *lambda);
+ }
+ else if (fabsf(w.z) >= 0.0001f) {
+ if (U > 1.0f - *G1)
+ return false;
+ if (*lambda >= 0.0f) {
+ *C1 = 1.0f;
+ }
+ else {
+ *C1 *= powf(1.0f - U, -1.0f / *lambda);
+ }
+ *h = mf_invC1(*C1);
+ *G1 = mf_G1(w, *C1, *lambda);
+ }
+ return true;
}
/* === PDF approximations for the different phase functions. ===
@@ -240,80 +260,92 @@ ccl_device_forceinline bool mf_sample_height(const float3 w, float *h, float *C1
* the missing energy is then approximated as a diffuse reflection for the PDF. */
ccl_device_forceinline float mf_ggx_albedo(float r)
{
- float albedo = 0.806495f*expf(-1.98712f*r*r) + 0.199531f;
- albedo -= ((((((1.76741f*r - 8.43891f)*r + 15.784f)*r - 14.398f)*r + 6.45221f)*r - 1.19722f)*r + 0.027803f)*r + 0.00568739f;
- return saturate(albedo);
+ float albedo = 0.806495f * expf(-1.98712f * r * r) + 0.199531f;
+ albedo -= ((((((1.76741f * r - 8.43891f) * r + 15.784f) * r - 14.398f) * r + 6.45221f) * r -
+ 1.19722f) *
+ r +
+ 0.027803f) *
+ r +
+ 0.00568739f;
+ return saturate(albedo);
}
ccl_device_inline float mf_ggx_transmission_albedo(float a, float ior)
{
- if(ior < 1.0f) {
- ior = 1.0f/ior;
- }
- a = saturate(a);
- ior = clamp(ior, 1.0f, 3.0f);
- float I_1 = 0.0476898f*expf(-0.978352f*(ior-0.65657f)*(ior-0.65657f)) - 0.033756f*ior + 0.993261f;
- float R_1 = (((0.116991f*a - 0.270369f)*a + 0.0501366f)*a - 0.00411511f)*a + 1.00008f;
- float I_2 = (((-2.08704f*ior + 26.3298f)*ior - 127.906f)*ior + 292.958f)*ior - 287.946f + 199.803f/(ior*ior) - 101.668f/(ior*ior*ior);
- float R_2 = ((((5.3725f*a -24.9307f)*a + 22.7437f)*a - 3.40751f)*a + 0.0986325f)*a + 0.00493504f;
-
- return saturate(1.0f + I_2*R_2*0.0019127f - (1.0f - I_1)*(1.0f - R_1)*9.3205f);
+ if (ior < 1.0f) {
+ ior = 1.0f / ior;
+ }
+ a = saturate(a);
+ ior = clamp(ior, 1.0f, 3.0f);
+ float I_1 = 0.0476898f * expf(-0.978352f * (ior - 0.65657f) * (ior - 0.65657f)) -
+ 0.033756f * ior + 0.993261f;
+ float R_1 = (((0.116991f * a - 0.270369f) * a + 0.0501366f) * a - 0.00411511f) * a + 1.00008f;
+ float I_2 = (((-2.08704f * ior + 26.3298f) * ior - 127.906f) * ior + 292.958f) * ior - 287.946f +
+ 199.803f / (ior * ior) - 101.668f / (ior * ior * ior);
+ float R_2 = ((((5.3725f * a - 24.9307f) * a + 22.7437f) * a - 3.40751f) * a + 0.0986325f) * a +
+ 0.00493504f;
+
+ return saturate(1.0f + I_2 * R_2 * 0.0019127f - (1.0f - I_1) * (1.0f - R_1) * 9.3205f);
}
ccl_device_forceinline float mf_ggx_pdf(const float3 wi, const float3 wo, const float alpha)
{
- float D = D_ggx(normalize(wi+wo), alpha);
- float lambda = mf_lambda(wi, make_float2(alpha, alpha));
- float singlescatter = 0.25f * D / max((1.0f + lambda) * wi.z, 1e-7f);
+ float D = D_ggx(normalize(wi + wo), alpha);
+ float lambda = mf_lambda(wi, make_float2(alpha, alpha));
+ float singlescatter = 0.25f * D / max((1.0f + lambda) * wi.z, 1e-7f);
- float multiscatter = wo.z * M_1_PI_F;
+ float multiscatter = wo.z * M_1_PI_F;
- float albedo = mf_ggx_albedo(alpha);
- return albedo*singlescatter + (1.0f - albedo)*multiscatter;
+ float albedo = mf_ggx_albedo(alpha);
+ return albedo * singlescatter + (1.0f - albedo) * multiscatter;
}
ccl_device_forceinline float mf_ggx_aniso_pdf(const float3 wi, const float3 wo, const float2 alpha)
{
- float D = D_ggx_aniso(normalize(wi+wo), alpha);
- float lambda = mf_lambda(wi, alpha);
- float singlescatter = 0.25f * D / max((1.0f + lambda) * wi.z, 1e-7f);
+ float D = D_ggx_aniso(normalize(wi + wo), alpha);
+ float lambda = mf_lambda(wi, alpha);
+ float singlescatter = 0.25f * D / max((1.0f + lambda) * wi.z, 1e-7f);
- float multiscatter = wo.z * M_1_PI_F;
+ float multiscatter = wo.z * M_1_PI_F;
- float albedo = mf_ggx_albedo(sqrtf(alpha.x*alpha.y));
- return albedo*singlescatter + (1.0f - albedo)*multiscatter;
+ float albedo = mf_ggx_albedo(sqrtf(alpha.x * alpha.y));
+ return albedo * singlescatter + (1.0f - albedo) * multiscatter;
}
-ccl_device_forceinline float mf_glass_pdf(const float3 wi, const float3 wo, const float alpha, const float eta)
+ccl_device_forceinline float mf_glass_pdf(const float3 wi,
+ const float3 wo,
+ const float alpha,
+ const float eta)
{
- bool reflective = (wi.z*wo.z > 0.0f);
-
- float wh_len;
- float3 wh = normalize_len(wi + (reflective? wo : (wo*eta)), &wh_len);
- if(wh.z < 0.0f)
- wh = -wh;
- float3 r_wi = (wi.z < 0.0f)? -wi: wi;
- float lambda = mf_lambda(r_wi, make_float2(alpha, alpha));
- float D = D_ggx(wh, alpha);
- float fresnel = fresnel_dielectric_cos(dot(r_wi, wh), eta);
-
- float multiscatter = fabsf(wo.z * M_1_PI_F);
- if(reflective) {
- float singlescatter = 0.25f * D / max((1.0f + lambda) * r_wi.z, 1e-7f);
- float albedo = mf_ggx_albedo(alpha);
- return fresnel * (albedo*singlescatter + (1.0f - albedo)*multiscatter);
- }
- else {
- float singlescatter = fabsf(dot(r_wi, wh)*dot(wo, wh) * D * eta*eta / max((1.0f + lambda) * r_wi.z * wh_len*wh_len, 1e-7f));
- float albedo = mf_ggx_transmission_albedo(alpha, eta);
- return (1.0f - fresnel) * (albedo*singlescatter + (1.0f - albedo)*multiscatter);
- }
+ bool reflective = (wi.z * wo.z > 0.0f);
+
+ float wh_len;
+ float3 wh = normalize_len(wi + (reflective ? wo : (wo * eta)), &wh_len);
+ if (wh.z < 0.0f)
+ wh = -wh;
+ float3 r_wi = (wi.z < 0.0f) ? -wi : wi;
+ float lambda = mf_lambda(r_wi, make_float2(alpha, alpha));
+ float D = D_ggx(wh, alpha);
+ float fresnel = fresnel_dielectric_cos(dot(r_wi, wh), eta);
+
+ float multiscatter = fabsf(wo.z * M_1_PI_F);
+ if (reflective) {
+ float singlescatter = 0.25f * D / max((1.0f + lambda) * r_wi.z, 1e-7f);
+ float albedo = mf_ggx_albedo(alpha);
+ return fresnel * (albedo * singlescatter + (1.0f - albedo) * multiscatter);
+ }
+ else {
+ float singlescatter = fabsf(dot(r_wi, wh) * dot(wo, wh) * D * eta * eta /
+ max((1.0f + lambda) * r_wi.z * wh_len * wh_len, 1e-7f));
+ float albedo = mf_ggx_transmission_albedo(alpha, eta);
+ return (1.0f - fresnel) * (albedo * singlescatter + (1.0f - albedo) * multiscatter);
+ }
}
/* === Actual random walk implementations, one version of mf_eval and mf_sample per phase function. === */
-#define MF_NAME_JOIN(x,y) x ## _ ## y
-#define MF_NAME_EVAL(x,y) MF_NAME_JOIN(x,y)
+#define MF_NAME_JOIN(x, y) x##_##y
+#define MF_NAME_EVAL(x, y) MF_NAME_JOIN(x, y)
#define MF_FUNCTION_FULL_NAME(prefix) MF_NAME_EVAL(prefix, MF_PHASE_FUNCTION)
#define MF_PHASE_FUNCTION glass
@@ -326,10 +358,10 @@ ccl_device_forceinline float mf_glass_pdf(const float3 wi, const float3 wo, cons
ccl_device void bsdf_microfacet_multi_ggx_blur(ShaderClosure *sc, float roughness)
{
- MicrofacetBsdf *bsdf = (MicrofacetBsdf*)sc;
+ MicrofacetBsdf *bsdf = (MicrofacetBsdf *)sc;
- bsdf->alpha_x = fmaxf(roughness, bsdf->alpha_x);
- bsdf->alpha_y = fmaxf(roughness, bsdf->alpha_y);
+ bsdf->alpha_x = fmaxf(roughness, bsdf->alpha_x);
+ bsdf->alpha_y = fmaxf(roughness, bsdf->alpha_y);
}
/* === Closure implementations === */
@@ -338,293 +370,395 @@ ccl_device void bsdf_microfacet_multi_ggx_blur(ShaderClosure *sc, float roughnes
ccl_device int bsdf_microfacet_multi_ggx_common_setup(MicrofacetBsdf *bsdf)
{
- bsdf->alpha_x = clamp(bsdf->alpha_x, 1e-4f, 1.0f);
- bsdf->alpha_y = clamp(bsdf->alpha_y, 1e-4f, 1.0f);
- bsdf->extra->color.x = saturate(bsdf->extra->color.x);
- bsdf->extra->color.y = saturate(bsdf->extra->color.y);
- bsdf->extra->color.z = saturate(bsdf->extra->color.z);
- bsdf->extra->cspec0.x = saturate(bsdf->extra->cspec0.x);
- bsdf->extra->cspec0.y = saturate(bsdf->extra->cspec0.y);
- bsdf->extra->cspec0.z = saturate(bsdf->extra->cspec0.z);
+ bsdf->alpha_x = clamp(bsdf->alpha_x, 1e-4f, 1.0f);
+ bsdf->alpha_y = clamp(bsdf->alpha_y, 1e-4f, 1.0f);
+ bsdf->extra->color.x = saturate(bsdf->extra->color.x);
+ bsdf->extra->color.y = saturate(bsdf->extra->color.y);
+ bsdf->extra->color.z = saturate(bsdf->extra->color.z);
+ bsdf->extra->cspec0.x = saturate(bsdf->extra->cspec0.x);
+ bsdf->extra->cspec0.y = saturate(bsdf->extra->cspec0.y);
+ bsdf->extra->cspec0.z = saturate(bsdf->extra->cspec0.z);
- return SD_BSDF|SD_BSDF_HAS_EVAL|SD_BSDF_NEEDS_LCG;
+ return SD_BSDF | SD_BSDF_HAS_EVAL | SD_BSDF_NEEDS_LCG;
}
ccl_device int bsdf_microfacet_multi_ggx_aniso_setup(MicrofacetBsdf *bsdf)
{
- if(is_zero(bsdf->T))
- bsdf->T = make_float3(1.0f, 0.0f, 0.0f);
+ if (is_zero(bsdf->T))
+ bsdf->T = make_float3(1.0f, 0.0f, 0.0f);
- bsdf->type = CLOSURE_BSDF_MICROFACET_MULTI_GGX_ID;
+ bsdf->type = CLOSURE_BSDF_MICROFACET_MULTI_GGX_ID;
- return bsdf_microfacet_multi_ggx_common_setup(bsdf);
+ return bsdf_microfacet_multi_ggx_common_setup(bsdf);
}
-ccl_device int bsdf_microfacet_multi_ggx_aniso_fresnel_setup(MicrofacetBsdf *bsdf, const ShaderData *sd)
+ccl_device int bsdf_microfacet_multi_ggx_aniso_fresnel_setup(MicrofacetBsdf *bsdf,
+ const ShaderData *sd)
{
- if(is_zero(bsdf->T))
- bsdf->T = make_float3(1.0f, 0.0f, 0.0f);
+ if (is_zero(bsdf->T))
+ bsdf->T = make_float3(1.0f, 0.0f, 0.0f);
- bsdf->type = CLOSURE_BSDF_MICROFACET_MULTI_GGX_FRESNEL_ID;
+ bsdf->type = CLOSURE_BSDF_MICROFACET_MULTI_GGX_FRESNEL_ID;
- float F0 = fresnel_dielectric_cos(1.0f, bsdf->ior);
- float F = average(interpolate_fresnel_color(sd->I, bsdf->N, bsdf->ior, F0, bsdf->extra->cspec0));
- bsdf->sample_weight *= F;
+ float F0 = fresnel_dielectric_cos(1.0f, bsdf->ior);
+ float F = average(interpolate_fresnel_color(sd->I, bsdf->N, bsdf->ior, F0, bsdf->extra->cspec0));
+ bsdf->sample_weight *= F;
- return bsdf_microfacet_multi_ggx_common_setup(bsdf);
+ return bsdf_microfacet_multi_ggx_common_setup(bsdf);
}
ccl_device int bsdf_microfacet_multi_ggx_setup(MicrofacetBsdf *bsdf)
{
- bsdf->alpha_y = bsdf->alpha_x;
+ bsdf->alpha_y = bsdf->alpha_x;
- bsdf->type = CLOSURE_BSDF_MICROFACET_MULTI_GGX_ID;
+ bsdf->type = CLOSURE_BSDF_MICROFACET_MULTI_GGX_ID;
- return bsdf_microfacet_multi_ggx_common_setup(bsdf);
+ return bsdf_microfacet_multi_ggx_common_setup(bsdf);
}
ccl_device int bsdf_microfacet_multi_ggx_fresnel_setup(MicrofacetBsdf *bsdf, const ShaderData *sd)
{
- bsdf->alpha_y = bsdf->alpha_x;
+ bsdf->alpha_y = bsdf->alpha_x;
- bsdf->type = CLOSURE_BSDF_MICROFACET_MULTI_GGX_FRESNEL_ID;
+ bsdf->type = CLOSURE_BSDF_MICROFACET_MULTI_GGX_FRESNEL_ID;
- float F0 = fresnel_dielectric_cos(1.0f, bsdf->ior);
- float F = average(interpolate_fresnel_color(sd->I, bsdf->N, bsdf->ior, F0, bsdf->extra->cspec0));
- bsdf->sample_weight *= F;
+ float F0 = fresnel_dielectric_cos(1.0f, bsdf->ior);
+ float F = average(interpolate_fresnel_color(sd->I, bsdf->N, bsdf->ior, F0, bsdf->extra->cspec0));
+ bsdf->sample_weight *= F;
- return bsdf_microfacet_multi_ggx_common_setup(bsdf);
+ return bsdf_microfacet_multi_ggx_common_setup(bsdf);
}
ccl_device int bsdf_microfacet_multi_ggx_refraction_setup(MicrofacetBsdf *bsdf)
{
- bsdf->alpha_y = bsdf->alpha_x;
-
- bsdf->type = CLOSURE_BSDF_MICROFACET_MULTI_GGX_ID;
+ bsdf->alpha_y = bsdf->alpha_x;
- return bsdf_microfacet_multi_ggx_common_setup(bsdf);
-}
+ bsdf->type = CLOSURE_BSDF_MICROFACET_MULTI_GGX_ID;
-ccl_device float3 bsdf_microfacet_multi_ggx_eval_transmit(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf, ccl_addr_space uint *lcg_state) {
- *pdf = 0.0f;
- return make_float3(0.0f, 0.0f, 0.0f);
+ return bsdf_microfacet_multi_ggx_common_setup(bsdf);
}
-ccl_device float3 bsdf_microfacet_multi_ggx_eval_reflect(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf, ccl_addr_space uint *lcg_state) {
- const MicrofacetBsdf *bsdf = (const MicrofacetBsdf*)sc;
-
- if(bsdf->alpha_x*bsdf->alpha_y < 1e-7f) {
- return make_float3(0.0f, 0.0f, 0.0f);
- }
-
- bool use_fresnel = (bsdf->type == CLOSURE_BSDF_MICROFACET_MULTI_GGX_FRESNEL_ID);
-
- bool is_aniso = (bsdf->alpha_x != bsdf->alpha_y);
- float3 X, Y, Z;
- Z = bsdf->N;
- if(is_aniso)
- make_orthonormals_tangent(Z, bsdf->T, &X, &Y);
- else
- make_orthonormals(Z, &X, &Y);
-
- float3 localI = make_float3(dot(I, X), dot(I, Y), dot(I, Z));
- float3 localO = make_float3(dot(omega_in, X), dot(omega_in, Y), dot(omega_in, Z));
-
- if(is_aniso)
- *pdf = mf_ggx_aniso_pdf(localI, localO, make_float2(bsdf->alpha_x, bsdf->alpha_y));
- else
- *pdf = mf_ggx_pdf(localI, localO, bsdf->alpha_x);
- return mf_eval_glossy(localI, localO, true, bsdf->extra->color, bsdf->alpha_x, bsdf->alpha_y, lcg_state, bsdf->ior, use_fresnel, bsdf->extra->cspec0);
+ccl_device float3 bsdf_microfacet_multi_ggx_eval_transmit(const ShaderClosure *sc,
+ const float3 I,
+ const float3 omega_in,
+ float *pdf,
+ ccl_addr_space uint *lcg_state)
+{
+ *pdf = 0.0f;
+ return make_float3(0.0f, 0.0f, 0.0f);
}
-ccl_device int bsdf_microfacet_multi_ggx_sample(KernelGlobals *kg, const ShaderClosure *sc, float3 Ng, float3 I, float3 dIdx, float3 dIdy, float randu, float randv, float3 *eval, float3 *omega_in, float3 *domega_in_dx, float3 *domega_in_dy, float *pdf, ccl_addr_space uint *lcg_state)
+ccl_device float3 bsdf_microfacet_multi_ggx_eval_reflect(const ShaderClosure *sc,
+ const float3 I,
+ const float3 omega_in,
+ float *pdf,
+ ccl_addr_space uint *lcg_state)
{
- const MicrofacetBsdf *bsdf = (const MicrofacetBsdf*)sc;
+ const MicrofacetBsdf *bsdf = (const MicrofacetBsdf *)sc;
+
+ if (bsdf->alpha_x * bsdf->alpha_y < 1e-7f) {
+ return make_float3(0.0f, 0.0f, 0.0f);
+ }
+
+ bool use_fresnel = (bsdf->type == CLOSURE_BSDF_MICROFACET_MULTI_GGX_FRESNEL_ID);
+
+ bool is_aniso = (bsdf->alpha_x != bsdf->alpha_y);
+ float3 X, Y, Z;
+ Z = bsdf->N;
+ if (is_aniso)
+ make_orthonormals_tangent(Z, bsdf->T, &X, &Y);
+ else
+ make_orthonormals(Z, &X, &Y);
+
+ float3 localI = make_float3(dot(I, X), dot(I, Y), dot(I, Z));
+ float3 localO = make_float3(dot(omega_in, X), dot(omega_in, Y), dot(omega_in, Z));
+
+ if (is_aniso)
+ *pdf = mf_ggx_aniso_pdf(localI, localO, make_float2(bsdf->alpha_x, bsdf->alpha_y));
+ else
+ *pdf = mf_ggx_pdf(localI, localO, bsdf->alpha_x);
+ return mf_eval_glossy(localI,
+ localO,
+ true,
+ bsdf->extra->color,
+ bsdf->alpha_x,
+ bsdf->alpha_y,
+ lcg_state,
+ bsdf->ior,
+ use_fresnel,
+ bsdf->extra->cspec0);
+}
+
+ccl_device int bsdf_microfacet_multi_ggx_sample(KernelGlobals *kg,
+ const ShaderClosure *sc,
+ float3 Ng,
+ float3 I,
+ float3 dIdx,
+ float3 dIdy,
+ float randu,
+ float randv,
+ float3 *eval,
+ float3 *omega_in,
+ float3 *domega_in_dx,
+ float3 *domega_in_dy,
+ float *pdf,
+ ccl_addr_space uint *lcg_state)
+{
+ const MicrofacetBsdf *bsdf = (const MicrofacetBsdf *)sc;
- float3 X, Y, Z;
- Z = bsdf->N;
+ float3 X, Y, Z;
+ Z = bsdf->N;
- if(bsdf->alpha_x*bsdf->alpha_y < 1e-7f) {
- *omega_in = 2*dot(Z, I)*Z - I;
- *pdf = 1e6f;
- *eval = make_float3(1e6f, 1e6f, 1e6f);
+ if (bsdf->alpha_x * bsdf->alpha_y < 1e-7f) {
+ *omega_in = 2 * dot(Z, I) * Z - I;
+ *pdf = 1e6f;
+ *eval = make_float3(1e6f, 1e6f, 1e6f);
#ifdef __RAY_DIFFERENTIALS__
- *domega_in_dx = (2 * dot(Z, dIdx)) * Z - dIdx;
- *domega_in_dy = (2 * dot(Z, dIdy)) * Z - dIdy;
+ *domega_in_dx = (2 * dot(Z, dIdx)) * Z - dIdx;
+ *domega_in_dy = (2 * dot(Z, dIdy)) * Z - dIdy;
#endif
- return LABEL_REFLECT|LABEL_SINGULAR;
- }
-
- bool use_fresnel = (bsdf->type == CLOSURE_BSDF_MICROFACET_MULTI_GGX_FRESNEL_ID);
-
- bool is_aniso = (bsdf->alpha_x != bsdf->alpha_y);
- if(is_aniso)
- make_orthonormals_tangent(Z, bsdf->T, &X, &Y);
- else
- make_orthonormals(Z, &X, &Y);
-
- float3 localI = make_float3(dot(I, X), dot(I, Y), dot(I, Z));
- float3 localO;
-
- *eval = mf_sample_glossy(localI, &localO, bsdf->extra->color, bsdf->alpha_x, bsdf->alpha_y, lcg_state, bsdf->ior, use_fresnel, bsdf->extra->cspec0);
- if(is_aniso)
- *pdf = mf_ggx_aniso_pdf(localI, localO, make_float2(bsdf->alpha_x, bsdf->alpha_y));
- else
- *pdf = mf_ggx_pdf(localI, localO, bsdf->alpha_x);
- *eval *= *pdf;
-
- *omega_in = X*localO.x + Y*localO.y + Z*localO.z;
+ return LABEL_REFLECT | LABEL_SINGULAR;
+ }
+
+ bool use_fresnel = (bsdf->type == CLOSURE_BSDF_MICROFACET_MULTI_GGX_FRESNEL_ID);
+
+ bool is_aniso = (bsdf->alpha_x != bsdf->alpha_y);
+ if (is_aniso)
+ make_orthonormals_tangent(Z, bsdf->T, &X, &Y);
+ else
+ make_orthonormals(Z, &X, &Y);
+
+ float3 localI = make_float3(dot(I, X), dot(I, Y), dot(I, Z));
+ float3 localO;
+
+ *eval = mf_sample_glossy(localI,
+ &localO,
+ bsdf->extra->color,
+ bsdf->alpha_x,
+ bsdf->alpha_y,
+ lcg_state,
+ bsdf->ior,
+ use_fresnel,
+ bsdf->extra->cspec0);
+ if (is_aniso)
+ *pdf = mf_ggx_aniso_pdf(localI, localO, make_float2(bsdf->alpha_x, bsdf->alpha_y));
+ else
+ *pdf = mf_ggx_pdf(localI, localO, bsdf->alpha_x);
+ *eval *= *pdf;
+
+ *omega_in = X * localO.x + Y * localO.y + Z * localO.z;
#ifdef __RAY_DIFFERENTIALS__
- *domega_in_dx = (2 * dot(Z, dIdx)) * Z - dIdx;
- *domega_in_dy = (2 * dot(Z, dIdy)) * Z - dIdy;
+ *domega_in_dx = (2 * dot(Z, dIdx)) * Z - dIdx;
+ *domega_in_dy = (2 * dot(Z, dIdy)) * Z - dIdy;
#endif
- return LABEL_REFLECT|LABEL_GLOSSY;
+ return LABEL_REFLECT | LABEL_GLOSSY;
}
/* Multiscattering GGX Glass closure */
ccl_device int bsdf_microfacet_multi_ggx_glass_setup(MicrofacetBsdf *bsdf)
{
- bsdf->alpha_x = clamp(bsdf->alpha_x, 1e-4f, 1.0f);
- bsdf->alpha_y = bsdf->alpha_x;
- bsdf->ior = max(0.0f, bsdf->ior);
- bsdf->extra->color.x = saturate(bsdf->extra->color.x);
- bsdf->extra->color.y = saturate(bsdf->extra->color.y);
- bsdf->extra->color.z = saturate(bsdf->extra->color.z);
+ bsdf->alpha_x = clamp(bsdf->alpha_x, 1e-4f, 1.0f);
+ bsdf->alpha_y = bsdf->alpha_x;
+ bsdf->ior = max(0.0f, bsdf->ior);
+ bsdf->extra->color.x = saturate(bsdf->extra->color.x);
+ bsdf->extra->color.y = saturate(bsdf->extra->color.y);
+ bsdf->extra->color.z = saturate(bsdf->extra->color.z);
- bsdf->type = CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID;
+ bsdf->type = CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID;
- return SD_BSDF|SD_BSDF_HAS_EVAL|SD_BSDF_NEEDS_LCG;
+ return SD_BSDF | SD_BSDF_HAS_EVAL | SD_BSDF_NEEDS_LCG;
}
-ccl_device int bsdf_microfacet_multi_ggx_glass_fresnel_setup(MicrofacetBsdf *bsdf, const ShaderData *sd)
+ccl_device int bsdf_microfacet_multi_ggx_glass_fresnel_setup(MicrofacetBsdf *bsdf,
+ const ShaderData *sd)
{
- bsdf->alpha_x = clamp(bsdf->alpha_x, 1e-4f, 1.0f);
- bsdf->alpha_y = bsdf->alpha_x;
- bsdf->ior = max(0.0f, bsdf->ior);
- bsdf->extra->color.x = saturate(bsdf->extra->color.x);
- bsdf->extra->color.y = saturate(bsdf->extra->color.y);
- bsdf->extra->color.z = saturate(bsdf->extra->color.z);
- bsdf->extra->cspec0.x = saturate(bsdf->extra->cspec0.x);
- bsdf->extra->cspec0.y = saturate(bsdf->extra->cspec0.y);
- bsdf->extra->cspec0.z = saturate(bsdf->extra->cspec0.z);
-
- bsdf->type = CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_FRESNEL_ID;
-
- float F0 = fresnel_dielectric_cos(1.0f, bsdf->ior);
- float F = average(interpolate_fresnel_color(sd->I, bsdf->N, bsdf->ior, F0, bsdf->extra->cspec0));
- bsdf->sample_weight *= F;
-
- return SD_BSDF|SD_BSDF_HAS_EVAL|SD_BSDF_NEEDS_LCG;
-}
-
-ccl_device float3 bsdf_microfacet_multi_ggx_glass_eval_transmit(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf, ccl_addr_space uint *lcg_state) {
- const MicrofacetBsdf *bsdf = (const MicrofacetBsdf*)sc;
-
- if(bsdf->alpha_x*bsdf->alpha_y < 1e-7f) {
- return make_float3(0.0f, 0.0f, 0.0f);
- }
-
- float3 X, Y, Z;
- Z = bsdf->N;
- make_orthonormals(Z, &X, &Y);
-
- float3 localI = make_float3(dot(I, X), dot(I, Y), dot(I, Z));
- float3 localO = make_float3(dot(omega_in, X), dot(omega_in, Y), dot(omega_in, Z));
-
- *pdf = mf_glass_pdf(localI, localO, bsdf->alpha_x, bsdf->ior);
- return mf_eval_glass(localI, localO, false, bsdf->extra->color, bsdf->alpha_x, bsdf->alpha_y, lcg_state, bsdf->ior, false, bsdf->extra->color);
-}
-
-ccl_device float3 bsdf_microfacet_multi_ggx_glass_eval_reflect(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf, ccl_addr_space uint *lcg_state) {
- const MicrofacetBsdf *bsdf = (const MicrofacetBsdf*)sc;
-
- if(bsdf->alpha_x*bsdf->alpha_y < 1e-7f) {
- return make_float3(0.0f, 0.0f, 0.0f);
- }
-
- bool use_fresnel = (bsdf->type == CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_FRESNEL_ID);
-
- float3 X, Y, Z;
- Z = bsdf->N;
- make_orthonormals(Z, &X, &Y);
-
- float3 localI = make_float3(dot(I, X), dot(I, Y), dot(I, Z));
- float3 localO = make_float3(dot(omega_in, X), dot(omega_in, Y), dot(omega_in, Z));
-
- *pdf = mf_glass_pdf(localI, localO, bsdf->alpha_x, bsdf->ior);
- return mf_eval_glass(localI, localO, true, bsdf->extra->color, bsdf->alpha_x, bsdf->alpha_y, lcg_state, bsdf->ior, use_fresnel, bsdf->extra->cspec0);
-}
-
-ccl_device int bsdf_microfacet_multi_ggx_glass_sample(KernelGlobals *kg, const ShaderClosure *sc, float3 Ng, float3 I, float3 dIdx, float3 dIdy, float randu, float randv, float3 *eval, float3 *omega_in, float3 *domega_in_dx, float3 *domega_in_dy, float *pdf, ccl_addr_space uint *lcg_state)
+ bsdf->alpha_x = clamp(bsdf->alpha_x, 1e-4f, 1.0f);
+ bsdf->alpha_y = bsdf->alpha_x;
+ bsdf->ior = max(0.0f, bsdf->ior);
+ bsdf->extra->color.x = saturate(bsdf->extra->color.x);
+ bsdf->extra->color.y = saturate(bsdf->extra->color.y);
+ bsdf->extra->color.z = saturate(bsdf->extra->color.z);
+ bsdf->extra->cspec0.x = saturate(bsdf->extra->cspec0.x);
+ bsdf->extra->cspec0.y = saturate(bsdf->extra->cspec0.y);
+ bsdf->extra->cspec0.z = saturate(bsdf->extra->cspec0.z);
+
+ bsdf->type = CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_FRESNEL_ID;
+
+ float F0 = fresnel_dielectric_cos(1.0f, bsdf->ior);
+ float F = average(interpolate_fresnel_color(sd->I, bsdf->N, bsdf->ior, F0, bsdf->extra->cspec0));
+ bsdf->sample_weight *= F;
+
+ return SD_BSDF | SD_BSDF_HAS_EVAL | SD_BSDF_NEEDS_LCG;
+}
+
+ccl_device float3 bsdf_microfacet_multi_ggx_glass_eval_transmit(const ShaderClosure *sc,
+ const float3 I,
+ const float3 omega_in,
+ float *pdf,
+ ccl_addr_space uint *lcg_state)
+{
+ const MicrofacetBsdf *bsdf = (const MicrofacetBsdf *)sc;
+
+ if (bsdf->alpha_x * bsdf->alpha_y < 1e-7f) {
+ return make_float3(0.0f, 0.0f, 0.0f);
+ }
+
+ float3 X, Y, Z;
+ Z = bsdf->N;
+ make_orthonormals(Z, &X, &Y);
+
+ float3 localI = make_float3(dot(I, X), dot(I, Y), dot(I, Z));
+ float3 localO = make_float3(dot(omega_in, X), dot(omega_in, Y), dot(omega_in, Z));
+
+ *pdf = mf_glass_pdf(localI, localO, bsdf->alpha_x, bsdf->ior);
+ return mf_eval_glass(localI,
+ localO,
+ false,
+ bsdf->extra->color,
+ bsdf->alpha_x,
+ bsdf->alpha_y,
+ lcg_state,
+ bsdf->ior,
+ false,
+ bsdf->extra->color);
+}
+
+ccl_device float3 bsdf_microfacet_multi_ggx_glass_eval_reflect(const ShaderClosure *sc,
+ const float3 I,
+ const float3 omega_in,
+ float *pdf,
+ ccl_addr_space uint *lcg_state)
+{
+ const MicrofacetBsdf *bsdf = (const MicrofacetBsdf *)sc;
+
+ if (bsdf->alpha_x * bsdf->alpha_y < 1e-7f) {
+ return make_float3(0.0f, 0.0f, 0.0f);
+ }
+
+ bool use_fresnel = (bsdf->type == CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_FRESNEL_ID);
+
+ float3 X, Y, Z;
+ Z = bsdf->N;
+ make_orthonormals(Z, &X, &Y);
+
+ float3 localI = make_float3(dot(I, X), dot(I, Y), dot(I, Z));
+ float3 localO = make_float3(dot(omega_in, X), dot(omega_in, Y), dot(omega_in, Z));
+
+ *pdf = mf_glass_pdf(localI, localO, bsdf->alpha_x, bsdf->ior);
+ return mf_eval_glass(localI,
+ localO,
+ true,
+ bsdf->extra->color,
+ bsdf->alpha_x,
+ bsdf->alpha_y,
+ lcg_state,
+ bsdf->ior,
+ use_fresnel,
+ bsdf->extra->cspec0);
+}
+
+ccl_device int bsdf_microfacet_multi_ggx_glass_sample(KernelGlobals *kg,
+ const ShaderClosure *sc,
+ float3 Ng,
+ float3 I,
+ float3 dIdx,
+ float3 dIdy,
+ float randu,
+ float randv,
+ float3 *eval,
+ float3 *omega_in,
+ float3 *domega_in_dx,
+ float3 *domega_in_dy,
+ float *pdf,
+ ccl_addr_space uint *lcg_state)
{
- const MicrofacetBsdf *bsdf = (const MicrofacetBsdf*)sc;
+ const MicrofacetBsdf *bsdf = (const MicrofacetBsdf *)sc;
- float3 X, Y, Z;
- Z = bsdf->N;
+ float3 X, Y, Z;
+ Z = bsdf->N;
- if(bsdf->alpha_x*bsdf->alpha_y < 1e-7f) {
- float3 R, T;
+ if (bsdf->alpha_x * bsdf->alpha_y < 1e-7f) {
+ float3 R, T;
#ifdef __RAY_DIFFERENTIALS__
- float3 dRdx, dRdy, dTdx, dTdy;
+ float3 dRdx, dRdy, dTdx, dTdy;
#endif
- bool inside;
- float fresnel = fresnel_dielectric(bsdf->ior, Z, I, &R, &T,
+ bool inside;
+ float fresnel = fresnel_dielectric(bsdf->ior,
+ Z,
+ I,
+ &R,
+ &T,
#ifdef __RAY_DIFFERENTIALS__
- dIdx, dIdy, &dRdx, &dRdy, &dTdx, &dTdy,
+ dIdx,
+ dIdy,
+ &dRdx,
+ &dRdy,
+ &dTdx,
+ &dTdy,
#endif
- &inside);
+ &inside);
- *pdf = 1e6f;
- *eval = make_float3(1e6f, 1e6f, 1e6f);
- if(randu < fresnel) {
- *omega_in = R;
+ *pdf = 1e6f;
+ *eval = make_float3(1e6f, 1e6f, 1e6f);
+ if (randu < fresnel) {
+ *omega_in = R;
#ifdef __RAY_DIFFERENTIALS__
- *domega_in_dx = dRdx;
- *domega_in_dy = dRdy;
+ *domega_in_dx = dRdx;
+ *domega_in_dy = dRdy;
#endif
- return LABEL_REFLECT|LABEL_SINGULAR;
- }
- else {
- *omega_in = T;
+ return LABEL_REFLECT | LABEL_SINGULAR;
+ }
+ else {
+ *omega_in = T;
#ifdef __RAY_DIFFERENTIALS__
- *domega_in_dx = dTdx;
- *domega_in_dy = dTdy;
+ *domega_in_dx = dTdx;
+ *domega_in_dy = dTdy;
#endif
- return LABEL_TRANSMIT|LABEL_SINGULAR;
- }
- }
-
- bool use_fresnel = (bsdf->type == CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_FRESNEL_ID);
-
- make_orthonormals(Z, &X, &Y);
-
- float3 localI = make_float3(dot(I, X), dot(I, Y), dot(I, Z));
- float3 localO;
-
- *eval = mf_sample_glass(localI, &localO, bsdf->extra->color, bsdf->alpha_x, bsdf->alpha_y, lcg_state, bsdf->ior, use_fresnel, bsdf->extra->cspec0);
- *pdf = mf_glass_pdf(localI, localO, bsdf->alpha_x, bsdf->ior);
- *eval *= *pdf;
-
- *omega_in = X*localO.x + Y*localO.y + Z*localO.z;
- if(localO.z*localI.z > 0.0f) {
+ return LABEL_TRANSMIT | LABEL_SINGULAR;
+ }
+ }
+
+ bool use_fresnel = (bsdf->type == CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_FRESNEL_ID);
+
+ make_orthonormals(Z, &X, &Y);
+
+ float3 localI = make_float3(dot(I, X), dot(I, Y), dot(I, Z));
+ float3 localO;
+
+ *eval = mf_sample_glass(localI,
+ &localO,
+ bsdf->extra->color,
+ bsdf->alpha_x,
+ bsdf->alpha_y,
+ lcg_state,
+ bsdf->ior,
+ use_fresnel,
+ bsdf->extra->cspec0);
+ *pdf = mf_glass_pdf(localI, localO, bsdf->alpha_x, bsdf->ior);
+ *eval *= *pdf;
+
+ *omega_in = X * localO.x + Y * localO.y + Z * localO.z;
+ if (localO.z * localI.z > 0.0f) {
#ifdef __RAY_DIFFERENTIALS__
- *domega_in_dx = (2 * dot(Z, dIdx)) * Z - dIdx;
- *domega_in_dy = (2 * dot(Z, dIdy)) * Z - dIdy;
+ *domega_in_dx = (2 * dot(Z, dIdx)) * Z - dIdx;
+ *domega_in_dy = (2 * dot(Z, dIdy)) * Z - dIdy;
#endif
- return LABEL_REFLECT|LABEL_GLOSSY;
- }
- else {
+ return LABEL_REFLECT | LABEL_GLOSSY;
+ }
+ else {
#ifdef __RAY_DIFFERENTIALS__
- float cosI = dot(Z, I);
- float dnp = max(sqrtf(1.0f - (bsdf->ior * bsdf->ior * (1.0f - cosI*cosI))), 1e-7f);
- *domega_in_dx = -(bsdf->ior * dIdx) + ((bsdf->ior - bsdf->ior * bsdf->ior * cosI / dnp) * dot(dIdx, Z)) * Z;
- *domega_in_dy = -(bsdf->ior * dIdy) + ((bsdf->ior - bsdf->ior * bsdf->ior * cosI / dnp) * dot(dIdy, Z)) * Z;
+ float cosI = dot(Z, I);
+ float dnp = max(sqrtf(1.0f - (bsdf->ior * bsdf->ior * (1.0f - cosI * cosI))), 1e-7f);
+ *domega_in_dx = -(bsdf->ior * dIdx) +
+ ((bsdf->ior - bsdf->ior * bsdf->ior * cosI / dnp) * dot(dIdx, Z)) * Z;
+ *domega_in_dy = -(bsdf->ior * dIdy) +
+ ((bsdf->ior - bsdf->ior * bsdf->ior * cosI / dnp) * dot(dIdy, Z)) * Z;
#endif
- return LABEL_TRANSMIT|LABEL_GLOSSY;
- }
+ return LABEL_TRANSMIT | LABEL_GLOSSY;
+ }
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/closure/bsdf_microfacet_multi_impl.h b/intern/cycles/kernel/closure/bsdf_microfacet_multi_impl.h
index 5d300ef6db5..79247ee8057 100644
--- a/intern/cycles/kernel/closure/bsdf_microfacet_multi_impl.h
+++ b/intern/cycles/kernel/closure/bsdf_microfacet_multi_impl.h
@@ -25,247 +25,251 @@
* energy is used. In combination with MIS, that is enough to produce an unbiased result, although
* the balance heuristic isn't necessarily optimal anymore.
*/
-ccl_device_forceinline float3 MF_FUNCTION_FULL_NAME(mf_eval)(
- float3 wi,
- float3 wo,
- const bool wo_outside,
- const float3 color,
- const float alpha_x,
- const float alpha_y,
- ccl_addr_space uint *lcg_state,
- const float eta,
- bool use_fresnel,
- const float3 cspec0)
+ccl_device_forceinline float3 MF_FUNCTION_FULL_NAME(mf_eval)(float3 wi,
+ float3 wo,
+ const bool wo_outside,
+ const float3 color,
+ const float alpha_x,
+ const float alpha_y,
+ ccl_addr_space uint *lcg_state,
+ const float eta,
+ bool use_fresnel,
+ const float3 cspec0)
{
- /* Evaluating for a shallower incoming direction produces less noise, and the properties of the BSDF guarantee reciprocity. */
- bool swapped = false;
+ /* Evaluating for a shallower incoming direction produces less noise, and the properties of the BSDF guarantee reciprocity. */
+ bool swapped = false;
#ifdef MF_MULTI_GLASS
- if(wi.z*wo.z < 0.0f) {
- /* Glass transmission is a special case and requires the directions to change hemisphere. */
- if(-wo.z < wi.z) {
- swapped = true;
- float3 tmp = -wo;
- wo = -wi;
- wi = tmp;
- }
- }
- else
+ if (wi.z * wo.z < 0.0f) {
+ /* Glass transmission is a special case and requires the directions to change hemisphere. */
+ if (-wo.z < wi.z) {
+ swapped = true;
+ float3 tmp = -wo;
+ wo = -wi;
+ wi = tmp;
+ }
+ }
+ else
#endif
- if(wo.z < wi.z) {
- swapped = true;
- float3 tmp = wo;
- wo = wi;
- wi = tmp;
- }
+ if (wo.z < wi.z) {
+ swapped = true;
+ float3 tmp = wo;
+ wo = wi;
+ wi = tmp;
+ }
- if(wi.z < 1e-5f || (wo.z < 1e-5f && wo_outside) || (wo.z > -1e-5f && !wo_outside))
- return make_float3(0.0f, 0.0f, 0.0f);
+ if (wi.z < 1e-5f || (wo.z < 1e-5f && wo_outside) || (wo.z > -1e-5f && !wo_outside))
+ return make_float3(0.0f, 0.0f, 0.0f);
- const float2 alpha = make_float2(alpha_x, alpha_y);
+ const float2 alpha = make_float2(alpha_x, alpha_y);
- float lambda_r = mf_lambda(-wi, alpha);
- float shadowing_lambda = mf_lambda(wo_outside? wo: -wo, alpha);
+ float lambda_r = mf_lambda(-wi, alpha);
+ float shadowing_lambda = mf_lambda(wo_outside ? wo : -wo, alpha);
- /* Analytically compute single scattering for lower noise. */
- float3 eval;
- float3 throughput = make_float3(1.0f, 1.0f, 1.0f);
- const float3 wh = normalize(wi+wo);
+ /* Analytically compute single scattering for lower noise. */
+ float3 eval;
+ float3 throughput = make_float3(1.0f, 1.0f, 1.0f);
+ const float3 wh = normalize(wi + wo);
#ifdef MF_MULTI_GLASS
- eval = mf_eval_phase_glass(-wi, lambda_r, wo, wo_outside, alpha, eta);
- if(wo_outside)
- eval *= -lambda_r / (shadowing_lambda - lambda_r);
- else
- eval *= -lambda_r * beta(-lambda_r, shadowing_lambda+1.0f);
-#else /* MF_MULTI_GLOSSY */
- const float G2 = 1.0f / (1.0f - (lambda_r + 1.0f) + shadowing_lambda);
- float val = G2 * 0.25f / wi.z;
- if(alpha.x == alpha.y)
- val *= D_ggx(wh, alpha.x);
- else
- val *= D_ggx_aniso(wh, alpha);
- eval = make_float3(val, val, val);
+ eval = mf_eval_phase_glass(-wi, lambda_r, wo, wo_outside, alpha, eta);
+ if (wo_outside)
+ eval *= -lambda_r / (shadowing_lambda - lambda_r);
+ else
+ eval *= -lambda_r * beta(-lambda_r, shadowing_lambda + 1.0f);
+#else /* MF_MULTI_GLOSSY */
+ const float G2 = 1.0f / (1.0f - (lambda_r + 1.0f) + shadowing_lambda);
+ float val = G2 * 0.25f / wi.z;
+ if (alpha.x == alpha.y)
+ val *= D_ggx(wh, alpha.x);
+ else
+ val *= D_ggx_aniso(wh, alpha);
+ eval = make_float3(val, val, val);
#endif
- float F0 = fresnel_dielectric_cos(1.0f, eta);
- if(use_fresnel) {
- throughput = interpolate_fresnel_color(wi, wh, eta, F0, cspec0);
+ float F0 = fresnel_dielectric_cos(1.0f, eta);
+ if (use_fresnel) {
+ throughput = interpolate_fresnel_color(wi, wh, eta, F0, cspec0);
- eval *= throughput;
- }
+ eval *= throughput;
+ }
- float3 wr = -wi;
- float hr = 1.0f;
- float C1_r = 1.0f;
- float G1_r = 0.0f;
- bool outside = true;
+ float3 wr = -wi;
+ float hr = 1.0f;
+ float C1_r = 1.0f;
+ float G1_r = 0.0f;
+ bool outside = true;
- for(int order = 0; order < 10; order++) {
- /* Sample microfacet height. */
- float height_rand = lcg_step_float_addrspace(lcg_state);
- if(!mf_sample_height(wr, &hr, &C1_r, &G1_r, &lambda_r, height_rand))
- break;
- /* Sample microfacet normal. */
- float vndf_rand_y = lcg_step_float_addrspace(lcg_state);
- float vndf_rand_x = lcg_step_float_addrspace(lcg_state);
- float3 wm = mf_sample_vndf(-wr, alpha, vndf_rand_x, vndf_rand_y);
+ for (int order = 0; order < 10; order++) {
+ /* Sample microfacet height. */
+ float height_rand = lcg_step_float_addrspace(lcg_state);
+ if (!mf_sample_height(wr, &hr, &C1_r, &G1_r, &lambda_r, height_rand))
+ break;
+ /* Sample microfacet normal. */
+ float vndf_rand_y = lcg_step_float_addrspace(lcg_state);
+ float vndf_rand_x = lcg_step_float_addrspace(lcg_state);
+ float3 wm = mf_sample_vndf(-wr, alpha, vndf_rand_x, vndf_rand_y);
#ifdef MF_MULTI_GLASS
- if(order == 0 && use_fresnel) {
- /* Evaluate amount of scattering towards wo on this microfacet. */
- float3 phase;
- if(outside)
- phase = mf_eval_phase_glass(wr, lambda_r, wo, wo_outside, alpha, eta);
- else
- phase = mf_eval_phase_glass(wr, lambda_r, -wo, !wo_outside, alpha, 1.0f / eta);
+ if (order == 0 && use_fresnel) {
+ /* Evaluate amount of scattering towards wo on this microfacet. */
+ float3 phase;
+ if (outside)
+ phase = mf_eval_phase_glass(wr, lambda_r, wo, wo_outside, alpha, eta);
+ else
+ phase = mf_eval_phase_glass(wr, lambda_r, -wo, !wo_outside, alpha, 1.0f / eta);
- eval = throughput * phase * mf_G1(wo_outside ? wo : -wo, mf_C1((outside == wo_outside) ? hr : -hr), shadowing_lambda);
- }
+ eval = throughput * phase *
+ mf_G1(wo_outside ? wo : -wo,
+ mf_C1((outside == wo_outside) ? hr : -hr),
+ shadowing_lambda);
+ }
#endif
- if(order > 0) {
- /* Evaluate amount of scattering towards wo on this microfacet. */
- float3 phase;
+ if (order > 0) {
+ /* Evaluate amount of scattering towards wo on this microfacet. */
+ float3 phase;
#ifdef MF_MULTI_GLASS
- if(outside)
- phase = mf_eval_phase_glass(wr, lambda_r, wo, wo_outside, alpha, eta);
- else
- phase = mf_eval_phase_glass(wr, lambda_r, -wo, !wo_outside, alpha, 1.0f/eta);
-#else /* MF_MULTI_GLOSSY */
- phase = mf_eval_phase_glossy(wr, lambda_r, wo, alpha) * throughput;
+ if (outside)
+ phase = mf_eval_phase_glass(wr, lambda_r, wo, wo_outside, alpha, eta);
+ else
+ phase = mf_eval_phase_glass(wr, lambda_r, -wo, !wo_outside, alpha, 1.0f / eta);
+#else /* MF_MULTI_GLOSSY */
+ phase = mf_eval_phase_glossy(wr, lambda_r, wo, alpha) * throughput;
#endif
- eval += throughput * phase * mf_G1(wo_outside? wo: -wo, mf_C1((outside == wo_outside)? hr: -hr), shadowing_lambda);
- }
- if(order+1 < 10) {
- /* Bounce from the microfacet. */
+ eval += throughput * phase *
+ mf_G1(wo_outside ? wo : -wo,
+ mf_C1((outside == wo_outside) ? hr : -hr),
+ shadowing_lambda);
+ }
+ if (order + 1 < 10) {
+ /* Bounce from the microfacet. */
#ifdef MF_MULTI_GLASS
- bool next_outside;
- float3 wi_prev = -wr;
- float phase_rand = lcg_step_float_addrspace(lcg_state);
- wr = mf_sample_phase_glass(-wr, outside? eta: 1.0f/eta, wm, phase_rand, &next_outside);
- if(!next_outside) {
- outside = !outside;
- wr = -wr;
- hr = -hr;
- }
+ bool next_outside;
+ float3 wi_prev = -wr;
+ float phase_rand = lcg_step_float_addrspace(lcg_state);
+ wr = mf_sample_phase_glass(-wr, outside ? eta : 1.0f / eta, wm, phase_rand, &next_outside);
+ if (!next_outside) {
+ outside = !outside;
+ wr = -wr;
+ hr = -hr;
+ }
- if(use_fresnel && !next_outside) {
- throughput *= color;
- }
- else if(use_fresnel && order > 0) {
- throughput *= interpolate_fresnel_color(wi_prev, wm, eta, F0, cspec0);
- }
-#else /* MF_MULTI_GLOSSY */
- if(use_fresnel && order > 0) {
- throughput *= interpolate_fresnel_color(-wr, wm, eta, F0, cspec0);
- }
- wr = mf_sample_phase_glossy(-wr, &throughput, wm);
+ if (use_fresnel && !next_outside) {
+ throughput *= color;
+ }
+ else if (use_fresnel && order > 0) {
+ throughput *= interpolate_fresnel_color(wi_prev, wm, eta, F0, cspec0);
+ }
+#else /* MF_MULTI_GLOSSY */
+ if (use_fresnel && order > 0) {
+ throughput *= interpolate_fresnel_color(-wr, wm, eta, F0, cspec0);
+ }
+ wr = mf_sample_phase_glossy(-wr, &throughput, wm);
#endif
- lambda_r = mf_lambda(wr, alpha);
+ lambda_r = mf_lambda(wr, alpha);
- if(!use_fresnel)
- throughput *= color;
+ if (!use_fresnel)
+ throughput *= color;
- C1_r = mf_C1(hr);
- G1_r = mf_G1(wr, C1_r, lambda_r);
- }
- }
+ C1_r = mf_C1(hr);
+ G1_r = mf_G1(wr, C1_r, lambda_r);
+ }
+ }
- if(swapped)
- eval *= fabsf(wi.z / wo.z);
- return eval;
+ if (swapped)
+ eval *= fabsf(wi.z / wo.z);
+ return eval;
}
/* Perform a random walk on the microsurface starting from wi, returning the direction in which the walk
* escaped the surface in wo. The function returns the throughput between wi and wo.
* Without reflection losses due to coloring or fresnel absorption in conductors, the sampling is optimal.
*/
-ccl_device_forceinline float3 MF_FUNCTION_FULL_NAME(mf_sample)(
- float3 wi,
- float3 *wo,
- const float3 color,
- const float alpha_x,
- const float alpha_y,
- ccl_addr_space uint *lcg_state,
- const float eta,
- bool use_fresnel,
- const float3 cspec0)
+ccl_device_forceinline float3 MF_FUNCTION_FULL_NAME(mf_sample)(float3 wi,
+ float3 *wo,
+ const float3 color,
+ const float alpha_x,
+ const float alpha_y,
+ ccl_addr_space uint *lcg_state,
+ const float eta,
+ bool use_fresnel,
+ const float3 cspec0)
{
- const float2 alpha = make_float2(alpha_x, alpha_y);
+ const float2 alpha = make_float2(alpha_x, alpha_y);
- float3 throughput = make_float3(1.0f, 1.0f, 1.0f);
- float3 wr = -wi;
- float lambda_r = mf_lambda(wr, alpha);
- float hr = 1.0f;
- float C1_r = 1.0f;
- float G1_r = 0.0f;
- bool outside = true;
+ float3 throughput = make_float3(1.0f, 1.0f, 1.0f);
+ float3 wr = -wi;
+ float lambda_r = mf_lambda(wr, alpha);
+ float hr = 1.0f;
+ float C1_r = 1.0f;
+ float G1_r = 0.0f;
+ bool outside = true;
- float F0 = fresnel_dielectric_cos(1.0f, eta);
- if(use_fresnel) {
- throughput = interpolate_fresnel_color(wi, normalize(wi + wr), eta, F0, cspec0);
- }
+ float F0 = fresnel_dielectric_cos(1.0f, eta);
+ if (use_fresnel) {
+ throughput = interpolate_fresnel_color(wi, normalize(wi + wr), eta, F0, cspec0);
+ }
- int order;
- for(order = 0; order < 10; order++) {
- /* Sample microfacet height. */
- float height_rand = lcg_step_float_addrspace(lcg_state);
- if(!mf_sample_height(wr, &hr, &C1_r, &G1_r, &lambda_r, height_rand)) {
- /* The random walk has left the surface. */
- *wo = outside? wr: -wr;
- return throughput;
- }
- /* Sample microfacet normal. */
- float vndf_rand_y = lcg_step_float_addrspace(lcg_state);
- float vndf_rand_x = lcg_step_float_addrspace(lcg_state);
- float3 wm = mf_sample_vndf(-wr, alpha, vndf_rand_x, vndf_rand_y);
+ int order;
+ for (order = 0; order < 10; order++) {
+ /* Sample microfacet height. */
+ float height_rand = lcg_step_float_addrspace(lcg_state);
+ if (!mf_sample_height(wr, &hr, &C1_r, &G1_r, &lambda_r, height_rand)) {
+ /* The random walk has left the surface. */
+ *wo = outside ? wr : -wr;
+ return throughput;
+ }
+ /* Sample microfacet normal. */
+ float vndf_rand_y = lcg_step_float_addrspace(lcg_state);
+ float vndf_rand_x = lcg_step_float_addrspace(lcg_state);
+ float3 wm = mf_sample_vndf(-wr, alpha, vndf_rand_x, vndf_rand_y);
- /* First-bounce color is already accounted for in mix weight. */
- if(!use_fresnel && order > 0)
- throughput *= color;
+ /* First-bounce color is already accounted for in mix weight. */
+ if (!use_fresnel && order > 0)
+ throughput *= color;
- /* Bounce from the microfacet. */
+ /* Bounce from the microfacet. */
#ifdef MF_MULTI_GLASS
- bool next_outside;
- float3 wi_prev = -wr;
- float phase_rand = lcg_step_float_addrspace(lcg_state);
- wr = mf_sample_phase_glass(-wr, outside? eta: 1.0f/eta, wm, phase_rand, &next_outside);
- if(!next_outside) {
- hr = -hr;
- wr = -wr;
- outside = !outside;
- }
+ bool next_outside;
+ float3 wi_prev = -wr;
+ float phase_rand = lcg_step_float_addrspace(lcg_state);
+ wr = mf_sample_phase_glass(-wr, outside ? eta : 1.0f / eta, wm, phase_rand, &next_outside);
+ if (!next_outside) {
+ hr = -hr;
+ wr = -wr;
+ outside = !outside;
+ }
- if(use_fresnel) {
- if(!next_outside) {
- throughput *= color;
- }
- else {
- float3 t_color = interpolate_fresnel_color(wi_prev, wm, eta, F0, cspec0);
+ if (use_fresnel) {
+ if (!next_outside) {
+ throughput *= color;
+ }
+ else {
+ float3 t_color = interpolate_fresnel_color(wi_prev, wm, eta, F0, cspec0);
- if(order == 0)
- throughput = t_color;
- else
- throughput *= t_color;
- }
- }
-#else /* MF_MULTI_GLOSSY */
- if(use_fresnel) {
- float3 t_color = interpolate_fresnel_color(-wr, wm, eta, F0, cspec0);
+ if (order == 0)
+ throughput = t_color;
+ else
+ throughput *= t_color;
+ }
+ }
+#else /* MF_MULTI_GLOSSY */
+ if (use_fresnel) {
+ float3 t_color = interpolate_fresnel_color(-wr, wm, eta, F0, cspec0);
- if(order == 0)
- throughput = t_color;
- else
- throughput *= t_color;
- }
- wr = mf_sample_phase_glossy(-wr, &throughput, wm);
+ if (order == 0)
+ throughput = t_color;
+ else
+ throughput *= t_color;
+ }
+ wr = mf_sample_phase_glossy(-wr, &throughput, wm);
#endif
- /* Update random walk parameters. */
- lambda_r = mf_lambda(wr, alpha);
- G1_r = mf_G1(wr, C1_r, lambda_r);
- }
- *wo = make_float3(0.0f, 0.0f, 1.0f);
- return make_float3(0.0f, 0.0f, 0.0f);
+ /* Update random walk parameters. */
+ lambda_r = mf_lambda(wr, alpha);
+ G1_r = mf_G1(wr, C1_r, lambda_r);
+ }
+ *wo = make_float3(0.0f, 0.0f, 1.0f);
+ return make_float3(0.0f, 0.0f, 0.0f);
}
#undef MF_MULTI_GLASS
diff --git a/intern/cycles/kernel/closure/bsdf_oren_nayar.h b/intern/cycles/kernel/closure/bsdf_oren_nayar.h
index 3446d1609d9..104ed5b2818 100644
--- a/intern/cycles/kernel/closure/bsdf_oren_nayar.h
+++ b/intern/cycles/kernel/closure/bsdf_oren_nayar.h
@@ -20,92 +20,110 @@
CCL_NAMESPACE_BEGIN
typedef ccl_addr_space struct OrenNayarBsdf {
- SHADER_CLOSURE_BASE;
+ SHADER_CLOSURE_BASE;
- float roughness;
- float a;
- float b;
+ float roughness;
+ float a;
+ float b;
} OrenNayarBsdf;
-ccl_device float3 bsdf_oren_nayar_get_intensity(const ShaderClosure *sc, float3 n, float3 v, float3 l)
+ccl_device float3 bsdf_oren_nayar_get_intensity(const ShaderClosure *sc,
+ float3 n,
+ float3 v,
+ float3 l)
{
- const OrenNayarBsdf *bsdf = (const OrenNayarBsdf*)sc;
- float nl = max(dot(n, l), 0.0f);
- float nv = max(dot(n, v), 0.0f);
- float t = dot(l, v) - nl * nv;
-
- if(t > 0.0f)
- t /= max(nl, nv) + FLT_MIN;
- float is = nl * (bsdf->a + bsdf->b * t);
- return make_float3(is, is, is);
+ const OrenNayarBsdf *bsdf = (const OrenNayarBsdf *)sc;
+ float nl = max(dot(n, l), 0.0f);
+ float nv = max(dot(n, v), 0.0f);
+ float t = dot(l, v) - nl * nv;
+
+ if (t > 0.0f)
+ t /= max(nl, nv) + FLT_MIN;
+ float is = nl * (bsdf->a + bsdf->b * t);
+ return make_float3(is, is, is);
}
ccl_device int bsdf_oren_nayar_setup(OrenNayarBsdf *bsdf)
{
- float sigma = bsdf->roughness;
+ float sigma = bsdf->roughness;
- bsdf->type = CLOSURE_BSDF_OREN_NAYAR_ID;
+ bsdf->type = CLOSURE_BSDF_OREN_NAYAR_ID;
- sigma = saturate(sigma);
+ sigma = saturate(sigma);
- float div = 1.0f / (M_PI_F + ((3.0f * M_PI_F - 4.0f) / 6.0f) * sigma);
+ float div = 1.0f / (M_PI_F + ((3.0f * M_PI_F - 4.0f) / 6.0f) * sigma);
- bsdf->a = 1.0f * div;
- bsdf->b = sigma * div;
+ bsdf->a = 1.0f * div;
+ bsdf->b = sigma * div;
- return SD_BSDF|SD_BSDF_HAS_EVAL;
+ return SD_BSDF | SD_BSDF_HAS_EVAL;
}
ccl_device bool bsdf_oren_nayar_merge(const ShaderClosure *a, const ShaderClosure *b)
{
- const OrenNayarBsdf *bsdf_a = (const OrenNayarBsdf*)a;
- const OrenNayarBsdf *bsdf_b = (const OrenNayarBsdf*)b;
+ const OrenNayarBsdf *bsdf_a = (const OrenNayarBsdf *)a;
+ const OrenNayarBsdf *bsdf_b = (const OrenNayarBsdf *)b;
- return (isequal_float3(bsdf_a->N, bsdf_b->N)) &&
- (bsdf_a->roughness == bsdf_b->roughness);
+ return (isequal_float3(bsdf_a->N, bsdf_b->N)) && (bsdf_a->roughness == bsdf_b->roughness);
}
-ccl_device float3 bsdf_oren_nayar_eval_reflect(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf)
+ccl_device float3 bsdf_oren_nayar_eval_reflect(const ShaderClosure *sc,
+ const float3 I,
+ const float3 omega_in,
+ float *pdf)
{
- const OrenNayarBsdf *bsdf = (const OrenNayarBsdf*)sc;
- if(dot(bsdf->N, omega_in) > 0.0f) {
- *pdf = 0.5f * M_1_PI_F;
- return bsdf_oren_nayar_get_intensity(sc, bsdf->N, I, omega_in);
- }
- else {
- *pdf = 0.0f;
- return make_float3(0.0f, 0.0f, 0.0f);
- }
+ const OrenNayarBsdf *bsdf = (const OrenNayarBsdf *)sc;
+ if (dot(bsdf->N, omega_in) > 0.0f) {
+ *pdf = 0.5f * M_1_PI_F;
+ return bsdf_oren_nayar_get_intensity(sc, bsdf->N, I, omega_in);
+ }
+ else {
+ *pdf = 0.0f;
+ return make_float3(0.0f, 0.0f, 0.0f);
+ }
}
-ccl_device float3 bsdf_oren_nayar_eval_transmit(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf)
+ccl_device float3 bsdf_oren_nayar_eval_transmit(const ShaderClosure *sc,
+ const float3 I,
+ const float3 omega_in,
+ float *pdf)
{
- return make_float3(0.0f, 0.0f, 0.0f);
+ return make_float3(0.0f, 0.0f, 0.0f);
}
-ccl_device int bsdf_oren_nayar_sample(const ShaderClosure *sc, float3 Ng, float3 I, float3 dIdx, float3 dIdy, float randu, float randv, float3 *eval, float3 *omega_in, float3 *domega_in_dx, float3 *domega_in_dy, float *pdf)
+ccl_device int bsdf_oren_nayar_sample(const ShaderClosure *sc,
+ float3 Ng,
+ float3 I,
+ float3 dIdx,
+ float3 dIdy,
+ float randu,
+ float randv,
+ float3 *eval,
+ float3 *omega_in,
+ float3 *domega_in_dx,
+ float3 *domega_in_dy,
+ float *pdf)
{
- const OrenNayarBsdf *bsdf = (const OrenNayarBsdf*)sc;
- sample_uniform_hemisphere(bsdf->N, randu, randv, omega_in, pdf);
+ const OrenNayarBsdf *bsdf = (const OrenNayarBsdf *)sc;
+ sample_uniform_hemisphere(bsdf->N, randu, randv, omega_in, pdf);
- if(dot(Ng, *omega_in) > 0.0f) {
- *eval = bsdf_oren_nayar_get_intensity(sc, bsdf->N, I, *omega_in);
+ if (dot(Ng, *omega_in) > 0.0f) {
+ *eval = bsdf_oren_nayar_get_intensity(sc, bsdf->N, I, *omega_in);
#ifdef __RAY_DIFFERENTIALS__
- // TODO: find a better approximation for the bounce
- *domega_in_dx = (2.0f * dot(bsdf->N, dIdx)) * bsdf->N - dIdx;
- *domega_in_dy = (2.0f * dot(bsdf->N, dIdy)) * bsdf->N - dIdy;
+ // TODO: find a better approximation for the bounce
+ *domega_in_dx = (2.0f * dot(bsdf->N, dIdx)) * bsdf->N - dIdx;
+ *domega_in_dy = (2.0f * dot(bsdf->N, dIdy)) * bsdf->N - dIdy;
#endif
- }
- else {
- *pdf = 0.0f;
- *eval = make_float3(0.0f, 0.0f, 0.0f);
- }
+ }
+ else {
+ *pdf = 0.0f;
+ *eval = make_float3(0.0f, 0.0f, 0.0f);
+ }
- return LABEL_REFLECT|LABEL_DIFFUSE;
+ return LABEL_REFLECT | LABEL_DIFFUSE;
}
-
CCL_NAMESPACE_END
-#endif /* __BSDF_OREN_NAYAR_H__ */
+#endif /* __BSDF_OREN_NAYAR_H__ */
diff --git a/intern/cycles/kernel/closure/bsdf_phong_ramp.h b/intern/cycles/kernel/closure/bsdf_phong_ramp.h
index 83da05ac435..b6fd0e68681 100644
--- a/intern/cycles/kernel/closure/bsdf_phong_ramp.h
+++ b/intern/cycles/kernel/closure/bsdf_phong_ramp.h
@@ -38,105 +38,118 @@ CCL_NAMESPACE_BEGIN
#ifdef __OSL__
typedef ccl_addr_space struct PhongRampBsdf {
- SHADER_CLOSURE_BASE;
+ SHADER_CLOSURE_BASE;
- float exponent;
- float3 *colors;
+ float exponent;
+ float3 *colors;
} PhongRampBsdf;
ccl_device float3 bsdf_phong_ramp_get_color(const float3 colors[8], float pos)
{
- int MAXCOLORS = 8;
-
- float npos = pos * (float)(MAXCOLORS - 1);
- int ipos = float_to_int(npos);
- if(ipos < 0)
- return colors[0];
- if(ipos >= (MAXCOLORS - 1))
- return colors[MAXCOLORS - 1];
- float offset = npos - (float)ipos;
- return colors[ipos] * (1.0f - offset) + colors[ipos+1] * offset;
+ int MAXCOLORS = 8;
+
+ float npos = pos * (float)(MAXCOLORS - 1);
+ int ipos = float_to_int(npos);
+ if (ipos < 0)
+ return colors[0];
+ if (ipos >= (MAXCOLORS - 1))
+ return colors[MAXCOLORS - 1];
+ float offset = npos - (float)ipos;
+ return colors[ipos] * (1.0f - offset) + colors[ipos + 1] * offset;
}
ccl_device int bsdf_phong_ramp_setup(PhongRampBsdf *bsdf)
{
- bsdf->type = CLOSURE_BSDF_PHONG_RAMP_ID;
- bsdf->exponent = max(bsdf->exponent, 0.0f);
- return SD_BSDF|SD_BSDF_HAS_EVAL;
+ bsdf->type = CLOSURE_BSDF_PHONG_RAMP_ID;
+ bsdf->exponent = max(bsdf->exponent, 0.0f);
+ return SD_BSDF | SD_BSDF_HAS_EVAL;
}
-ccl_device float3 bsdf_phong_ramp_eval_reflect(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf)
+ccl_device float3 bsdf_phong_ramp_eval_reflect(const ShaderClosure *sc,
+ const float3 I,
+ const float3 omega_in,
+ float *pdf)
{
- const PhongRampBsdf *bsdf = (const PhongRampBsdf*)sc;
- float m_exponent = bsdf->exponent;
- float cosNI = dot(bsdf->N, omega_in);
- float cosNO = dot(bsdf->N, I);
-
- if(cosNI > 0 && cosNO > 0) {
- // reflect the view vector
- float3 R = (2 * cosNO) * bsdf->N - I;
- float cosRI = dot(R, omega_in);
- if(cosRI > 0) {
- float cosp = powf(cosRI, m_exponent);
- float common = 0.5f * M_1_PI_F * cosp;
- float out = cosNI * (m_exponent + 2) * common;
- *pdf = (m_exponent + 1) * common;
- return bsdf_phong_ramp_get_color(bsdf->colors, cosp) * out;
- }
- }
-
- return make_float3(0.0f, 0.0f, 0.0f);
+ const PhongRampBsdf *bsdf = (const PhongRampBsdf *)sc;
+ float m_exponent = bsdf->exponent;
+ float cosNI = dot(bsdf->N, omega_in);
+ float cosNO = dot(bsdf->N, I);
+
+ if (cosNI > 0 && cosNO > 0) {
+ // reflect the view vector
+ float3 R = (2 * cosNO) * bsdf->N - I;
+ float cosRI = dot(R, omega_in);
+ if (cosRI > 0) {
+ float cosp = powf(cosRI, m_exponent);
+ float common = 0.5f * M_1_PI_F * cosp;
+ float out = cosNI * (m_exponent + 2) * common;
+ *pdf = (m_exponent + 1) * common;
+ return bsdf_phong_ramp_get_color(bsdf->colors, cosp) * out;
+ }
+ }
+
+ return make_float3(0.0f, 0.0f, 0.0f);
}
-ccl_device float3 bsdf_phong_ramp_eval_transmit(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf)
+ccl_device float3 bsdf_phong_ramp_eval_transmit(const ShaderClosure *sc,
+ const float3 I,
+ const float3 omega_in,
+ float *pdf)
{
- return make_float3(0.0f, 0.0f, 0.0f);
+ return make_float3(0.0f, 0.0f, 0.0f);
}
-ccl_device int bsdf_phong_ramp_sample(const ShaderClosure *sc, float3 Ng, float3 I, float3 dIdx, float3 dIdy, float randu, float randv, float3 *eval, float3 *omega_in, float3 *domega_in_dx, float3 *domega_in_dy, float *pdf)
+ccl_device int bsdf_phong_ramp_sample(const ShaderClosure *sc,
+ float3 Ng,
+ float3 I,
+ float3 dIdx,
+ float3 dIdy,
+ float randu,
+ float randv,
+ float3 *eval,
+ float3 *omega_in,
+ float3 *domega_in_dx,
+ float3 *domega_in_dy,
+ float *pdf)
{
- const PhongRampBsdf *bsdf = (const PhongRampBsdf*)sc;
- float cosNO = dot(bsdf->N, I);
- float m_exponent = bsdf->exponent;
-
- if(cosNO > 0) {
- // reflect the view vector
- float3 R = (2 * cosNO) * bsdf->N - I;
-
-#ifdef __RAY_DIFFERENTIALS__
- *domega_in_dx = (2 * dot(bsdf->N, dIdx)) * bsdf->N - dIdx;
- *domega_in_dy = (2 * dot(bsdf->N, dIdy)) * bsdf->N - dIdy;
-#endif
-
- float3 T, B;
- make_orthonormals (R, &T, &B);
- float phi = M_2PI_F * randu;
- float cosTheta = powf(randv, 1 / (m_exponent + 1));
- float sinTheta2 = 1 - cosTheta * cosTheta;
- float sinTheta = sinTheta2 > 0 ? sqrtf(sinTheta2) : 0;
- *omega_in = (cosf(phi) * sinTheta) * T +
- (sinf(phi) * sinTheta) * B +
- ( cosTheta) * R;
- if(dot(Ng, *omega_in) > 0.0f)
- {
- // common terms for pdf and eval
- float cosNI = dot(bsdf->N, *omega_in);
- // make sure the direction we chose is still in the right hemisphere
- if(cosNI > 0)
- {
- float cosp = powf(cosTheta, m_exponent);
- float common = 0.5f * M_1_PI_F * cosp;
- *pdf = (m_exponent + 1) * common;
- float out = cosNI * (m_exponent + 2) * common;
- *eval = bsdf_phong_ramp_get_color(bsdf->colors, cosp) * out;
- }
- }
- }
- return LABEL_REFLECT|LABEL_GLOSSY;
+ const PhongRampBsdf *bsdf = (const PhongRampBsdf *)sc;
+ float cosNO = dot(bsdf->N, I);
+ float m_exponent = bsdf->exponent;
+
+ if (cosNO > 0) {
+ // reflect the view vector
+ float3 R = (2 * cosNO) * bsdf->N - I;
+
+# ifdef __RAY_DIFFERENTIALS__
+ *domega_in_dx = (2 * dot(bsdf->N, dIdx)) * bsdf->N - dIdx;
+ *domega_in_dy = (2 * dot(bsdf->N, dIdy)) * bsdf->N - dIdy;
+# endif
+
+ float3 T, B;
+ make_orthonormals(R, &T, &B);
+ float phi = M_2PI_F * randu;
+ float cosTheta = powf(randv, 1 / (m_exponent + 1));
+ float sinTheta2 = 1 - cosTheta * cosTheta;
+ float sinTheta = sinTheta2 > 0 ? sqrtf(sinTheta2) : 0;
+ *omega_in = (cosf(phi) * sinTheta) * T + (sinf(phi) * sinTheta) * B + (cosTheta)*R;
+ if (dot(Ng, *omega_in) > 0.0f) {
+ // common terms for pdf and eval
+ float cosNI = dot(bsdf->N, *omega_in);
+ // make sure the direction we chose is still in the right hemisphere
+ if (cosNI > 0) {
+ float cosp = powf(cosTheta, m_exponent);
+ float common = 0.5f * M_1_PI_F * cosp;
+ *pdf = (m_exponent + 1) * common;
+ float out = cosNI * (m_exponent + 2) * common;
+ *eval = bsdf_phong_ramp_get_color(bsdf->colors, cosp) * out;
+ }
+ }
+ }
+ return LABEL_REFLECT | LABEL_GLOSSY;
}
-#endif /* __OSL__ */
+#endif /* __OSL__ */
CCL_NAMESPACE_END
-#endif /* __BSDF_PHONG_RAMP_H__ */
+#endif /* __BSDF_PHONG_RAMP_H__ */
diff --git a/intern/cycles/kernel/closure/bsdf_principled_diffuse.h b/intern/cycles/kernel/closure/bsdf_principled_diffuse.h
index 2f65fd54be2..d7795974ef5 100644
--- a/intern/cycles/kernel/closure/bsdf_principled_diffuse.h
+++ b/intern/cycles/kernel/closure/bsdf_principled_diffuse.h
@@ -25,101 +25,113 @@
CCL_NAMESPACE_BEGIN
typedef ccl_addr_space struct PrincipledDiffuseBsdf {
- SHADER_CLOSURE_BASE;
+ SHADER_CLOSURE_BASE;
- float roughness;
+ float roughness;
} PrincipledDiffuseBsdf;
-ccl_device float3 calculate_principled_diffuse_brdf(const PrincipledDiffuseBsdf *bsdf,
- float3 N, float3 V, float3 L, float3 H, float *pdf)
+ccl_device float3 calculate_principled_diffuse_brdf(
+ const PrincipledDiffuseBsdf *bsdf, float3 N, float3 V, float3 L, float3 H, float *pdf)
{
- float NdotL = max(dot(N, L), 0.0f);
- float NdotV = max(dot(N, V), 0.0f);
+ float NdotL = max(dot(N, L), 0.0f);
+ float NdotV = max(dot(N, V), 0.0f);
- if(NdotL < 0 || NdotV < 0) {
- *pdf = 0.0f;
- return make_float3(0.0f, 0.0f, 0.0f);
- }
+ if (NdotL < 0 || NdotV < 0) {
+ *pdf = 0.0f;
+ return make_float3(0.0f, 0.0f, 0.0f);
+ }
- float LdotH = dot(L, H);
+ float LdotH = dot(L, H);
- float FL = schlick_fresnel(NdotL), FV = schlick_fresnel(NdotV);
- const float Fd90 = 0.5f + 2.0f * LdotH*LdotH * bsdf->roughness;
- float Fd = (1.0f * (1.0f - FL) + Fd90 * FL) * (1.0f * (1.0f - FV) + Fd90 * FV);
+ float FL = schlick_fresnel(NdotL), FV = schlick_fresnel(NdotV);
+ const float Fd90 = 0.5f + 2.0f * LdotH * LdotH * bsdf->roughness;
+ float Fd = (1.0f * (1.0f - FL) + Fd90 * FL) * (1.0f * (1.0f - FV) + Fd90 * FV);
- float value = M_1_PI_F * NdotL * Fd;
+ float value = M_1_PI_F * NdotL * Fd;
- return make_float3(value, value, value);
+ return make_float3(value, value, value);
}
ccl_device int bsdf_principled_diffuse_setup(PrincipledDiffuseBsdf *bsdf)
{
- bsdf->type = CLOSURE_BSDF_PRINCIPLED_DIFFUSE_ID;
- return SD_BSDF|SD_BSDF_HAS_EVAL;
+ bsdf->type = CLOSURE_BSDF_PRINCIPLED_DIFFUSE_ID;
+ return SD_BSDF | SD_BSDF_HAS_EVAL;
}
ccl_device bool bsdf_principled_diffuse_merge(const ShaderClosure *a, const ShaderClosure *b)
{
- const PrincipledDiffuseBsdf *bsdf_a = (const PrincipledDiffuseBsdf*)a;
- const PrincipledDiffuseBsdf *bsdf_b = (const PrincipledDiffuseBsdf*)b;
+ const PrincipledDiffuseBsdf *bsdf_a = (const PrincipledDiffuseBsdf *)a;
+ const PrincipledDiffuseBsdf *bsdf_b = (const PrincipledDiffuseBsdf *)b;
- return (isequal_float3(bsdf_a->N, bsdf_b->N) && bsdf_a->roughness == bsdf_b->roughness);
+ return (isequal_float3(bsdf_a->N, bsdf_b->N) && bsdf_a->roughness == bsdf_b->roughness);
}
-ccl_device float3 bsdf_principled_diffuse_eval_reflect(const ShaderClosure *sc, const float3 I,
- const float3 omega_in, float *pdf)
+ccl_device float3 bsdf_principled_diffuse_eval_reflect(const ShaderClosure *sc,
+ const float3 I,
+ const float3 omega_in,
+ float *pdf)
{
- const PrincipledDiffuseBsdf *bsdf = (const PrincipledDiffuseBsdf *)sc;
-
- float3 N = bsdf->N;
- float3 V = I; // outgoing
- float3 L = omega_in; // incoming
- float3 H = normalize(L + V);
-
- if(dot(N, omega_in) > 0.0f) {
- *pdf = fmaxf(dot(N, omega_in), 0.0f) * M_1_PI_F;
- return calculate_principled_diffuse_brdf(bsdf, N, V, L, H, pdf);
- }
- else {
- *pdf = 0.0f;
- return make_float3(0.0f, 0.0f, 0.0f);
- }
+ const PrincipledDiffuseBsdf *bsdf = (const PrincipledDiffuseBsdf *)sc;
+
+ float3 N = bsdf->N;
+ float3 V = I; // outgoing
+ float3 L = omega_in; // incoming
+ float3 H = normalize(L + V);
+
+ if (dot(N, omega_in) > 0.0f) {
+ *pdf = fmaxf(dot(N, omega_in), 0.0f) * M_1_PI_F;
+ return calculate_principled_diffuse_brdf(bsdf, N, V, L, H, pdf);
+ }
+ else {
+ *pdf = 0.0f;
+ return make_float3(0.0f, 0.0f, 0.0f);
+ }
}
-ccl_device float3 bsdf_principled_diffuse_eval_transmit(const ShaderClosure *sc, const float3 I,
- const float3 omega_in, float *pdf)
+ccl_device float3 bsdf_principled_diffuse_eval_transmit(const ShaderClosure *sc,
+ const float3 I,
+ const float3 omega_in,
+ float *pdf)
{
- return make_float3(0.0f, 0.0f, 0.0f);
+ return make_float3(0.0f, 0.0f, 0.0f);
}
ccl_device int bsdf_principled_diffuse_sample(const ShaderClosure *sc,
- float3 Ng, float3 I, float3 dIdx, float3 dIdy, float randu, float randv,
- float3 *eval, float3 *omega_in, float3 *domega_in_dx,
- float3 *domega_in_dy, float *pdf)
+ float3 Ng,
+ float3 I,
+ float3 dIdx,
+ float3 dIdy,
+ float randu,
+ float randv,
+ float3 *eval,
+ float3 *omega_in,
+ float3 *domega_in_dx,
+ float3 *domega_in_dy,
+ float *pdf)
{
- const PrincipledDiffuseBsdf *bsdf = (const PrincipledDiffuseBsdf *)sc;
+ const PrincipledDiffuseBsdf *bsdf = (const PrincipledDiffuseBsdf *)sc;
- float3 N = bsdf->N;
+ float3 N = bsdf->N;
- sample_cos_hemisphere(N, randu, randv, omega_in, pdf);
+ sample_cos_hemisphere(N, randu, randv, omega_in, pdf);
- if(dot(Ng, *omega_in) > 0) {
- float3 H = normalize(I + *omega_in);
+ if (dot(Ng, *omega_in) > 0) {
+ float3 H = normalize(I + *omega_in);
- *eval = calculate_principled_diffuse_brdf(bsdf, N, I, *omega_in, H, pdf);
+ *eval = calculate_principled_diffuse_brdf(bsdf, N, I, *omega_in, H, pdf);
#ifdef __RAY_DIFFERENTIALS__
- // TODO: find a better approximation for the diffuse bounce
- *domega_in_dx = -((2 * dot(N, dIdx)) * N - dIdx);
- *domega_in_dy = -((2 * dot(N, dIdy)) * N - dIdy);
+ // TODO: find a better approximation for the diffuse bounce
+ *domega_in_dx = -((2 * dot(N, dIdx)) * N - dIdx);
+ *domega_in_dy = -((2 * dot(N, dIdy)) * N - dIdy);
#endif
- }
- else {
- *pdf = 0.0f;
- }
- return LABEL_REFLECT|LABEL_DIFFUSE;
+ }
+ else {
+ *pdf = 0.0f;
+ }
+ return LABEL_REFLECT | LABEL_DIFFUSE;
}
CCL_NAMESPACE_END
-#endif /* __BSDF_PRINCIPLED_DIFFUSE_H__ */
+#endif /* __BSDF_PRINCIPLED_DIFFUSE_H__ */
diff --git a/intern/cycles/kernel/closure/bsdf_principled_sheen.h b/intern/cycles/kernel/closure/bsdf_principled_sheen.h
index ccdcb1babd2..bc522095b3b 100644
--- a/intern/cycles/kernel/closure/bsdf_principled_sheen.h
+++ b/intern/cycles/kernel/closure/bsdf_principled_sheen.h
@@ -25,87 +25,99 @@
CCL_NAMESPACE_BEGIN
typedef ccl_addr_space struct PrincipledSheenBsdf {
- SHADER_CLOSURE_BASE;
+ SHADER_CLOSURE_BASE;
} PrincipledSheenBsdf;
-ccl_device float3 calculate_principled_sheen_brdf(const PrincipledSheenBsdf *bsdf,
- float3 N, float3 V, float3 L, float3 H, float *pdf)
+ccl_device float3 calculate_principled_sheen_brdf(
+ const PrincipledSheenBsdf *bsdf, float3 N, float3 V, float3 L, float3 H, float *pdf)
{
- float NdotL = dot(N, L);
- float NdotV = dot(N, V);
+ float NdotL = dot(N, L);
+ float NdotV = dot(N, V);
- if(NdotL < 0 || NdotV < 0) {
- *pdf = 0.0f;
- return make_float3(0.0f, 0.0f, 0.0f);
- }
+ if (NdotL < 0 || NdotV < 0) {
+ *pdf = 0.0f;
+ return make_float3(0.0f, 0.0f, 0.0f);
+ }
- float LdotH = dot(L, H);
+ float LdotH = dot(L, H);
- float value = schlick_fresnel(LdotH) * NdotL;
+ float value = schlick_fresnel(LdotH) * NdotL;
- return make_float3(value, value, value);
+ return make_float3(value, value, value);
}
ccl_device int bsdf_principled_sheen_setup(PrincipledSheenBsdf *bsdf)
{
- bsdf->type = CLOSURE_BSDF_PRINCIPLED_SHEEN_ID;
- return SD_BSDF|SD_BSDF_HAS_EVAL;
+ bsdf->type = CLOSURE_BSDF_PRINCIPLED_SHEEN_ID;
+ return SD_BSDF | SD_BSDF_HAS_EVAL;
}
-ccl_device float3 bsdf_principled_sheen_eval_reflect(const ShaderClosure *sc, const float3 I,
- const float3 omega_in, float *pdf)
+ccl_device float3 bsdf_principled_sheen_eval_reflect(const ShaderClosure *sc,
+ const float3 I,
+ const float3 omega_in,
+ float *pdf)
{
- const PrincipledSheenBsdf *bsdf = (const PrincipledSheenBsdf *)sc;
-
- float3 N = bsdf->N;
- float3 V = I; // outgoing
- float3 L = omega_in; // incoming
- float3 H = normalize(L + V);
-
- if(dot(N, omega_in) > 0.0f) {
- *pdf = fmaxf(dot(N, omega_in), 0.0f) * M_1_PI_F;
- return calculate_principled_sheen_brdf(bsdf, N, V, L, H, pdf);
- }
- else {
- *pdf = 0.0f;
- return make_float3(0.0f, 0.0f, 0.0f);
- }
+ const PrincipledSheenBsdf *bsdf = (const PrincipledSheenBsdf *)sc;
+
+ float3 N = bsdf->N;
+ float3 V = I; // outgoing
+ float3 L = omega_in; // incoming
+ float3 H = normalize(L + V);
+
+ if (dot(N, omega_in) > 0.0f) {
+ *pdf = fmaxf(dot(N, omega_in), 0.0f) * M_1_PI_F;
+ return calculate_principled_sheen_brdf(bsdf, N, V, L, H, pdf);
+ }
+ else {
+ *pdf = 0.0f;
+ return make_float3(0.0f, 0.0f, 0.0f);
+ }
}
-ccl_device float3 bsdf_principled_sheen_eval_transmit(const ShaderClosure *sc, const float3 I,
- const float3 omega_in, float *pdf)
+ccl_device float3 bsdf_principled_sheen_eval_transmit(const ShaderClosure *sc,
+ const float3 I,
+ const float3 omega_in,
+ float *pdf)
{
- return make_float3(0.0f, 0.0f, 0.0f);
+ return make_float3(0.0f, 0.0f, 0.0f);
}
ccl_device int bsdf_principled_sheen_sample(const ShaderClosure *sc,
- float3 Ng, float3 I, float3 dIdx, float3 dIdy, float randu, float randv,
- float3 *eval, float3 *omega_in, float3 *domega_in_dx,
- float3 *domega_in_dy, float *pdf)
+ float3 Ng,
+ float3 I,
+ float3 dIdx,
+ float3 dIdy,
+ float randu,
+ float randv,
+ float3 *eval,
+ float3 *omega_in,
+ float3 *domega_in_dx,
+ float3 *domega_in_dy,
+ float *pdf)
{
- const PrincipledSheenBsdf *bsdf = (const PrincipledSheenBsdf *)sc;
+ const PrincipledSheenBsdf *bsdf = (const PrincipledSheenBsdf *)sc;
- float3 N = bsdf->N;
+ float3 N = bsdf->N;
- sample_cos_hemisphere(N, randu, randv, omega_in, pdf);
+ sample_cos_hemisphere(N, randu, randv, omega_in, pdf);
- if(dot(Ng, *omega_in) > 0) {
- float3 H = normalize(I + *omega_in);
+ if (dot(Ng, *omega_in) > 0) {
+ float3 H = normalize(I + *omega_in);
- *eval = calculate_principled_sheen_brdf(bsdf, N, I, *omega_in, H, pdf);
+ *eval = calculate_principled_sheen_brdf(bsdf, N, I, *omega_in, H, pdf);
#ifdef __RAY_DIFFERENTIALS__
- // TODO: find a better approximation for the diffuse bounce
- *domega_in_dx = -((2 * dot(N, dIdx)) * N - dIdx);
- *domega_in_dy = -((2 * dot(N, dIdy)) * N - dIdy);
+ // TODO: find a better approximation for the diffuse bounce
+ *domega_in_dx = -((2 * dot(N, dIdx)) * N - dIdx);
+ *domega_in_dy = -((2 * dot(N, dIdy)) * N - dIdy);
#endif
- }
- else {
- *pdf = 0.0f;
- }
- return LABEL_REFLECT|LABEL_DIFFUSE;
+ }
+ else {
+ *pdf = 0.0f;
+ }
+ return LABEL_REFLECT | LABEL_DIFFUSE;
}
CCL_NAMESPACE_END
-#endif /* __BSDF_PRINCIPLED_SHEEN_H__ */
+#endif /* __BSDF_PRINCIPLED_SHEEN_H__ */
diff --git a/intern/cycles/kernel/closure/bsdf_reflection.h b/intern/cycles/kernel/closure/bsdf_reflection.h
index 94f1c283af7..c24ba170915 100644
--- a/intern/cycles/kernel/closure/bsdf_reflection.h
+++ b/intern/cycles/kernel/closure/bsdf_reflection.h
@@ -39,42 +39,59 @@ CCL_NAMESPACE_BEGIN
ccl_device int bsdf_reflection_setup(MicrofacetBsdf *bsdf)
{
- bsdf->type = CLOSURE_BSDF_REFLECTION_ID;
- return SD_BSDF;
+ bsdf->type = CLOSURE_BSDF_REFLECTION_ID;
+ return SD_BSDF;
}
-ccl_device float3 bsdf_reflection_eval_reflect(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf)
+ccl_device float3 bsdf_reflection_eval_reflect(const ShaderClosure *sc,
+ const float3 I,
+ const float3 omega_in,
+ float *pdf)
{
- return make_float3(0.0f, 0.0f, 0.0f);
+ return make_float3(0.0f, 0.0f, 0.0f);
}
-ccl_device float3 bsdf_reflection_eval_transmit(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf)
+ccl_device float3 bsdf_reflection_eval_transmit(const ShaderClosure *sc,
+ const float3 I,
+ const float3 omega_in,
+ float *pdf)
{
- return make_float3(0.0f, 0.0f, 0.0f);
+ return make_float3(0.0f, 0.0f, 0.0f);
}
-ccl_device int bsdf_reflection_sample(const ShaderClosure *sc, float3 Ng, float3 I, float3 dIdx, float3 dIdy, float randu, float randv, float3 *eval, float3 *omega_in, float3 *domega_in_dx, float3 *domega_in_dy, float *pdf)
+ccl_device int bsdf_reflection_sample(const ShaderClosure *sc,
+ float3 Ng,
+ float3 I,
+ float3 dIdx,
+ float3 dIdy,
+ float randu,
+ float randv,
+ float3 *eval,
+ float3 *omega_in,
+ float3 *domega_in_dx,
+ float3 *domega_in_dy,
+ float *pdf)
{
- const MicrofacetBsdf *bsdf = (const MicrofacetBsdf*)sc;
- float3 N = bsdf->N;
+ const MicrofacetBsdf *bsdf = (const MicrofacetBsdf *)sc;
+ float3 N = bsdf->N;
- // only one direction is possible
- float cosNO = dot(N, I);
- if(cosNO > 0) {
- *omega_in = (2 * cosNO) * N - I;
- if(dot(Ng, *omega_in) > 0) {
+ // only one direction is possible
+ float cosNO = dot(N, I);
+ if (cosNO > 0) {
+ *omega_in = (2 * cosNO) * N - I;
+ if (dot(Ng, *omega_in) > 0) {
#ifdef __RAY_DIFFERENTIALS__
- *domega_in_dx = 2 * dot(N, dIdx) * N - dIdx;
- *domega_in_dy = 2 * dot(N, dIdy) * N - dIdy;
+ *domega_in_dx = 2 * dot(N, dIdx) * N - dIdx;
+ *domega_in_dy = 2 * dot(N, dIdy) * N - dIdy;
#endif
- /* Some high number for MIS. */
- *pdf = 1e6f;
- *eval = make_float3(1e6f, 1e6f, 1e6f);
- }
- }
- return LABEL_REFLECT|LABEL_SINGULAR;
+ /* Some high number for MIS. */
+ *pdf = 1e6f;
+ *eval = make_float3(1e6f, 1e6f, 1e6f);
+ }
+ }
+ return LABEL_REFLECT | LABEL_SINGULAR;
}
CCL_NAMESPACE_END
-#endif /* __BSDF_REFLECTION_H__ */
+#endif /* __BSDF_REFLECTION_H__ */
diff --git a/intern/cycles/kernel/closure/bsdf_refraction.h b/intern/cycles/kernel/closure/bsdf_refraction.h
index abdd01c7a1d..d4fbe86dac0 100644
--- a/intern/cycles/kernel/closure/bsdf_refraction.h
+++ b/intern/cycles/kernel/closure/bsdf_refraction.h
@@ -39,51 +39,77 @@ CCL_NAMESPACE_BEGIN
ccl_device int bsdf_refraction_setup(MicrofacetBsdf *bsdf)
{
- bsdf->type = CLOSURE_BSDF_REFRACTION_ID;
- return SD_BSDF;
+ bsdf->type = CLOSURE_BSDF_REFRACTION_ID;
+ return SD_BSDF;
}
-ccl_device float3 bsdf_refraction_eval_reflect(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf)
+ccl_device float3 bsdf_refraction_eval_reflect(const ShaderClosure *sc,
+ const float3 I,
+ const float3 omega_in,
+ float *pdf)
{
- return make_float3(0.0f, 0.0f, 0.0f);
+ return make_float3(0.0f, 0.0f, 0.0f);
}
-ccl_device float3 bsdf_refraction_eval_transmit(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf)
+ccl_device float3 bsdf_refraction_eval_transmit(const ShaderClosure *sc,
+ const float3 I,
+ const float3 omega_in,
+ float *pdf)
{
- return make_float3(0.0f, 0.0f, 0.0f);
+ return make_float3(0.0f, 0.0f, 0.0f);
}
-ccl_device int bsdf_refraction_sample(const ShaderClosure *sc, float3 Ng, float3 I, float3 dIdx, float3 dIdy, float randu, float randv, float3 *eval, float3 *omega_in, float3 *domega_in_dx, float3 *domega_in_dy, float *pdf)
+ccl_device int bsdf_refraction_sample(const ShaderClosure *sc,
+ float3 Ng,
+ float3 I,
+ float3 dIdx,
+ float3 dIdy,
+ float randu,
+ float randv,
+ float3 *eval,
+ float3 *omega_in,
+ float3 *domega_in_dx,
+ float3 *domega_in_dy,
+ float *pdf)
{
- const MicrofacetBsdf *bsdf = (const MicrofacetBsdf*)sc;
- float m_eta = bsdf->ior;
- float3 N = bsdf->N;
+ const MicrofacetBsdf *bsdf = (const MicrofacetBsdf *)sc;
+ float m_eta = bsdf->ior;
+ float3 N = bsdf->N;
- float3 R, T;
+ float3 R, T;
#ifdef __RAY_DIFFERENTIALS__
- float3 dRdx, dRdy, dTdx, dTdy;
+ float3 dRdx, dRdy, dTdx, dTdy;
#endif
- bool inside;
- float fresnel;
- fresnel = fresnel_dielectric(m_eta, N, I, &R, &T,
+ bool inside;
+ float fresnel;
+ fresnel = fresnel_dielectric(m_eta,
+ N,
+ I,
+ &R,
+ &T,
#ifdef __RAY_DIFFERENTIALS__
- dIdx, dIdy, &dRdx, &dRdy, &dTdx, &dTdy,
+ dIdx,
+ dIdy,
+ &dRdx,
+ &dRdy,
+ &dTdx,
+ &dTdy,
#endif
- &inside);
+ &inside);
- if(!inside && fresnel != 1.0f) {
- /* Some high number for MIS. */
- *pdf = 1e6f;
- *eval = make_float3(1e6f, 1e6f, 1e6f);
- *omega_in = T;
+ if (!inside && fresnel != 1.0f) {
+ /* Some high number for MIS. */
+ *pdf = 1e6f;
+ *eval = make_float3(1e6f, 1e6f, 1e6f);
+ *omega_in = T;
#ifdef __RAY_DIFFERENTIALS__
- *domega_in_dx = dTdx;
- *domega_in_dy = dTdy;
+ *domega_in_dx = dTdx;
+ *domega_in_dy = dTdy;
#endif
- }
- return LABEL_TRANSMIT|LABEL_SINGULAR;
+ }
+ return LABEL_TRANSMIT | LABEL_SINGULAR;
}
CCL_NAMESPACE_END
-#endif /* __BSDF_REFRACTION_H__ */
+#endif /* __BSDF_REFRACTION_H__ */
diff --git a/intern/cycles/kernel/closure/bsdf_toon.h b/intern/cycles/kernel/closure/bsdf_toon.h
index 097a56f22eb..f37fd228087 100644
--- a/intern/cycles/kernel/closure/bsdf_toon.h
+++ b/intern/cycles/kernel/closure/bsdf_toon.h
@@ -36,183 +36,215 @@
CCL_NAMESPACE_BEGIN
typedef ccl_addr_space struct ToonBsdf {
- SHADER_CLOSURE_BASE;
+ SHADER_CLOSURE_BASE;
- float size;
- float smooth;
+ float size;
+ float smooth;
} ToonBsdf;
/* DIFFUSE TOON */
ccl_device int bsdf_diffuse_toon_setup(ToonBsdf *bsdf)
{
- bsdf->type = CLOSURE_BSDF_DIFFUSE_TOON_ID;
- bsdf->size = saturate(bsdf->size);
- bsdf->smooth = saturate(bsdf->smooth);
+ bsdf->type = CLOSURE_BSDF_DIFFUSE_TOON_ID;
+ bsdf->size = saturate(bsdf->size);
+ bsdf->smooth = saturate(bsdf->smooth);
- return SD_BSDF|SD_BSDF_HAS_EVAL;
+ return SD_BSDF | SD_BSDF_HAS_EVAL;
}
ccl_device bool bsdf_toon_merge(const ShaderClosure *a, const ShaderClosure *b)
{
- const ToonBsdf *bsdf_a = (const ToonBsdf*)a;
- const ToonBsdf *bsdf_b = (const ToonBsdf*)b;
+ const ToonBsdf *bsdf_a = (const ToonBsdf *)a;
+ const ToonBsdf *bsdf_b = (const ToonBsdf *)b;
- return (isequal_float3(bsdf_a->N, bsdf_b->N)) &&
- (bsdf_a->size == bsdf_b->size) &&
- (bsdf_a->smooth == bsdf_b->smooth);
+ return (isequal_float3(bsdf_a->N, bsdf_b->N)) && (bsdf_a->size == bsdf_b->size) &&
+ (bsdf_a->smooth == bsdf_b->smooth);
}
ccl_device float3 bsdf_toon_get_intensity(float max_angle, float smooth, float angle)
{
- float is;
+ float is;
- if(angle < max_angle)
- is = 1.0f;
- else if(angle < (max_angle + smooth) && smooth != 0.0f)
- is = (1.0f - (angle - max_angle)/smooth);
- else
- is = 0.0f;
+ if (angle < max_angle)
+ is = 1.0f;
+ else if (angle < (max_angle + smooth) && smooth != 0.0f)
+ is = (1.0f - (angle - max_angle) / smooth);
+ else
+ is = 0.0f;
- return make_float3(is, is, is);
+ return make_float3(is, is, is);
}
ccl_device float bsdf_toon_get_sample_angle(float max_angle, float smooth)
{
- return fminf(max_angle + smooth, M_PI_2_F);
+ return fminf(max_angle + smooth, M_PI_2_F);
}
-ccl_device float3 bsdf_diffuse_toon_eval_reflect(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf)
+ccl_device float3 bsdf_diffuse_toon_eval_reflect(const ShaderClosure *sc,
+ const float3 I,
+ const float3 omega_in,
+ float *pdf)
{
- const ToonBsdf *bsdf = (const ToonBsdf*)sc;
- float max_angle = bsdf->size*M_PI_2_F;
- float smooth = bsdf->smooth*M_PI_2_F;
- float angle = safe_acosf(fmaxf(dot(bsdf->N, omega_in), 0.0f));
+ const ToonBsdf *bsdf = (const ToonBsdf *)sc;
+ float max_angle = bsdf->size * M_PI_2_F;
+ float smooth = bsdf->smooth * M_PI_2_F;
+ float angle = safe_acosf(fmaxf(dot(bsdf->N, omega_in), 0.0f));
- float3 eval = bsdf_toon_get_intensity(max_angle, smooth, angle);
+ float3 eval = bsdf_toon_get_intensity(max_angle, smooth, angle);
- if(eval.x > 0.0f) {
- float sample_angle = bsdf_toon_get_sample_angle(max_angle, smooth);
+ if (eval.x > 0.0f) {
+ float sample_angle = bsdf_toon_get_sample_angle(max_angle, smooth);
- *pdf = 0.5f * M_1_PI_F / (1.0f - cosf(sample_angle));
- return *pdf * eval;
- }
+ *pdf = 0.5f * M_1_PI_F / (1.0f - cosf(sample_angle));
+ return *pdf * eval;
+ }
- return make_float3(0.0f, 0.0f, 0.0f);
+ return make_float3(0.0f, 0.0f, 0.0f);
}
-ccl_device float3 bsdf_diffuse_toon_eval_transmit(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf)
+ccl_device float3 bsdf_diffuse_toon_eval_transmit(const ShaderClosure *sc,
+ const float3 I,
+ const float3 omega_in,
+ float *pdf)
{
- return make_float3(0.0f, 0.0f, 0.0f);
+ return make_float3(0.0f, 0.0f, 0.0f);
}
-ccl_device int bsdf_diffuse_toon_sample(const ShaderClosure *sc, float3 Ng, float3 I, float3 dIdx, float3 dIdy, float randu, float randv, float3 *eval, float3 *omega_in, float3 *domega_in_dx, float3 *domega_in_dy, float *pdf)
+ccl_device int bsdf_diffuse_toon_sample(const ShaderClosure *sc,
+ float3 Ng,
+ float3 I,
+ float3 dIdx,
+ float3 dIdy,
+ float randu,
+ float randv,
+ float3 *eval,
+ float3 *omega_in,
+ float3 *domega_in_dx,
+ float3 *domega_in_dy,
+ float *pdf)
{
- const ToonBsdf *bsdf = (const ToonBsdf*)sc;
- float max_angle = bsdf->size*M_PI_2_F;
- float smooth = bsdf->smooth*M_PI_2_F;
- float sample_angle = bsdf_toon_get_sample_angle(max_angle, smooth);
- float angle = sample_angle*randu;
+ const ToonBsdf *bsdf = (const ToonBsdf *)sc;
+ float max_angle = bsdf->size * M_PI_2_F;
+ float smooth = bsdf->smooth * M_PI_2_F;
+ float sample_angle = bsdf_toon_get_sample_angle(max_angle, smooth);
+ float angle = sample_angle * randu;
- if(sample_angle > 0.0f) {
- sample_uniform_cone(bsdf->N, sample_angle, randu, randv, omega_in, pdf);
+ if (sample_angle > 0.0f) {
+ sample_uniform_cone(bsdf->N, sample_angle, randu, randv, omega_in, pdf);
- if(dot(Ng, *omega_in) > 0.0f) {
- *eval = *pdf * bsdf_toon_get_intensity(max_angle, smooth, angle);
+ if (dot(Ng, *omega_in) > 0.0f) {
+ *eval = *pdf * bsdf_toon_get_intensity(max_angle, smooth, angle);
#ifdef __RAY_DIFFERENTIALS__
- // TODO: find a better approximation for the bounce
- *domega_in_dx = (2.0f * dot(bsdf->N, dIdx)) * bsdf->N - dIdx;
- *domega_in_dy = (2.0f * dot(bsdf->N, dIdy)) * bsdf->N - dIdy;
+ // TODO: find a better approximation for the bounce
+ *domega_in_dx = (2.0f * dot(bsdf->N, dIdx)) * bsdf->N - dIdx;
+ *domega_in_dy = (2.0f * dot(bsdf->N, dIdy)) * bsdf->N - dIdy;
#endif
- }
- else
- *pdf = 0.0f;
- }
-
- return LABEL_REFLECT | LABEL_DIFFUSE;
+ }
+ else
+ *pdf = 0.0f;
+ }
+ return LABEL_REFLECT | LABEL_DIFFUSE;
}
/* GLOSSY TOON */
ccl_device int bsdf_glossy_toon_setup(ToonBsdf *bsdf)
{
- bsdf->type = CLOSURE_BSDF_GLOSSY_TOON_ID;
- bsdf->size = saturate(bsdf->size);
- bsdf->smooth = saturate(bsdf->smooth);
+ bsdf->type = CLOSURE_BSDF_GLOSSY_TOON_ID;
+ bsdf->size = saturate(bsdf->size);
+ bsdf->smooth = saturate(bsdf->smooth);
- return SD_BSDF|SD_BSDF_HAS_EVAL;
+ return SD_BSDF | SD_BSDF_HAS_EVAL;
}
-ccl_device float3 bsdf_glossy_toon_eval_reflect(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf)
+ccl_device float3 bsdf_glossy_toon_eval_reflect(const ShaderClosure *sc,
+ const float3 I,
+ const float3 omega_in,
+ float *pdf)
{
- const ToonBsdf *bsdf = (const ToonBsdf*)sc;
- float max_angle = bsdf->size*M_PI_2_F;
- float smooth = bsdf->smooth*M_PI_2_F;
- float cosNI = dot(bsdf->N, omega_in);
- float cosNO = dot(bsdf->N, I);
+ const ToonBsdf *bsdf = (const ToonBsdf *)sc;
+ float max_angle = bsdf->size * M_PI_2_F;
+ float smooth = bsdf->smooth * M_PI_2_F;
+ float cosNI = dot(bsdf->N, omega_in);
+ float cosNO = dot(bsdf->N, I);
- if(cosNI > 0 && cosNO > 0) {
- /* reflect the view vector */
- float3 R = (2 * cosNO) * bsdf->N - I;
- float cosRI = dot(R, omega_in);
+ if (cosNI > 0 && cosNO > 0) {
+ /* reflect the view vector */
+ float3 R = (2 * cosNO) * bsdf->N - I;
+ float cosRI = dot(R, omega_in);
- float angle = safe_acosf(fmaxf(cosRI, 0.0f));
+ float angle = safe_acosf(fmaxf(cosRI, 0.0f));
- float3 eval = bsdf_toon_get_intensity(max_angle, smooth, angle);
- float sample_angle = bsdf_toon_get_sample_angle(max_angle, smooth);
+ float3 eval = bsdf_toon_get_intensity(max_angle, smooth, angle);
+ float sample_angle = bsdf_toon_get_sample_angle(max_angle, smooth);
- *pdf = 0.5f * M_1_PI_F / (1.0f - cosf(sample_angle));
- return *pdf * eval;
- }
+ *pdf = 0.5f * M_1_PI_F / (1.0f - cosf(sample_angle));
+ return *pdf * eval;
+ }
- return make_float3(0.0f, 0.0f, 0.0f);
+ return make_float3(0.0f, 0.0f, 0.0f);
}
-ccl_device float3 bsdf_glossy_toon_eval_transmit(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf)
+ccl_device float3 bsdf_glossy_toon_eval_transmit(const ShaderClosure *sc,
+ const float3 I,
+ const float3 omega_in,
+ float *pdf)
{
- return make_float3(0.0f, 0.0f, 0.0f);
+ return make_float3(0.0f, 0.0f, 0.0f);
}
-ccl_device int bsdf_glossy_toon_sample(const ShaderClosure *sc, float3 Ng, float3 I, float3 dIdx, float3 dIdy, float randu, float randv, float3 *eval, float3 *omega_in, float3 *domega_in_dx, float3 *domega_in_dy, float *pdf)
+ccl_device int bsdf_glossy_toon_sample(const ShaderClosure *sc,
+ float3 Ng,
+ float3 I,
+ float3 dIdx,
+ float3 dIdy,
+ float randu,
+ float randv,
+ float3 *eval,
+ float3 *omega_in,
+ float3 *domega_in_dx,
+ float3 *domega_in_dy,
+ float *pdf)
{
- const ToonBsdf *bsdf = (const ToonBsdf*)sc;
- float max_angle = bsdf->size*M_PI_2_F;
- float smooth = bsdf->smooth*M_PI_2_F;
- float cosNO = dot(bsdf->N, I);
+ const ToonBsdf *bsdf = (const ToonBsdf *)sc;
+ float max_angle = bsdf->size * M_PI_2_F;
+ float smooth = bsdf->smooth * M_PI_2_F;
+ float cosNO = dot(bsdf->N, I);
- if(cosNO > 0) {
- /* reflect the view vector */
- float3 R = (2 * cosNO) * bsdf->N - I;
+ if (cosNO > 0) {
+ /* reflect the view vector */
+ float3 R = (2 * cosNO) * bsdf->N - I;
- float sample_angle = bsdf_toon_get_sample_angle(max_angle, smooth);
- float angle = sample_angle*randu;
+ float sample_angle = bsdf_toon_get_sample_angle(max_angle, smooth);
+ float angle = sample_angle * randu;
- sample_uniform_cone(R, sample_angle, randu, randv, omega_in, pdf);
+ sample_uniform_cone(R, sample_angle, randu, randv, omega_in, pdf);
- if(dot(Ng, *omega_in) > 0.0f) {
- float cosNI = dot(bsdf->N, *omega_in);
+ if (dot(Ng, *omega_in) > 0.0f) {
+ float cosNI = dot(bsdf->N, *omega_in);
- /* make sure the direction we chose is still in the right hemisphere */
- if(cosNI > 0) {
- *eval = *pdf * bsdf_toon_get_intensity(max_angle, smooth, angle);
+ /* make sure the direction we chose is still in the right hemisphere */
+ if (cosNI > 0) {
+ *eval = *pdf * bsdf_toon_get_intensity(max_angle, smooth, angle);
#ifdef __RAY_DIFFERENTIALS__
- *domega_in_dx = (2 * dot(bsdf->N, dIdx)) * bsdf->N - dIdx;
- *domega_in_dy = (2 * dot(bsdf->N, dIdy)) * bsdf->N - dIdy;
+ *domega_in_dx = (2 * dot(bsdf->N, dIdx)) * bsdf->N - dIdx;
+ *domega_in_dy = (2 * dot(bsdf->N, dIdy)) * bsdf->N - dIdy;
#endif
- }
- else
- *pdf = 0.0f;
- }
- else
- *pdf = 0.0f;
- }
-
- return LABEL_GLOSSY | LABEL_REFLECT;
+ }
+ else
+ *pdf = 0.0f;
+ }
+ else
+ *pdf = 0.0f;
+ }
+
+ return LABEL_GLOSSY | LABEL_REFLECT;
}
CCL_NAMESPACE_END
-#endif /* __BSDF_TOON_H__ */
+#endif /* __BSDF_TOON_H__ */
diff --git a/intern/cycles/kernel/closure/bsdf_transparent.h b/intern/cycles/kernel/closure/bsdf_transparent.h
index 060dff69f52..4e5513499e8 100644
--- a/intern/cycles/kernel/closure/bsdf_transparent.h
+++ b/intern/cycles/kernel/closure/bsdf_transparent.h
@@ -37,73 +37,91 @@ CCL_NAMESPACE_BEGIN
ccl_device void bsdf_transparent_setup(ShaderData *sd, const float3 weight, int path_flag)
{
- /* Check cutoff weight. */
- float sample_weight = fabsf(average(weight));
- if(!(sample_weight >= CLOSURE_WEIGHT_CUTOFF)) {
- return;
- }
+ /* Check cutoff weight. */
+ float sample_weight = fabsf(average(weight));
+ if (!(sample_weight >= CLOSURE_WEIGHT_CUTOFF)) {
+ return;
+ }
- if(sd->flag & SD_TRANSPARENT) {
- sd->closure_transparent_extinction += weight;
+ if (sd->flag & SD_TRANSPARENT) {
+ sd->closure_transparent_extinction += weight;
- /* Add weight to existing transparent BSDF. */
- for(int i = 0; i < sd->num_closure; i++) {
- ShaderClosure *sc = &sd->closure[i];
+ /* Add weight to existing transparent BSDF. */
+ for (int i = 0; i < sd->num_closure; i++) {
+ ShaderClosure *sc = &sd->closure[i];
- if(sc->type == CLOSURE_BSDF_TRANSPARENT_ID) {
- sc->weight += weight;
- sc->sample_weight += sample_weight;
- break;
- }
- }
- }
- else {
- sd->flag |= SD_BSDF|SD_TRANSPARENT;
- sd->closure_transparent_extinction = weight;
+ if (sc->type == CLOSURE_BSDF_TRANSPARENT_ID) {
+ sc->weight += weight;
+ sc->sample_weight += sample_weight;
+ break;
+ }
+ }
+ }
+ else {
+ sd->flag |= SD_BSDF | SD_TRANSPARENT;
+ sd->closure_transparent_extinction = weight;
- if(path_flag & PATH_RAY_TERMINATE) {
- /* In this case the number of closures is set to zero to disable
- * all others, but we still want to get transparency so increase
- * the number just for this. */
- sd->num_closure_left = 1;
- }
+ if (path_flag & PATH_RAY_TERMINATE) {
+ /* In this case the number of closures is set to zero to disable
+ * all others, but we still want to get transparency so increase
+ * the number just for this. */
+ sd->num_closure_left = 1;
+ }
- /* Create new transparent BSDF. */
- ShaderClosure *bsdf = closure_alloc(sd, sizeof(ShaderClosure), CLOSURE_BSDF_TRANSPARENT_ID, weight);
+ /* Create new transparent BSDF. */
+ ShaderClosure *bsdf = closure_alloc(
+ sd, sizeof(ShaderClosure), CLOSURE_BSDF_TRANSPARENT_ID, weight);
- if(bsdf) {
- bsdf->sample_weight = sample_weight;
- bsdf->N = sd->N;
- }
- else if(path_flag & PATH_RAY_TERMINATE) {
- sd->num_closure_left = 0;
- }
- }
+ if (bsdf) {
+ bsdf->sample_weight = sample_weight;
+ bsdf->N = sd->N;
+ }
+ else if (path_flag & PATH_RAY_TERMINATE) {
+ sd->num_closure_left = 0;
+ }
+ }
}
-ccl_device float3 bsdf_transparent_eval_reflect(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf)
+ccl_device float3 bsdf_transparent_eval_reflect(const ShaderClosure *sc,
+ const float3 I,
+ const float3 omega_in,
+ float *pdf)
{
- return make_float3(0.0f, 0.0f, 0.0f);
+ return make_float3(0.0f, 0.0f, 0.0f);
}
-ccl_device float3 bsdf_transparent_eval_transmit(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf)
+ccl_device float3 bsdf_transparent_eval_transmit(const ShaderClosure *sc,
+ const float3 I,
+ const float3 omega_in,
+ float *pdf)
{
- return make_float3(0.0f, 0.0f, 0.0f);
+ return make_float3(0.0f, 0.0f, 0.0f);
}
-ccl_device int bsdf_transparent_sample(const ShaderClosure *sc, float3 Ng, float3 I, float3 dIdx, float3 dIdy, float randu, float randv, float3 *eval, float3 *omega_in, float3 *domega_in_dx, float3 *domega_in_dy, float *pdf)
+ccl_device int bsdf_transparent_sample(const ShaderClosure *sc,
+ float3 Ng,
+ float3 I,
+ float3 dIdx,
+ float3 dIdy,
+ float randu,
+ float randv,
+ float3 *eval,
+ float3 *omega_in,
+ float3 *domega_in_dx,
+ float3 *domega_in_dy,
+ float *pdf)
{
- // only one direction is possible
- *omega_in = -I;
+ // only one direction is possible
+ *omega_in = -I;
#ifdef __RAY_DIFFERENTIALS__
- *domega_in_dx = -dIdx;
- *domega_in_dy = -dIdy;
+ *domega_in_dx = -dIdx;
+ *domega_in_dy = -dIdy;
#endif
- *pdf = 1;
- *eval = make_float3(1, 1, 1);
- return LABEL_TRANSMIT|LABEL_TRANSPARENT;
+ *pdf = 1;
+ *eval = make_float3(1, 1, 1);
+ return LABEL_TRANSMIT | LABEL_TRANSPARENT;
}
CCL_NAMESPACE_END
-#endif /* __BSDF_TRANSPARENT_H__ */
+#endif /* __BSDF_TRANSPARENT_H__ */
diff --git a/intern/cycles/kernel/closure/bsdf_util.h b/intern/cycles/kernel/closure/bsdf_util.h
index 4f3453675c7..a9a27edd7de 100644
--- a/intern/cycles/kernel/closure/bsdf_util.h
+++ b/intern/cycles/kernel/closure/bsdf_util.h
@@ -35,127 +35,134 @@
CCL_NAMESPACE_BEGIN
-ccl_device float fresnel_dielectric(
- float eta, const float3 N,
- const float3 I, float3 *R, float3 *T,
+ccl_device float fresnel_dielectric(float eta,
+ const float3 N,
+ const float3 I,
+ float3 *R,
+ float3 *T,
#ifdef __RAY_DIFFERENTIALS__
- const float3 dIdx, const float3 dIdy,
- float3 *dRdx, float3 *dRdy,
- float3 *dTdx, float3 *dTdy,
+ const float3 dIdx,
+ const float3 dIdy,
+ float3 *dRdx,
+ float3 *dRdy,
+ float3 *dTdx,
+ float3 *dTdy,
#endif
- bool *is_inside)
+ bool *is_inside)
{
- float cos = dot(N, I), neta;
- float3 Nn;
+ float cos = dot(N, I), neta;
+ float3 Nn;
- // check which side of the surface we are on
- if(cos > 0) {
- // we are on the outside of the surface, going in
- neta = 1 / eta;
- Nn = N;
- *is_inside = false;
- }
- else {
- // we are inside the surface
- cos = -cos;
- neta = eta;
- Nn = -N;
- *is_inside = true;
- }
+ // check which side of the surface we are on
+ if (cos > 0) {
+ // we are on the outside of the surface, going in
+ neta = 1 / eta;
+ Nn = N;
+ *is_inside = false;
+ }
+ else {
+ // we are inside the surface
+ cos = -cos;
+ neta = eta;
+ Nn = -N;
+ *is_inside = true;
+ }
- // compute reflection
- *R = (2 * cos)* Nn - I;
+ // compute reflection
+ *R = (2 * cos) * Nn - I;
#ifdef __RAY_DIFFERENTIALS__
- *dRdx = (2 * dot(Nn, dIdx)) * Nn - dIdx;
- *dRdy = (2 * dot(Nn, dIdy)) * Nn - dIdy;
+ *dRdx = (2 * dot(Nn, dIdx)) * Nn - dIdx;
+ *dRdy = (2 * dot(Nn, dIdy)) * Nn - dIdy;
#endif
- float arg = 1 -(neta * neta *(1 -(cos * cos)));
- if(arg < 0) {
- *T = make_float3(0.0f, 0.0f, 0.0f);
+ float arg = 1 - (neta * neta * (1 - (cos * cos)));
+ if (arg < 0) {
+ *T = make_float3(0.0f, 0.0f, 0.0f);
#ifdef __RAY_DIFFERENTIALS__
- *dTdx = make_float3(0.0f, 0.0f, 0.0f);
- *dTdy = make_float3(0.0f, 0.0f, 0.0f);
+ *dTdx = make_float3(0.0f, 0.0f, 0.0f);
+ *dTdy = make_float3(0.0f, 0.0f, 0.0f);
#endif
- return 1; // total internal reflection
- }
- else {
- float dnp = max(sqrtf(arg), 1e-7f);
- float nK = (neta * cos)- dnp;
- *T = -(neta * I)+(nK * Nn);
+ return 1; // total internal reflection
+ }
+ else {
+ float dnp = max(sqrtf(arg), 1e-7f);
+ float nK = (neta * cos) - dnp;
+ *T = -(neta * I) + (nK * Nn);
#ifdef __RAY_DIFFERENTIALS__
- *dTdx = -(neta * dIdx) + ((neta - neta * neta * cos / dnp) * dot(dIdx, Nn)) * Nn;
- *dTdy = -(neta * dIdy) + ((neta - neta * neta * cos / dnp) * dot(dIdy, Nn)) * Nn;
+ *dTdx = -(neta * dIdx) + ((neta - neta * neta * cos / dnp) * dot(dIdx, Nn)) * Nn;
+ *dTdy = -(neta * dIdy) + ((neta - neta * neta * cos / dnp) * dot(dIdy, Nn)) * Nn;
#endif
- // compute Fresnel terms
- float cosTheta1 = cos; // N.R
- float cosTheta2 = -dot(Nn, *T);
- float pPara = (cosTheta1 - eta * cosTheta2)/(cosTheta1 + eta * cosTheta2);
- float pPerp = (eta * cosTheta1 - cosTheta2)/(eta * cosTheta1 + cosTheta2);
- return 0.5f * (pPara * pPara + pPerp * pPerp);
- }
+ // compute Fresnel terms
+ float cosTheta1 = cos; // N.R
+ float cosTheta2 = -dot(Nn, *T);
+ float pPara = (cosTheta1 - eta * cosTheta2) / (cosTheta1 + eta * cosTheta2);
+ float pPerp = (eta * cosTheta1 - cosTheta2) / (eta * cosTheta1 + cosTheta2);
+ return 0.5f * (pPara * pPara + pPerp * pPerp);
+ }
}
ccl_device float fresnel_dielectric_cos(float cosi, float eta)
{
- // compute fresnel reflectance without explicitly computing
- // the refracted direction
- float c = fabsf(cosi);
- float g = eta * eta - 1 + c * c;
- if(g > 0) {
- g = sqrtf(g);
- float A = (g - c)/(g + c);
- float B = (c *(g + c)- 1)/(c *(g - c)+ 1);
- return 0.5f * A * A *(1 + B * B);
- }
- return 1.0f; // TIR(no refracted component)
+ // compute fresnel reflectance without explicitly computing
+ // the refracted direction
+ float c = fabsf(cosi);
+ float g = eta * eta - 1 + c * c;
+ if (g > 0) {
+ g = sqrtf(g);
+ float A = (g - c) / (g + c);
+ float B = (c * (g + c) - 1) / (c * (g - c) + 1);
+ return 0.5f * A * A * (1 + B * B);
+ }
+ return 1.0f; // TIR(no refracted component)
}
ccl_device float3 fresnel_conductor(float cosi, const float3 eta, const float3 k)
{
- float3 cosi2 = make_float3(cosi*cosi, cosi*cosi, cosi*cosi);
- float3 one = make_float3(1.0f, 1.0f, 1.0f);
- float3 tmp_f = eta * eta + k * k;
- float3 tmp = tmp_f * cosi2;
- float3 Rparl2 = (tmp - (2.0f * eta * cosi) + one) /
- (tmp + (2.0f * eta * cosi) + one);
- float3 Rperp2 = (tmp_f - (2.0f * eta * cosi) + cosi2) /
- (tmp_f + (2.0f * eta * cosi) + cosi2);
- return(Rparl2 + Rperp2) * 0.5f;
+ float3 cosi2 = make_float3(cosi * cosi, cosi * cosi, cosi * cosi);
+ float3 one = make_float3(1.0f, 1.0f, 1.0f);
+ float3 tmp_f = eta * eta + k * k;
+ float3 tmp = tmp_f * cosi2;
+ float3 Rparl2 = (tmp - (2.0f * eta * cosi) + one) / (tmp + (2.0f * eta * cosi) + one);
+ float3 Rperp2 = (tmp_f - (2.0f * eta * cosi) + cosi2) / (tmp_f + (2.0f * eta * cosi) + cosi2);
+ return (Rparl2 + Rperp2) * 0.5f;
}
ccl_device float schlick_fresnel(float u)
{
- float m = clamp(1.0f - u, 0.0f, 1.0f);
- float m2 = m * m;
- return m2 * m2 * m; // pow(m, 5)
+ float m = clamp(1.0f - u, 0.0f, 1.0f);
+ float m2 = m * m;
+ return m2 * m2 * m; // pow(m, 5)
}
ccl_device float smooth_step(float edge0, float edge1, float x)
{
- float result;
- if(x < edge0) result = 0.0f;
- else if(x >= edge1) result = 1.0f;
- else {
- float t = (x - edge0)/(edge1 - edge0);
- result = (3.0f-2.0f*t)*(t*t);
- }
- return result;
+ float result;
+ if (x < edge0)
+ result = 0.0f;
+ else if (x >= edge1)
+ result = 1.0f;
+ else {
+ float t = (x - edge0) / (edge1 - edge0);
+ result = (3.0f - 2.0f * t) * (t * t);
+ }
+ return result;
}
/* Calculate the fresnel color which is a blend between white and the F0 color (cspec0) */
-ccl_device_forceinline float3 interpolate_fresnel_color(float3 L, float3 H, float ior, float F0, float3 cspec0) {
- /* Calculate the fresnel interpolation factor
- * The value from fresnel_dielectric_cos(...) has to be normalized because
- * the cspec0 keeps the F0 color
- */
- float F0_norm = 1.0f / (1.0f - F0);
- float FH = (fresnel_dielectric_cos(dot(L, H), ior) - F0) * F0_norm;
+ccl_device_forceinline float3
+interpolate_fresnel_color(float3 L, float3 H, float ior, float F0, float3 cspec0)
+{
+ /* Calculate the fresnel interpolation factor
+ * The value from fresnel_dielectric_cos(...) has to be normalized because
+ * the cspec0 keeps the F0 color
+ */
+ float F0_norm = 1.0f / (1.0f - F0);
+ float FH = (fresnel_dielectric_cos(dot(L, H), ior) - F0) * F0_norm;
- /* Blend between white and a specular color with respect to the fresnel */
- return cspec0 * (1.0f - FH) + make_float3(1.0f, 1.0f, 1.0f) * FH;
+ /* Blend between white and a specular color with respect to the fresnel */
+ return cspec0 * (1.0f - FH) + make_float3(1.0f, 1.0f, 1.0f) * FH;
}
CCL_NAMESPACE_END
-#endif /* __BSDF_UTIL_H__ */
+#endif /* __BSDF_UTIL_H__ */
diff --git a/intern/cycles/kernel/closure/bssrdf.h b/intern/cycles/kernel/closure/bssrdf.h
index 98c7f23c288..57804eca269 100644
--- a/intern/cycles/kernel/closure/bssrdf.h
+++ b/intern/cycles/kernel/closure/bssrdf.h
@@ -20,14 +20,14 @@
CCL_NAMESPACE_BEGIN
typedef ccl_addr_space struct Bssrdf {
- SHADER_CLOSURE_BASE;
-
- float3 radius;
- float3 albedo;
- float sharpness;
- float texture_blur;
- float roughness;
- float channels;
+ SHADER_CLOSURE_BASE;
+
+ float3 radius;
+ float3 albedo;
+ float sharpness;
+ float texture_blur;
+ float roughness;
+ float channels;
} Bssrdf;
/* Planar Truncated Gaussian
@@ -41,41 +41,41 @@ typedef ccl_addr_space struct Bssrdf {
ccl_device float bssrdf_gaussian_eval(const float radius, float r)
{
- /* integrate (2*pi*r * exp(-r*r/(2*v)))/(2*pi*v)) from 0 to Rm
- * = 1 - exp(-Rm*Rm/(2*v)) */
- const float v = radius*radius*(0.25f*0.25f);
- const float Rm = sqrtf(v*GAUSS_TRUNCATE);
+ /* integrate (2*pi*r * exp(-r*r/(2*v)))/(2*pi*v)) from 0 to Rm
+ * = 1 - exp(-Rm*Rm/(2*v)) */
+ const float v = radius * radius * (0.25f * 0.25f);
+ const float Rm = sqrtf(v * GAUSS_TRUNCATE);
- if(r >= Rm)
- return 0.0f;
+ if (r >= Rm)
+ return 0.0f;
- return expf(-r*r/(2.0f*v))/(2.0f*M_PI_F*v);
+ return expf(-r * r / (2.0f * v)) / (2.0f * M_PI_F * v);
}
ccl_device float bssrdf_gaussian_pdf(const float radius, float r)
{
- /* 1.0 - expf(-Rm*Rm/(2*v)) simplified */
- const float area_truncated = 1.0f - expf(-0.5f*GAUSS_TRUNCATE);
+ /* 1.0 - expf(-Rm*Rm/(2*v)) simplified */
+ const float area_truncated = 1.0f - expf(-0.5f * GAUSS_TRUNCATE);
- return bssrdf_gaussian_eval(radius, r) * (1.0f/(area_truncated));
+ return bssrdf_gaussian_eval(radius, r) * (1.0f / (area_truncated));
}
ccl_device void bssrdf_gaussian_sample(const float radius, float xi, float *r, float *h)
{
- /* xi = integrate (2*pi*r * exp(-r*r/(2*v)))/(2*pi*v)) = -exp(-r^2/(2*v))
- * r = sqrt(-2*v*logf(xi)) */
- const float v = radius*radius*(0.25f*0.25f);
- const float Rm = sqrtf(v*GAUSS_TRUNCATE);
+ /* xi = integrate (2*pi*r * exp(-r*r/(2*v)))/(2*pi*v)) = -exp(-r^2/(2*v))
+ * r = sqrt(-2*v*logf(xi)) */
+ const float v = radius * radius * (0.25f * 0.25f);
+ const float Rm = sqrtf(v * GAUSS_TRUNCATE);
- /* 1.0 - expf(-Rm*Rm/(2*v)) simplified */
- const float area_truncated = 1.0f - expf(-0.5f*GAUSS_TRUNCATE);
+ /* 1.0 - expf(-Rm*Rm/(2*v)) simplified */
+ const float area_truncated = 1.0f - expf(-0.5f * GAUSS_TRUNCATE);
- /* r(xi) */
- const float r_squared = -2.0f*v*logf(1.0f - xi*area_truncated);
- *r = sqrtf(r_squared);
+ /* r(xi) */
+ const float r_squared = -2.0f * v * logf(1.0f - xi * area_truncated);
+ *r = sqrtf(r_squared);
- /* h^2 + r^2 = Rm^2 */
- *h = safe_sqrtf(Rm*Rm - r_squared);
+ /* h^2 + r^2 = Rm^2 */
+ *h = safe_sqrtf(Rm * Rm - r_squared);
}
/* Planar Cubic BSSRDF falloff
@@ -87,97 +87,97 @@ ccl_device void bssrdf_gaussian_sample(const float radius, float xi, float *r, f
ccl_device float bssrdf_cubic_eval(const float radius, const float sharpness, float r)
{
- if(sharpness == 0.0f) {
- const float Rm = radius;
-
- if(r >= Rm)
- return 0.0f;
-
- /* integrate (2*pi*r * 10*(R - r)^3)/(pi * R^5) from 0 to R = 1 */
- const float Rm5 = (Rm*Rm) * (Rm*Rm) * Rm;
- const float f = Rm - r;
- const float num = f*f*f;
-
- return (10.0f * num) / (Rm5 * M_PI_F);
-
- }
- else {
- float Rm = radius*(1.0f + sharpness);
-
- if(r >= Rm)
- return 0.0f;
-
- /* custom variation with extra sharpness, to match the previous code */
- const float y = 1.0f/(1.0f + sharpness);
- float Rmy, ry, ryinv;
-
- if(sharpness == 1.0f) {
- Rmy = sqrtf(Rm);
- ry = sqrtf(r);
- ryinv = (ry > 0.0f)? 1.0f/ry: 0.0f;
- }
- else {
- Rmy = powf(Rm, y);
- ry = powf(r, y);
- ryinv = (r > 0.0f)? powf(r, y - 1.0f): 0.0f;
- }
-
- const float Rmy5 = (Rmy*Rmy) * (Rmy*Rmy) * Rmy;
- const float f = Rmy - ry;
- const float num = f*(f*f)*(y*ryinv);
-
- return (10.0f * num) / (Rmy5 * M_PI_F);
- }
+ if (sharpness == 0.0f) {
+ const float Rm = radius;
+
+ if (r >= Rm)
+ return 0.0f;
+
+ /* integrate (2*pi*r * 10*(R - r)^3)/(pi * R^5) from 0 to R = 1 */
+ const float Rm5 = (Rm * Rm) * (Rm * Rm) * Rm;
+ const float f = Rm - r;
+ const float num = f * f * f;
+
+ return (10.0f * num) / (Rm5 * M_PI_F);
+ }
+ else {
+ float Rm = radius * (1.0f + sharpness);
+
+ if (r >= Rm)
+ return 0.0f;
+
+ /* custom variation with extra sharpness, to match the previous code */
+ const float y = 1.0f / (1.0f + sharpness);
+ float Rmy, ry, ryinv;
+
+ if (sharpness == 1.0f) {
+ Rmy = sqrtf(Rm);
+ ry = sqrtf(r);
+ ryinv = (ry > 0.0f) ? 1.0f / ry : 0.0f;
+ }
+ else {
+ Rmy = powf(Rm, y);
+ ry = powf(r, y);
+ ryinv = (r > 0.0f) ? powf(r, y - 1.0f) : 0.0f;
+ }
+
+ const float Rmy5 = (Rmy * Rmy) * (Rmy * Rmy) * Rmy;
+ const float f = Rmy - ry;
+ const float num = f * (f * f) * (y * ryinv);
+
+ return (10.0f * num) / (Rmy5 * M_PI_F);
+ }
}
ccl_device float bssrdf_cubic_pdf(const float radius, const float sharpness, float r)
{
- return bssrdf_cubic_eval(radius, sharpness, r);
+ return bssrdf_cubic_eval(radius, sharpness, r);
}
/* solve 10x^2 - 20x^3 + 15x^4 - 4x^5 - xi == 0 */
ccl_device_forceinline float bssrdf_cubic_quintic_root_find(float xi)
{
- /* newton-raphson iteration, usually succeeds in 2-4 iterations, except
- * outside 0.02 ... 0.98 where it can go up to 10, so overall performance
- * should not be too bad */
- const float tolerance = 1e-6f;
- const int max_iteration_count = 10;
- float x = 0.25f;
- int i;
+ /* newton-raphson iteration, usually succeeds in 2-4 iterations, except
+ * outside 0.02 ... 0.98 where it can go up to 10, so overall performance
+ * should not be too bad */
+ const float tolerance = 1e-6f;
+ const int max_iteration_count = 10;
+ float x = 0.25f;
+ int i;
- for(i = 0; i < max_iteration_count; i++) {
- float x2 = x*x;
- float x3 = x2*x;
- float nx = (1.0f - x);
+ for (i = 0; i < max_iteration_count; i++) {
+ float x2 = x * x;
+ float x3 = x2 * x;
+ float nx = (1.0f - x);
- float f = 10.0f*x2 - 20.0f*x3 + 15.0f*x2*x2 - 4.0f*x2*x3 - xi;
- float f_ = 20.0f*(x*nx)*(nx*nx);
+ float f = 10.0f * x2 - 20.0f * x3 + 15.0f * x2 * x2 - 4.0f * x2 * x3 - xi;
+ float f_ = 20.0f * (x * nx) * (nx * nx);
- if(fabsf(f) < tolerance || f_ == 0.0f)
- break;
+ if (fabsf(f) < tolerance || f_ == 0.0f)
+ break;
- x = saturate(x - f/f_);
- }
+ x = saturate(x - f / f_);
+ }
- return x;
+ return x;
}
-ccl_device void bssrdf_cubic_sample(const float radius, const float sharpness, float xi, float *r, float *h)
+ccl_device void bssrdf_cubic_sample(
+ const float radius, const float sharpness, float xi, float *r, float *h)
{
- float Rm = radius;
- float r_ = bssrdf_cubic_quintic_root_find(xi);
+ float Rm = radius;
+ float r_ = bssrdf_cubic_quintic_root_find(xi);
- if(sharpness != 0.0f) {
- r_ = powf(r_, 1.0f + sharpness);
- Rm *= (1.0f + sharpness);
- }
+ if (sharpness != 0.0f) {
+ r_ = powf(r_, 1.0f + sharpness);
+ Rm *= (1.0f + sharpness);
+ }
- r_ *= Rm;
- *r = r_;
+ r_ *= Rm;
+ *r = r_;
- /* h^2 + r^2 = Rm^2 */
- *h = safe_sqrtf(Rm*Rm - r_*r_);
+ /* h^2 + r^2 = Rm^2 */
+ *h = safe_sqrtf(Rm * Rm - r_ * r_);
}
/* Approximate Reflectance Profiles
@@ -188,13 +188,13 @@ ccl_device void bssrdf_cubic_sample(const float radius, const float sharpness, f
* the mean free length, but still not too big so sampling is still
* effective. Might need some further tweaks.
*/
-#define BURLEY_TRUNCATE 16.0f
-#define BURLEY_TRUNCATE_CDF 0.9963790093708328f // cdf(BURLEY_TRUNCATE)
+#define BURLEY_TRUNCATE 16.0f
+#define BURLEY_TRUNCATE_CDF 0.9963790093708328f // cdf(BURLEY_TRUNCATE)
ccl_device_inline float bssrdf_burley_fitting(float A)
{
- /* Diffuse surface transmission, equation (6). */
- return 1.9f - A + 3.5f * (A - 0.8f) * (A - 0.8f);
+ /* Diffuse surface transmission, equation (6). */
+ return 1.9f - A + 3.5f * (A - 0.8f) * (A - 0.8f);
}
/* Scale mean free path length so it gives similar looking result
@@ -202,45 +202,44 @@ ccl_device_inline float bssrdf_burley_fitting(float A)
*/
ccl_device_inline float3 bssrdf_burley_compatible_mfp(float3 r)
{
- return 0.25f * M_1_PI_F * r;
+ return 0.25f * M_1_PI_F * r;
}
ccl_device void bssrdf_burley_setup(Bssrdf *bssrdf)
{
- /* Mean free path length. */
- const float3 l = bssrdf_burley_compatible_mfp(bssrdf->radius);
- /* Surface albedo. */
- const float3 A = bssrdf->albedo;
- const float3 s = make_float3(bssrdf_burley_fitting(A.x),
- bssrdf_burley_fitting(A.y),
- bssrdf_burley_fitting(A.z));
-
- bssrdf->radius = l / s;
+ /* Mean free path length. */
+ const float3 l = bssrdf_burley_compatible_mfp(bssrdf->radius);
+ /* Surface albedo. */
+ const float3 A = bssrdf->albedo;
+ const float3 s = make_float3(
+ bssrdf_burley_fitting(A.x), bssrdf_burley_fitting(A.y), bssrdf_burley_fitting(A.z));
+
+ bssrdf->radius = l / s;
}
ccl_device float bssrdf_burley_eval(const float d, float r)
{
- const float Rm = BURLEY_TRUNCATE * d;
-
- if(r >= Rm)
- return 0.0f;
-
- /* Burley refletance profile, equation (3).
- *
- * NOTES:
- * - Surface albedo is already included into sc->weight, no need to
- * multiply by this term here.
- * - This is normalized diffuse model, so the equation is mutliplied
- * by 2*pi, which also matches cdf().
- */
- float exp_r_3_d = expf(-r / (3.0f * d));
- float exp_r_d = exp_r_3_d * exp_r_3_d * exp_r_3_d;
- return (exp_r_d + exp_r_3_d) / (4.0f*d);
+ const float Rm = BURLEY_TRUNCATE * d;
+
+ if (r >= Rm)
+ return 0.0f;
+
+ /* Burley refletance profile, equation (3).
+ *
+ * NOTES:
+ * - Surface albedo is already included into sc->weight, no need to
+ * multiply by this term here.
+ * - This is normalized diffuse model, so the equation is mutliplied
+ * by 2*pi, which also matches cdf().
+ */
+ float exp_r_3_d = expf(-r / (3.0f * d));
+ float exp_r_d = exp_r_3_d * exp_r_3_d * exp_r_3_d;
+ return (exp_r_d + exp_r_3_d) / (4.0f * d);
}
ccl_device float bssrdf_burley_pdf(const float d, float r)
{
- return bssrdf_burley_eval(d, r) * (1.0f/BURLEY_TRUNCATE_CDF);
+ return bssrdf_burley_eval(d, r) * (1.0f / BURLEY_TRUNCATE_CDF);
}
/* Find the radius for desired CDF value.
@@ -249,52 +248,49 @@ ccl_device float bssrdf_burley_pdf(const float d, float r)
*/
ccl_device_forceinline float bssrdf_burley_root_find(float xi)
{
- const float tolerance = 1e-6f;
- const int max_iteration_count = 10;
- /* Do initial guess based on manual curve fitting, this allows us to reduce
- * number of iterations to maximum 4 across the [0..1] range. We keep maximum
- * number of iteration higher just to be sure we didn't miss root in some
- * corner case.
- */
- float r;
- if(xi <= 0.9f) {
- r = expf(xi * xi * 2.4f) - 1.0f;
- }
- else {
- /* TODO(sergey): Some nicer curve fit is possible here. */
- r = 15.0f;
- }
- /* Solve against scaled radius. */
- for(int i = 0; i < max_iteration_count; i++) {
- float exp_r_3 = expf(-r / 3.0f);
- float exp_r = exp_r_3 * exp_r_3 * exp_r_3;
- float f = 1.0f - 0.25f * exp_r - 0.75f * exp_r_3 - xi;
- float f_ = 0.25f * exp_r + 0.25f * exp_r_3;
-
- if(fabsf(f) < tolerance || f_ == 0.0f) {
- break;
- }
-
- r = r - f/f_;
- if(r < 0.0f) {
- r = 0.0f;
- }
- }
- return r;
+ const float tolerance = 1e-6f;
+ const int max_iteration_count = 10;
+ /* Do initial guess based on manual curve fitting, this allows us to reduce
+ * number of iterations to maximum 4 across the [0..1] range. We keep maximum
+ * number of iteration higher just to be sure we didn't miss root in some
+ * corner case.
+ */
+ float r;
+ if (xi <= 0.9f) {
+ r = expf(xi * xi * 2.4f) - 1.0f;
+ }
+ else {
+ /* TODO(sergey): Some nicer curve fit is possible here. */
+ r = 15.0f;
+ }
+ /* Solve against scaled radius. */
+ for (int i = 0; i < max_iteration_count; i++) {
+ float exp_r_3 = expf(-r / 3.0f);
+ float exp_r = exp_r_3 * exp_r_3 * exp_r_3;
+ float f = 1.0f - 0.25f * exp_r - 0.75f * exp_r_3 - xi;
+ float f_ = 0.25f * exp_r + 0.25f * exp_r_3;
+
+ if (fabsf(f) < tolerance || f_ == 0.0f) {
+ break;
+ }
+
+ r = r - f / f_;
+ if (r < 0.0f) {
+ r = 0.0f;
+ }
+ }
+ return r;
}
-ccl_device void bssrdf_burley_sample(const float d,
- float xi,
- float *r,
- float *h)
+ccl_device void bssrdf_burley_sample(const float d, float xi, float *r, float *h)
{
- const float Rm = BURLEY_TRUNCATE * d;
- const float r_ = bssrdf_burley_root_find(xi * BURLEY_TRUNCATE_CDF) * d;
+ const float Rm = BURLEY_TRUNCATE * d;
+ const float r_ = bssrdf_burley_root_find(xi * BURLEY_TRUNCATE_CDF) * d;
- *r = r_;
+ *r = r_;
- /* h^2 + r^2 = Rm^2 */
- *h = safe_sqrtf(Rm*Rm - r_*r_);
+ /* h^2 + r^2 = Rm^2 */
+ *h = safe_sqrtf(Rm * Rm - r_ * r_);
}
/* None BSSRDF falloff
@@ -303,200 +299,195 @@ ccl_device void bssrdf_burley_sample(const float d,
ccl_device float bssrdf_none_eval(const float radius, float r)
{
- const float Rm = radius;
- return (r < Rm)? 1.0f: 0.0f;
+ const float Rm = radius;
+ return (r < Rm) ? 1.0f : 0.0f;
}
ccl_device float bssrdf_none_pdf(const float radius, float r)
{
- /* integrate (2*pi*r)/(pi*Rm*Rm) from 0 to Rm = 1 */
- const float Rm = radius;
- const float area = (M_PI_F*Rm*Rm);
+ /* integrate (2*pi*r)/(pi*Rm*Rm) from 0 to Rm = 1 */
+ const float Rm = radius;
+ const float area = (M_PI_F * Rm * Rm);
- return bssrdf_none_eval(radius, r) / area;
+ return bssrdf_none_eval(radius, r) / area;
}
ccl_device void bssrdf_none_sample(const float radius, float xi, float *r, float *h)
{
- /* xi = integrate (2*pi*r)/(pi*Rm*Rm) = r^2/Rm^2
- * r = sqrt(xi)*Rm */
- const float Rm = radius;
- const float r_ = sqrtf(xi)*Rm;
+ /* xi = integrate (2*pi*r)/(pi*Rm*Rm) = r^2/Rm^2
+ * r = sqrt(xi)*Rm */
+ const float Rm = radius;
+ const float r_ = sqrtf(xi) * Rm;
- *r = r_;
+ *r = r_;
- /* h^2 + r^2 = Rm^2 */
- *h = safe_sqrtf(Rm*Rm - r_*r_);
+ /* h^2 + r^2 = Rm^2 */
+ *h = safe_sqrtf(Rm * Rm - r_ * r_);
}
/* Generic */
ccl_device_inline Bssrdf *bssrdf_alloc(ShaderData *sd, float3 weight)
{
- Bssrdf *bssrdf = (Bssrdf*)closure_alloc(sd, sizeof(Bssrdf), CLOSURE_NONE_ID, weight);
+ Bssrdf *bssrdf = (Bssrdf *)closure_alloc(sd, sizeof(Bssrdf), CLOSURE_NONE_ID, weight);
- if(bssrdf == NULL) {
- return NULL;
- }
+ if (bssrdf == NULL) {
+ return NULL;
+ }
- float sample_weight = fabsf(average(weight));
- bssrdf->sample_weight = sample_weight;
- return (sample_weight >= CLOSURE_WEIGHT_CUTOFF) ? bssrdf : NULL;
+ float sample_weight = fabsf(average(weight));
+ bssrdf->sample_weight = sample_weight;
+ return (sample_weight >= CLOSURE_WEIGHT_CUTOFF) ? bssrdf : NULL;
}
ccl_device int bssrdf_setup(ShaderData *sd, Bssrdf *bssrdf, ClosureType type)
{
- int flag = 0;
- int bssrdf_channels = 3;
- float3 diffuse_weight = make_float3(0.0f, 0.0f, 0.0f);
-
- /* Verify if the radii are large enough to sample without precision issues. */
- if(bssrdf->radius.x < BSSRDF_MIN_RADIUS) {
- diffuse_weight.x = bssrdf->weight.x;
- bssrdf->weight.x = 0.0f;
- bssrdf->radius.x = 0.0f;
- bssrdf_channels--;
- }
- if(bssrdf->radius.y < BSSRDF_MIN_RADIUS) {
- diffuse_weight.y = bssrdf->weight.y;
- bssrdf->weight.y = 0.0f;
- bssrdf->radius.y = 0.0f;
- bssrdf_channels--;
- }
- if(bssrdf->radius.z < BSSRDF_MIN_RADIUS) {
- diffuse_weight.z = bssrdf->weight.z;
- bssrdf->weight.z = 0.0f;
- bssrdf->radius.z = 0.0f;
- bssrdf_channels--;
- }
-
- if(bssrdf_channels < 3) {
- /* Add diffuse BSDF if any radius too small. */
+ int flag = 0;
+ int bssrdf_channels = 3;
+ float3 diffuse_weight = make_float3(0.0f, 0.0f, 0.0f);
+
+ /* Verify if the radii are large enough to sample without precision issues. */
+ if (bssrdf->radius.x < BSSRDF_MIN_RADIUS) {
+ diffuse_weight.x = bssrdf->weight.x;
+ bssrdf->weight.x = 0.0f;
+ bssrdf->radius.x = 0.0f;
+ bssrdf_channels--;
+ }
+ if (bssrdf->radius.y < BSSRDF_MIN_RADIUS) {
+ diffuse_weight.y = bssrdf->weight.y;
+ bssrdf->weight.y = 0.0f;
+ bssrdf->radius.y = 0.0f;
+ bssrdf_channels--;
+ }
+ if (bssrdf->radius.z < BSSRDF_MIN_RADIUS) {
+ diffuse_weight.z = bssrdf->weight.z;
+ bssrdf->weight.z = 0.0f;
+ bssrdf->radius.z = 0.0f;
+ bssrdf_channels--;
+ }
+
+ if (bssrdf_channels < 3) {
+ /* Add diffuse BSDF if any radius too small. */
#ifdef __PRINCIPLED__
- if(type == CLOSURE_BSSRDF_PRINCIPLED_ID ||
- type == CLOSURE_BSSRDF_PRINCIPLED_RANDOM_WALK_ID)
- {
- float roughness = bssrdf->roughness;
- float3 N = bssrdf->N;
-
- PrincipledDiffuseBsdf *bsdf = (PrincipledDiffuseBsdf*)bsdf_alloc(sd, sizeof(PrincipledDiffuseBsdf), diffuse_weight);
-
- if(bsdf) {
- bsdf->type = CLOSURE_BSDF_BSSRDF_PRINCIPLED_ID;
- bsdf->N = N;
- bsdf->roughness = roughness;
- flag |= bsdf_principled_diffuse_setup(bsdf);
- }
- }
- else
-#endif /* __PRINCIPLED__ */
- {
- DiffuseBsdf *bsdf = (DiffuseBsdf*)bsdf_alloc(sd, sizeof(DiffuseBsdf), diffuse_weight);
-
- if(bsdf) {
- bsdf->type = CLOSURE_BSDF_BSSRDF_ID;
- bsdf->N = bssrdf->N;
- flag |= bsdf_diffuse_setup(bsdf);
- }
- }
- }
-
- /* Setup BSSRDF if radius is large enough. */
- if(bssrdf_channels > 0) {
- bssrdf->type = type;
- bssrdf->channels = bssrdf_channels;
- bssrdf->sample_weight = fabsf(average(bssrdf->weight)) * bssrdf->channels;
- bssrdf->texture_blur = saturate(bssrdf->texture_blur);
- bssrdf->sharpness = saturate(bssrdf->sharpness);
-
- if(type == CLOSURE_BSSRDF_BURLEY_ID ||
- type == CLOSURE_BSSRDF_PRINCIPLED_ID ||
- type == CLOSURE_BSSRDF_RANDOM_WALK_ID ||
- type == CLOSURE_BSSRDF_PRINCIPLED_RANDOM_WALK_ID)
- {
- bssrdf_burley_setup(bssrdf);
- }
-
- flag |= SD_BSSRDF;
- }
- else {
- bssrdf->type = type;
- bssrdf->sample_weight = 0.0f;
- }
-
- return flag;
+ if (type == CLOSURE_BSSRDF_PRINCIPLED_ID || type == CLOSURE_BSSRDF_PRINCIPLED_RANDOM_WALK_ID) {
+ float roughness = bssrdf->roughness;
+ float3 N = bssrdf->N;
+
+ PrincipledDiffuseBsdf *bsdf = (PrincipledDiffuseBsdf *)bsdf_alloc(
+ sd, sizeof(PrincipledDiffuseBsdf), diffuse_weight);
+
+ if (bsdf) {
+ bsdf->type = CLOSURE_BSDF_BSSRDF_PRINCIPLED_ID;
+ bsdf->N = N;
+ bsdf->roughness = roughness;
+ flag |= bsdf_principled_diffuse_setup(bsdf);
+ }
+ }
+ else
+#endif /* __PRINCIPLED__ */
+ {
+ DiffuseBsdf *bsdf = (DiffuseBsdf *)bsdf_alloc(sd, sizeof(DiffuseBsdf), diffuse_weight);
+
+ if (bsdf) {
+ bsdf->type = CLOSURE_BSDF_BSSRDF_ID;
+ bsdf->N = bssrdf->N;
+ flag |= bsdf_diffuse_setup(bsdf);
+ }
+ }
+ }
+
+ /* Setup BSSRDF if radius is large enough. */
+ if (bssrdf_channels > 0) {
+ bssrdf->type = type;
+ bssrdf->channels = bssrdf_channels;
+ bssrdf->sample_weight = fabsf(average(bssrdf->weight)) * bssrdf->channels;
+ bssrdf->texture_blur = saturate(bssrdf->texture_blur);
+ bssrdf->sharpness = saturate(bssrdf->sharpness);
+
+ if (type == CLOSURE_BSSRDF_BURLEY_ID || type == CLOSURE_BSSRDF_PRINCIPLED_ID ||
+ type == CLOSURE_BSSRDF_RANDOM_WALK_ID ||
+ type == CLOSURE_BSSRDF_PRINCIPLED_RANDOM_WALK_ID) {
+ bssrdf_burley_setup(bssrdf);
+ }
+
+ flag |= SD_BSSRDF;
+ }
+ else {
+ bssrdf->type = type;
+ bssrdf->sample_weight = 0.0f;
+ }
+
+ return flag;
}
ccl_device void bssrdf_sample(const ShaderClosure *sc, float xi, float *r, float *h)
{
- const Bssrdf *bssrdf = (const Bssrdf*)sc;
- float radius;
-
- /* Sample color channel and reuse random number. Only a subset of channels
- * may be used if their radius was too small to handle as BSSRDF. */
- xi *= bssrdf->channels;
-
- if(xi < 1.0f) {
- radius = (bssrdf->radius.x > 0.0f)? bssrdf->radius.x:
- (bssrdf->radius.y > 0.0f)? bssrdf->radius.y:
- bssrdf->radius.z;
- }
- else if(xi < 2.0f) {
- xi -= 1.0f;
- radius = (bssrdf->radius.x > 0.0f)? bssrdf->radius.y:
- bssrdf->radius.z;
- }
- else {
- xi -= 2.0f;
- radius = bssrdf->radius.z;
- }
-
- /* Sample BSSRDF. */
- if(bssrdf->type == CLOSURE_BSSRDF_CUBIC_ID) {
- bssrdf_cubic_sample(radius, bssrdf->sharpness, xi, r, h);
- }
- else if(bssrdf->type == CLOSURE_BSSRDF_GAUSSIAN_ID){
- bssrdf_gaussian_sample(radius, xi, r, h);
- }
- else { /*if(bssrdf->type == CLOSURE_BSSRDF_BURLEY_ID || bssrdf->type == CLOSURE_BSSRDF_PRINCIPLED_ID)*/
- bssrdf_burley_sample(radius, xi, r, h);
- }
+ const Bssrdf *bssrdf = (const Bssrdf *)sc;
+ float radius;
+
+ /* Sample color channel and reuse random number. Only a subset of channels
+ * may be used if their radius was too small to handle as BSSRDF. */
+ xi *= bssrdf->channels;
+
+ if (xi < 1.0f) {
+ radius = (bssrdf->radius.x > 0.0f) ?
+ bssrdf->radius.x :
+ (bssrdf->radius.y > 0.0f) ? bssrdf->radius.y : bssrdf->radius.z;
+ }
+ else if (xi < 2.0f) {
+ xi -= 1.0f;
+ radius = (bssrdf->radius.x > 0.0f) ? bssrdf->radius.y : bssrdf->radius.z;
+ }
+ else {
+ xi -= 2.0f;
+ radius = bssrdf->radius.z;
+ }
+
+ /* Sample BSSRDF. */
+ if (bssrdf->type == CLOSURE_BSSRDF_CUBIC_ID) {
+ bssrdf_cubic_sample(radius, bssrdf->sharpness, xi, r, h);
+ }
+ else if (bssrdf->type == CLOSURE_BSSRDF_GAUSSIAN_ID) {
+ bssrdf_gaussian_sample(radius, xi, r, h);
+ }
+ else { /*if(bssrdf->type == CLOSURE_BSSRDF_BURLEY_ID || bssrdf->type == CLOSURE_BSSRDF_PRINCIPLED_ID)*/
+ bssrdf_burley_sample(radius, xi, r, h);
+ }
}
ccl_device float bssrdf_channel_pdf(const Bssrdf *bssrdf, float radius, float r)
{
- if(radius == 0.0f) {
- return 0.0f;
- }
- else if(bssrdf->type == CLOSURE_BSSRDF_CUBIC_ID) {
- return bssrdf_cubic_pdf(radius, bssrdf->sharpness, r);
- }
- else if(bssrdf->type == CLOSURE_BSSRDF_GAUSSIAN_ID) {
- return bssrdf_gaussian_pdf(radius, r);
- }
- else { /*if(bssrdf->type == CLOSURE_BSSRDF_BURLEY_ID || bssrdf->type == CLOSURE_BSSRDF_PRINCIPLED_ID)*/
- return bssrdf_burley_pdf(radius, r);
- }
+ if (radius == 0.0f) {
+ return 0.0f;
+ }
+ else if (bssrdf->type == CLOSURE_BSSRDF_CUBIC_ID) {
+ return bssrdf_cubic_pdf(radius, bssrdf->sharpness, r);
+ }
+ else if (bssrdf->type == CLOSURE_BSSRDF_GAUSSIAN_ID) {
+ return bssrdf_gaussian_pdf(radius, r);
+ }
+ else { /*if(bssrdf->type == CLOSURE_BSSRDF_BURLEY_ID || bssrdf->type == CLOSURE_BSSRDF_PRINCIPLED_ID)*/
+ return bssrdf_burley_pdf(radius, r);
+ }
}
ccl_device_forceinline float3 bssrdf_eval(const ShaderClosure *sc, float r)
{
- const Bssrdf *bssrdf = (const Bssrdf*)sc;
+ const Bssrdf *bssrdf = (const Bssrdf *)sc;
- return make_float3(
- bssrdf_channel_pdf(bssrdf, bssrdf->radius.x, r),
- bssrdf_channel_pdf(bssrdf, bssrdf->radius.y, r),
- bssrdf_channel_pdf(bssrdf, bssrdf->radius.z, r));
+ return make_float3(bssrdf_channel_pdf(bssrdf, bssrdf->radius.x, r),
+ bssrdf_channel_pdf(bssrdf, bssrdf->radius.y, r),
+ bssrdf_channel_pdf(bssrdf, bssrdf->radius.z, r));
}
ccl_device_forceinline float bssrdf_pdf(const ShaderClosure *sc, float r)
{
- const Bssrdf *bssrdf = (const Bssrdf*)sc;
- float3 pdf = bssrdf_eval(sc, r);
+ const Bssrdf *bssrdf = (const Bssrdf *)sc;
+ float3 pdf = bssrdf_eval(sc, r);
- return (pdf.x + pdf.y + pdf.z) / bssrdf->channels;
+ return (pdf.x + pdf.y + pdf.z) / bssrdf->channels;
}
CCL_NAMESPACE_END
-#endif /* __KERNEL_BSSRDF_H__ */
+#endif /* __KERNEL_BSSRDF_H__ */
diff --git a/intern/cycles/kernel/closure/emissive.h b/intern/cycles/kernel/closure/emissive.h
index a7f4a2a7327..911382e6865 100644
--- a/intern/cycles/kernel/closure/emissive.h
+++ b/intern/cycles/kernel/closure/emissive.h
@@ -36,26 +36,26 @@ CCL_NAMESPACE_BEGIN
ccl_device void background_setup(ShaderData *sd, const float3 weight)
{
- if(sd->flag & SD_EMISSION) {
- sd->closure_emission_background += weight;
- }
- else {
- sd->flag |= SD_EMISSION;
- sd->closure_emission_background = weight;
- }
+ if (sd->flag & SD_EMISSION) {
+ sd->closure_emission_background += weight;
+ }
+ else {
+ sd->flag |= SD_EMISSION;
+ sd->closure_emission_background = weight;
+ }
}
/* EMISSION CLOSURE */
ccl_device void emission_setup(ShaderData *sd, const float3 weight)
{
- if(sd->flag & SD_EMISSION) {
- sd->closure_emission_background += weight;
- }
- else {
- sd->flag |= SD_EMISSION;
- sd->closure_emission_background = weight;
- }
+ if (sd->flag & SD_EMISSION) {
+ sd->closure_emission_background += weight;
+ }
+ else {
+ sd->flag |= SD_EMISSION;
+ sd->closure_emission_background = weight;
+ }
}
/* return the probability distribution function in the direction I,
@@ -63,21 +63,21 @@ ccl_device void emission_setup(ShaderData *sd, const float3 weight)
* the PDF computed by sample(). */
ccl_device float emissive_pdf(const float3 Ng, const float3 I)
{
- float cosNO = fabsf(dot(Ng, I));
- return (cosNO > 0.0f)? 1.0f: 0.0f;
+ float cosNO = fabsf(dot(Ng, I));
+ return (cosNO > 0.0f) ? 1.0f : 0.0f;
}
-ccl_device void emissive_sample(const float3 Ng, float randu, float randv,
- float3 *omega_out, float *pdf)
+ccl_device void emissive_sample(
+ const float3 Ng, float randu, float randv, float3 *omega_out, float *pdf)
{
- /* todo: not implemented and used yet */
+ /* todo: not implemented and used yet */
}
ccl_device float3 emissive_simple_eval(const float3 Ng, const float3 I)
{
- float res = emissive_pdf(Ng, I);
+ float res = emissive_pdf(Ng, I);
- return make_float3(res, res, res);
+ return make_float3(res, res, res);
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/closure/volume.h b/intern/cycles/kernel/closure/volume.h
index 872d06c936a..473bc0e8a82 100644
--- a/intern/cycles/kernel/closure/volume.h
+++ b/intern/cycles/kernel/closure/volume.h
@@ -23,21 +23,21 @@ CCL_NAMESPACE_BEGIN
ccl_device void volume_extinction_setup(ShaderData *sd, float3 weight)
{
- if(sd->flag & SD_EXTINCTION) {
- sd->closure_transparent_extinction += weight;
- }
- else {
- sd->flag |= SD_EXTINCTION;
- sd->closure_transparent_extinction = weight;
- }
+ if (sd->flag & SD_EXTINCTION) {
+ sd->closure_transparent_extinction += weight;
+ }
+ else {
+ sd->flag |= SD_EXTINCTION;
+ sd->closure_transparent_extinction = weight;
+ }
}
/* HENYEY-GREENSTEIN CLOSURE */
typedef ccl_addr_space struct HenyeyGreensteinVolume {
- SHADER_CLOSURE_BASE;
+ SHADER_CLOSURE_BASE;
- float g;
+ float g;
} HenyeyGreensteinVolume;
/* Given cosine between rays, return probability density that a photon bounces
@@ -45,119 +45,152 @@ typedef ccl_addr_space struct HenyeyGreensteinVolume {
* uniform sphere. g=0 uniform diffuse-like, g=1 close to sharp single ray. */
ccl_device float single_peaked_henyey_greenstein(float cos_theta, float g)
{
- return ((1.0f - g * g) / safe_powf(1.0f + g * g - 2.0f * g * cos_theta, 1.5f)) * (M_1_PI_F * 0.25f);
+ return ((1.0f - g * g) / safe_powf(1.0f + g * g - 2.0f * g * cos_theta, 1.5f)) *
+ (M_1_PI_F * 0.25f);
};
ccl_device int volume_henyey_greenstein_setup(HenyeyGreensteinVolume *volume)
{
- volume->type = CLOSURE_VOLUME_HENYEY_GREENSTEIN_ID;
+ volume->type = CLOSURE_VOLUME_HENYEY_GREENSTEIN_ID;
- /* clamp anisotropy to avoid delta function */
- volume->g = signf(volume->g) * min(fabsf(volume->g), 1.0f - 1e-3f);
+ /* clamp anisotropy to avoid delta function */
+ volume->g = signf(volume->g) * min(fabsf(volume->g), 1.0f - 1e-3f);
- return SD_SCATTER;
+ return SD_SCATTER;
}
ccl_device bool volume_henyey_greenstein_merge(const ShaderClosure *a, const ShaderClosure *b)
{
- const HenyeyGreensteinVolume *volume_a = (const HenyeyGreensteinVolume*)a;
- const HenyeyGreensteinVolume *volume_b = (const HenyeyGreensteinVolume*)b;
+ const HenyeyGreensteinVolume *volume_a = (const HenyeyGreensteinVolume *)a;
+ const HenyeyGreensteinVolume *volume_b = (const HenyeyGreensteinVolume *)b;
- return (volume_a->g == volume_b->g);
+ return (volume_a->g == volume_b->g);
}
-ccl_device float3 volume_henyey_greenstein_eval_phase(const ShaderClosure *sc, const float3 I, float3 omega_in, float *pdf)
+ccl_device float3 volume_henyey_greenstein_eval_phase(const ShaderClosure *sc,
+ const float3 I,
+ float3 omega_in,
+ float *pdf)
{
- const HenyeyGreensteinVolume *volume = (const HenyeyGreensteinVolume*)sc;
- float g = volume->g;
-
- /* note that I points towards the viewer */
- if(fabsf(g) < 1e-3f) {
- *pdf = M_1_PI_F * 0.25f;
- }
- else {
- float cos_theta = dot(-I, omega_in);
- *pdf = single_peaked_henyey_greenstein(cos_theta, g);
- }
-
- return make_float3(*pdf, *pdf, *pdf);
+ const HenyeyGreensteinVolume *volume = (const HenyeyGreensteinVolume *)sc;
+ float g = volume->g;
+
+ /* note that I points towards the viewer */
+ if (fabsf(g) < 1e-3f) {
+ *pdf = M_1_PI_F * 0.25f;
+ }
+ else {
+ float cos_theta = dot(-I, omega_in);
+ *pdf = single_peaked_henyey_greenstein(cos_theta, g);
+ }
+
+ return make_float3(*pdf, *pdf, *pdf);
}
-ccl_device float3 henyey_greenstrein_sample(float3 D, float g, float randu, float randv, float *pdf)
+ccl_device float3
+henyey_greenstrein_sample(float3 D, float g, float randu, float randv, float *pdf)
{
- /* match pdf for small g */
- float cos_theta;
- bool isotropic = fabsf(g) < 1e-3f;
-
- if(isotropic) {
- cos_theta = (1.0f - 2.0f * randu);
- if(pdf) {
- *pdf = M_1_PI_F * 0.25f;
- }
- }
- else {
- float k = (1.0f - g * g) / (1.0f - g + 2.0f * g * randu);
- cos_theta = (1.0f + g * g - k * k) / (2.0f * g);
- if(pdf) {
- *pdf = single_peaked_henyey_greenstein(cos_theta, g);
- }
- }
-
- float sin_theta = safe_sqrtf(1.0f - cos_theta * cos_theta);
- float phi = M_2PI_F * randv;
- float3 dir = make_float3(sin_theta * cosf(phi), sin_theta * sinf(phi), cos_theta);
-
- float3 T, B;
- make_orthonormals(D, &T, &B);
- dir = dir.x * T + dir.y * B + dir.z * D;
-
- return dir;
+ /* match pdf for small g */
+ float cos_theta;
+ bool isotropic = fabsf(g) < 1e-3f;
+
+ if (isotropic) {
+ cos_theta = (1.0f - 2.0f * randu);
+ if (pdf) {
+ *pdf = M_1_PI_F * 0.25f;
+ }
+ }
+ else {
+ float k = (1.0f - g * g) / (1.0f - g + 2.0f * g * randu);
+ cos_theta = (1.0f + g * g - k * k) / (2.0f * g);
+ if (pdf) {
+ *pdf = single_peaked_henyey_greenstein(cos_theta, g);
+ }
+ }
+
+ float sin_theta = safe_sqrtf(1.0f - cos_theta * cos_theta);
+ float phi = M_2PI_F * randv;
+ float3 dir = make_float3(sin_theta * cosf(phi), sin_theta * sinf(phi), cos_theta);
+
+ float3 T, B;
+ make_orthonormals(D, &T, &B);
+ dir = dir.x * T + dir.y * B + dir.z * D;
+
+ return dir;
}
-ccl_device int volume_henyey_greenstein_sample(const ShaderClosure *sc, float3 I, float3 dIdx, float3 dIdy, float randu, float randv,
- float3 *eval, float3 *omega_in, float3 *domega_in_dx, float3 *domega_in_dy, float *pdf)
+ccl_device int volume_henyey_greenstein_sample(const ShaderClosure *sc,
+ float3 I,
+ float3 dIdx,
+ float3 dIdy,
+ float randu,
+ float randv,
+ float3 *eval,
+ float3 *omega_in,
+ float3 *domega_in_dx,
+ float3 *domega_in_dy,
+ float *pdf)
{
- const HenyeyGreensteinVolume *volume = (const HenyeyGreensteinVolume*)sc;
- float g = volume->g;
+ const HenyeyGreensteinVolume *volume = (const HenyeyGreensteinVolume *)sc;
+ float g = volume->g;
- /* note that I points towards the viewer and so is used negated */
- *omega_in = henyey_greenstrein_sample(-I, g, randu, randv, pdf);
- *eval = make_float3(*pdf, *pdf, *pdf); /* perfect importance sampling */
+ /* note that I points towards the viewer and so is used negated */
+ *omega_in = henyey_greenstrein_sample(-I, g, randu, randv, pdf);
+ *eval = make_float3(*pdf, *pdf, *pdf); /* perfect importance sampling */
#ifdef __RAY_DIFFERENTIALS__
- /* todo: implement ray differential estimation */
- *domega_in_dx = make_float3(0.0f, 0.0f, 0.0f);
- *domega_in_dy = make_float3(0.0f, 0.0f, 0.0f);
+ /* todo: implement ray differential estimation */
+ *domega_in_dx = make_float3(0.0f, 0.0f, 0.0f);
+ *domega_in_dy = make_float3(0.0f, 0.0f, 0.0f);
#endif
- return LABEL_VOLUME_SCATTER;
+ return LABEL_VOLUME_SCATTER;
}
/* VOLUME CLOSURE */
-ccl_device float3 volume_phase_eval(const ShaderData *sd, const ShaderClosure *sc, float3 omega_in, float *pdf)
+ccl_device float3 volume_phase_eval(const ShaderData *sd,
+ const ShaderClosure *sc,
+ float3 omega_in,
+ float *pdf)
{
- kernel_assert(sc->type == CLOSURE_VOLUME_HENYEY_GREENSTEIN_ID);
+ kernel_assert(sc->type == CLOSURE_VOLUME_HENYEY_GREENSTEIN_ID);
- return volume_henyey_greenstein_eval_phase(sc, sd->I, omega_in, pdf);
+ return volume_henyey_greenstein_eval_phase(sc, sd->I, omega_in, pdf);
}
-ccl_device int volume_phase_sample(const ShaderData *sd, const ShaderClosure *sc, float randu,
- float randv, float3 *eval, float3 *omega_in, differential3 *domega_in, float *pdf)
+ccl_device int volume_phase_sample(const ShaderData *sd,
+ const ShaderClosure *sc,
+ float randu,
+ float randv,
+ float3 *eval,
+ float3 *omega_in,
+ differential3 *domega_in,
+ float *pdf)
{
- int label;
-
- switch(sc->type) {
- case CLOSURE_VOLUME_HENYEY_GREENSTEIN_ID:
- label = volume_henyey_greenstein_sample(sc, sd->I, sd->dI.dx, sd->dI.dy, randu, randv, eval, omega_in, &domega_in->dx, &domega_in->dy, pdf);
- break;
- default:
- *eval = make_float3(0.0f, 0.0f, 0.0f);
- label = LABEL_NONE;
- break;
- }
-
- return label;
+ int label;
+
+ switch (sc->type) {
+ case CLOSURE_VOLUME_HENYEY_GREENSTEIN_ID:
+ label = volume_henyey_greenstein_sample(sc,
+ sd->I,
+ sd->dI.dx,
+ sd->dI.dy,
+ randu,
+ randv,
+ eval,
+ omega_in,
+ &domega_in->dx,
+ &domega_in->dy,
+ pdf);
+ break;
+ default:
+ *eval = make_float3(0.0f, 0.0f, 0.0f);
+ label = LABEL_NONE;
+ break;
+ }
+
+ return label;
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/filter/filter.h b/intern/cycles/kernel/filter/filter.h
index 4209d69ee73..b067e53a8bf 100644
--- a/intern/cycles/kernel/filter/filter.h
+++ b/intern/cycles/kernel/filter/filter.h
@@ -25,8 +25,8 @@
CCL_NAMESPACE_BEGIN
-#define KERNEL_NAME_JOIN(x, y, z) x ## _ ## y ## _ ## z
-#define KERNEL_NAME_EVAL(arch, name) KERNEL_NAME_JOIN(kernel, arch, name)
+#define KERNEL_NAME_JOIN(x, y, z) x##_##y##_##z
+#define KERNEL_NAME_EVAL(arch, name) KERNEL_NAME_JOIN(kernel, arch, name)
#define KERNEL_FUNCTION_FULL_NAME(name) KERNEL_NAME_EVAL(KERNEL_ARCH, name)
#define KERNEL_ARCH cpu
@@ -49,4 +49,4 @@ CCL_NAMESPACE_BEGIN
CCL_NAMESPACE_END
-#endif /* __FILTER_H__ */
+#endif /* __FILTER_H__ */
diff --git a/intern/cycles/kernel/filter/filter_defines.h b/intern/cycles/kernel/filter/filter_defines.h
index cb04aac35f4..0e51eeef92f 100644
--- a/intern/cycles/kernel/filter/filter_defines.h
+++ b/intern/cycles/kernel/filter/filter_defines.h
@@ -18,59 +18,56 @@
#define __FILTER_DEFINES_H__
#define DENOISE_FEATURES 11
-#define TRANSFORM_SIZE (DENOISE_FEATURES*DENOISE_FEATURES)
-#define XTWX_SIZE (((DENOISE_FEATURES+1)*(DENOISE_FEATURES+2))/2)
-#define XTWY_SIZE (DENOISE_FEATURES+1)
+#define TRANSFORM_SIZE (DENOISE_FEATURES * DENOISE_FEATURES)
+#define XTWX_SIZE (((DENOISE_FEATURES + 1) * (DENOISE_FEATURES + 2)) / 2)
+#define XTWY_SIZE (DENOISE_FEATURES + 1)
#define DENOISE_MAX_FRAMES 16
typedef struct TileInfo {
- int offsets[9];
- int strides[9];
- int x[4];
- int y[4];
- int from_render;
- int frames[DENOISE_MAX_FRAMES];
- int num_frames;
- /* TODO(lukas): CUDA doesn't have uint64_t... */
+ int offsets[9];
+ int strides[9];
+ int x[4];
+ int y[4];
+ int from_render;
+ int frames[DENOISE_MAX_FRAMES];
+ int num_frames;
+ /* TODO(lukas): CUDA doesn't have uint64_t... */
#ifdef __KERNEL_OPENCL__
- ccl_global float *buffers[9];
+ ccl_global float *buffers[9];
#else
- long long int buffers[9];
+ long long int buffers[9];
#endif
} TileInfo;
#ifdef __KERNEL_OPENCL__
-# define CCL_FILTER_TILE_INFO ccl_global TileInfo* tile_info, \
- ccl_global float *tile_buffer_1, \
- ccl_global float *tile_buffer_2, \
- ccl_global float *tile_buffer_3, \
- ccl_global float *tile_buffer_4, \
- ccl_global float *tile_buffer_5, \
- ccl_global float *tile_buffer_6, \
- ccl_global float *tile_buffer_7, \
- ccl_global float *tile_buffer_8, \
- ccl_global float *tile_buffer_9
-# define CCL_FILTER_TILE_INFO_ARG tile_info, \
- tile_buffer_1, tile_buffer_2, tile_buffer_3, \
- tile_buffer_4, tile_buffer_5, tile_buffer_6, \
- tile_buffer_7, tile_buffer_8, tile_buffer_9
-# define ccl_get_tile_buffer(id) (id == 0 ? tile_buffer_1 \
- : id == 1 ? tile_buffer_2 \
- : id == 2 ? tile_buffer_3 \
- : id == 3 ? tile_buffer_4 \
- : id == 4 ? tile_buffer_5 \
- : id == 5 ? tile_buffer_6 \
- : id == 6 ? tile_buffer_7 \
- : id == 7 ? tile_buffer_8 \
- : tile_buffer_9)
+# define CCL_FILTER_TILE_INFO \
+ ccl_global TileInfo *tile_info, ccl_global float *tile_buffer_1, \
+ ccl_global float *tile_buffer_2, ccl_global float *tile_buffer_3, \
+ ccl_global float *tile_buffer_4, ccl_global float *tile_buffer_5, \
+ ccl_global float *tile_buffer_6, ccl_global float *tile_buffer_7, \
+ ccl_global float *tile_buffer_8, ccl_global float *tile_buffer_9
+# define CCL_FILTER_TILE_INFO_ARG \
+ tile_info, tile_buffer_1, tile_buffer_2, tile_buffer_3, tile_buffer_4, tile_buffer_5, \
+ tile_buffer_6, tile_buffer_7, tile_buffer_8, tile_buffer_9
+# define ccl_get_tile_buffer(id) \
+ (id == 0 ? tile_buffer_1 : \
+ id == 1 ? \
+ tile_buffer_2 : \
+ id == 2 ? \
+ tile_buffer_3 : \
+ id == 3 ? tile_buffer_4 : \
+ id == 4 ? tile_buffer_5 : \
+ id == 5 ? tile_buffer_6 : \
+ id == 6 ? tile_buffer_7 : \
+ id == 7 ? tile_buffer_8 : tile_buffer_9)
#else
# ifdef __KERNEL_CUDA__
-# define CCL_FILTER_TILE_INFO ccl_global TileInfo* tile_info
+# define CCL_FILTER_TILE_INFO ccl_global TileInfo *tile_info
# else
-# define CCL_FILTER_TILE_INFO TileInfo* tile_info
+# define CCL_FILTER_TILE_INFO TileInfo *tile_info
# endif
# define ccl_get_tile_buffer(id) (tile_info->buffers[id])
#endif
-#endif /* __FILTER_DEFINES_H__*/
+#endif /* __FILTER_DEFINES_H__*/
diff --git a/intern/cycles/kernel/filter/filter_features.h b/intern/cycles/kernel/filter/filter_features.h
index e1ea6487aa9..809ccfe8be6 100644
--- a/intern/cycles/kernel/filter/filter_features.h
+++ b/intern/cycles/kernel/filter/filter_features.h
@@ -14,22 +14,25 @@
* limitations under the License.
*/
- CCL_NAMESPACE_BEGIN
+CCL_NAMESPACE_BEGIN
#define ccl_get_feature(buffer, pass) (buffer)[(pass)*pass_stride]
/* Loop over the pixels in the range [low.x, high.x) x [low.y, high.y).+ * pixel_buffer always points to the current pixel in the first pass.
* Repeat the loop for every secondary frame if there are any. */
-#define FOR_PIXEL_WINDOW for(int frame = 0; frame < tile_info->num_frames; frame++) { \
- pixel.z = tile_info->frames[frame]; \
- pixel_buffer = buffer + (low.y - rect.y)*buffer_w + (low.x - rect.x) + frame*frame_stride; \
- for(pixel.y = low.y; pixel.y < high.y; pixel.y++) { \
- for(pixel.x = low.x; pixel.x < high.x; pixel.x++, pixel_buffer++) {
+#define FOR_PIXEL_WINDOW \
+ for (int frame = 0; frame < tile_info->num_frames; frame++) { \
+ pixel.z = tile_info->frames[frame]; \
+ pixel_buffer = buffer + (low.y - rect.y) * buffer_w + (low.x - rect.x) + \
+ frame * frame_stride; \
+ for (pixel.y = low.y; pixel.y < high.y; pixel.y++) { \
+ for (pixel.x = low.x; pixel.x < high.x; pixel.x++, pixel_buffer++) {
-#define END_FOR_PIXEL_WINDOW } \
- pixel_buffer += buffer_w - (high.x - low.x); \
- } \
- }
+#define END_FOR_PIXEL_WINDOW \
+ } \
+ pixel_buffer += buffer_w - (high.x - low.x); \
+ } \
+ }
ccl_device_inline void filter_get_features(int3 pixel,
const ccl_global float *ccl_restrict buffer,
@@ -38,24 +41,24 @@ ccl_device_inline void filter_get_features(int3 pixel,
const float *ccl_restrict mean,
int pass_stride)
{
- features[0] = pixel.x;
- features[1] = pixel.y;
- features[2] = fabsf(ccl_get_feature(buffer, 0));
- features[3] = ccl_get_feature(buffer, 1);
- features[4] = ccl_get_feature(buffer, 2);
- features[5] = ccl_get_feature(buffer, 3);
- features[6] = ccl_get_feature(buffer, 4);
- features[7] = ccl_get_feature(buffer, 5);
- features[8] = ccl_get_feature(buffer, 6);
- features[9] = ccl_get_feature(buffer, 7);
- if(use_time) {
- features[10] = pixel.z;
- }
- if(mean) {
- for(int i = 0; i < (use_time? 11 : 10); i++) {
- features[i] -= mean[i];
- }
- }
+ features[0] = pixel.x;
+ features[1] = pixel.y;
+ features[2] = fabsf(ccl_get_feature(buffer, 0));
+ features[3] = ccl_get_feature(buffer, 1);
+ features[4] = ccl_get_feature(buffer, 2);
+ features[5] = ccl_get_feature(buffer, 3);
+ features[6] = ccl_get_feature(buffer, 4);
+ features[7] = ccl_get_feature(buffer, 5);
+ features[8] = ccl_get_feature(buffer, 6);
+ features[9] = ccl_get_feature(buffer, 7);
+ if (use_time) {
+ features[10] = pixel.z;
+ }
+ if (mean) {
+ for (int i = 0; i < (use_time ? 11 : 10); i++) {
+ features[i] -= mean[i];
+ }
+ }
}
ccl_device_inline void filter_get_feature_scales(int3 pixel,
@@ -65,38 +68,39 @@ ccl_device_inline void filter_get_feature_scales(int3 pixel,
const float *ccl_restrict mean,
int pass_stride)
{
- scales[0] = fabsf(pixel.x - mean[0]);
- scales[1] = fabsf(pixel.y - mean[1]);
- scales[2] = fabsf(fabsf(ccl_get_feature(buffer, 0)) - mean[2]);
- scales[3] = len_squared(make_float3(ccl_get_feature(buffer, 1) - mean[3],
- ccl_get_feature(buffer, 2) - mean[4],
- ccl_get_feature(buffer, 3) - mean[5]));
- scales[4] = fabsf(ccl_get_feature(buffer, 4) - mean[6]);
- scales[5] = len_squared(make_float3(ccl_get_feature(buffer, 5) - mean[7],
- ccl_get_feature(buffer, 6) - mean[8],
- ccl_get_feature(buffer, 7) - mean[9]));
- if(use_time) {
- scales[6] = fabsf(pixel.z - mean[10]);
- }
+ scales[0] = fabsf(pixel.x - mean[0]);
+ scales[1] = fabsf(pixel.y - mean[1]);
+ scales[2] = fabsf(fabsf(ccl_get_feature(buffer, 0)) - mean[2]);
+ scales[3] = len_squared(make_float3(ccl_get_feature(buffer, 1) - mean[3],
+ ccl_get_feature(buffer, 2) - mean[4],
+ ccl_get_feature(buffer, 3) - mean[5]));
+ scales[4] = fabsf(ccl_get_feature(buffer, 4) - mean[6]);
+ scales[5] = len_squared(make_float3(ccl_get_feature(buffer, 5) - mean[7],
+ ccl_get_feature(buffer, 6) - mean[8],
+ ccl_get_feature(buffer, 7) - mean[9]));
+ if (use_time) {
+ scales[6] = fabsf(pixel.z - mean[10]);
+ }
}
ccl_device_inline void filter_calculate_scale(float *scale, bool use_time)
{
- scale[0] = 1.0f/max(scale[0], 0.01f);
- scale[1] = 1.0f/max(scale[1], 0.01f);
- scale[2] = 1.0f/max(scale[2], 0.01f);
- if(use_time) {
- scale[10] = 1.0f/max(scale[6], 0.01f);
- }
- scale[6] = 1.0f/max(scale[4], 0.01f);
- scale[7] = scale[8] = scale[9] = 1.0f/max(sqrtf(scale[5]), 0.01f);
- scale[3] = scale[4] = scale[5] = 1.0f/max(sqrtf(scale[3]), 0.01f);
+ scale[0] = 1.0f / max(scale[0], 0.01f);
+ scale[1] = 1.0f / max(scale[1], 0.01f);
+ scale[2] = 1.0f / max(scale[2], 0.01f);
+ if (use_time) {
+ scale[10] = 1.0f / max(scale[6], 0.01f);
+ }
+ scale[6] = 1.0f / max(scale[4], 0.01f);
+ scale[7] = scale[8] = scale[9] = 1.0f / max(sqrtf(scale[5]), 0.01f);
+ scale[3] = scale[4] = scale[5] = 1.0f / max(sqrtf(scale[3]), 0.01f);
}
ccl_device_inline float3 filter_get_color(const ccl_global float *ccl_restrict buffer,
int pass_stride)
{
- return make_float3(ccl_get_feature(buffer, 8), ccl_get_feature(buffer, 9), ccl_get_feature(buffer, 10));
+ return make_float3(
+ ccl_get_feature(buffer, 8), ccl_get_feature(buffer, 9), ccl_get_feature(buffer, 10));
}
ccl_device_inline void design_row_add(float *design_row,
@@ -107,42 +111,44 @@ ccl_device_inline void design_row_add(float *design_row,
float feature,
int transform_row_stride)
{
- for(int i = 0; i < rank; i++) {
- design_row[1+i] += transform[(row*transform_row_stride + i)*stride]*feature;
- }
+ for (int i = 0; i < rank; i++) {
+ design_row[1 + i] += transform[(row * transform_row_stride + i) * stride] * feature;
+ }
}
/* Fill the design row. */
-ccl_device_inline void filter_get_design_row_transform(int3 p_pixel,
- const ccl_global float *ccl_restrict p_buffer,
- int3 q_pixel,
- const ccl_global float *ccl_restrict q_buffer,
- int pass_stride,
- int rank,
- float *design_row,
- const ccl_global float *ccl_restrict transform,
- int stride,
- bool use_time)
+ccl_device_inline void filter_get_design_row_transform(
+ int3 p_pixel,
+ const ccl_global float *ccl_restrict p_buffer,
+ int3 q_pixel,
+ const ccl_global float *ccl_restrict q_buffer,
+ int pass_stride,
+ int rank,
+ float *design_row,
+ const ccl_global float *ccl_restrict transform,
+ int stride,
+ bool use_time)
{
- int num_features = use_time? 11 : 10;
+ int num_features = use_time ? 11 : 10;
- design_row[0] = 1.0f;
- math_vector_zero(design_row+1, rank);
+ design_row[0] = 1.0f;
+ math_vector_zero(design_row + 1, rank);
-#define DESIGN_ROW_ADD(I, F) design_row_add(design_row, rank, transform, stride, I, F, num_features);
- DESIGN_ROW_ADD(0, q_pixel.x - p_pixel.x);
- DESIGN_ROW_ADD(1, q_pixel.y - p_pixel.y);
- DESIGN_ROW_ADD(2, fabsf(ccl_get_feature(q_buffer, 0)) - fabsf(ccl_get_feature(p_buffer, 0)));
- DESIGN_ROW_ADD(3, ccl_get_feature(q_buffer, 1) - ccl_get_feature(p_buffer, 1));
- DESIGN_ROW_ADD(4, ccl_get_feature(q_buffer, 2) - ccl_get_feature(p_buffer, 2));
- DESIGN_ROW_ADD(5, ccl_get_feature(q_buffer, 3) - ccl_get_feature(p_buffer, 3));
- DESIGN_ROW_ADD(6, ccl_get_feature(q_buffer, 4) - ccl_get_feature(p_buffer, 4));
- DESIGN_ROW_ADD(7, ccl_get_feature(q_buffer, 5) - ccl_get_feature(p_buffer, 5));
- DESIGN_ROW_ADD(8, ccl_get_feature(q_buffer, 6) - ccl_get_feature(p_buffer, 6));
- DESIGN_ROW_ADD(9, ccl_get_feature(q_buffer, 7) - ccl_get_feature(p_buffer, 7));
- if(use_time) {
- DESIGN_ROW_ADD(10, q_pixel.z - p_pixel.z)
- }
+#define DESIGN_ROW_ADD(I, F) \
+ design_row_add(design_row, rank, transform, stride, I, F, num_features);
+ DESIGN_ROW_ADD(0, q_pixel.x - p_pixel.x);
+ DESIGN_ROW_ADD(1, q_pixel.y - p_pixel.y);
+ DESIGN_ROW_ADD(2, fabsf(ccl_get_feature(q_buffer, 0)) - fabsf(ccl_get_feature(p_buffer, 0)));
+ DESIGN_ROW_ADD(3, ccl_get_feature(q_buffer, 1) - ccl_get_feature(p_buffer, 1));
+ DESIGN_ROW_ADD(4, ccl_get_feature(q_buffer, 2) - ccl_get_feature(p_buffer, 2));
+ DESIGN_ROW_ADD(5, ccl_get_feature(q_buffer, 3) - ccl_get_feature(p_buffer, 3));
+ DESIGN_ROW_ADD(6, ccl_get_feature(q_buffer, 4) - ccl_get_feature(p_buffer, 4));
+ DESIGN_ROW_ADD(7, ccl_get_feature(q_buffer, 5) - ccl_get_feature(p_buffer, 5));
+ DESIGN_ROW_ADD(8, ccl_get_feature(q_buffer, 6) - ccl_get_feature(p_buffer, 6));
+ DESIGN_ROW_ADD(9, ccl_get_feature(q_buffer, 7) - ccl_get_feature(p_buffer, 7));
+ if (use_time) {
+ DESIGN_ROW_ADD(10, q_pixel.z - p_pixel.z)
+ }
#undef DESIGN_ROW_ADD
}
diff --git a/intern/cycles/kernel/filter/filter_features_sse.h b/intern/cycles/kernel/filter/filter_features_sse.h
index 5dd001ffb93..1e0d6e93453 100644
--- a/intern/cycles/kernel/filter/filter_features_sse.h
+++ b/intern/cycles/kernel/filter/filter_features_sse.h
@@ -22,22 +22,27 @@ CCL_NAMESPACE_BEGIN
* pixel_buffer always points to the first of the 4 current pixel in the first pass.
* x4 and y4 contain the coordinates of the four pixels, active_pixels contains a mask that's set for all pixels within the window.
* Repeat the loop for every secondary frame if there are any. */
-#define FOR_PIXEL_WINDOW_SSE for(int frame = 0; frame < tile_info->num_frames; frame++) { \
- pixel.z = tile_info->frames[frame]; \
- pixel_buffer = buffer + (low.y - rect.y)*buffer_w + (low.x - rect.x) + frame*frame_stride; \
- float4 t4 = make_float4(pixel.z); \
- for(pixel.y = low.y; pixel.y < high.y; pixel.y++) { \
- float4 y4 = make_float4(pixel.y); \
- for(pixel.x = low.x; pixel.x < high.x; pixel.x += 4, pixel_buffer += 4) { \
- float4 x4 = make_float4(pixel.x) + make_float4(0.0f, 1.0f, 2.0f, 3.0f); \
- int4 active_pixels = x4 < make_float4(high.x);
+#define FOR_PIXEL_WINDOW_SSE \
+ for (int frame = 0; frame < tile_info->num_frames; frame++) { \
+ pixel.z = tile_info->frames[frame]; \
+ pixel_buffer = buffer + (low.y - rect.y) * buffer_w + (low.x - rect.x) + \
+ frame * frame_stride; \
+ float4 t4 = make_float4(pixel.z); \
+ for (pixel.y = low.y; pixel.y < high.y; pixel.y++) { \
+ float4 y4 = make_float4(pixel.y); \
+ for (pixel.x = low.x; pixel.x < high.x; pixel.x += 4, pixel_buffer += 4) { \
+ float4 x4 = make_float4(pixel.x) + make_float4(0.0f, 1.0f, 2.0f, 3.0f); \
+ int4 active_pixels = x4 < make_float4(high.x);
-#define END_FOR_PIXEL_WINDOW_SSE } \
- pixel_buffer += buffer_w - (high.x - low.x); \
- } \
- }
+#define END_FOR_PIXEL_WINDOW_SSE \
+ } \
+ pixel_buffer += buffer_w - (high.x - low.x); \
+ } \
+ }
-ccl_device_inline void filter_get_features_sse(float4 x, float4 y, float4 t,
+ccl_device_inline void filter_get_features_sse(float4 x,
+ float4 y,
+ float4 t,
int4 active_pixels,
const float *ccl_restrict buffer,
float4 *features,
@@ -45,33 +50,35 @@ ccl_device_inline void filter_get_features_sse(float4 x, float4 y, float4 t,
const float4 *ccl_restrict mean,
int pass_stride)
{
- int num_features = use_time? 11 : 10;
+ int num_features = use_time ? 11 : 10;
- features[0] = x;
- features[1] = y;
- features[2] = fabs(ccl_get_feature_sse(0));
- features[3] = ccl_get_feature_sse(1);
- features[4] = ccl_get_feature_sse(2);
- features[5] = ccl_get_feature_sse(3);
- features[6] = ccl_get_feature_sse(4);
- features[7] = ccl_get_feature_sse(5);
- features[8] = ccl_get_feature_sse(6);
- features[9] = ccl_get_feature_sse(7);
- if(use_time) {
- features[10] = t;
- }
+ features[0] = x;
+ features[1] = y;
+ features[2] = fabs(ccl_get_feature_sse(0));
+ features[3] = ccl_get_feature_sse(1);
+ features[4] = ccl_get_feature_sse(2);
+ features[5] = ccl_get_feature_sse(3);
+ features[6] = ccl_get_feature_sse(4);
+ features[7] = ccl_get_feature_sse(5);
+ features[8] = ccl_get_feature_sse(6);
+ features[9] = ccl_get_feature_sse(7);
+ if (use_time) {
+ features[10] = t;
+ }
- if(mean) {
- for(int i = 0; i < num_features; i++) {
- features[i] = features[i] - mean[i];
- }
- }
- for(int i = 0; i < num_features; i++) {
- features[i] = mask(active_pixels, features[i]);
- }
+ if (mean) {
+ for (int i = 0; i < num_features; i++) {
+ features[i] = features[i] - mean[i];
+ }
+ }
+ for (int i = 0; i < num_features; i++) {
+ features[i] = mask(active_pixels, features[i]);
+ }
}
-ccl_device_inline void filter_get_feature_scales_sse(float4 x, float4 y, float4 t,
+ccl_device_inline void filter_get_feature_scales_sse(float4 x,
+ float4 y,
+ float4 t,
int4 active_pixels,
const float *ccl_restrict buffer,
float4 *scales,
@@ -79,36 +86,34 @@ ccl_device_inline void filter_get_feature_scales_sse(float4 x, float4 y, float4
const float4 *ccl_restrict mean,
int pass_stride)
{
- scales[0] = fabs(x - mean[0]);
- scales[1] = fabs(y - mean[1]);
- scales[2] = fabs(fabs(ccl_get_feature_sse(0)) - mean[2]);
- scales[3] = sqr(ccl_get_feature_sse(1) - mean[3]) +
- sqr(ccl_get_feature_sse(2) - mean[4]) +
- sqr(ccl_get_feature_sse(3) - mean[5]);
- scales[4] = fabs(ccl_get_feature_sse(4) - mean[6]);
- scales[5] = sqr(ccl_get_feature_sse(5) - mean[7]) +
- sqr(ccl_get_feature_sse(6) - mean[8]) +
- sqr(ccl_get_feature_sse(7) - mean[9]);
- if(use_time) {
- scales[6] = fabs(t - mean[10]);
- }
+ scales[0] = fabs(x - mean[0]);
+ scales[1] = fabs(y - mean[1]);
+ scales[2] = fabs(fabs(ccl_get_feature_sse(0)) - mean[2]);
+ scales[3] = sqr(ccl_get_feature_sse(1) - mean[3]) + sqr(ccl_get_feature_sse(2) - mean[4]) +
+ sqr(ccl_get_feature_sse(3) - mean[5]);
+ scales[4] = fabs(ccl_get_feature_sse(4) - mean[6]);
+ scales[5] = sqr(ccl_get_feature_sse(5) - mean[7]) + sqr(ccl_get_feature_sse(6) - mean[8]) +
+ sqr(ccl_get_feature_sse(7) - mean[9]);
+ if (use_time) {
+ scales[6] = fabs(t - mean[10]);
+ }
- for(int i = 0; i < (use_time? 7 : 6); i++)
- scales[i] = mask(active_pixels, scales[i]);
+ for (int i = 0; i < (use_time ? 7 : 6); i++)
+ scales[i] = mask(active_pixels, scales[i]);
}
ccl_device_inline void filter_calculate_scale_sse(float4 *scale, bool use_time)
{
- scale[0] = rcp(max(reduce_max(scale[0]), make_float4(0.01f)));
- scale[1] = rcp(max(reduce_max(scale[1]), make_float4(0.01f)));
- scale[2] = rcp(max(reduce_max(scale[2]), make_float4(0.01f)));
- if(use_time) {
- scale[10] = rcp(max(reduce_max(scale[6]), make_float4(0.01f)));;
- }
- scale[6] = rcp(max(reduce_max(scale[4]), make_float4(0.01f)));
- scale[7] = scale[8] = scale[9] = rcp(max(reduce_max(sqrt(scale[5])), make_float4(0.01f)));
- scale[3] = scale[4] = scale[5] = rcp(max(reduce_max(sqrt(scale[3])), make_float4(0.01f)));
+ scale[0] = rcp(max(reduce_max(scale[0]), make_float4(0.01f)));
+ scale[1] = rcp(max(reduce_max(scale[1]), make_float4(0.01f)));
+ scale[2] = rcp(max(reduce_max(scale[2]), make_float4(0.01f)));
+ if (use_time) {
+ scale[10] = rcp(max(reduce_max(scale[6]), make_float4(0.01f)));
+ ;
+ }
+ scale[6] = rcp(max(reduce_max(scale[4]), make_float4(0.01f)));
+ scale[7] = scale[8] = scale[9] = rcp(max(reduce_max(sqrt(scale[5])), make_float4(0.01f)));
+ scale[3] = scale[4] = scale[5] = rcp(max(reduce_max(sqrt(scale[3])), make_float4(0.01f)));
}
-
CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/filter/filter_nlm_cpu.h b/intern/cycles/kernel/filter/filter_nlm_cpu.h
index 9eb3c603a4a..a94266a8786 100644
--- a/intern/cycles/kernel/filter/filter_nlm_cpu.h
+++ b/intern/cycles/kernel/filter/filter_nlm_cpu.h
@@ -16,10 +16,11 @@
CCL_NAMESPACE_BEGIN
-#define load4_a(buf, ofs) (*((float4*) ((buf) + (ofs))))
-#define load4_u(buf, ofs) load_float4((buf)+(ofs))
+#define load4_a(buf, ofs) (*((float4 *)((buf) + (ofs))))
+#define load4_u(buf, ofs) load_float4((buf) + (ofs))
-ccl_device_inline void kernel_filter_nlm_calc_difference(int dx, int dy,
+ccl_device_inline void kernel_filter_nlm_calc_difference(int dx,
+ int dy,
const float *ccl_restrict weight_image,
const float *ccl_restrict variance_image,
const float *ccl_restrict scale_image,
@@ -31,122 +32,117 @@ ccl_device_inline void kernel_filter_nlm_calc_difference(int dx, int dy,
float a,
float k_2)
{
- /* Strides need to be aligned to 16 bytes. */
- kernel_assert((stride % 4) == 0 && (channel_offset % 4) == 0);
-
- int aligned_lowx = rect.x & (~3);
- const int numChannels = (channel_offset > 0)? 3 : 1;
- const float4 channel_fac = make_float4(1.0f / numChannels);
-
- for(int y = rect.y; y < rect.w; y++) {
- int idx_p = y*stride + aligned_lowx;
- int idx_q = (y+dy)*stride + aligned_lowx + dx + frame_offset;
- for(int x = aligned_lowx; x < rect.z; x += 4, idx_p += 4, idx_q += 4) {
- float4 diff = make_float4(0.0f);
- float4 scale_fac;
- if(scale_image) {
- scale_fac = clamp(load4_a(scale_image, idx_p) / load4_u(scale_image, idx_q),
- make_float4(0.25f), make_float4(4.0f));
- }
- else {
- scale_fac = make_float4(1.0f);
- }
- for(int c = 0, chan_ofs = 0; c < numChannels; c++, chan_ofs += channel_offset) {
- /* idx_p is guaranteed to be aligned, but idx_q isn't. */
- float4 color_p = load4_a(weight_image, idx_p + chan_ofs);
- float4 color_q = scale_fac*load4_u(weight_image, idx_q + chan_ofs);
- float4 cdiff = color_p - color_q;
- float4 var_p = load4_a(variance_image, idx_p + chan_ofs);
- float4 var_q = sqr(scale_fac)*load4_u(variance_image, idx_q + chan_ofs);
- diff += (cdiff*cdiff - a*(var_p + min(var_p, var_q))) / (make_float4(1e-8f) + k_2*(var_p+var_q));
- }
- load4_a(difference_image, idx_p) = diff*channel_fac;
- }
- }
+ /* Strides need to be aligned to 16 bytes. */
+ kernel_assert((stride % 4) == 0 && (channel_offset % 4) == 0);
+
+ int aligned_lowx = rect.x & (~3);
+ const int numChannels = (channel_offset > 0) ? 3 : 1;
+ const float4 channel_fac = make_float4(1.0f / numChannels);
+
+ for (int y = rect.y; y < rect.w; y++) {
+ int idx_p = y * stride + aligned_lowx;
+ int idx_q = (y + dy) * stride + aligned_lowx + dx + frame_offset;
+ for (int x = aligned_lowx; x < rect.z; x += 4, idx_p += 4, idx_q += 4) {
+ float4 diff = make_float4(0.0f);
+ float4 scale_fac;
+ if (scale_image) {
+ scale_fac = clamp(load4_a(scale_image, idx_p) / load4_u(scale_image, idx_q),
+ make_float4(0.25f),
+ make_float4(4.0f));
+ }
+ else {
+ scale_fac = make_float4(1.0f);
+ }
+ for (int c = 0, chan_ofs = 0; c < numChannels; c++, chan_ofs += channel_offset) {
+ /* idx_p is guaranteed to be aligned, but idx_q isn't. */
+ float4 color_p = load4_a(weight_image, idx_p + chan_ofs);
+ float4 color_q = scale_fac * load4_u(weight_image, idx_q + chan_ofs);
+ float4 cdiff = color_p - color_q;
+ float4 var_p = load4_a(variance_image, idx_p + chan_ofs);
+ float4 var_q = sqr(scale_fac) * load4_u(variance_image, idx_q + chan_ofs);
+ diff += (cdiff * cdiff - a * (var_p + min(var_p, var_q))) /
+ (make_float4(1e-8f) + k_2 * (var_p + var_q));
+ }
+ load4_a(difference_image, idx_p) = diff * channel_fac;
+ }
+ }
}
-ccl_device_inline void kernel_filter_nlm_blur(const float *ccl_restrict difference_image,
- float *out_image,
- int4 rect,
- int stride,
- int f)
+ccl_device_inline void kernel_filter_nlm_blur(
+ const float *ccl_restrict difference_image, float *out_image, int4 rect, int stride, int f)
{
- int aligned_lowx = round_down(rect.x, 4);
- for(int y = rect.y; y < rect.w; y++) {
- const int low = max(rect.y, y-f);
- const int high = min(rect.w, y+f+1);
- for(int x = aligned_lowx; x < rect.z; x += 4) {
- load4_a(out_image, y*stride + x) = make_float4(0.0f);
- }
- for(int y1 = low; y1 < high; y1++) {
- for(int x = aligned_lowx; x < rect.z; x += 4) {
- load4_a(out_image, y*stride + x) += load4_a(difference_image, y1*stride + x);
- }
- }
- float fac = 1.0f/(high - low);
- for(int x = aligned_lowx; x < rect.z; x += 4) {
- load4_a(out_image, y*stride + x) *= fac;
- }
- }
+ int aligned_lowx = round_down(rect.x, 4);
+ for (int y = rect.y; y < rect.w; y++) {
+ const int low = max(rect.y, y - f);
+ const int high = min(rect.w, y + f + 1);
+ for (int x = aligned_lowx; x < rect.z; x += 4) {
+ load4_a(out_image, y * stride + x) = make_float4(0.0f);
+ }
+ for (int y1 = low; y1 < high; y1++) {
+ for (int x = aligned_lowx; x < rect.z; x += 4) {
+ load4_a(out_image, y * stride + x) += load4_a(difference_image, y1 * stride + x);
+ }
+ }
+ float fac = 1.0f / (high - low);
+ for (int x = aligned_lowx; x < rect.z; x += 4) {
+ load4_a(out_image, y * stride + x) *= fac;
+ }
+ }
}
-ccl_device_inline void nlm_blur_horizontal(const float *ccl_restrict difference_image,
- float *out_image,
- int4 rect,
- int stride,
- int f)
+ccl_device_inline void nlm_blur_horizontal(
+ const float *ccl_restrict difference_image, float *out_image, int4 rect, int stride, int f)
{
- int aligned_lowx = round_down(rect.x, 4);
- for(int y = rect.y; y < rect.w; y++) {
- for(int x = aligned_lowx; x < rect.z; x += 4) {
- load4_a(out_image, y*stride + x) = make_float4(0.0f);
- }
- }
-
- for(int dx = -f; dx <= f; dx++) {
- aligned_lowx = round_down(rect.x - min(0, dx), 4);
- int highx = rect.z - max(0, dx);
- int4 lowx4 = make_int4(rect.x - min(0, dx));
- int4 highx4 = make_int4(rect.z - max(0, dx));
- for(int y = rect.y; y < rect.w; y++) {
- for(int x = aligned_lowx; x < highx; x += 4) {
- int4 x4 = make_int4(x) + make_int4(0, 1, 2, 3);
- int4 active = (x4 >= lowx4) & (x4 < highx4);
-
- float4 diff = load4_u(difference_image, y*stride + x + dx);
- load4_a(out_image, y*stride + x) += mask(active, diff);
- }
- }
- }
-
- aligned_lowx = round_down(rect.x, 4);
- for(int y = rect.y; y < rect.w; y++) {
- for(int x = aligned_lowx; x < rect.z; x += 4) {
- float4 x4 = make_float4(x) + make_float4(0.0f, 1.0f, 2.0f, 3.0f);
- float4 low = max(make_float4(rect.x), x4 - make_float4(f));
- float4 high = min(make_float4(rect.z), x4 + make_float4(f+1));
- load4_a(out_image, y*stride + x) *= rcp(high - low);
- }
- }
+ int aligned_lowx = round_down(rect.x, 4);
+ for (int y = rect.y; y < rect.w; y++) {
+ for (int x = aligned_lowx; x < rect.z; x += 4) {
+ load4_a(out_image, y * stride + x) = make_float4(0.0f);
+ }
+ }
+
+ for (int dx = -f; dx <= f; dx++) {
+ aligned_lowx = round_down(rect.x - min(0, dx), 4);
+ int highx = rect.z - max(0, dx);
+ int4 lowx4 = make_int4(rect.x - min(0, dx));
+ int4 highx4 = make_int4(rect.z - max(0, dx));
+ for (int y = rect.y; y < rect.w; y++) {
+ for (int x = aligned_lowx; x < highx; x += 4) {
+ int4 x4 = make_int4(x) + make_int4(0, 1, 2, 3);
+ int4 active = (x4 >= lowx4) & (x4 < highx4);
+
+ float4 diff = load4_u(difference_image, y * stride + x + dx);
+ load4_a(out_image, y * stride + x) += mask(active, diff);
+ }
+ }
+ }
+
+ aligned_lowx = round_down(rect.x, 4);
+ for (int y = rect.y; y < rect.w; y++) {
+ for (int x = aligned_lowx; x < rect.z; x += 4) {
+ float4 x4 = make_float4(x) + make_float4(0.0f, 1.0f, 2.0f, 3.0f);
+ float4 low = max(make_float4(rect.x), x4 - make_float4(f));
+ float4 high = min(make_float4(rect.z), x4 + make_float4(f + 1));
+ load4_a(out_image, y * stride + x) *= rcp(high - low);
+ }
+ }
}
-ccl_device_inline void kernel_filter_nlm_calc_weight(const float *ccl_restrict difference_image,
- float *out_image,
- int4 rect,
- int stride,
- int f)
+ccl_device_inline void kernel_filter_nlm_calc_weight(
+ const float *ccl_restrict difference_image, float *out_image, int4 rect, int stride, int f)
{
- nlm_blur_horizontal(difference_image, out_image, rect, stride, f);
-
- int aligned_lowx = round_down(rect.x, 4);
- for(int y = rect.y; y < rect.w; y++) {
- for(int x = aligned_lowx; x < rect.z; x += 4) {
- load4_a(out_image, y*stride + x) = fast_expf4(-max(load4_a(out_image, y*stride + x), make_float4(0.0f)));
- }
- }
+ nlm_blur_horizontal(difference_image, out_image, rect, stride, f);
+
+ int aligned_lowx = round_down(rect.x, 4);
+ for (int y = rect.y; y < rect.w; y++) {
+ for (int x = aligned_lowx; x < rect.z; x += 4) {
+ load4_a(out_image, y * stride + x) = fast_expf4(
+ -max(load4_a(out_image, y * stride + x), make_float4(0.0f)));
+ }
+ }
}
-ccl_device_inline void kernel_filter_nlm_update_output(int dx, int dy,
+ccl_device_inline void kernel_filter_nlm_update_output(int dx,
+ int dy,
const float *ccl_restrict difference_image,
const float *ccl_restrict image,
float *temp_image,
@@ -157,33 +153,36 @@ ccl_device_inline void kernel_filter_nlm_update_output(int dx, int dy,
int stride,
int f)
{
- nlm_blur_horizontal(difference_image, temp_image, rect, stride, f);
+ nlm_blur_horizontal(difference_image, temp_image, rect, stride, f);
- int aligned_lowx = round_down(rect.x, 4);
- for(int y = rect.y; y < rect.w; y++) {
- for(int x = aligned_lowx; x < rect.z; x += 4) {
- int4 x4 = make_int4(x) + make_int4(0, 1, 2, 3);
- int4 active = (x4 >= make_int4(rect.x)) & (x4 < make_int4(rect.z));
+ int aligned_lowx = round_down(rect.x, 4);
+ for (int y = rect.y; y < rect.w; y++) {
+ for (int x = aligned_lowx; x < rect.z; x += 4) {
+ int4 x4 = make_int4(x) + make_int4(0, 1, 2, 3);
+ int4 active = (x4 >= make_int4(rect.x)) & (x4 < make_int4(rect.z));
- int idx_p = y*stride + x, idx_q = (y+dy)*stride + (x+dx);
+ int idx_p = y * stride + x, idx_q = (y + dy) * stride + (x + dx);
- float4 weight = load4_a(temp_image, idx_p);
- load4_a(accum_image, idx_p) += mask(active, weight);
+ float4 weight = load4_a(temp_image, idx_p);
+ load4_a(accum_image, idx_p) += mask(active, weight);
- float4 val = load4_u(image, idx_q);
- if(channel_offset) {
- val += load4_u(image, idx_q + channel_offset);
- val += load4_u(image, idx_q + 2*channel_offset);
- val *= 1.0f/3.0f;
- }
+ float4 val = load4_u(image, idx_q);
+ if (channel_offset) {
+ val += load4_u(image, idx_q + channel_offset);
+ val += load4_u(image, idx_q + 2 * channel_offset);
+ val *= 1.0f / 3.0f;
+ }
- load4_a(out_image, idx_p) += mask(active, weight*val);
- }
- }
+ load4_a(out_image, idx_p) += mask(active, weight * val);
+ }
+ }
}
-ccl_device_inline void kernel_filter_nlm_construct_gramian(int dx, int dy, int t,
- const float *ccl_restrict difference_image,
+ccl_device_inline void kernel_filter_nlm_construct_gramian(int dx,
+ int dy,
+ int t,
+ const float *ccl_restrict
+ difference_image,
const float *ccl_restrict buffer,
float *transform,
int *rank,
@@ -191,40 +190,49 @@ ccl_device_inline void kernel_filter_nlm_construct_gramian(int dx, int dy, int t
float3 *XtWY,
int4 rect,
int4 filter_window,
- int stride, int f,
+ int stride,
+ int f,
int pass_stride,
int frame_offset,
bool use_time)
{
- int4 clip_area = rect_clip(rect, filter_window);
- /* fy and fy are in filter-window-relative coordinates, while x and y are in feature-window-relative coordinates. */
- for(int y = clip_area.y; y < clip_area.w; y++) {
- for(int x = clip_area.x; x < clip_area.z; x++) {
- const int low = max(rect.x, x-f);
- const int high = min(rect.z, x+f+1);
- float sum = 0.0f;
- for(int x1 = low; x1 < high; x1++) {
- sum += difference_image[y*stride + x1];
- }
- float weight = sum * (1.0f/(high - low));
-
- int storage_ofs = coord_to_local_index(filter_window, x, y);
- float *l_transform = transform + storage_ofs*TRANSFORM_SIZE;
- float *l_XtWX = XtWX + storage_ofs*XTWX_SIZE;
- float3 *l_XtWY = XtWY + storage_ofs*XTWY_SIZE;
- int *l_rank = rank + storage_ofs;
-
- kernel_filter_construct_gramian(x, y, 1,
- dx, dy, t,
- stride,
- pass_stride,
- frame_offset,
- use_time,
- buffer,
- l_transform, l_rank,
- weight, l_XtWX, l_XtWY, 0);
- }
- }
+ int4 clip_area = rect_clip(rect, filter_window);
+ /* fy and fy are in filter-window-relative coordinates, while x and y are in feature-window-relative coordinates. */
+ for (int y = clip_area.y; y < clip_area.w; y++) {
+ for (int x = clip_area.x; x < clip_area.z; x++) {
+ const int low = max(rect.x, x - f);
+ const int high = min(rect.z, x + f + 1);
+ float sum = 0.0f;
+ for (int x1 = low; x1 < high; x1++) {
+ sum += difference_image[y * stride + x1];
+ }
+ float weight = sum * (1.0f / (high - low));
+
+ int storage_ofs = coord_to_local_index(filter_window, x, y);
+ float *l_transform = transform + storage_ofs * TRANSFORM_SIZE;
+ float *l_XtWX = XtWX + storage_ofs * XTWX_SIZE;
+ float3 *l_XtWY = XtWY + storage_ofs * XTWY_SIZE;
+ int *l_rank = rank + storage_ofs;
+
+ kernel_filter_construct_gramian(x,
+ y,
+ 1,
+ dx,
+ dy,
+ t,
+ stride,
+ pass_stride,
+ frame_offset,
+ use_time,
+ buffer,
+ l_transform,
+ l_rank,
+ weight,
+ l_XtWX,
+ l_XtWY,
+ 0);
+ }
+ }
}
ccl_device_inline void kernel_filter_nlm_normalize(float *out_image,
@@ -232,11 +240,11 @@ ccl_device_inline void kernel_filter_nlm_normalize(float *out_image,
int4 rect,
int w)
{
- for(int y = rect.y; y < rect.w; y++) {
- for(int x = rect.x; x < rect.z; x++) {
- out_image[y*w+x] /= accum_image[y*w+x];
- }
- }
+ for (int y = rect.y; y < rect.w; y++) {
+ for (int x = rect.x; x < rect.z; x++) {
+ out_image[y * w + x] /= accum_image[y * w + x];
+ }
+ }
}
#undef load4_a
diff --git a/intern/cycles/kernel/filter/filter_nlm_gpu.h b/intern/cycles/kernel/filter/filter_nlm_gpu.h
index 12636393243..650c743f34f 100644
--- a/intern/cycles/kernel/filter/filter_nlm_gpu.h
+++ b/intern/cycles/kernel/filter/filter_nlm_gpu.h
@@ -24,203 +24,232 @@ CCL_NAMESPACE_BEGIN
* Window is the rect that should be processed.
* co is filled with (x, y, dx, dy).
*/
-ccl_device_inline bool get_nlm_coords_window(int w, int h, int r, int stride,
- int4 *rect, int4 *co, int *ofs,
- int4 window)
+ccl_device_inline bool get_nlm_coords_window(
+ int w, int h, int r, int stride, int4 *rect, int4 *co, int *ofs, int4 window)
{
- /* Determine the pixel offset that this thread should apply. */
- int s = 2*r+1;
- int si = ccl_global_id(1);
- int sx = si % s;
- int sy = si / s;
- if(sy >= s) {
- return false;
- }
-
- /* Pixels still need to lie inside the denoising buffer after applying the offset,
- * so determine the area for which this is the case. */
- int dx = sx - r;
- int dy = sy - r;
-
- *rect = make_int4(max(0, -dx), max(0, -dy),
- w - max(0, dx), h - max(0, dy));
-
- /* Find the intersection of the area that we want to process (window) and the area
- * that can be processed (rect) to get the final area for this offset. */
- int4 clip_area = rect_clip(window, *rect);
-
- /* If the radius is larger than one of the sides of the window,
- * there will be shifts for which there is no usable pixel at all. */
- if(!rect_is_valid(clip_area)) {
- return false;
- }
-
- /* Map the linear thread index to pixels inside the clip area. */
- int x, y;
- if(!local_index_to_coord(clip_area, ccl_global_id(0), &x, &y)) {
- return false;
- }
-
- *co = make_int4(x, y, dx, dy);
-
- *ofs = (sy*s + sx) * stride;
-
- return true;
+ /* Determine the pixel offset that this thread should apply. */
+ int s = 2 * r + 1;
+ int si = ccl_global_id(1);
+ int sx = si % s;
+ int sy = si / s;
+ if (sy >= s) {
+ return false;
+ }
+
+ /* Pixels still need to lie inside the denoising buffer after applying the offset,
+ * so determine the area for which this is the case. */
+ int dx = sx - r;
+ int dy = sy - r;
+
+ *rect = make_int4(max(0, -dx), max(0, -dy), w - max(0, dx), h - max(0, dy));
+
+ /* Find the intersection of the area that we want to process (window) and the area
+ * that can be processed (rect) to get the final area for this offset. */
+ int4 clip_area = rect_clip(window, *rect);
+
+ /* If the radius is larger than one of the sides of the window,
+ * there will be shifts for which there is no usable pixel at all. */
+ if (!rect_is_valid(clip_area)) {
+ return false;
+ }
+
+ /* Map the linear thread index to pixels inside the clip area. */
+ int x, y;
+ if (!local_index_to_coord(clip_area, ccl_global_id(0), &x, &y)) {
+ return false;
+ }
+
+ *co = make_int4(x, y, dx, dy);
+
+ *ofs = (sy * s + sx) * stride;
+
+ return true;
}
-ccl_device_inline bool get_nlm_coords(int w, int h, int r, int stride,
- int4 *rect, int4 *co, int *ofs)
+ccl_device_inline bool get_nlm_coords(
+ int w, int h, int r, int stride, int4 *rect, int4 *co, int *ofs)
{
- return get_nlm_coords_window(w, h, r, stride, rect, co, ofs, make_int4(0, 0, w, h));
+ return get_nlm_coords_window(w, h, r, stride, rect, co, ofs, make_int4(0, 0, w, h));
}
-ccl_device_inline void kernel_filter_nlm_calc_difference(int x, int y,
- int dx, int dy,
- const ccl_global float *ccl_restrict weight_image,
- const ccl_global float *ccl_restrict variance_image,
- const ccl_global float *ccl_restrict scale_image,
- ccl_global float *difference_image,
- int4 rect, int stride,
- int channel_offset,
- int frame_offset,
- float a, float k_2)
+ccl_device_inline void kernel_filter_nlm_calc_difference(
+ int x,
+ int y,
+ int dx,
+ int dy,
+ const ccl_global float *ccl_restrict weight_image,
+ const ccl_global float *ccl_restrict variance_image,
+ const ccl_global float *ccl_restrict scale_image,
+ ccl_global float *difference_image,
+ int4 rect,
+ int stride,
+ int channel_offset,
+ int frame_offset,
+ float a,
+ float k_2)
{
- int idx_p = y*stride + x, idx_q = (y+dy)*stride + (x+dx) + frame_offset;
- int numChannels = channel_offset? 3 : 1;
-
- float diff = 0.0f;
- float scale_fac = 1.0f;
- if(scale_image) {
- scale_fac = clamp(scale_image[idx_p] / scale_image[idx_q], 0.25f, 4.0f);
- }
-
- for(int c = 0; c < numChannels; c++, idx_p += channel_offset, idx_q += channel_offset) {
- float cdiff = weight_image[idx_p] - scale_fac*weight_image[idx_q];
- float pvar = variance_image[idx_p];
- float qvar = sqr(scale_fac)*variance_image[idx_q];
- diff += (cdiff*cdiff - a*(pvar + min(pvar, qvar))) / (1e-8f + k_2*(pvar+qvar));
- }
- if(numChannels > 1) {
- diff *= 1.0f/numChannels;
- }
- difference_image[y*stride + x] = diff;
+ int idx_p = y * stride + x, idx_q = (y + dy) * stride + (x + dx) + frame_offset;
+ int numChannels = channel_offset ? 3 : 1;
+
+ float diff = 0.0f;
+ float scale_fac = 1.0f;
+ if (scale_image) {
+ scale_fac = clamp(scale_image[idx_p] / scale_image[idx_q], 0.25f, 4.0f);
+ }
+
+ for (int c = 0; c < numChannels; c++, idx_p += channel_offset, idx_q += channel_offset) {
+ float cdiff = weight_image[idx_p] - scale_fac * weight_image[idx_q];
+ float pvar = variance_image[idx_p];
+ float qvar = sqr(scale_fac) * variance_image[idx_q];
+ diff += (cdiff * cdiff - a * (pvar + min(pvar, qvar))) / (1e-8f + k_2 * (pvar + qvar));
+ }
+ if (numChannels > 1) {
+ diff *= 1.0f / numChannels;
+ }
+ difference_image[y * stride + x] = diff;
}
-ccl_device_inline void kernel_filter_nlm_blur(int x, int y,
- const ccl_global float *ccl_restrict difference_image,
+ccl_device_inline void kernel_filter_nlm_blur(int x,
+ int y,
+ const ccl_global float *ccl_restrict
+ difference_image,
ccl_global float *out_image,
- int4 rect, int stride, int f)
+ int4 rect,
+ int stride,
+ int f)
{
- float sum = 0.0f;
- const int low = max(rect.y, y-f);
- const int high = min(rect.w, y+f+1);
- for(int y1 = low; y1 < high; y1++) {
- sum += difference_image[y1*stride + x];
- }
- sum *= 1.0f/(high-low);
- out_image[y*stride + x] = sum;
+ float sum = 0.0f;
+ const int low = max(rect.y, y - f);
+ const int high = min(rect.w, y + f + 1);
+ for (int y1 = low; y1 < high; y1++) {
+ sum += difference_image[y1 * stride + x];
+ }
+ sum *= 1.0f / (high - low);
+ out_image[y * stride + x] = sum;
}
-ccl_device_inline void kernel_filter_nlm_calc_weight(int x, int y,
- const ccl_global float *ccl_restrict difference_image,
+ccl_device_inline void kernel_filter_nlm_calc_weight(int x,
+ int y,
+ const ccl_global float *ccl_restrict
+ difference_image,
ccl_global float *out_image,
- int4 rect, int stride, int f)
+ int4 rect,
+ int stride,
+ int f)
{
- float sum = 0.0f;
- const int low = max(rect.x, x-f);
- const int high = min(rect.z, x+f+1);
- for(int x1 = low; x1 < high; x1++) {
- sum += difference_image[y*stride + x1];
- }
- sum *= 1.0f/(high-low);
- out_image[y*stride + x] = fast_expf(-max(sum, 0.0f));
+ float sum = 0.0f;
+ const int low = max(rect.x, x - f);
+ const int high = min(rect.z, x + f + 1);
+ for (int x1 = low; x1 < high; x1++) {
+ sum += difference_image[y * stride + x1];
+ }
+ sum *= 1.0f / (high - low);
+ out_image[y * stride + x] = fast_expf(-max(sum, 0.0f));
}
-ccl_device_inline void kernel_filter_nlm_update_output(int x, int y,
- int dx, int dy,
- const ccl_global float *ccl_restrict difference_image,
+ccl_device_inline void kernel_filter_nlm_update_output(int x,
+ int y,
+ int dx,
+ int dy,
+ const ccl_global float *ccl_restrict
+ difference_image,
const ccl_global float *ccl_restrict image,
ccl_global float *out_image,
ccl_global float *accum_image,
- int4 rect, int channel_offset,
- int stride, int f)
+ int4 rect,
+ int channel_offset,
+ int stride,
+ int f)
{
- float sum = 0.0f;
- const int low = max(rect.x, x-f);
- const int high = min(rect.z, x+f+1);
- for(int x1 = low; x1 < high; x1++) {
- sum += difference_image[y*stride + x1];
- }
- sum *= 1.0f/(high-low);
-
- int idx_p = y*stride + x, idx_q = (y+dy)*stride + (x+dx);
- if(out_image) {
- atomic_add_and_fetch_float(accum_image + idx_p, sum);
-
- float val = image[idx_q];
- if(channel_offset) {
- val += image[idx_q + channel_offset];
- val += image[idx_q + 2*channel_offset];
- val *= 1.0f/3.0f;
- }
- atomic_add_and_fetch_float(out_image + idx_p, sum*val);
- }
- else {
- accum_image[idx_p] = sum;
- }
+ float sum = 0.0f;
+ const int low = max(rect.x, x - f);
+ const int high = min(rect.z, x + f + 1);
+ for (int x1 = low; x1 < high; x1++) {
+ sum += difference_image[y * stride + x1];
+ }
+ sum *= 1.0f / (high - low);
+
+ int idx_p = y * stride + x, idx_q = (y + dy) * stride + (x + dx);
+ if (out_image) {
+ atomic_add_and_fetch_float(accum_image + idx_p, sum);
+
+ float val = image[idx_q];
+ if (channel_offset) {
+ val += image[idx_q + channel_offset];
+ val += image[idx_q + 2 * channel_offset];
+ val *= 1.0f / 3.0f;
+ }
+ atomic_add_and_fetch_float(out_image + idx_p, sum * val);
+ }
+ else {
+ accum_image[idx_p] = sum;
+ }
}
-ccl_device_inline void kernel_filter_nlm_construct_gramian(int x, int y,
- int dx, int dy, int t,
- const ccl_global float *ccl_restrict difference_image,
- const ccl_global float *ccl_restrict buffer,
- const ccl_global float *ccl_restrict transform,
- ccl_global int *rank,
- ccl_global float *XtWX,
- ccl_global float3 *XtWY,
- int4 rect,
- int4 filter_window,
- int stride, int f,
- int pass_stride,
- int frame_offset,
- bool use_time,
- int localIdx)
+ccl_device_inline void kernel_filter_nlm_construct_gramian(
+ int x,
+ int y,
+ int dx,
+ int dy,
+ int t,
+ const ccl_global float *ccl_restrict difference_image,
+ const ccl_global float *ccl_restrict buffer,
+ const ccl_global float *ccl_restrict transform,
+ ccl_global int *rank,
+ ccl_global float *XtWX,
+ ccl_global float3 *XtWY,
+ int4 rect,
+ int4 filter_window,
+ int stride,
+ int f,
+ int pass_stride,
+ int frame_offset,
+ bool use_time,
+ int localIdx)
{
- const int low = max(rect.x, x-f);
- const int high = min(rect.z, x+f+1);
- float sum = 0.0f;
- for(int x1 = low; x1 < high; x1++) {
- sum += difference_image[y*stride + x1];
- }
- float weight = sum * (1.0f/(high - low));
-
- /* Reconstruction data is only stored for pixels inside the filter window,
- * so compute the pixels's index in there. */
- int storage_ofs = coord_to_local_index(filter_window, x, y);
- transform += storage_ofs;
- rank += storage_ofs;
- XtWX += storage_ofs;
- XtWY += storage_ofs;
-
- kernel_filter_construct_gramian(x, y,
- rect_size(filter_window),
- dx, dy, t,
- stride,
- pass_stride,
- frame_offset,
- use_time,
- buffer,
- transform, rank,
- weight, XtWX, XtWY,
- localIdx);
+ const int low = max(rect.x, x - f);
+ const int high = min(rect.z, x + f + 1);
+ float sum = 0.0f;
+ for (int x1 = low; x1 < high; x1++) {
+ sum += difference_image[y * stride + x1];
+ }
+ float weight = sum * (1.0f / (high - low));
+
+ /* Reconstruction data is only stored for pixels inside the filter window,
+ * so compute the pixels's index in there. */
+ int storage_ofs = coord_to_local_index(filter_window, x, y);
+ transform += storage_ofs;
+ rank += storage_ofs;
+ XtWX += storage_ofs;
+ XtWY += storage_ofs;
+
+ kernel_filter_construct_gramian(x,
+ y,
+ rect_size(filter_window),
+ dx,
+ dy,
+ t,
+ stride,
+ pass_stride,
+ frame_offset,
+ use_time,
+ buffer,
+ transform,
+ rank,
+ weight,
+ XtWX,
+ XtWY,
+ localIdx);
}
-ccl_device_inline void kernel_filter_nlm_normalize(int x, int y,
+ccl_device_inline void kernel_filter_nlm_normalize(int x,
+ int y,
ccl_global float *out_image,
- const ccl_global float *ccl_restrict accum_image,
+ const ccl_global float *ccl_restrict
+ accum_image,
int stride)
{
- out_image[y*stride + x] /= accum_image[y*stride + x];
+ out_image[y * stride + x] /= accum_image[y * stride + x];
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/filter/filter_prefilter.h b/intern/cycles/kernel/filter/filter_prefilter.h
index e24f4feb28d..8211311313d 100644
--- a/intern/cycles/kernel/filter/filter_prefilter.h
+++ b/intern/cycles/kernel/filter/filter_prefilter.h
@@ -27,7 +27,8 @@ CCL_NAMESPACE_BEGIN
*/
ccl_device void kernel_filter_divide_shadow(int sample,
CCL_FILTER_TILE_INFO,
- int x, int y,
+ int x,
+ int y,
ccl_global float *unfilteredA,
ccl_global float *unfilteredB,
ccl_global float *sampleVariance,
@@ -37,37 +38,39 @@ ccl_device void kernel_filter_divide_shadow(int sample,
int buffer_pass_stride,
int buffer_denoising_offset)
{
- int xtile = (x < tile_info->x[1])? 0: ((x < tile_info->x[2])? 1: 2);
- int ytile = (y < tile_info->y[1])? 0: ((y < tile_info->y[2])? 1: 2);
- int tile = ytile*3+xtile;
+ int xtile = (x < tile_info->x[1]) ? 0 : ((x < tile_info->x[2]) ? 1 : 2);
+ int ytile = (y < tile_info->y[1]) ? 0 : ((y < tile_info->y[2]) ? 1 : 2);
+ int tile = ytile * 3 + xtile;
- int offset = tile_info->offsets[tile];
- int stride = tile_info->strides[tile];
- const ccl_global float *ccl_restrict center_buffer = (ccl_global float*) ccl_get_tile_buffer(tile);
- center_buffer += (y*stride + x + offset)*buffer_pass_stride;
- center_buffer += buffer_denoising_offset + 14;
+ int offset = tile_info->offsets[tile];
+ int stride = tile_info->strides[tile];
+ const ccl_global float *ccl_restrict center_buffer = (ccl_global float *)ccl_get_tile_buffer(
+ tile);
+ center_buffer += (y * stride + x + offset) * buffer_pass_stride;
+ center_buffer += buffer_denoising_offset + 14;
- int buffer_w = align_up(rect.z - rect.x, 4);
- int idx = (y-rect.y)*buffer_w + (x - rect.x);
- unfilteredA[idx] = center_buffer[1] / max(center_buffer[0], 1e-7f);
- unfilteredB[idx] = center_buffer[4] / max(center_buffer[3], 1e-7f);
+ int buffer_w = align_up(rect.z - rect.x, 4);
+ int idx = (y - rect.y) * buffer_w + (x - rect.x);
+ unfilteredA[idx] = center_buffer[1] / max(center_buffer[0], 1e-7f);
+ unfilteredB[idx] = center_buffer[4] / max(center_buffer[3], 1e-7f);
- float varA = center_buffer[2];
- float varB = center_buffer[5];
- int odd_sample = (sample+1)/2;
- int even_sample = sample/2;
+ float varA = center_buffer[2];
+ float varB = center_buffer[5];
+ int odd_sample = (sample + 1) / 2;
+ int even_sample = sample / 2;
- /* Approximate variance as E[x^2] - 1/N * (E[x])^2, since online variance
- * update does not work efficiently with atomics in the kernel. */
- varA = max(0.0f, varA - unfilteredA[idx]*unfilteredA[idx]*odd_sample);
- varB = max(0.0f, varB - unfilteredB[idx]*unfilteredB[idx]*even_sample);
+ /* Approximate variance as E[x^2] - 1/N * (E[x])^2, since online variance
+ * update does not work efficiently with atomics in the kernel. */
+ varA = max(0.0f, varA - unfilteredA[idx] * unfilteredA[idx] * odd_sample);
+ varB = max(0.0f, varB - unfilteredB[idx] * unfilteredB[idx] * even_sample);
- varA /= max(odd_sample - 1, 1);
- varB /= max(even_sample - 1, 1);
+ varA /= max(odd_sample - 1, 1);
+ varB /= max(even_sample - 1, 1);
- sampleVariance[idx] = 0.5f*(varA + varB) / sample;
- sampleVarianceV[idx] = 0.5f * (varA - varB) * (varA - varB) / (sample*sample);
- bufferVariance[idx] = 0.5f * (unfilteredA[idx] - unfilteredB[idx]) * (unfilteredA[idx] - unfilteredB[idx]);
+ sampleVariance[idx] = 0.5f * (varA + varB) / sample;
+ sampleVarianceV[idx] = 0.5f * (varA - varB) * (varA - varB) / (sample * sample);
+ bufferVariance[idx] = 0.5f * (unfilteredA[idx] - unfilteredB[idx]) *
+ (unfilteredA[idx] - unfilteredB[idx]);
}
/* Load a regular feature from the render buffers into the denoise buffer.
@@ -80,55 +83,65 @@ ccl_device void kernel_filter_divide_shadow(int sample,
*/
ccl_device void kernel_filter_get_feature(int sample,
CCL_FILTER_TILE_INFO,
- int m_offset, int v_offset,
- int x, int y,
+ int m_offset,
+ int v_offset,
+ int x,
+ int y,
ccl_global float *mean,
ccl_global float *variance,
float scale,
- int4 rect, int buffer_pass_stride,
+ int4 rect,
+ int buffer_pass_stride,
int buffer_denoising_offset)
{
- int xtile = (x < tile_info->x[1])? 0: ((x < tile_info->x[2])? 1: 2);
- int ytile = (y < tile_info->y[1])? 0: ((y < tile_info->y[2])? 1: 2);
- int tile = ytile*3+xtile;
- ccl_global float *center_buffer = ((ccl_global float*) ccl_get_tile_buffer(tile)) + (tile_info->offsets[tile] + y*tile_info->strides[tile] + x)*buffer_pass_stride + buffer_denoising_offset;
+ int xtile = (x < tile_info->x[1]) ? 0 : ((x < tile_info->x[2]) ? 1 : 2);
+ int ytile = (y < tile_info->y[1]) ? 0 : ((y < tile_info->y[2]) ? 1 : 2);
+ int tile = ytile * 3 + xtile;
+ ccl_global float *center_buffer = ((ccl_global float *)ccl_get_tile_buffer(tile)) +
+ (tile_info->offsets[tile] + y * tile_info->strides[tile] + x) *
+ buffer_pass_stride +
+ buffer_denoising_offset;
- int buffer_w = align_up(rect.z - rect.x, 4);
- int idx = (y-rect.y)*buffer_w + (x - rect.x);
+ int buffer_w = align_up(rect.z - rect.x, 4);
+ int idx = (y - rect.y) * buffer_w + (x - rect.x);
- float val = scale * center_buffer[m_offset];
- mean[idx] = val;
+ float val = scale * center_buffer[m_offset];
+ mean[idx] = val;
- if(v_offset >= 0) {
- if(sample > 1) {
- /* Approximate variance as E[x^2] - 1/N * (E[x])^2, since online variance
- * update does not work efficiently with atomics in the kernel. */
- variance[idx] = max(0.0f, (center_buffer[v_offset] - val*val*sample) / (sample * (sample-1)));
- }
- else {
- /* Can't compute variance with single sample, just set it very high. */
- variance[idx] = 1e10f;
- }
- }
+ if (v_offset >= 0) {
+ if (sample > 1) {
+ /* Approximate variance as E[x^2] - 1/N * (E[x])^2, since online variance
+ * update does not work efficiently with atomics in the kernel. */
+ variance[idx] = max(
+ 0.0f, (center_buffer[v_offset] - val * val * sample) / (sample * (sample - 1)));
+ }
+ else {
+ /* Can't compute variance with single sample, just set it very high. */
+ variance[idx] = 1e10f;
+ }
+ }
}
ccl_device void kernel_filter_write_feature(int sample,
- int x, int y,
+ int x,
+ int y,
int4 buffer_params,
ccl_global float *from,
ccl_global float *buffer,
int out_offset,
int4 rect)
{
- ccl_global float *combined_buffer = buffer + (y*buffer_params.y + x + buffer_params.x)*buffer_params.z;
+ ccl_global float *combined_buffer = buffer + (y * buffer_params.y + x + buffer_params.x) *
+ buffer_params.z;
- int buffer_w = align_up(rect.z - rect.x, 4);
- int idx = (y-rect.y)*buffer_w + (x - rect.x);
+ int buffer_w = align_up(rect.z - rect.x, 4);
+ int idx = (y - rect.y) * buffer_w + (x - rect.x);
- combined_buffer[out_offset] = from[idx];
+ combined_buffer[out_offset] = from[idx];
}
-ccl_device void kernel_filter_detect_outliers(int x, int y,
+ccl_device void kernel_filter_detect_outliers(int x,
+ int y,
ccl_global float *image,
ccl_global float *variance,
ccl_global float *depth,
@@ -136,123 +149,131 @@ ccl_device void kernel_filter_detect_outliers(int x, int y,
int4 rect,
int pass_stride)
{
- int buffer_w = align_up(rect.z - rect.x, 4);
+ int buffer_w = align_up(rect.z - rect.x, 4);
- int n = 0;
- float values[25];
- float pixel_variance, max_variance = 0.0f;
- for(int y1 = max(y-2, rect.y); y1 < min(y+3, rect.w); y1++) {
- for(int x1 = max(x-2, rect.x); x1 < min(x+3, rect.z); x1++) {
- int idx = (y1-rect.y)*buffer_w + (x1-rect.x);
- float3 color = make_float3(image[idx], image[idx+pass_stride], image[idx+2*pass_stride]);
- color = max(color, make_float3(0.0f, 0.0f, 0.0f));
- float L = average(color);
+ int n = 0;
+ float values[25];
+ float pixel_variance, max_variance = 0.0f;
+ for (int y1 = max(y - 2, rect.y); y1 < min(y + 3, rect.w); y1++) {
+ for (int x1 = max(x - 2, rect.x); x1 < min(x + 3, rect.z); x1++) {
+ int idx = (y1 - rect.y) * buffer_w + (x1 - rect.x);
+ float3 color = make_float3(
+ image[idx], image[idx + pass_stride], image[idx + 2 * pass_stride]);
+ color = max(color, make_float3(0.0f, 0.0f, 0.0f));
+ float L = average(color);
- /* Find the position of L. */
- int i;
- for(i = 0; i < n; i++) {
- if(values[i] > L) break;
- }
- /* Make space for L by shifting all following values to the right. */
- for(int j = n; j > i; j--) {
- values[j] = values[j-1];
- }
- /* Insert L. */
- values[i] = L;
- n++;
+ /* Find the position of L. */
+ int i;
+ for (i = 0; i < n; i++) {
+ if (values[i] > L)
+ break;
+ }
+ /* Make space for L by shifting all following values to the right. */
+ for (int j = n; j > i; j--) {
+ values[j] = values[j - 1];
+ }
+ /* Insert L. */
+ values[i] = L;
+ n++;
- float3 pixel_var = make_float3(variance[idx], variance[idx+pass_stride], variance[idx+2*pass_stride]);
- float var = average(pixel_var);
- if((x1 == x) && (y1 == y)) {
- pixel_variance = (pixel_var.x < 0.0f || pixel_var.y < 0.0f || pixel_var.z < 0.0f)? -1.0f : var;
- }
- else {
- max_variance = max(max_variance, var);
- }
- }
- }
+ float3 pixel_var = make_float3(
+ variance[idx], variance[idx + pass_stride], variance[idx + 2 * pass_stride]);
+ float var = average(pixel_var);
+ if ((x1 == x) && (y1 == y)) {
+ pixel_variance = (pixel_var.x < 0.0f || pixel_var.y < 0.0f || pixel_var.z < 0.0f) ? -1.0f :
+ var;
+ }
+ else {
+ max_variance = max(max_variance, var);
+ }
+ }
+ }
- max_variance += 1e-4f;
+ max_variance += 1e-4f;
- int idx = (y-rect.y)*buffer_w + (x-rect.x);
- float3 color = make_float3(image[idx], image[idx+pass_stride], image[idx+2*pass_stride]);
- color = max(color, make_float3(0.0f, 0.0f, 0.0f));
- float L = average(color);
+ int idx = (y - rect.y) * buffer_w + (x - rect.x);
+ float3 color = make_float3(image[idx], image[idx + pass_stride], image[idx + 2 * pass_stride]);
+ color = max(color, make_float3(0.0f, 0.0f, 0.0f));
+ float L = average(color);
- float ref = 2.0f*values[(int)(n*0.75f)];
+ float ref = 2.0f * values[(int)(n * 0.75f)];
- /* Slightly offset values to avoid false positives in (almost) black areas. */
- max_variance += 1e-5f;
- ref -= 1e-5f;
+ /* Slightly offset values to avoid false positives in (almost) black areas. */
+ max_variance += 1e-5f;
+ ref -= 1e-5f;
- if(L > ref) {
- /* The pixel appears to be an outlier.
- * However, it may just be a legitimate highlight. Therefore, it is checked how likely it is that the pixel
- * should actually be at the reference value:
- * If the reference is within the 3-sigma interval, the pixel is assumed to be a statistical outlier.
- * Otherwise, it is very unlikely that the pixel should be darker, which indicates a legitimate highlight.
- */
+ if (L > ref) {
+ /* The pixel appears to be an outlier.
+ * However, it may just be a legitimate highlight. Therefore, it is checked how likely it is that the pixel
+ * should actually be at the reference value:
+ * If the reference is within the 3-sigma interval, the pixel is assumed to be a statistical outlier.
+ * Otherwise, it is very unlikely that the pixel should be darker, which indicates a legitimate highlight.
+ */
- if(pixel_variance < 0.0f || pixel_variance > 9.0f * max_variance) {
- depth[idx] = -depth[idx];
- color *= ref/L;
- variance[idx] = variance[idx + pass_stride] = variance[idx + 2*pass_stride] = max_variance;
- }
- else {
- float stddev = sqrtf(pixel_variance);
- if(L - 3*stddev < ref) {
- /* The pixel is an outlier, so negate the depth value to mark it as one.
- * Also, scale its brightness down to the outlier threshold to avoid trouble with the NLM weights. */
- depth[idx] = -depth[idx];
- float fac = ref/L;
- color *= fac;
- variance[idx ] *= fac*fac;
- variance[idx + pass_stride] *= fac*fac;
- variance[idx+2*pass_stride] *= fac*fac;
- }
- }
- }
- out[idx ] = color.x;
- out[idx + pass_stride] = color.y;
- out[idx+2*pass_stride] = color.z;
+ if (pixel_variance < 0.0f || pixel_variance > 9.0f * max_variance) {
+ depth[idx] = -depth[idx];
+ color *= ref / L;
+ variance[idx] = variance[idx + pass_stride] = variance[idx + 2 * pass_stride] = max_variance;
+ }
+ else {
+ float stddev = sqrtf(pixel_variance);
+ if (L - 3 * stddev < ref) {
+ /* The pixel is an outlier, so negate the depth value to mark it as one.
+ * Also, scale its brightness down to the outlier threshold to avoid trouble with the NLM weights. */
+ depth[idx] = -depth[idx];
+ float fac = ref / L;
+ color *= fac;
+ variance[idx] *= fac * fac;
+ variance[idx + pass_stride] *= fac * fac;
+ variance[idx + 2 * pass_stride] *= fac * fac;
+ }
+ }
+ }
+ out[idx] = color.x;
+ out[idx + pass_stride] = color.y;
+ out[idx + 2 * pass_stride] = color.z;
}
/* Combine A/B buffers.
* Calculates the combined mean and the buffer variance. */
-ccl_device void kernel_filter_combine_halves(int x, int y,
+ccl_device void kernel_filter_combine_halves(int x,
+ int y,
ccl_global float *mean,
ccl_global float *variance,
ccl_global float *a,
ccl_global float *b,
- int4 rect, int r)
+ int4 rect,
+ int r)
{
- int buffer_w = align_up(rect.z - rect.x, 4);
- int idx = (y-rect.y)*buffer_w + (x - rect.x);
+ int buffer_w = align_up(rect.z - rect.x, 4);
+ int idx = (y - rect.y) * buffer_w + (x - rect.x);
- if(mean) mean[idx] = 0.5f * (a[idx]+b[idx]);
- if(variance) {
- if(r == 0) variance[idx] = 0.25f * (a[idx]-b[idx])*(a[idx]-b[idx]);
- else {
- variance[idx] = 0.0f;
- float values[25];
- int numValues = 0;
- for(int py = max(y-r, rect.y); py < min(y+r+1, rect.w); py++) {
- for(int px = max(x-r, rect.x); px < min(x+r+1, rect.z); px++) {
- int pidx = (py-rect.y)*buffer_w + (px-rect.x);
- values[numValues++] = 0.25f * (a[pidx]-b[pidx])*(a[pidx]-b[pidx]);
- }
- }
- /* Insertion-sort the variances (fast enough for 25 elements). */
- for(int i = 1; i < numValues; i++) {
- float v = values[i];
- int j;
- for(j = i-1; j >= 0 && values[j] > v; j--)
- values[j+1] = values[j];
- values[j+1] = v;
- }
- variance[idx] = values[(7*numValues)/8];
- }
- }
+ if (mean)
+ mean[idx] = 0.5f * (a[idx] + b[idx]);
+ if (variance) {
+ if (r == 0)
+ variance[idx] = 0.25f * (a[idx] - b[idx]) * (a[idx] - b[idx]);
+ else {
+ variance[idx] = 0.0f;
+ float values[25];
+ int numValues = 0;
+ for (int py = max(y - r, rect.y); py < min(y + r + 1, rect.w); py++) {
+ for (int px = max(x - r, rect.x); px < min(x + r + 1, rect.z); px++) {
+ int pidx = (py - rect.y) * buffer_w + (px - rect.x);
+ values[numValues++] = 0.25f * (a[pidx] - b[pidx]) * (a[pidx] - b[pidx]);
+ }
+ }
+ /* Insertion-sort the variances (fast enough for 25 elements). */
+ for (int i = 1; i < numValues; i++) {
+ float v = values[i];
+ int j;
+ for (j = i - 1; j >= 0 && values[j] > v; j--)
+ values[j + 1] = values[j];
+ values[j + 1] = v;
+ }
+ variance[idx] = values[(7 * numValues) / 8];
+ }
+ }
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/filter/filter_reconstruction.h b/intern/cycles/kernel/filter/filter_reconstruction.h
index ceda8f71f98..850f20584da 100644
--- a/intern/cycles/kernel/filter/filter_reconstruction.h
+++ b/intern/cycles/kernel/filter/filter_reconstruction.h
@@ -16,63 +16,75 @@
CCL_NAMESPACE_BEGIN
-ccl_device_inline void kernel_filter_construct_gramian(int x, int y,
+ccl_device_inline void kernel_filter_construct_gramian(int x,
+ int y,
int storage_stride,
- int dx, int dy, int t,
+ int dx,
+ int dy,
+ int t,
int buffer_stride,
int pass_stride,
int frame_offset,
bool use_time,
const ccl_global float *ccl_restrict buffer,
- const ccl_global float *ccl_restrict transform,
+ const ccl_global float *ccl_restrict
+ transform,
ccl_global int *rank,
float weight,
ccl_global float *XtWX,
ccl_global float3 *XtWY,
int localIdx)
{
- if(weight < 1e-3f) {
- return;
- }
+ if (weight < 1e-3f) {
+ return;
+ }
- int p_offset = y * buffer_stride + x;
- int q_offset = (y+dy) * buffer_stride + (x+dx) + frame_offset;
+ int p_offset = y * buffer_stride + x;
+ int q_offset = (y + dy) * buffer_stride + (x + dx) + frame_offset;
#ifdef __KERNEL_GPU__
- const int stride = storage_stride;
+ const int stride = storage_stride;
#else
- const int stride = 1;
- (void) storage_stride;
+ const int stride = 1;
+ (void)storage_stride;
#endif
#ifdef __KERNEL_CUDA__
- ccl_local float shared_design_row[(DENOISE_FEATURES+1)*CCL_MAX_LOCAL_SIZE];
- ccl_local_param float *design_row = shared_design_row + localIdx*(DENOISE_FEATURES+1);
+ ccl_local float shared_design_row[(DENOISE_FEATURES + 1) * CCL_MAX_LOCAL_SIZE];
+ ccl_local_param float *design_row = shared_design_row + localIdx * (DENOISE_FEATURES + 1);
#else
- float design_row[DENOISE_FEATURES+1];
+ float design_row[DENOISE_FEATURES + 1];
#endif
- float3 q_color = filter_get_color(buffer + q_offset, pass_stride);
+ float3 q_color = filter_get_color(buffer + q_offset, pass_stride);
- /* If the pixel was flagged as an outlier during prefiltering, skip it. */
- if(ccl_get_feature(buffer + q_offset, 0) < 0.0f) {
- return;
- }
+ /* If the pixel was flagged as an outlier during prefiltering, skip it. */
+ if (ccl_get_feature(buffer + q_offset, 0) < 0.0f) {
+ return;
+ }
- filter_get_design_row_transform(make_int3(x, y, t), buffer + p_offset,
- make_int3(x+dx, y+dy, t), buffer + q_offset,
- pass_stride, *rank, design_row, transform, stride, use_time);
+ filter_get_design_row_transform(make_int3(x, y, t),
+ buffer + p_offset,
+ make_int3(x + dx, y + dy, t),
+ buffer + q_offset,
+ pass_stride,
+ *rank,
+ design_row,
+ transform,
+ stride,
+ use_time);
#ifdef __KERNEL_GPU__
- math_trimatrix_add_gramian_strided(XtWX, (*rank)+1, design_row, weight, stride);
- math_vec3_add_strided(XtWY, (*rank)+1, design_row, weight * q_color, stride);
+ math_trimatrix_add_gramian_strided(XtWX, (*rank) + 1, design_row, weight, stride);
+ math_vec3_add_strided(XtWY, (*rank) + 1, design_row, weight * q_color, stride);
#else
- math_trimatrix_add_gramian(XtWX, (*rank)+1, design_row, weight);
- math_vec3_add(XtWY, (*rank)+1, design_row, weight * q_color);
+ math_trimatrix_add_gramian(XtWX, (*rank) + 1, design_row, weight);
+ math_vec3_add(XtWY, (*rank) + 1, design_row, weight * q_color);
#endif
}
-ccl_device_inline void kernel_filter_finalize(int x, int y,
+ccl_device_inline void kernel_filter_finalize(int x,
+ int y,
ccl_global float *buffer,
ccl_global int *rank,
int storage_stride,
@@ -82,47 +94,47 @@ ccl_device_inline void kernel_filter_finalize(int x, int y,
int sample)
{
#ifdef __KERNEL_GPU__
- const int stride = storage_stride;
+ const int stride = storage_stride;
#else
- const int stride = 1;
- (void) storage_stride;
+ const int stride = 1;
+ (void)storage_stride;
#endif
- if(XtWX[0] < 1e-3f) {
- /* There is not enough information to determine a denoised result.
- * As a fallback, keep the original value of the pixel. */
- return;
- }
-
- /* The weighted average of pixel colors (essentially, the NLM-filtered image).
- * In case the solution of the linear model fails due to numerical issues or
- * returns non-sensical negative values, fall back to this value. */
- float3 mean_color = XtWY[0]/XtWX[0];
-
- math_trimatrix_vec3_solve(XtWX, XtWY, (*rank)+1, stride);
-
- float3 final_color = XtWY[0];
- if(!isfinite3_safe(final_color) ||
- (final_color.x < -0.01f || final_color.y < -0.01f || final_color.z < -0.01f))
- {
- final_color = mean_color;
- }
-
- /* Clamp pixel value to positive values. */
- final_color = max(final_color, make_float3(0.0f, 0.0f, 0.0f));
-
- ccl_global float *combined_buffer = buffer + (y*buffer_params.y + x + buffer_params.x)*buffer_params.z;
- if(buffer_params.w >= 0) {
- final_color *= sample;
- if(buffer_params.w > 0) {
- final_color.x += combined_buffer[buffer_params.w+0];
- final_color.y += combined_buffer[buffer_params.w+1];
- final_color.z += combined_buffer[buffer_params.w+2];
- }
- }
- combined_buffer[0] = final_color.x;
- combined_buffer[1] = final_color.y;
- combined_buffer[2] = final_color.z;
+ if (XtWX[0] < 1e-3f) {
+ /* There is not enough information to determine a denoised result.
+ * As a fallback, keep the original value of the pixel. */
+ return;
+ }
+
+ /* The weighted average of pixel colors (essentially, the NLM-filtered image).
+ * In case the solution of the linear model fails due to numerical issues or
+ * returns non-sensical negative values, fall back to this value. */
+ float3 mean_color = XtWY[0] / XtWX[0];
+
+ math_trimatrix_vec3_solve(XtWX, XtWY, (*rank) + 1, stride);
+
+ float3 final_color = XtWY[0];
+ if (!isfinite3_safe(final_color) ||
+ (final_color.x < -0.01f || final_color.y < -0.01f || final_color.z < -0.01f)) {
+ final_color = mean_color;
+ }
+
+ /* Clamp pixel value to positive values. */
+ final_color = max(final_color, make_float3(0.0f, 0.0f, 0.0f));
+
+ ccl_global float *combined_buffer = buffer + (y * buffer_params.y + x + buffer_params.x) *
+ buffer_params.z;
+ if (buffer_params.w >= 0) {
+ final_color *= sample;
+ if (buffer_params.w > 0) {
+ final_color.x += combined_buffer[buffer_params.w + 0];
+ final_color.y += combined_buffer[buffer_params.w + 1];
+ final_color.z += combined_buffer[buffer_params.w + 2];
+ }
+ }
+ combined_buffer[0] = final_color.x;
+ combined_buffer[1] = final_color.y;
+ combined_buffer[2] = final_color.z;
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/filter/filter_transform.h b/intern/cycles/kernel/filter/filter_transform.h
index 94e27bb02fd..69e3c7c458d 100644
--- a/intern/cycles/kernel/filter/filter_transform.h
+++ b/intern/cycles/kernel/filter/filter_transform.h
@@ -18,92 +18,101 @@ CCL_NAMESPACE_BEGIN
ccl_device void kernel_filter_construct_transform(const float *ccl_restrict buffer,
CCL_FILTER_TILE_INFO,
- int x, int y, int4 rect,
- int pass_stride, int frame_stride,
+ int x,
+ int y,
+ int4 rect,
+ int pass_stride,
+ int frame_stride,
bool use_time,
- float *transform, int *rank,
- int radius, float pca_threshold)
+ float *transform,
+ int *rank,
+ int radius,
+ float pca_threshold)
{
- int buffer_w = align_up(rect.z - rect.x, 4);
-
- float features[DENOISE_FEATURES];
-
- const float *ccl_restrict pixel_buffer;
- int3 pixel;
-
- int num_features = use_time? 11 : 10;
-
- /* === Calculate denoising window. === */
- int2 low = make_int2(max(rect.x, x - radius),
- max(rect.y, y - radius));
- int2 high = make_int2(min(rect.z, x + radius + 1),
- min(rect.w, y + radius + 1));
- int num_pixels = (high.y - low.y) * (high.x - low.x) * tile_info->num_frames;
-
- /* === Shift feature passes to have mean 0. === */
- float feature_means[DENOISE_FEATURES];
- math_vector_zero(feature_means, num_features);
- FOR_PIXEL_WINDOW {
- filter_get_features(pixel, pixel_buffer, features, use_time, NULL, pass_stride);
- math_vector_add(feature_means, features, num_features);
- } END_FOR_PIXEL_WINDOW
-
- math_vector_scale(feature_means, 1.0f / num_pixels, num_features);
-
- /* === Scale the shifted feature passes to a range of [-1; 1], will be baked into the transform later. === */
- float feature_scale[DENOISE_FEATURES];
- math_vector_zero(feature_scale, num_features);
-
- FOR_PIXEL_WINDOW {
- filter_get_feature_scales(pixel, pixel_buffer, features, use_time, feature_means, pass_stride);
- math_vector_max(feature_scale, features, num_features);
- } END_FOR_PIXEL_WINDOW
-
- filter_calculate_scale(feature_scale, use_time);
-
- /* === Generate the feature transformation. ===
- * This transformation maps the num_features-dimentional feature space to a reduced feature (r-feature) space
- * which generally has fewer dimensions. This mainly helps to prevent overfitting. */
- float feature_matrix[DENOISE_FEATURES*DENOISE_FEATURES];
- math_matrix_zero(feature_matrix, num_features);
- FOR_PIXEL_WINDOW {
- filter_get_features(pixel, pixel_buffer, features, use_time, feature_means, pass_stride);
- math_vector_mul(features, feature_scale, num_features);
- math_matrix_add_gramian(feature_matrix, num_features, features, 1.0f);
- } END_FOR_PIXEL_WINDOW
-
- math_matrix_jacobi_eigendecomposition(feature_matrix, transform, num_features, 1);
- *rank = 0;
- /* Prevent overfitting when a small window is used. */
- int max_rank = min(num_features, num_pixels/3);
- if(pca_threshold < 0.0f) {
- float threshold_energy = 0.0f;
- for(int i = 0; i < num_features; i++) {
- threshold_energy += feature_matrix[i*num_features+i];
- }
- threshold_energy *= 1.0f - (-pca_threshold);
-
- float reduced_energy = 0.0f;
- for(int i = 0; i < max_rank; i++, (*rank)++) {
- if(i >= 2 && reduced_energy >= threshold_energy)
- break;
- float s = feature_matrix[i*num_features+i];
- reduced_energy += s;
- }
- }
- else {
- for(int i = 0; i < max_rank; i++, (*rank)++) {
- float s = feature_matrix[i*num_features+i];
- if(i >= 2 && sqrtf(s) < pca_threshold)
- break;
- }
- }
-
- /* Bake the feature scaling into the transformation matrix. */
- for(int i = 0; i < (*rank); i++) {
- math_vector_mul(transform + i*num_features, feature_scale, num_features);
- }
- math_matrix_transpose(transform, num_features, 1);
+ int buffer_w = align_up(rect.z - rect.x, 4);
+
+ float features[DENOISE_FEATURES];
+
+ const float *ccl_restrict pixel_buffer;
+ int3 pixel;
+
+ int num_features = use_time ? 11 : 10;
+
+ /* === Calculate denoising window. === */
+ int2 low = make_int2(max(rect.x, x - radius), max(rect.y, y - radius));
+ int2 high = make_int2(min(rect.z, x + radius + 1), min(rect.w, y + radius + 1));
+ int num_pixels = (high.y - low.y) * (high.x - low.x) * tile_info->num_frames;
+
+ /* === Shift feature passes to have mean 0. === */
+ float feature_means[DENOISE_FEATURES];
+ math_vector_zero(feature_means, num_features);
+ FOR_PIXEL_WINDOW
+ {
+ filter_get_features(pixel, pixel_buffer, features, use_time, NULL, pass_stride);
+ math_vector_add(feature_means, features, num_features);
+ }
+ END_FOR_PIXEL_WINDOW
+
+ math_vector_scale(feature_means, 1.0f / num_pixels, num_features);
+
+ /* === Scale the shifted feature passes to a range of [-1; 1], will be baked into the transform later. === */
+ float feature_scale[DENOISE_FEATURES];
+ math_vector_zero(feature_scale, num_features);
+
+ FOR_PIXEL_WINDOW
+ {
+ filter_get_feature_scales(pixel, pixel_buffer, features, use_time, feature_means, pass_stride);
+ math_vector_max(feature_scale, features, num_features);
+ }
+ END_FOR_PIXEL_WINDOW
+
+ filter_calculate_scale(feature_scale, use_time);
+
+ /* === Generate the feature transformation. ===
+ * This transformation maps the num_features-dimentional feature space to a reduced feature (r-feature) space
+ * which generally has fewer dimensions. This mainly helps to prevent overfitting. */
+ float feature_matrix[DENOISE_FEATURES * DENOISE_FEATURES];
+ math_matrix_zero(feature_matrix, num_features);
+ FOR_PIXEL_WINDOW
+ {
+ filter_get_features(pixel, pixel_buffer, features, use_time, feature_means, pass_stride);
+ math_vector_mul(features, feature_scale, num_features);
+ math_matrix_add_gramian(feature_matrix, num_features, features, 1.0f);
+ }
+ END_FOR_PIXEL_WINDOW
+
+ math_matrix_jacobi_eigendecomposition(feature_matrix, transform, num_features, 1);
+ *rank = 0;
+ /* Prevent overfitting when a small window is used. */
+ int max_rank = min(num_features, num_pixels / 3);
+ if (pca_threshold < 0.0f) {
+ float threshold_energy = 0.0f;
+ for (int i = 0; i < num_features; i++) {
+ threshold_energy += feature_matrix[i * num_features + i];
+ }
+ threshold_energy *= 1.0f - (-pca_threshold);
+
+ float reduced_energy = 0.0f;
+ for (int i = 0; i < max_rank; i++, (*rank)++) {
+ if (i >= 2 && reduced_energy >= threshold_energy)
+ break;
+ float s = feature_matrix[i * num_features + i];
+ reduced_energy += s;
+ }
+ }
+ else {
+ for (int i = 0; i < max_rank; i++, (*rank)++) {
+ float s = feature_matrix[i * num_features + i];
+ if (i >= 2 && sqrtf(s) < pca_threshold)
+ break;
+ }
+ }
+
+ /* Bake the feature scaling into the transformation matrix. */
+ for (int i = 0; i < (*rank); i++) {
+ math_vector_mul(transform + i * num_features, feature_scale, num_features);
+ }
+ math_matrix_transpose(transform, num_features, 1);
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/filter/filter_transform_gpu.h b/intern/cycles/kernel/filter/filter_transform_gpu.h
index ed8ddcb49b1..89cddfd927f 100644
--- a/intern/cycles/kernel/filter/filter_transform_gpu.h
+++ b/intern/cycles/kernel/filter/filter_transform_gpu.h
@@ -18,106 +18,110 @@ CCL_NAMESPACE_BEGIN
ccl_device void kernel_filter_construct_transform(const ccl_global float *ccl_restrict buffer,
CCL_FILTER_TILE_INFO,
- int x, int y, int4 rect,
- int pass_stride, int frame_stride,
+ int x,
+ int y,
+ int4 rect,
+ int pass_stride,
+ int frame_stride,
bool use_time,
ccl_global float *transform,
ccl_global int *rank,
- int radius, float pca_threshold,
- int transform_stride, int localIdx)
+ int radius,
+ float pca_threshold,
+ int transform_stride,
+ int localIdx)
{
- int buffer_w = align_up(rect.z - rect.x, 4);
+ int buffer_w = align_up(rect.z - rect.x, 4);
#ifdef __KERNEL_CUDA__
- ccl_local float shared_features[DENOISE_FEATURES*CCL_MAX_LOCAL_SIZE];
- ccl_local_param float *features = shared_features + localIdx*DENOISE_FEATURES;
+ ccl_local float shared_features[DENOISE_FEATURES * CCL_MAX_LOCAL_SIZE];
+ ccl_local_param float *features = shared_features + localIdx * DENOISE_FEATURES;
#else
- float features[DENOISE_FEATURES];
+ float features[DENOISE_FEATURES];
#endif
- int num_features = use_time? 11 : 10;
-
- /* === Calculate denoising window. === */
- int2 low = make_int2(max(rect.x, x - radius),
- max(rect.y, y - radius));
- int2 high = make_int2(min(rect.z, x + radius + 1),
- min(rect.w, y + radius + 1));
- int num_pixels = (high.y - low.y) * (high.x - low.x) * tile_info->num_frames;
- const ccl_global float *ccl_restrict pixel_buffer;
- int3 pixel;
-
-
-
-
- /* === Shift feature passes to have mean 0. === */
- float feature_means[DENOISE_FEATURES];
- math_vector_zero(feature_means, num_features);
- FOR_PIXEL_WINDOW {
- filter_get_features(pixel, pixel_buffer, features, use_time, NULL, pass_stride);
- math_vector_add(feature_means, features, num_features);
- } END_FOR_PIXEL_WINDOW
-
- math_vector_scale(feature_means, 1.0f / num_pixels, num_features);
-
- /* === Scale the shifted feature passes to a range of [-1; 1], will be baked into the transform later. === */
- float feature_scale[DENOISE_FEATURES];
- math_vector_zero(feature_scale, num_features);
-
- FOR_PIXEL_WINDOW {
- filter_get_feature_scales(pixel, pixel_buffer, features, use_time, feature_means, pass_stride);
- math_vector_max(feature_scale, features, num_features);
- } END_FOR_PIXEL_WINDOW
-
- filter_calculate_scale(feature_scale, use_time);
-
-
-
- /* === Generate the feature transformation. ===
- * This transformation maps the num_features-dimentional feature space to a reduced feature (r-feature) space
- * which generally has fewer dimensions. This mainly helps to prevent overfitting. */
- float feature_matrix[DENOISE_FEATURES*DENOISE_FEATURES];
- math_matrix_zero(feature_matrix, num_features);
- FOR_PIXEL_WINDOW {
- filter_get_features(pixel, pixel_buffer, features, use_time, feature_means, pass_stride);
- math_vector_mul(features, feature_scale, num_features);
- math_matrix_add_gramian(feature_matrix, num_features, features, 1.0f);
- } END_FOR_PIXEL_WINDOW
-
- math_matrix_jacobi_eigendecomposition(feature_matrix, transform, num_features, transform_stride);
- *rank = 0;
- /* Prevent overfitting when a small window is used. */
- int max_rank = min(num_features, num_pixels/3);
- if(pca_threshold < 0.0f) {
- float threshold_energy = 0.0f;
- for(int i = 0; i < num_features; i++) {
- threshold_energy += feature_matrix[i*num_features+i];
- }
- threshold_energy *= 1.0f - (-pca_threshold);
-
- float reduced_energy = 0.0f;
- for(int i = 0; i < max_rank; i++, (*rank)++) {
- if(i >= 2 && reduced_energy >= threshold_energy)
- break;
- float s = feature_matrix[i*num_features+i];
- reduced_energy += s;
- }
- }
- else {
- for(int i = 0; i < max_rank; i++, (*rank)++) {
- float s = feature_matrix[i*num_features+i];
- if(i >= 2 && sqrtf(s) < pca_threshold)
- break;
- }
- }
-
- math_matrix_transpose(transform, num_features, transform_stride);
-
- /* Bake the feature scaling into the transformation matrix. */
- for(int i = 0; i < num_features; i++) {
- for(int j = 0; j < (*rank); j++) {
- transform[(i*num_features + j)*transform_stride] *= feature_scale[i];
- }
- }
+ int num_features = use_time ? 11 : 10;
+
+ /* === Calculate denoising window. === */
+ int2 low = make_int2(max(rect.x, x - radius), max(rect.y, y - radius));
+ int2 high = make_int2(min(rect.z, x + radius + 1), min(rect.w, y + radius + 1));
+ int num_pixels = (high.y - low.y) * (high.x - low.x) * tile_info->num_frames;
+ const ccl_global float *ccl_restrict pixel_buffer;
+ int3 pixel;
+
+ /* === Shift feature passes to have mean 0. === */
+ float feature_means[DENOISE_FEATURES];
+ math_vector_zero(feature_means, num_features);
+ FOR_PIXEL_WINDOW
+ {
+ filter_get_features(pixel, pixel_buffer, features, use_time, NULL, pass_stride);
+ math_vector_add(feature_means, features, num_features);
+ }
+ END_FOR_PIXEL_WINDOW
+
+ math_vector_scale(feature_means, 1.0f / num_pixels, num_features);
+
+ /* === Scale the shifted feature passes to a range of [-1; 1], will be baked into the transform later. === */
+ float feature_scale[DENOISE_FEATURES];
+ math_vector_zero(feature_scale, num_features);
+
+ FOR_PIXEL_WINDOW
+ {
+ filter_get_feature_scales(pixel, pixel_buffer, features, use_time, feature_means, pass_stride);
+ math_vector_max(feature_scale, features, num_features);
+ }
+ END_FOR_PIXEL_WINDOW
+
+ filter_calculate_scale(feature_scale, use_time);
+
+ /* === Generate the feature transformation. ===
+ * This transformation maps the num_features-dimentional feature space to a reduced feature (r-feature) space
+ * which generally has fewer dimensions. This mainly helps to prevent overfitting. */
+ float feature_matrix[DENOISE_FEATURES * DENOISE_FEATURES];
+ math_matrix_zero(feature_matrix, num_features);
+ FOR_PIXEL_WINDOW
+ {
+ filter_get_features(pixel, pixel_buffer, features, use_time, feature_means, pass_stride);
+ math_vector_mul(features, feature_scale, num_features);
+ math_matrix_add_gramian(feature_matrix, num_features, features, 1.0f);
+ }
+ END_FOR_PIXEL_WINDOW
+
+ math_matrix_jacobi_eigendecomposition(feature_matrix, transform, num_features, transform_stride);
+ *rank = 0;
+ /* Prevent overfitting when a small window is used. */
+ int max_rank = min(num_features, num_pixels / 3);
+ if (pca_threshold < 0.0f) {
+ float threshold_energy = 0.0f;
+ for (int i = 0; i < num_features; i++) {
+ threshold_energy += feature_matrix[i * num_features + i];
+ }
+ threshold_energy *= 1.0f - (-pca_threshold);
+
+ float reduced_energy = 0.0f;
+ for (int i = 0; i < max_rank; i++, (*rank)++) {
+ if (i >= 2 && reduced_energy >= threshold_energy)
+ break;
+ float s = feature_matrix[i * num_features + i];
+ reduced_energy += s;
+ }
+ }
+ else {
+ for (int i = 0; i < max_rank; i++, (*rank)++) {
+ float s = feature_matrix[i * num_features + i];
+ if (i >= 2 && sqrtf(s) < pca_threshold)
+ break;
+ }
+ }
+
+ math_matrix_transpose(transform, num_features, transform_stride);
+
+ /* Bake the feature scaling into the transformation matrix. */
+ for (int i = 0; i < num_features; i++) {
+ for (int j = 0; j < (*rank); j++) {
+ transform[(i * num_features + j) * transform_stride] *= feature_scale[i];
+ }
+ }
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/filter/filter_transform_sse.h b/intern/cycles/kernel/filter/filter_transform_sse.h
index 10bd3e477e9..22397b292db 100644
--- a/intern/cycles/kernel/filter/filter_transform_sse.h
+++ b/intern/cycles/kernel/filter/filter_transform_sse.h
@@ -18,98 +18,110 @@ CCL_NAMESPACE_BEGIN
ccl_device void kernel_filter_construct_transform(const float *ccl_restrict buffer,
CCL_FILTER_TILE_INFO,
- int x, int y, int4 rect,
- int pass_stride, int frame_stride,
+ int x,
+ int y,
+ int4 rect,
+ int pass_stride,
+ int frame_stride,
bool use_time,
- float *transform, int *rank,
- int radius, float pca_threshold)
+ float *transform,
+ int *rank,
+ int radius,
+ float pca_threshold)
{
- int buffer_w = align_up(rect.z - rect.x, 4);
-
- float4 features[DENOISE_FEATURES];
- const float *ccl_restrict pixel_buffer;
- int3 pixel;
-
- int num_features = use_time? 11 : 10;
-
- /* === Calculate denoising window. === */
- int2 low = make_int2(max(rect.x, x - radius),
- max(rect.y, y - radius));
- int2 high = make_int2(min(rect.z, x + radius + 1),
- min(rect.w, y + radius + 1));
- int num_pixels = (high.y - low.y) * (high.x - low.x) * tile_info->num_frames;
-
- /* === Shift feature passes to have mean 0. === */
- float4 feature_means[DENOISE_FEATURES];
- math_vector_zero_sse(feature_means, num_features);
- FOR_PIXEL_WINDOW_SSE {
- filter_get_features_sse(x4, y4, t4, active_pixels, pixel_buffer, features, use_time, NULL, pass_stride);
- math_vector_add_sse(feature_means, num_features, features);
- } END_FOR_PIXEL_WINDOW_SSE
-
- float4 pixel_scale = make_float4(1.0f / num_pixels);
- for(int i = 0; i < num_features; i++) {
- feature_means[i] = reduce_add(feature_means[i]) * pixel_scale;
- }
-
- /* === Scale the shifted feature passes to a range of [-1; 1], will be baked into the transform later. === */
- float4 feature_scale[DENOISE_FEATURES];
- math_vector_zero_sse(feature_scale, num_features);
- FOR_PIXEL_WINDOW_SSE {
- filter_get_feature_scales_sse(x4, y4, t4, active_pixels, pixel_buffer, features, use_time, feature_means, pass_stride);
- math_vector_max_sse(feature_scale, features, num_features);
- } END_FOR_PIXEL_WINDOW_SSE
-
- filter_calculate_scale_sse(feature_scale, use_time);
-
- /* === Generate the feature transformation. ===
- * This transformation maps the num_features-dimentional feature space to a reduced feature (r-feature) space
- * which generally has fewer dimensions. This mainly helps to prevent overfitting. */
- float4 feature_matrix_sse[DENOISE_FEATURES*DENOISE_FEATURES];
- math_matrix_zero_sse(feature_matrix_sse, num_features);
- FOR_PIXEL_WINDOW_SSE {
- filter_get_features_sse(x4, y4, t4, active_pixels, pixel_buffer, features, use_time, feature_means, pass_stride);
- math_vector_mul_sse(features, num_features, feature_scale);
- math_matrix_add_gramian_sse(feature_matrix_sse, num_features, features, make_float4(1.0f));
- } END_FOR_PIXEL_WINDOW_SSE
-
- float feature_matrix[DENOISE_FEATURES*DENOISE_FEATURES];
- math_matrix_hsum(feature_matrix, num_features, feature_matrix_sse);
-
- math_matrix_jacobi_eigendecomposition(feature_matrix, transform, num_features, 1);
-
- *rank = 0;
- /* Prevent overfitting when a small window is used. */
- int max_rank = min(num_features, num_pixels/3);
- if(pca_threshold < 0.0f) {
- float threshold_energy = 0.0f;
- for(int i = 0; i < num_features; i++) {
- threshold_energy += feature_matrix[i*num_features+i];
- }
- threshold_energy *= 1.0f - (-pca_threshold);
-
- float reduced_energy = 0.0f;
- for(int i = 0; i < max_rank; i++, (*rank)++) {
- if(i >= 2 && reduced_energy >= threshold_energy)
- break;
- float s = feature_matrix[i*num_features+i];
- reduced_energy += s;
- }
- }
- else {
- for(int i = 0; i < max_rank; i++, (*rank)++) {
- float s = feature_matrix[i*num_features+i];
- if(i >= 2 && sqrtf(s) < pca_threshold)
- break;
- }
- }
-
- math_matrix_transpose(transform, num_features, 1);
-
- /* Bake the feature scaling into the transformation matrix. */
- for(int i = 0; i < num_features; i++) {
- math_vector_scale(transform + i*num_features, feature_scale[i][0], *rank);
- }
+ int buffer_w = align_up(rect.z - rect.x, 4);
+
+ float4 features[DENOISE_FEATURES];
+ const float *ccl_restrict pixel_buffer;
+ int3 pixel;
+
+ int num_features = use_time ? 11 : 10;
+
+ /* === Calculate denoising window. === */
+ int2 low = make_int2(max(rect.x, x - radius), max(rect.y, y - radius));
+ int2 high = make_int2(min(rect.z, x + radius + 1), min(rect.w, y + radius + 1));
+ int num_pixels = (high.y - low.y) * (high.x - low.x) * tile_info->num_frames;
+
+ /* === Shift feature passes to have mean 0. === */
+ float4 feature_means[DENOISE_FEATURES];
+ math_vector_zero_sse(feature_means, num_features);
+ FOR_PIXEL_WINDOW_SSE
+ {
+ filter_get_features_sse(
+ x4, y4, t4, active_pixels, pixel_buffer, features, use_time, NULL, pass_stride);
+ math_vector_add_sse(feature_means, num_features, features);
+ }
+ END_FOR_PIXEL_WINDOW_SSE
+
+ float4 pixel_scale = make_float4(1.0f / num_pixels);
+ for (int i = 0; i < num_features; i++) {
+ feature_means[i] = reduce_add(feature_means[i]) * pixel_scale;
+ }
+
+ /* === Scale the shifted feature passes to a range of [-1; 1], will be baked into the transform later. === */
+ float4 feature_scale[DENOISE_FEATURES];
+ math_vector_zero_sse(feature_scale, num_features);
+ FOR_PIXEL_WINDOW_SSE
+ {
+ filter_get_feature_scales_sse(
+ x4, y4, t4, active_pixels, pixel_buffer, features, use_time, feature_means, pass_stride);
+ math_vector_max_sse(feature_scale, features, num_features);
+ }
+ END_FOR_PIXEL_WINDOW_SSE
+
+ filter_calculate_scale_sse(feature_scale, use_time);
+
+ /* === Generate the feature transformation. ===
+ * This transformation maps the num_features-dimentional feature space to a reduced feature (r-feature) space
+ * which generally has fewer dimensions. This mainly helps to prevent overfitting. */
+ float4 feature_matrix_sse[DENOISE_FEATURES * DENOISE_FEATURES];
+ math_matrix_zero_sse(feature_matrix_sse, num_features);
+ FOR_PIXEL_WINDOW_SSE
+ {
+ filter_get_features_sse(
+ x4, y4, t4, active_pixels, pixel_buffer, features, use_time, feature_means, pass_stride);
+ math_vector_mul_sse(features, num_features, feature_scale);
+ math_matrix_add_gramian_sse(feature_matrix_sse, num_features, features, make_float4(1.0f));
+ }
+ END_FOR_PIXEL_WINDOW_SSE
+
+ float feature_matrix[DENOISE_FEATURES * DENOISE_FEATURES];
+ math_matrix_hsum(feature_matrix, num_features, feature_matrix_sse);
+
+ math_matrix_jacobi_eigendecomposition(feature_matrix, transform, num_features, 1);
+
+ *rank = 0;
+ /* Prevent overfitting when a small window is used. */
+ int max_rank = min(num_features, num_pixels / 3);
+ if (pca_threshold < 0.0f) {
+ float threshold_energy = 0.0f;
+ for (int i = 0; i < num_features; i++) {
+ threshold_energy += feature_matrix[i * num_features + i];
+ }
+ threshold_energy *= 1.0f - (-pca_threshold);
+
+ float reduced_energy = 0.0f;
+ for (int i = 0; i < max_rank; i++, (*rank)++) {
+ if (i >= 2 && reduced_energy >= threshold_energy)
+ break;
+ float s = feature_matrix[i * num_features + i];
+ reduced_energy += s;
+ }
+ }
+ else {
+ for (int i = 0; i < max_rank; i++, (*rank)++) {
+ float s = feature_matrix[i * num_features + i];
+ if (i >= 2 && sqrtf(s) < pca_threshold)
+ break;
+ }
+ }
+
+ math_matrix_transpose(transform, num_features, 1);
+
+ /* Bake the feature scaling into the transformation matrix. */
+ for (int i = 0; i < num_features; i++) {
+ math_vector_scale(transform + i * num_features, feature_scale[i][0], *rank);
+ }
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/geom/geom_attribute.h b/intern/cycles/kernel/geom/geom_attribute.h
index e991f3d685a..456608bfa22 100644
--- a/intern/cycles/kernel/geom/geom_attribute.h
+++ b/intern/cycles/kernel/geom/geom_attribute.h
@@ -30,81 +30,83 @@ ccl_device_inline uint subd_triangle_patch(KernelGlobals *kg, const ShaderData *
ccl_device_inline uint attribute_primitive_type(KernelGlobals *kg, const ShaderData *sd)
{
#ifdef __HAIR__
- if(sd->type & PRIMITIVE_ALL_CURVE) {
- return ATTR_PRIM_CURVE;
- }
- else
+ if (sd->type & PRIMITIVE_ALL_CURVE) {
+ return ATTR_PRIM_CURVE;
+ }
+ else
#endif
- if(subd_triangle_patch(kg, sd) != ~0) {
- return ATTR_PRIM_SUBD;
- }
- else {
- return ATTR_PRIM_TRIANGLE;
- }
+ if (subd_triangle_patch(kg, sd) != ~0) {
+ return ATTR_PRIM_SUBD;
+ }
+ else {
+ return ATTR_PRIM_TRIANGLE;
+ }
}
ccl_device_inline AttributeDescriptor attribute_not_found()
{
- const AttributeDescriptor desc = {ATTR_ELEMENT_NONE, (NodeAttributeType)0, 0, ATTR_STD_NOT_FOUND};
- return desc;
+ const AttributeDescriptor desc = {
+ ATTR_ELEMENT_NONE, (NodeAttributeType)0, 0, ATTR_STD_NOT_FOUND};
+ return desc;
}
/* Find attribute based on ID */
ccl_device_inline uint object_attribute_map_offset(KernelGlobals *kg, int object)
{
- return kernel_tex_fetch(__objects, object).attribute_map_offset;
+ return kernel_tex_fetch(__objects, object).attribute_map_offset;
}
-ccl_device_inline AttributeDescriptor find_attribute(KernelGlobals *kg, const ShaderData *sd, uint id)
+ccl_device_inline AttributeDescriptor find_attribute(KernelGlobals *kg,
+ const ShaderData *sd,
+ uint id)
{
- if(sd->object == OBJECT_NONE) {
- return attribute_not_found();
- }
-
- /* for SVM, find attribute by unique id */
- uint attr_offset = object_attribute_map_offset(kg, sd->object);
- attr_offset += attribute_primitive_type(kg, sd);
- uint4 attr_map = kernel_tex_fetch(__attributes_map, attr_offset);
-
- while(attr_map.x != id) {
- if(UNLIKELY(attr_map.x == ATTR_STD_NONE)) {
- return attribute_not_found();
- }
- attr_offset += ATTR_PRIM_TYPES;
- attr_map = kernel_tex_fetch(__attributes_map, attr_offset);
- }
-
- AttributeDescriptor desc;
- desc.element = (AttributeElement)attr_map.y;
-
- if(sd->prim == PRIM_NONE &&
- desc.element != ATTR_ELEMENT_MESH &&
- desc.element != ATTR_ELEMENT_VOXEL &&
- desc.element != ATTR_ELEMENT_OBJECT)
- {
- return attribute_not_found();
- }
-
- /* return result */
- desc.offset = (attr_map.y == ATTR_ELEMENT_NONE) ? (int)ATTR_STD_NOT_FOUND : (int)attr_map.z;
- desc.type = (NodeAttributeType)(attr_map.w & 0xff);
- desc.flags = (AttributeFlag)(attr_map.w >> 8);
-
- return desc;
+ if (sd->object == OBJECT_NONE) {
+ return attribute_not_found();
+ }
+
+ /* for SVM, find attribute by unique id */
+ uint attr_offset = object_attribute_map_offset(kg, sd->object);
+ attr_offset += attribute_primitive_type(kg, sd);
+ uint4 attr_map = kernel_tex_fetch(__attributes_map, attr_offset);
+
+ while (attr_map.x != id) {
+ if (UNLIKELY(attr_map.x == ATTR_STD_NONE)) {
+ return attribute_not_found();
+ }
+ attr_offset += ATTR_PRIM_TYPES;
+ attr_map = kernel_tex_fetch(__attributes_map, attr_offset);
+ }
+
+ AttributeDescriptor desc;
+ desc.element = (AttributeElement)attr_map.y;
+
+ if (sd->prim == PRIM_NONE && desc.element != ATTR_ELEMENT_MESH &&
+ desc.element != ATTR_ELEMENT_VOXEL && desc.element != ATTR_ELEMENT_OBJECT) {
+ return attribute_not_found();
+ }
+
+ /* return result */
+ desc.offset = (attr_map.y == ATTR_ELEMENT_NONE) ? (int)ATTR_STD_NOT_FOUND : (int)attr_map.z;
+ desc.type = (NodeAttributeType)(attr_map.w & 0xff);
+ desc.flags = (AttributeFlag)(attr_map.w >> 8);
+
+ return desc;
}
/* Transform matrix attribute on meshes */
-ccl_device Transform primitive_attribute_matrix(KernelGlobals *kg, const ShaderData *sd, const AttributeDescriptor desc)
+ccl_device Transform primitive_attribute_matrix(KernelGlobals *kg,
+ const ShaderData *sd,
+ const AttributeDescriptor desc)
{
- Transform tfm;
+ Transform tfm;
- tfm.x = kernel_tex_fetch(__attributes_float3, desc.offset + 0);
- tfm.y = kernel_tex_fetch(__attributes_float3, desc.offset + 1);
- tfm.z = kernel_tex_fetch(__attributes_float3, desc.offset + 2);
+ tfm.x = kernel_tex_fetch(__attributes_float3, desc.offset + 0);
+ tfm.y = kernel_tex_fetch(__attributes_float3, desc.offset + 1);
+ tfm.z = kernel_tex_fetch(__attributes_float3, desc.offset + 2);
- return tfm;
+ return tfm;
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/geom/geom_curve.h b/intern/cycles/kernel/geom/geom_curve.h
index 9b60cf6d56b..e0aacb434eb 100644
--- a/intern/cycles/kernel/geom/geom_curve.h
+++ b/intern/cycles/kernel/geom/geom_curve.h
@@ -27,169 +27,199 @@ CCL_NAMESPACE_BEGIN
ccl_device_inline float3 curvetangent(float t, float3 p0, float3 p1, float3 p2, float3 p3)
{
- float fc = 0.71f;
- float data[4];
- float t2 = t * t;
- data[0] = -3.0f * fc * t2 + 4.0f * fc * t - fc;
- data[1] = 3.0f * (2.0f - fc) * t2 + 2.0f * (fc - 3.0f) * t;
- data[2] = 3.0f * (fc - 2.0f) * t2 + 2.0f * (3.0f - 2.0f * fc) * t + fc;
- data[3] = 3.0f * fc * t2 - 2.0f * fc * t;
- return data[0] * p0 + data[1] * p1 + data[2] * p2 + data[3] * p3;
+ float fc = 0.71f;
+ float data[4];
+ float t2 = t * t;
+ data[0] = -3.0f * fc * t2 + 4.0f * fc * t - fc;
+ data[1] = 3.0f * (2.0f - fc) * t2 + 2.0f * (fc - 3.0f) * t;
+ data[2] = 3.0f * (fc - 2.0f) * t2 + 2.0f * (3.0f - 2.0f * fc) * t + fc;
+ data[3] = 3.0f * fc * t2 - 2.0f * fc * t;
+ return data[0] * p0 + data[1] * p1 + data[2] * p2 + data[3] * p3;
}
ccl_device_inline float3 curvepoint(float t, float3 p0, float3 p1, float3 p2, float3 p3)
{
- float data[4];
- float fc = 0.71f;
- float t2 = t * t;
- float t3 = t2 * t;
- data[0] = -fc * t3 + 2.0f * fc * t2 - fc * t;
- data[1] = (2.0f - fc) * t3 + (fc - 3.0f) * t2 + 1.0f;
- data[2] = (fc - 2.0f) * t3 + (3.0f - 2.0f * fc) * t2 + fc * t;
- data[3] = fc * t3 - fc * t2;
- return data[0] * p0 + data[1] * p1 + data[2] * p2 + data[3] * p3;
+ float data[4];
+ float fc = 0.71f;
+ float t2 = t * t;
+ float t3 = t2 * t;
+ data[0] = -fc * t3 + 2.0f * fc * t2 - fc * t;
+ data[1] = (2.0f - fc) * t3 + (fc - 3.0f) * t2 + 1.0f;
+ data[2] = (fc - 2.0f) * t3 + (3.0f - 2.0f * fc) * t2 + fc * t;
+ data[3] = fc * t3 - fc * t2;
+ return data[0] * p0 + data[1] * p1 + data[2] * p2 + data[3] * p3;
}
/* Reading attributes on various curve elements */
-ccl_device float curve_attribute_float(KernelGlobals *kg, const ShaderData *sd, const AttributeDescriptor desc, float *dx, float *dy)
+ccl_device float curve_attribute_float(
+ KernelGlobals *kg, const ShaderData *sd, const AttributeDescriptor desc, float *dx, float *dy)
{
- if(desc.element == ATTR_ELEMENT_CURVE) {
-#ifdef __RAY_DIFFERENTIALS__
- if(dx) *dx = 0.0f;
- if(dy) *dy = 0.0f;
-#endif
-
- return kernel_tex_fetch(__attributes_float, desc.offset + sd->prim);
- }
- else if(desc.element == ATTR_ELEMENT_CURVE_KEY || desc.element == ATTR_ELEMENT_CURVE_KEY_MOTION) {
- float4 curvedata = kernel_tex_fetch(__curves, sd->prim);
- int k0 = __float_as_int(curvedata.x) + PRIMITIVE_UNPACK_SEGMENT(sd->type);
- int k1 = k0 + 1;
-
- float f0 = kernel_tex_fetch(__attributes_float, desc.offset + k0);
- float f1 = kernel_tex_fetch(__attributes_float, desc.offset + k1);
-
-#ifdef __RAY_DIFFERENTIALS__
- if(dx) *dx = sd->du.dx*(f1 - f0);
- if(dy) *dy = 0.0f;
-#endif
-
- return (1.0f - sd->u)*f0 + sd->u*f1;
- }
- else {
-#ifdef __RAY_DIFFERENTIALS__
- if(dx) *dx = 0.0f;
- if(dy) *dy = 0.0f;
-#endif
-
- return 0.0f;
- }
+ if (desc.element == ATTR_ELEMENT_CURVE) {
+# ifdef __RAY_DIFFERENTIALS__
+ if (dx)
+ *dx = 0.0f;
+ if (dy)
+ *dy = 0.0f;
+# endif
+
+ return kernel_tex_fetch(__attributes_float, desc.offset + sd->prim);
+ }
+ else if (desc.element == ATTR_ELEMENT_CURVE_KEY ||
+ desc.element == ATTR_ELEMENT_CURVE_KEY_MOTION) {
+ float4 curvedata = kernel_tex_fetch(__curves, sd->prim);
+ int k0 = __float_as_int(curvedata.x) + PRIMITIVE_UNPACK_SEGMENT(sd->type);
+ int k1 = k0 + 1;
+
+ float f0 = kernel_tex_fetch(__attributes_float, desc.offset + k0);
+ float f1 = kernel_tex_fetch(__attributes_float, desc.offset + k1);
+
+# ifdef __RAY_DIFFERENTIALS__
+ if (dx)
+ *dx = sd->du.dx * (f1 - f0);
+ if (dy)
+ *dy = 0.0f;
+# endif
+
+ return (1.0f - sd->u) * f0 + sd->u * f1;
+ }
+ else {
+# ifdef __RAY_DIFFERENTIALS__
+ if (dx)
+ *dx = 0.0f;
+ if (dy)
+ *dy = 0.0f;
+# endif
+
+ return 0.0f;
+ }
}
-ccl_device float2 curve_attribute_float2(KernelGlobals *kg, const ShaderData *sd, const AttributeDescriptor desc, float2 *dx, float2 *dy)
+ccl_device float2 curve_attribute_float2(KernelGlobals *kg,
+ const ShaderData *sd,
+ const AttributeDescriptor desc,
+ float2 *dx,
+ float2 *dy)
{
- if(desc.element == ATTR_ELEMENT_CURVE) {
- /* idea: we can't derive any useful differentials here, but for tiled
- * mipmap image caching it would be useful to avoid reading the highest
- * detail level always. maybe a derivative based on the hair density
- * could be computed somehow? */
-#ifdef __RAY_DIFFERENTIALS__
- if(dx) *dx = make_float2(0.0f, 0.0f);
- if(dy) *dy = make_float2(0.0f, 0.0f);
-#endif
-
- return kernel_tex_fetch(__attributes_float2, desc.offset + sd->prim);
- }
- else if(desc.element == ATTR_ELEMENT_CURVE_KEY || desc.element == ATTR_ELEMENT_CURVE_KEY_MOTION) {
- float4 curvedata = kernel_tex_fetch(__curves, sd->prim);
- int k0 = __float_as_int(curvedata.x) + PRIMITIVE_UNPACK_SEGMENT(sd->type);
- int k1 = k0 + 1;
-
- float2 f0 = kernel_tex_fetch(__attributes_float2, desc.offset + k0);
- float2 f1 = kernel_tex_fetch(__attributes_float2, desc.offset + k1);
-
-#ifdef __RAY_DIFFERENTIALS__
- if(dx) *dx = sd->du.dx*(f1 - f0);
- if(dy) *dy = make_float2(0.0f, 0.0f);
-#endif
-
- return (1.0f - sd->u)*f0 + sd->u*f1;
- }
- else {
-#ifdef __RAY_DIFFERENTIALS__
- if(dx) *dx = make_float2(0.0f, 0.0f);
- if(dy) *dy = make_float2(0.0f, 0.0f);
-#endif
-
- return make_float2(0.0f, 0.0f);
- }
+ if (desc.element == ATTR_ELEMENT_CURVE) {
+ /* idea: we can't derive any useful differentials here, but for tiled
+ * mipmap image caching it would be useful to avoid reading the highest
+ * detail level always. maybe a derivative based on the hair density
+ * could be computed somehow? */
+# ifdef __RAY_DIFFERENTIALS__
+ if (dx)
+ *dx = make_float2(0.0f, 0.0f);
+ if (dy)
+ *dy = make_float2(0.0f, 0.0f);
+# endif
+
+ return kernel_tex_fetch(__attributes_float2, desc.offset + sd->prim);
+ }
+ else if (desc.element == ATTR_ELEMENT_CURVE_KEY ||
+ desc.element == ATTR_ELEMENT_CURVE_KEY_MOTION) {
+ float4 curvedata = kernel_tex_fetch(__curves, sd->prim);
+ int k0 = __float_as_int(curvedata.x) + PRIMITIVE_UNPACK_SEGMENT(sd->type);
+ int k1 = k0 + 1;
+
+ float2 f0 = kernel_tex_fetch(__attributes_float2, desc.offset + k0);
+ float2 f1 = kernel_tex_fetch(__attributes_float2, desc.offset + k1);
+
+# ifdef __RAY_DIFFERENTIALS__
+ if (dx)
+ *dx = sd->du.dx * (f1 - f0);
+ if (dy)
+ *dy = make_float2(0.0f, 0.0f);
+# endif
+
+ return (1.0f - sd->u) * f0 + sd->u * f1;
+ }
+ else {
+# ifdef __RAY_DIFFERENTIALS__
+ if (dx)
+ *dx = make_float2(0.0f, 0.0f);
+ if (dy)
+ *dy = make_float2(0.0f, 0.0f);
+# endif
+
+ return make_float2(0.0f, 0.0f);
+ }
}
-ccl_device float3 curve_attribute_float3(KernelGlobals *kg, const ShaderData *sd, const AttributeDescriptor desc, float3 *dx, float3 *dy)
+ccl_device float3 curve_attribute_float3(KernelGlobals *kg,
+ const ShaderData *sd,
+ const AttributeDescriptor desc,
+ float3 *dx,
+ float3 *dy)
{
- if(desc.element == ATTR_ELEMENT_CURVE) {
- /* idea: we can't derive any useful differentials here, but for tiled
- * mipmap image caching it would be useful to avoid reading the highest
- * detail level always. maybe a derivative based on the hair density
- * could be computed somehow? */
-#ifdef __RAY_DIFFERENTIALS__
- if(dx) *dx = make_float3(0.0f, 0.0f, 0.0f);
- if(dy) *dy = make_float3(0.0f, 0.0f, 0.0f);
-#endif
-
- return float4_to_float3(kernel_tex_fetch(__attributes_float3, desc.offset + sd->prim));
- }
- else if(desc.element == ATTR_ELEMENT_CURVE_KEY || desc.element == ATTR_ELEMENT_CURVE_KEY_MOTION) {
- float4 curvedata = kernel_tex_fetch(__curves, sd->prim);
- int k0 = __float_as_int(curvedata.x) + PRIMITIVE_UNPACK_SEGMENT(sd->type);
- int k1 = k0 + 1;
-
- float3 f0 = float4_to_float3(kernel_tex_fetch(__attributes_float3, desc.offset + k0));
- float3 f1 = float4_to_float3(kernel_tex_fetch(__attributes_float3, desc.offset + k1));
-
-#ifdef __RAY_DIFFERENTIALS__
- if(dx) *dx = sd->du.dx*(f1 - f0);
- if(dy) *dy = make_float3(0.0f, 0.0f, 0.0f);
-#endif
-
- return (1.0f - sd->u)*f0 + sd->u*f1;
- }
- else {
-#ifdef __RAY_DIFFERENTIALS__
- if(dx) *dx = make_float3(0.0f, 0.0f, 0.0f);
- if(dy) *dy = make_float3(0.0f, 0.0f, 0.0f);
-#endif
-
- return make_float3(0.0f, 0.0f, 0.0f);
- }
+ if (desc.element == ATTR_ELEMENT_CURVE) {
+ /* idea: we can't derive any useful differentials here, but for tiled
+ * mipmap image caching it would be useful to avoid reading the highest
+ * detail level always. maybe a derivative based on the hair density
+ * could be computed somehow? */
+# ifdef __RAY_DIFFERENTIALS__
+ if (dx)
+ *dx = make_float3(0.0f, 0.0f, 0.0f);
+ if (dy)
+ *dy = make_float3(0.0f, 0.0f, 0.0f);
+# endif
+
+ return float4_to_float3(kernel_tex_fetch(__attributes_float3, desc.offset + sd->prim));
+ }
+ else if (desc.element == ATTR_ELEMENT_CURVE_KEY ||
+ desc.element == ATTR_ELEMENT_CURVE_KEY_MOTION) {
+ float4 curvedata = kernel_tex_fetch(__curves, sd->prim);
+ int k0 = __float_as_int(curvedata.x) + PRIMITIVE_UNPACK_SEGMENT(sd->type);
+ int k1 = k0 + 1;
+
+ float3 f0 = float4_to_float3(kernel_tex_fetch(__attributes_float3, desc.offset + k0));
+ float3 f1 = float4_to_float3(kernel_tex_fetch(__attributes_float3, desc.offset + k1));
+
+# ifdef __RAY_DIFFERENTIALS__
+ if (dx)
+ *dx = sd->du.dx * (f1 - f0);
+ if (dy)
+ *dy = make_float3(0.0f, 0.0f, 0.0f);
+# endif
+
+ return (1.0f - sd->u) * f0 + sd->u * f1;
+ }
+ else {
+# ifdef __RAY_DIFFERENTIALS__
+ if (dx)
+ *dx = make_float3(0.0f, 0.0f, 0.0f);
+ if (dy)
+ *dy = make_float3(0.0f, 0.0f, 0.0f);
+# endif
+
+ return make_float3(0.0f, 0.0f, 0.0f);
+ }
}
/* Curve thickness */
ccl_device float curve_thickness(KernelGlobals *kg, ShaderData *sd)
{
- float r = 0.0f;
+ float r = 0.0f;
- if(sd->type & PRIMITIVE_ALL_CURVE) {
- float4 curvedata = kernel_tex_fetch(__curves, sd->prim);
- int k0 = __float_as_int(curvedata.x) + PRIMITIVE_UNPACK_SEGMENT(sd->type);
- int k1 = k0 + 1;
+ if (sd->type & PRIMITIVE_ALL_CURVE) {
+ float4 curvedata = kernel_tex_fetch(__curves, sd->prim);
+ int k0 = __float_as_int(curvedata.x) + PRIMITIVE_UNPACK_SEGMENT(sd->type);
+ int k1 = k0 + 1;
- float4 P_curve[2];
+ float4 P_curve[2];
- if(sd->type & PRIMITIVE_CURVE) {
- P_curve[0]= kernel_tex_fetch(__curve_keys, k0);
- P_curve[1]= kernel_tex_fetch(__curve_keys, k1);
- }
- else {
- motion_curve_keys(kg, sd->object, sd->prim, sd->time, k0, k1, P_curve);
- }
+ if (sd->type & PRIMITIVE_CURVE) {
+ P_curve[0] = kernel_tex_fetch(__curve_keys, k0);
+ P_curve[1] = kernel_tex_fetch(__curve_keys, k1);
+ }
+ else {
+ motion_curve_keys(kg, sd->object, sd->prim, sd->time, k0, k1, P_curve);
+ }
- r = (P_curve[1].w - P_curve[0].w) * sd->u + P_curve[0].w;
- }
+ r = (P_curve[1].w - P_curve[0].w) * sd->u + P_curve[0].w;
+ }
- return r*2.0f;
+ return r * 2.0f;
}
/* Curve location for motion pass, linear interpolation between keys and
@@ -197,89 +227,98 @@ ccl_device float curve_thickness(KernelGlobals *kg, ShaderData *sd)
ccl_device float3 curve_motion_center_location(KernelGlobals *kg, ShaderData *sd)
{
- float4 curvedata = kernel_tex_fetch(__curves, sd->prim);
- int k0 = __float_as_int(curvedata.x) + PRIMITIVE_UNPACK_SEGMENT(sd->type);
- int k1 = k0 + 1;
+ float4 curvedata = kernel_tex_fetch(__curves, sd->prim);
+ int k0 = __float_as_int(curvedata.x) + PRIMITIVE_UNPACK_SEGMENT(sd->type);
+ int k1 = k0 + 1;
- float4 P_curve[2];
+ float4 P_curve[2];
- P_curve[0]= kernel_tex_fetch(__curve_keys, k0);
- P_curve[1]= kernel_tex_fetch(__curve_keys, k1);
+ P_curve[0] = kernel_tex_fetch(__curve_keys, k0);
+ P_curve[1] = kernel_tex_fetch(__curve_keys, k1);
- return float4_to_float3(P_curve[1]) * sd->u + float4_to_float3(P_curve[0]) * (1.0f - sd->u);
+ return float4_to_float3(P_curve[1]) * sd->u + float4_to_float3(P_curve[0]) * (1.0f - sd->u);
}
/* Curve tangent normal */
ccl_device float3 curve_tangent_normal(KernelGlobals *kg, ShaderData *sd)
{
- float3 tgN = make_float3(0.0f,0.0f,0.0f);
+ float3 tgN = make_float3(0.0f, 0.0f, 0.0f);
- if(sd->type & PRIMITIVE_ALL_CURVE) {
+ if (sd->type & PRIMITIVE_ALL_CURVE) {
- tgN = -(-sd->I - sd->dPdu * (dot(sd->dPdu,-sd->I) / len_squared(sd->dPdu)));
- tgN = normalize(tgN);
+ tgN = -(-sd->I - sd->dPdu * (dot(sd->dPdu, -sd->I) / len_squared(sd->dPdu)));
+ tgN = normalize(tgN);
- /* need to find suitable scaled gd for corrected normal */
-#if 0
- tgN = normalize(tgN - gd * sd->dPdu);
-#endif
- }
+ /* need to find suitable scaled gd for corrected normal */
+# if 0
+ tgN = normalize(tgN - gd * sd->dPdu);
+# endif
+ }
- return tgN;
+ return tgN;
}
/* Curve bounds utility function */
-ccl_device_inline void curvebounds(float *lower, float *upper, float *extremta, float *extrema, float *extremtb, float *extremb, float p0, float p1, float p2, float p3)
+ccl_device_inline void curvebounds(float *lower,
+ float *upper,
+ float *extremta,
+ float *extrema,
+ float *extremtb,
+ float *extremb,
+ float p0,
+ float p1,
+ float p2,
+ float p3)
{
- float halfdiscroot = (p2 * p2 - 3 * p3 * p1);
- float ta = -1.0f;
- float tb = -1.0f;
-
- *extremta = -1.0f;
- *extremtb = -1.0f;
- *upper = p0;
- *lower = (p0 + p1) + (p2 + p3);
- *extrema = *upper;
- *extremb = *lower;
-
- if(*lower >= *upper) {
- *upper = *lower;
- *lower = p0;
- }
-
- if(halfdiscroot >= 0) {
- float inv3p3 = (1.0f/3.0f)/p3;
- halfdiscroot = sqrtf(halfdiscroot);
- ta = (-p2 - halfdiscroot) * inv3p3;
- tb = (-p2 + halfdiscroot) * inv3p3;
- }
-
- float t2;
- float t3;
-
- if(ta > 0.0f && ta < 1.0f) {
- t2 = ta * ta;
- t3 = t2 * ta;
- *extremta = ta;
- *extrema = p3 * t3 + p2 * t2 + p1 * ta + p0;
-
- *upper = fmaxf(*extrema, *upper);
- *lower = fminf(*extrema, *lower);
- }
-
- if(tb > 0.0f && tb < 1.0f) {
- t2 = tb * tb;
- t3 = t2 * tb;
- *extremtb = tb;
- *extremb = p3 * t3 + p2 * t2 + p1 * tb + p0;
-
- *upper = fmaxf(*extremb, *upper);
- *lower = fminf(*extremb, *lower);
- }
+ float halfdiscroot = (p2 * p2 - 3 * p3 * p1);
+ float ta = -1.0f;
+ float tb = -1.0f;
+
+ *extremta = -1.0f;
+ *extremtb = -1.0f;
+ *upper = p0;
+ *lower = (p0 + p1) + (p2 + p3);
+ *extrema = *upper;
+ *extremb = *lower;
+
+ if (*lower >= *upper) {
+ *upper = *lower;
+ *lower = p0;
+ }
+
+ if (halfdiscroot >= 0) {
+ float inv3p3 = (1.0f / 3.0f) / p3;
+ halfdiscroot = sqrtf(halfdiscroot);
+ ta = (-p2 - halfdiscroot) * inv3p3;
+ tb = (-p2 + halfdiscroot) * inv3p3;
+ }
+
+ float t2;
+ float t3;
+
+ if (ta > 0.0f && ta < 1.0f) {
+ t2 = ta * ta;
+ t3 = t2 * ta;
+ *extremta = ta;
+ *extrema = p3 * t3 + p2 * t2 + p1 * ta + p0;
+
+ *upper = fmaxf(*extrema, *upper);
+ *lower = fminf(*extrema, *lower);
+ }
+
+ if (tb > 0.0f && tb < 1.0f) {
+ t2 = tb * tb;
+ t3 = t2 * tb;
+ *extremtb = tb;
+ *extremb = p3 * t3 + p2 * t2 + p1 * tb + p0;
+
+ *upper = fmaxf(*extremb, *upper);
+ *lower = fminf(*extremb, *lower);
+ }
}
-#endif /* __HAIR__ */
+#endif /* __HAIR__ */
CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/geom/geom_curve_intersect.h b/intern/cycles/kernel/geom/geom_curve_intersect.h
index 5cf8713e3a8..5fd277c2f99 100644
--- a/intern/cycles/kernel/geom/geom_curve_intersect.h
+++ b/intern/cycles/kernel/geom/geom_curve_intersect.h
@@ -18,484 +18,534 @@ CCL_NAMESPACE_BEGIN
#ifdef __HAIR__
-#ifdef __KERNEL_SSE2__
+# ifdef __KERNEL_SSE2__
ccl_device_inline ssef transform_point_T3(const ssef t[3], const ssef &a)
{
- return madd(shuffle<0>(a), t[0], madd(shuffle<1>(a), t[1], shuffle<2>(a) * t[2]));
+ return madd(shuffle<0>(a), t[0], madd(shuffle<1>(a), t[1], shuffle<2>(a) * t[2]));
}
-#endif
+# endif
/* On CPU pass P and dir by reference to aligned vector. */
-ccl_device_forceinline bool cardinal_curve_intersect(
- KernelGlobals *kg,
- Intersection *isect,
- const float3 ccl_ref P,
- const float3 ccl_ref dir,
- uint visibility,
- int object,
- int curveAddr,
- float time,
- int type,
- uint *lcg_state,
- float difl,
- float extmax)
+ccl_device_forceinline bool cardinal_curve_intersect(KernelGlobals *kg,
+ Intersection *isect,
+ const float3 ccl_ref P,
+ const float3 ccl_ref dir,
+ uint visibility,
+ int object,
+ int curveAddr,
+ float time,
+ int type,
+ uint *lcg_state,
+ float difl,
+ float extmax)
{
- const bool is_curve_primitive = (type & PRIMITIVE_CURVE);
-
- if(!is_curve_primitive && kernel_data.bvh.use_bvh_steps) {
- const float2 prim_time = kernel_tex_fetch(__prim_time, curveAddr);
- if(time < prim_time.x || time > prim_time.y) {
- return false;
- }
- }
-
- int segment = PRIMITIVE_UNPACK_SEGMENT(type);
- float epsilon = 0.0f;
- float r_st, r_en;
-
- int depth = kernel_data.curve.subdivisions;
- int flags = kernel_data.curve.curveflags;
- int prim = kernel_tex_fetch(__prim_index, curveAddr);
-
-#ifdef __KERNEL_SSE2__
- ssef vdir = load4f(dir);
- ssef vcurve_coef[4];
- const float3 *curve_coef = (float3 *)vcurve_coef;
-
- {
- ssef dtmp = vdir * vdir;
- ssef d_ss = mm_sqrt(dtmp + shuffle<2>(dtmp));
- ssef rd_ss = load1f_first(1.0f) / d_ss;
-
- ssei v00vec = load4i((ssei *)&kg->__curves.data[prim]);
- int2 &v00 = (int2 &)v00vec;
-
- int k0 = v00.x + segment;
- int k1 = k0 + 1;
- int ka = max(k0 - 1, v00.x);
- int kb = min(k1 + 1, v00.x + v00.y - 1);
-
-#if defined(__KERNEL_AVX2__) && defined(__KERNEL_SSE__) && (!defined(_MSC_VER) || _MSC_VER > 1800)
- avxf P_curve_0_1, P_curve_2_3;
- if(is_curve_primitive) {
- P_curve_0_1 = _mm256_loadu2_m128(&kg->__curve_keys.data[k0].x, &kg->__curve_keys.data[ka].x);
- P_curve_2_3 = _mm256_loadu2_m128(&kg->__curve_keys.data[kb].x, &kg->__curve_keys.data[k1].x);
- }
- else {
- int fobject = (object == OBJECT_NONE) ? kernel_tex_fetch(__prim_object, curveAddr) : object;
- motion_cardinal_curve_keys_avx(kg, fobject, prim, time, ka, k0, k1, kb, &P_curve_0_1,&P_curve_2_3);
- }
-#else /* __KERNEL_AVX2__ */
- ssef P_curve[4];
-
- if(is_curve_primitive) {
- P_curve[0] = load4f(&kg->__curve_keys.data[ka].x);
- P_curve[1] = load4f(&kg->__curve_keys.data[k0].x);
- P_curve[2] = load4f(&kg->__curve_keys.data[k1].x);
- P_curve[3] = load4f(&kg->__curve_keys.data[kb].x);
- }
- else {
- int fobject = (object == OBJECT_NONE)? kernel_tex_fetch(__prim_object, curveAddr): object;
- motion_cardinal_curve_keys(kg, fobject, prim, time, ka, k0, k1, kb, (float4*)&P_curve);
- }
-#endif /* __KERNEL_AVX2__ */
-
- ssef rd_sgn = set_sign_bit<0, 1, 1, 1>(shuffle<0>(rd_ss));
- ssef mul_zxxy = shuffle<2, 0, 0, 1>(vdir) * rd_sgn;
- ssef mul_yz = shuffle<1, 2, 1, 2>(vdir) * mul_zxxy;
- ssef mul_shuf = shuffle<0, 1, 2, 3>(mul_zxxy, mul_yz);
- ssef vdir0 = vdir & cast(ssei(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0));
-
- ssef htfm0 = shuffle<0, 2, 0, 3>(mul_shuf, vdir0);
- ssef htfm1 = shuffle<1, 0, 1, 3>(load1f_first(extract<0>(d_ss)), vdir0);
- ssef htfm2 = shuffle<1, 3, 2, 3>(mul_shuf, vdir0);
-
-#if defined(__KERNEL_AVX2__) && defined(__KERNEL_SSE__) && (!defined(_MSC_VER) || _MSC_VER > 1800)
- const avxf vPP = _mm256_broadcast_ps(&P.m128);
- const avxf htfm00 = avxf(htfm0.m128, htfm0.m128);
- const avxf htfm11 = avxf(htfm1.m128, htfm1.m128);
- const avxf htfm22 = avxf(htfm2.m128, htfm2.m128);
-
- const avxf p01 = madd(shuffle<0>(P_curve_0_1 - vPP),
- htfm00,
- madd(shuffle<1>(P_curve_0_1 - vPP),
- htfm11,
- shuffle<2>(P_curve_0_1 - vPP) * htfm22));
- const avxf p23 = madd(shuffle<0>(P_curve_2_3 - vPP),
- htfm00,
- madd(shuffle<1>(P_curve_2_3 - vPP),
- htfm11,
- shuffle<2>(P_curve_2_3 - vPP)*htfm22));
-
- const ssef p0 = _mm256_castps256_ps128(p01);
- const ssef p1 = _mm256_extractf128_ps(p01, 1);
- const ssef p2 = _mm256_castps256_ps128(p23);
- const ssef p3 = _mm256_extractf128_ps(p23, 1);
-
- const ssef P_curve_1 = _mm256_extractf128_ps(P_curve_0_1, 1);
- r_st = ((float4 &)P_curve_1).w;
- const ssef P_curve_2 = _mm256_castps256_ps128(P_curve_2_3);
- r_en = ((float4 &)P_curve_2).w;
-#else /* __KERNEL_AVX2__ */
- ssef htfm[] = { htfm0, htfm1, htfm2 };
- ssef vP = load4f(P);
- ssef p0 = transform_point_T3(htfm, P_curve[0] - vP);
- ssef p1 = transform_point_T3(htfm, P_curve[1] - vP);
- ssef p2 = transform_point_T3(htfm, P_curve[2] - vP);
- ssef p3 = transform_point_T3(htfm, P_curve[3] - vP);
-
- r_st = ((float4 &)P_curve[1]).w;
- r_en = ((float4 &)P_curve[2]).w;
-#endif /* __KERNEL_AVX2__ */
-
- float fc = 0.71f;
- ssef vfc = ssef(fc);
- ssef vfcxp3 = vfc * p3;
-
- vcurve_coef[0] = p1;
- vcurve_coef[1] = vfc * (p2 - p0);
- vcurve_coef[2] = madd(ssef(fc * 2.0f), p0, madd(ssef(fc - 3.0f), p1, msub(ssef(3.0f - 2.0f * fc), p2, vfcxp3)));
- vcurve_coef[3] = msub(ssef(fc - 2.0f), p2 - p1, msub(vfc, p0, vfcxp3));
-
- }
-#else
- float3 curve_coef[4];
-
- /* curve Intersection check */
- /* obtain curve parameters */
- {
- /* ray transform created - this should be created at beginning of intersection loop */
- Transform htfm;
- float d = sqrtf(dir.x * dir.x + dir.z * dir.z);
- htfm = make_transform(
- dir.z / d, 0, -dir.x /d, 0,
- -dir.x * dir.y /d, d, -dir.y * dir.z /d, 0,
- dir.x, dir.y, dir.z, 0);
-
- float4 v00 = kernel_tex_fetch(__curves, prim);
-
- int k0 = __float_as_int(v00.x) + segment;
- int k1 = k0 + 1;
-
- int ka = max(k0 - 1,__float_as_int(v00.x));
- int kb = min(k1 + 1,__float_as_int(v00.x) + __float_as_int(v00.y) - 1);
-
- float4 P_curve[4];
-
- if(is_curve_primitive) {
- P_curve[0] = kernel_tex_fetch(__curve_keys, ka);
- P_curve[1] = kernel_tex_fetch(__curve_keys, k0);
- P_curve[2] = kernel_tex_fetch(__curve_keys, k1);
- P_curve[3] = kernel_tex_fetch(__curve_keys, kb);
- }
- else {
- int fobject = (object == OBJECT_NONE)? kernel_tex_fetch(__prim_object, curveAddr): object;
- motion_cardinal_curve_keys(kg, fobject, prim, time, ka, k0, k1, kb, P_curve);
- }
-
- float3 p0 = transform_point(&htfm, float4_to_float3(P_curve[0]) - P);
- float3 p1 = transform_point(&htfm, float4_to_float3(P_curve[1]) - P);
- float3 p2 = transform_point(&htfm, float4_to_float3(P_curve[2]) - P);
- float3 p3 = transform_point(&htfm, float4_to_float3(P_curve[3]) - P);
-
- float fc = 0.71f;
- curve_coef[0] = p1;
- curve_coef[1] = -fc*p0 + fc*p2;
- curve_coef[2] = 2.0f * fc * p0 + (fc - 3.0f) * p1 + (3.0f - 2.0f * fc) * p2 - fc * p3;
- curve_coef[3] = -fc * p0 + (2.0f - fc) * p1 + (fc - 2.0f) * p2 + fc * p3;
- r_st = P_curve[1].w;
- r_en = P_curve[2].w;
- }
-#endif
-
- float r_curr = max(r_st, r_en);
-
- if((flags & CURVE_KN_RIBBONS) || !(flags & CURVE_KN_BACKFACING))
- epsilon = 2 * r_curr;
-
- /* find bounds - this is slow for cubic curves */
- float upper, lower;
-
- float zextrem[4];
- curvebounds(&lower, &upper, &zextrem[0], &zextrem[1], &zextrem[2], &zextrem[3], curve_coef[0].z, curve_coef[1].z, curve_coef[2].z, curve_coef[3].z);
- if(lower - r_curr > isect->t || upper + r_curr < epsilon)
- return false;
-
- /* minimum width extension */
- float mw_extension = min(difl * fabsf(upper), extmax);
- float r_ext = mw_extension + r_curr;
-
- float xextrem[4];
- curvebounds(&lower, &upper, &xextrem[0], &xextrem[1], &xextrem[2], &xextrem[3], curve_coef[0].x, curve_coef[1].x, curve_coef[2].x, curve_coef[3].x);
- if(lower > r_ext || upper < -r_ext)
- return false;
-
- float yextrem[4];
- curvebounds(&lower, &upper, &yextrem[0], &yextrem[1], &yextrem[2], &yextrem[3], curve_coef[0].y, curve_coef[1].y, curve_coef[2].y, curve_coef[3].y);
- if(lower > r_ext || upper < -r_ext)
- return false;
-
- /* setup recurrent loop */
- int level = 1 << depth;
- int tree = 0;
- float resol = 1.0f / (float)level;
- bool hit = false;
-
- /* begin loop */
- while(!(tree >> (depth))) {
- const float i_st = tree * resol;
- const float i_en = i_st + (level * resol);
-
-#ifdef __KERNEL_SSE2__
- ssef vi_st = ssef(i_st), vi_en = ssef(i_en);
- ssef vp_st = madd(madd(madd(vcurve_coef[3], vi_st, vcurve_coef[2]), vi_st, vcurve_coef[1]), vi_st, vcurve_coef[0]);
- ssef vp_en = madd(madd(madd(vcurve_coef[3], vi_en, vcurve_coef[2]), vi_en, vcurve_coef[1]), vi_en, vcurve_coef[0]);
-
- ssef vbmin = min(vp_st, vp_en);
- ssef vbmax = max(vp_st, vp_en);
-
- float3 &bmin = (float3 &)vbmin, &bmax = (float3 &)vbmax;
- float &bminx = bmin.x, &bminy = bmin.y, &bminz = bmin.z;
- float &bmaxx = bmax.x, &bmaxy = bmax.y, &bmaxz = bmax.z;
- float3 &p_st = (float3 &)vp_st, &p_en = (float3 &)vp_en;
-#else
- float3 p_st = ((curve_coef[3] * i_st + curve_coef[2]) * i_st + curve_coef[1]) * i_st + curve_coef[0];
- float3 p_en = ((curve_coef[3] * i_en + curve_coef[2]) * i_en + curve_coef[1]) * i_en + curve_coef[0];
-
- float bminx = min(p_st.x, p_en.x);
- float bmaxx = max(p_st.x, p_en.x);
- float bminy = min(p_st.y, p_en.y);
- float bmaxy = max(p_st.y, p_en.y);
- float bminz = min(p_st.z, p_en.z);
- float bmaxz = max(p_st.z, p_en.z);
-#endif
-
- if(xextrem[0] >= i_st && xextrem[0] <= i_en) {
- bminx = min(bminx,xextrem[1]);
- bmaxx = max(bmaxx,xextrem[1]);
- }
- if(xextrem[2] >= i_st && xextrem[2] <= i_en) {
- bminx = min(bminx,xextrem[3]);
- bmaxx = max(bmaxx,xextrem[3]);
- }
- if(yextrem[0] >= i_st && yextrem[0] <= i_en) {
- bminy = min(bminy,yextrem[1]);
- bmaxy = max(bmaxy,yextrem[1]);
- }
- if(yextrem[2] >= i_st && yextrem[2] <= i_en) {
- bminy = min(bminy,yextrem[3]);
- bmaxy = max(bmaxy,yextrem[3]);
- }
- if(zextrem[0] >= i_st && zextrem[0] <= i_en) {
- bminz = min(bminz,zextrem[1]);
- bmaxz = max(bmaxz,zextrem[1]);
- }
- if(zextrem[2] >= i_st && zextrem[2] <= i_en) {
- bminz = min(bminz,zextrem[3]);
- bmaxz = max(bmaxz,zextrem[3]);
- }
-
- float r1 = r_st + (r_en - r_st) * i_st;
- float r2 = r_st + (r_en - r_st) * i_en;
- r_curr = max(r1, r2);
-
- mw_extension = min(difl * fabsf(bmaxz), extmax);
- float r_ext = mw_extension + r_curr;
- float coverage = 1.0f;
-
- if(bminz - r_curr > isect->t || bmaxz + r_curr < epsilon || bminx > r_ext|| bmaxx < -r_ext|| bminy > r_ext|| bmaxy < -r_ext) {
- /* the bounding box does not overlap the square centered at O */
- tree += level;
- level = tree & -tree;
- }
- else if(level == 1) {
-
- /* the maximum recursion depth is reached.
- * check if dP0.(Q-P0)>=0 and dPn.(Pn-Q)>=0.
- * dP* is reversed if necessary.*/
- float t = isect->t;
- float u = 0.0f;
- float gd = 0.0f;
-
- if(flags & CURVE_KN_RIBBONS) {
- float3 tg = (p_en - p_st);
-#ifdef __KERNEL_SSE__
- const float3 tg_sq = tg * tg;
- float w = tg_sq.x + tg_sq.y;
-#else
- float w = tg.x * tg.x + tg.y * tg.y;
-#endif
- if(w == 0) {
- tree++;
- level = tree & -tree;
- continue;
- }
-#ifdef __KERNEL_SSE__
- const float3 p_sttg = p_st * tg;
- w = -(p_sttg.x + p_sttg.y) / w;
-#else
- w = -(p_st.x * tg.x + p_st.y * tg.y) / w;
-#endif
- w = saturate(w);
-
- /* compute u on the curve segment */
- u = i_st * (1 - w) + i_en * w;
- r_curr = r_st + (r_en - r_st) * u;
- /* compare x-y distances */
- float3 p_curr = ((curve_coef[3] * u + curve_coef[2]) * u + curve_coef[1]) * u + curve_coef[0];
-
- float3 dp_st = (3 * curve_coef[3] * i_st + 2 * curve_coef[2]) * i_st + curve_coef[1];
- if(dot(tg, dp_st)< 0)
- dp_st *= -1;
- if(dot(dp_st, -p_st) + p_curr.z * dp_st.z < 0) {
- tree++;
- level = tree & -tree;
- continue;
- }
- float3 dp_en = (3 * curve_coef[3] * i_en + 2 * curve_coef[2]) * i_en + curve_coef[1];
- if(dot(tg, dp_en) < 0)
- dp_en *= -1;
- if(dot(dp_en, p_en) - p_curr.z * dp_en.z < 0) {
- tree++;
- level = tree & -tree;
- continue;
- }
-
- /* compute coverage */
- float r_ext = r_curr;
- coverage = 1.0f;
- if(difl != 0.0f) {
- mw_extension = min(difl * fabsf(bmaxz), extmax);
- r_ext = mw_extension + r_curr;
-#ifdef __KERNEL_SSE__
- const float3 p_curr_sq = p_curr * p_curr;
- const float3 dxxx(_mm_sqrt_ss(_mm_hadd_ps(p_curr_sq.m128, p_curr_sq.m128)));
- float d = dxxx.x;
-#else
- float d = sqrtf(p_curr.x * p_curr.x + p_curr.y * p_curr.y);
-#endif
- float d0 = d - r_curr;
- float d1 = d + r_curr;
- float inv_mw_extension = 1.0f/mw_extension;
- if(d0 >= 0)
- coverage = (min(d1 * inv_mw_extension, 1.0f) - min(d0 * inv_mw_extension, 1.0f)) * 0.5f;
- else // inside
- coverage = (min(d1 * inv_mw_extension, 1.0f) + min(-d0 * inv_mw_extension, 1.0f)) * 0.5f;
- }
-
- if(p_curr.x * p_curr.x + p_curr.y * p_curr.y >= r_ext * r_ext || p_curr.z <= epsilon || isect->t < p_curr.z) {
- tree++;
- level = tree & -tree;
- continue;
- }
-
- t = p_curr.z;
-
- /* stochastic fade from minimum width */
- if(difl != 0.0f && lcg_state) {
- if(coverage != 1.0f && (lcg_step_float(lcg_state) > coverage))
- return hit;
- }
- }
- else {
- float l = len(p_en - p_st);
- /* minimum width extension */
- float or1 = r1;
- float or2 = r2;
-
- if(difl != 0.0f) {
- mw_extension = min(len(p_st - P) * difl, extmax);
- or1 = r1 < mw_extension ? mw_extension : r1;
- mw_extension = min(len(p_en - P) * difl, extmax);
- or2 = r2 < mw_extension ? mw_extension : r2;
- }
- /* --- */
- float invl = 1.0f/l;
- float3 tg = (p_en - p_st) * invl;
- gd = (or2 - or1) * invl;
- float difz = -dot(p_st,tg);
- float cyla = 1.0f - (tg.z * tg.z * (1 + gd*gd));
- float invcyla = 1.0f/cyla;
- float halfb = (-p_st.z - tg.z*(difz + gd*(difz*gd + or1)));
- float tcentre = -halfb*invcyla;
- float zcentre = difz + (tg.z * tcentre);
- float3 tdif = - p_st;
- tdif.z += tcentre;
- float tdifz = dot(tdif,tg);
- float tb = 2*(tdif.z - tg.z*(tdifz + gd*(tdifz*gd + or1)));
- float tc = dot(tdif,tdif) - tdifz * tdifz * (1 + gd*gd) - or1*or1 - 2*or1*tdifz*gd;
- float td = tb*tb - 4*cyla*tc;
- if(td < 0.0f) {
- tree++;
- level = tree & -tree;
- continue;
- }
-
- float rootd = sqrtf(td);
- float correction = (-tb - rootd) * 0.5f * invcyla;
- t = tcentre + correction;
-
- float3 dp_st = (3 * curve_coef[3] * i_st + 2 * curve_coef[2]) * i_st + curve_coef[1];
- if(dot(tg, dp_st)< 0)
- dp_st *= -1;
- float3 dp_en = (3 * curve_coef[3] * i_en + 2 * curve_coef[2]) * i_en + curve_coef[1];
- if(dot(tg, dp_en) < 0)
- dp_en *= -1;
-
- if(flags & CURVE_KN_BACKFACING && (dot(dp_st, -p_st) + t * dp_st.z < 0 || dot(dp_en, p_en) - t * dp_en.z < 0 || isect->t < t || t <= 0.0f)) {
- correction = (-tb + rootd) * 0.5f * invcyla;
- t = tcentre + correction;
- }
-
- if(dot(dp_st, -p_st) + t * dp_st.z < 0 || dot(dp_en, p_en) - t * dp_en.z < 0 || isect->t < t || t <= 0.0f) {
- tree++;
- level = tree & -tree;
- continue;
- }
-
- float w = (zcentre + (tg.z * correction)) * invl;
- w = saturate(w);
- /* compute u on the curve segment */
- u = i_st * (1 - w) + i_en * w;
-
- /* stochastic fade from minimum width */
- if(difl != 0.0f && lcg_state) {
- r_curr = r1 + (r2 - r1) * w;
- r_ext = or1 + (or2 - or1) * w;
- coverage = r_curr/r_ext;
-
- if(coverage != 1.0f && (lcg_step_float(lcg_state) > coverage))
- return hit;
- }
- }
- /* we found a new intersection */
-
-#ifdef __VISIBILITY_FLAG__
- /* visibility flag test. we do it here under the assumption
- * that most triangles are culled by node flags */
- if(kernel_tex_fetch(__prim_visibility, curveAddr) & visibility)
-#endif
- {
- /* record intersection */
- isect->t = t;
- isect->u = u;
- isect->v = gd;
- isect->prim = curveAddr;
- isect->object = object;
- isect->type = type;
- hit = true;
- }
-
- tree++;
- level = tree & -tree;
- }
- else {
- /* split the curve into two curves and process */
- level = level >> 1;
- }
- }
-
- return hit;
+ const bool is_curve_primitive = (type & PRIMITIVE_CURVE);
+
+ if (!is_curve_primitive && kernel_data.bvh.use_bvh_steps) {
+ const float2 prim_time = kernel_tex_fetch(__prim_time, curveAddr);
+ if (time < prim_time.x || time > prim_time.y) {
+ return false;
+ }
+ }
+
+ int segment = PRIMITIVE_UNPACK_SEGMENT(type);
+ float epsilon = 0.0f;
+ float r_st, r_en;
+
+ int depth = kernel_data.curve.subdivisions;
+ int flags = kernel_data.curve.curveflags;
+ int prim = kernel_tex_fetch(__prim_index, curveAddr);
+
+# ifdef __KERNEL_SSE2__
+ ssef vdir = load4f(dir);
+ ssef vcurve_coef[4];
+ const float3 *curve_coef = (float3 *)vcurve_coef;
+
+ {
+ ssef dtmp = vdir * vdir;
+ ssef d_ss = mm_sqrt(dtmp + shuffle<2>(dtmp));
+ ssef rd_ss = load1f_first(1.0f) / d_ss;
+
+ ssei v00vec = load4i((ssei *)&kg->__curves.data[prim]);
+ int2 &v00 = (int2 &)v00vec;
+
+ int k0 = v00.x + segment;
+ int k1 = k0 + 1;
+ int ka = max(k0 - 1, v00.x);
+ int kb = min(k1 + 1, v00.x + v00.y - 1);
+
+# if defined(__KERNEL_AVX2__) && defined(__KERNEL_SSE__) && \
+ (!defined(_MSC_VER) || _MSC_VER > 1800)
+ avxf P_curve_0_1, P_curve_2_3;
+ if (is_curve_primitive) {
+ P_curve_0_1 = _mm256_loadu2_m128(&kg->__curve_keys.data[k0].x, &kg->__curve_keys.data[ka].x);
+ P_curve_2_3 = _mm256_loadu2_m128(&kg->__curve_keys.data[kb].x, &kg->__curve_keys.data[k1].x);
+ }
+ else {
+ int fobject = (object == OBJECT_NONE) ? kernel_tex_fetch(__prim_object, curveAddr) : object;
+ motion_cardinal_curve_keys_avx(
+ kg, fobject, prim, time, ka, k0, k1, kb, &P_curve_0_1, &P_curve_2_3);
+ }
+# else /* __KERNEL_AVX2__ */
+ ssef P_curve[4];
+
+ if (is_curve_primitive) {
+ P_curve[0] = load4f(&kg->__curve_keys.data[ka].x);
+ P_curve[1] = load4f(&kg->__curve_keys.data[k0].x);
+ P_curve[2] = load4f(&kg->__curve_keys.data[k1].x);
+ P_curve[3] = load4f(&kg->__curve_keys.data[kb].x);
+ }
+ else {
+ int fobject = (object == OBJECT_NONE) ? kernel_tex_fetch(__prim_object, curveAddr) : object;
+ motion_cardinal_curve_keys(kg, fobject, prim, time, ka, k0, k1, kb, (float4 *)&P_curve);
+ }
+# endif /* __KERNEL_AVX2__ */
+
+ ssef rd_sgn = set_sign_bit<0, 1, 1, 1>(shuffle<0>(rd_ss));
+ ssef mul_zxxy = shuffle<2, 0, 0, 1>(vdir) * rd_sgn;
+ ssef mul_yz = shuffle<1, 2, 1, 2>(vdir) * mul_zxxy;
+ ssef mul_shuf = shuffle<0, 1, 2, 3>(mul_zxxy, mul_yz);
+ ssef vdir0 = vdir & cast(ssei(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0));
+
+ ssef htfm0 = shuffle<0, 2, 0, 3>(mul_shuf, vdir0);
+ ssef htfm1 = shuffle<1, 0, 1, 3>(load1f_first(extract<0>(d_ss)), vdir0);
+ ssef htfm2 = shuffle<1, 3, 2, 3>(mul_shuf, vdir0);
+
+# if defined(__KERNEL_AVX2__) && defined(__KERNEL_SSE__) && \
+ (!defined(_MSC_VER) || _MSC_VER > 1800)
+ const avxf vPP = _mm256_broadcast_ps(&P.m128);
+ const avxf htfm00 = avxf(htfm0.m128, htfm0.m128);
+ const avxf htfm11 = avxf(htfm1.m128, htfm1.m128);
+ const avxf htfm22 = avxf(htfm2.m128, htfm2.m128);
+
+ const avxf p01 = madd(
+ shuffle<0>(P_curve_0_1 - vPP),
+ htfm00,
+ madd(shuffle<1>(P_curve_0_1 - vPP), htfm11, shuffle<2>(P_curve_0_1 - vPP) * htfm22));
+ const avxf p23 = madd(
+ shuffle<0>(P_curve_2_3 - vPP),
+ htfm00,
+ madd(shuffle<1>(P_curve_2_3 - vPP), htfm11, shuffle<2>(P_curve_2_3 - vPP) * htfm22));
+
+ const ssef p0 = _mm256_castps256_ps128(p01);
+ const ssef p1 = _mm256_extractf128_ps(p01, 1);
+ const ssef p2 = _mm256_castps256_ps128(p23);
+ const ssef p3 = _mm256_extractf128_ps(p23, 1);
+
+ const ssef P_curve_1 = _mm256_extractf128_ps(P_curve_0_1, 1);
+ r_st = ((float4 &)P_curve_1).w;
+ const ssef P_curve_2 = _mm256_castps256_ps128(P_curve_2_3);
+ r_en = ((float4 &)P_curve_2).w;
+# else /* __KERNEL_AVX2__ */
+ ssef htfm[] = {htfm0, htfm1, htfm2};
+ ssef vP = load4f(P);
+ ssef p0 = transform_point_T3(htfm, P_curve[0] - vP);
+ ssef p1 = transform_point_T3(htfm, P_curve[1] - vP);
+ ssef p2 = transform_point_T3(htfm, P_curve[2] - vP);
+ ssef p3 = transform_point_T3(htfm, P_curve[3] - vP);
+
+ r_st = ((float4 &)P_curve[1]).w;
+ r_en = ((float4 &)P_curve[2]).w;
+# endif /* __KERNEL_AVX2__ */
+
+ float fc = 0.71f;
+ ssef vfc = ssef(fc);
+ ssef vfcxp3 = vfc * p3;
+
+ vcurve_coef[0] = p1;
+ vcurve_coef[1] = vfc * (p2 - p0);
+ vcurve_coef[2] = madd(
+ ssef(fc * 2.0f), p0, madd(ssef(fc - 3.0f), p1, msub(ssef(3.0f - 2.0f * fc), p2, vfcxp3)));
+ vcurve_coef[3] = msub(ssef(fc - 2.0f), p2 - p1, msub(vfc, p0, vfcxp3));
+ }
+# else
+ float3 curve_coef[4];
+
+ /* curve Intersection check */
+ /* obtain curve parameters */
+ {
+ /* ray transform created - this should be created at beginning of intersection loop */
+ Transform htfm;
+ float d = sqrtf(dir.x * dir.x + dir.z * dir.z);
+ htfm = make_transform(dir.z / d,
+ 0,
+ -dir.x / d,
+ 0,
+ -dir.x * dir.y / d,
+ d,
+ -dir.y * dir.z / d,
+ 0,
+ dir.x,
+ dir.y,
+ dir.z,
+ 0);
+
+ float4 v00 = kernel_tex_fetch(__curves, prim);
+
+ int k0 = __float_as_int(v00.x) + segment;
+ int k1 = k0 + 1;
+
+ int ka = max(k0 - 1, __float_as_int(v00.x));
+ int kb = min(k1 + 1, __float_as_int(v00.x) + __float_as_int(v00.y) - 1);
+
+ float4 P_curve[4];
+
+ if (is_curve_primitive) {
+ P_curve[0] = kernel_tex_fetch(__curve_keys, ka);
+ P_curve[1] = kernel_tex_fetch(__curve_keys, k0);
+ P_curve[2] = kernel_tex_fetch(__curve_keys, k1);
+ P_curve[3] = kernel_tex_fetch(__curve_keys, kb);
+ }
+ else {
+ int fobject = (object == OBJECT_NONE) ? kernel_tex_fetch(__prim_object, curveAddr) : object;
+ motion_cardinal_curve_keys(kg, fobject, prim, time, ka, k0, k1, kb, P_curve);
+ }
+
+ float3 p0 = transform_point(&htfm, float4_to_float3(P_curve[0]) - P);
+ float3 p1 = transform_point(&htfm, float4_to_float3(P_curve[1]) - P);
+ float3 p2 = transform_point(&htfm, float4_to_float3(P_curve[2]) - P);
+ float3 p3 = transform_point(&htfm, float4_to_float3(P_curve[3]) - P);
+
+ float fc = 0.71f;
+ curve_coef[0] = p1;
+ curve_coef[1] = -fc * p0 + fc * p2;
+ curve_coef[2] = 2.0f * fc * p0 + (fc - 3.0f) * p1 + (3.0f - 2.0f * fc) * p2 - fc * p3;
+ curve_coef[3] = -fc * p0 + (2.0f - fc) * p1 + (fc - 2.0f) * p2 + fc * p3;
+ r_st = P_curve[1].w;
+ r_en = P_curve[2].w;
+ }
+# endif
+
+ float r_curr = max(r_st, r_en);
+
+ if ((flags & CURVE_KN_RIBBONS) || !(flags & CURVE_KN_BACKFACING))
+ epsilon = 2 * r_curr;
+
+ /* find bounds - this is slow for cubic curves */
+ float upper, lower;
+
+ float zextrem[4];
+ curvebounds(&lower,
+ &upper,
+ &zextrem[0],
+ &zextrem[1],
+ &zextrem[2],
+ &zextrem[3],
+ curve_coef[0].z,
+ curve_coef[1].z,
+ curve_coef[2].z,
+ curve_coef[3].z);
+ if (lower - r_curr > isect->t || upper + r_curr < epsilon)
+ return false;
+
+ /* minimum width extension */
+ float mw_extension = min(difl * fabsf(upper), extmax);
+ float r_ext = mw_extension + r_curr;
+
+ float xextrem[4];
+ curvebounds(&lower,
+ &upper,
+ &xextrem[0],
+ &xextrem[1],
+ &xextrem[2],
+ &xextrem[3],
+ curve_coef[0].x,
+ curve_coef[1].x,
+ curve_coef[2].x,
+ curve_coef[3].x);
+ if (lower > r_ext || upper < -r_ext)
+ return false;
+
+ float yextrem[4];
+ curvebounds(&lower,
+ &upper,
+ &yextrem[0],
+ &yextrem[1],
+ &yextrem[2],
+ &yextrem[3],
+ curve_coef[0].y,
+ curve_coef[1].y,
+ curve_coef[2].y,
+ curve_coef[3].y);
+ if (lower > r_ext || upper < -r_ext)
+ return false;
+
+ /* setup recurrent loop */
+ int level = 1 << depth;
+ int tree = 0;
+ float resol = 1.0f / (float)level;
+ bool hit = false;
+
+ /* begin loop */
+ while (!(tree >> (depth))) {
+ const float i_st = tree * resol;
+ const float i_en = i_st + (level * resol);
+
+# ifdef __KERNEL_SSE2__
+ ssef vi_st = ssef(i_st), vi_en = ssef(i_en);
+ ssef vp_st = madd(madd(madd(vcurve_coef[3], vi_st, vcurve_coef[2]), vi_st, vcurve_coef[1]),
+ vi_st,
+ vcurve_coef[0]);
+ ssef vp_en = madd(madd(madd(vcurve_coef[3], vi_en, vcurve_coef[2]), vi_en, vcurve_coef[1]),
+ vi_en,
+ vcurve_coef[0]);
+
+ ssef vbmin = min(vp_st, vp_en);
+ ssef vbmax = max(vp_st, vp_en);
+
+ float3 &bmin = (float3 &)vbmin, &bmax = (float3 &)vbmax;
+ float &bminx = bmin.x, &bminy = bmin.y, &bminz = bmin.z;
+ float &bmaxx = bmax.x, &bmaxy = bmax.y, &bmaxz = bmax.z;
+ float3 &p_st = (float3 &)vp_st, &p_en = (float3 &)vp_en;
+# else
+ float3 p_st = ((curve_coef[3] * i_st + curve_coef[2]) * i_st + curve_coef[1]) * i_st +
+ curve_coef[0];
+ float3 p_en = ((curve_coef[3] * i_en + curve_coef[2]) * i_en + curve_coef[1]) * i_en +
+ curve_coef[0];
+
+ float bminx = min(p_st.x, p_en.x);
+ float bmaxx = max(p_st.x, p_en.x);
+ float bminy = min(p_st.y, p_en.y);
+ float bmaxy = max(p_st.y, p_en.y);
+ float bminz = min(p_st.z, p_en.z);
+ float bmaxz = max(p_st.z, p_en.z);
+# endif
+
+ if (xextrem[0] >= i_st && xextrem[0] <= i_en) {
+ bminx = min(bminx, xextrem[1]);
+ bmaxx = max(bmaxx, xextrem[1]);
+ }
+ if (xextrem[2] >= i_st && xextrem[2] <= i_en) {
+ bminx = min(bminx, xextrem[3]);
+ bmaxx = max(bmaxx, xextrem[3]);
+ }
+ if (yextrem[0] >= i_st && yextrem[0] <= i_en) {
+ bminy = min(bminy, yextrem[1]);
+ bmaxy = max(bmaxy, yextrem[1]);
+ }
+ if (yextrem[2] >= i_st && yextrem[2] <= i_en) {
+ bminy = min(bminy, yextrem[3]);
+ bmaxy = max(bmaxy, yextrem[3]);
+ }
+ if (zextrem[0] >= i_st && zextrem[0] <= i_en) {
+ bminz = min(bminz, zextrem[1]);
+ bmaxz = max(bmaxz, zextrem[1]);
+ }
+ if (zextrem[2] >= i_st && zextrem[2] <= i_en) {
+ bminz = min(bminz, zextrem[3]);
+ bmaxz = max(bmaxz, zextrem[3]);
+ }
+
+ float r1 = r_st + (r_en - r_st) * i_st;
+ float r2 = r_st + (r_en - r_st) * i_en;
+ r_curr = max(r1, r2);
+
+ mw_extension = min(difl * fabsf(bmaxz), extmax);
+ float r_ext = mw_extension + r_curr;
+ float coverage = 1.0f;
+
+ if (bminz - r_curr > isect->t || bmaxz + r_curr < epsilon || bminx > r_ext || bmaxx < -r_ext ||
+ bminy > r_ext || bmaxy < -r_ext) {
+ /* the bounding box does not overlap the square centered at O */
+ tree += level;
+ level = tree & -tree;
+ }
+ else if (level == 1) {
+
+ /* the maximum recursion depth is reached.
+ * check if dP0.(Q-P0)>=0 and dPn.(Pn-Q)>=0.
+ * dP* is reversed if necessary.*/
+ float t = isect->t;
+ float u = 0.0f;
+ float gd = 0.0f;
+
+ if (flags & CURVE_KN_RIBBONS) {
+ float3 tg = (p_en - p_st);
+# ifdef __KERNEL_SSE__
+ const float3 tg_sq = tg * tg;
+ float w = tg_sq.x + tg_sq.y;
+# else
+ float w = tg.x * tg.x + tg.y * tg.y;
+# endif
+ if (w == 0) {
+ tree++;
+ level = tree & -tree;
+ continue;
+ }
+# ifdef __KERNEL_SSE__
+ const float3 p_sttg = p_st * tg;
+ w = -(p_sttg.x + p_sttg.y) / w;
+# else
+ w = -(p_st.x * tg.x + p_st.y * tg.y) / w;
+# endif
+ w = saturate(w);
+
+ /* compute u on the curve segment */
+ u = i_st * (1 - w) + i_en * w;
+ r_curr = r_st + (r_en - r_st) * u;
+ /* compare x-y distances */
+ float3 p_curr = ((curve_coef[3] * u + curve_coef[2]) * u + curve_coef[1]) * u +
+ curve_coef[0];
+
+ float3 dp_st = (3 * curve_coef[3] * i_st + 2 * curve_coef[2]) * i_st + curve_coef[1];
+ if (dot(tg, dp_st) < 0)
+ dp_st *= -1;
+ if (dot(dp_st, -p_st) + p_curr.z * dp_st.z < 0) {
+ tree++;
+ level = tree & -tree;
+ continue;
+ }
+ float3 dp_en = (3 * curve_coef[3] * i_en + 2 * curve_coef[2]) * i_en + curve_coef[1];
+ if (dot(tg, dp_en) < 0)
+ dp_en *= -1;
+ if (dot(dp_en, p_en) - p_curr.z * dp_en.z < 0) {
+ tree++;
+ level = tree & -tree;
+ continue;
+ }
+
+ /* compute coverage */
+ float r_ext = r_curr;
+ coverage = 1.0f;
+ if (difl != 0.0f) {
+ mw_extension = min(difl * fabsf(bmaxz), extmax);
+ r_ext = mw_extension + r_curr;
+# ifdef __KERNEL_SSE__
+ const float3 p_curr_sq = p_curr * p_curr;
+ const float3 dxxx(_mm_sqrt_ss(_mm_hadd_ps(p_curr_sq.m128, p_curr_sq.m128)));
+ float d = dxxx.x;
+# else
+ float d = sqrtf(p_curr.x * p_curr.x + p_curr.y * p_curr.y);
+# endif
+ float d0 = d - r_curr;
+ float d1 = d + r_curr;
+ float inv_mw_extension = 1.0f / mw_extension;
+ if (d0 >= 0)
+ coverage = (min(d1 * inv_mw_extension, 1.0f) - min(d0 * inv_mw_extension, 1.0f)) *
+ 0.5f;
+ else // inside
+ coverage = (min(d1 * inv_mw_extension, 1.0f) + min(-d0 * inv_mw_extension, 1.0f)) *
+ 0.5f;
+ }
+
+ if (p_curr.x * p_curr.x + p_curr.y * p_curr.y >= r_ext * r_ext || p_curr.z <= epsilon ||
+ isect->t < p_curr.z) {
+ tree++;
+ level = tree & -tree;
+ continue;
+ }
+
+ t = p_curr.z;
+
+ /* stochastic fade from minimum width */
+ if (difl != 0.0f && lcg_state) {
+ if (coverage != 1.0f && (lcg_step_float(lcg_state) > coverage))
+ return hit;
+ }
+ }
+ else {
+ float l = len(p_en - p_st);
+ /* minimum width extension */
+ float or1 = r1;
+ float or2 = r2;
+
+ if (difl != 0.0f) {
+ mw_extension = min(len(p_st - P) * difl, extmax);
+ or1 = r1 < mw_extension ? mw_extension : r1;
+ mw_extension = min(len(p_en - P) * difl, extmax);
+ or2 = r2 < mw_extension ? mw_extension : r2;
+ }
+ /* --- */
+ float invl = 1.0f / l;
+ float3 tg = (p_en - p_st) * invl;
+ gd = (or2 - or1) * invl;
+ float difz = -dot(p_st, tg);
+ float cyla = 1.0f - (tg.z * tg.z * (1 + gd * gd));
+ float invcyla = 1.0f / cyla;
+ float halfb = (-p_st.z - tg.z * (difz + gd * (difz * gd + or1)));
+ float tcentre = -halfb * invcyla;
+ float zcentre = difz + (tg.z * tcentre);
+ float3 tdif = -p_st;
+ tdif.z += tcentre;
+ float tdifz = dot(tdif, tg);
+ float tb = 2 * (tdif.z - tg.z * (tdifz + gd * (tdifz * gd + or1)));
+ float tc = dot(tdif, tdif) - tdifz * tdifz * (1 + gd * gd) - or1 * or1 -
+ 2 * or1 * tdifz * gd;
+ float td = tb * tb - 4 * cyla * tc;
+ if (td < 0.0f) {
+ tree++;
+ level = tree & -tree;
+ continue;
+ }
+
+ float rootd = sqrtf(td);
+ float correction = (-tb - rootd) * 0.5f * invcyla;
+ t = tcentre + correction;
+
+ float3 dp_st = (3 * curve_coef[3] * i_st + 2 * curve_coef[2]) * i_st + curve_coef[1];
+ if (dot(tg, dp_st) < 0)
+ dp_st *= -1;
+ float3 dp_en = (3 * curve_coef[3] * i_en + 2 * curve_coef[2]) * i_en + curve_coef[1];
+ if (dot(tg, dp_en) < 0)
+ dp_en *= -1;
+
+ if (flags & CURVE_KN_BACKFACING &&
+ (dot(dp_st, -p_st) + t * dp_st.z < 0 || dot(dp_en, p_en) - t * dp_en.z < 0 ||
+ isect->t < t || t <= 0.0f)) {
+ correction = (-tb + rootd) * 0.5f * invcyla;
+ t = tcentre + correction;
+ }
+
+ if (dot(dp_st, -p_st) + t * dp_st.z < 0 || dot(dp_en, p_en) - t * dp_en.z < 0 ||
+ isect->t < t || t <= 0.0f) {
+ tree++;
+ level = tree & -tree;
+ continue;
+ }
+
+ float w = (zcentre + (tg.z * correction)) * invl;
+ w = saturate(w);
+ /* compute u on the curve segment */
+ u = i_st * (1 - w) + i_en * w;
+
+ /* stochastic fade from minimum width */
+ if (difl != 0.0f && lcg_state) {
+ r_curr = r1 + (r2 - r1) * w;
+ r_ext = or1 + (or2 - or1) * w;
+ coverage = r_curr / r_ext;
+
+ if (coverage != 1.0f && (lcg_step_float(lcg_state) > coverage))
+ return hit;
+ }
+ }
+ /* we found a new intersection */
+
+# ifdef __VISIBILITY_FLAG__
+ /* visibility flag test. we do it here under the assumption
+ * that most triangles are culled by node flags */
+ if (kernel_tex_fetch(__prim_visibility, curveAddr) & visibility)
+# endif
+ {
+ /* record intersection */
+ isect->t = t;
+ isect->u = u;
+ isect->v = gd;
+ isect->prim = curveAddr;
+ isect->object = object;
+ isect->type = type;
+ hit = true;
+ }
+
+ tree++;
+ level = tree & -tree;
+ }
+ else {
+ /* split the curve into two curves and process */
+ level = level >> 1;
+ }
+ }
+
+ return hit;
}
ccl_device_forceinline bool curve_intersect(KernelGlobals *kg,
@@ -511,245 +561,247 @@ ccl_device_forceinline bool curve_intersect(KernelGlobals *kg,
float difl,
float extmax)
{
- /* define few macros to minimize code duplication for SSE */
-#ifndef __KERNEL_SSE2__
-# define len3_squared(x) len_squared(x)
-# define len3(x) len(x)
-# define dot3(x, y) dot(x, y)
-#endif
-
- const bool is_curve_primitive = (type & PRIMITIVE_CURVE);
-
- if(!is_curve_primitive && kernel_data.bvh.use_bvh_steps) {
- const float2 prim_time = kernel_tex_fetch(__prim_time, curveAddr);
- if(time < prim_time.x || time > prim_time.y) {
- return false;
- }
- }
-
- int segment = PRIMITIVE_UNPACK_SEGMENT(type);
- /* curve Intersection check */
- int flags = kernel_data.curve.curveflags;
-
- int prim = kernel_tex_fetch(__prim_index, curveAddr);
- float4 v00 = kernel_tex_fetch(__curves, prim);
-
- int cnum = __float_as_int(v00.x);
- int k0 = cnum + segment;
- int k1 = k0 + 1;
-
-#ifndef __KERNEL_SSE2__
- float4 P_curve[2];
-
- if(is_curve_primitive) {
- P_curve[0] = kernel_tex_fetch(__curve_keys, k0);
- P_curve[1] = kernel_tex_fetch(__curve_keys, k1);
- }
- else {
- int fobject = (object == OBJECT_NONE)? kernel_tex_fetch(__prim_object, curveAddr): object;
- motion_curve_keys(kg, fobject, prim, time, k0, k1, P_curve);
- }
-
- float or1 = P_curve[0].w;
- float or2 = P_curve[1].w;
- float3 p1 = float4_to_float3(P_curve[0]);
- float3 p2 = float4_to_float3(P_curve[1]);
-
- /* minimum width extension */
- float r1 = or1;
- float r2 = or2;
- float3 dif = P - p1;
- float3 dif_second = P - p2;
- if(difl != 0.0f) {
- float pixelsize = min(len3(dif) * difl, extmax);
- r1 = or1 < pixelsize ? pixelsize : or1;
- pixelsize = min(len3(dif_second) * difl, extmax);
- r2 = or2 < pixelsize ? pixelsize : or2;
- }
- /* --- */
-
- float3 p21_diff = p2 - p1;
- float3 sphere_dif1 = (dif + dif_second) * 0.5f;
- float3 dir = direction;
- float sphere_b_tmp = dot3(dir, sphere_dif1);
- float3 sphere_dif2 = sphere_dif1 - sphere_b_tmp * dir;
-#else
- ssef P_curve[2];
-
- if(is_curve_primitive) {
- P_curve[0] = load4f(&kg->__curve_keys.data[k0].x);
- P_curve[1] = load4f(&kg->__curve_keys.data[k1].x);
- }
- else {
- int fobject = (object == OBJECT_NONE)? kernel_tex_fetch(__prim_object, curveAddr): object;
- motion_curve_keys(kg, fobject, prim, time, k0, k1, (float4*)&P_curve);
- }
-
- const ssef or12 = shuffle<3, 3, 3, 3>(P_curve[0], P_curve[1]);
-
- ssef r12 = or12;
- const ssef vP = load4f(P);
- const ssef dif = vP - P_curve[0];
- const ssef dif_second = vP - P_curve[1];
- if(difl != 0.0f) {
- const ssef len1_sq = len3_squared_splat(dif);
- const ssef len2_sq = len3_squared_splat(dif_second);
- const ssef len12 = mm_sqrt(shuffle<0, 0, 0, 0>(len1_sq, len2_sq));
- const ssef pixelsize12 = min(len12 * difl, ssef(extmax));
- r12 = max(or12, pixelsize12);
- }
- float or1 = extract<0>(or12), or2 = extract<0>(shuffle<2>(or12));
- float r1 = extract<0>(r12), r2 = extract<0>(shuffle<2>(r12));
-
- const ssef p21_diff = P_curve[1] - P_curve[0];
- const ssef sphere_dif1 = (dif + dif_second) * 0.5f;
- const ssef dir = load4f(direction);
- const ssef sphere_b_tmp = dot3_splat(dir, sphere_dif1);
- const ssef sphere_dif2 = nmadd(sphere_b_tmp, dir, sphere_dif1);
-#endif
-
- float mr = max(r1, r2);
- float l = len3(p21_diff);
- float invl = 1.0f / l;
- float sp_r = mr + 0.5f * l;
-
- float sphere_b = dot3(dir, sphere_dif2);
- float sdisc = sphere_b * sphere_b - len3_squared(sphere_dif2) + sp_r * sp_r;
-
- if(sdisc < 0.0f)
- return false;
-
- /* obtain parameters and test midpoint distance for suitable modes */
-#ifndef __KERNEL_SSE2__
- float3 tg = p21_diff * invl;
-#else
- const ssef tg = p21_diff * invl;
-#endif
- float gd = (r2 - r1) * invl;
-
- float dirz = dot3(dir, tg);
- float difz = dot3(dif, tg);
-
- float a = 1.0f - (dirz*dirz*(1 + gd*gd));
-
- float halfb = dot3(dir, dif) - dirz*(difz + gd*(difz*gd + r1));
-
- float tcentre = -halfb/a;
- float zcentre = difz + (dirz * tcentre);
-
- if((tcentre > isect->t) && !(flags & CURVE_KN_ACCURATE))
- return false;
- if((zcentre < 0 || zcentre > l) && !(flags & CURVE_KN_ACCURATE) && !(flags & CURVE_KN_INTERSECTCORRECTION))
- return false;
-
- /* test minimum separation */
-#ifndef __KERNEL_SSE2__
- float3 cprod = cross(tg, dir);
- float cprod2sq = len3_squared(cross(tg, dif));
-#else
- const ssef cprod = cross(tg, dir);
- float cprod2sq = len3_squared(cross_zxy(tg, dif));
-#endif
- float cprodsq = len3_squared(cprod);
- float distscaled = dot3(cprod, dif);
-
- if(cprodsq == 0)
- distscaled = cprod2sq;
- else
- distscaled = (distscaled*distscaled)/cprodsq;
-
- if(distscaled > mr*mr)
- return false;
-
- /* calculate true intersection */
-#ifndef __KERNEL_SSE2__
- float3 tdif = dif + tcentre * dir;
-#else
- const ssef tdif = madd(ssef(tcentre), dir, dif);
-#endif
- float tdifz = dot3(tdif, tg);
- float tdifma = tdifz*gd + r1;
- float tb = 2*(dot3(dir, tdif) - dirz*(tdifz + gd*tdifma));
- float tc = dot3(tdif, tdif) - tdifz*tdifz - tdifma*tdifma;
- float td = tb*tb - 4*a*tc;
-
- if(td < 0.0f)
- return false;
-
- float rootd = 0.0f;
- float correction = 0.0f;
- if(flags & CURVE_KN_ACCURATE) {
- rootd = sqrtf(td);
- correction = ((-tb - rootd)/(2*a));
- }
-
- float t = tcentre + correction;
-
- if(t < isect->t) {
-
- if(flags & CURVE_KN_INTERSECTCORRECTION) {
- rootd = sqrtf(td);
- correction = ((-tb - rootd)/(2*a));
- t = tcentre + correction;
- }
-
- float z = zcentre + (dirz * correction);
- // bool backface = false;
-
- if(flags & CURVE_KN_BACKFACING && (t < 0.0f || z < 0 || z > l)) {
- // backface = true;
- correction = ((-tb + rootd)/(2*a));
- t = tcentre + correction;
- z = zcentre + (dirz * correction);
- }
-
- /* stochastic fade from minimum width */
- float adjradius = or1 + z * (or2 - or1) * invl;
- adjradius = adjradius / (r1 + z * gd);
- if(lcg_state && adjradius != 1.0f) {
- if(lcg_step_float(lcg_state) > adjradius)
- return false;
- }
- /* --- */
-
- if(t > 0.0f && t < isect->t && z >= 0 && z <= l) {
-
- if(flags & CURVE_KN_ENCLOSEFILTER) {
- float enc_ratio = 1.01f;
- if((difz > -r1 * enc_ratio) && (dot3(dif_second, tg) < r2 * enc_ratio)) {
- float a2 = 1.0f - (dirz*dirz*(1 + gd*gd*enc_ratio*enc_ratio));
- float c2 = dot3(dif, dif) - difz * difz * (1 + gd*gd*enc_ratio*enc_ratio) - r1*r1*enc_ratio*enc_ratio - 2*r1*difz*gd*enc_ratio;
- if(a2*c2 < 0.0f)
- return false;
- }
- }
-
-#ifdef __VISIBILITY_FLAG__
- /* visibility flag test. we do it here under the assumption
- * that most triangles are culled by node flags */
- if(kernel_tex_fetch(__prim_visibility, curveAddr) & visibility)
-#endif
- {
- /* record intersection */
- isect->t = t;
- isect->u = z*invl;
- isect->v = gd;
- isect->prim = curveAddr;
- isect->object = object;
- isect->type = type;
-
- return true;
- }
- }
- }
-
- return false;
-
-#ifndef __KERNEL_SSE2__
-# undef len3_squared
-# undef len3
-# undef dot3
-#endif
+ /* define few macros to minimize code duplication for SSE */
+# ifndef __KERNEL_SSE2__
+# define len3_squared(x) len_squared(x)
+# define len3(x) len(x)
+# define dot3(x, y) dot(x, y)
+# endif
+
+ const bool is_curve_primitive = (type & PRIMITIVE_CURVE);
+
+ if (!is_curve_primitive && kernel_data.bvh.use_bvh_steps) {
+ const float2 prim_time = kernel_tex_fetch(__prim_time, curveAddr);
+ if (time < prim_time.x || time > prim_time.y) {
+ return false;
+ }
+ }
+
+ int segment = PRIMITIVE_UNPACK_SEGMENT(type);
+ /* curve Intersection check */
+ int flags = kernel_data.curve.curveflags;
+
+ int prim = kernel_tex_fetch(__prim_index, curveAddr);
+ float4 v00 = kernel_tex_fetch(__curves, prim);
+
+ int cnum = __float_as_int(v00.x);
+ int k0 = cnum + segment;
+ int k1 = k0 + 1;
+
+# ifndef __KERNEL_SSE2__
+ float4 P_curve[2];
+
+ if (is_curve_primitive) {
+ P_curve[0] = kernel_tex_fetch(__curve_keys, k0);
+ P_curve[1] = kernel_tex_fetch(__curve_keys, k1);
+ }
+ else {
+ int fobject = (object == OBJECT_NONE) ? kernel_tex_fetch(__prim_object, curveAddr) : object;
+ motion_curve_keys(kg, fobject, prim, time, k0, k1, P_curve);
+ }
+
+ float or1 = P_curve[0].w;
+ float or2 = P_curve[1].w;
+ float3 p1 = float4_to_float3(P_curve[0]);
+ float3 p2 = float4_to_float3(P_curve[1]);
+
+ /* minimum width extension */
+ float r1 = or1;
+ float r2 = or2;
+ float3 dif = P - p1;
+ float3 dif_second = P - p2;
+ if (difl != 0.0f) {
+ float pixelsize = min(len3(dif) * difl, extmax);
+ r1 = or1 < pixelsize ? pixelsize : or1;
+ pixelsize = min(len3(dif_second) * difl, extmax);
+ r2 = or2 < pixelsize ? pixelsize : or2;
+ }
+ /* --- */
+
+ float3 p21_diff = p2 - p1;
+ float3 sphere_dif1 = (dif + dif_second) * 0.5f;
+ float3 dir = direction;
+ float sphere_b_tmp = dot3(dir, sphere_dif1);
+ float3 sphere_dif2 = sphere_dif1 - sphere_b_tmp * dir;
+# else
+ ssef P_curve[2];
+
+ if (is_curve_primitive) {
+ P_curve[0] = load4f(&kg->__curve_keys.data[k0].x);
+ P_curve[1] = load4f(&kg->__curve_keys.data[k1].x);
+ }
+ else {
+ int fobject = (object == OBJECT_NONE) ? kernel_tex_fetch(__prim_object, curveAddr) : object;
+ motion_curve_keys(kg, fobject, prim, time, k0, k1, (float4 *)&P_curve);
+ }
+
+ const ssef or12 = shuffle<3, 3, 3, 3>(P_curve[0], P_curve[1]);
+
+ ssef r12 = or12;
+ const ssef vP = load4f(P);
+ const ssef dif = vP - P_curve[0];
+ const ssef dif_second = vP - P_curve[1];
+ if (difl != 0.0f) {
+ const ssef len1_sq = len3_squared_splat(dif);
+ const ssef len2_sq = len3_squared_splat(dif_second);
+ const ssef len12 = mm_sqrt(shuffle<0, 0, 0, 0>(len1_sq, len2_sq));
+ const ssef pixelsize12 = min(len12 * difl, ssef(extmax));
+ r12 = max(or12, pixelsize12);
+ }
+ float or1 = extract<0>(or12), or2 = extract<0>(shuffle<2>(or12));
+ float r1 = extract<0>(r12), r2 = extract<0>(shuffle<2>(r12));
+
+ const ssef p21_diff = P_curve[1] - P_curve[0];
+ const ssef sphere_dif1 = (dif + dif_second) * 0.5f;
+ const ssef dir = load4f(direction);
+ const ssef sphere_b_tmp = dot3_splat(dir, sphere_dif1);
+ const ssef sphere_dif2 = nmadd(sphere_b_tmp, dir, sphere_dif1);
+# endif
+
+ float mr = max(r1, r2);
+ float l = len3(p21_diff);
+ float invl = 1.0f / l;
+ float sp_r = mr + 0.5f * l;
+
+ float sphere_b = dot3(dir, sphere_dif2);
+ float sdisc = sphere_b * sphere_b - len3_squared(sphere_dif2) + sp_r * sp_r;
+
+ if (sdisc < 0.0f)
+ return false;
+
+ /* obtain parameters and test midpoint distance for suitable modes */
+# ifndef __KERNEL_SSE2__
+ float3 tg = p21_diff * invl;
+# else
+ const ssef tg = p21_diff * invl;
+# endif
+ float gd = (r2 - r1) * invl;
+
+ float dirz = dot3(dir, tg);
+ float difz = dot3(dif, tg);
+
+ float a = 1.0f - (dirz * dirz * (1 + gd * gd));
+
+ float halfb = dot3(dir, dif) - dirz * (difz + gd * (difz * gd + r1));
+
+ float tcentre = -halfb / a;
+ float zcentre = difz + (dirz * tcentre);
+
+ if ((tcentre > isect->t) && !(flags & CURVE_KN_ACCURATE))
+ return false;
+ if ((zcentre < 0 || zcentre > l) && !(flags & CURVE_KN_ACCURATE) &&
+ !(flags & CURVE_KN_INTERSECTCORRECTION))
+ return false;
+
+ /* test minimum separation */
+# ifndef __KERNEL_SSE2__
+ float3 cprod = cross(tg, dir);
+ float cprod2sq = len3_squared(cross(tg, dif));
+# else
+ const ssef cprod = cross(tg, dir);
+ float cprod2sq = len3_squared(cross_zxy(tg, dif));
+# endif
+ float cprodsq = len3_squared(cprod);
+ float distscaled = dot3(cprod, dif);
+
+ if (cprodsq == 0)
+ distscaled = cprod2sq;
+ else
+ distscaled = (distscaled * distscaled) / cprodsq;
+
+ if (distscaled > mr * mr)
+ return false;
+
+ /* calculate true intersection */
+# ifndef __KERNEL_SSE2__
+ float3 tdif = dif + tcentre * dir;
+# else
+ const ssef tdif = madd(ssef(tcentre), dir, dif);
+# endif
+ float tdifz = dot3(tdif, tg);
+ float tdifma = tdifz * gd + r1;
+ float tb = 2 * (dot3(dir, tdif) - dirz * (tdifz + gd * tdifma));
+ float tc = dot3(tdif, tdif) - tdifz * tdifz - tdifma * tdifma;
+ float td = tb * tb - 4 * a * tc;
+
+ if (td < 0.0f)
+ return false;
+
+ float rootd = 0.0f;
+ float correction = 0.0f;
+ if (flags & CURVE_KN_ACCURATE) {
+ rootd = sqrtf(td);
+ correction = ((-tb - rootd) / (2 * a));
+ }
+
+ float t = tcentre + correction;
+
+ if (t < isect->t) {
+
+ if (flags & CURVE_KN_INTERSECTCORRECTION) {
+ rootd = sqrtf(td);
+ correction = ((-tb - rootd) / (2 * a));
+ t = tcentre + correction;
+ }
+
+ float z = zcentre + (dirz * correction);
+ // bool backface = false;
+
+ if (flags & CURVE_KN_BACKFACING && (t < 0.0f || z < 0 || z > l)) {
+ // backface = true;
+ correction = ((-tb + rootd) / (2 * a));
+ t = tcentre + correction;
+ z = zcentre + (dirz * correction);
+ }
+
+ /* stochastic fade from minimum width */
+ float adjradius = or1 + z * (or2 - or1) * invl;
+ adjradius = adjradius / (r1 + z * gd);
+ if (lcg_state && adjradius != 1.0f) {
+ if (lcg_step_float(lcg_state) > adjradius)
+ return false;
+ }
+ /* --- */
+
+ if (t > 0.0f && t < isect->t && z >= 0 && z <= l) {
+
+ if (flags & CURVE_KN_ENCLOSEFILTER) {
+ float enc_ratio = 1.01f;
+ if ((difz > -r1 * enc_ratio) && (dot3(dif_second, tg) < r2 * enc_ratio)) {
+ float a2 = 1.0f - (dirz * dirz * (1 + gd * gd * enc_ratio * enc_ratio));
+ float c2 = dot3(dif, dif) - difz * difz * (1 + gd * gd * enc_ratio * enc_ratio) -
+ r1 * r1 * enc_ratio * enc_ratio - 2 * r1 * difz * gd * enc_ratio;
+ if (a2 * c2 < 0.0f)
+ return false;
+ }
+ }
+
+# ifdef __VISIBILITY_FLAG__
+ /* visibility flag test. we do it here under the assumption
+ * that most triangles are culled by node flags */
+ if (kernel_tex_fetch(__prim_visibility, curveAddr) & visibility)
+# endif
+ {
+ /* record intersection */
+ isect->t = t;
+ isect->u = z * invl;
+ isect->v = gd;
+ isect->prim = curveAddr;
+ isect->object = object;
+ isect->type = type;
+
+ return true;
+ }
+ }
+ }
+
+ return false;
+
+# ifndef __KERNEL_SSE2__
+# undef len3_squared
+# undef len3
+# undef dot3
+# endif
}
ccl_device_inline float3 curve_refine(KernelGlobals *kg,
@@ -757,154 +809,154 @@ ccl_device_inline float3 curve_refine(KernelGlobals *kg,
const Intersection *isect,
const Ray *ray)
{
- int flag = kernel_data.curve.curveflags;
- float t = isect->t;
- float3 P = ray->P;
- float3 D = ray->D;
-
- if(isect->object != OBJECT_NONE) {
-#ifdef __OBJECT_MOTION__
- Transform tfm = sd->ob_itfm;
-#else
- Transform tfm = object_fetch_transform(kg, isect->object, OBJECT_INVERSE_TRANSFORM);
-#endif
-
- P = transform_point(&tfm, P);
- D = transform_direction(&tfm, D*t);
- D = normalize_len(D, &t);
- }
-
- int prim = kernel_tex_fetch(__prim_index, isect->prim);
- float4 v00 = kernel_tex_fetch(__curves, prim);
-
- int k0 = __float_as_int(v00.x) + PRIMITIVE_UNPACK_SEGMENT(sd->type);
- int k1 = k0 + 1;
-
- float3 tg;
-
- if(flag & CURVE_KN_INTERPOLATE) {
- int ka = max(k0 - 1,__float_as_int(v00.x));
- int kb = min(k1 + 1,__float_as_int(v00.x) + __float_as_int(v00.y) - 1);
-
- float4 P_curve[4];
-
- if(sd->type & PRIMITIVE_CURVE) {
- P_curve[0] = kernel_tex_fetch(__curve_keys, ka);
- P_curve[1] = kernel_tex_fetch(__curve_keys, k0);
- P_curve[2] = kernel_tex_fetch(__curve_keys, k1);
- P_curve[3] = kernel_tex_fetch(__curve_keys, kb);
- }
- else {
- motion_cardinal_curve_keys(kg, sd->object, sd->prim, sd->time, ka, k0, k1, kb, P_curve);
- }
-
- float3 p[4];
- p[0] = float4_to_float3(P_curve[0]);
- p[1] = float4_to_float3(P_curve[1]);
- p[2] = float4_to_float3(P_curve[2]);
- p[3] = float4_to_float3(P_curve[3]);
-
- P = P + D*t;
-
-#ifdef __UV__
- sd->u = isect->u;
- sd->v = 0.0f;
-#endif
-
- tg = normalize(curvetangent(isect->u, p[0], p[1], p[2], p[3]));
-
- if(kernel_data.curve.curveflags & CURVE_KN_RIBBONS) {
- sd->Ng = normalize(-(D - tg * (dot(tg, D))));
- }
- else {
-#ifdef __EMBREE__
- if(kernel_data.bvh.scene) {
- sd->Ng = normalize(isect->Ng);
- }
- else
-#endif
- {
- /* direction from inside to surface of curve */
- float3 p_curr = curvepoint(isect->u, p[0], p[1], p[2], p[3]);
- sd->Ng = normalize(P - p_curr);
-
- /* adjustment for changing radius */
- float gd = isect->v;
-
- if(gd != 0.0f) {
- sd->Ng = sd->Ng - gd * tg;
- sd->Ng = normalize(sd->Ng);
- }
- }
- }
-
- /* todo: sometimes the normal is still so that this is detected as
- * backfacing even if cull backfaces is enabled */
-
- sd->N = sd->Ng;
- }
- else {
- float4 P_curve[2];
-
- if(sd->type & PRIMITIVE_CURVE) {
- P_curve[0]= kernel_tex_fetch(__curve_keys, k0);
- P_curve[1]= kernel_tex_fetch(__curve_keys, k1);
- }
- else {
- motion_curve_keys(kg, sd->object, sd->prim, sd->time, k0, k1, P_curve);
- }
-
- float l = 1.0f;
- tg = normalize_len(float4_to_float3(P_curve[1] - P_curve[0]), &l);
-
- P = P + D*t;
-
- float3 dif = P - float4_to_float3(P_curve[0]);
-
-#ifdef __UV__
- sd->u = dot(dif,tg)/l;
- sd->v = 0.0f;
-#endif
-
- if(flag & CURVE_KN_TRUETANGENTGNORMAL) {
- sd->Ng = -(D - tg * dot(tg, D));
- sd->Ng = normalize(sd->Ng);
- }
- else {
- float gd = isect->v;
-
- /* direction from inside to surface of curve */
- float denom = fmaxf(P_curve[0].w + sd->u * l * gd, 1e-8f);
- sd->Ng = (dif - tg * sd->u * l) / denom;
-
- /* adjustment for changing radius */
- if(gd != 0.0f) {
- sd->Ng = sd->Ng - gd * tg;
- }
-
- sd->Ng = normalize(sd->Ng);
- }
-
- sd->N = sd->Ng;
- }
-
-#ifdef __DPDU__
- /* dPdu/dPdv */
- sd->dPdu = tg;
- sd->dPdv = cross(tg, sd->Ng);
-#endif
-
- if(isect->object != OBJECT_NONE) {
-#ifdef __OBJECT_MOTION__
- Transform tfm = sd->ob_tfm;
-#else
- Transform tfm = object_fetch_transform(kg, isect->object, OBJECT_TRANSFORM);
-#endif
-
- P = transform_point(&tfm, P);
- }
-
- return P;
+ int flag = kernel_data.curve.curveflags;
+ float t = isect->t;
+ float3 P = ray->P;
+ float3 D = ray->D;
+
+ if (isect->object != OBJECT_NONE) {
+# ifdef __OBJECT_MOTION__
+ Transform tfm = sd->ob_itfm;
+# else
+ Transform tfm = object_fetch_transform(kg, isect->object, OBJECT_INVERSE_TRANSFORM);
+# endif
+
+ P = transform_point(&tfm, P);
+ D = transform_direction(&tfm, D * t);
+ D = normalize_len(D, &t);
+ }
+
+ int prim = kernel_tex_fetch(__prim_index, isect->prim);
+ float4 v00 = kernel_tex_fetch(__curves, prim);
+
+ int k0 = __float_as_int(v00.x) + PRIMITIVE_UNPACK_SEGMENT(sd->type);
+ int k1 = k0 + 1;
+
+ float3 tg;
+
+ if (flag & CURVE_KN_INTERPOLATE) {
+ int ka = max(k0 - 1, __float_as_int(v00.x));
+ int kb = min(k1 + 1, __float_as_int(v00.x) + __float_as_int(v00.y) - 1);
+
+ float4 P_curve[4];
+
+ if (sd->type & PRIMITIVE_CURVE) {
+ P_curve[0] = kernel_tex_fetch(__curve_keys, ka);
+ P_curve[1] = kernel_tex_fetch(__curve_keys, k0);
+ P_curve[2] = kernel_tex_fetch(__curve_keys, k1);
+ P_curve[3] = kernel_tex_fetch(__curve_keys, kb);
+ }
+ else {
+ motion_cardinal_curve_keys(kg, sd->object, sd->prim, sd->time, ka, k0, k1, kb, P_curve);
+ }
+
+ float3 p[4];
+ p[0] = float4_to_float3(P_curve[0]);
+ p[1] = float4_to_float3(P_curve[1]);
+ p[2] = float4_to_float3(P_curve[2]);
+ p[3] = float4_to_float3(P_curve[3]);
+
+ P = P + D * t;
+
+# ifdef __UV__
+ sd->u = isect->u;
+ sd->v = 0.0f;
+# endif
+
+ tg = normalize(curvetangent(isect->u, p[0], p[1], p[2], p[3]));
+
+ if (kernel_data.curve.curveflags & CURVE_KN_RIBBONS) {
+ sd->Ng = normalize(-(D - tg * (dot(tg, D))));
+ }
+ else {
+# ifdef __EMBREE__
+ if (kernel_data.bvh.scene) {
+ sd->Ng = normalize(isect->Ng);
+ }
+ else
+# endif
+ {
+ /* direction from inside to surface of curve */
+ float3 p_curr = curvepoint(isect->u, p[0], p[1], p[2], p[3]);
+ sd->Ng = normalize(P - p_curr);
+
+ /* adjustment for changing radius */
+ float gd = isect->v;
+
+ if (gd != 0.0f) {
+ sd->Ng = sd->Ng - gd * tg;
+ sd->Ng = normalize(sd->Ng);
+ }
+ }
+ }
+
+ /* todo: sometimes the normal is still so that this is detected as
+ * backfacing even if cull backfaces is enabled */
+
+ sd->N = sd->Ng;
+ }
+ else {
+ float4 P_curve[2];
+
+ if (sd->type & PRIMITIVE_CURVE) {
+ P_curve[0] = kernel_tex_fetch(__curve_keys, k0);
+ P_curve[1] = kernel_tex_fetch(__curve_keys, k1);
+ }
+ else {
+ motion_curve_keys(kg, sd->object, sd->prim, sd->time, k0, k1, P_curve);
+ }
+
+ float l = 1.0f;
+ tg = normalize_len(float4_to_float3(P_curve[1] - P_curve[0]), &l);
+
+ P = P + D * t;
+
+ float3 dif = P - float4_to_float3(P_curve[0]);
+
+# ifdef __UV__
+ sd->u = dot(dif, tg) / l;
+ sd->v = 0.0f;
+# endif
+
+ if (flag & CURVE_KN_TRUETANGENTGNORMAL) {
+ sd->Ng = -(D - tg * dot(tg, D));
+ sd->Ng = normalize(sd->Ng);
+ }
+ else {
+ float gd = isect->v;
+
+ /* direction from inside to surface of curve */
+ float denom = fmaxf(P_curve[0].w + sd->u * l * gd, 1e-8f);
+ sd->Ng = (dif - tg * sd->u * l) / denom;
+
+ /* adjustment for changing radius */
+ if (gd != 0.0f) {
+ sd->Ng = sd->Ng - gd * tg;
+ }
+
+ sd->Ng = normalize(sd->Ng);
+ }
+
+ sd->N = sd->Ng;
+ }
+
+# ifdef __DPDU__
+ /* dPdu/dPdv */
+ sd->dPdu = tg;
+ sd->dPdv = cross(tg, sd->Ng);
+# endif
+
+ if (isect->object != OBJECT_NONE) {
+# ifdef __OBJECT_MOTION__
+ Transform tfm = sd->ob_tfm;
+# else
+ Transform tfm = object_fetch_transform(kg, isect->object, OBJECT_TRANSFORM);
+# endif
+
+ P = transform_point(&tfm, P);
+ }
+
+ return P;
}
#endif
diff --git a/intern/cycles/kernel/geom/geom_motion_curve.h b/intern/cycles/kernel/geom/geom_motion_curve.h
index 5cc22ae2155..7380c506bf4 100644
--- a/intern/cycles/kernel/geom/geom_motion_curve.h
+++ b/intern/cycles/kernel/geom/geom_motion_curve.h
@@ -25,96 +25,116 @@ CCL_NAMESPACE_BEGIN
#ifdef __HAIR__
-ccl_device_inline int find_attribute_curve_motion(KernelGlobals *kg, int object, uint id, AttributeElement *elem)
+ccl_device_inline int find_attribute_curve_motion(KernelGlobals *kg,
+ int object,
+ uint id,
+ AttributeElement *elem)
{
- /* todo: find a better (faster) solution for this, maybe store offset per object.
- *
- * NOTE: currently it's not a bottleneck because in test scenes the loop below runs
- * zero iterations and rendering is really slow with motion curves. For until other
- * areas are speed up it's probably not so crucial to optimize this out.
- */
- uint attr_offset = object_attribute_map_offset(kg, object) + ATTR_PRIM_CURVE;
- uint4 attr_map = kernel_tex_fetch(__attributes_map, attr_offset);
-
- while(attr_map.x != id) {
- attr_offset += ATTR_PRIM_TYPES;
- attr_map = kernel_tex_fetch(__attributes_map, attr_offset);
- }
-
- *elem = (AttributeElement)attr_map.y;
-
- /* return result */
- return (attr_map.y == ATTR_ELEMENT_NONE) ? (int)ATTR_STD_NOT_FOUND : (int)attr_map.z;
+ /* todo: find a better (faster) solution for this, maybe store offset per object.
+ *
+ * NOTE: currently it's not a bottleneck because in test scenes the loop below runs
+ * zero iterations and rendering is really slow with motion curves. For until other
+ * areas are speed up it's probably not so crucial to optimize this out.
+ */
+ uint attr_offset = object_attribute_map_offset(kg, object) + ATTR_PRIM_CURVE;
+ uint4 attr_map = kernel_tex_fetch(__attributes_map, attr_offset);
+
+ while (attr_map.x != id) {
+ attr_offset += ATTR_PRIM_TYPES;
+ attr_map = kernel_tex_fetch(__attributes_map, attr_offset);
+ }
+
+ *elem = (AttributeElement)attr_map.y;
+
+ /* return result */
+ return (attr_map.y == ATTR_ELEMENT_NONE) ? (int)ATTR_STD_NOT_FOUND : (int)attr_map.z;
}
-ccl_device_inline void motion_curve_keys_for_step(KernelGlobals *kg, int offset, int numkeys, int numsteps, int step, int k0, int k1, float4 keys[2])
+ccl_device_inline void motion_curve_keys_for_step(KernelGlobals *kg,
+ int offset,
+ int numkeys,
+ int numsteps,
+ int step,
+ int k0,
+ int k1,
+ float4 keys[2])
{
- if(step == numsteps) {
- /* center step: regular key location */
- keys[0] = kernel_tex_fetch(__curve_keys, k0);
- keys[1] = kernel_tex_fetch(__curve_keys, k1);
- }
- else {
- /* center step is not stored in this array */
- if(step > numsteps)
- step--;
-
- offset += step*numkeys;
-
- keys[0] = kernel_tex_fetch(__attributes_float3, offset + k0);
- keys[1] = kernel_tex_fetch(__attributes_float3, offset + k1);
- }
+ if (step == numsteps) {
+ /* center step: regular key location */
+ keys[0] = kernel_tex_fetch(__curve_keys, k0);
+ keys[1] = kernel_tex_fetch(__curve_keys, k1);
+ }
+ else {
+ /* center step is not stored in this array */
+ if (step > numsteps)
+ step--;
+
+ offset += step * numkeys;
+
+ keys[0] = kernel_tex_fetch(__attributes_float3, offset + k0);
+ keys[1] = kernel_tex_fetch(__attributes_float3, offset + k1);
+ }
}
/* return 2 curve key locations */
-ccl_device_inline void motion_curve_keys(KernelGlobals *kg, int object, int prim, float time, int k0, int k1, float4 keys[2])
+ccl_device_inline void motion_curve_keys(
+ KernelGlobals *kg, int object, int prim, float time, int k0, int k1, float4 keys[2])
{
- /* get motion info */
- int numsteps, numkeys;
- object_motion_info(kg, object, &numsteps, NULL, &numkeys);
+ /* get motion info */
+ int numsteps, numkeys;
+ object_motion_info(kg, object, &numsteps, NULL, &numkeys);
- /* figure out which steps we need to fetch and their interpolation factor */
- int maxstep = numsteps*2;
- int step = min((int)(time*maxstep), maxstep-1);
- float t = time*maxstep - step;
+ /* figure out which steps we need to fetch and their interpolation factor */
+ int maxstep = numsteps * 2;
+ int step = min((int)(time * maxstep), maxstep - 1);
+ float t = time * maxstep - step;
- /* find attribute */
- AttributeElement elem;
- int offset = find_attribute_curve_motion(kg, object, ATTR_STD_MOTION_VERTEX_POSITION, &elem);
- kernel_assert(offset != ATTR_STD_NOT_FOUND);
+ /* find attribute */
+ AttributeElement elem;
+ int offset = find_attribute_curve_motion(kg, object, ATTR_STD_MOTION_VERTEX_POSITION, &elem);
+ kernel_assert(offset != ATTR_STD_NOT_FOUND);
- /* fetch key coordinates */
- float4 next_keys[2];
+ /* fetch key coordinates */
+ float4 next_keys[2];
- motion_curve_keys_for_step(kg, offset, numkeys, numsteps, step, k0, k1, keys);
- motion_curve_keys_for_step(kg, offset, numkeys, numsteps, step+1, k0, k1, next_keys);
+ motion_curve_keys_for_step(kg, offset, numkeys, numsteps, step, k0, k1, keys);
+ motion_curve_keys_for_step(kg, offset, numkeys, numsteps, step + 1, k0, k1, next_keys);
- /* interpolate between steps */
- keys[0] = (1.0f - t)*keys[0] + t*next_keys[0];
- keys[1] = (1.0f - t)*keys[1] + t*next_keys[1];
+ /* interpolate between steps */
+ keys[0] = (1.0f - t) * keys[0] + t * next_keys[0];
+ keys[1] = (1.0f - t) * keys[1] + t * next_keys[1];
}
-ccl_device_inline void motion_cardinal_curve_keys_for_step(KernelGlobals *kg, int offset, int numkeys, int numsteps, int step, int k0, int k1, int k2, int k3, float4 keys[4])
+ccl_device_inline void motion_cardinal_curve_keys_for_step(KernelGlobals *kg,
+ int offset,
+ int numkeys,
+ int numsteps,
+ int step,
+ int k0,
+ int k1,
+ int k2,
+ int k3,
+ float4 keys[4])
{
- if(step == numsteps) {
- /* center step: regular key location */
- keys[0] = kernel_tex_fetch(__curve_keys, k0);
- keys[1] = kernel_tex_fetch(__curve_keys, k1);
- keys[2] = kernel_tex_fetch(__curve_keys, k2);
- keys[3] = kernel_tex_fetch(__curve_keys, k3);
- }
- else {
- /* center step is not stored in this array */
- if(step > numsteps)
- step--;
-
- offset += step*numkeys;
-
- keys[0] = kernel_tex_fetch(__attributes_float3, offset + k0);
- keys[1] = kernel_tex_fetch(__attributes_float3, offset + k1);
- keys[2] = kernel_tex_fetch(__attributes_float3, offset + k2);
- keys[3] = kernel_tex_fetch(__attributes_float3, offset + k3);
- }
+ if (step == numsteps) {
+ /* center step: regular key location */
+ keys[0] = kernel_tex_fetch(__curve_keys, k0);
+ keys[1] = kernel_tex_fetch(__curve_keys, k1);
+ keys[2] = kernel_tex_fetch(__curve_keys, k2);
+ keys[3] = kernel_tex_fetch(__curve_keys, k3);
+ }
+ else {
+ /* center step is not stored in this array */
+ if (step > numsteps)
+ step--;
+
+ offset += step * numkeys;
+
+ keys[0] = kernel_tex_fetch(__attributes_float3, offset + k0);
+ keys[1] = kernel_tex_fetch(__attributes_float3, offset + k1);
+ keys[2] = kernel_tex_fetch(__attributes_float3, offset + k2);
+ keys[3] = kernel_tex_fetch(__attributes_float3, offset + k3);
+ }
}
/* return 2 curve key locations */
@@ -122,37 +142,41 @@ ccl_device_inline void motion_cardinal_curve_keys(KernelGlobals *kg,
int object,
int prim,
float time,
- int k0, int k1, int k2, int k3,
+ int k0,
+ int k1,
+ int k2,
+ int k3,
float4 keys[4])
{
- /* get motion info */
- int numsteps, numkeys;
- object_motion_info(kg, object, &numsteps, NULL, &numkeys);
-
- /* figure out which steps we need to fetch and their interpolation factor */
- int maxstep = numsteps*2;
- int step = min((int)(time*maxstep), maxstep-1);
- float t = time*maxstep - step;
-
- /* find attribute */
- AttributeElement elem;
- int offset = find_attribute_curve_motion(kg, object, ATTR_STD_MOTION_VERTEX_POSITION, &elem);
- kernel_assert(offset != ATTR_STD_NOT_FOUND);
-
- /* fetch key coordinates */
- float4 next_keys[4];
-
- motion_cardinal_curve_keys_for_step(kg, offset, numkeys, numsteps, step, k0, k1, k2, k3, keys);
- motion_cardinal_curve_keys_for_step(kg, offset, numkeys, numsteps, step+1, k0, k1, k2, k3, next_keys);
-
- /* interpolate between steps */
- keys[0] = (1.0f - t)*keys[0] + t*next_keys[0];
- keys[1] = (1.0f - t)*keys[1] + t*next_keys[1];
- keys[2] = (1.0f - t)*keys[2] + t*next_keys[2];
- keys[3] = (1.0f - t)*keys[3] + t*next_keys[3];
+ /* get motion info */
+ int numsteps, numkeys;
+ object_motion_info(kg, object, &numsteps, NULL, &numkeys);
+
+ /* figure out which steps we need to fetch and their interpolation factor */
+ int maxstep = numsteps * 2;
+ int step = min((int)(time * maxstep), maxstep - 1);
+ float t = time * maxstep - step;
+
+ /* find attribute */
+ AttributeElement elem;
+ int offset = find_attribute_curve_motion(kg, object, ATTR_STD_MOTION_VERTEX_POSITION, &elem);
+ kernel_assert(offset != ATTR_STD_NOT_FOUND);
+
+ /* fetch key coordinates */
+ float4 next_keys[4];
+
+ motion_cardinal_curve_keys_for_step(kg, offset, numkeys, numsteps, step, k0, k1, k2, k3, keys);
+ motion_cardinal_curve_keys_for_step(
+ kg, offset, numkeys, numsteps, step + 1, k0, k1, k2, k3, next_keys);
+
+ /* interpolate between steps */
+ keys[0] = (1.0f - t) * keys[0] + t * next_keys[0];
+ keys[1] = (1.0f - t) * keys[1] + t * next_keys[1];
+ keys[2] = (1.0f - t) * keys[2] + t * next_keys[2];
+ keys[3] = (1.0f - t) * keys[3] + t * next_keys[3];
}
-#if defined(__KERNEL_AVX2__) && defined(__KERNEL_SSE__)
+# if defined(__KERNEL_AVX2__) && defined(__KERNEL_SSE__)
/* Similar to above, but returns keys as pair of two AVX registers with each
* holding two float4.
*/
@@ -160,56 +184,44 @@ ccl_device_inline void motion_cardinal_curve_keys_avx(KernelGlobals *kg,
int object,
int prim,
float time,
- int k0, int k1,
- int k2, int k3,
+ int k0,
+ int k1,
+ int k2,
+ int k3,
avxf *out_keys_0_1,
avxf *out_keys_2_3)
{
- /* Get motion info. */
- int numsteps, numkeys;
- object_motion_info(kg, object, &numsteps, NULL, &numkeys);
-
- /* Figure out which steps we need to fetch and their interpolation factor. */
- int maxstep = numsteps * 2;
- int step = min((int)(time*maxstep), maxstep - 1);
- float t = time*maxstep - step;
-
- /* Find attribute. */
- AttributeElement elem;
- int offset = find_attribute_curve_motion(kg,
- object,
- ATTR_STD_MOTION_VERTEX_POSITION,
- &elem);
- kernel_assert(offset != ATTR_STD_NOT_FOUND);
-
- /* Fetch key coordinates. */
- float4 next_keys[4];
- float4 keys[4];
- motion_cardinal_curve_keys_for_step(kg,
- offset,
- numkeys,
- numsteps,
- step,
- k0, k1, k2, k3,
- keys);
- motion_cardinal_curve_keys_for_step(kg,
- offset,
- numkeys,
- numsteps,
- step + 1,
- k0, k1, k2, k3,
- next_keys);
-
- const avxf keys_0_1 = avxf(keys[0].m128, keys[1].m128);
- const avxf keys_2_3 = avxf(keys[2].m128, keys[3].m128);
- const avxf next_keys_0_1 = avxf(next_keys[0].m128, next_keys[1].m128);
- const avxf next_keys_2_3 = avxf(next_keys[2].m128, next_keys[3].m128);
-
- /* Interpolate between steps. */
- *out_keys_0_1 = (1.0f - t) * keys_0_1 + t*next_keys_0_1;
- *out_keys_2_3 = (1.0f - t) * keys_2_3 + t*next_keys_2_3;
+ /* Get motion info. */
+ int numsteps, numkeys;
+ object_motion_info(kg, object, &numsteps, NULL, &numkeys);
+
+ /* Figure out which steps we need to fetch and their interpolation factor. */
+ int maxstep = numsteps * 2;
+ int step = min((int)(time * maxstep), maxstep - 1);
+ float t = time * maxstep - step;
+
+ /* Find attribute. */
+ AttributeElement elem;
+ int offset = find_attribute_curve_motion(kg, object, ATTR_STD_MOTION_VERTEX_POSITION, &elem);
+ kernel_assert(offset != ATTR_STD_NOT_FOUND);
+
+ /* Fetch key coordinates. */
+ float4 next_keys[4];
+ float4 keys[4];
+ motion_cardinal_curve_keys_for_step(kg, offset, numkeys, numsteps, step, k0, k1, k2, k3, keys);
+ motion_cardinal_curve_keys_for_step(
+ kg, offset, numkeys, numsteps, step + 1, k0, k1, k2, k3, next_keys);
+
+ const avxf keys_0_1 = avxf(keys[0].m128, keys[1].m128);
+ const avxf keys_2_3 = avxf(keys[2].m128, keys[3].m128);
+ const avxf next_keys_0_1 = avxf(next_keys[0].m128, next_keys[1].m128);
+ const avxf next_keys_2_3 = avxf(next_keys[2].m128, next_keys[3].m128);
+
+ /* Interpolate between steps. */
+ *out_keys_0_1 = (1.0f - t) * keys_0_1 + t * next_keys_0_1;
+ *out_keys_2_3 = (1.0f - t) * keys_2_3 + t * next_keys_2_3;
}
-#endif
+# endif
#endif
diff --git a/intern/cycles/kernel/geom/geom_motion_triangle.h b/intern/cycles/kernel/geom/geom_motion_triangle.h
index 64f6d027b99..53d6b92dd7e 100644
--- a/intern/cycles/kernel/geom/geom_motion_triangle.h
+++ b/intern/cycles/kernel/geom/geom_motion_triangle.h
@@ -29,127 +29,145 @@ CCL_NAMESPACE_BEGIN
/* Time interpolation of vertex positions and normals */
-ccl_device_inline int find_attribute_motion(KernelGlobals *kg, int object, uint id, AttributeElement *elem)
+ccl_device_inline int find_attribute_motion(KernelGlobals *kg,
+ int object,
+ uint id,
+ AttributeElement *elem)
{
- /* todo: find a better (faster) solution for this, maybe store offset per object */
- uint attr_offset = object_attribute_map_offset(kg, object);
- uint4 attr_map = kernel_tex_fetch(__attributes_map, attr_offset);
+ /* todo: find a better (faster) solution for this, maybe store offset per object */
+ uint attr_offset = object_attribute_map_offset(kg, object);
+ uint4 attr_map = kernel_tex_fetch(__attributes_map, attr_offset);
- while(attr_map.x != id) {
- attr_offset += ATTR_PRIM_TYPES;
- attr_map = kernel_tex_fetch(__attributes_map, attr_offset);
- }
+ while (attr_map.x != id) {
+ attr_offset += ATTR_PRIM_TYPES;
+ attr_map = kernel_tex_fetch(__attributes_map, attr_offset);
+ }
- *elem = (AttributeElement)attr_map.y;
+ *elem = (AttributeElement)attr_map.y;
- /* return result */
- return (attr_map.y == ATTR_ELEMENT_NONE) ? (int)ATTR_STD_NOT_FOUND : (int)attr_map.z;
+ /* return result */
+ return (attr_map.y == ATTR_ELEMENT_NONE) ? (int)ATTR_STD_NOT_FOUND : (int)attr_map.z;
}
-ccl_device_inline void motion_triangle_verts_for_step(KernelGlobals *kg, uint4 tri_vindex, int offset, int numverts, int numsteps, int step, float3 verts[3])
+ccl_device_inline void motion_triangle_verts_for_step(KernelGlobals *kg,
+ uint4 tri_vindex,
+ int offset,
+ int numverts,
+ int numsteps,
+ int step,
+ float3 verts[3])
{
- if(step == numsteps) {
- /* center step: regular vertex location */
- verts[0] = float4_to_float3(kernel_tex_fetch(__prim_tri_verts, tri_vindex.w+0));
- verts[1] = float4_to_float3(kernel_tex_fetch(__prim_tri_verts, tri_vindex.w+1));
- verts[2] = float4_to_float3(kernel_tex_fetch(__prim_tri_verts, tri_vindex.w+2));
- }
- else {
- /* center step not store in this array */
- if(step > numsteps)
- step--;
-
- offset += step*numverts;
-
- verts[0] = float4_to_float3(kernel_tex_fetch(__attributes_float3, offset + tri_vindex.x));
- verts[1] = float4_to_float3(kernel_tex_fetch(__attributes_float3, offset + tri_vindex.y));
- verts[2] = float4_to_float3(kernel_tex_fetch(__attributes_float3, offset + tri_vindex.z));
- }
+ if (step == numsteps) {
+ /* center step: regular vertex location */
+ verts[0] = float4_to_float3(kernel_tex_fetch(__prim_tri_verts, tri_vindex.w + 0));
+ verts[1] = float4_to_float3(kernel_tex_fetch(__prim_tri_verts, tri_vindex.w + 1));
+ verts[2] = float4_to_float3(kernel_tex_fetch(__prim_tri_verts, tri_vindex.w + 2));
+ }
+ else {
+ /* center step not store in this array */
+ if (step > numsteps)
+ step--;
+
+ offset += step * numverts;
+
+ verts[0] = float4_to_float3(kernel_tex_fetch(__attributes_float3, offset + tri_vindex.x));
+ verts[1] = float4_to_float3(kernel_tex_fetch(__attributes_float3, offset + tri_vindex.y));
+ verts[2] = float4_to_float3(kernel_tex_fetch(__attributes_float3, offset + tri_vindex.z));
+ }
}
-ccl_device_inline void motion_triangle_normals_for_step(KernelGlobals *kg, uint4 tri_vindex, int offset, int numverts, int numsteps, int step, float3 normals[3])
+ccl_device_inline void motion_triangle_normals_for_step(KernelGlobals *kg,
+ uint4 tri_vindex,
+ int offset,
+ int numverts,
+ int numsteps,
+ int step,
+ float3 normals[3])
{
- if(step == numsteps) {
- /* center step: regular vertex location */
- normals[0] = float4_to_float3(kernel_tex_fetch(__tri_vnormal, tri_vindex.x));
- normals[1] = float4_to_float3(kernel_tex_fetch(__tri_vnormal, tri_vindex.y));
- normals[2] = float4_to_float3(kernel_tex_fetch(__tri_vnormal, tri_vindex.z));
- }
- else {
- /* center step is not stored in this array */
- if(step > numsteps)
- step--;
-
- offset += step*numverts;
-
- normals[0] = float4_to_float3(kernel_tex_fetch(__attributes_float3, offset + tri_vindex.x));
- normals[1] = float4_to_float3(kernel_tex_fetch(__attributes_float3, offset + tri_vindex.y));
- normals[2] = float4_to_float3(kernel_tex_fetch(__attributes_float3, offset + tri_vindex.z));
- }
+ if (step == numsteps) {
+ /* center step: regular vertex location */
+ normals[0] = float4_to_float3(kernel_tex_fetch(__tri_vnormal, tri_vindex.x));
+ normals[1] = float4_to_float3(kernel_tex_fetch(__tri_vnormal, tri_vindex.y));
+ normals[2] = float4_to_float3(kernel_tex_fetch(__tri_vnormal, tri_vindex.z));
+ }
+ else {
+ /* center step is not stored in this array */
+ if (step > numsteps)
+ step--;
+
+ offset += step * numverts;
+
+ normals[0] = float4_to_float3(kernel_tex_fetch(__attributes_float3, offset + tri_vindex.x));
+ normals[1] = float4_to_float3(kernel_tex_fetch(__attributes_float3, offset + tri_vindex.y));
+ normals[2] = float4_to_float3(kernel_tex_fetch(__attributes_float3, offset + tri_vindex.z));
+ }
}
-ccl_device_inline void motion_triangle_vertices(KernelGlobals *kg, int object, int prim, float time, float3 verts[3])
+ccl_device_inline void motion_triangle_vertices(
+ KernelGlobals *kg, int object, int prim, float time, float3 verts[3])
{
- /* get motion info */
- int numsteps, numverts;
- object_motion_info(kg, object, &numsteps, &numverts, NULL);
-
- /* figure out which steps we need to fetch and their interpolation factor */
- int maxstep = numsteps*2;
- int step = min((int)(time*maxstep), maxstep-1);
- float t = time*maxstep - step;
-
- /* find attribute */
- AttributeElement elem;
- int offset = find_attribute_motion(kg, object, ATTR_STD_MOTION_VERTEX_POSITION, &elem);
- kernel_assert(offset != ATTR_STD_NOT_FOUND);
-
- /* fetch vertex coordinates */
- float3 next_verts[3];
- uint4 tri_vindex = kernel_tex_fetch(__tri_vindex, prim);
-
- motion_triangle_verts_for_step(kg, tri_vindex, offset, numverts, numsteps, step, verts);
- motion_triangle_verts_for_step(kg, tri_vindex, offset, numverts, numsteps, step+1, next_verts);
-
- /* interpolate between steps */
- verts[0] = (1.0f - t)*verts[0] + t*next_verts[0];
- verts[1] = (1.0f - t)*verts[1] + t*next_verts[1];
- verts[2] = (1.0f - t)*verts[2] + t*next_verts[2];
+ /* get motion info */
+ int numsteps, numverts;
+ object_motion_info(kg, object, &numsteps, &numverts, NULL);
+
+ /* figure out which steps we need to fetch and their interpolation factor */
+ int maxstep = numsteps * 2;
+ int step = min((int)(time * maxstep), maxstep - 1);
+ float t = time * maxstep - step;
+
+ /* find attribute */
+ AttributeElement elem;
+ int offset = find_attribute_motion(kg, object, ATTR_STD_MOTION_VERTEX_POSITION, &elem);
+ kernel_assert(offset != ATTR_STD_NOT_FOUND);
+
+ /* fetch vertex coordinates */
+ float3 next_verts[3];
+ uint4 tri_vindex = kernel_tex_fetch(__tri_vindex, prim);
+
+ motion_triangle_verts_for_step(kg, tri_vindex, offset, numverts, numsteps, step, verts);
+ motion_triangle_verts_for_step(kg, tri_vindex, offset, numverts, numsteps, step + 1, next_verts);
+
+ /* interpolate between steps */
+ verts[0] = (1.0f - t) * verts[0] + t * next_verts[0];
+ verts[1] = (1.0f - t) * verts[1] + t * next_verts[1];
+ verts[2] = (1.0f - t) * verts[2] + t * next_verts[2];
}
-ccl_device_inline float3 motion_triangle_smooth_normal(KernelGlobals *kg, float3 Ng, int object, int prim, float u, float v, float time)
+ccl_device_inline float3 motion_triangle_smooth_normal(
+ KernelGlobals *kg, float3 Ng, int object, int prim, float u, float v, float time)
{
- /* get motion info */
- int numsteps, numverts;
- object_motion_info(kg, object, &numsteps, &numverts, NULL);
-
- /* figure out which steps we need to fetch and their interpolation factor */
- int maxstep = numsteps*2;
- int step = min((int)(time*maxstep), maxstep-1);
- float t = time*maxstep - step;
-
- /* find attribute */
- AttributeElement elem;
- int offset = find_attribute_motion(kg, object, ATTR_STD_MOTION_VERTEX_NORMAL, &elem);
- kernel_assert(offset != ATTR_STD_NOT_FOUND);
-
- /* fetch normals */
- float3 normals[3], next_normals[3];
- uint4 tri_vindex = kernel_tex_fetch(__tri_vindex, prim);
-
- motion_triangle_normals_for_step(kg, tri_vindex, offset, numverts, numsteps, step, normals);
- motion_triangle_normals_for_step(kg, tri_vindex, offset, numverts, numsteps, step+1, next_normals);
-
- /* interpolate between steps */
- normals[0] = (1.0f - t)*normals[0] + t*next_normals[0];
- normals[1] = (1.0f - t)*normals[1] + t*next_normals[1];
- normals[2] = (1.0f - t)*normals[2] + t*next_normals[2];
-
- /* interpolate between vertices */
- float w = 1.0f - u - v;
- float3 N = safe_normalize(u*normals[0] + v*normals[1] + w*normals[2]);
-
- return is_zero(N)? Ng: N;
+ /* get motion info */
+ int numsteps, numverts;
+ object_motion_info(kg, object, &numsteps, &numverts, NULL);
+
+ /* figure out which steps we need to fetch and their interpolation factor */
+ int maxstep = numsteps * 2;
+ int step = min((int)(time * maxstep), maxstep - 1);
+ float t = time * maxstep - step;
+
+ /* find attribute */
+ AttributeElement elem;
+ int offset = find_attribute_motion(kg, object, ATTR_STD_MOTION_VERTEX_NORMAL, &elem);
+ kernel_assert(offset != ATTR_STD_NOT_FOUND);
+
+ /* fetch normals */
+ float3 normals[3], next_normals[3];
+ uint4 tri_vindex = kernel_tex_fetch(__tri_vindex, prim);
+
+ motion_triangle_normals_for_step(kg, tri_vindex, offset, numverts, numsteps, step, normals);
+ motion_triangle_normals_for_step(
+ kg, tri_vindex, offset, numverts, numsteps, step + 1, next_normals);
+
+ /* interpolate between steps */
+ normals[0] = (1.0f - t) * normals[0] + t * next_normals[0];
+ normals[1] = (1.0f - t) * normals[1] + t * next_normals[1];
+ normals[2] = (1.0f - t) * normals[2] + t * next_normals[2];
+
+ /* interpolate between vertices */
+ float w = 1.0f - u - v;
+ float3 N = safe_normalize(u * normals[0] + v * normals[1] + w * normals[2]);
+
+ return is_zero(N) ? Ng : N;
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/geom/geom_motion_triangle_intersect.h b/intern/cycles/kernel/geom/geom_motion_triangle_intersect.h
index ec7bfad7349..49d4829af38 100644
--- a/intern/cycles/kernel/geom/geom_motion_triangle_intersect.h
+++ b/intern/cycles/kernel/geom/geom_motion_triangle_intersect.h
@@ -32,64 +32,57 @@ CCL_NAMESPACE_BEGIN
* a closer distance.
*/
-ccl_device_inline float3 motion_triangle_refine(KernelGlobals *kg,
- ShaderData *sd,
- const Intersection *isect,
- const Ray *ray,
- float3 verts[3])
+ccl_device_inline float3 motion_triangle_refine(
+ KernelGlobals *kg, ShaderData *sd, const Intersection *isect, const Ray *ray, float3 verts[3])
{
- float3 P = ray->P;
- float3 D = ray->D;
- float t = isect->t;
+ float3 P = ray->P;
+ float3 D = ray->D;
+ float t = isect->t;
#ifdef __INTERSECTION_REFINE__
- if(isect->object != OBJECT_NONE) {
- if(UNLIKELY(t == 0.0f)) {
- return P;
- }
+ if (isect->object != OBJECT_NONE) {
+ if (UNLIKELY(t == 0.0f)) {
+ return P;
+ }
# ifdef __OBJECT_MOTION__
- Transform tfm = sd->ob_itfm;
+ Transform tfm = sd->ob_itfm;
# else
- Transform tfm = object_fetch_transform(kg,
- isect->object,
- OBJECT_INVERSE_TRANSFORM);
+ Transform tfm = object_fetch_transform(kg, isect->object, OBJECT_INVERSE_TRANSFORM);
# endif
- P = transform_point(&tfm, P);
- D = transform_direction(&tfm, D*t);
- D = normalize_len(D, &t);
- }
+ P = transform_point(&tfm, P);
+ D = transform_direction(&tfm, D * t);
+ D = normalize_len(D, &t);
+ }
- P = P + D*t;
+ P = P + D * t;
- /* Compute refined intersection distance. */
- const float3 e1 = verts[0] - verts[2];
- const float3 e2 = verts[1] - verts[2];
- const float3 s1 = cross(D, e2);
+ /* Compute refined intersection distance. */
+ const float3 e1 = verts[0] - verts[2];
+ const float3 e2 = verts[1] - verts[2];
+ const float3 s1 = cross(D, e2);
- const float invdivisor = 1.0f/dot(s1, e1);
- const float3 d = P - verts[2];
- const float3 s2 = cross(d, e1);
- float rt = dot(e2, s2)*invdivisor;
+ const float invdivisor = 1.0f / dot(s1, e1);
+ const float3 d = P - verts[2];
+ const float3 s2 = cross(d, e1);
+ float rt = dot(e2, s2) * invdivisor;
- /* Compute refined position. */
- P = P + D*rt;
+ /* Compute refined position. */
+ P = P + D * rt;
- if(isect->object != OBJECT_NONE) {
+ if (isect->object != OBJECT_NONE) {
# ifdef __OBJECT_MOTION__
- Transform tfm = sd->ob_tfm;
+ Transform tfm = sd->ob_tfm;
# else
- Transform tfm = object_fetch_transform(kg,
- isect->object,
- OBJECT_TRANSFORM);
+ Transform tfm = object_fetch_transform(kg, isect->object, OBJECT_TRANSFORM);
# endif
- P = transform_point(&tfm, P);
- }
+ P = transform_point(&tfm, P);
+ }
- return P;
+ return P;
#else
- return P + D*t;
+ return P + D * t;
#endif
}
@@ -103,116 +96,112 @@ ccl_device_noinline
# else
ccl_device_inline
# endif
-float3 motion_triangle_refine_local(KernelGlobals *kg,
- ShaderData *sd,
- const Intersection *isect,
- const Ray *ray,
- float3 verts[3])
+ float3
+ motion_triangle_refine_local(KernelGlobals *kg,
+ ShaderData *sd,
+ const Intersection *isect,
+ const Ray *ray,
+ float3 verts[3])
{
- float3 P = ray->P;
- float3 D = ray->D;
- float t = isect->t;
+ float3 P = ray->P;
+ float3 D = ray->D;
+ float t = isect->t;
# ifdef __INTERSECTION_REFINE__
- if(isect->object != OBJECT_NONE) {
+ if (isect->object != OBJECT_NONE) {
# ifdef __OBJECT_MOTION__
- Transform tfm = sd->ob_itfm;
+ Transform tfm = sd->ob_itfm;
# else
- Transform tfm = object_fetch_transform(kg,
- isect->object,
- OBJECT_INVERSE_TRANSFORM);
+ Transform tfm = object_fetch_transform(kg, isect->object, OBJECT_INVERSE_TRANSFORM);
# endif
- P = transform_point(&tfm, P);
- D = transform_direction(&tfm, D);
- D = normalize(D);
- }
+ P = transform_point(&tfm, P);
+ D = transform_direction(&tfm, D);
+ D = normalize(D);
+ }
- P = P + D*t;
+ P = P + D * t;
- /* compute refined intersection distance */
- const float3 e1 = verts[0] - verts[2];
- const float3 e2 = verts[1] - verts[2];
- const float3 s1 = cross(D, e2);
+ /* compute refined intersection distance */
+ const float3 e1 = verts[0] - verts[2];
+ const float3 e2 = verts[1] - verts[2];
+ const float3 s1 = cross(D, e2);
- const float invdivisor = 1.0f/dot(s1, e1);
- const float3 d = P - verts[2];
- const float3 s2 = cross(d, e1);
- float rt = dot(e2, s2)*invdivisor;
+ const float invdivisor = 1.0f / dot(s1, e1);
+ const float3 d = P - verts[2];
+ const float3 s2 = cross(d, e1);
+ float rt = dot(e2, s2) * invdivisor;
- P = P + D*rt;
+ P = P + D * rt;
- if(isect->object != OBJECT_NONE) {
+ if (isect->object != OBJECT_NONE) {
# ifdef __OBJECT_MOTION__
- Transform tfm = sd->ob_tfm;
+ Transform tfm = sd->ob_tfm;
# else
- Transform tfm = object_fetch_transform(kg,
- isect->object,
- OBJECT_TRANSFORM);
+ Transform tfm = object_fetch_transform(kg, isect->object, OBJECT_TRANSFORM);
# endif
- P = transform_point(&tfm, P);
- }
+ P = transform_point(&tfm, P);
+ }
- return P;
+ return P;
# else /* __INTERSECTION_REFINE__ */
- return P + D*t;
-# endif /* __INTERSECTION_REFINE__ */
+ return P + D * t;
+# endif /* __INTERSECTION_REFINE__ */
}
-#endif /* __BVH_LOCAL__ */
-
+#endif /* __BVH_LOCAL__ */
/* Ray intersection. We simply compute the vertex positions at the given ray
* time and do a ray intersection with the resulting triangle.
*/
-ccl_device_inline bool motion_triangle_intersect(
- KernelGlobals *kg,
- Intersection *isect,
- float3 P,
- float3 dir,
- float time,
- uint visibility,
- int object,
- int prim_addr)
+ccl_device_inline bool motion_triangle_intersect(KernelGlobals *kg,
+ Intersection *isect,
+ float3 P,
+ float3 dir,
+ float time,
+ uint visibility,
+ int object,
+ int prim_addr)
{
- /* Primitive index for vertex location lookup. */
- int prim = kernel_tex_fetch(__prim_index, prim_addr);
- int fobject = (object == OBJECT_NONE)
- ? kernel_tex_fetch(__prim_object, prim_addr)
- : object;
- /* Get vertex locations for intersection. */
- float3 verts[3];
- motion_triangle_vertices(kg, fobject, prim, time, verts);
- /* Ray-triangle intersection, unoptimized. */
- float t, u, v;
- if(ray_triangle_intersect(P,
- dir,
- isect->t,
+ /* Primitive index for vertex location lookup. */
+ int prim = kernel_tex_fetch(__prim_index, prim_addr);
+ int fobject = (object == OBJECT_NONE) ? kernel_tex_fetch(__prim_object, prim_addr) : object;
+ /* Get vertex locations for intersection. */
+ float3 verts[3];
+ motion_triangle_vertices(kg, fobject, prim, time, verts);
+ /* Ray-triangle intersection, unoptimized. */
+ float t, u, v;
+ if (ray_triangle_intersect(P,
+ dir,
+ isect->t,
#if defined(__KERNEL_SSE2__) && defined(__KERNEL_SSE__)
- (ssef*)verts,
+ (ssef *)verts,
#else
- verts[0], verts[1], verts[2],
+ verts[0],
+ verts[1],
+ verts[2],
#endif
- &u, &v, &t))
- {
+ &u,
+ &v,
+ &t)) {
#ifdef __VISIBILITY_FLAG__
- /* Visibility flag test. we do it here under the assumption
- * that most triangles are culled by node flags.
- */
- if(kernel_tex_fetch(__prim_visibility, prim_addr) & visibility)
+ /* Visibility flag test. we do it here under the assumption
+ * that most triangles are culled by node flags.
+ */
+ if (kernel_tex_fetch(__prim_visibility, prim_addr) & visibility)
#endif
- {
- isect->t = t;
- isect->u = u;
- isect->v = v;
- isect->prim = prim_addr;
- isect->object = object;
- isect->type = PRIMITIVE_MOTION_TRIANGLE;
- return true;
- }
- }
- return false;
+ {
+ isect->t = t;
+ isect->u = u;
+ isect->v = v;
+ isect->prim = prim_addr;
+ isect->object = object;
+ isect->type = PRIMITIVE_MOTION_TRIANGLE;
+ return true;
+ }
+ }
+ return false;
}
/* Special ray intersection routines for local intersections. In that case we
@@ -221,101 +210,102 @@ ccl_device_inline bool motion_triangle_intersect(
* Returns whether traversal should be stopped.
*/
#ifdef __BVH_LOCAL__
-ccl_device_inline bool motion_triangle_intersect_local(
- KernelGlobals *kg,
- LocalIntersection *local_isect,
- float3 P,
- float3 dir,
- float time,
- int object,
- int local_object,
- int prim_addr,
- float tmax,
- uint *lcg_state,
- int max_hits)
+ccl_device_inline bool motion_triangle_intersect_local(KernelGlobals *kg,
+ LocalIntersection *local_isect,
+ float3 P,
+ float3 dir,
+ float time,
+ int object,
+ int local_object,
+ int prim_addr,
+ float tmax,
+ uint *lcg_state,
+ int max_hits)
{
- /* Only intersect with matching object, for instanced objects we
- * already know we are only intersecting the right object. */
- if(object == OBJECT_NONE) {
- if(kernel_tex_fetch(__prim_object, prim_addr) != local_object) {
- return false;
- }
- }
-
- /* Primitive index for vertex location lookup. */
- int prim = kernel_tex_fetch(__prim_index, prim_addr);
- /* Get vertex locations for intersection. */
- float3 verts[3];
- motion_triangle_vertices(kg, local_object, prim, time, verts);
- /* Ray-triangle intersection, unoptimized. */
- float t, u, v;
- if(!ray_triangle_intersect(P,
- dir,
- tmax,
-#if defined(__KERNEL_SSE2__) && defined(__KERNEL_SSE__)
- (ssef*)verts,
-#else
- verts[0], verts[1], verts[2],
-#endif
- &u, &v, &t))
- {
- return false;
- }
-
- /* If no actual hit information is requested, just return here. */
- if(max_hits == 0) {
- return true;
- }
-
- int hit;
- if(lcg_state) {
- /* Record up to max_hits intersections. */
- for(int i = min(max_hits, local_isect->num_hits) - 1; i >= 0; --i) {
- if(local_isect->hits[i].t == t) {
- return false;
- }
- }
-
- local_isect->num_hits++;
-
- if(local_isect->num_hits <= max_hits) {
- hit = local_isect->num_hits - 1;
- }
- else {
- /* Reservoir sampling: if we are at the maximum number of
- * hits, randomly replace element or skip it.
- */
- hit = lcg_step_uint(lcg_state) % local_isect->num_hits;
-
- if(hit >= max_hits)
- return false;
- }
- }
- else {
- /* Record closest intersection only. */
- if(local_isect->num_hits && t > local_isect->hits[0].t) {
- return false;
- }
-
- hit = 0;
- local_isect->num_hits = 1;
- }
-
- /* Record intersection. */
- Intersection *isect = &local_isect->hits[hit];
- isect->t = t;
- isect->u = u;
- isect->v = v;
- isect->prim = prim_addr;
- isect->object = object;
- isect->type = PRIMITIVE_MOTION_TRIANGLE;
-
- /* Record geometric normal. */
- local_isect->Ng[hit] = normalize(cross(verts[1] - verts[0],
- verts[2] - verts[0]));
-
- return false;
+ /* Only intersect with matching object, for instanced objects we
+ * already know we are only intersecting the right object. */
+ if (object == OBJECT_NONE) {
+ if (kernel_tex_fetch(__prim_object, prim_addr) != local_object) {
+ return false;
+ }
+ }
+
+ /* Primitive index for vertex location lookup. */
+ int prim = kernel_tex_fetch(__prim_index, prim_addr);
+ /* Get vertex locations for intersection. */
+ float3 verts[3];
+ motion_triangle_vertices(kg, local_object, prim, time, verts);
+ /* Ray-triangle intersection, unoptimized. */
+ float t, u, v;
+ if (!ray_triangle_intersect(P,
+ dir,
+ tmax,
+# if defined(__KERNEL_SSE2__) && defined(__KERNEL_SSE__)
+ (ssef *)verts,
+# else
+ verts[0],
+ verts[1],
+ verts[2],
+# endif
+ &u,
+ &v,
+ &t)) {
+ return false;
+ }
+
+ /* If no actual hit information is requested, just return here. */
+ if (max_hits == 0) {
+ return true;
+ }
+
+ int hit;
+ if (lcg_state) {
+ /* Record up to max_hits intersections. */
+ for (int i = min(max_hits, local_isect->num_hits) - 1; i >= 0; --i) {
+ if (local_isect->hits[i].t == t) {
+ return false;
+ }
+ }
+
+ local_isect->num_hits++;
+
+ if (local_isect->num_hits <= max_hits) {
+ hit = local_isect->num_hits - 1;
+ }
+ else {
+ /* Reservoir sampling: if we are at the maximum number of
+ * hits, randomly replace element or skip it.
+ */
+ hit = lcg_step_uint(lcg_state) % local_isect->num_hits;
+
+ if (hit >= max_hits)
+ return false;
+ }
+ }
+ else {
+ /* Record closest intersection only. */
+ if (local_isect->num_hits && t > local_isect->hits[0].t) {
+ return false;
+ }
+
+ hit = 0;
+ local_isect->num_hits = 1;
+ }
+
+ /* Record intersection. */
+ Intersection *isect = &local_isect->hits[hit];
+ isect->t = t;
+ isect->u = u;
+ isect->v = v;
+ isect->prim = prim_addr;
+ isect->object = object;
+ isect->type = PRIMITIVE_MOTION_TRIANGLE;
+
+ /* Record geometric normal. */
+ local_isect->Ng[hit] = normalize(cross(verts[1] - verts[0], verts[2] - verts[0]));
+
+ return false;
}
-#endif /* __BVH_LOCAL__ */
+#endif /* __BVH_LOCAL__ */
CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/geom/geom_motion_triangle_shader.h b/intern/cycles/kernel/geom/geom_motion_triangle_shader.h
index e91a4be96ba..5333e82b346 100644
--- a/intern/cycles/kernel/geom/geom_motion_triangle_shader.h
+++ b/intern/cycles/kernel/geom/geom_motion_triangle_shader.h
@@ -32,91 +32,80 @@ CCL_NAMESPACE_BEGIN
* normals */
/* return 3 triangle vertex normals */
-ccl_device_noinline void motion_triangle_shader_setup(KernelGlobals *kg,
- ShaderData *sd, const
- Intersection *isect,
- const Ray *ray,
- bool is_local)
+ccl_device_noinline void motion_triangle_shader_setup(
+ KernelGlobals *kg, ShaderData *sd, const Intersection *isect, const Ray *ray, bool is_local)
{
- /* Get shader. */
- sd->shader = kernel_tex_fetch(__tri_shader, sd->prim);
- /* Get motion info. */
- /* TODO(sergey): This logic is really similar to motion_triangle_vertices(),
- * can we de-duplicate something here?
- */
- int numsteps, numverts;
- object_motion_info(kg, sd->object, &numsteps, &numverts, NULL);
- /* Figure out which steps we need to fetch and their interpolation factor. */
- int maxstep = numsteps*2;
- int step = min((int)(sd->time*maxstep), maxstep-1);
- float t = sd->time*maxstep - step;
- /* Find attribute. */
- AttributeElement elem;
- int offset = find_attribute_motion(kg, sd->object,
- ATTR_STD_MOTION_VERTEX_POSITION,
- &elem);
- kernel_assert(offset != ATTR_STD_NOT_FOUND);
- /* Fetch vertex coordinates. */
- float3 verts[3], next_verts[3];
- uint4 tri_vindex = kernel_tex_fetch(__tri_vindex, sd->prim);
- motion_triangle_verts_for_step(kg, tri_vindex, offset, numverts, numsteps, step, verts);
- motion_triangle_verts_for_step(kg, tri_vindex, offset, numverts, numsteps, step+1, next_verts);
- /* Interpolate between steps. */
- verts[0] = (1.0f - t)*verts[0] + t*next_verts[0];
- verts[1] = (1.0f - t)*verts[1] + t*next_verts[1];
- verts[2] = (1.0f - t)*verts[2] + t*next_verts[2];
- /* Compute refined position. */
+ /* Get shader. */
+ sd->shader = kernel_tex_fetch(__tri_shader, sd->prim);
+ /* Get motion info. */
+ /* TODO(sergey): This logic is really similar to motion_triangle_vertices(),
+ * can we de-duplicate something here?
+ */
+ int numsteps, numverts;
+ object_motion_info(kg, sd->object, &numsteps, &numverts, NULL);
+ /* Figure out which steps we need to fetch and their interpolation factor. */
+ int maxstep = numsteps * 2;
+ int step = min((int)(sd->time * maxstep), maxstep - 1);
+ float t = sd->time * maxstep - step;
+ /* Find attribute. */
+ AttributeElement elem;
+ int offset = find_attribute_motion(kg, sd->object, ATTR_STD_MOTION_VERTEX_POSITION, &elem);
+ kernel_assert(offset != ATTR_STD_NOT_FOUND);
+ /* Fetch vertex coordinates. */
+ float3 verts[3], next_verts[3];
+ uint4 tri_vindex = kernel_tex_fetch(__tri_vindex, sd->prim);
+ motion_triangle_verts_for_step(kg, tri_vindex, offset, numverts, numsteps, step, verts);
+ motion_triangle_verts_for_step(kg, tri_vindex, offset, numverts, numsteps, step + 1, next_verts);
+ /* Interpolate between steps. */
+ verts[0] = (1.0f - t) * verts[0] + t * next_verts[0];
+ verts[1] = (1.0f - t) * verts[1] + t * next_verts[1];
+ verts[2] = (1.0f - t) * verts[2] + t * next_verts[2];
+ /* Compute refined position. */
#ifdef __BVH_LOCAL__
- if(is_local) {
- sd->P = motion_triangle_refine_local(kg,
- sd,
- isect,
- ray,
- verts);
- }
- else
-#endif /* __BVH_LOCAL__*/
- {
- sd->P = motion_triangle_refine(kg, sd, isect, ray, verts);
- }
- /* Compute face normal. */
- float3 Ng;
- if(sd->object_flag & SD_OBJECT_NEGATIVE_SCALE_APPLIED) {
- Ng = normalize(cross(verts[2] - verts[0], verts[1] - verts[0]));
- }
- else {
- Ng = normalize(cross(verts[1] - verts[0], verts[2] - verts[0]));
- }
- sd->Ng = Ng;
- sd->N = Ng;
- /* Compute derivatives of P w.r.t. uv. */
+ if (is_local) {
+ sd->P = motion_triangle_refine_local(kg, sd, isect, ray, verts);
+ }
+ else
+#endif /* __BVH_LOCAL__*/
+ {
+ sd->P = motion_triangle_refine(kg, sd, isect, ray, verts);
+ }
+ /* Compute face normal. */
+ float3 Ng;
+ if (sd->object_flag & SD_OBJECT_NEGATIVE_SCALE_APPLIED) {
+ Ng = normalize(cross(verts[2] - verts[0], verts[1] - verts[0]));
+ }
+ else {
+ Ng = normalize(cross(verts[1] - verts[0], verts[2] - verts[0]));
+ }
+ sd->Ng = Ng;
+ sd->N = Ng;
+ /* Compute derivatives of P w.r.t. uv. */
#ifdef __DPDU__
- sd->dPdu = (verts[0] - verts[2]);
- sd->dPdv = (verts[1] - verts[2]);
+ sd->dPdu = (verts[0] - verts[2]);
+ sd->dPdv = (verts[1] - verts[2]);
#endif
- /* Compute smooth normal. */
- if(sd->shader & SHADER_SMOOTH_NORMAL) {
- /* Find attribute. */
- AttributeElement elem;
- int offset = find_attribute_motion(kg,
- sd->object,
- ATTR_STD_MOTION_VERTEX_NORMAL,
- &elem);
- kernel_assert(offset != ATTR_STD_NOT_FOUND);
- /* Fetch vertex coordinates. */
- float3 normals[3], next_normals[3];
- motion_triangle_normals_for_step(kg, tri_vindex, offset, numverts, numsteps, step, normals);
- motion_triangle_normals_for_step(kg, tri_vindex, offset, numverts, numsteps, step+1, next_normals);
- /* Interpolate between steps. */
- normals[0] = (1.0f - t)*normals[0] + t*next_normals[0];
- normals[1] = (1.0f - t)*normals[1] + t*next_normals[1];
- normals[2] = (1.0f - t)*normals[2] + t*next_normals[2];
- /* Interpolate between vertices. */
- float u = sd->u;
- float v = sd->v;
- float w = 1.0f - u - v;
- sd->N = (u*normals[0] + v*normals[1] + w*normals[2]);
- }
+ /* Compute smooth normal. */
+ if (sd->shader & SHADER_SMOOTH_NORMAL) {
+ /* Find attribute. */
+ AttributeElement elem;
+ int offset = find_attribute_motion(kg, sd->object, ATTR_STD_MOTION_VERTEX_NORMAL, &elem);
+ kernel_assert(offset != ATTR_STD_NOT_FOUND);
+ /* Fetch vertex coordinates. */
+ float3 normals[3], next_normals[3];
+ motion_triangle_normals_for_step(kg, tri_vindex, offset, numverts, numsteps, step, normals);
+ motion_triangle_normals_for_step(
+ kg, tri_vindex, offset, numverts, numsteps, step + 1, next_normals);
+ /* Interpolate between steps. */
+ normals[0] = (1.0f - t) * normals[0] + t * next_normals[0];
+ normals[1] = (1.0f - t) * normals[1] + t * next_normals[1];
+ normals[2] = (1.0f - t) * normals[2] + t * next_normals[2];
+ /* Interpolate between vertices. */
+ float u = sd->u;
+ float v = sd->v;
+ float w = 1.0f - u - v;
+ sd->N = (u * normals[0] + v * normals[1] + w * normals[2]);
+ }
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/geom/geom_object.h b/intern/cycles/kernel/geom/geom_object.h
index 669c932d720..2792fd64c61 100644
--- a/intern/cycles/kernel/geom/geom_object.h
+++ b/intern/cycles/kernel/geom/geom_object.h
@@ -27,131 +27,143 @@ CCL_NAMESPACE_BEGIN
/* Object attributes, for now a fixed size and contents */
enum ObjectTransform {
- OBJECT_TRANSFORM = 0,
- OBJECT_INVERSE_TRANSFORM = 1,
+ OBJECT_TRANSFORM = 0,
+ OBJECT_INVERSE_TRANSFORM = 1,
};
-enum ObjectVectorTransform {
- OBJECT_PASS_MOTION_PRE = 0,
- OBJECT_PASS_MOTION_POST = 1
-};
+enum ObjectVectorTransform { OBJECT_PASS_MOTION_PRE = 0, OBJECT_PASS_MOTION_POST = 1 };
/* Object to world space transformation */
-ccl_device_inline Transform object_fetch_transform(KernelGlobals *kg, int object, enum ObjectTransform type)
+ccl_device_inline Transform object_fetch_transform(KernelGlobals *kg,
+ int object,
+ enum ObjectTransform type)
{
- if(type == OBJECT_INVERSE_TRANSFORM) {
- return kernel_tex_fetch(__objects, object).itfm;
- }
- else {
- return kernel_tex_fetch(__objects, object).tfm;
- }
+ if (type == OBJECT_INVERSE_TRANSFORM) {
+ return kernel_tex_fetch(__objects, object).itfm;
+ }
+ else {
+ return kernel_tex_fetch(__objects, object).tfm;
+ }
}
/* Lamp to world space transformation */
ccl_device_inline Transform lamp_fetch_transform(KernelGlobals *kg, int lamp, bool inverse)
{
- if(inverse) {
- return kernel_tex_fetch(__lights, lamp).itfm;
- }
- else {
- return kernel_tex_fetch(__lights, lamp).tfm;
- }
+ if (inverse) {
+ return kernel_tex_fetch(__lights, lamp).itfm;
+ }
+ else {
+ return kernel_tex_fetch(__lights, lamp).tfm;
+ }
}
/* Object to world space transformation for motion vectors */
-ccl_device_inline Transform object_fetch_motion_pass_transform(KernelGlobals *kg, int object, enum ObjectVectorTransform type)
+ccl_device_inline Transform object_fetch_motion_pass_transform(KernelGlobals *kg,
+ int object,
+ enum ObjectVectorTransform type)
{
- int offset = object*OBJECT_MOTION_PASS_SIZE + (int)type;
- return kernel_tex_fetch(__object_motion_pass, offset);
+ int offset = object * OBJECT_MOTION_PASS_SIZE + (int)type;
+ return kernel_tex_fetch(__object_motion_pass, offset);
}
/* Motion blurred object transformations */
#ifdef __OBJECT_MOTION__
-ccl_device_inline Transform object_fetch_transform_motion(KernelGlobals *kg, int object, float time)
-{
- const uint motion_offset = kernel_tex_fetch(__objects, object).motion_offset;
- const ccl_global DecomposedTransform *motion = &kernel_tex_fetch(__object_motion, motion_offset);
- const uint num_steps = kernel_tex_fetch(__objects, object).numsteps * 2 + 1;
-
- Transform tfm;
-#ifdef __EMBREE__
- if(kernel_data.bvh.scene) {
- transform_motion_array_interpolate_straight(&tfm, motion, num_steps, time);
- }
- else
-#endif
- transform_motion_array_interpolate(&tfm, motion, num_steps, time);
+ccl_device_inline Transform object_fetch_transform_motion(KernelGlobals *kg,
+ int object,
+ float time)
+{
+ const uint motion_offset = kernel_tex_fetch(__objects, object).motion_offset;
+ const ccl_global DecomposedTransform *motion = &kernel_tex_fetch(__object_motion, motion_offset);
+ const uint num_steps = kernel_tex_fetch(__objects, object).numsteps * 2 + 1;
+
+ Transform tfm;
+# ifdef __EMBREE__
+ if (kernel_data.bvh.scene) {
+ transform_motion_array_interpolate_straight(&tfm, motion, num_steps, time);
+ }
+ else
+# endif
+ transform_motion_array_interpolate(&tfm, motion, num_steps, time);
- return tfm;
+ return tfm;
}
-ccl_device_inline Transform object_fetch_transform_motion_test(KernelGlobals *kg, int object, float time, Transform *itfm)
+ccl_device_inline Transform object_fetch_transform_motion_test(KernelGlobals *kg,
+ int object,
+ float time,
+ Transform *itfm)
{
- int object_flag = kernel_tex_fetch(__object_flag, object);
- if(object_flag & SD_OBJECT_MOTION) {
- /* if we do motion blur */
- Transform tfm = object_fetch_transform_motion(kg, object, time);
+ int object_flag = kernel_tex_fetch(__object_flag, object);
+ if (object_flag & SD_OBJECT_MOTION) {
+ /* if we do motion blur */
+ Transform tfm = object_fetch_transform_motion(kg, object, time);
- if(itfm)
- *itfm = transform_quick_inverse(tfm);
+ if (itfm)
+ *itfm = transform_quick_inverse(tfm);
- return tfm;
- }
- else {
- Transform tfm = object_fetch_transform(kg, object, OBJECT_TRANSFORM);
- if(itfm)
- *itfm = object_fetch_transform(kg, object, OBJECT_INVERSE_TRANSFORM);
+ return tfm;
+ }
+ else {
+ Transform tfm = object_fetch_transform(kg, object, OBJECT_TRANSFORM);
+ if (itfm)
+ *itfm = object_fetch_transform(kg, object, OBJECT_INVERSE_TRANSFORM);
- return tfm;
- }
+ return tfm;
+ }
}
#endif
/* Transform position from object to world space */
-ccl_device_inline void object_position_transform(KernelGlobals *kg, const ShaderData *sd, float3 *P)
+ccl_device_inline void object_position_transform(KernelGlobals *kg,
+ const ShaderData *sd,
+ float3 *P)
{
#ifdef __OBJECT_MOTION__
- *P = transform_point_auto(&sd->ob_tfm, *P);
+ *P = transform_point_auto(&sd->ob_tfm, *P);
#else
- Transform tfm = object_fetch_transform(kg, sd->object, OBJECT_TRANSFORM);
- *P = transform_point(&tfm, *P);
+ Transform tfm = object_fetch_transform(kg, sd->object, OBJECT_TRANSFORM);
+ *P = transform_point(&tfm, *P);
#endif
}
/* Transform position from world to object space */
-ccl_device_inline void object_inverse_position_transform(KernelGlobals *kg, const ShaderData *sd, float3 *P)
+ccl_device_inline void object_inverse_position_transform(KernelGlobals *kg,
+ const ShaderData *sd,
+ float3 *P)
{
#ifdef __OBJECT_MOTION__
- *P = transform_point_auto(&sd->ob_itfm, *P);
+ *P = transform_point_auto(&sd->ob_itfm, *P);
#else
- Transform tfm = object_fetch_transform(kg, sd->object, OBJECT_INVERSE_TRANSFORM);
- *P = transform_point(&tfm, *P);
+ Transform tfm = object_fetch_transform(kg, sd->object, OBJECT_INVERSE_TRANSFORM);
+ *P = transform_point(&tfm, *P);
#endif
}
/* Transform normal from world to object space */
-ccl_device_inline void object_inverse_normal_transform(KernelGlobals *kg, const ShaderData *sd, float3 *N)
+ccl_device_inline void object_inverse_normal_transform(KernelGlobals *kg,
+ const ShaderData *sd,
+ float3 *N)
{
#ifdef __OBJECT_MOTION__
- if((sd->object != OBJECT_NONE) || (sd->type == PRIMITIVE_LAMP)) {
- *N = normalize(transform_direction_transposed_auto(&sd->ob_tfm, *N));
- }
+ if ((sd->object != OBJECT_NONE) || (sd->type == PRIMITIVE_LAMP)) {
+ *N = normalize(transform_direction_transposed_auto(&sd->ob_tfm, *N));
+ }
#else
- if(sd->object != OBJECT_NONE) {
- Transform tfm = object_fetch_transform(kg, sd->object, OBJECT_TRANSFORM);
- *N = normalize(transform_direction_transposed(&tfm, *N));
- }
- else if(sd->type == PRIMITIVE_LAMP) {
- Transform tfm = lamp_fetch_transform(kg, sd->lamp, false);
- *N = normalize(transform_direction_transposed(&tfm, *N));
- }
+ if (sd->object != OBJECT_NONE) {
+ Transform tfm = object_fetch_transform(kg, sd->object, OBJECT_TRANSFORM);
+ *N = normalize(transform_direction_transposed(&tfm, *N));
+ }
+ else if (sd->type == PRIMITIVE_LAMP) {
+ Transform tfm = lamp_fetch_transform(kg, sd->lamp, false);
+ *N = normalize(transform_direction_transposed(&tfm, *N));
+ }
#endif
}
@@ -160,10 +172,10 @@ ccl_device_inline void object_inverse_normal_transform(KernelGlobals *kg, const
ccl_device_inline void object_normal_transform(KernelGlobals *kg, const ShaderData *sd, float3 *N)
{
#ifdef __OBJECT_MOTION__
- *N = normalize(transform_direction_transposed_auto(&sd->ob_itfm, *N));
+ *N = normalize(transform_direction_transposed_auto(&sd->ob_itfm, *N));
#else
- Transform tfm = object_fetch_transform(kg, sd->object, OBJECT_INVERSE_TRANSFORM);
- *N = normalize(transform_direction_transposed(&tfm, *N));
+ Transform tfm = object_fetch_transform(kg, sd->object, OBJECT_INVERSE_TRANSFORM);
+ *N = normalize(transform_direction_transposed(&tfm, *N));
#endif
}
@@ -172,22 +184,24 @@ ccl_device_inline void object_normal_transform(KernelGlobals *kg, const ShaderDa
ccl_device_inline void object_dir_transform(KernelGlobals *kg, const ShaderData *sd, float3 *D)
{
#ifdef __OBJECT_MOTION__
- *D = transform_direction_auto(&sd->ob_tfm, *D);
+ *D = transform_direction_auto(&sd->ob_tfm, *D);
#else
- Transform tfm = object_fetch_transform(kg, sd->object, OBJECT_TRANSFORM);
- *D = transform_direction(&tfm, *D);
+ Transform tfm = object_fetch_transform(kg, sd->object, OBJECT_TRANSFORM);
+ *D = transform_direction(&tfm, *D);
#endif
}
/* Transform direction vector from world to object space */
-ccl_device_inline void object_inverse_dir_transform(KernelGlobals *kg, const ShaderData *sd, float3 *D)
+ccl_device_inline void object_inverse_dir_transform(KernelGlobals *kg,
+ const ShaderData *sd,
+ float3 *D)
{
#ifdef __OBJECT_MOTION__
- *D = transform_direction_auto(&sd->ob_itfm, *D);
+ *D = transform_direction_auto(&sd->ob_itfm, *D);
#else
- Transform tfm = object_fetch_transform(kg, sd->object, OBJECT_INVERSE_TRANSFORM);
- *D = transform_direction(&tfm, *D);
+ Transform tfm = object_fetch_transform(kg, sd->object, OBJECT_INVERSE_TRANSFORM);
+ *D = transform_direction(&tfm, *D);
#endif
}
@@ -195,14 +209,14 @@ ccl_device_inline void object_inverse_dir_transform(KernelGlobals *kg, const Sha
ccl_device_inline float3 object_location(KernelGlobals *kg, const ShaderData *sd)
{
- if(sd->object == OBJECT_NONE)
- return make_float3(0.0f, 0.0f, 0.0f);
+ if (sd->object == OBJECT_NONE)
+ return make_float3(0.0f, 0.0f, 0.0f);
#ifdef __OBJECT_MOTION__
- return make_float3(sd->ob_tfm.x.w, sd->ob_tfm.y.w, sd->ob_tfm.z.w);
+ return make_float3(sd->ob_tfm.x.w, sd->ob_tfm.y.w, sd->ob_tfm.z.w);
#else
- Transform tfm = object_fetch_transform(kg, sd->object, OBJECT_TRANSFORM);
- return make_float3(tfm.x.w, tfm.y.w, tfm.z.w);
+ Transform tfm = object_fetch_transform(kg, sd->object, OBJECT_TRANSFORM);
+ return make_float3(tfm.x.w, tfm.y.w, tfm.z.w);
#endif
}
@@ -210,218 +224,211 @@ ccl_device_inline float3 object_location(KernelGlobals *kg, const ShaderData *sd
ccl_device_inline float object_surface_area(KernelGlobals *kg, int object)
{
- return kernel_tex_fetch(__objects, object).surface_area;
+ return kernel_tex_fetch(__objects, object).surface_area;
}
/* Pass ID number of object */
ccl_device_inline float object_pass_id(KernelGlobals *kg, int object)
{
- if(object == OBJECT_NONE)
- return 0.0f;
+ if (object == OBJECT_NONE)
+ return 0.0f;
- return kernel_tex_fetch(__objects, object).pass_id;
+ return kernel_tex_fetch(__objects, object).pass_id;
}
/* Per lamp random number for shader variation */
ccl_device_inline float lamp_random_number(KernelGlobals *kg, int lamp)
{
- if(lamp == LAMP_NONE)
- return 0.0f;
+ if (lamp == LAMP_NONE)
+ return 0.0f;
- return kernel_tex_fetch(__lights, lamp).random;
+ return kernel_tex_fetch(__lights, lamp).random;
}
/* Per object random number for shader variation */
ccl_device_inline float object_random_number(KernelGlobals *kg, int object)
{
- if(object == OBJECT_NONE)
- return 0.0f;
+ if (object == OBJECT_NONE)
+ return 0.0f;
- return kernel_tex_fetch(__objects, object).random_number;
+ return kernel_tex_fetch(__objects, object).random_number;
}
/* Particle ID from which this object was generated */
ccl_device_inline int object_particle_id(KernelGlobals *kg, int object)
{
- if(object == OBJECT_NONE)
- return 0;
+ if (object == OBJECT_NONE)
+ return 0;
- return kernel_tex_fetch(__objects, object).particle_index;
+ return kernel_tex_fetch(__objects, object).particle_index;
}
/* Generated texture coordinate on surface from where object was instanced */
ccl_device_inline float3 object_dupli_generated(KernelGlobals *kg, int object)
{
- if(object == OBJECT_NONE)
- return make_float3(0.0f, 0.0f, 0.0f);
+ if (object == OBJECT_NONE)
+ return make_float3(0.0f, 0.0f, 0.0f);
- const ccl_global KernelObject *kobject = &kernel_tex_fetch(__objects, object);
- return make_float3(kobject->dupli_generated[0],
- kobject->dupli_generated[1],
- kobject->dupli_generated[2]);
+ const ccl_global KernelObject *kobject = &kernel_tex_fetch(__objects, object);
+ return make_float3(
+ kobject->dupli_generated[0], kobject->dupli_generated[1], kobject->dupli_generated[2]);
}
/* UV texture coordinate on surface from where object was instanced */
ccl_device_inline float3 object_dupli_uv(KernelGlobals *kg, int object)
{
- if(object == OBJECT_NONE)
- return make_float3(0.0f, 0.0f, 0.0f);
+ if (object == OBJECT_NONE)
+ return make_float3(0.0f, 0.0f, 0.0f);
- const ccl_global KernelObject *kobject = &kernel_tex_fetch(__objects, object);
- return make_float3(kobject->dupli_uv[0],
- kobject->dupli_uv[1],
- 0.0f);
+ const ccl_global KernelObject *kobject = &kernel_tex_fetch(__objects, object);
+ return make_float3(kobject->dupli_uv[0], kobject->dupli_uv[1], 0.0f);
}
/* Information about mesh for motion blurred triangles and curves */
-ccl_device_inline void object_motion_info(KernelGlobals *kg, int object, int *numsteps, int *numverts, int *numkeys)
+ccl_device_inline void object_motion_info(
+ KernelGlobals *kg, int object, int *numsteps, int *numverts, int *numkeys)
{
- if(numkeys) {
- *numkeys = kernel_tex_fetch(__objects, object).numkeys;
- }
+ if (numkeys) {
+ *numkeys = kernel_tex_fetch(__objects, object).numkeys;
+ }
- if(numsteps)
- *numsteps = kernel_tex_fetch(__objects, object).numsteps;
- if(numverts)
- *numverts = kernel_tex_fetch(__objects, object).numverts;
+ if (numsteps)
+ *numsteps = kernel_tex_fetch(__objects, object).numsteps;
+ if (numverts)
+ *numverts = kernel_tex_fetch(__objects, object).numverts;
}
/* Offset to an objects patch map */
ccl_device_inline uint object_patch_map_offset(KernelGlobals *kg, int object)
{
- if(object == OBJECT_NONE)
- return 0;
+ if (object == OBJECT_NONE)
+ return 0;
- return kernel_tex_fetch(__objects, object).patch_map_offset;
+ return kernel_tex_fetch(__objects, object).patch_map_offset;
}
/* Pass ID for shader */
ccl_device int shader_pass_id(KernelGlobals *kg, const ShaderData *sd)
{
- return kernel_tex_fetch(__shaders, (sd->shader & SHADER_MASK)).pass_id;
+ return kernel_tex_fetch(__shaders, (sd->shader & SHADER_MASK)).pass_id;
}
/* Cryptomatte ID */
ccl_device_inline float object_cryptomatte_id(KernelGlobals *kg, int object)
{
- if(object == OBJECT_NONE)
- return 0.0f;
+ if (object == OBJECT_NONE)
+ return 0.0f;
- return kernel_tex_fetch(__objects, object).cryptomatte_object;
+ return kernel_tex_fetch(__objects, object).cryptomatte_object;
}
ccl_device_inline float object_cryptomatte_asset_id(KernelGlobals *kg, int object)
{
- if(object == OBJECT_NONE)
- return 0;
+ if (object == OBJECT_NONE)
+ return 0;
- return kernel_tex_fetch(__objects, object).cryptomatte_asset;
+ return kernel_tex_fetch(__objects, object).cryptomatte_asset;
}
/* Particle data from which object was instanced */
ccl_device_inline uint particle_index(KernelGlobals *kg, int particle)
{
- return kernel_tex_fetch(__particles, particle).index;
+ return kernel_tex_fetch(__particles, particle).index;
}
ccl_device float particle_age(KernelGlobals *kg, int particle)
{
- return kernel_tex_fetch(__particles, particle).age;
+ return kernel_tex_fetch(__particles, particle).age;
}
ccl_device float particle_lifetime(KernelGlobals *kg, int particle)
{
- return kernel_tex_fetch(__particles, particle).lifetime;
+ return kernel_tex_fetch(__particles, particle).lifetime;
}
ccl_device float particle_size(KernelGlobals *kg, int particle)
{
- return kernel_tex_fetch(__particles, particle).size;
+ return kernel_tex_fetch(__particles, particle).size;
}
ccl_device float4 particle_rotation(KernelGlobals *kg, int particle)
{
- return kernel_tex_fetch(__particles, particle).rotation;
+ return kernel_tex_fetch(__particles, particle).rotation;
}
ccl_device float3 particle_location(KernelGlobals *kg, int particle)
{
- return float4_to_float3(kernel_tex_fetch(__particles, particle).location);
+ return float4_to_float3(kernel_tex_fetch(__particles, particle).location);
}
ccl_device float3 particle_velocity(KernelGlobals *kg, int particle)
{
- return float4_to_float3(kernel_tex_fetch(__particles, particle).velocity);
+ return float4_to_float3(kernel_tex_fetch(__particles, particle).velocity);
}
ccl_device float3 particle_angular_velocity(KernelGlobals *kg, int particle)
{
- return float4_to_float3(kernel_tex_fetch(__particles, particle).angular_velocity);
+ return float4_to_float3(kernel_tex_fetch(__particles, particle).angular_velocity);
}
/* Object intersection in BVH */
ccl_device_inline float3 bvh_clamp_direction(float3 dir)
{
- /* clamp absolute values by exp2f(-80.0f) to avoid division by zero when calculating inverse direction */
+ /* clamp absolute values by exp2f(-80.0f) to avoid division by zero when calculating inverse direction */
#if defined(__KERNEL_SSE__) && defined(__KERNEL_SSE2__)
- const ssef oopes(8.271806E-25f,8.271806E-25f,8.271806E-25f,0.0f);
- const ssef mask = _mm_cmpgt_ps(fabs(dir), oopes);
- const ssef signdir = signmsk(dir.m128) | oopes;
+ const ssef oopes(8.271806E-25f, 8.271806E-25f, 8.271806E-25f, 0.0f);
+ const ssef mask = _mm_cmpgt_ps(fabs(dir), oopes);
+ const ssef signdir = signmsk(dir.m128) | oopes;
# ifndef __KERNEL_AVX__
- ssef res = mask & ssef(dir);
- res = _mm_or_ps(res,_mm_andnot_ps(mask, signdir));
+ ssef res = mask & ssef(dir);
+ res = _mm_or_ps(res, _mm_andnot_ps(mask, signdir));
# else
- ssef res = _mm_blendv_ps(signdir, dir, mask);
+ ssef res = _mm_blendv_ps(signdir, dir, mask);
# endif
- return float3(res);
+ return float3(res);
#else /* __KERNEL_SSE__ && __KERNEL_SSE2__ */
- const float ooeps = 8.271806E-25f;
- return make_float3((fabsf(dir.x) > ooeps)? dir.x: copysignf(ooeps, dir.x),
- (fabsf(dir.y) > ooeps)? dir.y: copysignf(ooeps, dir.y),
- (fabsf(dir.z) > ooeps)? dir.z: copysignf(ooeps, dir.z));
-#endif /* __KERNEL_SSE__ && __KERNEL_SSE2__ */
+ const float ooeps = 8.271806E-25f;
+ return make_float3((fabsf(dir.x) > ooeps) ? dir.x : copysignf(ooeps, dir.x),
+ (fabsf(dir.y) > ooeps) ? dir.y : copysignf(ooeps, dir.y),
+ (fabsf(dir.z) > ooeps) ? dir.z : copysignf(ooeps, dir.z));
+#endif /* __KERNEL_SSE__ && __KERNEL_SSE2__ */
}
ccl_device_inline float3 bvh_inverse_direction(float3 dir)
{
- return rcp(dir);
+ return rcp(dir);
}
/* Transform ray into object space to enter static object in BVH */
-ccl_device_inline float bvh_instance_push(KernelGlobals *kg,
- int object,
- const Ray *ray,
- float3 *P,
- float3 *dir,
- float3 *idir,
- float t)
+ccl_device_inline float bvh_instance_push(
+ KernelGlobals *kg, int object, const Ray *ray, float3 *P, float3 *dir, float3 *idir, float t)
{
- Transform tfm = object_fetch_transform(kg, object, OBJECT_INVERSE_TRANSFORM);
+ Transform tfm = object_fetch_transform(kg, object, OBJECT_INVERSE_TRANSFORM);
- *P = transform_point(&tfm, ray->P);
+ *P = transform_point(&tfm, ray->P);
- float len;
- *dir = bvh_clamp_direction(normalize_len(transform_direction(&tfm, ray->D), &len));
- *idir = bvh_inverse_direction(*dir);
+ float len;
+ *dir = bvh_clamp_direction(normalize_len(transform_direction(&tfm, ray->D), &len));
+ *idir = bvh_inverse_direction(*dir);
- if(t != FLT_MAX) {
- t *= len;
- }
+ if (t != FLT_MAX) {
+ t *= len;
+ }
- return t;
+ return t;
}
#ifdef __QBVH__
@@ -440,85 +447,85 @@ ccl_device_inline void qbvh_instance_push(KernelGlobals *kg,
float *t,
float *t1)
{
- Transform tfm = object_fetch_transform(kg, object, OBJECT_INVERSE_TRANSFORM);
+ Transform tfm = object_fetch_transform(kg, object, OBJECT_INVERSE_TRANSFORM);
- *P = transform_point(&tfm, ray->P);
+ *P = transform_point(&tfm, ray->P);
- float len;
- *dir = bvh_clamp_direction(normalize_len(transform_direction(&tfm, ray->D), &len));
- *idir = bvh_inverse_direction(*dir);
+ float len;
+ *dir = bvh_clamp_direction(normalize_len(transform_direction(&tfm, ray->D), &len));
+ *idir = bvh_inverse_direction(*dir);
- if(*t != FLT_MAX)
- *t *= len;
+ if (*t != FLT_MAX)
+ *t *= len;
- if(*t1 != -FLT_MAX)
- *t1 *= len;
+ if (*t1 != -FLT_MAX)
+ *t1 *= len;
}
#endif
/* Transorm ray to exit static object in BVH */
-ccl_device_inline float bvh_instance_pop(KernelGlobals *kg,
- int object,
- const Ray *ray,
- float3 *P,
- float3 *dir,
- float3 *idir,
- float t)
+ccl_device_inline float bvh_instance_pop(
+ KernelGlobals *kg, int object, const Ray *ray, float3 *P, float3 *dir, float3 *idir, float t)
{
- if(t != FLT_MAX) {
- Transform tfm = object_fetch_transform(kg, object, OBJECT_INVERSE_TRANSFORM);
- t /= len(transform_direction(&tfm, ray->D));
- }
+ if (t != FLT_MAX) {
+ Transform tfm = object_fetch_transform(kg, object, OBJECT_INVERSE_TRANSFORM);
+ t /= len(transform_direction(&tfm, ray->D));
+ }
- *P = ray->P;
- *dir = bvh_clamp_direction(ray->D);
- *idir = bvh_inverse_direction(*dir);
+ *P = ray->P;
+ *dir = bvh_clamp_direction(ray->D);
+ *idir = bvh_inverse_direction(*dir);
- return t;
+ return t;
}
/* Same as above, but returns scale factor to apply to multiple intersection distances */
-ccl_device_inline void bvh_instance_pop_factor(KernelGlobals *kg, int object, const Ray *ray, float3 *P, float3 *dir, float3 *idir, float *t_fac)
+ccl_device_inline void bvh_instance_pop_factor(KernelGlobals *kg,
+ int object,
+ const Ray *ray,
+ float3 *P,
+ float3 *dir,
+ float3 *idir,
+ float *t_fac)
{
- Transform tfm = object_fetch_transform(kg, object, OBJECT_INVERSE_TRANSFORM);
- *t_fac = 1.0f / len(transform_direction(&tfm, ray->D));
+ Transform tfm = object_fetch_transform(kg, object, OBJECT_INVERSE_TRANSFORM);
+ *t_fac = 1.0f / len(transform_direction(&tfm, ray->D));
- *P = ray->P;
- *dir = bvh_clamp_direction(ray->D);
- *idir = bvh_inverse_direction(*dir);
+ *P = ray->P;
+ *dir = bvh_clamp_direction(ray->D);
+ *idir = bvh_inverse_direction(*dir);
}
-
#ifdef __OBJECT_MOTION__
/* Transform ray into object space to enter motion blurred object in BVH */
ccl_device_inline float bvh_instance_motion_push(KernelGlobals *kg,
- int object,
- const Ray *ray,
- float3 *P,
- float3 *dir,
- float3 *idir,
- float t,
- Transform *itfm)
+ int object,
+ const Ray *ray,
+ float3 *P,
+ float3 *dir,
+ float3 *idir,
+ float t,
+ Transform *itfm)
{
- object_fetch_transform_motion_test(kg, object, ray->time, itfm);
+ object_fetch_transform_motion_test(kg, object, ray->time, itfm);
- *P = transform_point(itfm, ray->P);
+ *P = transform_point(itfm, ray->P);
- float len;
- *dir = bvh_clamp_direction(normalize_len(transform_direction(itfm, ray->D), &len));
- *idir = bvh_inverse_direction(*dir);
+ float len;
+ *dir = bvh_clamp_direction(normalize_len(transform_direction(itfm, ray->D), &len));
+ *idir = bvh_inverse_direction(*dir);
- if(t != FLT_MAX) {
- t *= len;
- }
+ if (t != FLT_MAX) {
+ t *= len;
+ }
- return t;
+ return t;
}
-#ifdef __QBVH__
+# ifdef __QBVH__
/* Same as above, but optimized for QBVH scene intersection,
* which needs to modify two max distances.
*
@@ -535,21 +542,21 @@ ccl_device_inline void qbvh_instance_motion_push(KernelGlobals *kg,
float *t1,
Transform *itfm)
{
- object_fetch_transform_motion_test(kg, object, ray->time, itfm);
+ object_fetch_transform_motion_test(kg, object, ray->time, itfm);
- *P = transform_point(itfm, ray->P);
+ *P = transform_point(itfm, ray->P);
- float len;
- *dir = bvh_clamp_direction(normalize_len(transform_direction(itfm, ray->D), &len));
- *idir = bvh_inverse_direction(*dir);
+ float len;
+ *dir = bvh_clamp_direction(normalize_len(transform_direction(itfm, ray->D), &len));
+ *idir = bvh_inverse_direction(*dir);
- if(*t != FLT_MAX)
- *t *= len;
+ if (*t != FLT_MAX)
+ *t *= len;
- if(*t1 != -FLT_MAX)
- *t1 *= len;
+ if (*t1 != -FLT_MAX)
+ *t1 *= len;
}
-#endif
+# endif
/* Transorm ray to exit motion blurred object in BVH */
@@ -562,15 +569,15 @@ ccl_device_inline float bvh_instance_motion_pop(KernelGlobals *kg,
float t,
Transform *itfm)
{
- if(t != FLT_MAX) {
- t /= len(transform_direction(itfm, ray->D));
- }
+ if (t != FLT_MAX) {
+ t /= len(transform_direction(itfm, ray->D));
+ }
- *P = ray->P;
- *dir = bvh_clamp_direction(ray->D);
- *idir = bvh_inverse_direction(*dir);
+ *P = ray->P;
+ *dir = bvh_clamp_direction(ray->D);
+ *idir = bvh_inverse_direction(*dir);
- return t;
+ return t;
}
/* Same as above, but returns scale factor to apply to multiple intersection distances */
@@ -584,10 +591,10 @@ ccl_device_inline void bvh_instance_motion_pop_factor(KernelGlobals *kg,
float *t_fac,
Transform *itfm)
{
- *t_fac = 1.0f / len(transform_direction(itfm, ray->D));
- *P = ray->P;
- *dir = bvh_clamp_direction(ray->D);
- *idir = bvh_inverse_direction(*dir);
+ *t_fac = 1.0f / len(transform_direction(itfm, ray->D));
+ *P = ray->P;
+ *dir = bvh_clamp_direction(ray->D);
+ *idir = bvh_inverse_direction(*dir);
}
#endif
@@ -599,30 +606,30 @@ ccl_device_inline void bvh_instance_motion_pop_factor(KernelGlobals *kg,
#ifdef __KERNEL_OPENCL__
ccl_device_inline void object_position_transform_addrspace(KernelGlobals *kg,
- const ShaderData *sd,
- ccl_addr_space float3 *P)
+ const ShaderData *sd,
+ ccl_addr_space float3 *P)
{
- float3 private_P = *P;
- object_position_transform(kg, sd, &private_P);
- *P = private_P;
+ float3 private_P = *P;
+ object_position_transform(kg, sd, &private_P);
+ *P = private_P;
}
ccl_device_inline void object_dir_transform_addrspace(KernelGlobals *kg,
const ShaderData *sd,
ccl_addr_space float3 *D)
{
- float3 private_D = *D;
- object_dir_transform(kg, sd, &private_D);
- *D = private_D;
+ float3 private_D = *D;
+ object_dir_transform(kg, sd, &private_D);
+ *D = private_D;
}
ccl_device_inline void object_normal_transform_addrspace(KernelGlobals *kg,
const ShaderData *sd,
ccl_addr_space float3 *N)
{
- float3 private_N = *N;
- object_normal_transform(kg, sd, &private_N);
- *N = private_N;
+ float3 private_N = *N;
+ object_normal_transform(kg, sd, &private_N);
+ *N = private_N;
}
#endif
diff --git a/intern/cycles/kernel/geom/geom_patch.h b/intern/cycles/kernel/geom/geom_patch.h
index edb82172959..df19199f68e 100644
--- a/intern/cycles/kernel/geom/geom_patch.h
+++ b/intern/cycles/kernel/geom/geom_patch.h
@@ -27,342 +27,394 @@
CCL_NAMESPACE_BEGIN
typedef struct PatchHandle {
- int array_index, patch_index, vert_index;
+ int array_index, patch_index, vert_index;
} PatchHandle;
ccl_device_inline int patch_map_resolve_quadrant(float median, float *u, float *v)
{
- int quadrant = -1;
-
- if(*u < median) {
- if(*v < median) {
- quadrant = 0;
- }
- else {
- quadrant = 1;
- *v -= median;
- }
- }
- else {
- if(*v < median) {
- quadrant = 3;
- }
- else {
- quadrant = 2;
- *v -= median;
- }
- *u -= median;
- }
-
- return quadrant;
+ int quadrant = -1;
+
+ if (*u < median) {
+ if (*v < median) {
+ quadrant = 0;
+ }
+ else {
+ quadrant = 1;
+ *v -= median;
+ }
+ }
+ else {
+ if (*v < median) {
+ quadrant = 3;
+ }
+ else {
+ quadrant = 2;
+ *v -= median;
+ }
+ *u -= median;
+ }
+
+ return quadrant;
}
/* retrieve PatchHandle from patch coords */
-ccl_device_inline PatchHandle patch_map_find_patch(KernelGlobals *kg, int object, int patch, float u, float v)
+ccl_device_inline PatchHandle
+patch_map_find_patch(KernelGlobals *kg, int object, int patch, float u, float v)
{
- PatchHandle handle;
+ PatchHandle handle;
- kernel_assert((u >= 0.0f) && (u <= 1.0f) && (v >= 0.0f) && (v <= 1.0f));
+ kernel_assert((u >= 0.0f) && (u <= 1.0f) && (v >= 0.0f) && (v <= 1.0f));
- int node = (object_patch_map_offset(kg, object) + patch)/2;
- float median = 0.5f;
+ int node = (object_patch_map_offset(kg, object) + patch) / 2;
+ float median = 0.5f;
- for(int depth = 0; depth < 0xff; depth++) {
- float delta = median * 0.5f;
+ for (int depth = 0; depth < 0xff; depth++) {
+ float delta = median * 0.5f;
- int quadrant = patch_map_resolve_quadrant(median, &u, &v);
- kernel_assert(quadrant >= 0);
+ int quadrant = patch_map_resolve_quadrant(median, &u, &v);
+ kernel_assert(quadrant >= 0);
- uint child = kernel_tex_fetch(__patches, node + quadrant);
+ uint child = kernel_tex_fetch(__patches, node + quadrant);
- /* is the quadrant a hole? */
- if(!(child & PATCH_MAP_NODE_IS_SET)) {
- handle.array_index = -1;
- return handle;
- }
+ /* is the quadrant a hole? */
+ if (!(child & PATCH_MAP_NODE_IS_SET)) {
+ handle.array_index = -1;
+ return handle;
+ }
- uint index = child & PATCH_MAP_NODE_INDEX_MASK;
+ uint index = child & PATCH_MAP_NODE_INDEX_MASK;
- if(child & PATCH_MAP_NODE_IS_LEAF) {
- handle.array_index = kernel_tex_fetch(__patches, index + 0);
- handle.patch_index = kernel_tex_fetch(__patches, index + 1);
- handle.vert_index = kernel_tex_fetch(__patches, index + 2);
+ if (child & PATCH_MAP_NODE_IS_LEAF) {
+ handle.array_index = kernel_tex_fetch(__patches, index + 0);
+ handle.patch_index = kernel_tex_fetch(__patches, index + 1);
+ handle.vert_index = kernel_tex_fetch(__patches, index + 2);
- return handle;
- } else {
- node = index;
- }
+ return handle;
+ }
+ else {
+ node = index;
+ }
- median = delta;
- }
+ median = delta;
+ }
- /* no leaf found */
- kernel_assert(0);
+ /* no leaf found */
+ kernel_assert(0);
- handle.array_index = -1;
- return handle;
+ handle.array_index = -1;
+ return handle;
}
ccl_device_inline void patch_eval_bspline_weights(float t, float *point, float *deriv)
{
- /* The four uniform cubic B-Spline basis functions evaluated at t */
- float inv_6 = 1.0f / 6.0f;
-
- float t2 = t * t;
- float t3 = t * t2;
-
- point[0] = inv_6 * (1.0f - 3.0f*(t - t2) - t3);
- point[1] = inv_6 * (4.0f - 6.0f*t2 + 3.0f*t3);
- point[2] = inv_6 * (1.0f + 3.0f*(t + t2 - t3));
- point[3] = inv_6 * t3;
-
- /* Derivatives of the above four basis functions at t */
- deriv[0] = -0.5f*t2 + t - 0.5f;
- deriv[1] = 1.5f*t2 - 2.0f*t;
- deriv[2] = -1.5f*t2 + t + 0.5f;
- deriv[3] = 0.5f*t2;
+ /* The four uniform cubic B-Spline basis functions evaluated at t */
+ float inv_6 = 1.0f / 6.0f;
+
+ float t2 = t * t;
+ float t3 = t * t2;
+
+ point[0] = inv_6 * (1.0f - 3.0f * (t - t2) - t3);
+ point[1] = inv_6 * (4.0f - 6.0f * t2 + 3.0f * t3);
+ point[2] = inv_6 * (1.0f + 3.0f * (t + t2 - t3));
+ point[3] = inv_6 * t3;
+
+ /* Derivatives of the above four basis functions at t */
+ deriv[0] = -0.5f * t2 + t - 0.5f;
+ deriv[1] = 1.5f * t2 - 2.0f * t;
+ deriv[2] = -1.5f * t2 + t + 0.5f;
+ deriv[3] = 0.5f * t2;
}
ccl_device_inline void patch_eval_adjust_boundary_weights(uint bits, float *s, float *t)
{
- int boundary = ((bits >> 8) & 0xf);
-
- if(boundary & 1) {
- t[2] -= t[0];
- t[1] += 2*t[0];
- t[0] = 0;
- }
-
- if(boundary & 2) {
- s[1] -= s[3];
- s[2] += 2*s[3];
- s[3] = 0;
- }
-
- if(boundary & 4) {
- t[1] -= t[3];
- t[2] += 2*t[3];
- t[3] = 0;
- }
-
- if(boundary & 8) {
- s[2] -= s[0];
- s[1] += 2*s[0];
- s[0] = 0;
- }
+ int boundary = ((bits >> 8) & 0xf);
+
+ if (boundary & 1) {
+ t[2] -= t[0];
+ t[1] += 2 * t[0];
+ t[0] = 0;
+ }
+
+ if (boundary & 2) {
+ s[1] -= s[3];
+ s[2] += 2 * s[3];
+ s[3] = 0;
+ }
+
+ if (boundary & 4) {
+ t[1] -= t[3];
+ t[2] += 2 * t[3];
+ t[3] = 0;
+ }
+
+ if (boundary & 8) {
+ s[2] -= s[0];
+ s[1] += 2 * s[0];
+ s[0] = 0;
+ }
}
ccl_device_inline int patch_eval_depth(uint patch_bits)
{
- return (patch_bits & 0xf);
+ return (patch_bits & 0xf);
}
ccl_device_inline float patch_eval_param_fraction(uint patch_bits)
{
- bool non_quad_root = (patch_bits >> 4) & 0x1;
- int depth = patch_eval_depth(patch_bits);
-
- if(non_quad_root) {
- return 1.0f / (float)(1 << (depth-1));
- }
- else {
- return 1.0f / (float)(1 << depth);
- }
+ bool non_quad_root = (patch_bits >> 4) & 0x1;
+ int depth = patch_eval_depth(patch_bits);
+
+ if (non_quad_root) {
+ return 1.0f / (float)(1 << (depth - 1));
+ }
+ else {
+ return 1.0f / (float)(1 << depth);
+ }
}
ccl_device_inline void patch_eval_normalize_coords(uint patch_bits, float *u, float *v)
{
- float frac = patch_eval_param_fraction(patch_bits);
+ float frac = patch_eval_param_fraction(patch_bits);
- int iu = (patch_bits >> 22) & 0x3ff;
- int iv = (patch_bits >> 12) & 0x3ff;
+ int iu = (patch_bits >> 22) & 0x3ff;
+ int iv = (patch_bits >> 12) & 0x3ff;
- /* top left corner */
- float pu = (float)iu*frac;
- float pv = (float)iv*frac;
+ /* top left corner */
+ float pu = (float)iu * frac;
+ float pv = (float)iv * frac;
- /* normalize uv coordinates */
- *u = (*u - pu) / frac;
- *v = (*v - pv) / frac;
+ /* normalize uv coordinates */
+ *u = (*u - pu) / frac;
+ *v = (*v - pv) / frac;
}
/* retrieve patch control indices */
-ccl_device_inline int patch_eval_indices(KernelGlobals *kg, const PatchHandle *handle, int channel,
+ccl_device_inline int patch_eval_indices(KernelGlobals *kg,
+ const PatchHandle *handle,
+ int channel,
int indices[PATCH_MAX_CONTROL_VERTS])
{
- int index_base = kernel_tex_fetch(__patches, handle->array_index + 2) + handle->vert_index;
+ int index_base = kernel_tex_fetch(__patches, handle->array_index + 2) + handle->vert_index;
- /* XXX: regular patches only */
- for(int i = 0; i < 16; i++) {
- indices[i] = kernel_tex_fetch(__patches, index_base + i);
- }
+ /* XXX: regular patches only */
+ for (int i = 0; i < 16; i++) {
+ indices[i] = kernel_tex_fetch(__patches, index_base + i);
+ }
- return 16;
+ return 16;
}
/* evaluate patch basis functions */
-ccl_device_inline void patch_eval_basis(KernelGlobals *kg, const PatchHandle *handle, float u, float v,
- float weights[PATCH_MAX_CONTROL_VERTS],
- float weights_du[PATCH_MAX_CONTROL_VERTS],
- float weights_dv[PATCH_MAX_CONTROL_VERTS])
+ccl_device_inline void patch_eval_basis(KernelGlobals *kg,
+ const PatchHandle *handle,
+ float u,
+ float v,
+ float weights[PATCH_MAX_CONTROL_VERTS],
+ float weights_du[PATCH_MAX_CONTROL_VERTS],
+ float weights_dv[PATCH_MAX_CONTROL_VERTS])
{
- uint patch_bits = kernel_tex_fetch(__patches, handle->patch_index + 1); /* read patch param */
- float d_scale = 1 << patch_eval_depth(patch_bits);
+ uint patch_bits = kernel_tex_fetch(__patches, handle->patch_index + 1); /* read patch param */
+ float d_scale = 1 << patch_eval_depth(patch_bits);
- bool non_quad_root = (patch_bits >> 4) & 0x1;
- if(non_quad_root) {
- d_scale *= 0.5f;
- }
+ bool non_quad_root = (patch_bits >> 4) & 0x1;
+ if (non_quad_root) {
+ d_scale *= 0.5f;
+ }
- patch_eval_normalize_coords(patch_bits, &u, &v);
+ patch_eval_normalize_coords(patch_bits, &u, &v);
- /* XXX: regular patches only for now. */
+ /* XXX: regular patches only for now. */
- float s[4], t[4], ds[4], dt[4];
+ float s[4], t[4], ds[4], dt[4];
- patch_eval_bspline_weights(u, s, ds);
- patch_eval_bspline_weights(v, t, dt);
+ patch_eval_bspline_weights(u, s, ds);
+ patch_eval_bspline_weights(v, t, dt);
- patch_eval_adjust_boundary_weights(patch_bits, s, t);
- patch_eval_adjust_boundary_weights(patch_bits, ds, dt);
+ patch_eval_adjust_boundary_weights(patch_bits, s, t);
+ patch_eval_adjust_boundary_weights(patch_bits, ds, dt);
- for(int k = 0; k < 4; k++) {
- for(int l = 0; l < 4; l++) {
- weights[4*k+l] = s[l] * t[k];
- weights_du[4*k+l] = ds[l] * t[k] * d_scale;
- weights_dv[4*k+l] = s[l] * dt[k] * d_scale;
- }
- }
+ for (int k = 0; k < 4; k++) {
+ for (int l = 0; l < 4; l++) {
+ weights[4 * k + l] = s[l] * t[k];
+ weights_du[4 * k + l] = ds[l] * t[k] * d_scale;
+ weights_dv[4 * k + l] = s[l] * dt[k] * d_scale;
+ }
+ }
}
/* generic function for evaluating indices and weights from patch coords */
-ccl_device_inline int patch_eval_control_verts(KernelGlobals *kg, int object, int patch, float u, float v, int channel,
- int indices[PATCH_MAX_CONTROL_VERTS],
- float weights[PATCH_MAX_CONTROL_VERTS],
- float weights_du[PATCH_MAX_CONTROL_VERTS],
- float weights_dv[PATCH_MAX_CONTROL_VERTS])
+ccl_device_inline int patch_eval_control_verts(KernelGlobals *kg,
+ int object,
+ int patch,
+ float u,
+ float v,
+ int channel,
+ int indices[PATCH_MAX_CONTROL_VERTS],
+ float weights[PATCH_MAX_CONTROL_VERTS],
+ float weights_du[PATCH_MAX_CONTROL_VERTS],
+ float weights_dv[PATCH_MAX_CONTROL_VERTS])
{
- PatchHandle handle = patch_map_find_patch(kg, object, patch, u, v);
- kernel_assert(handle.array_index >= 0);
+ PatchHandle handle = patch_map_find_patch(kg, object, patch, u, v);
+ kernel_assert(handle.array_index >= 0);
- int num_control = patch_eval_indices(kg, &handle, channel, indices);
- patch_eval_basis(kg, &handle, u, v, weights, weights_du, weights_dv);
+ int num_control = patch_eval_indices(kg, &handle, channel, indices);
+ patch_eval_basis(kg, &handle, u, v, weights, weights_du, weights_dv);
- return num_control;
+ return num_control;
}
/* functions for evaluating attributes on patches */
-ccl_device float patch_eval_float(KernelGlobals *kg, const ShaderData *sd, int offset,
- int patch, float u, float v, int channel,
- float *du, float* dv)
+ccl_device float patch_eval_float(KernelGlobals *kg,
+ const ShaderData *sd,
+ int offset,
+ int patch,
+ float u,
+ float v,
+ int channel,
+ float *du,
+ float *dv)
{
- int indices[PATCH_MAX_CONTROL_VERTS];
- float weights[PATCH_MAX_CONTROL_VERTS];
- float weights_du[PATCH_MAX_CONTROL_VERTS];
- float weights_dv[PATCH_MAX_CONTROL_VERTS];
-
- int num_control = patch_eval_control_verts(kg, sd->object, patch, u, v, channel,
- indices, weights, weights_du, weights_dv);
-
- float val = 0.0f;
- if(du) *du = 0.0f;
- if(dv) *dv = 0.0f;
-
- for(int i = 0; i < num_control; i++) {
- float v = kernel_tex_fetch(__attributes_float, offset + indices[i]);
-
- val += v * weights[i];
- if(du) *du += v * weights_du[i];
- if(dv) *dv += v * weights_dv[i];
- }
-
- return val;
+ int indices[PATCH_MAX_CONTROL_VERTS];
+ float weights[PATCH_MAX_CONTROL_VERTS];
+ float weights_du[PATCH_MAX_CONTROL_VERTS];
+ float weights_dv[PATCH_MAX_CONTROL_VERTS];
+
+ int num_control = patch_eval_control_verts(
+ kg, sd->object, patch, u, v, channel, indices, weights, weights_du, weights_dv);
+
+ float val = 0.0f;
+ if (du)
+ *du = 0.0f;
+ if (dv)
+ *dv = 0.0f;
+
+ for (int i = 0; i < num_control; i++) {
+ float v = kernel_tex_fetch(__attributes_float, offset + indices[i]);
+
+ val += v * weights[i];
+ if (du)
+ *du += v * weights_du[i];
+ if (dv)
+ *dv += v * weights_dv[i];
+ }
+
+ return val;
}
-ccl_device float2 patch_eval_float2(KernelGlobals *kg, const ShaderData *sd, int offset,
- int patch, float u, float v, int channel,
- float2 *du, float2 *dv)
+ccl_device float2 patch_eval_float2(KernelGlobals *kg,
+ const ShaderData *sd,
+ int offset,
+ int patch,
+ float u,
+ float v,
+ int channel,
+ float2 *du,
+ float2 *dv)
{
- int indices[PATCH_MAX_CONTROL_VERTS];
- float weights[PATCH_MAX_CONTROL_VERTS];
- float weights_du[PATCH_MAX_CONTROL_VERTS];
- float weights_dv[PATCH_MAX_CONTROL_VERTS];
-
- int num_control = patch_eval_control_verts(kg, sd->object, patch, u, v, channel,
- indices, weights, weights_du, weights_dv);
-
- float2 val = make_float2(0.0f, 0.0f);
- if(du) *du = make_float2(0.0f, 0.0f);
- if(dv) *dv = make_float2(0.0f, 0.0f);
-
- for(int i = 0; i < num_control; i++) {
- float2 v = kernel_tex_fetch(__attributes_float2, offset + indices[i]);
-
- val += v * weights[i];
- if(du) *du += v * weights_du[i];
- if(dv) *dv += v * weights_dv[i];
- }
-
- return val;
+ int indices[PATCH_MAX_CONTROL_VERTS];
+ float weights[PATCH_MAX_CONTROL_VERTS];
+ float weights_du[PATCH_MAX_CONTROL_VERTS];
+ float weights_dv[PATCH_MAX_CONTROL_VERTS];
+
+ int num_control = patch_eval_control_verts(
+ kg, sd->object, patch, u, v, channel, indices, weights, weights_du, weights_dv);
+
+ float2 val = make_float2(0.0f, 0.0f);
+ if (du)
+ *du = make_float2(0.0f, 0.0f);
+ if (dv)
+ *dv = make_float2(0.0f, 0.0f);
+
+ for (int i = 0; i < num_control; i++) {
+ float2 v = kernel_tex_fetch(__attributes_float2, offset + indices[i]);
+
+ val += v * weights[i];
+ if (du)
+ *du += v * weights_du[i];
+ if (dv)
+ *dv += v * weights_dv[i];
+ }
+
+ return val;
}
-ccl_device float3 patch_eval_float3(KernelGlobals *kg, const ShaderData *sd, int offset,
- int patch, float u, float v, int channel,
- float3 *du, float3 *dv)
+ccl_device float3 patch_eval_float3(KernelGlobals *kg,
+ const ShaderData *sd,
+ int offset,
+ int patch,
+ float u,
+ float v,
+ int channel,
+ float3 *du,
+ float3 *dv)
{
- int indices[PATCH_MAX_CONTROL_VERTS];
- float weights[PATCH_MAX_CONTROL_VERTS];
- float weights_du[PATCH_MAX_CONTROL_VERTS];
- float weights_dv[PATCH_MAX_CONTROL_VERTS];
-
- int num_control = patch_eval_control_verts(kg, sd->object, patch, u, v, channel,
- indices, weights, weights_du, weights_dv);
-
- float3 val = make_float3(0.0f, 0.0f, 0.0f);
- if(du) *du = make_float3(0.0f, 0.0f, 0.0f);
- if(dv) *dv = make_float3(0.0f, 0.0f, 0.0f);
-
- for(int i = 0; i < num_control; i++) {
- float3 v = float4_to_float3(kernel_tex_fetch(__attributes_float3, offset + indices[i]));
-
- val += v * weights[i];
- if(du) *du += v * weights_du[i];
- if(dv) *dv += v * weights_dv[i];
- }
-
- return val;
+ int indices[PATCH_MAX_CONTROL_VERTS];
+ float weights[PATCH_MAX_CONTROL_VERTS];
+ float weights_du[PATCH_MAX_CONTROL_VERTS];
+ float weights_dv[PATCH_MAX_CONTROL_VERTS];
+
+ int num_control = patch_eval_control_verts(
+ kg, sd->object, patch, u, v, channel, indices, weights, weights_du, weights_dv);
+
+ float3 val = make_float3(0.0f, 0.0f, 0.0f);
+ if (du)
+ *du = make_float3(0.0f, 0.0f, 0.0f);
+ if (dv)
+ *dv = make_float3(0.0f, 0.0f, 0.0f);
+
+ for (int i = 0; i < num_control; i++) {
+ float3 v = float4_to_float3(kernel_tex_fetch(__attributes_float3, offset + indices[i]));
+
+ val += v * weights[i];
+ if (du)
+ *du += v * weights_du[i];
+ if (dv)
+ *dv += v * weights_dv[i];
+ }
+
+ return val;
}
-ccl_device float3 patch_eval_uchar4(KernelGlobals *kg, const ShaderData *sd, int offset,
- int patch, float u, float v, int channel,
- float3 *du, float3 *dv)
+ccl_device float3 patch_eval_uchar4(KernelGlobals *kg,
+ const ShaderData *sd,
+ int offset,
+ int patch,
+ float u,
+ float v,
+ int channel,
+ float3 *du,
+ float3 *dv)
{
- int indices[PATCH_MAX_CONTROL_VERTS];
- float weights[PATCH_MAX_CONTROL_VERTS];
- float weights_du[PATCH_MAX_CONTROL_VERTS];
- float weights_dv[PATCH_MAX_CONTROL_VERTS];
-
- int num_control = patch_eval_control_verts(kg, sd->object, patch, u, v, channel,
- indices, weights, weights_du, weights_dv);
-
- float3 val = make_float3(0.0f, 0.0f, 0.0f);
- if(du) *du = make_float3(0.0f, 0.0f, 0.0f);
- if(dv) *dv = make_float3(0.0f, 0.0f, 0.0f);
-
- for(int i = 0; i < num_control; i++) {
- float3 v = color_byte_to_float(kernel_tex_fetch(__attributes_uchar4, offset + indices[i]));
-
- val += v * weights[i];
- if(du) *du += v * weights_du[i];
- if(dv) *dv += v * weights_dv[i];
- }
-
- return val;
+ int indices[PATCH_MAX_CONTROL_VERTS];
+ float weights[PATCH_MAX_CONTROL_VERTS];
+ float weights_du[PATCH_MAX_CONTROL_VERTS];
+ float weights_dv[PATCH_MAX_CONTROL_VERTS];
+
+ int num_control = patch_eval_control_verts(
+ kg, sd->object, patch, u, v, channel, indices, weights, weights_du, weights_dv);
+
+ float3 val = make_float3(0.0f, 0.0f, 0.0f);
+ if (du)
+ *du = make_float3(0.0f, 0.0f, 0.0f);
+ if (dv)
+ *dv = make_float3(0.0f, 0.0f, 0.0f);
+
+ for (int i = 0; i < num_control; i++) {
+ float3 v = color_byte_to_float(kernel_tex_fetch(__attributes_uchar4, offset + indices[i]));
+
+ val += v * weights[i];
+ if (du)
+ *du += v * weights_du[i];
+ if (dv)
+ *dv += v * weights_dv[i];
+ }
+
+ return val;
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/geom/geom_primitive.h b/intern/cycles/kernel/geom/geom_primitive.h
index 95d9d1050fb..7f2b52a24c4 100644
--- a/intern/cycles/kernel/geom/geom_primitive.h
+++ b/intern/cycles/kernel/geom/geom_primitive.h
@@ -22,57 +22,59 @@
CCL_NAMESPACE_BEGIN
/* Generic primitive attribute reading functions */
-ccl_device_inline float primitive_attribute_float(KernelGlobals *kg,
- const ShaderData *sd,
- const AttributeDescriptor desc,
- float *dx, float *dy)
+ccl_device_inline float primitive_attribute_float(
+ KernelGlobals *kg, const ShaderData *sd, const AttributeDescriptor desc, float *dx, float *dy)
{
- if(sd->type & PRIMITIVE_ALL_TRIANGLE) {
- if(subd_triangle_patch(kg, sd) == ~0)
- return triangle_attribute_float(kg, sd, desc, dx, dy);
- else
- return subd_triangle_attribute_float(kg, sd, desc, dx, dy);
- }
+ if (sd->type & PRIMITIVE_ALL_TRIANGLE) {
+ if (subd_triangle_patch(kg, sd) == ~0)
+ return triangle_attribute_float(kg, sd, desc, dx, dy);
+ else
+ return subd_triangle_attribute_float(kg, sd, desc, dx, dy);
+ }
#ifdef __HAIR__
- else if(sd->type & PRIMITIVE_ALL_CURVE) {
- return curve_attribute_float(kg, sd, desc, dx, dy);
- }
+ else if (sd->type & PRIMITIVE_ALL_CURVE) {
+ return curve_attribute_float(kg, sd, desc, dx, dy);
+ }
#endif
#ifdef __VOLUME__
- else if(sd->object != OBJECT_NONE && desc.element == ATTR_ELEMENT_VOXEL) {
- if(dx) *dx = 0.0f;
- if(dy) *dy = 0.0f;
- return volume_attribute_float(kg, sd, desc);
- }
+ else if (sd->object != OBJECT_NONE && desc.element == ATTR_ELEMENT_VOXEL) {
+ if (dx)
+ *dx = 0.0f;
+ if (dy)
+ *dy = 0.0f;
+ return volume_attribute_float(kg, sd, desc);
+ }
#endif
- else {
- if(dx) *dx = 0.0f;
- if(dy) *dy = 0.0f;
- return 0.0f;
- }
+ else {
+ if (dx)
+ *dx = 0.0f;
+ if (dy)
+ *dy = 0.0f;
+ return 0.0f;
+ }
}
-ccl_device_inline float primitive_surface_attribute_float(KernelGlobals *kg,
- const ShaderData *sd,
- const AttributeDescriptor desc,
- float *dx, float *dy)
+ccl_device_inline float primitive_surface_attribute_float(
+ KernelGlobals *kg, const ShaderData *sd, const AttributeDescriptor desc, float *dx, float *dy)
{
- if(sd->type & PRIMITIVE_ALL_TRIANGLE) {
- if(subd_triangle_patch(kg, sd) == ~0)
- return triangle_attribute_float(kg, sd, desc, dx, dy);
- else
- return subd_triangle_attribute_float(kg, sd, desc, dx, dy);
- }
+ if (sd->type & PRIMITIVE_ALL_TRIANGLE) {
+ if (subd_triangle_patch(kg, sd) == ~0)
+ return triangle_attribute_float(kg, sd, desc, dx, dy);
+ else
+ return subd_triangle_attribute_float(kg, sd, desc, dx, dy);
+ }
#ifdef __HAIR__
- else if(sd->type & PRIMITIVE_ALL_CURVE) {
- return curve_attribute_float(kg, sd, desc, dx, dy);
- }
+ else if (sd->type & PRIMITIVE_ALL_CURVE) {
+ return curve_attribute_float(kg, sd, desc, dx, dy);
+ }
#endif
- else {
- if(dx) *dx = 0.0f;
- if(dy) *dy = 0.0f;
- return 0.0f;
- }
+ else {
+ if (dx)
+ *dx = 0.0f;
+ if (dy)
+ *dy = 0.0f;
+ return 0.0f;
+ }
}
#ifdef __VOLUME__
@@ -80,120 +82,136 @@ ccl_device_inline float primitive_volume_attribute_float(KernelGlobals *kg,
const ShaderData *sd,
const AttributeDescriptor desc)
{
- if(sd->object != OBJECT_NONE && desc.element == ATTR_ELEMENT_VOXEL) {
- return volume_attribute_float(kg, sd, desc);
- }
- else {
- return 0.0f;
- }
+ if (sd->object != OBJECT_NONE && desc.element == ATTR_ELEMENT_VOXEL) {
+ return volume_attribute_float(kg, sd, desc);
+ }
+ else {
+ return 0.0f;
+ }
}
#endif
ccl_device_inline float2 primitive_attribute_float2(KernelGlobals *kg,
const ShaderData *sd,
const AttributeDescriptor desc,
- float2 *dx, float2 *dy)
+ float2 *dx,
+ float2 *dy)
{
- if(sd->type & PRIMITIVE_ALL_TRIANGLE) {
- if(subd_triangle_patch(kg, sd) == ~0)
- return triangle_attribute_float2(kg, sd, desc, dx, dy);
- else
- return subd_triangle_attribute_float2(kg, sd, desc, dx, dy);
- }
+ if (sd->type & PRIMITIVE_ALL_TRIANGLE) {
+ if (subd_triangle_patch(kg, sd) == ~0)
+ return triangle_attribute_float2(kg, sd, desc, dx, dy);
+ else
+ return subd_triangle_attribute_float2(kg, sd, desc, dx, dy);
+ }
#ifdef __HAIR__
- else if(sd->type & PRIMITIVE_ALL_CURVE) {
- return curve_attribute_float2(kg, sd, desc, dx, dy);
- }
+ else if (sd->type & PRIMITIVE_ALL_CURVE) {
+ return curve_attribute_float2(kg, sd, desc, dx, dy);
+ }
#endif
#ifdef __VOLUME__
- else if(sd->object != OBJECT_NONE && desc.element == ATTR_ELEMENT_VOXEL) {
- kernel_assert(0);
- if(dx) *dx = make_float2(0.0f, 0.0f);
- if(dy) *dy = make_float2(0.0f, 0.0f);
- return make_float2(0.0f, 0.0f);
- }
+ else if (sd->object != OBJECT_NONE && desc.element == ATTR_ELEMENT_VOXEL) {
+ kernel_assert(0);
+ if (dx)
+ *dx = make_float2(0.0f, 0.0f);
+ if (dy)
+ *dy = make_float2(0.0f, 0.0f);
+ return make_float2(0.0f, 0.0f);
+ }
#endif
- else {
- if(dx) *dx = make_float2(0.0f, 0.0f);
- if(dy) *dy = make_float2(0.0f, 0.0f);
- return make_float2(0.0f, 0.0f);
- }
+ else {
+ if (dx)
+ *dx = make_float2(0.0f, 0.0f);
+ if (dy)
+ *dy = make_float2(0.0f, 0.0f);
+ return make_float2(0.0f, 0.0f);
+ }
}
ccl_device_inline float3 primitive_attribute_float3(KernelGlobals *kg,
const ShaderData *sd,
const AttributeDescriptor desc,
- float3 *dx, float3 *dy)
+ float3 *dx,
+ float3 *dy)
{
- if(sd->type & PRIMITIVE_ALL_TRIANGLE) {
- if(subd_triangle_patch(kg, sd) == ~0)
- return triangle_attribute_float3(kg, sd, desc, dx, dy);
- else
- return subd_triangle_attribute_float3(kg, sd, desc, dx, dy);
- }
+ if (sd->type & PRIMITIVE_ALL_TRIANGLE) {
+ if (subd_triangle_patch(kg, sd) == ~0)
+ return triangle_attribute_float3(kg, sd, desc, dx, dy);
+ else
+ return subd_triangle_attribute_float3(kg, sd, desc, dx, dy);
+ }
#ifdef __HAIR__
- else if(sd->type & PRIMITIVE_ALL_CURVE) {
- return curve_attribute_float3(kg, sd, desc, dx, dy);
- }
+ else if (sd->type & PRIMITIVE_ALL_CURVE) {
+ return curve_attribute_float3(kg, sd, desc, dx, dy);
+ }
#endif
#ifdef __VOLUME__
- else if(sd->object != OBJECT_NONE && desc.element == ATTR_ELEMENT_VOXEL) {
- if(dx) *dx = make_float3(0.0f, 0.0f, 0.0f);
- if(dy) *dy = make_float3(0.0f, 0.0f, 0.0f);
- return volume_attribute_float3(kg, sd, desc);
- }
+ else if (sd->object != OBJECT_NONE && desc.element == ATTR_ELEMENT_VOXEL) {
+ if (dx)
+ *dx = make_float3(0.0f, 0.0f, 0.0f);
+ if (dy)
+ *dy = make_float3(0.0f, 0.0f, 0.0f);
+ return volume_attribute_float3(kg, sd, desc);
+ }
#endif
- else {
- if(dx) *dx = make_float3(0.0f, 0.0f, 0.0f);
- if(dy) *dy = make_float3(0.0f, 0.0f, 0.0f);
- return make_float3(0.0f, 0.0f, 0.0f);
- }
+ else {
+ if (dx)
+ *dx = make_float3(0.0f, 0.0f, 0.0f);
+ if (dy)
+ *dy = make_float3(0.0f, 0.0f, 0.0f);
+ return make_float3(0.0f, 0.0f, 0.0f);
+ }
}
ccl_device_inline float2 primitive_surface_attribute_float2(KernelGlobals *kg,
const ShaderData *sd,
const AttributeDescriptor desc,
- float2 *dx, float2 *dy)
+ float2 *dx,
+ float2 *dy)
{
- if(sd->type & PRIMITIVE_ALL_TRIANGLE) {
- if(subd_triangle_patch(kg, sd) == ~0)
- return triangle_attribute_float2(kg, sd, desc, dx, dy);
- else
- return subd_triangle_attribute_float2(kg, sd, desc, dx, dy);
- }
+ if (sd->type & PRIMITIVE_ALL_TRIANGLE) {
+ if (subd_triangle_patch(kg, sd) == ~0)
+ return triangle_attribute_float2(kg, sd, desc, dx, dy);
+ else
+ return subd_triangle_attribute_float2(kg, sd, desc, dx, dy);
+ }
#ifdef __HAIR__
- else if(sd->type & PRIMITIVE_ALL_CURVE) {
- return curve_attribute_float2(kg, sd, desc, dx, dy);
- }
+ else if (sd->type & PRIMITIVE_ALL_CURVE) {
+ return curve_attribute_float2(kg, sd, desc, dx, dy);
+ }
#endif
- else {
- if(dx) *dx = make_float2(0.0f, 0.0f);
- if(dy) *dy = make_float2(0.0f, 0.0f);
- return make_float2(0.0f, 0.0f);
- }
+ else {
+ if (dx)
+ *dx = make_float2(0.0f, 0.0f);
+ if (dy)
+ *dy = make_float2(0.0f, 0.0f);
+ return make_float2(0.0f, 0.0f);
+ }
}
ccl_device_inline float3 primitive_surface_attribute_float3(KernelGlobals *kg,
const ShaderData *sd,
const AttributeDescriptor desc,
- float3 *dx, float3 *dy)
+ float3 *dx,
+ float3 *dy)
{
- if(sd->type & PRIMITIVE_ALL_TRIANGLE) {
- if(subd_triangle_patch(kg, sd) == ~0)
- return triangle_attribute_float3(kg, sd, desc, dx, dy);
- else
- return subd_triangle_attribute_float3(kg, sd, desc, dx, dy);
- }
+ if (sd->type & PRIMITIVE_ALL_TRIANGLE) {
+ if (subd_triangle_patch(kg, sd) == ~0)
+ return triangle_attribute_float3(kg, sd, desc, dx, dy);
+ else
+ return subd_triangle_attribute_float3(kg, sd, desc, dx, dy);
+ }
#ifdef __HAIR__
- else if(sd->type & PRIMITIVE_ALL_CURVE) {
- return curve_attribute_float3(kg, sd, desc, dx, dy);
- }
+ else if (sd->type & PRIMITIVE_ALL_CURVE) {
+ return curve_attribute_float3(kg, sd, desc, dx, dy);
+ }
#endif
- else {
- if(dx) *dx = make_float3(0.0f, 0.0f, 0.0f);
- if(dy) *dy = make_float3(0.0f, 0.0f, 0.0f);
- return make_float3(0.0f, 0.0f, 0.0f);
- }
+ else {
+ if (dx)
+ *dx = make_float3(0.0f, 0.0f, 0.0f);
+ if (dy)
+ *dy = make_float3(0.0f, 0.0f, 0.0f);
+ return make_float3(0.0f, 0.0f, 0.0f);
+ }
}
#ifdef __VOLUME__
@@ -201,12 +219,12 @@ ccl_device_inline float3 primitive_volume_attribute_float3(KernelGlobals *kg,
const ShaderData *sd,
const AttributeDescriptor desc)
{
- if(sd->object != OBJECT_NONE && desc.element == ATTR_ELEMENT_VOXEL) {
- return volume_attribute_float3(kg, sd, desc);
- }
- else {
- return make_float3(0.0f, 0.0f, 0.0f);
- }
+ if (sd->object != OBJECT_NONE && desc.element == ATTR_ELEMENT_VOXEL) {
+ return volume_attribute_float3(kg, sd, desc);
+ }
+ else {
+ return make_float3(0.0f, 0.0f, 0.0f);
+ }
}
#endif
@@ -214,33 +232,33 @@ ccl_device_inline float3 primitive_volume_attribute_float3(KernelGlobals *kg,
ccl_device_inline float3 primitive_uv(KernelGlobals *kg, ShaderData *sd)
{
- const AttributeDescriptor desc = find_attribute(kg, sd, ATTR_STD_UV);
+ const AttributeDescriptor desc = find_attribute(kg, sd, ATTR_STD_UV);
- if(desc.offset == ATTR_STD_NOT_FOUND)
- return make_float3(0.0f, 0.0f, 0.0f);
+ if (desc.offset == ATTR_STD_NOT_FOUND)
+ return make_float3(0.0f, 0.0f, 0.0f);
- float2 uv = primitive_surface_attribute_float2(kg, sd, desc, NULL, NULL);
- return make_float3(uv.x, uv.y, 1.0f);
+ float2 uv = primitive_surface_attribute_float2(kg, sd, desc, NULL, NULL);
+ return make_float3(uv.x, uv.y, 1.0f);
}
/* Ptex coordinates */
ccl_device bool primitive_ptex(KernelGlobals *kg, ShaderData *sd, float2 *uv, int *face_id)
{
- /* storing ptex data as attributes is not memory efficient but simple for tests */
- const AttributeDescriptor desc_face_id = find_attribute(kg, sd, ATTR_STD_PTEX_FACE_ID);
- const AttributeDescriptor desc_uv = find_attribute(kg, sd, ATTR_STD_PTEX_UV);
+ /* storing ptex data as attributes is not memory efficient but simple for tests */
+ const AttributeDescriptor desc_face_id = find_attribute(kg, sd, ATTR_STD_PTEX_FACE_ID);
+ const AttributeDescriptor desc_uv = find_attribute(kg, sd, ATTR_STD_PTEX_UV);
- if(desc_face_id.offset == ATTR_STD_NOT_FOUND || desc_uv.offset == ATTR_STD_NOT_FOUND)
- return false;
+ if (desc_face_id.offset == ATTR_STD_NOT_FOUND || desc_uv.offset == ATTR_STD_NOT_FOUND)
+ return false;
- float3 uv3 = primitive_surface_attribute_float3(kg, sd, desc_uv, NULL, NULL);
- float face_id_f = primitive_surface_attribute_float(kg, sd, desc_face_id, NULL, NULL);
+ float3 uv3 = primitive_surface_attribute_float3(kg, sd, desc_uv, NULL, NULL);
+ float face_id_f = primitive_surface_attribute_float(kg, sd, desc_face_id, NULL, NULL);
- *uv = make_float2(uv3.x, uv3.y);
- *face_id = (int)face_id_f;
+ *uv = make_float2(uv3.x, uv3.y);
+ *face_id = (int)face_id_f;
- return true;
+ return true;
}
/* Surface tangent */
@@ -248,125 +266,125 @@ ccl_device bool primitive_ptex(KernelGlobals *kg, ShaderData *sd, float2 *uv, in
ccl_device float3 primitive_tangent(KernelGlobals *kg, ShaderData *sd)
{
#ifdef __HAIR__
- if(sd->type & PRIMITIVE_ALL_CURVE)
+ if (sd->type & PRIMITIVE_ALL_CURVE)
# ifdef __DPDU__
- return normalize(sd->dPdu);
+ return normalize(sd->dPdu);
# else
- return make_float3(0.0f, 0.0f, 0.0f);
+ return make_float3(0.0f, 0.0f, 0.0f);
# endif
#endif
- /* try to create spherical tangent from generated coordinates */
- const AttributeDescriptor desc = find_attribute(kg, sd, ATTR_STD_GENERATED);
-
- if(desc.offset != ATTR_STD_NOT_FOUND) {
- float3 data = primitive_surface_attribute_float3(kg, sd, desc, NULL, NULL);
- data = make_float3(-(data.y - 0.5f), (data.x - 0.5f), 0.0f);
- object_normal_transform(kg, sd, &data);
- return cross(sd->N, normalize(cross(data, sd->N)));
- }
- else {
- /* otherwise use surface derivatives */
+ /* try to create spherical tangent from generated coordinates */
+ const AttributeDescriptor desc = find_attribute(kg, sd, ATTR_STD_GENERATED);
+
+ if (desc.offset != ATTR_STD_NOT_FOUND) {
+ float3 data = primitive_surface_attribute_float3(kg, sd, desc, NULL, NULL);
+ data = make_float3(-(data.y - 0.5f), (data.x - 0.5f), 0.0f);
+ object_normal_transform(kg, sd, &data);
+ return cross(sd->N, normalize(cross(data, sd->N)));
+ }
+ else {
+ /* otherwise use surface derivatives */
#ifdef __DPDU__
- return normalize(sd->dPdu);
+ return normalize(sd->dPdu);
#else
- return make_float3(0.0f, 0.0f, 0.0f);
+ return make_float3(0.0f, 0.0f, 0.0f);
#endif
- }
+ }
}
/* Motion vector for motion pass */
ccl_device_inline float4 primitive_motion_vector(KernelGlobals *kg, ShaderData *sd)
{
- /* center position */
- float3 center;
+ /* center position */
+ float3 center;
#ifdef __HAIR__
- bool is_curve_primitive = sd->type & PRIMITIVE_ALL_CURVE;
- if(is_curve_primitive) {
- center = curve_motion_center_location(kg, sd);
-
- if(!(sd->object_flag & SD_OBJECT_TRANSFORM_APPLIED)) {
- object_position_transform(kg, sd, &center);
- }
- }
- else
+ bool is_curve_primitive = sd->type & PRIMITIVE_ALL_CURVE;
+ if (is_curve_primitive) {
+ center = curve_motion_center_location(kg, sd);
+
+ if (!(sd->object_flag & SD_OBJECT_TRANSFORM_APPLIED)) {
+ object_position_transform(kg, sd, &center);
+ }
+ }
+ else
#endif
- center = sd->P;
+ center = sd->P;
- float3 motion_pre = center, motion_post = center;
+ float3 motion_pre = center, motion_post = center;
- /* deformation motion */
- AttributeDescriptor desc = find_attribute(kg, sd, ATTR_STD_MOTION_VERTEX_POSITION);
+ /* deformation motion */
+ AttributeDescriptor desc = find_attribute(kg, sd, ATTR_STD_MOTION_VERTEX_POSITION);
- if(desc.offset != ATTR_STD_NOT_FOUND) {
- /* get motion info */
- int numverts, numkeys;
- object_motion_info(kg, sd->object, NULL, &numverts, &numkeys);
+ if (desc.offset != ATTR_STD_NOT_FOUND) {
+ /* get motion info */
+ int numverts, numkeys;
+ object_motion_info(kg, sd->object, NULL, &numverts, &numkeys);
- /* lookup attributes */
- motion_pre = primitive_surface_attribute_float3(kg, sd, desc, NULL, NULL);
+ /* lookup attributes */
+ motion_pre = primitive_surface_attribute_float3(kg, sd, desc, NULL, NULL);
- desc.offset += (sd->type & PRIMITIVE_ALL_TRIANGLE)? numverts: numkeys;
- motion_post = primitive_surface_attribute_float3(kg, sd, desc, NULL, NULL);
+ desc.offset += (sd->type & PRIMITIVE_ALL_TRIANGLE) ? numverts : numkeys;
+ motion_post = primitive_surface_attribute_float3(kg, sd, desc, NULL, NULL);
#ifdef __HAIR__
- if(is_curve_primitive && (sd->object_flag & SD_OBJECT_HAS_VERTEX_MOTION) == 0) {
- object_position_transform(kg, sd, &motion_pre);
- object_position_transform(kg, sd, &motion_post);
- }
+ if (is_curve_primitive && (sd->object_flag & SD_OBJECT_HAS_VERTEX_MOTION) == 0) {
+ object_position_transform(kg, sd, &motion_pre);
+ object_position_transform(kg, sd, &motion_post);
+ }
#endif
- }
-
- /* object motion. note that depending on the mesh having motion vectors, this
- * transformation was set match the world/object space of motion_pre/post */
- Transform tfm;
-
- tfm = object_fetch_motion_pass_transform(kg, sd->object, OBJECT_PASS_MOTION_PRE);
- motion_pre = transform_point(&tfm, motion_pre);
-
- tfm = object_fetch_motion_pass_transform(kg, sd->object, OBJECT_PASS_MOTION_POST);
- motion_post = transform_point(&tfm, motion_post);
-
- float3 motion_center;
-
- /* camera motion, for perspective/orthographic motion.pre/post will be a
- * world-to-raster matrix, for panorama it's world-to-camera */
- if(kernel_data.cam.type != CAMERA_PANORAMA) {
- ProjectionTransform projection = kernel_data.cam.worldtoraster;
- motion_center = transform_perspective(&projection, center);
-
- projection = kernel_data.cam.perspective_pre;
- motion_pre = transform_perspective(&projection, motion_pre);
-
- projection = kernel_data.cam.perspective_post;
- motion_post = transform_perspective(&projection, motion_post);
- }
- else {
- tfm = kernel_data.cam.worldtocamera;
- motion_center = normalize(transform_point(&tfm, center));
- motion_center = float2_to_float3(direction_to_panorama(&kernel_data.cam, motion_center));
- motion_center.x *= kernel_data.cam.width;
- motion_center.y *= kernel_data.cam.height;
-
- tfm = kernel_data.cam.motion_pass_pre;
- motion_pre = normalize(transform_point(&tfm, motion_pre));
- motion_pre = float2_to_float3(direction_to_panorama(&kernel_data.cam, motion_pre));
- motion_pre.x *= kernel_data.cam.width;
- motion_pre.y *= kernel_data.cam.height;
-
- tfm = kernel_data.cam.motion_pass_post;
- motion_post = normalize(transform_point(&tfm, motion_post));
- motion_post = float2_to_float3(direction_to_panorama(&kernel_data.cam, motion_post));
- motion_post.x *= kernel_data.cam.width;
- motion_post.y *= kernel_data.cam.height;
- }
-
- motion_pre = motion_pre - motion_center;
- motion_post = motion_center - motion_post;
-
- return make_float4(motion_pre.x, motion_pre.y, motion_post.x, motion_post.y);
+ }
+
+ /* object motion. note that depending on the mesh having motion vectors, this
+ * transformation was set match the world/object space of motion_pre/post */
+ Transform tfm;
+
+ tfm = object_fetch_motion_pass_transform(kg, sd->object, OBJECT_PASS_MOTION_PRE);
+ motion_pre = transform_point(&tfm, motion_pre);
+
+ tfm = object_fetch_motion_pass_transform(kg, sd->object, OBJECT_PASS_MOTION_POST);
+ motion_post = transform_point(&tfm, motion_post);
+
+ float3 motion_center;
+
+ /* camera motion, for perspective/orthographic motion.pre/post will be a
+ * world-to-raster matrix, for panorama it's world-to-camera */
+ if (kernel_data.cam.type != CAMERA_PANORAMA) {
+ ProjectionTransform projection = kernel_data.cam.worldtoraster;
+ motion_center = transform_perspective(&projection, center);
+
+ projection = kernel_data.cam.perspective_pre;
+ motion_pre = transform_perspective(&projection, motion_pre);
+
+ projection = kernel_data.cam.perspective_post;
+ motion_post = transform_perspective(&projection, motion_post);
+ }
+ else {
+ tfm = kernel_data.cam.worldtocamera;
+ motion_center = normalize(transform_point(&tfm, center));
+ motion_center = float2_to_float3(direction_to_panorama(&kernel_data.cam, motion_center));
+ motion_center.x *= kernel_data.cam.width;
+ motion_center.y *= kernel_data.cam.height;
+
+ tfm = kernel_data.cam.motion_pass_pre;
+ motion_pre = normalize(transform_point(&tfm, motion_pre));
+ motion_pre = float2_to_float3(direction_to_panorama(&kernel_data.cam, motion_pre));
+ motion_pre.x *= kernel_data.cam.width;
+ motion_pre.y *= kernel_data.cam.height;
+
+ tfm = kernel_data.cam.motion_pass_post;
+ motion_post = normalize(transform_point(&tfm, motion_post));
+ motion_post = float2_to_float3(direction_to_panorama(&kernel_data.cam, motion_post));
+ motion_post.x *= kernel_data.cam.width;
+ motion_post.y *= kernel_data.cam.height;
+ }
+
+ motion_pre = motion_pre - motion_center;
+ motion_post = motion_center - motion_post;
+
+ return make_float4(motion_pre.x, motion_pre.y, motion_post.x, motion_post.y);
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/geom/geom_subd_triangle.h b/intern/cycles/kernel/geom/geom_subd_triangle.h
index 251e070c21f..8d5b3c12833 100644
--- a/intern/cycles/kernel/geom/geom_subd_triangle.h
+++ b/intern/cycles/kernel/geom/geom_subd_triangle.h
@@ -22,455 +22,492 @@ CCL_NAMESPACE_BEGIN
ccl_device_inline uint subd_triangle_patch(KernelGlobals *kg, const ShaderData *sd)
{
- return (sd->prim != PRIM_NONE) ? kernel_tex_fetch(__tri_patch, sd->prim) : ~0;
+ return (sd->prim != PRIM_NONE) ? kernel_tex_fetch(__tri_patch, sd->prim) : ~0;
}
/* UV coords of triangle within patch */
-ccl_device_inline void subd_triangle_patch_uv(KernelGlobals *kg, const ShaderData *sd, float2 uv[3])
+ccl_device_inline void subd_triangle_patch_uv(KernelGlobals *kg,
+ const ShaderData *sd,
+ float2 uv[3])
{
- uint4 tri_vindex = kernel_tex_fetch(__tri_vindex, sd->prim);
+ uint4 tri_vindex = kernel_tex_fetch(__tri_vindex, sd->prim);
- uv[0] = kernel_tex_fetch(__tri_patch_uv, tri_vindex.x);
- uv[1] = kernel_tex_fetch(__tri_patch_uv, tri_vindex.y);
- uv[2] = kernel_tex_fetch(__tri_patch_uv, tri_vindex.z);
+ uv[0] = kernel_tex_fetch(__tri_patch_uv, tri_vindex.x);
+ uv[1] = kernel_tex_fetch(__tri_patch_uv, tri_vindex.y);
+ uv[2] = kernel_tex_fetch(__tri_patch_uv, tri_vindex.z);
}
/* Vertex indices of patch */
ccl_device_inline uint4 subd_triangle_patch_indices(KernelGlobals *kg, int patch)
{
- uint4 indices;
+ uint4 indices;
- indices.x = kernel_tex_fetch(__patches, patch+0);
- indices.y = kernel_tex_fetch(__patches, patch+1);
- indices.z = kernel_tex_fetch(__patches, patch+2);
- indices.w = kernel_tex_fetch(__patches, patch+3);
+ indices.x = kernel_tex_fetch(__patches, patch + 0);
+ indices.y = kernel_tex_fetch(__patches, patch + 1);
+ indices.z = kernel_tex_fetch(__patches, patch + 2);
+ indices.w = kernel_tex_fetch(__patches, patch + 3);
- return indices;
+ return indices;
}
/* Originating face for patch */
ccl_device_inline uint subd_triangle_patch_face(KernelGlobals *kg, int patch)
{
- return kernel_tex_fetch(__patches, patch+4);
+ return kernel_tex_fetch(__patches, patch + 4);
}
/* Number of corners on originating face */
ccl_device_inline uint subd_triangle_patch_num_corners(KernelGlobals *kg, int patch)
{
- return kernel_tex_fetch(__patches, patch+5) & 0xffff;
+ return kernel_tex_fetch(__patches, patch + 5) & 0xffff;
}
/* Indices of the four corners that are used by the patch */
ccl_device_inline void subd_triangle_patch_corners(KernelGlobals *kg, int patch, int corners[4])
{
- uint4 data;
-
- data.x = kernel_tex_fetch(__patches, patch+4);
- data.y = kernel_tex_fetch(__patches, patch+5);
- data.z = kernel_tex_fetch(__patches, patch+6);
- data.w = kernel_tex_fetch(__patches, patch+7);
-
- int num_corners = data.y & 0xffff;
-
- if(num_corners == 4) {
- /* quad */
- corners[0] = data.z;
- corners[1] = data.z+1;
- corners[2] = data.z+2;
- corners[3] = data.z+3;
- }
- else {
- /* ngon */
- int c = data.y >> 16;
-
- corners[0] = data.z + c;
- corners[1] = data.z + mod(c+1, num_corners);
- corners[2] = data.w;
- corners[3] = data.z + mod(c-1, num_corners);
- }
+ uint4 data;
+
+ data.x = kernel_tex_fetch(__patches, patch + 4);
+ data.y = kernel_tex_fetch(__patches, patch + 5);
+ data.z = kernel_tex_fetch(__patches, patch + 6);
+ data.w = kernel_tex_fetch(__patches, patch + 7);
+
+ int num_corners = data.y & 0xffff;
+
+ if (num_corners == 4) {
+ /* quad */
+ corners[0] = data.z;
+ corners[1] = data.z + 1;
+ corners[2] = data.z + 2;
+ corners[3] = data.z + 3;
+ }
+ else {
+ /* ngon */
+ int c = data.y >> 16;
+
+ corners[0] = data.z + c;
+ corners[1] = data.z + mod(c + 1, num_corners);
+ corners[2] = data.w;
+ corners[3] = data.z + mod(c - 1, num_corners);
+ }
}
/* Reading attributes on various subdivision triangle elements */
-ccl_device_noinline float subd_triangle_attribute_float(KernelGlobals *kg, const ShaderData *sd, const AttributeDescriptor desc, float *dx, float *dy)
+ccl_device_noinline float subd_triangle_attribute_float(
+ KernelGlobals *kg, const ShaderData *sd, const AttributeDescriptor desc, float *dx, float *dy)
{
- int patch = subd_triangle_patch(kg, sd);
+ int patch = subd_triangle_patch(kg, sd);
#ifdef __PATCH_EVAL__
- if(desc.flags & ATTR_SUBDIVIDED) {
- float2 uv[3];
- subd_triangle_patch_uv(kg, sd, uv);
-
- float2 dpdu = uv[0] - uv[2];
- float2 dpdv = uv[1] - uv[2];
-
- /* p is [s, t] */
- float2 p = dpdu * sd->u + dpdv * sd->v + uv[2];
-
- float a, dads, dadt;
- a = patch_eval_float(kg, sd, desc.offset, patch, p.x, p.y, 0, &dads, &dadt);
+ if (desc.flags & ATTR_SUBDIVIDED) {
+ float2 uv[3];
+ subd_triangle_patch_uv(kg, sd, uv);
+
+ float2 dpdu = uv[0] - uv[2];
+ float2 dpdv = uv[1] - uv[2];
+
+ /* p is [s, t] */
+ float2 p = dpdu * sd->u + dpdv * sd->v + uv[2];
+
+ float a, dads, dadt;
+ a = patch_eval_float(kg, sd, desc.offset, patch, p.x, p.y, 0, &dads, &dadt);
+
+# ifdef __RAY_DIFFERENTIALS__
+ if (dx || dy) {
+ float dsdu = dpdu.x;
+ float dtdu = dpdu.y;
+ float dsdv = dpdv.x;
+ float dtdv = dpdv.y;
+
+ if (dx) {
+ float dudx = sd->du.dx;
+ float dvdx = sd->dv.dx;
+
+ float dsdx = dsdu * dudx + dsdv * dvdx;
+ float dtdx = dtdu * dudx + dtdv * dvdx;
+
+ *dx = dads * dsdx + dadt * dtdx;
+ }
+ if (dy) {
+ float dudy = sd->du.dy;
+ float dvdy = sd->dv.dy;
+
+ float dsdy = dsdu * dudy + dsdv * dvdy;
+ float dtdy = dtdu * dudy + dtdv * dvdy;
+
+ *dy = dads * dsdy + dadt * dtdy;
+ }
+ }
+# endif
+
+ return a;
+ }
+ else
+#endif /* __PATCH_EVAL__ */
+ if (desc.element == ATTR_ELEMENT_FACE) {
+ if (dx)
+ *dx = 0.0f;
+ if (dy)
+ *dy = 0.0f;
+
+ return kernel_tex_fetch(__attributes_float, desc.offset + subd_triangle_patch_face(kg, patch));
+ }
+ else if (desc.element == ATTR_ELEMENT_VERTEX || desc.element == ATTR_ELEMENT_VERTEX_MOTION) {
+ float2 uv[3];
+ subd_triangle_patch_uv(kg, sd, uv);
+
+ uint4 v = subd_triangle_patch_indices(kg, patch);
+
+ float f0 = kernel_tex_fetch(__attributes_float, desc.offset + v.x);
+ float f1 = kernel_tex_fetch(__attributes_float, desc.offset + v.y);
+ float f2 = kernel_tex_fetch(__attributes_float, desc.offset + v.z);
+ float f3 = kernel_tex_fetch(__attributes_float, desc.offset + v.w);
+
+ if (subd_triangle_patch_num_corners(kg, patch) != 4) {
+ f1 = (f1 + f0) * 0.5f;
+ f3 = (f3 + f0) * 0.5f;
+ }
+
+ float a = mix(mix(f0, f1, uv[0].x), mix(f3, f2, uv[0].x), uv[0].y);
+ float b = mix(mix(f0, f1, uv[1].x), mix(f3, f2, uv[1].x), uv[1].y);
+ float c = mix(mix(f0, f1, uv[2].x), mix(f3, f2, uv[2].x), uv[2].y);
#ifdef __RAY_DIFFERENTIALS__
- if(dx || dy) {
- float dsdu = dpdu.x;
- float dtdu = dpdu.y;
- float dsdv = dpdv.x;
- float dtdv = dpdv.y;
-
- if(dx) {
- float dudx = sd->du.dx;
- float dvdx = sd->dv.dx;
-
- float dsdx = dsdu*dudx + dsdv*dvdx;
- float dtdx = dtdu*dudx + dtdv*dvdx;
-
- *dx = dads*dsdx + dadt*dtdx;
- }
- if(dy) {
- float dudy = sd->du.dy;
- float dvdy = sd->dv.dy;
-
- float dsdy = dsdu*dudy + dsdv*dvdy;
- float dtdy = dtdu*dudy + dtdv*dvdy;
-
- *dy = dads*dsdy + dadt*dtdy;
- }
- }
+ if (dx)
+ *dx = sd->du.dx * a + sd->dv.dx * b - (sd->du.dx + sd->dv.dx) * c;
+ if (dy)
+ *dy = sd->du.dy * a + sd->dv.dy * b - (sd->du.dy + sd->dv.dy) * c;
#endif
- return a;
- }
- else
-#endif /* __PATCH_EVAL__ */
- if(desc.element == ATTR_ELEMENT_FACE) {
- if(dx) *dx = 0.0f;
- if(dy) *dy = 0.0f;
+ return sd->u * a + sd->v * b + (1.0f - sd->u - sd->v) * c;
+ }
+ else if (desc.element == ATTR_ELEMENT_CORNER) {
+ float2 uv[3];
+ subd_triangle_patch_uv(kg, sd, uv);
- return kernel_tex_fetch(__attributes_float, desc.offset + subd_triangle_patch_face(kg, patch));
- }
- else if(desc.element == ATTR_ELEMENT_VERTEX || desc.element == ATTR_ELEMENT_VERTEX_MOTION) {
- float2 uv[3];
- subd_triangle_patch_uv(kg, sd, uv);
+ int corners[4];
+ subd_triangle_patch_corners(kg, patch, corners);
- uint4 v = subd_triangle_patch_indices(kg, patch);
+ float f0 = kernel_tex_fetch(__attributes_float, corners[0] + desc.offset);
+ float f1 = kernel_tex_fetch(__attributes_float, corners[1] + desc.offset);
+ float f2 = kernel_tex_fetch(__attributes_float, corners[2] + desc.offset);
+ float f3 = kernel_tex_fetch(__attributes_float, corners[3] + desc.offset);
- float f0 = kernel_tex_fetch(__attributes_float, desc.offset + v.x);
- float f1 = kernel_tex_fetch(__attributes_float, desc.offset + v.y);
- float f2 = kernel_tex_fetch(__attributes_float, desc.offset + v.z);
- float f3 = kernel_tex_fetch(__attributes_float, desc.offset + v.w);
+ if (subd_triangle_patch_num_corners(kg, patch) != 4) {
+ f1 = (f1 + f0) * 0.5f;
+ f3 = (f3 + f0) * 0.5f;
+ }
- if(subd_triangle_patch_num_corners(kg, patch) != 4) {
- f1 = (f1+f0)*0.5f;
- f3 = (f3+f0)*0.5f;
- }
-
- float a = mix(mix(f0, f1, uv[0].x), mix(f3, f2, uv[0].x), uv[0].y);
- float b = mix(mix(f0, f1, uv[1].x), mix(f3, f2, uv[1].x), uv[1].y);
- float c = mix(mix(f0, f1, uv[2].x), mix(f3, f2, uv[2].x), uv[2].y);
+ float a = mix(mix(f0, f1, uv[0].x), mix(f3, f2, uv[0].x), uv[0].y);
+ float b = mix(mix(f0, f1, uv[1].x), mix(f3, f2, uv[1].x), uv[1].y);
+ float c = mix(mix(f0, f1, uv[2].x), mix(f3, f2, uv[2].x), uv[2].y);
#ifdef __RAY_DIFFERENTIALS__
- if(dx) *dx = sd->du.dx*a + sd->dv.dx*b - (sd->du.dx + sd->dv.dx)*c;
- if(dy) *dy = sd->du.dy*a + sd->dv.dy*b - (sd->du.dy + sd->dv.dy)*c;
+ if (dx)
+ *dx = sd->du.dx * a + sd->dv.dx * b - (sd->du.dx + sd->dv.dx) * c;
+ if (dy)
+ *dy = sd->du.dy * a + sd->dv.dy * b - (sd->du.dy + sd->dv.dy) * c;
#endif
- return sd->u*a + sd->v*b + (1.0f - sd->u - sd->v)*c;
- }
- else if(desc.element == ATTR_ELEMENT_CORNER) {
- float2 uv[3];
- subd_triangle_patch_uv(kg, sd, uv);
-
- int corners[4];
- subd_triangle_patch_corners(kg, patch, corners);
+ return sd->u * a + sd->v * b + (1.0f - sd->u - sd->v) * c;
+ }
+ else {
+ if (dx)
+ *dx = 0.0f;
+ if (dy)
+ *dy = 0.0f;
- float f0 = kernel_tex_fetch(__attributes_float, corners[0] + desc.offset);
- float f1 = kernel_tex_fetch(__attributes_float, corners[1] + desc.offset);
- float f2 = kernel_tex_fetch(__attributes_float, corners[2] + desc.offset);
- float f3 = kernel_tex_fetch(__attributes_float, corners[3] + desc.offset);
-
- if(subd_triangle_patch_num_corners(kg, patch) != 4) {
- f1 = (f1+f0)*0.5f;
- f3 = (f3+f0)*0.5f;
- }
-
- float a = mix(mix(f0, f1, uv[0].x), mix(f3, f2, uv[0].x), uv[0].y);
- float b = mix(mix(f0, f1, uv[1].x), mix(f3, f2, uv[1].x), uv[1].y);
- float c = mix(mix(f0, f1, uv[2].x), mix(f3, f2, uv[2].x), uv[2].y);
-
-#ifdef __RAY_DIFFERENTIALS__
- if(dx) *dx = sd->du.dx*a + sd->dv.dx*b - (sd->du.dx + sd->dv.dx)*c;
- if(dy) *dy = sd->du.dy*a + sd->dv.dy*b - (sd->du.dy + sd->dv.dy)*c;
-#endif
-
- return sd->u*a + sd->v*b + (1.0f - sd->u - sd->v)*c;
- }
- else {
- if(dx) *dx = 0.0f;
- if(dy) *dy = 0.0f;
-
- return 0.0f;
- }
+ return 0.0f;
+ }
}
-ccl_device_noinline float2 subd_triangle_attribute_float2(KernelGlobals *kg, const ShaderData *sd, const AttributeDescriptor desc, float2 *dx, float2 *dy)
+ccl_device_noinline float2 subd_triangle_attribute_float2(KernelGlobals *kg,
+ const ShaderData *sd,
+ const AttributeDescriptor desc,
+ float2 *dx,
+ float2 *dy)
{
- int patch = subd_triangle_patch(kg, sd);
+ int patch = subd_triangle_patch(kg, sd);
#ifdef __PATCH_EVAL__
- if(desc.flags & ATTR_SUBDIVIDED) {
- float2 uv[3];
- subd_triangle_patch_uv(kg, sd, uv);
-
- float2 dpdu = uv[0] - uv[2];
- float2 dpdv = uv[1] - uv[2];
-
- /* p is [s, t] */
- float2 p = dpdu * sd->u + dpdv * sd->v + uv[2];
-
- float2 a, dads, dadt;
-
- a = patch_eval_float2(kg, sd, desc.offset, patch, p.x, p.y, 0, &dads, &dadt);
-
-#ifdef __RAY_DIFFERENTIALS__
- if(dx || dy) {
- float dsdu = dpdu.x;
- float dtdu = dpdu.y;
- float dsdv = dpdv.x;
- float dtdv = dpdv.y;
-
- if(dx) {
- float dudx = sd->du.dx;
- float dvdx = sd->dv.dx;
-
- float dsdx = dsdu*dudx + dsdv*dvdx;
- float dtdx = dtdu*dudx + dtdv*dvdx;
-
- *dx = dads*dsdx + dadt*dtdx;
- }
- if(dy) {
- float dudy = sd->du.dy;
- float dvdy = sd->dv.dy;
-
- float dsdy = dsdu*dudy + dsdv*dvdy;
- float dtdy = dtdu*dudy + dtdv*dvdy;
-
- *dy = dads*dsdy + dadt*dtdy;
- }
- }
-#endif
-
- return a;
- }
- else
-#endif /* __PATCH_EVAL__ */
- if(desc.element == ATTR_ELEMENT_FACE) {
- if(dx) *dx = make_float2(0.0f, 0.0f);
- if(dy) *dy = make_float2(0.0f, 0.0f);
-
- return kernel_tex_fetch(__attributes_float2, desc.offset + subd_triangle_patch_face(kg, patch));
- }
- else if(desc.element == ATTR_ELEMENT_VERTEX || desc.element == ATTR_ELEMENT_VERTEX_MOTION) {
- float2 uv[3];
- subd_triangle_patch_uv(kg, sd, uv);
-
- uint4 v = subd_triangle_patch_indices(kg, patch);
-
- float2 f0 = kernel_tex_fetch(__attributes_float2, desc.offset + v.x);
- float2 f1 = kernel_tex_fetch(__attributes_float2, desc.offset + v.y);
- float2 f2 = kernel_tex_fetch(__attributes_float2, desc.offset + v.z);
- float2 f3 = kernel_tex_fetch(__attributes_float2, desc.offset + v.w);
-
- if(subd_triangle_patch_num_corners(kg, patch) != 4) {
- f1 = (f1+f0)*0.5f;
- f3 = (f3+f0)*0.5f;
- }
-
- float2 a = mix(mix(f0, f1, uv[0].x), mix(f3, f2, uv[0].x), uv[0].y);
- float2 b = mix(mix(f0, f1, uv[1].x), mix(f3, f2, uv[1].x), uv[1].y);
- float2 c = mix(mix(f0, f1, uv[2].x), mix(f3, f2, uv[2].x), uv[2].y);
+ if (desc.flags & ATTR_SUBDIVIDED) {
+ float2 uv[3];
+ subd_triangle_patch_uv(kg, sd, uv);
+
+ float2 dpdu = uv[0] - uv[2];
+ float2 dpdv = uv[1] - uv[2];
+
+ /* p is [s, t] */
+ float2 p = dpdu * sd->u + dpdv * sd->v + uv[2];
+
+ float2 a, dads, dadt;
+
+ a = patch_eval_float2(kg, sd, desc.offset, patch, p.x, p.y, 0, &dads, &dadt);
+
+# ifdef __RAY_DIFFERENTIALS__
+ if (dx || dy) {
+ float dsdu = dpdu.x;
+ float dtdu = dpdu.y;
+ float dsdv = dpdv.x;
+ float dtdv = dpdv.y;
+
+ if (dx) {
+ float dudx = sd->du.dx;
+ float dvdx = sd->dv.dx;
+
+ float dsdx = dsdu * dudx + dsdv * dvdx;
+ float dtdx = dtdu * dudx + dtdv * dvdx;
+
+ *dx = dads * dsdx + dadt * dtdx;
+ }
+ if (dy) {
+ float dudy = sd->du.dy;
+ float dvdy = sd->dv.dy;
+
+ float dsdy = dsdu * dudy + dsdv * dvdy;
+ float dtdy = dtdu * dudy + dtdv * dvdy;
+
+ *dy = dads * dsdy + dadt * dtdy;
+ }
+ }
+# endif
+
+ return a;
+ }
+ else
+#endif /* __PATCH_EVAL__ */
+ if (desc.element == ATTR_ELEMENT_FACE) {
+ if (dx)
+ *dx = make_float2(0.0f, 0.0f);
+ if (dy)
+ *dy = make_float2(0.0f, 0.0f);
+
+ return kernel_tex_fetch(__attributes_float2,
+ desc.offset + subd_triangle_patch_face(kg, patch));
+ }
+ else if (desc.element == ATTR_ELEMENT_VERTEX || desc.element == ATTR_ELEMENT_VERTEX_MOTION) {
+ float2 uv[3];
+ subd_triangle_patch_uv(kg, sd, uv);
+
+ uint4 v = subd_triangle_patch_indices(kg, patch);
+
+ float2 f0 = kernel_tex_fetch(__attributes_float2, desc.offset + v.x);
+ float2 f1 = kernel_tex_fetch(__attributes_float2, desc.offset + v.y);
+ float2 f2 = kernel_tex_fetch(__attributes_float2, desc.offset + v.z);
+ float2 f3 = kernel_tex_fetch(__attributes_float2, desc.offset + v.w);
+
+ if (subd_triangle_patch_num_corners(kg, patch) != 4) {
+ f1 = (f1 + f0) * 0.5f;
+ f3 = (f3 + f0) * 0.5f;
+ }
+
+ float2 a = mix(mix(f0, f1, uv[0].x), mix(f3, f2, uv[0].x), uv[0].y);
+ float2 b = mix(mix(f0, f1, uv[1].x), mix(f3, f2, uv[1].x), uv[1].y);
+ float2 c = mix(mix(f0, f1, uv[2].x), mix(f3, f2, uv[2].x), uv[2].y);
#ifdef __RAY_DIFFERENTIALS__
- if(dx) *dx = sd->du.dx*a + sd->dv.dx*b - (sd->du.dx + sd->dv.dx)*c;
- if(dy) *dy = sd->du.dy*a + sd->dv.dy*b - (sd->du.dy + sd->dv.dy)*c;
+ if (dx)
+ *dx = sd->du.dx * a + sd->dv.dx * b - (sd->du.dx + sd->dv.dx) * c;
+ if (dy)
+ *dy = sd->du.dy * a + sd->dv.dy * b - (sd->du.dy + sd->dv.dy) * c;
#endif
- return sd->u*a + sd->v*b + (1.0f - sd->u - sd->v)*c;
- }
- else if(desc.element == ATTR_ELEMENT_CORNER) {
- float2 uv[3];
- subd_triangle_patch_uv(kg, sd, uv);
+ return sd->u * a + sd->v * b + (1.0f - sd->u - sd->v) * c;
+ }
+ else if (desc.element == ATTR_ELEMENT_CORNER) {
+ float2 uv[3];
+ subd_triangle_patch_uv(kg, sd, uv);
- int corners[4];
- subd_triangle_patch_corners(kg, patch, corners);
+ int corners[4];
+ subd_triangle_patch_corners(kg, patch, corners);
- float2 f0, f1, f2, f3;
+ float2 f0, f1, f2, f3;
- f0 = kernel_tex_fetch(__attributes_float2, corners[0] + desc.offset);
- f1 = kernel_tex_fetch(__attributes_float2, corners[1] + desc.offset);
- f2 = kernel_tex_fetch(__attributes_float2, corners[2] + desc.offset);
- f3 = kernel_tex_fetch(__attributes_float2, corners[3] + desc.offset);
+ f0 = kernel_tex_fetch(__attributes_float2, corners[0] + desc.offset);
+ f1 = kernel_tex_fetch(__attributes_float2, corners[1] + desc.offset);
+ f2 = kernel_tex_fetch(__attributes_float2, corners[2] + desc.offset);
+ f3 = kernel_tex_fetch(__attributes_float2, corners[3] + desc.offset);
- if(subd_triangle_patch_num_corners(kg, patch) != 4) {
- f1 = (f1+f0)*0.5f;
- f3 = (f3+f0)*0.5f;
- }
+ if (subd_triangle_patch_num_corners(kg, patch) != 4) {
+ f1 = (f1 + f0) * 0.5f;
+ f3 = (f3 + f0) * 0.5f;
+ }
- float2 a = mix(mix(f0, f1, uv[0].x), mix(f3, f2, uv[0].x), uv[0].y);
- float2 b = mix(mix(f0, f1, uv[1].x), mix(f3, f2, uv[1].x), uv[1].y);
- float2 c = mix(mix(f0, f1, uv[2].x), mix(f3, f2, uv[2].x), uv[2].y);
+ float2 a = mix(mix(f0, f1, uv[0].x), mix(f3, f2, uv[0].x), uv[0].y);
+ float2 b = mix(mix(f0, f1, uv[1].x), mix(f3, f2, uv[1].x), uv[1].y);
+ float2 c = mix(mix(f0, f1, uv[2].x), mix(f3, f2, uv[2].x), uv[2].y);
#ifdef __RAY_DIFFERENTIALS__
- if(dx) *dx = sd->du.dx*a + sd->dv.dx*b - (sd->du.dx + sd->dv.dx)*c;
- if(dy) *dy = sd->du.dy*a + sd->dv.dy*b - (sd->du.dy + sd->dv.dy)*c;
+ if (dx)
+ *dx = sd->du.dx * a + sd->dv.dx * b - (sd->du.dx + sd->dv.dx) * c;
+ if (dy)
+ *dy = sd->du.dy * a + sd->dv.dy * b - (sd->du.dy + sd->dv.dy) * c;
#endif
- return sd->u*a + sd->v*b + (1.0f - sd->u - sd->v)*c;
- }
- else {
- if(dx) *dx = make_float2(0.0f, 0.0f);
- if(dy) *dy = make_float2(0.0f, 0.0f);
+ return sd->u * a + sd->v * b + (1.0f - sd->u - sd->v) * c;
+ }
+ else {
+ if (dx)
+ *dx = make_float2(0.0f, 0.0f);
+ if (dy)
+ *dy = make_float2(0.0f, 0.0f);
- return make_float2(0.0f, 0.0f);
- }
+ return make_float2(0.0f, 0.0f);
+ }
}
-ccl_device_noinline float3 subd_triangle_attribute_float3(KernelGlobals *kg, const ShaderData *sd, const AttributeDescriptor desc, float3 *dx, float3 *dy)
+ccl_device_noinline float3 subd_triangle_attribute_float3(KernelGlobals *kg,
+ const ShaderData *sd,
+ const AttributeDescriptor desc,
+ float3 *dx,
+ float3 *dy)
{
- int patch = subd_triangle_patch(kg, sd);
+ int patch = subd_triangle_patch(kg, sd);
#ifdef __PATCH_EVAL__
- if(desc.flags & ATTR_SUBDIVIDED) {
- float2 uv[3];
- subd_triangle_patch_uv(kg, sd, uv);
-
- float2 dpdu = uv[0] - uv[2];
- float2 dpdv = uv[1] - uv[2];
-
- /* p is [s, t] */
- float2 p = dpdu * sd->u + dpdv * sd->v + uv[2];
-
- float3 a, dads, dadt;
-
- if(desc.element == ATTR_ELEMENT_CORNER_BYTE) {
- a = patch_eval_uchar4(kg, sd, desc.offset, patch, p.x, p.y, 0, &dads, &dadt);
- }
- else {
- a = patch_eval_float3(kg, sd, desc.offset, patch, p.x, p.y, 0, &dads, &dadt);
- }
-
-#ifdef __RAY_DIFFERENTIALS__
- if(dx || dy) {
- float dsdu = dpdu.x;
- float dtdu = dpdu.y;
- float dsdv = dpdv.x;
- float dtdv = dpdv.y;
-
- if(dx) {
- float dudx = sd->du.dx;
- float dvdx = sd->dv.dx;
-
- float dsdx = dsdu*dudx + dsdv*dvdx;
- float dtdx = dtdu*dudx + dtdv*dvdx;
-
- *dx = dads*dsdx + dadt*dtdx;
- }
- if(dy) {
- float dudy = sd->du.dy;
- float dvdy = sd->dv.dy;
-
- float dsdy = dsdu*dudy + dsdv*dvdy;
- float dtdy = dtdu*dudy + dtdv*dvdy;
-
- *dy = dads*dsdy + dadt*dtdy;
- }
- }
-#endif
-
- return a;
- }
- else
-#endif /* __PATCH_EVAL__ */
- if(desc.element == ATTR_ELEMENT_FACE) {
- if(dx) *dx = make_float3(0.0f, 0.0f, 0.0f);
- if(dy) *dy = make_float3(0.0f, 0.0f, 0.0f);
-
- return float4_to_float3(kernel_tex_fetch(__attributes_float3, desc.offset + subd_triangle_patch_face(kg, patch)));
- }
- else if(desc.element == ATTR_ELEMENT_VERTEX || desc.element == ATTR_ELEMENT_VERTEX_MOTION) {
- float2 uv[3];
- subd_triangle_patch_uv(kg, sd, uv);
-
- uint4 v = subd_triangle_patch_indices(kg, patch);
-
- float3 f0 = float4_to_float3(kernel_tex_fetch(__attributes_float3, desc.offset + v.x));
- float3 f1 = float4_to_float3(kernel_tex_fetch(__attributes_float3, desc.offset + v.y));
- float3 f2 = float4_to_float3(kernel_tex_fetch(__attributes_float3, desc.offset + v.z));
- float3 f3 = float4_to_float3(kernel_tex_fetch(__attributes_float3, desc.offset + v.w));
-
- if(subd_triangle_patch_num_corners(kg, patch) != 4) {
- f1 = (f1+f0)*0.5f;
- f3 = (f3+f0)*0.5f;
- }
-
- float3 a = mix(mix(f0, f1, uv[0].x), mix(f3, f2, uv[0].x), uv[0].y);
- float3 b = mix(mix(f0, f1, uv[1].x), mix(f3, f2, uv[1].x), uv[1].y);
- float3 c = mix(mix(f0, f1, uv[2].x), mix(f3, f2, uv[2].x), uv[2].y);
+ if (desc.flags & ATTR_SUBDIVIDED) {
+ float2 uv[3];
+ subd_triangle_patch_uv(kg, sd, uv);
+
+ float2 dpdu = uv[0] - uv[2];
+ float2 dpdv = uv[1] - uv[2];
+
+ /* p is [s, t] */
+ float2 p = dpdu * sd->u + dpdv * sd->v + uv[2];
+
+ float3 a, dads, dadt;
+
+ if (desc.element == ATTR_ELEMENT_CORNER_BYTE) {
+ a = patch_eval_uchar4(kg, sd, desc.offset, patch, p.x, p.y, 0, &dads, &dadt);
+ }
+ else {
+ a = patch_eval_float3(kg, sd, desc.offset, patch, p.x, p.y, 0, &dads, &dadt);
+ }
+
+# ifdef __RAY_DIFFERENTIALS__
+ if (dx || dy) {
+ float dsdu = dpdu.x;
+ float dtdu = dpdu.y;
+ float dsdv = dpdv.x;
+ float dtdv = dpdv.y;
+
+ if (dx) {
+ float dudx = sd->du.dx;
+ float dvdx = sd->dv.dx;
+
+ float dsdx = dsdu * dudx + dsdv * dvdx;
+ float dtdx = dtdu * dudx + dtdv * dvdx;
+
+ *dx = dads * dsdx + dadt * dtdx;
+ }
+ if (dy) {
+ float dudy = sd->du.dy;
+ float dvdy = sd->dv.dy;
+
+ float dsdy = dsdu * dudy + dsdv * dvdy;
+ float dtdy = dtdu * dudy + dtdv * dvdy;
+
+ *dy = dads * dsdy + dadt * dtdy;
+ }
+ }
+# endif
+
+ return a;
+ }
+ else
+#endif /* __PATCH_EVAL__ */
+ if (desc.element == ATTR_ELEMENT_FACE) {
+ if (dx)
+ *dx = make_float3(0.0f, 0.0f, 0.0f);
+ if (dy)
+ *dy = make_float3(0.0f, 0.0f, 0.0f);
+
+ return float4_to_float3(
+ kernel_tex_fetch(__attributes_float3, desc.offset + subd_triangle_patch_face(kg, patch)));
+ }
+ else if (desc.element == ATTR_ELEMENT_VERTEX || desc.element == ATTR_ELEMENT_VERTEX_MOTION) {
+ float2 uv[3];
+ subd_triangle_patch_uv(kg, sd, uv);
+
+ uint4 v = subd_triangle_patch_indices(kg, patch);
+
+ float3 f0 = float4_to_float3(kernel_tex_fetch(__attributes_float3, desc.offset + v.x));
+ float3 f1 = float4_to_float3(kernel_tex_fetch(__attributes_float3, desc.offset + v.y));
+ float3 f2 = float4_to_float3(kernel_tex_fetch(__attributes_float3, desc.offset + v.z));
+ float3 f3 = float4_to_float3(kernel_tex_fetch(__attributes_float3, desc.offset + v.w));
+
+ if (subd_triangle_patch_num_corners(kg, patch) != 4) {
+ f1 = (f1 + f0) * 0.5f;
+ f3 = (f3 + f0) * 0.5f;
+ }
+
+ float3 a = mix(mix(f0, f1, uv[0].x), mix(f3, f2, uv[0].x), uv[0].y);
+ float3 b = mix(mix(f0, f1, uv[1].x), mix(f3, f2, uv[1].x), uv[1].y);
+ float3 c = mix(mix(f0, f1, uv[2].x), mix(f3, f2, uv[2].x), uv[2].y);
#ifdef __RAY_DIFFERENTIALS__
- if(dx) *dx = sd->du.dx*a + sd->dv.dx*b - (sd->du.dx + sd->dv.dx)*c;
- if(dy) *dy = sd->du.dy*a + sd->dv.dy*b - (sd->du.dy + sd->dv.dy)*c;
+ if (dx)
+ *dx = sd->du.dx * a + sd->dv.dx * b - (sd->du.dx + sd->dv.dx) * c;
+ if (dy)
+ *dy = sd->du.dy * a + sd->dv.dy * b - (sd->du.dy + sd->dv.dy) * c;
#endif
- return sd->u*a + sd->v*b + (1.0f - sd->u - sd->v)*c;
- }
- else if(desc.element == ATTR_ELEMENT_CORNER || desc.element == ATTR_ELEMENT_CORNER_BYTE) {
- float2 uv[3];
- subd_triangle_patch_uv(kg, sd, uv);
-
- int corners[4];
- subd_triangle_patch_corners(kg, patch, corners);
-
- float3 f0, f1, f2, f3;
-
- if(desc.element == ATTR_ELEMENT_CORNER) {
- f0 = float4_to_float3(kernel_tex_fetch(__attributes_float3, corners[0] + desc.offset));
- f1 = float4_to_float3(kernel_tex_fetch(__attributes_float3, corners[1] + desc.offset));
- f2 = float4_to_float3(kernel_tex_fetch(__attributes_float3, corners[2] + desc.offset));
- f3 = float4_to_float3(kernel_tex_fetch(__attributes_float3, corners[3] + desc.offset));
- }
- else {
- f0 = color_byte_to_float(kernel_tex_fetch(__attributes_uchar4, corners[0] + desc.offset));
- f1 = color_byte_to_float(kernel_tex_fetch(__attributes_uchar4, corners[1] + desc.offset));
- f2 = color_byte_to_float(kernel_tex_fetch(__attributes_uchar4, corners[2] + desc.offset));
- f3 = color_byte_to_float(kernel_tex_fetch(__attributes_uchar4, corners[3] + desc.offset));
- }
-
- if(subd_triangle_patch_num_corners(kg, patch) != 4) {
- f1 = (f1+f0)*0.5f;
- f3 = (f3+f0)*0.5f;
- }
-
- float3 a = mix(mix(f0, f1, uv[0].x), mix(f3, f2, uv[0].x), uv[0].y);
- float3 b = mix(mix(f0, f1, uv[1].x), mix(f3, f2, uv[1].x), uv[1].y);
- float3 c = mix(mix(f0, f1, uv[2].x), mix(f3, f2, uv[2].x), uv[2].y);
+ return sd->u * a + sd->v * b + (1.0f - sd->u - sd->v) * c;
+ }
+ else if (desc.element == ATTR_ELEMENT_CORNER || desc.element == ATTR_ELEMENT_CORNER_BYTE) {
+ float2 uv[3];
+ subd_triangle_patch_uv(kg, sd, uv);
+
+ int corners[4];
+ subd_triangle_patch_corners(kg, patch, corners);
+
+ float3 f0, f1, f2, f3;
+
+ if (desc.element == ATTR_ELEMENT_CORNER) {
+ f0 = float4_to_float3(kernel_tex_fetch(__attributes_float3, corners[0] + desc.offset));
+ f1 = float4_to_float3(kernel_tex_fetch(__attributes_float3, corners[1] + desc.offset));
+ f2 = float4_to_float3(kernel_tex_fetch(__attributes_float3, corners[2] + desc.offset));
+ f3 = float4_to_float3(kernel_tex_fetch(__attributes_float3, corners[3] + desc.offset));
+ }
+ else {
+ f0 = color_byte_to_float(kernel_tex_fetch(__attributes_uchar4, corners[0] + desc.offset));
+ f1 = color_byte_to_float(kernel_tex_fetch(__attributes_uchar4, corners[1] + desc.offset));
+ f2 = color_byte_to_float(kernel_tex_fetch(__attributes_uchar4, corners[2] + desc.offset));
+ f3 = color_byte_to_float(kernel_tex_fetch(__attributes_uchar4, corners[3] + desc.offset));
+ }
+
+ if (subd_triangle_patch_num_corners(kg, patch) != 4) {
+ f1 = (f1 + f0) * 0.5f;
+ f3 = (f3 + f0) * 0.5f;
+ }
+
+ float3 a = mix(mix(f0, f1, uv[0].x), mix(f3, f2, uv[0].x), uv[0].y);
+ float3 b = mix(mix(f0, f1, uv[1].x), mix(f3, f2, uv[1].x), uv[1].y);
+ float3 c = mix(mix(f0, f1, uv[2].x), mix(f3, f2, uv[2].x), uv[2].y);
#ifdef __RAY_DIFFERENTIALS__
- if(dx) *dx = sd->du.dx*a + sd->dv.dx*b - (sd->du.dx + sd->dv.dx)*c;
- if(dy) *dy = sd->du.dy*a + sd->dv.dy*b - (sd->du.dy + sd->dv.dy)*c;
+ if (dx)
+ *dx = sd->du.dx * a + sd->dv.dx * b - (sd->du.dx + sd->dv.dx) * c;
+ if (dy)
+ *dy = sd->du.dy * a + sd->dv.dy * b - (sd->du.dy + sd->dv.dy) * c;
#endif
- return sd->u*a + sd->v*b + (1.0f - sd->u - sd->v)*c;
- }
- else {
- if(dx) *dx = make_float3(0.0f, 0.0f, 0.0f);
- if(dy) *dy = make_float3(0.0f, 0.0f, 0.0f);
+ return sd->u * a + sd->v * b + (1.0f - sd->u - sd->v) * c;
+ }
+ else {
+ if (dx)
+ *dx = make_float3(0.0f, 0.0f, 0.0f);
+ if (dy)
+ *dy = make_float3(0.0f, 0.0f, 0.0f);
- return make_float3(0.0f, 0.0f, 0.0f);
- }
+ return make_float3(0.0f, 0.0f, 0.0f);
+ }
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/geom/geom_triangle.h b/intern/cycles/kernel/geom/geom_triangle.h
index 300227c38e6..9938c0ba2c3 100644
--- a/intern/cycles/kernel/geom/geom_triangle.h
+++ b/intern/cycles/kernel/geom/geom_triangle.h
@@ -25,227 +25,268 @@ CCL_NAMESPACE_BEGIN
/* normal on triangle */
ccl_device_inline float3 triangle_normal(KernelGlobals *kg, ShaderData *sd)
{
- /* load triangle vertices */
- const uint4 tri_vindex = kernel_tex_fetch(__tri_vindex, sd->prim);
- const float3 v0 = float4_to_float3(kernel_tex_fetch(__prim_tri_verts, tri_vindex.w+0));
- const float3 v1 = float4_to_float3(kernel_tex_fetch(__prim_tri_verts, tri_vindex.w+1));
- const float3 v2 = float4_to_float3(kernel_tex_fetch(__prim_tri_verts, tri_vindex.w+2));
-
- /* return normal */
- if(sd->object_flag & SD_OBJECT_NEGATIVE_SCALE_APPLIED) {
- return normalize(cross(v2 - v0, v1 - v0));
- }
- else {
- return normalize(cross(v1 - v0, v2 - v0));
- }
+ /* load triangle vertices */
+ const uint4 tri_vindex = kernel_tex_fetch(__tri_vindex, sd->prim);
+ const float3 v0 = float4_to_float3(kernel_tex_fetch(__prim_tri_verts, tri_vindex.w + 0));
+ const float3 v1 = float4_to_float3(kernel_tex_fetch(__prim_tri_verts, tri_vindex.w + 1));
+ const float3 v2 = float4_to_float3(kernel_tex_fetch(__prim_tri_verts, tri_vindex.w + 2));
+
+ /* return normal */
+ if (sd->object_flag & SD_OBJECT_NEGATIVE_SCALE_APPLIED) {
+ return normalize(cross(v2 - v0, v1 - v0));
+ }
+ else {
+ return normalize(cross(v1 - v0, v2 - v0));
+ }
}
/* point and normal on triangle */
-ccl_device_inline void triangle_point_normal(KernelGlobals *kg, int object, int prim, float u, float v, float3 *P, float3 *Ng, int *shader)
+ccl_device_inline void triangle_point_normal(
+ KernelGlobals *kg, int object, int prim, float u, float v, float3 *P, float3 *Ng, int *shader)
{
- /* load triangle vertices */
- const uint4 tri_vindex = kernel_tex_fetch(__tri_vindex, prim);
- float3 v0 = float4_to_float3(kernel_tex_fetch(__prim_tri_verts, tri_vindex.w+0));
- float3 v1 = float4_to_float3(kernel_tex_fetch(__prim_tri_verts, tri_vindex.w+1));
- float3 v2 = float4_to_float3(kernel_tex_fetch(__prim_tri_verts, tri_vindex.w+2));
- /* compute point */
- float t = 1.0f - u - v;
- *P = (u*v0 + v*v1 + t*v2);
- /* get object flags */
- int object_flag = kernel_tex_fetch(__object_flag, object);
- /* compute normal */
- if(object_flag & SD_OBJECT_NEGATIVE_SCALE_APPLIED) {
- *Ng = normalize(cross(v2 - v0, v1 - v0));
- }
- else {
- *Ng = normalize(cross(v1 - v0, v2 - v0));
- }
- /* shader`*/
- *shader = kernel_tex_fetch(__tri_shader, prim);
+ /* load triangle vertices */
+ const uint4 tri_vindex = kernel_tex_fetch(__tri_vindex, prim);
+ float3 v0 = float4_to_float3(kernel_tex_fetch(__prim_tri_verts, tri_vindex.w + 0));
+ float3 v1 = float4_to_float3(kernel_tex_fetch(__prim_tri_verts, tri_vindex.w + 1));
+ float3 v2 = float4_to_float3(kernel_tex_fetch(__prim_tri_verts, tri_vindex.w + 2));
+ /* compute point */
+ float t = 1.0f - u - v;
+ *P = (u * v0 + v * v1 + t * v2);
+ /* get object flags */
+ int object_flag = kernel_tex_fetch(__object_flag, object);
+ /* compute normal */
+ if (object_flag & SD_OBJECT_NEGATIVE_SCALE_APPLIED) {
+ *Ng = normalize(cross(v2 - v0, v1 - v0));
+ }
+ else {
+ *Ng = normalize(cross(v1 - v0, v2 - v0));
+ }
+ /* shader`*/
+ *shader = kernel_tex_fetch(__tri_shader, prim);
}
/* Triangle vertex locations */
ccl_device_inline void triangle_vertices(KernelGlobals *kg, int prim, float3 P[3])
{
- const uint4 tri_vindex = kernel_tex_fetch(__tri_vindex, prim);
- P[0] = float4_to_float3(kernel_tex_fetch(__prim_tri_verts, tri_vindex.w+0));
- P[1] = float4_to_float3(kernel_tex_fetch(__prim_tri_verts, tri_vindex.w+1));
- P[2] = float4_to_float3(kernel_tex_fetch(__prim_tri_verts, tri_vindex.w+2));
+ const uint4 tri_vindex = kernel_tex_fetch(__tri_vindex, prim);
+ P[0] = float4_to_float3(kernel_tex_fetch(__prim_tri_verts, tri_vindex.w + 0));
+ P[1] = float4_to_float3(kernel_tex_fetch(__prim_tri_verts, tri_vindex.w + 1));
+ P[2] = float4_to_float3(kernel_tex_fetch(__prim_tri_verts, tri_vindex.w + 2));
}
/* Interpolate smooth vertex normal from vertices */
-ccl_device_inline float3 triangle_smooth_normal(KernelGlobals *kg, float3 Ng, int prim, float u, float v)
+ccl_device_inline float3
+triangle_smooth_normal(KernelGlobals *kg, float3 Ng, int prim, float u, float v)
{
- /* load triangle vertices */
- const uint4 tri_vindex = kernel_tex_fetch(__tri_vindex, prim);
- float3 n0 = float4_to_float3(kernel_tex_fetch(__tri_vnormal, tri_vindex.x));
- float3 n1 = float4_to_float3(kernel_tex_fetch(__tri_vnormal, tri_vindex.y));
- float3 n2 = float4_to_float3(kernel_tex_fetch(__tri_vnormal, tri_vindex.z));
+ /* load triangle vertices */
+ const uint4 tri_vindex = kernel_tex_fetch(__tri_vindex, prim);
+ float3 n0 = float4_to_float3(kernel_tex_fetch(__tri_vnormal, tri_vindex.x));
+ float3 n1 = float4_to_float3(kernel_tex_fetch(__tri_vnormal, tri_vindex.y));
+ float3 n2 = float4_to_float3(kernel_tex_fetch(__tri_vnormal, tri_vindex.z));
- float3 N = safe_normalize((1.0f - u - v)*n2 + u*n0 + v*n1);
+ float3 N = safe_normalize((1.0f - u - v) * n2 + u * n0 + v * n1);
- return is_zero(N)? Ng: N;
+ return is_zero(N) ? Ng : N;
}
/* Ray differentials on triangle */
-ccl_device_inline void triangle_dPdudv(KernelGlobals *kg, int prim, ccl_addr_space float3 *dPdu, ccl_addr_space float3 *dPdv)
+ccl_device_inline void triangle_dPdudv(KernelGlobals *kg,
+ int prim,
+ ccl_addr_space float3 *dPdu,
+ ccl_addr_space float3 *dPdv)
{
- /* fetch triangle vertex coordinates */
- const uint4 tri_vindex = kernel_tex_fetch(__tri_vindex, prim);
- const float3 p0 = float4_to_float3(kernel_tex_fetch(__prim_tri_verts, tri_vindex.w+0));
- const float3 p1 = float4_to_float3(kernel_tex_fetch(__prim_tri_verts, tri_vindex.w+1));
- const float3 p2 = float4_to_float3(kernel_tex_fetch(__prim_tri_verts, tri_vindex.w+2));
-
- /* compute derivatives of P w.r.t. uv */
- *dPdu = (p0 - p2);
- *dPdv = (p1 - p2);
+ /* fetch triangle vertex coordinates */
+ const uint4 tri_vindex = kernel_tex_fetch(__tri_vindex, prim);
+ const float3 p0 = float4_to_float3(kernel_tex_fetch(__prim_tri_verts, tri_vindex.w + 0));
+ const float3 p1 = float4_to_float3(kernel_tex_fetch(__prim_tri_verts, tri_vindex.w + 1));
+ const float3 p2 = float4_to_float3(kernel_tex_fetch(__prim_tri_verts, tri_vindex.w + 2));
+
+ /* compute derivatives of P w.r.t. uv */
+ *dPdu = (p0 - p2);
+ *dPdv = (p1 - p2);
}
/* Reading attributes on various triangle elements */
-ccl_device float triangle_attribute_float(KernelGlobals *kg, const ShaderData *sd, const AttributeDescriptor desc, float *dx, float *dy)
+ccl_device float triangle_attribute_float(
+ KernelGlobals *kg, const ShaderData *sd, const AttributeDescriptor desc, float *dx, float *dy)
{
- if(desc.element == ATTR_ELEMENT_FACE) {
- if(dx) *dx = 0.0f;
- if(dy) *dy = 0.0f;
+ if (desc.element == ATTR_ELEMENT_FACE) {
+ if (dx)
+ *dx = 0.0f;
+ if (dy)
+ *dy = 0.0f;
- return kernel_tex_fetch(__attributes_float, desc.offset + sd->prim);
- }
- else if(desc.element == ATTR_ELEMENT_VERTEX || desc.element == ATTR_ELEMENT_VERTEX_MOTION) {
- uint4 tri_vindex = kernel_tex_fetch(__tri_vindex, sd->prim);
+ return kernel_tex_fetch(__attributes_float, desc.offset + sd->prim);
+ }
+ else if (desc.element == ATTR_ELEMENT_VERTEX || desc.element == ATTR_ELEMENT_VERTEX_MOTION) {
+ uint4 tri_vindex = kernel_tex_fetch(__tri_vindex, sd->prim);
- float f0 = kernel_tex_fetch(__attributes_float, desc.offset + tri_vindex.x);
- float f1 = kernel_tex_fetch(__attributes_float, desc.offset + tri_vindex.y);
- float f2 = kernel_tex_fetch(__attributes_float, desc.offset + tri_vindex.z);
+ float f0 = kernel_tex_fetch(__attributes_float, desc.offset + tri_vindex.x);
+ float f1 = kernel_tex_fetch(__attributes_float, desc.offset + tri_vindex.y);
+ float f2 = kernel_tex_fetch(__attributes_float, desc.offset + tri_vindex.z);
#ifdef __RAY_DIFFERENTIALS__
- if(dx) *dx = sd->du.dx*f0 + sd->dv.dx*f1 - (sd->du.dx + sd->dv.dx)*f2;
- if(dy) *dy = sd->du.dy*f0 + sd->dv.dy*f1 - (sd->du.dy + sd->dv.dy)*f2;
+ if (dx)
+ *dx = sd->du.dx * f0 + sd->dv.dx * f1 - (sd->du.dx + sd->dv.dx) * f2;
+ if (dy)
+ *dy = sd->du.dy * f0 + sd->dv.dy * f1 - (sd->du.dy + sd->dv.dy) * f2;
#endif
- return sd->u*f0 + sd->v*f1 + (1.0f - sd->u - sd->v)*f2;
- }
- else if(desc.element == ATTR_ELEMENT_CORNER) {
- int tri = desc.offset + sd->prim*3;
- float f0 = kernel_tex_fetch(__attributes_float, tri + 0);
- float f1 = kernel_tex_fetch(__attributes_float, tri + 1);
- float f2 = kernel_tex_fetch(__attributes_float, tri + 2);
+ return sd->u * f0 + sd->v * f1 + (1.0f - sd->u - sd->v) * f2;
+ }
+ else if (desc.element == ATTR_ELEMENT_CORNER) {
+ int tri = desc.offset + sd->prim * 3;
+ float f0 = kernel_tex_fetch(__attributes_float, tri + 0);
+ float f1 = kernel_tex_fetch(__attributes_float, tri + 1);
+ float f2 = kernel_tex_fetch(__attributes_float, tri + 2);
#ifdef __RAY_DIFFERENTIALS__
- if(dx) *dx = sd->du.dx*f0 + sd->dv.dx*f1 - (sd->du.dx + sd->dv.dx)*f2;
- if(dy) *dy = sd->du.dy*f0 + sd->dv.dy*f1 - (sd->du.dy + sd->dv.dy)*f2;
+ if (dx)
+ *dx = sd->du.dx * f0 + sd->dv.dx * f1 - (sd->du.dx + sd->dv.dx) * f2;
+ if (dy)
+ *dy = sd->du.dy * f0 + sd->dv.dy * f1 - (sd->du.dy + sd->dv.dy) * f2;
#endif
- return sd->u*f0 + sd->v*f1 + (1.0f - sd->u - sd->v)*f2;
- }
- else {
- if(dx) *dx = 0.0f;
- if(dy) *dy = 0.0f;
+ return sd->u * f0 + sd->v * f1 + (1.0f - sd->u - sd->v) * f2;
+ }
+ else {
+ if (dx)
+ *dx = 0.0f;
+ if (dy)
+ *dy = 0.0f;
- return 0.0f;
- }
+ return 0.0f;
+ }
}
-ccl_device float2 triangle_attribute_float2(KernelGlobals *kg, const ShaderData *sd, const AttributeDescriptor desc, float2 *dx, float2 *dy)
+ccl_device float2 triangle_attribute_float2(KernelGlobals *kg,
+ const ShaderData *sd,
+ const AttributeDescriptor desc,
+ float2 *dx,
+ float2 *dy)
{
- if(desc.element == ATTR_ELEMENT_FACE) {
- if(dx) *dx = make_float2(0.0f, 0.0f);
- if(dy) *dy = make_float2(0.0f, 0.0f);
+ if (desc.element == ATTR_ELEMENT_FACE) {
+ if (dx)
+ *dx = make_float2(0.0f, 0.0f);
+ if (dy)
+ *dy = make_float2(0.0f, 0.0f);
- return kernel_tex_fetch(__attributes_float2, desc.offset + sd->prim);
- }
- else if(desc.element == ATTR_ELEMENT_VERTEX || desc.element == ATTR_ELEMENT_VERTEX_MOTION) {
- uint4 tri_vindex = kernel_tex_fetch(__tri_vindex, sd->prim);
+ return kernel_tex_fetch(__attributes_float2, desc.offset + sd->prim);
+ }
+ else if (desc.element == ATTR_ELEMENT_VERTEX || desc.element == ATTR_ELEMENT_VERTEX_MOTION) {
+ uint4 tri_vindex = kernel_tex_fetch(__tri_vindex, sd->prim);
- float2 f0 = kernel_tex_fetch(__attributes_float2, desc.offset + tri_vindex.x);
- float2 f1 = kernel_tex_fetch(__attributes_float2, desc.offset + tri_vindex.y);
- float2 f2 = kernel_tex_fetch(__attributes_float2, desc.offset + tri_vindex.z);
+ float2 f0 = kernel_tex_fetch(__attributes_float2, desc.offset + tri_vindex.x);
+ float2 f1 = kernel_tex_fetch(__attributes_float2, desc.offset + tri_vindex.y);
+ float2 f2 = kernel_tex_fetch(__attributes_float2, desc.offset + tri_vindex.z);
#ifdef __RAY_DIFFERENTIALS__
- if(dx) *dx = sd->du.dx*f0 + sd->dv.dx*f1 - (sd->du.dx + sd->dv.dx)*f2;
- if(dy) *dy = sd->du.dy*f0 + sd->dv.dy*f1 - (sd->du.dy + sd->dv.dy)*f2;
+ if (dx)
+ *dx = sd->du.dx * f0 + sd->dv.dx * f1 - (sd->du.dx + sd->dv.dx) * f2;
+ if (dy)
+ *dy = sd->du.dy * f0 + sd->dv.dy * f1 - (sd->du.dy + sd->dv.dy) * f2;
#endif
- return sd->u*f0 + sd->v*f1 + (1.0f - sd->u - sd->v)*f2;
- }
- else if(desc.element == ATTR_ELEMENT_CORNER) {
- int tri = desc.offset + sd->prim*3;
- float2 f0, f1, f2;
+ return sd->u * f0 + sd->v * f1 + (1.0f - sd->u - sd->v) * f2;
+ }
+ else if (desc.element == ATTR_ELEMENT_CORNER) {
+ int tri = desc.offset + sd->prim * 3;
+ float2 f0, f1, f2;
- if(desc.element == ATTR_ELEMENT_CORNER) {
- f0 = kernel_tex_fetch(__attributes_float2, tri + 0);
- f1 = kernel_tex_fetch(__attributes_float2, tri + 1);
- f2 = kernel_tex_fetch(__attributes_float2, tri + 2);
- }
+ if (desc.element == ATTR_ELEMENT_CORNER) {
+ f0 = kernel_tex_fetch(__attributes_float2, tri + 0);
+ f1 = kernel_tex_fetch(__attributes_float2, tri + 1);
+ f2 = kernel_tex_fetch(__attributes_float2, tri + 2);
+ }
#ifdef __RAY_DIFFERENTIALS__
- if(dx) *dx = sd->du.dx*f0 + sd->dv.dx*f1 - (sd->du.dx + sd->dv.dx)*f2;
- if(dy) *dy = sd->du.dy*f0 + sd->dv.dy*f1 - (sd->du.dy + sd->dv.dy)*f2;
+ if (dx)
+ *dx = sd->du.dx * f0 + sd->dv.dx * f1 - (sd->du.dx + sd->dv.dx) * f2;
+ if (dy)
+ *dy = sd->du.dy * f0 + sd->dv.dy * f1 - (sd->du.dy + sd->dv.dy) * f2;
#endif
- return sd->u*f0 + sd->v*f1 + (1.0f - sd->u - sd->v)*f2;
- }
- else {
- if(dx) *dx = make_float2(0.0f, 0.0f);
- if(dy) *dy = make_float2(0.0f, 0.0f);
+ return sd->u * f0 + sd->v * f1 + (1.0f - sd->u - sd->v) * f2;
+ }
+ else {
+ if (dx)
+ *dx = make_float2(0.0f, 0.0f);
+ if (dy)
+ *dy = make_float2(0.0f, 0.0f);
- return make_float2(0.0f, 0.0f);
- }
+ return make_float2(0.0f, 0.0f);
+ }
}
-ccl_device float3 triangle_attribute_float3(KernelGlobals *kg, const ShaderData *sd, const AttributeDescriptor desc, float3 *dx, float3 *dy)
+ccl_device float3 triangle_attribute_float3(KernelGlobals *kg,
+ const ShaderData *sd,
+ const AttributeDescriptor desc,
+ float3 *dx,
+ float3 *dy)
{
- if(desc.element == ATTR_ELEMENT_FACE) {
- if(dx) *dx = make_float3(0.0f, 0.0f, 0.0f);
- if(dy) *dy = make_float3(0.0f, 0.0f, 0.0f);
-
- return float4_to_float3(kernel_tex_fetch(__attributes_float3, desc.offset + sd->prim));
- }
- else if(desc.element == ATTR_ELEMENT_VERTEX || desc.element == ATTR_ELEMENT_VERTEX_MOTION) {
- uint4 tri_vindex = kernel_tex_fetch(__tri_vindex, sd->prim);
-
- float3 f0 = float4_to_float3(kernel_tex_fetch(__attributes_float3, desc.offset + tri_vindex.x));
- float3 f1 = float4_to_float3(kernel_tex_fetch(__attributes_float3, desc.offset + tri_vindex.y));
- float3 f2 = float4_to_float3(kernel_tex_fetch(__attributes_float3, desc.offset + tri_vindex.z));
+ if (desc.element == ATTR_ELEMENT_FACE) {
+ if (dx)
+ *dx = make_float3(0.0f, 0.0f, 0.0f);
+ if (dy)
+ *dy = make_float3(0.0f, 0.0f, 0.0f);
+
+ return float4_to_float3(kernel_tex_fetch(__attributes_float3, desc.offset + sd->prim));
+ }
+ else if (desc.element == ATTR_ELEMENT_VERTEX || desc.element == ATTR_ELEMENT_VERTEX_MOTION) {
+ uint4 tri_vindex = kernel_tex_fetch(__tri_vindex, sd->prim);
+
+ float3 f0 = float4_to_float3(
+ kernel_tex_fetch(__attributes_float3, desc.offset + tri_vindex.x));
+ float3 f1 = float4_to_float3(
+ kernel_tex_fetch(__attributes_float3, desc.offset + tri_vindex.y));
+ float3 f2 = float4_to_float3(
+ kernel_tex_fetch(__attributes_float3, desc.offset + tri_vindex.z));
#ifdef __RAY_DIFFERENTIALS__
- if(dx) *dx = sd->du.dx*f0 + sd->dv.dx*f1 - (sd->du.dx + sd->dv.dx)*f2;
- if(dy) *dy = sd->du.dy*f0 + sd->dv.dy*f1 - (sd->du.dy + sd->dv.dy)*f2;
+ if (dx)
+ *dx = sd->du.dx * f0 + sd->dv.dx * f1 - (sd->du.dx + sd->dv.dx) * f2;
+ if (dy)
+ *dy = sd->du.dy * f0 + sd->dv.dy * f1 - (sd->du.dy + sd->dv.dy) * f2;
#endif
- return sd->u*f0 + sd->v*f1 + (1.0f - sd->u - sd->v)*f2;
- }
- else if(desc.element == ATTR_ELEMENT_CORNER || desc.element == ATTR_ELEMENT_CORNER_BYTE) {
- int tri = desc.offset + sd->prim*3;
- float3 f0, f1, f2;
-
- if(desc.element == ATTR_ELEMENT_CORNER) {
- f0 = float4_to_float3(kernel_tex_fetch(__attributes_float3, tri + 0));
- f1 = float4_to_float3(kernel_tex_fetch(__attributes_float3, tri + 1));
- f2 = float4_to_float3(kernel_tex_fetch(__attributes_float3, tri + 2));
- }
- else {
- f0 = color_byte_to_float(kernel_tex_fetch(__attributes_uchar4, tri + 0));
- f1 = color_byte_to_float(kernel_tex_fetch(__attributes_uchar4, tri + 1));
- f2 = color_byte_to_float(kernel_tex_fetch(__attributes_uchar4, tri + 2));
- }
+ return sd->u * f0 + sd->v * f1 + (1.0f - sd->u - sd->v) * f2;
+ }
+ else if (desc.element == ATTR_ELEMENT_CORNER || desc.element == ATTR_ELEMENT_CORNER_BYTE) {
+ int tri = desc.offset + sd->prim * 3;
+ float3 f0, f1, f2;
+
+ if (desc.element == ATTR_ELEMENT_CORNER) {
+ f0 = float4_to_float3(kernel_tex_fetch(__attributes_float3, tri + 0));
+ f1 = float4_to_float3(kernel_tex_fetch(__attributes_float3, tri + 1));
+ f2 = float4_to_float3(kernel_tex_fetch(__attributes_float3, tri + 2));
+ }
+ else {
+ f0 = color_byte_to_float(kernel_tex_fetch(__attributes_uchar4, tri + 0));
+ f1 = color_byte_to_float(kernel_tex_fetch(__attributes_uchar4, tri + 1));
+ f2 = color_byte_to_float(kernel_tex_fetch(__attributes_uchar4, tri + 2));
+ }
#ifdef __RAY_DIFFERENTIALS__
- if(dx) *dx = sd->du.dx*f0 + sd->dv.dx*f1 - (sd->du.dx + sd->dv.dx)*f2;
- if(dy) *dy = sd->du.dy*f0 + sd->dv.dy*f1 - (sd->du.dy + sd->dv.dy)*f2;
+ if (dx)
+ *dx = sd->du.dx * f0 + sd->dv.dx * f1 - (sd->du.dx + sd->dv.dx) * f2;
+ if (dy)
+ *dy = sd->du.dy * f0 + sd->dv.dy * f1 - (sd->du.dy + sd->dv.dy) * f2;
#endif
- return sd->u*f0 + sd->v*f1 + (1.0f - sd->u - sd->v)*f2;
- }
- else {
- if(dx) *dx = make_float3(0.0f, 0.0f, 0.0f);
- if(dy) *dy = make_float3(0.0f, 0.0f, 0.0f);
+ return sd->u * f0 + sd->v * f1 + (1.0f - sd->u - sd->v) * f2;
+ }
+ else {
+ if (dx)
+ *dx = make_float3(0.0f, 0.0f, 0.0f);
+ if (dy)
+ *dy = make_float3(0.0f, 0.0f, 0.0f);
- return make_float3(0.0f, 0.0f, 0.0f);
- }
+ return make_float3(0.0f, 0.0f, 0.0f);
+ }
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/geom/geom_triangle_intersect.h b/intern/cycles/kernel/geom/geom_triangle_intersect.h
index 56dbc4473fa..bcad03102d2 100644
--- a/intern/cycles/kernel/geom/geom_triangle_intersect.h
+++ b/intern/cycles/kernel/geom/geom_triangle_intersect.h
@@ -1,4 +1,4 @@
- /*
+/*
* Copyright 2014, Blender Foundation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -30,447 +30,464 @@ ccl_device_inline bool triangle_intersect(KernelGlobals *kg,
int object,
int prim_addr)
{
- const uint tri_vindex = kernel_tex_fetch(__prim_tri_index, prim_addr);
+ const uint tri_vindex = kernel_tex_fetch(__prim_tri_index, prim_addr);
#if defined(__KERNEL_SSE2__) && defined(__KERNEL_SSE__)
- const ssef *ssef_verts = (ssef*)&kg->__prim_tri_verts.data[tri_vindex];
+ const ssef *ssef_verts = (ssef *)&kg->__prim_tri_verts.data[tri_vindex];
#else
- const float4 tri_a = kernel_tex_fetch(__prim_tri_verts, tri_vindex+0),
- tri_b = kernel_tex_fetch(__prim_tri_verts, tri_vindex+1),
- tri_c = kernel_tex_fetch(__prim_tri_verts, tri_vindex+2);
+ const float4 tri_a = kernel_tex_fetch(__prim_tri_verts, tri_vindex + 0),
+ tri_b = kernel_tex_fetch(__prim_tri_verts, tri_vindex + 1),
+ tri_c = kernel_tex_fetch(__prim_tri_verts, tri_vindex + 2);
#endif
- float t, u, v;
- if(ray_triangle_intersect(P,
- dir,
- isect->t,
+ float t, u, v;
+ if (ray_triangle_intersect(P,
+ dir,
+ isect->t,
#if defined(__KERNEL_SSE2__) && defined(__KERNEL_SSE__)
- ssef_verts,
+ ssef_verts,
#else
- float4_to_float3(tri_a),
- float4_to_float3(tri_b),
- float4_to_float3(tri_c),
+ float4_to_float3(tri_a),
+ float4_to_float3(tri_b),
+ float4_to_float3(tri_c),
#endif
- &u, &v, &t))
- {
+ &u,
+ &v,
+ &t)) {
#ifdef __VISIBILITY_FLAG__
- /* Visibility flag test. we do it here under the assumption
- * that most triangles are culled by node flags.
- */
- if(kernel_tex_fetch(__prim_visibility, prim_addr) & visibility)
+ /* Visibility flag test. we do it here under the assumption
+ * that most triangles are culled by node flags.
+ */
+ if (kernel_tex_fetch(__prim_visibility, prim_addr) & visibility)
#endif
- {
- isect->prim = prim_addr;
- isect->object = object;
- isect->type = PRIMITIVE_TRIANGLE;
- isect->u = u;
- isect->v = v;
- isect->t = t;
- return true;
- }
- }
- return false;
+ {
+ isect->prim = prim_addr;
+ isect->object = object;
+ isect->type = PRIMITIVE_TRIANGLE;
+ isect->u = u;
+ isect->v = v;
+ isect->t = t;
+ return true;
+ }
+ }
+ return false;
}
#ifdef __KERNEL_AVX2__
-#define cross256(A,B, C,D) _mm256_fmsub_ps(A,B, _mm256_mul_ps(C,D))
-ccl_device_inline int ray_triangle_intersect8(
- KernelGlobals *kg,
- float3 ray_P,
- float3 ray_dir,
- Intersection **isect,
- uint visibility,
- int object,
- __m256 *triA,
- __m256 *triB,
- __m256 *triC,
- int prim_addr,
- int prim_num,
- uint *num_hits,
- uint max_hits,
- int *num_hits_in_instance,
- float isect_t)
+# define cross256(A, B, C, D) _mm256_fmsub_ps(A, B, _mm256_mul_ps(C, D))
+ccl_device_inline int ray_triangle_intersect8(KernelGlobals *kg,
+ float3 ray_P,
+ float3 ray_dir,
+ Intersection **isect,
+ uint visibility,
+ int object,
+ __m256 *triA,
+ __m256 *triB,
+ __m256 *triC,
+ int prim_addr,
+ int prim_num,
+ uint *num_hits,
+ uint max_hits,
+ int *num_hits_in_instance,
+ float isect_t)
{
- const unsigned char prim_num_mask = (1 << prim_num) - 1;
-
- const __m256i zero256 = _mm256_setzero_si256();
-
- const __m256 Px256 = _mm256_set1_ps(ray_P.x);
- const __m256 Py256 = _mm256_set1_ps(ray_P.y);
- const __m256 Pz256 = _mm256_set1_ps(ray_P.z);
-
- const __m256 dirx256 = _mm256_set1_ps(ray_dir.x);
- const __m256 diry256 = _mm256_set1_ps(ray_dir.y);
- const __m256 dirz256 = _mm256_set1_ps(ray_dir.z);
-
- /* Calculate vertices relative to ray origin. */
- __m256 v0_x_256 = _mm256_sub_ps(triC[0], Px256);
- __m256 v0_y_256 = _mm256_sub_ps(triC[1], Py256);
- __m256 v0_z_256 = _mm256_sub_ps(triC[2], Pz256);
-
- __m256 v1_x_256 = _mm256_sub_ps(triA[0], Px256);
- __m256 v1_y_256 = _mm256_sub_ps(triA[1], Py256);
- __m256 v1_z_256 = _mm256_sub_ps(triA[2], Pz256);
-
- __m256 v2_x_256 = _mm256_sub_ps(triB[0], Px256);
- __m256 v2_y_256 = _mm256_sub_ps(triB[1], Py256);
- __m256 v2_z_256 = _mm256_sub_ps(triB[2], Pz256);
-
- __m256 v0_v1_x_256 = _mm256_add_ps(v0_x_256, v1_x_256);
- __m256 v0_v1_y_256 = _mm256_add_ps(v0_y_256, v1_y_256);
- __m256 v0_v1_z_256 = _mm256_add_ps(v0_z_256, v1_z_256);
-
- __m256 v0_v2_x_256 = _mm256_add_ps(v0_x_256, v2_x_256);
- __m256 v0_v2_y_256 = _mm256_add_ps(v0_y_256, v2_y_256);
- __m256 v0_v2_z_256 = _mm256_add_ps(v0_z_256, v2_z_256);
-
- __m256 v1_v2_x_256 = _mm256_add_ps(v1_x_256, v2_x_256);
- __m256 v1_v2_y_256 = _mm256_add_ps(v1_y_256, v2_y_256);
- __m256 v1_v2_z_256 = _mm256_add_ps(v1_z_256, v2_z_256);
-
- /* Calculate triangle edges. */
- __m256 e0_x_256 = _mm256_sub_ps(v2_x_256, v0_x_256);
- __m256 e0_y_256 = _mm256_sub_ps(v2_y_256, v0_y_256);
- __m256 e0_z_256 = _mm256_sub_ps(v2_z_256, v0_z_256);
-
- __m256 e1_x_256 = _mm256_sub_ps(v0_x_256, v1_x_256);
- __m256 e1_y_256 = _mm256_sub_ps(v0_y_256, v1_y_256);
- __m256 e1_z_256 = _mm256_sub_ps(v0_z_256, v1_z_256);
-
- __m256 e2_x_256 = _mm256_sub_ps(v1_x_256, v2_x_256);
- __m256 e2_y_256 = _mm256_sub_ps(v1_y_256, v2_y_256);
- __m256 e2_z_256 = _mm256_sub_ps(v1_z_256, v2_z_256);
-
- /* Perform edge tests. */
- /* cross (AyBz - AzBy, AzBx -AxBz, AxBy - AyBx) */
- __m256 U_x_256 = cross256(v0_v2_y_256, e0_z_256, v0_v2_z_256, e0_y_256);
- __m256 U_y_256 = cross256(v0_v2_z_256, e0_x_256, v0_v2_x_256, e0_z_256);
- __m256 U_z_256 = cross256(v0_v2_x_256, e0_y_256, v0_v2_y_256, e0_x_256);
- /* vertical dot */
- __m256 U_256 = _mm256_mul_ps(U_x_256, dirx256);
- U_256 = _mm256_fmadd_ps(U_y_256, diry256, U_256);
- U_256 = _mm256_fmadd_ps(U_z_256, dirz256, U_256);
-
- __m256 V_x_256 = cross256(v0_v1_y_256, e1_z_256, v0_v1_z_256, e1_y_256);
- __m256 V_y_256 = cross256(v0_v1_z_256, e1_x_256, v0_v1_x_256, e1_z_256);
- __m256 V_z_256 = cross256(v0_v1_x_256, e1_y_256, v0_v1_y_256, e1_x_256);
- /* vertical dot */
- __m256 V_256 = _mm256_mul_ps(V_x_256, dirx256);
- V_256 = _mm256_fmadd_ps(V_y_256, diry256, V_256);
- V_256 = _mm256_fmadd_ps(V_z_256, dirz256, V_256);
-
- __m256 W_x_256 = cross256(v1_v2_y_256, e2_z_256, v1_v2_z_256, e2_y_256);
- __m256 W_y_256 = cross256(v1_v2_z_256, e2_x_256, v1_v2_x_256, e2_z_256);
- __m256 W_z_256 = cross256(v1_v2_x_256, e2_y_256, v1_v2_y_256, e2_x_256);
- /* vertical dot */
- __m256 W_256 = _mm256_mul_ps(W_x_256, dirx256);
- W_256 = _mm256_fmadd_ps(W_y_256, diry256,W_256);
- W_256 = _mm256_fmadd_ps(W_z_256, dirz256,W_256);
-
- __m256i U_256_1 = _mm256_srli_epi32(_mm256_castps_si256(U_256), 31);
- __m256i V_256_1 = _mm256_srli_epi32(_mm256_castps_si256(V_256), 31);
- __m256i W_256_1 = _mm256_srli_epi32(_mm256_castps_si256(W_256), 31);
- __m256i UVW_256_1 = _mm256_add_epi32(_mm256_add_epi32(U_256_1, V_256_1), W_256_1);
-
- const __m256i one256 = _mm256_set1_epi32(1);
- const __m256i two256 = _mm256_set1_epi32(2);
-
- __m256i mask_minmaxUVW_256 = _mm256_or_si256(
- _mm256_cmpeq_epi32(one256, UVW_256_1),
- _mm256_cmpeq_epi32(two256, UVW_256_1));
-
- unsigned char mask_minmaxUVW_pos = _mm256_movemask_ps(_mm256_castsi256_ps(mask_minmaxUVW_256));
- if((mask_minmaxUVW_pos & prim_num_mask) == prim_num_mask) { //all bits set
- return false;
- }
-
- /* Calculate geometry normal and denominator. */
- __m256 Ng1_x_256 = cross256(e1_y_256, e0_z_256, e1_z_256, e0_y_256);
- __m256 Ng1_y_256 = cross256(e1_z_256, e0_x_256, e1_x_256, e0_z_256);
- __m256 Ng1_z_256 = cross256(e1_x_256, e0_y_256, e1_y_256, e0_x_256);
-
- Ng1_x_256 = _mm256_add_ps(Ng1_x_256, Ng1_x_256);
- Ng1_y_256 = _mm256_add_ps(Ng1_y_256, Ng1_y_256);
- Ng1_z_256 = _mm256_add_ps(Ng1_z_256, Ng1_z_256);
-
- /* vertical dot */
- __m256 den_256 = _mm256_mul_ps(Ng1_x_256, dirx256);
- den_256 = _mm256_fmadd_ps(Ng1_y_256, diry256,den_256);
- den_256 = _mm256_fmadd_ps(Ng1_z_256, dirz256,den_256);
-
- /* Perform depth test. */
- __m256 T_256 = _mm256_mul_ps(Ng1_x_256, v0_x_256);
- T_256 = _mm256_fmadd_ps(Ng1_y_256, v0_y_256,T_256);
- T_256 = _mm256_fmadd_ps(Ng1_z_256, v0_z_256,T_256);
-
- const __m256i c0x80000000 = _mm256_set1_epi32(0x80000000);
- __m256i sign_den_256 = _mm256_and_si256(_mm256_castps_si256(den_256), c0x80000000);
-
- __m256 sign_T_256 = _mm256_castsi256_ps(_mm256_xor_si256(_mm256_castps_si256(T_256), sign_den_256));
-
- unsigned char mask_sign_T = _mm256_movemask_ps(sign_T_256);
- if(((mask_minmaxUVW_pos | mask_sign_T) & prim_num_mask) == prim_num_mask) {
- return false;
- }
-
- __m256 xor_signmask_256 = _mm256_castsi256_ps(_mm256_xor_si256(_mm256_castps_si256(den_256), sign_den_256));
-
- ccl_align(32) float den8[8], U8[8], V8[8], T8[8], sign_T8[8], xor_signmask8[8];
- ccl_align(32) unsigned int mask_minmaxUVW8[8];
-
- if(visibility == PATH_RAY_SHADOW_OPAQUE) {
- __m256i mask_final_256 = _mm256_cmpeq_epi32(mask_minmaxUVW_256, zero256);
- __m256i maskden256 = _mm256_cmpeq_epi32(_mm256_castps_si256(den_256), zero256);
- __m256i mask0 = _mm256_cmpgt_epi32(zero256, _mm256_castps_si256(sign_T_256));
- __m256 rayt_256 = _mm256_set1_ps((*isect)->t);
- __m256i mask1 = _mm256_cmpgt_epi32(_mm256_castps_si256(sign_T_256),
- _mm256_castps_si256(
- _mm256_mul_ps(_mm256_castsi256_ps(_mm256_xor_si256(_mm256_castps_si256(den_256), sign_den_256)), rayt_256)
- )
- );
- mask0 = _mm256_or_si256(mask1, mask0);
- mask_final_256 = _mm256_andnot_si256(mask0, mask_final_256); //(~mask_minmaxUVW_pos) &(~mask)
- mask_final_256 = _mm256_andnot_si256(maskden256, mask_final_256); //(~mask_minmaxUVW_pos) &(~mask) & (~maskden)
- unsigned char mask_final = _mm256_movemask_ps(_mm256_castsi256_ps(mask_final_256));
- if((mask_final & prim_num_mask) == 0) {
- return false;
- }
- const int i = __bsf(mask_final);
- __m256 inv_den_256 = _mm256_rcp_ps(den_256);
- U_256 = _mm256_mul_ps(U_256, inv_den_256);
- V_256 = _mm256_mul_ps(V_256, inv_den_256);
- T_256 = _mm256_mul_ps(T_256, inv_den_256);
- _mm256_store_ps(U8, U_256);
- _mm256_store_ps(V8, V_256);
- _mm256_store_ps(T8, T_256);
- /* NOTE: Here we assume visibility for all triangles in the node is
- * the same. */
- (*isect)->u = U8[i];
- (*isect)->v = V8[i];
- (*isect)->t = T8[i];
- (*isect)->prim = (prim_addr + i);
- (*isect)->object = object;
- (*isect)->type = PRIMITIVE_TRIANGLE;
- return true;
- }
- else {
- _mm256_store_ps(den8, den_256);
- _mm256_store_ps(U8, U_256);
- _mm256_store_ps(V8, V_256);
- _mm256_store_ps(T8, T_256);
-
- _mm256_store_ps(sign_T8, sign_T_256);
- _mm256_store_ps(xor_signmask8, xor_signmask_256);
- _mm256_store_si256((__m256i*)mask_minmaxUVW8, mask_minmaxUVW_256);
-
- int ret = false;
-
- if(visibility == PATH_RAY_SHADOW) {
- for(int i = 0; i < prim_num; i++) {
- if(mask_minmaxUVW8[i]) {
- continue;
- }
-#ifdef __VISIBILITY_FLAG__
- if((kernel_tex_fetch(__prim_visibility, (prim_addr + i)) & visibility) == 0) {
- continue;
- }
-#endif
- if((sign_T8[i] < 0.0f) ||
- (sign_T8[i] > (*isect)->t * xor_signmask8[i]))
- {
- continue;
- }
- if(!den8[i]) {
- continue;
- }
- const float inv_den = 1.0f / den8[i];
- (*isect)->u = U8[i] * inv_den;
- (*isect)->v = V8[i] * inv_den;
- (*isect)->t = T8[i] * inv_den;
- (*isect)->prim = (prim_addr + i);
- (*isect)->object = object;
- (*isect)->type = PRIMITIVE_TRIANGLE;
- const int prim = kernel_tex_fetch(__prim_index, (*isect)->prim);
- int shader = 0;
-#ifdef __HAIR__
- if(kernel_tex_fetch(__prim_type, (*isect)->prim) & PRIMITIVE_ALL_TRIANGLE)
-#endif
- {
- shader = kernel_tex_fetch(__tri_shader, prim);
- }
-#ifdef __HAIR__
- else {
- float4 str = kernel_tex_fetch(__curves, prim);
- shader = __float_as_int(str.z);
- }
-#endif
- const int flag = kernel_tex_fetch(__shaders, (shader & SHADER_MASK)).flags;
- /* If no transparent shadows, all light is blocked. */
- if(!(flag & SD_HAS_TRANSPARENT_SHADOW)) {
- return 2;
- }
- /* If maximum number of hits reached, block all light. */
- else if(num_hits == NULL || *num_hits == max_hits) {
- return 2;
- }
- /* Move on to next entry in intersections array. */
- ret = true;
- (*isect)++;
- (*num_hits)++;
- (*num_hits_in_instance)++;
- (*isect)->t = isect_t;
- }
- }
- else {
- for(int i = 0; i < prim_num; i++) {
- if(mask_minmaxUVW8[i]) {
- continue;
- }
-#ifdef __VISIBILITY_FLAG__
- if((kernel_tex_fetch(__prim_visibility, (prim_addr + i)) & visibility) == 0) {
- continue;
- }
-#endif
- if((sign_T8[i] < 0.0f) ||
- (sign_T8[i] > (*isect)->t * xor_signmask8[i]))
- {
- continue;
- }
- if(!den8[i]) {
- continue;
- }
- const float inv_den = 1.0f / den8[i];
- (*isect)->u = U8[i] * inv_den;
- (*isect)->v = V8[i] * inv_den;
- (*isect)->t = T8[i] * inv_den;
- (*isect)->prim = (prim_addr + i);
- (*isect)->object = object;
- (*isect)->type = PRIMITIVE_TRIANGLE;
- ret = true;
- }
- }
- return ret;
- }
+ const unsigned char prim_num_mask = (1 << prim_num) - 1;
+
+ const __m256i zero256 = _mm256_setzero_si256();
+
+ const __m256 Px256 = _mm256_set1_ps(ray_P.x);
+ const __m256 Py256 = _mm256_set1_ps(ray_P.y);
+ const __m256 Pz256 = _mm256_set1_ps(ray_P.z);
+
+ const __m256 dirx256 = _mm256_set1_ps(ray_dir.x);
+ const __m256 diry256 = _mm256_set1_ps(ray_dir.y);
+ const __m256 dirz256 = _mm256_set1_ps(ray_dir.z);
+
+ /* Calculate vertices relative to ray origin. */
+ __m256 v0_x_256 = _mm256_sub_ps(triC[0], Px256);
+ __m256 v0_y_256 = _mm256_sub_ps(triC[1], Py256);
+ __m256 v0_z_256 = _mm256_sub_ps(triC[2], Pz256);
+
+ __m256 v1_x_256 = _mm256_sub_ps(triA[0], Px256);
+ __m256 v1_y_256 = _mm256_sub_ps(triA[1], Py256);
+ __m256 v1_z_256 = _mm256_sub_ps(triA[2], Pz256);
+
+ __m256 v2_x_256 = _mm256_sub_ps(triB[0], Px256);
+ __m256 v2_y_256 = _mm256_sub_ps(triB[1], Py256);
+ __m256 v2_z_256 = _mm256_sub_ps(triB[2], Pz256);
+
+ __m256 v0_v1_x_256 = _mm256_add_ps(v0_x_256, v1_x_256);
+ __m256 v0_v1_y_256 = _mm256_add_ps(v0_y_256, v1_y_256);
+ __m256 v0_v1_z_256 = _mm256_add_ps(v0_z_256, v1_z_256);
+
+ __m256 v0_v2_x_256 = _mm256_add_ps(v0_x_256, v2_x_256);
+ __m256 v0_v2_y_256 = _mm256_add_ps(v0_y_256, v2_y_256);
+ __m256 v0_v2_z_256 = _mm256_add_ps(v0_z_256, v2_z_256);
+
+ __m256 v1_v2_x_256 = _mm256_add_ps(v1_x_256, v2_x_256);
+ __m256 v1_v2_y_256 = _mm256_add_ps(v1_y_256, v2_y_256);
+ __m256 v1_v2_z_256 = _mm256_add_ps(v1_z_256, v2_z_256);
+
+ /* Calculate triangle edges. */
+ __m256 e0_x_256 = _mm256_sub_ps(v2_x_256, v0_x_256);
+ __m256 e0_y_256 = _mm256_sub_ps(v2_y_256, v0_y_256);
+ __m256 e0_z_256 = _mm256_sub_ps(v2_z_256, v0_z_256);
+
+ __m256 e1_x_256 = _mm256_sub_ps(v0_x_256, v1_x_256);
+ __m256 e1_y_256 = _mm256_sub_ps(v0_y_256, v1_y_256);
+ __m256 e1_z_256 = _mm256_sub_ps(v0_z_256, v1_z_256);
+
+ __m256 e2_x_256 = _mm256_sub_ps(v1_x_256, v2_x_256);
+ __m256 e2_y_256 = _mm256_sub_ps(v1_y_256, v2_y_256);
+ __m256 e2_z_256 = _mm256_sub_ps(v1_z_256, v2_z_256);
+
+ /* Perform edge tests. */
+ /* cross (AyBz - AzBy, AzBx -AxBz, AxBy - AyBx) */
+ __m256 U_x_256 = cross256(v0_v2_y_256, e0_z_256, v0_v2_z_256, e0_y_256);
+ __m256 U_y_256 = cross256(v0_v2_z_256, e0_x_256, v0_v2_x_256, e0_z_256);
+ __m256 U_z_256 = cross256(v0_v2_x_256, e0_y_256, v0_v2_y_256, e0_x_256);
+ /* vertical dot */
+ __m256 U_256 = _mm256_mul_ps(U_x_256, dirx256);
+ U_256 = _mm256_fmadd_ps(U_y_256, diry256, U_256);
+ U_256 = _mm256_fmadd_ps(U_z_256, dirz256, U_256);
+
+ __m256 V_x_256 = cross256(v0_v1_y_256, e1_z_256, v0_v1_z_256, e1_y_256);
+ __m256 V_y_256 = cross256(v0_v1_z_256, e1_x_256, v0_v1_x_256, e1_z_256);
+ __m256 V_z_256 = cross256(v0_v1_x_256, e1_y_256, v0_v1_y_256, e1_x_256);
+ /* vertical dot */
+ __m256 V_256 = _mm256_mul_ps(V_x_256, dirx256);
+ V_256 = _mm256_fmadd_ps(V_y_256, diry256, V_256);
+ V_256 = _mm256_fmadd_ps(V_z_256, dirz256, V_256);
+
+ __m256 W_x_256 = cross256(v1_v2_y_256, e2_z_256, v1_v2_z_256, e2_y_256);
+ __m256 W_y_256 = cross256(v1_v2_z_256, e2_x_256, v1_v2_x_256, e2_z_256);
+ __m256 W_z_256 = cross256(v1_v2_x_256, e2_y_256, v1_v2_y_256, e2_x_256);
+ /* vertical dot */
+ __m256 W_256 = _mm256_mul_ps(W_x_256, dirx256);
+ W_256 = _mm256_fmadd_ps(W_y_256, diry256, W_256);
+ W_256 = _mm256_fmadd_ps(W_z_256, dirz256, W_256);
+
+ __m256i U_256_1 = _mm256_srli_epi32(_mm256_castps_si256(U_256), 31);
+ __m256i V_256_1 = _mm256_srli_epi32(_mm256_castps_si256(V_256), 31);
+ __m256i W_256_1 = _mm256_srli_epi32(_mm256_castps_si256(W_256), 31);
+ __m256i UVW_256_1 = _mm256_add_epi32(_mm256_add_epi32(U_256_1, V_256_1), W_256_1);
+
+ const __m256i one256 = _mm256_set1_epi32(1);
+ const __m256i two256 = _mm256_set1_epi32(2);
+
+ __m256i mask_minmaxUVW_256 = _mm256_or_si256(_mm256_cmpeq_epi32(one256, UVW_256_1),
+ _mm256_cmpeq_epi32(two256, UVW_256_1));
+
+ unsigned char mask_minmaxUVW_pos = _mm256_movemask_ps(_mm256_castsi256_ps(mask_minmaxUVW_256));
+ if ((mask_minmaxUVW_pos & prim_num_mask) == prim_num_mask) { //all bits set
+ return false;
+ }
+
+ /* Calculate geometry normal and denominator. */
+ __m256 Ng1_x_256 = cross256(e1_y_256, e0_z_256, e1_z_256, e0_y_256);
+ __m256 Ng1_y_256 = cross256(e1_z_256, e0_x_256, e1_x_256, e0_z_256);
+ __m256 Ng1_z_256 = cross256(e1_x_256, e0_y_256, e1_y_256, e0_x_256);
+
+ Ng1_x_256 = _mm256_add_ps(Ng1_x_256, Ng1_x_256);
+ Ng1_y_256 = _mm256_add_ps(Ng1_y_256, Ng1_y_256);
+ Ng1_z_256 = _mm256_add_ps(Ng1_z_256, Ng1_z_256);
+
+ /* vertical dot */
+ __m256 den_256 = _mm256_mul_ps(Ng1_x_256, dirx256);
+ den_256 = _mm256_fmadd_ps(Ng1_y_256, diry256, den_256);
+ den_256 = _mm256_fmadd_ps(Ng1_z_256, dirz256, den_256);
+
+ /* Perform depth test. */
+ __m256 T_256 = _mm256_mul_ps(Ng1_x_256, v0_x_256);
+ T_256 = _mm256_fmadd_ps(Ng1_y_256, v0_y_256, T_256);
+ T_256 = _mm256_fmadd_ps(Ng1_z_256, v0_z_256, T_256);
+
+ const __m256i c0x80000000 = _mm256_set1_epi32(0x80000000);
+ __m256i sign_den_256 = _mm256_and_si256(_mm256_castps_si256(den_256), c0x80000000);
+
+ __m256 sign_T_256 = _mm256_castsi256_ps(
+ _mm256_xor_si256(_mm256_castps_si256(T_256), sign_den_256));
+
+ unsigned char mask_sign_T = _mm256_movemask_ps(sign_T_256);
+ if (((mask_minmaxUVW_pos | mask_sign_T) & prim_num_mask) == prim_num_mask) {
+ return false;
+ }
+
+ __m256 xor_signmask_256 = _mm256_castsi256_ps(
+ _mm256_xor_si256(_mm256_castps_si256(den_256), sign_den_256));
+
+ ccl_align(32) float den8[8], U8[8], V8[8], T8[8], sign_T8[8], xor_signmask8[8];
+ ccl_align(32) unsigned int mask_minmaxUVW8[8];
+
+ if (visibility == PATH_RAY_SHADOW_OPAQUE) {
+ __m256i mask_final_256 = _mm256_cmpeq_epi32(mask_minmaxUVW_256, zero256);
+ __m256i maskden256 = _mm256_cmpeq_epi32(_mm256_castps_si256(den_256), zero256);
+ __m256i mask0 = _mm256_cmpgt_epi32(zero256, _mm256_castps_si256(sign_T_256));
+ __m256 rayt_256 = _mm256_set1_ps((*isect)->t);
+ __m256i mask1 = _mm256_cmpgt_epi32(
+ _mm256_castps_si256(sign_T_256),
+ _mm256_castps_si256(_mm256_mul_ps(
+ _mm256_castsi256_ps(_mm256_xor_si256(_mm256_castps_si256(den_256), sign_den_256)),
+ rayt_256)));
+ mask0 = _mm256_or_si256(mask1, mask0);
+ mask_final_256 = _mm256_andnot_si256(mask0, mask_final_256); //(~mask_minmaxUVW_pos) &(~mask)
+ mask_final_256 = _mm256_andnot_si256(
+ maskden256, mask_final_256); //(~mask_minmaxUVW_pos) &(~mask) & (~maskden)
+ unsigned char mask_final = _mm256_movemask_ps(_mm256_castsi256_ps(mask_final_256));
+ if ((mask_final & prim_num_mask) == 0) {
+ return false;
+ }
+ const int i = __bsf(mask_final);
+ __m256 inv_den_256 = _mm256_rcp_ps(den_256);
+ U_256 = _mm256_mul_ps(U_256, inv_den_256);
+ V_256 = _mm256_mul_ps(V_256, inv_den_256);
+ T_256 = _mm256_mul_ps(T_256, inv_den_256);
+ _mm256_store_ps(U8, U_256);
+ _mm256_store_ps(V8, V_256);
+ _mm256_store_ps(T8, T_256);
+ /* NOTE: Here we assume visibility for all triangles in the node is
+ * the same. */
+ (*isect)->u = U8[i];
+ (*isect)->v = V8[i];
+ (*isect)->t = T8[i];
+ (*isect)->prim = (prim_addr + i);
+ (*isect)->object = object;
+ (*isect)->type = PRIMITIVE_TRIANGLE;
+ return true;
+ }
+ else {
+ _mm256_store_ps(den8, den_256);
+ _mm256_store_ps(U8, U_256);
+ _mm256_store_ps(V8, V_256);
+ _mm256_store_ps(T8, T_256);
+
+ _mm256_store_ps(sign_T8, sign_T_256);
+ _mm256_store_ps(xor_signmask8, xor_signmask_256);
+ _mm256_store_si256((__m256i *)mask_minmaxUVW8, mask_minmaxUVW_256);
+
+ int ret = false;
+
+ if (visibility == PATH_RAY_SHADOW) {
+ for (int i = 0; i < prim_num; i++) {
+ if (mask_minmaxUVW8[i]) {
+ continue;
+ }
+# ifdef __VISIBILITY_FLAG__
+ if ((kernel_tex_fetch(__prim_visibility, (prim_addr + i)) & visibility) == 0) {
+ continue;
+ }
+# endif
+ if ((sign_T8[i] < 0.0f) || (sign_T8[i] > (*isect)->t * xor_signmask8[i])) {
+ continue;
+ }
+ if (!den8[i]) {
+ continue;
+ }
+ const float inv_den = 1.0f / den8[i];
+ (*isect)->u = U8[i] * inv_den;
+ (*isect)->v = V8[i] * inv_den;
+ (*isect)->t = T8[i] * inv_den;
+ (*isect)->prim = (prim_addr + i);
+ (*isect)->object = object;
+ (*isect)->type = PRIMITIVE_TRIANGLE;
+ const int prim = kernel_tex_fetch(__prim_index, (*isect)->prim);
+ int shader = 0;
+# ifdef __HAIR__
+ if (kernel_tex_fetch(__prim_type, (*isect)->prim) & PRIMITIVE_ALL_TRIANGLE)
+# endif
+ {
+ shader = kernel_tex_fetch(__tri_shader, prim);
+ }
+# ifdef __HAIR__
+ else {
+ float4 str = kernel_tex_fetch(__curves, prim);
+ shader = __float_as_int(str.z);
+ }
+# endif
+ const int flag = kernel_tex_fetch(__shaders, (shader & SHADER_MASK)).flags;
+ /* If no transparent shadows, all light is blocked. */
+ if (!(flag & SD_HAS_TRANSPARENT_SHADOW)) {
+ return 2;
+ }
+ /* If maximum number of hits reached, block all light. */
+ else if (num_hits == NULL || *num_hits == max_hits) {
+ return 2;
+ }
+ /* Move on to next entry in intersections array. */
+ ret = true;
+ (*isect)++;
+ (*num_hits)++;
+ (*num_hits_in_instance)++;
+ (*isect)->t = isect_t;
+ }
+ }
+ else {
+ for (int i = 0; i < prim_num; i++) {
+ if (mask_minmaxUVW8[i]) {
+ continue;
+ }
+# ifdef __VISIBILITY_FLAG__
+ if ((kernel_tex_fetch(__prim_visibility, (prim_addr + i)) & visibility) == 0) {
+ continue;
+ }
+# endif
+ if ((sign_T8[i] < 0.0f) || (sign_T8[i] > (*isect)->t * xor_signmask8[i])) {
+ continue;
+ }
+ if (!den8[i]) {
+ continue;
+ }
+ const float inv_den = 1.0f / den8[i];
+ (*isect)->u = U8[i] * inv_den;
+ (*isect)->v = V8[i] * inv_den;
+ (*isect)->t = T8[i] * inv_den;
+ (*isect)->prim = (prim_addr + i);
+ (*isect)->object = object;
+ (*isect)->type = PRIMITIVE_TRIANGLE;
+ ret = true;
+ }
+ }
+ return ret;
+ }
}
-ccl_device_inline int triangle_intersect8(
- KernelGlobals *kg,
- Intersection **isect,
- float3 P,
- float3 dir,
- uint visibility,
- int object,
- int prim_addr,
- int prim_num,
- uint *num_hits,
- uint max_hits,
- int *num_hits_in_instance,
- float isect_t)
- {
- __m128 tri_a[8], tri_b[8], tri_c[8];
- __m256 tritmp[12], tri[12];
- __m256 triA[3], triB[3], triC[3];
-
- int i, r;
-
- uint tri_vindex = kernel_tex_fetch(__prim_tri_index, prim_addr);
- for(i = 0; i < prim_num; i++) {
- tri_a[i] = *(__m128*)&kg->__prim_tri_verts.data[tri_vindex++];
- tri_b[i] = *(__m128*)&kg->__prim_tri_verts.data[tri_vindex++];
- tri_c[i] = *(__m128*)&kg->__prim_tri_verts.data[tri_vindex++];
- }
- //create 9 or 12 placeholders
- tri[0] = _mm256_castps128_ps256(tri_a[0]); //_mm256_zextps128_ps256
- tri[1] = _mm256_castps128_ps256(tri_b[0]);//_mm256_zextps128_ps256
- tri[2] = _mm256_castps128_ps256(tri_c[0]);//_mm256_zextps128_ps256
-
- tri[3] = _mm256_castps128_ps256(tri_a[1]); //_mm256_zextps128_ps256
- tri[4] = _mm256_castps128_ps256(tri_b[1]);//_mm256_zextps128_ps256
- tri[5] = _mm256_castps128_ps256(tri_c[1]);//_mm256_zextps128_ps256
-
- tri[6] = _mm256_castps128_ps256(tri_a[2]); //_mm256_zextps128_ps256
- tri[7] = _mm256_castps128_ps256(tri_b[2]);//_mm256_zextps128_ps256
- tri[8] = _mm256_castps128_ps256(tri_c[2]);//_mm256_zextps128_ps256
-
- if(prim_num > 3) {
- tri[9] = _mm256_castps128_ps256(tri_a[3]); //_mm256_zextps128_ps256
- tri[10] = _mm256_castps128_ps256(tri_b[3]);//_mm256_zextps128_ps256
- tri[11] = _mm256_castps128_ps256(tri_c[3]);//_mm256_zextps128_ps256
- }
-
- for(i = 4, r = 0; i < prim_num; i ++, r += 3) {
- tri[r] = _mm256_insertf128_ps(tri[r] , tri_a[i], 1);
- tri[r + 1] = _mm256_insertf128_ps(tri[r + 1], tri_b[i], 1);
- tri[r + 2] = _mm256_insertf128_ps(tri[r + 2], tri_c[i], 1);
- }
-
- //------------------------------------------------
- //0! Xa0 Ya0 Za0 1 Xa4 Ya4 Za4 1
- //1! Xb0 Yb0 Zb0 1 Xb4 Yb4 Zb4 1
- //2! Xc0 Yc0 Zc0 1 Xc4 Yc4 Zc4 1
-
- //3! Xa1 Ya1 Za1 1 Xa5 Ya5 Za5 1
- //4! Xb1 Yb1 Zb1 1 Xb5 Yb5 Zb5 1
- //5! Xc1 Yc1 Zc1 1 Xc5 Yc5 Zc5 1
-
- //6! Xa2 Ya2 Za2 1 Xa6 Ya6 Za6 1
- //7! Xb2 Yb2 Zb2 1 Xb6 Yb6 Zb6 1
- //8! Xc2 Yc2 Zc2 1 Xc6 Yc6 Zc6 1
-
- //9! Xa3 Ya3 Za3 1 Xa7 Ya7 Za7 1
- //10! Xb3 Yb3 Zb3 1 Xb7 Yb7 Zb7 1
- //11! Xc3 Yc3 Zc3 1 Xc7 Yc7 Zc7 1
-
- //"transpose"
- tritmp[0] = _mm256_unpacklo_ps(tri[0], tri[3]); //0! Xa0 Xa1 Ya0 Ya1 Xa4 Xa5 Ya4 Ya5
- tritmp[1] = _mm256_unpackhi_ps(tri[0], tri[3]); //1! Za0 Za1 1 1 Za4 Za5 1 1
-
- tritmp[2] = _mm256_unpacklo_ps(tri[6], tri[9]); //2! Xa2 Xa3 Ya2 Ya3 Xa6 Xa7 Ya6 Ya7
- tritmp[3] = _mm256_unpackhi_ps(tri[6], tri[9]); //3! Za2 Za3 1 1 Za6 Za7 1 1
-
- tritmp[4] = _mm256_unpacklo_ps(tri[1], tri[4]); //4! Xb0 Xb1 Yb0 Yb1 Xb4 Xb5 Yb4 Yb5
- tritmp[5] = _mm256_unpackhi_ps(tri[1], tri[4]); //5! Zb0 Zb1 1 1 Zb4 Zb5 1 1
-
- tritmp[6] = _mm256_unpacklo_ps(tri[7], tri[10]); //6! Xb2 Xb3 Yb2 Yb3 Xb6 Xb7 Yb6 Yb7
- tritmp[7] = _mm256_unpackhi_ps(tri[7], tri[10]); //7! Zb2 Zb3 1 1 Zb6 Zb7 1 1
-
- tritmp[8] = _mm256_unpacklo_ps(tri[2], tri[5]); //8! Xc0 Xc1 Yc0 Yc1 Xc4 Xc5 Yc4 Yc5
- tritmp[9] = _mm256_unpackhi_ps(tri[2], tri[5]); //9! Zc0 Zc1 1 1 Zc4 Zc5 1 1
-
- tritmp[10] = _mm256_unpacklo_ps(tri[8], tri[11]); //10! Xc2 Xc3 Yc2 Yc3 Xc6 Xc7 Yc6 Yc7
- tritmp[11] = _mm256_unpackhi_ps(tri[8], tri[11]); //11! Zc2 Zc3 1 1 Zc6 Zc7 1 1
-
- /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
- triA[0] = _mm256_castpd_ps(_mm256_unpacklo_pd(_mm256_castps_pd(tritmp[0]), _mm256_castps_pd(tritmp[2]))); // Xa0 Xa1 Xa2 Xa3 Xa4 Xa5 Xa6 Xa7
- triA[1] = _mm256_castpd_ps(_mm256_unpackhi_pd(_mm256_castps_pd(tritmp[0]), _mm256_castps_pd(tritmp[2]))); // Ya0 Ya1 Ya2 Ya3 Ya4 Ya5 Ya6 Ya7
- triA[2] = _mm256_castpd_ps(_mm256_unpacklo_pd(_mm256_castps_pd(tritmp[1]), _mm256_castps_pd(tritmp[3]))); // Za0 Za1 Za2 Za3 Za4 Za5 Za6 Za7
-
- triB[0] = _mm256_castpd_ps(_mm256_unpacklo_pd(_mm256_castps_pd(tritmp[4]), _mm256_castps_pd(tritmp[6]))); // Xb0 Xb1 Xb2 Xb3 Xb4 Xb5 Xb5 Xb7
- triB[1] = _mm256_castpd_ps(_mm256_unpackhi_pd(_mm256_castps_pd(tritmp[4]), _mm256_castps_pd(tritmp[6]))); // Yb0 Yb1 Yb2 Yb3 Yb4 Yb5 Yb5 Yb7
- triB[2] = _mm256_castpd_ps(_mm256_unpacklo_pd(_mm256_castps_pd(tritmp[5]), _mm256_castps_pd(tritmp[7]))); // Zb0 Zb1 Zb2 Zb3 Zb4 Zb5 Zb5 Zb7
-
- triC[0] = _mm256_castpd_ps(_mm256_unpacklo_pd(_mm256_castps_pd(tritmp[8]), _mm256_castps_pd(tritmp[10]))); //Xc0 Xc1 Xc2 Xc3 Xc4 Xc5 Xc6 Xc7
- triC[1] = _mm256_castpd_ps(_mm256_unpackhi_pd(_mm256_castps_pd(tritmp[8]), _mm256_castps_pd(tritmp[10]))); //Yc0 Yc1 Yc2 Yc3 Yc4 Yc5 Yc6 Yc7
- triC[2] = _mm256_castpd_ps(_mm256_unpacklo_pd(_mm256_castps_pd(tritmp[9]), _mm256_castps_pd(tritmp[11]))); //Zc0 Zc1 Zc2 Zc3 Zc4 Zc5 Zc6 Zc7
-
- /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
-
- int result = ray_triangle_intersect8(kg, P,
- dir,
- isect,
- visibility, object,
- triA,
- triB,
- triC,
- prim_addr,
- prim_num,
- num_hits,
- max_hits,
- num_hits_in_instance,
- isect_t);
- return result;
+ccl_device_inline int triangle_intersect8(KernelGlobals *kg,
+ Intersection **isect,
+ float3 P,
+ float3 dir,
+ uint visibility,
+ int object,
+ int prim_addr,
+ int prim_num,
+ uint *num_hits,
+ uint max_hits,
+ int *num_hits_in_instance,
+ float isect_t)
+{
+ __m128 tri_a[8], tri_b[8], tri_c[8];
+ __m256 tritmp[12], tri[12];
+ __m256 triA[3], triB[3], triC[3];
+
+ int i, r;
+
+ uint tri_vindex = kernel_tex_fetch(__prim_tri_index, prim_addr);
+ for (i = 0; i < prim_num; i++) {
+ tri_a[i] = *(__m128 *)&kg->__prim_tri_verts.data[tri_vindex++];
+ tri_b[i] = *(__m128 *)&kg->__prim_tri_verts.data[tri_vindex++];
+ tri_c[i] = *(__m128 *)&kg->__prim_tri_verts.data[tri_vindex++];
+ }
+ //create 9 or 12 placeholders
+ tri[0] = _mm256_castps128_ps256(tri_a[0]); //_mm256_zextps128_ps256
+ tri[1] = _mm256_castps128_ps256(tri_b[0]); //_mm256_zextps128_ps256
+ tri[2] = _mm256_castps128_ps256(tri_c[0]); //_mm256_zextps128_ps256
+
+ tri[3] = _mm256_castps128_ps256(tri_a[1]); //_mm256_zextps128_ps256
+ tri[4] = _mm256_castps128_ps256(tri_b[1]); //_mm256_zextps128_ps256
+ tri[5] = _mm256_castps128_ps256(tri_c[1]); //_mm256_zextps128_ps256
+
+ tri[6] = _mm256_castps128_ps256(tri_a[2]); //_mm256_zextps128_ps256
+ tri[7] = _mm256_castps128_ps256(tri_b[2]); //_mm256_zextps128_ps256
+ tri[8] = _mm256_castps128_ps256(tri_c[2]); //_mm256_zextps128_ps256
+
+ if (prim_num > 3) {
+ tri[9] = _mm256_castps128_ps256(tri_a[3]); //_mm256_zextps128_ps256
+ tri[10] = _mm256_castps128_ps256(tri_b[3]); //_mm256_zextps128_ps256
+ tri[11] = _mm256_castps128_ps256(tri_c[3]); //_mm256_zextps128_ps256
+ }
+
+ for (i = 4, r = 0; i < prim_num; i++, r += 3) {
+ tri[r] = _mm256_insertf128_ps(tri[r], tri_a[i], 1);
+ tri[r + 1] = _mm256_insertf128_ps(tri[r + 1], tri_b[i], 1);
+ tri[r + 2] = _mm256_insertf128_ps(tri[r + 2], tri_c[i], 1);
+ }
+
+ //------------------------------------------------
+ //0! Xa0 Ya0 Za0 1 Xa4 Ya4 Za4 1
+ //1! Xb0 Yb0 Zb0 1 Xb4 Yb4 Zb4 1
+ //2! Xc0 Yc0 Zc0 1 Xc4 Yc4 Zc4 1
+
+ //3! Xa1 Ya1 Za1 1 Xa5 Ya5 Za5 1
+ //4! Xb1 Yb1 Zb1 1 Xb5 Yb5 Zb5 1
+ //5! Xc1 Yc1 Zc1 1 Xc5 Yc5 Zc5 1
+
+ //6! Xa2 Ya2 Za2 1 Xa6 Ya6 Za6 1
+ //7! Xb2 Yb2 Zb2 1 Xb6 Yb6 Zb6 1
+ //8! Xc2 Yc2 Zc2 1 Xc6 Yc6 Zc6 1
+
+ //9! Xa3 Ya3 Za3 1 Xa7 Ya7 Za7 1
+ //10! Xb3 Yb3 Zb3 1 Xb7 Yb7 Zb7 1
+ //11! Xc3 Yc3 Zc3 1 Xc7 Yc7 Zc7 1
+
+ //"transpose"
+ tritmp[0] = _mm256_unpacklo_ps(tri[0], tri[3]); //0! Xa0 Xa1 Ya0 Ya1 Xa4 Xa5 Ya4 Ya5
+ tritmp[1] = _mm256_unpackhi_ps(tri[0], tri[3]); //1! Za0 Za1 1 1 Za4 Za5 1 1
+
+ tritmp[2] = _mm256_unpacklo_ps(tri[6], tri[9]); //2! Xa2 Xa3 Ya2 Ya3 Xa6 Xa7 Ya6 Ya7
+ tritmp[3] = _mm256_unpackhi_ps(tri[6], tri[9]); //3! Za2 Za3 1 1 Za6 Za7 1 1
+
+ tritmp[4] = _mm256_unpacklo_ps(tri[1], tri[4]); //4! Xb0 Xb1 Yb0 Yb1 Xb4 Xb5 Yb4 Yb5
+ tritmp[5] = _mm256_unpackhi_ps(tri[1], tri[4]); //5! Zb0 Zb1 1 1 Zb4 Zb5 1 1
+
+ tritmp[6] = _mm256_unpacklo_ps(tri[7], tri[10]); //6! Xb2 Xb3 Yb2 Yb3 Xb6 Xb7 Yb6 Yb7
+ tritmp[7] = _mm256_unpackhi_ps(tri[7], tri[10]); //7! Zb2 Zb3 1 1 Zb6 Zb7 1 1
+
+ tritmp[8] = _mm256_unpacklo_ps(tri[2], tri[5]); //8! Xc0 Xc1 Yc0 Yc1 Xc4 Xc5 Yc4 Yc5
+ tritmp[9] = _mm256_unpackhi_ps(tri[2], tri[5]); //9! Zc0 Zc1 1 1 Zc4 Zc5 1 1
+
+ tritmp[10] = _mm256_unpacklo_ps(tri[8], tri[11]); //10! Xc2 Xc3 Yc2 Yc3 Xc6 Xc7 Yc6 Yc7
+ tritmp[11] = _mm256_unpackhi_ps(tri[8], tri[11]); //11! Zc2 Zc3 1 1 Zc6 Zc7 1 1
+
+ /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+ triA[0] = _mm256_castpd_ps(
+ _mm256_unpacklo_pd(_mm256_castps_pd(tritmp[0]),
+ _mm256_castps_pd(tritmp[2]))); // Xa0 Xa1 Xa2 Xa3 Xa4 Xa5 Xa6 Xa7
+ triA[1] = _mm256_castpd_ps(
+ _mm256_unpackhi_pd(_mm256_castps_pd(tritmp[0]),
+ _mm256_castps_pd(tritmp[2]))); // Ya0 Ya1 Ya2 Ya3 Ya4 Ya5 Ya6 Ya7
+ triA[2] = _mm256_castpd_ps(
+ _mm256_unpacklo_pd(_mm256_castps_pd(tritmp[1]),
+ _mm256_castps_pd(tritmp[3]))); // Za0 Za1 Za2 Za3 Za4 Za5 Za6 Za7
+
+ triB[0] = _mm256_castpd_ps(
+ _mm256_unpacklo_pd(_mm256_castps_pd(tritmp[4]),
+ _mm256_castps_pd(tritmp[6]))); // Xb0 Xb1 Xb2 Xb3 Xb4 Xb5 Xb5 Xb7
+ triB[1] = _mm256_castpd_ps(
+ _mm256_unpackhi_pd(_mm256_castps_pd(tritmp[4]),
+ _mm256_castps_pd(tritmp[6]))); // Yb0 Yb1 Yb2 Yb3 Yb4 Yb5 Yb5 Yb7
+ triB[2] = _mm256_castpd_ps(
+ _mm256_unpacklo_pd(_mm256_castps_pd(tritmp[5]),
+ _mm256_castps_pd(tritmp[7]))); // Zb0 Zb1 Zb2 Zb3 Zb4 Zb5 Zb5 Zb7
+
+ triC[0] = _mm256_castpd_ps(
+ _mm256_unpacklo_pd(_mm256_castps_pd(tritmp[8]),
+ _mm256_castps_pd(tritmp[10]))); //Xc0 Xc1 Xc2 Xc3 Xc4 Xc5 Xc6 Xc7
+ triC[1] = _mm256_castpd_ps(
+ _mm256_unpackhi_pd(_mm256_castps_pd(tritmp[8]),
+ _mm256_castps_pd(tritmp[10]))); //Yc0 Yc1 Yc2 Yc3 Yc4 Yc5 Yc6 Yc7
+ triC[2] = _mm256_castpd_ps(
+ _mm256_unpacklo_pd(_mm256_castps_pd(tritmp[9]),
+ _mm256_castps_pd(tritmp[11]))); //Zc0 Zc1 Zc2 Zc3 Zc4 Zc5 Zc6 Zc7
+
+ /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+ int result = ray_triangle_intersect8(kg,
+ P,
+ dir,
+ isect,
+ visibility,
+ object,
+ triA,
+ triB,
+ triC,
+ prim_addr,
+ prim_num,
+ num_hits,
+ max_hits,
+ num_hits_in_instance,
+ isect_t);
+ return result;
}
-#endif /* __KERNEL_AVX2__ */
+#endif /* __KERNEL_AVX2__ */
/* Special ray intersection routines for subsurface scattering. In that case we
* only want to intersect with primitives in the same object, and if case of
@@ -479,106 +496,108 @@ ccl_device_inline int triangle_intersect8(
*/
#ifdef __BVH_LOCAL__
-ccl_device_inline bool triangle_intersect_local(
- KernelGlobals *kg,
- LocalIntersection *local_isect,
- float3 P,
- float3 dir,
- int object,
- int local_object,
- int prim_addr,
- float tmax,
- uint *lcg_state,
- int max_hits)
+ccl_device_inline bool triangle_intersect_local(KernelGlobals *kg,
+ LocalIntersection *local_isect,
+ float3 P,
+ float3 dir,
+ int object,
+ int local_object,
+ int prim_addr,
+ float tmax,
+ uint *lcg_state,
+ int max_hits)
{
- /* Only intersect with matching object, for instanced objects we
- * already know we are only intersecting the right object. */
- if(object == OBJECT_NONE) {
- if(kernel_tex_fetch(__prim_object, prim_addr) != local_object) {
- return false;
- }
- }
-
- const uint tri_vindex = kernel_tex_fetch(__prim_tri_index, prim_addr);
-#if defined(__KERNEL_SSE2__) && defined(__KERNEL_SSE__)
- const ssef *ssef_verts = (ssef*)&kg->__prim_tri_verts.data[tri_vindex];
-#else
- const float3 tri_a = float4_to_float3(kernel_tex_fetch(__prim_tri_verts, tri_vindex+0)),
- tri_b = float4_to_float3(kernel_tex_fetch(__prim_tri_verts, tri_vindex+1)),
- tri_c = float4_to_float3(kernel_tex_fetch(__prim_tri_verts, tri_vindex+2));
-#endif
- float t, u, v;
- if(!ray_triangle_intersect(P,
- dir,
- tmax,
-#if defined(__KERNEL_SSE2__) && defined(__KERNEL_SSE__)
- ssef_verts,
-#else
- tri_a, tri_b, tri_c,
-#endif
- &u, &v, &t))
- {
- return false;
- }
-
- /* If no actual hit information is requested, just return here. */
- if(max_hits == 0) {
- return true;
- }
-
- int hit;
- if(lcg_state) {
- /* Record up to max_hits intersections. */
- for(int i = min(max_hits, local_isect->num_hits) - 1; i >= 0; --i) {
- if(local_isect->hits[i].t == t) {
- return false;
- }
- }
-
- local_isect->num_hits++;
-
- if(local_isect->num_hits <= max_hits) {
- hit = local_isect->num_hits - 1;
- }
- else {
- /* reservoir sampling: if we are at the maximum number of
- * hits, randomly replace element or skip it */
- hit = lcg_step_uint(lcg_state) % local_isect->num_hits;
-
- if(hit >= max_hits)
- return false;
- }
- }
- else {
- /* Record closest intersection only. */
- if(local_isect->num_hits && t > local_isect->hits[0].t) {
- return false;
- }
-
- hit = 0;
- local_isect->num_hits = 1;
- }
-
- /* Record intersection. */
- Intersection *isect = &local_isect->hits[hit];
- isect->prim = prim_addr;
- isect->object = object;
- isect->type = PRIMITIVE_TRIANGLE;
- isect->u = u;
- isect->v = v;
- isect->t = t;
-
- /* Record geometric normal. */
-#if defined(__KERNEL_SSE2__) && defined(__KERNEL_SSE__)
- const float3 tri_a = float4_to_float3(kernel_tex_fetch(__prim_tri_verts, tri_vindex+0)),
- tri_b = float4_to_float3(kernel_tex_fetch(__prim_tri_verts, tri_vindex+1)),
- tri_c = float4_to_float3(kernel_tex_fetch(__prim_tri_verts, tri_vindex+2));
-#endif
- local_isect->Ng[hit] = normalize(cross(tri_b - tri_a, tri_c - tri_a));
+ /* Only intersect with matching object, for instanced objects we
+ * already know we are only intersecting the right object. */
+ if (object == OBJECT_NONE) {
+ if (kernel_tex_fetch(__prim_object, prim_addr) != local_object) {
+ return false;
+ }
+ }
+
+ const uint tri_vindex = kernel_tex_fetch(__prim_tri_index, prim_addr);
+# if defined(__KERNEL_SSE2__) && defined(__KERNEL_SSE__)
+ const ssef *ssef_verts = (ssef *)&kg->__prim_tri_verts.data[tri_vindex];
+# else
+ const float3 tri_a = float4_to_float3(kernel_tex_fetch(__prim_tri_verts, tri_vindex + 0)),
+ tri_b = float4_to_float3(kernel_tex_fetch(__prim_tri_verts, tri_vindex + 1)),
+ tri_c = float4_to_float3(kernel_tex_fetch(__prim_tri_verts, tri_vindex + 2));
+# endif
+ float t, u, v;
+ if (!ray_triangle_intersect(P,
+ dir,
+ tmax,
+# if defined(__KERNEL_SSE2__) && defined(__KERNEL_SSE__)
+ ssef_verts,
+# else
+ tri_a,
+ tri_b,
+ tri_c,
+# endif
+ &u,
+ &v,
+ &t)) {
+ return false;
+ }
+
+ /* If no actual hit information is requested, just return here. */
+ if (max_hits == 0) {
+ return true;
+ }
+
+ int hit;
+ if (lcg_state) {
+ /* Record up to max_hits intersections. */
+ for (int i = min(max_hits, local_isect->num_hits) - 1; i >= 0; --i) {
+ if (local_isect->hits[i].t == t) {
+ return false;
+ }
+ }
+
+ local_isect->num_hits++;
+
+ if (local_isect->num_hits <= max_hits) {
+ hit = local_isect->num_hits - 1;
+ }
+ else {
+ /* reservoir sampling: if we are at the maximum number of
+ * hits, randomly replace element or skip it */
+ hit = lcg_step_uint(lcg_state) % local_isect->num_hits;
+
+ if (hit >= max_hits)
+ return false;
+ }
+ }
+ else {
+ /* Record closest intersection only. */
+ if (local_isect->num_hits && t > local_isect->hits[0].t) {
+ return false;
+ }
+
+ hit = 0;
+ local_isect->num_hits = 1;
+ }
+
+ /* Record intersection. */
+ Intersection *isect = &local_isect->hits[hit];
+ isect->prim = prim_addr;
+ isect->object = object;
+ isect->type = PRIMITIVE_TRIANGLE;
+ isect->u = u;
+ isect->v = v;
+ isect->t = t;
+
+ /* Record geometric normal. */
+# if defined(__KERNEL_SSE2__) && defined(__KERNEL_SSE__)
+ const float3 tri_a = float4_to_float3(kernel_tex_fetch(__prim_tri_verts, tri_vindex + 0)),
+ tri_b = float4_to_float3(kernel_tex_fetch(__prim_tri_verts, tri_vindex + 1)),
+ tri_c = float4_to_float3(kernel_tex_fetch(__prim_tri_verts, tri_vindex + 2));
+# endif
+ local_isect->Ng[hit] = normalize(cross(tri_b - tri_a, tri_c - tri_a));
- return false;
+ return false;
}
-#endif /* __BVH_LOCAL__ */
+#endif /* __BVH_LOCAL__ */
/* Refine triangle intersection to more precise hit point. For rays that travel
* far the precision is often not so good, this reintersects the primitive from
@@ -596,61 +615,61 @@ ccl_device_inline float3 triangle_refine(KernelGlobals *kg,
const Intersection *isect,
const Ray *ray)
{
- float3 P = ray->P;
- float3 D = ray->D;
- float t = isect->t;
+ float3 P = ray->P;
+ float3 D = ray->D;
+ float t = isect->t;
#ifdef __INTERSECTION_REFINE__
- if(isect->object != OBJECT_NONE) {
- if(UNLIKELY(t == 0.0f)) {
- return P;
- }
+ if (isect->object != OBJECT_NONE) {
+ if (UNLIKELY(t == 0.0f)) {
+ return P;
+ }
# ifdef __OBJECT_MOTION__
- Transform tfm = sd->ob_itfm;
+ Transform tfm = sd->ob_itfm;
# else
- Transform tfm = object_fetch_transform(kg, isect->object, OBJECT_INVERSE_TRANSFORM);
+ Transform tfm = object_fetch_transform(kg, isect->object, OBJECT_INVERSE_TRANSFORM);
# endif
- P = transform_point(&tfm, P);
- D = transform_direction(&tfm, D*t);
- D = normalize_len(D, &t);
- }
-
- P = P + D*t;
-
- const uint tri_vindex = kernel_tex_fetch(__prim_tri_index, isect->prim);
- const float4 tri_a = kernel_tex_fetch(__prim_tri_verts, tri_vindex+0),
- tri_b = kernel_tex_fetch(__prim_tri_verts, tri_vindex+1),
- tri_c = kernel_tex_fetch(__prim_tri_verts, tri_vindex+2);
- float3 edge1 = make_float3(tri_a.x - tri_c.x, tri_a.y - tri_c.y, tri_a.z - tri_c.z);
- float3 edge2 = make_float3(tri_b.x - tri_c.x, tri_b.y - tri_c.y, tri_b.z - tri_c.z);
- float3 tvec = make_float3(P.x - tri_c.x, P.y - tri_c.y, P.z - tri_c.z);
- float3 qvec = cross(tvec, edge1);
- float3 pvec = cross(D, edge2);
- float det = dot(edge1, pvec);
- if(det != 0.0f) {
- /* If determinant is zero it means ray lies in the plane of
- * the triangle. It is possible in theory due to watertight
- * nature of triangle intersection. For such cases we simply
- * don't refine intersection hoping it'll go all fine.
- */
- float rt = dot(edge2, qvec) / det;
- P = P + D*rt;
- }
-
- if(isect->object != OBJECT_NONE) {
+ P = transform_point(&tfm, P);
+ D = transform_direction(&tfm, D * t);
+ D = normalize_len(D, &t);
+ }
+
+ P = P + D * t;
+
+ const uint tri_vindex = kernel_tex_fetch(__prim_tri_index, isect->prim);
+ const float4 tri_a = kernel_tex_fetch(__prim_tri_verts, tri_vindex + 0),
+ tri_b = kernel_tex_fetch(__prim_tri_verts, tri_vindex + 1),
+ tri_c = kernel_tex_fetch(__prim_tri_verts, tri_vindex + 2);
+ float3 edge1 = make_float3(tri_a.x - tri_c.x, tri_a.y - tri_c.y, tri_a.z - tri_c.z);
+ float3 edge2 = make_float3(tri_b.x - tri_c.x, tri_b.y - tri_c.y, tri_b.z - tri_c.z);
+ float3 tvec = make_float3(P.x - tri_c.x, P.y - tri_c.y, P.z - tri_c.z);
+ float3 qvec = cross(tvec, edge1);
+ float3 pvec = cross(D, edge2);
+ float det = dot(edge1, pvec);
+ if (det != 0.0f) {
+ /* If determinant is zero it means ray lies in the plane of
+ * the triangle. It is possible in theory due to watertight
+ * nature of triangle intersection. For such cases we simply
+ * don't refine intersection hoping it'll go all fine.
+ */
+ float rt = dot(edge2, qvec) / det;
+ P = P + D * rt;
+ }
+
+ if (isect->object != OBJECT_NONE) {
# ifdef __OBJECT_MOTION__
- Transform tfm = sd->ob_tfm;
+ Transform tfm = sd->ob_tfm;
# else
- Transform tfm = object_fetch_transform(kg, isect->object, OBJECT_TRANSFORM);
+ Transform tfm = object_fetch_transform(kg, isect->object, OBJECT_TRANSFORM);
# endif
- P = transform_point(&tfm, P);
- }
+ P = transform_point(&tfm, P);
+ }
- return P;
+ return P;
#else
- return P + D*t;
+ return P + D * t;
#endif
}
@@ -662,61 +681,57 @@ ccl_device_inline float3 triangle_refine_local(KernelGlobals *kg,
const Intersection *isect,
const Ray *ray)
{
- float3 P = ray->P;
- float3 D = ray->D;
- float t = isect->t;
+ float3 P = ray->P;
+ float3 D = ray->D;
+ float t = isect->t;
- if(isect->object != OBJECT_NONE) {
+ if (isect->object != OBJECT_NONE) {
#ifdef __OBJECT_MOTION__
- Transform tfm = sd->ob_itfm;
+ Transform tfm = sd->ob_itfm;
#else
- Transform tfm = object_fetch_transform(kg,
- isect->object,
- OBJECT_INVERSE_TRANSFORM);
+ Transform tfm = object_fetch_transform(kg, isect->object, OBJECT_INVERSE_TRANSFORM);
#endif
- P = transform_point(&tfm, P);
- D = transform_direction(&tfm, D);
- D = normalize(D);
- }
+ P = transform_point(&tfm, P);
+ D = transform_direction(&tfm, D);
+ D = normalize(D);
+ }
- P = P + D*t;
+ P = P + D * t;
#ifdef __INTERSECTION_REFINE__
- const uint tri_vindex = kernel_tex_fetch(__prim_tri_index, isect->prim);
- const float4 tri_a = kernel_tex_fetch(__prim_tri_verts, tri_vindex+0),
- tri_b = kernel_tex_fetch(__prim_tri_verts, tri_vindex+1),
- tri_c = kernel_tex_fetch(__prim_tri_verts, tri_vindex+2);
- float3 edge1 = make_float3(tri_a.x - tri_c.x, tri_a.y - tri_c.y, tri_a.z - tri_c.z);
- float3 edge2 = make_float3(tri_b.x - tri_c.x, tri_b.y - tri_c.y, tri_b.z - tri_c.z);
- float3 tvec = make_float3(P.x - tri_c.x, P.y - tri_c.y, P.z - tri_c.z);
- float3 qvec = cross(tvec, edge1);
- float3 pvec = cross(D, edge2);
- float det = dot(edge1, pvec);
- if(det != 0.0f) {
- /* If determinant is zero it means ray lies in the plane of
- * the triangle. It is possible in theory due to watertight
- * nature of triangle intersection. For such cases we simply
- * don't refine intersection hoping it'll go all fine.
- */
- float rt = dot(edge2, qvec) / det;
- P = P + D*rt;
- }
-#endif /* __INTERSECTION_REFINE__ */
-
- if(isect->object != OBJECT_NONE) {
+ const uint tri_vindex = kernel_tex_fetch(__prim_tri_index, isect->prim);
+ const float4 tri_a = kernel_tex_fetch(__prim_tri_verts, tri_vindex + 0),
+ tri_b = kernel_tex_fetch(__prim_tri_verts, tri_vindex + 1),
+ tri_c = kernel_tex_fetch(__prim_tri_verts, tri_vindex + 2);
+ float3 edge1 = make_float3(tri_a.x - tri_c.x, tri_a.y - tri_c.y, tri_a.z - tri_c.z);
+ float3 edge2 = make_float3(tri_b.x - tri_c.x, tri_b.y - tri_c.y, tri_b.z - tri_c.z);
+ float3 tvec = make_float3(P.x - tri_c.x, P.y - tri_c.y, P.z - tri_c.z);
+ float3 qvec = cross(tvec, edge1);
+ float3 pvec = cross(D, edge2);
+ float det = dot(edge1, pvec);
+ if (det != 0.0f) {
+ /* If determinant is zero it means ray lies in the plane of
+ * the triangle. It is possible in theory due to watertight
+ * nature of triangle intersection. For such cases we simply
+ * don't refine intersection hoping it'll go all fine.
+ */
+ float rt = dot(edge2, qvec) / det;
+ P = P + D * rt;
+ }
+#endif /* __INTERSECTION_REFINE__ */
+
+ if (isect->object != OBJECT_NONE) {
#ifdef __OBJECT_MOTION__
- Transform tfm = sd->ob_tfm;
+ Transform tfm = sd->ob_tfm;
#else
- Transform tfm = object_fetch_transform(kg,
- isect->object,
- OBJECT_TRANSFORM);
+ Transform tfm = object_fetch_transform(kg, isect->object, OBJECT_TRANSFORM);
#endif
- P = transform_point(&tfm, P);
- }
+ P = transform_point(&tfm, P);
+ }
- return P;
+ return P;
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/geom/geom_volume.h b/intern/cycles/kernel/geom/geom_volume.h
index 1977d263ece..96cf35a40dc 100644
--- a/intern/cycles/kernel/geom/geom_volume.h
+++ b/intern/cycles/kernel/geom/geom_volume.h
@@ -33,41 +33,47 @@ ccl_device_inline float3 volume_normalized_position(KernelGlobals *kg,
const ShaderData *sd,
float3 P)
{
- /* todo: optimize this so it's just a single matrix multiplication when
- * possible (not motion blur), or perhaps even just translation + scale */
- const AttributeDescriptor desc = find_attribute(kg, sd, ATTR_STD_GENERATED_TRANSFORM);
+ /* todo: optimize this so it's just a single matrix multiplication when
+ * possible (not motion blur), or perhaps even just translation + scale */
+ const AttributeDescriptor desc = find_attribute(kg, sd, ATTR_STD_GENERATED_TRANSFORM);
- object_inverse_position_transform(kg, sd, &P);
+ object_inverse_position_transform(kg, sd, &P);
- if(desc.offset != ATTR_STD_NOT_FOUND) {
- Transform tfm = primitive_attribute_matrix(kg, sd, desc);
- P = transform_point(&tfm, P);
- }
+ if (desc.offset != ATTR_STD_NOT_FOUND) {
+ Transform tfm = primitive_attribute_matrix(kg, sd, desc);
+ P = transform_point(&tfm, P);
+ }
- return P;
+ return P;
}
-ccl_device float volume_attribute_float(KernelGlobals *kg, const ShaderData *sd, const AttributeDescriptor desc)
+ccl_device float volume_attribute_float(KernelGlobals *kg,
+ const ShaderData *sd,
+ const AttributeDescriptor desc)
{
- float3 P = volume_normalized_position(kg, sd, sd->P);
- InterpolationType interp = (sd->flag & SD_VOLUME_CUBIC)? INTERPOLATION_CUBIC: INTERPOLATION_NONE;
- float4 r = kernel_tex_image_interp_3d(kg, desc.offset, P.x, P.y, P.z, interp);
- return average(float4_to_float3(r));
+ float3 P = volume_normalized_position(kg, sd, sd->P);
+ InterpolationType interp = (sd->flag & SD_VOLUME_CUBIC) ? INTERPOLATION_CUBIC :
+ INTERPOLATION_NONE;
+ float4 r = kernel_tex_image_interp_3d(kg, desc.offset, P.x, P.y, P.z, interp);
+ return average(float4_to_float3(r));
}
-ccl_device float3 volume_attribute_float3(KernelGlobals *kg, const ShaderData *sd, const AttributeDescriptor desc)
+ccl_device float3 volume_attribute_float3(KernelGlobals *kg,
+ const ShaderData *sd,
+ const AttributeDescriptor desc)
{
- float3 P = volume_normalized_position(kg, sd, sd->P);
- InterpolationType interp = (sd->flag & SD_VOLUME_CUBIC)? INTERPOLATION_CUBIC: INTERPOLATION_NONE;
- float4 r = kernel_tex_image_interp_3d(kg, desc.offset, P.x, P.y, P.z, interp);
+ float3 P = volume_normalized_position(kg, sd, sd->P);
+ InterpolationType interp = (sd->flag & SD_VOLUME_CUBIC) ? INTERPOLATION_CUBIC :
+ INTERPOLATION_NONE;
+ float4 r = kernel_tex_image_interp_3d(kg, desc.offset, P.x, P.y, P.z, interp);
- if(r.w > 1e-6f && r.w != 1.0f) {
- /* For RGBA colors, unpremultiply after interpolation. */
- return float4_to_float3(r) / r.w;
- }
- else {
- return float4_to_float3(r);
- }
+ if (r.w > 1e-6f && r.w != 1.0f) {
+ /* For RGBA colors, unpremultiply after interpolation. */
+ return float4_to_float3(r) / r.w;
+ }
+ else {
+ return float4_to_float3(r);
+ }
}
#endif
diff --git a/intern/cycles/kernel/kernel.h b/intern/cycles/kernel/kernel.h
index 1c8c91d15e6..dfdd8843f29 100644
--- a/intern/cycles/kernel/kernel.h
+++ b/intern/cycles/kernel/kernel.h
@@ -24,8 +24,8 @@
CCL_NAMESPACE_BEGIN
-#define KERNEL_NAME_JOIN(x, y, z) x ## _ ## y ## _ ## z
-#define KERNEL_NAME_EVAL(arch, name) KERNEL_NAME_JOIN(kernel, arch, name)
+#define KERNEL_NAME_JOIN(x, y, z) x##_##y##_##z
+#define KERNEL_NAME_EVAL(arch, name) KERNEL_NAME_JOIN(kernel, arch, name)
#define KERNEL_FUNCTION_FULL_NAME(name) KERNEL_NAME_EVAL(KERNEL_ARCH, name)
struct KernelGlobals;
@@ -38,10 +38,7 @@ void *kernel_osl_memory(KernelGlobals *kg);
bool kernel_osl_use(KernelGlobals *kg);
void kernel_const_copy(KernelGlobals *kg, const char *name, void *host, size_t size);
-void kernel_tex_copy(KernelGlobals *kg,
- const char *name,
- void *mem,
- size_t size);
+void kernel_tex_copy(KernelGlobals *kg, const char *name, void *mem, size_t size);
#define KERNEL_ARCH cpu
#include "kernel/kernels/cpu/kernel_cpu.h"
@@ -63,4 +60,4 @@ void kernel_tex_copy(KernelGlobals *kg,
CCL_NAMESPACE_END
-#endif /* __KERNEL_H__ */
+#endif /* __KERNEL_H__ */
diff --git a/intern/cycles/kernel/kernel_accumulate.h b/intern/cycles/kernel/kernel_accumulate.h
index 86ad6e1a061..b9d723222a1 100644
--- a/intern/cycles/kernel/kernel_accumulate.h
+++ b/intern/cycles/kernel/kernel_accumulate.h
@@ -21,149 +21,150 @@ CCL_NAMESPACE_BEGIN
* BSDF evaluation result, split per BSDF type. This is used to accumulate
* render passes separately. */
-ccl_device float3 shader_bsdf_transparency(KernelGlobals *kg,
- const ShaderData *sd);
+ccl_device float3 shader_bsdf_transparency(KernelGlobals *kg, const ShaderData *sd);
-ccl_device_inline void bsdf_eval_init(BsdfEval *eval, ClosureType type, float3 value, int use_light_pass)
+ccl_device_inline void bsdf_eval_init(BsdfEval *eval,
+ ClosureType type,
+ float3 value,
+ int use_light_pass)
{
#ifdef __PASSES__
- eval->use_light_pass = use_light_pass;
-
- if(eval->use_light_pass) {
- eval->diffuse = make_float3(0.0f, 0.0f, 0.0f);
- eval->glossy = make_float3(0.0f, 0.0f, 0.0f);
- eval->transmission = make_float3(0.0f, 0.0f, 0.0f);
- eval->transparent = make_float3(0.0f, 0.0f, 0.0f);
- eval->subsurface = make_float3(0.0f, 0.0f, 0.0f);
- eval->scatter = make_float3(0.0f, 0.0f, 0.0f);
-
- if(type == CLOSURE_BSDF_TRANSPARENT_ID)
- eval->transparent = value;
- else if(CLOSURE_IS_BSDF_DIFFUSE(type))
- eval->diffuse = value;
- else if(CLOSURE_IS_BSDF_GLOSSY(type))
- eval->glossy = value;
- else if(CLOSURE_IS_BSDF_TRANSMISSION(type))
- eval->transmission = value;
- else if(CLOSURE_IS_BSDF_BSSRDF(type))
- eval->subsurface = value;
- else if(CLOSURE_IS_PHASE(type))
- eval->scatter = value;
- }
- else
-#endif
- {
- eval->diffuse = value;
- }
+ eval->use_light_pass = use_light_pass;
+
+ if (eval->use_light_pass) {
+ eval->diffuse = make_float3(0.0f, 0.0f, 0.0f);
+ eval->glossy = make_float3(0.0f, 0.0f, 0.0f);
+ eval->transmission = make_float3(0.0f, 0.0f, 0.0f);
+ eval->transparent = make_float3(0.0f, 0.0f, 0.0f);
+ eval->subsurface = make_float3(0.0f, 0.0f, 0.0f);
+ eval->scatter = make_float3(0.0f, 0.0f, 0.0f);
+
+ if (type == CLOSURE_BSDF_TRANSPARENT_ID)
+ eval->transparent = value;
+ else if (CLOSURE_IS_BSDF_DIFFUSE(type))
+ eval->diffuse = value;
+ else if (CLOSURE_IS_BSDF_GLOSSY(type))
+ eval->glossy = value;
+ else if (CLOSURE_IS_BSDF_TRANSMISSION(type))
+ eval->transmission = value;
+ else if (CLOSURE_IS_BSDF_BSSRDF(type))
+ eval->subsurface = value;
+ else if (CLOSURE_IS_PHASE(type))
+ eval->scatter = value;
+ }
+ else
+#endif
+ {
+ eval->diffuse = value;
+ }
#ifdef __SHADOW_TRICKS__
- eval->sum_no_mis = make_float3(0.0f, 0.0f, 0.0f);
+ eval->sum_no_mis = make_float3(0.0f, 0.0f, 0.0f);
#endif
}
-ccl_device_inline void bsdf_eval_accum(BsdfEval *eval, ClosureType type, float3 value, float mis_weight)
+ccl_device_inline void bsdf_eval_accum(BsdfEval *eval,
+ ClosureType type,
+ float3 value,
+ float mis_weight)
{
#ifdef __SHADOW_TRICKS__
- eval->sum_no_mis += value;
+ eval->sum_no_mis += value;
#endif
- value *= mis_weight;
+ value *= mis_weight;
#ifdef __PASSES__
- if(eval->use_light_pass) {
- if(CLOSURE_IS_BSDF_DIFFUSE(type))
- eval->diffuse += value;
- else if(CLOSURE_IS_BSDF_GLOSSY(type))
- eval->glossy += value;
- else if(CLOSURE_IS_BSDF_TRANSMISSION(type))
- eval->transmission += value;
- else if(CLOSURE_IS_BSDF_BSSRDF(type))
- eval->subsurface += value;
- else if(CLOSURE_IS_PHASE(type))
- eval->scatter += value;
-
- /* skipping transparent, this function is used by for eval(), will be zero then */
- }
- else
-#endif
- {
- eval->diffuse += value;
- }
+ if (eval->use_light_pass) {
+ if (CLOSURE_IS_BSDF_DIFFUSE(type))
+ eval->diffuse += value;
+ else if (CLOSURE_IS_BSDF_GLOSSY(type))
+ eval->glossy += value;
+ else if (CLOSURE_IS_BSDF_TRANSMISSION(type))
+ eval->transmission += value;
+ else if (CLOSURE_IS_BSDF_BSSRDF(type))
+ eval->subsurface += value;
+ else if (CLOSURE_IS_PHASE(type))
+ eval->scatter += value;
+
+ /* skipping transparent, this function is used by for eval(), will be zero then */
+ }
+ else
+#endif
+ {
+ eval->diffuse += value;
+ }
}
ccl_device_inline bool bsdf_eval_is_zero(BsdfEval *eval)
{
#ifdef __PASSES__
- if(eval->use_light_pass) {
- return is_zero(eval->diffuse)
- && is_zero(eval->glossy)
- && is_zero(eval->transmission)
- && is_zero(eval->transparent)
- && is_zero(eval->subsurface)
- && is_zero(eval->scatter);
- }
- else
-#endif
- {
- return is_zero(eval->diffuse);
- }
+ if (eval->use_light_pass) {
+ return is_zero(eval->diffuse) && is_zero(eval->glossy) && is_zero(eval->transmission) &&
+ is_zero(eval->transparent) && is_zero(eval->subsurface) && is_zero(eval->scatter);
+ }
+ else
+#endif
+ {
+ return is_zero(eval->diffuse);
+ }
}
ccl_device_inline void bsdf_eval_mis(BsdfEval *eval, float value)
{
#ifdef __PASSES__
- if(eval->use_light_pass) {
- eval->diffuse *= value;
- eval->glossy *= value;
- eval->transmission *= value;
- eval->subsurface *= value;
- eval->scatter *= value;
-
- /* skipping transparent, this function is used by for eval(), will be zero then */
- }
- else
-#endif
- {
- eval->diffuse *= value;
- }
+ if (eval->use_light_pass) {
+ eval->diffuse *= value;
+ eval->glossy *= value;
+ eval->transmission *= value;
+ eval->subsurface *= value;
+ eval->scatter *= value;
+
+ /* skipping transparent, this function is used by for eval(), will be zero then */
+ }
+ else
+#endif
+ {
+ eval->diffuse *= value;
+ }
}
ccl_device_inline void bsdf_eval_mul(BsdfEval *eval, float value)
{
#ifdef __SHADOW_TRICKS__
- eval->sum_no_mis *= value;
+ eval->sum_no_mis *= value;
#endif
- bsdf_eval_mis(eval, value);
+ bsdf_eval_mis(eval, value);
}
ccl_device_inline void bsdf_eval_mul3(BsdfEval *eval, float3 value)
{
#ifdef __SHADOW_TRICKS__
- eval->sum_no_mis *= value;
+ eval->sum_no_mis *= value;
#endif
#ifdef __PASSES__
- if(eval->use_light_pass) {
- eval->diffuse *= value;
- eval->glossy *= value;
- eval->transmission *= value;
- eval->subsurface *= value;
- eval->scatter *= value;
-
- /* skipping transparent, this function is used by for eval(), will be zero then */
- }
- else
- eval->diffuse *= value;
+ if (eval->use_light_pass) {
+ eval->diffuse *= value;
+ eval->glossy *= value;
+ eval->transmission *= value;
+ eval->subsurface *= value;
+ eval->scatter *= value;
+
+ /* skipping transparent, this function is used by for eval(), will be zero then */
+ }
+ else
+ eval->diffuse *= value;
#else
- eval->diffuse *= value;
+ eval->diffuse *= value;
#endif
}
ccl_device_inline float3 bsdf_eval_sum(const BsdfEval *eval)
{
#ifdef __PASSES__
- if(eval->use_light_pass) {
- return eval->diffuse + eval->glossy + eval->transmission + eval->subsurface + eval->scatter;
- }
- else
+ if (eval->use_light_pass) {
+ return eval->diffuse + eval->glossy + eval->transmission + eval->subsurface + eval->scatter;
+ }
+ else
#endif
- return eval->diffuse;
+ return eval->diffuse;
}
/* Path Radiance
@@ -175,115 +176,113 @@ ccl_device_inline float3 bsdf_eval_sum(const BsdfEval *eval)
ccl_device_inline void path_radiance_init(PathRadiance *L, int use_light_pass)
{
- /* clear all */
+ /* clear all */
#ifdef __PASSES__
- L->use_light_pass = use_light_pass;
-
- if(use_light_pass) {
- L->indirect = make_float3(0.0f, 0.0f, 0.0f);
- L->direct_emission = make_float3(0.0f, 0.0f, 0.0f);
-
- L->color_diffuse = make_float3(0.0f, 0.0f, 0.0f);
- L->color_glossy = make_float3(0.0f, 0.0f, 0.0f);
- L->color_transmission = make_float3(0.0f, 0.0f, 0.0f);
- L->color_subsurface = make_float3(0.0f, 0.0f, 0.0f);
-
- L->direct_diffuse = make_float3(0.0f, 0.0f, 0.0f);
- L->direct_glossy = make_float3(0.0f, 0.0f, 0.0f);
- L->direct_transmission = make_float3(0.0f, 0.0f, 0.0f);
- L->direct_subsurface = make_float3(0.0f, 0.0f, 0.0f);
- L->direct_scatter = make_float3(0.0f, 0.0f, 0.0f);
-
- L->indirect_diffuse = make_float3(0.0f, 0.0f, 0.0f);
- L->indirect_glossy = make_float3(0.0f, 0.0f, 0.0f);
- L->indirect_transmission = make_float3(0.0f, 0.0f, 0.0f);
- L->indirect_subsurface = make_float3(0.0f, 0.0f, 0.0f);
- L->indirect_scatter = make_float3(0.0f, 0.0f, 0.0f);
-
- L->transparent = 0.0f;
- L->emission = make_float3(0.0f, 0.0f, 0.0f);
- L->background = make_float3(0.0f, 0.0f, 0.0f);
- L->ao = make_float3(0.0f, 0.0f, 0.0f);
- L->shadow = make_float4(0.0f, 0.0f, 0.0f, 0.0f);
- L->mist = 0.0f;
-
- L->state.diffuse = make_float3(0.0f, 0.0f, 0.0f);
- L->state.glossy = make_float3(0.0f, 0.0f, 0.0f);
- L->state.transmission = make_float3(0.0f, 0.0f, 0.0f);
- L->state.subsurface = make_float3(0.0f, 0.0f, 0.0f);
- L->state.scatter = make_float3(0.0f, 0.0f, 0.0f);
- L->state.direct = make_float3(0.0f, 0.0f, 0.0f);
- }
- else
-#endif
- {
- L->transparent = 0.0f;
- L->emission = make_float3(0.0f, 0.0f, 0.0f);
- }
+ L->use_light_pass = use_light_pass;
+
+ if (use_light_pass) {
+ L->indirect = make_float3(0.0f, 0.0f, 0.0f);
+ L->direct_emission = make_float3(0.0f, 0.0f, 0.0f);
+
+ L->color_diffuse = make_float3(0.0f, 0.0f, 0.0f);
+ L->color_glossy = make_float3(0.0f, 0.0f, 0.0f);
+ L->color_transmission = make_float3(0.0f, 0.0f, 0.0f);
+ L->color_subsurface = make_float3(0.0f, 0.0f, 0.0f);
+
+ L->direct_diffuse = make_float3(0.0f, 0.0f, 0.0f);
+ L->direct_glossy = make_float3(0.0f, 0.0f, 0.0f);
+ L->direct_transmission = make_float3(0.0f, 0.0f, 0.0f);
+ L->direct_subsurface = make_float3(0.0f, 0.0f, 0.0f);
+ L->direct_scatter = make_float3(0.0f, 0.0f, 0.0f);
+
+ L->indirect_diffuse = make_float3(0.0f, 0.0f, 0.0f);
+ L->indirect_glossy = make_float3(0.0f, 0.0f, 0.0f);
+ L->indirect_transmission = make_float3(0.0f, 0.0f, 0.0f);
+ L->indirect_subsurface = make_float3(0.0f, 0.0f, 0.0f);
+ L->indirect_scatter = make_float3(0.0f, 0.0f, 0.0f);
+
+ L->transparent = 0.0f;
+ L->emission = make_float3(0.0f, 0.0f, 0.0f);
+ L->background = make_float3(0.0f, 0.0f, 0.0f);
+ L->ao = make_float3(0.0f, 0.0f, 0.0f);
+ L->shadow = make_float4(0.0f, 0.0f, 0.0f, 0.0f);
+ L->mist = 0.0f;
+
+ L->state.diffuse = make_float3(0.0f, 0.0f, 0.0f);
+ L->state.glossy = make_float3(0.0f, 0.0f, 0.0f);
+ L->state.transmission = make_float3(0.0f, 0.0f, 0.0f);
+ L->state.subsurface = make_float3(0.0f, 0.0f, 0.0f);
+ L->state.scatter = make_float3(0.0f, 0.0f, 0.0f);
+ L->state.direct = make_float3(0.0f, 0.0f, 0.0f);
+ }
+ else
+#endif
+ {
+ L->transparent = 0.0f;
+ L->emission = make_float3(0.0f, 0.0f, 0.0f);
+ }
#ifdef __SHADOW_TRICKS__
- L->path_total = make_float3(0.0f, 0.0f, 0.0f);
- L->path_total_shaded = make_float3(0.0f, 0.0f, 0.0f);
- L->shadow_background_color = make_float3(0.0f, 0.0f, 0.0f);
- L->shadow_throughput = 0.0f;
- L->shadow_transparency = 1.0f;
- L->has_shadow_catcher = 0;
+ L->path_total = make_float3(0.0f, 0.0f, 0.0f);
+ L->path_total_shaded = make_float3(0.0f, 0.0f, 0.0f);
+ L->shadow_background_color = make_float3(0.0f, 0.0f, 0.0f);
+ L->shadow_throughput = 0.0f;
+ L->shadow_transparency = 1.0f;
+ L->has_shadow_catcher = 0;
#endif
#ifdef __DENOISING_FEATURES__
- L->denoising_normal = make_float3(0.0f, 0.0f, 0.0f);
- L->denoising_albedo = make_float3(0.0f, 0.0f, 0.0f);
- L->denoising_depth = 0.0f;
+ L->denoising_normal = make_float3(0.0f, 0.0f, 0.0f);
+ L->denoising_albedo = make_float3(0.0f, 0.0f, 0.0f);
+ L->denoising_depth = 0.0f;
#endif
#ifdef __KERNEL_DEBUG__
- L->debug_data.num_bvh_traversed_nodes = 0;
- L->debug_data.num_bvh_traversed_instances = 0;
- L->debug_data.num_bvh_intersections = 0;
- L->debug_data.num_ray_bounces = 0;
+ L->debug_data.num_bvh_traversed_nodes = 0;
+ L->debug_data.num_bvh_traversed_instances = 0;
+ L->debug_data.num_bvh_intersections = 0;
+ L->debug_data.num_ray_bounces = 0;
#endif
}
-ccl_device_inline void path_radiance_bsdf_bounce(
- KernelGlobals *kg,
- PathRadianceState *L_state,
- ccl_addr_space float3 *throughput,
- BsdfEval *bsdf_eval,
- float bsdf_pdf, int bounce, int bsdf_label)
+ccl_device_inline void path_radiance_bsdf_bounce(KernelGlobals *kg,
+ PathRadianceState *L_state,
+ ccl_addr_space float3 *throughput,
+ BsdfEval *bsdf_eval,
+ float bsdf_pdf,
+ int bounce,
+ int bsdf_label)
{
- float inverse_pdf = 1.0f/bsdf_pdf;
+ float inverse_pdf = 1.0f / bsdf_pdf;
#ifdef __PASSES__
- if(kernel_data.film.use_light_pass) {
- if(bounce == 0 && !(bsdf_label & LABEL_TRANSPARENT)) {
- /* first on directly visible surface */
- float3 value = *throughput*inverse_pdf;
-
- L_state->diffuse = bsdf_eval->diffuse*value;
- L_state->glossy = bsdf_eval->glossy*value;
- L_state->transmission = bsdf_eval->transmission*value;
- L_state->subsurface = bsdf_eval->subsurface*value;
- L_state->scatter = bsdf_eval->scatter*value;
-
- *throughput = L_state->diffuse +
- L_state->glossy +
- L_state->transmission +
- L_state->subsurface +
- L_state->scatter;
-
- L_state->direct = *throughput;
- }
- else {
- /* transparent bounce before first hit, or indirectly visible through BSDF */
- float3 sum = (bsdf_eval_sum(bsdf_eval) + bsdf_eval->transparent) * inverse_pdf;
- *throughput *= sum;
- }
- }
- else
-#endif
- {
- *throughput *= bsdf_eval->diffuse*inverse_pdf;
- }
+ if (kernel_data.film.use_light_pass) {
+ if (bounce == 0 && !(bsdf_label & LABEL_TRANSPARENT)) {
+ /* first on directly visible surface */
+ float3 value = *throughput * inverse_pdf;
+
+ L_state->diffuse = bsdf_eval->diffuse * value;
+ L_state->glossy = bsdf_eval->glossy * value;
+ L_state->transmission = bsdf_eval->transmission * value;
+ L_state->subsurface = bsdf_eval->subsurface * value;
+ L_state->scatter = bsdf_eval->scatter * value;
+
+ *throughput = L_state->diffuse + L_state->glossy + L_state->transmission +
+ L_state->subsurface + L_state->scatter;
+
+ L_state->direct = *throughput;
+ }
+ else {
+ /* transparent bounce before first hit, or indirectly visible through BSDF */
+ float3 sum = (bsdf_eval_sum(bsdf_eval) + bsdf_eval->transparent) * inverse_pdf;
+ *throughput *= sum;
+ }
+ }
+ else
+#endif
+ {
+ *throughput *= bsdf_eval->diffuse * inverse_pdf;
+ }
}
ccl_device_inline void path_radiance_accum_emission(PathRadiance *L,
@@ -292,25 +291,25 @@ ccl_device_inline void path_radiance_accum_emission(PathRadiance *L,
float3 value)
{
#ifdef __SHADOW_TRICKS__
- if(state->flag & PATH_RAY_SHADOW_CATCHER) {
- return;
- }
+ if (state->flag & PATH_RAY_SHADOW_CATCHER) {
+ return;
+ }
#endif
#ifdef __PASSES__
- if(L->use_light_pass) {
- if(state->bounce == 0)
- L->emission += throughput*value;
- else if(state->bounce == 1)
- L->direct_emission += throughput*value;
- else
- L->indirect += throughput*value;
- }
- else
-#endif
- {
- L->emission += throughput*value;
- }
+ if (L->use_light_pass) {
+ if (state->bounce == 0)
+ L->emission += throughput * value;
+ else if (state->bounce == 1)
+ L->direct_emission += throughput * value;
+ else
+ L->indirect += throughput * value;
+ }
+ else
+#endif
+ {
+ L->emission += throughput * value;
+ }
}
ccl_device_inline void path_radiance_accum_ao(PathRadiance *L,
@@ -320,57 +319,56 @@ ccl_device_inline void path_radiance_accum_ao(PathRadiance *L,
float3 bsdf,
float3 ao)
{
- /* Store AO pass. */
- if(L->use_light_pass && state->bounce == 0) {
- L->ao += alpha*throughput*ao;
- }
+ /* Store AO pass. */
+ if (L->use_light_pass && state->bounce == 0) {
+ L->ao += alpha * throughput * ao;
+ }
#ifdef __SHADOW_TRICKS__
- /* For shadow catcher, accumulate ratio. */
- if(state->flag & PATH_RAY_STORE_SHADOW_INFO) {
- float3 light = throughput * bsdf;
- L->path_total += light;
- L->path_total_shaded += ao * light;
+ /* For shadow catcher, accumulate ratio. */
+ if (state->flag & PATH_RAY_STORE_SHADOW_INFO) {
+ float3 light = throughput * bsdf;
+ L->path_total += light;
+ L->path_total_shaded += ao * light;
- if(state->flag & PATH_RAY_SHADOW_CATCHER) {
- return;
- }
- }
+ if (state->flag & PATH_RAY_SHADOW_CATCHER) {
+ return;
+ }
+ }
#endif
#ifdef __PASSES__
- if(L->use_light_pass) {
- if(state->bounce == 0) {
- /* Directly visible lighting. */
- L->direct_diffuse += throughput*bsdf*ao;
- }
- else {
- /* Indirectly visible lighting after BSDF bounce. */
- L->indirect += throughput*bsdf*ao;
- }
- }
- else
-#endif
- {
- L->emission += throughput*bsdf*ao;
- }
+ if (L->use_light_pass) {
+ if (state->bounce == 0) {
+ /* Directly visible lighting. */
+ L->direct_diffuse += throughput * bsdf * ao;
+ }
+ else {
+ /* Indirectly visible lighting after BSDF bounce. */
+ L->indirect += throughput * bsdf * ao;
+ }
+ }
+ else
+#endif
+ {
+ L->emission += throughput * bsdf * ao;
+ }
}
-ccl_device_inline void path_radiance_accum_total_ao(
- PathRadiance *L,
- ccl_addr_space PathState *state,
- float3 throughput,
- float3 bsdf)
+ccl_device_inline void path_radiance_accum_total_ao(PathRadiance *L,
+ ccl_addr_space PathState *state,
+ float3 throughput,
+ float3 bsdf)
{
#ifdef __SHADOW_TRICKS__
- if(state->flag & PATH_RAY_STORE_SHADOW_INFO) {
- L->path_total += throughput * bsdf;
- }
+ if (state->flag & PATH_RAY_STORE_SHADOW_INFO) {
+ L->path_total += throughput * bsdf;
+ }
#else
- (void) L;
- (void) state;
- (void) throughput;
- (void) bsdf;
+ (void)L;
+ (void)state;
+ (void)throughput;
+ (void)bsdf;
#endif
}
@@ -383,171 +381,166 @@ ccl_device_inline void path_radiance_accum_light(PathRadiance *L,
bool is_lamp)
{
#ifdef __SHADOW_TRICKS__
- if(state->flag & PATH_RAY_STORE_SHADOW_INFO) {
- float3 light = throughput * bsdf_eval->sum_no_mis;
- L->path_total += light;
- L->path_total_shaded += shadow * light;
+ if (state->flag & PATH_RAY_STORE_SHADOW_INFO) {
+ float3 light = throughput * bsdf_eval->sum_no_mis;
+ L->path_total += light;
+ L->path_total_shaded += shadow * light;
- if(state->flag & PATH_RAY_SHADOW_CATCHER) {
- return;
- }
- }
+ if (state->flag & PATH_RAY_SHADOW_CATCHER) {
+ return;
+ }
+ }
#endif
#ifdef __PASSES__
- if(L->use_light_pass) {
- if(state->bounce == 0) {
- /* directly visible lighting */
- L->direct_diffuse += throughput*bsdf_eval->diffuse*shadow;
- L->direct_glossy += throughput*bsdf_eval->glossy*shadow;
- L->direct_transmission += throughput*bsdf_eval->transmission*shadow;
- L->direct_subsurface += throughput*bsdf_eval->subsurface*shadow;
- L->direct_scatter += throughput*bsdf_eval->scatter*shadow;
-
- if(is_lamp) {
- L->shadow.x += shadow.x*shadow_fac;
- L->shadow.y += shadow.y*shadow_fac;
- L->shadow.z += shadow.z*shadow_fac;
- }
- }
- else {
- /* indirectly visible lighting after BSDF bounce */
- L->indirect += throughput*bsdf_eval_sum(bsdf_eval)*shadow;
- }
- }
- else
-#endif
- {
- L->emission += throughput*bsdf_eval->diffuse*shadow;
- }
+ if (L->use_light_pass) {
+ if (state->bounce == 0) {
+ /* directly visible lighting */
+ L->direct_diffuse += throughput * bsdf_eval->diffuse * shadow;
+ L->direct_glossy += throughput * bsdf_eval->glossy * shadow;
+ L->direct_transmission += throughput * bsdf_eval->transmission * shadow;
+ L->direct_subsurface += throughput * bsdf_eval->subsurface * shadow;
+ L->direct_scatter += throughput * bsdf_eval->scatter * shadow;
+
+ if (is_lamp) {
+ L->shadow.x += shadow.x * shadow_fac;
+ L->shadow.y += shadow.y * shadow_fac;
+ L->shadow.z += shadow.z * shadow_fac;
+ }
+ }
+ else {
+ /* indirectly visible lighting after BSDF bounce */
+ L->indirect += throughput * bsdf_eval_sum(bsdf_eval) * shadow;
+ }
+ }
+ else
+#endif
+ {
+ L->emission += throughput * bsdf_eval->diffuse * shadow;
+ }
}
-ccl_device_inline void path_radiance_accum_total_light(
- PathRadiance *L,
- ccl_addr_space PathState *state,
- float3 throughput,
- const BsdfEval *bsdf_eval)
+ccl_device_inline void path_radiance_accum_total_light(PathRadiance *L,
+ ccl_addr_space PathState *state,
+ float3 throughput,
+ const BsdfEval *bsdf_eval)
{
#ifdef __SHADOW_TRICKS__
- if(state->flag & PATH_RAY_STORE_SHADOW_INFO) {
- L->path_total += throughput * bsdf_eval->sum_no_mis;
- }
+ if (state->flag & PATH_RAY_STORE_SHADOW_INFO) {
+ L->path_total += throughput * bsdf_eval->sum_no_mis;
+ }
#else
- (void) L;
- (void) state;
- (void) throughput;
- (void) bsdf_eval;
+ (void)L;
+ (void)state;
+ (void)throughput;
+ (void)bsdf_eval;
#endif
}
-ccl_device_inline void path_radiance_accum_background(
- PathRadiance *L,
- ccl_addr_space PathState *state,
- float3 throughput,
- float3 value)
+ccl_device_inline void path_radiance_accum_background(PathRadiance *L,
+ ccl_addr_space PathState *state,
+ float3 throughput,
+ float3 value)
{
#ifdef __SHADOW_TRICKS__
- if(state->flag & PATH_RAY_STORE_SHADOW_INFO) {
- L->path_total += throughput * value;
- L->path_total_shaded += throughput * value * L->shadow_transparency;
+ if (state->flag & PATH_RAY_STORE_SHADOW_INFO) {
+ L->path_total += throughput * value;
+ L->path_total_shaded += throughput * value * L->shadow_transparency;
- if(state->flag & PATH_RAY_SHADOW_CATCHER) {
- return;
- }
- }
+ if (state->flag & PATH_RAY_SHADOW_CATCHER) {
+ return;
+ }
+ }
#endif
#ifdef __PASSES__
- if(L->use_light_pass) {
- if(state->flag & PATH_RAY_TRANSPARENT_BACKGROUND)
- L->background += throughput*value;
- else if(state->bounce == 1)
- L->direct_emission += throughput*value;
- else
- L->indirect += throughput*value;
- }
- else
-#endif
- {
- L->emission += throughput*value;
- }
+ if (L->use_light_pass) {
+ if (state->flag & PATH_RAY_TRANSPARENT_BACKGROUND)
+ L->background += throughput * value;
+ else if (state->bounce == 1)
+ L->direct_emission += throughput * value;
+ else
+ L->indirect += throughput * value;
+ }
+ else
+#endif
+ {
+ L->emission += throughput * value;
+ }
#ifdef __DENOISING_FEATURES__
- L->denoising_albedo += state->denoising_feature_weight * value;
-#endif /* __DENOISING_FEATURES__ */
+ L->denoising_albedo += state->denoising_feature_weight * value;
+#endif /* __DENOISING_FEATURES__ */
}
-ccl_device_inline void path_radiance_accum_transparent(
- PathRadiance *L,
- ccl_addr_space PathState *state,
- float3 throughput)
+ccl_device_inline void path_radiance_accum_transparent(PathRadiance *L,
+ ccl_addr_space PathState *state,
+ float3 throughput)
{
- L->transparent += average(throughput);
+ L->transparent += average(throughput);
}
#ifdef __SHADOW_TRICKS__
-ccl_device_inline void path_radiance_accum_shadowcatcher(
- PathRadiance *L,
- float3 throughput,
- float3 background)
+ccl_device_inline void path_radiance_accum_shadowcatcher(PathRadiance *L,
+ float3 throughput,
+ float3 background)
{
- L->shadow_throughput += average(throughput);
- L->shadow_background_color += throughput * background;
- L->has_shadow_catcher = 1;
+ L->shadow_throughput += average(throughput);
+ L->shadow_background_color += throughput * background;
+ L->has_shadow_catcher = 1;
}
#endif
ccl_device_inline void path_radiance_sum_indirect(PathRadiance *L)
{
#ifdef __PASSES__
- /* this division is a bit ugly, but means we only have to keep track of
- * only a single throughput further along the path, here we recover just
- * the indirect path that is not influenced by any particular BSDF type */
- if(L->use_light_pass) {
- L->direct_emission = safe_divide_color(L->direct_emission, L->state.direct);
- L->direct_diffuse += L->state.diffuse*L->direct_emission;
- L->direct_glossy += L->state.glossy*L->direct_emission;
- L->direct_transmission += L->state.transmission*L->direct_emission;
- L->direct_subsurface += L->state.subsurface*L->direct_emission;
- L->direct_scatter += L->state.scatter*L->direct_emission;
-
- L->indirect = safe_divide_color(L->indirect, L->state.direct);
- L->indirect_diffuse += L->state.diffuse*L->indirect;
- L->indirect_glossy += L->state.glossy*L->indirect;
- L->indirect_transmission += L->state.transmission*L->indirect;
- L->indirect_subsurface += L->state.subsurface*L->indirect;
- L->indirect_scatter += L->state.scatter*L->indirect;
- }
+ /* this division is a bit ugly, but means we only have to keep track of
+ * only a single throughput further along the path, here we recover just
+ * the indirect path that is not influenced by any particular BSDF type */
+ if (L->use_light_pass) {
+ L->direct_emission = safe_divide_color(L->direct_emission, L->state.direct);
+ L->direct_diffuse += L->state.diffuse * L->direct_emission;
+ L->direct_glossy += L->state.glossy * L->direct_emission;
+ L->direct_transmission += L->state.transmission * L->direct_emission;
+ L->direct_subsurface += L->state.subsurface * L->direct_emission;
+ L->direct_scatter += L->state.scatter * L->direct_emission;
+
+ L->indirect = safe_divide_color(L->indirect, L->state.direct);
+ L->indirect_diffuse += L->state.diffuse * L->indirect;
+ L->indirect_glossy += L->state.glossy * L->indirect;
+ L->indirect_transmission += L->state.transmission * L->indirect;
+ L->indirect_subsurface += L->state.subsurface * L->indirect;
+ L->indirect_scatter += L->state.scatter * L->indirect;
+ }
#endif
}
ccl_device_inline void path_radiance_reset_indirect(PathRadiance *L)
{
#ifdef __PASSES__
- if(L->use_light_pass) {
- L->state.diffuse = make_float3(0.0f, 0.0f, 0.0f);
- L->state.glossy = make_float3(0.0f, 0.0f, 0.0f);
- L->state.transmission = make_float3(0.0f, 0.0f, 0.0f);
- L->state.subsurface = make_float3(0.0f, 0.0f, 0.0f);
- L->state.scatter = make_float3(0.0f, 0.0f, 0.0f);
+ if (L->use_light_pass) {
+ L->state.diffuse = make_float3(0.0f, 0.0f, 0.0f);
+ L->state.glossy = make_float3(0.0f, 0.0f, 0.0f);
+ L->state.transmission = make_float3(0.0f, 0.0f, 0.0f);
+ L->state.subsurface = make_float3(0.0f, 0.0f, 0.0f);
+ L->state.scatter = make_float3(0.0f, 0.0f, 0.0f);
- L->direct_emission = make_float3(0.0f, 0.0f, 0.0f);
- L->indirect = make_float3(0.0f, 0.0f, 0.0f);
- }
+ L->direct_emission = make_float3(0.0f, 0.0f, 0.0f);
+ L->indirect = make_float3(0.0f, 0.0f, 0.0f);
+ }
#endif
}
-ccl_device_inline void path_radiance_copy_indirect(PathRadiance *L,
- const PathRadiance *L_src)
+ccl_device_inline void path_radiance_copy_indirect(PathRadiance *L, const PathRadiance *L_src)
{
#ifdef __PASSES__
- if(L->use_light_pass) {
- L->state = L_src->state;
+ if (L->use_light_pass) {
+ L->state = L_src->state;
- L->direct_emission = L_src->direct_emission;
- L->indirect = L_src->indirect;
- }
+ L->direct_emission = L_src->direct_emission;
+ L->indirect = L_src->indirect;
+ }
#endif
}
@@ -557,213 +550,219 @@ ccl_device_inline void path_radiance_sum_shadowcatcher(KernelGlobals *kg,
float3 *L_sum,
float *alpha)
{
- /* Calculate current shadow of the path. */
- float path_total = average(L->path_total);
- float shadow;
-
- if(UNLIKELY(!isfinite_safe(path_total))) {
- kernel_assert(!"Non-finite total radiance along the path");
- shadow = 0.0f;
- }
- else if(path_total == 0.0f) {
- shadow = L->shadow_transparency;
- }
- else {
- float path_total_shaded = average(L->path_total_shaded);
- shadow = path_total_shaded / path_total;
- }
-
- /* Calculate final light sum and transparency for shadow catcher object. */
- if(kernel_data.background.transparent) {
- *alpha -= L->shadow_throughput * shadow;
- }
- else {
- L->shadow_background_color *= shadow;
- *L_sum += L->shadow_background_color;
- }
+ /* Calculate current shadow of the path. */
+ float path_total = average(L->path_total);
+ float shadow;
+
+ if (UNLIKELY(!isfinite_safe(path_total))) {
+ kernel_assert(!"Non-finite total radiance along the path");
+ shadow = 0.0f;
+ }
+ else if (path_total == 0.0f) {
+ shadow = L->shadow_transparency;
+ }
+ else {
+ float path_total_shaded = average(L->path_total_shaded);
+ shadow = path_total_shaded / path_total;
+ }
+
+ /* Calculate final light sum and transparency for shadow catcher object. */
+ if (kernel_data.background.transparent) {
+ *alpha -= L->shadow_throughput * shadow;
+ }
+ else {
+ L->shadow_background_color *= shadow;
+ *L_sum += L->shadow_background_color;
+ }
}
#endif
-ccl_device_inline float3 path_radiance_clamp_and_sum(KernelGlobals *kg, PathRadiance *L, float *alpha)
+ccl_device_inline float3 path_radiance_clamp_and_sum(KernelGlobals *kg,
+ PathRadiance *L,
+ float *alpha)
{
- float3 L_sum;
- /* Light Passes are used */
+ float3 L_sum;
+ /* Light Passes are used */
#ifdef __PASSES__
- float3 L_direct, L_indirect;
- float clamp_direct = kernel_data.integrator.sample_clamp_direct;
- float clamp_indirect = kernel_data.integrator.sample_clamp_indirect;
- if(L->use_light_pass) {
- path_radiance_sum_indirect(L);
-
- L_direct = L->direct_diffuse + L->direct_glossy + L->direct_transmission + L->direct_subsurface + L->direct_scatter + L->emission;
- L_indirect = L->indirect_diffuse + L->indirect_glossy + L->indirect_transmission + L->indirect_subsurface + L->indirect_scatter;
-
- if(!kernel_data.background.transparent)
- L_direct += L->background;
-
- L_sum = L_direct + L_indirect;
- float sum = fabsf((L_sum).x) + fabsf((L_sum).y) + fabsf((L_sum).z);
-
- /* Reject invalid value */
- if(!isfinite_safe(sum)) {
- kernel_assert(!"Non-finite sum in path_radiance_clamp_and_sum!");
- L_sum = make_float3(0.0f, 0.0f, 0.0f);
-
- L->direct_diffuse = make_float3(0.0f, 0.0f, 0.0f);
- L->direct_glossy = make_float3(0.0f, 0.0f, 0.0f);
- L->direct_transmission = make_float3(0.0f, 0.0f, 0.0f);
- L->direct_subsurface = make_float3(0.0f, 0.0f, 0.0f);
- L->direct_scatter = make_float3(0.0f, 0.0f, 0.0f);
-
- L->indirect_diffuse = make_float3(0.0f, 0.0f, 0.0f);
- L->indirect_glossy = make_float3(0.0f, 0.0f, 0.0f);
- L->indirect_transmission = make_float3(0.0f, 0.0f, 0.0f);
- L->indirect_subsurface = make_float3(0.0f, 0.0f, 0.0f);
- L->indirect_scatter = make_float3(0.0f, 0.0f, 0.0f);
-
- L->emission = make_float3(0.0f, 0.0f, 0.0f);
- }
-
- /* Clamp direct and indirect samples */
-#ifdef __CLAMP_SAMPLE__
- else if(sum > clamp_direct || sum > clamp_indirect) {
- float scale;
-
- /* Direct */
- float sum_direct = fabsf(L_direct.x) + fabsf(L_direct.y) + fabsf(L_direct.z);
- if(sum_direct > clamp_direct) {
- scale = clamp_direct/sum_direct;
- L_direct *= scale;
-
- L->direct_diffuse *= scale;
- L->direct_glossy *= scale;
- L->direct_transmission *= scale;
- L->direct_subsurface *= scale;
- L->direct_scatter *= scale;
- L->emission *= scale;
- L->background *= scale;
- }
-
- /* Indirect */
- float sum_indirect = fabsf(L_indirect.x) + fabsf(L_indirect.y) + fabsf(L_indirect.z);
- if(sum_indirect > clamp_indirect) {
- scale = clamp_indirect/sum_indirect;
- L_indirect *= scale;
-
- L->indirect_diffuse *= scale;
- L->indirect_glossy *= scale;
- L->indirect_transmission *= scale;
- L->indirect_subsurface *= scale;
- L->indirect_scatter *= scale;
- }
-
- /* Sum again, after clamping */
- L_sum = L_direct + L_indirect;
- }
-#endif
- }
-
- /* No Light Passes */
- else
-#endif
- {
- L_sum = L->emission;
-
- /* Reject invalid value */
- float sum = fabsf((L_sum).x) + fabsf((L_sum).y) + fabsf((L_sum).z);
- if(!isfinite_safe(sum)) {
- kernel_assert(!"Non-finite final sum in path_radiance_clamp_and_sum!");
- L_sum = make_float3(0.0f, 0.0f, 0.0f);
- }
- }
-
- /* Compute alpha. */
- *alpha = 1.0f - L->transparent;
-
- /* Add shadow catcher contributions. */
+ float3 L_direct, L_indirect;
+ float clamp_direct = kernel_data.integrator.sample_clamp_direct;
+ float clamp_indirect = kernel_data.integrator.sample_clamp_indirect;
+ if (L->use_light_pass) {
+ path_radiance_sum_indirect(L);
+
+ L_direct = L->direct_diffuse + L->direct_glossy + L->direct_transmission +
+ L->direct_subsurface + L->direct_scatter + L->emission;
+ L_indirect = L->indirect_diffuse + L->indirect_glossy + L->indirect_transmission +
+ L->indirect_subsurface + L->indirect_scatter;
+
+ if (!kernel_data.background.transparent)
+ L_direct += L->background;
+
+ L_sum = L_direct + L_indirect;
+ float sum = fabsf((L_sum).x) + fabsf((L_sum).y) + fabsf((L_sum).z);
+
+ /* Reject invalid value */
+ if (!isfinite_safe(sum)) {
+ kernel_assert(!"Non-finite sum in path_radiance_clamp_and_sum!");
+ L_sum = make_float3(0.0f, 0.0f, 0.0f);
+
+ L->direct_diffuse = make_float3(0.0f, 0.0f, 0.0f);
+ L->direct_glossy = make_float3(0.0f, 0.0f, 0.0f);
+ L->direct_transmission = make_float3(0.0f, 0.0f, 0.0f);
+ L->direct_subsurface = make_float3(0.0f, 0.0f, 0.0f);
+ L->direct_scatter = make_float3(0.0f, 0.0f, 0.0f);
+
+ L->indirect_diffuse = make_float3(0.0f, 0.0f, 0.0f);
+ L->indirect_glossy = make_float3(0.0f, 0.0f, 0.0f);
+ L->indirect_transmission = make_float3(0.0f, 0.0f, 0.0f);
+ L->indirect_subsurface = make_float3(0.0f, 0.0f, 0.0f);
+ L->indirect_scatter = make_float3(0.0f, 0.0f, 0.0f);
+
+ L->emission = make_float3(0.0f, 0.0f, 0.0f);
+ }
+
+ /* Clamp direct and indirect samples */
+# ifdef __CLAMP_SAMPLE__
+ else if (sum > clamp_direct || sum > clamp_indirect) {
+ float scale;
+
+ /* Direct */
+ float sum_direct = fabsf(L_direct.x) + fabsf(L_direct.y) + fabsf(L_direct.z);
+ if (sum_direct > clamp_direct) {
+ scale = clamp_direct / sum_direct;
+ L_direct *= scale;
+
+ L->direct_diffuse *= scale;
+ L->direct_glossy *= scale;
+ L->direct_transmission *= scale;
+ L->direct_subsurface *= scale;
+ L->direct_scatter *= scale;
+ L->emission *= scale;
+ L->background *= scale;
+ }
+
+ /* Indirect */
+ float sum_indirect = fabsf(L_indirect.x) + fabsf(L_indirect.y) + fabsf(L_indirect.z);
+ if (sum_indirect > clamp_indirect) {
+ scale = clamp_indirect / sum_indirect;
+ L_indirect *= scale;
+
+ L->indirect_diffuse *= scale;
+ L->indirect_glossy *= scale;
+ L->indirect_transmission *= scale;
+ L->indirect_subsurface *= scale;
+ L->indirect_scatter *= scale;
+ }
+
+ /* Sum again, after clamping */
+ L_sum = L_direct + L_indirect;
+ }
+# endif
+ }
+
+ /* No Light Passes */
+ else
+#endif
+ {
+ L_sum = L->emission;
+
+ /* Reject invalid value */
+ float sum = fabsf((L_sum).x) + fabsf((L_sum).y) + fabsf((L_sum).z);
+ if (!isfinite_safe(sum)) {
+ kernel_assert(!"Non-finite final sum in path_radiance_clamp_and_sum!");
+ L_sum = make_float3(0.0f, 0.0f, 0.0f);
+ }
+ }
+
+ /* Compute alpha. */
+ *alpha = 1.0f - L->transparent;
+
+ /* Add shadow catcher contributions. */
#ifdef __SHADOW_TRICKS__
- if(L->has_shadow_catcher) {
- path_radiance_sum_shadowcatcher(kg, L, &L_sum, alpha);
- }
-#endif /* __SHADOW_TRICKS__ */
+ if (L->has_shadow_catcher) {
+ path_radiance_sum_shadowcatcher(kg, L, &L_sum, alpha);
+ }
+#endif /* __SHADOW_TRICKS__ */
- return L_sum;
+ return L_sum;
}
-ccl_device_inline void path_radiance_split_denoising(KernelGlobals *kg, PathRadiance *L, float3 *noisy, float3 *clean)
+ccl_device_inline void path_radiance_split_denoising(KernelGlobals *kg,
+ PathRadiance *L,
+ float3 *noisy,
+ float3 *clean)
{
#ifdef __PASSES__
- kernel_assert(L->use_light_pass);
-
- *clean = L->emission + L->background;
- *noisy = L->direct_scatter + L->indirect_scatter;
-
-# define ADD_COMPONENT(flag, component) \
- if(kernel_data.film.denoising_flags & flag) \
- *clean += component; \
- else \
- *noisy += component;
-
- ADD_COMPONENT(DENOISING_CLEAN_DIFFUSE_DIR, L->direct_diffuse);
- ADD_COMPONENT(DENOISING_CLEAN_DIFFUSE_IND, L->indirect_diffuse);
- ADD_COMPONENT(DENOISING_CLEAN_GLOSSY_DIR, L->direct_glossy);
- ADD_COMPONENT(DENOISING_CLEAN_GLOSSY_IND, L->indirect_glossy);
- ADD_COMPONENT(DENOISING_CLEAN_TRANSMISSION_DIR, L->direct_transmission);
- ADD_COMPONENT(DENOISING_CLEAN_TRANSMISSION_IND, L->indirect_transmission);
- ADD_COMPONENT(DENOISING_CLEAN_SUBSURFACE_DIR, L->direct_subsurface);
- ADD_COMPONENT(DENOISING_CLEAN_SUBSURFACE_IND, L->indirect_subsurface);
+ kernel_assert(L->use_light_pass);
+
+ *clean = L->emission + L->background;
+ *noisy = L->direct_scatter + L->indirect_scatter;
+
+# define ADD_COMPONENT(flag, component) \
+ if (kernel_data.film.denoising_flags & flag) \
+ *clean += component; \
+ else \
+ *noisy += component;
+
+ ADD_COMPONENT(DENOISING_CLEAN_DIFFUSE_DIR, L->direct_diffuse);
+ ADD_COMPONENT(DENOISING_CLEAN_DIFFUSE_IND, L->indirect_diffuse);
+ ADD_COMPONENT(DENOISING_CLEAN_GLOSSY_DIR, L->direct_glossy);
+ ADD_COMPONENT(DENOISING_CLEAN_GLOSSY_IND, L->indirect_glossy);
+ ADD_COMPONENT(DENOISING_CLEAN_TRANSMISSION_DIR, L->direct_transmission);
+ ADD_COMPONENT(DENOISING_CLEAN_TRANSMISSION_IND, L->indirect_transmission);
+ ADD_COMPONENT(DENOISING_CLEAN_SUBSURFACE_DIR, L->direct_subsurface);
+ ADD_COMPONENT(DENOISING_CLEAN_SUBSURFACE_IND, L->indirect_subsurface);
# undef ADD_COMPONENT
#else
- *noisy = L->emission;
- *clean = make_float3(0.0f, 0.0f, 0.0f);
+ *noisy = L->emission;
+ *clean = make_float3(0.0f, 0.0f, 0.0f);
#endif
#ifdef __SHADOW_TRICKS__
- if(L->has_shadow_catcher) {
- *noisy += L->shadow_background_color;
- }
+ if (L->has_shadow_catcher) {
+ *noisy += L->shadow_background_color;
+ }
#endif
- *noisy = ensure_finite3(*noisy);
- *clean = ensure_finite3(*clean);
+ *noisy = ensure_finite3(*noisy);
+ *clean = ensure_finite3(*clean);
}
ccl_device_inline void path_radiance_accum_sample(PathRadiance *L, PathRadiance *L_sample)
{
#ifdef __SPLIT_KERNEL__
# define safe_float3_add(f, v) \
- do { \
- ccl_global float *p = (ccl_global float*)(&(f)); \
- atomic_add_and_fetch_float(p+0, (v).x); \
- atomic_add_and_fetch_float(p+1, (v).y); \
- atomic_add_and_fetch_float(p+2, (v).z); \
- } while(0)
-# define safe_float_add(f, v) \
- atomic_add_and_fetch_float(&(f), (v))
+ do { \
+ ccl_global float *p = (ccl_global float *)(&(f)); \
+ atomic_add_and_fetch_float(p + 0, (v).x); \
+ atomic_add_and_fetch_float(p + 1, (v).y); \
+ atomic_add_and_fetch_float(p + 2, (v).z); \
+ } while (0)
+# define safe_float_add(f, v) atomic_add_and_fetch_float(&(f), (v))
#else
# define safe_float3_add(f, v) (f) += (v)
# define safe_float_add(f, v) (f) += (v)
-#endif /* __SPLIT_KERNEL__ */
+#endif /* __SPLIT_KERNEL__ */
#ifdef __PASSES__
- safe_float3_add(L->direct_diffuse, L_sample->direct_diffuse);
- safe_float3_add(L->direct_glossy, L_sample->direct_glossy);
- safe_float3_add(L->direct_transmission, L_sample->direct_transmission);
- safe_float3_add(L->direct_subsurface, L_sample->direct_subsurface);
- safe_float3_add(L->direct_scatter, L_sample->direct_scatter);
-
- safe_float3_add(L->indirect_diffuse, L_sample->indirect_diffuse);
- safe_float3_add(L->indirect_glossy, L_sample->indirect_glossy);
- safe_float3_add(L->indirect_transmission, L_sample->indirect_transmission);
- safe_float3_add(L->indirect_subsurface, L_sample->indirect_subsurface);
- safe_float3_add(L->indirect_scatter, L_sample->indirect_scatter);
-
- safe_float3_add(L->background, L_sample->background);
- safe_float3_add(L->ao, L_sample->ao);
- safe_float3_add(L->shadow, L_sample->shadow);
- safe_float_add(L->mist, L_sample->mist);
-#endif /* __PASSES__ */
- safe_float3_add(L->emission, L_sample->emission);
+ safe_float3_add(L->direct_diffuse, L_sample->direct_diffuse);
+ safe_float3_add(L->direct_glossy, L_sample->direct_glossy);
+ safe_float3_add(L->direct_transmission, L_sample->direct_transmission);
+ safe_float3_add(L->direct_subsurface, L_sample->direct_subsurface);
+ safe_float3_add(L->direct_scatter, L_sample->direct_scatter);
+
+ safe_float3_add(L->indirect_diffuse, L_sample->indirect_diffuse);
+ safe_float3_add(L->indirect_glossy, L_sample->indirect_glossy);
+ safe_float3_add(L->indirect_transmission, L_sample->indirect_transmission);
+ safe_float3_add(L->indirect_subsurface, L_sample->indirect_subsurface);
+ safe_float3_add(L->indirect_scatter, L_sample->indirect_scatter);
+
+ safe_float3_add(L->background, L_sample->background);
+ safe_float3_add(L->ao, L_sample->ao);
+ safe_float3_add(L->shadow, L_sample->shadow);
+ safe_float_add(L->mist, L_sample->mist);
+#endif /* __PASSES__ */
+ safe_float3_add(L->emission, L_sample->emission);
#undef safe_float_add
#undef safe_float3_add
diff --git a/intern/cycles/kernel/kernel_bake.h b/intern/cycles/kernel/kernel_bake.h
index 37c163f2538..10b71bc6bdf 100644
--- a/intern/cycles/kernel/kernel_bake.h
+++ b/intern/cycles/kernel/kernel_bake.h
@@ -18,191 +18,172 @@ CCL_NAMESPACE_BEGIN
#ifdef __BAKING__
-ccl_device_inline void compute_light_pass(KernelGlobals *kg,
- ShaderData *sd,
- PathRadiance *L,
- uint rng_hash,
- int pass_filter,
- int sample)
+ccl_device_inline void compute_light_pass(
+ KernelGlobals *kg, ShaderData *sd, PathRadiance *L, uint rng_hash, int pass_filter, int sample)
{
- kernel_assert(kernel_data.film.use_light_pass);
-
- PathRadiance L_sample;
- PathState state;
- Ray ray;
- float3 throughput = make_float3(1.0f, 1.0f, 1.0f);
-
- /* emission and indirect shader data memory used by various functions */
- ShaderData emission_sd, indirect_sd;
-
- ray.P = sd->P + sd->Ng;
- ray.D = -sd->Ng;
- ray.t = FLT_MAX;
-#ifdef __CAMERA_MOTION__
- ray.time = 0.5f;
-#endif
-
- /* init radiance */
- path_radiance_init(&L_sample, kernel_data.film.use_light_pass);
-
- /* init path state */
- path_state_init(kg, &emission_sd, &state, rng_hash, sample, NULL);
-
- /* evaluate surface shader */
- shader_eval_surface(kg, sd, &state, state.flag);
-
- /* TODO, disable more closures we don't need besides transparent */
- shader_bsdf_disable_transparency(kg, sd);
-
-#ifdef __BRANCHED_PATH__
- if(!kernel_data.integrator.branched) {
- /* regular path tracer */
-#endif
-
- /* sample ambient occlusion */
- if(pass_filter & BAKE_FILTER_AO) {
- kernel_path_ao(kg, sd, &emission_sd, &L_sample, &state, throughput, shader_bsdf_alpha(kg, sd));
- }
-
- /* sample emission */
- if((pass_filter & BAKE_FILTER_EMISSION) && (sd->flag & SD_EMISSION)) {
- float3 emission = indirect_primitive_emission(kg, sd, 0.0f, state.flag, state.ray_pdf);
- path_radiance_accum_emission(&L_sample, &state, throughput, emission);
- }
-
- bool is_sss_sample = false;
-
-#ifdef __SUBSURFACE__
- /* sample subsurface scattering */
- if((pass_filter & BAKE_FILTER_SUBSURFACE) && (sd->flag & SD_BSSRDF)) {
- /* when mixing BSSRDF and BSDF closures we should skip BSDF lighting if scattering was successful */
- SubsurfaceIndirectRays ss_indirect;
- kernel_path_subsurface_init_indirect(&ss_indirect);
- if(kernel_path_subsurface_scatter(kg,
- sd,
- &emission_sd,
- &L_sample,
- &state,
- &ray,
- &throughput,
- &ss_indirect))
- {
- while(ss_indirect.num_rays) {
- kernel_path_subsurface_setup_indirect(kg,
- &ss_indirect,
- &state,
- &ray,
- &L_sample,
- &throughput);
- kernel_path_indirect(kg,
- &indirect_sd,
- &emission_sd,
- &ray,
- throughput,
- &state,
- &L_sample);
- }
- is_sss_sample = true;
- }
- }
-#endif
-
- /* sample light and BSDF */
- if(!is_sss_sample && (pass_filter & (BAKE_FILTER_DIRECT | BAKE_FILTER_INDIRECT))) {
- kernel_path_surface_connect_light(kg, sd, &emission_sd, throughput, &state, &L_sample);
-
- if(kernel_path_surface_bounce(kg, sd, &throughput, &state, &L_sample.state, &ray)) {
-#ifdef __LAMP_MIS__
- state.ray_t = 0.0f;
-#endif
- /* compute indirect light */
- kernel_path_indirect(kg, &indirect_sd, &emission_sd, &ray, throughput, &state, &L_sample);
-
- /* sum and reset indirect light pass variables for the next samples */
- path_radiance_sum_indirect(&L_sample);
- path_radiance_reset_indirect(&L_sample);
- }
- }
-#ifdef __BRANCHED_PATH__
- }
- else {
- /* branched path tracer */
-
- /* sample ambient occlusion */
- if(pass_filter & BAKE_FILTER_AO) {
- kernel_branched_path_ao(kg, sd, &emission_sd, &L_sample, &state, throughput);
- }
-
- /* sample emission */
- if((pass_filter & BAKE_FILTER_EMISSION) && (sd->flag & SD_EMISSION)) {
- float3 emission = indirect_primitive_emission(kg, sd, 0.0f, state.flag, state.ray_pdf);
- path_radiance_accum_emission(&L_sample, &state, throughput, emission);
- }
-
-#ifdef __SUBSURFACE__
- /* sample subsurface scattering */
- if((pass_filter & BAKE_FILTER_SUBSURFACE) && (sd->flag & SD_BSSRDF)) {
- /* when mixing BSSRDF and BSDF closures we should skip BSDF lighting if scattering was successful */
- kernel_branched_path_subsurface_scatter(kg, sd, &indirect_sd,
- &emission_sd, &L_sample, &state, &ray, throughput);
- }
-#endif
-
- /* sample light and BSDF */
- if(pass_filter & (BAKE_FILTER_DIRECT | BAKE_FILTER_INDIRECT)) {
-#if defined(__EMISSION__)
- /* direct light */
- if(kernel_data.integrator.use_direct_light) {
- int all = kernel_data.integrator.sample_all_lights_direct;
- kernel_branched_path_surface_connect_light(kg,
- sd, &emission_sd, &state, throughput, 1.0f, &L_sample, all);
- }
-#endif
-
- /* indirect light */
- kernel_branched_path_surface_indirect_light(kg,
- sd, &indirect_sd, &emission_sd, throughput, 1.0f, &state, &L_sample);
- }
- }
-#endif
-
- /* accumulate into master L */
- path_radiance_accum_sample(L, &L_sample);
+ kernel_assert(kernel_data.film.use_light_pass);
+
+ PathRadiance L_sample;
+ PathState state;
+ Ray ray;
+ float3 throughput = make_float3(1.0f, 1.0f, 1.0f);
+
+ /* emission and indirect shader data memory used by various functions */
+ ShaderData emission_sd, indirect_sd;
+
+ ray.P = sd->P + sd->Ng;
+ ray.D = -sd->Ng;
+ ray.t = FLT_MAX;
+# ifdef __CAMERA_MOTION__
+ ray.time = 0.5f;
+# endif
+
+ /* init radiance */
+ path_radiance_init(&L_sample, kernel_data.film.use_light_pass);
+
+ /* init path state */
+ path_state_init(kg, &emission_sd, &state, rng_hash, sample, NULL);
+
+ /* evaluate surface shader */
+ shader_eval_surface(kg, sd, &state, state.flag);
+
+ /* TODO, disable more closures we don't need besides transparent */
+ shader_bsdf_disable_transparency(kg, sd);
+
+# ifdef __BRANCHED_PATH__
+ if (!kernel_data.integrator.branched) {
+ /* regular path tracer */
+# endif
+
+ /* sample ambient occlusion */
+ if (pass_filter & BAKE_FILTER_AO) {
+ kernel_path_ao(
+ kg, sd, &emission_sd, &L_sample, &state, throughput, shader_bsdf_alpha(kg, sd));
+ }
+
+ /* sample emission */
+ if ((pass_filter & BAKE_FILTER_EMISSION) && (sd->flag & SD_EMISSION)) {
+ float3 emission = indirect_primitive_emission(kg, sd, 0.0f, state.flag, state.ray_pdf);
+ path_radiance_accum_emission(&L_sample, &state, throughput, emission);
+ }
+
+ bool is_sss_sample = false;
+
+# ifdef __SUBSURFACE__
+ /* sample subsurface scattering */
+ if ((pass_filter & BAKE_FILTER_SUBSURFACE) && (sd->flag & SD_BSSRDF)) {
+ /* when mixing BSSRDF and BSDF closures we should skip BSDF lighting if scattering was successful */
+ SubsurfaceIndirectRays ss_indirect;
+ kernel_path_subsurface_init_indirect(&ss_indirect);
+ if (kernel_path_subsurface_scatter(
+ kg, sd, &emission_sd, &L_sample, &state, &ray, &throughput, &ss_indirect)) {
+ while (ss_indirect.num_rays) {
+ kernel_path_subsurface_setup_indirect(
+ kg, &ss_indirect, &state, &ray, &L_sample, &throughput);
+ kernel_path_indirect(
+ kg, &indirect_sd, &emission_sd, &ray, throughput, &state, &L_sample);
+ }
+ is_sss_sample = true;
+ }
+ }
+# endif
+
+ /* sample light and BSDF */
+ if (!is_sss_sample && (pass_filter & (BAKE_FILTER_DIRECT | BAKE_FILTER_INDIRECT))) {
+ kernel_path_surface_connect_light(kg, sd, &emission_sd, throughput, &state, &L_sample);
+
+ if (kernel_path_surface_bounce(kg, sd, &throughput, &state, &L_sample.state, &ray)) {
+# ifdef __LAMP_MIS__
+ state.ray_t = 0.0f;
+# endif
+ /* compute indirect light */
+ kernel_path_indirect(kg, &indirect_sd, &emission_sd, &ray, throughput, &state, &L_sample);
+
+ /* sum and reset indirect light pass variables for the next samples */
+ path_radiance_sum_indirect(&L_sample);
+ path_radiance_reset_indirect(&L_sample);
+ }
+ }
+# ifdef __BRANCHED_PATH__
+ }
+ else {
+ /* branched path tracer */
+
+ /* sample ambient occlusion */
+ if (pass_filter & BAKE_FILTER_AO) {
+ kernel_branched_path_ao(kg, sd, &emission_sd, &L_sample, &state, throughput);
+ }
+
+ /* sample emission */
+ if ((pass_filter & BAKE_FILTER_EMISSION) && (sd->flag & SD_EMISSION)) {
+ float3 emission = indirect_primitive_emission(kg, sd, 0.0f, state.flag, state.ray_pdf);
+ path_radiance_accum_emission(&L_sample, &state, throughput, emission);
+ }
+
+# ifdef __SUBSURFACE__
+ /* sample subsurface scattering */
+ if ((pass_filter & BAKE_FILTER_SUBSURFACE) && (sd->flag & SD_BSSRDF)) {
+ /* when mixing BSSRDF and BSDF closures we should skip BSDF lighting if scattering was successful */
+ kernel_branched_path_subsurface_scatter(
+ kg, sd, &indirect_sd, &emission_sd, &L_sample, &state, &ray, throughput);
+ }
+# endif
+
+ /* sample light and BSDF */
+ if (pass_filter & (BAKE_FILTER_DIRECT | BAKE_FILTER_INDIRECT)) {
+# if defined(__EMISSION__)
+ /* direct light */
+ if (kernel_data.integrator.use_direct_light) {
+ int all = kernel_data.integrator.sample_all_lights_direct;
+ kernel_branched_path_surface_connect_light(
+ kg, sd, &emission_sd, &state, throughput, 1.0f, &L_sample, all);
+ }
+# endif
+
+ /* indirect light */
+ kernel_branched_path_surface_indirect_light(
+ kg, sd, &indirect_sd, &emission_sd, throughput, 1.0f, &state, &L_sample);
+ }
+ }
+# endif
+
+ /* accumulate into master L */
+ path_radiance_accum_sample(L, &L_sample);
}
/* this helps with AA but it's not the real solution as it does not AA the geometry
* but it's better than nothing, thus committed */
ccl_device_inline float bake_clamp_mirror_repeat(float u, float max)
{
- /* use mirror repeat (like opengl texture) so that if the barycentric
- * coordinate goes past the end of the triangle it is not always clamped
- * to the same value, gives ugly patterns */
- u /= max;
- float fu = floorf(u);
- u = u - fu;
-
- return ((((int)fu) & 1)? 1.0f - u: u) * max;
+ /* use mirror repeat (like opengl texture) so that if the barycentric
+ * coordinate goes past the end of the triangle it is not always clamped
+ * to the same value, gives ugly patterns */
+ u /= max;
+ float fu = floorf(u);
+ u = u - fu;
+
+ return ((((int)fu) & 1) ? 1.0f - u : u) * max;
}
ccl_device_inline float3 kernel_bake_shader_bsdf(KernelGlobals *kg,
ShaderData *sd,
const ShaderEvalType type)
{
- switch(type) {
- case SHADER_EVAL_DIFFUSE:
- return shader_bsdf_diffuse(kg, sd);
- case SHADER_EVAL_GLOSSY:
- return shader_bsdf_glossy(kg, sd);
- case SHADER_EVAL_TRANSMISSION:
- return shader_bsdf_transmission(kg, sd);
-#ifdef __SUBSURFACE__
- case SHADER_EVAL_SUBSURFACE:
- return shader_bsdf_subsurface(kg, sd);
-#endif
- default:
- kernel_assert(!"Unknown bake type passed to BSDF evaluate");
- return make_float3(0.0f, 0.0f, 0.0f);
- }
+ switch (type) {
+ case SHADER_EVAL_DIFFUSE:
+ return shader_bsdf_diffuse(kg, sd);
+ case SHADER_EVAL_GLOSSY:
+ return shader_bsdf_glossy(kg, sd);
+ case SHADER_EVAL_TRANSMISSION:
+ return shader_bsdf_transmission(kg, sd);
+# ifdef __SUBSURFACE__
+ case SHADER_EVAL_SUBSURFACE:
+ return shader_bsdf_subsurface(kg, sd);
+# endif
+ default:
+ kernel_assert(!"Unknown bake type passed to BSDF evaluate");
+ return make_float3(0.0f, 0.0f, 0.0f);
+ }
}
ccl_device float3 kernel_bake_evaluate_direct_indirect(KernelGlobals *kg,
@@ -213,316 +194,301 @@ ccl_device float3 kernel_bake_evaluate_direct_indirect(KernelGlobals *kg,
const ShaderEvalType type,
const int pass_filter)
{
- float3 color;
- const bool is_color = (pass_filter & BAKE_FILTER_COLOR) != 0;
- const bool is_direct = (pass_filter & BAKE_FILTER_DIRECT) != 0;
- const bool is_indirect = (pass_filter & BAKE_FILTER_INDIRECT) != 0;
- float3 out = make_float3(0.0f, 0.0f, 0.0f);
-
- if(is_color) {
- if(is_direct || is_indirect) {
- /* Leave direct and diffuse channel colored. */
- color = make_float3(1.0f, 1.0f, 1.0f);
- }
- else {
- /* surface color of the pass only */
- shader_eval_surface(kg, sd, state, 0);
- return kernel_bake_shader_bsdf(kg, sd, type);
- }
- }
- else {
- shader_eval_surface(kg, sd, state, 0);
- color = kernel_bake_shader_bsdf(kg, sd, type);
- }
-
- if(is_direct) {
- out += safe_divide_even_color(direct, color);
- }
-
- if(is_indirect) {
- out += safe_divide_even_color(indirect, color);
- }
-
- return out;
+ float3 color;
+ const bool is_color = (pass_filter & BAKE_FILTER_COLOR) != 0;
+ const bool is_direct = (pass_filter & BAKE_FILTER_DIRECT) != 0;
+ const bool is_indirect = (pass_filter & BAKE_FILTER_INDIRECT) != 0;
+ float3 out = make_float3(0.0f, 0.0f, 0.0f);
+
+ if (is_color) {
+ if (is_direct || is_indirect) {
+ /* Leave direct and diffuse channel colored. */
+ color = make_float3(1.0f, 1.0f, 1.0f);
+ }
+ else {
+ /* surface color of the pass only */
+ shader_eval_surface(kg, sd, state, 0);
+ return kernel_bake_shader_bsdf(kg, sd, type);
+ }
+ }
+ else {
+ shader_eval_surface(kg, sd, state, 0);
+ color = kernel_bake_shader_bsdf(kg, sd, type);
+ }
+
+ if (is_direct) {
+ out += safe_divide_even_color(direct, color);
+ }
+
+ if (is_indirect) {
+ out += safe_divide_even_color(indirect, color);
+ }
+
+ return out;
}
-ccl_device void kernel_bake_evaluate(KernelGlobals *kg, ccl_global uint4 *input, ccl_global float4 *output,
- ShaderEvalType type, int pass_filter, int i, int offset, int sample)
+ccl_device void kernel_bake_evaluate(KernelGlobals *kg,
+ ccl_global uint4 *input,
+ ccl_global float4 *output,
+ ShaderEvalType type,
+ int pass_filter,
+ int i,
+ int offset,
+ int sample)
{
- ShaderData sd;
- PathState state = {0};
- uint4 in = input[i * 2];
- uint4 diff = input[i * 2 + 1];
-
- float3 out = make_float3(0.0f, 0.0f, 0.0f);
-
- int object = in.x;
- int prim = in.y;
-
- if(prim == -1)
- return;
-
- float u = __uint_as_float(in.z);
- float v = __uint_as_float(in.w);
-
- float dudx = __uint_as_float(diff.x);
- float dudy = __uint_as_float(diff.y);
- float dvdx = __uint_as_float(diff.z);
- float dvdy = __uint_as_float(diff.w);
-
- int num_samples = kernel_data.integrator.aa_samples;
-
- /* random number generator */
- uint rng_hash = cmj_hash(offset + i, kernel_data.integrator.seed);
-
- float filter_x, filter_y;
- if(sample == 0) {
- filter_x = filter_y = 0.5f;
- }
- else {
- path_rng_2D(kg, rng_hash, sample, num_samples, PRNG_FILTER_U, &filter_x, &filter_y);
- }
-
- /* subpixel u/v offset */
- if(sample > 0) {
- u = bake_clamp_mirror_repeat(u + dudx*(filter_x - 0.5f) + dudy*(filter_y - 0.5f), 1.0f);
- v = bake_clamp_mirror_repeat(v + dvdx*(filter_x - 0.5f) + dvdy*(filter_y - 0.5f), 1.0f - u);
- }
-
- /* triangle */
- int shader;
- float3 P, Ng;
-
- triangle_point_normal(kg, object, prim, u, v, &P, &Ng, &shader);
-
- /* light passes */
- PathRadiance L;
- path_radiance_init(&L, kernel_data.film.use_light_pass);
-
- shader_setup_from_sample(kg, &sd,
- P, Ng, Ng,
- shader, object, prim,
- u, v, 1.0f, 0.5f,
- !(kernel_tex_fetch(__object_flag, object) & SD_OBJECT_TRANSFORM_APPLIED),
- LAMP_NONE);
- sd.I = sd.N;
-
- /* update differentials */
- sd.dP.dx = sd.dPdu * dudx + sd.dPdv * dvdx;
- sd.dP.dy = sd.dPdu * dudy + sd.dPdv * dvdy;
- sd.du.dx = dudx;
- sd.du.dy = dudy;
- sd.dv.dx = dvdx;
- sd.dv.dy = dvdy;
-
- /* set RNG state for shaders that use sampling */
- state.rng_hash = rng_hash;
- state.rng_offset = 0;
- state.sample = sample;
- state.num_samples = num_samples;
- state.min_ray_pdf = FLT_MAX;
-
- /* light passes if we need more than color */
- if(pass_filter & ~BAKE_FILTER_COLOR)
- compute_light_pass(kg, &sd, &L, rng_hash, pass_filter, sample);
-
- switch(type) {
- /* data passes */
- case SHADER_EVAL_NORMAL:
- case SHADER_EVAL_ROUGHNESS:
- case SHADER_EVAL_EMISSION:
- {
- if(type != SHADER_EVAL_NORMAL || (sd.flag & SD_HAS_BUMP)) {
- int path_flag = (type == SHADER_EVAL_EMISSION) ? PATH_RAY_EMISSION : 0;
- shader_eval_surface(kg, &sd, &state, path_flag);
- }
-
- if(type == SHADER_EVAL_NORMAL) {
- float3 N = sd.N;
- if(sd.flag & SD_HAS_BUMP) {
- N = shader_bsdf_average_normal(kg, &sd);
- }
-
- /* encoding: normal = (2 * color) - 1 */
- out = N * 0.5f + make_float3(0.5f, 0.5f, 0.5f);
- }
- else if(type == SHADER_EVAL_ROUGHNESS) {
- float roughness = shader_bsdf_average_roughness(&sd);
- out = make_float3(roughness, roughness, roughness);
- }
- else {
- out = shader_emissive_eval(&sd);
- }
- break;
- }
- case SHADER_EVAL_UV:
- {
- out = primitive_uv(kg, &sd);
- break;
- }
-#ifdef __PASSES__
- /* light passes */
- case SHADER_EVAL_AO:
- {
- out = L.ao;
- break;
- }
- case SHADER_EVAL_COMBINED:
- {
- if((pass_filter & BAKE_FILTER_COMBINED) == BAKE_FILTER_COMBINED) {
- float alpha;
- out = path_radiance_clamp_and_sum(kg, &L, &alpha);
- break;
- }
-
- if((pass_filter & BAKE_FILTER_DIFFUSE_DIRECT) == BAKE_FILTER_DIFFUSE_DIRECT)
- out += L.direct_diffuse;
- if((pass_filter & BAKE_FILTER_DIFFUSE_INDIRECT) == BAKE_FILTER_DIFFUSE_INDIRECT)
- out += L.indirect_diffuse;
-
- if((pass_filter & BAKE_FILTER_GLOSSY_DIRECT) == BAKE_FILTER_GLOSSY_DIRECT)
- out += L.direct_glossy;
- if((pass_filter & BAKE_FILTER_GLOSSY_INDIRECT) == BAKE_FILTER_GLOSSY_INDIRECT)
- out += L.indirect_glossy;
-
- if((pass_filter & BAKE_FILTER_TRANSMISSION_DIRECT) == BAKE_FILTER_TRANSMISSION_DIRECT)
- out += L.direct_transmission;
- if((pass_filter & BAKE_FILTER_TRANSMISSION_INDIRECT) == BAKE_FILTER_TRANSMISSION_INDIRECT)
- out += L.indirect_transmission;
-
- if((pass_filter & BAKE_FILTER_SUBSURFACE_DIRECT) == BAKE_FILTER_SUBSURFACE_DIRECT)
- out += L.direct_subsurface;
- if((pass_filter & BAKE_FILTER_SUBSURFACE_INDIRECT) == BAKE_FILTER_SUBSURFACE_INDIRECT)
- out += L.indirect_subsurface;
-
- if((pass_filter & BAKE_FILTER_EMISSION) != 0)
- out += L.emission;
-
- break;
- }
- case SHADER_EVAL_SHADOW:
- {
- out = make_float3(L.shadow.x, L.shadow.y, L.shadow.z);
- break;
- }
- case SHADER_EVAL_DIFFUSE:
- {
- out = kernel_bake_evaluate_direct_indirect(kg,
- &sd,
- &state,
- L.direct_diffuse,
- L.indirect_diffuse,
- type,
- pass_filter);
- break;
- }
- case SHADER_EVAL_GLOSSY:
- {
- out = kernel_bake_evaluate_direct_indirect(kg,
- &sd,
- &state,
- L.direct_glossy,
- L.indirect_glossy,
- type,
- pass_filter);
- break;
- }
- case SHADER_EVAL_TRANSMISSION:
- {
- out = kernel_bake_evaluate_direct_indirect(kg,
- &sd,
- &state,
- L.direct_transmission,
- L.indirect_transmission,
- type,
- pass_filter);
- break;
- }
- case SHADER_EVAL_SUBSURFACE:
- {
-#ifdef __SUBSURFACE__
- out = kernel_bake_evaluate_direct_indirect(kg,
- &sd,
- &state,
- L.direct_subsurface,
- L.indirect_subsurface,
- type,
- pass_filter);
-#endif
- break;
- }
-#endif
-
- /* extra */
- case SHADER_EVAL_ENVIRONMENT:
- {
- /* setup ray */
- Ray ray;
-
- ray.P = make_float3(0.0f, 0.0f, 0.0f);
- ray.D = normalize(P);
- ray.t = 0.0f;
-#ifdef __CAMERA_MOTION__
- ray.time = 0.5f;
-#endif
-
-#ifdef __RAY_DIFFERENTIALS__
- ray.dD = differential3_zero();
- ray.dP = differential3_zero();
-#endif
-
- /* setup shader data */
- shader_setup_from_background(kg, &sd, &ray);
-
- /* evaluate */
- int path_flag = 0; /* we can't know which type of BSDF this is for */
- shader_eval_surface(kg, &sd, &state, path_flag | PATH_RAY_EMISSION);
- out = shader_background_eval(&sd);
- break;
- }
- default:
- {
- /* no real shader, returning the position of the verts for debugging */
- out = normalize(P);
- break;
- }
- }
-
- /* write output */
- const float output_fac = 1.0f/num_samples;
- const float4 scaled_result = make_float4(out.x, out.y, out.z, 1.0f) * output_fac;
-
- output[i] = (sample == 0)? scaled_result: output[i] + scaled_result;
+ ShaderData sd;
+ PathState state = {0};
+ uint4 in = input[i * 2];
+ uint4 diff = input[i * 2 + 1];
+
+ float3 out = make_float3(0.0f, 0.0f, 0.0f);
+
+ int object = in.x;
+ int prim = in.y;
+
+ if (prim == -1)
+ return;
+
+ float u = __uint_as_float(in.z);
+ float v = __uint_as_float(in.w);
+
+ float dudx = __uint_as_float(diff.x);
+ float dudy = __uint_as_float(diff.y);
+ float dvdx = __uint_as_float(diff.z);
+ float dvdy = __uint_as_float(diff.w);
+
+ int num_samples = kernel_data.integrator.aa_samples;
+
+ /* random number generator */
+ uint rng_hash = cmj_hash(offset + i, kernel_data.integrator.seed);
+
+ float filter_x, filter_y;
+ if (sample == 0) {
+ filter_x = filter_y = 0.5f;
+ }
+ else {
+ path_rng_2D(kg, rng_hash, sample, num_samples, PRNG_FILTER_U, &filter_x, &filter_y);
+ }
+
+ /* subpixel u/v offset */
+ if (sample > 0) {
+ u = bake_clamp_mirror_repeat(u + dudx * (filter_x - 0.5f) + dudy * (filter_y - 0.5f), 1.0f);
+ v = bake_clamp_mirror_repeat(v + dvdx * (filter_x - 0.5f) + dvdy * (filter_y - 0.5f),
+ 1.0f - u);
+ }
+
+ /* triangle */
+ int shader;
+ float3 P, Ng;
+
+ triangle_point_normal(kg, object, prim, u, v, &P, &Ng, &shader);
+
+ /* light passes */
+ PathRadiance L;
+ path_radiance_init(&L, kernel_data.film.use_light_pass);
+
+ shader_setup_from_sample(
+ kg,
+ &sd,
+ P,
+ Ng,
+ Ng,
+ shader,
+ object,
+ prim,
+ u,
+ v,
+ 1.0f,
+ 0.5f,
+ !(kernel_tex_fetch(__object_flag, object) & SD_OBJECT_TRANSFORM_APPLIED),
+ LAMP_NONE);
+ sd.I = sd.N;
+
+ /* update differentials */
+ sd.dP.dx = sd.dPdu * dudx + sd.dPdv * dvdx;
+ sd.dP.dy = sd.dPdu * dudy + sd.dPdv * dvdy;
+ sd.du.dx = dudx;
+ sd.du.dy = dudy;
+ sd.dv.dx = dvdx;
+ sd.dv.dy = dvdy;
+
+ /* set RNG state for shaders that use sampling */
+ state.rng_hash = rng_hash;
+ state.rng_offset = 0;
+ state.sample = sample;
+ state.num_samples = num_samples;
+ state.min_ray_pdf = FLT_MAX;
+
+ /* light passes if we need more than color */
+ if (pass_filter & ~BAKE_FILTER_COLOR)
+ compute_light_pass(kg, &sd, &L, rng_hash, pass_filter, sample);
+
+ switch (type) {
+ /* data passes */
+ case SHADER_EVAL_NORMAL:
+ case SHADER_EVAL_ROUGHNESS:
+ case SHADER_EVAL_EMISSION: {
+ if (type != SHADER_EVAL_NORMAL || (sd.flag & SD_HAS_BUMP)) {
+ int path_flag = (type == SHADER_EVAL_EMISSION) ? PATH_RAY_EMISSION : 0;
+ shader_eval_surface(kg, &sd, &state, path_flag);
+ }
+
+ if (type == SHADER_EVAL_NORMAL) {
+ float3 N = sd.N;
+ if (sd.flag & SD_HAS_BUMP) {
+ N = shader_bsdf_average_normal(kg, &sd);
+ }
+
+ /* encoding: normal = (2 * color) - 1 */
+ out = N * 0.5f + make_float3(0.5f, 0.5f, 0.5f);
+ }
+ else if (type == SHADER_EVAL_ROUGHNESS) {
+ float roughness = shader_bsdf_average_roughness(&sd);
+ out = make_float3(roughness, roughness, roughness);
+ }
+ else {
+ out = shader_emissive_eval(&sd);
+ }
+ break;
+ }
+ case SHADER_EVAL_UV: {
+ out = primitive_uv(kg, &sd);
+ break;
+ }
+# ifdef __PASSES__
+ /* light passes */
+ case SHADER_EVAL_AO: {
+ out = L.ao;
+ break;
+ }
+ case SHADER_EVAL_COMBINED: {
+ if ((pass_filter & BAKE_FILTER_COMBINED) == BAKE_FILTER_COMBINED) {
+ float alpha;
+ out = path_radiance_clamp_and_sum(kg, &L, &alpha);
+ break;
+ }
+
+ if ((pass_filter & BAKE_FILTER_DIFFUSE_DIRECT) == BAKE_FILTER_DIFFUSE_DIRECT)
+ out += L.direct_diffuse;
+ if ((pass_filter & BAKE_FILTER_DIFFUSE_INDIRECT) == BAKE_FILTER_DIFFUSE_INDIRECT)
+ out += L.indirect_diffuse;
+
+ if ((pass_filter & BAKE_FILTER_GLOSSY_DIRECT) == BAKE_FILTER_GLOSSY_DIRECT)
+ out += L.direct_glossy;
+ if ((pass_filter & BAKE_FILTER_GLOSSY_INDIRECT) == BAKE_FILTER_GLOSSY_INDIRECT)
+ out += L.indirect_glossy;
+
+ if ((pass_filter & BAKE_FILTER_TRANSMISSION_DIRECT) == BAKE_FILTER_TRANSMISSION_DIRECT)
+ out += L.direct_transmission;
+ if ((pass_filter & BAKE_FILTER_TRANSMISSION_INDIRECT) == BAKE_FILTER_TRANSMISSION_INDIRECT)
+ out += L.indirect_transmission;
+
+ if ((pass_filter & BAKE_FILTER_SUBSURFACE_DIRECT) == BAKE_FILTER_SUBSURFACE_DIRECT)
+ out += L.direct_subsurface;
+ if ((pass_filter & BAKE_FILTER_SUBSURFACE_INDIRECT) == BAKE_FILTER_SUBSURFACE_INDIRECT)
+ out += L.indirect_subsurface;
+
+ if ((pass_filter & BAKE_FILTER_EMISSION) != 0)
+ out += L.emission;
+
+ break;
+ }
+ case SHADER_EVAL_SHADOW: {
+ out = make_float3(L.shadow.x, L.shadow.y, L.shadow.z);
+ break;
+ }
+ case SHADER_EVAL_DIFFUSE: {
+ out = kernel_bake_evaluate_direct_indirect(
+ kg, &sd, &state, L.direct_diffuse, L.indirect_diffuse, type, pass_filter);
+ break;
+ }
+ case SHADER_EVAL_GLOSSY: {
+ out = kernel_bake_evaluate_direct_indirect(
+ kg, &sd, &state, L.direct_glossy, L.indirect_glossy, type, pass_filter);
+ break;
+ }
+ case SHADER_EVAL_TRANSMISSION: {
+ out = kernel_bake_evaluate_direct_indirect(
+ kg, &sd, &state, L.direct_transmission, L.indirect_transmission, type, pass_filter);
+ break;
+ }
+ case SHADER_EVAL_SUBSURFACE: {
+# ifdef __SUBSURFACE__
+ out = kernel_bake_evaluate_direct_indirect(
+ kg, &sd, &state, L.direct_subsurface, L.indirect_subsurface, type, pass_filter);
+# endif
+ break;
+ }
+# endif
+
+ /* extra */
+ case SHADER_EVAL_ENVIRONMENT: {
+ /* setup ray */
+ Ray ray;
+
+ ray.P = make_float3(0.0f, 0.0f, 0.0f);
+ ray.D = normalize(P);
+ ray.t = 0.0f;
+# ifdef __CAMERA_MOTION__
+ ray.time = 0.5f;
+# endif
+
+# ifdef __RAY_DIFFERENTIALS__
+ ray.dD = differential3_zero();
+ ray.dP = differential3_zero();
+# endif
+
+ /* setup shader data */
+ shader_setup_from_background(kg, &sd, &ray);
+
+ /* evaluate */
+ int path_flag = 0; /* we can't know which type of BSDF this is for */
+ shader_eval_surface(kg, &sd, &state, path_flag | PATH_RAY_EMISSION);
+ out = shader_background_eval(&sd);
+ break;
+ }
+ default: {
+ /* no real shader, returning the position of the verts for debugging */
+ out = normalize(P);
+ break;
+ }
+ }
+
+ /* write output */
+ const float output_fac = 1.0f / num_samples;
+ const float4 scaled_result = make_float4(out.x, out.y, out.z, 1.0f) * output_fac;
+
+ output[i] = (sample == 0) ? scaled_result : output[i] + scaled_result;
}
-#endif /* __BAKING__ */
+#endif /* __BAKING__ */
ccl_device void kernel_displace_evaluate(KernelGlobals *kg,
ccl_global uint4 *input,
ccl_global float4 *output,
int i)
{
- ShaderData sd;
- PathState state = {0};
- uint4 in = input[i];
+ ShaderData sd;
+ PathState state = {0};
+ uint4 in = input[i];
- /* setup shader data */
- int object = in.x;
- int prim = in.y;
- float u = __uint_as_float(in.z);
- float v = __uint_as_float(in.w);
+ /* setup shader data */
+ int object = in.x;
+ int prim = in.y;
+ float u = __uint_as_float(in.z);
+ float v = __uint_as_float(in.w);
- shader_setup_from_displace(kg, &sd, object, prim, u, v);
+ shader_setup_from_displace(kg, &sd, object, prim, u, v);
- /* evaluate */
- float3 P = sd.P;
- shader_eval_displacement(kg, &sd, &state);
- float3 D = sd.P - P;
+ /* evaluate */
+ float3 P = sd.P;
+ shader_eval_displacement(kg, &sd, &state);
+ float3 D = sd.P - P;
- object_inverse_dir_transform(kg, &sd, &D);
+ object_inverse_dir_transform(kg, &sd, &D);
- /* write output */
- output[i] += make_float4(D.x, D.y, D.z, 0.0f);
+ /* write output */
+ output[i] += make_float4(D.x, D.y, D.z, 0.0f);
}
ccl_device void kernel_background_evaluate(KernelGlobals *kg,
@@ -530,37 +496,37 @@ ccl_device void kernel_background_evaluate(KernelGlobals *kg,
ccl_global float4 *output,
int i)
{
- ShaderData sd;
- PathState state = {0};
- uint4 in = input[i];
-
- /* setup ray */
- Ray ray;
- float u = __uint_as_float(in.x);
- float v = __uint_as_float(in.y);
-
- ray.P = make_float3(0.0f, 0.0f, 0.0f);
- ray.D = equirectangular_to_direction(u, v);
- ray.t = 0.0f;
+ ShaderData sd;
+ PathState state = {0};
+ uint4 in = input[i];
+
+ /* setup ray */
+ Ray ray;
+ float u = __uint_as_float(in.x);
+ float v = __uint_as_float(in.y);
+
+ ray.P = make_float3(0.0f, 0.0f, 0.0f);
+ ray.D = equirectangular_to_direction(u, v);
+ ray.t = 0.0f;
#ifdef __CAMERA_MOTION__
- ray.time = 0.5f;
+ ray.time = 0.5f;
#endif
#ifdef __RAY_DIFFERENTIALS__
- ray.dD = differential3_zero();
- ray.dP = differential3_zero();
+ ray.dD = differential3_zero();
+ ray.dP = differential3_zero();
#endif
- /* setup shader data */
- shader_setup_from_background(kg, &sd, &ray);
+ /* setup shader data */
+ shader_setup_from_background(kg, &sd, &ray);
- /* evaluate */
- int path_flag = 0; /* we can't know which type of BSDF this is for */
- shader_eval_surface(kg, &sd, &state, path_flag | PATH_RAY_EMISSION);
- float3 color = shader_background_eval(&sd);
+ /* evaluate */
+ int path_flag = 0; /* we can't know which type of BSDF this is for */
+ shader_eval_surface(kg, &sd, &state, path_flag | PATH_RAY_EMISSION);
+ float3 color = shader_background_eval(&sd);
- /* write output */
- output[i] += make_float4(color.x, color.y, color.z, 0.0f);
+ /* write output */
+ output[i] += make_float4(color.x, color.y, color.z, 0.0f);
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/kernel_camera.h b/intern/cycles/kernel/kernel_camera.h
index b73ad47dad3..1085930c33a 100644
--- a/intern/cycles/kernel/kernel_camera.h
+++ b/intern/cycles/kernel/kernel_camera.h
@@ -20,209 +20,217 @@ CCL_NAMESPACE_BEGIN
ccl_device float2 camera_sample_aperture(ccl_constant KernelCamera *cam, float u, float v)
{
- float blades = cam->blades;
- float2 bokeh;
-
- if(blades == 0.0f) {
- /* sample disk */
- bokeh = concentric_sample_disk(u, v);
- }
- else {
- /* sample polygon */
- float rotation = cam->bladesrotation;
- bokeh = regular_polygon_sample(blades, rotation, u, v);
- }
-
- /* anamorphic lens bokeh */
- bokeh.x *= cam->inv_aperture_ratio;
-
- return bokeh;
+ float blades = cam->blades;
+ float2 bokeh;
+
+ if (blades == 0.0f) {
+ /* sample disk */
+ bokeh = concentric_sample_disk(u, v);
+ }
+ else {
+ /* sample polygon */
+ float rotation = cam->bladesrotation;
+ bokeh = regular_polygon_sample(blades, rotation, u, v);
+ }
+
+ /* anamorphic lens bokeh */
+ bokeh.x *= cam->inv_aperture_ratio;
+
+ return bokeh;
}
-ccl_device void camera_sample_perspective(KernelGlobals *kg, float raster_x, float raster_y, float lens_u, float lens_v, ccl_addr_space Ray *ray)
+ccl_device void camera_sample_perspective(KernelGlobals *kg,
+ float raster_x,
+ float raster_y,
+ float lens_u,
+ float lens_v,
+ ccl_addr_space Ray *ray)
{
- /* create ray form raster position */
- ProjectionTransform rastertocamera = kernel_data.cam.rastertocamera;
- float3 raster = make_float3(raster_x, raster_y, 0.0f);
- float3 Pcamera = transform_perspective(&rastertocamera, raster);
+ /* create ray form raster position */
+ ProjectionTransform rastertocamera = kernel_data.cam.rastertocamera;
+ float3 raster = make_float3(raster_x, raster_y, 0.0f);
+ float3 Pcamera = transform_perspective(&rastertocamera, raster);
#ifdef __CAMERA_MOTION__
- if(kernel_data.cam.have_perspective_motion) {
- /* TODO(sergey): Currently we interpolate projected coordinate which
- * gives nice looking result and which is simple, but is in fact a bit
- * different comparing to constructing projective matrix from an
- * interpolated field of view.
- */
- if(ray->time < 0.5f) {
- ProjectionTransform rastertocamera_pre = kernel_data.cam.perspective_pre;
- float3 Pcamera_pre =
- transform_perspective(&rastertocamera_pre, raster);
- Pcamera = interp(Pcamera_pre, Pcamera, ray->time * 2.0f);
- }
- else {
- ProjectionTransform rastertocamera_post = kernel_data.cam.perspective_post;
- float3 Pcamera_post =
- transform_perspective(&rastertocamera_post, raster);
- Pcamera = interp(Pcamera, Pcamera_post, (ray->time - 0.5f) * 2.0f);
- }
- }
+ if (kernel_data.cam.have_perspective_motion) {
+ /* TODO(sergey): Currently we interpolate projected coordinate which
+ * gives nice looking result and which is simple, but is in fact a bit
+ * different comparing to constructing projective matrix from an
+ * interpolated field of view.
+ */
+ if (ray->time < 0.5f) {
+ ProjectionTransform rastertocamera_pre = kernel_data.cam.perspective_pre;
+ float3 Pcamera_pre = transform_perspective(&rastertocamera_pre, raster);
+ Pcamera = interp(Pcamera_pre, Pcamera, ray->time * 2.0f);
+ }
+ else {
+ ProjectionTransform rastertocamera_post = kernel_data.cam.perspective_post;
+ float3 Pcamera_post = transform_perspective(&rastertocamera_post, raster);
+ Pcamera = interp(Pcamera, Pcamera_post, (ray->time - 0.5f) * 2.0f);
+ }
+ }
#endif
- float3 P = make_float3(0.0f, 0.0f, 0.0f);
- float3 D = Pcamera;
+ float3 P = make_float3(0.0f, 0.0f, 0.0f);
+ float3 D = Pcamera;
- /* modify ray for depth of field */
- float aperturesize = kernel_data.cam.aperturesize;
+ /* modify ray for depth of field */
+ float aperturesize = kernel_data.cam.aperturesize;
- if(aperturesize > 0.0f) {
- /* sample point on aperture */
- float2 lensuv = camera_sample_aperture(&kernel_data.cam, lens_u, lens_v)*aperturesize;
+ if (aperturesize > 0.0f) {
+ /* sample point on aperture */
+ float2 lensuv = camera_sample_aperture(&kernel_data.cam, lens_u, lens_v) * aperturesize;
- /* compute point on plane of focus */
- float ft = kernel_data.cam.focaldistance/D.z;
- float3 Pfocus = D*ft;
+ /* compute point on plane of focus */
+ float ft = kernel_data.cam.focaldistance / D.z;
+ float3 Pfocus = D * ft;
- /* update ray for effect of lens */
- P = make_float3(lensuv.x, lensuv.y, 0.0f);
- D = normalize(Pfocus - P);
- }
+ /* update ray for effect of lens */
+ P = make_float3(lensuv.x, lensuv.y, 0.0f);
+ D = normalize(Pfocus - P);
+ }
- /* transform ray from camera to world */
- Transform cameratoworld = kernel_data.cam.cameratoworld;
+ /* transform ray from camera to world */
+ Transform cameratoworld = kernel_data.cam.cameratoworld;
#ifdef __CAMERA_MOTION__
- if(kernel_data.cam.num_motion_steps) {
- transform_motion_array_interpolate(
- &cameratoworld,
- kernel_tex_array(__camera_motion),
- kernel_data.cam.num_motion_steps,
- ray->time);
- }
+ if (kernel_data.cam.num_motion_steps) {
+ transform_motion_array_interpolate(&cameratoworld,
+ kernel_tex_array(__camera_motion),
+ kernel_data.cam.num_motion_steps,
+ ray->time);
+ }
#endif
- P = transform_point(&cameratoworld, P);
- D = normalize(transform_direction(&cameratoworld, D));
+ P = transform_point(&cameratoworld, P);
+ D = normalize(transform_direction(&cameratoworld, D));
- bool use_stereo = kernel_data.cam.interocular_offset != 0.0f;
- if(!use_stereo) {
- /* No stereo */
- ray->P = P;
- ray->D = D;
+ bool use_stereo = kernel_data.cam.interocular_offset != 0.0f;
+ if (!use_stereo) {
+ /* No stereo */
+ ray->P = P;
+ ray->D = D;
#ifdef __RAY_DIFFERENTIALS__
- float3 Dcenter = transform_direction(&cameratoworld, Pcamera);
+ float3 Dcenter = transform_direction(&cameratoworld, Pcamera);
- ray->dP = differential3_zero();
- ray->dD.dx = normalize(Dcenter + float4_to_float3(kernel_data.cam.dx)) - normalize(Dcenter);
- ray->dD.dy = normalize(Dcenter + float4_to_float3(kernel_data.cam.dy)) - normalize(Dcenter);
+ ray->dP = differential3_zero();
+ ray->dD.dx = normalize(Dcenter + float4_to_float3(kernel_data.cam.dx)) - normalize(Dcenter);
+ ray->dD.dy = normalize(Dcenter + float4_to_float3(kernel_data.cam.dy)) - normalize(Dcenter);
#endif
- }
- else {
- /* Spherical stereo */
- spherical_stereo_transform(&kernel_data.cam, &P, &D);
- ray->P = P;
- ray->D = D;
+ }
+ else {
+ /* Spherical stereo */
+ spherical_stereo_transform(&kernel_data.cam, &P, &D);
+ ray->P = P;
+ ray->D = D;
#ifdef __RAY_DIFFERENTIALS__
- /* Ray differentials, computed from scratch using the raster coordinates
- * because we don't want to be affected by depth of field. We compute
- * ray origin and direction for the center and two neighbouring pixels
- * and simply take their differences. */
- float3 Pnostereo = transform_point(&cameratoworld, make_float3(0.0f, 0.0f, 0.0f));
-
- float3 Pcenter = Pnostereo;
- float3 Dcenter = Pcamera;
- Dcenter = normalize(transform_direction(&cameratoworld, Dcenter));
- spherical_stereo_transform(&kernel_data.cam, &Pcenter, &Dcenter);
-
- float3 Px = Pnostereo;
- float3 Dx = transform_perspective(&rastertocamera, make_float3(raster_x + 1.0f, raster_y, 0.0f));
- Dx = normalize(transform_direction(&cameratoworld, Dx));
- spherical_stereo_transform(&kernel_data.cam, &Px, &Dx);
-
- ray->dP.dx = Px - Pcenter;
- ray->dD.dx = Dx - Dcenter;
-
- float3 Py = Pnostereo;
- float3 Dy = transform_perspective(&rastertocamera, make_float3(raster_x, raster_y + 1.0f, 0.0f));
- Dy = normalize(transform_direction(&cameratoworld, Dy));
- spherical_stereo_transform(&kernel_data.cam, &Py, &Dy);
-
- ray->dP.dy = Py - Pcenter;
- ray->dD.dy = Dy - Dcenter;
+ /* Ray differentials, computed from scratch using the raster coordinates
+ * because we don't want to be affected by depth of field. We compute
+ * ray origin and direction for the center and two neighbouring pixels
+ * and simply take their differences. */
+ float3 Pnostereo = transform_point(&cameratoworld, make_float3(0.0f, 0.0f, 0.0f));
+
+ float3 Pcenter = Pnostereo;
+ float3 Dcenter = Pcamera;
+ Dcenter = normalize(transform_direction(&cameratoworld, Dcenter));
+ spherical_stereo_transform(&kernel_data.cam, &Pcenter, &Dcenter);
+
+ float3 Px = Pnostereo;
+ float3 Dx = transform_perspective(&rastertocamera,
+ make_float3(raster_x + 1.0f, raster_y, 0.0f));
+ Dx = normalize(transform_direction(&cameratoworld, Dx));
+ spherical_stereo_transform(&kernel_data.cam, &Px, &Dx);
+
+ ray->dP.dx = Px - Pcenter;
+ ray->dD.dx = Dx - Dcenter;
+
+ float3 Py = Pnostereo;
+ float3 Dy = transform_perspective(&rastertocamera,
+ make_float3(raster_x, raster_y + 1.0f, 0.0f));
+ Dy = normalize(transform_direction(&cameratoworld, Dy));
+ spherical_stereo_transform(&kernel_data.cam, &Py, &Dy);
+
+ ray->dP.dy = Py - Pcenter;
+ ray->dD.dy = Dy - Dcenter;
#endif
- }
+ }
#ifdef __CAMERA_CLIPPING__
- /* clipping */
- float z_inv = 1.0f / normalize(Pcamera).z;
- float nearclip = kernel_data.cam.nearclip * z_inv;
- ray->P += nearclip * ray->D;
- ray->dP.dx += nearclip * ray->dD.dx;
- ray->dP.dy += nearclip * ray->dD.dy;
- ray->t = kernel_data.cam.cliplength * z_inv;
+ /* clipping */
+ float z_inv = 1.0f / normalize(Pcamera).z;
+ float nearclip = kernel_data.cam.nearclip * z_inv;
+ ray->P += nearclip * ray->D;
+ ray->dP.dx += nearclip * ray->dD.dx;
+ ray->dP.dy += nearclip * ray->dD.dy;
+ ray->t = kernel_data.cam.cliplength * z_inv;
#else
- ray->t = FLT_MAX;
+ ray->t = FLT_MAX;
#endif
}
/* Orthographic Camera */
-ccl_device void camera_sample_orthographic(KernelGlobals *kg, float raster_x, float raster_y, float lens_u, float lens_v, ccl_addr_space Ray *ray)
+ccl_device void camera_sample_orthographic(KernelGlobals *kg,
+ float raster_x,
+ float raster_y,
+ float lens_u,
+ float lens_v,
+ ccl_addr_space Ray *ray)
{
- /* create ray form raster position */
- ProjectionTransform rastertocamera = kernel_data.cam.rastertocamera;
- float3 Pcamera = transform_perspective(&rastertocamera, make_float3(raster_x, raster_y, 0.0f));
-
- float3 P;
- float3 D = make_float3(0.0f, 0.0f, 1.0f);
-
- /* modify ray for depth of field */
- float aperturesize = kernel_data.cam.aperturesize;
-
- if(aperturesize > 0.0f) {
- /* sample point on aperture */
- float2 lensuv = camera_sample_aperture(&kernel_data.cam, lens_u, lens_v)*aperturesize;
-
- /* compute point on plane of focus */
- float3 Pfocus = D * kernel_data.cam.focaldistance;
-
- /* update ray for effect of lens */
- float3 lensuvw = make_float3(lensuv.x, lensuv.y, 0.0f);
- P = Pcamera + lensuvw;
- D = normalize(Pfocus - lensuvw);
- }
- else {
- P = Pcamera;
- }
- /* transform ray from camera to world */
- Transform cameratoworld = kernel_data.cam.cameratoworld;
+ /* create ray form raster position */
+ ProjectionTransform rastertocamera = kernel_data.cam.rastertocamera;
+ float3 Pcamera = transform_perspective(&rastertocamera, make_float3(raster_x, raster_y, 0.0f));
+
+ float3 P;
+ float3 D = make_float3(0.0f, 0.0f, 1.0f);
+
+ /* modify ray for depth of field */
+ float aperturesize = kernel_data.cam.aperturesize;
+
+ if (aperturesize > 0.0f) {
+ /* sample point on aperture */
+ float2 lensuv = camera_sample_aperture(&kernel_data.cam, lens_u, lens_v) * aperturesize;
+
+ /* compute point on plane of focus */
+ float3 Pfocus = D * kernel_data.cam.focaldistance;
+
+ /* update ray for effect of lens */
+ float3 lensuvw = make_float3(lensuv.x, lensuv.y, 0.0f);
+ P = Pcamera + lensuvw;
+ D = normalize(Pfocus - lensuvw);
+ }
+ else {
+ P = Pcamera;
+ }
+ /* transform ray from camera to world */
+ Transform cameratoworld = kernel_data.cam.cameratoworld;
#ifdef __CAMERA_MOTION__
- if(kernel_data.cam.num_motion_steps) {
- transform_motion_array_interpolate(
- &cameratoworld,
- kernel_tex_array(__camera_motion),
- kernel_data.cam.num_motion_steps,
- ray->time);
- }
+ if (kernel_data.cam.num_motion_steps) {
+ transform_motion_array_interpolate(&cameratoworld,
+ kernel_tex_array(__camera_motion),
+ kernel_data.cam.num_motion_steps,
+ ray->time);
+ }
#endif
- ray->P = transform_point(&cameratoworld, P);
- ray->D = normalize(transform_direction(&cameratoworld, D));
+ ray->P = transform_point(&cameratoworld, P);
+ ray->D = normalize(transform_direction(&cameratoworld, D));
#ifdef __RAY_DIFFERENTIALS__
- /* ray differential */
- ray->dP.dx = float4_to_float3(kernel_data.cam.dx);
- ray->dP.dy = float4_to_float3(kernel_data.cam.dy);
+ /* ray differential */
+ ray->dP.dx = float4_to_float3(kernel_data.cam.dx);
+ ray->dP.dy = float4_to_float3(kernel_data.cam.dy);
- ray->dD = differential3_zero();
+ ray->dD = differential3_zero();
#endif
#ifdef __CAMERA_CLIPPING__
- /* clipping */
- ray->t = kernel_data.cam.cliplength;
+ /* clipping */
+ ray->t = kernel_data.cam.cliplength;
#else
- ray->t = FLT_MAX;
+ ray->t = FLT_MAX;
#endif
}
@@ -230,242 +238,244 @@ ccl_device void camera_sample_orthographic(KernelGlobals *kg, float raster_x, fl
ccl_device_inline void camera_sample_panorama(ccl_constant KernelCamera *cam,
const ccl_global DecomposedTransform *cam_motion,
- float raster_x, float raster_y,
- float lens_u, float lens_v,
+ float raster_x,
+ float raster_y,
+ float lens_u,
+ float lens_v,
ccl_addr_space Ray *ray)
{
- ProjectionTransform rastertocamera = cam->rastertocamera;
- float3 Pcamera = transform_perspective(&rastertocamera, make_float3(raster_x, raster_y, 0.0f));
+ ProjectionTransform rastertocamera = cam->rastertocamera;
+ float3 Pcamera = transform_perspective(&rastertocamera, make_float3(raster_x, raster_y, 0.0f));
- /* create ray form raster position */
- float3 P = make_float3(0.0f, 0.0f, 0.0f);
- float3 D = panorama_to_direction(cam, Pcamera.x, Pcamera.y);
+ /* create ray form raster position */
+ float3 P = make_float3(0.0f, 0.0f, 0.0f);
+ float3 D = panorama_to_direction(cam, Pcamera.x, Pcamera.y);
- /* indicates ray should not receive any light, outside of the lens */
- if(is_zero(D)) {
- ray->t = 0.0f;
- return;
- }
+ /* indicates ray should not receive any light, outside of the lens */
+ if (is_zero(D)) {
+ ray->t = 0.0f;
+ return;
+ }
- /* modify ray for depth of field */
- float aperturesize = cam->aperturesize;
+ /* modify ray for depth of field */
+ float aperturesize = cam->aperturesize;
- if(aperturesize > 0.0f) {
- /* sample point on aperture */
- float2 lensuv = camera_sample_aperture(cam, lens_u, lens_v)*aperturesize;
+ if (aperturesize > 0.0f) {
+ /* sample point on aperture */
+ float2 lensuv = camera_sample_aperture(cam, lens_u, lens_v) * aperturesize;
- /* compute point on plane of focus */
- float3 Dfocus = normalize(D);
- float3 Pfocus = Dfocus * cam->focaldistance;
+ /* compute point on plane of focus */
+ float3 Dfocus = normalize(D);
+ float3 Pfocus = Dfocus * cam->focaldistance;
- /* calculate orthonormal coordinates perpendicular to Dfocus */
- float3 U, V;
- U = normalize(make_float3(1.0f, 0.0f, 0.0f) - Dfocus.x * Dfocus);
- V = normalize(cross(Dfocus, U));
+ /* calculate orthonormal coordinates perpendicular to Dfocus */
+ float3 U, V;
+ U = normalize(make_float3(1.0f, 0.0f, 0.0f) - Dfocus.x * Dfocus);
+ V = normalize(cross(Dfocus, U));
- /* update ray for effect of lens */
- P = U * lensuv.x + V * lensuv.y;
- D = normalize(Pfocus - P);
- }
+ /* update ray for effect of lens */
+ P = U * lensuv.x + V * lensuv.y;
+ D = normalize(Pfocus - P);
+ }
- /* transform ray from camera to world */
- Transform cameratoworld = cam->cameratoworld;
+ /* transform ray from camera to world */
+ Transform cameratoworld = cam->cameratoworld;
#ifdef __CAMERA_MOTION__
- if(cam->num_motion_steps) {
- transform_motion_array_interpolate(
- &cameratoworld,
- cam_motion,
- cam->num_motion_steps,
- ray->time);
- }
+ if (cam->num_motion_steps) {
+ transform_motion_array_interpolate(
+ &cameratoworld, cam_motion, cam->num_motion_steps, ray->time);
+ }
#endif
- P = transform_point(&cameratoworld, P);
- D = normalize(transform_direction(&cameratoworld, D));
+ P = transform_point(&cameratoworld, P);
+ D = normalize(transform_direction(&cameratoworld, D));
- /* Stereo transform */
- bool use_stereo = cam->interocular_offset != 0.0f;
- if(use_stereo) {
- spherical_stereo_transform(cam, &P, &D);
- }
+ /* Stereo transform */
+ bool use_stereo = cam->interocular_offset != 0.0f;
+ if (use_stereo) {
+ spherical_stereo_transform(cam, &P, &D);
+ }
- ray->P = P;
- ray->D = D;
+ ray->P = P;
+ ray->D = D;
#ifdef __RAY_DIFFERENTIALS__
- /* Ray differentials, computed from scratch using the raster coordinates
- * because we don't want to be affected by depth of field. We compute
- * ray origin and direction for the center and two neighbouring pixels
- * and simply take their differences. */
- float3 Pcenter = Pcamera;
- float3 Dcenter = panorama_to_direction(cam, Pcenter.x, Pcenter.y);
- Pcenter = transform_point(&cameratoworld, Pcenter);
- Dcenter = normalize(transform_direction(&cameratoworld, Dcenter));
- if(use_stereo) {
- spherical_stereo_transform(cam, &Pcenter, &Dcenter);
- }
-
- float3 Px = transform_perspective(&rastertocamera, make_float3(raster_x + 1.0f, raster_y, 0.0f));
- float3 Dx = panorama_to_direction(cam, Px.x, Px.y);
- Px = transform_point(&cameratoworld, Px);
- Dx = normalize(transform_direction(&cameratoworld, Dx));
- if(use_stereo) {
- spherical_stereo_transform(cam, &Px, &Dx);
- }
-
- ray->dP.dx = Px - Pcenter;
- ray->dD.dx = Dx - Dcenter;
-
- float3 Py = transform_perspective(&rastertocamera, make_float3(raster_x, raster_y + 1.0f, 0.0f));
- float3 Dy = panorama_to_direction(cam, Py.x, Py.y);
- Py = transform_point(&cameratoworld, Py);
- Dy = normalize(transform_direction(&cameratoworld, Dy));
- if(use_stereo) {
- spherical_stereo_transform(cam, &Py, &Dy);
- }
-
- ray->dP.dy = Py - Pcenter;
- ray->dD.dy = Dy - Dcenter;
+ /* Ray differentials, computed from scratch using the raster coordinates
+ * because we don't want to be affected by depth of field. We compute
+ * ray origin and direction for the center and two neighbouring pixels
+ * and simply take their differences. */
+ float3 Pcenter = Pcamera;
+ float3 Dcenter = panorama_to_direction(cam, Pcenter.x, Pcenter.y);
+ Pcenter = transform_point(&cameratoworld, Pcenter);
+ Dcenter = normalize(transform_direction(&cameratoworld, Dcenter));
+ if (use_stereo) {
+ spherical_stereo_transform(cam, &Pcenter, &Dcenter);
+ }
+
+ float3 Px = transform_perspective(&rastertocamera, make_float3(raster_x + 1.0f, raster_y, 0.0f));
+ float3 Dx = panorama_to_direction(cam, Px.x, Px.y);
+ Px = transform_point(&cameratoworld, Px);
+ Dx = normalize(transform_direction(&cameratoworld, Dx));
+ if (use_stereo) {
+ spherical_stereo_transform(cam, &Px, &Dx);
+ }
+
+ ray->dP.dx = Px - Pcenter;
+ ray->dD.dx = Dx - Dcenter;
+
+ float3 Py = transform_perspective(&rastertocamera, make_float3(raster_x, raster_y + 1.0f, 0.0f));
+ float3 Dy = panorama_to_direction(cam, Py.x, Py.y);
+ Py = transform_point(&cameratoworld, Py);
+ Dy = normalize(transform_direction(&cameratoworld, Dy));
+ if (use_stereo) {
+ spherical_stereo_transform(cam, &Py, &Dy);
+ }
+
+ ray->dP.dy = Py - Pcenter;
+ ray->dD.dy = Dy - Dcenter;
#endif
#ifdef __CAMERA_CLIPPING__
- /* clipping */
- float nearclip = cam->nearclip;
- ray->P += nearclip * ray->D;
- ray->dP.dx += nearclip * ray->dD.dx;
- ray->dP.dy += nearclip * ray->dD.dy;
- ray->t = cam->cliplength;
+ /* clipping */
+ float nearclip = cam->nearclip;
+ ray->P += nearclip * ray->D;
+ ray->dP.dx += nearclip * ray->dD.dx;
+ ray->dP.dy += nearclip * ray->dD.dy;
+ ray->t = cam->cliplength;
#else
- ray->t = FLT_MAX;
+ ray->t = FLT_MAX;
#endif
}
/* Common */
ccl_device_inline void camera_sample(KernelGlobals *kg,
- int x, int y,
- float filter_u, float filter_v,
- float lens_u, float lens_v,
+ int x,
+ int y,
+ float filter_u,
+ float filter_v,
+ float lens_u,
+ float lens_v,
float time,
ccl_addr_space Ray *ray)
{
- /* pixel filter */
- int filter_table_offset = kernel_data.film.filter_table_offset;
- float raster_x = x + lookup_table_read(kg, filter_u, filter_table_offset, FILTER_TABLE_SIZE);
- float raster_y = y + lookup_table_read(kg, filter_v, filter_table_offset, FILTER_TABLE_SIZE);
+ /* pixel filter */
+ int filter_table_offset = kernel_data.film.filter_table_offset;
+ float raster_x = x + lookup_table_read(kg, filter_u, filter_table_offset, FILTER_TABLE_SIZE);
+ float raster_y = y + lookup_table_read(kg, filter_v, filter_table_offset, FILTER_TABLE_SIZE);
#ifdef __CAMERA_MOTION__
- /* motion blur */
- if(kernel_data.cam.shuttertime == -1.0f) {
- ray->time = 0.5f;
- }
- else {
- /* TODO(sergey): Such lookup is unneeded when there's rolling shutter
- * effect in use but rolling shutter duration is set to 0.0.
- */
- const int shutter_table_offset = kernel_data.cam.shutter_table_offset;
- ray->time = lookup_table_read(kg, time, shutter_table_offset, SHUTTER_TABLE_SIZE);
- /* TODO(sergey): Currently single rolling shutter effect type only
- * where scanlines are acquired from top to bottom and whole scanline
- * is acquired at once (no delay in acquisition happens between pixels
- * of single scanline).
- *
- * Might want to support more models in the future.
- */
- if(kernel_data.cam.rolling_shutter_type) {
- /* Time corresponding to a fully rolling shutter only effect:
- * top of the frame is time 0.0, bottom of the frame is time 1.0.
- */
- const float time = 1.0f - (float)y / kernel_data.cam.height;
- const float duration = kernel_data.cam.rolling_shutter_duration;
- if(duration != 0.0f) {
- /* This isn't fully physical correct, but lets us to have simple
- * controls in the interface. The idea here is basically sort of
- * linear interpolation between how much rolling shutter effect
- * exist on the frame and how much of it is a motion blur effect.
- */
- ray->time = (ray->time - 0.5f) * duration;
- ray->time += (time - 0.5f) * (1.0f - duration) + 0.5f;
- }
- else {
- ray->time = time;
- }
- }
- }
+ /* motion blur */
+ if (kernel_data.cam.shuttertime == -1.0f) {
+ ray->time = 0.5f;
+ }
+ else {
+ /* TODO(sergey): Such lookup is unneeded when there's rolling shutter
+ * effect in use but rolling shutter duration is set to 0.0.
+ */
+ const int shutter_table_offset = kernel_data.cam.shutter_table_offset;
+ ray->time = lookup_table_read(kg, time, shutter_table_offset, SHUTTER_TABLE_SIZE);
+ /* TODO(sergey): Currently single rolling shutter effect type only
+ * where scanlines are acquired from top to bottom and whole scanline
+ * is acquired at once (no delay in acquisition happens between pixels
+ * of single scanline).
+ *
+ * Might want to support more models in the future.
+ */
+ if (kernel_data.cam.rolling_shutter_type) {
+ /* Time corresponding to a fully rolling shutter only effect:
+ * top of the frame is time 0.0, bottom of the frame is time 1.0.
+ */
+ const float time = 1.0f - (float)y / kernel_data.cam.height;
+ const float duration = kernel_data.cam.rolling_shutter_duration;
+ if (duration != 0.0f) {
+ /* This isn't fully physical correct, but lets us to have simple
+ * controls in the interface. The idea here is basically sort of
+ * linear interpolation between how much rolling shutter effect
+ * exist on the frame and how much of it is a motion blur effect.
+ */
+ ray->time = (ray->time - 0.5f) * duration;
+ ray->time += (time - 0.5f) * (1.0f - duration) + 0.5f;
+ }
+ else {
+ ray->time = time;
+ }
+ }
+ }
#endif
- /* sample */
- if(kernel_data.cam.type == CAMERA_PERSPECTIVE) {
- camera_sample_perspective(kg, raster_x, raster_y, lens_u, lens_v, ray);
- }
- else if(kernel_data.cam.type == CAMERA_ORTHOGRAPHIC) {
- camera_sample_orthographic(kg, raster_x, raster_y, lens_u, lens_v, ray);
- }
- else {
- const ccl_global DecomposedTransform *cam_motion = kernel_tex_array(__camera_motion);
- camera_sample_panorama(&kernel_data.cam, cam_motion, raster_x, raster_y, lens_u, lens_v, ray);
- }
+ /* sample */
+ if (kernel_data.cam.type == CAMERA_PERSPECTIVE) {
+ camera_sample_perspective(kg, raster_x, raster_y, lens_u, lens_v, ray);
+ }
+ else if (kernel_data.cam.type == CAMERA_ORTHOGRAPHIC) {
+ camera_sample_orthographic(kg, raster_x, raster_y, lens_u, lens_v, ray);
+ }
+ else {
+ const ccl_global DecomposedTransform *cam_motion = kernel_tex_array(__camera_motion);
+ camera_sample_panorama(&kernel_data.cam, cam_motion, raster_x, raster_y, lens_u, lens_v, ray);
+ }
}
/* Utilities */
ccl_device_inline float3 camera_position(KernelGlobals *kg)
{
- Transform cameratoworld = kernel_data.cam.cameratoworld;
- return make_float3(cameratoworld.x.w, cameratoworld.y.w, cameratoworld.z.w);
+ Transform cameratoworld = kernel_data.cam.cameratoworld;
+ return make_float3(cameratoworld.x.w, cameratoworld.y.w, cameratoworld.z.w);
}
ccl_device_inline float camera_distance(KernelGlobals *kg, float3 P)
{
- Transform cameratoworld = kernel_data.cam.cameratoworld;
- float3 camP = make_float3(cameratoworld.x.w, cameratoworld.y.w, cameratoworld.z.w);
-
- if(kernel_data.cam.type == CAMERA_ORTHOGRAPHIC) {
- float3 camD = make_float3(cameratoworld.x.z, cameratoworld.y.z, cameratoworld.z.z);
- return fabsf(dot((P - camP), camD));
- }
- else
- return len(P - camP);
+ Transform cameratoworld = kernel_data.cam.cameratoworld;
+ float3 camP = make_float3(cameratoworld.x.w, cameratoworld.y.w, cameratoworld.z.w);
+
+ if (kernel_data.cam.type == CAMERA_ORTHOGRAPHIC) {
+ float3 camD = make_float3(cameratoworld.x.z, cameratoworld.y.z, cameratoworld.z.z);
+ return fabsf(dot((P - camP), camD));
+ }
+ else
+ return len(P - camP);
}
ccl_device_inline float3 camera_direction_from_point(KernelGlobals *kg, float3 P)
{
- Transform cameratoworld = kernel_data.cam.cameratoworld;
-
- if(kernel_data.cam.type == CAMERA_ORTHOGRAPHIC) {
- float3 camD = make_float3(cameratoworld.x.z, cameratoworld.y.z, cameratoworld.z.z);
- return -camD;
- }
- else {
- float3 camP = make_float3(cameratoworld.x.w, cameratoworld.y.w, cameratoworld.z.w);
- return normalize(camP - P);
- }
+ Transform cameratoworld = kernel_data.cam.cameratoworld;
+
+ if (kernel_data.cam.type == CAMERA_ORTHOGRAPHIC) {
+ float3 camD = make_float3(cameratoworld.x.z, cameratoworld.y.z, cameratoworld.z.z);
+ return -camD;
+ }
+ else {
+ float3 camP = make_float3(cameratoworld.x.w, cameratoworld.y.w, cameratoworld.z.w);
+ return normalize(camP - P);
+ }
}
ccl_device_inline float3 camera_world_to_ndc(KernelGlobals *kg, ShaderData *sd, float3 P)
{
- if(kernel_data.cam.type != CAMERA_PANORAMA) {
- /* perspective / ortho */
- if(sd->object == PRIM_NONE && kernel_data.cam.type == CAMERA_PERSPECTIVE)
- P += camera_position(kg);
-
- ProjectionTransform tfm = kernel_data.cam.worldtondc;
- return transform_perspective(&tfm, P);
- }
- else {
- /* panorama */
- Transform tfm = kernel_data.cam.worldtocamera;
-
- if(sd->object != OBJECT_NONE)
- P = normalize(transform_point(&tfm, P));
- else
- P = normalize(transform_direction(&tfm, P));
-
- float2 uv = direction_to_panorama(&kernel_data.cam, P);
-
- return make_float3(uv.x, uv.y, 0.0f);
- }
+ if (kernel_data.cam.type != CAMERA_PANORAMA) {
+ /* perspective / ortho */
+ if (sd->object == PRIM_NONE && kernel_data.cam.type == CAMERA_PERSPECTIVE)
+ P += camera_position(kg);
+
+ ProjectionTransform tfm = kernel_data.cam.worldtondc;
+ return transform_perspective(&tfm, P);
+ }
+ else {
+ /* panorama */
+ Transform tfm = kernel_data.cam.worldtocamera;
+
+ if (sd->object != OBJECT_NONE)
+ P = normalize(transform_point(&tfm, P));
+ else
+ P = normalize(transform_direction(&tfm, P));
+
+ float2 uv = direction_to_panorama(&kernel_data.cam, P);
+
+ return make_float3(uv.x, uv.y, 0.0f);
+ }
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/kernel_color.h b/intern/cycles/kernel/kernel_color.h
index ea478a8a5d3..5eb1bdad02e 100644
--- a/intern/cycles/kernel/kernel_color.h
+++ b/intern/cycles/kernel/kernel_color.h
@@ -23,16 +23,16 @@ CCL_NAMESPACE_BEGIN
ccl_device float3 xyz_to_rgb(KernelGlobals *kg, float3 xyz)
{
- return make_float3(dot(float4_to_float3(kernel_data.film.xyz_to_r), xyz),
- dot(float4_to_float3(kernel_data.film.xyz_to_g), xyz),
- dot(float4_to_float3(kernel_data.film.xyz_to_b), xyz));
+ return make_float3(dot(float4_to_float3(kernel_data.film.xyz_to_r), xyz),
+ dot(float4_to_float3(kernel_data.film.xyz_to_g), xyz),
+ dot(float4_to_float3(kernel_data.film.xyz_to_b), xyz));
}
ccl_device float linear_rgb_to_gray(KernelGlobals *kg, float3 c)
{
- return dot(c, float4_to_float3(kernel_data.film.rgb_to_y));
+ return dot(c, float4_to_float3(kernel_data.film.rgb_to_y));
}
CCL_NAMESPACE_END
-#endif /* __KERNEL_COLOR_H__ */
+#endif /* __KERNEL_COLOR_H__ */
diff --git a/intern/cycles/kernel/kernel_compat_cpu.h b/intern/cycles/kernel/kernel_compat_cpu.h
index 4ee80850402..e8fedca4489 100644
--- a/intern/cycles/kernel/kernel_compat_cpu.h
+++ b/intern/cycles/kernel/kernel_compat_cpu.h
@@ -55,9 +55,9 @@
/* On x86_64, versions of glibc < 2.16 have an issue where expf is
* much slower than the double version. This was fixed in glibc 2.16.
*/
-#if !defined(__KERNEL_GPU__) && defined(__x86_64__) && defined(__x86_64__) && \
- defined(__GNU_LIBRARY__) && defined(__GLIBC__ ) && defined(__GLIBC_MINOR__) && \
- (__GLIBC__ <= 2 && __GLIBC_MINOR__ < 16)
+#if !defined(__KERNEL_GPU__) && defined(__x86_64__) && defined(__x86_64__) && \
+ defined(__GNU_LIBRARY__) && defined(__GLIBC__) && defined(__GLIBC_MINOR__) && \
+ (__GLIBC__ <= 2 && __GLIBC_MINOR__ < 16)
# define expf(x) ((float)exp((double)(x)))
#endif
@@ -71,41 +71,41 @@ CCL_NAMESPACE_BEGIN
/* Texture types to be compatible with CUDA textures. These are really just
* simple arrays and after inlining fetch hopefully revert to being a simple
* pointer lookup. */
-template<typename T> struct texture {
- ccl_always_inline const T& fetch(int index)
- {
- kernel_assert(index >= 0 && index < width);
- return data[index];
- }
+template<typename T> struct texture {
+ ccl_always_inline const T &fetch(int index)
+ {
+ kernel_assert(index >= 0 && index < width);
+ return data[index];
+ }
#if defined(__KERNEL_AVX__) || defined(__KERNEL_AVX2__)
- /* Reads 256 bytes but indexes in blocks of 128 bytes to maintain
- * compatibility with existing indicies and data structures.
- */
- ccl_always_inline avxf fetch_avxf(const int index)
- {
- kernel_assert(index >= 0 && (index+1) < width);
- ssef *ssef_data = (ssef*)data;
- ssef *ssef_node_data = &ssef_data[index];
- return _mm256_loadu_ps((float *)ssef_node_data);
- }
+ /* Reads 256 bytes but indexes in blocks of 128 bytes to maintain
+ * compatibility with existing indicies and data structures.
+ */
+ ccl_always_inline avxf fetch_avxf(const int index)
+ {
+ kernel_assert(index >= 0 && (index + 1) < width);
+ ssef *ssef_data = (ssef *)data;
+ ssef *ssef_node_data = &ssef_data[index];
+ return _mm256_loadu_ps((float *)ssef_node_data);
+ }
#endif
#ifdef __KERNEL_SSE2__
- ccl_always_inline ssef fetch_ssef(int index)
- {
- kernel_assert(index >= 0 && index < width);
- return ((ssef*)data)[index];
- }
-
- ccl_always_inline ssei fetch_ssei(int index)
- {
- kernel_assert(index >= 0 && index < width);
- return ((ssei*)data)[index];
- }
+ ccl_always_inline ssef fetch_ssef(int index)
+ {
+ kernel_assert(index >= 0 && index < width);
+ return ((ssef *)data)[index];
+ }
+
+ ccl_always_inline ssei fetch_ssei(int index)
+ {
+ kernel_assert(index >= 0 && index < width);
+ return ((ssei *)data)[index];
+ }
#endif
- T *data;
- int width;
+ T *data;
+ int width;
};
/* Macros to handle different memory storage on different devices */
@@ -124,33 +124,33 @@ typedef vector3<sseb> sse3b;
typedef vector3<ssef> sse3f;
typedef vector3<ssei> sse3i;
-ccl_device_inline void print_sse3b(const char *label, sse3b& a)
+ccl_device_inline void print_sse3b(const char *label, sse3b &a)
{
- print_sseb(label, a.x);
- print_sseb(label, a.y);
- print_sseb(label, a.z);
+ print_sseb(label, a.x);
+ print_sseb(label, a.y);
+ print_sseb(label, a.z);
}
-ccl_device_inline void print_sse3f(const char *label, sse3f& a)
+ccl_device_inline void print_sse3f(const char *label, sse3f &a)
{
- print_ssef(label, a.x);
- print_ssef(label, a.y);
- print_ssef(label, a.z);
+ print_ssef(label, a.x);
+ print_ssef(label, a.y);
+ print_ssef(label, a.z);
}
-ccl_device_inline void print_sse3i(const char *label, sse3i& a)
+ccl_device_inline void print_sse3i(const char *label, sse3i &a)
{
- print_ssei(label, a.x);
- print_ssei(label, a.y);
- print_ssei(label, a.z);
+ print_ssei(label, a.x);
+ print_ssei(label, a.y);
+ print_ssei(label, a.z);
}
-#if defined(__KERNEL_AVX__) || defined(__KERNEL_AVX2__)
+# if defined(__KERNEL_AVX__) || defined(__KERNEL_AVX2__)
typedef vector3<avxf> avx3f;
-#endif
+# endif
#endif
CCL_NAMESPACE_END
-#endif /* __KERNEL_COMPAT_CPU_H__ */
+#endif /* __KERNEL_COMPAT_CPU_H__ */
diff --git a/intern/cycles/kernel/kernel_compat_cuda.h b/intern/cycles/kernel/kernel_compat_cuda.h
index 8ed96bbae64..469b81d120b 100644
--- a/intern/cycles/kernel/kernel_compat_cuda.h
+++ b/intern/cycles/kernel/kernel_compat_cuda.h
@@ -42,22 +42,22 @@ typedef unsigned long long CUtexObject;
__device__ half __float2half(const float f)
{
- half val;
- asm("{ cvt.rn.f16.f32 %0, %1;}\n" : "=h"(val) : "f"(f));
- return val;
+ half val;
+ asm("{ cvt.rn.f16.f32 %0, %1;}\n" : "=h"(val) : "f"(f));
+ return val;
}
/* Qualifier wrappers for different names on different devices */
-#define ccl_device __device__ __inline__
+#define ccl_device __device__ __inline__
#if __CUDA_ARCH__ < 500
-# define ccl_device_inline __device__ __forceinline__
-# define ccl_device_forceinline __device__ __forceinline__
+# define ccl_device_inline __device__ __forceinline__
+# define ccl_device_forceinline __device__ __forceinline__
#else
-# define ccl_device_inline __device__ __inline__
-# define ccl_device_forceinline __device__ __forceinline__
+# define ccl_device_inline __device__ __inline__
+# define ccl_device_forceinline __device__ __forceinline__
#endif
-#define ccl_device_noinline __device__ __noinline__
+#define ccl_device_noinline __device__ __noinline__
#define ccl_global
#define ccl_static_constant __constant__
#define ccl_constant const
@@ -75,8 +75,7 @@ __device__ half __float2half(const float f)
#define ATTR_FALLTHROUGH
-#define CCL_MAX_LOCAL_SIZE (CUDA_THREADS_BLOCK_WIDTH*CUDA_THREADS_BLOCK_WIDTH)
-
+#define CCL_MAX_LOCAL_SIZE (CUDA_THREADS_BLOCK_WIDTH * CUDA_THREADS_BLOCK_WIDTH)
/* No assert supported for CUDA */
@@ -91,46 +90,62 @@ __device__ half __float2half(const float f)
ccl_device_inline uint ccl_local_id(uint d)
{
- switch(d) {
- case 0: return threadIdx.x;
- case 1: return threadIdx.y;
- case 2: return threadIdx.z;
- default: return 0;
- }
+ switch (d) {
+ case 0:
+ return threadIdx.x;
+ case 1:
+ return threadIdx.y;
+ case 2:
+ return threadIdx.z;
+ default:
+ return 0;
+ }
}
#define ccl_global_id(d) (ccl_group_id(d) * ccl_local_size(d) + ccl_local_id(d))
ccl_device_inline uint ccl_local_size(uint d)
{
- switch(d) {
- case 0: return blockDim.x;
- case 1: return blockDim.y;
- case 2: return blockDim.z;
- default: return 0;
- }
+ switch (d) {
+ case 0:
+ return blockDim.x;
+ case 1:
+ return blockDim.y;
+ case 2:
+ return blockDim.z;
+ default:
+ return 0;
+ }
}
#define ccl_global_size(d) (ccl_num_groups(d) * ccl_local_size(d))
ccl_device_inline uint ccl_group_id(uint d)
{
- switch(d) {
- case 0: return blockIdx.x;
- case 1: return blockIdx.y;
- case 2: return blockIdx.z;
- default: return 0;
- }
+ switch (d) {
+ case 0:
+ return blockIdx.x;
+ case 1:
+ return blockIdx.y;
+ case 2:
+ return blockIdx.z;
+ default:
+ return 0;
+ }
}
ccl_device_inline uint ccl_num_groups(uint d)
{
- switch(d) {
- case 0: return gridDim.x;
- case 1: return gridDim.y;
- case 2: return gridDim.z;
- default: return 0;
- }
+ switch (d) {
+ case 0:
+ return gridDim.x;
+ case 1:
+ return gridDim.y;
+ case 2:
+ return gridDim.z;
+ default:
+ return 0;
+ }
}
/* Textures */
@@ -150,4 +165,4 @@ ccl_device_inline uint ccl_num_groups(uint d)
#define logf(x) __logf(((float)(x)))
#define expf(x) __expf(((float)(x)))
-#endif /* __KERNEL_COMPAT_CUDA_H__ */
+#endif /* __KERNEL_COMPAT_CUDA_H__ */
diff --git a/intern/cycles/kernel/kernel_compat_opencl.h b/intern/cycles/kernel/kernel_compat_opencl.h
index d3d0934a626..e040ea88d7c 100644
--- a/intern/cycles/kernel/kernel_compat_opencl.h
+++ b/intern/cycles/kernel/kernel_compat_opencl.h
@@ -134,7 +134,7 @@
# define expf(x) native_exp(((float)(x)))
# define sqrtf(x) native_sqrt(((float)(x)))
# define logf(x) native_log(((float)(x)))
-# define rcp(x) native_recip(x)
+# define rcp(x) native_recip(x)
#else
# define sinf(x) sin(((float)(x)))
# define cosf(x) cos(((float)(x)))
@@ -142,12 +142,13 @@
# define expf(x) exp(((float)(x)))
# define sqrtf(x) sqrt(((float)(x)))
# define logf(x) log(((float)(x)))
-# define rcp(x) recip(x)
+# define rcp(x) recip(x)
#endif
/* data lookup defines */
#define kernel_data (*kg->data)
-#define kernel_tex_array(tex) ((const ccl_global tex##_t*)(kg->buffers[kg->tex.cl_buffer] + kg->tex.data))
+#define kernel_tex_array(tex) \
+ ((const ccl_global tex##_t *)(kg->buffers[kg->tex.cl_buffer] + kg->tex.data))
#define kernel_tex_fetch(tex, index) kernel_tex_array(tex)[(index)]
/* define NULL */
@@ -155,10 +156,10 @@
/* enable extensions */
#ifdef __KERNEL_CL_KHR_FP16__
-#pragma OPENCL EXTENSION cl_khr_fp16 : enable
+# pragma OPENCL EXTENSION cl_khr_fp16 : enable
#endif
#include "util/util_half.h"
#include "util/util_types.h"
-#endif /* __KERNEL_COMPAT_OPENCL_H__ */
+#endif /* __KERNEL_COMPAT_OPENCL_H__ */
diff --git a/intern/cycles/kernel/kernel_differential.h b/intern/cycles/kernel/kernel_differential.h
index 924d96c72e5..8513de0d843 100644
--- a/intern/cycles/kernel/kernel_differential.h
+++ b/intern/cycles/kernel/kernel_differential.h
@@ -18,88 +18,98 @@ CCL_NAMESPACE_BEGIN
/* See "Tracing Ray Differentials", Homan Igehy, 1999. */
-ccl_device void differential_transfer(ccl_addr_space differential3 *dP_, const differential3 dP, float3 D, const differential3 dD, float3 Ng, float t)
+ccl_device void differential_transfer(ccl_addr_space differential3 *dP_,
+ const differential3 dP,
+ float3 D,
+ const differential3 dD,
+ float3 Ng,
+ float t)
{
- /* ray differential transfer through homogeneous medium, to
- * compute dPdx/dy at a shading point from the incoming ray */
+ /* ray differential transfer through homogeneous medium, to
+ * compute dPdx/dy at a shading point from the incoming ray */
- float3 tmp = D/dot(D, Ng);
- float3 tmpx = dP.dx + t*dD.dx;
- float3 tmpy = dP.dy + t*dD.dy;
+ float3 tmp = D / dot(D, Ng);
+ float3 tmpx = dP.dx + t * dD.dx;
+ float3 tmpy = dP.dy + t * dD.dy;
- dP_->dx = tmpx - dot(tmpx, Ng)*tmp;
- dP_->dy = tmpy - dot(tmpy, Ng)*tmp;
+ dP_->dx = tmpx - dot(tmpx, Ng) * tmp;
+ dP_->dy = tmpy - dot(tmpy, Ng) * tmp;
}
ccl_device void differential_incoming(ccl_addr_space differential3 *dI, const differential3 dD)
{
- /* compute dIdx/dy at a shading point, we just need to negate the
- * differential of the ray direction */
+ /* compute dIdx/dy at a shading point, we just need to negate the
+ * differential of the ray direction */
- dI->dx = -dD.dx;
- dI->dy = -dD.dy;
+ dI->dx = -dD.dx;
+ dI->dy = -dD.dy;
}
-ccl_device void differential_dudv(ccl_addr_space differential *du, ccl_addr_space differential *dv, float3 dPdu, float3 dPdv, differential3 dP, float3 Ng)
+ccl_device void differential_dudv(ccl_addr_space differential *du,
+ ccl_addr_space differential *dv,
+ float3 dPdu,
+ float3 dPdv,
+ differential3 dP,
+ float3 Ng)
{
- /* now we have dPdx/dy from the ray differential transfer, and dPdu/dv
- * from the primitive, we can compute dudx/dy and dvdx/dy. these are
- * mainly used for differentials of arbitrary mesh attributes. */
-
- /* find most stable axis to project to 2D */
- float xn = fabsf(Ng.x);
- float yn = fabsf(Ng.y);
- float zn = fabsf(Ng.z);
-
- if(zn < xn || zn < yn) {
- if(yn < xn || yn < zn) {
- dPdu.x = dPdu.y;
- dPdv.x = dPdv.y;
- dP.dx.x = dP.dx.y;
- dP.dy.x = dP.dy.y;
- }
-
- dPdu.y = dPdu.z;
- dPdv.y = dPdv.z;
- dP.dx.y = dP.dx.z;
- dP.dy.y = dP.dy.z;
- }
-
- /* using Cramer's rule, we solve for dudx and dvdx in a 2x2 linear system,
- * and the same for dudy and dvdy. the denominator is the same for both
- * solutions, so we compute it only once.
- *
- * dP.dx = dPdu * dudx + dPdv * dvdx;
- * dP.dy = dPdu * dudy + dPdv * dvdy; */
-
- float det = (dPdu.x*dPdv.y - dPdv.x*dPdu.y);
-
- if(det != 0.0f)
- det = 1.0f/det;
-
- du->dx = (dP.dx.x*dPdv.y - dP.dx.y*dPdv.x)*det;
- dv->dx = (dP.dx.y*dPdu.x - dP.dx.x*dPdu.y)*det;
-
- du->dy = (dP.dy.x*dPdv.y - dP.dy.y*dPdv.x)*det;
- dv->dy = (dP.dy.y*dPdu.x - dP.dy.x*dPdu.y)*det;
+ /* now we have dPdx/dy from the ray differential transfer, and dPdu/dv
+ * from the primitive, we can compute dudx/dy and dvdx/dy. these are
+ * mainly used for differentials of arbitrary mesh attributes. */
+
+ /* find most stable axis to project to 2D */
+ float xn = fabsf(Ng.x);
+ float yn = fabsf(Ng.y);
+ float zn = fabsf(Ng.z);
+
+ if (zn < xn || zn < yn) {
+ if (yn < xn || yn < zn) {
+ dPdu.x = dPdu.y;
+ dPdv.x = dPdv.y;
+ dP.dx.x = dP.dx.y;
+ dP.dy.x = dP.dy.y;
+ }
+
+ dPdu.y = dPdu.z;
+ dPdv.y = dPdv.z;
+ dP.dx.y = dP.dx.z;
+ dP.dy.y = dP.dy.z;
+ }
+
+ /* using Cramer's rule, we solve for dudx and dvdx in a 2x2 linear system,
+ * and the same for dudy and dvdy. the denominator is the same for both
+ * solutions, so we compute it only once.
+ *
+ * dP.dx = dPdu * dudx + dPdv * dvdx;
+ * dP.dy = dPdu * dudy + dPdv * dvdy; */
+
+ float det = (dPdu.x * dPdv.y - dPdv.x * dPdu.y);
+
+ if (det != 0.0f)
+ det = 1.0f / det;
+
+ du->dx = (dP.dx.x * dPdv.y - dP.dx.y * dPdv.x) * det;
+ dv->dx = (dP.dx.y * dPdu.x - dP.dx.x * dPdu.y) * det;
+
+ du->dy = (dP.dy.x * dPdv.y - dP.dy.y * dPdv.x) * det;
+ dv->dy = (dP.dy.y * dPdu.x - dP.dy.x * dPdu.y) * det;
}
ccl_device differential differential_zero()
{
- differential d;
- d.dx = 0.0f;
- d.dy = 0.0f;
+ differential d;
+ d.dx = 0.0f;
+ d.dy = 0.0f;
- return d;
+ return d;
}
ccl_device differential3 differential3_zero()
{
- differential3 d;
- d.dx = make_float3(0.0f, 0.0f, 0.0f);
- d.dy = make_float3(0.0f, 0.0f, 0.0f);
+ differential3 d;
+ d.dx = make_float3(0.0f, 0.0f, 0.0f);
+ d.dy = make_float3(0.0f, 0.0f, 0.0f);
- return d;
+ return d;
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/kernel_emission.h b/intern/cycles/kernel/kernel_emission.h
index 80bb8d48caf..f2eaa7b50a5 100644
--- a/intern/cycles/kernel/kernel_emission.h
+++ b/intern/cycles/kernel/kernel_emission.h
@@ -26,61 +26,71 @@ ccl_device_noinline float3 direct_emissive_eval(KernelGlobals *kg,
float t,
float time)
{
- /* setup shading at emitter */
- float3 eval;
-
- if(shader_constant_emission_eval(kg, ls->shader, &eval)) {
- if((ls->prim != PRIM_NONE) && dot(ls->Ng, I) < 0.0f) {
- ls->Ng = -ls->Ng;
- }
- }
- else {
- /* Setup shader data and call shader_eval_surface once, better
- * for GPU coherence and compile times. */
+ /* setup shading at emitter */
+ float3 eval;
+
+ if (shader_constant_emission_eval(kg, ls->shader, &eval)) {
+ if ((ls->prim != PRIM_NONE) && dot(ls->Ng, I) < 0.0f) {
+ ls->Ng = -ls->Ng;
+ }
+ }
+ else {
+ /* Setup shader data and call shader_eval_surface once, better
+ * for GPU coherence and compile times. */
#ifdef __BACKGROUND_MIS__
- if(ls->type == LIGHT_BACKGROUND) {
- Ray ray;
- ray.D = ls->D;
- ray.P = ls->P;
- ray.t = 1.0f;
- ray.time = time;
- ray.dP = differential3_zero();
- ray.dD = dI;
-
- shader_setup_from_background(kg, emission_sd, &ray);
- }
- else
+ if (ls->type == LIGHT_BACKGROUND) {
+ Ray ray;
+ ray.D = ls->D;
+ ray.P = ls->P;
+ ray.t = 1.0f;
+ ray.time = time;
+ ray.dP = differential3_zero();
+ ray.dD = dI;
+
+ shader_setup_from_background(kg, emission_sd, &ray);
+ }
+ else
#endif
- {
- shader_setup_from_sample(kg, emission_sd,
- ls->P, ls->Ng, I,
- ls->shader, ls->object, ls->prim,
- ls->u, ls->v, t, time, false, ls->lamp);
-
- ls->Ng = emission_sd->Ng;
- }
-
- /* No proper path flag, we're evaluating this for all closures. that's
- * weak but we'd have to do multiple evaluations otherwise. */
- path_state_modify_bounce(state, true);
- shader_eval_surface(kg, emission_sd, state, PATH_RAY_EMISSION);
- path_state_modify_bounce(state, false);
-
- /* Evaluate closures. */
+ {
+ shader_setup_from_sample(kg,
+ emission_sd,
+ ls->P,
+ ls->Ng,
+ I,
+ ls->shader,
+ ls->object,
+ ls->prim,
+ ls->u,
+ ls->v,
+ t,
+ time,
+ false,
+ ls->lamp);
+
+ ls->Ng = emission_sd->Ng;
+ }
+
+ /* No proper path flag, we're evaluating this for all closures. that's
+ * weak but we'd have to do multiple evaluations otherwise. */
+ path_state_modify_bounce(state, true);
+ shader_eval_surface(kg, emission_sd, state, PATH_RAY_EMISSION);
+ path_state_modify_bounce(state, false);
+
+ /* Evaluate closures. */
#ifdef __BACKGROUND_MIS__
- if (ls->type == LIGHT_BACKGROUND) {
- eval = shader_background_eval(emission_sd);
- }
- else
+ if (ls->type == LIGHT_BACKGROUND) {
+ eval = shader_background_eval(emission_sd);
+ }
+ else
#endif
- {
- eval = shader_emissive_eval(emission_sd);
- }
- }
+ {
+ eval = shader_emissive_eval(emission_sd);
+ }
+ }
- eval *= ls->eval_fac;
+ eval *= ls->eval_fac;
- return eval;
+ return eval;
}
ccl_device_noinline bool direct_emission(KernelGlobals *kg,
@@ -93,132 +103,128 @@ ccl_device_noinline bool direct_emission(KernelGlobals *kg,
bool *is_lamp,
float rand_terminate)
{
- if(ls->pdf == 0.0f)
- return false;
+ if (ls->pdf == 0.0f)
+ return false;
- /* todo: implement */
- differential3 dD = differential3_zero();
+ /* todo: implement */
+ differential3 dD = differential3_zero();
- /* evaluate closure */
+ /* evaluate closure */
- float3 light_eval = direct_emissive_eval(kg,
- emission_sd,
- ls,
- state,
- -ls->D,
- dD,
- ls->t,
- sd->time);
+ float3 light_eval = direct_emissive_eval(
+ kg, emission_sd, ls, state, -ls->D, dD, ls->t, sd->time);
- if(is_zero(light_eval))
- return false;
+ if (is_zero(light_eval))
+ return false;
- /* evaluate BSDF at shading point */
+ /* evaluate BSDF at shading point */
#ifdef __VOLUME__
- if(sd->prim != PRIM_NONE)
- shader_bsdf_eval(kg, sd, ls->D, eval, ls->pdf, ls->shader & SHADER_USE_MIS);
- else {
- float bsdf_pdf;
- shader_volume_phase_eval(kg, sd, ls->D, eval, &bsdf_pdf);
- if(ls->shader & SHADER_USE_MIS) {
- /* Multiple importance sampling. */
- float mis_weight = power_heuristic(ls->pdf, bsdf_pdf);
- light_eval *= mis_weight;
- }
- }
+ if (sd->prim != PRIM_NONE)
+ shader_bsdf_eval(kg, sd, ls->D, eval, ls->pdf, ls->shader & SHADER_USE_MIS);
+ else {
+ float bsdf_pdf;
+ shader_volume_phase_eval(kg, sd, ls->D, eval, &bsdf_pdf);
+ if (ls->shader & SHADER_USE_MIS) {
+ /* Multiple importance sampling. */
+ float mis_weight = power_heuristic(ls->pdf, bsdf_pdf);
+ light_eval *= mis_weight;
+ }
+ }
#else
- shader_bsdf_eval(kg, sd, ls->D, eval, ls->pdf, ls->shader & SHADER_USE_MIS);
+ shader_bsdf_eval(kg, sd, ls->D, eval, ls->pdf, ls->shader & SHADER_USE_MIS);
#endif
- bsdf_eval_mul3(eval, light_eval/ls->pdf);
+ bsdf_eval_mul3(eval, light_eval / ls->pdf);
#ifdef __PASSES__
- /* use visibility flag to skip lights */
- if(ls->shader & SHADER_EXCLUDE_ANY) {
- if(ls->shader & SHADER_EXCLUDE_DIFFUSE) {
- eval->diffuse = make_float3(0.0f, 0.0f, 0.0f);
- eval->subsurface = make_float3(0.0f, 0.0f, 0.0f);
- }
- if(ls->shader & SHADER_EXCLUDE_GLOSSY)
- eval->glossy = make_float3(0.0f, 0.0f, 0.0f);
- if(ls->shader & SHADER_EXCLUDE_TRANSMIT)
- eval->transmission = make_float3(0.0f, 0.0f, 0.0f);
- if(ls->shader & SHADER_EXCLUDE_SCATTER)
- eval->scatter = make_float3(0.0f, 0.0f, 0.0f);
- }
+ /* use visibility flag to skip lights */
+ if (ls->shader & SHADER_EXCLUDE_ANY) {
+ if (ls->shader & SHADER_EXCLUDE_DIFFUSE) {
+ eval->diffuse = make_float3(0.0f, 0.0f, 0.0f);
+ eval->subsurface = make_float3(0.0f, 0.0f, 0.0f);
+ }
+ if (ls->shader & SHADER_EXCLUDE_GLOSSY)
+ eval->glossy = make_float3(0.0f, 0.0f, 0.0f);
+ if (ls->shader & SHADER_EXCLUDE_TRANSMIT)
+ eval->transmission = make_float3(0.0f, 0.0f, 0.0f);
+ if (ls->shader & SHADER_EXCLUDE_SCATTER)
+ eval->scatter = make_float3(0.0f, 0.0f, 0.0f);
+ }
#endif
- if(bsdf_eval_is_zero(eval))
- return false;
+ if (bsdf_eval_is_zero(eval))
+ return false;
- if(kernel_data.integrator.light_inv_rr_threshold > 0.0f
+ if (kernel_data.integrator.light_inv_rr_threshold > 0.0f
#ifdef __SHADOW_TRICKS__
- && (state->flag & PATH_RAY_SHADOW_CATCHER) == 0
+ && (state->flag & PATH_RAY_SHADOW_CATCHER) == 0
#endif
- )
- {
- float probability = max3(fabs(bsdf_eval_sum(eval))) * kernel_data.integrator.light_inv_rr_threshold;
- if(probability < 1.0f) {
- if(rand_terminate >= probability) {
- return false;
- }
- bsdf_eval_mul(eval, 1.0f / probability);
- }
- }
-
- if(ls->shader & SHADER_CAST_SHADOW) {
- /* setup ray */
- bool transmit = (dot(sd->Ng, ls->D) < 0.0f);
- ray->P = ray_offset(sd->P, (transmit)? -sd->Ng: sd->Ng);
-
- if(ls->t == FLT_MAX) {
- /* distant light */
- ray->D = ls->D;
- ray->t = ls->t;
- }
- else {
- /* other lights, avoid self-intersection */
- ray->D = ray_offset(ls->P, ls->Ng) - ray->P;
- ray->D = normalize_len(ray->D, &ray->t);
- }
-
- ray->dP = sd->dP;
- ray->dD = differential3_zero();
- }
- else {
- /* signal to not cast shadow ray */
- ray->t = 0.0f;
- }
-
- /* return if it's a lamp for shadow pass */
- *is_lamp = (ls->prim == PRIM_NONE && ls->type != LIGHT_BACKGROUND);
-
- return true;
+ ) {
+ float probability = max3(fabs(bsdf_eval_sum(eval))) *
+ kernel_data.integrator.light_inv_rr_threshold;
+ if (probability < 1.0f) {
+ if (rand_terminate >= probability) {
+ return false;
+ }
+ bsdf_eval_mul(eval, 1.0f / probability);
+ }
+ }
+
+ if (ls->shader & SHADER_CAST_SHADOW) {
+ /* setup ray */
+ bool transmit = (dot(sd->Ng, ls->D) < 0.0f);
+ ray->P = ray_offset(sd->P, (transmit) ? -sd->Ng : sd->Ng);
+
+ if (ls->t == FLT_MAX) {
+ /* distant light */
+ ray->D = ls->D;
+ ray->t = ls->t;
+ }
+ else {
+ /* other lights, avoid self-intersection */
+ ray->D = ray_offset(ls->P, ls->Ng) - ray->P;
+ ray->D = normalize_len(ray->D, &ray->t);
+ }
+
+ ray->dP = sd->dP;
+ ray->dD = differential3_zero();
+ }
+ else {
+ /* signal to not cast shadow ray */
+ ray->t = 0.0f;
+ }
+
+ /* return if it's a lamp for shadow pass */
+ *is_lamp = (ls->prim == PRIM_NONE && ls->type != LIGHT_BACKGROUND);
+
+ return true;
}
/* Indirect Primitive Emission */
-ccl_device_noinline float3 indirect_primitive_emission(KernelGlobals *kg, ShaderData *sd, float t, int path_flag, float bsdf_pdf)
+ccl_device_noinline float3 indirect_primitive_emission(
+ KernelGlobals *kg, ShaderData *sd, float t, int path_flag, float bsdf_pdf)
{
- /* evaluate emissive closure */
- float3 L = shader_emissive_eval(sd);
+ /* evaluate emissive closure */
+ float3 L = shader_emissive_eval(sd);
#ifdef __HAIR__
- if(!(path_flag & PATH_RAY_MIS_SKIP) && (sd->flag & SD_USE_MIS) && (sd->type & PRIMITIVE_ALL_TRIANGLE))
+ if (!(path_flag & PATH_RAY_MIS_SKIP) && (sd->flag & SD_USE_MIS) &&
+ (sd->type & PRIMITIVE_ALL_TRIANGLE))
#else
- if(!(path_flag & PATH_RAY_MIS_SKIP) && (sd->flag & SD_USE_MIS))
+ if (!(path_flag & PATH_RAY_MIS_SKIP) && (sd->flag & SD_USE_MIS))
#endif
- {
- /* multiple importance sampling, get triangle light pdf,
- * and compute weight with respect to BSDF pdf */
- float pdf = triangle_light_pdf(kg, sd, t);
- float mis_weight = power_heuristic(bsdf_pdf, pdf);
+ {
+ /* multiple importance sampling, get triangle light pdf,
+ * and compute weight with respect to BSDF pdf */
+ float pdf = triangle_light_pdf(kg, sd, t);
+ float mis_weight = power_heuristic(bsdf_pdf, pdf);
- return L*mis_weight;
- }
+ return L * mis_weight;
+ }
- return L;
+ return L;
}
/* Indirect Lamp Emission */
@@ -229,60 +235,55 @@ ccl_device_noinline bool indirect_lamp_emission(KernelGlobals *kg,
Ray *ray,
float3 *emission)
{
- bool hit_lamp = false;
+ bool hit_lamp = false;
- *emission = make_float3(0.0f, 0.0f, 0.0f);
+ *emission = make_float3(0.0f, 0.0f, 0.0f);
- for(int lamp = 0; lamp < kernel_data.integrator.num_all_lights; lamp++) {
- LightSample ls;
+ for (int lamp = 0; lamp < kernel_data.integrator.num_all_lights; lamp++) {
+ LightSample ls;
- if(!lamp_light_eval(kg, lamp, ray->P, ray->D, ray->t, &ls))
- continue;
+ if (!lamp_light_eval(kg, lamp, ray->P, ray->D, ray->t, &ls))
+ continue;
#ifdef __PASSES__
- /* use visibility flag to skip lights */
- if(ls.shader & SHADER_EXCLUDE_ANY) {
- if(((ls.shader & SHADER_EXCLUDE_DIFFUSE) && (state->flag & PATH_RAY_DIFFUSE)) ||
- ((ls.shader & SHADER_EXCLUDE_GLOSSY) &&
- ((state->flag & (PATH_RAY_GLOSSY|PATH_RAY_REFLECT)) == (PATH_RAY_GLOSSY|PATH_RAY_REFLECT))) ||
- ((ls.shader & SHADER_EXCLUDE_TRANSMIT) && (state->flag & PATH_RAY_TRANSMIT)) ||
- ((ls.shader & SHADER_EXCLUDE_SCATTER) && (state->flag & PATH_RAY_VOLUME_SCATTER)))
- continue;
- }
+ /* use visibility flag to skip lights */
+ if (ls.shader & SHADER_EXCLUDE_ANY) {
+ if (((ls.shader & SHADER_EXCLUDE_DIFFUSE) && (state->flag & PATH_RAY_DIFFUSE)) ||
+ ((ls.shader & SHADER_EXCLUDE_GLOSSY) &&
+ ((state->flag & (PATH_RAY_GLOSSY | PATH_RAY_REFLECT)) ==
+ (PATH_RAY_GLOSSY | PATH_RAY_REFLECT))) ||
+ ((ls.shader & SHADER_EXCLUDE_TRANSMIT) && (state->flag & PATH_RAY_TRANSMIT)) ||
+ ((ls.shader & SHADER_EXCLUDE_SCATTER) && (state->flag & PATH_RAY_VOLUME_SCATTER)))
+ continue;
+ }
#endif
- float3 L = direct_emissive_eval(kg,
- emission_sd,
- &ls,
- state,
- -ray->D,
- ray->dD,
- ls.t,
- ray->time);
+ float3 L = direct_emissive_eval(
+ kg, emission_sd, &ls, state, -ray->D, ray->dD, ls.t, ray->time);
#ifdef __VOLUME__
- if(state->volume_stack[0].shader != SHADER_NONE) {
- /* shadow attenuation */
- Ray volume_ray = *ray;
- volume_ray.t = ls.t;
- float3 volume_tp = make_float3(1.0f, 1.0f, 1.0f);
- kernel_volume_shadow(kg, emission_sd, state, &volume_ray, &volume_tp);
- L *= volume_tp;
- }
+ if (state->volume_stack[0].shader != SHADER_NONE) {
+ /* shadow attenuation */
+ Ray volume_ray = *ray;
+ volume_ray.t = ls.t;
+ float3 volume_tp = make_float3(1.0f, 1.0f, 1.0f);
+ kernel_volume_shadow(kg, emission_sd, state, &volume_ray, &volume_tp);
+ L *= volume_tp;
+ }
#endif
- if(!(state->flag & PATH_RAY_MIS_SKIP)) {
- /* multiple importance sampling, get regular light pdf,
- * and compute weight with respect to BSDF pdf */
- float mis_weight = power_heuristic(state->ray_pdf, ls.pdf);
- L *= mis_weight;
- }
+ if (!(state->flag & PATH_RAY_MIS_SKIP)) {
+ /* multiple importance sampling, get regular light pdf,
+ * and compute weight with respect to BSDF pdf */
+ float mis_weight = power_heuristic(state->ray_pdf, ls.pdf);
+ L *= mis_weight;
+ }
- *emission += L;
- hit_lamp = true;
- }
+ *emission += L;
+ hit_lamp = true;
+ }
- return hit_lamp;
+ return hit_lamp;
}
/* Indirect Background */
@@ -293,55 +294,55 @@ ccl_device_noinline float3 indirect_background(KernelGlobals *kg,
ccl_addr_space Ray *ray)
{
#ifdef __BACKGROUND__
- int shader = kernel_data.background.surface_shader;
-
- /* Use visibility flag to skip lights. */
- if(shader & SHADER_EXCLUDE_ANY) {
- if(((shader & SHADER_EXCLUDE_DIFFUSE) && (state->flag & PATH_RAY_DIFFUSE)) ||
- ((shader & SHADER_EXCLUDE_GLOSSY) &&
- ((state->flag & (PATH_RAY_GLOSSY|PATH_RAY_REFLECT)) == (PATH_RAY_GLOSSY|PATH_RAY_REFLECT))) ||
- ((shader & SHADER_EXCLUDE_TRANSMIT) && (state->flag & PATH_RAY_TRANSMIT)) ||
- ((shader & SHADER_EXCLUDE_CAMERA) && (state->flag & PATH_RAY_CAMERA)) ||
- ((shader & SHADER_EXCLUDE_SCATTER) && (state->flag & PATH_RAY_VOLUME_SCATTER)))
- return make_float3(0.0f, 0.0f, 0.0f);
- }
-
-
- /* Evaluate background shader. */
- float3 L;
- if(!shader_constant_emission_eval(kg, shader, &L)) {
+ int shader = kernel_data.background.surface_shader;
+
+ /* Use visibility flag to skip lights. */
+ if (shader & SHADER_EXCLUDE_ANY) {
+ if (((shader & SHADER_EXCLUDE_DIFFUSE) && (state->flag & PATH_RAY_DIFFUSE)) ||
+ ((shader & SHADER_EXCLUDE_GLOSSY) &&
+ ((state->flag & (PATH_RAY_GLOSSY | PATH_RAY_REFLECT)) ==
+ (PATH_RAY_GLOSSY | PATH_RAY_REFLECT))) ||
+ ((shader & SHADER_EXCLUDE_TRANSMIT) && (state->flag & PATH_RAY_TRANSMIT)) ||
+ ((shader & SHADER_EXCLUDE_CAMERA) && (state->flag & PATH_RAY_CAMERA)) ||
+ ((shader & SHADER_EXCLUDE_SCATTER) && (state->flag & PATH_RAY_VOLUME_SCATTER)))
+ return make_float3(0.0f, 0.0f, 0.0f);
+ }
+
+ /* Evaluate background shader. */
+ float3 L;
+ if (!shader_constant_emission_eval(kg, shader, &L)) {
# ifdef __SPLIT_KERNEL__
- Ray priv_ray = *ray;
- shader_setup_from_background(kg, emission_sd, &priv_ray);
+ Ray priv_ray = *ray;
+ shader_setup_from_background(kg, emission_sd, &priv_ray);
# else
- shader_setup_from_background(kg, emission_sd, ray);
+ shader_setup_from_background(kg, emission_sd, ray);
# endif
- path_state_modify_bounce(state, true);
- shader_eval_surface(kg, emission_sd, state, state->flag | PATH_RAY_EMISSION);
- path_state_modify_bounce(state, false);
+ path_state_modify_bounce(state, true);
+ shader_eval_surface(kg, emission_sd, state, state->flag | PATH_RAY_EMISSION);
+ path_state_modify_bounce(state, false);
- L = shader_background_eval(emission_sd);
- }
+ L = shader_background_eval(emission_sd);
+ }
- /* Background MIS weights. */
-#ifdef __BACKGROUND_MIS__
- /* Check if background light exists or if we should skip pdf. */
- int res_x = kernel_data.integrator.pdf_background_res_x;
+ /* Background MIS weights. */
+# ifdef __BACKGROUND_MIS__
+ /* Check if background light exists or if we should skip pdf. */
+ int res_x = kernel_data.integrator.pdf_background_res_x;
- if(!(state->flag & PATH_RAY_MIS_SKIP) && res_x) {
- /* multiple importance sampling, get background light pdf for ray
- * direction, and compute weight with respect to BSDF pdf */
- float pdf = background_light_pdf(kg, ray->P, ray->D);
- float mis_weight = power_heuristic(state->ray_pdf, pdf);
+ if (!(state->flag & PATH_RAY_MIS_SKIP) && res_x) {
+ /* multiple importance sampling, get background light pdf for ray
+ * direction, and compute weight with respect to BSDF pdf */
+ float pdf = background_light_pdf(kg, ray->P, ray->D);
+ float mis_weight = power_heuristic(state->ray_pdf, pdf);
- return L*mis_weight;
- }
-#endif
+ return L * mis_weight;
+ }
+# endif
- return L;
+ return L;
#else
- return make_float3(0.8f, 0.8f, 0.8f);
+ return make_float3(0.8f, 0.8f, 0.8f);
#endif
}
diff --git a/intern/cycles/kernel/kernel_film.h b/intern/cycles/kernel/kernel_film.h
index b5f151d8663..d20f1adf663 100644
--- a/intern/cycles/kernel/kernel_film.h
+++ b/intern/cycles/kernel/kernel_film.h
@@ -18,72 +18,82 @@ CCL_NAMESPACE_BEGIN
ccl_device float4 film_map(KernelGlobals *kg, float4 irradiance, float scale)
{
- float exposure = kernel_data.film.exposure;
- float4 result = irradiance*scale;
+ float exposure = kernel_data.film.exposure;
+ float4 result = irradiance * scale;
- /* conversion to srgb */
- result.x = color_linear_to_srgb(result.x*exposure);
- result.y = color_linear_to_srgb(result.y*exposure);
- result.z = color_linear_to_srgb(result.z*exposure);
+ /* conversion to srgb */
+ result.x = color_linear_to_srgb(result.x * exposure);
+ result.y = color_linear_to_srgb(result.y * exposure);
+ result.z = color_linear_to_srgb(result.z * exposure);
- /* clamp since alpha might be > 1.0 due to russian roulette */
- result.w = saturate(result.w);
+ /* clamp since alpha might be > 1.0 due to russian roulette */
+ result.w = saturate(result.w);
- return result;
+ return result;
}
ccl_device uchar4 film_float_to_byte(float4 color)
{
- uchar4 result;
+ uchar4 result;
- /* simple float to byte conversion */
- result.x = (uchar)(saturate(color.x)*255.0f);
- result.y = (uchar)(saturate(color.y)*255.0f);
- result.z = (uchar)(saturate(color.z)*255.0f);
- result.w = (uchar)(saturate(color.w)*255.0f);
+ /* simple float to byte conversion */
+ result.x = (uchar)(saturate(color.x) * 255.0f);
+ result.y = (uchar)(saturate(color.y) * 255.0f);
+ result.z = (uchar)(saturate(color.z) * 255.0f);
+ result.w = (uchar)(saturate(color.w) * 255.0f);
- return result;
+ return result;
}
ccl_device void kernel_film_convert_to_byte(KernelGlobals *kg,
- ccl_global uchar4 *rgba, ccl_global float *buffer,
- float sample_scale, int x, int y, int offset, int stride)
+ ccl_global uchar4 *rgba,
+ ccl_global float *buffer,
+ float sample_scale,
+ int x,
+ int y,
+ int offset,
+ int stride)
{
- /* buffer offset */
- int index = offset + x + y*stride;
+ /* buffer offset */
+ int index = offset + x + y * stride;
- rgba += index;
- buffer += index*kernel_data.film.pass_stride;
+ rgba += index;
+ buffer += index * kernel_data.film.pass_stride;
- /* map colors */
- float4 irradiance = *((ccl_global float4*)buffer);
- float4 float_result = film_map(kg, irradiance, sample_scale);
- uchar4 byte_result = film_float_to_byte(float_result);
+ /* map colors */
+ float4 irradiance = *((ccl_global float4 *)buffer);
+ float4 float_result = film_map(kg, irradiance, sample_scale);
+ uchar4 byte_result = film_float_to_byte(float_result);
- *rgba = byte_result;
+ *rgba = byte_result;
}
ccl_device void kernel_film_convert_to_half_float(KernelGlobals *kg,
- ccl_global uchar4 *rgba, ccl_global float *buffer,
- float sample_scale, int x, int y, int offset, int stride)
+ ccl_global uchar4 *rgba,
+ ccl_global float *buffer,
+ float sample_scale,
+ int x,
+ int y,
+ int offset,
+ int stride)
{
- /* buffer offset */
- int index = offset + x + y*stride;
+ /* buffer offset */
+ int index = offset + x + y * stride;
- ccl_global float4 *in = (ccl_global float4*)(buffer + index*kernel_data.film.pass_stride);
- ccl_global half *out = (ccl_global half*)rgba + index*4;
+ ccl_global float4 *in = (ccl_global float4 *)(buffer + index * kernel_data.film.pass_stride);
+ ccl_global half *out = (ccl_global half *)rgba + index * 4;
- float exposure = kernel_data.film.exposure;
+ float exposure = kernel_data.film.exposure;
- float4 rgba_in = *in;
+ float4 rgba_in = *in;
- if(exposure != 1.0f) {
- rgba_in.x *= exposure;
- rgba_in.y *= exposure;
- rgba_in.z *= exposure;
- }
+ if (exposure != 1.0f) {
+ rgba_in.x *= exposure;
+ rgba_in.y *= exposure;
+ rgba_in.z *= exposure;
+ }
- float4_store_half(out, rgba_in, sample_scale);
+ float4_store_half(out, rgba_in, sample_scale);
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/kernel_globals.h b/intern/cycles/kernel/kernel_globals.h
index 59f1e252d21..9dbf3b7ea2e 100644
--- a/intern/cycles/kernel/kernel_globals.h
+++ b/intern/cycles/kernel/kernel_globals.h
@@ -54,41 +54,41 @@ typedef struct KernelGlobals {
# define KERNEL_TEX(type, name) texture<type> name;
# include "kernel/kernel_textures.h"
- KernelData __data;
+ KernelData __data;
# ifdef __OSL__
- /* On the CPU, we also have the OSL globals here. Most data structures are shared
- * with SVM, the difference is in the shaders and object/mesh attributes. */
- OSLGlobals *osl;
- OSLShadingSystem *osl_ss;
- OSLThreadData *osl_tdata;
+ /* On the CPU, we also have the OSL globals here. Most data structures are shared
+ * with SVM, the difference is in the shaders and object/mesh attributes. */
+ OSLGlobals *osl;
+ OSLShadingSystem *osl_ss;
+ OSLThreadData *osl_tdata;
# endif
- /* **** Run-time data **** */
+ /* **** Run-time data **** */
- /* Heap-allocated storage for transparent shadows intersections. */
- Intersection *transparent_shadow_intersections;
+ /* Heap-allocated storage for transparent shadows intersections. */
+ Intersection *transparent_shadow_intersections;
- /* Storage for decoupled volume steps. */
- VolumeStep *decoupled_volume_steps[2];
- int decoupled_volume_steps_index;
+ /* Storage for decoupled volume steps. */
+ VolumeStep *decoupled_volume_steps[2];
+ int decoupled_volume_steps_index;
- /* A buffer for storing per-pixel coverage for Cryptomatte. */
- CoverageMap *coverage_object;
- CoverageMap *coverage_material;
- CoverageMap *coverage_asset;
+ /* A buffer for storing per-pixel coverage for Cryptomatte. */
+ CoverageMap *coverage_object;
+ CoverageMap *coverage_material;
+ CoverageMap *coverage_asset;
- /* split kernel */
- SplitData split_data;
- SplitParams split_param_data;
+ /* split kernel */
+ SplitData split_data;
+ SplitParams split_param_data;
- int2 global_size;
- int2 global_id;
+ int2 global_size;
+ int2 global_id;
- ProfilingState profiler;
+ ProfilingState profiler;
} KernelGlobals;
-#endif /* __KERNEL_CPU__ */
+#endif /* __KERNEL_CPU__ */
/* For CUDA, constant memory textures must be globals, so we can't put them
* into a struct. As a result we don't actually use this struct and use actual
@@ -99,124 +99,117 @@ typedef struct KernelGlobals {
__constant__ KernelData __data;
typedef struct KernelGlobals {
- /* NOTE: Keep the size in sync with SHADOW_STACK_MAX_HITS. */
- Intersection hits_stack[64];
+ /* NOTE: Keep the size in sync with SHADOW_STACK_MAX_HITS. */
+ Intersection hits_stack[64];
} KernelGlobals;
# define KERNEL_TEX(type, name) const __constant__ __device__ type *name;
# include "kernel/kernel_textures.h"
-#endif /* __KERNEL_CUDA__ */
+#endif /* __KERNEL_CUDA__ */
/* OpenCL */
#ifdef __KERNEL_OPENCL__
-# define KERNEL_TEX(type, name) \
-typedef type name##_t;
+# define KERNEL_TEX(type, name) typedef type name##_t;
# include "kernel/kernel_textures.h"
typedef ccl_addr_space struct KernelGlobals {
- ccl_constant KernelData *data;
- ccl_global char *buffers[8];
+ ccl_constant KernelData *data;
+ ccl_global char *buffers[8];
-# define KERNEL_TEX(type, name) \
- TextureInfo name;
+# define KERNEL_TEX(type, name) TextureInfo name;
# include "kernel/kernel_textures.h"
# ifdef __SPLIT_KERNEL__
- SplitData split_data;
- SplitParams split_param_data;
+ SplitData split_data;
+ SplitParams split_param_data;
# endif
} KernelGlobals;
-#define KERNEL_BUFFER_PARAMS \
- ccl_global char *buffer0, \
- ccl_global char *buffer1, \
- ccl_global char *buffer2, \
- ccl_global char *buffer3, \
- ccl_global char *buffer4, \
- ccl_global char *buffer5, \
- ccl_global char *buffer6, \
- ccl_global char *buffer7
+# define KERNEL_BUFFER_PARAMS \
+ ccl_global char *buffer0, ccl_global char *buffer1, ccl_global char *buffer2, \
+ ccl_global char *buffer3, ccl_global char *buffer4, ccl_global char *buffer5, \
+ ccl_global char *buffer6, ccl_global char *buffer7
-#define KERNEL_BUFFER_ARGS buffer0, buffer1, buffer2, buffer3, buffer4, buffer5, buffer6, buffer7
+# define KERNEL_BUFFER_ARGS buffer0, buffer1, buffer2, buffer3, buffer4, buffer5, buffer6, buffer7
ccl_device_inline void kernel_set_buffer_pointers(KernelGlobals *kg, KERNEL_BUFFER_PARAMS)
{
-#ifdef __SPLIT_KERNEL__
- if(ccl_local_id(0) + ccl_local_id(1) == 0)
-#endif
- {
- kg->buffers[0] = buffer0;
- kg->buffers[1] = buffer1;
- kg->buffers[2] = buffer2;
- kg->buffers[3] = buffer3;
- kg->buffers[4] = buffer4;
- kg->buffers[5] = buffer5;
- kg->buffers[6] = buffer6;
- kg->buffers[7] = buffer7;
- }
+# ifdef __SPLIT_KERNEL__
+ if (ccl_local_id(0) + ccl_local_id(1) == 0)
+# endif
+ {
+ kg->buffers[0] = buffer0;
+ kg->buffers[1] = buffer1;
+ kg->buffers[2] = buffer2;
+ kg->buffers[3] = buffer3;
+ kg->buffers[4] = buffer4;
+ kg->buffers[5] = buffer5;
+ kg->buffers[6] = buffer6;
+ kg->buffers[7] = buffer7;
+ }
# ifdef __SPLIT_KERNEL__
- ccl_barrier(CCL_LOCAL_MEM_FENCE);
+ ccl_barrier(CCL_LOCAL_MEM_FENCE);
# endif
}
ccl_device_inline void kernel_set_buffer_info(KernelGlobals *kg)
{
# ifdef __SPLIT_KERNEL__
- if(ccl_local_id(0) + ccl_local_id(1) == 0)
+ if (ccl_local_id(0) + ccl_local_id(1) == 0)
# endif
- {
- ccl_global TextureInfo *info = (ccl_global TextureInfo*)kg->buffers[0];
+ {
+ ccl_global TextureInfo *info = (ccl_global TextureInfo *)kg->buffers[0];
-# define KERNEL_TEX(type, name) \
- kg->name = *(info++);
+# define KERNEL_TEX(type, name) kg->name = *(info++);
# include "kernel/kernel_textures.h"
- }
+ }
# ifdef __SPLIT_KERNEL__
- ccl_barrier(CCL_LOCAL_MEM_FENCE);
+ ccl_barrier(CCL_LOCAL_MEM_FENCE);
# endif
}
-#endif /* __KERNEL_OPENCL__ */
+#endif /* __KERNEL_OPENCL__ */
/* Interpolated lookup table access */
ccl_device float lookup_table_read(KernelGlobals *kg, float x, int offset, int size)
{
- x = saturate(x)*(size-1);
+ x = saturate(x) * (size - 1);
- int index = min(float_to_int(x), size-1);
- int nindex = min(index+1, size-1);
- float t = x - index;
+ int index = min(float_to_int(x), size - 1);
+ int nindex = min(index + 1, size - 1);
+ float t = x - index;
- float data0 = kernel_tex_fetch(__lookup_table, index + offset);
- if(t == 0.0f)
- return data0;
+ float data0 = kernel_tex_fetch(__lookup_table, index + offset);
+ if (t == 0.0f)
+ return data0;
- float data1 = kernel_tex_fetch(__lookup_table, nindex + offset);
- return (1.0f - t)*data0 + t*data1;
+ float data1 = kernel_tex_fetch(__lookup_table, nindex + offset);
+ return (1.0f - t) * data0 + t * data1;
}
-ccl_device float lookup_table_read_2D(KernelGlobals *kg, float x, float y, int offset, int xsize, int ysize)
+ccl_device float lookup_table_read_2D(
+ KernelGlobals *kg, float x, float y, int offset, int xsize, int ysize)
{
- y = saturate(y)*(ysize-1);
+ y = saturate(y) * (ysize - 1);
- int index = min(float_to_int(y), ysize-1);
- int nindex = min(index+1, ysize-1);
- float t = y - index;
+ int index = min(float_to_int(y), ysize - 1);
+ int nindex = min(index + 1, ysize - 1);
+ float t = y - index;
- float data0 = lookup_table_read(kg, x, offset + xsize*index, xsize);
- if(t == 0.0f)
- return data0;
+ float data0 = lookup_table_read(kg, x, offset + xsize * index, xsize);
+ if (t == 0.0f)
+ return data0;
- float data1 = lookup_table_read(kg, x, offset + xsize*nindex, xsize);
- return (1.0f - t)*data0 + t*data1;
+ float data1 = lookup_table_read(kg, x, offset + xsize * nindex, xsize);
+ return (1.0f - t) * data0 + t * data1;
}
CCL_NAMESPACE_END
-#endif /* __KERNEL_GLOBALS_H__ */
+#endif /* __KERNEL_GLOBALS_H__ */
diff --git a/intern/cycles/kernel/kernel_id_passes.h b/intern/cycles/kernel/kernel_id_passes.h
index 0cd65b1f2e8..c1f4e39e5e7 100644
--- a/intern/cycles/kernel/kernel_id_passes.h
+++ b/intern/cycles/kernel/kernel_id_passes.h
@@ -16,78 +16,83 @@
CCL_NAMESPACE_BEGIN
-ccl_device_inline void kernel_write_id_slots(ccl_global float *buffer, int num_slots, float id, float weight)
+ccl_device_inline void kernel_write_id_slots(ccl_global float *buffer,
+ int num_slots,
+ float id,
+ float weight)
{
- kernel_assert(id != ID_NONE);
- if(weight == 0.0f) {
- return;
- }
+ kernel_assert(id != ID_NONE);
+ if (weight == 0.0f) {
+ return;
+ }
- for(int slot = 0; slot < num_slots; slot++) {
- ccl_global float2 *id_buffer = (ccl_global float2*)buffer;
+ for (int slot = 0; slot < num_slots; slot++) {
+ ccl_global float2 *id_buffer = (ccl_global float2 *)buffer;
#ifdef __ATOMIC_PASS_WRITE__
- /* If the loop reaches an empty slot, the ID isn't in any slot yet - so add it! */
- if(id_buffer[slot].x == ID_NONE) {
- /* Use an atomic to claim this slot.
- * If a different thread got here first, try again from this slot on. */
- float old_id = atomic_compare_and_swap_float(buffer+slot*2, ID_NONE, id);
- if(old_id != ID_NONE && old_id != id) {
- continue;
- }
- atomic_add_and_fetch_float(buffer+slot*2+1, weight);
- break;
- }
- /* If there already is a slot for that ID, add the weight.
- * If no slot was found, add it to the last. */
- else if(id_buffer[slot].x == id || slot == num_slots - 1) {
- atomic_add_and_fetch_float(buffer+slot*2+1, weight);
- break;
- }
+ /* If the loop reaches an empty slot, the ID isn't in any slot yet - so add it! */
+ if (id_buffer[slot].x == ID_NONE) {
+ /* Use an atomic to claim this slot.
+ * If a different thread got here first, try again from this slot on. */
+ float old_id = atomic_compare_and_swap_float(buffer + slot * 2, ID_NONE, id);
+ if (old_id != ID_NONE && old_id != id) {
+ continue;
+ }
+ atomic_add_and_fetch_float(buffer + slot * 2 + 1, weight);
+ break;
+ }
+ /* If there already is a slot for that ID, add the weight.
+ * If no slot was found, add it to the last. */
+ else if (id_buffer[slot].x == id || slot == num_slots - 1) {
+ atomic_add_and_fetch_float(buffer + slot * 2 + 1, weight);
+ break;
+ }
#else /* __ATOMIC_PASS_WRITE__ */
- /* If the loop reaches an empty slot, the ID isn't in any slot yet - so add it! */
- if(id_buffer[slot].x == ID_NONE) {
- id_buffer[slot].x = id;
- id_buffer[slot].y = weight;
- break;
- }
- /* If there already is a slot for that ID, add the weight.
- * If no slot was found, add it to the last. */
- else if(id_buffer[slot].x == id || slot == num_slots - 1) {
- id_buffer[slot].y += weight;
- break;
- }
-#endif /* __ATOMIC_PASS_WRITE__ */
- }
+ /* If the loop reaches an empty slot, the ID isn't in any slot yet - so add it! */
+ if (id_buffer[slot].x == ID_NONE) {
+ id_buffer[slot].x = id;
+ id_buffer[slot].y = weight;
+ break;
+ }
+ /* If there already is a slot for that ID, add the weight.
+ * If no slot was found, add it to the last. */
+ else if (id_buffer[slot].x == id || slot == num_slots - 1) {
+ id_buffer[slot].y += weight;
+ break;
+ }
+#endif /* __ATOMIC_PASS_WRITE__ */
+ }
}
ccl_device_inline void kernel_sort_id_slots(ccl_global float *buffer, int num_slots)
{
- ccl_global float2 *id_buffer = (ccl_global float2*)buffer;
- for(int slot = 1; slot < num_slots; ++slot) {
- if(id_buffer[slot].x == ID_NONE) {
- return;
- }
- /* Since we're dealing with a tiny number of elements, insertion sort should be fine. */
- int i = slot;
- while(i > 0 && id_buffer[i].y > id_buffer[i - 1].y) {
- float2 swap = id_buffer[i];
- id_buffer[i] = id_buffer[i - 1];
- id_buffer[i - 1] = swap;
- --i;
- }
- }
+ ccl_global float2 *id_buffer = (ccl_global float2 *)buffer;
+ for (int slot = 1; slot < num_slots; ++slot) {
+ if (id_buffer[slot].x == ID_NONE) {
+ return;
+ }
+ /* Since we're dealing with a tiny number of elements, insertion sort should be fine. */
+ int i = slot;
+ while (i > 0 && id_buffer[i].y > id_buffer[i - 1].y) {
+ float2 swap = id_buffer[i];
+ id_buffer[i] = id_buffer[i - 1];
+ id_buffer[i - 1] = swap;
+ --i;
+ }
+ }
}
#ifdef __KERNEL_GPU__
/* post-sorting for Cryptomatte */
-ccl_device void kernel_cryptomatte_post(KernelGlobals *kg, ccl_global float *buffer, uint sample, int x, int y, int offset, int stride)
+ccl_device void kernel_cryptomatte_post(
+ KernelGlobals *kg, ccl_global float *buffer, uint sample, int x, int y, int offset, int stride)
{
- if(sample - 1 == kernel_data.integrator.aa_samples) {
- int index = offset + x + y * stride;
- int pass_stride = kernel_data.film.pass_stride;
- ccl_global float *cryptomatte_buffer = buffer + index * pass_stride + kernel_data.film.pass_cryptomatte;
- kernel_sort_id_slots(cryptomatte_buffer, 2 * kernel_data.film.cryptomatte_depth);
- }
+ if (sample - 1 == kernel_data.integrator.aa_samples) {
+ int index = offset + x + y * stride;
+ int pass_stride = kernel_data.film.pass_stride;
+ ccl_global float *cryptomatte_buffer = buffer + index * pass_stride +
+ kernel_data.film.pass_cryptomatte;
+ kernel_sort_id_slots(cryptomatte_buffer, 2 * kernel_data.film.cryptomatte_depth);
+ }
}
#endif
diff --git a/intern/cycles/kernel/kernel_jitter.h b/intern/cycles/kernel/kernel_jitter.h
index 3bde96b078c..f7270a14940 100644
--- a/intern/cycles/kernel/kernel_jitter.h
+++ b/intern/cycles/kernel/kernel_jitter.h
@@ -26,202 +26,202 @@ CCL_NAMESPACE_BEGIN
ccl_device_inline bool cmj_is_pow2(int i)
{
- return (i > 1) && ((i & (i - 1)) == 0);
+ return (i > 1) && ((i & (i - 1)) == 0);
}
ccl_device_inline int cmj_fast_mod_pow2(int a, int b)
{
- return (a & (b - 1));
+ return (a & (b - 1));
}
/* b must be > 1 */
ccl_device_inline int cmj_fast_div_pow2(int a, int b)
{
- kernel_assert(b > 1);
+ kernel_assert(b > 1);
#if defined(__KERNEL_SSE2__)
# ifdef _MSC_VER
- unsigned long ctz;
- _BitScanForward(&ctz, b);
- return a >> ctz;
+ unsigned long ctz;
+ _BitScanForward(&ctz, b);
+ return a >> ctz;
# else
- return a >> __builtin_ctz(b);
+ return a >> __builtin_ctz(b);
# endif
#elif defined(__KERNEL_CUDA__)
- return a >> (__ffs(b) - 1);
+ return a >> (__ffs(b) - 1);
#else
- return a/b;
+ return a / b;
#endif
}
ccl_device_inline uint cmj_w_mask(uint w)
{
- kernel_assert(w > 1);
+ kernel_assert(w > 1);
#if defined(__KERNEL_SSE2__)
# ifdef _MSC_VER
- unsigned long leading_zero;
- _BitScanReverse(&leading_zero, w);
- return ((1 << (1 + leading_zero)) - 1);
+ unsigned long leading_zero;
+ _BitScanReverse(&leading_zero, w);
+ return ((1 << (1 + leading_zero)) - 1);
# else
- return ((1 << (32 - __builtin_clz(w))) - 1);
+ return ((1 << (32 - __builtin_clz(w))) - 1);
# endif
#elif defined(__KERNEL_CUDA__)
- return ((1 << (32 - __clz(w))) - 1);
+ return ((1 << (32 - __clz(w))) - 1);
#else
- w |= w >> 1;
- w |= w >> 2;
- w |= w >> 4;
- w |= w >> 8;
- w |= w >> 16;
+ w |= w >> 1;
+ w |= w >> 2;
+ w |= w >> 4;
+ w |= w >> 8;
+ w |= w >> 16;
- return w;
+ return w;
#endif
}
ccl_device_inline uint cmj_permute(uint i, uint l, uint p)
{
- uint w = l - 1;
-
- if((l & w) == 0) {
- /* l is a power of two (fast) */
- i ^= p;
- i *= 0xe170893d;
- i ^= p >> 16;
- i ^= (i & w) >> 4;
- i ^= p >> 8;
- i *= 0x0929eb3f;
- i ^= p >> 23;
- i ^= (i & w) >> 1;
- i *= 1 | p >> 27;
- i *= 0x6935fa69;
- i ^= (i & w) >> 11;
- i *= 0x74dcb303;
- i ^= (i & w) >> 2;
- i *= 0x9e501cc3;
- i ^= (i & w) >> 2;
- i *= 0xc860a3df;
- i &= w;
- i ^= i >> 5;
-
- return (i + p) & w;
- }
- else {
- /* l is not a power of two (slow) */
- w = cmj_w_mask(w);
-
- do {
- i ^= p;
- i *= 0xe170893d;
- i ^= p >> 16;
- i ^= (i & w) >> 4;
- i ^= p >> 8;
- i *= 0x0929eb3f;
- i ^= p >> 23;
- i ^= (i & w) >> 1;
- i *= 1 | p >> 27;
- i *= 0x6935fa69;
- i ^= (i & w) >> 11;
- i *= 0x74dcb303;
- i ^= (i & w) >> 2;
- i *= 0x9e501cc3;
- i ^= (i & w) >> 2;
- i *= 0xc860a3df;
- i &= w;
- i ^= i >> 5;
- } while(i >= l);
-
- return (i + p) % l;
- }
+ uint w = l - 1;
+
+ if ((l & w) == 0) {
+ /* l is a power of two (fast) */
+ i ^= p;
+ i *= 0xe170893d;
+ i ^= p >> 16;
+ i ^= (i & w) >> 4;
+ i ^= p >> 8;
+ i *= 0x0929eb3f;
+ i ^= p >> 23;
+ i ^= (i & w) >> 1;
+ i *= 1 | p >> 27;
+ i *= 0x6935fa69;
+ i ^= (i & w) >> 11;
+ i *= 0x74dcb303;
+ i ^= (i & w) >> 2;
+ i *= 0x9e501cc3;
+ i ^= (i & w) >> 2;
+ i *= 0xc860a3df;
+ i &= w;
+ i ^= i >> 5;
+
+ return (i + p) & w;
+ }
+ else {
+ /* l is not a power of two (slow) */
+ w = cmj_w_mask(w);
+
+ do {
+ i ^= p;
+ i *= 0xe170893d;
+ i ^= p >> 16;
+ i ^= (i & w) >> 4;
+ i ^= p >> 8;
+ i *= 0x0929eb3f;
+ i ^= p >> 23;
+ i ^= (i & w) >> 1;
+ i *= 1 | p >> 27;
+ i *= 0x6935fa69;
+ i ^= (i & w) >> 11;
+ i *= 0x74dcb303;
+ i ^= (i & w) >> 2;
+ i *= 0x9e501cc3;
+ i ^= (i & w) >> 2;
+ i *= 0xc860a3df;
+ i &= w;
+ i ^= i >> 5;
+ } while (i >= l);
+
+ return (i + p) % l;
+ }
}
ccl_device_inline uint cmj_hash(uint i, uint p)
{
- i ^= p;
- i ^= i >> 17;
- i ^= i >> 10;
- i *= 0xb36534e5;
- i ^= i >> 12;
- i ^= i >> 21;
- i *= 0x93fc4795;
- i ^= 0xdf6e307f;
- i ^= i >> 17;
- i *= 1 | p >> 18;
-
- return i;
+ i ^= p;
+ i ^= i >> 17;
+ i ^= i >> 10;
+ i *= 0xb36534e5;
+ i ^= i >> 12;
+ i ^= i >> 21;
+ i *= 0x93fc4795;
+ i ^= 0xdf6e307f;
+ i ^= i >> 17;
+ i *= 1 | p >> 18;
+
+ return i;
}
ccl_device_inline uint cmj_hash_simple(uint i, uint p)
{
- i = (i ^ 61) ^ p;
- i += i << 3;
- i ^= i >> 4;
- i *= 0x27d4eb2d;
- return i;
+ i = (i ^ 61) ^ p;
+ i += i << 3;
+ i ^= i >> 4;
+ i *= 0x27d4eb2d;
+ return i;
}
ccl_device_inline float cmj_randfloat(uint i, uint p)
{
- return cmj_hash(i, p) * (1.0f / 4294967808.0f);
+ return cmj_hash(i, p) * (1.0f / 4294967808.0f);
}
#ifdef __CMJ__
ccl_device float cmj_sample_1D(int s, int N, int p)
{
- kernel_assert(s < N);
+ kernel_assert(s < N);
- uint x = cmj_permute(s, N, p * 0x68bc21eb);
- float jx = cmj_randfloat(s, p * 0x967a889b);
+ uint x = cmj_permute(s, N, p * 0x68bc21eb);
+ float jx = cmj_randfloat(s, p * 0x967a889b);
- float invN = 1.0f/N;
- return (x + jx)*invN;
+ float invN = 1.0f / N;
+ return (x + jx) * invN;
}
/* TODO(sergey): Do some extra tests and consider moving to util_math.h. */
ccl_device_inline int cmj_isqrt(int value)
{
-#if defined(__KERNEL_CUDA__)
- return float_to_int(__fsqrt_ru(value));
-#elif defined(__KERNEL_GPU__)
- return float_to_int(sqrtf(value));
-#else
- /* This is a work around for fast-math on CPU which might replace sqrtf()
- * with am approximated version.
- */
- return float_to_int(sqrtf(value) + 1e-6f);
-#endif
+# if defined(__KERNEL_CUDA__)
+ return float_to_int(__fsqrt_ru(value));
+# elif defined(__KERNEL_GPU__)
+ return float_to_int(sqrtf(value));
+# else
+ /* This is a work around for fast-math on CPU which might replace sqrtf()
+ * with am approximated version.
+ */
+ return float_to_int(sqrtf(value) + 1e-6f);
+# endif
}
ccl_device void cmj_sample_2D(int s, int N, int p, float *fx, float *fy)
{
- kernel_assert(s < N);
+ kernel_assert(s < N);
- int m = cmj_isqrt(N);
- int n = (N - 1)/m + 1;
- float invN = 1.0f/N;
- float invm = 1.0f/m;
- float invn = 1.0f/n;
+ int m = cmj_isqrt(N);
+ int n = (N - 1) / m + 1;
+ float invN = 1.0f / N;
+ float invm = 1.0f / m;
+ float invn = 1.0f / n;
- s = cmj_permute(s, N, p * 0x51633e2d);
+ s = cmj_permute(s, N, p * 0x51633e2d);
- int sdivm, smodm;
+ int sdivm, smodm;
- if(cmj_is_pow2(m)) {
- sdivm = cmj_fast_div_pow2(s, m);
- smodm = cmj_fast_mod_pow2(s, m);
- }
- else {
- /* Doing s*inmv gives precision issues here. */
- sdivm = s / m;
- smodm = s - sdivm*m;
- }
+ if (cmj_is_pow2(m)) {
+ sdivm = cmj_fast_div_pow2(s, m);
+ smodm = cmj_fast_mod_pow2(s, m);
+ }
+ else {
+ /* Doing s*inmv gives precision issues here. */
+ sdivm = s / m;
+ smodm = s - sdivm * m;
+ }
- uint sx = cmj_permute(smodm, m, p * 0x68bc21eb);
- uint sy = cmj_permute(sdivm, n, p * 0x02e5be93);
+ uint sx = cmj_permute(smodm, m, p * 0x68bc21eb);
+ uint sy = cmj_permute(sdivm, n, p * 0x02e5be93);
- float jx = cmj_randfloat(s, p * 0x967a889b);
- float jy = cmj_randfloat(s, p * 0x368cc8b7);
+ float jx = cmj_randfloat(s, p * 0x967a889b);
+ float jy = cmj_randfloat(s, p * 0x368cc8b7);
- *fx = (sx + (sy + jx)*invn)*invm;
- *fy = (s + jy)*invN;
+ *fx = (sx + (sy + jx) * invn) * invm;
+ *fy = (s + jy) * invN;
}
#endif
diff --git a/intern/cycles/kernel/kernel_light.h b/intern/cycles/kernel/kernel_light.h
index 262d7df1364..5e24f8dedaf 100644
--- a/intern/cycles/kernel/kernel_light.h
+++ b/intern/cycles/kernel/kernel_light.h
@@ -19,18 +19,18 @@ CCL_NAMESPACE_BEGIN
/* Light Sample result */
typedef struct LightSample {
- float3 P; /* position on light, or direction for distant light */
- float3 Ng; /* normal on light */
- float3 D; /* direction from shading point to light */
- float t; /* distance to light (FLT_MAX for distant light) */
- float u, v; /* parametric coordinate on primitive */
- float pdf; /* light sampling probability density function */
- float eval_fac; /* intensity multiplier */
- int object; /* object id for triangle/curve lights */
- int prim; /* primitive id for triangle/curve lights */
- int shader; /* shader id */
- int lamp; /* lamp id */
- LightType type; /* type of light */
+ float3 P; /* position on light, or direction for distant light */
+ float3 Ng; /* normal on light */
+ float3 D; /* direction from shading point to light */
+ float t; /* distance to light (FLT_MAX for distant light) */
+ float u, v; /* parametric coordinate on primitive */
+ float pdf; /* light sampling probability density function */
+ float eval_fac; /* intensity multiplier */
+ int object; /* object id for triangle/curve lights */
+ int prim; /* primitive id for triangle/curve lights */
+ int shader; /* shader id */
+ int lamp; /* lamp id */
+ LightType type; /* type of light */
} LightSample;
/* Area light sampling */
@@ -46,130 +46,136 @@ typedef struct LightSample {
*/
ccl_device_inline float rect_light_sample(float3 P,
float3 *light_p,
- float3 axisu, float3 axisv,
- float randu, float randv,
+ float3 axisu,
+ float3 axisv,
+ float randu,
+ float randv,
bool sample_coord)
{
- /* In our name system we're using P for the center,
- * which is o in the paper.
- */
-
- float3 corner = *light_p - axisu * 0.5f - axisv * 0.5f;
- float axisu_len, axisv_len;
- /* Compute local reference system R. */
- float3 x = normalize_len(axisu, &axisu_len);
- float3 y = normalize_len(axisv, &axisv_len);
- float3 z = cross(x, y);
- /* Compute rectangle coords in local reference system. */
- float3 dir = corner - P;
- float z0 = dot(dir, z);
- /* Flip 'z' to make it point against Q. */
- if(z0 > 0.0f) {
- z *= -1.0f;
- z0 *= -1.0f;
- }
- float x0 = dot(dir, x);
- float y0 = dot(dir, y);
- float x1 = x0 + axisu_len;
- float y1 = y0 + axisv_len;
- /* Compute internal angles (gamma_i). */
- float4 diff = make_float4(x0, y1, x1, y0) - make_float4(x1, y0, x0, y1);
- float4 nz = make_float4(y0, x1, y1, x0) * diff;
- nz = nz / sqrt(z0 * z0 * diff * diff + nz * nz);
- float g0 = safe_acosf(-nz.x * nz.y);
- float g1 = safe_acosf(-nz.y * nz.z);
- float g2 = safe_acosf(-nz.z * nz.w);
- float g3 = safe_acosf(-nz.w * nz.x);
- /* Compute predefined constants. */
- float b0 = nz.x;
- float b1 = nz.z;
- float b0sq = b0 * b0;
- float k = M_2PI_F - g2 - g3;
- /* Compute solid angle from internal angles. */
- float S = g0 + g1 - k;
-
- if(sample_coord) {
- /* Compute cu. */
- float au = randu * S + k;
- float fu = (cosf(au) * b0 - b1) / sinf(au);
- float cu = 1.0f / sqrtf(fu * fu + b0sq) * (fu > 0.0f ? 1.0f : -1.0f);
- cu = clamp(cu, -1.0f, 1.0f);
- /* Compute xu. */
- float xu = -(cu * z0) / max(sqrtf(1.0f - cu * cu), 1e-7f);
- xu = clamp(xu, x0, x1);
- /* Compute yv. */
- float z0sq = z0 * z0;
- float y0sq = y0 * y0;
- float y1sq = y1 * y1;
- float d = sqrtf(xu * xu + z0sq);
- float h0 = y0 / sqrtf(d * d + y0sq);
- float h1 = y1 / sqrtf(d * d + y1sq);
- float hv = h0 + randv * (h1 - h0), hv2 = hv * hv;
- float yv = (hv2 < 1.0f - 1e-6f) ? (hv * d) / sqrtf(1.0f - hv2) : y1;
-
- /* Transform (xu, yv, z0) to world coords. */
- *light_p = P + xu * x + yv * y + z0 * z;
- }
-
- /* return pdf */
- if(S != 0.0f)
- return 1.0f / S;
- else
- return 0.0f;
+ /* In our name system we're using P for the center,
+ * which is o in the paper.
+ */
+
+ float3 corner = *light_p - axisu * 0.5f - axisv * 0.5f;
+ float axisu_len, axisv_len;
+ /* Compute local reference system R. */
+ float3 x = normalize_len(axisu, &axisu_len);
+ float3 y = normalize_len(axisv, &axisv_len);
+ float3 z = cross(x, y);
+ /* Compute rectangle coords in local reference system. */
+ float3 dir = corner - P;
+ float z0 = dot(dir, z);
+ /* Flip 'z' to make it point against Q. */
+ if (z0 > 0.0f) {
+ z *= -1.0f;
+ z0 *= -1.0f;
+ }
+ float x0 = dot(dir, x);
+ float y0 = dot(dir, y);
+ float x1 = x0 + axisu_len;
+ float y1 = y0 + axisv_len;
+ /* Compute internal angles (gamma_i). */
+ float4 diff = make_float4(x0, y1, x1, y0) - make_float4(x1, y0, x0, y1);
+ float4 nz = make_float4(y0, x1, y1, x0) * diff;
+ nz = nz / sqrt(z0 * z0 * diff * diff + nz * nz);
+ float g0 = safe_acosf(-nz.x * nz.y);
+ float g1 = safe_acosf(-nz.y * nz.z);
+ float g2 = safe_acosf(-nz.z * nz.w);
+ float g3 = safe_acosf(-nz.w * nz.x);
+ /* Compute predefined constants. */
+ float b0 = nz.x;
+ float b1 = nz.z;
+ float b0sq = b0 * b0;
+ float k = M_2PI_F - g2 - g3;
+ /* Compute solid angle from internal angles. */
+ float S = g0 + g1 - k;
+
+ if (sample_coord) {
+ /* Compute cu. */
+ float au = randu * S + k;
+ float fu = (cosf(au) * b0 - b1) / sinf(au);
+ float cu = 1.0f / sqrtf(fu * fu + b0sq) * (fu > 0.0f ? 1.0f : -1.0f);
+ cu = clamp(cu, -1.0f, 1.0f);
+ /* Compute xu. */
+ float xu = -(cu * z0) / max(sqrtf(1.0f - cu * cu), 1e-7f);
+ xu = clamp(xu, x0, x1);
+ /* Compute yv. */
+ float z0sq = z0 * z0;
+ float y0sq = y0 * y0;
+ float y1sq = y1 * y1;
+ float d = sqrtf(xu * xu + z0sq);
+ float h0 = y0 / sqrtf(d * d + y0sq);
+ float h1 = y1 / sqrtf(d * d + y1sq);
+ float hv = h0 + randv * (h1 - h0), hv2 = hv * hv;
+ float yv = (hv2 < 1.0f - 1e-6f) ? (hv * d) / sqrtf(1.0f - hv2) : y1;
+
+ /* Transform (xu, yv, z0) to world coords. */
+ *light_p = P + xu * x + yv * y + z0 * z;
+ }
+
+ /* return pdf */
+ if (S != 0.0f)
+ return 1.0f / S;
+ else
+ return 0.0f;
}
ccl_device_inline float3 ellipse_sample(float3 ru, float3 rv, float randu, float randv)
{
- to_unit_disk(&randu, &randv);
- return ru*randu + rv*randv;
+ to_unit_disk(&randu, &randv);
+ return ru * randu + rv * randv;
}
ccl_device float3 disk_light_sample(float3 v, float randu, float randv)
{
- float3 ru, rv;
+ float3 ru, rv;
- make_orthonormals(v, &ru, &rv);
+ make_orthonormals(v, &ru, &rv);
- return ellipse_sample(ru, rv, randu, randv);
+ return ellipse_sample(ru, rv, randu, randv);
}
ccl_device float3 distant_light_sample(float3 D, float radius, float randu, float randv)
{
- return normalize(D + disk_light_sample(D, randu, randv)*radius);
+ return normalize(D + disk_light_sample(D, randu, randv) * radius);
}
-ccl_device float3 sphere_light_sample(float3 P, float3 center, float radius, float randu, float randv)
+ccl_device float3
+sphere_light_sample(float3 P, float3 center, float radius, float randu, float randv)
{
- return disk_light_sample(normalize(P - center), randu, randv)*radius;
+ return disk_light_sample(normalize(P - center), randu, randv) * radius;
}
-ccl_device float spot_light_attenuation(float3 dir, float spot_angle, float spot_smooth, LightSample *ls)
+ccl_device float spot_light_attenuation(float3 dir,
+ float spot_angle,
+ float spot_smooth,
+ LightSample *ls)
{
- float3 I = ls->Ng;
+ float3 I = ls->Ng;
- float attenuation = dot(dir, I);
+ float attenuation = dot(dir, I);
- if(attenuation <= spot_angle) {
- attenuation = 0.0f;
- }
- else {
- float t = attenuation - spot_angle;
+ if (attenuation <= spot_angle) {
+ attenuation = 0.0f;
+ }
+ else {
+ float t = attenuation - spot_angle;
- if(t < spot_smooth && spot_smooth != 0.0f)
- attenuation *= smoothstepf(t/spot_smooth);
- }
+ if (t < spot_smooth && spot_smooth != 0.0f)
+ attenuation *= smoothstepf(t / spot_smooth);
+ }
- return attenuation;
+ return attenuation;
}
ccl_device float lamp_light_pdf(KernelGlobals *kg, const float3 Ng, const float3 I, float t)
{
- float cos_pi = dot(Ng, I);
+ float cos_pi = dot(Ng, I);
- if(cos_pi <= 0.0f)
- return 0.0f;
+ if (cos_pi <= 0.0f)
+ return 0.0f;
- return t*t/cos_pi;
+ return t * t / cos_pi;
}
/* Background Light */
@@ -180,203 +186,219 @@ ccl_device float lamp_light_pdf(KernelGlobals *kg, const float3 Ng, const float3
* devices, but we're so close to the release so better not screw things
* up for CPU at least.
*/
-#ifdef __KERNEL_GPU__
+# ifdef __KERNEL_GPU__
ccl_device_noinline
-#else
+# else
ccl_device
-#endif
-float3 background_map_sample(KernelGlobals *kg, float randu, float randv, float *pdf)
+# endif
+ float3
+ background_map_sample(KernelGlobals *kg, float randu, float randv, float *pdf)
{
- /* for the following, the CDF values are actually a pair of floats, with the
- * function value as X and the actual CDF as Y. The last entry's function
- * value is the CDF total. */
- int res_x = kernel_data.integrator.pdf_background_res_x;
- int res_y = kernel_data.integrator.pdf_background_res_y;
- int cdf_width = res_x + 1;
-
- /* this is basically std::lower_bound as used by pbrt */
- int first = 0;
- int count = res_y;
-
- while(count > 0) {
- int step = count >> 1;
- int middle = first + step;
-
- if(kernel_tex_fetch(__light_background_marginal_cdf, middle).y < randv) {
- first = middle + 1;
- count -= step + 1;
- }
- else
- count = step;
- }
-
- int index_v = max(0, first - 1);
- kernel_assert(index_v >= 0 && index_v < res_y);
-
- float2 cdf_v = kernel_tex_fetch(__light_background_marginal_cdf, index_v);
- float2 cdf_next_v = kernel_tex_fetch(__light_background_marginal_cdf, index_v + 1);
- float2 cdf_last_v = kernel_tex_fetch(__light_background_marginal_cdf, res_y);
-
- /* importance-sampled V direction */
- float dv = inverse_lerp(cdf_v.y, cdf_next_v.y, randv);
- float v = (index_v + dv) / res_y;
-
- /* this is basically std::lower_bound as used by pbrt */
- first = 0;
- count = res_x;
- while(count > 0) {
- int step = count >> 1;
- int middle = first + step;
-
- if(kernel_tex_fetch(__light_background_conditional_cdf, index_v * cdf_width + middle).y < randu) {
- first = middle + 1;
- count -= step + 1;
- }
- else
- count = step;
- }
-
- int index_u = max(0, first - 1);
- kernel_assert(index_u >= 0 && index_u < res_x);
-
- float2 cdf_u = kernel_tex_fetch(__light_background_conditional_cdf, index_v * cdf_width + index_u);
- float2 cdf_next_u = kernel_tex_fetch(__light_background_conditional_cdf, index_v * cdf_width + index_u + 1);
- float2 cdf_last_u = kernel_tex_fetch(__light_background_conditional_cdf, index_v * cdf_width + res_x);
-
- /* importance-sampled U direction */
- float du = inverse_lerp(cdf_u.y, cdf_next_u.y, randu);
- float u = (index_u + du) / res_x;
-
- /* compute pdf */
- float denom = cdf_last_u.x * cdf_last_v.x;
- float sin_theta = sinf(M_PI_F * v);
-
- if(sin_theta == 0.0f || denom == 0.0f)
- *pdf = 0.0f;
- else
- *pdf = (cdf_u.x * cdf_v.x)/(M_2PI_F * M_PI_F * sin_theta * denom);
-
- /* compute direction */
- return equirectangular_to_direction(u, v);
+ /* for the following, the CDF values are actually a pair of floats, with the
+ * function value as X and the actual CDF as Y. The last entry's function
+ * value is the CDF total. */
+ int res_x = kernel_data.integrator.pdf_background_res_x;
+ int res_y = kernel_data.integrator.pdf_background_res_y;
+ int cdf_width = res_x + 1;
+
+ /* this is basically std::lower_bound as used by pbrt */
+ int first = 0;
+ int count = res_y;
+
+ while (count > 0) {
+ int step = count >> 1;
+ int middle = first + step;
+
+ if (kernel_tex_fetch(__light_background_marginal_cdf, middle).y < randv) {
+ first = middle + 1;
+ count -= step + 1;
+ }
+ else
+ count = step;
+ }
+
+ int index_v = max(0, first - 1);
+ kernel_assert(index_v >= 0 && index_v < res_y);
+
+ float2 cdf_v = kernel_tex_fetch(__light_background_marginal_cdf, index_v);
+ float2 cdf_next_v = kernel_tex_fetch(__light_background_marginal_cdf, index_v + 1);
+ float2 cdf_last_v = kernel_tex_fetch(__light_background_marginal_cdf, res_y);
+
+ /* importance-sampled V direction */
+ float dv = inverse_lerp(cdf_v.y, cdf_next_v.y, randv);
+ float v = (index_v + dv) / res_y;
+
+ /* this is basically std::lower_bound as used by pbrt */
+ first = 0;
+ count = res_x;
+ while (count > 0) {
+ int step = count >> 1;
+ int middle = first + step;
+
+ if (kernel_tex_fetch(__light_background_conditional_cdf, index_v * cdf_width + middle).y <
+ randu) {
+ first = middle + 1;
+ count -= step + 1;
+ }
+ else
+ count = step;
+ }
+
+ int index_u = max(0, first - 1);
+ kernel_assert(index_u >= 0 && index_u < res_x);
+
+ float2 cdf_u = kernel_tex_fetch(__light_background_conditional_cdf,
+ index_v * cdf_width + index_u);
+ float2 cdf_next_u = kernel_tex_fetch(__light_background_conditional_cdf,
+ index_v * cdf_width + index_u + 1);
+ float2 cdf_last_u = kernel_tex_fetch(__light_background_conditional_cdf,
+ index_v * cdf_width + res_x);
+
+ /* importance-sampled U direction */
+ float du = inverse_lerp(cdf_u.y, cdf_next_u.y, randu);
+ float u = (index_u + du) / res_x;
+
+ /* compute pdf */
+ float denom = cdf_last_u.x * cdf_last_v.x;
+ float sin_theta = sinf(M_PI_F * v);
+
+ if (sin_theta == 0.0f || denom == 0.0f)
+ *pdf = 0.0f;
+ else
+ *pdf = (cdf_u.x * cdf_v.x) / (M_2PI_F * M_PI_F * sin_theta * denom);
+
+ /* compute direction */
+ return equirectangular_to_direction(u, v);
}
/* TODO(sergey): Same as above, after the release we should consider using
* 'noinline' for all devices.
*/
-#ifdef __KERNEL_GPU__
+# ifdef __KERNEL_GPU__
ccl_device_noinline
-#else
+# else
ccl_device
-#endif
-float background_map_pdf(KernelGlobals *kg, float3 direction)
+# endif
+ float
+ background_map_pdf(KernelGlobals *kg, float3 direction)
{
- float2 uv = direction_to_equirectangular(direction);
- int res_x = kernel_data.integrator.pdf_background_res_x;
- int res_y = kernel_data.integrator.pdf_background_res_y;
- int cdf_width = res_x + 1;
+ float2 uv = direction_to_equirectangular(direction);
+ int res_x = kernel_data.integrator.pdf_background_res_x;
+ int res_y = kernel_data.integrator.pdf_background_res_y;
+ int cdf_width = res_x + 1;
- float sin_theta = sinf(uv.y * M_PI_F);
+ float sin_theta = sinf(uv.y * M_PI_F);
- if(sin_theta == 0.0f)
- return 0.0f;
+ if (sin_theta == 0.0f)
+ return 0.0f;
- int index_u = clamp(float_to_int(uv.x * res_x), 0, res_x - 1);
- int index_v = clamp(float_to_int(uv.y * res_y), 0, res_y - 1);
+ int index_u = clamp(float_to_int(uv.x * res_x), 0, res_x - 1);
+ int index_v = clamp(float_to_int(uv.y * res_y), 0, res_y - 1);
- /* pdfs in V direction */
- float2 cdf_last_u = kernel_tex_fetch(__light_background_conditional_cdf, index_v * cdf_width + res_x);
- float2 cdf_last_v = kernel_tex_fetch(__light_background_marginal_cdf, res_y);
+ /* pdfs in V direction */
+ float2 cdf_last_u = kernel_tex_fetch(__light_background_conditional_cdf,
+ index_v * cdf_width + res_x);
+ float2 cdf_last_v = kernel_tex_fetch(__light_background_marginal_cdf, res_y);
- float denom = cdf_last_u.x * cdf_last_v.x;
+ float denom = cdf_last_u.x * cdf_last_v.x;
- if(denom == 0.0f)
- return 0.0f;
+ if (denom == 0.0f)
+ return 0.0f;
- /* pdfs in U direction */
- float2 cdf_u = kernel_tex_fetch(__light_background_conditional_cdf, index_v * cdf_width + index_u);
- float2 cdf_v = kernel_tex_fetch(__light_background_marginal_cdf, index_v);
+ /* pdfs in U direction */
+ float2 cdf_u = kernel_tex_fetch(__light_background_conditional_cdf,
+ index_v * cdf_width + index_u);
+ float2 cdf_v = kernel_tex_fetch(__light_background_marginal_cdf, index_v);
- return (cdf_u.x * cdf_v.x)/(M_2PI_F * M_PI_F * sin_theta * denom);
+ return (cdf_u.x * cdf_v.x) / (M_2PI_F * M_PI_F * sin_theta * denom);
}
-ccl_device_inline bool background_portal_data_fetch_and_check_side(KernelGlobals *kg,
- float3 P,
- int index,
- float3 *lightpos,
- float3 *dir)
+ccl_device_inline bool background_portal_data_fetch_and_check_side(
+ KernelGlobals *kg, float3 P, int index, float3 *lightpos, float3 *dir)
{
- int portal = kernel_data.integrator.portal_offset + index;
- const ccl_global KernelLight *klight = &kernel_tex_fetch(__lights, portal);
+ int portal = kernel_data.integrator.portal_offset + index;
+ const ccl_global KernelLight *klight = &kernel_tex_fetch(__lights, portal);
- *lightpos = make_float3(klight->co[0], klight->co[1], klight->co[2]);
- *dir = make_float3(klight->area.dir[0], klight->area.dir[1], klight->area.dir[2]);
+ *lightpos = make_float3(klight->co[0], klight->co[1], klight->co[2]);
+ *dir = make_float3(klight->area.dir[0], klight->area.dir[1], klight->area.dir[2]);
- /* Check whether portal is on the right side. */
- if(dot(*dir, P - *lightpos) > 1e-4f)
- return true;
+ /* Check whether portal is on the right side. */
+ if (dot(*dir, P - *lightpos) > 1e-4f)
+ return true;
- return false;
+ return false;
}
-ccl_device_inline float background_portal_pdf(KernelGlobals *kg,
- float3 P,
- float3 direction,
- int ignore_portal,
- bool *is_possible)
+ccl_device_inline float background_portal_pdf(
+ KernelGlobals *kg, float3 P, float3 direction, int ignore_portal, bool *is_possible)
{
- float portal_pdf = 0.0f;
-
- int num_possible = 0;
- for(int p = 0; p < kernel_data.integrator.num_portals; p++) {
- if(p == ignore_portal)
- continue;
-
- float3 lightpos, dir;
- if(!background_portal_data_fetch_and_check_side(kg, P, p, &lightpos, &dir))
- continue;
-
- /* There's a portal that could be sampled from this position. */
- if(is_possible) {
- *is_possible = true;
- }
- num_possible++;
-
- int portal = kernel_data.integrator.portal_offset + p;
- const ccl_global KernelLight *klight = &kernel_tex_fetch(__lights, portal);
- float3 axisu = make_float3(klight->area.axisu[0], klight->area.axisu[1], klight->area.axisu[2]);
- float3 axisv = make_float3(klight->area.axisv[0], klight->area.axisv[1], klight->area.axisv[2]);
- bool is_round = (klight->area.invarea < 0.0f);
-
- if(!ray_quad_intersect(P, direction, 1e-4f, FLT_MAX, lightpos, axisu, axisv, dir, NULL, NULL, NULL, NULL, is_round))
- continue;
-
- if(is_round) {
- float t;
- float3 D = normalize_len(lightpos - P, &t);
- portal_pdf += fabsf(klight->area.invarea) * lamp_light_pdf(kg, dir, -D, t);
- }
- else {
- portal_pdf += rect_light_sample(P, &lightpos, axisu, axisv, 0.0f, 0.0f, false);
- }
- }
-
- if(ignore_portal >= 0) {
- /* We have skipped a portal that could be sampled as well. */
- num_possible++;
- }
-
- return (num_possible > 0)? portal_pdf / num_possible: 0.0f;
+ float portal_pdf = 0.0f;
+
+ int num_possible = 0;
+ for (int p = 0; p < kernel_data.integrator.num_portals; p++) {
+ if (p == ignore_portal)
+ continue;
+
+ float3 lightpos, dir;
+ if (!background_portal_data_fetch_and_check_side(kg, P, p, &lightpos, &dir))
+ continue;
+
+ /* There's a portal that could be sampled from this position. */
+ if (is_possible) {
+ *is_possible = true;
+ }
+ num_possible++;
+
+ int portal = kernel_data.integrator.portal_offset + p;
+ const ccl_global KernelLight *klight = &kernel_tex_fetch(__lights, portal);
+ float3 axisu = make_float3(
+ klight->area.axisu[0], klight->area.axisu[1], klight->area.axisu[2]);
+ float3 axisv = make_float3(
+ klight->area.axisv[0], klight->area.axisv[1], klight->area.axisv[2]);
+ bool is_round = (klight->area.invarea < 0.0f);
+
+ if (!ray_quad_intersect(P,
+ direction,
+ 1e-4f,
+ FLT_MAX,
+ lightpos,
+ axisu,
+ axisv,
+ dir,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ is_round))
+ continue;
+
+ if (is_round) {
+ float t;
+ float3 D = normalize_len(lightpos - P, &t);
+ portal_pdf += fabsf(klight->area.invarea) * lamp_light_pdf(kg, dir, -D, t);
+ }
+ else {
+ portal_pdf += rect_light_sample(P, &lightpos, axisu, axisv, 0.0f, 0.0f, false);
+ }
+ }
+
+ if (ignore_portal >= 0) {
+ /* We have skipped a portal that could be sampled as well. */
+ num_possible++;
+ }
+
+ return (num_possible > 0) ? portal_pdf / num_possible : 0.0f;
}
ccl_device int background_num_possible_portals(KernelGlobals *kg, float3 P)
{
- int num_possible_portals = 0;
- for(int p = 0; p < kernel_data.integrator.num_portals; p++) {
- float3 lightpos, dir;
- if(background_portal_data_fetch_and_check_side(kg, P, p, &lightpos, &dir))
- num_possible_portals++;
- }
- return num_possible_portals;
+ int num_possible_portals = 0;
+ for (int p = 0; p < kernel_data.integrator.num_portals; p++) {
+ float3 lightpos, dir;
+ if (background_portal_data_fetch_and_check_side(kg, P, p, &lightpos, &dir))
+ num_possible_portals++;
+ }
+ return num_possible_portals;
}
ccl_device float3 background_portal_sample(KernelGlobals *kg,
@@ -387,774 +409,754 @@ ccl_device float3 background_portal_sample(KernelGlobals *kg,
int *sampled_portal,
float *pdf)
{
- /* Pick a portal, then re-normalize randv. */
- randv *= num_possible;
- int portal = (int)randv;
- randv -= portal;
-
- /* TODO(sergey): Some smarter way of finding portal to sample
- * is welcome.
- */
- for(int p = 0; p < kernel_data.integrator.num_portals; p++) {
- /* Search for the sampled portal. */
- float3 lightpos, dir;
- if(!background_portal_data_fetch_and_check_side(kg, P, p, &lightpos, &dir))
- continue;
-
- if(portal == 0) {
- /* p is the portal to be sampled. */
- int portal = kernel_data.integrator.portal_offset + p;
- const ccl_global KernelLight *klight = &kernel_tex_fetch(__lights, portal);
- float3 axisu = make_float3(klight->area.axisu[0], klight->area.axisu[1], klight->area.axisu[2]);
- float3 axisv = make_float3(klight->area.axisv[0], klight->area.axisv[1], klight->area.axisv[2]);
- bool is_round = (klight->area.invarea < 0.0f);
-
- float3 D;
- if(is_round) {
- lightpos += ellipse_sample(axisu*0.5f, axisv*0.5f, randu, randv);
- float t;
- D = normalize_len(lightpos - P, &t);
- *pdf = fabsf(klight->area.invarea) * lamp_light_pdf(kg, dir, -D, t);
- }
- else {
- *pdf = rect_light_sample(P, &lightpos,
- axisu, axisv,
- randu, randv,
- true);
- D = normalize(lightpos - P);
- }
-
- *pdf /= num_possible;
- *sampled_portal = p;
- return D;
- }
-
- portal--;
- }
-
- return make_float3(0.0f, 0.0f, 0.0f);
+ /* Pick a portal, then re-normalize randv. */
+ randv *= num_possible;
+ int portal = (int)randv;
+ randv -= portal;
+
+ /* TODO(sergey): Some smarter way of finding portal to sample
+ * is welcome.
+ */
+ for (int p = 0; p < kernel_data.integrator.num_portals; p++) {
+ /* Search for the sampled portal. */
+ float3 lightpos, dir;
+ if (!background_portal_data_fetch_and_check_side(kg, P, p, &lightpos, &dir))
+ continue;
+
+ if (portal == 0) {
+ /* p is the portal to be sampled. */
+ int portal = kernel_data.integrator.portal_offset + p;
+ const ccl_global KernelLight *klight = &kernel_tex_fetch(__lights, portal);
+ float3 axisu = make_float3(
+ klight->area.axisu[0], klight->area.axisu[1], klight->area.axisu[2]);
+ float3 axisv = make_float3(
+ klight->area.axisv[0], klight->area.axisv[1], klight->area.axisv[2]);
+ bool is_round = (klight->area.invarea < 0.0f);
+
+ float3 D;
+ if (is_round) {
+ lightpos += ellipse_sample(axisu * 0.5f, axisv * 0.5f, randu, randv);
+ float t;
+ D = normalize_len(lightpos - P, &t);
+ *pdf = fabsf(klight->area.invarea) * lamp_light_pdf(kg, dir, -D, t);
+ }
+ else {
+ *pdf = rect_light_sample(P, &lightpos, axisu, axisv, randu, randv, true);
+ D = normalize(lightpos - P);
+ }
+
+ *pdf /= num_possible;
+ *sampled_portal = p;
+ return D;
+ }
+
+ portal--;
+ }
+
+ return make_float3(0.0f, 0.0f, 0.0f);
}
-ccl_device_inline float3 background_light_sample(KernelGlobals *kg,
- float3 P,
- float randu, float randv,
- float *pdf)
+ccl_device_inline float3
+background_light_sample(KernelGlobals *kg, float3 P, float randu, float randv, float *pdf)
{
- /* Probability of sampling portals instead of the map. */
- float portal_sampling_pdf = kernel_data.integrator.portal_pdf;
-
- /* Check if there are portals in the scene which we can sample. */
- if(portal_sampling_pdf > 0.0f) {
- int num_portals = background_num_possible_portals(kg, P);
- if(num_portals > 0) {
- if(portal_sampling_pdf == 1.0f || randu < portal_sampling_pdf) {
- if(portal_sampling_pdf < 1.0f) {
- randu /= portal_sampling_pdf;
- }
- int portal;
- float3 D = background_portal_sample(kg, P, randu, randv, num_portals, &portal, pdf);
- if(num_portals > 1) {
- /* Ignore the chosen portal, its pdf is already included. */
- *pdf += background_portal_pdf(kg, P, D, portal, NULL);
- }
- /* We could also have sampled the map, so combine with MIS. */
- if(portal_sampling_pdf < 1.0f) {
- float cdf_pdf = background_map_pdf(kg, D);
- *pdf = (portal_sampling_pdf * (*pdf)
- + (1.0f - portal_sampling_pdf) * cdf_pdf);
- }
- return D;
- }
- else {
- /* Sample map, but with nonzero portal_sampling_pdf for MIS. */
- randu = (randu - portal_sampling_pdf) / (1.0f - portal_sampling_pdf);
- }
- }
- else {
- /* We can't sample a portal.
- * Check if we can sample the map instead.
- */
- if(portal_sampling_pdf == 1.0f) {
- /* Use uniform as a fallback if we can't sample the map. */
- *pdf = 1.0f / M_4PI_F;
- return sample_uniform_sphere(randu, randv);
- }
- else {
- portal_sampling_pdf = 0.0f;
- }
- }
- }
-
- float3 D = background_map_sample(kg, randu, randv, pdf);
- /* Use MIS if portals could be sampled as well. */
- if(portal_sampling_pdf > 0.0f) {
- float portal_pdf = background_portal_pdf(kg, P, D, -1, NULL);
- *pdf = (portal_sampling_pdf * portal_pdf
- + (1.0f - portal_sampling_pdf) * (*pdf));
- }
- return D;
+ /* Probability of sampling portals instead of the map. */
+ float portal_sampling_pdf = kernel_data.integrator.portal_pdf;
+
+ /* Check if there are portals in the scene which we can sample. */
+ if (portal_sampling_pdf > 0.0f) {
+ int num_portals = background_num_possible_portals(kg, P);
+ if (num_portals > 0) {
+ if (portal_sampling_pdf == 1.0f || randu < portal_sampling_pdf) {
+ if (portal_sampling_pdf < 1.0f) {
+ randu /= portal_sampling_pdf;
+ }
+ int portal;
+ float3 D = background_portal_sample(kg, P, randu, randv, num_portals, &portal, pdf);
+ if (num_portals > 1) {
+ /* Ignore the chosen portal, its pdf is already included. */
+ *pdf += background_portal_pdf(kg, P, D, portal, NULL);
+ }
+ /* We could also have sampled the map, so combine with MIS. */
+ if (portal_sampling_pdf < 1.0f) {
+ float cdf_pdf = background_map_pdf(kg, D);
+ *pdf = (portal_sampling_pdf * (*pdf) + (1.0f - portal_sampling_pdf) * cdf_pdf);
+ }
+ return D;
+ }
+ else {
+ /* Sample map, but with nonzero portal_sampling_pdf for MIS. */
+ randu = (randu - portal_sampling_pdf) / (1.0f - portal_sampling_pdf);
+ }
+ }
+ else {
+ /* We can't sample a portal.
+ * Check if we can sample the map instead.
+ */
+ if (portal_sampling_pdf == 1.0f) {
+ /* Use uniform as a fallback if we can't sample the map. */
+ *pdf = 1.0f / M_4PI_F;
+ return sample_uniform_sphere(randu, randv);
+ }
+ else {
+ portal_sampling_pdf = 0.0f;
+ }
+ }
+ }
+
+ float3 D = background_map_sample(kg, randu, randv, pdf);
+ /* Use MIS if portals could be sampled as well. */
+ if (portal_sampling_pdf > 0.0f) {
+ float portal_pdf = background_portal_pdf(kg, P, D, -1, NULL);
+ *pdf = (portal_sampling_pdf * portal_pdf + (1.0f - portal_sampling_pdf) * (*pdf));
+ }
+ return D;
}
ccl_device float background_light_pdf(KernelGlobals *kg, float3 P, float3 direction)
{
- /* Probability of sampling portals instead of the map. */
- float portal_sampling_pdf = kernel_data.integrator.portal_pdf;
-
- float portal_pdf = 0.0f, map_pdf = 0.0f;
- if(portal_sampling_pdf > 0.0f) {
- /* Evaluate PDF of sampling this direction by portal sampling. */
- bool is_possible = false;
- portal_pdf = background_portal_pdf(kg, P, direction, -1, &is_possible) * portal_sampling_pdf;
- if(!is_possible) {
- /* Portal sampling is not possible here because all portals point to the wrong side.
- * If map sampling is possible, it would be used instead, otherwise fallback sampling is used. */
- if(portal_sampling_pdf == 1.0f) {
- return kernel_data.integrator.pdf_lights / M_4PI_F;
- }
- else {
- /* Force map sampling. */
- portal_sampling_pdf = 0.0f;
- }
- }
- }
- if(portal_sampling_pdf < 1.0f) {
- /* Evaluate PDF of sampling this direction by map sampling. */
- map_pdf = background_map_pdf(kg, direction) * (1.0f - portal_sampling_pdf);
- }
- return (portal_pdf + map_pdf) * kernel_data.integrator.pdf_lights;
+ /* Probability of sampling portals instead of the map. */
+ float portal_sampling_pdf = kernel_data.integrator.portal_pdf;
+
+ float portal_pdf = 0.0f, map_pdf = 0.0f;
+ if (portal_sampling_pdf > 0.0f) {
+ /* Evaluate PDF of sampling this direction by portal sampling. */
+ bool is_possible = false;
+ portal_pdf = background_portal_pdf(kg, P, direction, -1, &is_possible) * portal_sampling_pdf;
+ if (!is_possible) {
+ /* Portal sampling is not possible here because all portals point to the wrong side.
+ * If map sampling is possible, it would be used instead, otherwise fallback sampling is used. */
+ if (portal_sampling_pdf == 1.0f) {
+ return kernel_data.integrator.pdf_lights / M_4PI_F;
+ }
+ else {
+ /* Force map sampling. */
+ portal_sampling_pdf = 0.0f;
+ }
+ }
+ }
+ if (portal_sampling_pdf < 1.0f) {
+ /* Evaluate PDF of sampling this direction by map sampling. */
+ map_pdf = background_map_pdf(kg, direction) * (1.0f - portal_sampling_pdf);
+ }
+ return (portal_pdf + map_pdf) * kernel_data.integrator.pdf_lights;
}
#endif
/* Regular Light */
-ccl_device_inline bool lamp_light_sample(KernelGlobals *kg,
- int lamp,
- float randu, float randv,
- float3 P,
- LightSample *ls)
+ccl_device_inline bool lamp_light_sample(
+ KernelGlobals *kg, int lamp, float randu, float randv, float3 P, LightSample *ls)
{
- const ccl_global KernelLight *klight = &kernel_tex_fetch(__lights, lamp);
- LightType type = (LightType)klight->type;
- ls->type = type;
- ls->shader = klight->shader_id;
- ls->object = PRIM_NONE;
- ls->prim = PRIM_NONE;
- ls->lamp = lamp;
- ls->u = randu;
- ls->v = randv;
-
- if(type == LIGHT_DISTANT) {
- /* distant light */
- float3 lightD = make_float3(klight->co[0], klight->co[1], klight->co[2]);
- float3 D = lightD;
- float radius = klight->distant.radius;
- float invarea = klight->distant.invarea;
-
- if(radius > 0.0f)
- D = distant_light_sample(D, radius, randu, randv);
-
- ls->P = D;
- ls->Ng = D;
- ls->D = -D;
- ls->t = FLT_MAX;
-
- float costheta = dot(lightD, D);
- ls->pdf = invarea/(costheta*costheta*costheta);
- ls->eval_fac = ls->pdf;
- }
+ const ccl_global KernelLight *klight = &kernel_tex_fetch(__lights, lamp);
+ LightType type = (LightType)klight->type;
+ ls->type = type;
+ ls->shader = klight->shader_id;
+ ls->object = PRIM_NONE;
+ ls->prim = PRIM_NONE;
+ ls->lamp = lamp;
+ ls->u = randu;
+ ls->v = randv;
+
+ if (type == LIGHT_DISTANT) {
+ /* distant light */
+ float3 lightD = make_float3(klight->co[0], klight->co[1], klight->co[2]);
+ float3 D = lightD;
+ float radius = klight->distant.radius;
+ float invarea = klight->distant.invarea;
+
+ if (radius > 0.0f)
+ D = distant_light_sample(D, radius, randu, randv);
+
+ ls->P = D;
+ ls->Ng = D;
+ ls->D = -D;
+ ls->t = FLT_MAX;
+
+ float costheta = dot(lightD, D);
+ ls->pdf = invarea / (costheta * costheta * costheta);
+ ls->eval_fac = ls->pdf;
+ }
#ifdef __BACKGROUND_MIS__
- else if(type == LIGHT_BACKGROUND) {
- /* infinite area light (e.g. light dome or env light) */
- float3 D = -background_light_sample(kg, P, randu, randv, &ls->pdf);
-
- ls->P = D;
- ls->Ng = D;
- ls->D = -D;
- ls->t = FLT_MAX;
- ls->eval_fac = 1.0f;
- }
+ else if (type == LIGHT_BACKGROUND) {
+ /* infinite area light (e.g. light dome or env light) */
+ float3 D = -background_light_sample(kg, P, randu, randv, &ls->pdf);
+
+ ls->P = D;
+ ls->Ng = D;
+ ls->D = -D;
+ ls->t = FLT_MAX;
+ ls->eval_fac = 1.0f;
+ }
#endif
- else {
- ls->P = make_float3(klight->co[0], klight->co[1], klight->co[2]);
-
- if(type == LIGHT_POINT || type == LIGHT_SPOT) {
- float radius = klight->spot.radius;
-
- if(radius > 0.0f)
- /* sphere light */
- ls->P += sphere_light_sample(P, ls->P, radius, randu, randv);
-
- ls->D = normalize_len(ls->P - P, &ls->t);
- ls->Ng = -ls->D;
-
- float invarea = klight->spot.invarea;
- ls->eval_fac = (0.25f*M_1_PI_F)*invarea;
- ls->pdf = invarea;
-
- if(type == LIGHT_SPOT) {
- /* spot light attenuation */
- float3 dir = make_float3(klight->spot.dir[0],
- klight->spot.dir[1],
- klight->spot.dir[2]);
- ls->eval_fac *= spot_light_attenuation(dir,
- klight->spot.spot_angle,
- klight->spot.spot_smooth,
- ls);
- if(ls->eval_fac == 0.0f) {
- return false;
- }
- }
- float2 uv = map_to_sphere(ls->Ng);
- ls->u = uv.x;
- ls->v = uv.y;
-
- ls->pdf *= lamp_light_pdf(kg, ls->Ng, -ls->D, ls->t);
- }
- else {
- /* area light */
- float3 axisu = make_float3(klight->area.axisu[0],
- klight->area.axisu[1],
- klight->area.axisu[2]);
- float3 axisv = make_float3(klight->area.axisv[0],
- klight->area.axisv[1],
- klight->area.axisv[2]);
- float3 D = make_float3(klight->area.dir[0],
- klight->area.dir[1],
- klight->area.dir[2]);
- float invarea = fabsf(klight->area.invarea);
- bool is_round = (klight->area.invarea < 0.0f);
-
- if(dot(ls->P - P, D) > 0.0f) {
- return false;
- }
-
- float3 inplane;
-
- if(is_round) {
- inplane = ellipse_sample(axisu*0.5f, axisv*0.5f, randu, randv);
- ls->P += inplane;
- ls->pdf = invarea;
- }
- else {
- inplane = ls->P;
- ls->pdf = rect_light_sample(P, &ls->P,
- axisu, axisv,
- randu, randv,
- true);
- inplane = ls->P - inplane;
- }
-
- ls->u = dot(inplane, axisu) * (1.0f / dot(axisu, axisu)) + 0.5f;
- ls->v = dot(inplane, axisv) * (1.0f / dot(axisv, axisv)) + 0.5f;
-
- ls->Ng = D;
- ls->D = normalize_len(ls->P - P, &ls->t);
-
- ls->eval_fac = 0.25f*invarea;
- if(is_round) {
- ls->pdf *= lamp_light_pdf(kg, D, -ls->D, ls->t);
- }
- }
- }
-
- ls->pdf *= kernel_data.integrator.pdf_lights;
-
- return (ls->pdf > 0.0f);
+ else {
+ ls->P = make_float3(klight->co[0], klight->co[1], klight->co[2]);
+
+ if (type == LIGHT_POINT || type == LIGHT_SPOT) {
+ float radius = klight->spot.radius;
+
+ if (radius > 0.0f)
+ /* sphere light */
+ ls->P += sphere_light_sample(P, ls->P, radius, randu, randv);
+
+ ls->D = normalize_len(ls->P - P, &ls->t);
+ ls->Ng = -ls->D;
+
+ float invarea = klight->spot.invarea;
+ ls->eval_fac = (0.25f * M_1_PI_F) * invarea;
+ ls->pdf = invarea;
+
+ if (type == LIGHT_SPOT) {
+ /* spot light attenuation */
+ float3 dir = make_float3(klight->spot.dir[0], klight->spot.dir[1], klight->spot.dir[2]);
+ ls->eval_fac *= spot_light_attenuation(
+ dir, klight->spot.spot_angle, klight->spot.spot_smooth, ls);
+ if (ls->eval_fac == 0.0f) {
+ return false;
+ }
+ }
+ float2 uv = map_to_sphere(ls->Ng);
+ ls->u = uv.x;
+ ls->v = uv.y;
+
+ ls->pdf *= lamp_light_pdf(kg, ls->Ng, -ls->D, ls->t);
+ }
+ else {
+ /* area light */
+ float3 axisu = make_float3(
+ klight->area.axisu[0], klight->area.axisu[1], klight->area.axisu[2]);
+ float3 axisv = make_float3(
+ klight->area.axisv[0], klight->area.axisv[1], klight->area.axisv[2]);
+ float3 D = make_float3(klight->area.dir[0], klight->area.dir[1], klight->area.dir[2]);
+ float invarea = fabsf(klight->area.invarea);
+ bool is_round = (klight->area.invarea < 0.0f);
+
+ if (dot(ls->P - P, D) > 0.0f) {
+ return false;
+ }
+
+ float3 inplane;
+
+ if (is_round) {
+ inplane = ellipse_sample(axisu * 0.5f, axisv * 0.5f, randu, randv);
+ ls->P += inplane;
+ ls->pdf = invarea;
+ }
+ else {
+ inplane = ls->P;
+ ls->pdf = rect_light_sample(P, &ls->P, axisu, axisv, randu, randv, true);
+ inplane = ls->P - inplane;
+ }
+
+ ls->u = dot(inplane, axisu) * (1.0f / dot(axisu, axisu)) + 0.5f;
+ ls->v = dot(inplane, axisv) * (1.0f / dot(axisv, axisv)) + 0.5f;
+
+ ls->Ng = D;
+ ls->D = normalize_len(ls->P - P, &ls->t);
+
+ ls->eval_fac = 0.25f * invarea;
+ if (is_round) {
+ ls->pdf *= lamp_light_pdf(kg, D, -ls->D, ls->t);
+ }
+ }
+ }
+
+ ls->pdf *= kernel_data.integrator.pdf_lights;
+
+ return (ls->pdf > 0.0f);
}
-ccl_device bool lamp_light_eval(KernelGlobals *kg, int lamp, float3 P, float3 D, float t, LightSample *ls)
+ccl_device bool lamp_light_eval(
+ KernelGlobals *kg, int lamp, float3 P, float3 D, float t, LightSample *ls)
{
- const ccl_global KernelLight *klight = &kernel_tex_fetch(__lights, lamp);
- LightType type = (LightType)klight->type;
- ls->type = type;
- ls->shader = klight->shader_id;
- ls->object = PRIM_NONE;
- ls->prim = PRIM_NONE;
- ls->lamp = lamp;
- /* todo: missing texture coordinates */
- ls->u = 0.0f;
- ls->v = 0.0f;
-
- if(!(ls->shader & SHADER_USE_MIS))
- return false;
-
- if(type == LIGHT_DISTANT) {
- /* distant light */
- float radius = klight->distant.radius;
-
- if(radius == 0.0f)
- return false;
- if(t != FLT_MAX)
- return false;
-
- /* a distant light is infinitely far away, but equivalent to a disk
- * shaped light exactly 1 unit away from the current shading point.
- *
- * radius t^2/cos(theta)
- * <----------> t = sqrt(1^2 + tan(theta)^2)
- * tan(th) area = radius*radius*pi
- * <----->
- * \ | (1 + tan(theta)^2)/cos(theta)
- * \ | (1 + tan(acos(cos(theta)))^2)/cos(theta)
- * t \th| 1 simplifies to
- * \-| 1/(cos(theta)^3)
- * \| magic!
- * P
- */
-
- float3 lightD = make_float3(klight->co[0], klight->co[1], klight->co[2]);
- float costheta = dot(-lightD, D);
- float cosangle = klight->distant.cosangle;
-
- if(costheta < cosangle)
- return false;
-
- ls->P = -D;
- ls->Ng = -D;
- ls->D = D;
- ls->t = FLT_MAX;
-
- /* compute pdf */
- float invarea = klight->distant.invarea;
- ls->pdf = invarea/(costheta*costheta*costheta);
- ls->eval_fac = ls->pdf;
- }
- else if(type == LIGHT_POINT || type == LIGHT_SPOT) {
- float3 lightP = make_float3(klight->co[0], klight->co[1], klight->co[2]);
-
- float radius = klight->spot.radius;
-
- /* sphere light */
- if(radius == 0.0f)
- return false;
-
- if(!ray_aligned_disk_intersect(P, D, t,
- lightP, radius, &ls->P, &ls->t))
- {
- return false;
- }
-
- ls->Ng = -D;
- ls->D = D;
-
- float invarea = klight->spot.invarea;
- ls->eval_fac = (0.25f*M_1_PI_F)*invarea;
- ls->pdf = invarea;
-
- if(type == LIGHT_SPOT) {
- /* spot light attenuation */
- float3 dir = make_float3(klight->spot.dir[0],
- klight->spot.dir[1],
- klight->spot.dir[2]);
- ls->eval_fac *= spot_light_attenuation(dir,
- klight->spot.spot_angle,
- klight->spot.spot_smooth,
- ls);
-
- if(ls->eval_fac == 0.0f)
- return false;
- }
- float2 uv = map_to_sphere(ls->Ng);
- ls->u = uv.x;
- ls->v = uv.y;
-
- /* compute pdf */
- if(ls->t != FLT_MAX)
- ls->pdf *= lamp_light_pdf(kg, ls->Ng, -ls->D, ls->t);
- }
- else if(type == LIGHT_AREA) {
- /* area light */
- float invarea = fabsf(klight->area.invarea);
- bool is_round = (klight->area.invarea < 0.0f);
- if(invarea == 0.0f)
- return false;
-
- float3 axisu = make_float3(klight->area.axisu[0],
- klight->area.axisu[1],
- klight->area.axisu[2]);
- float3 axisv = make_float3(klight->area.axisv[0],
- klight->area.axisv[1],
- klight->area.axisv[2]);
- float3 Ng = make_float3(klight->area.dir[0],
- klight->area.dir[1],
- klight->area.dir[2]);
-
- /* one sided */
- if(dot(D, Ng) >= 0.0f)
- return false;
-
- float3 light_P = make_float3(klight->co[0], klight->co[1], klight->co[2]);
-
- if(!ray_quad_intersect(P, D, 0.0f, t, light_P,
- axisu, axisv, Ng,
- &ls->P, &ls->t,
- &ls->u, &ls->v,
- is_round))
- {
- return false;
- }
-
- ls->D = D;
- ls->Ng = Ng;
- if(is_round) {
- ls->pdf = invarea * lamp_light_pdf(kg, Ng, -D, ls->t);
- }
- else {
- ls->pdf = rect_light_sample(P, &light_P, axisu, axisv, 0, 0, false);
- }
- ls->eval_fac = 0.25f*invarea;
- }
- else {
- return false;
- }
-
- ls->pdf *= kernel_data.integrator.pdf_lights;
-
- return true;
+ const ccl_global KernelLight *klight = &kernel_tex_fetch(__lights, lamp);
+ LightType type = (LightType)klight->type;
+ ls->type = type;
+ ls->shader = klight->shader_id;
+ ls->object = PRIM_NONE;
+ ls->prim = PRIM_NONE;
+ ls->lamp = lamp;
+ /* todo: missing texture coordinates */
+ ls->u = 0.0f;
+ ls->v = 0.0f;
+
+ if (!(ls->shader & SHADER_USE_MIS))
+ return false;
+
+ if (type == LIGHT_DISTANT) {
+ /* distant light */
+ float radius = klight->distant.radius;
+
+ if (radius == 0.0f)
+ return false;
+ if (t != FLT_MAX)
+ return false;
+
+ /* a distant light is infinitely far away, but equivalent to a disk
+ * shaped light exactly 1 unit away from the current shading point.
+ *
+ * radius t^2/cos(theta)
+ * <----------> t = sqrt(1^2 + tan(theta)^2)
+ * tan(th) area = radius*radius*pi
+ * <----->
+ * \ | (1 + tan(theta)^2)/cos(theta)
+ * \ | (1 + tan(acos(cos(theta)))^2)/cos(theta)
+ * t \th| 1 simplifies to
+ * \-| 1/(cos(theta)^3)
+ * \| magic!
+ * P
+ */
+
+ float3 lightD = make_float3(klight->co[0], klight->co[1], klight->co[2]);
+ float costheta = dot(-lightD, D);
+ float cosangle = klight->distant.cosangle;
+
+ if (costheta < cosangle)
+ return false;
+
+ ls->P = -D;
+ ls->Ng = -D;
+ ls->D = D;
+ ls->t = FLT_MAX;
+
+ /* compute pdf */
+ float invarea = klight->distant.invarea;
+ ls->pdf = invarea / (costheta * costheta * costheta);
+ ls->eval_fac = ls->pdf;
+ }
+ else if (type == LIGHT_POINT || type == LIGHT_SPOT) {
+ float3 lightP = make_float3(klight->co[0], klight->co[1], klight->co[2]);
+
+ float radius = klight->spot.radius;
+
+ /* sphere light */
+ if (radius == 0.0f)
+ return false;
+
+ if (!ray_aligned_disk_intersect(P, D, t, lightP, radius, &ls->P, &ls->t)) {
+ return false;
+ }
+
+ ls->Ng = -D;
+ ls->D = D;
+
+ float invarea = klight->spot.invarea;
+ ls->eval_fac = (0.25f * M_1_PI_F) * invarea;
+ ls->pdf = invarea;
+
+ if (type == LIGHT_SPOT) {
+ /* spot light attenuation */
+ float3 dir = make_float3(klight->spot.dir[0], klight->spot.dir[1], klight->spot.dir[2]);
+ ls->eval_fac *= spot_light_attenuation(
+ dir, klight->spot.spot_angle, klight->spot.spot_smooth, ls);
+
+ if (ls->eval_fac == 0.0f)
+ return false;
+ }
+ float2 uv = map_to_sphere(ls->Ng);
+ ls->u = uv.x;
+ ls->v = uv.y;
+
+ /* compute pdf */
+ if (ls->t != FLT_MAX)
+ ls->pdf *= lamp_light_pdf(kg, ls->Ng, -ls->D, ls->t);
+ }
+ else if (type == LIGHT_AREA) {
+ /* area light */
+ float invarea = fabsf(klight->area.invarea);
+ bool is_round = (klight->area.invarea < 0.0f);
+ if (invarea == 0.0f)
+ return false;
+
+ float3 axisu = make_float3(
+ klight->area.axisu[0], klight->area.axisu[1], klight->area.axisu[2]);
+ float3 axisv = make_float3(
+ klight->area.axisv[0], klight->area.axisv[1], klight->area.axisv[2]);
+ float3 Ng = make_float3(klight->area.dir[0], klight->area.dir[1], klight->area.dir[2]);
+
+ /* one sided */
+ if (dot(D, Ng) >= 0.0f)
+ return false;
+
+ float3 light_P = make_float3(klight->co[0], klight->co[1], klight->co[2]);
+
+ if (!ray_quad_intersect(
+ P, D, 0.0f, t, light_P, axisu, axisv, Ng, &ls->P, &ls->t, &ls->u, &ls->v, is_round)) {
+ return false;
+ }
+
+ ls->D = D;
+ ls->Ng = Ng;
+ if (is_round) {
+ ls->pdf = invarea * lamp_light_pdf(kg, Ng, -D, ls->t);
+ }
+ else {
+ ls->pdf = rect_light_sample(P, &light_P, axisu, axisv, 0, 0, false);
+ }
+ ls->eval_fac = 0.25f * invarea;
+ }
+ else {
+ return false;
+ }
+
+ ls->pdf *= kernel_data.integrator.pdf_lights;
+
+ return true;
}
/* Triangle Light */
/* returns true if the triangle is has motion blur or an instancing transform applied */
-ccl_device_inline bool triangle_world_space_vertices(KernelGlobals *kg, int object, int prim, float time, float3 V[3])
+ccl_device_inline bool triangle_world_space_vertices(
+ KernelGlobals *kg, int object, int prim, float time, float3 V[3])
{
- bool has_motion = false;
- const int object_flag = kernel_tex_fetch(__object_flag, object);
+ bool has_motion = false;
+ const int object_flag = kernel_tex_fetch(__object_flag, object);
- if(object_flag & SD_OBJECT_HAS_VERTEX_MOTION && time >= 0.0f) {
- motion_triangle_vertices(kg, object, prim, time, V);
- has_motion = true;
- }
- else {
- triangle_vertices(kg, prim, V);
- }
+ if (object_flag & SD_OBJECT_HAS_VERTEX_MOTION && time >= 0.0f) {
+ motion_triangle_vertices(kg, object, prim, time, V);
+ has_motion = true;
+ }
+ else {
+ triangle_vertices(kg, prim, V);
+ }
#ifdef __INSTANCING__
- if(!(object_flag & SD_OBJECT_TRANSFORM_APPLIED)) {
+ if (!(object_flag & SD_OBJECT_TRANSFORM_APPLIED)) {
# ifdef __OBJECT_MOTION__
- float object_time = (time >= 0.0f) ? time : 0.5f;
- Transform tfm = object_fetch_transform_motion_test(kg, object, object_time, NULL);
+ float object_time = (time >= 0.0f) ? time : 0.5f;
+ Transform tfm = object_fetch_transform_motion_test(kg, object, object_time, NULL);
# else
- Transform tfm = object_fetch_transform(kg, object, OBJECT_TRANSFORM);
+ Transform tfm = object_fetch_transform(kg, object, OBJECT_TRANSFORM);
# endif
- V[0] = transform_point(&tfm, V[0]);
- V[1] = transform_point(&tfm, V[1]);
- V[2] = transform_point(&tfm, V[2]);
- has_motion = true;
- }
+ V[0] = transform_point(&tfm, V[0]);
+ V[1] = transform_point(&tfm, V[1]);
+ V[2] = transform_point(&tfm, V[2]);
+ has_motion = true;
+ }
#endif
- return has_motion;
+ return has_motion;
}
-ccl_device_inline float triangle_light_pdf_area(KernelGlobals *kg, const float3 Ng, const float3 I, float t)
+ccl_device_inline float triangle_light_pdf_area(KernelGlobals *kg,
+ const float3 Ng,
+ const float3 I,
+ float t)
{
- float pdf = kernel_data.integrator.pdf_triangles;
- float cos_pi = fabsf(dot(Ng, I));
+ float pdf = kernel_data.integrator.pdf_triangles;
+ float cos_pi = fabsf(dot(Ng, I));
- if(cos_pi == 0.0f)
- return 0.0f;
+ if (cos_pi == 0.0f)
+ return 0.0f;
- return t*t*pdf/cos_pi;
+ return t * t * pdf / cos_pi;
}
ccl_device_forceinline float triangle_light_pdf(KernelGlobals *kg, ShaderData *sd, float t)
{
- /* A naive heuristic to decide between costly solid angle sampling
- * and simple area sampling, comparing the distance to the triangle plane
- * to the length of the edges of the triangle. */
-
- float3 V[3];
- bool has_motion = triangle_world_space_vertices(kg, sd->object, sd->prim, sd->time, V);
-
- const float3 e0 = V[1] - V[0];
- const float3 e1 = V[2] - V[0];
- const float3 e2 = V[2] - V[1];
- const float longest_edge_squared = max(len_squared(e0), max(len_squared(e1), len_squared(e2)));
- const float3 N = cross(e0, e1);
- const float distance_to_plane = fabsf(dot(N, sd->I * t))/dot(N, N);
-
- if(longest_edge_squared > distance_to_plane*distance_to_plane) {
- /* sd contains the point on the light source
- * calculate Px, the point that we're shading */
- const float3 Px = sd->P + sd->I * t;
- const float3 v0_p = V[0] - Px;
- const float3 v1_p = V[1] - Px;
- const float3 v2_p = V[2] - Px;
-
- const float3 u01 = safe_normalize(cross(v0_p, v1_p));
- const float3 u02 = safe_normalize(cross(v0_p, v2_p));
- const float3 u12 = safe_normalize(cross(v1_p, v2_p));
-
- const float alpha = fast_acosf(dot(u02, u01));
- const float beta = fast_acosf(-dot(u01, u12));
- const float gamma = fast_acosf(dot(u02, u12));
- const float solid_angle = alpha + beta + gamma - M_PI_F;
-
- /* pdf_triangles is calculated over triangle area, but we're not sampling over its area */
- if(UNLIKELY(solid_angle == 0.0f)) {
- return 0.0f;
- }
- else {
- float area = 1.0f;
- if(has_motion) {
- /* get the center frame vertices, this is what the PDF was calculated from */
- triangle_world_space_vertices(kg, sd->object, sd->prim, -1.0f, V);
- area = triangle_area(V[0], V[1], V[2]);
- }
- else {
- area = 0.5f * len(N);
- }
- const float pdf = area * kernel_data.integrator.pdf_triangles;
- return pdf / solid_angle;
- }
- }
- else {
- float pdf = triangle_light_pdf_area(kg, sd->Ng, sd->I, t);
- if(has_motion) {
- const float area = 0.5f * len(N);
- if(UNLIKELY(area == 0.0f)) {
- return 0.0f;
- }
- /* scale the PDF.
- * area = the area the sample was taken from
- * area_pre = the are from which pdf_triangles was calculated from */
- triangle_world_space_vertices(kg, sd->object, sd->prim, -1.0f, V);
- const float area_pre = triangle_area(V[0], V[1], V[2]);
- pdf = pdf * area_pre / area;
- }
- return pdf;
- }
+ /* A naive heuristic to decide between costly solid angle sampling
+ * and simple area sampling, comparing the distance to the triangle plane
+ * to the length of the edges of the triangle. */
+
+ float3 V[3];
+ bool has_motion = triangle_world_space_vertices(kg, sd->object, sd->prim, sd->time, V);
+
+ const float3 e0 = V[1] - V[0];
+ const float3 e1 = V[2] - V[0];
+ const float3 e2 = V[2] - V[1];
+ const float longest_edge_squared = max(len_squared(e0), max(len_squared(e1), len_squared(e2)));
+ const float3 N = cross(e0, e1);
+ const float distance_to_plane = fabsf(dot(N, sd->I * t)) / dot(N, N);
+
+ if (longest_edge_squared > distance_to_plane * distance_to_plane) {
+ /* sd contains the point on the light source
+ * calculate Px, the point that we're shading */
+ const float3 Px = sd->P + sd->I * t;
+ const float3 v0_p = V[0] - Px;
+ const float3 v1_p = V[1] - Px;
+ const float3 v2_p = V[2] - Px;
+
+ const float3 u01 = safe_normalize(cross(v0_p, v1_p));
+ const float3 u02 = safe_normalize(cross(v0_p, v2_p));
+ const float3 u12 = safe_normalize(cross(v1_p, v2_p));
+
+ const float alpha = fast_acosf(dot(u02, u01));
+ const float beta = fast_acosf(-dot(u01, u12));
+ const float gamma = fast_acosf(dot(u02, u12));
+ const float solid_angle = alpha + beta + gamma - M_PI_F;
+
+ /* pdf_triangles is calculated over triangle area, but we're not sampling over its area */
+ if (UNLIKELY(solid_angle == 0.0f)) {
+ return 0.0f;
+ }
+ else {
+ float area = 1.0f;
+ if (has_motion) {
+ /* get the center frame vertices, this is what the PDF was calculated from */
+ triangle_world_space_vertices(kg, sd->object, sd->prim, -1.0f, V);
+ area = triangle_area(V[0], V[1], V[2]);
+ }
+ else {
+ area = 0.5f * len(N);
+ }
+ const float pdf = area * kernel_data.integrator.pdf_triangles;
+ return pdf / solid_angle;
+ }
+ }
+ else {
+ float pdf = triangle_light_pdf_area(kg, sd->Ng, sd->I, t);
+ if (has_motion) {
+ const float area = 0.5f * len(N);
+ if (UNLIKELY(area == 0.0f)) {
+ return 0.0f;
+ }
+ /* scale the PDF.
+ * area = the area the sample was taken from
+ * area_pre = the are from which pdf_triangles was calculated from */
+ triangle_world_space_vertices(kg, sd->object, sd->prim, -1.0f, V);
+ const float area_pre = triangle_area(V[0], V[1], V[2]);
+ pdf = pdf * area_pre / area;
+ }
+ return pdf;
+ }
}
-ccl_device_forceinline void triangle_light_sample(KernelGlobals *kg, int prim, int object,
- float randu, float randv, float time, LightSample *ls, const float3 P)
+ccl_device_forceinline void triangle_light_sample(KernelGlobals *kg,
+ int prim,
+ int object,
+ float randu,
+ float randv,
+ float time,
+ LightSample *ls,
+ const float3 P)
{
- /* A naive heuristic to decide between costly solid angle sampling
- * and simple area sampling, comparing the distance to the triangle plane
- * to the length of the edges of the triangle. */
-
- float3 V[3];
- bool has_motion = triangle_world_space_vertices(kg, object, prim, time, V);
-
- const float3 e0 = V[1] - V[0];
- const float3 e1 = V[2] - V[0];
- const float3 e2 = V[2] - V[1];
- const float longest_edge_squared = max(len_squared(e0), max(len_squared(e1), len_squared(e2)));
- const float3 N0 = cross(e0, e1);
- float Nl = 0.0f;
- ls->Ng = safe_normalize_len(N0, &Nl);
- float area = 0.5f * Nl;
-
- /* flip normal if necessary */
- const int object_flag = kernel_tex_fetch(__object_flag, object);
- if(object_flag & SD_OBJECT_NEGATIVE_SCALE_APPLIED) {
- ls->Ng = -ls->Ng;
- }
- ls->eval_fac = 1.0f;
- ls->shader = kernel_tex_fetch(__tri_shader, prim);
- ls->object = object;
- ls->prim = prim;
- ls->lamp = LAMP_NONE;
- ls->shader |= SHADER_USE_MIS;
- ls->type = LIGHT_TRIANGLE;
-
- float distance_to_plane = fabsf(dot(N0, V[0] - P)/dot(N0, N0));
-
- if(longest_edge_squared > distance_to_plane*distance_to_plane) {
- /* see James Arvo, "Stratified Sampling of Spherical Triangles"
- * http://www.graphics.cornell.edu/pubs/1995/Arv95c.pdf */
-
- /* project the triangle to the unit sphere
- * and calculate its edges and angles */
- const float3 v0_p = V[0] - P;
- const float3 v1_p = V[1] - P;
- const float3 v2_p = V[2] - P;
-
- const float3 u01 = safe_normalize(cross(v0_p, v1_p));
- const float3 u02 = safe_normalize(cross(v0_p, v2_p));
- const float3 u12 = safe_normalize(cross(v1_p, v2_p));
-
- const float3 A = safe_normalize(v0_p);
- const float3 B = safe_normalize(v1_p);
- const float3 C = safe_normalize(v2_p);
-
- const float cos_alpha = dot(u02, u01);
- const float cos_beta = -dot(u01, u12);
- const float cos_gamma = dot(u02, u12);
-
- /* calculate dihedral angles */
- const float alpha = fast_acosf(cos_alpha);
- const float beta = fast_acosf(cos_beta);
- const float gamma = fast_acosf(cos_gamma);
- /* the area of the unit spherical triangle = solid angle */
- const float solid_angle = alpha + beta + gamma - M_PI_F;
-
- /* precompute a few things
- * these could be re-used to take several samples
- * as they are independent of randu/randv */
- const float cos_c = dot(A, B);
- const float sin_alpha = fast_sinf(alpha);
- const float product = sin_alpha * cos_c;
-
- /* Select a random sub-area of the spherical triangle
- * and calculate the third vertex C_ of that new triangle */
- const float phi = randu * solid_angle - alpha;
- float s, t;
- fast_sincosf(phi, &s, &t);
- const float u = t - cos_alpha;
- const float v = s + product;
-
- const float3 U = safe_normalize(C - dot(C, A) * A);
-
- float q = 1.0f;
- const float det = ((v * s + u * t) * sin_alpha);
- if(det != 0.0f) {
- q = ((v * t - u * s) * cos_alpha - v) / det;
- }
- const float temp = max(1.0f - q*q, 0.0f);
-
- const float3 C_ = safe_normalize(q * A + sqrtf(temp) * U);
-
- /* Finally, select a random point along the edge of the new triangle
- * That point on the spherical triangle is the sampled ray direction */
- const float z = 1.0f - randv * (1.0f - dot(C_, B));
- ls->D = z * B + safe_sqrtf(1.0f - z*z) * safe_normalize(C_ - dot(C_, B) * B);
-
- /* calculate intersection with the planar triangle */
- if(!ray_triangle_intersect(P, ls->D, FLT_MAX,
+ /* A naive heuristic to decide between costly solid angle sampling
+ * and simple area sampling, comparing the distance to the triangle plane
+ * to the length of the edges of the triangle. */
+
+ float3 V[3];
+ bool has_motion = triangle_world_space_vertices(kg, object, prim, time, V);
+
+ const float3 e0 = V[1] - V[0];
+ const float3 e1 = V[2] - V[0];
+ const float3 e2 = V[2] - V[1];
+ const float longest_edge_squared = max(len_squared(e0), max(len_squared(e1), len_squared(e2)));
+ const float3 N0 = cross(e0, e1);
+ float Nl = 0.0f;
+ ls->Ng = safe_normalize_len(N0, &Nl);
+ float area = 0.5f * Nl;
+
+ /* flip normal if necessary */
+ const int object_flag = kernel_tex_fetch(__object_flag, object);
+ if (object_flag & SD_OBJECT_NEGATIVE_SCALE_APPLIED) {
+ ls->Ng = -ls->Ng;
+ }
+ ls->eval_fac = 1.0f;
+ ls->shader = kernel_tex_fetch(__tri_shader, prim);
+ ls->object = object;
+ ls->prim = prim;
+ ls->lamp = LAMP_NONE;
+ ls->shader |= SHADER_USE_MIS;
+ ls->type = LIGHT_TRIANGLE;
+
+ float distance_to_plane = fabsf(dot(N0, V[0] - P) / dot(N0, N0));
+
+ if (longest_edge_squared > distance_to_plane * distance_to_plane) {
+ /* see James Arvo, "Stratified Sampling of Spherical Triangles"
+ * http://www.graphics.cornell.edu/pubs/1995/Arv95c.pdf */
+
+ /* project the triangle to the unit sphere
+ * and calculate its edges and angles */
+ const float3 v0_p = V[0] - P;
+ const float3 v1_p = V[1] - P;
+ const float3 v2_p = V[2] - P;
+
+ const float3 u01 = safe_normalize(cross(v0_p, v1_p));
+ const float3 u02 = safe_normalize(cross(v0_p, v2_p));
+ const float3 u12 = safe_normalize(cross(v1_p, v2_p));
+
+ const float3 A = safe_normalize(v0_p);
+ const float3 B = safe_normalize(v1_p);
+ const float3 C = safe_normalize(v2_p);
+
+ const float cos_alpha = dot(u02, u01);
+ const float cos_beta = -dot(u01, u12);
+ const float cos_gamma = dot(u02, u12);
+
+ /* calculate dihedral angles */
+ const float alpha = fast_acosf(cos_alpha);
+ const float beta = fast_acosf(cos_beta);
+ const float gamma = fast_acosf(cos_gamma);
+ /* the area of the unit spherical triangle = solid angle */
+ const float solid_angle = alpha + beta + gamma - M_PI_F;
+
+ /* precompute a few things
+ * these could be re-used to take several samples
+ * as they are independent of randu/randv */
+ const float cos_c = dot(A, B);
+ const float sin_alpha = fast_sinf(alpha);
+ const float product = sin_alpha * cos_c;
+
+ /* Select a random sub-area of the spherical triangle
+ * and calculate the third vertex C_ of that new triangle */
+ const float phi = randu * solid_angle - alpha;
+ float s, t;
+ fast_sincosf(phi, &s, &t);
+ const float u = t - cos_alpha;
+ const float v = s + product;
+
+ const float3 U = safe_normalize(C - dot(C, A) * A);
+
+ float q = 1.0f;
+ const float det = ((v * s + u * t) * sin_alpha);
+ if (det != 0.0f) {
+ q = ((v * t - u * s) * cos_alpha - v) / det;
+ }
+ const float temp = max(1.0f - q * q, 0.0f);
+
+ const float3 C_ = safe_normalize(q * A + sqrtf(temp) * U);
+
+ /* Finally, select a random point along the edge of the new triangle
+ * That point on the spherical triangle is the sampled ray direction */
+ const float z = 1.0f - randv * (1.0f - dot(C_, B));
+ ls->D = z * B + safe_sqrtf(1.0f - z * z) * safe_normalize(C_ - dot(C_, B) * B);
+
+ /* calculate intersection with the planar triangle */
+ if (!ray_triangle_intersect(P,
+ ls->D,
+ FLT_MAX,
#if defined(__KERNEL_SSE2__) && defined(__KERNEL_SSE__)
- (ssef*)V,
+ (ssef *)V,
#else
- V[0], V[1], V[2],
+ V[0],
+ V[1],
+ V[2],
#endif
- &ls->u, &ls->v, &ls->t)) {
- ls->pdf = 0.0f;
- return;
- }
-
- ls->P = P + ls->D * ls->t;
-
- /* pdf_triangles is calculated over triangle area, but we're sampling over solid angle */
- if(UNLIKELY(solid_angle == 0.0f)) {
- ls->pdf = 0.0f;
- return;
- }
- else {
- if(has_motion) {
- /* get the center frame vertices, this is what the PDF was calculated from */
- triangle_world_space_vertices(kg, object, prim, -1.0f, V);
- area = triangle_area(V[0], V[1], V[2]);
- }
- const float pdf = area * kernel_data.integrator.pdf_triangles;
- ls->pdf = pdf / solid_angle;
- }
- }
- else {
- /* compute random point in triangle */
- randu = sqrtf(randu);
-
- const float u = 1.0f - randu;
- const float v = randv*randu;
- const float t = 1.0f - u - v;
- ls->P = u * V[0] + v * V[1] + t * V[2];
- /* compute incoming direction, distance and pdf */
- ls->D = normalize_len(ls->P - P, &ls->t);
- ls->pdf = triangle_light_pdf_area(kg, ls->Ng, -ls->D, ls->t);
- if(has_motion && area != 0.0f) {
- /* scale the PDF.
- * area = the area the sample was taken from
- * area_pre = the are from which pdf_triangles was calculated from */
- triangle_world_space_vertices(kg, object, prim, -1.0f, V);
- const float area_pre = triangle_area(V[0], V[1], V[2]);
- ls->pdf = ls->pdf * area_pre / area;
- }
- ls->u = u;
- ls->v = v;
- }
+ &ls->u,
+ &ls->v,
+ &ls->t)) {
+ ls->pdf = 0.0f;
+ return;
+ }
+
+ ls->P = P + ls->D * ls->t;
+
+ /* pdf_triangles is calculated over triangle area, but we're sampling over solid angle */
+ if (UNLIKELY(solid_angle == 0.0f)) {
+ ls->pdf = 0.0f;
+ return;
+ }
+ else {
+ if (has_motion) {
+ /* get the center frame vertices, this is what the PDF was calculated from */
+ triangle_world_space_vertices(kg, object, prim, -1.0f, V);
+ area = triangle_area(V[0], V[1], V[2]);
+ }
+ const float pdf = area * kernel_data.integrator.pdf_triangles;
+ ls->pdf = pdf / solid_angle;
+ }
+ }
+ else {
+ /* compute random point in triangle */
+ randu = sqrtf(randu);
+
+ const float u = 1.0f - randu;
+ const float v = randv * randu;
+ const float t = 1.0f - u - v;
+ ls->P = u * V[0] + v * V[1] + t * V[2];
+ /* compute incoming direction, distance and pdf */
+ ls->D = normalize_len(ls->P - P, &ls->t);
+ ls->pdf = triangle_light_pdf_area(kg, ls->Ng, -ls->D, ls->t);
+ if (has_motion && area != 0.0f) {
+ /* scale the PDF.
+ * area = the area the sample was taken from
+ * area_pre = the are from which pdf_triangles was calculated from */
+ triangle_world_space_vertices(kg, object, prim, -1.0f, V);
+ const float area_pre = triangle_area(V[0], V[1], V[2]);
+ ls->pdf = ls->pdf * area_pre / area;
+ }
+ ls->u = u;
+ ls->v = v;
+ }
}
/* Light Distribution */
ccl_device int light_distribution_sample(KernelGlobals *kg, float *randu)
{
- /* This is basically std::upper_bound as used by pbrt, to find a point light or
- * triangle to emit from, proportional to area. a good improvement would be to
- * also sample proportional to power, though it's not so well defined with
- * arbitrary shaders. */
- int first = 0;
- int len = kernel_data.integrator.num_distribution + 1;
- float r = *randu;
-
- while(len > 0) {
- int half_len = len >> 1;
- int middle = first + half_len;
-
- if(r < kernel_tex_fetch(__light_distribution, middle).totarea) {
- len = half_len;
- }
- else {
- first = middle + 1;
- len = len - half_len - 1;
- }
- }
-
- /* Clamping should not be needed but float rounding errors seem to
- * make this fail on rare occasions. */
- int index = clamp(first-1, 0, kernel_data.integrator.num_distribution-1);
-
- /* Rescale to reuse random number. this helps the 2D samples within
- * each area light be stratified as well. */
- float distr_min = kernel_tex_fetch(__light_distribution, index).totarea;
- float distr_max = kernel_tex_fetch(__light_distribution, index+1).totarea;
- *randu = (r - distr_min)/(distr_max - distr_min);
-
- return index;
+ /* This is basically std::upper_bound as used by pbrt, to find a point light or
+ * triangle to emit from, proportional to area. a good improvement would be to
+ * also sample proportional to power, though it's not so well defined with
+ * arbitrary shaders. */
+ int first = 0;
+ int len = kernel_data.integrator.num_distribution + 1;
+ float r = *randu;
+
+ while (len > 0) {
+ int half_len = len >> 1;
+ int middle = first + half_len;
+
+ if (r < kernel_tex_fetch(__light_distribution, middle).totarea) {
+ len = half_len;
+ }
+ else {
+ first = middle + 1;
+ len = len - half_len - 1;
+ }
+ }
+
+ /* Clamping should not be needed but float rounding errors seem to
+ * make this fail on rare occasions. */
+ int index = clamp(first - 1, 0, kernel_data.integrator.num_distribution - 1);
+
+ /* Rescale to reuse random number. this helps the 2D samples within
+ * each area light be stratified as well. */
+ float distr_min = kernel_tex_fetch(__light_distribution, index).totarea;
+ float distr_max = kernel_tex_fetch(__light_distribution, index + 1).totarea;
+ *randu = (r - distr_min) / (distr_max - distr_min);
+
+ return index;
}
/* Generic Light */
ccl_device bool light_select_reached_max_bounces(KernelGlobals *kg, int index, int bounce)
{
- return (bounce > kernel_tex_fetch(__lights, index).max_bounces);
+ return (bounce > kernel_tex_fetch(__lights, index).max_bounces);
}
-ccl_device_noinline bool light_sample(KernelGlobals *kg,
- float randu,
- float randv,
- float time,
- float3 P,
- int bounce,
- LightSample *ls)
+ccl_device_noinline bool light_sample(
+ KernelGlobals *kg, float randu, float randv, float time, float3 P, int bounce, LightSample *ls)
{
- /* sample index */
- int index = light_distribution_sample(kg, &randu);
-
- /* fetch light data */
- const ccl_global KernelLightDistribution *kdistribution = &kernel_tex_fetch(__light_distribution, index);
- int prim = kdistribution->prim;
-
- if(prim >= 0) {
- int object = kdistribution->mesh_light.object_id;
- int shader_flag = kdistribution->mesh_light.shader_flag;
-
- triangle_light_sample(kg, prim, object, randu, randv, time, ls, P);
- ls->shader |= shader_flag;
- return (ls->pdf > 0.0f);
- }
- else {
- int lamp = -prim-1;
-
- if(UNLIKELY(light_select_reached_max_bounces(kg, lamp, bounce))) {
- return false;
- }
-
- return lamp_light_sample(kg, lamp, randu, randv, P, ls);
- }
+ /* sample index */
+ int index = light_distribution_sample(kg, &randu);
+
+ /* fetch light data */
+ const ccl_global KernelLightDistribution *kdistribution = &kernel_tex_fetch(__light_distribution,
+ index);
+ int prim = kdistribution->prim;
+
+ if (prim >= 0) {
+ int object = kdistribution->mesh_light.object_id;
+ int shader_flag = kdistribution->mesh_light.shader_flag;
+
+ triangle_light_sample(kg, prim, object, randu, randv, time, ls, P);
+ ls->shader |= shader_flag;
+ return (ls->pdf > 0.0f);
+ }
+ else {
+ int lamp = -prim - 1;
+
+ if (UNLIKELY(light_select_reached_max_bounces(kg, lamp, bounce))) {
+ return false;
+ }
+
+ return lamp_light_sample(kg, lamp, randu, randv, P, ls);
+ }
}
ccl_device int light_select_num_samples(KernelGlobals *kg, int index)
{
- return kernel_tex_fetch(__lights, index).samples;
+ return kernel_tex_fetch(__lights, index).samples;
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/kernel_math.h b/intern/cycles/kernel/kernel_math.h
index a8a43f3ea4a..96391db7649 100644
--- a/intern/cycles/kernel/kernel_math.h
+++ b/intern/cycles/kernel/kernel_math.h
@@ -25,4 +25,4 @@
#include "util/util_texture.h"
#include "util/util_transform.h"
-#endif /* __KERNEL_MATH_H__ */
+#endif /* __KERNEL_MATH_H__ */
diff --git a/intern/cycles/kernel/kernel_montecarlo.h b/intern/cycles/kernel/kernel_montecarlo.h
index dde93844dd3..a933be970c2 100644
--- a/intern/cycles/kernel/kernel_montecarlo.h
+++ b/intern/cycles/kernel/kernel_montecarlo.h
@@ -38,248 +38,245 @@ CCL_NAMESPACE_BEGIN
/* distribute uniform xy on [0,1] over unit disk [-1,1] */
ccl_device void to_unit_disk(float *x, float *y)
{
- float phi = M_2PI_F * (*x);
- float r = sqrtf(*y);
+ float phi = M_2PI_F * (*x);
+ float r = sqrtf(*y);
- *x = r * cosf(phi);
- *y = r * sinf(phi);
+ *x = r * cosf(phi);
+ *y = r * sinf(phi);
}
/* return an orthogonal tangent and bitangent given a normal and tangent that
* may not be exactly orthogonal */
ccl_device void make_orthonormals_tangent(const float3 N, const float3 T, float3 *a, float3 *b)
{
- *b = normalize(cross(N, T));
- *a = cross(*b, N);
+ *b = normalize(cross(N, T));
+ *a = cross(*b, N);
}
/* sample direction with cosine weighted distributed in hemisphere */
-ccl_device_inline void sample_cos_hemisphere(const float3 N,
- float randu, float randv, float3 *omega_in, float *pdf)
+ccl_device_inline void sample_cos_hemisphere(
+ const float3 N, float randu, float randv, float3 *omega_in, float *pdf)
{
- to_unit_disk(&randu, &randv);
- float costheta = sqrtf(max(1.0f - randu * randu - randv * randv, 0.0f));
- float3 T, B;
- make_orthonormals(N, &T, &B);
- *omega_in = randu * T + randv * B + costheta * N;
- *pdf = costheta *M_1_PI_F;
+ to_unit_disk(&randu, &randv);
+ float costheta = sqrtf(max(1.0f - randu * randu - randv * randv, 0.0f));
+ float3 T, B;
+ make_orthonormals(N, &T, &B);
+ *omega_in = randu * T + randv * B + costheta * N;
+ *pdf = costheta * M_1_PI_F;
}
/* sample direction uniformly distributed in hemisphere */
-ccl_device_inline void sample_uniform_hemisphere(const float3 N,
- float randu, float randv,
- float3 *omega_in, float *pdf)
+ccl_device_inline void sample_uniform_hemisphere(
+ const float3 N, float randu, float randv, float3 *omega_in, float *pdf)
{
- float z = randu;
- float r = sqrtf(max(0.0f, 1.0f - z*z));
- float phi = M_2PI_F * randv;
- float x = r * cosf(phi);
- float y = r * sinf(phi);
-
- float3 T, B;
- make_orthonormals (N, &T, &B);
- *omega_in = x * T + y * B + z * N;
- *pdf = 0.5f * M_1_PI_F;
+ float z = randu;
+ float r = sqrtf(max(0.0f, 1.0f - z * z));
+ float phi = M_2PI_F * randv;
+ float x = r * cosf(phi);
+ float y = r * sinf(phi);
+
+ float3 T, B;
+ make_orthonormals(N, &T, &B);
+ *omega_in = x * T + y * B + z * N;
+ *pdf = 0.5f * M_1_PI_F;
}
/* sample direction uniformly distributed in cone */
-ccl_device_inline void sample_uniform_cone(const float3 N, float angle,
- float randu, float randv,
- float3 *omega_in, float *pdf)
+ccl_device_inline void sample_uniform_cone(
+ const float3 N, float angle, float randu, float randv, float3 *omega_in, float *pdf)
{
- float z = cosf(angle*randu);
- float r = sqrtf(max(0.0f, 1.0f - z*z));
- float phi = M_2PI_F * randv;
- float x = r * cosf(phi);
- float y = r * sinf(phi);
-
- float3 T, B;
- make_orthonormals (N, &T, &B);
- *omega_in = x * T + y * B + z * N;
- *pdf = 0.5f * M_1_PI_F / (1.0f - cosf(angle));
+ float z = cosf(angle * randu);
+ float r = sqrtf(max(0.0f, 1.0f - z * z));
+ float phi = M_2PI_F * randv;
+ float x = r * cosf(phi);
+ float y = r * sinf(phi);
+
+ float3 T, B;
+ make_orthonormals(N, &T, &B);
+ *omega_in = x * T + y * B + z * N;
+ *pdf = 0.5f * M_1_PI_F / (1.0f - cosf(angle));
}
/* sample uniform point on the surface of a sphere */
ccl_device float3 sample_uniform_sphere(float u1, float u2)
{
- float z = 1.0f - 2.0f*u1;
- float r = sqrtf(fmaxf(0.0f, 1.0f - z*z));
- float phi = M_2PI_F*u2;
- float x = r*cosf(phi);
- float y = r*sinf(phi);
+ float z = 1.0f - 2.0f * u1;
+ float r = sqrtf(fmaxf(0.0f, 1.0f - z * z));
+ float phi = M_2PI_F * u2;
+ float x = r * cosf(phi);
+ float y = r * sinf(phi);
- return make_float3(x, y, z);
+ return make_float3(x, y, z);
}
ccl_device float balance_heuristic(float a, float b)
{
- return (a)/(a + b);
+ return (a) / (a + b);
}
ccl_device float balance_heuristic_3(float a, float b, float c)
{
- return (a)/(a + b + c);
+ return (a) / (a + b + c);
}
ccl_device float power_heuristic(float a, float b)
{
- return (a*a)/(a*a + b*b);
+ return (a * a) / (a * a + b * b);
}
ccl_device float power_heuristic_3(float a, float b, float c)
{
- return (a*a)/(a*a + b*b + c*c);
+ return (a * a) / (a * a + b * b + c * c);
}
ccl_device float max_heuristic(float a, float b)
{
- return (a > b)? 1.0f: 0.0f;
+ return (a > b) ? 1.0f : 0.0f;
}
/* distribute uniform xy on [0,1] over unit disk [-1,1], with concentric mapping
* to better preserve stratification for some RNG sequences */
ccl_device float2 concentric_sample_disk(float u1, float u2)
{
- float phi, r;
- float a = 2.0f*u1 - 1.0f;
- float b = 2.0f*u2 - 1.0f;
-
- if(a == 0.0f && b == 0.0f) {
- return make_float2(0.0f, 0.0f);
- }
- else if(a*a > b*b) {
- r = a;
- phi = M_PI_4_F * (b/a);
- }
- else {
- r = b;
- phi = M_PI_2_F - M_PI_4_F * (a/b);
- }
-
- return make_float2(r*cosf(phi), r*sinf(phi));
+ float phi, r;
+ float a = 2.0f * u1 - 1.0f;
+ float b = 2.0f * u2 - 1.0f;
+
+ if (a == 0.0f && b == 0.0f) {
+ return make_float2(0.0f, 0.0f);
+ }
+ else if (a * a > b * b) {
+ r = a;
+ phi = M_PI_4_F * (b / a);
+ }
+ else {
+ r = b;
+ phi = M_PI_2_F - M_PI_4_F * (a / b);
+ }
+
+ return make_float2(r * cosf(phi), r * sinf(phi));
}
/* sample point in unit polygon with given number of corners and rotation */
ccl_device float2 regular_polygon_sample(float corners, float rotation, float u, float v)
{
- /* sample corner number and reuse u */
- float corner = floorf(u*corners);
- u = u*corners - corner;
+ /* sample corner number and reuse u */
+ float corner = floorf(u * corners);
+ u = u * corners - corner;
- /* uniform sampled triangle weights */
- u = sqrtf(u);
- v = v*u;
- u = 1.0f - u;
+ /* uniform sampled triangle weights */
+ u = sqrtf(u);
+ v = v * u;
+ u = 1.0f - u;
- /* point in triangle */
- float angle = M_PI_F/corners;
- float2 p = make_float2((u + v)*cosf(angle), (u - v)*sinf(angle));
+ /* point in triangle */
+ float angle = M_PI_F / corners;
+ float2 p = make_float2((u + v) * cosf(angle), (u - v) * sinf(angle));
- /* rotate */
- rotation += corner*2.0f*angle;
+ /* rotate */
+ rotation += corner * 2.0f * angle;
- float cr = cosf(rotation);
- float sr = sinf(rotation);
+ float cr = cosf(rotation);
+ float sr = sinf(rotation);
- return make_float2(cr*p.x - sr*p.y, sr*p.x + cr*p.y);
+ return make_float2(cr * p.x - sr * p.y, sr * p.x + cr * p.y);
}
ccl_device float3 ensure_valid_reflection(float3 Ng, float3 I, float3 N)
{
- float3 R = 2*dot(N, I)*N - I;
-
- /* Reflection rays may always be at least as shallow as the incoming ray. */
- float threshold = min(0.9f*dot(Ng, I), 0.01f);
- if(dot(Ng, R) >= threshold) {
- return N;
- }
-
- /* Form coordinate system with Ng as the Z axis and N inside the X-Z-plane.
- * The X axis is found by normalizing the component of N that's orthogonal to Ng.
- * The Y axis isn't actually needed.
- */
- float NdotNg = dot(N, Ng);
- float3 X = normalize(N - NdotNg*Ng);
-
- /* Calculate N.z and N.x in the local coordinate system.
- *
- * The goal of this computation is to find a N' that is rotated towards Ng just enough
- * to lift R' above the threshold (here called t), therefore dot(R', Ng) = t.
- *
- * According to the standard reflection equation, this means that we want dot(2*dot(N', I)*N' - I, Ng) = t.
- *
- * Since the Z axis of our local coordinate system is Ng, dot(x, Ng) is just x.z, so we get 2*dot(N', I)*N'.z - I.z = t.
- *
- * The rotation is simple to express in the coordinate system we formed - since N lies in the X-Z-plane, we know that
- * N' will also lie in the X-Z-plane, so N'.y = 0 and therefore dot(N', I) = N'.x*I.x + N'.z*I.z .
- *
- * Furthermore, we want N' to be normalized, so N'.x = sqrt(1 - N'.z^2).
- *
- * With these simplifications, we get the final equation 2*(sqrt(1 - N'.z^2)*I.x + N'.z*I.z)*N'.z - I.z = t.
- *
- * The only unknown here is N'.z, so we can solve for that.
- *
- * The equation has four solutions in general:
- *
- * N'.z = +-sqrt(0.5*(+-sqrt(I.x^2*(I.x^2 + I.z^2 - t^2)) + t*I.z + I.x^2 + I.z^2)/(I.x^2 + I.z^2))
- * We can simplify this expression a bit by grouping terms:
- *
- * a = I.x^2 + I.z^2
- * b = sqrt(I.x^2 * (a - t^2))
- * c = I.z*t + a
- * N'.z = +-sqrt(0.5*(+-b + c)/a)
- *
- * Two solutions can immediately be discarded because they're negative so N' would lie in the lower hemisphere.
- */
- float Ix = dot(I, X), Iz = dot(I, Ng);
- float Ix2 = sqr(Ix), Iz2 = sqr(Iz);
- float a = Ix2 + Iz2;
-
- float b = safe_sqrtf(Ix2*(a - sqr(threshold)));
- float c = Iz*threshold + a;
-
- /* Evaluate both solutions.
- * In many cases one can be immediately discarded (if N'.z would be imaginary or larger than one), so check for that first.
- * If no option is viable (might happen in extreme cases like N being in the wrong hemisphere), give up and return Ng. */
- float fac = 0.5f/a;
- float N1_z2 = fac*(b+c), N2_z2 = fac*(-b+c);
- bool valid1 = (N1_z2 > 1e-5f) && (N1_z2 <= (1.0f + 1e-5f));
- bool valid2 = (N2_z2 > 1e-5f) && (N2_z2 <= (1.0f + 1e-5f));
-
- float2 N_new;
- if(valid1 && valid2) {
- /* If both are possible, do the expensive reflection-based check. */
- float2 N1 = make_float2(safe_sqrtf(1.0f - N1_z2), safe_sqrtf(N1_z2));
- float2 N2 = make_float2(safe_sqrtf(1.0f - N2_z2), safe_sqrtf(N2_z2));
-
- float R1 = 2*(N1.x*Ix + N1.y*Iz)*N1.y - Iz;
- float R2 = 2*(N2.x*Ix + N2.y*Iz)*N2.y - Iz;
-
- valid1 = (R1 >= 1e-5f);
- valid2 = (R2 >= 1e-5f);
- if(valid1 && valid2) {
- /* If both solutions are valid, return the one with the shallower reflection since it will be closer to the input
- * (if the original reflection wasn't shallow, we would not be in this part of the function). */
- N_new = (R1 < R2)? N1 : N2;
- }
- else {
- /* If only one reflection is valid (= positive), pick that one. */
- N_new = (R1 > R2)? N1 : N2;
- }
-
- }
- else if(valid1 || valid2) {
- /* Only one solution passes the N'.z criterium, so pick that one. */
- float Nz2 = valid1? N1_z2 : N2_z2;
- N_new = make_float2(safe_sqrtf(1.0f - Nz2), safe_sqrtf(Nz2));
- }
- else {
- return Ng;
- }
-
- return N_new.x*X + N_new.y*Ng;
+ float3 R = 2 * dot(N, I) * N - I;
+
+ /* Reflection rays may always be at least as shallow as the incoming ray. */
+ float threshold = min(0.9f * dot(Ng, I), 0.01f);
+ if (dot(Ng, R) >= threshold) {
+ return N;
+ }
+
+ /* Form coordinate system with Ng as the Z axis and N inside the X-Z-plane.
+ * The X axis is found by normalizing the component of N that's orthogonal to Ng.
+ * The Y axis isn't actually needed.
+ */
+ float NdotNg = dot(N, Ng);
+ float3 X = normalize(N - NdotNg * Ng);
+
+ /* Calculate N.z and N.x in the local coordinate system.
+ *
+ * The goal of this computation is to find a N' that is rotated towards Ng just enough
+ * to lift R' above the threshold (here called t), therefore dot(R', Ng) = t.
+ *
+ * According to the standard reflection equation, this means that we want dot(2*dot(N', I)*N' - I, Ng) = t.
+ *
+ * Since the Z axis of our local coordinate system is Ng, dot(x, Ng) is just x.z, so we get 2*dot(N', I)*N'.z - I.z = t.
+ *
+ * The rotation is simple to express in the coordinate system we formed - since N lies in the X-Z-plane, we know that
+ * N' will also lie in the X-Z-plane, so N'.y = 0 and therefore dot(N', I) = N'.x*I.x + N'.z*I.z .
+ *
+ * Furthermore, we want N' to be normalized, so N'.x = sqrt(1 - N'.z^2).
+ *
+ * With these simplifications, we get the final equation 2*(sqrt(1 - N'.z^2)*I.x + N'.z*I.z)*N'.z - I.z = t.
+ *
+ * The only unknown here is N'.z, so we can solve for that.
+ *
+ * The equation has four solutions in general:
+ *
+ * N'.z = +-sqrt(0.5*(+-sqrt(I.x^2*(I.x^2 + I.z^2 - t^2)) + t*I.z + I.x^2 + I.z^2)/(I.x^2 + I.z^2))
+ * We can simplify this expression a bit by grouping terms:
+ *
+ * a = I.x^2 + I.z^2
+ * b = sqrt(I.x^2 * (a - t^2))
+ * c = I.z*t + a
+ * N'.z = +-sqrt(0.5*(+-b + c)/a)
+ *
+ * Two solutions can immediately be discarded because they're negative so N' would lie in the lower hemisphere.
+ */
+ float Ix = dot(I, X), Iz = dot(I, Ng);
+ float Ix2 = sqr(Ix), Iz2 = sqr(Iz);
+ float a = Ix2 + Iz2;
+
+ float b = safe_sqrtf(Ix2 * (a - sqr(threshold)));
+ float c = Iz * threshold + a;
+
+ /* Evaluate both solutions.
+ * In many cases one can be immediately discarded (if N'.z would be imaginary or larger than one), so check for that first.
+ * If no option is viable (might happen in extreme cases like N being in the wrong hemisphere), give up and return Ng. */
+ float fac = 0.5f / a;
+ float N1_z2 = fac * (b + c), N2_z2 = fac * (-b + c);
+ bool valid1 = (N1_z2 > 1e-5f) && (N1_z2 <= (1.0f + 1e-5f));
+ bool valid2 = (N2_z2 > 1e-5f) && (N2_z2 <= (1.0f + 1e-5f));
+
+ float2 N_new;
+ if (valid1 && valid2) {
+ /* If both are possible, do the expensive reflection-based check. */
+ float2 N1 = make_float2(safe_sqrtf(1.0f - N1_z2), safe_sqrtf(N1_z2));
+ float2 N2 = make_float2(safe_sqrtf(1.0f - N2_z2), safe_sqrtf(N2_z2));
+
+ float R1 = 2 * (N1.x * Ix + N1.y * Iz) * N1.y - Iz;
+ float R2 = 2 * (N2.x * Ix + N2.y * Iz) * N2.y - Iz;
+
+ valid1 = (R1 >= 1e-5f);
+ valid2 = (R2 >= 1e-5f);
+ if (valid1 && valid2) {
+ /* If both solutions are valid, return the one with the shallower reflection since it will be closer to the input
+ * (if the original reflection wasn't shallow, we would not be in this part of the function). */
+ N_new = (R1 < R2) ? N1 : N2;
+ }
+ else {
+ /* If only one reflection is valid (= positive), pick that one. */
+ N_new = (R1 > R2) ? N1 : N2;
+ }
+ }
+ else if (valid1 || valid2) {
+ /* Only one solution passes the N'.z criterium, so pick that one. */
+ float Nz2 = valid1 ? N1_z2 : N2_z2;
+ N_new = make_float2(safe_sqrtf(1.0f - Nz2), safe_sqrtf(Nz2));
+ }
+ else {
+ return Ng;
+ }
+
+ return N_new.x * X + N_new.y * Ng;
}
CCL_NAMESPACE_END
-#endif /* __KERNEL_MONTECARLO_CL__ */
+#endif /* __KERNEL_MONTECARLO_CL__ */
diff --git a/intern/cycles/kernel/kernel_passes.h b/intern/cycles/kernel/kernel_passes.h
index 08e9db05c39..462ec037ee7 100644
--- a/intern/cycles/kernel/kernel_passes.h
+++ b/intern/cycles/kernel/kernel_passes.h
@@ -15,7 +15,7 @@
*/
#if defined(__SPLIT_KERNEL__) || defined(__KERNEL_CUDA__)
-#define __ATOMIC_PASS_WRITE__
+# define __ATOMIC_PASS_WRITE__
#endif
#include "kernel/kernel_id_passes.h"
@@ -24,56 +24,56 @@ CCL_NAMESPACE_BEGIN
ccl_device_inline void kernel_write_pass_float(ccl_global float *buffer, float value)
{
- ccl_global float *buf = buffer;
+ ccl_global float *buf = buffer;
#ifdef __ATOMIC_PASS_WRITE__
- atomic_add_and_fetch_float(buf, value);
+ atomic_add_and_fetch_float(buf, value);
#else
- *buf += value;
+ *buf += value;
#endif
}
ccl_device_inline void kernel_write_pass_float3(ccl_global float *buffer, float3 value)
{
#ifdef __ATOMIC_PASS_WRITE__
- ccl_global float *buf_x = buffer + 0;
- ccl_global float *buf_y = buffer + 1;
- ccl_global float *buf_z = buffer + 2;
+ ccl_global float *buf_x = buffer + 0;
+ ccl_global float *buf_y = buffer + 1;
+ ccl_global float *buf_z = buffer + 2;
- atomic_add_and_fetch_float(buf_x, value.x);
- atomic_add_and_fetch_float(buf_y, value.y);
- atomic_add_and_fetch_float(buf_z, value.z);
+ atomic_add_and_fetch_float(buf_x, value.x);
+ atomic_add_and_fetch_float(buf_y, value.y);
+ atomic_add_and_fetch_float(buf_z, value.z);
#else
- ccl_global float3 *buf = (ccl_global float3*)buffer;
- *buf += value;
+ ccl_global float3 *buf = (ccl_global float3 *)buffer;
+ *buf += value;
#endif
}
ccl_device_inline void kernel_write_pass_float4(ccl_global float *buffer, float4 value)
{
#ifdef __ATOMIC_PASS_WRITE__
- ccl_global float *buf_x = buffer + 0;
- ccl_global float *buf_y = buffer + 1;
- ccl_global float *buf_z = buffer + 2;
- ccl_global float *buf_w = buffer + 3;
-
- atomic_add_and_fetch_float(buf_x, value.x);
- atomic_add_and_fetch_float(buf_y, value.y);
- atomic_add_and_fetch_float(buf_z, value.z);
- atomic_add_and_fetch_float(buf_w, value.w);
+ ccl_global float *buf_x = buffer + 0;
+ ccl_global float *buf_y = buffer + 1;
+ ccl_global float *buf_z = buffer + 2;
+ ccl_global float *buf_w = buffer + 3;
+
+ atomic_add_and_fetch_float(buf_x, value.x);
+ atomic_add_and_fetch_float(buf_y, value.y);
+ atomic_add_and_fetch_float(buf_z, value.z);
+ atomic_add_and_fetch_float(buf_w, value.w);
#else
- ccl_global float4 *buf = (ccl_global float4*)buffer;
- *buf += value;
+ ccl_global float4 *buf = (ccl_global float4 *)buffer;
+ *buf += value;
#endif
}
#ifdef __DENOISING_FEATURES__
ccl_device_inline void kernel_write_pass_float_variance(ccl_global float *buffer, float value)
{
- kernel_write_pass_float(buffer, value);
+ kernel_write_pass_float(buffer, value);
- /* The online one-pass variance update that's used for the megakernel can't easily be implemented
- * with atomics, so for the split kernel the E[x^2] - 1/N * (E[x])^2 fallback is used. */
- kernel_write_pass_float(buffer+1, value*value);
+ /* The online one-pass variance update that's used for the megakernel can't easily be implemented
+ * with atomics, so for the split kernel the E[x^2] - 1/N * (E[x])^2 fallback is used. */
+ kernel_write_pass_float(buffer + 1, value * value);
}
# ifdef __ATOMIC_PASS_WRITE__
@@ -81,36 +81,39 @@ ccl_device_inline void kernel_write_pass_float_variance(ccl_global float *buffer
# else
ccl_device_inline void kernel_write_pass_float3_unaligned(ccl_global float *buffer, float3 value)
{
- buffer[0] += value.x;
- buffer[1] += value.y;
- buffer[2] += value.z;
+ buffer[0] += value.x;
+ buffer[1] += value.y;
+ buffer[2] += value.z;
}
# endif
ccl_device_inline void kernel_write_pass_float3_variance(ccl_global float *buffer, float3 value)
{
- kernel_write_pass_float3_unaligned(buffer, value);
- kernel_write_pass_float3_unaligned(buffer+3, value*value);
+ kernel_write_pass_float3_unaligned(buffer, value);
+ kernel_write_pass_float3_unaligned(buffer + 3, value * value);
}
-ccl_device_inline void kernel_write_denoising_shadow(KernelGlobals *kg, ccl_global float *buffer,
- int sample, float path_total, float path_total_shaded)
+ccl_device_inline void kernel_write_denoising_shadow(KernelGlobals *kg,
+ ccl_global float *buffer,
+ int sample,
+ float path_total,
+ float path_total_shaded)
{
- if(kernel_data.film.pass_denoising_data == 0)
- return;
+ if (kernel_data.film.pass_denoising_data == 0)
+ return;
- buffer += (sample & 1)? DENOISING_PASS_SHADOW_B : DENOISING_PASS_SHADOW_A;
+ buffer += (sample & 1) ? DENOISING_PASS_SHADOW_B : DENOISING_PASS_SHADOW_A;
- path_total = ensure_finite(path_total);
- path_total_shaded = ensure_finite(path_total_shaded);
+ path_total = ensure_finite(path_total);
+ path_total_shaded = ensure_finite(path_total_shaded);
- kernel_write_pass_float(buffer, path_total);
- kernel_write_pass_float(buffer+1, path_total_shaded);
+ kernel_write_pass_float(buffer, path_total);
+ kernel_write_pass_float(buffer + 1, path_total_shaded);
- float value = path_total_shaded / max(path_total, 1e-7f);
- kernel_write_pass_float(buffer+2, value*value);
+ float value = path_total_shaded / max(path_total, 1e-7f);
+ kernel_write_pass_float(buffer + 2, value * value);
}
-#endif /* __DENOISING_FEATURES__ */
+#endif /* __DENOISING_FEATURES__ */
ccl_device_inline void kernel_update_denoising_features(KernelGlobals *kg,
ShaderData *sd,
@@ -118,52 +121,52 @@ ccl_device_inline void kernel_update_denoising_features(KernelGlobals *kg,
PathRadiance *L)
{
#ifdef __DENOISING_FEATURES__
- if(state->denoising_feature_weight == 0.0f) {
- return;
- }
-
- L->denoising_depth += ensure_finite(state->denoising_feature_weight * sd->ray_length);
-
- /* Skip implicitly transparent surfaces. */
- if(sd->flag & SD_HAS_ONLY_VOLUME) {
- return;
- }
-
- float3 normal = make_float3(0.0f, 0.0f, 0.0f);
- float3 albedo = make_float3(0.0f, 0.0f, 0.0f);
- float sum_weight = 0.0f, sum_nonspecular_weight = 0.0f;
-
- for(int i = 0; i < sd->num_closure; i++) {
- ShaderClosure *sc = &sd->closure[i];
-
- if(!CLOSURE_IS_BSDF_OR_BSSRDF(sc->type))
- continue;
-
- /* All closures contribute to the normal feature, but only diffuse-like ones to the albedo. */
- normal += sc->N * sc->sample_weight;
- sum_weight += sc->sample_weight;
- if(bsdf_get_specular_roughness_squared(sc) > sqr(0.075f)) {
- albedo += sc->weight;
- sum_nonspecular_weight += sc->sample_weight;
- }
- }
-
- /* Wait for next bounce if 75% or more sample weight belongs to specular-like closures. */
- if((sum_weight == 0.0f) || (sum_nonspecular_weight*4.0f > sum_weight)) {
- if(sum_weight != 0.0f) {
- normal /= sum_weight;
- }
- L->denoising_normal += ensure_finite3(state->denoising_feature_weight * normal);
- L->denoising_albedo += ensure_finite3(state->denoising_feature_weight * albedo);
-
- state->denoising_feature_weight = 0.0f;
- }
+ if (state->denoising_feature_weight == 0.0f) {
+ return;
+ }
+
+ L->denoising_depth += ensure_finite(state->denoising_feature_weight * sd->ray_length);
+
+ /* Skip implicitly transparent surfaces. */
+ if (sd->flag & SD_HAS_ONLY_VOLUME) {
+ return;
+ }
+
+ float3 normal = make_float3(0.0f, 0.0f, 0.0f);
+ float3 albedo = make_float3(0.0f, 0.0f, 0.0f);
+ float sum_weight = 0.0f, sum_nonspecular_weight = 0.0f;
+
+ for (int i = 0; i < sd->num_closure; i++) {
+ ShaderClosure *sc = &sd->closure[i];
+
+ if (!CLOSURE_IS_BSDF_OR_BSSRDF(sc->type))
+ continue;
+
+ /* All closures contribute to the normal feature, but only diffuse-like ones to the albedo. */
+ normal += sc->N * sc->sample_weight;
+ sum_weight += sc->sample_weight;
+ if (bsdf_get_specular_roughness_squared(sc) > sqr(0.075f)) {
+ albedo += sc->weight;
+ sum_nonspecular_weight += sc->sample_weight;
+ }
+ }
+
+ /* Wait for next bounce if 75% or more sample weight belongs to specular-like closures. */
+ if ((sum_weight == 0.0f) || (sum_nonspecular_weight * 4.0f > sum_weight)) {
+ if (sum_weight != 0.0f) {
+ normal /= sum_weight;
+ }
+ L->denoising_normal += ensure_finite3(state->denoising_feature_weight * normal);
+ L->denoising_albedo += ensure_finite3(state->denoising_feature_weight * albedo);
+
+ state->denoising_feature_weight = 0.0f;
+ }
#else
- (void) kg;
- (void) sd;
- (void) state;
- (void) L;
-#endif /* __DENOISING_FEATURES__ */
+ (void)kg;
+ (void)sd;
+ (void)state;
+ (void)L;
+#endif /* __DENOISING_FEATURES__ */
}
#ifdef __KERNEL_DEBUG__
@@ -171,203 +174,221 @@ ccl_device_inline void kernel_write_debug_passes(KernelGlobals *kg,
ccl_global float *buffer,
PathRadiance *L)
{
- int flag = kernel_data.film.pass_flag;
- if(flag & PASSMASK(BVH_TRAVERSED_NODES)) {
- kernel_write_pass_float(buffer + kernel_data.film.pass_bvh_traversed_nodes,
- L->debug_data.num_bvh_traversed_nodes);
- }
- if(flag & PASSMASK(BVH_TRAVERSED_INSTANCES)) {
- kernel_write_pass_float(buffer + kernel_data.film.pass_bvh_traversed_instances,
- L->debug_data.num_bvh_traversed_instances);
- }
- if(flag & PASSMASK(BVH_INTERSECTIONS)) {
- kernel_write_pass_float(buffer + kernel_data.film.pass_bvh_intersections,
- L->debug_data.num_bvh_intersections);
- }
- if(flag & PASSMASK(RAY_BOUNCES)) {
- kernel_write_pass_float(buffer + kernel_data.film.pass_ray_bounces,
- L->debug_data.num_ray_bounces);
- }
+ int flag = kernel_data.film.pass_flag;
+ if (flag & PASSMASK(BVH_TRAVERSED_NODES)) {
+ kernel_write_pass_float(buffer + kernel_data.film.pass_bvh_traversed_nodes,
+ L->debug_data.num_bvh_traversed_nodes);
+ }
+ if (flag & PASSMASK(BVH_TRAVERSED_INSTANCES)) {
+ kernel_write_pass_float(buffer + kernel_data.film.pass_bvh_traversed_instances,
+ L->debug_data.num_bvh_traversed_instances);
+ }
+ if (flag & PASSMASK(BVH_INTERSECTIONS)) {
+ kernel_write_pass_float(buffer + kernel_data.film.pass_bvh_intersections,
+ L->debug_data.num_bvh_intersections);
+ }
+ if (flag & PASSMASK(RAY_BOUNCES)) {
+ kernel_write_pass_float(buffer + kernel_data.film.pass_ray_bounces,
+ L->debug_data.num_ray_bounces);
+ }
}
-#endif /* __KERNEL_DEBUG__ */
+#endif /* __KERNEL_DEBUG__ */
#ifdef __KERNEL_CPU__
-#define WRITE_ID_SLOT(buffer, depth, id, matte_weight, name) kernel_write_id_pass_cpu(buffer, depth * 2, id, matte_weight, kg->coverage_##name)
-ccl_device_inline size_t kernel_write_id_pass_cpu(float *buffer, size_t depth, float id, float matte_weight, CoverageMap *map)
+# define WRITE_ID_SLOT(buffer, depth, id, matte_weight, name) \
+ kernel_write_id_pass_cpu(buffer, depth * 2, id, matte_weight, kg->coverage_##name)
+ccl_device_inline size_t kernel_write_id_pass_cpu(
+ float *buffer, size_t depth, float id, float matte_weight, CoverageMap *map)
{
- if(map) {
- (*map)[id] += matte_weight;
- return 0;
- }
-#else /* __KERNEL_CPU__ */
-#define WRITE_ID_SLOT(buffer, depth, id, matte_weight, name) kernel_write_id_slots_gpu(buffer, depth * 2, id, matte_weight)
-ccl_device_inline size_t kernel_write_id_slots_gpu(ccl_global float *buffer, size_t depth, float id, float matte_weight)
+ if (map) {
+ (*map)[id] += matte_weight;
+ return 0;
+ }
+#else /* __KERNEL_CPU__ */
+# define WRITE_ID_SLOT(buffer, depth, id, matte_weight, name) \
+ kernel_write_id_slots_gpu(buffer, depth * 2, id, matte_weight)
+ccl_device_inline size_t kernel_write_id_slots_gpu(ccl_global float *buffer,
+ size_t depth,
+ float id,
+ float matte_weight)
{
-#endif /* __KERNEL_CPU__ */
- kernel_write_id_slots(buffer, depth, id, matte_weight);
- return depth * 2;
+#endif /* __KERNEL_CPU__ */
+ kernel_write_id_slots(buffer, depth, id, matte_weight);
+ return depth * 2;
}
-ccl_device_inline void kernel_write_data_passes(KernelGlobals *kg, ccl_global float *buffer, PathRadiance *L,
- ShaderData *sd, ccl_addr_space PathState *state, float3 throughput)
+ccl_device_inline void kernel_write_data_passes(KernelGlobals *kg,
+ ccl_global float *buffer,
+ PathRadiance *L,
+ ShaderData *sd,
+ ccl_addr_space PathState *state,
+ float3 throughput)
{
#ifdef __PASSES__
- int path_flag = state->flag;
-
- if(!(path_flag & PATH_RAY_CAMERA))
- return;
-
- int flag = kernel_data.film.pass_flag;
- int light_flag = kernel_data.film.light_pass_flag;
-
- if(!((flag | light_flag) & PASS_ANY))
- return;
-
- if(!(path_flag & PATH_RAY_SINGLE_PASS_DONE)) {
- if(!(sd->flag & SD_TRANSPARENT) ||
- kernel_data.film.pass_alpha_threshold == 0.0f ||
- average(shader_bsdf_alpha(kg, sd)) >= kernel_data.film.pass_alpha_threshold)
- {
- if(state->sample == 0) {
- if(flag & PASSMASK(DEPTH)) {
- float depth = camera_distance(kg, sd->P);
- kernel_write_pass_float(buffer + kernel_data.film.pass_depth, depth);
- }
- if(flag & PASSMASK(OBJECT_ID)) {
- float id = object_pass_id(kg, sd->object);
- kernel_write_pass_float(buffer + kernel_data.film.pass_object_id, id);
- }
- if(flag & PASSMASK(MATERIAL_ID)) {
- float id = shader_pass_id(kg, sd);
- kernel_write_pass_float(buffer + kernel_data.film.pass_material_id, id);
- }
- }
-
- if(flag & PASSMASK(NORMAL)) {
- float3 normal = shader_bsdf_average_normal(kg, sd);
- kernel_write_pass_float3(buffer + kernel_data.film.pass_normal, normal);
- }
- if(flag & PASSMASK(UV)) {
- float3 uv = primitive_uv(kg, sd);
- kernel_write_pass_float3(buffer + kernel_data.film.pass_uv, uv);
- }
- if(flag & PASSMASK(MOTION)) {
- float4 speed = primitive_motion_vector(kg, sd);
- kernel_write_pass_float4(buffer + kernel_data.film.pass_motion, speed);
- kernel_write_pass_float(buffer + kernel_data.film.pass_motion_weight, 1.0f);
- }
-
- state->flag |= PATH_RAY_SINGLE_PASS_DONE;
- }
- }
-
- if(kernel_data.film.cryptomatte_passes) {
- const float matte_weight = average(throughput) * (1.0f - average(shader_bsdf_transparency(kg, sd)));
- if(matte_weight > 0.0f) {
- ccl_global float *cryptomatte_buffer = buffer + kernel_data.film.pass_cryptomatte;
- if(kernel_data.film.cryptomatte_passes & CRYPT_OBJECT) {
- float id = object_cryptomatte_id(kg, sd->object);
- cryptomatte_buffer += WRITE_ID_SLOT(cryptomatte_buffer, kernel_data.film.cryptomatte_depth, id, matte_weight, object);
- }
- if(kernel_data.film.cryptomatte_passes & CRYPT_MATERIAL) {
- float id = shader_cryptomatte_id(kg, sd->shader);
- cryptomatte_buffer += WRITE_ID_SLOT(cryptomatte_buffer, kernel_data.film.cryptomatte_depth, id, matte_weight, material);
- }
- if(kernel_data.film.cryptomatte_passes & CRYPT_ASSET) {
- float id = object_cryptomatte_asset_id(kg, sd->object);
- cryptomatte_buffer += WRITE_ID_SLOT(cryptomatte_buffer, kernel_data.film.cryptomatte_depth, id, matte_weight, asset);
- }
- }
- }
-
-
- if(light_flag & PASSMASK_COMPONENT(DIFFUSE))
- L->color_diffuse += shader_bsdf_diffuse(kg, sd)*throughput;
- if(light_flag & PASSMASK_COMPONENT(GLOSSY))
- L->color_glossy += shader_bsdf_glossy(kg, sd)*throughput;
- if(light_flag & PASSMASK_COMPONENT(TRANSMISSION))
- L->color_transmission += shader_bsdf_transmission(kg, sd)*throughput;
- if(light_flag & PASSMASK_COMPONENT(SUBSURFACE))
- L->color_subsurface += shader_bsdf_subsurface(kg, sd)*throughput;
-
- if(light_flag & PASSMASK(MIST)) {
- /* bring depth into 0..1 range */
- float mist_start = kernel_data.film.mist_start;
- float mist_inv_depth = kernel_data.film.mist_inv_depth;
-
- float depth = camera_distance(kg, sd->P);
- float mist = saturate((depth - mist_start)*mist_inv_depth);
-
- /* falloff */
- float mist_falloff = kernel_data.film.mist_falloff;
-
- if(mist_falloff == 1.0f)
- ;
- else if(mist_falloff == 2.0f)
- mist = mist*mist;
- else if(mist_falloff == 0.5f)
- mist = sqrtf(mist);
- else
- mist = powf(mist, mist_falloff);
-
- /* modulate by transparency */
- float3 alpha = shader_bsdf_alpha(kg, sd);
- L->mist += (1.0f - mist)*average(throughput*alpha);
- }
+ int path_flag = state->flag;
+
+ if (!(path_flag & PATH_RAY_CAMERA))
+ return;
+
+ int flag = kernel_data.film.pass_flag;
+ int light_flag = kernel_data.film.light_pass_flag;
+
+ if (!((flag | light_flag) & PASS_ANY))
+ return;
+
+ if (!(path_flag & PATH_RAY_SINGLE_PASS_DONE)) {
+ if (!(sd->flag & SD_TRANSPARENT) || kernel_data.film.pass_alpha_threshold == 0.0f ||
+ average(shader_bsdf_alpha(kg, sd)) >= kernel_data.film.pass_alpha_threshold) {
+ if (state->sample == 0) {
+ if (flag & PASSMASK(DEPTH)) {
+ float depth = camera_distance(kg, sd->P);
+ kernel_write_pass_float(buffer + kernel_data.film.pass_depth, depth);
+ }
+ if (flag & PASSMASK(OBJECT_ID)) {
+ float id = object_pass_id(kg, sd->object);
+ kernel_write_pass_float(buffer + kernel_data.film.pass_object_id, id);
+ }
+ if (flag & PASSMASK(MATERIAL_ID)) {
+ float id = shader_pass_id(kg, sd);
+ kernel_write_pass_float(buffer + kernel_data.film.pass_material_id, id);
+ }
+ }
+
+ if (flag & PASSMASK(NORMAL)) {
+ float3 normal = shader_bsdf_average_normal(kg, sd);
+ kernel_write_pass_float3(buffer + kernel_data.film.pass_normal, normal);
+ }
+ if (flag & PASSMASK(UV)) {
+ float3 uv = primitive_uv(kg, sd);
+ kernel_write_pass_float3(buffer + kernel_data.film.pass_uv, uv);
+ }
+ if (flag & PASSMASK(MOTION)) {
+ float4 speed = primitive_motion_vector(kg, sd);
+ kernel_write_pass_float4(buffer + kernel_data.film.pass_motion, speed);
+ kernel_write_pass_float(buffer + kernel_data.film.pass_motion_weight, 1.0f);
+ }
+
+ state->flag |= PATH_RAY_SINGLE_PASS_DONE;
+ }
+ }
+
+ if (kernel_data.film.cryptomatte_passes) {
+ const float matte_weight = average(throughput) *
+ (1.0f - average(shader_bsdf_transparency(kg, sd)));
+ if (matte_weight > 0.0f) {
+ ccl_global float *cryptomatte_buffer = buffer + kernel_data.film.pass_cryptomatte;
+ if (kernel_data.film.cryptomatte_passes & CRYPT_OBJECT) {
+ float id = object_cryptomatte_id(kg, sd->object);
+ cryptomatte_buffer += WRITE_ID_SLOT(
+ cryptomatte_buffer, kernel_data.film.cryptomatte_depth, id, matte_weight, object);
+ }
+ if (kernel_data.film.cryptomatte_passes & CRYPT_MATERIAL) {
+ float id = shader_cryptomatte_id(kg, sd->shader);
+ cryptomatte_buffer += WRITE_ID_SLOT(
+ cryptomatte_buffer, kernel_data.film.cryptomatte_depth, id, matte_weight, material);
+ }
+ if (kernel_data.film.cryptomatte_passes & CRYPT_ASSET) {
+ float id = object_cryptomatte_asset_id(kg, sd->object);
+ cryptomatte_buffer += WRITE_ID_SLOT(
+ cryptomatte_buffer, kernel_data.film.cryptomatte_depth, id, matte_weight, asset);
+ }
+ }
+ }
+
+ if (light_flag & PASSMASK_COMPONENT(DIFFUSE))
+ L->color_diffuse += shader_bsdf_diffuse(kg, sd) * throughput;
+ if (light_flag & PASSMASK_COMPONENT(GLOSSY))
+ L->color_glossy += shader_bsdf_glossy(kg, sd) * throughput;
+ if (light_flag & PASSMASK_COMPONENT(TRANSMISSION))
+ L->color_transmission += shader_bsdf_transmission(kg, sd) * throughput;
+ if (light_flag & PASSMASK_COMPONENT(SUBSURFACE))
+ L->color_subsurface += shader_bsdf_subsurface(kg, sd) * throughput;
+
+ if (light_flag & PASSMASK(MIST)) {
+ /* bring depth into 0..1 range */
+ float mist_start = kernel_data.film.mist_start;
+ float mist_inv_depth = kernel_data.film.mist_inv_depth;
+
+ float depth = camera_distance(kg, sd->P);
+ float mist = saturate((depth - mist_start) * mist_inv_depth);
+
+ /* falloff */
+ float mist_falloff = kernel_data.film.mist_falloff;
+
+ if (mist_falloff == 1.0f)
+ ;
+ else if (mist_falloff == 2.0f)
+ mist = mist * mist;
+ else if (mist_falloff == 0.5f)
+ mist = sqrtf(mist);
+ else
+ mist = powf(mist, mist_falloff);
+
+ /* modulate by transparency */
+ float3 alpha = shader_bsdf_alpha(kg, sd);
+ L->mist += (1.0f - mist) * average(throughput * alpha);
+ }
#endif
}
-ccl_device_inline void kernel_write_light_passes(KernelGlobals *kg, ccl_global float *buffer, PathRadiance *L)
+ccl_device_inline void kernel_write_light_passes(KernelGlobals *kg,
+ ccl_global float *buffer,
+ PathRadiance *L)
{
#ifdef __PASSES__
- int light_flag = kernel_data.film.light_pass_flag;
-
- if(!kernel_data.film.use_light_pass)
- return;
-
- if(light_flag & PASSMASK(DIFFUSE_INDIRECT))
- kernel_write_pass_float3(buffer + kernel_data.film.pass_diffuse_indirect, L->indirect_diffuse);
- if(light_flag & PASSMASK(GLOSSY_INDIRECT))
- kernel_write_pass_float3(buffer + kernel_data.film.pass_glossy_indirect, L->indirect_glossy);
- if(light_flag & PASSMASK(TRANSMISSION_INDIRECT))
- kernel_write_pass_float3(buffer + kernel_data.film.pass_transmission_indirect, L->indirect_transmission);
- if(light_flag & PASSMASK(SUBSURFACE_INDIRECT))
- kernel_write_pass_float3(buffer + kernel_data.film.pass_subsurface_indirect, L->indirect_subsurface);
- if(light_flag & PASSMASK(VOLUME_INDIRECT))
- kernel_write_pass_float3(buffer + kernel_data.film.pass_volume_indirect, L->indirect_scatter);
- if(light_flag & PASSMASK(DIFFUSE_DIRECT))
- kernel_write_pass_float3(buffer + kernel_data.film.pass_diffuse_direct, L->direct_diffuse);
- if(light_flag & PASSMASK(GLOSSY_DIRECT))
- kernel_write_pass_float3(buffer + kernel_data.film.pass_glossy_direct, L->direct_glossy);
- if(light_flag & PASSMASK(TRANSMISSION_DIRECT))
- kernel_write_pass_float3(buffer + kernel_data.film.pass_transmission_direct, L->direct_transmission);
- if(light_flag & PASSMASK(SUBSURFACE_DIRECT))
- kernel_write_pass_float3(buffer + kernel_data.film.pass_subsurface_direct, L->direct_subsurface);
- if(light_flag & PASSMASK(VOLUME_DIRECT))
- kernel_write_pass_float3(buffer + kernel_data.film.pass_volume_direct, L->direct_scatter);
-
- if(light_flag & PASSMASK(EMISSION))
- kernel_write_pass_float3(buffer + kernel_data.film.pass_emission, L->emission);
- if(light_flag & PASSMASK(BACKGROUND))
- kernel_write_pass_float3(buffer + kernel_data.film.pass_background, L->background);
- if(light_flag & PASSMASK(AO))
- kernel_write_pass_float3(buffer + kernel_data.film.pass_ao, L->ao);
-
- if(light_flag & PASSMASK(DIFFUSE_COLOR))
- kernel_write_pass_float3(buffer + kernel_data.film.pass_diffuse_color, L->color_diffuse);
- if(light_flag & PASSMASK(GLOSSY_COLOR))
- kernel_write_pass_float3(buffer + kernel_data.film.pass_glossy_color, L->color_glossy);
- if(light_flag & PASSMASK(TRANSMISSION_COLOR))
- kernel_write_pass_float3(buffer + kernel_data.film.pass_transmission_color, L->color_transmission);
- if(light_flag & PASSMASK(SUBSURFACE_COLOR))
- kernel_write_pass_float3(buffer + kernel_data.film.pass_subsurface_color, L->color_subsurface);
- if(light_flag & PASSMASK(SHADOW)) {
- float4 shadow = L->shadow;
- shadow.w = kernel_data.film.pass_shadow_scale;
- kernel_write_pass_float4(buffer + kernel_data.film.pass_shadow, shadow);
- }
- if(light_flag & PASSMASK(MIST))
- kernel_write_pass_float(buffer + kernel_data.film.pass_mist, 1.0f - L->mist);
+ int light_flag = kernel_data.film.light_pass_flag;
+
+ if (!kernel_data.film.use_light_pass)
+ return;
+
+ if (light_flag & PASSMASK(DIFFUSE_INDIRECT))
+ kernel_write_pass_float3(buffer + kernel_data.film.pass_diffuse_indirect, L->indirect_diffuse);
+ if (light_flag & PASSMASK(GLOSSY_INDIRECT))
+ kernel_write_pass_float3(buffer + kernel_data.film.pass_glossy_indirect, L->indirect_glossy);
+ if (light_flag & PASSMASK(TRANSMISSION_INDIRECT))
+ kernel_write_pass_float3(buffer + kernel_data.film.pass_transmission_indirect,
+ L->indirect_transmission);
+ if (light_flag & PASSMASK(SUBSURFACE_INDIRECT))
+ kernel_write_pass_float3(buffer + kernel_data.film.pass_subsurface_indirect,
+ L->indirect_subsurface);
+ if (light_flag & PASSMASK(VOLUME_INDIRECT))
+ kernel_write_pass_float3(buffer + kernel_data.film.pass_volume_indirect, L->indirect_scatter);
+ if (light_flag & PASSMASK(DIFFUSE_DIRECT))
+ kernel_write_pass_float3(buffer + kernel_data.film.pass_diffuse_direct, L->direct_diffuse);
+ if (light_flag & PASSMASK(GLOSSY_DIRECT))
+ kernel_write_pass_float3(buffer + kernel_data.film.pass_glossy_direct, L->direct_glossy);
+ if (light_flag & PASSMASK(TRANSMISSION_DIRECT))
+ kernel_write_pass_float3(buffer + kernel_data.film.pass_transmission_direct,
+ L->direct_transmission);
+ if (light_flag & PASSMASK(SUBSURFACE_DIRECT))
+ kernel_write_pass_float3(buffer + kernel_data.film.pass_subsurface_direct,
+ L->direct_subsurface);
+ if (light_flag & PASSMASK(VOLUME_DIRECT))
+ kernel_write_pass_float3(buffer + kernel_data.film.pass_volume_direct, L->direct_scatter);
+
+ if (light_flag & PASSMASK(EMISSION))
+ kernel_write_pass_float3(buffer + kernel_data.film.pass_emission, L->emission);
+ if (light_flag & PASSMASK(BACKGROUND))
+ kernel_write_pass_float3(buffer + kernel_data.film.pass_background, L->background);
+ if (light_flag & PASSMASK(AO))
+ kernel_write_pass_float3(buffer + kernel_data.film.pass_ao, L->ao);
+
+ if (light_flag & PASSMASK(DIFFUSE_COLOR))
+ kernel_write_pass_float3(buffer + kernel_data.film.pass_diffuse_color, L->color_diffuse);
+ if (light_flag & PASSMASK(GLOSSY_COLOR))
+ kernel_write_pass_float3(buffer + kernel_data.film.pass_glossy_color, L->color_glossy);
+ if (light_flag & PASSMASK(TRANSMISSION_COLOR))
+ kernel_write_pass_float3(buffer + kernel_data.film.pass_transmission_color,
+ L->color_transmission);
+ if (light_flag & PASSMASK(SUBSURFACE_COLOR))
+ kernel_write_pass_float3(buffer + kernel_data.film.pass_subsurface_color, L->color_subsurface);
+ if (light_flag & PASSMASK(SHADOW)) {
+ float4 shadow = L->shadow;
+ shadow.w = kernel_data.film.pass_shadow_scale;
+ kernel_write_pass_float4(buffer + kernel_data.film.pass_shadow, shadow);
+ }
+ if (light_flag & PASSMASK(MIST))
+ kernel_write_pass_float(buffer + kernel_data.film.pass_mist, 1.0f - L->mist);
#endif
}
@@ -376,60 +397,54 @@ ccl_device_inline void kernel_write_result(KernelGlobals *kg,
int sample,
PathRadiance *L)
{
- PROFILING_INIT(kg, PROFILING_WRITE_RESULT);
- PROFILING_OBJECT(PRIM_NONE);
+ PROFILING_INIT(kg, PROFILING_WRITE_RESULT);
+ PROFILING_OBJECT(PRIM_NONE);
- float alpha;
- float3 L_sum = path_radiance_clamp_and_sum(kg, L, &alpha);
+ float alpha;
+ float3 L_sum = path_radiance_clamp_and_sum(kg, L, &alpha);
- kernel_write_pass_float4(buffer, make_float4(L_sum.x, L_sum.y, L_sum.z, alpha));
+ kernel_write_pass_float4(buffer, make_float4(L_sum.x, L_sum.y, L_sum.z, alpha));
- kernel_write_light_passes(kg, buffer, L);
+ kernel_write_light_passes(kg, buffer, L);
#ifdef __DENOISING_FEATURES__
- if(kernel_data.film.pass_denoising_data) {
+ if (kernel_data.film.pass_denoising_data) {
# ifdef __SHADOW_TRICKS__
- kernel_write_denoising_shadow(kg,
- buffer + kernel_data.film.pass_denoising_data,
- sample,
- average(L->path_total),
- average(L->path_total_shaded));
+ kernel_write_denoising_shadow(kg,
+ buffer + kernel_data.film.pass_denoising_data,
+ sample,
+ average(L->path_total),
+ average(L->path_total_shaded));
# else
- kernel_write_denoising_shadow(kg,
- buffer + kernel_data.film.pass_denoising_data,
- sample,
- 0.0f, 0.0f);
+ kernel_write_denoising_shadow(
+ kg, buffer + kernel_data.film.pass_denoising_data, sample, 0.0f, 0.0f);
# endif
- if(kernel_data.film.pass_denoising_clean) {
- float3 noisy, clean;
- path_radiance_split_denoising(kg, L, &noisy, &clean);
- kernel_write_pass_float3_variance(
- buffer + kernel_data.film.pass_denoising_data + DENOISING_PASS_COLOR,
- noisy);
- kernel_write_pass_float3_unaligned(
- buffer + kernel_data.film.pass_denoising_clean,
- clean);
- }
- else {
- kernel_write_pass_float3_variance(buffer + kernel_data.film.pass_denoising_data + DENOISING_PASS_COLOR,
- ensure_finite3(L_sum));
- }
-
- kernel_write_pass_float3_variance(
- buffer + kernel_data.film.pass_denoising_data + DENOISING_PASS_NORMAL,
- L->denoising_normal);
- kernel_write_pass_float3_variance(
- buffer + kernel_data.film.pass_denoising_data + DENOISING_PASS_ALBEDO,
- L->denoising_albedo);
- kernel_write_pass_float_variance(
- buffer + kernel_data.film.pass_denoising_data + DENOISING_PASS_DEPTH,
- L->denoising_depth);
- }
-#endif /* __DENOISING_FEATURES__ */
-
+ if (kernel_data.film.pass_denoising_clean) {
+ float3 noisy, clean;
+ path_radiance_split_denoising(kg, L, &noisy, &clean);
+ kernel_write_pass_float3_variance(
+ buffer + kernel_data.film.pass_denoising_data + DENOISING_PASS_COLOR, noisy);
+ kernel_write_pass_float3_unaligned(buffer + kernel_data.film.pass_denoising_clean, clean);
+ }
+ else {
+ kernel_write_pass_float3_variance(buffer + kernel_data.film.pass_denoising_data +
+ DENOISING_PASS_COLOR,
+ ensure_finite3(L_sum));
+ }
+
+ kernel_write_pass_float3_variance(buffer + kernel_data.film.pass_denoising_data +
+ DENOISING_PASS_NORMAL,
+ L->denoising_normal);
+ kernel_write_pass_float3_variance(buffer + kernel_data.film.pass_denoising_data +
+ DENOISING_PASS_ALBEDO,
+ L->denoising_albedo);
+ kernel_write_pass_float_variance(
+ buffer + kernel_data.film.pass_denoising_data + DENOISING_PASS_DEPTH, L->denoising_depth);
+ }
+#endif /* __DENOISING_FEATURES__ */
#ifdef __KERNEL_DEBUG__
- kernel_write_debug_passes(kg, buffer, L);
+ kernel_write_debug_passes(kg, buffer, L);
#endif
}
diff --git a/intern/cycles/kernel/kernel_path.h b/intern/cycles/kernel/kernel_path.h
index a1fc6028293..2be1b745632 100644
--- a/intern/cycles/kernel/kernel_path.h
+++ b/intern/cycles/kernel/kernel_path.h
@@ -50,309 +50,298 @@
CCL_NAMESPACE_BEGIN
-ccl_device_forceinline bool kernel_path_scene_intersect(
- KernelGlobals *kg,
- ccl_addr_space PathState *state,
- Ray *ray,
- Intersection *isect,
- PathRadiance *L)
+ccl_device_forceinline bool kernel_path_scene_intersect(KernelGlobals *kg,
+ ccl_addr_space PathState *state,
+ Ray *ray,
+ Intersection *isect,
+ PathRadiance *L)
{
- PROFILING_INIT(kg, PROFILING_SCENE_INTERSECT);
+ PROFILING_INIT(kg, PROFILING_SCENE_INTERSECT);
- uint visibility = path_state_ray_visibility(kg, state);
+ uint visibility = path_state_ray_visibility(kg, state);
- if(path_state_ao_bounce(kg, state)) {
- visibility = PATH_RAY_SHADOW;
- ray->t = kernel_data.background.ao_distance;
- }
+ if (path_state_ao_bounce(kg, state)) {
+ visibility = PATH_RAY_SHADOW;
+ ray->t = kernel_data.background.ao_distance;
+ }
#ifdef __HAIR__
- float difl = 0.0f, extmax = 0.0f;
- uint lcg_state = 0;
+ float difl = 0.0f, extmax = 0.0f;
+ uint lcg_state = 0;
- if(kernel_data.bvh.have_curves) {
- if((kernel_data.cam.resolution == 1) && (state->flag & PATH_RAY_CAMERA)) {
- float3 pixdiff = ray->dD.dx + ray->dD.dy;
- /*pixdiff = pixdiff - dot(pixdiff, ray.D)*ray.D;*/
- difl = kernel_data.curve.minimum_width * len(pixdiff) * 0.5f;
- }
+ if (kernel_data.bvh.have_curves) {
+ if ((kernel_data.cam.resolution == 1) && (state->flag & PATH_RAY_CAMERA)) {
+ float3 pixdiff = ray->dD.dx + ray->dD.dy;
+ /*pixdiff = pixdiff - dot(pixdiff, ray.D)*ray.D;*/
+ difl = kernel_data.curve.minimum_width * len(pixdiff) * 0.5f;
+ }
- extmax = kernel_data.curve.maximum_width;
- lcg_state = lcg_state_init_addrspace(state, 0x51633e2d);
- }
+ extmax = kernel_data.curve.maximum_width;
+ lcg_state = lcg_state_init_addrspace(state, 0x51633e2d);
+ }
- bool hit = scene_intersect(kg, *ray, visibility, isect, &lcg_state, difl, extmax);
+ bool hit = scene_intersect(kg, *ray, visibility, isect, &lcg_state, difl, extmax);
#else
- bool hit = scene_intersect(kg, *ray, visibility, isect, NULL, 0.0f, 0.0f);
-#endif /* __HAIR__ */
+ bool hit = scene_intersect(kg, *ray, visibility, isect, NULL, 0.0f, 0.0f);
+#endif /* __HAIR__ */
#ifdef __KERNEL_DEBUG__
- if(state->flag & PATH_RAY_CAMERA) {
- L->debug_data.num_bvh_traversed_nodes += isect->num_traversed_nodes;
- L->debug_data.num_bvh_traversed_instances += isect->num_traversed_instances;
- L->debug_data.num_bvh_intersections += isect->num_intersections;
- }
- L->debug_data.num_ray_bounces++;
-#endif /* __KERNEL_DEBUG__ */
-
- return hit;
+ if (state->flag & PATH_RAY_CAMERA) {
+ L->debug_data.num_bvh_traversed_nodes += isect->num_traversed_nodes;
+ L->debug_data.num_bvh_traversed_instances += isect->num_traversed_instances;
+ L->debug_data.num_bvh_intersections += isect->num_intersections;
+ }
+ L->debug_data.num_ray_bounces++;
+#endif /* __KERNEL_DEBUG__ */
+
+ return hit;
}
-ccl_device_forceinline void kernel_path_lamp_emission(
- KernelGlobals *kg,
- ccl_addr_space PathState *state,
- Ray *ray,
- float3 throughput,
- ccl_addr_space Intersection *isect,
- ShaderData *emission_sd,
- PathRadiance *L)
+ccl_device_forceinline void kernel_path_lamp_emission(KernelGlobals *kg,
+ ccl_addr_space PathState *state,
+ Ray *ray,
+ float3 throughput,
+ ccl_addr_space Intersection *isect,
+ ShaderData *emission_sd,
+ PathRadiance *L)
{
- PROFILING_INIT(kg, PROFILING_INDIRECT_EMISSION);
+ PROFILING_INIT(kg, PROFILING_INDIRECT_EMISSION);
#ifdef __LAMP_MIS__
- if(kernel_data.integrator.use_lamp_mis && !(state->flag & PATH_RAY_CAMERA)) {
- /* ray starting from previous non-transparent bounce */
- Ray light_ray;
-
- light_ray.P = ray->P - state->ray_t*ray->D;
- state->ray_t += isect->t;
- light_ray.D = ray->D;
- light_ray.t = state->ray_t;
- light_ray.time = ray->time;
- light_ray.dD = ray->dD;
- light_ray.dP = ray->dP;
-
- /* intersect with lamp */
- float3 emission;
-
- if(indirect_lamp_emission(kg, emission_sd, state, &light_ray, &emission))
- path_radiance_accum_emission(L, state, throughput, emission);
- }
-#endif /* __LAMP_MIS__ */
+ if (kernel_data.integrator.use_lamp_mis && !(state->flag & PATH_RAY_CAMERA)) {
+ /* ray starting from previous non-transparent bounce */
+ Ray light_ray;
+
+ light_ray.P = ray->P - state->ray_t * ray->D;
+ state->ray_t += isect->t;
+ light_ray.D = ray->D;
+ light_ray.t = state->ray_t;
+ light_ray.time = ray->time;
+ light_ray.dD = ray->dD;
+ light_ray.dP = ray->dP;
+
+ /* intersect with lamp */
+ float3 emission;
+
+ if (indirect_lamp_emission(kg, emission_sd, state, &light_ray, &emission))
+ path_radiance_accum_emission(L, state, throughput, emission);
+ }
+#endif /* __LAMP_MIS__ */
}
-ccl_device_forceinline void kernel_path_background(
- KernelGlobals *kg,
- ccl_addr_space PathState *state,
- ccl_addr_space Ray *ray,
- float3 throughput,
- ShaderData *sd,
- PathRadiance *L)
+ccl_device_forceinline void kernel_path_background(KernelGlobals *kg,
+ ccl_addr_space PathState *state,
+ ccl_addr_space Ray *ray,
+ float3 throughput,
+ ShaderData *sd,
+ PathRadiance *L)
{
- /* eval background shader if nothing hit */
- if(kernel_data.background.transparent && (state->flag & PATH_RAY_TRANSPARENT_BACKGROUND)) {
- L->transparent += average(throughput);
+ /* eval background shader if nothing hit */
+ if (kernel_data.background.transparent && (state->flag & PATH_RAY_TRANSPARENT_BACKGROUND)) {
+ L->transparent += average(throughput);
#ifdef __PASSES__
- if(!(kernel_data.film.light_pass_flag & PASSMASK(BACKGROUND)))
-#endif /* __PASSES__ */
- return;
- }
+ if (!(kernel_data.film.light_pass_flag & PASSMASK(BACKGROUND)))
+#endif /* __PASSES__ */
+ return;
+ }
- /* When using the ao bounces approximation, adjust background
- * shader intensity with ao factor. */
- if(path_state_ao_bounce(kg, state)) {
- throughput *= kernel_data.background.ao_bounces_factor;
- }
+ /* When using the ao bounces approximation, adjust background
+ * shader intensity with ao factor. */
+ if (path_state_ao_bounce(kg, state)) {
+ throughput *= kernel_data.background.ao_bounces_factor;
+ }
#ifdef __BACKGROUND__
- /* sample background shader */
- float3 L_background = indirect_background(kg, sd, state, ray);
- path_radiance_accum_background(L, state, throughput, L_background);
-#endif /* __BACKGROUND__ */
+ /* sample background shader */
+ float3 L_background = indirect_background(kg, sd, state, ray);
+ path_radiance_accum_background(L, state, throughput, L_background);
+#endif /* __BACKGROUND__ */
}
#ifndef __SPLIT_KERNEL__
-#ifdef __VOLUME__
-ccl_device_forceinline VolumeIntegrateResult kernel_path_volume(
- KernelGlobals *kg,
- ShaderData *sd,
- PathState *state,
- Ray *ray,
- float3 *throughput,
- ccl_addr_space Intersection *isect,
- bool hit,
- ShaderData *emission_sd,
- PathRadiance *L)
+# ifdef __VOLUME__
+ccl_device_forceinline VolumeIntegrateResult kernel_path_volume(KernelGlobals *kg,
+ ShaderData *sd,
+ PathState *state,
+ Ray *ray,
+ float3 *throughput,
+ ccl_addr_space Intersection *isect,
+ bool hit,
+ ShaderData *emission_sd,
+ PathRadiance *L)
{
- PROFILING_INIT(kg, PROFILING_VOLUME);
-
- /* Sanitize volume stack. */
- if(!hit) {
- kernel_volume_clean_stack(kg, state->volume_stack);
- }
-
- if(state->volume_stack[0].shader == SHADER_NONE) {
- return VOLUME_PATH_ATTENUATED;
- }
-
- /* volume attenuation, emission, scatter */
- Ray volume_ray = *ray;
- volume_ray.t = (hit)? isect->t: FLT_MAX;
-
- bool heterogeneous = volume_stack_is_heterogeneous(kg, state->volume_stack);
-
-# ifdef __VOLUME_DECOUPLED__
- int sampling_method = volume_stack_sampling_method(kg, state->volume_stack);
- bool direct = (state->flag & PATH_RAY_CAMERA) != 0;
- bool decoupled = kernel_volume_use_decoupled(kg, heterogeneous, direct, sampling_method);
-
- if(decoupled) {
- /* cache steps along volume for repeated sampling */
- VolumeSegment volume_segment;
-
- shader_setup_from_volume(kg, sd, &volume_ray);
- kernel_volume_decoupled_record(kg, state,
- &volume_ray, sd, &volume_segment, heterogeneous);
-
- volume_segment.sampling_method = sampling_method;
-
- /* emission */
- if(volume_segment.closure_flag & SD_EMISSION)
- path_radiance_accum_emission(L, state, *throughput, volume_segment.accum_emission);
-
- /* scattering */
- VolumeIntegrateResult result = VOLUME_PATH_ATTENUATED;
-
- if(volume_segment.closure_flag & SD_SCATTER) {
- int all = kernel_data.integrator.sample_all_lights_indirect;
-
- /* direct light sampling */
- kernel_branched_path_volume_connect_light(kg, sd,
- emission_sd, *throughput, state, L, all,
- &volume_ray, &volume_segment);
-
- /* indirect sample. if we use distance sampling and take just
- * one sample for direct and indirect light, we could share
- * this computation, but makes code a bit complex */
- float rphase = path_state_rng_1D(kg, state, PRNG_PHASE_CHANNEL);
- float rscatter = path_state_rng_1D(kg, state, PRNG_SCATTER_DISTANCE);
-
- result = kernel_volume_decoupled_scatter(kg,
- state, &volume_ray, sd, throughput,
- rphase, rscatter, &volume_segment, NULL, true);
- }
-
- /* free cached steps */
- kernel_volume_decoupled_free(kg, &volume_segment);
-
- if(result == VOLUME_PATH_SCATTERED) {
- if(kernel_path_volume_bounce(kg, sd, throughput, state, &L->state, ray))
- return VOLUME_PATH_SCATTERED;
- else
- return VOLUME_PATH_MISSED;
- }
- else {
- *throughput *= volume_segment.accum_transmittance;
- }
- }
- else
-# endif /* __VOLUME_DECOUPLED__ */
- {
- /* integrate along volume segment with distance sampling */
- VolumeIntegrateResult result = kernel_volume_integrate(
- kg, state, sd, &volume_ray, L, throughput, heterogeneous);
-
-# ifdef __VOLUME_SCATTER__
- if(result == VOLUME_PATH_SCATTERED) {
- /* direct lighting */
- kernel_path_volume_connect_light(kg, sd, emission_sd, *throughput, state, L);
-
- /* indirect light bounce */
- if(kernel_path_volume_bounce(kg, sd, throughput, state, &L->state, ray))
- return VOLUME_PATH_SCATTERED;
- else
- return VOLUME_PATH_MISSED;
- }
-# endif /* __VOLUME_SCATTER__ */
- }
-
- return VOLUME_PATH_ATTENUATED;
+ PROFILING_INIT(kg, PROFILING_VOLUME);
+
+ /* Sanitize volume stack. */
+ if (!hit) {
+ kernel_volume_clean_stack(kg, state->volume_stack);
+ }
+
+ if (state->volume_stack[0].shader == SHADER_NONE) {
+ return VOLUME_PATH_ATTENUATED;
+ }
+
+ /* volume attenuation, emission, scatter */
+ Ray volume_ray = *ray;
+ volume_ray.t = (hit) ? isect->t : FLT_MAX;
+
+ bool heterogeneous = volume_stack_is_heterogeneous(kg, state->volume_stack);
+
+# ifdef __VOLUME_DECOUPLED__
+ int sampling_method = volume_stack_sampling_method(kg, state->volume_stack);
+ bool direct = (state->flag & PATH_RAY_CAMERA) != 0;
+ bool decoupled = kernel_volume_use_decoupled(kg, heterogeneous, direct, sampling_method);
+
+ if (decoupled) {
+ /* cache steps along volume for repeated sampling */
+ VolumeSegment volume_segment;
+
+ shader_setup_from_volume(kg, sd, &volume_ray);
+ kernel_volume_decoupled_record(kg, state, &volume_ray, sd, &volume_segment, heterogeneous);
+
+ volume_segment.sampling_method = sampling_method;
+
+ /* emission */
+ if (volume_segment.closure_flag & SD_EMISSION)
+ path_radiance_accum_emission(L, state, *throughput, volume_segment.accum_emission);
+
+ /* scattering */
+ VolumeIntegrateResult result = VOLUME_PATH_ATTENUATED;
+
+ if (volume_segment.closure_flag & SD_SCATTER) {
+ int all = kernel_data.integrator.sample_all_lights_indirect;
+
+ /* direct light sampling */
+ kernel_branched_path_volume_connect_light(
+ kg, sd, emission_sd, *throughput, state, L, all, &volume_ray, &volume_segment);
+
+ /* indirect sample. if we use distance sampling and take just
+ * one sample for direct and indirect light, we could share
+ * this computation, but makes code a bit complex */
+ float rphase = path_state_rng_1D(kg, state, PRNG_PHASE_CHANNEL);
+ float rscatter = path_state_rng_1D(kg, state, PRNG_SCATTER_DISTANCE);
+
+ result = kernel_volume_decoupled_scatter(
+ kg, state, &volume_ray, sd, throughput, rphase, rscatter, &volume_segment, NULL, true);
+ }
+
+ /* free cached steps */
+ kernel_volume_decoupled_free(kg, &volume_segment);
+
+ if (result == VOLUME_PATH_SCATTERED) {
+ if (kernel_path_volume_bounce(kg, sd, throughput, state, &L->state, ray))
+ return VOLUME_PATH_SCATTERED;
+ else
+ return VOLUME_PATH_MISSED;
+ }
+ else {
+ *throughput *= volume_segment.accum_transmittance;
+ }
+ }
+ else
+# endif /* __VOLUME_DECOUPLED__ */
+ {
+ /* integrate along volume segment with distance sampling */
+ VolumeIntegrateResult result = kernel_volume_integrate(
+ kg, state, sd, &volume_ray, L, throughput, heterogeneous);
+
+# ifdef __VOLUME_SCATTER__
+ if (result == VOLUME_PATH_SCATTERED) {
+ /* direct lighting */
+ kernel_path_volume_connect_light(kg, sd, emission_sd, *throughput, state, L);
+
+ /* indirect light bounce */
+ if (kernel_path_volume_bounce(kg, sd, throughput, state, &L->state, ray))
+ return VOLUME_PATH_SCATTERED;
+ else
+ return VOLUME_PATH_MISSED;
+ }
+# endif /* __VOLUME_SCATTER__ */
+ }
+
+ return VOLUME_PATH_ATTENUATED;
}
-#endif /* __VOLUME__ */
-
-#endif /* __SPLIT_KERNEL__ */
-
-ccl_device_forceinline bool kernel_path_shader_apply(
- KernelGlobals *kg,
- ShaderData *sd,
- ccl_addr_space PathState *state,
- ccl_addr_space Ray *ray,
- float3 throughput,
- ShaderData *emission_sd,
- PathRadiance *L,
- ccl_global float *buffer)
+# endif /* __VOLUME__ */
+
+#endif /* __SPLIT_KERNEL__ */
+
+ccl_device_forceinline bool kernel_path_shader_apply(KernelGlobals *kg,
+ ShaderData *sd,
+ ccl_addr_space PathState *state,
+ ccl_addr_space Ray *ray,
+ float3 throughput,
+ ShaderData *emission_sd,
+ PathRadiance *L,
+ ccl_global float *buffer)
{
- PROFILING_INIT(kg, PROFILING_SHADER_APPLY);
+ PROFILING_INIT(kg, PROFILING_SHADER_APPLY);
#ifdef __SHADOW_TRICKS__
- if((sd->object_flag & SD_OBJECT_SHADOW_CATCHER)) {
- if(state->flag & PATH_RAY_TRANSPARENT_BACKGROUND) {
- state->flag |= (PATH_RAY_SHADOW_CATCHER |
- PATH_RAY_STORE_SHADOW_INFO);
-
- float3 bg = make_float3(0.0f, 0.0f, 0.0f);
- if(!kernel_data.background.transparent) {
- bg = indirect_background(kg, emission_sd, state, ray);
- }
- path_radiance_accum_shadowcatcher(L, throughput, bg);
- }
- }
- else if(state->flag & PATH_RAY_SHADOW_CATCHER) {
- /* Only update transparency after shadow catcher bounce. */
- L->shadow_transparency *=
- average(shader_bsdf_transparency(kg, sd));
- }
-#endif /* __SHADOW_TRICKS__ */
-
- /* holdout */
+ if ((sd->object_flag & SD_OBJECT_SHADOW_CATCHER)) {
+ if (state->flag & PATH_RAY_TRANSPARENT_BACKGROUND) {
+ state->flag |= (PATH_RAY_SHADOW_CATCHER | PATH_RAY_STORE_SHADOW_INFO);
+
+ float3 bg = make_float3(0.0f, 0.0f, 0.0f);
+ if (!kernel_data.background.transparent) {
+ bg = indirect_background(kg, emission_sd, state, ray);
+ }
+ path_radiance_accum_shadowcatcher(L, throughput, bg);
+ }
+ }
+ else if (state->flag & PATH_RAY_SHADOW_CATCHER) {
+ /* Only update transparency after shadow catcher bounce. */
+ L->shadow_transparency *= average(shader_bsdf_transparency(kg, sd));
+ }
+#endif /* __SHADOW_TRICKS__ */
+
+ /* holdout */
#ifdef __HOLDOUT__
- if(((sd->flag & SD_HOLDOUT) ||
- (sd->object_flag & SD_OBJECT_HOLDOUT_MASK)) &&
- (state->flag & PATH_RAY_TRANSPARENT_BACKGROUND))
- {
- if(kernel_data.background.transparent) {
- float3 holdout_weight;
- if(sd->object_flag & SD_OBJECT_HOLDOUT_MASK) {
- holdout_weight = make_float3(1.0f, 1.0f, 1.0f);
- }
- else {
- holdout_weight = shader_holdout_eval(kg, sd);
- }
- /* any throughput is ok, should all be identical here */
- L->transparent += average(holdout_weight*throughput);
- }
-
- if(sd->object_flag & SD_OBJECT_HOLDOUT_MASK) {
- return false;
- }
- }
-#endif /* __HOLDOUT__ */
-
- /* holdout mask objects do not write data passes */
- kernel_write_data_passes(kg, buffer, L, sd, 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) {
- 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;
- shader_bsdf_blur(kg, sd, blur_roughness);
- }
- }
+ if (((sd->flag & SD_HOLDOUT) || (sd->object_flag & SD_OBJECT_HOLDOUT_MASK)) &&
+ (state->flag & PATH_RAY_TRANSPARENT_BACKGROUND)) {
+ if (kernel_data.background.transparent) {
+ float3 holdout_weight;
+ if (sd->object_flag & SD_OBJECT_HOLDOUT_MASK) {
+ holdout_weight = make_float3(1.0f, 1.0f, 1.0f);
+ }
+ else {
+ holdout_weight = shader_holdout_eval(kg, sd);
+ }
+ /* any throughput is ok, should all be identical here */
+ L->transparent += average(holdout_weight * throughput);
+ }
+
+ if (sd->object_flag & SD_OBJECT_HOLDOUT_MASK) {
+ return false;
+ }
+ }
+#endif /* __HOLDOUT__ */
+
+ /* holdout mask objects do not write data passes */
+ kernel_write_data_passes(kg, buffer, L, sd, 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) {
+ 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;
+ shader_bsdf_blur(kg, sd, blur_roughness);
+ }
+ }
#ifdef __EMISSION__
- /* emission */
- if(sd->flag & SD_EMISSION) {
- float3 emission = indirect_primitive_emission(kg, sd, sd->ray_length, state->flag, state->ray_pdf);
- path_radiance_accum_emission(L, state, throughput, emission);
- }
-#endif /* __EMISSION__ */
-
- return true;
+ /* emission */
+ if (sd->flag & SD_EMISSION) {
+ float3 emission = indirect_primitive_emission(
+ kg, sd, sd->ray_length, state->flag, state->ray_pdf);
+ path_radiance_accum_emission(L, state, throughput, emission);
+ }
+#endif /* __EMISSION__ */
+
+ return true;
}
ccl_device_noinline void kernel_path_ao(KernelGlobals *kg,
@@ -363,44 +352,44 @@ ccl_device_noinline void kernel_path_ao(KernelGlobals *kg,
float3 throughput,
float3 ao_alpha)
{
- PROFILING_INIT(kg, PROFILING_AO);
-
- /* todo: solve correlation */
- float bsdf_u, bsdf_v;
-
- path_state_rng_2D(kg, state, PRNG_BSDF_U, &bsdf_u, &bsdf_v);
-
- float ao_factor = kernel_data.background.ao_factor;
- float3 ao_N;
- float3 ao_bsdf = shader_bsdf_ao(kg, sd, ao_factor, &ao_N);
- 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 light_ray;
- float3 ao_shadow;
-
- light_ray.P = ray_offset(sd->P, sd->Ng);
- light_ray.D = ao_D;
- light_ray.t = kernel_data.background.ao_distance;
- light_ray.time = sd->time;
- light_ray.dP = sd->dP;
- light_ray.dD = differential3_zero();
-
- if(!shadow_blocked(kg, sd, emission_sd, state, &light_ray, &ao_shadow)) {
- path_radiance_accum_ao(L, state, throughput, ao_alpha, ao_bsdf, ao_shadow);
- }
- else {
- path_radiance_accum_total_ao(L, state, throughput, ao_bsdf);
- }
- }
+ PROFILING_INIT(kg, PROFILING_AO);
+
+ /* todo: solve correlation */
+ float bsdf_u, bsdf_v;
+
+ path_state_rng_2D(kg, state, PRNG_BSDF_U, &bsdf_u, &bsdf_v);
+
+ float ao_factor = kernel_data.background.ao_factor;
+ float3 ao_N;
+ float3 ao_bsdf = shader_bsdf_ao(kg, sd, ao_factor, &ao_N);
+ 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 light_ray;
+ float3 ao_shadow;
+
+ light_ray.P = ray_offset(sd->P, sd->Ng);
+ light_ray.D = ao_D;
+ light_ray.t = kernel_data.background.ao_distance;
+ light_ray.time = sd->time;
+ light_ray.dP = sd->dP;
+ light_ray.dD = differential3_zero();
+
+ if (!shadow_blocked(kg, sd, emission_sd, state, &light_ray, &ao_shadow)) {
+ path_radiance_accum_ao(L, state, throughput, ao_alpha, ao_bsdf, ao_shadow);
+ }
+ else {
+ path_radiance_accum_total_ao(L, state, throughput, ao_bsdf);
+ }
+ }
}
#ifndef __SPLIT_KERNEL__
-#if defined(__BRANCHED_PATH__) || defined(__BAKING__)
+# if defined(__BRANCHED_PATH__) || defined(__BAKING__)
ccl_device void kernel_path_indirect(KernelGlobals *kg,
ShaderData *sd,
@@ -410,369 +399,300 @@ ccl_device void kernel_path_indirect(KernelGlobals *kg,
PathState *state,
PathRadiance *L)
{
-#ifdef __SUBSURFACE__
- SubsurfaceIndirectRays ss_indirect;
- kernel_path_subsurface_init_indirect(&ss_indirect);
-
- for(;;) {
-#endif /* __SUBSURFACE__ */
-
- /* path iteration */
- for(;;) {
- /* Find intersection with objects in scene. */
- Intersection isect;
- bool hit = kernel_path_scene_intersect(kg, state, ray, &isect, L);
-
- /* Find intersection with lamps and compute emission for MIS. */
- kernel_path_lamp_emission(kg, state, ray, throughput, &isect, sd, L);
-
-#ifdef __VOLUME__
- /* Volume integration. */
- VolumeIntegrateResult result = kernel_path_volume(kg,
- sd,
- state,
- ray,
- &throughput,
- &isect,
- hit,
- emission_sd,
- L);
-
- if(result == VOLUME_PATH_SCATTERED) {
- continue;
- }
- else if(result == VOLUME_PATH_MISSED) {
- break;
- }
-#endif /* __VOLUME__*/
-
- /* Shade background. */
- if(!hit) {
- kernel_path_background(kg, state, ray, throughput, sd, L);
- break;
- }
- else if(path_state_ao_bounce(kg, state)) {
- break;
- }
-
- /* Setup shader data. */
- shader_setup_from_ray(kg, sd, &isect, ray);
-
- /* Skip most work for volume bounding surface. */
-#ifdef __VOLUME__
- if(!(sd->flag & SD_HAS_ONLY_VOLUME)) {
-#endif
-
- /* Evaluate shader. */
- shader_eval_surface(kg, sd, state, state->flag);
- shader_prepare_closures(sd, state);
-
- /* Apply shadow catcher, holdout, emission. */
- if(!kernel_path_shader_apply(kg,
- sd,
- state,
- ray,
- throughput,
- emission_sd,
- L,
- NULL))
- {
- break;
- }
-
- /* path termination. this is a strange place to put the termination, it's
- * 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 */
- float probability = path_state_continuation_probability(kg, state, throughput);
-
- if(probability == 0.0f) {
- break;
- }
- else if(probability != 1.0f) {
- float terminate = path_state_rng_1D(kg, state, PRNG_TERMINATE);
-
- if(terminate >= probability)
- break;
-
- throughput /= probability;
- }
-
- kernel_update_denoising_features(kg, sd, state, L);
-
-#ifdef __AO__
- /* ambient occlusion */
- if(kernel_data.integrator.use_ambient_occlusion) {
- kernel_path_ao(kg, sd, emission_sd, L, state, throughput, make_float3(0.0f, 0.0f, 0.0f));
- }
-#endif /* __AO__ */
-
-
-#ifdef __SUBSURFACE__
- /* bssrdf scatter to a different location on the same object, replacing
- * the closures with a diffuse BSDF */
- if(sd->flag & SD_BSSRDF) {
- if(kernel_path_subsurface_scatter(kg,
- sd,
- emission_sd,
- L,
- state,
- ray,
- &throughput,
- &ss_indirect))
- {
- break;
- }
- }
-#endif /* __SUBSURFACE__ */
-
-#if defined(__EMISSION__)
- if(kernel_data.integrator.use_direct_light) {
- int all = (kernel_data.integrator.sample_all_lights_indirect) ||
- (state->flag & PATH_RAY_SHADOW_CATCHER);
- kernel_branched_path_surface_connect_light(kg,
- sd,
- emission_sd,
- state,
- throughput,
- 1.0f,
- L,
- all);
- }
-#endif /* defined(__EMISSION__) */
-
-#ifdef __VOLUME__
- }
-#endif
-
- if(!kernel_path_surface_bounce(kg, sd, &throughput, state, &L->state, ray))
- break;
- }
-
-#ifdef __SUBSURFACE__
- /* 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);
- }
- else {
- break;
- }
- }
-#endif /* __SUBSURFACE__ */
+# ifdef __SUBSURFACE__
+ SubsurfaceIndirectRays ss_indirect;
+ kernel_path_subsurface_init_indirect(&ss_indirect);
+
+ for (;;) {
+# endif /* __SUBSURFACE__ */
+
+ /* path iteration */
+ for (;;) {
+ /* Find intersection with objects in scene. */
+ Intersection isect;
+ bool hit = kernel_path_scene_intersect(kg, state, ray, &isect, L);
+
+ /* Find intersection with lamps and compute emission for MIS. */
+ kernel_path_lamp_emission(kg, state, ray, throughput, &isect, sd, L);
+
+# ifdef __VOLUME__
+ /* Volume integration. */
+ VolumeIntegrateResult result = kernel_path_volume(
+ kg, sd, state, ray, &throughput, &isect, hit, emission_sd, L);
+
+ if (result == VOLUME_PATH_SCATTERED) {
+ continue;
+ }
+ else if (result == VOLUME_PATH_MISSED) {
+ break;
+ }
+# endif /* __VOLUME__*/
+
+ /* Shade background. */
+ if (!hit) {
+ kernel_path_background(kg, state, ray, throughput, sd, L);
+ break;
+ }
+ else if (path_state_ao_bounce(kg, state)) {
+ break;
+ }
+
+ /* Setup shader data. */
+ shader_setup_from_ray(kg, sd, &isect, ray);
+
+ /* Skip most work for volume bounding surface. */
+# ifdef __VOLUME__
+ if (!(sd->flag & SD_HAS_ONLY_VOLUME)) {
+# endif
+
+ /* Evaluate shader. */
+ shader_eval_surface(kg, sd, state, state->flag);
+ shader_prepare_closures(sd, state);
+
+ /* Apply shadow catcher, holdout, emission. */
+ if (!kernel_path_shader_apply(kg, sd, state, ray, throughput, emission_sd, L, NULL)) {
+ break;
+ }
+
+ /* path termination. this is a strange place to put the termination, it's
+ * 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 */
+ float probability = path_state_continuation_probability(kg, state, throughput);
+
+ if (probability == 0.0f) {
+ break;
+ }
+ else if (probability != 1.0f) {
+ float terminate = path_state_rng_1D(kg, state, PRNG_TERMINATE);
+
+ if (terminate >= probability)
+ break;
+
+ throughput /= probability;
+ }
+
+ kernel_update_denoising_features(kg, sd, state, L);
+
+# ifdef __AO__
+ /* ambient occlusion */
+ if (kernel_data.integrator.use_ambient_occlusion) {
+ kernel_path_ao(kg, sd, emission_sd, L, state, throughput, make_float3(0.0f, 0.0f, 0.0f));
+ }
+# endif /* __AO__ */
+
+# ifdef __SUBSURFACE__
+ /* bssrdf scatter to a different location on the same object, replacing
+ * the closures with a diffuse BSDF */
+ if (sd->flag & SD_BSSRDF) {
+ if (kernel_path_subsurface_scatter(
+ kg, sd, emission_sd, L, state, ray, &throughput, &ss_indirect)) {
+ break;
+ }
+ }
+# endif /* __SUBSURFACE__ */
+
+# if defined(__EMISSION__)
+ if (kernel_data.integrator.use_direct_light) {
+ int all = (kernel_data.integrator.sample_all_lights_indirect) ||
+ (state->flag & PATH_RAY_SHADOW_CATCHER);
+ kernel_branched_path_surface_connect_light(
+ kg, sd, emission_sd, state, throughput, 1.0f, L, all);
+ }
+# endif /* defined(__EMISSION__) */
+
+# ifdef __VOLUME__
+ }
+# endif
+
+ if (!kernel_path_surface_bounce(kg, sd, &throughput, state, &L->state, ray))
+ break;
+ }
+
+# ifdef __SUBSURFACE__
+ /* 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);
+ }
+ else {
+ break;
+ }
+ }
+# endif /* __SUBSURFACE__ */
}
-#endif /* defined(__BRANCHED_PATH__) || defined(__BAKING__) */
+# endif /* defined(__BRANCHED_PATH__) || defined(__BAKING__) */
-ccl_device_forceinline void kernel_path_integrate(
- KernelGlobals *kg,
- PathState *state,
- float3 throughput,
- Ray *ray,
- PathRadiance *L,
- ccl_global float *buffer,
- ShaderData *emission_sd)
+ccl_device_forceinline void kernel_path_integrate(KernelGlobals *kg,
+ PathState *state,
+ float3 throughput,
+ Ray *ray,
+ PathRadiance *L,
+ ccl_global float *buffer,
+ ShaderData *emission_sd)
{
- PROFILING_INIT(kg, PROFILING_PATH_INTEGRATE);
-
- /* Shader data memory used for both volumes and surfaces, saves stack space. */
- ShaderData sd;
-
-#ifdef __SUBSURFACE__
- SubsurfaceIndirectRays ss_indirect;
- kernel_path_subsurface_init_indirect(&ss_indirect);
-
- for(;;) {
-#endif /* __SUBSURFACE__ */
-
- /* path iteration */
- for(;;) {
- /* Find intersection with objects in scene. */
- Intersection isect;
- bool hit = kernel_path_scene_intersect(kg, state, ray, &isect, L);
-
- /* Find intersection with lamps and compute emission for MIS. */
- kernel_path_lamp_emission(kg, state, ray, throughput, &isect, &sd, L);
-
-#ifdef __VOLUME__
- /* Volume integration. */
- VolumeIntegrateResult result = kernel_path_volume(kg,
- &sd,
- state,
- ray,
- &throughput,
- &isect,
- hit,
- emission_sd,
- L);
-
- if(result == VOLUME_PATH_SCATTERED) {
- continue;
- }
- else if(result == VOLUME_PATH_MISSED) {
- break;
- }
-#endif /* __VOLUME__*/
-
- /* Shade background. */
- if(!hit) {
- kernel_path_background(kg, state, ray, throughput, &sd, L);
- break;
- }
- else if(path_state_ao_bounce(kg, state)) {
- break;
- }
-
- /* Setup shader data. */
- shader_setup_from_ray(kg, &sd, &isect, ray);
-
- /* Skip most work for volume bounding surface. */
-#ifdef __VOLUME__
- if(!(sd.flag & SD_HAS_ONLY_VOLUME)) {
-#endif
-
- /* Evaluate shader. */
- shader_eval_surface(kg, &sd, state, state->flag);
- shader_prepare_closures(&sd, state);
-
- /* Apply shadow catcher, holdout, emission. */
- if(!kernel_path_shader_apply(kg,
- &sd,
- state,
- ray,
- throughput,
- emission_sd,
- L,
- buffer))
- {
- break;
- }
-
- /* path termination. this is a strange place to put the termination, it's
- * 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 */
- float probability = path_state_continuation_probability(kg, state, throughput);
-
- if(probability == 0.0f) {
- break;
- }
- else if(probability != 1.0f) {
- float terminate = path_state_rng_1D(kg, state, PRNG_TERMINATE);
- if(terminate >= probability)
- break;
-
- throughput /= probability;
- }
-
- kernel_update_denoising_features(kg, &sd, state, L);
-
-#ifdef __AO__
- /* ambient occlusion */
- if(kernel_data.integrator.use_ambient_occlusion) {
- kernel_path_ao(kg, &sd, emission_sd, L, state, throughput, shader_bsdf_alpha(kg, &sd));
- }
-#endif /* __AO__ */
-
-#ifdef __SUBSURFACE__
- /* bssrdf scatter to a different location on the same object, replacing
- * the closures with a diffuse BSDF */
- if(sd.flag & SD_BSSRDF) {
- if(kernel_path_subsurface_scatter(kg,
- &sd,
- emission_sd,
- L,
- state,
- ray,
- &throughput,
- &ss_indirect))
- {
- break;
- }
- }
-#endif /* __SUBSURFACE__ */
-
- /* direct lighting */
- kernel_path_surface_connect_light(kg, &sd, emission_sd, throughput, state, L);
-
-#ifdef __VOLUME__
- }
-#endif
-
- /* compute direct lighting and next bounce */
- if(!kernel_path_surface_bounce(kg, &sd, &throughput, state, &L->state, ray))
- break;
- }
-
-#ifdef __SUBSURFACE__
- /* 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);
- }
- else {
- break;
- }
- }
-#endif /* __SUBSURFACE__ */
+ PROFILING_INIT(kg, PROFILING_PATH_INTEGRATE);
+
+ /* Shader data memory used for both volumes and surfaces, saves stack space. */
+ ShaderData sd;
+
+# ifdef __SUBSURFACE__
+ SubsurfaceIndirectRays ss_indirect;
+ kernel_path_subsurface_init_indirect(&ss_indirect);
+
+ for (;;) {
+# endif /* __SUBSURFACE__ */
+
+ /* path iteration */
+ for (;;) {
+ /* Find intersection with objects in scene. */
+ Intersection isect;
+ bool hit = kernel_path_scene_intersect(kg, state, ray, &isect, L);
+
+ /* Find intersection with lamps and compute emission for MIS. */
+ kernel_path_lamp_emission(kg, state, ray, throughput, &isect, &sd, L);
+
+# ifdef __VOLUME__
+ /* Volume integration. */
+ VolumeIntegrateResult result = kernel_path_volume(
+ kg, &sd, state, ray, &throughput, &isect, hit, emission_sd, L);
+
+ if (result == VOLUME_PATH_SCATTERED) {
+ continue;
+ }
+ else if (result == VOLUME_PATH_MISSED) {
+ break;
+ }
+# endif /* __VOLUME__*/
+
+ /* Shade background. */
+ if (!hit) {
+ kernel_path_background(kg, state, ray, throughput, &sd, L);
+ break;
+ }
+ else if (path_state_ao_bounce(kg, state)) {
+ break;
+ }
+
+ /* Setup shader data. */
+ shader_setup_from_ray(kg, &sd, &isect, ray);
+
+ /* Skip most work for volume bounding surface. */
+# ifdef __VOLUME__
+ if (!(sd.flag & SD_HAS_ONLY_VOLUME)) {
+# endif
+
+ /* Evaluate shader. */
+ shader_eval_surface(kg, &sd, state, state->flag);
+ shader_prepare_closures(&sd, state);
+
+ /* Apply shadow catcher, holdout, emission. */
+ if (!kernel_path_shader_apply(kg, &sd, state, ray, throughput, emission_sd, L, buffer)) {
+ break;
+ }
+
+ /* path termination. this is a strange place to put the termination, it's
+ * 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 */
+ float probability = path_state_continuation_probability(kg, state, throughput);
+
+ if (probability == 0.0f) {
+ break;
+ }
+ else if (probability != 1.0f) {
+ float terminate = path_state_rng_1D(kg, state, PRNG_TERMINATE);
+ if (terminate >= probability)
+ break;
+
+ throughput /= probability;
+ }
+
+ kernel_update_denoising_features(kg, &sd, state, L);
+
+# ifdef __AO__
+ /* ambient occlusion */
+ if (kernel_data.integrator.use_ambient_occlusion) {
+ kernel_path_ao(kg, &sd, emission_sd, L, state, throughput, shader_bsdf_alpha(kg, &sd));
+ }
+# endif /* __AO__ */
+
+# ifdef __SUBSURFACE__
+ /* bssrdf scatter to a different location on the same object, replacing
+ * the closures with a diffuse BSDF */
+ if (sd.flag & SD_BSSRDF) {
+ if (kernel_path_subsurface_scatter(
+ kg, &sd, emission_sd, L, state, ray, &throughput, &ss_indirect)) {
+ break;
+ }
+ }
+# endif /* __SUBSURFACE__ */
+
+ /* direct lighting */
+ kernel_path_surface_connect_light(kg, &sd, emission_sd, throughput, state, L);
+
+# ifdef __VOLUME__
+ }
+# endif
+
+ /* compute direct lighting and next bounce */
+ if (!kernel_path_surface_bounce(kg, &sd, &throughput, state, &L->state, ray))
+ break;
+ }
+
+# ifdef __SUBSURFACE__
+ /* 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);
+ }
+ else {
+ break;
+ }
+ }
+# endif /* __SUBSURFACE__ */
}
-ccl_device void kernel_path_trace(KernelGlobals *kg,
- ccl_global float *buffer,
- int sample, int x, int y, int offset, int stride)
+ccl_device void kernel_path_trace(
+ KernelGlobals *kg, ccl_global float *buffer, int sample, int x, int y, int offset, int stride)
{
- PROFILING_INIT(kg, PROFILING_RAY_SETUP);
+ PROFILING_INIT(kg, PROFILING_RAY_SETUP);
- /* buffer offset */
- int index = offset + x + y*stride;
- int pass_stride = kernel_data.film.pass_stride;
+ /* buffer offset */
+ int index = offset + x + y * stride;
+ int pass_stride = kernel_data.film.pass_stride;
- buffer += index*pass_stride;
+ buffer += index * pass_stride;
- /* Initialize random numbers and sample ray. */
- uint rng_hash;
- Ray ray;
+ /* Initialize random numbers and sample ray. */
+ uint rng_hash;
+ Ray ray;
- kernel_path_trace_setup(kg, sample, x, y, &rng_hash, &ray);
+ kernel_path_trace_setup(kg, sample, x, y, &rng_hash, &ray);
- if(ray.t == 0.0f) {
- return;
- }
+ if (ray.t == 0.0f) {
+ return;
+ }
- /* Initialize state. */
- float3 throughput = make_float3(1.0f, 1.0f, 1.0f);
+ /* Initialize state. */
+ float3 throughput = make_float3(1.0f, 1.0f, 1.0f);
- PathRadiance L;
- path_radiance_init(&L, kernel_data.film.use_light_pass);
+ PathRadiance L;
+ path_radiance_init(&L, kernel_data.film.use_light_pass);
- ShaderDataTinyStorage emission_sd_storage;
- ShaderData *emission_sd = AS_SHADER_DATA(&emission_sd_storage);
+ ShaderDataTinyStorage emission_sd_storage;
+ ShaderData *emission_sd = AS_SHADER_DATA(&emission_sd_storage);
- PathState state;
- path_state_init(kg, emission_sd, &state, rng_hash, sample, &ray);
+ PathState state;
+ path_state_init(kg, emission_sd, &state, rng_hash, sample, &ray);
- /* Integrate. */
- kernel_path_integrate(kg,
- &state,
- throughput,
- &ray,
- &L,
- buffer,
- emission_sd);
+ /* Integrate. */
+ kernel_path_integrate(kg, &state, throughput, &ray, &L, buffer, emission_sd);
- kernel_write_result(kg, buffer, sample, &L);
+ kernel_write_result(kg, buffer, sample, &L);
}
-#endif /* __SPLIT_KERNEL__ */
+#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 21da4d9308b..e8ce61024b3 100644
--- a/intern/cycles/kernel/kernel_path_branched.h
+++ b/intern/cycles/kernel/kernel_path_branched.h
@@ -25,297 +25,262 @@ ccl_device_inline void kernel_branched_path_ao(KernelGlobals *kg,
ccl_addr_space PathState *state,
float3 throughput)
{
- int num_samples = kernel_data.integrator.ao_samples;
- float num_samples_inv = 1.0f/num_samples;
- float ao_factor = kernel_data.background.ao_factor;
- float3 ao_N;
- float3 ao_bsdf = shader_bsdf_ao(kg, sd, ao_factor, &ao_N);
- float3 ao_alpha = shader_bsdf_alpha(kg, sd);
-
- for(int j = 0; j < num_samples; j++) {
- float bsdf_u, bsdf_v;
- path_branched_rng_2D(kg, state->rng_hash, state, j, num_samples, PRNG_BSDF_U, &bsdf_u, &bsdf_v);
-
- 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 light_ray;
- float3 ao_shadow;
-
- light_ray.P = ray_offset(sd->P, sd->Ng);
- light_ray.D = ao_D;
- light_ray.t = kernel_data.background.ao_distance;
- light_ray.time = sd->time;
- light_ray.dP = sd->dP;
- light_ray.dD = differential3_zero();
-
- if(!shadow_blocked(kg, sd, emission_sd, state, &light_ray, &ao_shadow)) {
- path_radiance_accum_ao(L, state, throughput*num_samples_inv, ao_alpha, ao_bsdf, ao_shadow);
- }
- else {
- path_radiance_accum_total_ao(L, state, throughput*num_samples_inv, ao_bsdf);
- }
- }
- }
+ int num_samples = kernel_data.integrator.ao_samples;
+ float num_samples_inv = 1.0f / num_samples;
+ float ao_factor = kernel_data.background.ao_factor;
+ float3 ao_N;
+ float3 ao_bsdf = shader_bsdf_ao(kg, sd, ao_factor, &ao_N);
+ float3 ao_alpha = shader_bsdf_alpha(kg, sd);
+
+ for (int j = 0; j < num_samples; j++) {
+ float bsdf_u, bsdf_v;
+ path_branched_rng_2D(
+ kg, state->rng_hash, state, j, num_samples, PRNG_BSDF_U, &bsdf_u, &bsdf_v);
+
+ 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 light_ray;
+ float3 ao_shadow;
+
+ light_ray.P = ray_offset(sd->P, sd->Ng);
+ light_ray.D = ao_D;
+ light_ray.t = kernel_data.background.ao_distance;
+ light_ray.time = sd->time;
+ light_ray.dP = sd->dP;
+ light_ray.dD = differential3_zero();
+
+ if (!shadow_blocked(kg, sd, emission_sd, state, &light_ray, &ao_shadow)) {
+ path_radiance_accum_ao(
+ L, state, throughput * num_samples_inv, ao_alpha, ao_bsdf, ao_shadow);
+ }
+ else {
+ path_radiance_accum_total_ao(L, state, throughput * num_samples_inv, ao_bsdf);
+ }
+ }
+ }
}
-#ifndef __SPLIT_KERNEL__
-
-#ifdef __VOLUME__
-ccl_device_forceinline void kernel_branched_path_volume(
- KernelGlobals *kg,
- ShaderData *sd,
- PathState *state,
- Ray *ray,
- float3 *throughput,
- ccl_addr_space Intersection *isect,
- bool hit,
- ShaderData *indirect_sd,
- ShaderData *emission_sd,
- PathRadiance *L)
+# ifndef __SPLIT_KERNEL__
+
+# ifdef __VOLUME__
+ccl_device_forceinline void kernel_branched_path_volume(KernelGlobals *kg,
+ ShaderData *sd,
+ PathState *state,
+ Ray *ray,
+ float3 *throughput,
+ ccl_addr_space Intersection *isect,
+ bool hit,
+ ShaderData *indirect_sd,
+ ShaderData *emission_sd,
+ PathRadiance *L)
{
- /* Sanitize volume stack. */
- if(!hit) {
- kernel_volume_clean_stack(kg, state->volume_stack);
- }
-
- if(state->volume_stack[0].shader == SHADER_NONE) {
- return;
- }
-
- /* volume attenuation, emission, scatter */
- Ray volume_ray = *ray;
- volume_ray.t = (hit)? isect->t: FLT_MAX;
-
- bool heterogeneous = volume_stack_is_heterogeneous(kg, state->volume_stack);
-
-# ifdef __VOLUME_DECOUPLED__
- /* decoupled ray marching only supported on CPU */
- if(kernel_data.integrator.volume_decoupled) {
- /* cache steps along volume for repeated sampling */
- VolumeSegment volume_segment;
-
- shader_setup_from_volume(kg, sd, &volume_ray);
- kernel_volume_decoupled_record(kg, state,
- &volume_ray, sd, &volume_segment, heterogeneous);
-
- /* direct light sampling */
- if(volume_segment.closure_flag & SD_SCATTER) {
- volume_segment.sampling_method = volume_stack_sampling_method(kg, state->volume_stack);
-
- int all = kernel_data.integrator.sample_all_lights_direct;
-
- kernel_branched_path_volume_connect_light(kg, sd,
- emission_sd, *throughput, state, L, all,
- &volume_ray, &volume_segment);
-
- /* indirect light sampling */
- int num_samples = kernel_data.integrator.volume_samples;
- float num_samples_inv = 1.0f/num_samples;
-
- for(int j = 0; j < num_samples; j++) {
- PathState ps = *state;
- Ray pray = *ray;
- float3 tp = *throughput;
-
- /* branch RNG state */
- path_state_branch(&ps, j, num_samples);
-
- /* scatter sample. if we use distance sampling and take just one
- * sample for direct and indirect light, we could share this
- * computation, but makes code a bit complex */
- float rphase = path_state_rng_1D(kg, &ps, PRNG_PHASE_CHANNEL);
- float rscatter = path_state_rng_1D(kg, &ps, PRNG_SCATTER_DISTANCE);
-
- VolumeIntegrateResult result = kernel_volume_decoupled_scatter(kg,
- &ps, &pray, sd, &tp, rphase, rscatter, &volume_segment, NULL, false);
-
- if(result == VOLUME_PATH_SCATTERED &&
- kernel_path_volume_bounce(kg,
- sd,
- &tp,
- &ps,
- &L->state,
- &pray))
- {
- kernel_path_indirect(kg,
- indirect_sd,
- emission_sd,
- &pray,
- tp*num_samples_inv,
- &ps,
- L);
-
- /* for render passes, sum and reset indirect light pass variables
- * for the next samples */
- path_radiance_sum_indirect(L);
- path_radiance_reset_indirect(L);
- }
- }
- }
-
- /* emission and transmittance */
- if(volume_segment.closure_flag & SD_EMISSION)
- path_radiance_accum_emission(L, state, *throughput, volume_segment.accum_emission);
- *throughput *= volume_segment.accum_transmittance;
-
- /* free cached steps */
- kernel_volume_decoupled_free(kg, &volume_segment);
- }
- else
-# endif /* __VOLUME_DECOUPLED__ */
- {
- /* GPU: no decoupled ray marching, scatter probalistically */
- int num_samples = kernel_data.integrator.volume_samples;
- float num_samples_inv = 1.0f/num_samples;
-
- /* todo: we should cache the shader evaluations from stepping
- * through the volume, for now we redo them multiple times */
-
- for(int j = 0; j < num_samples; j++) {
- PathState ps = *state;
- Ray pray = *ray;
- float3 tp = (*throughput) * num_samples_inv;
-
- /* branch RNG state */
- path_state_branch(&ps, j, num_samples);
-
- VolumeIntegrateResult result = kernel_volume_integrate(
- kg, &ps, sd, &volume_ray, L, &tp, heterogeneous);
-
-# ifdef __VOLUME_SCATTER__
- if(result == VOLUME_PATH_SCATTERED) {
- /* todo: support equiangular, MIS and all light sampling.
- * alternatively get decoupled ray marching working on the GPU */
- kernel_path_volume_connect_light(kg, sd, emission_sd, tp, state, L);
-
- if(kernel_path_volume_bounce(kg,
- sd,
- &tp,
- &ps,
- &L->state,
- &pray))
- {
- kernel_path_indirect(kg,
- indirect_sd,
- emission_sd,
- &pray,
- tp,
- &ps,
- L);
-
- /* for render passes, sum and reset indirect light pass variables
- * for the next samples */
- path_radiance_sum_indirect(L);
- path_radiance_reset_indirect(L);
- }
- }
-# endif /* __VOLUME_SCATTER__ */
- }
-
- /* todo: avoid this calculation using decoupled ray marching */
- kernel_volume_shadow(kg, emission_sd, state, &volume_ray, throughput);
- }
+ /* Sanitize volume stack. */
+ if (!hit) {
+ kernel_volume_clean_stack(kg, state->volume_stack);
+ }
+
+ if (state->volume_stack[0].shader == SHADER_NONE) {
+ return;
+ }
+
+ /* volume attenuation, emission, scatter */
+ Ray volume_ray = *ray;
+ volume_ray.t = (hit) ? isect->t : FLT_MAX;
+
+ bool heterogeneous = volume_stack_is_heterogeneous(kg, state->volume_stack);
+
+# ifdef __VOLUME_DECOUPLED__
+ /* decoupled ray marching only supported on CPU */
+ if (kernel_data.integrator.volume_decoupled) {
+ /* cache steps along volume for repeated sampling */
+ VolumeSegment volume_segment;
+
+ shader_setup_from_volume(kg, sd, &volume_ray);
+ kernel_volume_decoupled_record(kg, state, &volume_ray, sd, &volume_segment, heterogeneous);
+
+ /* direct light sampling */
+ if (volume_segment.closure_flag & SD_SCATTER) {
+ volume_segment.sampling_method = volume_stack_sampling_method(kg, state->volume_stack);
+
+ int all = kernel_data.integrator.sample_all_lights_direct;
+
+ kernel_branched_path_volume_connect_light(
+ kg, sd, emission_sd, *throughput, state, L, all, &volume_ray, &volume_segment);
+
+ /* indirect light sampling */
+ int num_samples = kernel_data.integrator.volume_samples;
+ float num_samples_inv = 1.0f / num_samples;
+
+ for (int j = 0; j < num_samples; j++) {
+ PathState ps = *state;
+ Ray pray = *ray;
+ float3 tp = *throughput;
+
+ /* branch RNG state */
+ path_state_branch(&ps, j, num_samples);
+
+ /* scatter sample. if we use distance sampling and take just one
+ * sample for direct and indirect light, we could share this
+ * computation, but makes code a bit complex */
+ float rphase = path_state_rng_1D(kg, &ps, PRNG_PHASE_CHANNEL);
+ float rscatter = path_state_rng_1D(kg, &ps, PRNG_SCATTER_DISTANCE);
+
+ VolumeIntegrateResult result = kernel_volume_decoupled_scatter(
+ kg, &ps, &pray, sd, &tp, rphase, rscatter, &volume_segment, NULL, false);
+
+ if (result == VOLUME_PATH_SCATTERED &&
+ kernel_path_volume_bounce(kg, sd, &tp, &ps, &L->state, &pray)) {
+ kernel_path_indirect(kg, indirect_sd, emission_sd, &pray, tp * num_samples_inv, &ps, L);
+
+ /* for render passes, sum and reset indirect light pass variables
+ * for the next samples */
+ path_radiance_sum_indirect(L);
+ path_radiance_reset_indirect(L);
+ }
+ }
+ }
+
+ /* emission and transmittance */
+ if (volume_segment.closure_flag & SD_EMISSION)
+ path_radiance_accum_emission(L, state, *throughput, volume_segment.accum_emission);
+ *throughput *= volume_segment.accum_transmittance;
+
+ /* free cached steps */
+ kernel_volume_decoupled_free(kg, &volume_segment);
+ }
+ else
+# endif /* __VOLUME_DECOUPLED__ */
+ {
+ /* GPU: no decoupled ray marching, scatter probalistically */
+ int num_samples = kernel_data.integrator.volume_samples;
+ float num_samples_inv = 1.0f / num_samples;
+
+ /* todo: we should cache the shader evaluations from stepping
+ * through the volume, for now we redo them multiple times */
+
+ for (int j = 0; j < num_samples; j++) {
+ PathState ps = *state;
+ Ray pray = *ray;
+ float3 tp = (*throughput) * num_samples_inv;
+
+ /* branch RNG state */
+ path_state_branch(&ps, j, num_samples);
+
+ VolumeIntegrateResult result = kernel_volume_integrate(
+ kg, &ps, sd, &volume_ray, L, &tp, heterogeneous);
+
+# ifdef __VOLUME_SCATTER__
+ if (result == VOLUME_PATH_SCATTERED) {
+ /* todo: support equiangular, MIS and all light sampling.
+ * alternatively get decoupled ray marching working on the GPU */
+ kernel_path_volume_connect_light(kg, sd, emission_sd, tp, state, L);
+
+ if (kernel_path_volume_bounce(kg, sd, &tp, &ps, &L->state, &pray)) {
+ kernel_path_indirect(kg, indirect_sd, emission_sd, &pray, tp, &ps, L);
+
+ /* for render passes, sum and reset indirect light pass variables
+ * for the next samples */
+ path_radiance_sum_indirect(L);
+ path_radiance_reset_indirect(L);
+ }
+ }
+# endif /* __VOLUME_SCATTER__ */
+ }
+
+ /* todo: avoid this calculation using decoupled ray marching */
+ kernel_volume_shadow(kg, emission_sd, state, &volume_ray, throughput);
+ }
}
-#endif /* __VOLUME__ */
+# endif /* __VOLUME__ */
/* bounce off surface and integrate indirect light */
ccl_device_noinline void kernel_branched_path_surface_indirect_light(KernelGlobals *kg,
- ShaderData *sd, ShaderData *indirect_sd, ShaderData *emission_sd,
- float3 throughput, float num_samples_adjust, PathState *state, PathRadiance *L)
+ ShaderData *sd,
+ ShaderData *indirect_sd,
+ ShaderData *emission_sd,
+ float3 throughput,
+ float num_samples_adjust,
+ PathState *state,
+ PathRadiance *L)
{
- float sum_sample_weight = 0.0f;
-#ifdef __DENOISING_FEATURES__
- if(state->denoising_feature_weight > 0.0f) {
- for(int i = 0; i < sd->num_closure; i++) {
- const ShaderClosure *sc = &sd->closure[i];
-
- /* transparency is not handled here, but in outer loop */
- if(!CLOSURE_IS_BSDF(sc->type) || CLOSURE_IS_BSDF_TRANSPARENT(sc->type)) {
- continue;
- }
-
- sum_sample_weight += sc->sample_weight;
- }
- }
- else {
- sum_sample_weight = 1.0f;
- }
-#endif /* __DENOISING_FEATURES__ */
-
- for(int i = 0; i < sd->num_closure; i++) {
- const ShaderClosure *sc = &sd->closure[i];
-
- /* transparency is not handled here, but in outer loop */
- if(!CLOSURE_IS_BSDF(sc->type) || CLOSURE_IS_BSDF_TRANSPARENT(sc->type)) {
- 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;
-
- for(int j = 0; j < num_samples; j++) {
- PathState ps = *state;
- float3 tp = throughput;
- Ray bsdf_ray;
-#ifdef __SHADOW_TRICKS__
- float shadow_transparency = L->shadow_transparency;
-#endif
-
- ps.rng_hash = cmj_hash(state->rng_hash, i);
-
- if(!kernel_branched_path_surface_bounce(kg,
- sd,
- sc,
- j,
- num_samples,
- &tp,
- &ps,
- &L->state,
- &bsdf_ray,
- sum_sample_weight))
- {
- continue;
- }
-
- ps.rng_hash = state->rng_hash;
-
- kernel_path_indirect(kg,
- indirect_sd,
- emission_sd,
- &bsdf_ray,
- tp*num_samples_inv,
- &ps,
- L);
-
- /* for render passes, sum and reset indirect light pass variables
- * for the next samples */
- path_radiance_sum_indirect(L);
- path_radiance_reset_indirect(L);
-
-#ifdef __SHADOW_TRICKS__
- L->shadow_transparency = shadow_transparency;
-#endif
- }
- }
+ float sum_sample_weight = 0.0f;
+# ifdef __DENOISING_FEATURES__
+ if (state->denoising_feature_weight > 0.0f) {
+ for (int i = 0; i < sd->num_closure; i++) {
+ const ShaderClosure *sc = &sd->closure[i];
+
+ /* transparency is not handled here, but in outer loop */
+ if (!CLOSURE_IS_BSDF(sc->type) || CLOSURE_IS_BSDF_TRANSPARENT(sc->type)) {
+ continue;
+ }
+
+ sum_sample_weight += sc->sample_weight;
+ }
+ }
+ else {
+ sum_sample_weight = 1.0f;
+ }
+# endif /* __DENOISING_FEATURES__ */
+
+ for (int i = 0; i < sd->num_closure; i++) {
+ const ShaderClosure *sc = &sd->closure[i];
+
+ /* transparency is not handled here, but in outer loop */
+ if (!CLOSURE_IS_BSDF(sc->type) || CLOSURE_IS_BSDF_TRANSPARENT(sc->type)) {
+ 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;
+
+ for (int j = 0; j < num_samples; j++) {
+ PathState ps = *state;
+ float3 tp = throughput;
+ Ray bsdf_ray;
+# ifdef __SHADOW_TRICKS__
+ float shadow_transparency = L->shadow_transparency;
+# endif
+
+ ps.rng_hash = cmj_hash(state->rng_hash, i);
+
+ if (!kernel_branched_path_surface_bounce(
+ kg, sd, sc, j, num_samples, &tp, &ps, &L->state, &bsdf_ray, sum_sample_weight)) {
+ continue;
+ }
+
+ ps.rng_hash = state->rng_hash;
+
+ kernel_path_indirect(kg, indirect_sd, emission_sd, &bsdf_ray, tp * num_samples_inv, &ps, L);
+
+ /* for render passes, sum and reset indirect light pass variables
+ * for the next samples */
+ path_radiance_sum_indirect(L);
+ path_radiance_reset_indirect(L);
+
+# ifdef __SHADOW_TRICKS__
+ L->shadow_transparency = shadow_transparency;
+# endif
+ }
+ }
}
-#ifdef __SUBSURFACE__
+# ifdef __SUBSURFACE__
ccl_device void kernel_branched_path_subsurface_scatter(KernelGlobals *kg,
ShaderData *sd,
ShaderData *indirect_sd,
@@ -325,111 +290,81 @@ ccl_device void kernel_branched_path_subsurface_scatter(KernelGlobals *kg,
Ray *ray,
float3 throughput)
{
- for(int i = 0; i < sd->num_closure; i++) {
- ShaderClosure *sc = &sd->closure[i];
-
- if(!CLOSURE_IS_BSSRDF(sc->type))
- continue;
-
- /* set up random number generator */
- uint lcg_state = lcg_state_init(state, 0x68bc21eb);
- int num_samples = kernel_data.integrator.subsurface_samples * 3;
- float num_samples_inv = 1.0f/num_samples;
- uint bssrdf_rng_hash = cmj_hash(state->rng_hash, i);
-
- /* do subsurface scatter step with copy of shader data, this will
- * replace the BSSRDF with a diffuse BSDF closure */
- for(int j = 0; j < num_samples; j++) {
- PathState hit_state = *state;
- path_state_branch(&hit_state, j, num_samples);
- hit_state.rng_hash = bssrdf_rng_hash;
-
- LocalIntersection ss_isect;
- float bssrdf_u, bssrdf_v;
- path_state_rng_2D(kg, &hit_state, PRNG_BSDF_U, &bssrdf_u, &bssrdf_v);
- int num_hits = subsurface_scatter_multi_intersect(kg,
- &ss_isect,
- sd,
- &hit_state,
- sc,
- &lcg_state,
- bssrdf_u, bssrdf_v,
- true);
-
- hit_state.rng_offset += PRNG_BOUNCE_NUM;
-
-#ifdef __VOLUME__
- Ray volume_ray = *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 = 0; hit < num_hits; hit++) {
- ShaderData bssrdf_sd = *sd;
- Bssrdf *bssrdf = (Bssrdf *)sc;
- ClosureType bssrdf_type = sc->type;
- float bssrdf_roughness = bssrdf->roughness;
- subsurface_scatter_multi_setup(kg,
- &ss_isect,
- hit,
- &bssrdf_sd,
- &hit_state,
- bssrdf_type,
- bssrdf_roughness);
-
-#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);
-
- for(int k = 0; k < VOLUME_STACK_SIZE; k++) {
- hit_state.volume_stack[k] = state->volume_stack[k];
- }
-
- kernel_volume_stack_update_for_subsurface(
- kg,
- emission_sd,
- &volume_ray,
- hit_state.volume_stack);
- }
-#endif /* __VOLUME__ */
-
-#ifdef __EMISSION__
- /* direct light */
- if(kernel_data.integrator.use_direct_light) {
- int all = (kernel_data.integrator.sample_all_lights_direct) ||
- (hit_state.flag & PATH_RAY_SHADOW_CATCHER);
- kernel_branched_path_surface_connect_light(
- kg,
- &bssrdf_sd,
- emission_sd,
- &hit_state,
- throughput,
- num_samples_inv,
- L,
- all);
- }
-#endif /* __EMISSION__ */
-
- /* indirect light */
- kernel_branched_path_surface_indirect_light(
- kg,
- &bssrdf_sd,
- indirect_sd,
- emission_sd,
- throughput,
- num_samples_inv,
- &hit_state,
- L);
- }
- }
- }
+ for (int i = 0; i < sd->num_closure; i++) {
+ ShaderClosure *sc = &sd->closure[i];
+
+ if (!CLOSURE_IS_BSSRDF(sc->type))
+ continue;
+
+ /* set up random number generator */
+ uint lcg_state = lcg_state_init(state, 0x68bc21eb);
+ int num_samples = kernel_data.integrator.subsurface_samples * 3;
+ float num_samples_inv = 1.0f / num_samples;
+ uint bssrdf_rng_hash = cmj_hash(state->rng_hash, i);
+
+ /* do subsurface scatter step with copy of shader data, this will
+ * replace the BSSRDF with a diffuse BSDF closure */
+ for (int j = 0; j < num_samples; j++) {
+ PathState hit_state = *state;
+ path_state_branch(&hit_state, j, num_samples);
+ hit_state.rng_hash = bssrdf_rng_hash;
+
+ LocalIntersection ss_isect;
+ float bssrdf_u, bssrdf_v;
+ path_state_rng_2D(kg, &hit_state, PRNG_BSDF_U, &bssrdf_u, &bssrdf_v);
+ int num_hits = subsurface_scatter_multi_intersect(
+ kg, &ss_isect, sd, &hit_state, sc, &lcg_state, bssrdf_u, bssrdf_v, true);
+
+ hit_state.rng_offset += PRNG_BOUNCE_NUM;
+
+# ifdef __VOLUME__
+ Ray volume_ray = *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 = 0; hit < num_hits; hit++) {
+ ShaderData bssrdf_sd = *sd;
+ Bssrdf *bssrdf = (Bssrdf *)sc;
+ ClosureType bssrdf_type = sc->type;
+ float bssrdf_roughness = bssrdf->roughness;
+ subsurface_scatter_multi_setup(
+ kg, &ss_isect, hit, &bssrdf_sd, &hit_state, bssrdf_type, bssrdf_roughness);
+
+# 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);
+
+ for (int k = 0; k < VOLUME_STACK_SIZE; k++) {
+ hit_state.volume_stack[k] = state->volume_stack[k];
+ }
+
+ kernel_volume_stack_update_for_subsurface(
+ kg, emission_sd, &volume_ray, hit_state.volume_stack);
+ }
+# endif /* __VOLUME__ */
+
+# ifdef __EMISSION__
+ /* direct light */
+ if (kernel_data.integrator.use_direct_light) {
+ int all = (kernel_data.integrator.sample_all_lights_direct) ||
+ (hit_state.flag & PATH_RAY_SHADOW_CATCHER);
+ kernel_branched_path_surface_connect_light(
+ kg, &bssrdf_sd, emission_sd, &hit_state, throughput, num_samples_inv, L, all);
+ }
+# endif /* __EMISSION__ */
+
+ /* indirect light */
+ kernel_branched_path_surface_indirect_light(
+ kg, &bssrdf_sd, indirect_sd, emission_sd, throughput, num_samples_inv, &hit_state, L);
+ }
+ }
+ }
}
-#endif /* __SUBSURFACE__ */
+# endif /* __SUBSURFACE__ */
ccl_device void kernel_branched_path_integrate(KernelGlobals *kg,
uint rng_hash,
@@ -438,188 +373,171 @@ ccl_device void kernel_branched_path_integrate(KernelGlobals *kg,
ccl_global float *buffer,
PathRadiance *L)
{
- /* initialize */
- float3 throughput = make_float3(1.0f, 1.0f, 1.0f);
-
- path_radiance_init(L, kernel_data.film.use_light_pass);
-
- /* shader data memory used for both volumes and surfaces, saves stack space */
- ShaderData sd;
- /* shader data used by emission, shadows, volume stacks, indirect path */
- ShaderDataTinyStorage emission_sd_storage;
- ShaderData *emission_sd = AS_SHADER_DATA(&emission_sd_storage);
- ShaderData indirect_sd;
-
- PathState state;
- path_state_init(kg, emission_sd, &state, rng_hash, sample, &ray);
-
- /* Main Loop
- * Here we only handle transparency intersections from the camera ray.
- * Indirect bounces are handled in kernel_branched_path_surface_indirect_light().
- */
- for(;;) {
- /* Find intersection with objects in scene. */
- Intersection isect;
- bool hit = kernel_path_scene_intersect(kg, &state, &ray, &isect, L);
-
-#ifdef __VOLUME__
- /* Volume integration. */
- kernel_branched_path_volume(kg,
- &sd,
- &state,
- &ray,
- &throughput,
- &isect,
- hit,
- &indirect_sd,
- emission_sd,
- L);
-#endif /* __VOLUME__ */
-
- /* Shade background. */
- if(!hit) {
- kernel_path_background(kg, &state, &ray, throughput, &sd, L);
- break;
- }
-
- /* Setup and evaluate shader. */
- shader_setup_from_ray(kg, &sd, &isect, &ray);
-
- /* Skip most work for volume bounding surface. */
-#ifdef __VOLUME__
- if(!(sd.flag & SD_HAS_ONLY_VOLUME)) {
-#endif
-
- shader_eval_surface(kg, &sd, &state, state.flag);
- shader_merge_closures(&sd);
-
- /* Apply shadow catcher, holdout, emission. */
- if(!kernel_path_shader_apply(kg,
- &sd,
- &state,
- &ray,
- throughput,
- emission_sd,
- L,
- buffer))
- {
- break;
- }
-
- /* transparency termination */
- if(state.flag & PATH_RAY_TRANSPARENT) {
- /* path termination. this is a strange place to put the termination, it's
- * 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 */
- float probability = path_state_continuation_probability(kg, &state, throughput);
-
- if(probability == 0.0f) {
- break;
- }
- else if(probability != 1.0f) {
- float terminate = path_state_rng_1D(kg, &state, PRNG_TERMINATE);
-
- if(terminate >= probability)
- break;
-
- throughput /= probability;
- }
- }
-
- kernel_update_denoising_features(kg, &sd, &state, L);
-
-#ifdef __AO__
- /* ambient occlusion */
- if(kernel_data.integrator.use_ambient_occlusion) {
- kernel_branched_path_ao(kg, &sd, emission_sd, L, &state, throughput);
- }
-#endif /* __AO__ */
-
-#ifdef __SUBSURFACE__
- /* bssrdf scatter to a different location on the same object */
- if(sd.flag & SD_BSSRDF) {
- kernel_branched_path_subsurface_scatter(kg, &sd, &indirect_sd, emission_sd,
- L, &state, &ray, throughput);
- }
-#endif /* __SUBSURFACE__ */
-
- PathState hit_state = state;
-
-#ifdef __EMISSION__
- /* direct light */
- if(kernel_data.integrator.use_direct_light) {
- int all = (kernel_data.integrator.sample_all_lights_direct) ||
- (state.flag & PATH_RAY_SHADOW_CATCHER);
- kernel_branched_path_surface_connect_light(kg,
- &sd, emission_sd, &hit_state, throughput, 1.0f, L, all);
- }
-#endif /* __EMISSION__ */
-
- /* indirect light */
- kernel_branched_path_surface_indirect_light(kg,
- &sd, &indirect_sd, emission_sd, throughput, 1.0f, &hit_state, L);
-
- /* continue in case of transparency */
- throughput *= shader_bsdf_transparency(kg, &sd);
-
- if(is_zero(throughput))
- break;
-
- /* Update Path State */
- path_state_next(kg, &state, LABEL_TRANSPARENT);
-
-#ifdef __VOLUME__
- }
- else {
- if(!path_state_volume_next(kg, &state)) {
- break;
- }
- }
-#endif
-
- 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__ */
- }
+ /* initialize */
+ float3 throughput = make_float3(1.0f, 1.0f, 1.0f);
+
+ path_radiance_init(L, kernel_data.film.use_light_pass);
+
+ /* shader data memory used for both volumes and surfaces, saves stack space */
+ ShaderData sd;
+ /* shader data used by emission, shadows, volume stacks, indirect path */
+ ShaderDataTinyStorage emission_sd_storage;
+ ShaderData *emission_sd = AS_SHADER_DATA(&emission_sd_storage);
+ ShaderData indirect_sd;
+
+ PathState state;
+ path_state_init(kg, emission_sd, &state, rng_hash, sample, &ray);
+
+ /* Main Loop
+ * Here we only handle transparency intersections from the camera ray.
+ * Indirect bounces are handled in kernel_branched_path_surface_indirect_light().
+ */
+ for (;;) {
+ /* Find intersection with objects in scene. */
+ Intersection isect;
+ bool hit = kernel_path_scene_intersect(kg, &state, &ray, &isect, L);
+
+# ifdef __VOLUME__
+ /* Volume integration. */
+ kernel_branched_path_volume(
+ kg, &sd, &state, &ray, &throughput, &isect, hit, &indirect_sd, emission_sd, L);
+# endif /* __VOLUME__ */
+
+ /* Shade background. */
+ if (!hit) {
+ kernel_path_background(kg, &state, &ray, throughput, &sd, L);
+ break;
+ }
+
+ /* Setup and evaluate shader. */
+ shader_setup_from_ray(kg, &sd, &isect, &ray);
+
+ /* Skip most work for volume bounding surface. */
+# ifdef __VOLUME__
+ if (!(sd.flag & SD_HAS_ONLY_VOLUME)) {
+# endif
+
+ shader_eval_surface(kg, &sd, &state, state.flag);
+ shader_merge_closures(&sd);
+
+ /* Apply shadow catcher, holdout, emission. */
+ if (!kernel_path_shader_apply(kg, &sd, &state, &ray, throughput, emission_sd, L, buffer)) {
+ break;
+ }
+
+ /* transparency termination */
+ if (state.flag & PATH_RAY_TRANSPARENT) {
+ /* path termination. this is a strange place to put the termination, it's
+ * 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 */
+ float probability = path_state_continuation_probability(kg, &state, throughput);
+
+ if (probability == 0.0f) {
+ break;
+ }
+ else if (probability != 1.0f) {
+ float terminate = path_state_rng_1D(kg, &state, PRNG_TERMINATE);
+
+ if (terminate >= probability)
+ break;
+
+ throughput /= probability;
+ }
+ }
+
+ kernel_update_denoising_features(kg, &sd, &state, L);
+
+# ifdef __AO__
+ /* ambient occlusion */
+ if (kernel_data.integrator.use_ambient_occlusion) {
+ kernel_branched_path_ao(kg, &sd, emission_sd, L, &state, throughput);
+ }
+# endif /* __AO__ */
+
+# ifdef __SUBSURFACE__
+ /* bssrdf scatter to a different location on the same object */
+ if (sd.flag & SD_BSSRDF) {
+ kernel_branched_path_subsurface_scatter(
+ kg, &sd, &indirect_sd, emission_sd, L, &state, &ray, throughput);
+ }
+# endif /* __SUBSURFACE__ */
+
+ PathState hit_state = state;
+
+# ifdef __EMISSION__
+ /* direct light */
+ if (kernel_data.integrator.use_direct_light) {
+ int all = (kernel_data.integrator.sample_all_lights_direct) ||
+ (state.flag & PATH_RAY_SHADOW_CATCHER);
+ kernel_branched_path_surface_connect_light(
+ kg, &sd, emission_sd, &hit_state, throughput, 1.0f, L, all);
+ }
+# endif /* __EMISSION__ */
+
+ /* indirect light */
+ kernel_branched_path_surface_indirect_light(
+ kg, &sd, &indirect_sd, emission_sd, throughput, 1.0f, &hit_state, L);
+
+ /* continue in case of transparency */
+ throughput *= shader_bsdf_transparency(kg, &sd);
+
+ if (is_zero(throughput))
+ break;
+
+ /* Update Path State */
+ path_state_next(kg, &state, LABEL_TRANSPARENT);
+
+# ifdef __VOLUME__
+ }
+ else {
+ if (!path_state_volume_next(kg, &state)) {
+ break;
+ }
+ }
+# endif
+
+ 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__ */
+ }
}
-ccl_device void kernel_branched_path_trace(KernelGlobals *kg,
- ccl_global float *buffer,
- int sample, int x, int y, int offset, int stride)
+ccl_device void kernel_branched_path_trace(
+ KernelGlobals *kg, ccl_global float *buffer, int sample, int x, int y, int offset, int stride)
{
- /* buffer offset */
- int index = offset + x + y*stride;
- int pass_stride = kernel_data.film.pass_stride;
+ /* buffer offset */
+ int index = offset + x + y * stride;
+ int pass_stride = kernel_data.film.pass_stride;
- buffer += index*pass_stride;
+ buffer += index * pass_stride;
- /* initialize random numbers and ray */
- uint rng_hash;
- Ray ray;
+ /* initialize random numbers and ray */
+ uint rng_hash;
+ Ray ray;
- kernel_path_trace_setup(kg, sample, x, y, &rng_hash, &ray);
+ kernel_path_trace_setup(kg, sample, x, y, &rng_hash, &ray);
- /* integrate */
- PathRadiance L;
+ /* integrate */
+ PathRadiance L;
- if(ray.t != 0.0f) {
- kernel_branched_path_integrate(kg, rng_hash, sample, ray, buffer, &L);
- kernel_write_result(kg, buffer, sample, &L);
- }
+ if (ray.t != 0.0f) {
+ kernel_branched_path_integrate(kg, rng_hash, sample, ray, buffer, &L);
+ kernel_write_result(kg, buffer, sample, &L);
+ }
}
-#endif /* __SPLIT_KERNEL__ */
+# endif /* __SPLIT_KERNEL__ */
-#endif /* __BRANCHED_PATH__ */
+#endif /* __BRANCHED_PATH__ */
CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/kernel_path_common.h b/intern/cycles/kernel/kernel_path_common.h
index d83fd474cde..815767595a9 100644
--- a/intern/cycles/kernel/kernel_path_common.h
+++ b/intern/cycles/kernel/kernel_path_common.h
@@ -18,34 +18,31 @@
CCL_NAMESPACE_BEGIN
-ccl_device_inline void kernel_path_trace_setup(KernelGlobals *kg,
- int sample,
- int x, int y,
- uint *rng_hash,
- ccl_addr_space Ray *ray)
+ccl_device_inline void kernel_path_trace_setup(
+ KernelGlobals *kg, int sample, int x, int y, uint *rng_hash, ccl_addr_space Ray *ray)
{
- float filter_u;
- float filter_v;
+ float filter_u;
+ float filter_v;
- int num_samples = kernel_data.integrator.aa_samples;
+ int num_samples = kernel_data.integrator.aa_samples;
- path_rng_init(kg, sample, num_samples, rng_hash, x, y, &filter_u, &filter_v);
+ path_rng_init(kg, sample, num_samples, rng_hash, x, y, &filter_u, &filter_v);
- /* sample camera ray */
+ /* sample camera ray */
- float lens_u = 0.0f, lens_v = 0.0f;
+ float lens_u = 0.0f, lens_v = 0.0f;
- if(kernel_data.cam.aperturesize > 0.0f)
- path_rng_2D(kg, *rng_hash, sample, num_samples, PRNG_LENS_U, &lens_u, &lens_v);
+ if (kernel_data.cam.aperturesize > 0.0f)
+ path_rng_2D(kg, *rng_hash, sample, num_samples, PRNG_LENS_U, &lens_u, &lens_v);
- float time = 0.0f;
+ float time = 0.0f;
#ifdef __CAMERA_MOTION__
- if(kernel_data.cam.shuttertime != -1.0f)
- time = path_rng_1D(kg, *rng_hash, sample, num_samples, PRNG_TIME);
+ if (kernel_data.cam.shuttertime != -1.0f)
+ time = path_rng_1D(kg, *rng_hash, sample, num_samples, PRNG_TIME);
#endif
- camera_sample(kg, x, y, filter_u, filter_v, lens_u, lens_v, time, ray);
+ camera_sample(kg, x, y, filter_u, filter_v, lens_u, lens_v, time, ray);
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/kernel_path_state.h b/intern/cycles/kernel/kernel_path_state.h
index e85050df4bb..cdca0b1f9bf 100644
--- a/intern/cycles/kernel/kernel_path_state.h
+++ b/intern/cycles/kernel/kernel_path_state.h
@@ -23,249 +23,252 @@ ccl_device_inline void path_state_init(KernelGlobals *kg,
int sample,
ccl_addr_space Ray *ray)
{
- state->flag = PATH_RAY_CAMERA|PATH_RAY_MIS_SKIP|PATH_RAY_TRANSPARENT_BACKGROUND;
+ state->flag = PATH_RAY_CAMERA | PATH_RAY_MIS_SKIP | PATH_RAY_TRANSPARENT_BACKGROUND;
- state->rng_hash = rng_hash;
- state->rng_offset = PRNG_BASE_NUM;
- state->sample = sample;
- state->num_samples = kernel_data.integrator.aa_samples;
- state->branch_factor = 1.0f;
+ state->rng_hash = rng_hash;
+ state->rng_offset = PRNG_BASE_NUM;
+ state->sample = sample;
+ state->num_samples = kernel_data.integrator.aa_samples;
+ state->branch_factor = 1.0f;
- state->bounce = 0;
- state->diffuse_bounce = 0;
- state->glossy_bounce = 0;
- state->transmission_bounce = 0;
- state->transparent_bounce = 0;
+ state->bounce = 0;
+ state->diffuse_bounce = 0;
+ state->glossy_bounce = 0;
+ state->transmission_bounce = 0;
+ state->transparent_bounce = 0;
#ifdef __DENOISING_FEATURES__
- if(kernel_data.film.pass_denoising_data) {
- state->flag |= PATH_RAY_STORE_SHADOW_INFO;
- state->denoising_feature_weight = 1.0f;
- }
- else {
- state->denoising_feature_weight = 0.0f;
- }
-#endif /* __DENOISING_FEATURES__ */
-
- state->min_ray_pdf = FLT_MAX;
- state->ray_pdf = 0.0f;
+ if (kernel_data.film.pass_denoising_data) {
+ state->flag |= PATH_RAY_STORE_SHADOW_INFO;
+ state->denoising_feature_weight = 1.0f;
+ }
+ else {
+ state->denoising_feature_weight = 0.0f;
+ }
+#endif /* __DENOISING_FEATURES__ */
+
+ state->min_ray_pdf = FLT_MAX;
+ state->ray_pdf = 0.0f;
#ifdef __LAMP_MIS__
- state->ray_t = 0.0f;
+ state->ray_t = 0.0f;
#endif
#ifdef __VOLUME__
- state->volume_bounce = 0;
- state->volume_bounds_bounce = 0;
-
- if(kernel_data.integrator.use_volumes) {
- /* Initialize volume stack with volume we are inside of. */
- kernel_volume_stack_init(kg, stack_sd, state, ray, state->volume_stack);
- }
- else {
- state->volume_stack[0].shader = SHADER_NONE;
- }
+ state->volume_bounce = 0;
+ state->volume_bounds_bounce = 0;
+
+ if (kernel_data.integrator.use_volumes) {
+ /* Initialize volume stack with volume we are inside of. */
+ kernel_volume_stack_init(kg, stack_sd, state, ray, state->volume_stack);
+ }
+ else {
+ state->volume_stack[0].shader = SHADER_NONE;
+ }
#endif
}
-ccl_device_inline void path_state_next(KernelGlobals *kg, ccl_addr_space PathState *state, int label)
+ccl_device_inline void path_state_next(KernelGlobals *kg,
+ ccl_addr_space PathState *state,
+ int label)
{
- /* ray through transparent keeps same flags from previous ray and is
- * not counted as a regular bounce, transparent has separate max */
- if(label & LABEL_TRANSPARENT) {
- state->flag |= PATH_RAY_TRANSPARENT;
- state->transparent_bounce++;
- if(state->transparent_bounce >= kernel_data.integrator.transparent_max_bounce) {
- state->flag |= PATH_RAY_TERMINATE_IMMEDIATE;
- }
+ /* ray through transparent keeps same flags from previous ray and is
+ * not counted as a regular bounce, transparent has separate max */
+ if (label & LABEL_TRANSPARENT) {
+ state->flag |= PATH_RAY_TRANSPARENT;
+ state->transparent_bounce++;
+ if (state->transparent_bounce >= kernel_data.integrator.transparent_max_bounce) {
+ state->flag |= PATH_RAY_TERMINATE_IMMEDIATE;
+ }
- if(!kernel_data.integrator.transparent_shadows)
- state->flag |= PATH_RAY_MIS_SKIP;
+ if (!kernel_data.integrator.transparent_shadows)
+ state->flag |= PATH_RAY_MIS_SKIP;
- /* random number generator next bounce */
- state->rng_offset += PRNG_BOUNCE_NUM;
+ /* random number generator next bounce */
+ state->rng_offset += PRNG_BOUNCE_NUM;
- return;
- }
+ return;
+ }
- state->bounce++;
- if(state->bounce >= kernel_data.integrator.max_bounce) {
- state->flag |= PATH_RAY_TERMINATE_AFTER_TRANSPARENT;
- }
+ state->bounce++;
+ if (state->bounce >= kernel_data.integrator.max_bounce) {
+ state->flag |= PATH_RAY_TERMINATE_AFTER_TRANSPARENT;
+ }
- state->flag &= ~(PATH_RAY_ALL_VISIBILITY|PATH_RAY_MIS_SKIP);
+ state->flag &= ~(PATH_RAY_ALL_VISIBILITY | PATH_RAY_MIS_SKIP);
#ifdef __VOLUME__
- if(label & LABEL_VOLUME_SCATTER) {
- /* volume scatter */
- state->flag |= PATH_RAY_VOLUME_SCATTER;
- state->flag &= ~PATH_RAY_TRANSPARENT_BACKGROUND;
-
- state->volume_bounce++;
- if(state->volume_bounce >= kernel_data.integrator.max_volume_bounce) {
- state->flag |= PATH_RAY_TERMINATE_AFTER_TRANSPARENT;
- }
- }
- else
+ if (label & LABEL_VOLUME_SCATTER) {
+ /* volume scatter */
+ state->flag |= PATH_RAY_VOLUME_SCATTER;
+ state->flag &= ~PATH_RAY_TRANSPARENT_BACKGROUND;
+
+ state->volume_bounce++;
+ if (state->volume_bounce >= kernel_data.integrator.max_volume_bounce) {
+ state->flag |= PATH_RAY_TERMINATE_AFTER_TRANSPARENT;
+ }
+ }
+ else
#endif
- {
- /* surface reflection/transmission */
- if(label & LABEL_REFLECT) {
- state->flag |= PATH_RAY_REFLECT;
- state->flag &= ~PATH_RAY_TRANSPARENT_BACKGROUND;
-
- if(label & LABEL_DIFFUSE) {
- state->diffuse_bounce++;
- if(state->diffuse_bounce >= kernel_data.integrator.max_diffuse_bounce) {
- state->flag |= PATH_RAY_TERMINATE_AFTER_TRANSPARENT;
- }
- }
- else {
- state->glossy_bounce++;
- if(state->glossy_bounce >= kernel_data.integrator.max_glossy_bounce) {
- state->flag |= PATH_RAY_TERMINATE_AFTER_TRANSPARENT;
- }
- }
- }
- else {
- kernel_assert(label & LABEL_TRANSMIT);
-
- state->flag |= PATH_RAY_TRANSMIT;
-
- if(!(label & LABEL_TRANSMIT_TRANSPARENT)) {
- state->flag &= ~PATH_RAY_TRANSPARENT_BACKGROUND;
- }
-
- state->transmission_bounce++;
- if(state->transmission_bounce >= kernel_data.integrator.max_transmission_bounce) {
- state->flag |= PATH_RAY_TERMINATE_AFTER_TRANSPARENT;
- }
- }
-
- /* diffuse/glossy/singular */
- if(label & LABEL_DIFFUSE) {
- state->flag |= PATH_RAY_DIFFUSE|PATH_RAY_DIFFUSE_ANCESTOR;
- }
- else if(label & LABEL_GLOSSY) {
- state->flag |= PATH_RAY_GLOSSY;
- }
- else {
- kernel_assert(label & LABEL_SINGULAR);
- state->flag |= PATH_RAY_GLOSSY|PATH_RAY_SINGULAR|PATH_RAY_MIS_SKIP;
- }
- }
-
- /* random number generator next bounce */
- state->rng_offset += PRNG_BOUNCE_NUM;
+ {
+ /* surface reflection/transmission */
+ if (label & LABEL_REFLECT) {
+ state->flag |= PATH_RAY_REFLECT;
+ state->flag &= ~PATH_RAY_TRANSPARENT_BACKGROUND;
+
+ if (label & LABEL_DIFFUSE) {
+ state->diffuse_bounce++;
+ if (state->diffuse_bounce >= kernel_data.integrator.max_diffuse_bounce) {
+ state->flag |= PATH_RAY_TERMINATE_AFTER_TRANSPARENT;
+ }
+ }
+ else {
+ state->glossy_bounce++;
+ if (state->glossy_bounce >= kernel_data.integrator.max_glossy_bounce) {
+ state->flag |= PATH_RAY_TERMINATE_AFTER_TRANSPARENT;
+ }
+ }
+ }
+ else {
+ kernel_assert(label & LABEL_TRANSMIT);
+
+ state->flag |= PATH_RAY_TRANSMIT;
+
+ if (!(label & LABEL_TRANSMIT_TRANSPARENT)) {
+ state->flag &= ~PATH_RAY_TRANSPARENT_BACKGROUND;
+ }
+
+ state->transmission_bounce++;
+ if (state->transmission_bounce >= kernel_data.integrator.max_transmission_bounce) {
+ state->flag |= PATH_RAY_TERMINATE_AFTER_TRANSPARENT;
+ }
+ }
+
+ /* diffuse/glossy/singular */
+ if (label & LABEL_DIFFUSE) {
+ state->flag |= PATH_RAY_DIFFUSE | PATH_RAY_DIFFUSE_ANCESTOR;
+ }
+ else if (label & LABEL_GLOSSY) {
+ state->flag |= PATH_RAY_GLOSSY;
+ }
+ else {
+ kernel_assert(label & LABEL_SINGULAR);
+ state->flag |= PATH_RAY_GLOSSY | PATH_RAY_SINGULAR | PATH_RAY_MIS_SKIP;
+ }
+ }
+
+ /* random number generator next bounce */
+ state->rng_offset += PRNG_BOUNCE_NUM;
#ifdef __DENOISING_FEATURES__
- if((state->denoising_feature_weight == 0.0f) && !(state->flag & PATH_RAY_SHADOW_CATCHER)) {
- state->flag &= ~PATH_RAY_STORE_SHADOW_INFO;
- }
+ if ((state->denoising_feature_weight == 0.0f) && !(state->flag & PATH_RAY_SHADOW_CATCHER)) {
+ state->flag &= ~PATH_RAY_STORE_SHADOW_INFO;
+ }
#endif
}
#ifdef __VOLUME__
ccl_device_inline bool path_state_volume_next(KernelGlobals *kg, ccl_addr_space PathState *state)
{
- /* For volume bounding meshes we pass through without counting transparent
- * bounces, only sanity check in case self intersection gets us stuck. */
- state->volume_bounds_bounce++;
- if(state->volume_bounds_bounce > VOLUME_BOUNDS_MAX) {
- return false;
- }
-
- /* Random number generator next bounce. */
- if(state->volume_bounds_bounce > 1) {
- state->rng_offset += PRNG_BOUNCE_NUM;
- }
-
- return true;
+ /* For volume bounding meshes we pass through without counting transparent
+ * bounces, only sanity check in case self intersection gets us stuck. */
+ state->volume_bounds_bounce++;
+ if (state->volume_bounds_bounce > VOLUME_BOUNDS_MAX) {
+ return false;
+ }
+
+ /* Random number generator next bounce. */
+ if (state->volume_bounds_bounce > 1) {
+ state->rng_offset += PRNG_BOUNCE_NUM;
+ }
+
+ return true;
}
#endif
-ccl_device_inline uint path_state_ray_visibility(KernelGlobals *kg, ccl_addr_space PathState *state)
+ccl_device_inline uint path_state_ray_visibility(KernelGlobals *kg,
+ ccl_addr_space PathState *state)
{
- uint flag = state->flag & PATH_RAY_ALL_VISIBILITY;
+ uint flag = state->flag & PATH_RAY_ALL_VISIBILITY;
- /* for visibility, diffuse/glossy are for reflection only */
- if(flag & PATH_RAY_TRANSMIT)
- flag &= ~(PATH_RAY_DIFFUSE|PATH_RAY_GLOSSY);
- /* todo: this is not supported as its own ray visibility yet */
- if(state->flag & PATH_RAY_VOLUME_SCATTER)
- flag |= PATH_RAY_DIFFUSE;
+ /* for visibility, diffuse/glossy are for reflection only */
+ if (flag & PATH_RAY_TRANSMIT)
+ flag &= ~(PATH_RAY_DIFFUSE | PATH_RAY_GLOSSY);
+ /* todo: this is not supported as its own ray visibility yet */
+ if (state->flag & PATH_RAY_VOLUME_SCATTER)
+ flag |= PATH_RAY_DIFFUSE;
- return flag;
+ return flag;
}
ccl_device_inline float path_state_continuation_probability(KernelGlobals *kg,
ccl_addr_space PathState *state,
const float3 throughput)
{
- if(state->flag & PATH_RAY_TERMINATE_IMMEDIATE) {
- /* Ray is to be terminated immediately. */
- return 0.0f;
- }
- else if(state->flag & PATH_RAY_TRANSPARENT) {
- /* Do at least one bounce without RR. */
- if(state->transparent_bounce <= 1) {
- return 1.0f;
- }
+ if (state->flag & PATH_RAY_TERMINATE_IMMEDIATE) {
+ /* Ray is to be terminated immediately. */
+ return 0.0f;
+ }
+ else if (state->flag & PATH_RAY_TRANSPARENT) {
+ /* Do at least one bounce without RR. */
+ if (state->transparent_bounce <= 1) {
+ return 1.0f;
+ }
#ifdef __SHADOW_TRICKS__
- /* Exception for shadow catcher not working correctly with RR. */
- else if((state->flag & PATH_RAY_SHADOW_CATCHER) && (state->transparent_bounce <= 8)) {
- return 1.0f;
- }
+ /* Exception for shadow catcher not working correctly with RR. */
+ else if ((state->flag & PATH_RAY_SHADOW_CATCHER) && (state->transparent_bounce <= 8)) {
+ return 1.0f;
+ }
#endif
- }
- else {
- /* Do at least one bounce without RR. */
- if(state->bounce <= 1) {
- return 1.0f;
- }
+ }
+ else {
+ /* Do at least one bounce without RR. */
+ if (state->bounce <= 1) {
+ return 1.0f;
+ }
#ifdef __SHADOW_TRICKS__
- /* Exception for shadow catcher not working correctly with RR. */
- else if((state->flag & PATH_RAY_SHADOW_CATCHER) && (state->bounce <= 3)) {
- return 1.0f;
- }
+ /* Exception for shadow catcher not working correctly with RR. */
+ else if ((state->flag & PATH_RAY_SHADOW_CATCHER) && (state->bounce <= 3)) {
+ return 1.0f;
+ }
#endif
- }
+ }
- /* Probabilistic termination: use sqrt() to roughly match typical view
- * transform and do path termination a bit later on average. */
- return min(sqrtf(max3(fabs(throughput)) * state->branch_factor), 1.0f);
+ /* Probabilistic termination: use sqrt() to roughly match typical view
+ * transform and do path termination a bit later on average. */
+ return min(sqrtf(max3(fabs(throughput)) * state->branch_factor), 1.0f);
}
/* TODO(DingTo): Find more meaningful name for this */
ccl_device_inline void path_state_modify_bounce(ccl_addr_space PathState *state, bool increase)
{
- /* Modify bounce temporarily for shader eval */
- if(increase)
- state->bounce += 1;
- else
- state->bounce -= 1;
+ /* Modify bounce temporarily for shader eval */
+ if (increase)
+ state->bounce += 1;
+ else
+ state->bounce -= 1;
}
ccl_device_inline bool path_state_ao_bounce(KernelGlobals *kg, ccl_addr_space PathState *state)
{
- if(state->bounce <= kernel_data.integrator.ao_bounces) {
- return false;
- }
+ if (state->bounce <= kernel_data.integrator.ao_bounces) {
+ return false;
+ }
- int bounce = state->bounce - state->transmission_bounce - (state->glossy_bounce > 0);
- return (bounce > kernel_data.integrator.ao_bounces);
+ int bounce = state->bounce - state->transmission_bounce - (state->glossy_bounce > 0);
+ return (bounce > kernel_data.integrator.ao_bounces);
}
ccl_device_inline void path_state_branch(ccl_addr_space PathState *state,
int branch,
int num_branches)
{
- if(num_branches > 1) {
- /* Path is splitting into a branch, adjust so that each branch
- * still gets a unique sample from the same sequence. */
- state->sample = state->sample*num_branches + branch;
- state->num_samples = state->num_samples*num_branches;
- state->branch_factor *= num_branches;
- }
+ if (num_branches > 1) {
+ /* Path is splitting into a branch, adjust so that each branch
+ * still gets a unique sample from the same sequence. */
+ state->sample = state->sample * num_branches + branch;
+ state->num_samples = state->num_samples * num_branches;
+ state->branch_factor *= num_branches;
+ }
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/kernel_path_subsurface.h b/intern/cycles/kernel/kernel_path_subsurface.h
index b5a92c74ed5..97d3f292ca3 100644
--- a/intern/cycles/kernel/kernel_path_subsurface.h
+++ b/intern/cycles/kernel/kernel_path_subsurface.h
@@ -22,141 +22,118 @@ ccl_device
# else
ccl_device_inline
# endif
-bool kernel_path_subsurface_scatter(
- KernelGlobals *kg,
- ShaderData *sd,
- ShaderData *emission_sd,
- PathRadiance *L,
- ccl_addr_space PathState *state,
- ccl_addr_space Ray *ray,
- ccl_addr_space float3 *throughput,
- ccl_addr_space SubsurfaceIndirectRays *ss_indirect)
+ bool
+ kernel_path_subsurface_scatter(KernelGlobals *kg,
+ ShaderData *sd,
+ ShaderData *emission_sd,
+ PathRadiance *L,
+ ccl_addr_space PathState *state,
+ ccl_addr_space Ray *ray,
+ ccl_addr_space float3 *throughput,
+ ccl_addr_space SubsurfaceIndirectRays *ss_indirect)
{
- PROFILING_INIT(kg, PROFILING_SUBSURFACE);
-
- float bssrdf_u, bssrdf_v;
- path_state_rng_2D(kg, state, PRNG_BSDF_U, &bssrdf_u, &bssrdf_v);
-
- const ShaderClosure *sc = shader_bssrdf_pick(sd, throughput, &bssrdf_u);
-
- /* do bssrdf scatter step if we picked a bssrdf closure */
- if(sc) {
- /* We should never have two consecutive BSSRDF bounces,
- * the second one should be converted to a diffuse BSDF to
- * avoid this.
- */
- kernel_assert(!(state->flag & PATH_RAY_DIFFUSE_ANCESTOR));
-
- uint lcg_state = lcg_state_init_addrspace(state, 0x68bc21eb);
-
- LocalIntersection ss_isect;
- int num_hits = subsurface_scatter_multi_intersect(kg,
- &ss_isect,
- sd,
- state,
- sc,
- &lcg_state,
- bssrdf_u, bssrdf_v,
- false);
+ PROFILING_INIT(kg, PROFILING_SUBSURFACE);
+
+ float bssrdf_u, bssrdf_v;
+ path_state_rng_2D(kg, state, PRNG_BSDF_U, &bssrdf_u, &bssrdf_v);
+
+ const ShaderClosure *sc = shader_bssrdf_pick(sd, throughput, &bssrdf_u);
+
+ /* do bssrdf scatter step if we picked a bssrdf closure */
+ if (sc) {
+ /* We should never have two consecutive BSSRDF bounces,
+ * the second one should be converted to a diffuse BSDF to
+ * avoid this.
+ */
+ kernel_assert(!(state->flag & PATH_RAY_DIFFUSE_ANCESTOR));
+
+ uint lcg_state = lcg_state_init_addrspace(state, 0x68bc21eb);
+
+ LocalIntersection ss_isect;
+ int num_hits = subsurface_scatter_multi_intersect(
+ kg, &ss_isect, sd, state, sc, &lcg_state, bssrdf_u, bssrdf_v, false);
# ifdef __VOLUME__
- bool need_update_volume_stack =
- kernel_data.integrator.use_volumes &&
- sd->object_flag & SD_OBJECT_INTERSECTS_VOLUME;
-# endif /* __VOLUME__ */
-
- /* Closure memory will be overwritten, so read required variables now. */
- Bssrdf *bssrdf = (Bssrdf *)sc;
- ClosureType bssrdf_type = sc->type;
- float bssrdf_roughness = bssrdf->roughness;
-
- /* compute lighting with the BSDF closure */
- for(int hit = 0; hit < num_hits; hit++) {
- /* NOTE: We reuse the existing ShaderData, we assume the path
- * integration loop stops when this function returns true.
- */
- subsurface_scatter_multi_setup(kg,
- &ss_isect,
- hit,
- sd,
- state,
- bssrdf_type,
- bssrdf_roughness);
-
- kernel_path_surface_connect_light(kg, sd, emission_sd, *throughput, state, L);
-
- ccl_addr_space PathState *hit_state = &ss_indirect->state[ss_indirect->num_rays];
- ccl_addr_space Ray *hit_ray = &ss_indirect->rays[ss_indirect->num_rays];
- ccl_addr_space float3 *hit_tp = &ss_indirect->throughputs[ss_indirect->num_rays];
- PathRadianceState *hit_L_state = &ss_indirect->L_state[ss_indirect->num_rays];
-
- *hit_state = *state;
- *hit_ray = *ray;
- *hit_tp = *throughput;
- *hit_L_state = L->state;
-
- hit_state->rng_offset += PRNG_BOUNCE_NUM;
-
- if(kernel_path_surface_bounce(kg,
- sd,
- hit_tp,
- hit_state,
- hit_L_state,
- hit_ray))
- {
+ bool need_update_volume_stack = kernel_data.integrator.use_volumes &&
+ sd->object_flag & SD_OBJECT_INTERSECTS_VOLUME;
+# endif /* __VOLUME__ */
+
+ /* Closure memory will be overwritten, so read required variables now. */
+ Bssrdf *bssrdf = (Bssrdf *)sc;
+ ClosureType bssrdf_type = sc->type;
+ float bssrdf_roughness = bssrdf->roughness;
+
+ /* compute lighting with the BSDF closure */
+ for (int hit = 0; hit < num_hits; hit++) {
+ /* NOTE: We reuse the existing ShaderData, we assume the path
+ * integration loop stops when this function returns true.
+ */
+ subsurface_scatter_multi_setup(kg, &ss_isect, hit, sd, state, bssrdf_type, bssrdf_roughness);
+
+ kernel_path_surface_connect_light(kg, sd, emission_sd, *throughput, state, L);
+
+ ccl_addr_space PathState *hit_state = &ss_indirect->state[ss_indirect->num_rays];
+ ccl_addr_space Ray *hit_ray = &ss_indirect->rays[ss_indirect->num_rays];
+ ccl_addr_space float3 *hit_tp = &ss_indirect->throughputs[ss_indirect->num_rays];
+ PathRadianceState *hit_L_state = &ss_indirect->L_state[ss_indirect->num_rays];
+
+ *hit_state = *state;
+ *hit_ray = *ray;
+ *hit_tp = *throughput;
+ *hit_L_state = L->state;
+
+ hit_state->rng_offset += PRNG_BOUNCE_NUM;
+
+ if (kernel_path_surface_bounce(kg, sd, hit_tp, hit_state, hit_L_state, hit_ray)) {
# ifdef __LAMP_MIS__
- hit_state->ray_t = 0.0f;
-# endif /* __LAMP_MIS__ */
+ hit_state->ray_t = 0.0f;
+# endif /* __LAMP_MIS__ */
# ifdef __VOLUME__
- if(need_update_volume_stack) {
- Ray volume_ray = *ray;
- /* Setup ray from previous surface point to the new one. */
- volume_ray.D = normalize_len(hit_ray->P - volume_ray.P,
- &volume_ray.t);
-
- kernel_volume_stack_update_for_subsurface(
- kg,
- emission_sd,
- &volume_ray,
- hit_state->volume_stack);
- }
-# endif /* __VOLUME__ */
- ss_indirect->num_rays++;
- }
- }
- return true;
- }
- return false;
+ if (need_update_volume_stack) {
+ Ray volume_ray = *ray;
+ /* Setup ray from previous surface point to the new one. */
+ volume_ray.D = normalize_len(hit_ray->P - volume_ray.P, &volume_ray.t);
+
+ kernel_volume_stack_update_for_subsurface(
+ kg, emission_sd, &volume_ray, hit_state->volume_stack);
+ }
+# endif /* __VOLUME__ */
+ ss_indirect->num_rays++;
+ }
+ }
+ return true;
+ }
+ return false;
}
ccl_device_inline void kernel_path_subsurface_init_indirect(
- ccl_addr_space SubsurfaceIndirectRays *ss_indirect)
+ ccl_addr_space SubsurfaceIndirectRays *ss_indirect)
{
- ss_indirect->num_rays = 0;
+ ss_indirect->num_rays = 0;
}
ccl_device void kernel_path_subsurface_setup_indirect(
- KernelGlobals *kg,
- ccl_addr_space SubsurfaceIndirectRays *ss_indirect,
- ccl_addr_space PathState *state,
- ccl_addr_space Ray *ray,
- PathRadiance *L,
- ccl_addr_space float3 *throughput)
+ KernelGlobals *kg,
+ ccl_addr_space SubsurfaceIndirectRays *ss_indirect,
+ ccl_addr_space PathState *state,
+ ccl_addr_space Ray *ray,
+ PathRadiance *L,
+ ccl_addr_space float3 *throughput)
{
- /* Setup state, ray and throughput for indirect SSS rays. */
- ss_indirect->num_rays--;
+ /* Setup state, ray and throughput for indirect SSS rays. */
+ ss_indirect->num_rays--;
- path_radiance_sum_indirect(L);
- path_radiance_reset_indirect(L);
+ path_radiance_sum_indirect(L);
+ path_radiance_reset_indirect(L);
- *state = ss_indirect->state[ss_indirect->num_rays];
- *ray = ss_indirect->rays[ss_indirect->num_rays];
- L->state = ss_indirect->L_state[ss_indirect->num_rays];
- *throughput = ss_indirect->throughputs[ss_indirect->num_rays];
+ *state = ss_indirect->state[ss_indirect->num_rays];
+ *ray = ss_indirect->rays[ss_indirect->num_rays];
+ L->state = ss_indirect->L_state[ss_indirect->num_rays];
+ *throughput = ss_indirect->throughputs[ss_indirect->num_rays];
- state->rng_offset += ss_indirect->num_rays * PRNG_BOUNCE_NUM;
+ state->rng_offset += ss_indirect->num_rays * PRNG_BOUNCE_NUM;
}
-#endif /* __SUBSURFACE__ */
+#endif /* __SUBSURFACE__ */
CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/kernel_path_surface.h b/intern/cycles/kernel/kernel_path_surface.h
index 0d18a1e8c77..6251313c5f8 100644
--- a/intern/cycles/kernel/kernel_path_surface.h
+++ b/intern/cycles/kernel/kernel_path_surface.h
@@ -16,255 +16,280 @@
CCL_NAMESPACE_BEGIN
-#if defined(__BRANCHED_PATH__) || defined(__SUBSURFACE__) || defined(__SHADOW_TRICKS__) || defined(__BAKING__)
+#if defined(__BRANCHED_PATH__) || defined(__SUBSURFACE__) || defined(__SHADOW_TRICKS__) || \
+ defined(__BAKING__)
/* branched path tracing: connect path directly to position on one or more lights and add it to L */
ccl_device_noinline void kernel_branched_path_surface_connect_light(
- KernelGlobals *kg,
- ShaderData *sd,
- ShaderData *emission_sd,
- ccl_addr_space PathState *state,
- float3 throughput,
- float num_samples_adjust,
- PathRadiance *L,
- int sample_all_lights)
+ KernelGlobals *kg,
+ ShaderData *sd,
+ ShaderData *emission_sd,
+ ccl_addr_space PathState *state,
+ float3 throughput,
+ float num_samples_adjust,
+ PathRadiance *L,
+ int sample_all_lights)
{
-#ifdef __EMISSION__
- /* sample illumination from lights to find path contribution */
- if(!(sd->flag & SD_BSDF_HAS_EVAL))
- return;
-
- Ray light_ray;
- BsdfEval L_light;
- bool is_lamp;
-
-# ifdef __OBJECT_MOTION__
- light_ray.time = sd->time;
+# ifdef __EMISSION__
+ /* sample illumination from lights to find path contribution */
+ if (!(sd->flag & SD_BSDF_HAS_EVAL))
+ return;
+
+ Ray light_ray;
+ BsdfEval L_light;
+ bool is_lamp;
+
+# ifdef __OBJECT_MOTION__
+ light_ray.time = sd->time;
+# endif
+
+ if (sample_all_lights) {
+ /* lamp sampling */
+ for (int i = 0; i < kernel_data.integrator.num_all_lights; i++) {
+ if (UNLIKELY(light_select_reached_max_bounces(kg, i, state->bounce)))
+ continue;
+
+ int num_samples = ceil_to_int(num_samples_adjust * light_select_num_samples(kg, i));
+ float num_samples_inv = num_samples_adjust /
+ (num_samples * kernel_data.integrator.num_all_lights);
+ uint lamp_rng_hash = cmj_hash(state->rng_hash, i);
+
+ for (int j = 0; j < num_samples; j++) {
+ float light_u, light_v;
+ path_branched_rng_2D(
+ kg, lamp_rng_hash, state, j, num_samples, PRNG_LIGHT_U, &light_u, &light_v);
+ float terminate = path_branched_rng_light_termination(
+ kg, lamp_rng_hash, state, j, num_samples);
+
+ LightSample ls;
+ if (lamp_light_sample(kg, i, light_u, light_v, sd->P, &ls)) {
+ /* The sampling probability returned by lamp_light_sample assumes that all lights were sampled.
+ * However, this code only samples lamps, so if the scene also had mesh lights, the real probability is twice as high. */
+ if (kernel_data.integrator.pdf_triangles != 0.0f)
+ ls.pdf *= 2.0f;
+
+ if (direct_emission(
+ kg, sd, emission_sd, &ls, state, &light_ray, &L_light, &is_lamp, terminate)) {
+ /* trace shadow ray */
+ float3 shadow;
+
+ if (!shadow_blocked(kg, sd, emission_sd, state, &light_ray, &shadow)) {
+ /* accumulate */
+ path_radiance_accum_light(L,
+ state,
+ throughput * num_samples_inv,
+ &L_light,
+ shadow,
+ num_samples_inv,
+ is_lamp);
+ }
+ else {
+ path_radiance_accum_total_light(L, state, throughput * num_samples_inv, &L_light);
+ }
+ }
+ }
+ }
+ }
+
+ /* mesh light sampling */
+ if (kernel_data.integrator.pdf_triangles != 0.0f) {
+ int num_samples = ceil_to_int(num_samples_adjust *
+ kernel_data.integrator.mesh_light_samples);
+ float num_samples_inv = num_samples_adjust / num_samples;
+
+ for (int j = 0; j < num_samples; j++) {
+ float light_u, light_v;
+ path_branched_rng_2D(
+ kg, state->rng_hash, state, j, num_samples, PRNG_LIGHT_U, &light_u, &light_v);
+ float terminate = path_branched_rng_light_termination(
+ kg, state->rng_hash, state, j, num_samples);
+
+ /* only sample triangle lights */
+ if (kernel_data.integrator.num_all_lights)
+ light_u = 0.5f * light_u;
+
+ LightSample ls;
+ if (light_sample(kg, light_u, light_v, sd->time, sd->P, state->bounce, &ls)) {
+ /* Same as above, probability needs to be corrected since the sampling was forced to select a mesh light. */
+ if (kernel_data.integrator.num_all_lights)
+ ls.pdf *= 2.0f;
+
+ if (direct_emission(
+ kg, sd, emission_sd, &ls, state, &light_ray, &L_light, &is_lamp, terminate)) {
+ /* trace shadow ray */
+ float3 shadow;
+
+ if (!shadow_blocked(kg, sd, emission_sd, state, &light_ray, &shadow)) {
+ /* accumulate */
+ path_radiance_accum_light(L,
+ state,
+ throughput * num_samples_inv,
+ &L_light,
+ shadow,
+ num_samples_inv,
+ is_lamp);
+ }
+ else {
+ path_radiance_accum_total_light(L, state, throughput * num_samples_inv, &L_light);
+ }
+ }
+ }
+ }
+ }
+ }
+ else {
+ /* sample one light at random */
+ float light_u, light_v;
+ path_state_rng_2D(kg, state, PRNG_LIGHT_U, &light_u, &light_v);
+ float terminate = path_state_rng_light_termination(kg, state);
+
+ LightSample ls;
+ if (light_sample(kg, light_u, light_v, sd->time, sd->P, state->bounce, &ls)) {
+ /* sample random light */
+ if (direct_emission(
+ kg, sd, emission_sd, &ls, state, &light_ray, &L_light, &is_lamp, terminate)) {
+ /* trace shadow ray */
+ float3 shadow;
+
+ if (!shadow_blocked(kg, sd, emission_sd, state, &light_ray, &shadow)) {
+ /* accumulate */
+ path_radiance_accum_light(L,
+ state,
+ throughput * num_samples_adjust,
+ &L_light,
+ shadow,
+ num_samples_adjust,
+ is_lamp);
+ }
+ else {
+ path_radiance_accum_total_light(L, state, throughput * num_samples_adjust, &L_light);
+ }
+ }
+ }
+ }
# endif
-
- if(sample_all_lights) {
- /* lamp sampling */
- for(int i = 0; i < kernel_data.integrator.num_all_lights; i++) {
- if(UNLIKELY(light_select_reached_max_bounces(kg, i, state->bounce)))
- continue;
-
- int num_samples = ceil_to_int(num_samples_adjust*light_select_num_samples(kg, i));
- float num_samples_inv = num_samples_adjust/(num_samples*kernel_data.integrator.num_all_lights);
- uint lamp_rng_hash = cmj_hash(state->rng_hash, i);
-
- for(int j = 0; j < num_samples; j++) {
- float light_u, light_v;
- path_branched_rng_2D(kg, lamp_rng_hash, state, j, num_samples, PRNG_LIGHT_U, &light_u, &light_v);
- float terminate = path_branched_rng_light_termination(kg, lamp_rng_hash, state, j, num_samples);
-
- LightSample ls;
- if(lamp_light_sample(kg, i, light_u, light_v, sd->P, &ls)) {
- /* The sampling probability returned by lamp_light_sample assumes that all lights were sampled.
- * However, this code only samples lamps, so if the scene also had mesh lights, the real probability is twice as high. */
- if(kernel_data.integrator.pdf_triangles != 0.0f)
- ls.pdf *= 2.0f;
-
- if(direct_emission(kg, sd, emission_sd, &ls, state, &light_ray, &L_light, &is_lamp, terminate)) {
- /* trace shadow ray */
- float3 shadow;
-
- if(!shadow_blocked(kg, sd, emission_sd, state, &light_ray, &shadow)) {
- /* accumulate */
- path_radiance_accum_light(L, state, throughput*num_samples_inv, &L_light, shadow, num_samples_inv, is_lamp);
- }
- else {
- path_radiance_accum_total_light(L, state, throughput*num_samples_inv, &L_light);
- }
- }
- }
- }
- }
-
- /* mesh light sampling */
- if(kernel_data.integrator.pdf_triangles != 0.0f) {
- int num_samples = ceil_to_int(num_samples_adjust*kernel_data.integrator.mesh_light_samples);
- float num_samples_inv = num_samples_adjust/num_samples;
-
- for(int j = 0; j < num_samples; j++) {
- float light_u, light_v;
- path_branched_rng_2D(kg, state->rng_hash, state, j, num_samples, PRNG_LIGHT_U, &light_u, &light_v);
- float terminate = path_branched_rng_light_termination(kg, state->rng_hash, state, j, num_samples);
-
- /* only sample triangle lights */
- if(kernel_data.integrator.num_all_lights)
- light_u = 0.5f*light_u;
-
- LightSample ls;
- if(light_sample(kg, light_u, light_v, sd->time, sd->P, state->bounce, &ls)) {
- /* Same as above, probability needs to be corrected since the sampling was forced to select a mesh light. */
- if(kernel_data.integrator.num_all_lights)
- ls.pdf *= 2.0f;
-
- if(direct_emission(kg, sd, emission_sd, &ls, state, &light_ray, &L_light, &is_lamp, terminate)) {
- /* trace shadow ray */
- float3 shadow;
-
- if(!shadow_blocked(kg, sd, emission_sd, state, &light_ray, &shadow)) {
- /* accumulate */
- path_radiance_accum_light(L, state, throughput*num_samples_inv, &L_light, shadow, num_samples_inv, is_lamp);
- }
- else {
- path_radiance_accum_total_light(L, state, throughput*num_samples_inv, &L_light);
- }
- }
- }
- }
- }
- }
- else {
- /* sample one light at random */
- float light_u, light_v;
- path_state_rng_2D(kg, state, PRNG_LIGHT_U, &light_u, &light_v);
- float terminate = path_state_rng_light_termination(kg, state);
-
- LightSample ls;
- if(light_sample(kg, light_u, light_v, sd->time, sd->P, state->bounce, &ls)) {
- /* sample random light */
- if(direct_emission(kg, sd, emission_sd, &ls, state, &light_ray, &L_light, &is_lamp, terminate)) {
- /* trace shadow ray */
- float3 shadow;
-
- if(!shadow_blocked(kg, sd, emission_sd, state, &light_ray, &shadow)) {
- /* accumulate */
- path_radiance_accum_light(L, state, throughput*num_samples_adjust, &L_light, shadow, num_samples_adjust, is_lamp);
- }
- else {
- path_radiance_accum_total_light(L, state, throughput*num_samples_adjust, &L_light);
- }
- }
- }
- }
-#endif
}
/* branched path tracing: bounce off or through surface to with new direction stored in ray */
-ccl_device bool kernel_branched_path_surface_bounce(
- KernelGlobals *kg,
- ShaderData *sd,
- const ShaderClosure *sc,
- int sample,
- int num_samples,
- ccl_addr_space float3 *throughput,
- ccl_addr_space PathState *state,
- PathRadianceState *L_state,
- ccl_addr_space Ray *ray,
- float sum_sample_weight)
+ccl_device bool kernel_branched_path_surface_bounce(KernelGlobals *kg,
+ ShaderData *sd,
+ const ShaderClosure *sc,
+ int sample,
+ int num_samples,
+ ccl_addr_space float3 *throughput,
+ ccl_addr_space PathState *state,
+ PathRadianceState *L_state,
+ ccl_addr_space Ray *ray,
+ float sum_sample_weight)
{
- /* sample BSDF */
- float bsdf_pdf;
- BsdfEval bsdf_eval;
- float3 bsdf_omega_in;
- differential3 bsdf_domega_in;
- float bsdf_u, bsdf_v;
- path_branched_rng_2D(kg, state->rng_hash, state, sample, num_samples, PRNG_BSDF_U, &bsdf_u, &bsdf_v);
- int label;
-
- label = shader_bsdf_sample_closure(kg, sd, sc, bsdf_u, bsdf_v, &bsdf_eval,
- &bsdf_omega_in, &bsdf_domega_in, &bsdf_pdf);
-
- if(bsdf_pdf == 0.0f || bsdf_eval_is_zero(&bsdf_eval))
- return false;
-
- /* modify throughput */
- path_radiance_bsdf_bounce(kg, L_state, throughput, &bsdf_eval, bsdf_pdf, state->bounce, label);
-
-#ifdef __DENOISING_FEATURES__
- state->denoising_feature_weight *= sc->sample_weight / (sum_sample_weight * num_samples);
-#endif
+ /* sample BSDF */
+ float bsdf_pdf;
+ BsdfEval bsdf_eval;
+ float3 bsdf_omega_in;
+ differential3 bsdf_domega_in;
+ float bsdf_u, bsdf_v;
+ path_branched_rng_2D(
+ kg, state->rng_hash, state, sample, num_samples, PRNG_BSDF_U, &bsdf_u, &bsdf_v);
+ int label;
+
+ label = shader_bsdf_sample_closure(
+ kg, sd, sc, bsdf_u, bsdf_v, &bsdf_eval, &bsdf_omega_in, &bsdf_domega_in, &bsdf_pdf);
+
+ if (bsdf_pdf == 0.0f || bsdf_eval_is_zero(&bsdf_eval))
+ return false;
+
+ /* modify throughput */
+ path_radiance_bsdf_bounce(kg, L_state, throughput, &bsdf_eval, bsdf_pdf, state->bounce, label);
+
+# ifdef __DENOISING_FEATURES__
+ state->denoising_feature_weight *= sc->sample_weight / (sum_sample_weight * num_samples);
+# endif
- /* modify path state */
- path_state_next(kg, state, label);
+ /* modify path state */
+ path_state_next(kg, state, label);
- /* setup ray */
- ray->P = ray_offset(sd->P, (label & LABEL_TRANSMIT)? -sd->Ng: sd->Ng);
- ray->D = normalize(bsdf_omega_in);
- ray->t = FLT_MAX;
-#ifdef __RAY_DIFFERENTIALS__
- ray->dP = sd->dP;
- ray->dD = bsdf_domega_in;
-#endif
-#ifdef __OBJECT_MOTION__
- ray->time = sd->time;
-#endif
+ /* setup ray */
+ ray->P = ray_offset(sd->P, (label & LABEL_TRANSMIT) ? -sd->Ng : sd->Ng);
+ ray->D = normalize(bsdf_omega_in);
+ ray->t = FLT_MAX;
+# ifdef __RAY_DIFFERENTIALS__
+ ray->dP = sd->dP;
+ ray->dD = bsdf_domega_in;
+# endif
+# ifdef __OBJECT_MOTION__
+ ray->time = sd->time;
+# endif
-#ifdef __VOLUME__
- /* enter/exit volume */
- if(label & LABEL_TRANSMIT)
- kernel_volume_stack_enter_exit(kg, sd, state->volume_stack);
-#endif
+# ifdef __VOLUME__
+ /* enter/exit volume */
+ if (label & LABEL_TRANSMIT)
+ kernel_volume_stack_enter_exit(kg, sd, state->volume_stack);
+# endif
- /* branch RNG state */
- path_state_branch(state, sample, num_samples);
+ /* branch RNG state */
+ path_state_branch(state, sample, num_samples);
- /* set MIS state */
- state->min_ray_pdf = fminf(bsdf_pdf, FLT_MAX);
- state->ray_pdf = bsdf_pdf;
-#ifdef __LAMP_MIS__
- state->ray_t = 0.0f;
-#endif
+ /* set MIS state */
+ state->min_ray_pdf = fminf(bsdf_pdf, FLT_MAX);
+ state->ray_pdf = bsdf_pdf;
+# ifdef __LAMP_MIS__
+ state->ray_t = 0.0f;
+# endif
- return true;
+ return true;
}
#endif
/* path tracing: connect path directly to position on a light and add it to L */
ccl_device_inline void kernel_path_surface_connect_light(KernelGlobals *kg,
- ShaderData *sd, ShaderData *emission_sd, float3 throughput, ccl_addr_space PathState *state,
- PathRadiance *L)
+ ShaderData *sd,
+ ShaderData *emission_sd,
+ float3 throughput,
+ ccl_addr_space PathState *state,
+ PathRadiance *L)
{
- PROFILING_INIT(kg, PROFILING_CONNECT_LIGHT);
+ PROFILING_INIT(kg, PROFILING_CONNECT_LIGHT);
#ifdef __EMISSION__
- if(!(kernel_data.integrator.use_direct_light && (sd->flag & SD_BSDF_HAS_EVAL)))
- return;
-
-#ifdef __SHADOW_TRICKS__
- if(state->flag & PATH_RAY_SHADOW_CATCHER) {
- kernel_branched_path_surface_connect_light(kg,
- sd,
- emission_sd,
- state,
- throughput,
- 1.0f,
- L,
- 1);
- return;
- }
-#endif
+ if (!(kernel_data.integrator.use_direct_light && (sd->flag & SD_BSDF_HAS_EVAL)))
+ return;
+
+# ifdef __SHADOW_TRICKS__
+ if (state->flag & PATH_RAY_SHADOW_CATCHER) {
+ kernel_branched_path_surface_connect_light(kg, sd, emission_sd, state, throughput, 1.0f, L, 1);
+ return;
+ }
+# endif
- /* sample illumination from lights to find path contribution */
- float light_u, light_v;
- path_state_rng_2D(kg, state, PRNG_LIGHT_U, &light_u, &light_v);
+ /* sample illumination from lights to find path contribution */
+ float light_u, light_v;
+ path_state_rng_2D(kg, state, PRNG_LIGHT_U, &light_u, &light_v);
- Ray light_ray;
- BsdfEval L_light;
- bool is_lamp;
+ Ray light_ray;
+ BsdfEval L_light;
+ bool is_lamp;
-#ifdef __OBJECT_MOTION__
- light_ray.time = sd->time;
-#endif
+# ifdef __OBJECT_MOTION__
+ light_ray.time = sd->time;
+# endif
- LightSample ls;
- if(light_sample(kg, light_u, light_v, sd->time, sd->P, state->bounce, &ls)) {
- float terminate = path_state_rng_light_termination(kg, state);
- if(direct_emission(kg, sd, emission_sd, &ls, state, &light_ray, &L_light, &is_lamp, terminate)) {
- /* trace shadow ray */
- float3 shadow;
-
- if(!shadow_blocked(kg, sd, emission_sd, state, &light_ray, &shadow)) {
- /* accumulate */
- path_radiance_accum_light(L, state, throughput, &L_light, shadow, 1.0f, is_lamp);
- }
- else {
- path_radiance_accum_total_light(L, state, throughput, &L_light);
- }
- }
- }
+ LightSample ls;
+ if (light_sample(kg, light_u, light_v, sd->time, sd->P, state->bounce, &ls)) {
+ float terminate = path_state_rng_light_termination(kg, state);
+ if (direct_emission(
+ kg, sd, emission_sd, &ls, state, &light_ray, &L_light, &is_lamp, terminate)) {
+ /* trace shadow ray */
+ float3 shadow;
+
+ if (!shadow_blocked(kg, sd, emission_sd, state, &light_ray, &shadow)) {
+ /* accumulate */
+ path_radiance_accum_light(L, state, throughput, &L_light, shadow, 1.0f, is_lamp);
+ }
+ else {
+ path_radiance_accum_total_light(L, state, throughput, &L_light);
+ }
+ }
+ }
#endif
}
@@ -276,87 +301,87 @@ ccl_device bool kernel_path_surface_bounce(KernelGlobals *kg,
PathRadianceState *L_state,
ccl_addr_space Ray *ray)
{
- PROFILING_INIT(kg, PROFILING_SURFACE_BOUNCE);
-
- /* no BSDF? we can stop here */
- if(sd->flag & SD_BSDF) {
- /* sample BSDF */
- float bsdf_pdf;
- BsdfEval bsdf_eval;
- float3 bsdf_omega_in;
- differential3 bsdf_domega_in;
- float bsdf_u, bsdf_v;
- path_state_rng_2D(kg, state, PRNG_BSDF_U, &bsdf_u, &bsdf_v);
- int label;
-
- label = shader_bsdf_sample(kg, sd, bsdf_u, bsdf_v, &bsdf_eval,
- &bsdf_omega_in, &bsdf_domega_in, &bsdf_pdf);
-
- if(bsdf_pdf == 0.0f || bsdf_eval_is_zero(&bsdf_eval))
- return false;
-
- /* modify throughput */
- path_radiance_bsdf_bounce(kg, L_state, throughput, &bsdf_eval, bsdf_pdf, state->bounce, label);
-
- /* set labels */
- if(!(label & LABEL_TRANSPARENT)) {
- state->ray_pdf = bsdf_pdf;
+ PROFILING_INIT(kg, PROFILING_SURFACE_BOUNCE);
+
+ /* no BSDF? we can stop here */
+ if (sd->flag & SD_BSDF) {
+ /* sample BSDF */
+ float bsdf_pdf;
+ BsdfEval bsdf_eval;
+ float3 bsdf_omega_in;
+ differential3 bsdf_domega_in;
+ float bsdf_u, bsdf_v;
+ path_state_rng_2D(kg, state, PRNG_BSDF_U, &bsdf_u, &bsdf_v);
+ int label;
+
+ label = shader_bsdf_sample(
+ kg, sd, bsdf_u, bsdf_v, &bsdf_eval, &bsdf_omega_in, &bsdf_domega_in, &bsdf_pdf);
+
+ if (bsdf_pdf == 0.0f || bsdf_eval_is_zero(&bsdf_eval))
+ return false;
+
+ /* modify throughput */
+ path_radiance_bsdf_bounce(kg, L_state, throughput, &bsdf_eval, bsdf_pdf, state->bounce, label);
+
+ /* set labels */
+ if (!(label & LABEL_TRANSPARENT)) {
+ state->ray_pdf = bsdf_pdf;
#ifdef __LAMP_MIS__
- state->ray_t = 0.0f;
+ state->ray_t = 0.0f;
#endif
- state->min_ray_pdf = fminf(bsdf_pdf, state->min_ray_pdf);
- }
+ state->min_ray_pdf = fminf(bsdf_pdf, state->min_ray_pdf);
+ }
- /* update path state */
- path_state_next(kg, state, label);
+ /* update path state */
+ path_state_next(kg, state, label);
- /* setup ray */
- ray->P = ray_offset(sd->P, (label & LABEL_TRANSMIT)? -sd->Ng: sd->Ng);
- ray->D = normalize(bsdf_omega_in);
+ /* setup ray */
+ ray->P = ray_offset(sd->P, (label & LABEL_TRANSMIT) ? -sd->Ng : sd->Ng);
+ ray->D = normalize(bsdf_omega_in);
- if(state->bounce == 0)
- ray->t -= sd->ray_length; /* clipping works through transparent */
- else
- ray->t = FLT_MAX;
+ if (state->bounce == 0)
+ ray->t -= sd->ray_length; /* clipping works through transparent */
+ else
+ ray->t = FLT_MAX;
#ifdef __RAY_DIFFERENTIALS__
- ray->dP = sd->dP;
- ray->dD = bsdf_domega_in;
+ ray->dP = sd->dP;
+ ray->dD = bsdf_domega_in;
#endif
#ifdef __VOLUME__
- /* enter/exit volume */
- if(label & LABEL_TRANSMIT)
- kernel_volume_stack_enter_exit(kg, sd, state->volume_stack);
+ /* enter/exit volume */
+ if (label & LABEL_TRANSMIT)
+ kernel_volume_stack_enter_exit(kg, sd, state->volume_stack);
#endif
- return true;
- }
+ return true;
+ }
#ifdef __VOLUME__
- else if(sd->flag & SD_HAS_ONLY_VOLUME) {
- if(!path_state_volume_next(kg, state)) {
- return false;
- }
-
- if(state->bounce == 0)
- ray->t -= sd->ray_length; /* clipping works through transparent */
- else
- ray->t = FLT_MAX;
-
- /* setup ray position, direction stays unchanged */
- ray->P = ray_offset(sd->P, -sd->Ng);
-#ifdef __RAY_DIFFERENTIALS__
- ray->dP = sd->dP;
-#endif
+ else if (sd->flag & SD_HAS_ONLY_VOLUME) {
+ if (!path_state_volume_next(kg, state)) {
+ return false;
+ }
+
+ if (state->bounce == 0)
+ ray->t -= sd->ray_length; /* clipping works through transparent */
+ else
+ ray->t = FLT_MAX;
+
+ /* setup ray position, direction stays unchanged */
+ ray->P = ray_offset(sd->P, -sd->Ng);
+# ifdef __RAY_DIFFERENTIALS__
+ ray->dP = sd->dP;
+# endif
- /* enter/exit volume */
- kernel_volume_stack_enter_exit(kg, sd, state->volume_stack);
- return true;
- }
+ /* enter/exit volume */
+ kernel_volume_stack_enter_exit(kg, sd, state->volume_stack);
+ return true;
+ }
#endif
- else {
- /* no bsdf or volume? */
- return false;
- }
+ else {
+ /* no bsdf or volume? */
+ return false;
+ }
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/kernel_path_volume.h b/intern/cycles/kernel/kernel_path_volume.h
index d2506fc1e7e..fea4dfc159d 100644
--- a/intern/cycles/kernel/kernel_path_volume.h
+++ b/intern/cycles/kernel/kernel_path_volume.h
@@ -18,269 +18,307 @@ CCL_NAMESPACE_BEGIN
#ifdef __VOLUME_SCATTER__
-ccl_device_inline void kernel_path_volume_connect_light(
- KernelGlobals *kg,
- ShaderData *sd,
- ShaderData *emission_sd,
- float3 throughput,
- ccl_addr_space PathState *state,
- PathRadiance *L)
+ccl_device_inline void kernel_path_volume_connect_light(KernelGlobals *kg,
+ ShaderData *sd,
+ ShaderData *emission_sd,
+ float3 throughput,
+ ccl_addr_space PathState *state,
+ PathRadiance *L)
{
-#ifdef __EMISSION__
- if(!kernel_data.integrator.use_direct_light)
- return;
-
- /* sample illumination from lights to find path contribution */
- float light_u, light_v;
- path_state_rng_2D(kg, state, PRNG_LIGHT_U, &light_u, &light_v);
-
- Ray light_ray;
- BsdfEval L_light;
- LightSample ls;
- bool is_lamp;
-
- /* connect to light from given point where shader has been evaluated */
- light_ray.time = sd->time;
-
- if(light_sample(kg, light_u, light_v, sd->time, sd->P, state->bounce, &ls))
- {
- float terminate = path_state_rng_light_termination(kg, state);
- if(direct_emission(kg, sd, emission_sd, &ls, state, &light_ray, &L_light, &is_lamp, terminate)) {
- /* trace shadow ray */
- float3 shadow;
-
- if(!shadow_blocked(kg, sd, emission_sd, state, &light_ray, &shadow)) {
- /* accumulate */
- path_radiance_accum_light(L, state, throughput, &L_light, shadow, 1.0f, is_lamp);
- }
- }
- }
-#endif /* __EMISSION__ */
+# ifdef __EMISSION__
+ if (!kernel_data.integrator.use_direct_light)
+ return;
+
+ /* sample illumination from lights to find path contribution */
+ float light_u, light_v;
+ path_state_rng_2D(kg, state, PRNG_LIGHT_U, &light_u, &light_v);
+
+ Ray light_ray;
+ BsdfEval L_light;
+ LightSample ls;
+ bool is_lamp;
+
+ /* connect to light from given point where shader has been evaluated */
+ light_ray.time = sd->time;
+
+ if (light_sample(kg, light_u, light_v, sd->time, sd->P, state->bounce, &ls)) {
+ float terminate = path_state_rng_light_termination(kg, state);
+ if (direct_emission(
+ kg, sd, emission_sd, &ls, state, &light_ray, &L_light, &is_lamp, terminate)) {
+ /* trace shadow ray */
+ float3 shadow;
+
+ if (!shadow_blocked(kg, sd, emission_sd, state, &light_ray, &shadow)) {
+ /* accumulate */
+ path_radiance_accum_light(L, state, throughput, &L_light, shadow, 1.0f, is_lamp);
+ }
+ }
+ }
+# endif /* __EMISSION__ */
}
-#ifdef __KERNEL_GPU__
+# ifdef __KERNEL_GPU__
ccl_device_noinline
-#else
+# else
ccl_device
-#endif
-bool kernel_path_volume_bounce(
- KernelGlobals *kg,
- ShaderData *sd,
- ccl_addr_space float3 *throughput,
- ccl_addr_space PathState *state,
- PathRadianceState *L_state,
- ccl_addr_space Ray *ray)
+# endif
+ bool
+ kernel_path_volume_bounce(KernelGlobals *kg,
+ ShaderData *sd,
+ ccl_addr_space float3 *throughput,
+ ccl_addr_space PathState *state,
+ PathRadianceState *L_state,
+ ccl_addr_space Ray *ray)
{
- /* sample phase function */
- float phase_pdf;
- BsdfEval phase_eval;
- float3 phase_omega_in;
- differential3 phase_domega_in;
- float phase_u, phase_v;
- path_state_rng_2D(kg, state, PRNG_BSDF_U, &phase_u, &phase_v);
- int label;
-
- label = shader_volume_phase_sample(kg, sd, phase_u, phase_v, &phase_eval,
- &phase_omega_in, &phase_domega_in, &phase_pdf);
-
- if(phase_pdf == 0.0f || bsdf_eval_is_zero(&phase_eval))
- return false;
-
- /* modify throughput */
- path_radiance_bsdf_bounce(kg, L_state, throughput, &phase_eval, phase_pdf, state->bounce, label);
-
- /* set labels */
- state->ray_pdf = phase_pdf;
-#ifdef __LAMP_MIS__
- state->ray_t = 0.0f;
-#endif
- state->min_ray_pdf = fminf(phase_pdf, state->min_ray_pdf);
-
- /* update path state */
- path_state_next(kg, state, label);
-
- /* Russian roulette termination of volume ray scattering. */
- float probability = path_state_continuation_probability(kg, state, *throughput);
-
- if(probability == 0.0f) {
- return false;
- }
- else if(probability != 1.0f) {
- /* Use dimension from the previous bounce, has not been used yet. */
- float terminate = path_state_rng_1D(kg, state, PRNG_TERMINATE - PRNG_BOUNCE_NUM);
-
- if(terminate >= probability) {
- return false;
- }
-
- *throughput /= probability;
- }
-
- /* setup ray */
- ray->P = sd->P;
- ray->D = phase_omega_in;
- ray->t = FLT_MAX;
-
-#ifdef __RAY_DIFFERENTIALS__
- ray->dP = sd->dP;
- ray->dD = phase_domega_in;
-#endif
-
- return true;
+ /* sample phase function */
+ float phase_pdf;
+ BsdfEval phase_eval;
+ float3 phase_omega_in;
+ differential3 phase_domega_in;
+ float phase_u, phase_v;
+ path_state_rng_2D(kg, state, PRNG_BSDF_U, &phase_u, &phase_v);
+ int label;
+
+ label = shader_volume_phase_sample(
+ kg, sd, phase_u, phase_v, &phase_eval, &phase_omega_in, &phase_domega_in, &phase_pdf);
+
+ if (phase_pdf == 0.0f || bsdf_eval_is_zero(&phase_eval))
+ return false;
+
+ /* modify throughput */
+ path_radiance_bsdf_bounce(kg, L_state, throughput, &phase_eval, phase_pdf, state->bounce, label);
+
+ /* set labels */
+ state->ray_pdf = phase_pdf;
+# ifdef __LAMP_MIS__
+ state->ray_t = 0.0f;
+# endif
+ state->min_ray_pdf = fminf(phase_pdf, state->min_ray_pdf);
+
+ /* update path state */
+ path_state_next(kg, state, label);
+
+ /* Russian roulette termination of volume ray scattering. */
+ float probability = path_state_continuation_probability(kg, state, *throughput);
+
+ if (probability == 0.0f) {
+ return false;
+ }
+ else if (probability != 1.0f) {
+ /* Use dimension from the previous bounce, has not been used yet. */
+ float terminate = path_state_rng_1D(kg, state, PRNG_TERMINATE - PRNG_BOUNCE_NUM);
+
+ if (terminate >= probability) {
+ return false;
+ }
+
+ *throughput /= probability;
+ }
+
+ /* setup ray */
+ ray->P = sd->P;
+ ray->D = phase_omega_in;
+ ray->t = FLT_MAX;
+
+# ifdef __RAY_DIFFERENTIALS__
+ ray->dP = sd->dP;
+ ray->dD = phase_domega_in;
+# endif
+
+ return true;
}
-#ifndef __SPLIT_KERNEL__
-ccl_device void kernel_branched_path_volume_connect_light(
- KernelGlobals *kg,
- ShaderData *sd,
- ShaderData *emission_sd,
- float3 throughput,
- ccl_addr_space PathState *state,
- PathRadiance *L,
- bool sample_all_lights,
- Ray *ray,
- const VolumeSegment *segment)
+# ifndef __SPLIT_KERNEL__
+ccl_device void kernel_branched_path_volume_connect_light(KernelGlobals *kg,
+ ShaderData *sd,
+ ShaderData *emission_sd,
+ float3 throughput,
+ ccl_addr_space PathState *state,
+ PathRadiance *L,
+ bool sample_all_lights,
+ Ray *ray,
+ const VolumeSegment *segment)
{
-#ifdef __EMISSION__
- if(!kernel_data.integrator.use_direct_light)
- return;
-
- Ray light_ray;
- BsdfEval L_light;
- bool is_lamp;
-
- light_ray.time = sd->time;
-
- if(sample_all_lights) {
- /* lamp sampling */
- for(int i = 0; i < kernel_data.integrator.num_all_lights; i++) {
- if(UNLIKELY(light_select_reached_max_bounces(kg, i, state->bounce)))
- continue;
-
- int num_samples = light_select_num_samples(kg, i);
- float num_samples_inv = 1.0f/(num_samples*kernel_data.integrator.num_all_lights);
- uint lamp_rng_hash = cmj_hash(state->rng_hash, i);
-
- for(int j = 0; j < num_samples; j++) {
- /* sample random position on given light */
- float light_u, light_v;
- path_branched_rng_2D(kg, lamp_rng_hash, state, j, num_samples, PRNG_LIGHT_U, &light_u, &light_v);
-
- LightSample ls;
- lamp_light_sample(kg, i, light_u, light_v, ray->P, &ls);
-
- float3 tp = throughput;
-
- /* sample position on volume segment */
- float rphase = path_branched_rng_1D(kg, state->rng_hash, state, j, num_samples, PRNG_PHASE_CHANNEL);
- float rscatter = path_branched_rng_1D(kg, state->rng_hash, state, j, num_samples, PRNG_SCATTER_DISTANCE);
-
- VolumeIntegrateResult result = kernel_volume_decoupled_scatter(kg,
- state, ray, sd, &tp, rphase, rscatter, segment, (ls.t != FLT_MAX)? &ls.P: NULL, false);
-
- /* todo: split up light_sample so we don't have to call it again with new position */
- if(result == VOLUME_PATH_SCATTERED &&
- lamp_light_sample(kg, i, light_u, light_v, sd->P, &ls)) {
- if(kernel_data.integrator.pdf_triangles != 0.0f)
- ls.pdf *= 2.0f;
-
- float terminate = path_branched_rng_light_termination(kg, state->rng_hash, state, j, num_samples);
- if(direct_emission(kg, sd, emission_sd, &ls, state, &light_ray, &L_light, &is_lamp, terminate)) {
- /* trace shadow ray */
- float3 shadow;
-
- if(!shadow_blocked(kg, sd, emission_sd, state, &light_ray, &shadow)) {
- /* accumulate */
- path_radiance_accum_light(L, state, tp*num_samples_inv, &L_light, shadow, num_samples_inv, is_lamp);
- }
- }
- }
- }
- }
-
- /* mesh light sampling */
- if(kernel_data.integrator.pdf_triangles != 0.0f) {
- int num_samples = kernel_data.integrator.mesh_light_samples;
- float num_samples_inv = 1.0f/num_samples;
-
- for(int j = 0; j < num_samples; j++) {
- /* sample random position on random triangle */
- float light_u, light_v;
- path_branched_rng_2D(kg, state->rng_hash, state, j, num_samples, PRNG_LIGHT_U, &light_u, &light_v);
-
- /* only sample triangle lights */
- if(kernel_data.integrator.num_all_lights)
- light_u = 0.5f*light_u;
-
- LightSample ls;
- light_sample(kg, light_u, light_v, sd->time, ray->P, state->bounce, &ls);
-
- float3 tp = throughput;
-
- /* sample position on volume segment */
- float rphase = path_branched_rng_1D(kg, state->rng_hash, state, j, num_samples, PRNG_PHASE_CHANNEL);
- float rscatter = path_branched_rng_1D(kg, state->rng_hash, state, j, num_samples, PRNG_SCATTER_DISTANCE);
-
- VolumeIntegrateResult result = kernel_volume_decoupled_scatter(kg,
- state, ray, sd, &tp, rphase, rscatter, segment, (ls.t != FLT_MAX)? &ls.P: NULL, false);
-
- /* todo: split up light_sample so we don't have to call it again with new position */
- if(result == VOLUME_PATH_SCATTERED &&
- light_sample(kg, light_u, light_v, sd->time, sd->P, state->bounce, &ls)) {
- if(kernel_data.integrator.num_all_lights)
- ls.pdf *= 2.0f;
-
- float terminate = path_branched_rng_light_termination(kg, state->rng_hash, state, j, num_samples);
- if(direct_emission(kg, sd, emission_sd, &ls, state, &light_ray, &L_light, &is_lamp, terminate)) {
- /* trace shadow ray */
- float3 shadow;
-
- if(!shadow_blocked(kg, sd, emission_sd, state, &light_ray, &shadow)) {
- /* accumulate */
- path_radiance_accum_light(L, state, tp*num_samples_inv, &L_light, shadow, num_samples_inv, is_lamp);
- }
- }
- }
- }
- }
- }
- else {
- /* sample random position on random light */
- float light_u, light_v;
- path_state_rng_2D(kg, state, PRNG_LIGHT_U, &light_u, &light_v);
-
- LightSample ls;
- light_sample(kg, light_u, light_v, sd->time, ray->P, state->bounce, &ls);
-
- float3 tp = throughput;
-
- /* sample position on volume segment */
- float rphase = path_state_rng_1D(kg, state, PRNG_PHASE_CHANNEL);
- float rscatter = path_state_rng_1D(kg, state, PRNG_SCATTER_DISTANCE);
-
- VolumeIntegrateResult result = kernel_volume_decoupled_scatter(kg,
- state, ray, sd, &tp, rphase, rscatter, segment, (ls.t != FLT_MAX)? &ls.P: NULL, false);
-
- /* todo: split up light_sample so we don't have to call it again with new position */
- if(result == VOLUME_PATH_SCATTERED &&
- light_sample(kg, light_u, light_v, sd->time, sd->P, state->bounce, &ls)) {
- /* sample random light */
- float terminate = path_state_rng_light_termination(kg, state);
- if(direct_emission(kg, sd, emission_sd, &ls, state, &light_ray, &L_light, &is_lamp, terminate)) {
- /* trace shadow ray */
- float3 shadow;
-
- if(!shadow_blocked(kg, sd, emission_sd, state, &light_ray, &shadow)) {
- /* accumulate */
- path_radiance_accum_light(L, state, tp, &L_light, shadow, 1.0f, is_lamp);
- }
- }
- }
- }
-#endif /* __EMISSION__ */
+# ifdef __EMISSION__
+ if (!kernel_data.integrator.use_direct_light)
+ return;
+
+ Ray light_ray;
+ BsdfEval L_light;
+ bool is_lamp;
+
+ light_ray.time = sd->time;
+
+ if (sample_all_lights) {
+ /* lamp sampling */
+ for (int i = 0; i < kernel_data.integrator.num_all_lights; i++) {
+ if (UNLIKELY(light_select_reached_max_bounces(kg, i, state->bounce)))
+ continue;
+
+ int num_samples = light_select_num_samples(kg, i);
+ float num_samples_inv = 1.0f / (num_samples * kernel_data.integrator.num_all_lights);
+ uint lamp_rng_hash = cmj_hash(state->rng_hash, i);
+
+ for (int j = 0; j < num_samples; j++) {
+ /* sample random position on given light */
+ float light_u, light_v;
+ path_branched_rng_2D(
+ kg, lamp_rng_hash, state, j, num_samples, PRNG_LIGHT_U, &light_u, &light_v);
+
+ LightSample ls;
+ lamp_light_sample(kg, i, light_u, light_v, ray->P, &ls);
+
+ float3 tp = throughput;
+
+ /* sample position on volume segment */
+ float rphase = path_branched_rng_1D(
+ kg, state->rng_hash, state, j, num_samples, PRNG_PHASE_CHANNEL);
+ float rscatter = path_branched_rng_1D(
+ kg, state->rng_hash, state, j, num_samples, PRNG_SCATTER_DISTANCE);
+
+ VolumeIntegrateResult result = kernel_volume_decoupled_scatter(kg,
+ state,
+ ray,
+ sd,
+ &tp,
+ rphase,
+ rscatter,
+ segment,
+ (ls.t != FLT_MAX) ? &ls.P :
+ NULL,
+ false);
+
+ /* todo: split up light_sample so we don't have to call it again with new position */
+ if (result == VOLUME_PATH_SCATTERED &&
+ lamp_light_sample(kg, i, light_u, light_v, sd->P, &ls)) {
+ if (kernel_data.integrator.pdf_triangles != 0.0f)
+ ls.pdf *= 2.0f;
+
+ float terminate = path_branched_rng_light_termination(
+ kg, state->rng_hash, state, j, num_samples);
+ if (direct_emission(
+ kg, sd, emission_sd, &ls, state, &light_ray, &L_light, &is_lamp, terminate)) {
+ /* trace shadow ray */
+ float3 shadow;
+
+ if (!shadow_blocked(kg, sd, emission_sd, state, &light_ray, &shadow)) {
+ /* accumulate */
+ path_radiance_accum_light(
+ L, state, tp * num_samples_inv, &L_light, shadow, num_samples_inv, is_lamp);
+ }
+ }
+ }
+ }
+ }
+
+ /* mesh light sampling */
+ if (kernel_data.integrator.pdf_triangles != 0.0f) {
+ int num_samples = kernel_data.integrator.mesh_light_samples;
+ float num_samples_inv = 1.0f / num_samples;
+
+ for (int j = 0; j < num_samples; j++) {
+ /* sample random position on random triangle */
+ float light_u, light_v;
+ path_branched_rng_2D(
+ kg, state->rng_hash, state, j, num_samples, PRNG_LIGHT_U, &light_u, &light_v);
+
+ /* only sample triangle lights */
+ if (kernel_data.integrator.num_all_lights)
+ light_u = 0.5f * light_u;
+
+ LightSample ls;
+ light_sample(kg, light_u, light_v, sd->time, ray->P, state->bounce, &ls);
+
+ float3 tp = throughput;
+
+ /* sample position on volume segment */
+ float rphase = path_branched_rng_1D(
+ kg, state->rng_hash, state, j, num_samples, PRNG_PHASE_CHANNEL);
+ float rscatter = path_branched_rng_1D(
+ kg, state->rng_hash, state, j, num_samples, PRNG_SCATTER_DISTANCE);
+
+ VolumeIntegrateResult result = kernel_volume_decoupled_scatter(kg,
+ state,
+ ray,
+ sd,
+ &tp,
+ rphase,
+ rscatter,
+ segment,
+ (ls.t != FLT_MAX) ? &ls.P :
+ NULL,
+ false);
+
+ /* todo: split up light_sample so we don't have to call it again with new position */
+ if (result == VOLUME_PATH_SCATTERED &&
+ light_sample(kg, light_u, light_v, sd->time, sd->P, state->bounce, &ls)) {
+ if (kernel_data.integrator.num_all_lights)
+ ls.pdf *= 2.0f;
+
+ float terminate = path_branched_rng_light_termination(
+ kg, state->rng_hash, state, j, num_samples);
+ if (direct_emission(
+ kg, sd, emission_sd, &ls, state, &light_ray, &L_light, &is_lamp, terminate)) {
+ /* trace shadow ray */
+ float3 shadow;
+
+ if (!shadow_blocked(kg, sd, emission_sd, state, &light_ray, &shadow)) {
+ /* accumulate */
+ path_radiance_accum_light(
+ L, state, tp * num_samples_inv, &L_light, shadow, num_samples_inv, is_lamp);
+ }
+ }
+ }
+ }
+ }
+ }
+ else {
+ /* sample random position on random light */
+ float light_u, light_v;
+ path_state_rng_2D(kg, state, PRNG_LIGHT_U, &light_u, &light_v);
+
+ LightSample ls;
+ light_sample(kg, light_u, light_v, sd->time, ray->P, state->bounce, &ls);
+
+ float3 tp = throughput;
+
+ /* sample position on volume segment */
+ float rphase = path_state_rng_1D(kg, state, PRNG_PHASE_CHANNEL);
+ float rscatter = path_state_rng_1D(kg, state, PRNG_SCATTER_DISTANCE);
+
+ VolumeIntegrateResult result = kernel_volume_decoupled_scatter(kg,
+ state,
+ ray,
+ sd,
+ &tp,
+ rphase,
+ rscatter,
+ segment,
+ (ls.t != FLT_MAX) ? &ls.P :
+ NULL,
+ false);
+
+ /* todo: split up light_sample so we don't have to call it again with new position */
+ if (result == VOLUME_PATH_SCATTERED &&
+ light_sample(kg, light_u, light_v, sd->time, sd->P, state->bounce, &ls)) {
+ /* sample random light */
+ float terminate = path_state_rng_light_termination(kg, state);
+ if (direct_emission(
+ kg, sd, emission_sd, &ls, state, &light_ray, &L_light, &is_lamp, terminate)) {
+ /* trace shadow ray */
+ float3 shadow;
+
+ if (!shadow_blocked(kg, sd, emission_sd, state, &light_ray, &shadow)) {
+ /* accumulate */
+ path_radiance_accum_light(L, state, tp, &L_light, shadow, 1.0f, is_lamp);
+ }
+ }
+ }
+ }
+# endif /* __EMISSION__ */
}
-#endif /* __SPLIT_KERNEL__ */
+# endif /* __SPLIT_KERNEL__ */
-#endif /* __VOLUME_SCATTER__ */
+#endif /* __VOLUME_SCATTER__ */
CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/kernel_profiling.h b/intern/cycles/kernel/kernel_profiling.h
index a46d6376473..780830879d8 100644
--- a/intern/cycles/kernel/kernel_profiling.h
+++ b/intern/cycles/kernel/kernel_profiling.h
@@ -26,15 +26,21 @@ CCL_NAMESPACE_BEGIN
#ifdef __KERNEL_CPU__
# define PROFILING_INIT(kg, event) ProfilingHelper profiling_helper(&kg->profiler, event)
# define PROFILING_EVENT(event) profiling_helper.set_event(event)
-# define PROFILING_SHADER(shader) if((shader) != SHADER_NONE) { profiling_helper.set_shader((shader) & SHADER_MASK); }
-# define PROFILING_OBJECT(object) if((object) != PRIM_NONE) { profiling_helper.set_object(object); }
+# define PROFILING_SHADER(shader) \
+ if ((shader) != SHADER_NONE) { \
+ profiling_helper.set_shader((shader)&SHADER_MASK); \
+ }
+# define PROFILING_OBJECT(object) \
+ if ((object) != PRIM_NONE) { \
+ profiling_helper.set_object(object); \
+ }
#else
# define PROFILING_INIT(kg, event)
# define PROFILING_EVENT(event)
# define PROFILING_SHADER(shader)
# define PROFILING_OBJECT(object)
-#endif /* __KERNEL_CPU__ */
+#endif /* __KERNEL_CPU__ */
CCL_NAMESPACE_END
-#endif /* __KERNEL_PROFILING_H__ */
+#endif /* __KERNEL_PROFILING_H__ */
diff --git a/intern/cycles/kernel/kernel_projection.h b/intern/cycles/kernel/kernel_projection.h
index 7bad89c831c..f74ced45fd5 100644
--- a/intern/cycles/kernel/kernel_projection.h
+++ b/intern/cycles/kernel/kernel_projection.h
@@ -39,233 +39,223 @@ CCL_NAMESPACE_BEGIN
ccl_device float2 direction_to_spherical(float3 dir)
{
- float theta = safe_acosf(dir.z);
- float phi = atan2f(dir.x, dir.y);
+ float theta = safe_acosf(dir.z);
+ float phi = atan2f(dir.x, dir.y);
- return make_float2(theta, phi);
+ return make_float2(theta, phi);
}
ccl_device float3 spherical_to_direction(float theta, float phi)
{
- float sin_theta = sinf(theta);
- return make_float3(sin_theta*cosf(phi),
- sin_theta*sinf(phi),
- cosf(theta));
+ float sin_theta = sinf(theta);
+ return make_float3(sin_theta * cosf(phi), sin_theta * sinf(phi), cosf(theta));
}
/* Equirectangular coordinates <-> Cartesian direction */
ccl_device float2 direction_to_equirectangular_range(float3 dir, float4 range)
{
- if(is_zero(dir))
- return make_float2(0.0f, 0.0f);
+ if (is_zero(dir))
+ return make_float2(0.0f, 0.0f);
- float u = (atan2f(dir.y, dir.x) - range.y) / range.x;
- float v = (acosf(dir.z / len(dir)) - range.w) / range.z;
+ float u = (atan2f(dir.y, dir.x) - range.y) / range.x;
+ float v = (acosf(dir.z / len(dir)) - range.w) / range.z;
- return make_float2(u, v);
+ return make_float2(u, v);
}
ccl_device float3 equirectangular_range_to_direction(float u, float v, float4 range)
{
- float phi = range.x*u + range.y;
- float theta = range.z*v + range.w;
- float sin_theta = sinf(theta);
- return make_float3(sin_theta*cosf(phi),
- sin_theta*sinf(phi),
- cosf(theta));
+ float phi = range.x * u + range.y;
+ float theta = range.z * v + range.w;
+ float sin_theta = sinf(theta);
+ return make_float3(sin_theta * cosf(phi), sin_theta * sinf(phi), cosf(theta));
}
ccl_device float2 direction_to_equirectangular(float3 dir)
{
- return direction_to_equirectangular_range(dir, make_float4(-M_2PI_F, M_PI_F, -M_PI_F, M_PI_F));
+ return direction_to_equirectangular_range(dir, make_float4(-M_2PI_F, M_PI_F, -M_PI_F, M_PI_F));
}
ccl_device float3 equirectangular_to_direction(float u, float v)
{
- return equirectangular_range_to_direction(u, v, make_float4(-M_2PI_F, M_PI_F, -M_PI_F, M_PI_F));
+ return equirectangular_range_to_direction(u, v, make_float4(-M_2PI_F, M_PI_F, -M_PI_F, M_PI_F));
}
/* Fisheye <-> Cartesian direction */
ccl_device float2 direction_to_fisheye(float3 dir, float fov)
{
- float r = atan2f(sqrtf(dir.y*dir.y + dir.z*dir.z), dir.x) / fov;
- float phi = atan2f(dir.z, dir.y);
+ float r = atan2f(sqrtf(dir.y * dir.y + dir.z * dir.z), dir.x) / fov;
+ float phi = atan2f(dir.z, dir.y);
- float u = r * cosf(phi) + 0.5f;
- float v = r * sinf(phi) + 0.5f;
+ float u = r * cosf(phi) + 0.5f;
+ float v = r * sinf(phi) + 0.5f;
- return make_float2(u, v);
+ return make_float2(u, v);
}
ccl_device float3 fisheye_to_direction(float u, float v, float fov)
{
- u = (u - 0.5f) * 2.0f;
- v = (v - 0.5f) * 2.0f;
+ u = (u - 0.5f) * 2.0f;
+ v = (v - 0.5f) * 2.0f;
- float r = sqrtf(u*u + v*v);
+ float r = sqrtf(u * u + v * v);
- if(r > 1.0f)
- return make_float3(0.0f, 0.0f, 0.0f);
+ if (r > 1.0f)
+ return make_float3(0.0f, 0.0f, 0.0f);
- float phi = safe_acosf((r != 0.0f)? u/r: 0.0f);
- float theta = r * fov * 0.5f;
+ float phi = safe_acosf((r != 0.0f) ? u / r : 0.0f);
+ float theta = r * fov * 0.5f;
- if(v < 0.0f) phi = -phi;
+ if (v < 0.0f)
+ phi = -phi;
- return make_float3(
- cosf(theta),
- -cosf(phi)*sinf(theta),
- sinf(phi)*sinf(theta)
- );
+ return make_float3(cosf(theta), -cosf(phi) * sinf(theta), sinf(phi) * sinf(theta));
}
ccl_device float2 direction_to_fisheye_equisolid(float3 dir, float lens, float width, float height)
{
- float theta = safe_acosf(dir.x);
- float r = 2.0f * lens * sinf(theta * 0.5f);
- float phi = atan2f(dir.z, dir.y);
+ float theta = safe_acosf(dir.x);
+ float r = 2.0f * lens * sinf(theta * 0.5f);
+ float phi = atan2f(dir.z, dir.y);
- float u = r * cosf(phi) / width + 0.5f;
- float v = r * sinf(phi) / height + 0.5f;
+ float u = r * cosf(phi) / width + 0.5f;
+ float v = r * sinf(phi) / height + 0.5f;
- return make_float2(u, v);
+ return make_float2(u, v);
}
-ccl_device_inline float3 fisheye_equisolid_to_direction(float u, float v,
- float lens,
- float fov,
- float width, float height)
+ccl_device_inline float3
+fisheye_equisolid_to_direction(float u, float v, float lens, float fov, float width, float height)
{
- u = (u - 0.5f) * width;
- v = (v - 0.5f) * height;
+ u = (u - 0.5f) * width;
+ v = (v - 0.5f) * height;
- float rmax = 2.0f * lens * sinf(fov * 0.25f);
- float r = sqrtf(u*u + v*v);
+ float rmax = 2.0f * lens * sinf(fov * 0.25f);
+ float r = sqrtf(u * u + v * v);
- if(r > rmax)
- return make_float3(0.0f, 0.0f, 0.0f);
+ if (r > rmax)
+ return make_float3(0.0f, 0.0f, 0.0f);
- float phi = safe_acosf((r != 0.0f)? u/r: 0.0f);
- float theta = 2.0f * asinf(r/(2.0f * lens));
+ float phi = safe_acosf((r != 0.0f) ? u / r : 0.0f);
+ float theta = 2.0f * asinf(r / (2.0f * lens));
- if(v < 0.0f) phi = -phi;
+ if (v < 0.0f)
+ phi = -phi;
- return make_float3(
- cosf(theta),
- -cosf(phi)*sinf(theta),
- sinf(phi)*sinf(theta)
- );
+ return make_float3(cosf(theta), -cosf(phi) * sinf(theta), sinf(phi) * sinf(theta));
}
/* Mirror Ball <-> Cartesion direction */
ccl_device float3 mirrorball_to_direction(float u, float v)
{
- /* point on sphere */
- float3 dir;
+ /* point on sphere */
+ float3 dir;
- dir.x = 2.0f*u - 1.0f;
- dir.z = 2.0f*v - 1.0f;
+ dir.x = 2.0f * u - 1.0f;
+ dir.z = 2.0f * v - 1.0f;
- if(dir.x*dir.x + dir.z*dir.z > 1.0f)
- return make_float3(0.0f, 0.0f, 0.0f);
+ if (dir.x * dir.x + dir.z * dir.z > 1.0f)
+ return make_float3(0.0f, 0.0f, 0.0f);
- dir.y = -sqrtf(max(1.0f - dir.x*dir.x - dir.z*dir.z, 0.0f));
+ dir.y = -sqrtf(max(1.0f - dir.x * dir.x - dir.z * dir.z, 0.0f));
- /* reflection */
- float3 I = make_float3(0.0f, -1.0f, 0.0f);
+ /* reflection */
+ float3 I = make_float3(0.0f, -1.0f, 0.0f);
- return 2.0f*dot(dir, I)*dir - I;
+ return 2.0f * dot(dir, I) * dir - I;
}
ccl_device float2 direction_to_mirrorball(float3 dir)
{
- /* inverse of mirrorball_to_direction */
- dir.y -= 1.0f;
+ /* inverse of mirrorball_to_direction */
+ dir.y -= 1.0f;
- float div = 2.0f*sqrtf(max(-0.5f*dir.y, 0.0f));
- if(div > 0.0f)
- dir /= div;
+ float div = 2.0f * sqrtf(max(-0.5f * dir.y, 0.0f));
+ if (div > 0.0f)
+ dir /= div;
- float u = 0.5f*(dir.x + 1.0f);
- float v = 0.5f*(dir.z + 1.0f);
+ float u = 0.5f * (dir.x + 1.0f);
+ float v = 0.5f * (dir.z + 1.0f);
- return make_float2(u, v);
+ return make_float2(u, v);
}
ccl_device_inline float3 panorama_to_direction(ccl_constant KernelCamera *cam, float u, float v)
{
- switch(cam->panorama_type) {
- case PANORAMA_EQUIRECTANGULAR:
- return equirectangular_range_to_direction(u, v, cam->equirectangular_range);
- case PANORAMA_MIRRORBALL:
- return mirrorball_to_direction(u, v);
- case PANORAMA_FISHEYE_EQUIDISTANT:
- return fisheye_to_direction(u, v, cam->fisheye_fov);
- case PANORAMA_FISHEYE_EQUISOLID:
- default:
- return fisheye_equisolid_to_direction(u, v, cam->fisheye_lens,
- cam->fisheye_fov, cam->sensorwidth, cam->sensorheight);
- }
+ switch (cam->panorama_type) {
+ case PANORAMA_EQUIRECTANGULAR:
+ return equirectangular_range_to_direction(u, v, cam->equirectangular_range);
+ case PANORAMA_MIRRORBALL:
+ return mirrorball_to_direction(u, v);
+ case PANORAMA_FISHEYE_EQUIDISTANT:
+ return fisheye_to_direction(u, v, cam->fisheye_fov);
+ case PANORAMA_FISHEYE_EQUISOLID:
+ default:
+ return fisheye_equisolid_to_direction(
+ u, v, cam->fisheye_lens, cam->fisheye_fov, cam->sensorwidth, cam->sensorheight);
+ }
}
ccl_device_inline float2 direction_to_panorama(ccl_constant KernelCamera *cam, float3 dir)
{
- switch(cam->panorama_type) {
- case PANORAMA_EQUIRECTANGULAR:
- return direction_to_equirectangular_range(dir, cam->equirectangular_range);
- case PANORAMA_MIRRORBALL:
- return direction_to_mirrorball(dir);
- case PANORAMA_FISHEYE_EQUIDISTANT:
- return direction_to_fisheye(dir, cam->fisheye_fov);
- case PANORAMA_FISHEYE_EQUISOLID:
- default:
- return direction_to_fisheye_equisolid(dir, cam->fisheye_lens,
- cam->sensorwidth, cam->sensorheight);
- }
+ switch (cam->panorama_type) {
+ case PANORAMA_EQUIRECTANGULAR:
+ return direction_to_equirectangular_range(dir, cam->equirectangular_range);
+ case PANORAMA_MIRRORBALL:
+ return direction_to_mirrorball(dir);
+ case PANORAMA_FISHEYE_EQUIDISTANT:
+ return direction_to_fisheye(dir, cam->fisheye_fov);
+ case PANORAMA_FISHEYE_EQUISOLID:
+ default:
+ return direction_to_fisheye_equisolid(
+ dir, cam->fisheye_lens, cam->sensorwidth, cam->sensorheight);
+ }
}
-ccl_device_inline void spherical_stereo_transform(ccl_constant KernelCamera *cam, float3 *P, float3 *D)
+ccl_device_inline void spherical_stereo_transform(ccl_constant KernelCamera *cam,
+ float3 *P,
+ float3 *D)
{
- float interocular_offset = cam->interocular_offset;
-
- /* Interocular offset of zero means either non stereo, or stereo without
- * spherical stereo. */
- kernel_assert(interocular_offset != 0.0f);
-
- if(cam->pole_merge_angle_to > 0.0f) {
- const float pole_merge_angle_from = cam->pole_merge_angle_from,
- pole_merge_angle_to = cam->pole_merge_angle_to;
- float altitude = fabsf(safe_asinf((*D).z));
- if(altitude > pole_merge_angle_to) {
- interocular_offset = 0.0f;
- }
- else if(altitude > pole_merge_angle_from) {
- float fac = (altitude - pole_merge_angle_from) / (pole_merge_angle_to - pole_merge_angle_from);
- float fade = cosf(fac * M_PI_2_F);
- interocular_offset *= fade;
- }
- }
-
- float3 up = make_float3(0.0f, 0.0f, 1.0f);
- float3 side = normalize(cross(*D, up));
- float3 stereo_offset = side * interocular_offset;
-
- *P += stereo_offset;
-
- /* Convergence distance is FLT_MAX in the case of parallel convergence mode,
- * no need to modify direction in this case either. */
- const float convergence_distance = cam->convergence_distance;
-
- if(convergence_distance != FLT_MAX)
- {
- float3 screen_offset = convergence_distance * (*D);
- *D = normalize(screen_offset - stereo_offset);
- }
+ float interocular_offset = cam->interocular_offset;
+
+ /* Interocular offset of zero means either non stereo, or stereo without
+ * spherical stereo. */
+ kernel_assert(interocular_offset != 0.0f);
+
+ if (cam->pole_merge_angle_to > 0.0f) {
+ const float pole_merge_angle_from = cam->pole_merge_angle_from,
+ pole_merge_angle_to = cam->pole_merge_angle_to;
+ float altitude = fabsf(safe_asinf((*D).z));
+ if (altitude > pole_merge_angle_to) {
+ interocular_offset = 0.0f;
+ }
+ else if (altitude > pole_merge_angle_from) {
+ float fac = (altitude - pole_merge_angle_from) /
+ (pole_merge_angle_to - pole_merge_angle_from);
+ float fade = cosf(fac * M_PI_2_F);
+ interocular_offset *= fade;
+ }
+ }
+
+ float3 up = make_float3(0.0f, 0.0f, 1.0f);
+ float3 side = normalize(cross(*D, up));
+ float3 stereo_offset = side * interocular_offset;
+
+ *P += stereo_offset;
+
+ /* Convergence distance is FLT_MAX in the case of parallel convergence mode,
+ * no need to modify direction in this case either. */
+ const float convergence_distance = cam->convergence_distance;
+
+ if (convergence_distance != FLT_MAX) {
+ float3 screen_offset = convergence_distance * (*D);
+ *D = normalize(screen_offset - stereo_offset);
+ }
}
CCL_NAMESPACE_END
-#endif /* __KERNEL_PROJECTION_CL__ */
+#endif /* __KERNEL_PROJECTION_CL__ */
diff --git a/intern/cycles/kernel/kernel_queues.h b/intern/cycles/kernel/kernel_queues.h
index de8cc4a0cef..91a39fc1465 100644
--- a/intern/cycles/kernel/kernel_queues.h
+++ b/intern/cycles/kernel/kernel_queues.h
@@ -23,24 +23,24 @@ CCL_NAMESPACE_BEGIN
* Queue utility functions for split kernel
*/
#ifdef __KERNEL_OPENCL__
-#pragma OPENCL EXTENSION cl_khr_global_int32_base_atomics : enable
-#pragma OPENCL EXTENSION cl_khr_local_int32_base_atomics : enable
+# pragma OPENCL EXTENSION cl_khr_global_int32_base_atomics : enable
+# pragma OPENCL EXTENSION cl_khr_local_int32_base_atomics : enable
#endif
/*
* Enqueue ray index into the queue
*/
ccl_device void enqueue_ray_index(
- int ray_index, /* Ray index to be enqueued. */
- int queue_number, /* Queue in which the ray index should be enqueued. */
- ccl_global int *queues, /* Buffer of all queues. */
- int queue_size, /* Size of each queue. */
- ccl_global int *queue_index) /* Array of size num_queues; Used for atomic increment. */
+ int ray_index, /* Ray index to be enqueued. */
+ int queue_number, /* Queue in which the ray index should be enqueued. */
+ ccl_global int *queues, /* Buffer of all queues. */
+ int queue_size, /* Size of each queue. */
+ ccl_global int *queue_index) /* Array of size num_queues; Used for atomic increment. */
{
- /* This thread's queue index. */
- int my_queue_index = atomic_fetch_and_inc_uint32((ccl_global uint*)&queue_index[queue_number])
- + (queue_number * queue_size);
- queues[my_queue_index] = ray_index;
+ /* This thread's queue index. */
+ int my_queue_index = atomic_fetch_and_inc_uint32((ccl_global uint *)&queue_index[queue_number]) +
+ (queue_number * queue_size);
+ queues[my_queue_index] = ray_index;
}
/*
@@ -51,96 +51,95 @@ ccl_device void enqueue_ray_index(
* is no more ray to allocate to other threads.
*/
ccl_device int get_ray_index(
- KernelGlobals *kg,
- int thread_index, /* Global thread index. */
- int queue_number, /* Queue to operate on. */
- ccl_global int *queues, /* Buffer of all queues. */
- int queuesize, /* Size of a queue. */
- int empty_queue) /* Empty the queue slot as soon as we fetch the ray index. */
+ KernelGlobals *kg,
+ int thread_index, /* Global thread index. */
+ int queue_number, /* Queue to operate on. */
+ ccl_global int *queues, /* Buffer of all queues. */
+ int queuesize, /* Size of a queue. */
+ int empty_queue) /* Empty the queue slot as soon as we fetch the ray index. */
{
- int ray_index = queues[queue_number * queuesize + thread_index];
- if(empty_queue && ray_index != QUEUE_EMPTY_SLOT) {
- queues[queue_number * queuesize + thread_index] = QUEUE_EMPTY_SLOT;
- }
- return ray_index;
+ int ray_index = queues[queue_number * queuesize + thread_index];
+ if (empty_queue && ray_index != QUEUE_EMPTY_SLOT) {
+ queues[queue_number * queuesize + thread_index] = QUEUE_EMPTY_SLOT;
+ }
+ return ray_index;
}
/* The following functions are to realize Local memory variant of enqueue ray index function. */
/* All threads should call this function. */
ccl_device void enqueue_ray_index_local(
- int ray_index, /* Ray index to enqueue. */
- int queue_number, /* Queue in which to enqueue ray index. */
- char enqueue_flag, /* True for threads whose ray index has to be enqueued. */
- int queuesize, /* queue size. */
- ccl_local_param unsigned int *local_queue_atomics, /* To to local queue atomics. */
- ccl_global int *Queue_data, /* Queues. */
- ccl_global int *Queue_index) /* To do global queue atomics. */
+ int ray_index, /* Ray index to enqueue. */
+ int queue_number, /* Queue in which to enqueue ray index. */
+ char enqueue_flag, /* True for threads whose ray index has to be enqueued. */
+ int queuesize, /* queue size. */
+ ccl_local_param unsigned int *local_queue_atomics, /* To to local queue atomics. */
+ ccl_global int *Queue_data, /* Queues. */
+ ccl_global int *Queue_index) /* To do global queue atomics. */
{
- int lidx = ccl_local_id(1) * ccl_local_size(0) + ccl_local_id(0);
-
- /* Get local queue id .*/
- unsigned int lqidx;
- if(enqueue_flag) {
- lqidx = atomic_fetch_and_inc_uint32(local_queue_atomics);
- }
- ccl_barrier(CCL_LOCAL_MEM_FENCE);
-
- /* Get global queue offset. */
- if(lidx == 0) {
- *local_queue_atomics = atomic_fetch_and_add_uint32((ccl_global uint*)&Queue_index[queue_number],
- *local_queue_atomics);
- }
- ccl_barrier(CCL_LOCAL_MEM_FENCE);
-
- /* Get global queue index and enqueue ray. */
- if(enqueue_flag) {
- unsigned int my_gqidx = queue_number * queuesize + (*local_queue_atomics) + lqidx;
- Queue_data[my_gqidx] = ray_index;
- }
+ int lidx = ccl_local_id(1) * ccl_local_size(0) + ccl_local_id(0);
+
+ /* Get local queue id .*/
+ unsigned int lqidx;
+ if (enqueue_flag) {
+ lqidx = atomic_fetch_and_inc_uint32(local_queue_atomics);
+ }
+ ccl_barrier(CCL_LOCAL_MEM_FENCE);
+
+ /* Get global queue offset. */
+ if (lidx == 0) {
+ *local_queue_atomics = atomic_fetch_and_add_uint32(
+ (ccl_global uint *)&Queue_index[queue_number], *local_queue_atomics);
+ }
+ ccl_barrier(CCL_LOCAL_MEM_FENCE);
+
+ /* Get global queue index and enqueue ray. */
+ if (enqueue_flag) {
+ unsigned int my_gqidx = queue_number * queuesize + (*local_queue_atomics) + lqidx;
+ Queue_data[my_gqidx] = ray_index;
+ }
}
ccl_device unsigned int get_local_queue_index(
- int queue_number, /* Queue in which to enqueue the ray; -1 if no queue */
- ccl_local_param unsigned int *local_queue_atomics)
+ int queue_number, /* Queue in which to enqueue the ray; -1 if no queue */
+ ccl_local_param unsigned int *local_queue_atomics)
{
- int my_lqidx = atomic_fetch_and_inc_uint32(&local_queue_atomics[queue_number]);
- return my_lqidx;
+ int my_lqidx = atomic_fetch_and_inc_uint32(&local_queue_atomics[queue_number]);
+ return my_lqidx;
}
ccl_device unsigned int get_global_per_queue_offset(
- int queue_number,
- ccl_local_param unsigned int *local_queue_atomics,
- ccl_global int* global_queue_atomics)
+ int queue_number,
+ ccl_local_param unsigned int *local_queue_atomics,
+ ccl_global int *global_queue_atomics)
{
- unsigned int queue_offset = atomic_fetch_and_add_uint32((ccl_global uint*)&global_queue_atomics[queue_number],
- local_queue_atomics[queue_number]);
- return queue_offset;
+ unsigned int queue_offset = atomic_fetch_and_add_uint32(
+ (ccl_global uint *)&global_queue_atomics[queue_number], local_queue_atomics[queue_number]);
+ return queue_offset;
}
ccl_device unsigned int get_global_queue_index(
int queue_number,
int queuesize,
unsigned int lqidx,
- ccl_local_param unsigned int * global_per_queue_offset)
+ ccl_local_param unsigned int *global_per_queue_offset)
{
- int my_gqidx = queuesize * queue_number + lqidx + global_per_queue_offset[queue_number];
- return my_gqidx;
+ int my_gqidx = queuesize * queue_number + lqidx + global_per_queue_offset[queue_number];
+ return my_gqidx;
}
-ccl_device int dequeue_ray_index(
- int queue_number,
- ccl_global int *queues,
- int queue_size,
- ccl_global int *queue_index)
+ccl_device int dequeue_ray_index(int queue_number,
+ ccl_global int *queues,
+ int queue_size,
+ ccl_global int *queue_index)
{
- int index = atomic_fetch_and_dec_uint32((ccl_global uint*)&queue_index[queue_number])-1;
+ int index = atomic_fetch_and_dec_uint32((ccl_global uint *)&queue_index[queue_number]) - 1;
- if(index < 0) {
- return QUEUE_EMPTY_SLOT;
- }
+ if (index < 0) {
+ return QUEUE_EMPTY_SLOT;
+ }
- return queues[index + queue_number * queue_size];
+ return queues[index + queue_number * queue_size];
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/kernel_random.h b/intern/cycles/kernel/kernel_random.h
index 61ddf4a4f81..6779c1f7160 100644
--- a/intern/cycles/kernel/kernel_random.h
+++ b/intern/cycles/kernel/kernel_random.h
@@ -23,7 +23,6 @@ CCL_NAMESPACE_BEGIN
* this single threaded on a CPU for repeatable results. */
//#define __DEBUG_CORRELATION__
-
/* High Dimensional Sobol.
*
* Multidimensional sobol with generator matrices. Dimension 0 and 1 are equal
@@ -36,136 +35,138 @@ CCL_NAMESPACE_BEGIN
* progressive pattern that doesn't suffer from this problem, because even
* with this offset some dimensions are quite poor.
*/
-#define SOBOL_SKIP 64
+# define SOBOL_SKIP 64
ccl_device uint sobol_dimension(KernelGlobals *kg, int index, int dimension)
{
- uint result = 0;
- uint i = index + SOBOL_SKIP;
- for(uint j = 0; i; i >>= 1, j++) {
- if(i & 1) {
- result ^= kernel_tex_fetch(__sobol_directions, 32*dimension + j);
- }
- }
- return result;
+ uint result = 0;
+ uint i = index + SOBOL_SKIP;
+ for (uint j = 0; i; i >>= 1, j++) {
+ if (i & 1) {
+ result ^= kernel_tex_fetch(__sobol_directions, 32 * dimension + j);
+ }
+ }
+ return result;
}
-#endif /* __SOBOL__ */
-
+#endif /* __SOBOL__ */
-ccl_device_forceinline float path_rng_1D(KernelGlobals *kg,
- uint rng_hash,
- int sample, int num_samples,
- int dimension)
+ccl_device_forceinline float path_rng_1D(
+ KernelGlobals *kg, uint rng_hash, int sample, int num_samples, int dimension)
{
#ifdef __DEBUG_CORRELATION__
- return (float)drand48();
+ return (float)drand48();
#endif
#ifdef __CMJ__
# ifdef __SOBOL__
- if(kernel_data.integrator.sampling_pattern == SAMPLING_PATTERN_CMJ)
+ if (kernel_data.integrator.sampling_pattern == SAMPLING_PATTERN_CMJ)
# endif
- {
- /* Correlated multi-jitter. */
- int p = rng_hash + dimension;
- return cmj_sample_1D(sample, num_samples, p);
- }
+ {
+ /* Correlated multi-jitter. */
+ int p = rng_hash + dimension;
+ return cmj_sample_1D(sample, num_samples, p);
+ }
#endif
#ifdef __SOBOL__
- /* Sobol sequence value using direction vectors. */
- uint result = sobol_dimension(kg, sample, dimension);
- float r = (float)result * (1.0f/(float)0xFFFFFFFF);
+ /* Sobol sequence value using direction vectors. */
+ uint result = sobol_dimension(kg, sample, dimension);
+ float r = (float)result * (1.0f / (float)0xFFFFFFFF);
- /* Cranly-Patterson rotation using rng seed */
- float shift;
+ /* Cranly-Patterson rotation using rng seed */
+ float shift;
- /* Hash rng with dimension to solve correlation issues.
- * See T38710, T50116.
- */
- uint tmp_rng = cmj_hash_simple(dimension, rng_hash);
- shift = tmp_rng * (1.0f/(float)0xFFFFFFFF);
+ /* Hash rng with dimension to solve correlation issues.
+ * See T38710, T50116.
+ */
+ uint tmp_rng = cmj_hash_simple(dimension, rng_hash);
+ shift = tmp_rng * (1.0f / (float)0xFFFFFFFF);
- return r + shift - floorf(r + shift);
+ return r + shift - floorf(r + shift);
#endif
}
ccl_device_forceinline void path_rng_2D(KernelGlobals *kg,
uint rng_hash,
- int sample, int num_samples,
+ int sample,
+ int num_samples,
int dimension,
- float *fx, float *fy)
+ float *fx,
+ float *fy)
{
#ifdef __DEBUG_CORRELATION__
- *fx = (float)drand48();
- *fy = (float)drand48();
- return;
+ *fx = (float)drand48();
+ *fy = (float)drand48();
+ return;
#endif
#ifdef __CMJ__
# ifdef __SOBOL__
- if(kernel_data.integrator.sampling_pattern == SAMPLING_PATTERN_CMJ)
+ if (kernel_data.integrator.sampling_pattern == SAMPLING_PATTERN_CMJ)
# endif
- {
- /* Correlated multi-jitter. */
- int p = rng_hash + dimension;
- cmj_sample_2D(sample, num_samples, p, fx, fy);
- return;
- }
+ {
+ /* Correlated multi-jitter. */
+ int p = rng_hash + dimension;
+ cmj_sample_2D(sample, num_samples, p, fx, fy);
+ return;
+ }
#endif
#ifdef __SOBOL__
- /* Sobol. */
- *fx = path_rng_1D(kg, rng_hash, sample, num_samples, dimension);
- *fy = path_rng_1D(kg, rng_hash, sample, num_samples, dimension + 1);
+ /* Sobol. */
+ *fx = path_rng_1D(kg, rng_hash, sample, num_samples, dimension);
+ *fy = path_rng_1D(kg, rng_hash, sample, num_samples, dimension + 1);
#endif
}
ccl_device_inline void path_rng_init(KernelGlobals *kg,
- int sample, int num_samples,
+ int sample,
+ int num_samples,
uint *rng_hash,
- int x, int y,
- float *fx, float *fy)
+ int x,
+ int y,
+ float *fx,
+ float *fy)
{
- /* load state */
- *rng_hash = hash_int_2d(x, y);
- *rng_hash ^= kernel_data.integrator.seed;
+ /* load state */
+ *rng_hash = hash_int_2d(x, y);
+ *rng_hash ^= kernel_data.integrator.seed;
#ifdef __DEBUG_CORRELATION__
- srand48(*rng_hash + sample);
+ srand48(*rng_hash + sample);
#endif
- if(sample == 0) {
- *fx = 0.5f;
- *fy = 0.5f;
- }
- else {
- path_rng_2D(kg, *rng_hash, sample, num_samples, PRNG_FILTER_U, fx, fy);
- }
+ if (sample == 0) {
+ *fx = 0.5f;
+ *fy = 0.5f;
+ }
+ else {
+ path_rng_2D(kg, *rng_hash, sample, num_samples, PRNG_FILTER_U, fx, fy);
+ }
}
/* Linear Congruential Generator */
ccl_device uint lcg_step_uint(uint *rng)
{
- /* implicit mod 2^32 */
- *rng = (1103515245*(*rng) + 12345);
- return *rng;
+ /* implicit mod 2^32 */
+ *rng = (1103515245 * (*rng) + 12345);
+ return *rng;
}
ccl_device float lcg_step_float(uint *rng)
{
- /* implicit mod 2^32 */
- *rng = (1103515245*(*rng) + 12345);
- return (float)*rng * (1.0f/(float)0xFFFFFFFF);
+ /* implicit mod 2^32 */
+ *rng = (1103515245 * (*rng) + 12345);
+ return (float)*rng * (1.0f / (float)0xFFFFFFFF);
}
ccl_device uint lcg_init(uint seed)
{
- uint rng = seed;
- lcg_step_uint(&rng);
- return rng;
+ uint rng = seed;
+ lcg_step_uint(&rng);
+ return rng;
}
/* Path Tracing Utility Functions
@@ -181,118 +182,107 @@ ccl_device_inline float path_state_rng_1D(KernelGlobals *kg,
const ccl_addr_space PathState *state,
int dimension)
{
- return path_rng_1D(kg,
- state->rng_hash,
- state->sample, state->num_samples,
- state->rng_offset + dimension);
+ return path_rng_1D(
+ kg, state->rng_hash, state->sample, state->num_samples, state->rng_offset + dimension);
}
-ccl_device_inline void path_state_rng_2D(KernelGlobals *kg,
- const ccl_addr_space PathState *state,
- int dimension,
- float *fx, float *fy)
+ccl_device_inline void path_state_rng_2D(
+ KernelGlobals *kg, const ccl_addr_space PathState *state, int dimension, float *fx, float *fy)
{
- path_rng_2D(kg,
- state->rng_hash,
- state->sample, state->num_samples,
- state->rng_offset + dimension,
- fx, fy);
+ path_rng_2D(kg,
+ state->rng_hash,
+ state->sample,
+ state->num_samples,
+ state->rng_offset + dimension,
+ fx,
+ fy);
}
ccl_device_inline float path_state_rng_1D_hash(KernelGlobals *kg,
- const ccl_addr_space PathState *state,
- uint hash)
+ const ccl_addr_space PathState *state,
+ uint hash)
{
- /* Use a hash instead of dimension, this is not great but avoids adding
- * more dimensions to each bounce which reduces quality of dimensions we
- * are already using. */
- return path_rng_1D(kg,
- cmj_hash_simple(state->rng_hash, hash),
- state->sample, state->num_samples,
- state->rng_offset);
+ /* Use a hash instead of dimension, this is not great but avoids adding
+ * more dimensions to each bounce which reduces quality of dimensions we
+ * are already using. */
+ return path_rng_1D(kg,
+ cmj_hash_simple(state->rng_hash, hash),
+ state->sample,
+ state->num_samples,
+ state->rng_offset);
}
-ccl_device_inline float path_branched_rng_1D(
- KernelGlobals *kg,
- uint rng_hash,
- const ccl_addr_space PathState *state,
- int branch,
- int num_branches,
- int dimension)
+ccl_device_inline float path_branched_rng_1D(KernelGlobals *kg,
+ uint rng_hash,
+ const ccl_addr_space PathState *state,
+ int branch,
+ int num_branches,
+ int dimension)
{
- return path_rng_1D(kg,
- rng_hash,
- state->sample * num_branches + branch,
- state->num_samples * num_branches,
- state->rng_offset + dimension);
+ return path_rng_1D(kg,
+ rng_hash,
+ state->sample * num_branches + branch,
+ state->num_samples * num_branches,
+ state->rng_offset + dimension);
}
-ccl_device_inline void path_branched_rng_2D(
- KernelGlobals *kg,
- uint rng_hash,
- const ccl_addr_space PathState *state,
- int branch,
- int num_branches,
- int dimension,
- float *fx, float *fy)
+ccl_device_inline void path_branched_rng_2D(KernelGlobals *kg,
+ uint rng_hash,
+ const ccl_addr_space PathState *state,
+ int branch,
+ int num_branches,
+ int dimension,
+ float *fx,
+ float *fy)
{
- path_rng_2D(kg,
- rng_hash,
- state->sample * num_branches + branch,
- state->num_samples * num_branches,
- state->rng_offset + dimension,
- fx, fy);
+ path_rng_2D(kg,
+ rng_hash,
+ state->sample * num_branches + branch,
+ state->num_samples * num_branches,
+ state->rng_offset + dimension,
+ fx,
+ fy);
}
/* Utitility functions to get light termination value,
* since it might not be needed in many cases.
*/
-ccl_device_inline float path_state_rng_light_termination(
- KernelGlobals *kg,
- const ccl_addr_space PathState *state)
+ccl_device_inline float path_state_rng_light_termination(KernelGlobals *kg,
+ const ccl_addr_space PathState *state)
{
- if(kernel_data.integrator.light_inv_rr_threshold > 0.0f) {
- return path_state_rng_1D(kg, state, PRNG_LIGHT_TERMINATE);
- }
- return 0.0f;
+ if (kernel_data.integrator.light_inv_rr_threshold > 0.0f) {
+ return path_state_rng_1D(kg, state, PRNG_LIGHT_TERMINATE);
+ }
+ return 0.0f;
}
-ccl_device_inline float path_branched_rng_light_termination(
- KernelGlobals *kg,
- uint rng_hash,
- const ccl_addr_space PathState *state,
- int branch,
- int num_branches)
+ccl_device_inline float path_branched_rng_light_termination(KernelGlobals *kg,
+ uint rng_hash,
+ const ccl_addr_space PathState *state,
+ int branch,
+ int num_branches)
{
- if(kernel_data.integrator.light_inv_rr_threshold > 0.0f) {
- return path_branched_rng_1D(kg,
- rng_hash,
- state,
- branch,
- num_branches,
- PRNG_LIGHT_TERMINATE);
- }
- return 0.0f;
+ if (kernel_data.integrator.light_inv_rr_threshold > 0.0f) {
+ return path_branched_rng_1D(kg, rng_hash, state, branch, num_branches, PRNG_LIGHT_TERMINATE);
+ }
+ return 0.0f;
}
-ccl_device_inline uint lcg_state_init(PathState *state,
- uint scramble)
+ccl_device_inline uint lcg_state_init(PathState *state, uint scramble)
{
- return lcg_init(state->rng_hash + state->rng_offset + state->sample*scramble);
+ return lcg_init(state->rng_hash + state->rng_offset + state->sample * scramble);
}
-ccl_device_inline uint lcg_state_init_addrspace(ccl_addr_space PathState *state,
- uint scramble)
+ccl_device_inline uint lcg_state_init_addrspace(ccl_addr_space PathState *state, uint scramble)
{
- return lcg_init(state->rng_hash + state->rng_offset + state->sample*scramble);
+ return lcg_init(state->rng_hash + state->rng_offset + state->sample * scramble);
}
-
ccl_device float lcg_step_float_addrspace(ccl_addr_space uint *rng)
{
- /* Implicit mod 2^32 */
- *rng = (1103515245*(*rng) + 12345);
- return (float)*rng * (1.0f/(float)0xFFFFFFFF);
+ /* Implicit mod 2^32 */
+ *rng = (1103515245 * (*rng) + 12345);
+ return (float)*rng * (1.0f / (float)0xFFFFFFFF);
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/kernel_shader.h b/intern/cycles/kernel/kernel_shader.h
index b1da523501d..351b623addb 100644
--- a/intern/cycles/kernel/kernel_shader.h
+++ b/intern/cycles/kernel/kernel_shader.h
@@ -37,14 +37,14 @@ CCL_NAMESPACE_BEGIN
#ifdef __OBJECT_MOTION__
ccl_device void shader_setup_object_transforms(KernelGlobals *kg, ShaderData *sd, float time)
{
- if(sd->object_flag & SD_OBJECT_MOTION) {
- sd->ob_tfm = object_fetch_transform_motion(kg, sd->object, time);
- sd->ob_itfm = transform_quick_inverse(sd->ob_tfm);
- }
- else {
- sd->ob_tfm = object_fetch_transform(kg, sd->object, OBJECT_TRANSFORM);
- sd->ob_itfm = object_fetch_transform(kg, sd->object, OBJECT_INVERSE_TRANSFORM);
- }
+ if (sd->object_flag & SD_OBJECT_MOTION) {
+ sd->ob_tfm = object_fetch_transform_motion(kg, sd->object, time);
+ sd->ob_itfm = transform_quick_inverse(sd->ob_tfm);
+ }
+ else {
+ sd->ob_tfm = object_fetch_transform(kg, sd->object, OBJECT_TRANSFORM);
+ sd->ob_itfm = object_fetch_transform(kg, sd->object, OBJECT_INVERSE_TRANSFORM);
+ }
}
#endif
@@ -53,104 +53,104 @@ ccl_device_noinline void shader_setup_from_ray(KernelGlobals *kg,
const Intersection *isect,
const Ray *ray)
{
- PROFILING_INIT(kg, PROFILING_SHADER_SETUP);
+ PROFILING_INIT(kg, PROFILING_SHADER_SETUP);
#ifdef __INSTANCING__
- sd->object = (isect->object == OBJECT_NONE)? kernel_tex_fetch(__prim_object, isect->prim): isect->object;
+ sd->object = (isect->object == OBJECT_NONE) ? kernel_tex_fetch(__prim_object, isect->prim) :
+ isect->object;
#endif
- sd->lamp = LAMP_NONE;
+ sd->lamp = LAMP_NONE;
- sd->type = isect->type;
- sd->flag = 0;
- sd->object_flag = kernel_tex_fetch(__object_flag,
- sd->object);
+ sd->type = isect->type;
+ sd->flag = 0;
+ sd->object_flag = kernel_tex_fetch(__object_flag, sd->object);
- /* matrices and time */
+ /* matrices and time */
#ifdef __OBJECT_MOTION__
- shader_setup_object_transforms(kg, sd, ray->time);
+ shader_setup_object_transforms(kg, sd, ray->time);
#endif
- sd->time = ray->time;
+ sd->time = ray->time;
- sd->prim = kernel_tex_fetch(__prim_index, isect->prim);
- sd->ray_length = isect->t;
+ sd->prim = kernel_tex_fetch(__prim_index, isect->prim);
+ sd->ray_length = isect->t;
#ifdef __UV__
- sd->u = isect->u;
- sd->v = isect->v;
+ sd->u = isect->u;
+ sd->v = isect->v;
#endif
#ifdef __HAIR__
- if(sd->type & PRIMITIVE_ALL_CURVE) {
- /* curve */
- float4 curvedata = kernel_tex_fetch(__curves, sd->prim);
-
- sd->shader = __float_as_int(curvedata.z);
- sd->P = curve_refine(kg, sd, isect, ray);
- }
- else
+ if (sd->type & PRIMITIVE_ALL_CURVE) {
+ /* curve */
+ float4 curvedata = kernel_tex_fetch(__curves, sd->prim);
+
+ sd->shader = __float_as_int(curvedata.z);
+ sd->P = curve_refine(kg, sd, isect, ray);
+ }
+ else
#endif
- if(sd->type & PRIMITIVE_TRIANGLE) {
- /* static triangle */
- float3 Ng = triangle_normal(kg, sd);
- sd->shader = kernel_tex_fetch(__tri_shader, sd->prim);
+ if (sd->type & PRIMITIVE_TRIANGLE) {
+ /* static triangle */
+ float3 Ng = triangle_normal(kg, sd);
+ sd->shader = kernel_tex_fetch(__tri_shader, sd->prim);
- /* vectors */
- sd->P = triangle_refine(kg, sd, isect, ray);
- sd->Ng = Ng;
- sd->N = Ng;
+ /* vectors */
+ sd->P = triangle_refine(kg, sd, isect, ray);
+ sd->Ng = Ng;
+ sd->N = Ng;
- /* smooth normal */
- if(sd->shader & SHADER_SMOOTH_NORMAL)
- sd->N = triangle_smooth_normal(kg, Ng, sd->prim, sd->u, sd->v);
+ /* smooth normal */
+ if (sd->shader & SHADER_SMOOTH_NORMAL)
+ sd->N = triangle_smooth_normal(kg, Ng, sd->prim, sd->u, sd->v);
#ifdef __DPDU__
- /* dPdu/dPdv */
- triangle_dPdudv(kg, sd->prim, &sd->dPdu, &sd->dPdv);
+ /* dPdu/dPdv */
+ triangle_dPdudv(kg, sd->prim, &sd->dPdu, &sd->dPdv);
#endif
- }
- else {
- /* motion triangle */
- motion_triangle_shader_setup(kg, sd, isect, ray, false);
- }
+ }
+ else {
+ /* motion triangle */
+ motion_triangle_shader_setup(kg, sd, isect, ray, false);
+ }
- sd->I = -ray->D;
+ sd->I = -ray->D;
- sd->flag |= kernel_tex_fetch(__shaders, (sd->shader & SHADER_MASK)).flags;
+ sd->flag |= kernel_tex_fetch(__shaders, (sd->shader & SHADER_MASK)).flags;
#ifdef __INSTANCING__
- if(isect->object != OBJECT_NONE) {
- /* instance transform */
- object_normal_transform_auto(kg, sd, &sd->N);
- object_normal_transform_auto(kg, sd, &sd->Ng);
+ if (isect->object != OBJECT_NONE) {
+ /* instance transform */
+ object_normal_transform_auto(kg, sd, &sd->N);
+ object_normal_transform_auto(kg, sd, &sd->Ng);
# ifdef __DPDU__
- object_dir_transform_auto(kg, sd, &sd->dPdu);
- object_dir_transform_auto(kg, sd, &sd->dPdv);
+ object_dir_transform_auto(kg, sd, &sd->dPdu);
+ object_dir_transform_auto(kg, sd, &sd->dPdv);
# endif
- }
+ }
#endif
- /* backfacing test */
- bool backfacing = (dot(sd->Ng, sd->I) < 0.0f);
+ /* backfacing test */
+ bool backfacing = (dot(sd->Ng, sd->I) < 0.0f);
- if(backfacing) {
- sd->flag |= SD_BACKFACING;
- sd->Ng = -sd->Ng;
- sd->N = -sd->N;
+ if (backfacing) {
+ sd->flag |= SD_BACKFACING;
+ sd->Ng = -sd->Ng;
+ sd->N = -sd->N;
#ifdef __DPDU__
- sd->dPdu = -sd->dPdu;
- sd->dPdv = -sd->dPdv;
+ sd->dPdu = -sd->dPdu;
+ sd->dPdv = -sd->dPdv;
#endif
- }
+ }
#ifdef __RAY_DIFFERENTIALS__
- /* differentials */
- differential_transfer(&sd->dP, ray->dP, ray->D, ray->dD, sd->Ng, isect->t);
- differential_incoming(&sd->dI, ray->dD);
- differential_dudv(&sd->du, &sd->dv, sd->dPdu, sd->dPdv, sd->dP, sd->Ng);
+ /* differentials */
+ differential_transfer(&sd->dP, ray->dP, ray->D, ray->dD, sd->Ng, isect->t);
+ differential_incoming(&sd->dI, ray->dD);
+ differential_dudv(&sd->du, &sd->dv, sd->dPdu, sd->dPdv, sd->dP, sd->Ng);
#endif
- PROFILING_SHADER(sd->shader);
- PROFILING_OBJECT(sd->object);
+ PROFILING_SHADER(sd->shader);
+ PROFILING_OBJECT(sd->object);
}
/* ShaderData setup from BSSRDF scatter */
@@ -161,86 +161,86 @@ ccl_device
# else
ccl_device_inline
# endif
-void shader_setup_from_subsurface(
- KernelGlobals *kg,
- ShaderData *sd,
- const Intersection *isect,
- const Ray *ray)
+ void
+ shader_setup_from_subsurface(KernelGlobals *kg,
+ ShaderData *sd,
+ const Intersection *isect,
+ const Ray *ray)
{
- PROFILING_INIT(kg, PROFILING_SHADER_SETUP);
+ PROFILING_INIT(kg, PROFILING_SHADER_SETUP);
- const bool backfacing = sd->flag & SD_BACKFACING;
+ const bool backfacing = sd->flag & SD_BACKFACING;
- /* object, matrices, time, ray_length stay the same */
- sd->flag = 0;
- sd->object_flag = kernel_tex_fetch(__object_flag, sd->object);
- sd->prim = kernel_tex_fetch(__prim_index, isect->prim);
- sd->type = isect->type;
+ /* object, matrices, time, ray_length stay the same */
+ sd->flag = 0;
+ sd->object_flag = kernel_tex_fetch(__object_flag, sd->object);
+ sd->prim = kernel_tex_fetch(__prim_index, isect->prim);
+ sd->type = isect->type;
# ifdef __UV__
- sd->u = isect->u;
- sd->v = isect->v;
+ sd->u = isect->u;
+ sd->v = isect->v;
# endif
- /* fetch triangle data */
- if(sd->type == PRIMITIVE_TRIANGLE) {
- float3 Ng = triangle_normal(kg, sd);
- sd->shader = kernel_tex_fetch(__tri_shader, sd->prim);
+ /* fetch triangle data */
+ if (sd->type == PRIMITIVE_TRIANGLE) {
+ float3 Ng = triangle_normal(kg, sd);
+ sd->shader = kernel_tex_fetch(__tri_shader, sd->prim);
- /* static triangle */
- sd->P = triangle_refine_local(kg, sd, isect, ray);
- sd->Ng = Ng;
- sd->N = Ng;
+ /* static triangle */
+ sd->P = triangle_refine_local(kg, sd, isect, ray);
+ sd->Ng = Ng;
+ sd->N = Ng;
- if(sd->shader & SHADER_SMOOTH_NORMAL)
- sd->N = triangle_smooth_normal(kg, Ng, sd->prim, sd->u, sd->v);
+ if (sd->shader & SHADER_SMOOTH_NORMAL)
+ sd->N = triangle_smooth_normal(kg, Ng, sd->prim, sd->u, sd->v);
# ifdef __DPDU__
- /* dPdu/dPdv */
- triangle_dPdudv(kg, sd->prim, &sd->dPdu, &sd->dPdv);
+ /* dPdu/dPdv */
+ triangle_dPdudv(kg, sd->prim, &sd->dPdu, &sd->dPdv);
# endif
- }
- else {
- /* motion triangle */
- motion_triangle_shader_setup(kg, sd, isect, ray, true);
- }
+ }
+ else {
+ /* motion triangle */
+ motion_triangle_shader_setup(kg, sd, isect, ray, true);
+ }
- sd->flag |= kernel_tex_fetch(__shaders, (sd->shader & SHADER_MASK)).flags;
+ sd->flag |= kernel_tex_fetch(__shaders, (sd->shader & SHADER_MASK)).flags;
# ifdef __INSTANCING__
- if(isect->object != OBJECT_NONE) {
- /* instance transform */
- object_normal_transform_auto(kg, sd, &sd->N);
- object_normal_transform_auto(kg, sd, &sd->Ng);
+ if (isect->object != OBJECT_NONE) {
+ /* instance transform */
+ object_normal_transform_auto(kg, sd, &sd->N);
+ object_normal_transform_auto(kg, sd, &sd->Ng);
# ifdef __DPDU__
- object_dir_transform_auto(kg, sd, &sd->dPdu);
- object_dir_transform_auto(kg, sd, &sd->dPdv);
+ object_dir_transform_auto(kg, sd, &sd->dPdu);
+ object_dir_transform_auto(kg, sd, &sd->dPdv);
# endif
- }
+ }
# endif
- /* backfacing test */
- if(backfacing) {
- sd->flag |= SD_BACKFACING;
- sd->Ng = -sd->Ng;
- sd->N = -sd->N;
+ /* backfacing test */
+ if (backfacing) {
+ sd->flag |= SD_BACKFACING;
+ sd->Ng = -sd->Ng;
+ sd->N = -sd->N;
# ifdef __DPDU__
- sd->dPdu = -sd->dPdu;
- sd->dPdv = -sd->dPdv;
+ sd->dPdu = -sd->dPdu;
+ sd->dPdv = -sd->dPdv;
# endif
- }
+ }
- /* should not get used in principle as the shading will only use a diffuse
- * BSDF, but the shader might still access it */
- sd->I = sd->N;
+ /* should not get used in principle as the shading will only use a diffuse
+ * BSDF, but the shader might still access it */
+ sd->I = sd->N;
# ifdef __RAY_DIFFERENTIALS__
- /* differentials */
- differential_dudv(&sd->du, &sd->dv, sd->dPdu, sd->dPdv, sd->dP, sd->Ng);
- /* don't modify dP and dI */
+ /* differentials */
+ differential_dudv(&sd->du, &sd->dv, sd->dPdu, sd->dPdv, sd->dP, sd->Ng);
+ /* don't modify dP and dI */
# endif
- PROFILING_SHADER(sd->shader);
+ PROFILING_SHADER(sd->shader);
}
#endif
@@ -251,194 +251,208 @@ ccl_device_inline void shader_setup_from_sample(KernelGlobals *kg,
const float3 P,
const float3 Ng,
const float3 I,
- int shader, int object, int prim,
- float u, float v, float t,
+ int shader,
+ int object,
+ int prim,
+ float u,
+ float v,
+ float t,
float time,
bool object_space,
int lamp)
{
- PROFILING_INIT(kg, PROFILING_SHADER_SETUP);
-
- /* vectors */
- sd->P = P;
- sd->N = Ng;
- sd->Ng = Ng;
- sd->I = I;
- sd->shader = shader;
- if(prim != PRIM_NONE)
- sd->type = PRIMITIVE_TRIANGLE;
- else if(lamp != LAMP_NONE)
- sd->type = PRIMITIVE_LAMP;
- else
- sd->type = PRIMITIVE_NONE;
-
- /* primitive */
+ PROFILING_INIT(kg, PROFILING_SHADER_SETUP);
+
+ /* vectors */
+ sd->P = P;
+ sd->N = Ng;
+ sd->Ng = Ng;
+ sd->I = I;
+ sd->shader = shader;
+ if (prim != PRIM_NONE)
+ sd->type = PRIMITIVE_TRIANGLE;
+ else if (lamp != LAMP_NONE)
+ sd->type = PRIMITIVE_LAMP;
+ else
+ sd->type = PRIMITIVE_NONE;
+
+ /* primitive */
#ifdef __INSTANCING__
- sd->object = object;
+ sd->object = object;
#endif
- sd->lamp = LAMP_NONE;
- /* currently no access to bvh prim index for strand sd->prim*/
- sd->prim = prim;
+ sd->lamp = LAMP_NONE;
+ /* currently no access to bvh prim index for strand sd->prim*/
+ sd->prim = prim;
#ifdef __UV__
- sd->u = u;
- sd->v = v;
+ sd->u = u;
+ sd->v = v;
#endif
- sd->time = time;
- sd->ray_length = t;
+ sd->time = time;
+ sd->ray_length = t;
- sd->flag = kernel_tex_fetch(__shaders, (sd->shader & SHADER_MASK)).flags;
- sd->object_flag = 0;
- if(sd->object != OBJECT_NONE) {
- sd->object_flag |= kernel_tex_fetch(__object_flag,
- sd->object);
+ sd->flag = kernel_tex_fetch(__shaders, (sd->shader & SHADER_MASK)).flags;
+ sd->object_flag = 0;
+ if (sd->object != OBJECT_NONE) {
+ sd->object_flag |= kernel_tex_fetch(__object_flag, sd->object);
#ifdef __OBJECT_MOTION__
- shader_setup_object_transforms(kg, sd, time);
- }
- else if(lamp != LAMP_NONE) {
- sd->ob_tfm = lamp_fetch_transform(kg, lamp, false);
- sd->ob_itfm = lamp_fetch_transform(kg, lamp, true);
- sd->lamp = lamp;
+ shader_setup_object_transforms(kg, sd, time);
+ }
+ else if (lamp != LAMP_NONE) {
+ sd->ob_tfm = lamp_fetch_transform(kg, lamp, false);
+ sd->ob_itfm = lamp_fetch_transform(kg, lamp, true);
+ sd->lamp = lamp;
#else
- }
- else if(lamp != LAMP_NONE) {
- sd->lamp = lamp;
+ }
+ else if (lamp != LAMP_NONE) {
+ sd->lamp = lamp;
#endif
- }
+ }
- /* transform into world space */
- if(object_space) {
- object_position_transform_auto(kg, sd, &sd->P);
- object_normal_transform_auto(kg, sd, &sd->Ng);
- sd->N = sd->Ng;
- object_dir_transform_auto(kg, sd, &sd->I);
- }
+ /* transform into world space */
+ if (object_space) {
+ object_position_transform_auto(kg, sd, &sd->P);
+ object_normal_transform_auto(kg, sd, &sd->Ng);
+ sd->N = sd->Ng;
+ object_dir_transform_auto(kg, sd, &sd->I);
+ }
- if(sd->type & PRIMITIVE_TRIANGLE) {
- /* smooth normal */
- if(sd->shader & SHADER_SMOOTH_NORMAL) {
- sd->N = triangle_smooth_normal(kg, Ng, sd->prim, sd->u, sd->v);
+ if (sd->type & PRIMITIVE_TRIANGLE) {
+ /* smooth normal */
+ if (sd->shader & SHADER_SMOOTH_NORMAL) {
+ sd->N = triangle_smooth_normal(kg, Ng, sd->prim, sd->u, sd->v);
#ifdef __INSTANCING__
- if(!(sd->object_flag & SD_OBJECT_TRANSFORM_APPLIED)) {
- object_normal_transform_auto(kg, sd, &sd->N);
- }
+ if (!(sd->object_flag & SD_OBJECT_TRANSFORM_APPLIED)) {
+ object_normal_transform_auto(kg, sd, &sd->N);
+ }
#endif
- }
+ }
- /* dPdu/dPdv */
+ /* dPdu/dPdv */
#ifdef __DPDU__
- triangle_dPdudv(kg, sd->prim, &sd->dPdu, &sd->dPdv);
+ triangle_dPdudv(kg, sd->prim, &sd->dPdu, &sd->dPdv);
# ifdef __INSTANCING__
- if(!(sd->object_flag & SD_OBJECT_TRANSFORM_APPLIED)) {
- object_dir_transform_auto(kg, sd, &sd->dPdu);
- object_dir_transform_auto(kg, sd, &sd->dPdv);
- }
+ if (!(sd->object_flag & SD_OBJECT_TRANSFORM_APPLIED)) {
+ object_dir_transform_auto(kg, sd, &sd->dPdu);
+ object_dir_transform_auto(kg, sd, &sd->dPdv);
+ }
# endif
#endif
- }
- else {
+ }
+ else {
#ifdef __DPDU__
- sd->dPdu = make_float3(0.0f, 0.0f, 0.0f);
- sd->dPdv = make_float3(0.0f, 0.0f, 0.0f);
+ sd->dPdu = make_float3(0.0f, 0.0f, 0.0f);
+ sd->dPdv = make_float3(0.0f, 0.0f, 0.0f);
#endif
- }
+ }
- /* backfacing test */
- if(sd->prim != PRIM_NONE) {
- bool backfacing = (dot(sd->Ng, sd->I) < 0.0f);
+ /* backfacing test */
+ if (sd->prim != PRIM_NONE) {
+ bool backfacing = (dot(sd->Ng, sd->I) < 0.0f);
- if(backfacing) {
- sd->flag |= SD_BACKFACING;
- sd->Ng = -sd->Ng;
- sd->N = -sd->N;
+ if (backfacing) {
+ sd->flag |= SD_BACKFACING;
+ sd->Ng = -sd->Ng;
+ sd->N = -sd->N;
#ifdef __DPDU__
- sd->dPdu = -sd->dPdu;
- sd->dPdv = -sd->dPdv;
+ sd->dPdu = -sd->dPdu;
+ sd->dPdv = -sd->dPdv;
#endif
- }
- }
+ }
+ }
#ifdef __RAY_DIFFERENTIALS__
- /* no ray differentials here yet */
- sd->dP = differential3_zero();
- sd->dI = differential3_zero();
- sd->du = differential_zero();
- sd->dv = differential_zero();
+ /* no ray differentials here yet */
+ sd->dP = differential3_zero();
+ sd->dI = differential3_zero();
+ sd->du = differential_zero();
+ sd->dv = differential_zero();
#endif
- PROFILING_SHADER(sd->shader);
- PROFILING_OBJECT(sd->object);
+ PROFILING_SHADER(sd->shader);
+ PROFILING_OBJECT(sd->object);
}
/* ShaderData setup for displacement */
-ccl_device void shader_setup_from_displace(KernelGlobals *kg, ShaderData *sd,
- int object, int prim, float u, float v)
+ccl_device void shader_setup_from_displace(
+ KernelGlobals *kg, ShaderData *sd, int object, int prim, float u, float v)
{
- float3 P, Ng, I = make_float3(0.0f, 0.0f, 0.0f);
- int shader;
-
- triangle_point_normal(kg, object, prim, u, v, &P, &Ng, &shader);
-
- /* force smooth shading for displacement */
- shader |= SHADER_SMOOTH_NORMAL;
-
- shader_setup_from_sample(kg, sd,
- P, Ng, I,
- shader, object, prim,
- u, v, 0.0f, 0.5f,
- !(kernel_tex_fetch(__object_flag, object) & SD_OBJECT_TRANSFORM_APPLIED),
- LAMP_NONE);
+ float3 P, Ng, I = make_float3(0.0f, 0.0f, 0.0f);
+ int shader;
+
+ triangle_point_normal(kg, object, prim, u, v, &P, &Ng, &shader);
+
+ /* force smooth shading for displacement */
+ shader |= SHADER_SMOOTH_NORMAL;
+
+ shader_setup_from_sample(
+ kg,
+ sd,
+ P,
+ Ng,
+ I,
+ shader,
+ object,
+ prim,
+ u,
+ v,
+ 0.0f,
+ 0.5f,
+ !(kernel_tex_fetch(__object_flag, object) & SD_OBJECT_TRANSFORM_APPLIED),
+ LAMP_NONE);
}
/* ShaderData setup from ray into background */
-ccl_device_inline void shader_setup_from_background(KernelGlobals *kg, ShaderData *sd, const Ray *ray)
+ccl_device_inline void shader_setup_from_background(KernelGlobals *kg,
+ ShaderData *sd,
+ const Ray *ray)
{
- PROFILING_INIT(kg, PROFILING_SHADER_SETUP);
-
- /* vectors */
- sd->P = ray->D;
- sd->N = -ray->D;
- sd->Ng = -ray->D;
- sd->I = -ray->D;
- sd->shader = kernel_data.background.surface_shader;
- sd->flag = kernel_tex_fetch(__shaders, (sd->shader & SHADER_MASK)).flags;
- sd->object_flag = 0;
- sd->time = ray->time;
- sd->ray_length = 0.0f;
+ PROFILING_INIT(kg, PROFILING_SHADER_SETUP);
+
+ /* vectors */
+ sd->P = ray->D;
+ sd->N = -ray->D;
+ sd->Ng = -ray->D;
+ sd->I = -ray->D;
+ sd->shader = kernel_data.background.surface_shader;
+ sd->flag = kernel_tex_fetch(__shaders, (sd->shader & SHADER_MASK)).flags;
+ sd->object_flag = 0;
+ sd->time = ray->time;
+ sd->ray_length = 0.0f;
#ifdef __INSTANCING__
- sd->object = OBJECT_NONE;
+ sd->object = OBJECT_NONE;
#endif
- sd->lamp = LAMP_NONE;
- sd->prim = PRIM_NONE;
+ sd->lamp = LAMP_NONE;
+ sd->prim = PRIM_NONE;
#ifdef __UV__
- sd->u = 0.0f;
- sd->v = 0.0f;
+ sd->u = 0.0f;
+ sd->v = 0.0f;
#endif
#ifdef __DPDU__
- /* dPdu/dPdv */
- sd->dPdu = make_float3(0.0f, 0.0f, 0.0f);
- sd->dPdv = make_float3(0.0f, 0.0f, 0.0f);
+ /* dPdu/dPdv */
+ sd->dPdu = make_float3(0.0f, 0.0f, 0.0f);
+ sd->dPdv = make_float3(0.0f, 0.0f, 0.0f);
#endif
#ifdef __RAY_DIFFERENTIALS__
- /* differentials */
- sd->dP = ray->dD;
- differential_incoming(&sd->dI, sd->dP);
- sd->du = differential_zero();
- sd->dv = differential_zero();
+ /* differentials */
+ sd->dP = ray->dD;
+ differential_incoming(&sd->dI, sd->dP);
+ sd->du = differential_zero();
+ sd->dv = differential_zero();
#endif
- /* for NDC coordinates */
- sd->ray_P = ray->P;
+ /* for NDC coordinates */
+ sd->ray_P = ray->P;
- PROFILING_SHADER(sd->shader);
- PROFILING_OBJECT(sd->object);
+ PROFILING_SHADER(sd->shader);
+ PROFILING_OBJECT(sd->object);
}
/* ShaderData setup from point inside volume */
@@ -446,141 +460,145 @@ ccl_device_inline void shader_setup_from_background(KernelGlobals *kg, ShaderDat
#ifdef __VOLUME__
ccl_device_inline void shader_setup_from_volume(KernelGlobals *kg, ShaderData *sd, const Ray *ray)
{
- PROFILING_INIT(kg, PROFILING_SHADER_SETUP);
-
- /* vectors */
- sd->P = ray->P;
- sd->N = -ray->D;
- sd->Ng = -ray->D;
- sd->I = -ray->D;
- sd->shader = SHADER_NONE;
- sd->flag = 0;
- sd->object_flag = 0;
- sd->time = ray->time;
- sd->ray_length = 0.0f; /* todo: can we set this to some useful value? */
+ PROFILING_INIT(kg, PROFILING_SHADER_SETUP);
+
+ /* vectors */
+ sd->P = ray->P;
+ sd->N = -ray->D;
+ sd->Ng = -ray->D;
+ sd->I = -ray->D;
+ sd->shader = SHADER_NONE;
+ sd->flag = 0;
+ sd->object_flag = 0;
+ sd->time = ray->time;
+ sd->ray_length = 0.0f; /* todo: can we set this to some useful value? */
# ifdef __INSTANCING__
- sd->object = OBJECT_NONE; /* todo: fill this for texture coordinates */
+ sd->object = OBJECT_NONE; /* todo: fill this for texture coordinates */
# endif
- sd->lamp = LAMP_NONE;
- sd->prim = PRIM_NONE;
- sd->type = PRIMITIVE_NONE;
+ sd->lamp = LAMP_NONE;
+ sd->prim = PRIM_NONE;
+ sd->type = PRIMITIVE_NONE;
# ifdef __UV__
- sd->u = 0.0f;
- sd->v = 0.0f;
+ sd->u = 0.0f;
+ sd->v = 0.0f;
# endif
# ifdef __DPDU__
- /* dPdu/dPdv */
- sd->dPdu = make_float3(0.0f, 0.0f, 0.0f);
- sd->dPdv = make_float3(0.0f, 0.0f, 0.0f);
+ /* dPdu/dPdv */
+ sd->dPdu = make_float3(0.0f, 0.0f, 0.0f);
+ sd->dPdv = make_float3(0.0f, 0.0f, 0.0f);
# endif
# ifdef __RAY_DIFFERENTIALS__
- /* differentials */
- sd->dP = ray->dD;
- differential_incoming(&sd->dI, sd->dP);
- sd->du = differential_zero();
- sd->dv = differential_zero();
+ /* differentials */
+ sd->dP = ray->dD;
+ differential_incoming(&sd->dI, sd->dP);
+ sd->du = differential_zero();
+ sd->dv = differential_zero();
# endif
- /* for NDC coordinates */
- sd->ray_P = ray->P;
- sd->ray_dP = ray->dP;
+ /* for NDC coordinates */
+ sd->ray_P = ray->P;
+ sd->ray_dP = ray->dP;
- PROFILING_SHADER(sd->shader);
- PROFILING_OBJECT(sd->object);
+ PROFILING_SHADER(sd->shader);
+ PROFILING_OBJECT(sd->object);
}
-#endif /* __VOLUME__ */
+#endif /* __VOLUME__ */
/* Merging */
#if defined(__BRANCHED_PATH__) || defined(__VOLUME__)
ccl_device_inline void shader_merge_closures(ShaderData *sd)
{
- /* merge identical closures, better when we sample a single closure at a time */
- for(int i = 0; i < sd->num_closure; i++) {
- ShaderClosure *sci = &sd->closure[i];
-
- for(int j = i + 1; j < sd->num_closure; j++) {
- ShaderClosure *scj = &sd->closure[j];
-
- if(sci->type != scj->type)
- continue;
- if(!bsdf_merge(sci, scj))
- continue;
-
- sci->weight += scj->weight;
- sci->sample_weight += scj->sample_weight;
-
- int size = sd->num_closure - (j+1);
- if(size > 0) {
- for(int k = 0; k < size; k++) {
- scj[k] = scj[k+1];
- }
- }
-
- sd->num_closure--;
- kernel_assert(sd->num_closure >= 0);
- j--;
- }
- }
+ /* merge identical closures, better when we sample a single closure at a time */
+ for (int i = 0; i < sd->num_closure; i++) {
+ ShaderClosure *sci = &sd->closure[i];
+
+ for (int j = i + 1; j < sd->num_closure; j++) {
+ ShaderClosure *scj = &sd->closure[j];
+
+ if (sci->type != scj->type)
+ continue;
+ if (!bsdf_merge(sci, scj))
+ continue;
+
+ sci->weight += scj->weight;
+ sci->sample_weight += scj->sample_weight;
+
+ int size = sd->num_closure - (j + 1);
+ if (size > 0) {
+ for (int k = 0; k < size; k++) {
+ scj[k] = scj[k + 1];
+ }
+ }
+
+ sd->num_closure--;
+ kernel_assert(sd->num_closure >= 0);
+ j--;
+ }
+ }
}
-#endif /* __BRANCHED_PATH__ || __VOLUME__ */
+#endif /* __BRANCHED_PATH__ || __VOLUME__ */
/* Defensive sampling. */
-ccl_device_inline void shader_prepare_closures(ShaderData *sd,
- ccl_addr_space PathState *state)
+ccl_device_inline void shader_prepare_closures(ShaderData *sd, ccl_addr_space PathState *state)
{
- /* We can likely also do defensive sampling at deeper bounces, particularly
- * for cases like a perfect mirror but possibly also others. This will need
- * a good heuristic. */
- if(state->bounce + state->transparent_bounce == 0 && sd->num_closure > 1) {
- float sum = 0.0f;
-
- for(int i = 0; i < sd->num_closure; i++) {
- ShaderClosure *sc = &sd->closure[i];
- if(CLOSURE_IS_BSDF_OR_BSSRDF(sc->type)) {
- sum += sc->sample_weight;
- }
- }
-
- for(int i = 0; i < sd->num_closure; i++) {
- ShaderClosure *sc = &sd->closure[i];
- if(CLOSURE_IS_BSDF_OR_BSSRDF(sc->type)) {
- sc->sample_weight = max(sc->sample_weight, 0.125f * sum);
- }
- }
- }
+ /* We can likely also do defensive sampling at deeper bounces, particularly
+ * for cases like a perfect mirror but possibly also others. This will need
+ * a good heuristic. */
+ if (state->bounce + state->transparent_bounce == 0 && sd->num_closure > 1) {
+ float sum = 0.0f;
+
+ for (int i = 0; i < sd->num_closure; i++) {
+ ShaderClosure *sc = &sd->closure[i];
+ if (CLOSURE_IS_BSDF_OR_BSSRDF(sc->type)) {
+ sum += sc->sample_weight;
+ }
+ }
+
+ for (int i = 0; i < sd->num_closure; i++) {
+ ShaderClosure *sc = &sd->closure[i];
+ if (CLOSURE_IS_BSDF_OR_BSSRDF(sc->type)) {
+ sc->sample_weight = max(sc->sample_weight, 0.125f * sum);
+ }
+ }
+ }
}
-
/* BSDF */
-ccl_device_inline void _shader_bsdf_multi_eval(KernelGlobals *kg, ShaderData *sd, const float3 omega_in, float *pdf,
- const ShaderClosure *skip_sc, BsdfEval *result_eval, float sum_pdf, float sum_sample_weight)
+ccl_device_inline void _shader_bsdf_multi_eval(KernelGlobals *kg,
+ ShaderData *sd,
+ const float3 omega_in,
+ float *pdf,
+ const ShaderClosure *skip_sc,
+ BsdfEval *result_eval,
+ float sum_pdf,
+ float sum_sample_weight)
{
- /* this is the veach one-sample model with balance heuristic, some pdf
- * factors drop out when using balance heuristic weighting */
- for(int i = 0; i < sd->num_closure; i++) {
- const ShaderClosure *sc = &sd->closure[i];
+ /* this is the veach one-sample model with balance heuristic, some pdf
+ * factors drop out when using balance heuristic weighting */
+ for (int i = 0; i < sd->num_closure; i++) {
+ const ShaderClosure *sc = &sd->closure[i];
- if(sc != skip_sc && CLOSURE_IS_BSDF(sc->type)) {
- float bsdf_pdf = 0.0f;
- float3 eval = bsdf_eval(kg, sd, sc, omega_in, &bsdf_pdf);
+ if (sc != skip_sc && CLOSURE_IS_BSDF(sc->type)) {
+ float bsdf_pdf = 0.0f;
+ float3 eval = bsdf_eval(kg, sd, sc, omega_in, &bsdf_pdf);
- if(bsdf_pdf != 0.0f) {
- bsdf_eval_accum(result_eval, sc->type, eval*sc->weight, 1.0f);
- sum_pdf += bsdf_pdf*sc->sample_weight;
- }
+ if (bsdf_pdf != 0.0f) {
+ bsdf_eval_accum(result_eval, sc->type, eval * sc->weight, 1.0f);
+ sum_pdf += bsdf_pdf * sc->sample_weight;
+ }
- sum_sample_weight += sc->sample_weight;
- }
- }
+ sum_sample_weight += sc->sample_weight;
+ }
+ }
- *pdf = (sum_sample_weight > 0.0f)? sum_pdf/sum_sample_weight: 0.0f;
+ *pdf = (sum_sample_weight > 0.0f) ? sum_pdf / sum_sample_weight : 0.0f;
}
#ifdef __BRANCHED_PATH__
@@ -591,633 +609,654 @@ ccl_device_inline void _shader_bsdf_multi_eval_branched(KernelGlobals *kg,
float light_pdf,
bool use_mis)
{
- for(int i = 0; i < sd->num_closure; i++) {
- const ShaderClosure *sc = &sd->closure[i];
- if(CLOSURE_IS_BSDF(sc->type)) {
- float bsdf_pdf = 0.0f;
- float3 eval = bsdf_eval(kg, sd, sc, omega_in, &bsdf_pdf);
- if(bsdf_pdf != 0.0f) {
- float mis_weight = use_mis? power_heuristic(light_pdf, bsdf_pdf): 1.0f;
- bsdf_eval_accum(result_eval,
- sc->type,
- eval * sc->weight,
- mis_weight);
- }
- }
- }
+ for (int i = 0; i < sd->num_closure; i++) {
+ const ShaderClosure *sc = &sd->closure[i];
+ if (CLOSURE_IS_BSDF(sc->type)) {
+ float bsdf_pdf = 0.0f;
+ float3 eval = bsdf_eval(kg, sd, sc, omega_in, &bsdf_pdf);
+ if (bsdf_pdf != 0.0f) {
+ float mis_weight = use_mis ? power_heuristic(light_pdf, bsdf_pdf) : 1.0f;
+ bsdf_eval_accum(result_eval, sc->type, eval * sc->weight, mis_weight);
+ }
+ }
+ }
}
-#endif /* __BRANCHED_PATH__ */
-
+#endif /* __BRANCHED_PATH__ */
#ifndef __KERNEL_CUDA__
ccl_device
#else
ccl_device_inline
#endif
-void shader_bsdf_eval(KernelGlobals *kg,
- ShaderData *sd,
- const float3 omega_in,
- BsdfEval *eval,
- float light_pdf,
- bool use_mis)
+ void
+ shader_bsdf_eval(KernelGlobals *kg,
+ ShaderData *sd,
+ const float3 omega_in,
+ BsdfEval *eval,
+ float light_pdf,
+ bool use_mis)
{
- PROFILING_INIT(kg, PROFILING_CLOSURE_EVAL);
+ PROFILING_INIT(kg, PROFILING_CLOSURE_EVAL);
- bsdf_eval_init(eval, NBUILTIN_CLOSURES, make_float3(0.0f, 0.0f, 0.0f), kernel_data.film.use_light_pass);
+ bsdf_eval_init(
+ eval, NBUILTIN_CLOSURES, make_float3(0.0f, 0.0f, 0.0f), kernel_data.film.use_light_pass);
#ifdef __BRANCHED_PATH__
- if(kernel_data.integrator.branched)
- _shader_bsdf_multi_eval_branched(kg, sd, omega_in, eval, light_pdf, use_mis);
- else
+ if (kernel_data.integrator.branched)
+ _shader_bsdf_multi_eval_branched(kg, sd, omega_in, eval, light_pdf, use_mis);
+ else
#endif
- {
- float pdf;
- _shader_bsdf_multi_eval(kg, sd, omega_in, &pdf, NULL, eval, 0.0f, 0.0f);
- if(use_mis) {
- float weight = power_heuristic(light_pdf, pdf);
- bsdf_eval_mis(eval, weight);
- }
- }
+ {
+ float pdf;
+ _shader_bsdf_multi_eval(kg, sd, omega_in, &pdf, NULL, eval, 0.0f, 0.0f);
+ if (use_mis) {
+ float weight = power_heuristic(light_pdf, pdf);
+ bsdf_eval_mis(eval, weight);
+ }
+ }
}
-ccl_device_inline const ShaderClosure *shader_bsdf_pick(ShaderData *sd,
- float *randu)
+ccl_device_inline const ShaderClosure *shader_bsdf_pick(ShaderData *sd, float *randu)
{
- /* Note the sampling here must match shader_bssrdf_pick,
- * since we reuse the same random number. */
- int sampled = 0;
+ /* Note the sampling here must match shader_bssrdf_pick,
+ * since we reuse the same random number. */
+ int sampled = 0;
- if(sd->num_closure > 1) {
- /* Pick a BSDF or based on sample weights. */
- float sum = 0.0f;
+ if (sd->num_closure > 1) {
+ /* Pick a BSDF or based on sample weights. */
+ float sum = 0.0f;
- for(int i = 0; i < sd->num_closure; i++) {
- const ShaderClosure *sc = &sd->closure[i];
+ for (int i = 0; i < sd->num_closure; i++) {
+ const ShaderClosure *sc = &sd->closure[i];
- if(CLOSURE_IS_BSDF_OR_BSSRDF(sc->type)) {
- sum += sc->sample_weight;
- }
- }
+ if (CLOSURE_IS_BSDF_OR_BSSRDF(sc->type)) {
+ sum += sc->sample_weight;
+ }
+ }
- float r = (*randu)*sum;
- float partial_sum = 0.0f;
+ float r = (*randu) * sum;
+ float partial_sum = 0.0f;
- for(int i = 0; i < sd->num_closure; i++) {
- const ShaderClosure *sc = &sd->closure[i];
+ for (int i = 0; i < sd->num_closure; i++) {
+ const ShaderClosure *sc = &sd->closure[i];
- if(CLOSURE_IS_BSDF_OR_BSSRDF(sc->type)) {
- float next_sum = partial_sum + sc->sample_weight;
+ if (CLOSURE_IS_BSDF_OR_BSSRDF(sc->type)) {
+ float next_sum = partial_sum + sc->sample_weight;
- if(r < next_sum) {
- sampled = i;
+ if (r < next_sum) {
+ sampled = i;
- /* Rescale to reuse for direction sample, to better
- * preserve stratifaction. */
- *randu = (r - partial_sum) / sc->sample_weight;
- break;
- }
+ /* Rescale to reuse for direction sample, to better
+ * preserve stratifaction. */
+ *randu = (r - partial_sum) / sc->sample_weight;
+ break;
+ }
- partial_sum = next_sum;
- }
- }
- }
+ partial_sum = next_sum;
+ }
+ }
+ }
- const ShaderClosure *sc = &sd->closure[sampled];
- return CLOSURE_IS_BSDF(sc->type)? sc: NULL;
+ const ShaderClosure *sc = &sd->closure[sampled];
+ return CLOSURE_IS_BSDF(sc->type) ? sc : NULL;
}
ccl_device_inline const ShaderClosure *shader_bssrdf_pick(ShaderData *sd,
ccl_addr_space float3 *throughput,
float *randu)
{
- /* Note the sampling here must match shader_bsdf_pick,
- * since we reuse the same random number. */
- int sampled = 0;
-
- if(sd->num_closure > 1) {
- /* Pick a BSDF or BSSRDF or based on sample weights. */
- float sum_bsdf = 0.0f;
- float sum_bssrdf = 0.0f;
-
- for(int i = 0; i < sd->num_closure; i++) {
- const ShaderClosure *sc = &sd->closure[i];
-
- if(CLOSURE_IS_BSDF(sc->type)) {
- sum_bsdf += sc->sample_weight;
- }
- else if(CLOSURE_IS_BSSRDF(sc->type)) {
- sum_bssrdf += sc->sample_weight;
- }
- }
-
- float r = (*randu)*(sum_bsdf + sum_bssrdf);
- float partial_sum = 0.0f;
-
- for(int i = 0; i < sd->num_closure; i++) {
- const ShaderClosure *sc = &sd->closure[i];
-
- if(CLOSURE_IS_BSDF_OR_BSSRDF(sc->type)) {
- float next_sum = partial_sum + sc->sample_weight;
-
- if(r < next_sum) {
- if(CLOSURE_IS_BSDF(sc->type)) {
- *throughput *= (sum_bsdf + sum_bssrdf) / sum_bsdf;
- return NULL;
- }
- else {
- *throughput *= (sum_bsdf + sum_bssrdf) / sum_bssrdf;
- sampled = i;
-
- /* Rescale to reuse for direction sample, to better
- * preserve stratifaction. */
- *randu = (r - partial_sum) / sc->sample_weight;
- break;
- }
- }
-
- partial_sum = next_sum;
- }
- }
- }
-
- const ShaderClosure *sc = &sd->closure[sampled];
- return CLOSURE_IS_BSSRDF(sc->type)? sc: NULL;
+ /* Note the sampling here must match shader_bsdf_pick,
+ * since we reuse the same random number. */
+ int sampled = 0;
+
+ if (sd->num_closure > 1) {
+ /* Pick a BSDF or BSSRDF or based on sample weights. */
+ float sum_bsdf = 0.0f;
+ float sum_bssrdf = 0.0f;
+
+ for (int i = 0; i < sd->num_closure; i++) {
+ const ShaderClosure *sc = &sd->closure[i];
+
+ if (CLOSURE_IS_BSDF(sc->type)) {
+ sum_bsdf += sc->sample_weight;
+ }
+ else if (CLOSURE_IS_BSSRDF(sc->type)) {
+ sum_bssrdf += sc->sample_weight;
+ }
+ }
+
+ float r = (*randu) * (sum_bsdf + sum_bssrdf);
+ float partial_sum = 0.0f;
+
+ for (int i = 0; i < sd->num_closure; i++) {
+ const ShaderClosure *sc = &sd->closure[i];
+
+ if (CLOSURE_IS_BSDF_OR_BSSRDF(sc->type)) {
+ float next_sum = partial_sum + sc->sample_weight;
+
+ if (r < next_sum) {
+ if (CLOSURE_IS_BSDF(sc->type)) {
+ *throughput *= (sum_bsdf + sum_bssrdf) / sum_bsdf;
+ return NULL;
+ }
+ else {
+ *throughput *= (sum_bsdf + sum_bssrdf) / sum_bssrdf;
+ sampled = i;
+
+ /* Rescale to reuse for direction sample, to better
+ * preserve stratifaction. */
+ *randu = (r - partial_sum) / sc->sample_weight;
+ break;
+ }
+ }
+
+ partial_sum = next_sum;
+ }
+ }
+ }
+
+ const ShaderClosure *sc = &sd->closure[sampled];
+ return CLOSURE_IS_BSSRDF(sc->type) ? sc : NULL;
}
ccl_device_inline int shader_bsdf_sample(KernelGlobals *kg,
ShaderData *sd,
- float randu, float randv,
+ float randu,
+ float randv,
BsdfEval *bsdf_eval,
float3 *omega_in,
differential3 *domega_in,
float *pdf)
{
- PROFILING_INIT(kg, PROFILING_CLOSURE_SAMPLE);
+ PROFILING_INIT(kg, PROFILING_CLOSURE_SAMPLE);
- const ShaderClosure *sc = shader_bsdf_pick(sd, &randu);
- if(sc == NULL) {
- *pdf = 0.0f;
- return LABEL_NONE;
- }
+ const ShaderClosure *sc = shader_bsdf_pick(sd, &randu);
+ if (sc == NULL) {
+ *pdf = 0.0f;
+ return LABEL_NONE;
+ }
- /* BSSRDF should already have been handled elsewhere. */
- kernel_assert(CLOSURE_IS_BSDF(sc->type));
+ /* BSSRDF should already have been handled elsewhere. */
+ kernel_assert(CLOSURE_IS_BSDF(sc->type));
- int label;
- float3 eval;
+ int label;
+ float3 eval;
- *pdf = 0.0f;
- label = bsdf_sample(kg, sd, sc, randu, randv, &eval, omega_in, domega_in, pdf);
+ *pdf = 0.0f;
+ label = bsdf_sample(kg, sd, sc, randu, randv, &eval, omega_in, domega_in, pdf);
- if(*pdf != 0.0f) {
- bsdf_eval_init(bsdf_eval, sc->type, eval*sc->weight, kernel_data.film.use_light_pass);
+ if (*pdf != 0.0f) {
+ bsdf_eval_init(bsdf_eval, sc->type, eval * sc->weight, kernel_data.film.use_light_pass);
- if(sd->num_closure > 1) {
- float sweight = sc->sample_weight;
- _shader_bsdf_multi_eval(kg, sd, *omega_in, pdf, sc, bsdf_eval, *pdf*sweight, sweight);
- }
- }
+ if (sd->num_closure > 1) {
+ float sweight = sc->sample_weight;
+ _shader_bsdf_multi_eval(kg, sd, *omega_in, pdf, sc, bsdf_eval, *pdf * sweight, sweight);
+ }
+ }
- return label;
+ return label;
}
-ccl_device int shader_bsdf_sample_closure(KernelGlobals *kg, ShaderData *sd,
- const ShaderClosure *sc, float randu, float randv, BsdfEval *bsdf_eval,
- float3 *omega_in, differential3 *domega_in, float *pdf)
+ccl_device int shader_bsdf_sample_closure(KernelGlobals *kg,
+ ShaderData *sd,
+ const ShaderClosure *sc,
+ float randu,
+ float randv,
+ BsdfEval *bsdf_eval,
+ float3 *omega_in,
+ differential3 *domega_in,
+ float *pdf)
{
- PROFILING_INIT(kg, PROFILING_CLOSURE_SAMPLE);
+ PROFILING_INIT(kg, PROFILING_CLOSURE_SAMPLE);
- int label;
- float3 eval;
+ int label;
+ float3 eval;
- *pdf = 0.0f;
- label = bsdf_sample(kg, sd, sc, randu, randv, &eval, omega_in, domega_in, pdf);
+ *pdf = 0.0f;
+ label = bsdf_sample(kg, sd, sc, randu, randv, &eval, omega_in, domega_in, pdf);
- if(*pdf != 0.0f)
- bsdf_eval_init(bsdf_eval, sc->type, eval*sc->weight, kernel_data.film.use_light_pass);
+ if (*pdf != 0.0f)
+ bsdf_eval_init(bsdf_eval, sc->type, eval * sc->weight, kernel_data.film.use_light_pass);
- return label;
+ return label;
}
ccl_device float shader_bsdf_average_roughness(ShaderData *sd)
{
- float roughness = 0.0f;
- float sum_weight = 0.0f;
-
- for(int i = 0; i < sd->num_closure; i++) {
- ShaderClosure *sc = &sd->closure[i];
-
- if(CLOSURE_IS_BSDF(sc->type)) {
- /* sqrt once to undo the squaring from multiplying roughness on the
- * two axes, and once for the squared roughness convention. */
- float weight = fabsf(average(sc->weight));
- roughness += weight * sqrtf(safe_sqrtf(bsdf_get_roughness_squared(sc)));
- sum_weight += weight;
- }
- }
-
- return (sum_weight > 0.0f) ? roughness / sum_weight : 0.0f;
+ float roughness = 0.0f;
+ float sum_weight = 0.0f;
+
+ for (int i = 0; i < sd->num_closure; i++) {
+ ShaderClosure *sc = &sd->closure[i];
+
+ if (CLOSURE_IS_BSDF(sc->type)) {
+ /* sqrt once to undo the squaring from multiplying roughness on the
+ * two axes, and once for the squared roughness convention. */
+ float weight = fabsf(average(sc->weight));
+ roughness += weight * sqrtf(safe_sqrtf(bsdf_get_roughness_squared(sc)));
+ sum_weight += weight;
+ }
+ }
+
+ return (sum_weight > 0.0f) ? roughness / sum_weight : 0.0f;
}
ccl_device void shader_bsdf_blur(KernelGlobals *kg, ShaderData *sd, float roughness)
{
- for(int i = 0; i < sd->num_closure; i++) {
- ShaderClosure *sc = &sd->closure[i];
+ for (int i = 0; i < sd->num_closure; i++) {
+ ShaderClosure *sc = &sd->closure[i];
- if(CLOSURE_IS_BSDF(sc->type))
- bsdf_blur(kg, sc, roughness);
- }
+ if (CLOSURE_IS_BSDF(sc->type))
+ bsdf_blur(kg, sc, roughness);
+ }
}
ccl_device float3 shader_bsdf_transparency(KernelGlobals *kg, const ShaderData *sd)
{
- if(sd->flag & SD_HAS_ONLY_VOLUME) {
- return make_float3(1.0f, 1.0f, 1.0f);
- }
- else if(sd->flag & SD_TRANSPARENT) {
- return sd->closure_transparent_extinction;
- }
- else {
- return make_float3(0.0f, 0.0f, 0.0f);
- }
+ if (sd->flag & SD_HAS_ONLY_VOLUME) {
+ return make_float3(1.0f, 1.0f, 1.0f);
+ }
+ else if (sd->flag & SD_TRANSPARENT) {
+ return sd->closure_transparent_extinction;
+ }
+ else {
+ return make_float3(0.0f, 0.0f, 0.0f);
+ }
}
ccl_device void shader_bsdf_disable_transparency(KernelGlobals *kg, ShaderData *sd)
{
- if(sd->flag & SD_TRANSPARENT) {
- for(int i = 0; i < sd->num_closure; i++) {
- ShaderClosure *sc = &sd->closure[i];
-
- if(sc->type == CLOSURE_BSDF_TRANSPARENT_ID) {
- sc->sample_weight = 0.0f;
- sc->weight = make_float3(0.0f, 0.0f, 0.0f);
- }
- }
-
- sd->flag &= ~SD_TRANSPARENT;
- }
+ if (sd->flag & SD_TRANSPARENT) {
+ for (int i = 0; i < sd->num_closure; i++) {
+ ShaderClosure *sc = &sd->closure[i];
+
+ if (sc->type == CLOSURE_BSDF_TRANSPARENT_ID) {
+ sc->sample_weight = 0.0f;
+ sc->weight = make_float3(0.0f, 0.0f, 0.0f);
+ }
+ }
+
+ sd->flag &= ~SD_TRANSPARENT;
+ }
}
ccl_device float3 shader_bsdf_alpha(KernelGlobals *kg, ShaderData *sd)
{
- float3 alpha = make_float3(1.0f, 1.0f, 1.0f) - shader_bsdf_transparency(kg, sd);
+ float3 alpha = make_float3(1.0f, 1.0f, 1.0f) - shader_bsdf_transparency(kg, sd);
- alpha = max(alpha, make_float3(0.0f, 0.0f, 0.0f));
- alpha = min(alpha, make_float3(1.0f, 1.0f, 1.0f));
+ alpha = max(alpha, make_float3(0.0f, 0.0f, 0.0f));
+ alpha = min(alpha, make_float3(1.0f, 1.0f, 1.0f));
- return alpha;
+ return alpha;
}
ccl_device float3 shader_bsdf_diffuse(KernelGlobals *kg, ShaderData *sd)
{
- float3 eval = make_float3(0.0f, 0.0f, 0.0f);
+ float3 eval = make_float3(0.0f, 0.0f, 0.0f);
- for(int i = 0; i < sd->num_closure; i++) {
- ShaderClosure *sc = &sd->closure[i];
+ for (int i = 0; i < sd->num_closure; i++) {
+ ShaderClosure *sc = &sd->closure[i];
- if(CLOSURE_IS_BSDF_DIFFUSE(sc->type))
- eval += sc->weight;
- }
+ if (CLOSURE_IS_BSDF_DIFFUSE(sc->type))
+ eval += sc->weight;
+ }
- return eval;
+ return eval;
}
ccl_device float3 shader_bsdf_glossy(KernelGlobals *kg, ShaderData *sd)
{
- float3 eval = make_float3(0.0f, 0.0f, 0.0f);
+ float3 eval = make_float3(0.0f, 0.0f, 0.0f);
- for(int i = 0; i < sd->num_closure; i++) {
- ShaderClosure *sc = &sd->closure[i];
+ for (int i = 0; i < sd->num_closure; i++) {
+ ShaderClosure *sc = &sd->closure[i];
- if(CLOSURE_IS_BSDF_GLOSSY(sc->type))
- eval += sc->weight;
- }
+ if (CLOSURE_IS_BSDF_GLOSSY(sc->type))
+ eval += sc->weight;
+ }
- return eval;
+ return eval;
}
ccl_device float3 shader_bsdf_transmission(KernelGlobals *kg, ShaderData *sd)
{
- float3 eval = make_float3(0.0f, 0.0f, 0.0f);
+ float3 eval = make_float3(0.0f, 0.0f, 0.0f);
- for(int i = 0; i < sd->num_closure; i++) {
- ShaderClosure *sc = &sd->closure[i];
+ for (int i = 0; i < sd->num_closure; i++) {
+ ShaderClosure *sc = &sd->closure[i];
- if(CLOSURE_IS_BSDF_TRANSMISSION(sc->type))
- eval += sc->weight;
- }
+ if (CLOSURE_IS_BSDF_TRANSMISSION(sc->type))
+ eval += sc->weight;
+ }
- return eval;
+ return eval;
}
ccl_device float3 shader_bsdf_subsurface(KernelGlobals *kg, ShaderData *sd)
{
- float3 eval = make_float3(0.0f, 0.0f, 0.0f);
+ float3 eval = make_float3(0.0f, 0.0f, 0.0f);
- for(int i = 0; i < sd->num_closure; i++) {
- ShaderClosure *sc = &sd->closure[i];
+ for (int i = 0; i < sd->num_closure; i++) {
+ ShaderClosure *sc = &sd->closure[i];
- if(CLOSURE_IS_BSSRDF(sc->type) || CLOSURE_IS_BSDF_BSSRDF(sc->type))
- eval += sc->weight;
- }
+ if (CLOSURE_IS_BSSRDF(sc->type) || CLOSURE_IS_BSDF_BSSRDF(sc->type))
+ eval += sc->weight;
+ }
- return eval;
+ return eval;
}
ccl_device float3 shader_bsdf_average_normal(KernelGlobals *kg, ShaderData *sd)
{
- float3 N = make_float3(0.0f, 0.0f, 0.0f);
+ float3 N = make_float3(0.0f, 0.0f, 0.0f);
- for(int i = 0; i < sd->num_closure; i++) {
- ShaderClosure *sc = &sd->closure[i];
- if(CLOSURE_IS_BSDF_OR_BSSRDF(sc->type))
- N += sc->N*fabsf(average(sc->weight));
- }
+ for (int i = 0; i < sd->num_closure; i++) {
+ ShaderClosure *sc = &sd->closure[i];
+ if (CLOSURE_IS_BSDF_OR_BSSRDF(sc->type))
+ N += sc->N * fabsf(average(sc->weight));
+ }
- return (is_zero(N))? sd->N : normalize(N);
+ return (is_zero(N)) ? sd->N : normalize(N);
}
ccl_device float3 shader_bsdf_ao(KernelGlobals *kg, ShaderData *sd, float ao_factor, float3 *N_)
{
- float3 eval = make_float3(0.0f, 0.0f, 0.0f);
- float3 N = make_float3(0.0f, 0.0f, 0.0f);
+ float3 eval = make_float3(0.0f, 0.0f, 0.0f);
+ float3 N = make_float3(0.0f, 0.0f, 0.0f);
- for(int i = 0; i < sd->num_closure; i++) {
- ShaderClosure *sc = &sd->closure[i];
+ for (int i = 0; i < sd->num_closure; i++) {
+ ShaderClosure *sc = &sd->closure[i];
- if(CLOSURE_IS_BSDF_DIFFUSE(sc->type)) {
- const DiffuseBsdf *bsdf = (const DiffuseBsdf*)sc;
- eval += sc->weight*ao_factor;
- N += bsdf->N*fabsf(average(sc->weight));
- }
- }
+ if (CLOSURE_IS_BSDF_DIFFUSE(sc->type)) {
+ const DiffuseBsdf *bsdf = (const DiffuseBsdf *)sc;
+ eval += sc->weight * ao_factor;
+ N += bsdf->N * fabsf(average(sc->weight));
+ }
+ }
- *N_ = (is_zero(N))? sd->N : normalize(N);
- return eval;
+ *N_ = (is_zero(N)) ? sd->N : normalize(N);
+ return eval;
}
#ifdef __SUBSURFACE__
ccl_device float3 shader_bssrdf_sum(ShaderData *sd, float3 *N_, float *texture_blur_)
{
- float3 eval = make_float3(0.0f, 0.0f, 0.0f);
- float3 N = make_float3(0.0f, 0.0f, 0.0f);
- float texture_blur = 0.0f, weight_sum = 0.0f;
+ float3 eval = make_float3(0.0f, 0.0f, 0.0f);
+ float3 N = make_float3(0.0f, 0.0f, 0.0f);
+ float texture_blur = 0.0f, weight_sum = 0.0f;
- for(int i = 0; i < sd->num_closure; i++) {
- ShaderClosure *sc = &sd->closure[i];
+ for (int i = 0; i < sd->num_closure; i++) {
+ ShaderClosure *sc = &sd->closure[i];
- if(CLOSURE_IS_BSSRDF(sc->type)) {
- const Bssrdf *bssrdf = (const Bssrdf*)sc;
- float avg_weight = fabsf(average(sc->weight));
+ if (CLOSURE_IS_BSSRDF(sc->type)) {
+ const Bssrdf *bssrdf = (const Bssrdf *)sc;
+ float avg_weight = fabsf(average(sc->weight));
- N += bssrdf->N*avg_weight;
- eval += sc->weight;
- texture_blur += bssrdf->texture_blur*avg_weight;
- weight_sum += avg_weight;
- }
- }
+ N += bssrdf->N * avg_weight;
+ eval += sc->weight;
+ texture_blur += bssrdf->texture_blur * avg_weight;
+ weight_sum += avg_weight;
+ }
+ }
- if(N_)
- *N_ = (is_zero(N))? sd->N: normalize(N);
+ if (N_)
+ *N_ = (is_zero(N)) ? sd->N : normalize(N);
- if(texture_blur_)
- *texture_blur_ = safe_divide(texture_blur, weight_sum);
+ if (texture_blur_)
+ *texture_blur_ = safe_divide(texture_blur, weight_sum);
- return eval;
+ return eval;
}
-#endif /* __SUBSURFACE__ */
+#endif /* __SUBSURFACE__ */
/* Constant emission optimization */
ccl_device bool shader_constant_emission_eval(KernelGlobals *kg, int shader, float3 *eval)
{
- int shader_index = shader & SHADER_MASK;
- int shader_flag = kernel_tex_fetch(__shaders, shader_index).flags;
+ int shader_index = shader & SHADER_MASK;
+ int shader_flag = kernel_tex_fetch(__shaders, shader_index).flags;
- if (shader_flag & SD_HAS_CONSTANT_EMISSION) {
- *eval = make_float3(
- kernel_tex_fetch(__shaders, shader_index).constant_emission[0],
- kernel_tex_fetch(__shaders, shader_index).constant_emission[1],
- kernel_tex_fetch(__shaders, shader_index).constant_emission[2]);
+ if (shader_flag & SD_HAS_CONSTANT_EMISSION) {
+ *eval = make_float3(kernel_tex_fetch(__shaders, shader_index).constant_emission[0],
+ kernel_tex_fetch(__shaders, shader_index).constant_emission[1],
+ kernel_tex_fetch(__shaders, shader_index).constant_emission[2]);
- return true;
- }
+ return true;
+ }
- return false;
+ return false;
}
/* Background */
ccl_device float3 shader_background_eval(ShaderData *sd)
{
- if(sd->flag & SD_EMISSION) {
- return sd->closure_emission_background;
- }
- else {
- return make_float3(0.0f, 0.0f, 0.0f);
- }
+ if (sd->flag & SD_EMISSION) {
+ return sd->closure_emission_background;
+ }
+ else {
+ return make_float3(0.0f, 0.0f, 0.0f);
+ }
}
/* Emission */
ccl_device float3 shader_emissive_eval(ShaderData *sd)
{
- if(sd->flag & SD_EMISSION) {
- return emissive_simple_eval(sd->Ng, sd->I) * sd->closure_emission_background;
- }
- else {
- return make_float3(0.0f, 0.0f, 0.0f);
- }
+ if (sd->flag & SD_EMISSION) {
+ return emissive_simple_eval(sd->Ng, sd->I) * sd->closure_emission_background;
+ }
+ else {
+ return make_float3(0.0f, 0.0f, 0.0f);
+ }
}
/* Holdout */
ccl_device float3 shader_holdout_eval(KernelGlobals *kg, ShaderData *sd)
{
- float3 weight = make_float3(0.0f, 0.0f, 0.0f);
+ float3 weight = make_float3(0.0f, 0.0f, 0.0f);
- for(int i = 0; i < sd->num_closure; i++) {
- ShaderClosure *sc = &sd->closure[i];
+ for (int i = 0; i < sd->num_closure; i++) {
+ ShaderClosure *sc = &sd->closure[i];
- if(CLOSURE_IS_HOLDOUT(sc->type))
- weight += sc->weight;
- }
+ if (CLOSURE_IS_HOLDOUT(sc->type))
+ weight += sc->weight;
+ }
- return weight;
+ return weight;
}
/* Surface Evaluation */
-ccl_device void shader_eval_surface(KernelGlobals *kg, ShaderData *sd,
- ccl_addr_space PathState *state, int path_flag)
+ccl_device void shader_eval_surface(KernelGlobals *kg,
+ ShaderData *sd,
+ ccl_addr_space PathState *state,
+ int path_flag)
{
- PROFILING_INIT(kg, PROFILING_SHADER_EVAL);
-
- /* If path is being terminated, we are tracing a shadow ray or evaluating
- * emission, then we don't need to store closures. The emission and shadow
- * shader data also do not have a closure array to save GPU memory. */
- int max_closures;
- if(path_flag & (PATH_RAY_TERMINATE|PATH_RAY_SHADOW|PATH_RAY_EMISSION)) {
- max_closures = 0;
- }
- else {
- max_closures = kernel_data.integrator.max_closures;
- }
-
- sd->num_closure = 0;
- sd->num_closure_left = max_closures;
+ PROFILING_INIT(kg, PROFILING_SHADER_EVAL);
+
+ /* If path is being terminated, we are tracing a shadow ray or evaluating
+ * emission, then we don't need to store closures. The emission and shadow
+ * shader data also do not have a closure array to save GPU memory. */
+ int max_closures;
+ if (path_flag & (PATH_RAY_TERMINATE | PATH_RAY_SHADOW | PATH_RAY_EMISSION)) {
+ max_closures = 0;
+ }
+ else {
+ max_closures = kernel_data.integrator.max_closures;
+ }
+
+ sd->num_closure = 0;
+ sd->num_closure_left = max_closures;
#ifdef __OSL__
- if(kg->osl) {
- if (sd->object == OBJECT_NONE) {
- OSLShader::eval_background(kg, sd, state, path_flag);
- }
- else {
- OSLShader::eval_surface(kg, sd, state, path_flag);
- }
- }
- else
+ if (kg->osl) {
+ if (sd->object == OBJECT_NONE) {
+ OSLShader::eval_background(kg, sd, state, path_flag);
+ }
+ else {
+ OSLShader::eval_surface(kg, sd, state, path_flag);
+ }
+ }
+ else
#endif
- {
+ {
#ifdef __SVM__
- svm_eval_nodes(kg, sd, state, SHADER_TYPE_SURFACE, path_flag);
+ svm_eval_nodes(kg, sd, state, SHADER_TYPE_SURFACE, path_flag);
#else
- if(sd->object == OBJECT_NONE) {
- sd->closure_emission_background = make_float3(0.8f, 0.8f, 0.8f);
- sd->flag |= SD_EMISSION;
- }
- else {
- DiffuseBsdf *bsdf = (DiffuseBsdf*)bsdf_alloc(sd,
- sizeof(DiffuseBsdf),
- make_float3(0.8f, 0.8f, 0.8f));
- if(bsdf != NULL) {
- bsdf->N = sd->N;
- sd->flag |= bsdf_diffuse_setup(bsdf);
- }
- }
+ if (sd->object == OBJECT_NONE) {
+ sd->closure_emission_background = make_float3(0.8f, 0.8f, 0.8f);
+ sd->flag |= SD_EMISSION;
+ }
+ else {
+ DiffuseBsdf *bsdf = (DiffuseBsdf *)bsdf_alloc(
+ sd, sizeof(DiffuseBsdf), make_float3(0.8f, 0.8f, 0.8f));
+ if (bsdf != NULL) {
+ bsdf->N = sd->N;
+ sd->flag |= bsdf_diffuse_setup(bsdf);
+ }
+ }
#endif
- }
+ }
- if(sd->flag & SD_BSDF_NEEDS_LCG) {
- sd->lcg_state = lcg_state_init_addrspace(state, 0xb4bc3953);
- }
+ if (sd->flag & SD_BSDF_NEEDS_LCG) {
+ sd->lcg_state = lcg_state_init_addrspace(state, 0xb4bc3953);
+ }
}
/* Volume */
#ifdef __VOLUME__
-ccl_device_inline void _shader_volume_phase_multi_eval(const ShaderData *sd, const float3 omega_in, float *pdf,
- int skip_phase, BsdfEval *result_eval, float sum_pdf, float sum_sample_weight)
+ccl_device_inline void _shader_volume_phase_multi_eval(const ShaderData *sd,
+ const float3 omega_in,
+ float *pdf,
+ int skip_phase,
+ BsdfEval *result_eval,
+ float sum_pdf,
+ float sum_sample_weight)
{
- for(int i = 0; i < sd->num_closure; i++) {
- if(i == skip_phase)
- continue;
+ for (int i = 0; i < sd->num_closure; i++) {
+ if (i == skip_phase)
+ continue;
- const ShaderClosure *sc = &sd->closure[i];
+ const ShaderClosure *sc = &sd->closure[i];
- if(CLOSURE_IS_PHASE(sc->type)) {
- float phase_pdf = 0.0f;
- float3 eval = volume_phase_eval(sd, sc, omega_in, &phase_pdf);
+ if (CLOSURE_IS_PHASE(sc->type)) {
+ float phase_pdf = 0.0f;
+ float3 eval = volume_phase_eval(sd, sc, omega_in, &phase_pdf);
- if(phase_pdf != 0.0f) {
- bsdf_eval_accum(result_eval, sc->type, eval, 1.0f);
- sum_pdf += phase_pdf*sc->sample_weight;
- }
+ if (phase_pdf != 0.0f) {
+ bsdf_eval_accum(result_eval, sc->type, eval, 1.0f);
+ sum_pdf += phase_pdf * sc->sample_weight;
+ }
- sum_sample_weight += sc->sample_weight;
- }
- }
+ sum_sample_weight += sc->sample_weight;
+ }
+ }
- *pdf = (sum_sample_weight > 0.0f)? sum_pdf/sum_sample_weight: 0.0f;
+ *pdf = (sum_sample_weight > 0.0f) ? sum_pdf / sum_sample_weight : 0.0f;
}
-ccl_device void shader_volume_phase_eval(KernelGlobals *kg, const ShaderData *sd,
- const float3 omega_in, BsdfEval *eval, float *pdf)
+ccl_device void shader_volume_phase_eval(
+ KernelGlobals *kg, const ShaderData *sd, const float3 omega_in, BsdfEval *eval, float *pdf)
{
- PROFILING_INIT(kg, PROFILING_CLOSURE_VOLUME_EVAL);
+ PROFILING_INIT(kg, PROFILING_CLOSURE_VOLUME_EVAL);
- bsdf_eval_init(eval, NBUILTIN_CLOSURES, make_float3(0.0f, 0.0f, 0.0f), kernel_data.film.use_light_pass);
+ bsdf_eval_init(
+ eval, NBUILTIN_CLOSURES, make_float3(0.0f, 0.0f, 0.0f), kernel_data.film.use_light_pass);
- _shader_volume_phase_multi_eval(sd, omega_in, pdf, -1, eval, 0.0f, 0.0f);
+ _shader_volume_phase_multi_eval(sd, omega_in, pdf, -1, eval, 0.0f, 0.0f);
}
-ccl_device int shader_volume_phase_sample(KernelGlobals *kg, const ShaderData *sd,
- float randu, float randv, BsdfEval *phase_eval,
- float3 *omega_in, differential3 *domega_in, float *pdf)
+ccl_device int shader_volume_phase_sample(KernelGlobals *kg,
+ const ShaderData *sd,
+ float randu,
+ float randv,
+ BsdfEval *phase_eval,
+ float3 *omega_in,
+ differential3 *domega_in,
+ float *pdf)
{
- PROFILING_INIT(kg, PROFILING_CLOSURE_VOLUME_SAMPLE);
+ PROFILING_INIT(kg, PROFILING_CLOSURE_VOLUME_SAMPLE);
- int sampled = 0;
+ int sampled = 0;
- if(sd->num_closure > 1) {
- /* pick a phase closure based on sample weights */
- float sum = 0.0f;
+ if (sd->num_closure > 1) {
+ /* pick a phase closure based on sample weights */
+ float sum = 0.0f;
- for(sampled = 0; sampled < sd->num_closure; sampled++) {
- const ShaderClosure *sc = &sd->closure[sampled];
+ for (sampled = 0; sampled < sd->num_closure; sampled++) {
+ const ShaderClosure *sc = &sd->closure[sampled];
- if(CLOSURE_IS_PHASE(sc->type))
- sum += sc->sample_weight;
- }
+ if (CLOSURE_IS_PHASE(sc->type))
+ sum += sc->sample_weight;
+ }
- float r = randu*sum;
- float partial_sum = 0.0f;
+ float r = randu * sum;
+ float partial_sum = 0.0f;
- for(sampled = 0; sampled < sd->num_closure; sampled++) {
- const ShaderClosure *sc = &sd->closure[sampled];
+ for (sampled = 0; sampled < sd->num_closure; sampled++) {
+ const ShaderClosure *sc = &sd->closure[sampled];
- if(CLOSURE_IS_PHASE(sc->type)) {
- float next_sum = partial_sum + sc->sample_weight;
+ if (CLOSURE_IS_PHASE(sc->type)) {
+ float next_sum = partial_sum + sc->sample_weight;
- if(r <= next_sum) {
- /* Rescale to reuse for BSDF direction sample. */
- randu = (r - partial_sum) / sc->sample_weight;
- break;
- }
+ if (r <= next_sum) {
+ /* Rescale to reuse for BSDF direction sample. */
+ randu = (r - partial_sum) / sc->sample_weight;
+ break;
+ }
- partial_sum = next_sum;
- }
- }
+ partial_sum = next_sum;
+ }
+ }
- if(sampled == sd->num_closure) {
- *pdf = 0.0f;
- return LABEL_NONE;
- }
- }
+ if (sampled == sd->num_closure) {
+ *pdf = 0.0f;
+ return LABEL_NONE;
+ }
+ }
- /* todo: this isn't quite correct, we don't weight anisotropy properly
- * depending on color channels, even if this is perhaps not a common case */
- const ShaderClosure *sc = &sd->closure[sampled];
- int label;
- float3 eval;
+ /* todo: this isn't quite correct, we don't weight anisotropy properly
+ * depending on color channels, even if this is perhaps not a common case */
+ const ShaderClosure *sc = &sd->closure[sampled];
+ int label;
+ float3 eval;
- *pdf = 0.0f;
- label = volume_phase_sample(sd, sc, randu, randv, &eval, omega_in, domega_in, pdf);
+ *pdf = 0.0f;
+ label = volume_phase_sample(sd, sc, randu, randv, &eval, omega_in, domega_in, pdf);
- if(*pdf != 0.0f) {
- bsdf_eval_init(phase_eval, sc->type, eval, kernel_data.film.use_light_pass);
- }
+ if (*pdf != 0.0f) {
+ bsdf_eval_init(phase_eval, sc->type, eval, kernel_data.film.use_light_pass);
+ }
- return label;
+ return label;
}
-ccl_device int shader_phase_sample_closure(KernelGlobals *kg, const ShaderData *sd,
- const ShaderClosure *sc, float randu, float randv, BsdfEval *phase_eval,
- float3 *omega_in, differential3 *domega_in, float *pdf)
+ccl_device int shader_phase_sample_closure(KernelGlobals *kg,
+ const ShaderData *sd,
+ const ShaderClosure *sc,
+ float randu,
+ float randv,
+ BsdfEval *phase_eval,
+ float3 *omega_in,
+ differential3 *domega_in,
+ float *pdf)
{
- PROFILING_INIT(kg, PROFILING_CLOSURE_VOLUME_SAMPLE);
+ PROFILING_INIT(kg, PROFILING_CLOSURE_VOLUME_SAMPLE);
- int label;
- float3 eval;
+ int label;
+ float3 eval;
- *pdf = 0.0f;
- label = volume_phase_sample(sd, sc, randu, randv, &eval, omega_in, domega_in, pdf);
+ *pdf = 0.0f;
+ label = volume_phase_sample(sd, sc, randu, randv, &eval, omega_in, domega_in, pdf);
- if(*pdf != 0.0f)
- bsdf_eval_init(phase_eval, sc->type, eval, kernel_data.film.use_light_pass);
+ if (*pdf != 0.0f)
+ bsdf_eval_init(phase_eval, sc->type, eval, kernel_data.film.use_light_pass);
- return label;
+ return label;
}
/* Volume Evaluation */
@@ -1228,83 +1267,85 @@ ccl_device_inline void shader_eval_volume(KernelGlobals *kg,
ccl_addr_space VolumeStack *stack,
int path_flag)
{
- /* If path is being terminated, we are tracing a shadow ray or evaluating
- * emission, then we don't need to store closures. The emission and shadow
- * shader data also do not have a closure array to save GPU memory. */
- int max_closures;
- if(path_flag & (PATH_RAY_TERMINATE|PATH_RAY_SHADOW|PATH_RAY_EMISSION)) {
- max_closures = 0;
- }
- else {
- max_closures = kernel_data.integrator.max_closures;
- }
-
- /* reset closures once at the start, we will be accumulating the closures
- * for all volumes in the stack into a single array of closures */
- sd->num_closure = 0;
- sd->num_closure_left = max_closures;
- sd->flag = 0;
- sd->object_flag = 0;
-
- for(int i = 0; stack[i].shader != SHADER_NONE; i++) {
- /* setup shaderdata from stack. it's mostly setup already in
- * shader_setup_from_volume, this switching should be quick */
- sd->object = stack[i].object;
- sd->lamp = LAMP_NONE;
- sd->shader = stack[i].shader;
-
- sd->flag &= ~SD_SHADER_FLAGS;
- sd->flag |= kernel_tex_fetch(__shaders, (sd->shader & SHADER_MASK)).flags;
- sd->object_flag &= ~SD_OBJECT_FLAGS;
-
- if(sd->object != OBJECT_NONE) {
- sd->object_flag |= kernel_tex_fetch(__object_flag, sd->object);
-
-#ifdef __OBJECT_MOTION__
- /* todo: this is inefficient for motion blur, we should be
- * caching matrices instead of recomputing them each step */
- shader_setup_object_transforms(kg, sd, sd->time);
-#endif
- }
-
- /* evaluate shader */
-#ifdef __SVM__
-# ifdef __OSL__
- if(kg->osl) {
- OSLShader::eval_volume(kg, sd, state, path_flag);
- }
- else
+ /* If path is being terminated, we are tracing a shadow ray or evaluating
+ * emission, then we don't need to store closures. The emission and shadow
+ * shader data also do not have a closure array to save GPU memory. */
+ int max_closures;
+ if (path_flag & (PATH_RAY_TERMINATE | PATH_RAY_SHADOW | PATH_RAY_EMISSION)) {
+ max_closures = 0;
+ }
+ else {
+ max_closures = kernel_data.integrator.max_closures;
+ }
+
+ /* reset closures once at the start, we will be accumulating the closures
+ * for all volumes in the stack into a single array of closures */
+ sd->num_closure = 0;
+ sd->num_closure_left = max_closures;
+ sd->flag = 0;
+ sd->object_flag = 0;
+
+ for (int i = 0; stack[i].shader != SHADER_NONE; i++) {
+ /* setup shaderdata from stack. it's mostly setup already in
+ * shader_setup_from_volume, this switching should be quick */
+ sd->object = stack[i].object;
+ sd->lamp = LAMP_NONE;
+ sd->shader = stack[i].shader;
+
+ sd->flag &= ~SD_SHADER_FLAGS;
+ sd->flag |= kernel_tex_fetch(__shaders, (sd->shader & SHADER_MASK)).flags;
+ sd->object_flag &= ~SD_OBJECT_FLAGS;
+
+ if (sd->object != OBJECT_NONE) {
+ sd->object_flag |= kernel_tex_fetch(__object_flag, sd->object);
+
+# ifdef __OBJECT_MOTION__
+ /* todo: this is inefficient for motion blur, we should be
+ * caching matrices instead of recomputing them each step */
+ shader_setup_object_transforms(kg, sd, sd->time);
+# endif
+ }
+
+ /* evaluate shader */
+# ifdef __SVM__
+# ifdef __OSL__
+ if (kg->osl) {
+ OSLShader::eval_volume(kg, sd, state, path_flag);
+ }
+ else
+# endif
+ {
+ svm_eval_nodes(kg, sd, state, SHADER_TYPE_VOLUME, path_flag);
+ }
# endif
- {
- svm_eval_nodes(kg, sd, state, SHADER_TYPE_VOLUME, path_flag);
- }
-#endif
- /* merge closures to avoid exceeding number of closures limit */
- if(i > 0)
- shader_merge_closures(sd);
- }
+ /* merge closures to avoid exceeding number of closures limit */
+ if (i > 0)
+ shader_merge_closures(sd);
+ }
}
-#endif /* __VOLUME__ */
+#endif /* __VOLUME__ */
/* Displacement Evaluation */
-ccl_device void shader_eval_displacement(KernelGlobals *kg, ShaderData *sd, ccl_addr_space PathState *state)
+ccl_device void shader_eval_displacement(KernelGlobals *kg,
+ ShaderData *sd,
+ ccl_addr_space PathState *state)
{
- sd->num_closure = 0;
- sd->num_closure_left = 0;
+ sd->num_closure = 0;
+ sd->num_closure_left = 0;
- /* this will modify sd->P */
+ /* this will modify sd->P */
#ifdef __SVM__
# ifdef __OSL__
- if(kg->osl)
- OSLShader::eval_displacement(kg, sd, state);
- else
+ if (kg->osl)
+ OSLShader::eval_displacement(kg, sd, state);
+ else
# endif
- {
- svm_eval_nodes(kg, sd, state, SHADER_TYPE_DISPLACEMENT, 0);
- }
+ {
+ svm_eval_nodes(kg, sd, state, SHADER_TYPE_DISPLACEMENT, 0);
+ }
#endif
}
@@ -1313,29 +1354,29 @@ ccl_device void shader_eval_displacement(KernelGlobals *kg, ShaderData *sd, ccl_
#ifdef __TRANSPARENT_SHADOWS__
ccl_device bool shader_transparent_shadow(KernelGlobals *kg, Intersection *isect)
{
- int prim = kernel_tex_fetch(__prim_index, isect->prim);
- int shader = 0;
+ int prim = kernel_tex_fetch(__prim_index, isect->prim);
+ int shader = 0;
-#ifdef __HAIR__
- if(kernel_tex_fetch(__prim_type, isect->prim) & PRIMITIVE_ALL_TRIANGLE) {
-#endif
- shader = kernel_tex_fetch(__tri_shader, prim);
-#ifdef __HAIR__
- }
- else {
- float4 str = kernel_tex_fetch(__curves, prim);
- shader = __float_as_int(str.z);
- }
-#endif
- int flag = kernel_tex_fetch(__shaders, (shader & SHADER_MASK)).flags;
+# ifdef __HAIR__
+ if (kernel_tex_fetch(__prim_type, isect->prim) & PRIMITIVE_ALL_TRIANGLE) {
+# endif
+ shader = kernel_tex_fetch(__tri_shader, prim);
+# ifdef __HAIR__
+ }
+ else {
+ float4 str = kernel_tex_fetch(__curves, prim);
+ shader = __float_as_int(str.z);
+ }
+# endif
+ int flag = kernel_tex_fetch(__shaders, (shader & SHADER_MASK)).flags;
- return (flag & SD_HAS_TRANSPARENT_SHADOW) != 0;
+ return (flag & SD_HAS_TRANSPARENT_SHADOW) != 0;
}
-#endif /* __TRANSPARENT_SHADOWS__ */
+#endif /* __TRANSPARENT_SHADOWS__ */
ccl_device float shader_cryptomatte_id(KernelGlobals *kg, int shader)
{
- return kernel_tex_fetch(__shaders, (shader & SHADER_MASK)).cryptomatte_id;
+ return kernel_tex_fetch(__shaders, (shader & SHADER_MASK)).cryptomatte_id;
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/kernel_shadow.h b/intern/cycles/kernel/kernel_shadow.h
index fafa3ad4bfa..6af1369feab 100644
--- a/intern/cycles/kernel/kernel_shadow.h
+++ b/intern/cycles/kernel/kernel_shadow.h
@@ -20,7 +20,7 @@ CCL_NAMESPACE_BEGIN
typedef struct VolumeState {
# ifdef __SPLIT_KERNEL__
# else
- PathState ps;
+ PathState ps;
# endif
} VolumeState;
@@ -28,77 +28,70 @@ typedef struct VolumeState {
# ifdef __SPLIT_KERNEL__
ccl_addr_space
# endif
-ccl_device_inline PathState *shadow_blocked_volume_path_state(
- KernelGlobals *kg,
- VolumeState *volume_state,
- ccl_addr_space PathState *state,
- ShaderData *sd,
- Ray *ray)
+ ccl_device_inline PathState *
+ shadow_blocked_volume_path_state(KernelGlobals *kg,
+ VolumeState *volume_state,
+ ccl_addr_space PathState *state,
+ ShaderData *sd,
+ Ray *ray)
{
# ifdef __SPLIT_KERNEL__
- ccl_addr_space PathState *ps =
- &kernel_split_state.state_shadow[ccl_global_id(1) * ccl_global_size(0) + ccl_global_id(0)];
+ ccl_addr_space PathState *ps =
+ &kernel_split_state.state_shadow[ccl_global_id(1) * ccl_global_size(0) + ccl_global_id(0)];
# else
- PathState *ps = &volume_state->ps;
+ PathState *ps = &volume_state->ps;
# endif
- *ps = *state;
- /* We are checking for shadow on the "other" side of the surface, so need
- * to discard volume we are currently at.
- */
- if(dot(sd->Ng, ray->D) < 0.0f) {
- kernel_volume_stack_enter_exit(kg, sd, ps->volume_stack);
- }
- return ps;
+ *ps = *state;
+ /* We are checking for shadow on the "other" side of the surface, so need
+ * to discard volume we are currently at.
+ */
+ if (dot(sd->Ng, ray->D) < 0.0f) {
+ kernel_volume_stack_enter_exit(kg, sd, ps->volume_stack);
+ }
+ return ps;
}
-#endif /* __VOLUME__ */
+#endif /* __VOLUME__ */
/* Attenuate throughput accordingly to the given intersection event.
* Returns true if the throughput is zero and traversal can be aborted.
*/
ccl_device_forceinline bool shadow_handle_transparent_isect(
- KernelGlobals *kg,
- ShaderData *shadow_sd,
- ccl_addr_space PathState *state,
-# ifdef __VOLUME__
- ccl_addr_space struct PathState *volume_state,
-# endif
- Intersection *isect,
- Ray *ray,
- float3 *throughput)
+ KernelGlobals *kg,
+ ShaderData *shadow_sd,
+ ccl_addr_space PathState *state,
+#ifdef __VOLUME__
+ ccl_addr_space struct PathState *volume_state,
+#endif
+ Intersection *isect,
+ Ray *ray,
+ float3 *throughput)
{
#ifdef __VOLUME__
- /* Attenuation between last surface and next surface. */
- if(volume_state->volume_stack[0].shader != SHADER_NONE) {
- Ray segment_ray = *ray;
- segment_ray.t = isect->t;
- kernel_volume_shadow(kg,
- shadow_sd,
- volume_state,
- &segment_ray,
- throughput);
- }
+ /* Attenuation between last surface and next surface. */
+ if (volume_state->volume_stack[0].shader != SHADER_NONE) {
+ Ray segment_ray = *ray;
+ segment_ray.t = isect->t;
+ kernel_volume_shadow(kg, shadow_sd, volume_state, &segment_ray, throughput);
+ }
#endif
- /* Setup shader data at surface. */
- shader_setup_from_ray(kg, shadow_sd, isect, ray);
- /* Attenuation from transparent surface. */
- if(!(shadow_sd->flag & SD_HAS_ONLY_VOLUME)) {
- path_state_modify_bounce(state, true);
- shader_eval_surface(kg,
- shadow_sd,
- state,
- PATH_RAY_SHADOW);
- path_state_modify_bounce(state, false);
- *throughput *= shader_bsdf_transparency(kg, shadow_sd);
- }
- /* Stop if all light is blocked. */
- if(is_zero(*throughput)) {
- return true;
- }
+ /* Setup shader data at surface. */
+ shader_setup_from_ray(kg, shadow_sd, isect, ray);
+ /* Attenuation from transparent surface. */
+ if (!(shadow_sd->flag & SD_HAS_ONLY_VOLUME)) {
+ path_state_modify_bounce(state, true);
+ shader_eval_surface(kg, shadow_sd, state, PATH_RAY_SHADOW);
+ path_state_modify_bounce(state, false);
+ *throughput *= shader_bsdf_transparency(kg, shadow_sd);
+ }
+ /* Stop if all light is blocked. */
+ if (is_zero(*throughput)) {
+ return true;
+ }
#ifdef __VOLUME__
- /* Exit/enter volume. */
- kernel_volume_stack_enter_exit(kg, shadow_sd, volume_state->volume_stack);
+ /* Exit/enter volume. */
+ kernel_volume_stack_enter_exit(kg, shadow_sd, volume_state->volume_stack);
#endif
- return false;
+ return false;
}
/* Special version which only handles opaque shadows. */
@@ -110,19 +103,15 @@ ccl_device bool shadow_blocked_opaque(KernelGlobals *kg,
Intersection *isect,
float3 *shadow)
{
- const bool blocked = scene_intersect(kg,
- *ray,
- visibility & PATH_RAY_SHADOW_OPAQUE,
- isect,
- NULL,
- 0.0f, 0.0f);
+ const bool blocked = scene_intersect(
+ kg, *ray, visibility & PATH_RAY_SHADOW_OPAQUE, isect, NULL, 0.0f, 0.0f);
#ifdef __VOLUME__
- if(!blocked && state->volume_stack[0].shader != SHADER_NONE) {
- /* Apply attenuation from current volume shader. */
- kernel_volume_shadow(kg, shadow_sd, state, ray, shadow);
- }
+ if (!blocked && state->volume_stack[0].shader != SHADER_NONE) {
+ /* Apply attenuation from current volume shader. */
+ kernel_volume_shadow(kg, shadow_sd, state, ray, shadow);
+ }
#endif
- return blocked;
+ return blocked;
}
#ifdef __TRANSPARENT_SHADOWS__
@@ -169,94 +158,80 @@ ccl_device bool shadow_blocked_transparent_all_loop(KernelGlobals *kg,
uint max_hits,
float3 *shadow)
{
- /* Intersect to find an opaque surface, or record all transparent
- * surface hits.
- */
- uint num_hits;
- const bool blocked = scene_intersect_shadow_all(kg,
- ray,
- hits,
- visibility,
- max_hits,
- &num_hits);
+ /* Intersect to find an opaque surface, or record all transparent
+ * surface hits.
+ */
+ uint num_hits;
+ const bool blocked = scene_intersect_shadow_all(kg, ray, hits, visibility, max_hits, &num_hits);
# ifdef __VOLUME__
- VolumeState volume_state;
+ VolumeState volume_state;
# endif
- /* If no opaque surface found but we did find transparent hits,
- * shade them.
- */
- if(!blocked && num_hits > 0) {
- float3 throughput = make_float3(1.0f, 1.0f, 1.0f);
- float3 Pend = ray->P + ray->D*ray->t;
- float last_t = 0.0f;
- int bounce = state->transparent_bounce;
- Intersection *isect = hits;
+ /* If no opaque surface found but we did find transparent hits,
+ * shade them.
+ */
+ if (!blocked && num_hits > 0) {
+ float3 throughput = make_float3(1.0f, 1.0f, 1.0f);
+ float3 Pend = ray->P + ray->D * ray->t;
+ float last_t = 0.0f;
+ int bounce = state->transparent_bounce;
+ Intersection *isect = hits;
# ifdef __VOLUME__
# ifdef __SPLIT_KERNEL__
- ccl_addr_space
+ ccl_addr_space
# endif
- PathState *ps = shadow_blocked_volume_path_state(kg,
- &volume_state,
- state,
- sd,
- ray);
+ PathState *ps = shadow_blocked_volume_path_state(kg, &volume_state, state, sd, ray);
# endif
- sort_intersections(hits, num_hits);
- for(int hit = 0; hit < num_hits; hit++, isect++) {
- /* Adjust intersection distance for moving ray forward. */
- float new_t = isect->t;
- isect->t -= last_t;
- /* Skip hit if we did not move forward, step by step raytracing
- * would have skipped it as well then.
- */
- if(last_t == new_t) {
- continue;
- }
- last_t = new_t;
- /* Attenuate the throughput. */
- if(shadow_handle_transparent_isect(kg,
- shadow_sd,
- state,
-#ifdef __VOLUME__
- ps,
-#endif
- isect,
- ray,
- &throughput))
- {
- return true;
- }
- /* Move ray forward. */
- ray->P = shadow_sd->P;
- if(ray->t != FLT_MAX) {
- ray->D = normalize_len(Pend - ray->P, &ray->t);
- }
- bounce++;
- }
+ sort_intersections(hits, num_hits);
+ for (int hit = 0; hit < num_hits; hit++, isect++) {
+ /* Adjust intersection distance for moving ray forward. */
+ float new_t = isect->t;
+ isect->t -= last_t;
+ /* Skip hit if we did not move forward, step by step raytracing
+ * would have skipped it as well then.
+ */
+ if (last_t == new_t) {
+ continue;
+ }
+ last_t = new_t;
+ /* Attenuate the throughput. */
+ if (shadow_handle_transparent_isect(kg,
+ shadow_sd,
+ state,
# ifdef __VOLUME__
- /* Attenuation for last line segment towards light. */
- if(ps->volume_stack[0].shader != SHADER_NONE) {
- kernel_volume_shadow(kg, shadow_sd, ps, ray, &throughput);
- }
+ ps,
# endif
- *shadow = throughput;
- return is_zero(throughput);
- }
+ isect,
+ ray,
+ &throughput)) {
+ return true;
+ }
+ /* Move ray forward. */
+ ray->P = shadow_sd->P;
+ if (ray->t != FLT_MAX) {
+ ray->D = normalize_len(Pend - ray->P, &ray->t);
+ }
+ bounce++;
+ }
# ifdef __VOLUME__
- if(!blocked && state->volume_stack[0].shader != SHADER_NONE) {
- /* Apply attenuation from current volume shader. */
+ /* Attenuation for last line segment towards light. */
+ if (ps->volume_stack[0].shader != SHADER_NONE) {
+ kernel_volume_shadow(kg, shadow_sd, ps, ray, &throughput);
+ }
+# endif
+ *shadow = throughput;
+ return is_zero(throughput);
+ }
+# ifdef __VOLUME__
+ if (!blocked && state->volume_stack[0].shader != SHADER_NONE) {
+ /* Apply attenuation from current volume shader. */
# ifdef __SPLIT_KERNEL__
- ccl_addr_space
+ ccl_addr_space
# endif
- PathState *ps = shadow_blocked_volume_path_state(kg,
- &volume_state,
- state,
- sd,
- ray);
- kernel_volume_shadow(kg, shadow_sd, ps, ray, shadow);
- }
+ PathState *ps = shadow_blocked_volume_path_state(kg, &volume_state, state, sd, ray);
+ kernel_volume_shadow(kg, shadow_sd, ps, ray, shadow);
+ }
# endif
- return blocked;
+ return blocked;
}
/* Here we do all device specific trickery before invoking actual traversal
@@ -272,43 +247,36 @@ ccl_device bool shadow_blocked_transparent_all(KernelGlobals *kg,
float3 *shadow)
{
# ifdef __SPLIT_KERNEL__
- Intersection hits_[SHADOW_STACK_MAX_HITS];
- Intersection *hits = &hits_[0];
+ Intersection hits_[SHADOW_STACK_MAX_HITS];
+ Intersection *hits = &hits_[0];
# elif defined(__KERNEL_CUDA__)
- Intersection *hits = kg->hits_stack;
+ Intersection *hits = kg->hits_stack;
# else
- Intersection hits_stack[SHADOW_STACK_MAX_HITS];
- Intersection *hits = hits_stack;
+ Intersection hits_stack[SHADOW_STACK_MAX_HITS];
+ Intersection *hits = hits_stack;
# endif
# ifndef __KERNEL_GPU__
- /* Prefer to use stack but use dynamic allocation if too deep max hits
- * we need max_hits + 1 storage space due to the logic in
- * scene_intersect_shadow_all which will first store and then check if
- * the limit is exceeded.
- *
- * Ignore this on GPU because of slow/unavailable malloc().
- */
- if(max_hits + 1 > SHADOW_STACK_MAX_HITS) {
- if(kg->transparent_shadow_intersections == NULL) {
- const int transparent_max_bounce = kernel_data.integrator.transparent_max_bounce;
- kg->transparent_shadow_intersections =
- (Intersection*)malloc(sizeof(Intersection)*(transparent_max_bounce + 1));
- }
- hits = kg->transparent_shadow_intersections;
- }
-# endif /* __KERNEL_GPU__ */
- /* Invoke actual traversal. */
- return shadow_blocked_transparent_all_loop(kg,
- sd,
- shadow_sd,
- state,
- visibility,
- ray,
- hits,
- max_hits,
- shadow);
+ /* Prefer to use stack but use dynamic allocation if too deep max hits
+ * we need max_hits + 1 storage space due to the logic in
+ * scene_intersect_shadow_all which will first store and then check if
+ * the limit is exceeded.
+ *
+ * Ignore this on GPU because of slow/unavailable malloc().
+ */
+ if (max_hits + 1 > SHADOW_STACK_MAX_HITS) {
+ if (kg->transparent_shadow_intersections == NULL) {
+ const int transparent_max_bounce = kernel_data.integrator.transparent_max_bounce;
+ kg->transparent_shadow_intersections = (Intersection *)malloc(sizeof(Intersection) *
+ (transparent_max_bounce + 1));
+ }
+ hits = kg->transparent_shadow_intersections;
+ }
+# endif /* __KERNEL_GPU__ */
+ /* Invoke actual traversal. */
+ return shadow_blocked_transparent_all_loop(
+ kg, sd, shadow_sd, state, visibility, ray, hits, max_hits, shadow);
}
-# endif /* __SHADOW_RECORD_ALL__ */
+# endif /* __SHADOW_RECORD_ALL__ */
# if defined(__KERNEL_GPU__) || !defined(__SHADOW_RECORD_ALL__)
/* Shadow function to compute how much light is blocked,
@@ -323,130 +291,100 @@ ccl_device bool shadow_blocked_transparent_all(KernelGlobals *kg,
/* This function is only implementing device-independent traversal logic
* which requires some precalculation done.
*/
-ccl_device bool shadow_blocked_transparent_stepped_loop(
- KernelGlobals *kg,
- ShaderData *sd,
- ShaderData *shadow_sd,
- ccl_addr_space PathState *state,
- const uint visibility,
- Ray *ray,
- Intersection *isect,
- const bool blocked,
- const bool is_transparent_isect,
- float3 *shadow)
+ccl_device bool shadow_blocked_transparent_stepped_loop(KernelGlobals *kg,
+ ShaderData *sd,
+ ShaderData *shadow_sd,
+ ccl_addr_space PathState *state,
+ const uint visibility,
+ Ray *ray,
+ Intersection *isect,
+ const bool blocked,
+ const bool is_transparent_isect,
+ float3 *shadow)
{
# ifdef __VOLUME__
- VolumeState volume_state;
+ VolumeState volume_state;
# endif
- if(blocked && is_transparent_isect) {
- float3 throughput = make_float3(1.0f, 1.0f, 1.0f);
- float3 Pend = ray->P + ray->D*ray->t;
- int bounce = state->transparent_bounce;
+ if (blocked && is_transparent_isect) {
+ float3 throughput = make_float3(1.0f, 1.0f, 1.0f);
+ float3 Pend = ray->P + ray->D * ray->t;
+ int bounce = state->transparent_bounce;
# ifdef __VOLUME__
# ifdef __SPLIT_KERNEL__
- ccl_addr_space
+ ccl_addr_space
# endif
- PathState *ps = shadow_blocked_volume_path_state(kg,
- &volume_state,
- state,
- sd,
- ray);
+ PathState *ps = shadow_blocked_volume_path_state(kg, &volume_state, state, sd, ray);
# endif
- for(;;) {
- if(bounce >= kernel_data.integrator.transparent_max_bounce) {
- return true;
- }
- if(!scene_intersect(kg,
- *ray,
- visibility & PATH_RAY_SHADOW_TRANSPARENT,
- isect,
- NULL,
- 0.0f, 0.0f))
- {
- break;
- }
- if(!shader_transparent_shadow(kg, isect)) {
- return true;
- }
- /* Attenuate the throughput. */
- if(shadow_handle_transparent_isect(kg,
- shadow_sd,
- state,
-#ifdef __VOLUME__
- ps,
-#endif
- isect,
- ray,
- &throughput))
- {
- return true;
- }
- /* Move ray forward. */
- ray->P = ray_offset(shadow_sd->P, -shadow_sd->Ng);
- if(ray->t != FLT_MAX) {
- ray->D = normalize_len(Pend - ray->P, &ray->t);
- }
- bounce++;
- }
+ for (;;) {
+ if (bounce >= kernel_data.integrator.transparent_max_bounce) {
+ return true;
+ }
+ if (!scene_intersect(
+ kg, *ray, visibility & PATH_RAY_SHADOW_TRANSPARENT, isect, NULL, 0.0f, 0.0f)) {
+ break;
+ }
+ if (!shader_transparent_shadow(kg, isect)) {
+ return true;
+ }
+ /* Attenuate the throughput. */
+ if (shadow_handle_transparent_isect(kg,
+ shadow_sd,
+ state,
+# ifdef __VOLUME__
+ ps,
+# endif
+ isect,
+ ray,
+ &throughput)) {
+ return true;
+ }
+ /* Move ray forward. */
+ ray->P = ray_offset(shadow_sd->P, -shadow_sd->Ng);
+ if (ray->t != FLT_MAX) {
+ ray->D = normalize_len(Pend - ray->P, &ray->t);
+ }
+ bounce++;
+ }
# ifdef __VOLUME__
- /* Attenuation for last line segment towards light. */
- if(ps->volume_stack[0].shader != SHADER_NONE) {
- kernel_volume_shadow(kg, shadow_sd, ps, ray, &throughput);
- }
+ /* Attenuation for last line segment towards light. */
+ if (ps->volume_stack[0].shader != SHADER_NONE) {
+ kernel_volume_shadow(kg, shadow_sd, ps, ray, &throughput);
+ }
# endif
- *shadow *= throughput;
- return is_zero(throughput);
- }
+ *shadow *= throughput;
+ return is_zero(throughput);
+ }
# ifdef __VOLUME__
- if(!blocked && state->volume_stack[0].shader != SHADER_NONE) {
- /* Apply attenuation from current volume shader. */
+ if (!blocked && state->volume_stack[0].shader != SHADER_NONE) {
+ /* Apply attenuation from current volume shader. */
# ifdef __SPLIT_KERNEL__
- ccl_addr_space
+ ccl_addr_space
# endif
- PathState *ps = shadow_blocked_volume_path_state(kg,
- &volume_state,
- state,
- sd,
- ray);
- kernel_volume_shadow(kg, shadow_sd, ps, ray, shadow);
- }
+ PathState *ps = shadow_blocked_volume_path_state(kg, &volume_state, state, sd, ray);
+ kernel_volume_shadow(kg, shadow_sd, ps, ray, shadow);
+ }
# endif
- return blocked;
+ return blocked;
}
-ccl_device bool shadow_blocked_transparent_stepped(
- KernelGlobals *kg,
- ShaderData *sd,
- ShaderData *shadow_sd,
- ccl_addr_space PathState *state,
- const uint visibility,
- Ray *ray,
- Intersection *isect,
- float3 *shadow)
+ccl_device bool shadow_blocked_transparent_stepped(KernelGlobals *kg,
+ ShaderData *sd,
+ ShaderData *shadow_sd,
+ ccl_addr_space PathState *state,
+ const uint visibility,
+ Ray *ray,
+ Intersection *isect,
+ float3 *shadow)
{
- bool blocked = scene_intersect(kg,
- *ray,
- visibility & PATH_RAY_SHADOW_OPAQUE,
- isect,
- NULL,
- 0.0f, 0.0f);
- bool is_transparent_isect = blocked
- ? shader_transparent_shadow(kg, isect)
- : false;
- return shadow_blocked_transparent_stepped_loop(kg,
- sd,
- shadow_sd,
- state,
- visibility,
- ray,
- isect,
- blocked,
- is_transparent_isect,
- shadow);
+ bool blocked = scene_intersect(
+ kg, *ray, visibility & PATH_RAY_SHADOW_OPAQUE, isect, NULL, 0.0f, 0.0f);
+ bool is_transparent_isect = blocked ? shader_transparent_shadow(kg, isect) : false;
+ return shadow_blocked_transparent_stepped_loop(
+ kg, sd, shadow_sd, state, visibility, ray, isect, blocked, is_transparent_isect, shadow);
}
-# endif /* __KERNEL_GPU__ || !__SHADOW_RECORD_ALL__ */
-#endif /* __TRANSPARENT_SHADOWS__ */
+# endif /* __KERNEL_GPU__ || !__SHADOW_RECORD_ALL__ */
+#endif /* __TRANSPARENT_SHADOWS__ */
ccl_device_inline bool shadow_blocked(KernelGlobals *kg,
ShaderData *sd,
@@ -455,100 +393,65 @@ ccl_device_inline bool shadow_blocked(KernelGlobals *kg,
Ray *ray_input,
float3 *shadow)
{
- Ray *ray = ray_input;
- Intersection isect;
- /* Some common early checks. */
- *shadow = make_float3(1.0f, 1.0f, 1.0f);
- if(ray->t == 0.0f) {
- return false;
- }
+ Ray *ray = ray_input;
+ Intersection isect;
+ /* Some common early checks. */
+ *shadow = make_float3(1.0f, 1.0f, 1.0f);
+ if (ray->t == 0.0f) {
+ return false;
+ }
#ifdef __SHADOW_TRICKS__
- const uint visibility = (state->flag & PATH_RAY_SHADOW_CATCHER)
- ? PATH_RAY_SHADOW_NON_CATCHER
- : PATH_RAY_SHADOW;
+ const uint visibility = (state->flag & PATH_RAY_SHADOW_CATCHER) ? PATH_RAY_SHADOW_NON_CATCHER :
+ PATH_RAY_SHADOW;
#else
- const uint visibility = PATH_RAY_SHADOW;
+ const uint visibility = PATH_RAY_SHADOW;
#endif
- /* Do actual shadow shading. */
- /* First of all, we check if integrator requires transparent shadows.
- * if not, we use simplest and fastest ever way to calculate occlusion.
- */
+ /* Do actual shadow shading. */
+ /* First of all, we check if integrator requires transparent shadows.
+ * if not, we use simplest and fastest ever way to calculate occlusion.
+ */
#ifdef __TRANSPARENT_SHADOWS__
- if(!kernel_data.integrator.transparent_shadows)
+ if (!kernel_data.integrator.transparent_shadows)
#endif
- {
- return shadow_blocked_opaque(kg,
- shadow_sd,
- state,
- visibility,
- ray,
- &isect,
- shadow);
- }
+ {
+ return shadow_blocked_opaque(kg, shadow_sd, state, visibility, ray, &isect, shadow);
+ }
#ifdef __TRANSPARENT_SHADOWS__
# ifdef __SHADOW_RECORD_ALL__
- /* For the transparent shadows we try to use record-all logic on the
- * devices which supports this.
- */
- const int transparent_max_bounce = kernel_data.integrator.transparent_max_bounce;
- /* Check transparent bounces here, for volume scatter which can do
- * lighting before surface path termination is checked.
- */
- if(state->transparent_bounce >= transparent_max_bounce) {
- return true;
- }
- const uint max_hits = transparent_max_bounce - state->transparent_bounce - 1;
+ /* For the transparent shadows we try to use record-all logic on the
+ * devices which supports this.
+ */
+ const int transparent_max_bounce = kernel_data.integrator.transparent_max_bounce;
+ /* Check transparent bounces here, for volume scatter which can do
+ * lighting before surface path termination is checked.
+ */
+ if (state->transparent_bounce >= transparent_max_bounce) {
+ return true;
+ }
+ const uint max_hits = transparent_max_bounce - state->transparent_bounce - 1;
# ifdef __KERNEL_GPU__
- /* On GPU we do trickey with tracing opaque ray first, this avoids speed
- * regressions in some files.
- *
- * TODO(sergey): Check why using record-all behavior causes slowdown in such
- * cases. Could that be caused by a higher spill pressure?
- */
- const bool blocked = scene_intersect(kg,
- *ray,
- visibility & PATH_RAY_SHADOW_OPAQUE,
- &isect,
- NULL,
- 0.0f, 0.0f);
- const bool is_transparent_isect = blocked
- ? shader_transparent_shadow(kg, &isect)
- : false;
- if(!blocked || !is_transparent_isect ||
- max_hits + 1 >= SHADOW_STACK_MAX_HITS)
- {
- return shadow_blocked_transparent_stepped_loop(kg,
- sd,
- shadow_sd,
- state,
- visibility,
- ray,
- &isect,
- blocked,
- is_transparent_isect,
- shadow);
- }
-# endif /* __KERNEL_GPU__ */
- return shadow_blocked_transparent_all(kg,
- sd,
- shadow_sd,
- state,
- visibility,
- ray,
- max_hits,
- shadow);
+ /* On GPU we do trickey with tracing opaque ray first, this avoids speed
+ * regressions in some files.
+ *
+ * TODO(sergey): Check why using record-all behavior causes slowdown in such
+ * cases. Could that be caused by a higher spill pressure?
+ */
+ const bool blocked = scene_intersect(
+ kg, *ray, visibility & PATH_RAY_SHADOW_OPAQUE, &isect, NULL, 0.0f, 0.0f);
+ const bool is_transparent_isect = blocked ? shader_transparent_shadow(kg, &isect) : false;
+ if (!blocked || !is_transparent_isect || max_hits + 1 >= SHADOW_STACK_MAX_HITS) {
+ return shadow_blocked_transparent_stepped_loop(
+ kg, sd, shadow_sd, state, visibility, ray, &isect, blocked, is_transparent_isect, shadow);
+ }
+# endif /* __KERNEL_GPU__ */
+ return shadow_blocked_transparent_all(
+ kg, sd, shadow_sd, state, visibility, ray, max_hits, shadow);
# else /* __SHADOW_RECORD_ALL__ */
- /* Fallback to a slowest version which works on all devices. */
- return shadow_blocked_transparent_stepped(kg,
- sd,
- shadow_sd,
- state,
- visibility,
- ray,
- &isect,
- shadow);
-# endif /* __SHADOW_RECORD_ALL__ */
-#endif /* __TRANSPARENT_SHADOWS__ */
+ /* Fallback to a slowest version which works on all devices. */
+ return shadow_blocked_transparent_stepped(
+ kg, sd, shadow_sd, state, visibility, ray, &isect, shadow);
+# endif /* __SHADOW_RECORD_ALL__ */
+#endif /* __TRANSPARENT_SHADOWS__ */
}
#undef SHADOW_STACK_MAX_HITS
diff --git a/intern/cycles/kernel/kernel_subsurface.h b/intern/cycles/kernel/kernel_subsurface.h
index 96b717530ce..7510e50a962 100644
--- a/intern/cycles/kernel/kernel_subsurface.h
+++ b/intern/cycles/kernel/kernel_subsurface.h
@@ -22,317 +22,295 @@ CCL_NAMESPACE_BEGIN
* http://library.imageworks.com/pdfs/imageworks-library-BSSRDF-sampling.pdf
*/
-ccl_device_inline float3 subsurface_scatter_eval(ShaderData *sd,
- const ShaderClosure *sc,
- float disk_r,
- float r,
- bool all)
+ccl_device_inline float3
+subsurface_scatter_eval(ShaderData *sd, const ShaderClosure *sc, float disk_r, float r, bool all)
{
- /* this is the veach one-sample model with balance heuristic, some pdf
- * factors drop out when using balance heuristic weighting */
- float3 eval_sum = make_float3(0.0f, 0.0f, 0.0f);
- float pdf_sum = 0.0f;
- float sample_weight_inv = 0.0f;
+ /* this is the veach one-sample model with balance heuristic, some pdf
+ * factors drop out when using balance heuristic weighting */
+ float3 eval_sum = make_float3(0.0f, 0.0f, 0.0f);
+ float pdf_sum = 0.0f;
+ float sample_weight_inv = 0.0f;
- if(!all) {
- float sample_weight_sum = 0.0f;
+ if (!all) {
+ float sample_weight_sum = 0.0f;
- for(int i = 0; i < sd->num_closure; i++) {
- sc = &sd->closure[i];
+ for (int i = 0; i < sd->num_closure; i++) {
+ sc = &sd->closure[i];
- if(CLOSURE_IS_DISK_BSSRDF(sc->type)) {
- sample_weight_sum += sc->sample_weight;
- }
- }
+ if (CLOSURE_IS_DISK_BSSRDF(sc->type)) {
+ sample_weight_sum += sc->sample_weight;
+ }
+ }
- sample_weight_inv = 1.0f/sample_weight_sum;
- }
+ sample_weight_inv = 1.0f / sample_weight_sum;
+ }
- for(int i = 0; i < sd->num_closure; i++) {
- sc = &sd->closure[i];
+ for (int i = 0; i < sd->num_closure; i++) {
+ sc = &sd->closure[i];
- if(CLOSURE_IS_DISK_BSSRDF(sc->type)) {
- /* in case of branched path integrate we sample all bssrdf's once,
- * for path trace we pick one, so adjust pdf for that */
- float sample_weight = (all)? 1.0f: sc->sample_weight * sample_weight_inv;
+ if (CLOSURE_IS_DISK_BSSRDF(sc->type)) {
+ /* in case of branched path integrate we sample all bssrdf's once,
+ * for path trace we pick one, so adjust pdf for that */
+ float sample_weight = (all) ? 1.0f : sc->sample_weight * sample_weight_inv;
- /* compute pdf */
- float3 eval = bssrdf_eval(sc, r);
- float pdf = bssrdf_pdf(sc, disk_r);
+ /* compute pdf */
+ float3 eval = bssrdf_eval(sc, r);
+ float pdf = bssrdf_pdf(sc, disk_r);
- eval_sum += sc->weight * eval;
- pdf_sum += sample_weight * pdf;
- }
- }
+ eval_sum += sc->weight * eval;
+ pdf_sum += sample_weight * pdf;
+ }
+ }
- return (pdf_sum > 0.0f)? eval_sum / pdf_sum : make_float3(0.0f, 0.0f, 0.0f);
+ return (pdf_sum > 0.0f) ? eval_sum / pdf_sum : make_float3(0.0f, 0.0f, 0.0f);
}
/* replace closures with a single diffuse bsdf closure after scatter step */
-ccl_device void subsurface_scatter_setup_diffuse_bsdf(KernelGlobals *kg, ShaderData *sd, ClosureType type, float roughness, float3 weight, float3 N)
+ccl_device void subsurface_scatter_setup_diffuse_bsdf(
+ KernelGlobals *kg, ShaderData *sd, ClosureType type, float roughness, float3 weight, float3 N)
{
- sd->flag &= ~SD_CLOSURE_FLAGS;
- sd->num_closure = 0;
- sd->num_closure_left = kernel_data.integrator.max_closures;
+ sd->flag &= ~SD_CLOSURE_FLAGS;
+ sd->num_closure = 0;
+ sd->num_closure_left = kernel_data.integrator.max_closures;
#ifdef __PRINCIPLED__
- if(type == CLOSURE_BSSRDF_PRINCIPLED_ID ||
- type == CLOSURE_BSSRDF_PRINCIPLED_RANDOM_WALK_ID)
- {
- PrincipledDiffuseBsdf *bsdf = (PrincipledDiffuseBsdf*)bsdf_alloc(sd, sizeof(PrincipledDiffuseBsdf), weight);
-
- if(bsdf) {
- bsdf->N = N;
- bsdf->roughness = roughness;
- sd->flag |= bsdf_principled_diffuse_setup(bsdf);
-
- /* replace CLOSURE_BSDF_PRINCIPLED_DIFFUSE_ID with this special ID so render passes
- * can recognize it as not being a regular Disney principled diffuse closure */
- bsdf->type = CLOSURE_BSDF_BSSRDF_PRINCIPLED_ID;
- }
- }
- else if(CLOSURE_IS_BSDF_BSSRDF(type) ||
- CLOSURE_IS_BSSRDF(type))
-#endif /* __PRINCIPLED__ */
- {
- DiffuseBsdf *bsdf = (DiffuseBsdf*)bsdf_alloc(sd, sizeof(DiffuseBsdf), weight);
-
- if(bsdf) {
- bsdf->N = N;
- sd->flag |= bsdf_diffuse_setup(bsdf);
-
- /* replace CLOSURE_BSDF_DIFFUSE_ID with this special ID so render passes
- * can recognize it as not being a regular diffuse closure */
- bsdf->type = CLOSURE_BSDF_BSSRDF_ID;
- }
- }
+ if (type == CLOSURE_BSSRDF_PRINCIPLED_ID || type == CLOSURE_BSSRDF_PRINCIPLED_RANDOM_WALK_ID) {
+ PrincipledDiffuseBsdf *bsdf = (PrincipledDiffuseBsdf *)bsdf_alloc(
+ sd, sizeof(PrincipledDiffuseBsdf), weight);
+
+ if (bsdf) {
+ bsdf->N = N;
+ bsdf->roughness = roughness;
+ sd->flag |= bsdf_principled_diffuse_setup(bsdf);
+
+ /* replace CLOSURE_BSDF_PRINCIPLED_DIFFUSE_ID with this special ID so render passes
+ * can recognize it as not being a regular Disney principled diffuse closure */
+ bsdf->type = CLOSURE_BSDF_BSSRDF_PRINCIPLED_ID;
+ }
+ }
+ else if (CLOSURE_IS_BSDF_BSSRDF(type) || CLOSURE_IS_BSSRDF(type))
+#endif /* __PRINCIPLED__ */
+ {
+ DiffuseBsdf *bsdf = (DiffuseBsdf *)bsdf_alloc(sd, sizeof(DiffuseBsdf), weight);
+
+ if (bsdf) {
+ bsdf->N = N;
+ sd->flag |= bsdf_diffuse_setup(bsdf);
+
+ /* replace CLOSURE_BSDF_DIFFUSE_ID with this special ID so render passes
+ * can recognize it as not being a regular diffuse closure */
+ bsdf->type = CLOSURE_BSDF_BSSRDF_ID;
+ }
+ }
}
/* optionally do blurring of color and/or bump mapping, at the cost of a shader evaluation */
ccl_device float3 subsurface_color_pow(float3 color, float exponent)
{
- color = max(color, make_float3(0.0f, 0.0f, 0.0f));
-
- if(exponent == 1.0f) {
- /* nothing to do */
- }
- else if(exponent == 0.5f) {
- color.x = sqrtf(color.x);
- color.y = sqrtf(color.y);
- color.z = sqrtf(color.z);
- }
- else {
- color.x = powf(color.x, exponent);
- color.y = powf(color.y, exponent);
- color.z = powf(color.z, exponent);
- }
-
- return color;
+ color = max(color, make_float3(0.0f, 0.0f, 0.0f));
+
+ if (exponent == 1.0f) {
+ /* nothing to do */
+ }
+ else if (exponent == 0.5f) {
+ color.x = sqrtf(color.x);
+ color.y = sqrtf(color.y);
+ color.z = sqrtf(color.z);
+ }
+ else {
+ color.x = powf(color.x, exponent);
+ color.y = powf(color.y, exponent);
+ color.z = powf(color.z, exponent);
+ }
+
+ return color;
}
-ccl_device void subsurface_color_bump_blur(KernelGlobals *kg,
- ShaderData *sd,
- ccl_addr_space PathState *state,
- float3 *eval,
- float3 *N)
+ccl_device void subsurface_color_bump_blur(
+ KernelGlobals *kg, ShaderData *sd, ccl_addr_space PathState *state, float3 *eval, float3 *N)
{
- /* average color and texture blur at outgoing point */
- float texture_blur;
- float3 out_color = shader_bssrdf_sum(sd, NULL, &texture_blur);
-
- /* do we have bump mapping? */
- bool bump = (sd->flag & SD_HAS_BSSRDF_BUMP) != 0;
-
- if(bump || texture_blur > 0.0f) {
- /* average color and normal at incoming point */
- shader_eval_surface(kg, sd, state, state->flag);
- float3 in_color = shader_bssrdf_sum(sd, (bump)? N: NULL, NULL);
-
- /* we simply divide out the average color and multiply with the average
- * of the other one. we could try to do this per closure but it's quite
- * tricky to match closures between shader evaluations, their number and
- * order may change, this is simpler */
- if(texture_blur > 0.0f) {
- out_color = subsurface_color_pow(out_color, texture_blur);
- in_color = subsurface_color_pow(in_color, texture_blur);
-
- *eval *= safe_divide_color(in_color, out_color);
- }
- }
+ /* average color and texture blur at outgoing point */
+ float texture_blur;
+ float3 out_color = shader_bssrdf_sum(sd, NULL, &texture_blur);
+
+ /* do we have bump mapping? */
+ bool bump = (sd->flag & SD_HAS_BSSRDF_BUMP) != 0;
+
+ if (bump || texture_blur > 0.0f) {
+ /* average color and normal at incoming point */
+ shader_eval_surface(kg, sd, state, state->flag);
+ float3 in_color = shader_bssrdf_sum(sd, (bump) ? N : NULL, NULL);
+
+ /* we simply divide out the average color and multiply with the average
+ * of the other one. we could try to do this per closure but it's quite
+ * tricky to match closures between shader evaluations, their number and
+ * order may change, this is simpler */
+ if (texture_blur > 0.0f) {
+ out_color = subsurface_color_pow(out_color, texture_blur);
+ in_color = subsurface_color_pow(in_color, texture_blur);
+
+ *eval *= safe_divide_color(in_color, out_color);
+ }
+ }
}
/* Subsurface scattering step, from a point on the surface to other
* nearby points on the same object.
*/
-ccl_device_inline int subsurface_scatter_disk(
- KernelGlobals *kg,
- LocalIntersection *ss_isect,
- ShaderData *sd,
- const ShaderClosure *sc,
- uint *lcg_state,
- float disk_u,
- float disk_v,
- bool all)
+ccl_device_inline int subsurface_scatter_disk(KernelGlobals *kg,
+ LocalIntersection *ss_isect,
+ ShaderData *sd,
+ const ShaderClosure *sc,
+ uint *lcg_state,
+ float disk_u,
+ float disk_v,
+ bool all)
{
- /* pick random axis in local frame and point on disk */
- float3 disk_N, disk_T, disk_B;
- float pick_pdf_N, pick_pdf_T, pick_pdf_B;
-
- disk_N = sd->Ng;
- make_orthonormals(disk_N, &disk_T, &disk_B);
-
- if(disk_v < 0.5f) {
- pick_pdf_N = 0.5f;
- pick_pdf_T = 0.25f;
- pick_pdf_B = 0.25f;
- disk_v *= 2.0f;
- }
- else if(disk_v < 0.75f) {
- float3 tmp = disk_N;
- disk_N = disk_T;
- disk_T = tmp;
- pick_pdf_N = 0.25f;
- pick_pdf_T = 0.5f;
- pick_pdf_B = 0.25f;
- disk_v = (disk_v - 0.5f)*4.0f;
- }
- else {
- float3 tmp = disk_N;
- disk_N = disk_B;
- disk_B = tmp;
- pick_pdf_N = 0.25f;
- pick_pdf_T = 0.25f;
- pick_pdf_B = 0.5f;
- disk_v = (disk_v - 0.75f)*4.0f;
- }
-
- /* sample point on disk */
- float phi = M_2PI_F * disk_v;
- float disk_height, disk_r;
-
- bssrdf_sample(sc, disk_u, &disk_r, &disk_height);
-
- float3 disk_P = (disk_r*cosf(phi)) * disk_T + (disk_r*sinf(phi)) * disk_B;
-
- /* create ray */
+ /* pick random axis in local frame and point on disk */
+ float3 disk_N, disk_T, disk_B;
+ float pick_pdf_N, pick_pdf_T, pick_pdf_B;
+
+ disk_N = sd->Ng;
+ make_orthonormals(disk_N, &disk_T, &disk_B);
+
+ if (disk_v < 0.5f) {
+ pick_pdf_N = 0.5f;
+ pick_pdf_T = 0.25f;
+ pick_pdf_B = 0.25f;
+ disk_v *= 2.0f;
+ }
+ else if (disk_v < 0.75f) {
+ float3 tmp = disk_N;
+ disk_N = disk_T;
+ disk_T = tmp;
+ pick_pdf_N = 0.25f;
+ pick_pdf_T = 0.5f;
+ pick_pdf_B = 0.25f;
+ disk_v = (disk_v - 0.5f) * 4.0f;
+ }
+ else {
+ float3 tmp = disk_N;
+ disk_N = disk_B;
+ disk_B = tmp;
+ pick_pdf_N = 0.25f;
+ pick_pdf_T = 0.25f;
+ pick_pdf_B = 0.5f;
+ disk_v = (disk_v - 0.75f) * 4.0f;
+ }
+
+ /* sample point on disk */
+ float phi = M_2PI_F * disk_v;
+ float disk_height, disk_r;
+
+ bssrdf_sample(sc, disk_u, &disk_r, &disk_height);
+
+ float3 disk_P = (disk_r * cosf(phi)) * disk_T + (disk_r * sinf(phi)) * disk_B;
+
+ /* create ray */
#ifdef __SPLIT_KERNEL__
- Ray ray_object = ss_isect->ray;
- Ray *ray = &ray_object;
+ Ray ray_object = ss_isect->ray;
+ Ray *ray = &ray_object;
#else
- Ray *ray = &ss_isect->ray;
+ Ray *ray = &ss_isect->ray;
#endif
- ray->P = sd->P + disk_N*disk_height + disk_P;
- ray->D = -disk_N;
- ray->t = 2.0f*disk_height;
- ray->dP = sd->dP;
- ray->dD = differential3_zero();
- ray->time = sd->time;
-
- /* intersect with the same object. if multiple intersections are found it
- * will use at most BSSRDF_MAX_HITS hits, a random subset of all hits */
- scene_intersect_local(kg,
- *ray,
- ss_isect,
- sd->object,
- lcg_state,
- BSSRDF_MAX_HITS);
- int num_eval_hits = min(ss_isect->num_hits, BSSRDF_MAX_HITS);
-
- for(int hit = 0; hit < num_eval_hits; hit++) {
- /* Quickly retrieve P and Ng without setting up ShaderData. */
- float3 hit_P;
- if(sd->type & PRIMITIVE_TRIANGLE) {
- hit_P = triangle_refine_local(kg,
- sd,
- &ss_isect->hits[hit],
- ray);
- }
+ ray->P = sd->P + disk_N * disk_height + disk_P;
+ ray->D = -disk_N;
+ ray->t = 2.0f * disk_height;
+ ray->dP = sd->dP;
+ ray->dD = differential3_zero();
+ ray->time = sd->time;
+
+ /* intersect with the same object. if multiple intersections are found it
+ * will use at most BSSRDF_MAX_HITS hits, a random subset of all hits */
+ scene_intersect_local(kg, *ray, ss_isect, sd->object, lcg_state, BSSRDF_MAX_HITS);
+ int num_eval_hits = min(ss_isect->num_hits, BSSRDF_MAX_HITS);
+
+ for (int hit = 0; hit < num_eval_hits; hit++) {
+ /* Quickly retrieve P and Ng without setting up ShaderData. */
+ float3 hit_P;
+ if (sd->type & PRIMITIVE_TRIANGLE) {
+ hit_P = triangle_refine_local(kg, sd, &ss_isect->hits[hit], ray);
+ }
#ifdef __OBJECT_MOTION__
- else if(sd->type & PRIMITIVE_MOTION_TRIANGLE) {
- float3 verts[3];
- motion_triangle_vertices(
- kg,
- sd->object,
- kernel_tex_fetch(__prim_index, ss_isect->hits[hit].prim),
- sd->time,
- verts);
- hit_P = motion_triangle_refine_local(kg,
- sd,
- &ss_isect->hits[hit],
- ray,
- verts);
- }
-#endif /* __OBJECT_MOTION__ */
- else {
- ss_isect->weight[hit] = make_float3(0.0f, 0.0f, 0.0f);
- continue;
- }
-
- float3 hit_Ng = ss_isect->Ng[hit];
- if(ss_isect->hits[hit].object != OBJECT_NONE) {
- object_normal_transform(kg, sd, &hit_Ng);
- }
-
- /* Probability densities for local frame axes. */
- float pdf_N = pick_pdf_N * fabsf(dot(disk_N, hit_Ng));
- float pdf_T = pick_pdf_T * fabsf(dot(disk_T, hit_Ng));
- float pdf_B = pick_pdf_B * fabsf(dot(disk_B, hit_Ng));
-
- /* Multiple importance sample between 3 axes, power heuristic
- * found to be slightly better than balance heuristic. pdf_N
- * in the MIS weight and denominator cancelled out. */
- float w = pdf_N / (sqr(pdf_N) + sqr(pdf_T) + sqr(pdf_B));
- if(ss_isect->num_hits > BSSRDF_MAX_HITS) {
- w *= ss_isect->num_hits/(float)BSSRDF_MAX_HITS;
- }
-
- /* Real distance to sampled point. */
- float r = len(hit_P - sd->P);
-
- /* Evaluate profiles. */
- float3 eval = subsurface_scatter_eval(sd, sc, disk_r, r, all) * w;
-
- ss_isect->weight[hit] = eval;
- }
+ else if (sd->type & PRIMITIVE_MOTION_TRIANGLE) {
+ float3 verts[3];
+ motion_triangle_vertices(kg,
+ sd->object,
+ kernel_tex_fetch(__prim_index, ss_isect->hits[hit].prim),
+ sd->time,
+ verts);
+ hit_P = motion_triangle_refine_local(kg, sd, &ss_isect->hits[hit], ray, verts);
+ }
+#endif /* __OBJECT_MOTION__ */
+ else {
+ ss_isect->weight[hit] = make_float3(0.0f, 0.0f, 0.0f);
+ continue;
+ }
+
+ float3 hit_Ng = ss_isect->Ng[hit];
+ if (ss_isect->hits[hit].object != OBJECT_NONE) {
+ object_normal_transform(kg, sd, &hit_Ng);
+ }
+
+ /* Probability densities for local frame axes. */
+ float pdf_N = pick_pdf_N * fabsf(dot(disk_N, hit_Ng));
+ float pdf_T = pick_pdf_T * fabsf(dot(disk_T, hit_Ng));
+ float pdf_B = pick_pdf_B * fabsf(dot(disk_B, hit_Ng));
+
+ /* Multiple importance sample between 3 axes, power heuristic
+ * found to be slightly better than balance heuristic. pdf_N
+ * in the MIS weight and denominator cancelled out. */
+ float w = pdf_N / (sqr(pdf_N) + sqr(pdf_T) + sqr(pdf_B));
+ if (ss_isect->num_hits > BSSRDF_MAX_HITS) {
+ w *= ss_isect->num_hits / (float)BSSRDF_MAX_HITS;
+ }
+
+ /* Real distance to sampled point. */
+ float r = len(hit_P - sd->P);
+
+ /* Evaluate profiles. */
+ float3 eval = subsurface_scatter_eval(sd, sc, disk_r, r, all) * w;
+
+ ss_isect->weight[hit] = eval;
+ }
#ifdef __SPLIT_KERNEL__
- ss_isect->ray = *ray;
+ ss_isect->ray = *ray;
#endif
- return num_eval_hits;
+ return num_eval_hits;
}
-ccl_device_noinline void subsurface_scatter_multi_setup(
- KernelGlobals *kg,
- LocalIntersection* ss_isect,
- int hit,
- ShaderData *sd,
- ccl_addr_space PathState *state,
- ClosureType type,
- float roughness)
+ccl_device_noinline void subsurface_scatter_multi_setup(KernelGlobals *kg,
+ LocalIntersection *ss_isect,
+ int hit,
+ ShaderData *sd,
+ ccl_addr_space PathState *state,
+ ClosureType type,
+ float roughness)
{
#ifdef __SPLIT_KERNEL__
- Ray ray_object = ss_isect->ray;
- Ray *ray = &ray_object;
+ Ray ray_object = ss_isect->ray;
+ Ray *ray = &ray_object;
#else
- Ray *ray = &ss_isect->ray;
+ Ray *ray = &ss_isect->ray;
#endif
- /* Workaround for AMD GPU OpenCL compiler. Most probably cache bypass issue. */
+ /* Workaround for AMD GPU OpenCL compiler. Most probably cache bypass issue. */
#if defined(__SPLIT_KERNEL__) && defined(__KERNEL_OPENCL_AMD__) && defined(__KERNEL_GPU__)
- kernel_split_params.dummy_sd_flag = sd->flag;
+ kernel_split_params.dummy_sd_flag = sd->flag;
#endif
- /* Setup new shading point. */
- shader_setup_from_subsurface(kg, sd, &ss_isect->hits[hit], ray);
+ /* Setup new shading point. */
+ shader_setup_from_subsurface(kg, sd, &ss_isect->hits[hit], ray);
- /* Optionally blur colors and bump mapping. */
- float3 weight = ss_isect->weight[hit];
- float3 N = sd->N;
- subsurface_color_bump_blur(kg, sd, state, &weight, &N);
+ /* Optionally blur colors and bump mapping. */
+ float3 weight = ss_isect->weight[hit];
+ float3 N = sd->N;
+ subsurface_color_bump_blur(kg, sd, state, &weight, &N);
- /* Setup diffuse BSDF. */
- subsurface_scatter_setup_diffuse_bsdf(kg, sd, type, roughness, weight, N);
+ /* Setup diffuse BSDF. */
+ subsurface_scatter_setup_diffuse_bsdf(kg, sd, type, roughness, weight, N);
}
/* Random walk subsurface scattering.
@@ -340,196 +318,178 @@ ccl_device_noinline void subsurface_scatter_multi_setup(
* "Practical and Controllable Subsurface Scattering for Production Path
* Tracing". Matt Jen-Yuan Chiang, Peter Kutz, Brent Burley. SIGGRAPH 2016. */
-ccl_device void subsurface_random_walk_remap(
- const float A,
- const float d,
- float *sigma_t,
- float *sigma_s)
+ccl_device void subsurface_random_walk_remap(const float A,
+ const float d,
+ float *sigma_t,
+ float *sigma_s)
{
- /* Compute attenuation and scattering coefficients from albedo. */
- const float a = 1.0f - expf(A * (-5.09406f + A * (2.61188f - A * 4.31805f)));
- const float s = 1.9f - A + 3.5f * sqr(A - 0.8f);
+ /* Compute attenuation and scattering coefficients from albedo. */
+ const float a = 1.0f - expf(A * (-5.09406f + A * (2.61188f - A * 4.31805f)));
+ const float s = 1.9f - A + 3.5f * sqr(A - 0.8f);
- *sigma_t = 1.0f / fmaxf(d * s, 1e-16f);
- *sigma_s = *sigma_t * a;
+ *sigma_t = 1.0f / fmaxf(d * s, 1e-16f);
+ *sigma_s = *sigma_t * a;
}
-ccl_device void subsurface_random_walk_coefficients(
- const ShaderClosure *sc,
- float3 *sigma_t,
- float3 *sigma_s,
- float3 *weight)
+ccl_device void subsurface_random_walk_coefficients(const ShaderClosure *sc,
+ float3 *sigma_t,
+ float3 *sigma_s,
+ float3 *weight)
{
- const Bssrdf *bssrdf = (const Bssrdf*)sc;
- const float3 A = bssrdf->albedo;
- const float3 d = bssrdf->radius;
- float sigma_t_x, sigma_t_y, sigma_t_z;
- float sigma_s_x, sigma_s_y, sigma_s_z;
+ const Bssrdf *bssrdf = (const Bssrdf *)sc;
+ const float3 A = bssrdf->albedo;
+ const float3 d = bssrdf->radius;
+ float sigma_t_x, sigma_t_y, sigma_t_z;
+ float sigma_s_x, sigma_s_y, sigma_s_z;
- subsurface_random_walk_remap(A.x, d.x, &sigma_t_x, &sigma_s_x);
- subsurface_random_walk_remap(A.y, d.y, &sigma_t_y, &sigma_s_y);
- subsurface_random_walk_remap(A.z, d.z, &sigma_t_z, &sigma_s_z);
+ subsurface_random_walk_remap(A.x, d.x, &sigma_t_x, &sigma_s_x);
+ subsurface_random_walk_remap(A.y, d.y, &sigma_t_y, &sigma_s_y);
+ subsurface_random_walk_remap(A.z, d.z, &sigma_t_z, &sigma_s_z);
- *sigma_t = make_float3(sigma_t_x, sigma_t_y, sigma_t_z);
- *sigma_s = make_float3(sigma_s_x, sigma_s_y, sigma_s_z);
+ *sigma_t = make_float3(sigma_t_x, sigma_t_y, sigma_t_z);
+ *sigma_s = make_float3(sigma_s_x, sigma_s_y, sigma_s_z);
- /* Closure mixing and Fresnel weights separate from albedo. */
- *weight = safe_divide_color(bssrdf->weight, A);
+ /* Closure mixing and Fresnel weights separate from albedo. */
+ *weight = safe_divide_color(bssrdf->weight, A);
}
-ccl_device_noinline bool subsurface_random_walk(
- KernelGlobals *kg,
- LocalIntersection *ss_isect,
- ShaderData *sd,
- ccl_addr_space PathState *state,
- const ShaderClosure *sc,
- const float bssrdf_u,
- const float bssrdf_v)
+ccl_device_noinline bool subsurface_random_walk(KernelGlobals *kg,
+ LocalIntersection *ss_isect,
+ ShaderData *sd,
+ ccl_addr_space PathState *state,
+ const ShaderClosure *sc,
+ const float bssrdf_u,
+ const float bssrdf_v)
{
- /* Sample diffuse surface scatter into the object. */
- float3 D;
- float pdf;
- sample_cos_hemisphere(-sd->N, bssrdf_u, bssrdf_v, &D, &pdf);
- if(dot(-sd->Ng, D) <= 0.0f) {
- return 0;
- }
-
- /* Convert subsurface to volume coefficients. */
- float3 sigma_t, sigma_s;
- float3 throughput = make_float3(1.0f, 1.0f, 1.0f);
- subsurface_random_walk_coefficients(sc, &sigma_t, &sigma_s, &throughput);
-
- /* Setup ray. */
+ /* Sample diffuse surface scatter into the object. */
+ float3 D;
+ float pdf;
+ sample_cos_hemisphere(-sd->N, bssrdf_u, bssrdf_v, &D, &pdf);
+ if (dot(-sd->Ng, D) <= 0.0f) {
+ return 0;
+ }
+
+ /* Convert subsurface to volume coefficients. */
+ float3 sigma_t, sigma_s;
+ float3 throughput = make_float3(1.0f, 1.0f, 1.0f);
+ subsurface_random_walk_coefficients(sc, &sigma_t, &sigma_s, &throughput);
+
+ /* Setup ray. */
#ifdef __SPLIT_KERNEL__
- Ray ray_object = ss_isect->ray;
- Ray *ray = &ray_object;
+ Ray ray_object = ss_isect->ray;
+ Ray *ray = &ray_object;
#else
- Ray *ray = &ss_isect->ray;
+ Ray *ray = &ss_isect->ray;
#endif
- ray->P = ray_offset(sd->P, -sd->Ng);
- ray->D = D;
- ray->t = FLT_MAX;
- ray->time = sd->time;
-
- /* Modify state for RNGs, decorrelated from other paths. */
- uint prev_rng_offset = state->rng_offset;
- uint prev_rng_hash = state->rng_hash;
- state->rng_hash = cmj_hash(state->rng_hash + state->rng_offset, 0xdeadbeef);
-
- /* Random walk until we hit the surface again. */
- bool hit = false;
-
- for(int bounce = 0; bounce < BSSRDF_MAX_BOUNCES; bounce++) {
- /* Advance random number offset. */
- state->rng_offset += PRNG_BOUNCE_NUM;
-
- if(bounce > 0) {
- /* Sample scattering direction. */
- const float anisotropy = 0.0f;
- float scatter_u, scatter_v;
- path_state_rng_2D(kg, state, PRNG_BSDF_U, &scatter_u, &scatter_v);
- ray->D = henyey_greenstrein_sample(ray->D, anisotropy, scatter_u, scatter_v, NULL);
- }
-
- /* Sample color channel, use MIS with balance heuristic. */
- float rphase = path_state_rng_1D(kg, state, PRNG_PHASE_CHANNEL);
- float3 albedo = safe_divide_color(sigma_s, sigma_t);
- float3 channel_pdf;
- int channel = kernel_volume_sample_channel(albedo, throughput, rphase, &channel_pdf);
-
- /* Distance sampling. */
- float rdist = path_state_rng_1D(kg, state, PRNG_SCATTER_DISTANCE);
- float sample_sigma_t = kernel_volume_channel_get(sigma_t, channel);
- float t = -logf(1.0f - rdist)/sample_sigma_t;
-
- ray->t = t;
- scene_intersect_local(kg, *ray, ss_isect, sd->object, NULL, 1);
- hit = (ss_isect->num_hits > 0);
-
- if(hit) {
- /* Compute world space distance to surface hit. */
- float3 D = ray->D;
- object_inverse_dir_transform(kg, sd, &D);
- D = normalize(D) * ss_isect->hits[0].t;
- object_dir_transform(kg, sd, &D);
- t = len(D);
- }
-
- /* Advance to new scatter location. */
- ray->P += t * ray->D;
-
- /* Update throughput. */
- float3 transmittance = volume_color_transmittance(sigma_t, t);
- float pdf = dot(channel_pdf, (hit)? transmittance: sigma_t * transmittance);
- throughput *= ((hit)? transmittance: sigma_s * transmittance) / pdf;
-
- if(hit) {
- /* If we hit the surface, we are done. */
- break;
- }
-
- /* Russian roulette. */
- float terminate = path_state_rng_1D(kg, state, PRNG_TERMINATE);
- float probability = min(max3(fabs(throughput)), 1.0f);
- if(terminate >= probability) {
- break;
- }
- throughput /= probability;
- }
-
- kernel_assert(isfinite_safe(throughput.x) &&
- isfinite_safe(throughput.y) &&
- isfinite_safe(throughput.z));
-
- state->rng_offset = prev_rng_offset;
- state->rng_hash = prev_rng_hash;
-
- /* Return number of hits in ss_isect. */
- if(!hit) {
- return 0;
- }
-
- /* TODO: gain back performance lost from merging with disk BSSRDF. We
- * only need to return on hit so this indirect ray push/pop overhead
- * is not actually needed, but it does keep the code simpler. */
- ss_isect->weight[0] = throughput;
+ ray->P = ray_offset(sd->P, -sd->Ng);
+ ray->D = D;
+ ray->t = FLT_MAX;
+ ray->time = sd->time;
+
+ /* Modify state for RNGs, decorrelated from other paths. */
+ uint prev_rng_offset = state->rng_offset;
+ uint prev_rng_hash = state->rng_hash;
+ state->rng_hash = cmj_hash(state->rng_hash + state->rng_offset, 0xdeadbeef);
+
+ /* Random walk until we hit the surface again. */
+ bool hit = false;
+
+ for (int bounce = 0; bounce < BSSRDF_MAX_BOUNCES; bounce++) {
+ /* Advance random number offset. */
+ state->rng_offset += PRNG_BOUNCE_NUM;
+
+ if (bounce > 0) {
+ /* Sample scattering direction. */
+ const float anisotropy = 0.0f;
+ float scatter_u, scatter_v;
+ path_state_rng_2D(kg, state, PRNG_BSDF_U, &scatter_u, &scatter_v);
+ ray->D = henyey_greenstrein_sample(ray->D, anisotropy, scatter_u, scatter_v, NULL);
+ }
+
+ /* Sample color channel, use MIS with balance heuristic. */
+ float rphase = path_state_rng_1D(kg, state, PRNG_PHASE_CHANNEL);
+ float3 albedo = safe_divide_color(sigma_s, sigma_t);
+ float3 channel_pdf;
+ int channel = kernel_volume_sample_channel(albedo, throughput, rphase, &channel_pdf);
+
+ /* Distance sampling. */
+ float rdist = path_state_rng_1D(kg, state, PRNG_SCATTER_DISTANCE);
+ float sample_sigma_t = kernel_volume_channel_get(sigma_t, channel);
+ float t = -logf(1.0f - rdist) / sample_sigma_t;
+
+ ray->t = t;
+ scene_intersect_local(kg, *ray, ss_isect, sd->object, NULL, 1);
+ hit = (ss_isect->num_hits > 0);
+
+ if (hit) {
+ /* Compute world space distance to surface hit. */
+ float3 D = ray->D;
+ object_inverse_dir_transform(kg, sd, &D);
+ D = normalize(D) * ss_isect->hits[0].t;
+ object_dir_transform(kg, sd, &D);
+ t = len(D);
+ }
+
+ /* Advance to new scatter location. */
+ ray->P += t * ray->D;
+
+ /* Update throughput. */
+ float3 transmittance = volume_color_transmittance(sigma_t, t);
+ float pdf = dot(channel_pdf, (hit) ? transmittance : sigma_t * transmittance);
+ throughput *= ((hit) ? transmittance : sigma_s * transmittance) / pdf;
+
+ if (hit) {
+ /* If we hit the surface, we are done. */
+ break;
+ }
+
+ /* Russian roulette. */
+ float terminate = path_state_rng_1D(kg, state, PRNG_TERMINATE);
+ float probability = min(max3(fabs(throughput)), 1.0f);
+ if (terminate >= probability) {
+ break;
+ }
+ throughput /= probability;
+ }
+
+ kernel_assert(isfinite_safe(throughput.x) && isfinite_safe(throughput.y) &&
+ isfinite_safe(throughput.z));
+
+ state->rng_offset = prev_rng_offset;
+ state->rng_hash = prev_rng_hash;
+
+ /* Return number of hits in ss_isect. */
+ if (!hit) {
+ return 0;
+ }
+
+ /* TODO: gain back performance lost from merging with disk BSSRDF. We
+ * only need to return on hit so this indirect ray push/pop overhead
+ * is not actually needed, but it does keep the code simpler. */
+ ss_isect->weight[0] = throughput;
#ifdef __SPLIT_KERNEL__
- ss_isect->ray = *ray;
+ ss_isect->ray = *ray;
#endif
- return 1;
+ return 1;
}
-ccl_device_inline int subsurface_scatter_multi_intersect(
- KernelGlobals *kg,
- LocalIntersection *ss_isect,
- ShaderData *sd,
- ccl_addr_space PathState *state,
- const ShaderClosure *sc,
- uint *lcg_state,
- float bssrdf_u,
- float bssrdf_v,
- bool all)
+ccl_device_inline int subsurface_scatter_multi_intersect(KernelGlobals *kg,
+ LocalIntersection *ss_isect,
+ ShaderData *sd,
+ ccl_addr_space PathState *state,
+ const ShaderClosure *sc,
+ uint *lcg_state,
+ float bssrdf_u,
+ float bssrdf_v,
+ bool all)
{
- if(CLOSURE_IS_DISK_BSSRDF(sc->type)) {
- return subsurface_scatter_disk(kg,
- ss_isect,
- sd,
- sc,
- lcg_state,
- bssrdf_u,
- bssrdf_v,
- all);
- }
- else {
- return subsurface_random_walk(kg,
- ss_isect,
- sd,
- state,
- sc,
- bssrdf_u,
- bssrdf_v);
- }
+ if (CLOSURE_IS_DISK_BSSRDF(sc->type)) {
+ return subsurface_scatter_disk(kg, ss_isect, sd, sc, lcg_state, bssrdf_u, bssrdf_v, all);
+ }
+ else {
+ return subsurface_random_walk(kg, ss_isect, sd, state, sc, bssrdf_u, bssrdf_v);
+ }
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/kernel_types.h b/intern/cycles/kernel/kernel_types.h
index 4b1c8e82dfa..3f62b726b6a 100644
--- a/intern/cycles/kernel/kernel_types.h
+++ b/intern/cycles/kernel/kernel_types.h
@@ -42,26 +42,26 @@ CCL_NAMESPACE_BEGIN
/* Constants */
#define OBJECT_MOTION_PASS_SIZE 2
-#define FILTER_TABLE_SIZE 1024
-#define RAMP_TABLE_SIZE 256
-#define SHUTTER_TABLE_SIZE 256
+#define FILTER_TABLE_SIZE 1024
+#define RAMP_TABLE_SIZE 256
+#define SHUTTER_TABLE_SIZE 256
-#define BSSRDF_MIN_RADIUS 1e-8f
-#define BSSRDF_MAX_HITS 4
-#define BSSRDF_MAX_BOUNCES 256
-#define LOCAL_MAX_HITS 4
+#define BSSRDF_MIN_RADIUS 1e-8f
+#define BSSRDF_MAX_HITS 4
+#define BSSRDF_MAX_BOUNCES 256
+#define LOCAL_MAX_HITS 4
-#define VOLUME_BOUNDS_MAX 1024
+#define VOLUME_BOUNDS_MAX 1024
-#define BECKMANN_TABLE_SIZE 256
+#define BECKMANN_TABLE_SIZE 256
-#define SHADER_NONE (~0)
-#define OBJECT_NONE (~0)
-#define PRIM_NONE (~0)
-#define LAMP_NONE (~0)
-#define ID_NONE (0.0f)
+#define SHADER_NONE (~0)
+#define OBJECT_NONE (~0)
+#define PRIM_NONE (~0)
+#define LAMP_NONE (~0)
+#define ID_NONE (0.0f)
-#define VOLUME_STACK_SIZE 32
+#define VOLUME_STACK_SIZE 32
/* Split kernel constants */
#define WORK_POOL_SIZE_GPU 64
@@ -72,7 +72,6 @@ CCL_NAMESPACE_BEGIN
# define WORK_POOL_SIZE WORK_POOL_SIZE_CPU
#endif
-
#define SHADER_SORT_BLOCK_SIZE 2048
#ifdef __KERNEL_OPENCL__
@@ -137,16 +136,16 @@ CCL_NAMESPACE_BEGIN
# endif
# define __VOLUME_DECOUPLED__
# define __VOLUME_RECORD_ALL__
-#endif /* __KERNEL_CPU__ */
+#endif /* __KERNEL_CPU__ */
#ifdef __KERNEL_CUDA__
# ifdef __SPLIT_KERNEL__
# undef __BRANCHED_PATH__
# endif
-#endif /* __KERNEL_CUDA__ */
+#endif /* __KERNEL_CUDA__ */
#ifdef __KERNEL_OPENCL__
-#endif /* __KERNEL_OPENCL__ */
+#endif /* __KERNEL_OPENCL__ */
/* Scene-based selective features compilation. */
#ifdef __NO_CAMERA_MOTION__
@@ -202,273 +201,269 @@ CCL_NAMESPACE_BEGIN
/* Shader Evaluation */
typedef enum ShaderEvalType {
- SHADER_EVAL_DISPLACE,
- SHADER_EVAL_BACKGROUND,
- /* bake types */
- SHADER_EVAL_BAKE, /* no real shade, it's used in the code to
- * differentiate the type of shader eval from the above
- */
- /* data passes */
- SHADER_EVAL_NORMAL,
- SHADER_EVAL_UV,
- SHADER_EVAL_ROUGHNESS,
- SHADER_EVAL_DIFFUSE_COLOR,
- SHADER_EVAL_GLOSSY_COLOR,
- SHADER_EVAL_TRANSMISSION_COLOR,
- SHADER_EVAL_SUBSURFACE_COLOR,
- SHADER_EVAL_EMISSION,
-
- /* light passes */
- SHADER_EVAL_AO,
- SHADER_EVAL_COMBINED,
- SHADER_EVAL_SHADOW,
- SHADER_EVAL_DIFFUSE,
- SHADER_EVAL_GLOSSY,
- SHADER_EVAL_TRANSMISSION,
- SHADER_EVAL_SUBSURFACE,
-
- /* extra */
- SHADER_EVAL_ENVIRONMENT,
+ SHADER_EVAL_DISPLACE,
+ SHADER_EVAL_BACKGROUND,
+ /* bake types */
+ SHADER_EVAL_BAKE, /* no real shade, it's used in the code to
+ * differentiate the type of shader eval from the above
+ */
+ /* data passes */
+ SHADER_EVAL_NORMAL,
+ SHADER_EVAL_UV,
+ SHADER_EVAL_ROUGHNESS,
+ SHADER_EVAL_DIFFUSE_COLOR,
+ SHADER_EVAL_GLOSSY_COLOR,
+ SHADER_EVAL_TRANSMISSION_COLOR,
+ SHADER_EVAL_SUBSURFACE_COLOR,
+ SHADER_EVAL_EMISSION,
+
+ /* light passes */
+ SHADER_EVAL_AO,
+ SHADER_EVAL_COMBINED,
+ SHADER_EVAL_SHADOW,
+ SHADER_EVAL_DIFFUSE,
+ SHADER_EVAL_GLOSSY,
+ SHADER_EVAL_TRANSMISSION,
+ SHADER_EVAL_SUBSURFACE,
+
+ /* extra */
+ SHADER_EVAL_ENVIRONMENT,
} ShaderEvalType;
/* Path Tracing
* note we need to keep the u/v pairs at even values */
enum PathTraceDimension {
- PRNG_FILTER_U = 0,
- PRNG_FILTER_V = 1,
- PRNG_LENS_U = 2,
- PRNG_LENS_V = 3,
- PRNG_TIME = 4,
- PRNG_UNUSED_0 = 5,
- PRNG_UNUSED_1 = 6, /* for some reason (6, 7) is a bad sobol pattern */
- PRNG_UNUSED_2 = 7, /* with a low number of samples (< 64) */
- PRNG_BASE_NUM = 10,
-
- PRNG_BSDF_U = 0,
- PRNG_BSDF_V = 1,
- PRNG_LIGHT_U = 2,
- PRNG_LIGHT_V = 3,
- PRNG_LIGHT_TERMINATE = 4,
- PRNG_TERMINATE = 5,
- PRNG_PHASE_CHANNEL = 6,
- PRNG_SCATTER_DISTANCE = 7,
- PRNG_BOUNCE_NUM = 8,
-
- PRNG_BEVEL_U = 6, /* reuse volume dimension, correlation won't harm */
- PRNG_BEVEL_V = 7,
+ PRNG_FILTER_U = 0,
+ PRNG_FILTER_V = 1,
+ PRNG_LENS_U = 2,
+ PRNG_LENS_V = 3,
+ PRNG_TIME = 4,
+ PRNG_UNUSED_0 = 5,
+ PRNG_UNUSED_1 = 6, /* for some reason (6, 7) is a bad sobol pattern */
+ PRNG_UNUSED_2 = 7, /* with a low number of samples (< 64) */
+ PRNG_BASE_NUM = 10,
+
+ PRNG_BSDF_U = 0,
+ PRNG_BSDF_V = 1,
+ PRNG_LIGHT_U = 2,
+ PRNG_LIGHT_V = 3,
+ PRNG_LIGHT_TERMINATE = 4,
+ PRNG_TERMINATE = 5,
+ PRNG_PHASE_CHANNEL = 6,
+ PRNG_SCATTER_DISTANCE = 7,
+ PRNG_BOUNCE_NUM = 8,
+
+ PRNG_BEVEL_U = 6, /* reuse volume dimension, correlation won't harm */
+ PRNG_BEVEL_V = 7,
};
enum SamplingPattern {
- SAMPLING_PATTERN_SOBOL = 0,
- SAMPLING_PATTERN_CMJ = 1,
+ SAMPLING_PATTERN_SOBOL = 0,
+ SAMPLING_PATTERN_CMJ = 1,
- SAMPLING_NUM_PATTERNS,
+ SAMPLING_NUM_PATTERNS,
};
/* these flags values correspond to raytypes in osl.cpp, so keep them in sync! */
enum PathRayFlag {
- PATH_RAY_CAMERA = (1 << 0),
- PATH_RAY_REFLECT = (1 << 1),
- PATH_RAY_TRANSMIT = (1 << 2),
- PATH_RAY_DIFFUSE = (1 << 3),
- PATH_RAY_GLOSSY = (1 << 4),
- PATH_RAY_SINGULAR = (1 << 5),
- PATH_RAY_TRANSPARENT = (1 << 6),
-
- PATH_RAY_SHADOW_OPAQUE_NON_CATCHER = (1 << 7),
- PATH_RAY_SHADOW_OPAQUE_CATCHER = (1 << 8),
- PATH_RAY_SHADOW_OPAQUE = (PATH_RAY_SHADOW_OPAQUE_NON_CATCHER|PATH_RAY_SHADOW_OPAQUE_CATCHER),
- PATH_RAY_SHADOW_TRANSPARENT_NON_CATCHER = (1 << 9),
- PATH_RAY_SHADOW_TRANSPARENT_CATCHER = (1 << 10),
- PATH_RAY_SHADOW_TRANSPARENT = (PATH_RAY_SHADOW_TRANSPARENT_NON_CATCHER|PATH_RAY_SHADOW_TRANSPARENT_CATCHER),
- PATH_RAY_SHADOW_NON_CATCHER = (PATH_RAY_SHADOW_OPAQUE_NON_CATCHER|PATH_RAY_SHADOW_TRANSPARENT_NON_CATCHER),
- PATH_RAY_SHADOW = (PATH_RAY_SHADOW_OPAQUE|PATH_RAY_SHADOW_TRANSPARENT),
-
- PATH_RAY_CURVE = (1 << 11), /* visibility flag to define curve segments */
- PATH_RAY_VOLUME_SCATTER = (1 << 12), /* volume scattering */
-
- /* Special flag to tag unaligned BVH nodes. */
- PATH_RAY_NODE_UNALIGNED = (1 << 13),
-
- PATH_RAY_ALL_VISIBILITY = ((1 << 14)-1),
-
- /* Don't apply multiple importance sampling weights to emission from
- * lamp or surface hits, because they were not direct light sampled. */
- PATH_RAY_MIS_SKIP = (1 << 14),
- /* Diffuse bounce earlier in the path, skip SSS to improve performance
- * and avoid branching twice with disk sampling SSS. */
- PATH_RAY_DIFFUSE_ANCESTOR = (1 << 15),
- /* Single pass has been written. */
- PATH_RAY_SINGLE_PASS_DONE = (1 << 16),
- /* Ray is behind a shadow catcher .*/
- PATH_RAY_SHADOW_CATCHER = (1 << 17),
- /* Store shadow data for shadow catcher or denoising. */
- PATH_RAY_STORE_SHADOW_INFO = (1 << 18),
- /* Zero background alpha, for camera or transparent glass rays. */
- PATH_RAY_TRANSPARENT_BACKGROUND = (1 << 19),
- /* Terminate ray immediately at next bounce. */
- PATH_RAY_TERMINATE_IMMEDIATE = (1 << 20),
- /* Ray is to be terminated, but continue with transparent bounces and
- * emission as long as we encounter them. This is required to make the
- * MIS between direct and indirect light rays match, as shadow rays go
- * through transparent surfaces to reach emisison too. */
- PATH_RAY_TERMINATE_AFTER_TRANSPARENT = (1 << 21),
- /* Ray is to be terminated. */
- PATH_RAY_TERMINATE = (PATH_RAY_TERMINATE_IMMEDIATE|PATH_RAY_TERMINATE_AFTER_TRANSPARENT),
- /* Path and shader is being evaluated for direct lighting emission. */
- PATH_RAY_EMISSION = (1 << 22)
+ PATH_RAY_CAMERA = (1 << 0),
+ PATH_RAY_REFLECT = (1 << 1),
+ PATH_RAY_TRANSMIT = (1 << 2),
+ PATH_RAY_DIFFUSE = (1 << 3),
+ PATH_RAY_GLOSSY = (1 << 4),
+ PATH_RAY_SINGULAR = (1 << 5),
+ PATH_RAY_TRANSPARENT = (1 << 6),
+
+ PATH_RAY_SHADOW_OPAQUE_NON_CATCHER = (1 << 7),
+ PATH_RAY_SHADOW_OPAQUE_CATCHER = (1 << 8),
+ PATH_RAY_SHADOW_OPAQUE = (PATH_RAY_SHADOW_OPAQUE_NON_CATCHER | PATH_RAY_SHADOW_OPAQUE_CATCHER),
+ PATH_RAY_SHADOW_TRANSPARENT_NON_CATCHER = (1 << 9),
+ PATH_RAY_SHADOW_TRANSPARENT_CATCHER = (1 << 10),
+ PATH_RAY_SHADOW_TRANSPARENT = (PATH_RAY_SHADOW_TRANSPARENT_NON_CATCHER |
+ PATH_RAY_SHADOW_TRANSPARENT_CATCHER),
+ PATH_RAY_SHADOW_NON_CATCHER = (PATH_RAY_SHADOW_OPAQUE_NON_CATCHER |
+ PATH_RAY_SHADOW_TRANSPARENT_NON_CATCHER),
+ PATH_RAY_SHADOW = (PATH_RAY_SHADOW_OPAQUE | PATH_RAY_SHADOW_TRANSPARENT),
+
+ PATH_RAY_CURVE = (1 << 11), /* visibility flag to define curve segments */
+ PATH_RAY_VOLUME_SCATTER = (1 << 12), /* volume scattering */
+
+ /* Special flag to tag unaligned BVH nodes. */
+ PATH_RAY_NODE_UNALIGNED = (1 << 13),
+
+ PATH_RAY_ALL_VISIBILITY = ((1 << 14) - 1),
+
+ /* Don't apply multiple importance sampling weights to emission from
+ * lamp or surface hits, because they were not direct light sampled. */
+ PATH_RAY_MIS_SKIP = (1 << 14),
+ /* Diffuse bounce earlier in the path, skip SSS to improve performance
+ * and avoid branching twice with disk sampling SSS. */
+ PATH_RAY_DIFFUSE_ANCESTOR = (1 << 15),
+ /* Single pass has been written. */
+ PATH_RAY_SINGLE_PASS_DONE = (1 << 16),
+ /* Ray is behind a shadow catcher .*/
+ PATH_RAY_SHADOW_CATCHER = (1 << 17),
+ /* Store shadow data for shadow catcher or denoising. */
+ PATH_RAY_STORE_SHADOW_INFO = (1 << 18),
+ /* Zero background alpha, for camera or transparent glass rays. */
+ PATH_RAY_TRANSPARENT_BACKGROUND = (1 << 19),
+ /* Terminate ray immediately at next bounce. */
+ PATH_RAY_TERMINATE_IMMEDIATE = (1 << 20),
+ /* Ray is to be terminated, but continue with transparent bounces and
+ * emission as long as we encounter them. This is required to make the
+ * MIS between direct and indirect light rays match, as shadow rays go
+ * through transparent surfaces to reach emisison too. */
+ PATH_RAY_TERMINATE_AFTER_TRANSPARENT = (1 << 21),
+ /* Ray is to be terminated. */
+ PATH_RAY_TERMINATE = (PATH_RAY_TERMINATE_IMMEDIATE | PATH_RAY_TERMINATE_AFTER_TRANSPARENT),
+ /* Path and shader is being evaluated for direct lighting emission. */
+ PATH_RAY_EMISSION = (1 << 22)
};
/* Closure Label */
typedef enum ClosureLabel {
- LABEL_NONE = 0,
- LABEL_TRANSMIT = 1,
- LABEL_REFLECT = 2,
- LABEL_DIFFUSE = 4,
- LABEL_GLOSSY = 8,
- LABEL_SINGULAR = 16,
- LABEL_TRANSPARENT = 32,
- LABEL_VOLUME_SCATTER = 64,
- LABEL_TRANSMIT_TRANSPARENT = 128,
+ LABEL_NONE = 0,
+ LABEL_TRANSMIT = 1,
+ LABEL_REFLECT = 2,
+ LABEL_DIFFUSE = 4,
+ LABEL_GLOSSY = 8,
+ LABEL_SINGULAR = 16,
+ LABEL_TRANSPARENT = 32,
+ LABEL_VOLUME_SCATTER = 64,
+ LABEL_TRANSMIT_TRANSPARENT = 128,
} ClosureLabel;
/* Render Passes */
-#define PASS_NAME_JOIN(a, b) a ## _ ## b
+#define PASS_NAME_JOIN(a, b) a##_##b
#define PASSMASK(pass) (1 << ((PASS_NAME_JOIN(PASS, pass)) % 32))
-#define PASSMASK_COMPONENT(comp) (PASSMASK(PASS_NAME_JOIN(comp, DIRECT)) | \
- PASSMASK(PASS_NAME_JOIN(comp, INDIRECT)) | \
- PASSMASK(PASS_NAME_JOIN(comp, COLOR)))
+#define PASSMASK_COMPONENT(comp) \
+ (PASSMASK(PASS_NAME_JOIN(comp, DIRECT)) | PASSMASK(PASS_NAME_JOIN(comp, INDIRECT)) | \
+ PASSMASK(PASS_NAME_JOIN(comp, COLOR)))
typedef enum PassType {
- PASS_NONE = 0,
-
- /* Main passes */
- PASS_COMBINED = 1,
- PASS_DEPTH,
- PASS_NORMAL,
- PASS_UV,
- PASS_OBJECT_ID,
- PASS_MATERIAL_ID,
- PASS_MOTION,
- PASS_MOTION_WEIGHT,
+ PASS_NONE = 0,
+
+ /* Main passes */
+ PASS_COMBINED = 1,
+ PASS_DEPTH,
+ PASS_NORMAL,
+ PASS_UV,
+ PASS_OBJECT_ID,
+ PASS_MATERIAL_ID,
+ PASS_MOTION,
+ PASS_MOTION_WEIGHT,
#ifdef __KERNEL_DEBUG__
- PASS_BVH_TRAVERSED_NODES,
- PASS_BVH_TRAVERSED_INSTANCES,
- PASS_BVH_INTERSECTIONS,
- PASS_RAY_BOUNCES,
+ PASS_BVH_TRAVERSED_NODES,
+ PASS_BVH_TRAVERSED_INSTANCES,
+ PASS_BVH_INTERSECTIONS,
+ PASS_RAY_BOUNCES,
#endif
- PASS_RENDER_TIME,
- PASS_CRYPTOMATTE,
- PASS_CATEGORY_MAIN_END = 31,
-
- PASS_MIST = 32,
- PASS_EMISSION,
- PASS_BACKGROUND,
- PASS_AO,
- PASS_SHADOW,
- PASS_LIGHT, /* no real pass, used to force use_light_pass */
- PASS_DIFFUSE_DIRECT,
- PASS_DIFFUSE_INDIRECT,
- PASS_DIFFUSE_COLOR,
- PASS_GLOSSY_DIRECT,
- PASS_GLOSSY_INDIRECT,
- PASS_GLOSSY_COLOR,
- PASS_TRANSMISSION_DIRECT,
- PASS_TRANSMISSION_INDIRECT,
- PASS_TRANSMISSION_COLOR,
- PASS_SUBSURFACE_DIRECT,
- PASS_SUBSURFACE_INDIRECT,
- PASS_SUBSURFACE_COLOR,
- PASS_VOLUME_DIRECT,
- PASS_VOLUME_INDIRECT,
- /* No Scatter color since it's tricky to define what it would even mean. */
- PASS_CATEGORY_LIGHT_END = 63,
+ PASS_RENDER_TIME,
+ PASS_CRYPTOMATTE,
+ PASS_CATEGORY_MAIN_END = 31,
+
+ PASS_MIST = 32,
+ PASS_EMISSION,
+ PASS_BACKGROUND,
+ PASS_AO,
+ PASS_SHADOW,
+ PASS_LIGHT, /* no real pass, used to force use_light_pass */
+ PASS_DIFFUSE_DIRECT,
+ PASS_DIFFUSE_INDIRECT,
+ PASS_DIFFUSE_COLOR,
+ PASS_GLOSSY_DIRECT,
+ PASS_GLOSSY_INDIRECT,
+ PASS_GLOSSY_COLOR,
+ PASS_TRANSMISSION_DIRECT,
+ PASS_TRANSMISSION_INDIRECT,
+ PASS_TRANSMISSION_COLOR,
+ PASS_SUBSURFACE_DIRECT,
+ PASS_SUBSURFACE_INDIRECT,
+ PASS_SUBSURFACE_COLOR,
+ PASS_VOLUME_DIRECT,
+ PASS_VOLUME_INDIRECT,
+ /* No Scatter color since it's tricky to define what it would even mean. */
+ PASS_CATEGORY_LIGHT_END = 63,
} PassType;
#define PASS_ANY (~0)
typedef enum CryptomatteType {
- CRYPT_NONE = 0,
- CRYPT_OBJECT = (1 << 0),
- CRYPT_MATERIAL = (1 << 1),
- CRYPT_ASSET = (1 << 2),
- CRYPT_ACCURATE = (1 << 3),
+ CRYPT_NONE = 0,
+ CRYPT_OBJECT = (1 << 0),
+ CRYPT_MATERIAL = (1 << 1),
+ CRYPT_ASSET = (1 << 2),
+ CRYPT_ACCURATE = (1 << 3),
} CryptomatteType;
typedef enum DenoisingPassOffsets {
- DENOISING_PASS_NORMAL = 0,
- DENOISING_PASS_NORMAL_VAR = 3,
- DENOISING_PASS_ALBEDO = 6,
- DENOISING_PASS_ALBEDO_VAR = 9,
- DENOISING_PASS_DEPTH = 12,
- DENOISING_PASS_DEPTH_VAR = 13,
- DENOISING_PASS_SHADOW_A = 14,
- DENOISING_PASS_SHADOW_B = 17,
- DENOISING_PASS_COLOR = 20,
- DENOISING_PASS_COLOR_VAR = 23,
- DENOISING_PASS_CLEAN = 26,
-
- DENOISING_PASS_PREFILTERED_DEPTH = 0,
- DENOISING_PASS_PREFILTERED_NORMAL = 1,
- DENOISING_PASS_PREFILTERED_SHADOWING = 4,
- DENOISING_PASS_PREFILTERED_ALBEDO = 5,
- DENOISING_PASS_PREFILTERED_COLOR = 8,
- DENOISING_PASS_PREFILTERED_VARIANCE = 11,
- DENOISING_PASS_PREFILTERED_INTENSITY = 14,
-
- DENOISING_PASS_SIZE_BASE = 26,
- DENOISING_PASS_SIZE_CLEAN = 3,
- DENOISING_PASS_SIZE_PREFILTERED = 15,
+ DENOISING_PASS_NORMAL = 0,
+ DENOISING_PASS_NORMAL_VAR = 3,
+ DENOISING_PASS_ALBEDO = 6,
+ DENOISING_PASS_ALBEDO_VAR = 9,
+ DENOISING_PASS_DEPTH = 12,
+ DENOISING_PASS_DEPTH_VAR = 13,
+ DENOISING_PASS_SHADOW_A = 14,
+ DENOISING_PASS_SHADOW_B = 17,
+ DENOISING_PASS_COLOR = 20,
+ DENOISING_PASS_COLOR_VAR = 23,
+ DENOISING_PASS_CLEAN = 26,
+
+ DENOISING_PASS_PREFILTERED_DEPTH = 0,
+ DENOISING_PASS_PREFILTERED_NORMAL = 1,
+ DENOISING_PASS_PREFILTERED_SHADOWING = 4,
+ DENOISING_PASS_PREFILTERED_ALBEDO = 5,
+ DENOISING_PASS_PREFILTERED_COLOR = 8,
+ DENOISING_PASS_PREFILTERED_VARIANCE = 11,
+ DENOISING_PASS_PREFILTERED_INTENSITY = 14,
+
+ DENOISING_PASS_SIZE_BASE = 26,
+ DENOISING_PASS_SIZE_CLEAN = 3,
+ DENOISING_PASS_SIZE_PREFILTERED = 15,
} DenoisingPassOffsets;
typedef enum eBakePassFilter {
- BAKE_FILTER_NONE = 0,
- BAKE_FILTER_DIRECT = (1 << 0),
- BAKE_FILTER_INDIRECT = (1 << 1),
- BAKE_FILTER_COLOR = (1 << 2),
- BAKE_FILTER_DIFFUSE = (1 << 3),
- BAKE_FILTER_GLOSSY = (1 << 4),
- BAKE_FILTER_TRANSMISSION = (1 << 5),
- BAKE_FILTER_SUBSURFACE = (1 << 6),
- BAKE_FILTER_EMISSION = (1 << 7),
- BAKE_FILTER_AO = (1 << 8),
+ BAKE_FILTER_NONE = 0,
+ BAKE_FILTER_DIRECT = (1 << 0),
+ BAKE_FILTER_INDIRECT = (1 << 1),
+ BAKE_FILTER_COLOR = (1 << 2),
+ BAKE_FILTER_DIFFUSE = (1 << 3),
+ BAKE_FILTER_GLOSSY = (1 << 4),
+ BAKE_FILTER_TRANSMISSION = (1 << 5),
+ BAKE_FILTER_SUBSURFACE = (1 << 6),
+ BAKE_FILTER_EMISSION = (1 << 7),
+ BAKE_FILTER_AO = (1 << 8),
} eBakePassFilter;
typedef enum BakePassFilterCombos {
- BAKE_FILTER_COMBINED = (
- BAKE_FILTER_DIRECT |
- BAKE_FILTER_INDIRECT |
- BAKE_FILTER_DIFFUSE |
- BAKE_FILTER_GLOSSY |
- BAKE_FILTER_TRANSMISSION |
- BAKE_FILTER_SUBSURFACE |
- BAKE_FILTER_EMISSION |
- BAKE_FILTER_AO),
- BAKE_FILTER_DIFFUSE_DIRECT = (BAKE_FILTER_DIRECT | BAKE_FILTER_DIFFUSE),
- BAKE_FILTER_GLOSSY_DIRECT = (BAKE_FILTER_DIRECT | BAKE_FILTER_GLOSSY),
- BAKE_FILTER_TRANSMISSION_DIRECT = (BAKE_FILTER_DIRECT | BAKE_FILTER_TRANSMISSION),
- BAKE_FILTER_SUBSURFACE_DIRECT = (BAKE_FILTER_DIRECT | BAKE_FILTER_SUBSURFACE),
- BAKE_FILTER_DIFFUSE_INDIRECT = (BAKE_FILTER_INDIRECT | BAKE_FILTER_DIFFUSE),
- BAKE_FILTER_GLOSSY_INDIRECT = (BAKE_FILTER_INDIRECT | BAKE_FILTER_GLOSSY),
- BAKE_FILTER_TRANSMISSION_INDIRECT = (BAKE_FILTER_INDIRECT | BAKE_FILTER_TRANSMISSION),
- BAKE_FILTER_SUBSURFACE_INDIRECT = (BAKE_FILTER_INDIRECT | BAKE_FILTER_SUBSURFACE),
+ BAKE_FILTER_COMBINED = (BAKE_FILTER_DIRECT | BAKE_FILTER_INDIRECT | BAKE_FILTER_DIFFUSE |
+ BAKE_FILTER_GLOSSY | BAKE_FILTER_TRANSMISSION | BAKE_FILTER_SUBSURFACE |
+ BAKE_FILTER_EMISSION | BAKE_FILTER_AO),
+ BAKE_FILTER_DIFFUSE_DIRECT = (BAKE_FILTER_DIRECT | BAKE_FILTER_DIFFUSE),
+ BAKE_FILTER_GLOSSY_DIRECT = (BAKE_FILTER_DIRECT | BAKE_FILTER_GLOSSY),
+ BAKE_FILTER_TRANSMISSION_DIRECT = (BAKE_FILTER_DIRECT | BAKE_FILTER_TRANSMISSION),
+ BAKE_FILTER_SUBSURFACE_DIRECT = (BAKE_FILTER_DIRECT | BAKE_FILTER_SUBSURFACE),
+ BAKE_FILTER_DIFFUSE_INDIRECT = (BAKE_FILTER_INDIRECT | BAKE_FILTER_DIFFUSE),
+ BAKE_FILTER_GLOSSY_INDIRECT = (BAKE_FILTER_INDIRECT | BAKE_FILTER_GLOSSY),
+ BAKE_FILTER_TRANSMISSION_INDIRECT = (BAKE_FILTER_INDIRECT | BAKE_FILTER_TRANSMISSION),
+ BAKE_FILTER_SUBSURFACE_INDIRECT = (BAKE_FILTER_INDIRECT | BAKE_FILTER_SUBSURFACE),
} BakePassFilterCombos;
typedef enum DenoiseFlag {
- DENOISING_CLEAN_DIFFUSE_DIR = (1 << 0),
- DENOISING_CLEAN_DIFFUSE_IND = (1 << 1),
- DENOISING_CLEAN_GLOSSY_DIR = (1 << 2),
- DENOISING_CLEAN_GLOSSY_IND = (1 << 3),
- DENOISING_CLEAN_TRANSMISSION_DIR = (1 << 4),
- DENOISING_CLEAN_TRANSMISSION_IND = (1 << 5),
- DENOISING_CLEAN_SUBSURFACE_DIR = (1 << 6),
- DENOISING_CLEAN_SUBSURFACE_IND = (1 << 7),
- DENOISING_CLEAN_ALL_PASSES = (1 << 8)-1,
+ DENOISING_CLEAN_DIFFUSE_DIR = (1 << 0),
+ DENOISING_CLEAN_DIFFUSE_IND = (1 << 1),
+ DENOISING_CLEAN_GLOSSY_DIR = (1 << 2),
+ DENOISING_CLEAN_GLOSSY_IND = (1 << 3),
+ DENOISING_CLEAN_TRANSMISSION_DIR = (1 << 4),
+ DENOISING_CLEAN_TRANSMISSION_IND = (1 << 5),
+ DENOISING_CLEAN_SUBSURFACE_DIR = (1 << 6),
+ DENOISING_CLEAN_SUBSURFACE_IND = (1 << 7),
+ DENOISING_CLEAN_ALL_PASSES = (1 << 8) - 1,
} DenoiseFlag;
#ifdef __KERNEL_DEBUG__
@@ -476,173 +471,171 @@ typedef enum DenoiseFlag {
* really important here.
*/
typedef struct DebugData {
- int num_bvh_traversed_nodes;
- int num_bvh_traversed_instances;
- int num_bvh_intersections;
- int num_ray_bounces;
+ int num_bvh_traversed_nodes;
+ int num_bvh_traversed_instances;
+ int num_bvh_intersections;
+ int num_ray_bounces;
} DebugData;
#endif
typedef ccl_addr_space struct PathRadianceState {
#ifdef __PASSES__
- float3 diffuse;
- float3 glossy;
- float3 transmission;
- float3 subsurface;
- float3 scatter;
+ float3 diffuse;
+ float3 glossy;
+ float3 transmission;
+ float3 subsurface;
+ float3 scatter;
- float3 direct;
+ float3 direct;
#endif
} PathRadianceState;
typedef ccl_addr_space struct PathRadiance {
#ifdef __PASSES__
- int use_light_pass;
+ int use_light_pass;
#endif
- float transparent;
- float3 emission;
+ float transparent;
+ float3 emission;
#ifdef __PASSES__
- float3 background;
- float3 ao;
-
- float3 indirect;
- float3 direct_emission;
-
- float3 color_diffuse;
- float3 color_glossy;
- float3 color_transmission;
- float3 color_subsurface;
-
- float3 direct_diffuse;
- float3 direct_glossy;
- float3 direct_transmission;
- float3 direct_subsurface;
- float3 direct_scatter;
-
- float3 indirect_diffuse;
- float3 indirect_glossy;
- float3 indirect_transmission;
- float3 indirect_subsurface;
- float3 indirect_scatter;
-
- float4 shadow;
- float mist;
+ float3 background;
+ float3 ao;
+
+ float3 indirect;
+ float3 direct_emission;
+
+ float3 color_diffuse;
+ float3 color_glossy;
+ float3 color_transmission;
+ float3 color_subsurface;
+
+ float3 direct_diffuse;
+ float3 direct_glossy;
+ float3 direct_transmission;
+ float3 direct_subsurface;
+ float3 direct_scatter;
+
+ float3 indirect_diffuse;
+ float3 indirect_glossy;
+ float3 indirect_transmission;
+ float3 indirect_subsurface;
+ float3 indirect_scatter;
+
+ float4 shadow;
+ float mist;
#endif
- struct PathRadianceState state;
+ struct PathRadianceState state;
#ifdef __SHADOW_TRICKS__
- /* Total light reachable across the path, ignoring shadow blocked queries. */
- float3 path_total;
- /* Total light reachable across the path with shadow blocked queries
- * applied here.
- *
- * Dividing this figure by path_total will give estimate of shadow pass.
- */
- float3 path_total_shaded;
-
- /* Color of the background on which shadow is alpha-overed. */
- float3 shadow_background_color;
-
- /* Path radiance sum and throughput at the moment when ray hits shadow
- * catcher object.
- */
- float shadow_throughput;
-
- /* Accumulated transparency along the path after shadow catcher bounce. */
- float shadow_transparency;
-
- /* Indicate if any shadow catcher data is set. */
- int has_shadow_catcher;
+ /* Total light reachable across the path, ignoring shadow blocked queries. */
+ float3 path_total;
+ /* Total light reachable across the path with shadow blocked queries
+ * applied here.
+ *
+ * Dividing this figure by path_total will give estimate of shadow pass.
+ */
+ float3 path_total_shaded;
+
+ /* Color of the background on which shadow is alpha-overed. */
+ float3 shadow_background_color;
+
+ /* Path radiance sum and throughput at the moment when ray hits shadow
+ * catcher object.
+ */
+ float shadow_throughput;
+
+ /* Accumulated transparency along the path after shadow catcher bounce. */
+ float shadow_transparency;
+
+ /* Indicate if any shadow catcher data is set. */
+ int has_shadow_catcher;
#endif
#ifdef __DENOISING_FEATURES__
- float3 denoising_normal;
- float3 denoising_albedo;
- float denoising_depth;
-#endif /* __DENOISING_FEATURES__ */
+ float3 denoising_normal;
+ float3 denoising_albedo;
+ float denoising_depth;
+#endif /* __DENOISING_FEATURES__ */
#ifdef __KERNEL_DEBUG__
- DebugData debug_data;
-#endif /* __KERNEL_DEBUG__ */
+ DebugData debug_data;
+#endif /* __KERNEL_DEBUG__ */
} PathRadiance;
typedef struct BsdfEval {
#ifdef __PASSES__
- int use_light_pass;
+ int use_light_pass;
#endif
- float3 diffuse;
+ float3 diffuse;
#ifdef __PASSES__
- float3 glossy;
- float3 transmission;
- float3 transparent;
- float3 subsurface;
- float3 scatter;
+ float3 glossy;
+ float3 transmission;
+ float3 transparent;
+ float3 subsurface;
+ float3 scatter;
#endif
#ifdef __SHADOW_TRICKS__
- float3 sum_no_mis;
+ float3 sum_no_mis;
#endif
} BsdfEval;
/* Shader Flag */
typedef enum ShaderFlag {
- SHADER_SMOOTH_NORMAL = (1 << 31),
- SHADER_CAST_SHADOW = (1 << 30),
- SHADER_AREA_LIGHT = (1 << 29),
- SHADER_USE_MIS = (1 << 28),
- SHADER_EXCLUDE_DIFFUSE = (1 << 27),
- SHADER_EXCLUDE_GLOSSY = (1 << 26),
- SHADER_EXCLUDE_TRANSMIT = (1 << 25),
- SHADER_EXCLUDE_CAMERA = (1 << 24),
- SHADER_EXCLUDE_SCATTER = (1 << 23),
- SHADER_EXCLUDE_ANY = (SHADER_EXCLUDE_DIFFUSE|SHADER_EXCLUDE_GLOSSY|SHADER_EXCLUDE_TRANSMIT|SHADER_EXCLUDE_CAMERA|SHADER_EXCLUDE_SCATTER),
-
- SHADER_MASK = ~(SHADER_SMOOTH_NORMAL|SHADER_CAST_SHADOW|SHADER_AREA_LIGHT|SHADER_USE_MIS|SHADER_EXCLUDE_ANY)
+ SHADER_SMOOTH_NORMAL = (1 << 31),
+ SHADER_CAST_SHADOW = (1 << 30),
+ SHADER_AREA_LIGHT = (1 << 29),
+ SHADER_USE_MIS = (1 << 28),
+ SHADER_EXCLUDE_DIFFUSE = (1 << 27),
+ SHADER_EXCLUDE_GLOSSY = (1 << 26),
+ SHADER_EXCLUDE_TRANSMIT = (1 << 25),
+ SHADER_EXCLUDE_CAMERA = (1 << 24),
+ SHADER_EXCLUDE_SCATTER = (1 << 23),
+ SHADER_EXCLUDE_ANY = (SHADER_EXCLUDE_DIFFUSE | SHADER_EXCLUDE_GLOSSY | SHADER_EXCLUDE_TRANSMIT |
+ SHADER_EXCLUDE_CAMERA | SHADER_EXCLUDE_SCATTER),
+
+ SHADER_MASK = ~(SHADER_SMOOTH_NORMAL | SHADER_CAST_SHADOW | SHADER_AREA_LIGHT | SHADER_USE_MIS |
+ SHADER_EXCLUDE_ANY)
} ShaderFlag;
/* Light Type */
typedef enum LightType {
- LIGHT_POINT,
- LIGHT_DISTANT,
- LIGHT_BACKGROUND,
- LIGHT_AREA,
- LIGHT_SPOT,
- LIGHT_TRIANGLE
+ LIGHT_POINT,
+ LIGHT_DISTANT,
+ LIGHT_BACKGROUND,
+ LIGHT_AREA,
+ LIGHT_SPOT,
+ LIGHT_TRIANGLE
} LightType;
/* Camera Type */
-enum CameraType {
- CAMERA_PERSPECTIVE,
- CAMERA_ORTHOGRAPHIC,
- CAMERA_PANORAMA
-};
+enum CameraType { CAMERA_PERSPECTIVE, CAMERA_ORTHOGRAPHIC, CAMERA_PANORAMA };
/* Panorama Type */
enum PanoramaType {
- PANORAMA_EQUIRECTANGULAR = 0,
- PANORAMA_FISHEYE_EQUIDISTANT = 1,
- PANORAMA_FISHEYE_EQUISOLID = 2,
- PANORAMA_MIRRORBALL = 3,
+ PANORAMA_EQUIRECTANGULAR = 0,
+ PANORAMA_FISHEYE_EQUIDISTANT = 1,
+ PANORAMA_FISHEYE_EQUISOLID = 2,
+ PANORAMA_MIRRORBALL = 3,
- PANORAMA_NUM_TYPES,
+ PANORAMA_NUM_TYPES,
};
/* Differential */
typedef struct differential3 {
- float3 dx;
- float3 dy;
+ float3 dx;
+ float3 dy;
} differential3;
typedef struct differential {
- float dx;
- float dy;
+ float dx;
+ float dy;
} differential;
/* Ray */
@@ -657,21 +650,21 @@ typedef struct Ray {
* is fixed.
*/
#ifndef __KERNEL_OPENCL_AMD__
- float3 P; /* origin */
- float3 D; /* direction */
+ float3 P; /* origin */
+ float3 D; /* direction */
- float t; /* length of the ray */
- float time; /* time (for motion blur) */
+ float t; /* length of the ray */
+ float time; /* time (for motion blur) */
#else
- float t; /* length of the ray */
- float time; /* time (for motion blur) */
- float3 P; /* origin */
- float3 D; /* direction */
+ float t; /* length of the ray */
+ float time; /* time (for motion blur) */
+ float3 P; /* origin */
+ float3 D; /* direction */
#endif
#ifdef __RAY_DIFFERENTIALS__
- differential3 dP;
- differential3 dD;
+ differential3 dP;
+ differential3 dD;
#endif
} Ray;
@@ -679,42 +672,42 @@ typedef struct Ray {
typedef struct Intersection {
#ifdef __EMBREE__
- float3 Ng;
+ float3 Ng;
#endif
- float t, u, v;
- int prim;
- int object;
- int type;
+ float t, u, v;
+ int prim;
+ int object;
+ int type;
#ifdef __KERNEL_DEBUG__
- int num_traversed_nodes;
- int num_traversed_instances;
- int num_intersections;
+ int num_traversed_nodes;
+ int num_traversed_instances;
+ int num_intersections;
#endif
} Intersection;
/* Primitives */
typedef enum PrimitiveType {
- PRIMITIVE_NONE = 0,
- PRIMITIVE_TRIANGLE = (1 << 0),
- PRIMITIVE_MOTION_TRIANGLE = (1 << 1),
- PRIMITIVE_CURVE = (1 << 2),
- PRIMITIVE_MOTION_CURVE = (1 << 3),
- /* Lamp primitive is not included below on purpose,
- * since it is no real traceable primitive.
- */
- PRIMITIVE_LAMP = (1 << 4),
-
- PRIMITIVE_ALL_TRIANGLE = (PRIMITIVE_TRIANGLE|PRIMITIVE_MOTION_TRIANGLE),
- PRIMITIVE_ALL_CURVE = (PRIMITIVE_CURVE|PRIMITIVE_MOTION_CURVE),
- PRIMITIVE_ALL_MOTION = (PRIMITIVE_MOTION_TRIANGLE|PRIMITIVE_MOTION_CURVE),
- PRIMITIVE_ALL = (PRIMITIVE_ALL_TRIANGLE|PRIMITIVE_ALL_CURVE),
-
- /* Total number of different traceable primitives.
- * NOTE: This is an actual value, not a bitflag.
- */
- PRIMITIVE_NUM_TOTAL = 4,
+ PRIMITIVE_NONE = 0,
+ PRIMITIVE_TRIANGLE = (1 << 0),
+ PRIMITIVE_MOTION_TRIANGLE = (1 << 1),
+ PRIMITIVE_CURVE = (1 << 2),
+ PRIMITIVE_MOTION_CURVE = (1 << 3),
+ /* Lamp primitive is not included below on purpose,
+ * since it is no real traceable primitive.
+ */
+ PRIMITIVE_LAMP = (1 << 4),
+
+ PRIMITIVE_ALL_TRIANGLE = (PRIMITIVE_TRIANGLE | PRIMITIVE_MOTION_TRIANGLE),
+ PRIMITIVE_ALL_CURVE = (PRIMITIVE_CURVE | PRIMITIVE_MOTION_CURVE),
+ PRIMITIVE_ALL_MOTION = (PRIMITIVE_MOTION_TRIANGLE | PRIMITIVE_MOTION_CURVE),
+ PRIMITIVE_ALL = (PRIMITIVE_ALL_TRIANGLE | PRIMITIVE_ALL_CURVE),
+
+ /* Total number of different traceable primitives.
+ * NOTE: This is an actual value, not a bitflag.
+ */
+ PRIMITIVE_NUM_TOTAL = 4,
} PrimitiveType;
#define PRIMITIVE_PACK_SEGMENT(type, segment) ((segment << PRIMITIVE_NUM_TOTAL) | (type))
@@ -723,68 +716,68 @@ typedef enum PrimitiveType {
/* Attributes */
typedef enum AttributePrimitive {
- ATTR_PRIM_TRIANGLE = 0,
- ATTR_PRIM_CURVE,
- ATTR_PRIM_SUBD,
+ ATTR_PRIM_TRIANGLE = 0,
+ ATTR_PRIM_CURVE,
+ ATTR_PRIM_SUBD,
- ATTR_PRIM_TYPES
+ ATTR_PRIM_TYPES
} AttributePrimitive;
typedef enum AttributeElement {
- ATTR_ELEMENT_NONE,
- ATTR_ELEMENT_OBJECT,
- ATTR_ELEMENT_MESH,
- ATTR_ELEMENT_FACE,
- ATTR_ELEMENT_VERTEX,
- ATTR_ELEMENT_VERTEX_MOTION,
- ATTR_ELEMENT_CORNER,
- ATTR_ELEMENT_CORNER_BYTE,
- ATTR_ELEMENT_CURVE,
- ATTR_ELEMENT_CURVE_KEY,
- ATTR_ELEMENT_CURVE_KEY_MOTION,
- ATTR_ELEMENT_VOXEL
+ ATTR_ELEMENT_NONE,
+ ATTR_ELEMENT_OBJECT,
+ ATTR_ELEMENT_MESH,
+ ATTR_ELEMENT_FACE,
+ ATTR_ELEMENT_VERTEX,
+ ATTR_ELEMENT_VERTEX_MOTION,
+ ATTR_ELEMENT_CORNER,
+ ATTR_ELEMENT_CORNER_BYTE,
+ ATTR_ELEMENT_CURVE,
+ ATTR_ELEMENT_CURVE_KEY,
+ ATTR_ELEMENT_CURVE_KEY_MOTION,
+ ATTR_ELEMENT_VOXEL
} AttributeElement;
typedef enum AttributeStandard {
- ATTR_STD_NONE = 0,
- ATTR_STD_VERTEX_NORMAL,
- ATTR_STD_FACE_NORMAL,
- ATTR_STD_UV,
- ATTR_STD_UV_TANGENT,
- ATTR_STD_UV_TANGENT_SIGN,
- ATTR_STD_GENERATED,
- ATTR_STD_GENERATED_TRANSFORM,
- ATTR_STD_POSITION_UNDEFORMED,
- ATTR_STD_POSITION_UNDISPLACED,
- ATTR_STD_MOTION_VERTEX_POSITION,
- ATTR_STD_MOTION_VERTEX_NORMAL,
- ATTR_STD_PARTICLE,
- ATTR_STD_CURVE_INTERCEPT,
- ATTR_STD_CURVE_RANDOM,
- ATTR_STD_PTEX_FACE_ID,
- ATTR_STD_PTEX_UV,
- ATTR_STD_VOLUME_DENSITY,
- ATTR_STD_VOLUME_COLOR,
- ATTR_STD_VOLUME_FLAME,
- ATTR_STD_VOLUME_HEAT,
- ATTR_STD_VOLUME_TEMPERATURE,
- ATTR_STD_VOLUME_VELOCITY,
- ATTR_STD_POINTINESS,
- ATTR_STD_NUM,
-
- ATTR_STD_NOT_FOUND = ~0
+ ATTR_STD_NONE = 0,
+ ATTR_STD_VERTEX_NORMAL,
+ ATTR_STD_FACE_NORMAL,
+ ATTR_STD_UV,
+ ATTR_STD_UV_TANGENT,
+ ATTR_STD_UV_TANGENT_SIGN,
+ ATTR_STD_GENERATED,
+ ATTR_STD_GENERATED_TRANSFORM,
+ ATTR_STD_POSITION_UNDEFORMED,
+ ATTR_STD_POSITION_UNDISPLACED,
+ ATTR_STD_MOTION_VERTEX_POSITION,
+ ATTR_STD_MOTION_VERTEX_NORMAL,
+ ATTR_STD_PARTICLE,
+ ATTR_STD_CURVE_INTERCEPT,
+ ATTR_STD_CURVE_RANDOM,
+ ATTR_STD_PTEX_FACE_ID,
+ ATTR_STD_PTEX_UV,
+ ATTR_STD_VOLUME_DENSITY,
+ ATTR_STD_VOLUME_COLOR,
+ ATTR_STD_VOLUME_FLAME,
+ ATTR_STD_VOLUME_HEAT,
+ ATTR_STD_VOLUME_TEMPERATURE,
+ ATTR_STD_VOLUME_VELOCITY,
+ ATTR_STD_POINTINESS,
+ ATTR_STD_NUM,
+
+ ATTR_STD_NOT_FOUND = ~0
} AttributeStandard;
typedef enum AttributeFlag {
- ATTR_FINAL_SIZE = (1 << 0),
- ATTR_SUBDIVIDED = (1 << 1),
+ ATTR_FINAL_SIZE = (1 << 0),
+ ATTR_SUBDIVIDED = (1 << 1),
} AttributeFlag;
typedef struct AttributeDescriptor {
- AttributeElement element;
- NodeAttributeType type;
- uint flags; /* see enum AttributeFlag */
- int offset;
+ AttributeElement element;
+ NodeAttributeType type;
+ uint flags; /* see enum AttributeFlag */
+ int offset;
} AttributeDescriptor;
/* Closure data */
@@ -794,7 +787,7 @@ typedef struct AttributeDescriptor {
# define MAX_CLOSURE 1
# else
# ifndef __MAX_CLOSURE__
-# define MAX_CLOSURE 64
+# define MAX_CLOSURE 64
# else
# define MAX_CLOSURE __MAX_CLOSURE__
# endif
@@ -815,16 +808,18 @@ typedef struct AttributeDescriptor {
* we assume to be the maximum required alignment for any struct. */
#define SHADER_CLOSURE_BASE \
- float3 weight; \
- ClosureType type; \
- float sample_weight; \
- float3 N
+ float3 weight; \
+ ClosureType type; \
+ float sample_weight; \
+ float3 N
-typedef ccl_addr_space struct ccl_align(16) ShaderClosure {
- SHADER_CLOSURE_BASE;
+typedef ccl_addr_space struct ccl_align(16) ShaderClosure
+{
+ SHADER_CLOSURE_BASE;
- float data[10]; /* pad to 80 bytes */
-} ShaderClosure;
+ float data[10]; /* pad to 80 bytes */
+}
+ShaderClosure;
/* Shader Data
*
@@ -833,272 +828,253 @@ typedef ccl_addr_space struct ccl_align(16) ShaderClosure {
*/
enum ShaderDataFlag {
- /* Runtime flags. */
-
- /* Set when ray hits backside of surface. */
- SD_BACKFACING = (1 << 0),
- /* Shader has non-zero emission. */
- SD_EMISSION = (1 << 1),
- /* Shader has BSDF closure. */
- SD_BSDF = (1 << 2),
- /* Shader has non-singular BSDF closure. */
- SD_BSDF_HAS_EVAL = (1 << 3),
- /* Shader has BSSRDF closure. */
- SD_BSSRDF = (1 << 4),
- /* Shader has holdout closure. */
- SD_HOLDOUT = (1 << 5),
- /* Shader has non-zero volume extinction. */
- SD_EXTINCTION = (1 << 6),
- /* Shader has have volume phase (scatter) closure. */
- SD_SCATTER = (1 << 7),
- /* Shader has transparent closure. */
- SD_TRANSPARENT = (1 << 9),
- /* BSDF requires LCG for evaluation. */
- SD_BSDF_NEEDS_LCG = (1 << 10),
-
- SD_CLOSURE_FLAGS = (SD_EMISSION |
- SD_BSDF |
- SD_BSDF_HAS_EVAL |
- SD_BSSRDF |
- SD_HOLDOUT |
- SD_EXTINCTION |
- SD_SCATTER |
- SD_BSDF_NEEDS_LCG),
-
- /* Shader flags. */
-
- /* direct light sample */
- SD_USE_MIS = (1 << 16),
- /* Has transparent shadow. */
- SD_HAS_TRANSPARENT_SHADOW = (1 << 17),
- /* Has volume shader. */
- SD_HAS_VOLUME = (1 << 18),
- /* Has only volume shader, no surface. */
- SD_HAS_ONLY_VOLUME = (1 << 19),
- /* Has heterogeneous volume. */
- SD_HETEROGENEOUS_VOLUME = (1 << 20),
- /* BSSRDF normal uses bump. */
- SD_HAS_BSSRDF_BUMP = (1 << 21),
- /* Use equiangular volume sampling */
- SD_VOLUME_EQUIANGULAR = (1 << 22),
- /* Use multiple importance volume sampling. */
- SD_VOLUME_MIS = (1 << 23),
- /* Use cubic interpolation for voxels. */
- SD_VOLUME_CUBIC = (1 << 24),
- /* Has data connected to the displacement input or uses bump map. */
- SD_HAS_BUMP = (1 << 25),
- /* Has true displacement. */
- SD_HAS_DISPLACEMENT = (1 << 26),
- /* Has constant emission (value stored in __shaders) */
- SD_HAS_CONSTANT_EMISSION = (1 << 27),
- /* Needs to access attributes */
- SD_NEED_ATTRIBUTES = (1 << 28),
-
- SD_SHADER_FLAGS = (SD_USE_MIS |
- SD_HAS_TRANSPARENT_SHADOW |
- SD_HAS_VOLUME |
- SD_HAS_ONLY_VOLUME |
- SD_HETEROGENEOUS_VOLUME |
- SD_HAS_BSSRDF_BUMP |
- SD_VOLUME_EQUIANGULAR |
- SD_VOLUME_MIS |
- SD_VOLUME_CUBIC |
- SD_HAS_BUMP |
- SD_HAS_DISPLACEMENT |
- SD_HAS_CONSTANT_EMISSION |
- SD_NEED_ATTRIBUTES)
+ /* Runtime flags. */
+
+ /* Set when ray hits backside of surface. */
+ SD_BACKFACING = (1 << 0),
+ /* Shader has non-zero emission. */
+ SD_EMISSION = (1 << 1),
+ /* Shader has BSDF closure. */
+ SD_BSDF = (1 << 2),
+ /* Shader has non-singular BSDF closure. */
+ SD_BSDF_HAS_EVAL = (1 << 3),
+ /* Shader has BSSRDF closure. */
+ SD_BSSRDF = (1 << 4),
+ /* Shader has holdout closure. */
+ SD_HOLDOUT = (1 << 5),
+ /* Shader has non-zero volume extinction. */
+ SD_EXTINCTION = (1 << 6),
+ /* Shader has have volume phase (scatter) closure. */
+ SD_SCATTER = (1 << 7),
+ /* Shader has transparent closure. */
+ SD_TRANSPARENT = (1 << 9),
+ /* BSDF requires LCG for evaluation. */
+ SD_BSDF_NEEDS_LCG = (1 << 10),
+
+ SD_CLOSURE_FLAGS = (SD_EMISSION | SD_BSDF | SD_BSDF_HAS_EVAL | SD_BSSRDF | SD_HOLDOUT |
+ SD_EXTINCTION | SD_SCATTER | SD_BSDF_NEEDS_LCG),
+
+ /* Shader flags. */
+
+ /* direct light sample */
+ SD_USE_MIS = (1 << 16),
+ /* Has transparent shadow. */
+ SD_HAS_TRANSPARENT_SHADOW = (1 << 17),
+ /* Has volume shader. */
+ SD_HAS_VOLUME = (1 << 18),
+ /* Has only volume shader, no surface. */
+ SD_HAS_ONLY_VOLUME = (1 << 19),
+ /* Has heterogeneous volume. */
+ SD_HETEROGENEOUS_VOLUME = (1 << 20),
+ /* BSSRDF normal uses bump. */
+ SD_HAS_BSSRDF_BUMP = (1 << 21),
+ /* Use equiangular volume sampling */
+ SD_VOLUME_EQUIANGULAR = (1 << 22),
+ /* Use multiple importance volume sampling. */
+ SD_VOLUME_MIS = (1 << 23),
+ /* Use cubic interpolation for voxels. */
+ SD_VOLUME_CUBIC = (1 << 24),
+ /* Has data connected to the displacement input or uses bump map. */
+ SD_HAS_BUMP = (1 << 25),
+ /* Has true displacement. */
+ SD_HAS_DISPLACEMENT = (1 << 26),
+ /* Has constant emission (value stored in __shaders) */
+ SD_HAS_CONSTANT_EMISSION = (1 << 27),
+ /* Needs to access attributes */
+ SD_NEED_ATTRIBUTES = (1 << 28),
+
+ SD_SHADER_FLAGS = (SD_USE_MIS | SD_HAS_TRANSPARENT_SHADOW | SD_HAS_VOLUME | SD_HAS_ONLY_VOLUME |
+ SD_HETEROGENEOUS_VOLUME | SD_HAS_BSSRDF_BUMP | SD_VOLUME_EQUIANGULAR |
+ SD_VOLUME_MIS | SD_VOLUME_CUBIC | SD_HAS_BUMP | SD_HAS_DISPLACEMENT |
+ SD_HAS_CONSTANT_EMISSION | SD_NEED_ATTRIBUTES)
};
- /* Object flags. */
+/* Object flags. */
enum ShaderDataObjectFlag {
- /* Holdout for camera rays. */
- SD_OBJECT_HOLDOUT_MASK = (1 << 0),
- /* Has object motion blur. */
- SD_OBJECT_MOTION = (1 << 1),
- /* Vertices have transform applied. */
- SD_OBJECT_TRANSFORM_APPLIED = (1 << 2),
- /* Vertices have negative scale applied. */
- SD_OBJECT_NEGATIVE_SCALE_APPLIED = (1 << 3),
- /* Object has a volume shader. */
- SD_OBJECT_HAS_VOLUME = (1 << 4),
- /* Object intersects AABB of an object with volume shader. */
- SD_OBJECT_INTERSECTS_VOLUME = (1 << 5),
- /* Has position for motion vertices. */
- SD_OBJECT_HAS_VERTEX_MOTION = (1 << 6),
- /* object is used to catch shadows */
- SD_OBJECT_SHADOW_CATCHER = (1 << 7),
- /* object has volume attributes */
- SD_OBJECT_HAS_VOLUME_ATTRIBUTES = (1 << 8),
-
- SD_OBJECT_FLAGS = (SD_OBJECT_HOLDOUT_MASK |
- SD_OBJECT_MOTION |
- SD_OBJECT_TRANSFORM_APPLIED |
- SD_OBJECT_NEGATIVE_SCALE_APPLIED |
- SD_OBJECT_HAS_VOLUME |
- SD_OBJECT_INTERSECTS_VOLUME |
- SD_OBJECT_SHADOW_CATCHER |
- SD_OBJECT_HAS_VOLUME_ATTRIBUTES)
+ /* Holdout for camera rays. */
+ SD_OBJECT_HOLDOUT_MASK = (1 << 0),
+ /* Has object motion blur. */
+ SD_OBJECT_MOTION = (1 << 1),
+ /* Vertices have transform applied. */
+ SD_OBJECT_TRANSFORM_APPLIED = (1 << 2),
+ /* Vertices have negative scale applied. */
+ SD_OBJECT_NEGATIVE_SCALE_APPLIED = (1 << 3),
+ /* Object has a volume shader. */
+ SD_OBJECT_HAS_VOLUME = (1 << 4),
+ /* Object intersects AABB of an object with volume shader. */
+ SD_OBJECT_INTERSECTS_VOLUME = (1 << 5),
+ /* Has position for motion vertices. */
+ SD_OBJECT_HAS_VERTEX_MOTION = (1 << 6),
+ /* object is used to catch shadows */
+ SD_OBJECT_SHADOW_CATCHER = (1 << 7),
+ /* object has volume attributes */
+ SD_OBJECT_HAS_VOLUME_ATTRIBUTES = (1 << 8),
+
+ SD_OBJECT_FLAGS = (SD_OBJECT_HOLDOUT_MASK | SD_OBJECT_MOTION | SD_OBJECT_TRANSFORM_APPLIED |
+ SD_OBJECT_NEGATIVE_SCALE_APPLIED | SD_OBJECT_HAS_VOLUME |
+ SD_OBJECT_INTERSECTS_VOLUME | SD_OBJECT_SHADOW_CATCHER |
+ SD_OBJECT_HAS_VOLUME_ATTRIBUTES)
};
typedef ccl_addr_space struct ShaderData {
- /* position */
- float3 P;
- /* smooth normal for shading */
- float3 N;
- /* true geometric normal */
- float3 Ng;
- /* view/incoming direction */
- float3 I;
- /* shader id */
- int shader;
- /* booleans describing shader, see ShaderDataFlag */
- int flag;
- /* booleans describing object of the shader, see ShaderDataObjectFlag */
- int object_flag;
-
- /* primitive id if there is one, ~0 otherwise */
- int prim;
-
- /* combined type and curve segment for hair */
- int type;
-
- /* parametric coordinates
- * - barycentric weights for triangles */
- float u;
- float v;
- /* object id if there is one, ~0 otherwise */
- int object;
- /* lamp id if there is one, ~0 otherwise */
- int lamp;
-
- /* motion blur sample time */
- float time;
-
- /* length of the ray being shaded */
- float ray_length;
+ /* position */
+ float3 P;
+ /* smooth normal for shading */
+ float3 N;
+ /* true geometric normal */
+ float3 Ng;
+ /* view/incoming direction */
+ float3 I;
+ /* shader id */
+ int shader;
+ /* booleans describing shader, see ShaderDataFlag */
+ int flag;
+ /* booleans describing object of the shader, see ShaderDataObjectFlag */
+ int object_flag;
+
+ /* primitive id if there is one, ~0 otherwise */
+ int prim;
+
+ /* combined type and curve segment for hair */
+ int type;
+
+ /* parametric coordinates
+ * - barycentric weights for triangles */
+ float u;
+ float v;
+ /* object id if there is one, ~0 otherwise */
+ int object;
+ /* lamp id if there is one, ~0 otherwise */
+ int lamp;
+
+ /* motion blur sample time */
+ float time;
+
+ /* length of the ray being shaded */
+ float ray_length;
#ifdef __RAY_DIFFERENTIALS__
- /* differential of P. these are orthogonal to Ng, not N */
- differential3 dP;
- /* differential of I */
- differential3 dI;
- /* differential of u, v */
- differential du;
- differential dv;
+ /* differential of P. these are orthogonal to Ng, not N */
+ differential3 dP;
+ /* differential of I */
+ differential3 dI;
+ /* differential of u, v */
+ differential du;
+ differential dv;
#endif
#ifdef __DPDU__
- /* differential of P w.r.t. parametric coordinates. note that dPdu is
- * not readily suitable as a tangent for shading on triangles. */
- float3 dPdu;
- float3 dPdv;
+ /* differential of P w.r.t. parametric coordinates. note that dPdu is
+ * not readily suitable as a tangent for shading on triangles. */
+ float3 dPdu;
+ float3 dPdv;
#endif
#ifdef __OBJECT_MOTION__
- /* object <-> world space transformations, cached to avoid
- * re-interpolating them constantly for shading */
- Transform ob_tfm;
- Transform ob_itfm;
+ /* object <-> world space transformations, cached to avoid
+ * re-interpolating them constantly for shading */
+ Transform ob_tfm;
+ Transform ob_itfm;
#endif
- /* ray start position, only set for backgrounds */
- float3 ray_P;
- differential3 ray_dP;
+ /* ray start position, only set for backgrounds */
+ float3 ray_P;
+ differential3 ray_dP;
#ifdef __OSL__
- struct KernelGlobals *osl_globals;
- struct PathState *osl_path_state;
+ struct KernelGlobals *osl_globals;
+ struct PathState *osl_path_state;
#endif
- /* LCG state for closures that require additional random numbers. */
- uint lcg_state;
+ /* LCG state for closures that require additional random numbers. */
+ uint lcg_state;
- /* Closure data, we store a fixed array of closures */
- int num_closure;
- int num_closure_left;
- float randb_closure;
- float3 svm_closure_weight;
+ /* Closure data, we store a fixed array of closures */
+ int num_closure;
+ int num_closure_left;
+ float randb_closure;
+ float3 svm_closure_weight;
- /* Closure weights summed directly, so we can evaluate
- * emission and shadow transparency with MAX_CLOSURE 0. */
- float3 closure_emission_background;
- float3 closure_transparent_extinction;
+ /* Closure weights summed directly, so we can evaluate
+ * emission and shadow transparency with MAX_CLOSURE 0. */
+ float3 closure_emission_background;
+ float3 closure_transparent_extinction;
- /* At the end so we can adjust size in ShaderDataTinyStorage. */
- struct ShaderClosure closure[MAX_CLOSURE];
+ /* At the end so we can adjust size in ShaderDataTinyStorage. */
+ struct ShaderClosure closure[MAX_CLOSURE];
} ShaderData;
typedef ccl_addr_space struct ShaderDataTinyStorage {
- char pad[sizeof(ShaderData) - sizeof(ShaderClosure) * MAX_CLOSURE];
+ char pad[sizeof(ShaderData) - sizeof(ShaderClosure) * MAX_CLOSURE];
} ShaderDataTinyStorage;
-#define AS_SHADER_DATA(shader_data_tiny_storage) ((ShaderData*)shader_data_tiny_storage)
+#define AS_SHADER_DATA(shader_data_tiny_storage) ((ShaderData *)shader_data_tiny_storage)
/* Path State */
#ifdef __VOLUME__
typedef struct VolumeStack {
- int object;
- int shader;
+ int object;
+ int shader;
} VolumeStack;
#endif
typedef struct PathState {
- /* see enum PathRayFlag */
- int flag;
-
- /* random number generator state */
- uint rng_hash; /* per pixel hash */
- int rng_offset; /* dimension offset */
- int sample; /* path sample number */
- int num_samples; /* total number of times this path will be sampled */
- float branch_factor; /* number of branches in indirect paths */
-
- /* bounce counting */
- int bounce;
- int diffuse_bounce;
- int glossy_bounce;
- int transmission_bounce;
- int transparent_bounce;
+ /* see enum PathRayFlag */
+ int flag;
+
+ /* random number generator state */
+ uint rng_hash; /* per pixel hash */
+ int rng_offset; /* dimension offset */
+ int sample; /* path sample number */
+ int num_samples; /* total number of times this path will be sampled */
+ float branch_factor; /* number of branches in indirect paths */
+
+ /* bounce counting */
+ int bounce;
+ int diffuse_bounce;
+ int glossy_bounce;
+ int transmission_bounce;
+ int transparent_bounce;
#ifdef __DENOISING_FEATURES__
- float denoising_feature_weight;
-#endif /* __DENOISING_FEATURES__ */
+ float denoising_feature_weight;
+#endif /* __DENOISING_FEATURES__ */
- /* multiple importance sampling */
- float min_ray_pdf; /* smallest bounce pdf over entire path up to now */
- float ray_pdf; /* last bounce pdf */
+ /* multiple importance sampling */
+ float min_ray_pdf; /* smallest bounce pdf over entire path up to now */
+ float ray_pdf; /* last bounce pdf */
#ifdef __LAMP_MIS__
- float ray_t; /* accumulated distance through transparent surfaces */
+ float ray_t; /* accumulated distance through transparent surfaces */
#endif
- /* volume rendering */
+ /* volume rendering */
#ifdef __VOLUME__
- int volume_bounce;
- int volume_bounds_bounce;
- VolumeStack volume_stack[VOLUME_STACK_SIZE];
+ int volume_bounce;
+ int volume_bounds_bounce;
+ VolumeStack volume_stack[VOLUME_STACK_SIZE];
#endif
} PathState;
/* Struct to gather multiple nearby intersections. */
typedef struct LocalIntersection {
- Ray ray;
- float3 weight[LOCAL_MAX_HITS];
+ Ray ray;
+ float3 weight[LOCAL_MAX_HITS];
- int num_hits;
- struct Intersection hits[LOCAL_MAX_HITS];
- float3 Ng[LOCAL_MAX_HITS];
+ int num_hits;
+ struct Intersection hits[LOCAL_MAX_HITS];
+ float3 Ng[LOCAL_MAX_HITS];
} LocalIntersection;
/* Subsurface */
/* Struct to gather SSS indirect rays and delay tracing them. */
typedef struct SubsurfaceIndirectRays {
- PathState state[BSSRDF_MAX_HITS];
+ PathState state[BSSRDF_MAX_HITS];
- int num_rays;
+ int num_rays;
- struct Ray rays[BSSRDF_MAX_HITS];
- float3 throughputs[BSSRDF_MAX_HITS];
- struct PathRadianceState L_state[BSSRDF_MAX_HITS];
+ struct Ray rays[BSSRDF_MAX_HITS];
+ float3 throughputs[BSSRDF_MAX_HITS];
+ struct PathRadianceState L_state[BSSRDF_MAX_HITS];
} SubsurfaceIndirectRays;
static_assert(BSSRDF_MAX_HITS <= LOCAL_MAX_HITS, "BSSRDF hits too high.");
@@ -1109,424 +1085,424 @@ static_assert(BSSRDF_MAX_HITS <= LOCAL_MAX_HITS, "BSSRDF hits too high.");
* do not use float3 because its size may not be the same on all devices. */
typedef struct KernelCamera {
- /* type */
- int type;
-
- /* panorama */
- int panorama_type;
- float fisheye_fov;
- float fisheye_lens;
- float4 equirectangular_range;
-
- /* stereo */
- float interocular_offset;
- float convergence_distance;
- float pole_merge_angle_from;
- float pole_merge_angle_to;
-
- /* matrices */
- Transform cameratoworld;
- ProjectionTransform rastertocamera;
-
- /* differentials */
- float4 dx;
- float4 dy;
-
- /* depth of field */
- float aperturesize;
- float blades;
- float bladesrotation;
- float focaldistance;
-
- /* motion blur */
- float shuttertime;
- int num_motion_steps, have_perspective_motion;
-
- /* clipping */
- float nearclip;
- float cliplength;
-
- /* sensor size */
- float sensorwidth;
- float sensorheight;
-
- /* render size */
- float width, height;
- int resolution;
-
- /* anamorphic lens bokeh */
- float inv_aperture_ratio;
-
- int is_inside_volume;
-
- /* more matrices */
- ProjectionTransform screentoworld;
- ProjectionTransform rastertoworld;
- ProjectionTransform ndctoworld;
- ProjectionTransform worldtoscreen;
- ProjectionTransform worldtoraster;
- ProjectionTransform worldtondc;
- Transform worldtocamera;
-
- /* Stores changes in the projeciton matrix. Use for camera zoom motion
- * blur and motion pass output for perspective camera. */
- ProjectionTransform perspective_pre;
- ProjectionTransform perspective_post;
-
- /* Transforms for motion pass. */
- Transform motion_pass_pre;
- Transform motion_pass_post;
-
- int shutter_table_offset;
-
- /* Rolling shutter */
- int rolling_shutter_type;
- float rolling_shutter_duration;
-
- int pad;
+ /* type */
+ int type;
+
+ /* panorama */
+ int panorama_type;
+ float fisheye_fov;
+ float fisheye_lens;
+ float4 equirectangular_range;
+
+ /* stereo */
+ float interocular_offset;
+ float convergence_distance;
+ float pole_merge_angle_from;
+ float pole_merge_angle_to;
+
+ /* matrices */
+ Transform cameratoworld;
+ ProjectionTransform rastertocamera;
+
+ /* differentials */
+ float4 dx;
+ float4 dy;
+
+ /* depth of field */
+ float aperturesize;
+ float blades;
+ float bladesrotation;
+ float focaldistance;
+
+ /* motion blur */
+ float shuttertime;
+ int num_motion_steps, have_perspective_motion;
+
+ /* clipping */
+ float nearclip;
+ float cliplength;
+
+ /* sensor size */
+ float sensorwidth;
+ float sensorheight;
+
+ /* render size */
+ float width, height;
+ int resolution;
+
+ /* anamorphic lens bokeh */
+ float inv_aperture_ratio;
+
+ int is_inside_volume;
+
+ /* more matrices */
+ ProjectionTransform screentoworld;
+ ProjectionTransform rastertoworld;
+ ProjectionTransform ndctoworld;
+ ProjectionTransform worldtoscreen;
+ ProjectionTransform worldtoraster;
+ ProjectionTransform worldtondc;
+ Transform worldtocamera;
+
+ /* Stores changes in the projeciton matrix. Use for camera zoom motion
+ * blur and motion pass output for perspective camera. */
+ ProjectionTransform perspective_pre;
+ ProjectionTransform perspective_post;
+
+ /* Transforms for motion pass. */
+ Transform motion_pass_pre;
+ Transform motion_pass_post;
+
+ int shutter_table_offset;
+
+ /* Rolling shutter */
+ int rolling_shutter_type;
+ float rolling_shutter_duration;
+
+ int pad;
} KernelCamera;
static_assert_align(KernelCamera, 16);
typedef struct KernelFilm {
- float exposure;
- int pass_flag;
- int light_pass_flag;
- int pass_stride;
- int use_light_pass;
-
- int pass_combined;
- int pass_depth;
- int pass_normal;
- int pass_motion;
-
- int pass_motion_weight;
- int pass_uv;
- int pass_object_id;
- int pass_material_id;
-
- int pass_diffuse_color;
- int pass_glossy_color;
- int pass_transmission_color;
- int pass_subsurface_color;
-
- int pass_diffuse_indirect;
- int pass_glossy_indirect;
- int pass_transmission_indirect;
- int pass_subsurface_indirect;
- int pass_volume_indirect;
-
- int pass_diffuse_direct;
- int pass_glossy_direct;
- int pass_transmission_direct;
- int pass_subsurface_direct;
- int pass_volume_direct;
-
- int pass_emission;
- int pass_background;
- int pass_ao;
- float pass_alpha_threshold;
-
- int pass_shadow;
- float pass_shadow_scale;
- int filter_table_offset;
- int cryptomatte_passes;
- int cryptomatte_depth;
- int pass_cryptomatte;
-
- int pass_mist;
- float mist_start;
- float mist_inv_depth;
- float mist_falloff;
-
- int pass_denoising_data;
- int pass_denoising_clean;
- int denoising_flags;
-
- /* XYZ to rendering color space transform. float4 instead of float3 to
- * ensure consistent padding/alignment across devices. */
- float4 xyz_to_r;
- float4 xyz_to_g;
- float4 xyz_to_b;
- float4 rgb_to_y;
+ float exposure;
+ int pass_flag;
+ int light_pass_flag;
+ int pass_stride;
+ int use_light_pass;
+
+ int pass_combined;
+ int pass_depth;
+ int pass_normal;
+ int pass_motion;
+
+ int pass_motion_weight;
+ int pass_uv;
+ int pass_object_id;
+ int pass_material_id;
+
+ int pass_diffuse_color;
+ int pass_glossy_color;
+ int pass_transmission_color;
+ int pass_subsurface_color;
+
+ int pass_diffuse_indirect;
+ int pass_glossy_indirect;
+ int pass_transmission_indirect;
+ int pass_subsurface_indirect;
+ int pass_volume_indirect;
+
+ int pass_diffuse_direct;
+ int pass_glossy_direct;
+ int pass_transmission_direct;
+ int pass_subsurface_direct;
+ int pass_volume_direct;
+
+ int pass_emission;
+ int pass_background;
+ int pass_ao;
+ float pass_alpha_threshold;
+
+ int pass_shadow;
+ float pass_shadow_scale;
+ int filter_table_offset;
+ int cryptomatte_passes;
+ int cryptomatte_depth;
+ int pass_cryptomatte;
+
+ int pass_mist;
+ float mist_start;
+ float mist_inv_depth;
+ float mist_falloff;
+
+ int pass_denoising_data;
+ int pass_denoising_clean;
+ int denoising_flags;
+
+ /* XYZ to rendering color space transform. float4 instead of float3 to
+ * ensure consistent padding/alignment across devices. */
+ float4 xyz_to_r;
+ float4 xyz_to_g;
+ float4 xyz_to_b;
+ float4 rgb_to_y;
#ifdef __KERNEL_DEBUG__
- int pass_bvh_traversed_nodes;
- int pass_bvh_traversed_instances;
- int pass_bvh_intersections;
- int pass_ray_bounces;
+ int pass_bvh_traversed_nodes;
+ int pass_bvh_traversed_instances;
+ int pass_bvh_intersections;
+ int pass_ray_bounces;
#endif
} KernelFilm;
static_assert_align(KernelFilm, 16);
typedef struct KernelBackground {
- /* only shader index */
- int surface_shader;
- int volume_shader;
- int transparent;
- float transparent_roughness_squared_threshold;
-
- /* ambient occlusion */
- float ao_factor;
- float ao_distance;
- float ao_bounces_factor;
- float ao_pad;
+ /* only shader index */
+ int surface_shader;
+ int volume_shader;
+ int transparent;
+ float transparent_roughness_squared_threshold;
+
+ /* ambient occlusion */
+ float ao_factor;
+ float ao_distance;
+ float ao_bounces_factor;
+ float ao_pad;
} KernelBackground;
static_assert_align(KernelBackground, 16);
typedef struct KernelIntegrator {
- /* emission */
- int use_direct_light;
- int use_ambient_occlusion;
- int num_distribution;
- int num_all_lights;
- float pdf_triangles;
- float pdf_lights;
- int pdf_background_res_x;
- int pdf_background_res_y;
- float light_inv_rr_threshold;
-
- /* light portals */
- float portal_pdf;
- int num_portals;
- int portal_offset;
-
- /* bounces */
- int max_bounce;
-
- int max_diffuse_bounce;
- int max_glossy_bounce;
- int max_transmission_bounce;
- int max_volume_bounce;
-
- int ao_bounces;
-
- /* transparent */
- int transparent_max_bounce;
- int transparent_shadows;
-
- /* caustics */
- int caustics_reflective;
- int caustics_refractive;
- float filter_glossy;
-
- /* seed */
- int seed;
-
- /* clamp */
- float sample_clamp_direct;
- float sample_clamp_indirect;
-
- /* branched path */
- int branched;
- int volume_decoupled;
- int diffuse_samples;
- int glossy_samples;
- int transmission_samples;
- int ao_samples;
- int mesh_light_samples;
- int subsurface_samples;
- int sample_all_lights_direct;
- int sample_all_lights_indirect;
-
- /* mis */
- int use_lamp_mis;
-
- /* sampler */
- int sampling_pattern;
- int aa_samples;
-
- /* volume render */
- int use_volumes;
- int volume_max_steps;
- float volume_step_size;
- int volume_samples;
-
- int start_sample;
-
- int max_closures;
-
- int pad1, pad2, pad3;
+ /* emission */
+ int use_direct_light;
+ int use_ambient_occlusion;
+ int num_distribution;
+ int num_all_lights;
+ float pdf_triangles;
+ float pdf_lights;
+ int pdf_background_res_x;
+ int pdf_background_res_y;
+ float light_inv_rr_threshold;
+
+ /* light portals */
+ float portal_pdf;
+ int num_portals;
+ int portal_offset;
+
+ /* bounces */
+ int max_bounce;
+
+ int max_diffuse_bounce;
+ int max_glossy_bounce;
+ int max_transmission_bounce;
+ int max_volume_bounce;
+
+ int ao_bounces;
+
+ /* transparent */
+ int transparent_max_bounce;
+ int transparent_shadows;
+
+ /* caustics */
+ int caustics_reflective;
+ int caustics_refractive;
+ float filter_glossy;
+
+ /* seed */
+ int seed;
+
+ /* clamp */
+ float sample_clamp_direct;
+ float sample_clamp_indirect;
+
+ /* branched path */
+ int branched;
+ int volume_decoupled;
+ int diffuse_samples;
+ int glossy_samples;
+ int transmission_samples;
+ int ao_samples;
+ int mesh_light_samples;
+ int subsurface_samples;
+ int sample_all_lights_direct;
+ int sample_all_lights_indirect;
+
+ /* mis */
+ int use_lamp_mis;
+
+ /* sampler */
+ int sampling_pattern;
+ int aa_samples;
+
+ /* volume render */
+ int use_volumes;
+ int volume_max_steps;
+ float volume_step_size;
+ int volume_samples;
+
+ int start_sample;
+
+ int max_closures;
+
+ int pad1, pad2, pad3;
} KernelIntegrator;
static_assert_align(KernelIntegrator, 16);
typedef enum KernelBVHLayout {
- BVH_LAYOUT_NONE = 0,
-
- BVH_LAYOUT_BVH2 = (1 << 0),
- BVH_LAYOUT_BVH4 = (1 << 1),
- BVH_LAYOUT_BVH8 = (1 << 2),
- BVH_LAYOUT_EMBREE = (1 << 3),
- BVH_LAYOUT_DEFAULT = BVH_LAYOUT_BVH8,
- BVH_LAYOUT_ALL = (unsigned int)(-1),
+ BVH_LAYOUT_NONE = 0,
+
+ BVH_LAYOUT_BVH2 = (1 << 0),
+ BVH_LAYOUT_BVH4 = (1 << 1),
+ BVH_LAYOUT_BVH8 = (1 << 2),
+ BVH_LAYOUT_EMBREE = (1 << 3),
+ BVH_LAYOUT_DEFAULT = BVH_LAYOUT_BVH8,
+ BVH_LAYOUT_ALL = (unsigned int)(-1),
} KernelBVHLayout;
typedef struct KernelBVH {
- /* Own BVH */
- int root;
- int have_motion;
- int have_curves;
- int have_instancing;
- int bvh_layout;
- int use_bvh_steps;
-
- /* Embree */
+ /* Own BVH */
+ int root;
+ int have_motion;
+ int have_curves;
+ int have_instancing;
+ int bvh_layout;
+ int use_bvh_steps;
+
+ /* Embree */
#ifdef __EMBREE__
- RTCScene scene;
+ RTCScene scene;
# ifndef __KERNEL_64_BIT__
- int pad1;
+ int pad1;
# endif
#else
- int pad1, pad2;
+ int pad1, pad2;
#endif
} KernelBVH;
static_assert_align(KernelBVH, 16);
typedef enum CurveFlag {
- /* runtime flags */
- CURVE_KN_BACKFACING = 1, /* backside of cylinder? */
- CURVE_KN_ENCLOSEFILTER = 2, /* don't consider strands surrounding start point? */
- CURVE_KN_INTERPOLATE = 4, /* render as a curve? */
- CURVE_KN_ACCURATE = 8, /* use accurate intersections test? */
- CURVE_KN_INTERSECTCORRECTION = 16, /* correct for width after determing closest midpoint? */
- CURVE_KN_TRUETANGENTGNORMAL = 32, /* use tangent normal for geometry? */
- CURVE_KN_RIBBONS = 64, /* use flat curve ribbons */
+ /* runtime flags */
+ CURVE_KN_BACKFACING = 1, /* backside of cylinder? */
+ CURVE_KN_ENCLOSEFILTER = 2, /* don't consider strands surrounding start point? */
+ CURVE_KN_INTERPOLATE = 4, /* render as a curve? */
+ CURVE_KN_ACCURATE = 8, /* use accurate intersections test? */
+ CURVE_KN_INTERSECTCORRECTION = 16, /* correct for width after determing closest midpoint? */
+ CURVE_KN_TRUETANGENTGNORMAL = 32, /* use tangent normal for geometry? */
+ CURVE_KN_RIBBONS = 64, /* use flat curve ribbons */
} CurveFlag;
typedef struct KernelCurves {
- int curveflags;
- int subdivisions;
+ int curveflags;
+ int subdivisions;
- float minimum_width;
- float maximum_width;
+ float minimum_width;
+ float maximum_width;
} KernelCurves;
static_assert_align(KernelCurves, 16);
typedef struct KernelTables {
- int beckmann_offset;
- int pad1, pad2, pad3;
+ int beckmann_offset;
+ int pad1, pad2, pad3;
} KernelTables;
static_assert_align(KernelTables, 16);
typedef struct KernelData {
- KernelCamera cam;
- KernelFilm film;
- KernelBackground background;
- KernelIntegrator integrator;
- KernelBVH bvh;
- KernelCurves curve;
- KernelTables tables;
+ KernelCamera cam;
+ KernelFilm film;
+ KernelBackground background;
+ KernelIntegrator integrator;
+ KernelBVH bvh;
+ KernelCurves curve;
+ KernelTables tables;
} KernelData;
static_assert_align(KernelData, 16);
/* Kernel data structures. */
typedef struct KernelObject {
- Transform tfm;
- Transform itfm;
+ Transform tfm;
+ Transform itfm;
- float surface_area;
- float pass_id;
- float random_number;
- int particle_index;
+ float surface_area;
+ float pass_id;
+ float random_number;
+ int particle_index;
- float dupli_generated[3];
- float dupli_uv[2];
+ float dupli_generated[3];
+ float dupli_uv[2];
- int numkeys;
- int numsteps;
- int numverts;
+ int numkeys;
+ int numsteps;
+ int numverts;
- uint patch_map_offset;
- uint attribute_map_offset;
- uint motion_offset;
- uint pad1;
+ uint patch_map_offset;
+ uint attribute_map_offset;
+ uint motion_offset;
+ uint pad1;
- float cryptomatte_object;
- float cryptomatte_asset;
- float pad2, pad3;
+ float cryptomatte_object;
+ float cryptomatte_asset;
+ float pad2, pad3;
} KernelObject;
static_assert_align(KernelObject, 16);
typedef struct KernelSpotLight {
- float radius;
- float invarea;
- float spot_angle;
- float spot_smooth;
- float dir[3];
- float pad;
+ float radius;
+ float invarea;
+ float spot_angle;
+ float spot_smooth;
+ float dir[3];
+ float pad;
} KernelSpotLight;
/* PointLight is SpotLight with only radius and invarea being used. */
typedef struct KernelAreaLight {
- float axisu[3];
- float invarea;
- float axisv[3];
- float pad1;
- float dir[3];
- float pad2;
+ float axisu[3];
+ float invarea;
+ float axisv[3];
+ float pad1;
+ float dir[3];
+ float pad2;
} KernelAreaLight;
typedef struct KernelDistantLight {
- float radius;
- float cosangle;
- float invarea;
- float pad;
+ float radius;
+ float cosangle;
+ float invarea;
+ float pad;
} KernelDistantLight;
typedef struct KernelLight {
- int type;
- float co[3];
- int shader_id;
- int samples;
- float max_bounces;
- float random;
- Transform tfm;
- Transform itfm;
- union {
- KernelSpotLight spot;
- KernelAreaLight area;
- KernelDistantLight distant;
- };
+ int type;
+ float co[3];
+ int shader_id;
+ int samples;
+ float max_bounces;
+ float random;
+ Transform tfm;
+ Transform itfm;
+ union {
+ KernelSpotLight spot;
+ KernelAreaLight area;
+ KernelDistantLight distant;
+ };
} KernelLight;
static_assert_align(KernelLight, 16);
typedef struct KernelLightDistribution {
- float totarea;
- int prim;
- union {
- struct {
- int shader_flag;
- int object_id;
- } mesh_light;
- struct {
- float pad;
- float size;
- } lamp;
- };
+ float totarea;
+ int prim;
+ union {
+ struct {
+ int shader_flag;
+ int object_id;
+ } mesh_light;
+ struct {
+ float pad;
+ float size;
+ } lamp;
+ };
} KernelLightDistribution;
static_assert_align(KernelLightDistribution, 16);
typedef struct KernelParticle {
- int index;
- float age;
- float lifetime;
- float size;
- float4 rotation;
- /* Only xyz are used of the following. float4 instead of float3 are used
- * to ensure consistent padding/alignment across devices. */
- float4 location;
- float4 velocity;
- float4 angular_velocity;
+ int index;
+ float age;
+ float lifetime;
+ float size;
+ float4 rotation;
+ /* Only xyz are used of the following. float4 instead of float3 are used
+ * to ensure consistent padding/alignment across devices. */
+ float4 location;
+ float4 velocity;
+ float4 angular_velocity;
} KernelParticle;
static_assert_align(KernelParticle, 16);
typedef struct KernelShader {
- float constant_emission[3];
- float cryptomatte_id;
- int flags;
- int pass_id;
- int pad2, pad3;
+ float constant_emission[3];
+ float cryptomatte_id;
+ int flags;
+ int pass_id;
+ int pad2, pad3;
} KernelShader;
static_assert_align(KernelShader, 16);
@@ -1545,88 +1521,93 @@ static_assert_align(KernelShader, 16);
/* Queue names */
enum QueueNumber {
- /* All active rays and regenerated rays are enqueued here. */
- QUEUE_ACTIVE_AND_REGENERATED_RAYS = 0,
-
- /* All
- * 1. Background-hit rays,
- * 2. Rays that has exited path-iteration but needs to update output buffer
- * 3. Rays to be regenerated
- * are enqueued here.
- */
- 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,
-
- /* 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,
-
- /* Rays sorted according to shader->id */
- QUEUE_SHADER_SORTED_RAYS,
+ /* All active rays and regenerated rays are enqueued here. */
+ QUEUE_ACTIVE_AND_REGENERATED_RAYS = 0,
+
+ /* All
+ * 1. Background-hit rays,
+ * 2. Rays that has exited path-iteration but needs to update output buffer
+ * 3. Rays to be regenerated
+ * are enqueued here.
+ */
+ 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,
+
+ /* 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,
+
+ /* 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,
- /* Queue of all inactive rays. These are candidates for sharing work of indirect loops */
- QUEUE_INACTIVE_RAYS,
+ /* All rays moving to next iteration of the indirect loop for light */
+ QUEUE_LIGHT_INDIRECT_ITER,
+ /* Queue of all inactive rays. These are candidates for sharing work of indirect loops */
+ QUEUE_INACTIVE_RAYS,
# ifdef __VOLUME__
- /* All rays moving to next iteration of the indirect loop for volumes */
- QUEUE_VOLUME_INDIRECT_ITER,
+ /* 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,
+ /* All rays moving to next iteration of the indirect loop for subsurface */
+ QUEUE_SUBSURFACE_INDIRECT_ITER,
# endif
-#endif /* __BRANCHED_PATH__ */
+#endif /* __BRANCHED_PATH__ */
- NUM_QUEUES
+ NUM_QUEUES
};
/* 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. */
- RAY_ACTIVE,
- /* Denotes ray has completed processing all samples and is inactive. */
- RAY_INACTIVE,
- /* Denotes ray has exited path-iteration and needs to update output buffer. */
- RAY_UPDATE_BUFFER,
- /* Denotes ray needs to skip most surface shader work. */
- RAY_HAS_ONLY_VOLUME,
- /* Donotes ray has hit background */
- RAY_HIT_BACKGROUND,
- /* Denotes ray has to be regenerated */
- RAY_TO_REGENERATE,
- /* Denotes ray has been regenerated */
- RAY_REGENERATED,
- /* 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),
-
- /* Ray is evaluating an iteration of an indirect loop for another thread */
- RAY_BRANCHED_INDIRECT_SHARED = (1 << 7),
+ RAY_INVALID = 0,
+ /* Denotes ray is actively involved in path-iteration. */
+ RAY_ACTIVE,
+ /* Denotes ray has completed processing all samples and is inactive. */
+ RAY_INACTIVE,
+ /* Denotes ray has exited path-iteration and needs to update output buffer. */
+ RAY_UPDATE_BUFFER,
+ /* Denotes ray needs to skip most surface shader work. */
+ RAY_HAS_ONLY_VOLUME,
+ /* Donotes ray has hit background */
+ RAY_HIT_BACKGROUND,
+ /* Denotes ray has to be regenerated */
+ RAY_TO_REGENERATE,
+ /* Denotes ray has been regenerated */
+ RAY_REGENERATED,
+ /* 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),
+
+ /* Ray is evaluating an iteration of an indirect loop for another thread */
+ RAY_BRANCHED_INDIRECT_SHARED = (1 << 7),
};
-#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_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 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_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)
/* Patches */
@@ -1642,17 +1623,17 @@ enum RayState {
/* Work Tiles */
typedef struct WorkTile {
- uint x, y, w, h;
+ uint x, y, w, h;
- uint start_sample;
- uint num_samples;
+ uint start_sample;
+ uint num_samples;
- uint offset;
- uint stride;
+ uint offset;
+ uint stride;
- ccl_global float *buffer;
+ ccl_global float *buffer;
} WorkTile;
CCL_NAMESPACE_END
-#endif /* __KERNEL_TYPES_H__ */
+#endif /* __KERNEL_TYPES_H__ */
diff --git a/intern/cycles/kernel/kernel_volume.h b/intern/cycles/kernel/kernel_volume.h
index 44c8f795d2c..e024003252f 100644
--- a/intern/cycles/kernel/kernel_volume.h
+++ b/intern/cycles/kernel/kernel_volume.h
@@ -19,9 +19,9 @@ CCL_NAMESPACE_BEGIN
/* Events for probalistic scattering */
typedef enum VolumeIntegrateResult {
- VOLUME_PATH_SCATTERED = 0,
- VOLUME_PATH_ATTENUATED = 1,
- VOLUME_PATH_MISSED = 2
+ VOLUME_PATH_SCATTERED = 0,
+ VOLUME_PATH_ATTENUATED = 1,
+ VOLUME_PATH_MISSED = 2
} VolumeIntegrateResult;
/* Volume shader properties
@@ -30,9 +30,9 @@ typedef enum VolumeIntegrateResult {
* sigma_t = sigma_a + sigma_s */
typedef struct VolumeShaderCoefficients {
- float3 sigma_t;
- float3 sigma_s;
- float3 emission;
+ float3 sigma_t;
+ float3 sigma_s;
+ float3 emission;
} VolumeShaderCoefficients;
#ifdef __VOLUME__
@@ -44,16 +44,16 @@ ccl_device_inline bool volume_shader_extinction_sample(KernelGlobals *kg,
float3 P,
float3 *extinction)
{
- sd->P = P;
- shader_eval_volume(kg, sd, state, state->volume_stack, PATH_RAY_SHADOW);
-
- if(sd->flag & SD_EXTINCTION) {
- *extinction = sd->closure_transparent_extinction;
- return true;
- }
- else {
- return false;
- }
+ sd->P = P;
+ shader_eval_volume(kg, sd, state, state->volume_stack, PATH_RAY_SHADOW);
+
+ if (sd->flag & SD_EXTINCTION) {
+ *extinction = sd->closure_transparent_extinction;
+ return true;
+ }
+ else {
+ return false;
+ }
}
/* evaluate shader to get absorption, scattering and emission at P */
@@ -63,97 +63,97 @@ ccl_device_inline bool volume_shader_sample(KernelGlobals *kg,
float3 P,
VolumeShaderCoefficients *coeff)
{
- sd->P = P;
- shader_eval_volume(kg, sd, state, state->volume_stack, state->flag);
+ sd->P = P;
+ shader_eval_volume(kg, sd, state, state->volume_stack, state->flag);
- if(!(sd->flag & (SD_EXTINCTION|SD_SCATTER|SD_EMISSION)))
- return false;
+ if (!(sd->flag & (SD_EXTINCTION | SD_SCATTER | SD_EMISSION)))
+ return false;
- coeff->sigma_s = make_float3(0.0f, 0.0f, 0.0f);
- coeff->sigma_t = (sd->flag & SD_EXTINCTION)? sd->closure_transparent_extinction:
- make_float3(0.0f, 0.0f, 0.0f);
- coeff->emission = (sd->flag & SD_EMISSION)? sd->closure_emission_background:
- make_float3(0.0f, 0.0f, 0.0f);
+ coeff->sigma_s = make_float3(0.0f, 0.0f, 0.0f);
+ coeff->sigma_t = (sd->flag & SD_EXTINCTION) ? sd->closure_transparent_extinction :
+ make_float3(0.0f, 0.0f, 0.0f);
+ coeff->emission = (sd->flag & SD_EMISSION) ? sd->closure_emission_background :
+ make_float3(0.0f, 0.0f, 0.0f);
- if(sd->flag & SD_SCATTER) {
- for(int i = 0; i < sd->num_closure; i++) {
- const ShaderClosure *sc = &sd->closure[i];
+ if (sd->flag & SD_SCATTER) {
+ for (int i = 0; i < sd->num_closure; i++) {
+ const ShaderClosure *sc = &sd->closure[i];
- if(CLOSURE_IS_VOLUME(sc->type))
- coeff->sigma_s += sc->weight;
- }
- }
+ if (CLOSURE_IS_VOLUME(sc->type))
+ coeff->sigma_s += sc->weight;
+ }
+ }
- return true;
+ return true;
}
-#endif /* __VOLUME__ */
+#endif /* __VOLUME__ */
ccl_device float3 volume_color_transmittance(float3 sigma, float t)
{
- return exp3(-sigma * t);
+ return exp3(-sigma * t);
}
ccl_device float kernel_volume_channel_get(float3 value, int channel)
{
- return (channel == 0)? value.x: ((channel == 1)? value.y: value.z);
+ return (channel == 0) ? value.x : ((channel == 1) ? value.y : value.z);
}
#ifdef __VOLUME__
ccl_device bool volume_stack_is_heterogeneous(KernelGlobals *kg, ccl_addr_space VolumeStack *stack)
{
- for(int i = 0; stack[i].shader != SHADER_NONE; i++) {
- int shader_flag = kernel_tex_fetch(__shaders, (stack[i].shader & SHADER_MASK)).flags;
-
- if(shader_flag & SD_HETEROGENEOUS_VOLUME) {
- return true;
- }
- else if(shader_flag & SD_NEED_ATTRIBUTES) {
- /* We want to render world or objects without any volume grids
- * as homogenous, but can only verify this at runtime since other
- * heterogenous volume objects may be using the same shader. */
- int object = stack[i].object;
- if(object != OBJECT_NONE) {
- int object_flag = kernel_tex_fetch(__object_flag, object);
- if(object_flag & SD_OBJECT_HAS_VOLUME_ATTRIBUTES) {
- return true;
- }
- }
- }
- }
-
- return false;
+ for (int i = 0; stack[i].shader != SHADER_NONE; i++) {
+ int shader_flag = kernel_tex_fetch(__shaders, (stack[i].shader & SHADER_MASK)).flags;
+
+ if (shader_flag & SD_HETEROGENEOUS_VOLUME) {
+ return true;
+ }
+ else if (shader_flag & SD_NEED_ATTRIBUTES) {
+ /* We want to render world or objects without any volume grids
+ * as homogenous, but can only verify this at runtime since other
+ * heterogenous volume objects may be using the same shader. */
+ int object = stack[i].object;
+ if (object != OBJECT_NONE) {
+ int object_flag = kernel_tex_fetch(__object_flag, object);
+ if (object_flag & SD_OBJECT_HAS_VOLUME_ATTRIBUTES) {
+ return true;
+ }
+ }
+ }
+ }
+
+ return false;
}
ccl_device int volume_stack_sampling_method(KernelGlobals *kg, VolumeStack *stack)
{
- if(kernel_data.integrator.num_all_lights == 0)
- return 0;
+ if (kernel_data.integrator.num_all_lights == 0)
+ return 0;
- int method = -1;
+ int method = -1;
- for(int i = 0; stack[i].shader != SHADER_NONE; i++) {
- int shader_flag = kernel_tex_fetch(__shaders, (stack[i].shader & SHADER_MASK)).flags;
+ for (int i = 0; stack[i].shader != SHADER_NONE; i++) {
+ int shader_flag = kernel_tex_fetch(__shaders, (stack[i].shader & SHADER_MASK)).flags;
- if(shader_flag & SD_VOLUME_MIS) {
- return SD_VOLUME_MIS;
- }
- else if(shader_flag & SD_VOLUME_EQUIANGULAR) {
- if(method == 0)
- return SD_VOLUME_MIS;
+ if (shader_flag & SD_VOLUME_MIS) {
+ return SD_VOLUME_MIS;
+ }
+ else if (shader_flag & SD_VOLUME_EQUIANGULAR) {
+ if (method == 0)
+ return SD_VOLUME_MIS;
- method = SD_VOLUME_EQUIANGULAR;
- }
- else {
- if(method == SD_VOLUME_EQUIANGULAR)
- return SD_VOLUME_MIS;
+ method = SD_VOLUME_EQUIANGULAR;
+ }
+ else {
+ if (method == SD_VOLUME_EQUIANGULAR)
+ return SD_VOLUME_MIS;
- method = 0;
- }
- }
+ method = 0;
+ }
+ }
- return method;
+ return method;
}
ccl_device_inline void kernel_volume_step_init(KernelGlobals *kg,
@@ -162,16 +162,16 @@ ccl_device_inline void kernel_volume_step_init(KernelGlobals *kg,
float *step_size,
float *step_offset)
{
- const int max_steps = kernel_data.integrator.volume_max_steps;
- float step = min(kernel_data.integrator.volume_step_size, t);
+ const int max_steps = kernel_data.integrator.volume_max_steps;
+ float step = min(kernel_data.integrator.volume_step_size, t);
- /* compute exact steps in advance for malloc */
- if(t > max_steps * step) {
- step = t / (float)max_steps;
- }
+ /* compute exact steps in advance for malloc */
+ if (t > max_steps * step) {
+ step = t / (float)max_steps;
+ }
- *step_size = step;
- *step_offset = path_state_rng_1D_hash(kg, state, 0x1e31d8a4) * step;
+ *step_size = step;
+ *step_offset = path_state_rng_1D_hash(kg, state, 0x1e31d8a4) * step;
}
/* Volume Shadows
@@ -187,10 +187,10 @@ ccl_device void kernel_volume_shadow_homogeneous(KernelGlobals *kg,
ShaderData *sd,
float3 *throughput)
{
- float3 sigma_t;
+ float3 sigma_t;
- if(volume_shader_extinction_sample(kg, sd, state, ray->P, &sigma_t))
- *throughput *= volume_color_transmittance(sigma_t, ray->t);
+ if (volume_shader_extinction_sample(kg, sd, state, ray->P, &sigma_t))
+ *throughput *= volume_color_transmittance(sigma_t, ray->t);
}
/* heterogeneous volume: integrate stepping through the volume until we
@@ -201,57 +201,57 @@ ccl_device void kernel_volume_shadow_heterogeneous(KernelGlobals *kg,
ShaderData *sd,
float3 *throughput)
{
- float3 tp = *throughput;
- const float tp_eps = 1e-6f; /* todo: this is likely not the right value */
-
- /* prepare for stepping */
- int max_steps = kernel_data.integrator.volume_max_steps;
- float step_offset, step_size;
- kernel_volume_step_init(kg, state, ray->t, &step_size, &step_offset);
-
- /* compute extinction at the start */
- float t = 0.0f;
-
- float3 sum = make_float3(0.0f, 0.0f, 0.0f);
-
- for(int i = 0; i < max_steps; i++) {
- /* advance to new position */
- float new_t = min(ray->t, (i+1) * step_size);
-
- /* use random position inside this segment to sample shader, adjust
- * for last step that is shorter than other steps. */
- if(new_t == ray->t) {
- step_offset *= (new_t - t) / step_size;
- }
-
- float3 new_P = ray->P + ray->D * (t + step_offset);
- float3 sigma_t;
-
- /* compute attenuation over segment */
- if(volume_shader_extinction_sample(kg, sd, state, new_P, &sigma_t)) {
- /* Compute expf() only for every Nth step, to save some calculations
- * because exp(a)*exp(b) = exp(a+b), also do a quick tp_eps check then. */
-
- sum += (-sigma_t * (new_t - t));
- if((i & 0x07) == 0) { /* ToDo: Other interval? */
- tp = *throughput * exp3(sum);
-
- /* stop if nearly all light is blocked */
- if(tp.x < tp_eps && tp.y < tp_eps && tp.z < tp_eps)
- break;
- }
- }
-
- /* stop if at the end of the volume */
- t = new_t;
- if(t == ray->t) {
- /* Update throughput in case we haven't done it above */
- tp = *throughput * exp3(sum);
- break;
- }
- }
-
- *throughput = tp;
+ float3 tp = *throughput;
+ const float tp_eps = 1e-6f; /* todo: this is likely not the right value */
+
+ /* prepare for stepping */
+ int max_steps = kernel_data.integrator.volume_max_steps;
+ float step_offset, step_size;
+ kernel_volume_step_init(kg, state, ray->t, &step_size, &step_offset);
+
+ /* compute extinction at the start */
+ float t = 0.0f;
+
+ float3 sum = make_float3(0.0f, 0.0f, 0.0f);
+
+ for (int i = 0; i < max_steps; i++) {
+ /* advance to new position */
+ float new_t = min(ray->t, (i + 1) * step_size);
+
+ /* use random position inside this segment to sample shader, adjust
+ * for last step that is shorter than other steps. */
+ if (new_t == ray->t) {
+ step_offset *= (new_t - t) / step_size;
+ }
+
+ float3 new_P = ray->P + ray->D * (t + step_offset);
+ float3 sigma_t;
+
+ /* compute attenuation over segment */
+ if (volume_shader_extinction_sample(kg, sd, state, new_P, &sigma_t)) {
+ /* Compute expf() only for every Nth step, to save some calculations
+ * because exp(a)*exp(b) = exp(a+b), also do a quick tp_eps check then. */
+
+ sum += (-sigma_t * (new_t - t));
+ if ((i & 0x07) == 0) { /* ToDo: Other interval? */
+ tp = *throughput * exp3(sum);
+
+ /* stop if nearly all light is blocked */
+ if (tp.x < tp_eps && tp.y < tp_eps && tp.z < tp_eps)
+ break;
+ }
+ }
+
+ /* stop if at the end of the volume */
+ t = new_t;
+ if (t == ray->t) {
+ /* Update throughput in case we haven't done it above */
+ tp = *throughput * exp3(sum);
+ break;
+ }
+ }
+
+ *throughput = tp;
}
/* get the volume attenuation over line segment defined by ray, with the
@@ -262,422 +262,433 @@ ccl_device_noinline void kernel_volume_shadow(KernelGlobals *kg,
Ray *ray,
float3 *throughput)
{
- shader_setup_from_volume(kg, shadow_sd, ray);
+ shader_setup_from_volume(kg, shadow_sd, ray);
- if(volume_stack_is_heterogeneous(kg, state->volume_stack))
- kernel_volume_shadow_heterogeneous(kg, state, ray, shadow_sd, throughput);
- else
- kernel_volume_shadow_homogeneous(kg, state, ray, shadow_sd, throughput);
+ if (volume_stack_is_heterogeneous(kg, state->volume_stack))
+ kernel_volume_shadow_heterogeneous(kg, state, ray, shadow_sd, throughput);
+ else
+ kernel_volume_shadow_homogeneous(kg, state, ray, shadow_sd, throughput);
}
-#endif /* __VOLUME__ */
+#endif /* __VOLUME__ */
/* Equi-angular sampling as in:
* "Importance Sampling Techniques for Path Tracing in Participating Media" */
ccl_device float kernel_volume_equiangular_sample(Ray *ray, float3 light_P, float xi, float *pdf)
{
- float t = ray->t;
-
- float delta = dot((light_P - ray->P) , ray->D);
- float D = safe_sqrtf(len_squared(light_P - ray->P) - delta * delta);
- if(UNLIKELY(D == 0.0f)) {
- *pdf = 0.0f;
- return 0.0f;
- }
- float theta_a = -atan2f(delta, D);
- float theta_b = atan2f(t - delta, D);
- float t_ = D * tanf((xi * theta_b) + (1 - xi) * theta_a);
- if(UNLIKELY(theta_b == theta_a)) {
- *pdf = 0.0f;
- return 0.0f;
- }
- *pdf = D / ((theta_b - theta_a) * (D * D + t_ * t_));
-
- return min(t, delta + t_); /* min is only for float precision errors */
+ float t = ray->t;
+
+ float delta = dot((light_P - ray->P), ray->D);
+ float D = safe_sqrtf(len_squared(light_P - ray->P) - delta * delta);
+ if (UNLIKELY(D == 0.0f)) {
+ *pdf = 0.0f;
+ return 0.0f;
+ }
+ float theta_a = -atan2f(delta, D);
+ float theta_b = atan2f(t - delta, D);
+ float t_ = D * tanf((xi * theta_b) + (1 - xi) * theta_a);
+ if (UNLIKELY(theta_b == theta_a)) {
+ *pdf = 0.0f;
+ return 0.0f;
+ }
+ *pdf = D / ((theta_b - theta_a) * (D * D + t_ * t_));
+
+ return min(t, delta + t_); /* min is only for float precision errors */
}
ccl_device float kernel_volume_equiangular_pdf(Ray *ray, float3 light_P, float sample_t)
{
- float delta = dot((light_P - ray->P) , ray->D);
- float D = safe_sqrtf(len_squared(light_P - ray->P) - delta * delta);
- if(UNLIKELY(D == 0.0f)) {
- return 0.0f;
- }
+ float delta = dot((light_P - ray->P), ray->D);
+ float D = safe_sqrtf(len_squared(light_P - ray->P) - delta * delta);
+ if (UNLIKELY(D == 0.0f)) {
+ return 0.0f;
+ }
- float t = ray->t;
- float t_ = sample_t - delta;
+ float t = ray->t;
+ float t_ = sample_t - delta;
- float theta_a = -atan2f(delta, D);
- float theta_b = atan2f(t - delta, D);
- if(UNLIKELY(theta_b == theta_a)) {
- return 0.0f;
- }
+ float theta_a = -atan2f(delta, D);
+ float theta_b = atan2f(t - delta, D);
+ if (UNLIKELY(theta_b == theta_a)) {
+ return 0.0f;
+ }
- float pdf = D / ((theta_b - theta_a) * (D * D + t_ * t_));
+ float pdf = D / ((theta_b - theta_a) * (D * D + t_ * t_));
- return pdf;
+ return pdf;
}
/* Distance sampling */
-ccl_device float kernel_volume_distance_sample(float max_t, float3 sigma_t, int channel, float xi, float3 *transmittance, float3 *pdf)
+ccl_device float kernel_volume_distance_sample(
+ float max_t, float3 sigma_t, int channel, float xi, float3 *transmittance, float3 *pdf)
{
- /* xi is [0, 1[ so log(0) should never happen, division by zero is
- * avoided because sample_sigma_t > 0 when SD_SCATTER is set */
- float sample_sigma_t = kernel_volume_channel_get(sigma_t, channel);
- float3 full_transmittance = volume_color_transmittance(sigma_t, max_t);
- float sample_transmittance = kernel_volume_channel_get(full_transmittance, channel);
+ /* xi is [0, 1[ so log(0) should never happen, division by zero is
+ * avoided because sample_sigma_t > 0 when SD_SCATTER is set */
+ float sample_sigma_t = kernel_volume_channel_get(sigma_t, channel);
+ float3 full_transmittance = volume_color_transmittance(sigma_t, max_t);
+ float sample_transmittance = kernel_volume_channel_get(full_transmittance, channel);
- float sample_t = min(max_t, -logf(1.0f - xi*(1.0f - sample_transmittance))/sample_sigma_t);
+ float sample_t = min(max_t, -logf(1.0f - xi * (1.0f - sample_transmittance)) / sample_sigma_t);
- *transmittance = volume_color_transmittance(sigma_t, sample_t);
- *pdf = safe_divide_color(sigma_t * *transmittance, make_float3(1.0f, 1.0f, 1.0f) - full_transmittance);
+ *transmittance = volume_color_transmittance(sigma_t, sample_t);
+ *pdf = safe_divide_color(sigma_t * *transmittance,
+ make_float3(1.0f, 1.0f, 1.0f) - full_transmittance);
- /* todo: optimization: when taken together with hit/miss decision,
- * the full_transmittance cancels out drops out and xi does not
- * need to be remapped */
+ /* todo: optimization: when taken together with hit/miss decision,
+ * the full_transmittance cancels out drops out and xi does not
+ * need to be remapped */
- return sample_t;
+ return sample_t;
}
ccl_device float3 kernel_volume_distance_pdf(float max_t, float3 sigma_t, float sample_t)
{
- float3 full_transmittance = volume_color_transmittance(sigma_t, max_t);
- float3 transmittance = volume_color_transmittance(sigma_t, sample_t);
+ float3 full_transmittance = volume_color_transmittance(sigma_t, max_t);
+ float3 transmittance = volume_color_transmittance(sigma_t, sample_t);
- return safe_divide_color(sigma_t * transmittance, make_float3(1.0f, 1.0f, 1.0f) - full_transmittance);
+ return safe_divide_color(sigma_t * transmittance,
+ make_float3(1.0f, 1.0f, 1.0f) - full_transmittance);
}
/* Emission */
-ccl_device float3 kernel_volume_emission_integrate(VolumeShaderCoefficients *coeff, int closure_flag, float3 transmittance, float t)
+ccl_device float3 kernel_volume_emission_integrate(VolumeShaderCoefficients *coeff,
+ int closure_flag,
+ float3 transmittance,
+ float t)
{
- /* integral E * exp(-sigma_t * t) from 0 to t = E * (1 - exp(-sigma_t * t))/sigma_t
- * this goes to E * t as sigma_t goes to zero
- *
- * todo: we should use an epsilon to avoid precision issues near zero sigma_t */
- float3 emission = coeff->emission;
-
- if(closure_flag & SD_EXTINCTION) {
- float3 sigma_t = coeff->sigma_t;
-
- emission.x *= (sigma_t.x > 0.0f)? (1.0f - transmittance.x)/sigma_t.x: t;
- emission.y *= (sigma_t.y > 0.0f)? (1.0f - transmittance.y)/sigma_t.y: t;
- emission.z *= (sigma_t.z > 0.0f)? (1.0f - transmittance.z)/sigma_t.z: t;
- }
- else
- emission *= t;
-
- return emission;
+ /* integral E * exp(-sigma_t * t) from 0 to t = E * (1 - exp(-sigma_t * t))/sigma_t
+ * this goes to E * t as sigma_t goes to zero
+ *
+ * todo: we should use an epsilon to avoid precision issues near zero sigma_t */
+ float3 emission = coeff->emission;
+
+ if (closure_flag & SD_EXTINCTION) {
+ float3 sigma_t = coeff->sigma_t;
+
+ emission.x *= (sigma_t.x > 0.0f) ? (1.0f - transmittance.x) / sigma_t.x : t;
+ emission.y *= (sigma_t.y > 0.0f) ? (1.0f - transmittance.y) / sigma_t.y : t;
+ emission.z *= (sigma_t.z > 0.0f) ? (1.0f - transmittance.z) / sigma_t.z : t;
+ }
+ else
+ emission *= t;
+
+ return emission;
}
/* Volume Path */
-ccl_device int kernel_volume_sample_channel(float3 albedo, float3 throughput, float rand, float3 *pdf)
+ccl_device int kernel_volume_sample_channel(float3 albedo,
+ float3 throughput,
+ float rand,
+ float3 *pdf)
{
- /* Sample color channel proportional to throughput and single scattering
- * albedo, to significantly reduce noise with many bounce, following:
- *
- * "Practical and Controllable Subsurface Scattering for Production Path
- * Tracing". Matt Jen-Yuan Chiang, Peter Kutz, Brent Burley. SIGGRAPH 2016. */
- float3 weights = fabs(throughput * albedo);
- float sum_weights = weights.x + weights.y + weights.z;
- float3 weights_pdf;
-
- if(sum_weights > 0.0f) {
- weights_pdf = weights/sum_weights;
- }
- else {
- weights_pdf = make_float3(1.0f/3.0f, 1.0f/3.0f, 1.0f/3.0f);
- }
-
- *pdf = weights_pdf;
-
- /* OpenCL does not support -> on float3, so don't use pdf->x. */
- if(rand < weights_pdf.x) {
- return 0;
- }
- else if(rand < weights_pdf.x + weights_pdf.y) {
- return 1;
- }
- else {
- return 2;
- }
+ /* Sample color channel proportional to throughput and single scattering
+ * albedo, to significantly reduce noise with many bounce, following:
+ *
+ * "Practical and Controllable Subsurface Scattering for Production Path
+ * Tracing". Matt Jen-Yuan Chiang, Peter Kutz, Brent Burley. SIGGRAPH 2016. */
+ float3 weights = fabs(throughput * albedo);
+ float sum_weights = weights.x + weights.y + weights.z;
+ float3 weights_pdf;
+
+ if (sum_weights > 0.0f) {
+ weights_pdf = weights / sum_weights;
+ }
+ else {
+ weights_pdf = make_float3(1.0f / 3.0f, 1.0f / 3.0f, 1.0f / 3.0f);
+ }
+
+ *pdf = weights_pdf;
+
+ /* OpenCL does not support -> on float3, so don't use pdf->x. */
+ if (rand < weights_pdf.x) {
+ return 0;
+ }
+ else if (rand < weights_pdf.x + weights_pdf.y) {
+ return 1;
+ }
+ else {
+ return 2;
+ }
}
#ifdef __VOLUME__
/* homogeneous volume: assume shader evaluation at the start gives
* the volume shading coefficient for the entire line segment */
-ccl_device VolumeIntegrateResult kernel_volume_integrate_homogeneous(
- KernelGlobals *kg,
- ccl_addr_space PathState *state,
- Ray *ray,
- ShaderData *sd,
- PathRadiance *L,
- ccl_addr_space float3 *throughput,
- bool probalistic_scatter)
+ccl_device VolumeIntegrateResult
+kernel_volume_integrate_homogeneous(KernelGlobals *kg,
+ ccl_addr_space PathState *state,
+ Ray *ray,
+ ShaderData *sd,
+ PathRadiance *L,
+ ccl_addr_space float3 *throughput,
+ bool probalistic_scatter)
{
- VolumeShaderCoefficients coeff;
-
- if(!volume_shader_sample(kg, sd, state, ray->P, &coeff))
- return VOLUME_PATH_MISSED;
-
- int closure_flag = sd->flag;
- float t = ray->t;
- float3 new_tp;
-
-#ifdef __VOLUME_SCATTER__
- /* randomly scatter, and if we do t is shortened */
- if(closure_flag & SD_SCATTER) {
- /* Sample channel, use MIS with balance heuristic. */
- float rphase = path_state_rng_1D(kg, state, PRNG_PHASE_CHANNEL);
- float3 albedo = safe_divide_color(coeff.sigma_s, coeff.sigma_t);
- float3 channel_pdf;
- int channel = kernel_volume_sample_channel(albedo, *throughput, rphase, &channel_pdf);
-
- /* decide if we will hit or miss */
- bool scatter = true;
- float xi = path_state_rng_1D(kg, state, PRNG_SCATTER_DISTANCE);
-
- if(probalistic_scatter) {
- float sample_sigma_t = kernel_volume_channel_get(coeff.sigma_t, channel);
- float sample_transmittance = expf(-sample_sigma_t * t);
-
- if(1.0f - xi >= sample_transmittance) {
- scatter = true;
-
- /* rescale random number so we can reuse it */
- xi = 1.0f - (1.0f - xi - sample_transmittance)/(1.0f - sample_transmittance);
-
- }
- else
- scatter = false;
- }
-
- if(scatter) {
- /* scattering */
- float3 pdf;
- float3 transmittance;
- float sample_t;
-
- /* distance sampling */
- sample_t = kernel_volume_distance_sample(ray->t, coeff.sigma_t, channel, xi, &transmittance, &pdf);
-
- /* modify pdf for hit/miss decision */
- if(probalistic_scatter)
- pdf *= make_float3(1.0f, 1.0f, 1.0f) - volume_color_transmittance(coeff.sigma_t, t);
-
- new_tp = *throughput * coeff.sigma_s * transmittance / dot(channel_pdf, pdf);
- t = sample_t;
- }
- else {
- /* no scattering */
- float3 transmittance = volume_color_transmittance(coeff.sigma_t, t);
- float pdf = dot(channel_pdf, transmittance);
- new_tp = *throughput * transmittance / pdf;
- }
- }
- else
-#endif
- if(closure_flag & SD_EXTINCTION) {
- /* absorption only, no sampling needed */
- float3 transmittance = volume_color_transmittance(coeff.sigma_t, t);
- new_tp = *throughput * transmittance;
- }
- else {
- new_tp = *throughput;
- }
-
- /* integrate emission attenuated by extinction */
- if(L && (closure_flag & SD_EMISSION)) {
- float3 transmittance = volume_color_transmittance(coeff.sigma_t, ray->t);
- float3 emission = kernel_volume_emission_integrate(&coeff, closure_flag, transmittance, ray->t);
- path_radiance_accum_emission(L, state, *throughput, emission);
- }
-
- /* modify throughput */
- if(closure_flag & SD_EXTINCTION) {
- *throughput = new_tp;
-
- /* prepare to scatter to new direction */
- if(t < ray->t) {
- /* adjust throughput and move to new location */
- sd->P = ray->P + t*ray->D;
-
- return VOLUME_PATH_SCATTERED;
- }
- }
-
- return VOLUME_PATH_ATTENUATED;
+ VolumeShaderCoefficients coeff;
+
+ if (!volume_shader_sample(kg, sd, state, ray->P, &coeff))
+ return VOLUME_PATH_MISSED;
+
+ int closure_flag = sd->flag;
+ float t = ray->t;
+ float3 new_tp;
+
+# ifdef __VOLUME_SCATTER__
+ /* randomly scatter, and if we do t is shortened */
+ if (closure_flag & SD_SCATTER) {
+ /* Sample channel, use MIS with balance heuristic. */
+ float rphase = path_state_rng_1D(kg, state, PRNG_PHASE_CHANNEL);
+ float3 albedo = safe_divide_color(coeff.sigma_s, coeff.sigma_t);
+ float3 channel_pdf;
+ int channel = kernel_volume_sample_channel(albedo, *throughput, rphase, &channel_pdf);
+
+ /* decide if we will hit or miss */
+ bool scatter = true;
+ float xi = path_state_rng_1D(kg, state, PRNG_SCATTER_DISTANCE);
+
+ if (probalistic_scatter) {
+ float sample_sigma_t = kernel_volume_channel_get(coeff.sigma_t, channel);
+ float sample_transmittance = expf(-sample_sigma_t * t);
+
+ if (1.0f - xi >= sample_transmittance) {
+ scatter = true;
+
+ /* rescale random number so we can reuse it */
+ xi = 1.0f - (1.0f - xi - sample_transmittance) / (1.0f - sample_transmittance);
+ }
+ else
+ scatter = false;
+ }
+
+ if (scatter) {
+ /* scattering */
+ float3 pdf;
+ float3 transmittance;
+ float sample_t;
+
+ /* distance sampling */
+ sample_t = kernel_volume_distance_sample(
+ ray->t, coeff.sigma_t, channel, xi, &transmittance, &pdf);
+
+ /* modify pdf for hit/miss decision */
+ if (probalistic_scatter)
+ pdf *= make_float3(1.0f, 1.0f, 1.0f) - volume_color_transmittance(coeff.sigma_t, t);
+
+ new_tp = *throughput * coeff.sigma_s * transmittance / dot(channel_pdf, pdf);
+ t = sample_t;
+ }
+ else {
+ /* no scattering */
+ float3 transmittance = volume_color_transmittance(coeff.sigma_t, t);
+ float pdf = dot(channel_pdf, transmittance);
+ new_tp = *throughput * transmittance / pdf;
+ }
+ }
+ else
+# endif
+ if (closure_flag & SD_EXTINCTION) {
+ /* absorption only, no sampling needed */
+ float3 transmittance = volume_color_transmittance(coeff.sigma_t, t);
+ new_tp = *throughput * transmittance;
+ }
+ else {
+ new_tp = *throughput;
+ }
+
+ /* integrate emission attenuated by extinction */
+ if (L && (closure_flag & SD_EMISSION)) {
+ float3 transmittance = volume_color_transmittance(coeff.sigma_t, ray->t);
+ float3 emission = kernel_volume_emission_integrate(
+ &coeff, closure_flag, transmittance, ray->t);
+ path_radiance_accum_emission(L, state, *throughput, emission);
+ }
+
+ /* modify throughput */
+ if (closure_flag & SD_EXTINCTION) {
+ *throughput = new_tp;
+
+ /* prepare to scatter to new direction */
+ if (t < ray->t) {
+ /* adjust throughput and move to new location */
+ sd->P = ray->P + t * ray->D;
+
+ return VOLUME_PATH_SCATTERED;
+ }
+ }
+
+ return VOLUME_PATH_ATTENUATED;
}
/* heterogeneous volume distance sampling: integrate stepping through the
* volume until we reach the end, get absorbed entirely, or run out of
* iterations. this does probabilistically scatter or get transmitted through
* for path tracing where we don't want to branch. */
-ccl_device VolumeIntegrateResult kernel_volume_integrate_heterogeneous_distance(
- KernelGlobals *kg,
- ccl_addr_space PathState *state,
- Ray *ray,
- ShaderData *sd,
- PathRadiance *L,
- ccl_addr_space float3 *throughput)
+ccl_device VolumeIntegrateResult
+kernel_volume_integrate_heterogeneous_distance(KernelGlobals *kg,
+ ccl_addr_space PathState *state,
+ Ray *ray,
+ ShaderData *sd,
+ PathRadiance *L,
+ ccl_addr_space float3 *throughput)
{
- float3 tp = *throughput;
- const float tp_eps = 1e-6f; /* todo: this is likely not the right value */
-
- /* prepare for stepping */
- int max_steps = kernel_data.integrator.volume_max_steps;
- float step_offset, step_size;
- kernel_volume_step_init(kg, state, ray->t, &step_size, &step_offset);
-
- /* compute coefficients at the start */
- float t = 0.0f;
- float3 accum_transmittance = make_float3(1.0f, 1.0f, 1.0f);
-
- /* pick random color channel, we use the Veach one-sample
- * model with balance heuristic for the channels */
- float xi = path_state_rng_1D(kg, state, PRNG_SCATTER_DISTANCE);
- float rphase = path_state_rng_1D(kg, state, PRNG_PHASE_CHANNEL);
- bool has_scatter = false;
-
- for(int i = 0; i < max_steps; i++) {
- /* advance to new position */
- float new_t = min(ray->t, (i+1) * step_size);
- float dt = new_t - t;
-
- /* use random position inside this segment to sample shader,
- * for last shorter step we remap it to fit within the segment. */
- if(new_t == ray->t) {
- step_offset *= (new_t - t) / step_size;
- }
-
- float3 new_P = ray->P + ray->D * (t + step_offset);
- VolumeShaderCoefficients coeff;
-
- /* compute segment */
- if(volume_shader_sample(kg, sd, state, new_P, &coeff)) {
- int closure_flag = sd->flag;
- float3 new_tp;
- float3 transmittance;
- bool scatter = false;
-
- /* distance sampling */
-#ifdef __VOLUME_SCATTER__
- if((closure_flag & SD_SCATTER) || (has_scatter && (closure_flag & SD_EXTINCTION))) {
- has_scatter = true;
-
- /* Sample channel, use MIS with balance heuristic. */
- float3 albedo = safe_divide_color(coeff.sigma_s, coeff.sigma_t);
- float3 channel_pdf;
- int channel = kernel_volume_sample_channel(albedo, tp, rphase, &channel_pdf);
-
- /* compute transmittance over full step */
- transmittance = volume_color_transmittance(coeff.sigma_t, dt);
-
- /* decide if we will scatter or continue */
- float sample_transmittance = kernel_volume_channel_get(transmittance, channel);
-
- if(1.0f - xi >= sample_transmittance) {
- /* compute sampling distance */
- float sample_sigma_t = kernel_volume_channel_get(coeff.sigma_t, channel);
- float new_dt = -logf(1.0f - xi)/sample_sigma_t;
- new_t = t + new_dt;
-
- /* transmittance and pdf */
- float3 new_transmittance = volume_color_transmittance(coeff.sigma_t, new_dt);
- float3 pdf = coeff.sigma_t * new_transmittance;
-
- /* throughput */
- new_tp = tp * coeff.sigma_s * new_transmittance / dot(channel_pdf, pdf);
- scatter = true;
- }
- else {
- /* throughput */
- float pdf = dot(channel_pdf, transmittance);
- new_tp = tp * transmittance / pdf;
-
- /* remap xi so we can reuse it and keep thing stratified */
- xi = 1.0f - (1.0f - xi)/sample_transmittance;
- }
- }
- else
-#endif
- if(closure_flag & SD_EXTINCTION) {
- /* absorption only, no sampling needed */
- transmittance = volume_color_transmittance(coeff.sigma_t, dt);
- new_tp = tp * transmittance;
- }
- else {
- new_tp = tp;
- }
-
- /* integrate emission attenuated by absorption */
- if(L && (closure_flag & SD_EMISSION)) {
- float3 emission = kernel_volume_emission_integrate(&coeff, closure_flag, transmittance, dt);
- path_radiance_accum_emission(L, state, tp, emission);
- }
-
- /* modify throughput */
- if(closure_flag & SD_EXTINCTION) {
- tp = new_tp;
-
- /* stop if nearly all light blocked */
- if(tp.x < tp_eps && tp.y < tp_eps && tp.z < tp_eps) {
- tp = make_float3(0.0f, 0.0f, 0.0f);
- break;
- }
- }
-
- /* prepare to scatter to new direction */
- if(scatter) {
- /* adjust throughput and move to new location */
- sd->P = ray->P + new_t*ray->D;
- *throughput = tp;
-
- return VOLUME_PATH_SCATTERED;
- }
- else {
- /* accumulate transmittance */
- accum_transmittance *= transmittance;
- }
- }
-
- /* stop if at the end of the volume */
- t = new_t;
- if(t == ray->t)
- break;
- }
-
- *throughput = tp;
-
- return VOLUME_PATH_ATTENUATED;
+ float3 tp = *throughput;
+ const float tp_eps = 1e-6f; /* todo: this is likely not the right value */
+
+ /* prepare for stepping */
+ int max_steps = kernel_data.integrator.volume_max_steps;
+ float step_offset, step_size;
+ kernel_volume_step_init(kg, state, ray->t, &step_size, &step_offset);
+
+ /* compute coefficients at the start */
+ float t = 0.0f;
+ float3 accum_transmittance = make_float3(1.0f, 1.0f, 1.0f);
+
+ /* pick random color channel, we use the Veach one-sample
+ * model with balance heuristic for the channels */
+ float xi = path_state_rng_1D(kg, state, PRNG_SCATTER_DISTANCE);
+ float rphase = path_state_rng_1D(kg, state, PRNG_PHASE_CHANNEL);
+ bool has_scatter = false;
+
+ for (int i = 0; i < max_steps; i++) {
+ /* advance to new position */
+ float new_t = min(ray->t, (i + 1) * step_size);
+ float dt = new_t - t;
+
+ /* use random position inside this segment to sample shader,
+ * for last shorter step we remap it to fit within the segment. */
+ if (new_t == ray->t) {
+ step_offset *= (new_t - t) / step_size;
+ }
+
+ float3 new_P = ray->P + ray->D * (t + step_offset);
+ VolumeShaderCoefficients coeff;
+
+ /* compute segment */
+ if (volume_shader_sample(kg, sd, state, new_P, &coeff)) {
+ int closure_flag = sd->flag;
+ float3 new_tp;
+ float3 transmittance;
+ bool scatter = false;
+
+ /* distance sampling */
+# ifdef __VOLUME_SCATTER__
+ if ((closure_flag & SD_SCATTER) || (has_scatter && (closure_flag & SD_EXTINCTION))) {
+ has_scatter = true;
+
+ /* Sample channel, use MIS with balance heuristic. */
+ float3 albedo = safe_divide_color(coeff.sigma_s, coeff.sigma_t);
+ float3 channel_pdf;
+ int channel = kernel_volume_sample_channel(albedo, tp, rphase, &channel_pdf);
+
+ /* compute transmittance over full step */
+ transmittance = volume_color_transmittance(coeff.sigma_t, dt);
+
+ /* decide if we will scatter or continue */
+ float sample_transmittance = kernel_volume_channel_get(transmittance, channel);
+
+ if (1.0f - xi >= sample_transmittance) {
+ /* compute sampling distance */
+ float sample_sigma_t = kernel_volume_channel_get(coeff.sigma_t, channel);
+ float new_dt = -logf(1.0f - xi) / sample_sigma_t;
+ new_t = t + new_dt;
+
+ /* transmittance and pdf */
+ float3 new_transmittance = volume_color_transmittance(coeff.sigma_t, new_dt);
+ float3 pdf = coeff.sigma_t * new_transmittance;
+
+ /* throughput */
+ new_tp = tp * coeff.sigma_s * new_transmittance / dot(channel_pdf, pdf);
+ scatter = true;
+ }
+ else {
+ /* throughput */
+ float pdf = dot(channel_pdf, transmittance);
+ new_tp = tp * transmittance / pdf;
+
+ /* remap xi so we can reuse it and keep thing stratified */
+ xi = 1.0f - (1.0f - xi) / sample_transmittance;
+ }
+ }
+ else
+# endif
+ if (closure_flag & SD_EXTINCTION) {
+ /* absorption only, no sampling needed */
+ transmittance = volume_color_transmittance(coeff.sigma_t, dt);
+ new_tp = tp * transmittance;
+ }
+ else {
+ new_tp = tp;
+ }
+
+ /* integrate emission attenuated by absorption */
+ if (L && (closure_flag & SD_EMISSION)) {
+ float3 emission = kernel_volume_emission_integrate(
+ &coeff, closure_flag, transmittance, dt);
+ path_radiance_accum_emission(L, state, tp, emission);
+ }
+
+ /* modify throughput */
+ if (closure_flag & SD_EXTINCTION) {
+ tp = new_tp;
+
+ /* stop if nearly all light blocked */
+ if (tp.x < tp_eps && tp.y < tp_eps && tp.z < tp_eps) {
+ tp = make_float3(0.0f, 0.0f, 0.0f);
+ break;
+ }
+ }
+
+ /* prepare to scatter to new direction */
+ if (scatter) {
+ /* adjust throughput and move to new location */
+ sd->P = ray->P + new_t * ray->D;
+ *throughput = tp;
+
+ return VOLUME_PATH_SCATTERED;
+ }
+ else {
+ /* accumulate transmittance */
+ accum_transmittance *= transmittance;
+ }
+ }
+
+ /* stop if at the end of the volume */
+ t = new_t;
+ if (t == ray->t)
+ break;
+ }
+
+ *throughput = tp;
+
+ return VOLUME_PATH_ATTENUATED;
}
/* get the volume attenuation and emission over line segment defined by
* ray, with the assumption that there are no surfaces blocking light
* between the endpoints. distance sampling is used to decide if we will
* scatter or not. */
-ccl_device_noinline VolumeIntegrateResult kernel_volume_integrate(
- KernelGlobals *kg,
- ccl_addr_space PathState *state,
- ShaderData *sd,
- Ray *ray,
- PathRadiance *L,
- ccl_addr_space float3 *throughput,
- bool heterogeneous)
+ccl_device_noinline VolumeIntegrateResult
+kernel_volume_integrate(KernelGlobals *kg,
+ ccl_addr_space PathState *state,
+ ShaderData *sd,
+ Ray *ray,
+ PathRadiance *L,
+ ccl_addr_space float3 *throughput,
+ bool heterogeneous)
{
- shader_setup_from_volume(kg, sd, ray);
+ shader_setup_from_volume(kg, sd, ray);
- if(heterogeneous)
- return kernel_volume_integrate_heterogeneous_distance(kg, state, ray, sd, L, throughput);
- else
- return kernel_volume_integrate_homogeneous(kg, state, ray, sd, L, throughput, true);
+ if (heterogeneous)
+ return kernel_volume_integrate_heterogeneous_distance(kg, state, ray, sd, L, throughput);
+ else
+ return kernel_volume_integrate_homogeneous(kg, state, ray, sd, L, throughput, true);
}
-#ifndef __SPLIT_KERNEL__
+# ifndef __SPLIT_KERNEL__
/* Decoupled Volume Sampling
*
* VolumeSegment is list of coefficients and transmittance stored at all steps
@@ -689,26 +700,26 @@ ccl_device_noinline VolumeIntegrateResult kernel_volume_integrate(
* no support for malloc/free and too much stack usage with a fix size array. */
typedef struct VolumeStep {
- float3 sigma_s; /* scatter coefficient */
- float3 sigma_t; /* extinction coefficient */
- float3 accum_transmittance; /* accumulated transmittance including this step */
- float3 cdf_distance; /* cumulative density function for distance sampling */
- float t; /* distance at end of this step */
- float shade_t; /* jittered distance where shading was done in step */
- int closure_flag; /* shader evaluation closure flags */
+ float3 sigma_s; /* scatter coefficient */
+ float3 sigma_t; /* extinction coefficient */
+ float3 accum_transmittance; /* accumulated transmittance including this step */
+ float3 cdf_distance; /* cumulative density function for distance sampling */
+ float t; /* distance at end of this step */
+ float shade_t; /* jittered distance where shading was done in step */
+ int closure_flag; /* shader evaluation closure flags */
} VolumeStep;
typedef struct VolumeSegment {
- VolumeStep stack_step; /* stack storage for homogeneous step, to avoid malloc */
- VolumeStep *steps; /* recorded steps */
- int numsteps; /* number of steps */
- int closure_flag; /* accumulated closure flags from all steps */
+ VolumeStep stack_step; /* stack storage for homogeneous step, to avoid malloc */
+ VolumeStep *steps; /* recorded steps */
+ int numsteps; /* number of steps */
+ int closure_flag; /* accumulated closure flags from all steps */
- float3 accum_emission; /* accumulated emission at end of segment */
- float3 accum_transmittance; /* accumulated transmittance at end of segment */
- float3 accum_albedo; /* accumulated average albedo over segment */
+ float3 accum_emission; /* accumulated emission at end of segment */
+ float3 accum_transmittance; /* accumulated transmittance at end of segment */
+ float3 accum_albedo; /* accumulated average albedo over segment */
- int sampling_method; /* volume sampling method */
+ int sampling_method; /* volume sampling method */
} VolumeSegment;
/* record volume steps to the end of the volume.
@@ -717,400 +728,412 @@ typedef struct VolumeSegment {
* but the entire segment is needed to do always scattering, rather than probabilistically
* hitting or missing the volume. if we don't know the transmittance at the end of the
* volume we can't generate stratified distance samples up to that transmittance */
-#ifdef __VOLUME_DECOUPLED__
-ccl_device void kernel_volume_decoupled_record(KernelGlobals *kg, PathState *state,
- Ray *ray, ShaderData *sd, VolumeSegment *segment, bool heterogeneous)
+# ifdef __VOLUME_DECOUPLED__
+ccl_device void kernel_volume_decoupled_record(KernelGlobals *kg,
+ PathState *state,
+ Ray *ray,
+ ShaderData *sd,
+ VolumeSegment *segment,
+ bool heterogeneous)
{
- const float tp_eps = 1e-6f; /* todo: this is likely not the right value */
-
- /* prepare for volume stepping */
- int max_steps;
- float step_size, step_offset;
-
- if(heterogeneous) {
- max_steps = kernel_data.integrator.volume_max_steps;
- kernel_volume_step_init(kg, state, ray->t, &step_size, &step_offset);
-
-#ifdef __KERNEL_CPU__
- /* NOTE: For the branched path tracing it's possible to have direct
- * and indirect light integration both having volume segments allocated.
- * We detect this using index in the pre-allocated memory. Currently we
- * only support two segments allocated at a time, if more needed some
- * modifications to the KernelGlobals will be needed.
- *
- * This gives us restrictions that decoupled record should only happen
- * in the stack manner, meaning if there's subsequent call of decoupled
- * record it'll need to free memory before it's caller frees memory.
- */
- const int index = kg->decoupled_volume_steps_index;
- assert(index < sizeof(kg->decoupled_volume_steps) /
- sizeof(*kg->decoupled_volume_steps));
- if(kg->decoupled_volume_steps[index] == NULL) {
- kg->decoupled_volume_steps[index] =
- (VolumeStep*)malloc(sizeof(VolumeStep)*max_steps);
- }
- segment->steps = kg->decoupled_volume_steps[index];
- ++kg->decoupled_volume_steps_index;
-#else
- segment->steps = (VolumeStep*)malloc(sizeof(VolumeStep)*max_steps);
-#endif
- }
- else {
- max_steps = 1;
- step_size = ray->t;
- step_offset = 0.0f;
- segment->steps = &segment->stack_step;
- }
-
- /* init accumulation variables */
- float3 accum_emission = make_float3(0.0f, 0.0f, 0.0f);
- float3 accum_transmittance = make_float3(1.0f, 1.0f, 1.0f);
- float3 accum_albedo = make_float3(0.0f, 0.0f, 0.0f);
- float3 cdf_distance = make_float3(0.0f, 0.0f, 0.0f);
- float t = 0.0f;
-
- segment->numsteps = 0;
- segment->closure_flag = 0;
- bool is_last_step_empty = false;
-
- VolumeStep *step = segment->steps;
-
- for(int i = 0; i < max_steps; i++, step++) {
- /* advance to new position */
- float new_t = min(ray->t, (i+1) * step_size);
- float dt = new_t - t;
-
- /* use random position inside this segment to sample shader,
- * for last shorter step we remap it to fit within the segment. */
- if(new_t == ray->t) {
- step_offset *= (new_t - t) / step_size;
- }
-
- float3 new_P = ray->P + ray->D * (t + step_offset);
- VolumeShaderCoefficients coeff;
-
- /* compute segment */
- if(volume_shader_sample(kg, sd, state, new_P, &coeff)) {
- int closure_flag = sd->flag;
- float3 sigma_t = coeff.sigma_t;
-
- /* compute average albedo for channel sampling */
- if(closure_flag & SD_SCATTER) {
- accum_albedo += dt * safe_divide_color(coeff.sigma_s, sigma_t);
- }
-
- /* compute accumulated transmittance */
- float3 transmittance = volume_color_transmittance(sigma_t, dt);
-
- /* compute emission attenuated by absorption */
- if(closure_flag & SD_EMISSION) {
- float3 emission = kernel_volume_emission_integrate(&coeff, closure_flag, transmittance, dt);
- accum_emission += accum_transmittance * emission;
- }
-
- accum_transmittance *= transmittance;
-
- /* compute pdf for distance sampling */
- float3 pdf_distance = dt * accum_transmittance * coeff.sigma_s;
- cdf_distance = cdf_distance + pdf_distance;
-
- /* write step data */
- step->sigma_t = sigma_t;
- step->sigma_s = coeff.sigma_s;
- step->closure_flag = closure_flag;
-
- segment->closure_flag |= closure_flag;
-
- is_last_step_empty = false;
- segment->numsteps++;
- }
- else {
- if(is_last_step_empty) {
- /* consecutive empty step, merge */
- step--;
- }
- else {
- /* store empty step */
- step->sigma_t = make_float3(0.0f, 0.0f, 0.0f);
- step->sigma_s = make_float3(0.0f, 0.0f, 0.0f);
- step->closure_flag = 0;
-
- segment->numsteps++;
- is_last_step_empty = true;
- }
- }
-
- step->accum_transmittance = accum_transmittance;
- step->cdf_distance = cdf_distance;
- step->t = new_t;
- step->shade_t = t + step_offset;
-
- /* stop if at the end of the volume */
- t = new_t;
- if(t == ray->t)
- break;
-
- /* stop if nearly all light blocked */
- if(accum_transmittance.x < tp_eps && accum_transmittance.y < tp_eps && accum_transmittance.z < tp_eps)
- break;
- }
-
- /* store total emission and transmittance */
- segment->accum_emission = accum_emission;
- segment->accum_transmittance = accum_transmittance;
- segment->accum_albedo = accum_albedo;
-
- /* normalize cumulative density function for distance sampling */
- VolumeStep *last_step = segment->steps + segment->numsteps - 1;
-
- if(!is_zero(last_step->cdf_distance)) {
- VolumeStep *step = &segment->steps[0];
- int numsteps = segment->numsteps;
- float3 inv_cdf_distance_sum = safe_invert_color(last_step->cdf_distance);
-
- for(int i = 0; i < numsteps; i++, step++)
- step->cdf_distance *= inv_cdf_distance_sum;
- }
+ const float tp_eps = 1e-6f; /* todo: this is likely not the right value */
+
+ /* prepare for volume stepping */
+ int max_steps;
+ float step_size, step_offset;
+
+ if (heterogeneous) {
+ max_steps = kernel_data.integrator.volume_max_steps;
+ kernel_volume_step_init(kg, state, ray->t, &step_size, &step_offset);
+
+# ifdef __KERNEL_CPU__
+ /* NOTE: For the branched path tracing it's possible to have direct
+ * and indirect light integration both having volume segments allocated.
+ * We detect this using index in the pre-allocated memory. Currently we
+ * only support two segments allocated at a time, if more needed some
+ * modifications to the KernelGlobals will be needed.
+ *
+ * This gives us restrictions that decoupled record should only happen
+ * in the stack manner, meaning if there's subsequent call of decoupled
+ * record it'll need to free memory before it's caller frees memory.
+ */
+ const int index = kg->decoupled_volume_steps_index;
+ assert(index < sizeof(kg->decoupled_volume_steps) / sizeof(*kg->decoupled_volume_steps));
+ if (kg->decoupled_volume_steps[index] == NULL) {
+ kg->decoupled_volume_steps[index] = (VolumeStep *)malloc(sizeof(VolumeStep) * max_steps);
+ }
+ segment->steps = kg->decoupled_volume_steps[index];
+ ++kg->decoupled_volume_steps_index;
+# else
+ segment->steps = (VolumeStep *)malloc(sizeof(VolumeStep) * max_steps);
+# endif
+ }
+ else {
+ max_steps = 1;
+ step_size = ray->t;
+ step_offset = 0.0f;
+ segment->steps = &segment->stack_step;
+ }
+
+ /* init accumulation variables */
+ float3 accum_emission = make_float3(0.0f, 0.0f, 0.0f);
+ float3 accum_transmittance = make_float3(1.0f, 1.0f, 1.0f);
+ float3 accum_albedo = make_float3(0.0f, 0.0f, 0.0f);
+ float3 cdf_distance = make_float3(0.0f, 0.0f, 0.0f);
+ float t = 0.0f;
+
+ segment->numsteps = 0;
+ segment->closure_flag = 0;
+ bool is_last_step_empty = false;
+
+ VolumeStep *step = segment->steps;
+
+ for (int i = 0; i < max_steps; i++, step++) {
+ /* advance to new position */
+ float new_t = min(ray->t, (i + 1) * step_size);
+ float dt = new_t - t;
+
+ /* use random position inside this segment to sample shader,
+ * for last shorter step we remap it to fit within the segment. */
+ if (new_t == ray->t) {
+ step_offset *= (new_t - t) / step_size;
+ }
+
+ float3 new_P = ray->P + ray->D * (t + step_offset);
+ VolumeShaderCoefficients coeff;
+
+ /* compute segment */
+ if (volume_shader_sample(kg, sd, state, new_P, &coeff)) {
+ int closure_flag = sd->flag;
+ float3 sigma_t = coeff.sigma_t;
+
+ /* compute average albedo for channel sampling */
+ if (closure_flag & SD_SCATTER) {
+ accum_albedo += dt * safe_divide_color(coeff.sigma_s, sigma_t);
+ }
+
+ /* compute accumulated transmittance */
+ float3 transmittance = volume_color_transmittance(sigma_t, dt);
+
+ /* compute emission attenuated by absorption */
+ if (closure_flag & SD_EMISSION) {
+ float3 emission = kernel_volume_emission_integrate(
+ &coeff, closure_flag, transmittance, dt);
+ accum_emission += accum_transmittance * emission;
+ }
+
+ accum_transmittance *= transmittance;
+
+ /* compute pdf for distance sampling */
+ float3 pdf_distance = dt * accum_transmittance * coeff.sigma_s;
+ cdf_distance = cdf_distance + pdf_distance;
+
+ /* write step data */
+ step->sigma_t = sigma_t;
+ step->sigma_s = coeff.sigma_s;
+ step->closure_flag = closure_flag;
+
+ segment->closure_flag |= closure_flag;
+
+ is_last_step_empty = false;
+ segment->numsteps++;
+ }
+ else {
+ if (is_last_step_empty) {
+ /* consecutive empty step, merge */
+ step--;
+ }
+ else {
+ /* store empty step */
+ step->sigma_t = make_float3(0.0f, 0.0f, 0.0f);
+ step->sigma_s = make_float3(0.0f, 0.0f, 0.0f);
+ step->closure_flag = 0;
+
+ segment->numsteps++;
+ is_last_step_empty = true;
+ }
+ }
+
+ step->accum_transmittance = accum_transmittance;
+ step->cdf_distance = cdf_distance;
+ step->t = new_t;
+ step->shade_t = t + step_offset;
+
+ /* stop if at the end of the volume */
+ t = new_t;
+ if (t == ray->t)
+ break;
+
+ /* stop if nearly all light blocked */
+ if (accum_transmittance.x < tp_eps && accum_transmittance.y < tp_eps &&
+ accum_transmittance.z < tp_eps)
+ break;
+ }
+
+ /* store total emission and transmittance */
+ segment->accum_emission = accum_emission;
+ segment->accum_transmittance = accum_transmittance;
+ segment->accum_albedo = accum_albedo;
+
+ /* normalize cumulative density function for distance sampling */
+ VolumeStep *last_step = segment->steps + segment->numsteps - 1;
+
+ if (!is_zero(last_step->cdf_distance)) {
+ VolumeStep *step = &segment->steps[0];
+ int numsteps = segment->numsteps;
+ float3 inv_cdf_distance_sum = safe_invert_color(last_step->cdf_distance);
+
+ for (int i = 0; i < numsteps; i++, step++)
+ step->cdf_distance *= inv_cdf_distance_sum;
+ }
}
ccl_device void kernel_volume_decoupled_free(KernelGlobals *kg, VolumeSegment *segment)
{
- if(segment->steps != &segment->stack_step) {
-#ifdef __KERNEL_CPU__
- /* NOTE: We only allow free last allocated segment.
- * No random order of alloc/free is supported.
- */
- assert(kg->decoupled_volume_steps_index > 0);
- assert(segment->steps == kg->decoupled_volume_steps[kg->decoupled_volume_steps_index - 1]);
- --kg->decoupled_volume_steps_index;
-#else
- free(segment->steps);
-#endif
- }
+ if (segment->steps != &segment->stack_step) {
+# ifdef __KERNEL_CPU__
+ /* NOTE: We only allow free last allocated segment.
+ * No random order of alloc/free is supported.
+ */
+ assert(kg->decoupled_volume_steps_index > 0);
+ assert(segment->steps == kg->decoupled_volume_steps[kg->decoupled_volume_steps_index - 1]);
+ --kg->decoupled_volume_steps_index;
+# else
+ free(segment->steps);
+# endif
+ }
}
-#endif /* __VOLUME_DECOUPLED__ */
+# endif /* __VOLUME_DECOUPLED__ */
/* scattering for homogeneous and heterogeneous volumes, using decoupled ray
* marching.
*
* function is expected to return VOLUME_PATH_SCATTERED when probalistic_scatter is false */
-ccl_device VolumeIntegrateResult kernel_volume_decoupled_scatter(
- KernelGlobals *kg, PathState *state, Ray *ray, ShaderData *sd,
- float3 *throughput, float rphase, float rscatter,
- const VolumeSegment *segment, const float3 *light_P, bool probalistic_scatter)
+ccl_device VolumeIntegrateResult kernel_volume_decoupled_scatter(KernelGlobals *kg,
+ PathState *state,
+ Ray *ray,
+ ShaderData *sd,
+ float3 *throughput,
+ float rphase,
+ float rscatter,
+ const VolumeSegment *segment,
+ const float3 *light_P,
+ bool probalistic_scatter)
{
- kernel_assert(segment->closure_flag & SD_SCATTER);
-
- /* Sample color channel, use MIS with balance heuristic. */
- float3 channel_pdf;
- int channel = kernel_volume_sample_channel(segment->accum_albedo,
- *throughput,
- rphase,
- &channel_pdf);
-
- float xi = rscatter;
-
- /* probabilistic scattering decision based on transmittance */
- if(probalistic_scatter) {
- float sample_transmittance = kernel_volume_channel_get(segment->accum_transmittance, channel);
-
- if(1.0f - xi >= sample_transmittance) {
- /* rescale random number so we can reuse it */
- xi = 1.0f - (1.0f - xi - sample_transmittance)/(1.0f - sample_transmittance);
- }
- else {
- *throughput /= sample_transmittance;
- return VOLUME_PATH_MISSED;
- }
- }
-
- VolumeStep *step;
- float3 transmittance;
- float pdf, sample_t;
- float mis_weight = 1.0f;
- bool distance_sample = true;
- bool use_mis = false;
-
- if(segment->sampling_method && light_P) {
- if(segment->sampling_method == SD_VOLUME_MIS) {
- /* multiple importance sample: randomly pick between
- * equiangular and distance sampling strategy */
- if(xi < 0.5f) {
- xi *= 2.0f;
- }
- else {
- xi = (xi - 0.5f)*2.0f;
- distance_sample = false;
- }
-
- use_mis = true;
- }
- else {
- /* only equiangular sampling */
- distance_sample = false;
- }
- }
-
- /* distance sampling */
- if(distance_sample) {
- /* find step in cdf */
- step = segment->steps;
-
- float prev_t = 0.0f;
- float3 step_pdf_distance = make_float3(1.0f, 1.0f, 1.0f);
-
- if(segment->numsteps > 1) {
- float prev_cdf = 0.0f;
- float step_cdf = 1.0f;
- float3 prev_cdf_distance = make_float3(0.0f, 0.0f, 0.0f);
-
- for(int i = 0; ; i++, step++) {
- /* todo: optimize using binary search */
- step_cdf = kernel_volume_channel_get(step->cdf_distance, channel);
-
- if(xi < step_cdf || i == segment->numsteps-1)
- break;
-
- prev_cdf = step_cdf;
- prev_t = step->t;
- prev_cdf_distance = step->cdf_distance;
- }
-
- /* remap xi so we can reuse it */
- xi = (xi - prev_cdf)/(step_cdf - prev_cdf);
-
- /* pdf for picking step */
- step_pdf_distance = step->cdf_distance - prev_cdf_distance;
- }
-
- /* determine range in which we will sample */
- float step_t = step->t - prev_t;
-
- /* sample distance and compute transmittance */
- float3 distance_pdf;
- sample_t = prev_t + kernel_volume_distance_sample(step_t, step->sigma_t, channel, xi, &transmittance, &distance_pdf);
-
- /* modify pdf for hit/miss decision */
- if(probalistic_scatter)
- distance_pdf *= make_float3(1.0f, 1.0f, 1.0f) - segment->accum_transmittance;
-
- pdf = dot(channel_pdf, distance_pdf * step_pdf_distance);
-
- /* multiple importance sampling */
- if(use_mis) {
- float equi_pdf = kernel_volume_equiangular_pdf(ray, *light_P, sample_t);
- mis_weight = 2.0f*power_heuristic(pdf, equi_pdf);
- }
- }
- /* equi-angular sampling */
- else {
- /* sample distance */
- sample_t = kernel_volume_equiangular_sample(ray, *light_P, xi, &pdf);
-
- /* find step in which sampled distance is located */
- step = segment->steps;
-
- float prev_t = 0.0f;
- float3 step_pdf_distance = make_float3(1.0f, 1.0f, 1.0f);
-
- if(segment->numsteps > 1) {
- float3 prev_cdf_distance = make_float3(0.0f, 0.0f, 0.0f);
-
- int numsteps = segment->numsteps;
- int high = numsteps - 1;
- int low = 0;
- int mid;
-
- while(low < high) {
- mid = (low + high) >> 1;
-
- if(sample_t < step[mid].t)
- high = mid;
- else if(sample_t >= step[mid + 1].t)
- low = mid + 1;
- else {
- /* found our interval in step[mid] .. step[mid+1] */
- prev_t = step[mid].t;
- prev_cdf_distance = step[mid].cdf_distance;
- step += mid+1;
- break;
- }
- }
-
- if(low >= numsteps - 1) {
- prev_t = step[numsteps - 1].t;
- prev_cdf_distance = step[numsteps-1].cdf_distance;
- step += numsteps - 1;
- }
-
- /* pdf for picking step with distance sampling */
- step_pdf_distance = step->cdf_distance - prev_cdf_distance;
- }
-
- /* determine range in which we will sample */
- float step_t = step->t - prev_t;
- float step_sample_t = sample_t - prev_t;
-
- /* compute transmittance */
- transmittance = volume_color_transmittance(step->sigma_t, step_sample_t);
-
- /* multiple importance sampling */
- if(use_mis) {
- float3 distance_pdf3 = kernel_volume_distance_pdf(step_t, step->sigma_t, step_sample_t);
- float distance_pdf = dot(channel_pdf, distance_pdf3 * step_pdf_distance);
- mis_weight = 2.0f*power_heuristic(pdf, distance_pdf);
- }
- }
- if(sample_t < 0.0f || pdf == 0.0f) {
- return VOLUME_PATH_MISSED;
- }
-
- /* compute transmittance up to this step */
- if(step != segment->steps)
- transmittance *= (step-1)->accum_transmittance;
-
- /* modify throughput */
- *throughput *= step->sigma_s * transmittance * (mis_weight / pdf);
-
- /* evaluate shader to create closures at shading point */
- if(segment->numsteps > 1) {
- sd->P = ray->P + step->shade_t*ray->D;
-
- VolumeShaderCoefficients coeff;
- volume_shader_sample(kg, sd, state, sd->P, &coeff);
- }
-
- /* move to new position */
- sd->P = ray->P + sample_t*ray->D;
-
- return VOLUME_PATH_SCATTERED;
+ kernel_assert(segment->closure_flag & SD_SCATTER);
+
+ /* Sample color channel, use MIS with balance heuristic. */
+ float3 channel_pdf;
+ int channel = kernel_volume_sample_channel(
+ segment->accum_albedo, *throughput, rphase, &channel_pdf);
+
+ float xi = rscatter;
+
+ /* probabilistic scattering decision based on transmittance */
+ if (probalistic_scatter) {
+ float sample_transmittance = kernel_volume_channel_get(segment->accum_transmittance, channel);
+
+ if (1.0f - xi >= sample_transmittance) {
+ /* rescale random number so we can reuse it */
+ xi = 1.0f - (1.0f - xi - sample_transmittance) / (1.0f - sample_transmittance);
+ }
+ else {
+ *throughput /= sample_transmittance;
+ return VOLUME_PATH_MISSED;
+ }
+ }
+
+ VolumeStep *step;
+ float3 transmittance;
+ float pdf, sample_t;
+ float mis_weight = 1.0f;
+ bool distance_sample = true;
+ bool use_mis = false;
+
+ if (segment->sampling_method && light_P) {
+ if (segment->sampling_method == SD_VOLUME_MIS) {
+ /* multiple importance sample: randomly pick between
+ * equiangular and distance sampling strategy */
+ if (xi < 0.5f) {
+ xi *= 2.0f;
+ }
+ else {
+ xi = (xi - 0.5f) * 2.0f;
+ distance_sample = false;
+ }
+
+ use_mis = true;
+ }
+ else {
+ /* only equiangular sampling */
+ distance_sample = false;
+ }
+ }
+
+ /* distance sampling */
+ if (distance_sample) {
+ /* find step in cdf */
+ step = segment->steps;
+
+ float prev_t = 0.0f;
+ float3 step_pdf_distance = make_float3(1.0f, 1.0f, 1.0f);
+
+ if (segment->numsteps > 1) {
+ float prev_cdf = 0.0f;
+ float step_cdf = 1.0f;
+ float3 prev_cdf_distance = make_float3(0.0f, 0.0f, 0.0f);
+
+ for (int i = 0;; i++, step++) {
+ /* todo: optimize using binary search */
+ step_cdf = kernel_volume_channel_get(step->cdf_distance, channel);
+
+ if (xi < step_cdf || i == segment->numsteps - 1)
+ break;
+
+ prev_cdf = step_cdf;
+ prev_t = step->t;
+ prev_cdf_distance = step->cdf_distance;
+ }
+
+ /* remap xi so we can reuse it */
+ xi = (xi - prev_cdf) / (step_cdf - prev_cdf);
+
+ /* pdf for picking step */
+ step_pdf_distance = step->cdf_distance - prev_cdf_distance;
+ }
+
+ /* determine range in which we will sample */
+ float step_t = step->t - prev_t;
+
+ /* sample distance and compute transmittance */
+ float3 distance_pdf;
+ sample_t = prev_t + kernel_volume_distance_sample(
+ step_t, step->sigma_t, channel, xi, &transmittance, &distance_pdf);
+
+ /* modify pdf for hit/miss decision */
+ if (probalistic_scatter)
+ distance_pdf *= make_float3(1.0f, 1.0f, 1.0f) - segment->accum_transmittance;
+
+ pdf = dot(channel_pdf, distance_pdf * step_pdf_distance);
+
+ /* multiple importance sampling */
+ if (use_mis) {
+ float equi_pdf = kernel_volume_equiangular_pdf(ray, *light_P, sample_t);
+ mis_weight = 2.0f * power_heuristic(pdf, equi_pdf);
+ }
+ }
+ /* equi-angular sampling */
+ else {
+ /* sample distance */
+ sample_t = kernel_volume_equiangular_sample(ray, *light_P, xi, &pdf);
+
+ /* find step in which sampled distance is located */
+ step = segment->steps;
+
+ float prev_t = 0.0f;
+ float3 step_pdf_distance = make_float3(1.0f, 1.0f, 1.0f);
+
+ if (segment->numsteps > 1) {
+ float3 prev_cdf_distance = make_float3(0.0f, 0.0f, 0.0f);
+
+ int numsteps = segment->numsteps;
+ int high = numsteps - 1;
+ int low = 0;
+ int mid;
+
+ while (low < high) {
+ mid = (low + high) >> 1;
+
+ if (sample_t < step[mid].t)
+ high = mid;
+ else if (sample_t >= step[mid + 1].t)
+ low = mid + 1;
+ else {
+ /* found our interval in step[mid] .. step[mid+1] */
+ prev_t = step[mid].t;
+ prev_cdf_distance = step[mid].cdf_distance;
+ step += mid + 1;
+ break;
+ }
+ }
+
+ if (low >= numsteps - 1) {
+ prev_t = step[numsteps - 1].t;
+ prev_cdf_distance = step[numsteps - 1].cdf_distance;
+ step += numsteps - 1;
+ }
+
+ /* pdf for picking step with distance sampling */
+ step_pdf_distance = step->cdf_distance - prev_cdf_distance;
+ }
+
+ /* determine range in which we will sample */
+ float step_t = step->t - prev_t;
+ float step_sample_t = sample_t - prev_t;
+
+ /* compute transmittance */
+ transmittance = volume_color_transmittance(step->sigma_t, step_sample_t);
+
+ /* multiple importance sampling */
+ if (use_mis) {
+ float3 distance_pdf3 = kernel_volume_distance_pdf(step_t, step->sigma_t, step_sample_t);
+ float distance_pdf = dot(channel_pdf, distance_pdf3 * step_pdf_distance);
+ mis_weight = 2.0f * power_heuristic(pdf, distance_pdf);
+ }
+ }
+ if (sample_t < 0.0f || pdf == 0.0f) {
+ return VOLUME_PATH_MISSED;
+ }
+
+ /* compute transmittance up to this step */
+ if (step != segment->steps)
+ transmittance *= (step - 1)->accum_transmittance;
+
+ /* modify throughput */
+ *throughput *= step->sigma_s * transmittance * (mis_weight / pdf);
+
+ /* evaluate shader to create closures at shading point */
+ if (segment->numsteps > 1) {
+ sd->P = ray->P + step->shade_t * ray->D;
+
+ VolumeShaderCoefficients coeff;
+ volume_shader_sample(kg, sd, state, sd->P, &coeff);
+ }
+
+ /* move to new position */
+ sd->P = ray->P + sample_t * ray->D;
+
+ return VOLUME_PATH_SCATTERED;
}
-#endif /* __SPLIT_KERNEL */
+# endif /* __SPLIT_KERNEL */
/* decide if we need to use decoupled or not */
-ccl_device bool kernel_volume_use_decoupled(KernelGlobals *kg, bool heterogeneous, bool direct, int sampling_method)
+ccl_device bool kernel_volume_use_decoupled(KernelGlobals *kg,
+ bool heterogeneous,
+ bool direct,
+ int sampling_method)
{
- /* decoupled ray marching for heterogeneous volumes not supported on the GPU,
- * which also means equiangular and multiple importance sampling is not
- * support for that case */
- if(!kernel_data.integrator.volume_decoupled)
- return false;
-
-#ifdef __KERNEL_GPU__
- if(heterogeneous)
- return false;
-#endif
-
- /* equiangular and multiple importance sampling only implemented for decoupled */
- if(sampling_method != 0)
- return true;
-
- /* for all light sampling use decoupled, reusing shader evaluations is
- * typically faster in that case */
- if(direct)
- return kernel_data.integrator.sample_all_lights_direct;
- else
- return kernel_data.integrator.sample_all_lights_indirect;
+ /* decoupled ray marching for heterogeneous volumes not supported on the GPU,
+ * which also means equiangular and multiple importance sampling is not
+ * support for that case */
+ if (!kernel_data.integrator.volume_decoupled)
+ return false;
+
+# ifdef __KERNEL_GPU__
+ if (heterogeneous)
+ return false;
+# endif
+
+ /* equiangular and multiple importance sampling only implemented for decoupled */
+ if (sampling_method != 0)
+ return true;
+
+ /* for all light sampling use decoupled, reusing shader evaluations is
+ * typically faster in that case */
+ if (direct)
+ return kernel_data.integrator.sample_all_lights_direct;
+ else
+ return kernel_data.integrator.sample_all_lights_indirect;
}
/* Volume Stack
@@ -1124,242 +1147,231 @@ ccl_device void kernel_volume_stack_init(KernelGlobals *kg,
ccl_addr_space const Ray *ray,
ccl_addr_space VolumeStack *stack)
{
- /* NULL ray happens in the baker, does it need proper initialization of
- * camera in volume?
- */
- if(!kernel_data.cam.is_inside_volume || ray == NULL) {
- /* Camera is guaranteed to be in the air, only take background volume
- * into account in this case.
- */
- if(kernel_data.background.volume_shader != SHADER_NONE) {
- stack[0].shader = kernel_data.background.volume_shader;
- stack[0].object = PRIM_NONE;
- stack[1].shader = SHADER_NONE;
- }
- else {
- stack[0].shader = SHADER_NONE;
- }
- return;
- }
-
- kernel_assert(state->flag & PATH_RAY_CAMERA);
-
- Ray volume_ray = *ray;
- volume_ray.t = FLT_MAX;
-
- const uint visibility = (state->flag & PATH_RAY_ALL_VISIBILITY);
- int stack_index = 0, enclosed_index = 0;
-
-#ifdef __VOLUME_RECORD_ALL__
- Intersection hits[2*VOLUME_STACK_SIZE + 1];
- uint num_hits = scene_intersect_volume_all(kg,
- &volume_ray,
- hits,
- 2*VOLUME_STACK_SIZE,
- visibility);
- if(num_hits > 0) {
- int enclosed_volumes[VOLUME_STACK_SIZE];
- Intersection *isect = hits;
-
- qsort(hits, num_hits, sizeof(Intersection), intersections_compare);
-
- for(uint hit = 0; hit < num_hits; ++hit, ++isect) {
- shader_setup_from_ray(kg, stack_sd, isect, &volume_ray);
- if(stack_sd->flag & SD_BACKFACING) {
- bool need_add = true;
- for(int i = 0; i < enclosed_index && need_add; ++i) {
- /* If ray exited the volume and never entered to that volume
- * it means that camera is inside such a volume.
- */
- if(enclosed_volumes[i] == stack_sd->object) {
- need_add = false;
- }
- }
- for(int i = 0; i < stack_index && need_add; ++i) {
- /* Don't add intersections twice. */
- if(stack[i].object == stack_sd->object) {
- need_add = false;
- break;
- }
- }
- if(need_add && stack_index < VOLUME_STACK_SIZE - 1) {
- stack[stack_index].object = stack_sd->object;
- stack[stack_index].shader = stack_sd->shader;
- ++stack_index;
- }
- }
- else {
- /* If ray from camera enters the volume, this volume shouldn't
- * be added to the stack on exit.
- */
- enclosed_volumes[enclosed_index++] = stack_sd->object;
- }
- }
- }
-#else
- int enclosed_volumes[VOLUME_STACK_SIZE];
- int step = 0;
-
- while(stack_index < VOLUME_STACK_SIZE - 1 &&
- enclosed_index < VOLUME_STACK_SIZE - 1 &&
- step < 2 * VOLUME_STACK_SIZE)
- {
- Intersection isect;
- if(!scene_intersect_volume(kg, &volume_ray, &isect, visibility)) {
- break;
- }
-
- shader_setup_from_ray(kg, stack_sd, &isect, &volume_ray);
- if(stack_sd->flag & SD_BACKFACING) {
- /* If ray exited the volume and never entered to that volume
- * it means that camera is inside such a volume.
- */
- bool need_add = true;
- for(int i = 0; i < enclosed_index && need_add; ++i) {
- /* If ray exited the volume and never entered to that volume
- * it means that camera is inside such a volume.
- */
- if(enclosed_volumes[i] == stack_sd->object) {
- need_add = false;
- }
- }
- for(int i = 0; i < stack_index && need_add; ++i) {
- /* Don't add intersections twice. */
- if(stack[i].object == stack_sd->object) {
- need_add = false;
- break;
- }
- }
- if(need_add) {
- stack[stack_index].object = stack_sd->object;
- stack[stack_index].shader = stack_sd->shader;
- ++stack_index;
- }
- }
- else {
- /* If ray from camera enters the volume, this volume shouldn't
- * be added to the stack on exit.
- */
- enclosed_volumes[enclosed_index++] = stack_sd->object;
- }
-
- /* Move ray forward. */
- volume_ray.P = ray_offset(stack_sd->P, -stack_sd->Ng);
- ++step;
- }
-#endif
- /* stack_index of 0 means quick checks outside of the kernel gave false
- * positive, nothing to worry about, just we've wasted quite a few of
- * ticks just to come into conclusion that camera is in the air.
- *
- * In this case we're doing the same above -- check whether background has
- * volume.
- */
- if(stack_index == 0 && kernel_data.background.volume_shader == SHADER_NONE) {
- stack[0].shader = kernel_data.background.volume_shader;
- stack[0].object = PRIM_NONE;
- stack[1].shader = SHADER_NONE;
- }
- else {
- stack[stack_index].shader = SHADER_NONE;
- }
+ /* NULL ray happens in the baker, does it need proper initialization of
+ * camera in volume?
+ */
+ if (!kernel_data.cam.is_inside_volume || ray == NULL) {
+ /* Camera is guaranteed to be in the air, only take background volume
+ * into account in this case.
+ */
+ if (kernel_data.background.volume_shader != SHADER_NONE) {
+ stack[0].shader = kernel_data.background.volume_shader;
+ stack[0].object = PRIM_NONE;
+ stack[1].shader = SHADER_NONE;
+ }
+ else {
+ stack[0].shader = SHADER_NONE;
+ }
+ return;
+ }
+
+ kernel_assert(state->flag & PATH_RAY_CAMERA);
+
+ Ray volume_ray = *ray;
+ volume_ray.t = FLT_MAX;
+
+ const uint visibility = (state->flag & PATH_RAY_ALL_VISIBILITY);
+ int stack_index = 0, enclosed_index = 0;
+
+# ifdef __VOLUME_RECORD_ALL__
+ Intersection hits[2 * VOLUME_STACK_SIZE + 1];
+ uint num_hits = scene_intersect_volume_all(
+ kg, &volume_ray, hits, 2 * VOLUME_STACK_SIZE, visibility);
+ if (num_hits > 0) {
+ int enclosed_volumes[VOLUME_STACK_SIZE];
+ Intersection *isect = hits;
+
+ qsort(hits, num_hits, sizeof(Intersection), intersections_compare);
+
+ for (uint hit = 0; hit < num_hits; ++hit, ++isect) {
+ shader_setup_from_ray(kg, stack_sd, isect, &volume_ray);
+ if (stack_sd->flag & SD_BACKFACING) {
+ bool need_add = true;
+ for (int i = 0; i < enclosed_index && need_add; ++i) {
+ /* If ray exited the volume and never entered to that volume
+ * it means that camera is inside such a volume.
+ */
+ if (enclosed_volumes[i] == stack_sd->object) {
+ need_add = false;
+ }
+ }
+ for (int i = 0; i < stack_index && need_add; ++i) {
+ /* Don't add intersections twice. */
+ if (stack[i].object == stack_sd->object) {
+ need_add = false;
+ break;
+ }
+ }
+ if (need_add && stack_index < VOLUME_STACK_SIZE - 1) {
+ stack[stack_index].object = stack_sd->object;
+ stack[stack_index].shader = stack_sd->shader;
+ ++stack_index;
+ }
+ }
+ else {
+ /* If ray from camera enters the volume, this volume shouldn't
+ * be added to the stack on exit.
+ */
+ enclosed_volumes[enclosed_index++] = stack_sd->object;
+ }
+ }
+ }
+# else
+ int enclosed_volumes[VOLUME_STACK_SIZE];
+ int step = 0;
+
+ while (stack_index < VOLUME_STACK_SIZE - 1 && enclosed_index < VOLUME_STACK_SIZE - 1 &&
+ step < 2 * VOLUME_STACK_SIZE) {
+ Intersection isect;
+ if (!scene_intersect_volume(kg, &volume_ray, &isect, visibility)) {
+ break;
+ }
+
+ shader_setup_from_ray(kg, stack_sd, &isect, &volume_ray);
+ if (stack_sd->flag & SD_BACKFACING) {
+ /* If ray exited the volume and never entered to that volume
+ * it means that camera is inside such a volume.
+ */
+ bool need_add = true;
+ for (int i = 0; i < enclosed_index && need_add; ++i) {
+ /* If ray exited the volume and never entered to that volume
+ * it means that camera is inside such a volume.
+ */
+ if (enclosed_volumes[i] == stack_sd->object) {
+ need_add = false;
+ }
+ }
+ for (int i = 0; i < stack_index && need_add; ++i) {
+ /* Don't add intersections twice. */
+ if (stack[i].object == stack_sd->object) {
+ need_add = false;
+ break;
+ }
+ }
+ if (need_add) {
+ stack[stack_index].object = stack_sd->object;
+ stack[stack_index].shader = stack_sd->shader;
+ ++stack_index;
+ }
+ }
+ else {
+ /* If ray from camera enters the volume, this volume shouldn't
+ * be added to the stack on exit.
+ */
+ enclosed_volumes[enclosed_index++] = stack_sd->object;
+ }
+
+ /* Move ray forward. */
+ volume_ray.P = ray_offset(stack_sd->P, -stack_sd->Ng);
+ ++step;
+ }
+# endif
+ /* stack_index of 0 means quick checks outside of the kernel gave false
+ * positive, nothing to worry about, just we've wasted quite a few of
+ * ticks just to come into conclusion that camera is in the air.
+ *
+ * In this case we're doing the same above -- check whether background has
+ * volume.
+ */
+ if (stack_index == 0 && kernel_data.background.volume_shader == SHADER_NONE) {
+ stack[0].shader = kernel_data.background.volume_shader;
+ stack[0].object = PRIM_NONE;
+ stack[1].shader = SHADER_NONE;
+ }
+ else {
+ stack[stack_index].shader = SHADER_NONE;
+ }
}
-ccl_device void kernel_volume_stack_enter_exit(KernelGlobals *kg, ShaderData *sd, ccl_addr_space VolumeStack *stack)
+ccl_device void kernel_volume_stack_enter_exit(KernelGlobals *kg,
+ ShaderData *sd,
+ ccl_addr_space VolumeStack *stack)
{
- /* todo: we should have some way for objects to indicate if they want the
- * world shader to work inside them. excluding it by default is problematic
- * because non-volume objects can't be assumed to be closed manifolds */
-
- if(!(sd->flag & SD_HAS_VOLUME))
- return;
-
- if(sd->flag & SD_BACKFACING) {
- /* exit volume object: remove from stack */
- for(int i = 0; stack[i].shader != SHADER_NONE; i++) {
- if(stack[i].object == sd->object) {
- /* shift back next stack entries */
- do {
- stack[i] = stack[i+1];
- i++;
- }
- while(stack[i].shader != SHADER_NONE);
-
- return;
- }
- }
- }
- else {
- /* enter volume object: add to stack */
- int i;
-
- for(i = 0; stack[i].shader != SHADER_NONE; i++) {
- /* already in the stack? then we have nothing to do */
- if(stack[i].object == sd->object)
- return;
- }
-
- /* if we exceed the stack limit, ignore */
- if(i >= VOLUME_STACK_SIZE-1)
- return;
-
- /* add to the end of the stack */
- stack[i].shader = sd->shader;
- stack[i].object = sd->object;
- stack[i+1].shader = SHADER_NONE;
- }
+ /* todo: we should have some way for objects to indicate if they want the
+ * world shader to work inside them. excluding it by default is problematic
+ * because non-volume objects can't be assumed to be closed manifolds */
+
+ if (!(sd->flag & SD_HAS_VOLUME))
+ return;
+
+ if (sd->flag & SD_BACKFACING) {
+ /* exit volume object: remove from stack */
+ for (int i = 0; stack[i].shader != SHADER_NONE; i++) {
+ if (stack[i].object == sd->object) {
+ /* shift back next stack entries */
+ do {
+ stack[i] = stack[i + 1];
+ i++;
+ } while (stack[i].shader != SHADER_NONE);
+
+ return;
+ }
+ }
+ }
+ else {
+ /* enter volume object: add to stack */
+ int i;
+
+ for (i = 0; stack[i].shader != SHADER_NONE; i++) {
+ /* already in the stack? then we have nothing to do */
+ if (stack[i].object == sd->object)
+ return;
+ }
+
+ /* if we exceed the stack limit, ignore */
+ if (i >= VOLUME_STACK_SIZE - 1)
+ return;
+
+ /* add to the end of the stack */
+ stack[i].shader = sd->shader;
+ stack[i].object = sd->object;
+ stack[i + 1].shader = SHADER_NONE;
+ }
}
-#ifdef __SUBSURFACE__
+# ifdef __SUBSURFACE__
ccl_device void kernel_volume_stack_update_for_subsurface(KernelGlobals *kg,
ShaderData *stack_sd,
Ray *ray,
ccl_addr_space VolumeStack *stack)
{
- kernel_assert(kernel_data.integrator.use_volumes);
-
- Ray volume_ray = *ray;
-
-# ifdef __VOLUME_RECORD_ALL__
- Intersection hits[2*VOLUME_STACK_SIZE + 1];
- uint num_hits = scene_intersect_volume_all(kg,
- &volume_ray,
- hits,
- 2*VOLUME_STACK_SIZE,
- PATH_RAY_ALL_VISIBILITY);
- if(num_hits > 0) {
- Intersection *isect = hits;
-
- qsort(hits, num_hits, sizeof(Intersection), intersections_compare);
-
- for(uint hit = 0; hit < num_hits; ++hit, ++isect) {
- shader_setup_from_ray(kg, stack_sd, isect, &volume_ray);
- kernel_volume_stack_enter_exit(kg, stack_sd, stack);
- }
- }
-# else
- Intersection isect;
- int step = 0;
- float3 Pend = ray->P + ray->D*ray->t;
- while(step < 2 * VOLUME_STACK_SIZE &&
- scene_intersect_volume(kg,
- &volume_ray,
- &isect,
- PATH_RAY_ALL_VISIBILITY))
- {
- shader_setup_from_ray(kg, stack_sd, &isect, &volume_ray);
- kernel_volume_stack_enter_exit(kg, stack_sd, stack);
-
- /* Move ray forward. */
- volume_ray.P = ray_offset(stack_sd->P, -stack_sd->Ng);
- if(volume_ray.t != FLT_MAX) {
- volume_ray.D = normalize_len(Pend - volume_ray.P, &volume_ray.t);
- }
- ++step;
- }
-# endif
+ kernel_assert(kernel_data.integrator.use_volumes);
+
+ Ray volume_ray = *ray;
+
+# ifdef __VOLUME_RECORD_ALL__
+ Intersection hits[2 * VOLUME_STACK_SIZE + 1];
+ uint num_hits = scene_intersect_volume_all(
+ kg, &volume_ray, hits, 2 * VOLUME_STACK_SIZE, PATH_RAY_ALL_VISIBILITY);
+ if (num_hits > 0) {
+ Intersection *isect = hits;
+
+ qsort(hits, num_hits, sizeof(Intersection), intersections_compare);
+
+ for (uint hit = 0; hit < num_hits; ++hit, ++isect) {
+ shader_setup_from_ray(kg, stack_sd, isect, &volume_ray);
+ kernel_volume_stack_enter_exit(kg, stack_sd, stack);
+ }
+ }
+# else
+ Intersection isect;
+ int step = 0;
+ float3 Pend = ray->P + ray->D * ray->t;
+ while (step < 2 * VOLUME_STACK_SIZE &&
+ scene_intersect_volume(kg, &volume_ray, &isect, PATH_RAY_ALL_VISIBILITY)) {
+ shader_setup_from_ray(kg, stack_sd, &isect, &volume_ray);
+ kernel_volume_stack_enter_exit(kg, stack_sd, stack);
+
+ /* Move ray forward. */
+ volume_ray.P = ray_offset(stack_sd->P, -stack_sd->Ng);
+ if (volume_ray.t != FLT_MAX) {
+ volume_ray.D = normalize_len(Pend - volume_ray.P, &volume_ray.t);
+ }
+ ++step;
+ }
+# endif
}
-#endif
+# endif
/* Clean stack after the last bounce.
*
@@ -1378,15 +1390,15 @@ ccl_device void kernel_volume_stack_update_for_subsurface(KernelGlobals *kg,
ccl_device_inline void kernel_volume_clean_stack(KernelGlobals *kg,
ccl_addr_space VolumeStack *volume_stack)
{
- if(kernel_data.background.volume_shader != SHADER_NONE) {
- /* Keep the world's volume in stack. */
- volume_stack[1].shader = SHADER_NONE;
- }
- else {
- volume_stack[0].shader = SHADER_NONE;
- }
+ if (kernel_data.background.volume_shader != SHADER_NONE) {
+ /* Keep the world's volume in stack. */
+ volume_stack[1].shader = SHADER_NONE;
+ }
+ else {
+ volume_stack[0].shader = SHADER_NONE;
+ }
}
-#endif /* __VOLUME__ */
+#endif /* __VOLUME__ */
CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/kernel_work_stealing.h b/intern/cycles/kernel/kernel_work_stealing.h
index 9667156eaf5..799561a7466 100644
--- a/intern/cycles/kernel/kernel_work_stealing.h
+++ b/intern/cycles/kernel/kernel_work_stealing.h
@@ -35,27 +35,26 @@ ccl_device bool get_next_work(KernelGlobals *kg,
uint ray_index,
ccl_private uint *global_work_index)
{
- /* With a small amount of work there may be more threads than work due to
- * rounding up of global size, stop such threads immediately. */
- if(ray_index >= total_work_size) {
- return false;
- }
+ /* With a small amount of work there may be more threads than work due to
+ * rounding up of global size, stop such threads immediately. */
+ if (ray_index >= total_work_size) {
+ return false;
+ }
- /* Increase atomic work index counter in pool. */
- uint pool = ray_index / WORK_POOL_SIZE;
- uint work_index = atomic_fetch_and_inc_uint32(&work_pools[pool]);
+ /* Increase atomic work index counter in pool. */
+ uint pool = ray_index / WORK_POOL_SIZE;
+ uint work_index = atomic_fetch_and_inc_uint32(&work_pools[pool]);
- /* Map per-pool work index to a global work index. */
- uint global_size = ccl_global_size(0) * ccl_global_size(1);
- kernel_assert(global_size % WORK_POOL_SIZE == 0);
- kernel_assert(ray_index < global_size);
+ /* Map per-pool work index to a global work index. */
+ uint global_size = ccl_global_size(0) * ccl_global_size(1);
+ kernel_assert(global_size % WORK_POOL_SIZE == 0);
+ kernel_assert(ray_index < global_size);
- *global_work_index = (work_index / WORK_POOL_SIZE) * global_size
- + (pool * WORK_POOL_SIZE)
- + (work_index % WORK_POOL_SIZE);
+ *global_work_index = (work_index / WORK_POOL_SIZE) * global_size + (pool * WORK_POOL_SIZE) +
+ (work_index % WORK_POOL_SIZE);
- /* Test if all work for this pool is done. */
- return (*global_work_index < total_work_size);
+ /* Test if all work for this pool is done. */
+ return (*global_work_index < total_work_size);
}
#endif
@@ -67,22 +66,22 @@ ccl_device_inline void get_work_pixel(ccl_global const WorkTile *tile,
ccl_private uint *sample)
{
#ifdef __KERNEL_CUDA__
- /* Keeping threads for the same pixel together improves performance on CUDA. */
- uint sample_offset = global_work_index % tile->num_samples;
- uint pixel_offset = global_work_index / tile->num_samples;
-#else /* __KERNEL_CUDA__ */
- uint tile_pixels = tile->w * tile->h;
- uint sample_offset = global_work_index / tile_pixels;
- uint pixel_offset = global_work_index - sample_offset * tile_pixels;
+ /* Keeping threads for the same pixel together improves performance on CUDA. */
+ uint sample_offset = global_work_index % tile->num_samples;
+ uint pixel_offset = global_work_index / tile->num_samples;
+#else /* __KERNEL_CUDA__ */
+ uint tile_pixels = tile->w * tile->h;
+ uint sample_offset = global_work_index / tile_pixels;
+ uint pixel_offset = global_work_index - sample_offset * tile_pixels;
#endif /* __KERNEL_CUDA__ */
- uint y_offset = pixel_offset / tile->w;
- uint x_offset = pixel_offset - y_offset * tile->w;
+ uint y_offset = pixel_offset / tile->w;
+ uint x_offset = pixel_offset - y_offset * tile->w;
- *x = tile->x + x_offset;
- *y = tile->y + y_offset;
- *sample = tile->start_sample + sample_offset;
+ *x = tile->x + x_offset;
+ *y = tile->y + y_offset;
+ *sample = tile->start_sample + sample_offset;
}
CCL_NAMESPACE_END
-#endif /* __KERNEL_WORK_STEALING_H__ */
+#endif /* __KERNEL_WORK_STEALING_H__ */
diff --git a/intern/cycles/kernel/kernels/cpu/filter.cpp b/intern/cycles/kernel/kernels/cpu/filter.cpp
index 2ff1a392dc3..145a6b6ac40 100644
--- a/intern/cycles/kernel/kernels/cpu/filter.cpp
+++ b/intern/cycles/kernel/kernels/cpu/filter.cpp
@@ -53,7 +53,7 @@
/* quiet unused define warnings */
#if defined(__KERNEL_SSE2__)
- /* do nothing */
+/* do nothing */
#endif
#include "kernel/filter/filter.h"
diff --git a/intern/cycles/kernel/kernels/cpu/filter_avx.cpp b/intern/cycles/kernel/kernels/cpu/filter_avx.cpp
index 4a9e6047ecf..1d68214c8e7 100644
--- a/intern/cycles/kernel/kernels/cpu/filter_avx.cpp
+++ b/intern/cycles/kernel/kernels/cpu/filter_avx.cpp
@@ -32,7 +32,7 @@
# define __KERNEL_SSE41__
# define __KERNEL_AVX__
# endif
-#endif /* WITH_CYCLES_OPTIMIZED_KERNEL_AVX */
+#endif /* WITH_CYCLES_OPTIMIZED_KERNEL_AVX */
#include "kernel/filter/filter.h"
#define KERNEL_ARCH cpu_avx
diff --git a/intern/cycles/kernel/kernels/cpu/filter_avx2.cpp b/intern/cycles/kernel/kernels/cpu/filter_avx2.cpp
index c22ec576254..b6709fbc529 100644
--- a/intern/cycles/kernel/kernels/cpu/filter_avx2.cpp
+++ b/intern/cycles/kernel/kernels/cpu/filter_avx2.cpp
@@ -33,7 +33,7 @@
# define __KERNEL_AVX__
# define __KERNEL_AVX2__
# endif
-#endif /* WITH_CYCLES_OPTIMIZED_KERNEL_AVX2 */
+#endif /* WITH_CYCLES_OPTIMIZED_KERNEL_AVX2 */
#include "kernel/filter/filter.h"
#define KERNEL_ARCH cpu_avx2
diff --git a/intern/cycles/kernel/kernels/cpu/filter_cpu.h b/intern/cycles/kernel/kernels/cpu/filter_cpu.h
index 02c85562db8..1423b182ab8 100644
--- a/intern/cycles/kernel/kernels/cpu/filter_cpu.h
+++ b/intern/cycles/kernel/kernels/cpu/filter_cpu.h
@@ -25,7 +25,7 @@ void KERNEL_FUNCTION_FULL_NAME(filter_divide_shadow)(int sample,
float *sampleV,
float *sampleVV,
float *bufferV,
- int* prefilter_rect,
+ int *prefilter_rect,
int buffer_pass_stride,
int buffer_denoising_offset);
@@ -38,7 +38,7 @@ void KERNEL_FUNCTION_FULL_NAME(filter_get_feature)(int sample,
float *mean,
float *variance,
float scale,
- int* prefilter_rect,
+ int *prefilter_rect,
int buffer_pass_stride,
int buffer_denoising_offset);
@@ -49,9 +49,10 @@ void KERNEL_FUNCTION_FULL_NAME(filter_write_feature)(int sample,
float *from,
float *buffer,
int out_offset,
- int* prefilter_rect);
+ int *prefilter_rect);
-void KERNEL_FUNCTION_FULL_NAME(filter_detect_outliers)(int x, int y,
+void KERNEL_FUNCTION_FULL_NAME(filter_detect_outliers)(int x,
+ int y,
ccl_global float *image,
ccl_global float *variance,
ccl_global float *depth,
@@ -59,22 +60,17 @@ void KERNEL_FUNCTION_FULL_NAME(filter_detect_outliers)(int x, int y,
int *rect,
int pass_stride);
-void KERNEL_FUNCTION_FULL_NAME(filter_combine_halves)(int x, int y,
- float *mean,
- float *variance,
- float *a,
- float *b,
- int* prefilter_rect,
- int r);
+void KERNEL_FUNCTION_FULL_NAME(filter_combine_halves)(
+ int x, int y, float *mean, float *variance, float *a, float *b, int *prefilter_rect, int r);
-void KERNEL_FUNCTION_FULL_NAME(filter_construct_transform)(float* buffer,
+void KERNEL_FUNCTION_FULL_NAME(filter_construct_transform)(float *buffer,
TileInfo *tiles,
int x,
int y,
int storage_ofs,
float *transform,
int *rank,
- int* rect,
+ int *rect,
int pass_stride,
int frame_stride,
bool use_time,
@@ -87,24 +83,18 @@ void KERNEL_FUNCTION_FULL_NAME(filter_nlm_calc_difference)(int dx,
float *variance_image,
float *scale_image,
float *difference_image,
- int* rect,
+ int *rect,
int stride,
int channel_offset,
int frame_offset,
float a,
float k_2);
-void KERNEL_FUNCTION_FULL_NAME(filter_nlm_blur)(float *difference_image,
- float *out_image,
- int* rect,
- int stride,
- int f);
+void KERNEL_FUNCTION_FULL_NAME(filter_nlm_blur)(
+ float *difference_image, float *out_image, int *rect, int stride, int f);
-void KERNEL_FUNCTION_FULL_NAME(filter_nlm_calc_weight)(float *difference_image,
- float *out_image,
- int* rect,
- int stride,
- int f);
+void KERNEL_FUNCTION_FULL_NAME(filter_nlm_calc_weight)(
+ float *difference_image, float *out_image, int *rect, int stride, int f);
void KERNEL_FUNCTION_FULL_NAME(filter_nlm_update_output)(int dx,
int dy,
@@ -113,7 +103,7 @@ void KERNEL_FUNCTION_FULL_NAME(filter_nlm_update_output)(int dx,
float *temp_image,
float *out_image,
float *accum_image,
- int* rect,
+ int *rect,
int channel_offset,
int stride,
int f);
@@ -137,7 +127,7 @@ void KERNEL_FUNCTION_FULL_NAME(filter_nlm_construct_gramian)(int dx,
void KERNEL_FUNCTION_FULL_NAME(filter_nlm_normalize)(float *out_image,
float *accum_image,
- int* rect,
+ int *rect,
int stride);
void KERNEL_FUNCTION_FULL_NAME(filter_finalize)(int x,
diff --git a/intern/cycles/kernel/kernels/cpu/filter_cpu_impl.h b/intern/cycles/kernel/kernels/cpu/filter_cpu_impl.h
index c29505880cb..3d4cb87e104 100644
--- a/intern/cycles/kernel/kernels/cpu/filter_cpu_impl.h
+++ b/intern/cycles/kernel/kernels/cpu/filter_cpu_impl.h
@@ -25,12 +25,12 @@
#include "kernel/filter/filter_kernel.h"
#ifdef KERNEL_STUB
-# define STUB_ASSERT(arch, name) assert(!(#name " kernel stub for architecture " #arch " was called!"))
+# define STUB_ASSERT(arch, name) \
+ assert(!(#name " kernel stub for architecture " #arch " was called!"))
#endif
CCL_NAMESPACE_BEGIN
-
/* Denoise filter */
void KERNEL_FUNCTION_FULL_NAME(filter_divide_shadow)(int sample,
@@ -42,23 +42,25 @@ void KERNEL_FUNCTION_FULL_NAME(filter_divide_shadow)(int sample,
float *sampleVariance,
float *sampleVarianceV,
float *bufferVariance,
- int* prefilter_rect,
+ int *prefilter_rect,
int buffer_pass_stride,
int buffer_denoising_offset)
{
#ifdef KERNEL_STUB
- STUB_ASSERT(KERNEL_ARCH, filter_divide_shadow);
+ STUB_ASSERT(KERNEL_ARCH, filter_divide_shadow);
#else
- kernel_filter_divide_shadow(sample, tile_info,
- x, y,
- unfilteredA,
- unfilteredB,
- sampleVariance,
- sampleVarianceV,
- bufferVariance,
- load_int4(prefilter_rect),
- buffer_pass_stride,
- buffer_denoising_offset);
+ kernel_filter_divide_shadow(sample,
+ tile_info,
+ x,
+ y,
+ unfilteredA,
+ unfilteredB,
+ sampleVariance,
+ sampleVarianceV,
+ bufferVariance,
+ load_int4(prefilter_rect),
+ buffer_pass_stride,
+ buffer_denoising_offset);
#endif
}
@@ -68,23 +70,28 @@ void KERNEL_FUNCTION_FULL_NAME(filter_get_feature)(int sample,
int v_offset,
int x,
int y,
- float *mean, float *variance,
+ float *mean,
+ float *variance,
float scale,
- int* prefilter_rect,
+ int *prefilter_rect,
int buffer_pass_stride,
int buffer_denoising_offset)
{
#ifdef KERNEL_STUB
- STUB_ASSERT(KERNEL_ARCH, filter_get_feature);
+ STUB_ASSERT(KERNEL_ARCH, filter_get_feature);
#else
- kernel_filter_get_feature(sample, tile_info,
- m_offset, v_offset,
- x, y,
- mean, variance,
- scale,
- load_int4(prefilter_rect),
- buffer_pass_stride,
- buffer_denoising_offset);
+ kernel_filter_get_feature(sample,
+ tile_info,
+ m_offset,
+ v_offset,
+ x,
+ y,
+ mean,
+ variance,
+ scale,
+ load_int4(prefilter_rect),
+ buffer_pass_stride,
+ buffer_denoising_offset);
#endif
}
@@ -95,16 +102,18 @@ void KERNEL_FUNCTION_FULL_NAME(filter_write_feature)(int sample,
float *from,
float *buffer,
int out_offset,
- int* prefilter_rect)
+ int *prefilter_rect)
{
#ifdef KERNEL_STUB
- STUB_ASSERT(KERNEL_ARCH, filter_write_feature);
+ STUB_ASSERT(KERNEL_ARCH, filter_write_feature);
#else
- kernel_filter_write_feature(sample, x, y, load_int4(buffer_params), from, buffer, out_offset, load_int4(prefilter_rect));
+ kernel_filter_write_feature(
+ sample, x, y, load_int4(buffer_params), from, buffer, out_offset, load_int4(prefilter_rect));
#endif
}
-void KERNEL_FUNCTION_FULL_NAME(filter_detect_outliers)(int x, int y,
+void KERNEL_FUNCTION_FULL_NAME(filter_detect_outliers)(int x,
+ int y,
ccl_global float *image,
ccl_global float *variance,
ccl_global float *depth,
@@ -113,35 +122,31 @@ void KERNEL_FUNCTION_FULL_NAME(filter_detect_outliers)(int x, int y,
int pass_stride)
{
#ifdef KERNEL_STUB
- STUB_ASSERT(KERNEL_ARCH, filter_detect_outliers);
+ STUB_ASSERT(KERNEL_ARCH, filter_detect_outliers);
#else
- kernel_filter_detect_outliers(x, y, image, variance, depth, output, load_int4(rect), pass_stride);
+ kernel_filter_detect_outliers(
+ x, y, image, variance, depth, output, load_int4(rect), pass_stride);
#endif
}
-void KERNEL_FUNCTION_FULL_NAME(filter_combine_halves)(int x, int y,
- float *mean,
- float *variance,
- float *a,
- float *b,
- int* prefilter_rect,
- int r)
+void KERNEL_FUNCTION_FULL_NAME(filter_combine_halves)(
+ int x, int y, float *mean, float *variance, float *a, float *b, int *prefilter_rect, int r)
{
#ifdef KERNEL_STUB
- STUB_ASSERT(KERNEL_ARCH, filter_combine_halves);
+ STUB_ASSERT(KERNEL_ARCH, filter_combine_halves);
#else
- kernel_filter_combine_halves(x, y, mean, variance, a, b, load_int4(prefilter_rect), r);
+ kernel_filter_combine_halves(x, y, mean, variance, a, b, load_int4(prefilter_rect), r);
#endif
}
-void KERNEL_FUNCTION_FULL_NAME(filter_construct_transform)(float* buffer,
+void KERNEL_FUNCTION_FULL_NAME(filter_construct_transform)(float *buffer,
TileInfo *tile_info,
int x,
int y,
int storage_ofs,
float *transform,
int *rank,
- int* prefilter_rect,
+ int *prefilter_rect,
int pass_stride,
int frame_stride,
bool use_time,
@@ -149,21 +154,22 @@ void KERNEL_FUNCTION_FULL_NAME(filter_construct_transform)(float* buffer,
float pca_threshold)
{
#ifdef KERNEL_STUB
- STUB_ASSERT(KERNEL_ARCH, filter_construct_transform);
+ STUB_ASSERT(KERNEL_ARCH, filter_construct_transform);
#else
- rank += storage_ofs;
- transform += storage_ofs*TRANSFORM_SIZE;
- kernel_filter_construct_transform(buffer,
- tile_info,
- x, y,
- load_int4(prefilter_rect),
- pass_stride,
- frame_stride,
- use_time,
- transform,
- rank,
- radius,
- pca_threshold);
+ rank += storage_ofs;
+ transform += storage_ofs * TRANSFORM_SIZE;
+ kernel_filter_construct_transform(buffer,
+ tile_info,
+ x,
+ y,
+ load_int4(prefilter_rect),
+ pass_stride,
+ frame_stride,
+ use_time,
+ transform,
+ rank,
+ radius,
+ pca_threshold);
#endif
}
@@ -181,44 +187,40 @@ void KERNEL_FUNCTION_FULL_NAME(filter_nlm_calc_difference)(int dx,
float k_2)
{
#ifdef KERNEL_STUB
- STUB_ASSERT(KERNEL_ARCH, filter_nlm_calc_difference);
+ STUB_ASSERT(KERNEL_ARCH, filter_nlm_calc_difference);
#else
- kernel_filter_nlm_calc_difference(dx, dy,
- weight_image,
- variance_image,
- scale_image,
- difference_image,
- load_int4(rect),
- stride,
- channel_offset,
- frame_offset,
- a, k_2);
+ kernel_filter_nlm_calc_difference(dx,
+ dy,
+ weight_image,
+ variance_image,
+ scale_image,
+ difference_image,
+ load_int4(rect),
+ stride,
+ channel_offset,
+ frame_offset,
+ a,
+ k_2);
#endif
}
-void KERNEL_FUNCTION_FULL_NAME(filter_nlm_blur)(float *difference_image,
- float *out_image,
- int *rect,
- int stride,
- int f)
+void KERNEL_FUNCTION_FULL_NAME(filter_nlm_blur)(
+ float *difference_image, float *out_image, int *rect, int stride, int f)
{
#ifdef KERNEL_STUB
- STUB_ASSERT(KERNEL_ARCH, filter_nlm_blur);
+ STUB_ASSERT(KERNEL_ARCH, filter_nlm_blur);
#else
- kernel_filter_nlm_blur(difference_image, out_image, load_int4(rect), stride, f);
+ kernel_filter_nlm_blur(difference_image, out_image, load_int4(rect), stride, f);
#endif
}
-void KERNEL_FUNCTION_FULL_NAME(filter_nlm_calc_weight)(float *difference_image,
- float *out_image,
- int *rect,
- int stride,
- int f)
+void KERNEL_FUNCTION_FULL_NAME(filter_nlm_calc_weight)(
+ float *difference_image, float *out_image, int *rect, int stride, int f)
{
#ifdef KERNEL_STUB
- STUB_ASSERT(KERNEL_ARCH, filter_nlm_calc_weight);
+ STUB_ASSERT(KERNEL_ARCH, filter_nlm_calc_weight);
#else
- kernel_filter_nlm_calc_weight(difference_image, out_image, load_int4(rect), stride, f);
+ kernel_filter_nlm_calc_weight(difference_image, out_image, load_int4(rect), stride, f);
#endif
}
@@ -235,17 +237,19 @@ void KERNEL_FUNCTION_FULL_NAME(filter_nlm_update_output)(int dx,
int f)
{
#ifdef KERNEL_STUB
- STUB_ASSERT(KERNEL_ARCH, filter_nlm_update_output);
+ STUB_ASSERT(KERNEL_ARCH, filter_nlm_update_output);
#else
- kernel_filter_nlm_update_output(dx, dy,
- difference_image,
- image,
- temp_image,
- out_image,
- accum_image,
- load_int4(rect),
- channel_offset,
- stride, f);
+ kernel_filter_nlm_update_output(dx,
+ dy,
+ difference_image,
+ image,
+ temp_image,
+ out_image,
+ accum_image,
+ load_int4(rect),
+ channel_offset,
+ stride,
+ f);
#endif
}
@@ -267,19 +271,24 @@ void KERNEL_FUNCTION_FULL_NAME(filter_nlm_construct_gramian)(int dx,
bool use_time)
{
#ifdef KERNEL_STUB
- STUB_ASSERT(KERNEL_ARCH, filter_nlm_construct_gramian);
+ STUB_ASSERT(KERNEL_ARCH, filter_nlm_construct_gramian);
#else
- kernel_filter_nlm_construct_gramian(dx, dy, t,
- difference_image,
- buffer,
- transform, rank,
- XtWX, XtWY,
- load_int4(rect),
- load_int4(filter_window),
- stride, f,
- pass_stride,
- frame_offset,
- use_time);
+ kernel_filter_nlm_construct_gramian(dx,
+ dy,
+ t,
+ difference_image,
+ buffer,
+ transform,
+ rank,
+ XtWX,
+ XtWY,
+ load_int4(rect),
+ load_int4(filter_window),
+ stride,
+ f,
+ pass_stride,
+ frame_offset,
+ use_time);
#endif
}
@@ -289,9 +298,9 @@ void KERNEL_FUNCTION_FULL_NAME(filter_nlm_normalize)(float *out_image,
int stride)
{
#ifdef KERNEL_STUB
- STUB_ASSERT(KERNEL_ARCH, filter_nlm_normalize);
+ STUB_ASSERT(KERNEL_ARCH, filter_nlm_normalize);
#else
- kernel_filter_nlm_normalize(out_image, accum_image, load_int4(rect), stride);
+ kernel_filter_nlm_normalize(out_image, accum_image, load_int4(rect), stride);
#endif
}
@@ -306,12 +315,12 @@ void KERNEL_FUNCTION_FULL_NAME(filter_finalize)(int x,
int sample)
{
#ifdef KERNEL_STUB
- STUB_ASSERT(KERNEL_ARCH, filter_finalize);
+ STUB_ASSERT(KERNEL_ARCH, filter_finalize);
#else
- XtWX += storage_ofs*XTWX_SIZE;
- XtWY += storage_ofs*XTWY_SIZE;
- rank += storage_ofs;
- kernel_filter_finalize(x, y, buffer, rank, 1, XtWX, XtWY, load_int4(buffer_params), sample);
+ XtWX += storage_ofs * XTWX_SIZE;
+ XtWY += storage_ofs * XTWY_SIZE;
+ rank += storage_ofs;
+ kernel_filter_finalize(x, y, buffer, rank, 1, XtWX, XtWY, load_int4(buffer_params), sample);
#endif
}
diff --git a/intern/cycles/kernel/kernels/cpu/filter_sse2.cpp b/intern/cycles/kernel/kernels/cpu/filter_sse2.cpp
index f7c9935f1d0..6c6c3e78696 100644
--- a/intern/cycles/kernel/kernels/cpu/filter_sse2.cpp
+++ b/intern/cycles/kernel/kernels/cpu/filter_sse2.cpp
@@ -27,7 +27,7 @@
# if !(defined(__GNUC__) && (defined(i386) || defined(_M_IX86)))
# define __KERNEL_SSE2__
# endif
-#endif /* WITH_CYCLES_OPTIMIZED_KERNEL_SSE2 */
+#endif /* WITH_CYCLES_OPTIMIZED_KERNEL_SSE2 */
#include "kernel/filter/filter.h"
#define KERNEL_ARCH cpu_sse2
diff --git a/intern/cycles/kernel/kernels/cpu/filter_sse3.cpp b/intern/cycles/kernel/kernels/cpu/filter_sse3.cpp
index 070b95a3505..e2243000331 100644
--- a/intern/cycles/kernel/kernels/cpu/filter_sse3.cpp
+++ b/intern/cycles/kernel/kernels/cpu/filter_sse3.cpp
@@ -29,7 +29,7 @@
# define __KERNEL_SSE3__
# define __KERNEL_SSSE3__
# endif
-#endif /* WITH_CYCLES_OPTIMIZED_KERNEL_SSE3 */
+#endif /* WITH_CYCLES_OPTIMIZED_KERNEL_SSE3 */
#include "kernel/filter/filter.h"
#define KERNEL_ARCH cpu_sse3
diff --git a/intern/cycles/kernel/kernels/cpu/filter_sse41.cpp b/intern/cycles/kernel/kernels/cpu/filter_sse41.cpp
index 254025be4e2..068889365e3 100644
--- a/intern/cycles/kernel/kernels/cpu/filter_sse41.cpp
+++ b/intern/cycles/kernel/kernels/cpu/filter_sse41.cpp
@@ -31,7 +31,7 @@
# define __KERNEL_SSSE3__
# define __KERNEL_SSE41__
# endif
-#endif /* WITH_CYCLES_OPTIMIZED_KERNEL_SSE41 */
+#endif /* WITH_CYCLES_OPTIMIZED_KERNEL_SSE41 */
#include "kernel/filter/filter.h"
#define KERNEL_ARCH cpu_sse41
diff --git a/intern/cycles/kernel/kernels/cpu/kernel.cpp b/intern/cycles/kernel/kernels/cpu/kernel.cpp
index de487f6123f..f2146302a27 100644
--- a/intern/cycles/kernel/kernels/cpu/kernel.cpp
+++ b/intern/cycles/kernel/kernels/cpu/kernel.cpp
@@ -53,7 +53,7 @@
/* quiet unused define warnings */
#if defined(__KERNEL_SSE2__)
- /* do nothing */
+/* do nothing */
#endif
#include "kernel/kernel.h"
@@ -66,29 +66,27 @@ CCL_NAMESPACE_BEGIN
void kernel_const_copy(KernelGlobals *kg, const char *name, void *host, size_t size)
{
- if(strcmp(name, "__data") == 0)
- memcpy(&kg->__data, host, size);
- else
- assert(0);
+ if (strcmp(name, "__data") == 0)
+ memcpy(&kg->__data, host, size);
+ else
+ assert(0);
}
-void kernel_tex_copy(KernelGlobals *kg,
- const char *name,
- void *mem,
- size_t size)
+void kernel_tex_copy(KernelGlobals *kg, const char *name, void *mem, size_t size)
{
- if(0) {
- }
+ if (0) {
+ }
#define KERNEL_TEX(type, tname) \
- else if(strcmp(name, #tname) == 0) { \
- kg->tname.data = (type*)mem; \
- kg->tname.width = size; \
- }
+ else if (strcmp(name, #tname) == 0) \
+ { \
+ kg->tname.data = (type *)mem; \
+ kg->tname.width = size; \
+ }
#include "kernel/kernel_textures.h"
- else {
- assert(0);
- }
+ else {
+ assert(0);
+ }
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/kernels/cpu/kernel_avx.cpp b/intern/cycles/kernel/kernels/cpu/kernel_avx.cpp
index a645fb4d8dd..0656fc9dd00 100644
--- a/intern/cycles/kernel/kernels/cpu/kernel_avx.cpp
+++ b/intern/cycles/kernel/kernels/cpu/kernel_avx.cpp
@@ -32,7 +32,7 @@
# define __KERNEL_SSE41__
# define __KERNEL_AVX__
# endif
-#endif /* WITH_CYCLES_OPTIMIZED_KERNEL_AVX */
+#endif /* WITH_CYCLES_OPTIMIZED_KERNEL_AVX */
#include "kernel/kernel.h"
#define KERNEL_ARCH cpu_avx
diff --git a/intern/cycles/kernel/kernels/cpu/kernel_avx2.cpp b/intern/cycles/kernel/kernels/cpu/kernel_avx2.cpp
index 6bbb87727b9..5baafdc699e 100644
--- a/intern/cycles/kernel/kernels/cpu/kernel_avx2.cpp
+++ b/intern/cycles/kernel/kernels/cpu/kernel_avx2.cpp
@@ -33,7 +33,7 @@
# define __KERNEL_AVX__
# define __KERNEL_AVX2__
# endif
-#endif /* WITH_CYCLES_OPTIMIZED_KERNEL_AVX2 */
+#endif /* WITH_CYCLES_OPTIMIZED_KERNEL_AVX2 */
#include "kernel/kernel.h"
#define KERNEL_ARCH cpu_avx2
diff --git a/intern/cycles/kernel/kernels/cpu/kernel_cpu.h b/intern/cycles/kernel/kernels/cpu/kernel_cpu.h
index 6bdb8546a24..f5d981fb71a 100644
--- a/intern/cycles/kernel/kernels/cpu/kernel_cpu.h
+++ b/intern/cycles/kernel/kernels/cpu/kernel_cpu.h
@@ -16,25 +16,24 @@
/* Templated common declaration part of all CPU kernels. */
-void KERNEL_FUNCTION_FULL_NAME(path_trace)(KernelGlobals *kg,
- float *buffer,
- int sample,
- int x, int y,
- int offset,
- int stride);
+void KERNEL_FUNCTION_FULL_NAME(path_trace)(
+ KernelGlobals *kg, float *buffer, int sample, int x, int y, int offset, int stride);
void KERNEL_FUNCTION_FULL_NAME(convert_to_byte)(KernelGlobals *kg,
uchar4 *rgba,
float *buffer,
float sample_scale,
- int x, int y,
- int offset, int stride);
+ int x,
+ int y,
+ int offset,
+ int stride);
void KERNEL_FUNCTION_FULL_NAME(convert_to_half_float)(KernelGlobals *kg,
uchar4 *rgba,
float *buffer,
float sample_scale,
- int x, int y,
+ int x,
+ int y,
int offset,
int stride);
@@ -49,24 +48,28 @@ void KERNEL_FUNCTION_FULL_NAME(shader)(KernelGlobals *kg,
/* Split kernels */
-void KERNEL_FUNCTION_FULL_NAME(data_init)(
- KernelGlobals *kg,
- ccl_constant KernelData *data,
- ccl_global void *split_data_buffer,
- int num_elements,
- ccl_global char *ray_state,
- int start_sample,
- int end_sample,
- int sx, int sy, int sw, int sh, int offset, int stride,
- ccl_global int *Queue_index,
- int queuesize,
- ccl_global char *use_queues_flag,
- ccl_global unsigned int *work_pool_wgs,
- unsigned int num_samples,
- ccl_global float *buffer);
+void KERNEL_FUNCTION_FULL_NAME(data_init)(KernelGlobals *kg,
+ ccl_constant KernelData *data,
+ ccl_global void *split_data_buffer,
+ int num_elements,
+ ccl_global char *ray_state,
+ int start_sample,
+ int end_sample,
+ int sx,
+ int sy,
+ int sw,
+ int sh,
+ int offset,
+ int stride,
+ ccl_global int *Queue_index,
+ int queuesize,
+ ccl_global char *use_queues_flag,
+ ccl_global unsigned int *work_pool_wgs,
+ unsigned int num_samples,
+ ccl_global float *buffer);
#define DECLARE_SPLIT_KERNEL_FUNCTION(name) \
- void KERNEL_FUNCTION_FULL_NAME(name)(KernelGlobals *kg, KernelData *data);
+ void KERNEL_FUNCTION_FULL_NAME(name)(KernelGlobals * kg, KernelData * data);
DECLARE_SPLIT_KERNEL_FUNCTION(path_init)
DECLARE_SPLIT_KERNEL_FUNCTION(scene_intersect)
diff --git a/intern/cycles/kernel/kernels/cpu/kernel_cpu_image.h b/intern/cycles/kernel/kernels/cpu/kernel_cpu_image.h
index ae4fd85780d..4289e2bbb85 100644
--- a/intern/cycles/kernel/kernels/cpu/kernel_cpu_image.h
+++ b/intern/cycles/kernel/kernels/cpu/kernel_cpu_image.h
@@ -19,523 +19,508 @@
CCL_NAMESPACE_BEGIN
-template<typename T> struct TextureInterpolator {
+template<typename T> struct TextureInterpolator {
#define SET_CUBIC_SPLINE_WEIGHTS(u, t) \
- { \
- u[0] = (((-1.0f/6.0f)* t + 0.5f) * t - 0.5f) * t + (1.0f/6.0f); \
- u[1] = (( 0.5f * t - 1.0f) * t ) * t + (2.0f/3.0f); \
- u[2] = (( -0.5f * t + 0.5f) * t + 0.5f) * t + (1.0f/6.0f); \
- u[3] = (1.0f / 6.0f) * t * t * t; \
- } (void) 0
-
- static ccl_always_inline float4 read(float4 r)
- {
- return r;
- }
-
- static ccl_always_inline float4 read(uchar4 r)
- {
- float f = 1.0f / 255.0f;
- return make_float4(r.x*f, r.y*f, r.z*f, r.w*f);
- }
-
- static ccl_always_inline float4 read(uchar r)
- {
- float f = r * (1.0f / 255.0f);
- return make_float4(f, f, f, 1.0f);
- }
-
- static ccl_always_inline float4 read(float r)
- {
- /* TODO(dingto): Optimize this, so interpolation
- * happens on float instead of float4 */
- return make_float4(r, r, r, 1.0f);
- }
-
- static ccl_always_inline float4 read(half4 r)
- {
- return half4_to_float4(r);
- }
-
- static ccl_always_inline float4 read(half r)
- {
- float f = half_to_float(r);
- return make_float4(f, f, f, 1.0f);
- }
-
- static ccl_always_inline float4 read(uint16_t r)
- {
- float f = r*(1.0f/65535.0f);
- return make_float4(f, f, f, 1.0f);
- }
-
- static ccl_always_inline float4 read(ushort4 r)
- {
- float f = 1.0f/65535.0f;
- return make_float4(r.x*f, r.y*f, r.z*f, r.w*f);
- }
-
- static ccl_always_inline float4 read(const T *data,
- int x, int y,
- int width, int height)
- {
- if(x < 0 || y < 0 || x >= width || y >= height) {
- return make_float4(0.0f, 0.0f, 0.0f, 0.0f);
- }
- return read(data[y * width + x]);
- }
-
- static ccl_always_inline int wrap_periodic(int x, int width)
- {
- x %= width;
- if(x < 0)
- x += width;
- return x;
- }
-
- static ccl_always_inline int wrap_clamp(int x, int width)
- {
- return clamp(x, 0, width-1);
- }
-
- static ccl_always_inline float frac(float x, int *ix)
- {
- int i = float_to_int(x) - ((x < 0.0f)? 1: 0);
- *ix = i;
- return x - (float)i;
- }
-
- /* ******** 2D interpolation ******** */
-
- static ccl_always_inline float4 interp_closest(const TextureInfo& info,
- float x, float y)
- {
- const T *data = (const T*)info.data;
- const int width = info.width;
- const int height = info.height;
- int ix, iy;
- frac(x*(float)width, &ix);
- frac(y*(float)height, &iy);
- switch(info.extension) {
- case EXTENSION_REPEAT:
- ix = wrap_periodic(ix, width);
- iy = wrap_periodic(iy, height);
- break;
- case EXTENSION_CLIP:
- if(x < 0.0f || y < 0.0f || x > 1.0f || y > 1.0f) {
- return make_float4(0.0f, 0.0f, 0.0f, 0.0f);
- }
- ATTR_FALLTHROUGH;
- case EXTENSION_EXTEND:
- ix = wrap_clamp(ix, width);
- iy = wrap_clamp(iy, height);
- break;
- default:
- kernel_assert(0);
- return make_float4(0.0f, 0.0f, 0.0f, 0.0f);
- }
- return read(data[ix + iy*width]);
- }
-
- static ccl_always_inline float4 interp_linear(const TextureInfo& info,
- float x, float y)
- {
- const T *data = (const T*)info.data;
- const int width = info.width;
- const int height = info.height;
- int ix, iy, nix, niy;
- const float tx = frac(x*(float)width - 0.5f, &ix);
- const float ty = frac(y*(float)height - 0.5f, &iy);
- switch(info.extension) {
- case EXTENSION_REPEAT:
- ix = wrap_periodic(ix, width);
- iy = wrap_periodic(iy, height);
- nix = wrap_periodic(ix+1, width);
- niy = wrap_periodic(iy+1, height);
- break;
- case EXTENSION_CLIP:
- nix = ix + 1;
- niy = iy + 1;
- break;
- case EXTENSION_EXTEND:
- nix = wrap_clamp(ix+1, width);
- niy = wrap_clamp(iy+1, height);
- ix = wrap_clamp(ix, width);
- iy = wrap_clamp(iy, height);
- break;
- default:
- kernel_assert(0);
- return make_float4(0.0f, 0.0f, 0.0f, 0.0f);
- }
- return (1.0f - ty) * (1.0f - tx) * read(data, ix, iy, width, height) +
- (1.0f - ty) * tx * read(data, nix, iy, width, height) +
- ty * (1.0f - tx) * read(data, ix, niy, width, height) +
- ty * tx * read(data, nix, niy, width, height);
- }
-
- static ccl_always_inline float4 interp_cubic(const TextureInfo& info,
- float x, float y)
- {
- const T *data = (const T*)info.data;
- const int width = info.width;
- const int height = info.height;
- int ix, iy, nix, niy;
- const float tx = frac(x*(float)width - 0.5f, &ix);
- const float ty = frac(y*(float)height - 0.5f, &iy);
- int pix, piy, nnix, nniy;
- switch(info.extension) {
- case EXTENSION_REPEAT:
- ix = wrap_periodic(ix, width);
- iy = wrap_periodic(iy, height);
- pix = wrap_periodic(ix-1, width);
- piy = wrap_periodic(iy-1, height);
- nix = wrap_periodic(ix+1, width);
- niy = wrap_periodic(iy+1, height);
- nnix = wrap_periodic(ix+2, width);
- nniy = wrap_periodic(iy+2, height);
- break;
- case EXTENSION_CLIP:
- pix = ix - 1;
- piy = iy - 1;
- nix = ix + 1;
- niy = iy + 1;
- nnix = ix + 2;
- nniy = iy + 2;
- break;
- case EXTENSION_EXTEND:
- pix = wrap_clamp(ix-1, width);
- piy = wrap_clamp(iy-1, height);
- nix = wrap_clamp(ix+1, width);
- niy = wrap_clamp(iy+1, height);
- nnix = wrap_clamp(ix+2, width);
- nniy = wrap_clamp(iy+2, height);
- ix = wrap_clamp(ix, width);
- iy = wrap_clamp(iy, height);
- break;
- default:
- kernel_assert(0);
- return make_float4(0.0f, 0.0f, 0.0f, 0.0f);
- }
- const int xc[4] = {pix, ix, nix, nnix};
- const int yc[4] = {piy, iy, niy, nniy};
- float u[4], v[4];
- /* Some helper macro to keep code reasonable size,
- * let compiler to inline all the matrix multiplications.
- */
+ { \
+ u[0] = (((-1.0f / 6.0f) * t + 0.5f) * t - 0.5f) * t + (1.0f / 6.0f); \
+ u[1] = ((0.5f * t - 1.0f) * t) * t + (2.0f / 3.0f); \
+ u[2] = ((-0.5f * t + 0.5f) * t + 0.5f) * t + (1.0f / 6.0f); \
+ u[3] = (1.0f / 6.0f) * t * t * t; \
+ } \
+ (void)0
+
+ static ccl_always_inline float4 read(float4 r)
+ {
+ return r;
+ }
+
+ static ccl_always_inline float4 read(uchar4 r)
+ {
+ float f = 1.0f / 255.0f;
+ return make_float4(r.x * f, r.y * f, r.z * f, r.w * f);
+ }
+
+ static ccl_always_inline float4 read(uchar r)
+ {
+ float f = r * (1.0f / 255.0f);
+ return make_float4(f, f, f, 1.0f);
+ }
+
+ static ccl_always_inline float4 read(float r)
+ {
+ /* TODO(dingto): Optimize this, so interpolation
+ * happens on float instead of float4 */
+ return make_float4(r, r, r, 1.0f);
+ }
+
+ static ccl_always_inline float4 read(half4 r)
+ {
+ return half4_to_float4(r);
+ }
+
+ static ccl_always_inline float4 read(half r)
+ {
+ float f = half_to_float(r);
+ return make_float4(f, f, f, 1.0f);
+ }
+
+ static ccl_always_inline float4 read(uint16_t r)
+ {
+ float f = r * (1.0f / 65535.0f);
+ return make_float4(f, f, f, 1.0f);
+ }
+
+ static ccl_always_inline float4 read(ushort4 r)
+ {
+ float f = 1.0f / 65535.0f;
+ return make_float4(r.x * f, r.y * f, r.z * f, r.w * f);
+ }
+
+ static ccl_always_inline float4 read(const T *data, int x, int y, int width, int height)
+ {
+ if (x < 0 || y < 0 || x >= width || y >= height) {
+ return make_float4(0.0f, 0.0f, 0.0f, 0.0f);
+ }
+ return read(data[y * width + x]);
+ }
+
+ static ccl_always_inline int wrap_periodic(int x, int width)
+ {
+ x %= width;
+ if (x < 0)
+ x += width;
+ return x;
+ }
+
+ static ccl_always_inline int wrap_clamp(int x, int width)
+ {
+ return clamp(x, 0, width - 1);
+ }
+
+ static ccl_always_inline float frac(float x, int *ix)
+ {
+ int i = float_to_int(x) - ((x < 0.0f) ? 1 : 0);
+ *ix = i;
+ return x - (float)i;
+ }
+
+ /* ******** 2D interpolation ******** */
+
+ static ccl_always_inline float4 interp_closest(const TextureInfo &info, float x, float y)
+ {
+ const T *data = (const T *)info.data;
+ const int width = info.width;
+ const int height = info.height;
+ int ix, iy;
+ frac(x * (float)width, &ix);
+ frac(y * (float)height, &iy);
+ switch (info.extension) {
+ case EXTENSION_REPEAT:
+ ix = wrap_periodic(ix, width);
+ iy = wrap_periodic(iy, height);
+ break;
+ case EXTENSION_CLIP:
+ if (x < 0.0f || y < 0.0f || x > 1.0f || y > 1.0f) {
+ return make_float4(0.0f, 0.0f, 0.0f, 0.0f);
+ }
+ ATTR_FALLTHROUGH;
+ case EXTENSION_EXTEND:
+ ix = wrap_clamp(ix, width);
+ iy = wrap_clamp(iy, height);
+ break;
+ default:
+ kernel_assert(0);
+ return make_float4(0.0f, 0.0f, 0.0f, 0.0f);
+ }
+ return read(data[ix + iy * width]);
+ }
+
+ static ccl_always_inline float4 interp_linear(const TextureInfo &info, float x, float y)
+ {
+ const T *data = (const T *)info.data;
+ const int width = info.width;
+ const int height = info.height;
+ int ix, iy, nix, niy;
+ const float tx = frac(x * (float)width - 0.5f, &ix);
+ const float ty = frac(y * (float)height - 0.5f, &iy);
+ switch (info.extension) {
+ case EXTENSION_REPEAT:
+ ix = wrap_periodic(ix, width);
+ iy = wrap_periodic(iy, height);
+ nix = wrap_periodic(ix + 1, width);
+ niy = wrap_periodic(iy + 1, height);
+ break;
+ case EXTENSION_CLIP:
+ nix = ix + 1;
+ niy = iy + 1;
+ break;
+ case EXTENSION_EXTEND:
+ nix = wrap_clamp(ix + 1, width);
+ niy = wrap_clamp(iy + 1, height);
+ ix = wrap_clamp(ix, width);
+ iy = wrap_clamp(iy, height);
+ break;
+ default:
+ kernel_assert(0);
+ return make_float4(0.0f, 0.0f, 0.0f, 0.0f);
+ }
+ return (1.0f - ty) * (1.0f - tx) * read(data, ix, iy, width, height) +
+ (1.0f - ty) * tx * read(data, nix, iy, width, height) +
+ ty * (1.0f - tx) * read(data, ix, niy, width, height) +
+ ty * tx * read(data, nix, niy, width, height);
+ }
+
+ static ccl_always_inline float4 interp_cubic(const TextureInfo &info, float x, float y)
+ {
+ const T *data = (const T *)info.data;
+ const int width = info.width;
+ const int height = info.height;
+ int ix, iy, nix, niy;
+ const float tx = frac(x * (float)width - 0.5f, &ix);
+ const float ty = frac(y * (float)height - 0.5f, &iy);
+ int pix, piy, nnix, nniy;
+ switch (info.extension) {
+ case EXTENSION_REPEAT:
+ ix = wrap_periodic(ix, width);
+ iy = wrap_periodic(iy, height);
+ pix = wrap_periodic(ix - 1, width);
+ piy = wrap_periodic(iy - 1, height);
+ nix = wrap_periodic(ix + 1, width);
+ niy = wrap_periodic(iy + 1, height);
+ nnix = wrap_periodic(ix + 2, width);
+ nniy = wrap_periodic(iy + 2, height);
+ break;
+ case EXTENSION_CLIP:
+ pix = ix - 1;
+ piy = iy - 1;
+ nix = ix + 1;
+ niy = iy + 1;
+ nnix = ix + 2;
+ nniy = iy + 2;
+ break;
+ case EXTENSION_EXTEND:
+ pix = wrap_clamp(ix - 1, width);
+ piy = wrap_clamp(iy - 1, height);
+ nix = wrap_clamp(ix + 1, width);
+ niy = wrap_clamp(iy + 1, height);
+ nnix = wrap_clamp(ix + 2, width);
+ nniy = wrap_clamp(iy + 2, height);
+ ix = wrap_clamp(ix, width);
+ iy = wrap_clamp(iy, height);
+ break;
+ default:
+ kernel_assert(0);
+ return make_float4(0.0f, 0.0f, 0.0f, 0.0f);
+ }
+ const int xc[4] = {pix, ix, nix, nnix};
+ const int yc[4] = {piy, iy, niy, nniy};
+ float u[4], v[4];
+ /* Some helper macro to keep code reasonable size,
+ * let compiler to inline all the matrix multiplications.
+ */
#define DATA(x, y) (read(data, xc[x], yc[y], width, height))
#define TERM(col) \
- (v[col] * (u[0] * DATA(0, col) + \
- u[1] * DATA(1, col) + \
- u[2] * DATA(2, col) + \
- u[3] * DATA(3, col)))
+ (v[col] * \
+ (u[0] * DATA(0, col) + u[1] * DATA(1, col) + u[2] * DATA(2, col) + u[3] * DATA(3, col)))
- SET_CUBIC_SPLINE_WEIGHTS(u, tx);
- SET_CUBIC_SPLINE_WEIGHTS(v, ty);
+ SET_CUBIC_SPLINE_WEIGHTS(u, tx);
+ SET_CUBIC_SPLINE_WEIGHTS(v, ty);
- /* Actual interpolation. */
- return TERM(0) + TERM(1) + TERM(2) + TERM(3);
+ /* Actual interpolation. */
+ return TERM(0) + TERM(1) + TERM(2) + TERM(3);
#undef TERM
#undef DATA
- }
-
- static ccl_always_inline float4 interp(const TextureInfo& info,
- float x, float y)
- {
- if(UNLIKELY(!info.data)) {
- return make_float4(0.0f, 0.0f, 0.0f, 0.0f);
- }
- switch(info.interpolation) {
- case INTERPOLATION_CLOSEST:
- return interp_closest(info, x, y);
- case INTERPOLATION_LINEAR:
- return interp_linear(info, x, y);
- default:
- return interp_cubic(info, x, y);
- }
- }
-
- /* ******** 3D interpolation ******** */
-
- static ccl_always_inline float4 interp_3d_closest(const TextureInfo& info,
- float x, float y, float z)
- {
- int width = info.width;
- int height = info.height;
- int depth = info.depth;
- int ix, iy, iz;
-
- frac(x*(float)width, &ix);
- frac(y*(float)height, &iy);
- frac(z*(float)depth, &iz);
-
- switch(info.extension) {
- case EXTENSION_REPEAT:
- ix = wrap_periodic(ix, width);
- iy = wrap_periodic(iy, height);
- iz = wrap_periodic(iz, depth);
- break;
- case EXTENSION_CLIP:
- if(x < 0.0f || y < 0.0f || z < 0.0f ||
- x > 1.0f || y > 1.0f || z > 1.0f)
- {
- return make_float4(0.0f, 0.0f, 0.0f, 0.0f);
- }
- ATTR_FALLTHROUGH;
- case EXTENSION_EXTEND:
- ix = wrap_clamp(ix, width);
- iy = wrap_clamp(iy, height);
- iz = wrap_clamp(iz, depth);
- break;
- default:
- kernel_assert(0);
- return make_float4(0.0f, 0.0f, 0.0f, 0.0f);
- }
-
- const T *data = (const T*)info.data;
- return read(data[ix + iy*width + iz*width*height]);
- }
-
- static ccl_always_inline float4 interp_3d_linear(const TextureInfo& info,
- float x, float y, float z)
- {
- int width = info.width;
- int height = info.height;
- int depth = info.depth;
- int ix, iy, iz;
- int nix, niy, niz;
-
- float tx = frac(x*(float)width - 0.5f, &ix);
- float ty = frac(y*(float)height - 0.5f, &iy);
- float tz = frac(z*(float)depth - 0.5f, &iz);
-
- switch(info.extension) {
- case EXTENSION_REPEAT:
- ix = wrap_periodic(ix, width);
- iy = wrap_periodic(iy, height);
- iz = wrap_periodic(iz, depth);
-
- nix = wrap_periodic(ix+1, width);
- niy = wrap_periodic(iy+1, height);
- niz = wrap_periodic(iz+1, depth);
- break;
- case EXTENSION_CLIP:
- if(x < 0.0f || y < 0.0f || z < 0.0f ||
- x > 1.0f || y > 1.0f || z > 1.0f)
- {
- return make_float4(0.0f, 0.0f, 0.0f, 0.0f);
- }
- ATTR_FALLTHROUGH;
- case EXTENSION_EXTEND:
- nix = wrap_clamp(ix+1, width);
- niy = wrap_clamp(iy+1, height);
- niz = wrap_clamp(iz+1, depth);
-
- ix = wrap_clamp(ix, width);
- iy = wrap_clamp(iy, height);
- iz = wrap_clamp(iz, depth);
- break;
- default:
- kernel_assert(0);
- return make_float4(0.0f, 0.0f, 0.0f, 0.0f);
- }
-
- const T *data = (const T*)info.data;
- float4 r;
-
- r = (1.0f - tz)*(1.0f - ty)*(1.0f - tx)*read(data[ix + iy*width + iz*width*height]);
- r += (1.0f - tz)*(1.0f - ty)*tx*read(data[nix + iy*width + iz*width*height]);
- r += (1.0f - tz)*ty*(1.0f - tx)*read(data[ix + niy*width + iz*width*height]);
- r += (1.0f - tz)*ty*tx*read(data[nix + niy*width + iz*width*height]);
-
- r += tz*(1.0f - ty)*(1.0f - tx)*read(data[ix + iy*width + niz*width*height]);
- r += tz*(1.0f - ty)*tx*read(data[nix + iy*width + niz*width*height]);
- r += tz*ty*(1.0f - tx)*read(data[ix + niy*width + niz*width*height]);
- r += tz*ty*tx*read(data[nix + niy*width + niz*width*height]);
-
- return r;
- }
-
- /* TODO(sergey): For some unspeakable reason both GCC-6 and Clang-3.9 are
- * causing stack overflow issue in this function unless it is inlined.
- *
- * Only happens for AVX2 kernel and global __KERNEL_SSE__ vectorization
- * enabled.
- */
+ }
+
+ static ccl_always_inline float4 interp(const TextureInfo &info, float x, float y)
+ {
+ if (UNLIKELY(!info.data)) {
+ return make_float4(0.0f, 0.0f, 0.0f, 0.0f);
+ }
+ switch (info.interpolation) {
+ case INTERPOLATION_CLOSEST:
+ return interp_closest(info, x, y);
+ case INTERPOLATION_LINEAR:
+ return interp_linear(info, x, y);
+ default:
+ return interp_cubic(info, x, y);
+ }
+ }
+
+ /* ******** 3D interpolation ******** */
+
+ static ccl_always_inline float4 interp_3d_closest(const TextureInfo &info,
+ float x,
+ float y,
+ float z)
+ {
+ int width = info.width;
+ int height = info.height;
+ int depth = info.depth;
+ int ix, iy, iz;
+
+ frac(x * (float)width, &ix);
+ frac(y * (float)height, &iy);
+ frac(z * (float)depth, &iz);
+
+ switch (info.extension) {
+ case EXTENSION_REPEAT:
+ ix = wrap_periodic(ix, width);
+ iy = wrap_periodic(iy, height);
+ iz = wrap_periodic(iz, depth);
+ break;
+ case EXTENSION_CLIP:
+ if (x < 0.0f || y < 0.0f || z < 0.0f || x > 1.0f || y > 1.0f || z > 1.0f) {
+ return make_float4(0.0f, 0.0f, 0.0f, 0.0f);
+ }
+ ATTR_FALLTHROUGH;
+ case EXTENSION_EXTEND:
+ ix = wrap_clamp(ix, width);
+ iy = wrap_clamp(iy, height);
+ iz = wrap_clamp(iz, depth);
+ break;
+ default:
+ kernel_assert(0);
+ return make_float4(0.0f, 0.0f, 0.0f, 0.0f);
+ }
+
+ const T *data = (const T *)info.data;
+ return read(data[ix + iy * width + iz * width * height]);
+ }
+
+ static ccl_always_inline float4 interp_3d_linear(const TextureInfo &info,
+ float x,
+ float y,
+ float z)
+ {
+ int width = info.width;
+ int height = info.height;
+ int depth = info.depth;
+ int ix, iy, iz;
+ int nix, niy, niz;
+
+ float tx = frac(x * (float)width - 0.5f, &ix);
+ float ty = frac(y * (float)height - 0.5f, &iy);
+ float tz = frac(z * (float)depth - 0.5f, &iz);
+
+ switch (info.extension) {
+ case EXTENSION_REPEAT:
+ ix = wrap_periodic(ix, width);
+ iy = wrap_periodic(iy, height);
+ iz = wrap_periodic(iz, depth);
+
+ nix = wrap_periodic(ix + 1, width);
+ niy = wrap_periodic(iy + 1, height);
+ niz = wrap_periodic(iz + 1, depth);
+ break;
+ case EXTENSION_CLIP:
+ if (x < 0.0f || y < 0.0f || z < 0.0f || x > 1.0f || y > 1.0f || z > 1.0f) {
+ return make_float4(0.0f, 0.0f, 0.0f, 0.0f);
+ }
+ ATTR_FALLTHROUGH;
+ case EXTENSION_EXTEND:
+ nix = wrap_clamp(ix + 1, width);
+ niy = wrap_clamp(iy + 1, height);
+ niz = wrap_clamp(iz + 1, depth);
+
+ ix = wrap_clamp(ix, width);
+ iy = wrap_clamp(iy, height);
+ iz = wrap_clamp(iz, depth);
+ break;
+ default:
+ kernel_assert(0);
+ return make_float4(0.0f, 0.0f, 0.0f, 0.0f);
+ }
+
+ const T *data = (const T *)info.data;
+ float4 r;
+
+ r = (1.0f - tz) * (1.0f - ty) * (1.0f - tx) *
+ read(data[ix + iy * width + iz * width * height]);
+ r += (1.0f - tz) * (1.0f - ty) * tx * read(data[nix + iy * width + iz * width * height]);
+ r += (1.0f - tz) * ty * (1.0f - tx) * read(data[ix + niy * width + iz * width * height]);
+ r += (1.0f - tz) * ty * tx * read(data[nix + niy * width + iz * width * height]);
+
+ r += tz * (1.0f - ty) * (1.0f - tx) * read(data[ix + iy * width + niz * width * height]);
+ r += tz * (1.0f - ty) * tx * read(data[nix + iy * width + niz * width * height]);
+ r += tz * ty * (1.0f - tx) * read(data[ix + niy * width + niz * width * height]);
+ r += tz * ty * tx * read(data[nix + niy * width + niz * width * height]);
+
+ return r;
+ }
+
+ /* TODO(sergey): For some unspeakable reason both GCC-6 and Clang-3.9 are
+ * causing stack overflow issue in this function unless it is inlined.
+ *
+ * Only happens for AVX2 kernel and global __KERNEL_SSE__ vectorization
+ * enabled.
+ */
#if defined(__GNUC__) || defined(__clang__)
- static ccl_always_inline
+ static ccl_always_inline
#else
- static ccl_never_inline
+ static ccl_never_inline
#endif
- float4 interp_3d_tricubic(const TextureInfo& info, float x, float y, float z)
- {
- int width = info.width;
- int height = info.height;
- int depth = info.depth;
- int ix, iy, iz;
- int nix, niy, niz;
- /* Tricubic b-spline interpolation. */
- const float tx = frac(x*(float)width - 0.5f, &ix);
- const float ty = frac(y*(float)height - 0.5f, &iy);
- const float tz = frac(z*(float)depth - 0.5f, &iz);
- int pix, piy, piz, nnix, nniy, nniz;
-
- switch(info.extension) {
- case EXTENSION_REPEAT:
- ix = wrap_periodic(ix, width);
- iy = wrap_periodic(iy, height);
- iz = wrap_periodic(iz, depth);
-
- pix = wrap_periodic(ix-1, width);
- piy = wrap_periodic(iy-1, height);
- piz = wrap_periodic(iz-1, depth);
-
- nix = wrap_periodic(ix+1, width);
- niy = wrap_periodic(iy+1, height);
- niz = wrap_periodic(iz+1, depth);
-
- nnix = wrap_periodic(ix+2, width);
- nniy = wrap_periodic(iy+2, height);
- nniz = wrap_periodic(iz+2, depth);
- break;
- case EXTENSION_CLIP:
- if(x < 0.0f || y < 0.0f || z < 0.0f ||
- x > 1.0f || y > 1.0f || z > 1.0f)
- {
- return make_float4(0.0f, 0.0f, 0.0f, 0.0f);
- }
- ATTR_FALLTHROUGH;
- case EXTENSION_EXTEND:
- pix = wrap_clamp(ix-1, width);
- piy = wrap_clamp(iy-1, height);
- piz = wrap_clamp(iz-1, depth);
-
- nix = wrap_clamp(ix+1, width);
- niy = wrap_clamp(iy+1, height);
- niz = wrap_clamp(iz+1, depth);
-
- nnix = wrap_clamp(ix+2, width);
- nniy = wrap_clamp(iy+2, height);
- nniz = wrap_clamp(iz+2, depth);
-
- ix = wrap_clamp(ix, width);
- iy = wrap_clamp(iy, height);
- iz = wrap_clamp(iz, depth);
- break;
- default:
- kernel_assert(0);
- return make_float4(0.0f, 0.0f, 0.0f, 0.0f);
- }
-
- const int xc[4] = {pix, ix, nix, nnix};
- const int yc[4] = {width * piy,
- width * iy,
- width * niy,
- width * nniy};
- const int zc[4] = {width * height * piz,
- width * height * iz,
- width * height * niz,
- width * height * nniz};
- float u[4], v[4], w[4];
-
- /* Some helper macro to keep code reasonable size,
- * let compiler to inline all the matrix multiplications.
- */
+ float4
+ interp_3d_tricubic(const TextureInfo &info, float x, float y, float z)
+ {
+ int width = info.width;
+ int height = info.height;
+ int depth = info.depth;
+ int ix, iy, iz;
+ int nix, niy, niz;
+ /* Tricubic b-spline interpolation. */
+ const float tx = frac(x * (float)width - 0.5f, &ix);
+ const float ty = frac(y * (float)height - 0.5f, &iy);
+ const float tz = frac(z * (float)depth - 0.5f, &iz);
+ int pix, piy, piz, nnix, nniy, nniz;
+
+ switch (info.extension) {
+ case EXTENSION_REPEAT:
+ ix = wrap_periodic(ix, width);
+ iy = wrap_periodic(iy, height);
+ iz = wrap_periodic(iz, depth);
+
+ pix = wrap_periodic(ix - 1, width);
+ piy = wrap_periodic(iy - 1, height);
+ piz = wrap_periodic(iz - 1, depth);
+
+ nix = wrap_periodic(ix + 1, width);
+ niy = wrap_periodic(iy + 1, height);
+ niz = wrap_periodic(iz + 1, depth);
+
+ nnix = wrap_periodic(ix + 2, width);
+ nniy = wrap_periodic(iy + 2, height);
+ nniz = wrap_periodic(iz + 2, depth);
+ break;
+ case EXTENSION_CLIP:
+ if (x < 0.0f || y < 0.0f || z < 0.0f || x > 1.0f || y > 1.0f || z > 1.0f) {
+ return make_float4(0.0f, 0.0f, 0.0f, 0.0f);
+ }
+ ATTR_FALLTHROUGH;
+ case EXTENSION_EXTEND:
+ pix = wrap_clamp(ix - 1, width);
+ piy = wrap_clamp(iy - 1, height);
+ piz = wrap_clamp(iz - 1, depth);
+
+ nix = wrap_clamp(ix + 1, width);
+ niy = wrap_clamp(iy + 1, height);
+ niz = wrap_clamp(iz + 1, depth);
+
+ nnix = wrap_clamp(ix + 2, width);
+ nniy = wrap_clamp(iy + 2, height);
+ nniz = wrap_clamp(iz + 2, depth);
+
+ ix = wrap_clamp(ix, width);
+ iy = wrap_clamp(iy, height);
+ iz = wrap_clamp(iz, depth);
+ break;
+ default:
+ kernel_assert(0);
+ return make_float4(0.0f, 0.0f, 0.0f, 0.0f);
+ }
+
+ const int xc[4] = {pix, ix, nix, nnix};
+ const int yc[4] = {width * piy, width * iy, width * niy, width * nniy};
+ const int zc[4] = {
+ width * height * piz, width * height * iz, width * height * niz, width * height * nniz};
+ float u[4], v[4], w[4];
+
+ /* Some helper macro to keep code reasonable size,
+ * let compiler to inline all the matrix multiplications.
+ */
#define DATA(x, y, z) (read(data[xc[x] + yc[y] + zc[z]]))
#define COL_TERM(col, row) \
- (v[col] * (u[0] * DATA(0, col, row) + \
- u[1] * DATA(1, col, row) + \
- u[2] * DATA(2, col, row) + \
- u[3] * DATA(3, col, row)))
+ (v[col] * (u[0] * DATA(0, col, row) + u[1] * DATA(1, col, row) + u[2] * DATA(2, col, row) + \
+ u[3] * DATA(3, col, row)))
#define ROW_TERM(row) \
- (w[row] * (COL_TERM(0, row) + \
- COL_TERM(1, row) + \
- COL_TERM(2, row) + \
- COL_TERM(3, row)))
+ (w[row] * (COL_TERM(0, row) + COL_TERM(1, row) + COL_TERM(2, row) + COL_TERM(3, row)))
- SET_CUBIC_SPLINE_WEIGHTS(u, tx);
- SET_CUBIC_SPLINE_WEIGHTS(v, ty);
- SET_CUBIC_SPLINE_WEIGHTS(w, tz);
+ SET_CUBIC_SPLINE_WEIGHTS(u, tx);
+ SET_CUBIC_SPLINE_WEIGHTS(v, ty);
+ SET_CUBIC_SPLINE_WEIGHTS(w, tz);
- /* Actual interpolation. */
- const T *data = (const T*)info.data;
- return ROW_TERM(0) + ROW_TERM(1) + ROW_TERM(2) + ROW_TERM(3);
+ /* Actual interpolation. */
+ const T *data = (const T *)info.data;
+ return ROW_TERM(0) + ROW_TERM(1) + ROW_TERM(2) + ROW_TERM(3);
#undef COL_TERM
#undef ROW_TERM
#undef DATA
- }
-
- static ccl_always_inline float4 interp_3d(const TextureInfo& info,
- float x, float y, float z,
- InterpolationType interp)
- {
- if(UNLIKELY(!info.data))
- return make_float4(0.0f, 0.0f, 0.0f, 0.0f);
-
- switch((interp == INTERPOLATION_NONE)? info.interpolation: interp) {
- case INTERPOLATION_CLOSEST:
- return interp_3d_closest(info, x, y, z);
- case INTERPOLATION_LINEAR:
- return interp_3d_linear(info, x, y, z);
- default:
- return interp_3d_tricubic(info, x, y, z);
- }
- }
+ }
+
+ static ccl_always_inline float4
+ interp_3d(const TextureInfo &info, float x, float y, float z, InterpolationType interp)
+ {
+ if (UNLIKELY(!info.data))
+ return make_float4(0.0f, 0.0f, 0.0f, 0.0f);
+
+ switch ((interp == INTERPOLATION_NONE) ? info.interpolation : interp) {
+ case INTERPOLATION_CLOSEST:
+ return interp_3d_closest(info, x, y, z);
+ case INTERPOLATION_LINEAR:
+ return interp_3d_linear(info, x, y, z);
+ default:
+ return interp_3d_tricubic(info, x, y, z);
+ }
+ }
#undef SET_CUBIC_SPLINE_WEIGHTS
};
ccl_device float4 kernel_tex_image_interp(KernelGlobals *kg, int id, float x, float y)
{
- const TextureInfo& info = kernel_tex_fetch(__texture_info, id);
-
- switch(kernel_tex_type(id)) {
- case IMAGE_DATA_TYPE_HALF:
- return TextureInterpolator<half>::interp(info, x, y);
- case IMAGE_DATA_TYPE_BYTE:
- return TextureInterpolator<uchar>::interp(info, x, y);
- case IMAGE_DATA_TYPE_USHORT:
- return TextureInterpolator<uint16_t>::interp(info, x, y);
- case IMAGE_DATA_TYPE_FLOAT:
- return TextureInterpolator<float>::interp(info, x, y);
- case IMAGE_DATA_TYPE_HALF4:
- return TextureInterpolator<half4>::interp(info, x, y);
- case IMAGE_DATA_TYPE_BYTE4:
- return TextureInterpolator<uchar4>::interp(info, x, y);
- case IMAGE_DATA_TYPE_USHORT4:
- return TextureInterpolator<ushort4>::interp(info, x, y);
- case IMAGE_DATA_TYPE_FLOAT4:
- return TextureInterpolator<float4>::interp(info, x, y);
- default:
- assert(0);
- return make_float4(TEX_IMAGE_MISSING_R, TEX_IMAGE_MISSING_G, TEX_IMAGE_MISSING_B, TEX_IMAGE_MISSING_A);
- }
+ const TextureInfo &info = kernel_tex_fetch(__texture_info, id);
+
+ switch (kernel_tex_type(id)) {
+ case IMAGE_DATA_TYPE_HALF:
+ return TextureInterpolator<half>::interp(info, x, y);
+ case IMAGE_DATA_TYPE_BYTE:
+ return TextureInterpolator<uchar>::interp(info, x, y);
+ case IMAGE_DATA_TYPE_USHORT:
+ return TextureInterpolator<uint16_t>::interp(info, x, y);
+ case IMAGE_DATA_TYPE_FLOAT:
+ return TextureInterpolator<float>::interp(info, x, y);
+ case IMAGE_DATA_TYPE_HALF4:
+ return TextureInterpolator<half4>::interp(info, x, y);
+ case IMAGE_DATA_TYPE_BYTE4:
+ return TextureInterpolator<uchar4>::interp(info, x, y);
+ case IMAGE_DATA_TYPE_USHORT4:
+ return TextureInterpolator<ushort4>::interp(info, x, y);
+ case IMAGE_DATA_TYPE_FLOAT4:
+ return TextureInterpolator<float4>::interp(info, x, y);
+ default:
+ assert(0);
+ return make_float4(
+ TEX_IMAGE_MISSING_R, TEX_IMAGE_MISSING_G, TEX_IMAGE_MISSING_B, TEX_IMAGE_MISSING_A);
+ }
}
-ccl_device float4 kernel_tex_image_interp_3d(KernelGlobals *kg, int id, float x, float y, float z, InterpolationType interp)
+ccl_device float4 kernel_tex_image_interp_3d(
+ KernelGlobals *kg, int id, float x, float y, float z, InterpolationType interp)
{
- const TextureInfo& info = kernel_tex_fetch(__texture_info, id);
-
- switch(kernel_tex_type(id)) {
- case IMAGE_DATA_TYPE_HALF:
- return TextureInterpolator<half>::interp_3d(info, x, y, z, interp);
- case IMAGE_DATA_TYPE_BYTE:
- return TextureInterpolator<uchar>::interp_3d(info, x, y, z, interp);
- case IMAGE_DATA_TYPE_USHORT:
- return TextureInterpolator<uint16_t>::interp_3d(info, x, y, z, interp);
- case IMAGE_DATA_TYPE_FLOAT:
- return TextureInterpolator<float>::interp_3d(info, x, y, z, interp);
- case IMAGE_DATA_TYPE_HALF4:
- return TextureInterpolator<half4>::interp_3d(info, x, y, z, interp);
- case IMAGE_DATA_TYPE_BYTE4:
- return TextureInterpolator<uchar4>::interp_3d(info, x, y, z, interp);
- case IMAGE_DATA_TYPE_USHORT4:
- return TextureInterpolator<ushort4>::interp_3d(info, x, y, z, interp);
- case IMAGE_DATA_TYPE_FLOAT4:
- return TextureInterpolator<float4>::interp_3d(info, x, y, z, interp);
- default:
- assert(0);
- return make_float4(TEX_IMAGE_MISSING_R, TEX_IMAGE_MISSING_G, TEX_IMAGE_MISSING_B, TEX_IMAGE_MISSING_A);
- }
+ const TextureInfo &info = kernel_tex_fetch(__texture_info, id);
+
+ switch (kernel_tex_type(id)) {
+ case IMAGE_DATA_TYPE_HALF:
+ return TextureInterpolator<half>::interp_3d(info, x, y, z, interp);
+ case IMAGE_DATA_TYPE_BYTE:
+ return TextureInterpolator<uchar>::interp_3d(info, x, y, z, interp);
+ case IMAGE_DATA_TYPE_USHORT:
+ return TextureInterpolator<uint16_t>::interp_3d(info, x, y, z, interp);
+ case IMAGE_DATA_TYPE_FLOAT:
+ return TextureInterpolator<float>::interp_3d(info, x, y, z, interp);
+ case IMAGE_DATA_TYPE_HALF4:
+ return TextureInterpolator<half4>::interp_3d(info, x, y, z, interp);
+ case IMAGE_DATA_TYPE_BYTE4:
+ return TextureInterpolator<uchar4>::interp_3d(info, x, y, z, interp);
+ case IMAGE_DATA_TYPE_USHORT4:
+ return TextureInterpolator<ushort4>::interp_3d(info, x, y, z, interp);
+ case IMAGE_DATA_TYPE_FLOAT4:
+ return TextureInterpolator<float4>::interp_3d(info, x, y, z, interp);
+ default:
+ assert(0);
+ return make_float4(
+ TEX_IMAGE_MISSING_R, TEX_IMAGE_MISSING_G, TEX_IMAGE_MISSING_B, TEX_IMAGE_MISSING_A);
+ }
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/kernels/cpu/kernel_cpu_impl.h b/intern/cycles/kernel/kernels/cpu/kernel_cpu_impl.h
index 759b7e4c20d..9ca3f46b5b6 100644
--- a/intern/cycles/kernel/kernels/cpu/kernel_cpu_impl.h
+++ b/intern/cycles/kernel/kernels/cpu/kernel_cpu_impl.h
@@ -58,14 +58,15 @@
# include "kernel/split/kernel_next_iteration_setup.h"
# include "kernel/split/kernel_indirect_subsurface.h"
# include "kernel/split/kernel_buffer_update.h"
-# endif /* __SPLIT_KERNEL__ */
+# endif /* __SPLIT_KERNEL__ */
#else
-# define STUB_ASSERT(arch, name) assert(!(#name " kernel stub for architecture " #arch " was called!"))
+# define STUB_ASSERT(arch, name) \
+ assert(!(#name " kernel stub for architecture " #arch " was called!"))
# ifdef __SPLIT_KERNEL__
# include "kernel/split/kernel_data_init.h"
-# endif /* __SPLIT_KERNEL__ */
-#endif /* KERNEL_STUB */
+# endif /* __SPLIT_KERNEL__ */
+#endif /* KERNEL_STUB */
CCL_NAMESPACE_BEGIN
@@ -73,31 +74,22 @@ CCL_NAMESPACE_BEGIN
/* Path Tracing */
-void KERNEL_FUNCTION_FULL_NAME(path_trace)(KernelGlobals *kg,
- float *buffer,
- int sample,
- int x, int y,
- int offset,
- int stride)
+void KERNEL_FUNCTION_FULL_NAME(path_trace)(
+ KernelGlobals *kg, float *buffer, int sample, int x, int y, int offset, int stride)
{
-#ifdef KERNEL_STUB
- STUB_ASSERT(KERNEL_ARCH, path_trace);
-#else
-# ifdef __BRANCHED_PATH__
- if(kernel_data.integrator.branched) {
- kernel_branched_path_trace(kg,
- buffer,
- sample,
- x, y,
- offset,
- stride);
- }
- else
-# endif
- {
- kernel_path_trace(kg, buffer, sample, x, y, offset, stride);
- }
-#endif /* KERNEL_STUB */
+# ifdef KERNEL_STUB
+ STUB_ASSERT(KERNEL_ARCH, path_trace);
+# else
+# ifdef __BRANCHED_PATH__
+ if (kernel_data.integrator.branched) {
+ kernel_branched_path_trace(kg, buffer, sample, x, y, offset, stride);
+ }
+ else
+# endif
+ {
+ kernel_path_trace(kg, buffer, sample, x, y, offset, stride);
+ }
+# endif /* KERNEL_STUB */
}
/* Film */
@@ -106,42 +98,32 @@ void KERNEL_FUNCTION_FULL_NAME(convert_to_byte)(KernelGlobals *kg,
uchar4 *rgba,
float *buffer,
float sample_scale,
- int x, int y,
+ int x,
+ int y,
int offset,
int stride)
{
-#ifdef KERNEL_STUB
- STUB_ASSERT(KERNEL_ARCH, convert_to_byte);
-#else
- kernel_film_convert_to_byte(kg,
- rgba,
- buffer,
- sample_scale,
- x, y,
- offset,
- stride);
-#endif /* KERNEL_STUB */
+# ifdef KERNEL_STUB
+ STUB_ASSERT(KERNEL_ARCH, convert_to_byte);
+# else
+ kernel_film_convert_to_byte(kg, rgba, buffer, sample_scale, x, y, offset, stride);
+# endif /* KERNEL_STUB */
}
void KERNEL_FUNCTION_FULL_NAME(convert_to_half_float)(KernelGlobals *kg,
uchar4 *rgba,
float *buffer,
float sample_scale,
- int x, int y,
+ int x,
+ int y,
int offset,
int stride)
{
-#ifdef KERNEL_STUB
- STUB_ASSERT(KERNEL_ARCH, convert_to_half_float);
-#else
- kernel_film_convert_to_half_float(kg,
- rgba,
- buffer,
- sample_scale,
- x, y,
- offset,
- stride);
-#endif /* KERNEL_STUB */
+# ifdef KERNEL_STUB
+ STUB_ASSERT(KERNEL_ARCH, convert_to_half_float);
+# else
+ kernel_film_convert_to_half_float(kg, rgba, buffer, sample_scale, x, y, offset, stride);
+# endif /* KERNEL_STUB */
}
/* Shader Evaluate */
@@ -155,60 +137,53 @@ void KERNEL_FUNCTION_FULL_NAME(shader)(KernelGlobals *kg,
int offset,
int sample)
{
-#ifdef KERNEL_STUB
- STUB_ASSERT(KERNEL_ARCH, shader);
-#else
- if(type >= SHADER_EVAL_BAKE) {
-# ifdef __BAKING__
- kernel_bake_evaluate(kg,
- input,
- output,
- (ShaderEvalType)type,
- filter,
- i,
- offset,
- sample);
-# endif
- }
- else if(type == SHADER_EVAL_DISPLACE) {
- kernel_displace_evaluate(kg, input, output, i);
- }
- else {
- kernel_background_evaluate(kg, input, output, i);
- }
-#endif /* KERNEL_STUB */
+# ifdef KERNEL_STUB
+ STUB_ASSERT(KERNEL_ARCH, shader);
+# else
+ if (type >= SHADER_EVAL_BAKE) {
+# ifdef __BAKING__
+ kernel_bake_evaluate(kg, input, output, (ShaderEvalType)type, filter, i, offset, sample);
+# endif
+ }
+ else if (type == SHADER_EVAL_DISPLACE) {
+ kernel_displace_evaluate(kg, input, output, i);
+ }
+ else {
+ kernel_background_evaluate(kg, input, output, i);
+ }
+# endif /* KERNEL_STUB */
}
-#else /* __SPLIT_KERNEL__ */
+#else /* __SPLIT_KERNEL__ */
/* Split Kernel Path Tracing */
-#ifdef KERNEL_STUB
-# define DEFINE_SPLIT_KERNEL_FUNCTION(name) \
- void KERNEL_FUNCTION_FULL_NAME(name)(KernelGlobals *kg, KernelData* /*data*/) \
- { \
- STUB_ASSERT(KERNEL_ARCH, name); \
- }
-
-# define DEFINE_SPLIT_KERNEL_FUNCTION_LOCALS(name, type) \
- void KERNEL_FUNCTION_FULL_NAME(name)(KernelGlobals *kg, KernelData* /*data*/) \
- { \
- STUB_ASSERT(KERNEL_ARCH, name); \
- }
-#else
-# define DEFINE_SPLIT_KERNEL_FUNCTION(name) \
- void KERNEL_FUNCTION_FULL_NAME(name)(KernelGlobals *kg, KernelData* /*data*/) \
- { \
- kernel_##name(kg); \
- }
-
-# define DEFINE_SPLIT_KERNEL_FUNCTION_LOCALS(name, type) \
- void KERNEL_FUNCTION_FULL_NAME(name)(KernelGlobals *kg, KernelData* /*data*/) \
- { \
- ccl_local type locals; \
- kernel_##name(kg, &locals); \
- }
-#endif /* KERNEL_STUB */
+# ifdef KERNEL_STUB
+# define DEFINE_SPLIT_KERNEL_FUNCTION(name) \
+ void KERNEL_FUNCTION_FULL_NAME(name)(KernelGlobals * kg, KernelData * /*data*/) \
+ { \
+ STUB_ASSERT(KERNEL_ARCH, name); \
+ }
+
+# define DEFINE_SPLIT_KERNEL_FUNCTION_LOCALS(name, type) \
+ void KERNEL_FUNCTION_FULL_NAME(name)(KernelGlobals * kg, KernelData * /*data*/) \
+ { \
+ STUB_ASSERT(KERNEL_ARCH, name); \
+ }
+# else
+# define DEFINE_SPLIT_KERNEL_FUNCTION(name) \
+ void KERNEL_FUNCTION_FULL_NAME(name)(KernelGlobals * kg, KernelData * /*data*/) \
+ { \
+ kernel_##name(kg); \
+ }
+
+# define DEFINE_SPLIT_KERNEL_FUNCTION_LOCALS(name, type) \
+ void KERNEL_FUNCTION_FULL_NAME(name)(KernelGlobals * kg, KernelData * /*data*/) \
+ { \
+ ccl_local type locals; \
+ kernel_##name(kg, &locals); \
+ }
+# endif /* KERNEL_STUB */
DEFINE_SPLIT_KERNEL_FUNCTION(path_init)
DEFINE_SPLIT_KERNEL_FUNCTION(scene_intersect)
@@ -219,7 +194,8 @@ DEFINE_SPLIT_KERNEL_FUNCTION(indirect_background)
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(holdout_emission_blurring_pathtermination_ao,
+ BackgroundAOLocals)
DEFINE_SPLIT_KERNEL_FUNCTION(subsurface_scatter)
DEFINE_SPLIT_KERNEL_FUNCTION_LOCALS(direct_lighting, uint)
DEFINE_SPLIT_KERNEL_FUNCTION(shadow_blocked_ao)
@@ -228,7 +204,7 @@ DEFINE_SPLIT_KERNEL_FUNCTION_LOCALS(enqueue_inactive, uint)
DEFINE_SPLIT_KERNEL_FUNCTION_LOCALS(next_iteration_setup, uint)
DEFINE_SPLIT_KERNEL_FUNCTION(indirect_subsurface)
DEFINE_SPLIT_KERNEL_FUNCTION_LOCALS(buffer_update, uint)
-#endif /* __SPLIT_KERNEL__ */
+#endif /* __SPLIT_KERNEL__ */
#undef KERNEL_STUB
#undef STUB_ASSERT
diff --git a/intern/cycles/kernel/kernels/cpu/kernel_split.cpp b/intern/cycles/kernel/kernels/cpu/kernel_split.cpp
index c5e199b0a69..989f5e5aaa8 100644
--- a/intern/cycles/kernel/kernels/cpu/kernel_split.cpp
+++ b/intern/cycles/kernel/kernels/cpu/kernel_split.cpp
@@ -54,7 +54,7 @@
/* quiet unused define warnings */
#if defined(__KERNEL_SSE2__)
- /* do nothing */
+/* do nothing */
#endif
#include "kernel/kernel.h"
diff --git a/intern/cycles/kernel/kernels/cpu/kernel_split_avx.cpp b/intern/cycles/kernel/kernels/cpu/kernel_split_avx.cpp
index 6ba3425a343..1b2e2516751 100644
--- a/intern/cycles/kernel/kernels/cpu/kernel_split_avx.cpp
+++ b/intern/cycles/kernel/kernels/cpu/kernel_split_avx.cpp
@@ -34,7 +34,7 @@
# define __KERNEL_SSE41__
# define __KERNEL_AVX__
# endif
-#endif /* WITH_CYCLES_OPTIMIZED_KERNEL_AVX */
+#endif /* WITH_CYCLES_OPTIMIZED_KERNEL_AVX */
#include "kernel/kernel.h"
#define KERNEL_ARCH cpu_avx
diff --git a/intern/cycles/kernel/kernels/cpu/kernel_split_avx2.cpp b/intern/cycles/kernel/kernels/cpu/kernel_split_avx2.cpp
index 76b2d77ebb8..43b8bfbf864 100644
--- a/intern/cycles/kernel/kernels/cpu/kernel_split_avx2.cpp
+++ b/intern/cycles/kernel/kernels/cpu/kernel_split_avx2.cpp
@@ -35,7 +35,7 @@
# define __KERNEL_AVX__
# define __KERNEL_AVX2__
# endif
-#endif /* WITH_CYCLES_OPTIMIZED_KERNEL_AVX2 */
+#endif /* WITH_CYCLES_OPTIMIZED_KERNEL_AVX2 */
#include "kernel/kernel.h"
#define KERNEL_ARCH cpu_avx2
diff --git a/intern/cycles/kernel/kernels/cpu/kernel_split_sse2.cpp b/intern/cycles/kernel/kernels/cpu/kernel_split_sse2.cpp
index b468b6f44c8..9743789179d 100644
--- a/intern/cycles/kernel/kernels/cpu/kernel_split_sse2.cpp
+++ b/intern/cycles/kernel/kernels/cpu/kernel_split_sse2.cpp
@@ -29,7 +29,7 @@
# if !(defined(__GNUC__) && (defined(i386) || defined(_M_IX86)))
# define __KERNEL_SSE2__
# endif
-#endif /* WITH_CYCLES_OPTIMIZED_KERNEL_SSE2 */
+#endif /* WITH_CYCLES_OPTIMIZED_KERNEL_SSE2 */
#include "kernel/kernel.h"
#define KERNEL_ARCH cpu_sse2
diff --git a/intern/cycles/kernel/kernels/cpu/kernel_split_sse3.cpp b/intern/cycles/kernel/kernels/cpu/kernel_split_sse3.cpp
index 3e5792d0b17..1bec7633500 100644
--- a/intern/cycles/kernel/kernels/cpu/kernel_split_sse3.cpp
+++ b/intern/cycles/kernel/kernels/cpu/kernel_split_sse3.cpp
@@ -31,7 +31,7 @@
# define __KERNEL_SSE3__
# define __KERNEL_SSSE3__
# endif
-#endif /* WITH_CYCLES_OPTIMIZED_KERNEL_SSE3 */
+#endif /* WITH_CYCLES_OPTIMIZED_KERNEL_SSE3 */
#include "kernel/kernel.h"
#define KERNEL_ARCH cpu_sse3
diff --git a/intern/cycles/kernel/kernels/cpu/kernel_split_sse41.cpp b/intern/cycles/kernel/kernels/cpu/kernel_split_sse41.cpp
index 3629f21cd29..c0efc2350e9 100644
--- a/intern/cycles/kernel/kernels/cpu/kernel_split_sse41.cpp
+++ b/intern/cycles/kernel/kernels/cpu/kernel_split_sse41.cpp
@@ -32,7 +32,7 @@
# define __KERNEL_SSSE3__
# define __KERNEL_SSE41__
# endif
-#endif /* WITH_CYCLES_OPTIMIZED_KERNEL_SSE41 */
+#endif /* WITH_CYCLES_OPTIMIZED_KERNEL_SSE41 */
#include "kernel/kernel.h"
#define KERNEL_ARCH cpu_sse41
diff --git a/intern/cycles/kernel/kernels/cpu/kernel_sse2.cpp b/intern/cycles/kernel/kernels/cpu/kernel_sse2.cpp
index 57530c88710..173be8e93ce 100644
--- a/intern/cycles/kernel/kernels/cpu/kernel_sse2.cpp
+++ b/intern/cycles/kernel/kernels/cpu/kernel_sse2.cpp
@@ -27,7 +27,7 @@
# if !(defined(__GNUC__) && (defined(i386) || defined(_M_IX86)))
# define __KERNEL_SSE2__
# endif
-#endif /* WITH_CYCLES_OPTIMIZED_KERNEL_SSE2 */
+#endif /* WITH_CYCLES_OPTIMIZED_KERNEL_SSE2 */
#include "kernel/kernel.h"
#define KERNEL_ARCH cpu_sse2
diff --git a/intern/cycles/kernel/kernels/cpu/kernel_sse3.cpp b/intern/cycles/kernel/kernels/cpu/kernel_sse3.cpp
index c607753bc4b..31273fe3344 100644
--- a/intern/cycles/kernel/kernels/cpu/kernel_sse3.cpp
+++ b/intern/cycles/kernel/kernels/cpu/kernel_sse3.cpp
@@ -29,7 +29,7 @@
# define __KERNEL_SSE3__
# define __KERNEL_SSSE3__
# endif
-#endif /* WITH_CYCLES_OPTIMIZED_KERNEL_SSE3 */
+#endif /* WITH_CYCLES_OPTIMIZED_KERNEL_SSE3 */
#include "kernel/kernel.h"
#define KERNEL_ARCH cpu_sse3
diff --git a/intern/cycles/kernel/kernels/cpu/kernel_sse41.cpp b/intern/cycles/kernel/kernels/cpu/kernel_sse41.cpp
index a278554731c..1d020b7fee6 100644
--- a/intern/cycles/kernel/kernels/cpu/kernel_sse41.cpp
+++ b/intern/cycles/kernel/kernels/cpu/kernel_sse41.cpp
@@ -30,7 +30,7 @@
# define __KERNEL_SSSE3__
# define __KERNEL_SSE41__
# endif
-#endif /* WITH_CYCLES_OPTIMIZED_KERNEL_SSE41 */
+#endif /* WITH_CYCLES_OPTIMIZED_KERNEL_SSE41 */
#include "kernel/kernel.h"
#define KERNEL_ARCH cpu_sse41
diff --git a/intern/cycles/kernel/kernels/cuda/kernel_config.h b/intern/cycles/kernel/kernels/cuda/kernel_config.h
index 6d41dc15785..d9f349837a8 100644
--- a/intern/cycles/kernel/kernels/cuda/kernel_config.h
+++ b/intern/cycles/kernel/kernels/cuda/kernel_config.h
@@ -81,7 +81,6 @@
# define CUDA_KERNEL_MAX_REGISTERS 64
# define CUDA_KERNEL_BRANCHED_MAX_REGISTERS 72
-
/* unknown architecture */
#else
# error "Unknown or unsupported CUDA architecture, can't determine launch bounds"
@@ -96,18 +95,19 @@
* given the maximum number of registers per thread. */
#define CUDA_LAUNCH_BOUNDS(threads_block_width, thread_num_registers) \
- __launch_bounds__( \
- threads_block_width*threads_block_width, \
- CUDA_MULTIPRESSOR_MAX_REGISTERS/(threads_block_width*threads_block_width*thread_num_registers) \
- )
+ __launch_bounds__(threads_block_width *threads_block_width, \
+ CUDA_MULTIPRESSOR_MAX_REGISTERS / \
+ (threads_block_width * threads_block_width * thread_num_registers))
/* sanity checks */
-#if CUDA_THREADS_BLOCK_WIDTH*CUDA_THREADS_BLOCK_WIDTH > CUDA_BLOCK_MAX_THREADS
+#if CUDA_THREADS_BLOCK_WIDTH * CUDA_THREADS_BLOCK_WIDTH > CUDA_BLOCK_MAX_THREADS
# error "Maximum number of threads per block exceeded"
#endif
-#if CUDA_MULTIPRESSOR_MAX_REGISTERS/(CUDA_THREADS_BLOCK_WIDTH*CUDA_THREADS_BLOCK_WIDTH*CUDA_KERNEL_MAX_REGISTERS) > CUDA_MULTIPROCESSOR_MAX_BLOCKS
+#if CUDA_MULTIPRESSOR_MAX_REGISTERS / \
+ (CUDA_THREADS_BLOCK_WIDTH * CUDA_THREADS_BLOCK_WIDTH * CUDA_KERNEL_MAX_REGISTERS) > \
+ CUDA_MULTIPROCESSOR_MAX_BLOCKS
# error "Maximum number of blocks per multiprocessor exceeded"
#endif
diff --git a/intern/cycles/kernel/kernels/cuda/kernel_cuda_image.h b/intern/cycles/kernel/kernels/cuda/kernel_cuda_image.h
index 37cfbbcb235..7c68f08ea10 100644
--- a/intern/cycles/kernel/kernels/cuda/kernel_cuda_image.h
+++ b/intern/cycles/kernel/kernels/cuda/kernel_cuda_image.h
@@ -17,174 +17,165 @@
/* w0, w1, w2, and w3 are the four cubic B-spline basis functions. */
ccl_device float cubic_w0(float a)
{
- return (1.0f/6.0f)*(a*(a*(-a + 3.0f) - 3.0f) + 1.0f);
+ return (1.0f / 6.0f) * (a * (a * (-a + 3.0f) - 3.0f) + 1.0f);
}
ccl_device float cubic_w1(float a)
{
- return (1.0f/6.0f)*(a*a*(3.0f*a - 6.0f) + 4.0f);
+ return (1.0f / 6.0f) * (a * a * (3.0f * a - 6.0f) + 4.0f);
}
ccl_device float cubic_w2(float a)
{
- return (1.0f/6.0f)*(a*(a*(-3.0f*a + 3.0f) + 3.0f) + 1.0f);
+ return (1.0f / 6.0f) * (a * (a * (-3.0f * a + 3.0f) + 3.0f) + 1.0f);
}
ccl_device float cubic_w3(float a)
{
- return (1.0f/6.0f)*(a*a*a);
+ return (1.0f / 6.0f) * (a * a * a);
}
/* g0 and g1 are the two amplitude functions. */
ccl_device float cubic_g0(float a)
{
- return cubic_w0(a) + cubic_w1(a);
+ return cubic_w0(a) + cubic_w1(a);
}
ccl_device float cubic_g1(float a)
{
- return cubic_w2(a) + cubic_w3(a);
+ return cubic_w2(a) + cubic_w3(a);
}
/* h0 and h1 are the two offset functions */
ccl_device float cubic_h0(float a)
{
- /* Note +0.5 offset to compensate for CUDA linear filtering convention. */
- return -1.0f + cubic_w1(a) / (cubic_w0(a) + cubic_w1(a)) + 0.5f;
+ /* Note +0.5 offset to compensate for CUDA linear filtering convention. */
+ return -1.0f + cubic_w1(a) / (cubic_w0(a) + cubic_w1(a)) + 0.5f;
}
ccl_device float cubic_h1(float a)
{
- return 1.0f + cubic_w3(a) / (cubic_w2(a) + cubic_w3(a)) + 0.5f;
+ return 1.0f + cubic_w3(a) / (cubic_w2(a) + cubic_w3(a)) + 0.5f;
}
/* Fast bicubic texture lookup using 4 bilinear lookups, adapted from CUDA samples. */
template<typename T>
-ccl_device T kernel_tex_image_interp_bicubic(const TextureInfo& info, CUtexObject tex, float x, float y)
+ccl_device T
+kernel_tex_image_interp_bicubic(const TextureInfo &info, CUtexObject tex, float x, float y)
{
- x = (x * info.width) - 0.5f;
- y = (y * info.height) - 0.5f;
-
- float px = floor(x);
- float py = floor(y);
- float fx = x - px;
- float fy = y - py;
-
- float g0x = cubic_g0(fx);
- float g1x = cubic_g1(fx);
- float x0 = (px + cubic_h0(fx)) / info.width;
- float x1 = (px + cubic_h1(fx)) / info.width;
- float y0 = (py + cubic_h0(fy)) / info.height;
- float y1 = (py + cubic_h1(fy)) / info.height;
-
- return cubic_g0(fy) * (g0x * tex2D<T>(tex, x0, y0) +
- g1x * tex2D<T>(tex, x1, y0)) +
- cubic_g1(fy) * (g0x * tex2D<T>(tex, x0, y1) +
- g1x * tex2D<T>(tex, x1, y1));
+ x = (x * info.width) - 0.5f;
+ y = (y * info.height) - 0.5f;
+
+ float px = floor(x);
+ float py = floor(y);
+ float fx = x - px;
+ float fy = y - py;
+
+ float g0x = cubic_g0(fx);
+ float g1x = cubic_g1(fx);
+ float x0 = (px + cubic_h0(fx)) / info.width;
+ float x1 = (px + cubic_h1(fx)) / info.width;
+ float y0 = (py + cubic_h0(fy)) / info.height;
+ float y1 = (py + cubic_h1(fy)) / info.height;
+
+ return cubic_g0(fy) * (g0x * tex2D<T>(tex, x0, y0) + g1x * tex2D<T>(tex, x1, y0)) +
+ cubic_g1(fy) * (g0x * tex2D<T>(tex, x0, y1) + g1x * tex2D<T>(tex, x1, y1));
}
/* Fast tricubic texture lookup using 8 trilinear lookups. */
template<typename T>
-ccl_device T kernel_tex_image_interp_bicubic_3d(const TextureInfo& info, CUtexObject tex, float x, float y, float z)
+ccl_device T kernel_tex_image_interp_bicubic_3d(
+ const TextureInfo &info, CUtexObject tex, float x, float y, float z)
{
- x = (x * info.width) - 0.5f;
- y = (y * info.height) - 0.5f;
- z = (z * info.depth) - 0.5f;
-
- float px = floor(x);
- float py = floor(y);
- float pz = floor(z);
- float fx = x - px;
- float fy = y - py;
- float fz = z - pz;
-
- float g0x = cubic_g0(fx);
- float g1x = cubic_g1(fx);
- float g0y = cubic_g0(fy);
- float g1y = cubic_g1(fy);
- float g0z = cubic_g0(fz);
- float g1z = cubic_g1(fz);
-
- float x0 = (px + cubic_h0(fx)) / info.width;
- float x1 = (px + cubic_h1(fx)) / info.width;
- float y0 = (py + cubic_h0(fy)) / info.height;
- float y1 = (py + cubic_h1(fy)) / info.height;
- float z0 = (pz + cubic_h0(fz)) / info.depth;
- float z1 = (pz + cubic_h1(fz)) / info.depth;
-
- return g0z * (g0y * (g0x * tex3D<T>(tex, x0, y0, z0) +
- g1x * tex3D<T>(tex, x1, y0, z0)) +
- g1y * (g0x * tex3D<T>(tex, x0, y1, z0) +
- g1x * tex3D<T>(tex, x1, y1, z0))) +
- g1z * (g0y * (g0x * tex3D<T>(tex, x0, y0, z1) +
- g1x * tex3D<T>(tex, x1, y0, z1)) +
- g1y * (g0x * tex3D<T>(tex, x0, y1, z1) +
- g1x * tex3D<T>(tex, x1, y1, z1)));
+ x = (x * info.width) - 0.5f;
+ y = (y * info.height) - 0.5f;
+ z = (z * info.depth) - 0.5f;
+
+ float px = floor(x);
+ float py = floor(y);
+ float pz = floor(z);
+ float fx = x - px;
+ float fy = y - py;
+ float fz = z - pz;
+
+ float g0x = cubic_g0(fx);
+ float g1x = cubic_g1(fx);
+ float g0y = cubic_g0(fy);
+ float g1y = cubic_g1(fy);
+ float g0z = cubic_g0(fz);
+ float g1z = cubic_g1(fz);
+
+ float x0 = (px + cubic_h0(fx)) / info.width;
+ float x1 = (px + cubic_h1(fx)) / info.width;
+ float y0 = (py + cubic_h0(fy)) / info.height;
+ float y1 = (py + cubic_h1(fy)) / info.height;
+ float z0 = (pz + cubic_h0(fz)) / info.depth;
+ float z1 = (pz + cubic_h1(fz)) / info.depth;
+
+ return g0z * (g0y * (g0x * tex3D<T>(tex, x0, y0, z0) + g1x * tex3D<T>(tex, x1, y0, z0)) +
+ g1y * (g0x * tex3D<T>(tex, x0, y1, z0) + g1x * tex3D<T>(tex, x1, y1, z0))) +
+ g1z * (g0y * (g0x * tex3D<T>(tex, x0, y0, z1) + g1x * tex3D<T>(tex, x1, y0, z1)) +
+ g1y * (g0x * tex3D<T>(tex, x0, y1, z1) + g1x * tex3D<T>(tex, x1, y1, z1)));
}
ccl_device float4 kernel_tex_image_interp(KernelGlobals *kg, int id, float x, float y)
{
- const TextureInfo& info = kernel_tex_fetch(__texture_info, id);
- CUtexObject tex = (CUtexObject)info.data;
-
- /* float4, byte4, ushort4 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 ||
- texture_type == IMAGE_DATA_TYPE_USHORT4)
- {
- if(info.interpolation == INTERPOLATION_CUBIC) {
- return kernel_tex_image_interp_bicubic<float4>(info, tex, x, y);
- }
- else {
- return tex2D<float4>(tex, x, y);
- }
- }
- /* float, byte and half */
- else {
- float f;
-
- if(info.interpolation == INTERPOLATION_CUBIC) {
- f = kernel_tex_image_interp_bicubic<float>(info, tex, x, y);
- }
- else {
- f = tex2D<float>(tex, x, y);
- }
-
- return make_float4(f, f, f, 1.0f);
- }
+ const TextureInfo &info = kernel_tex_fetch(__texture_info, id);
+ CUtexObject tex = (CUtexObject)info.data;
+
+ /* float4, byte4, ushort4 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 || texture_type == IMAGE_DATA_TYPE_USHORT4) {
+ if (info.interpolation == INTERPOLATION_CUBIC) {
+ return kernel_tex_image_interp_bicubic<float4>(info, tex, x, y);
+ }
+ else {
+ return tex2D<float4>(tex, x, y);
+ }
+ }
+ /* float, byte and half */
+ else {
+ float f;
+
+ if (info.interpolation == INTERPOLATION_CUBIC) {
+ f = kernel_tex_image_interp_bicubic<float>(info, tex, x, y);
+ }
+ else {
+ f = tex2D<float>(tex, x, y);
+ }
+
+ return make_float4(f, f, f, 1.0f);
+ }
}
-ccl_device float4 kernel_tex_image_interp_3d(KernelGlobals *kg, int id, float x, float y, float z, InterpolationType interp)
+ccl_device float4 kernel_tex_image_interp_3d(
+ KernelGlobals *kg, int id, float x, float y, float z, InterpolationType interp)
{
- const TextureInfo& info = kernel_tex_fetch(__texture_info, id);
- CUtexObject tex = (CUtexObject)info.data;
- uint interpolation = (interp == INTERPOLATION_NONE)? info.interpolation: interp;
-
- 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 ||
- texture_type == IMAGE_DATA_TYPE_USHORT4)
- {
- if(interpolation == INTERPOLATION_CUBIC) {
- return kernel_tex_image_interp_bicubic_3d<float4>(info, tex, x, y, z);
- }
- else {
- return tex3D<float4>(tex, x, y, z);
- }
- }
- else {
- float f;
-
- if(interpolation == INTERPOLATION_CUBIC) {
- f = kernel_tex_image_interp_bicubic_3d<float>(info, tex, x, y, z);
- }
- else {
- f = tex3D<float>(tex, x, y, z);
- }
-
- return make_float4(f, f, f, 1.0f);
- }
+ const TextureInfo &info = kernel_tex_fetch(__texture_info, id);
+ CUtexObject tex = (CUtexObject)info.data;
+ uint interpolation = (interp == INTERPOLATION_NONE) ? info.interpolation : interp;
+
+ 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 || texture_type == IMAGE_DATA_TYPE_USHORT4) {
+ if (interpolation == INTERPOLATION_CUBIC) {
+ return kernel_tex_image_interp_bicubic_3d<float4>(info, tex, x, y, z);
+ }
+ else {
+ return tex3D<float4>(tex, x, y, z);
+ }
+ }
+ else {
+ float f;
+
+ if (interpolation == INTERPOLATION_CUBIC) {
+ f = kernel_tex_image_interp_bicubic_3d<float>(info, tex, x, y, z);
+ }
+ else {
+ f = tex3D<float>(tex, x, y, z);
+ }
+
+ return make_float4(f, f, f, 1.0f);
+ }
}
diff --git a/intern/cycles/kernel/kernels/opencl/kernel_opencl_image.h b/intern/cycles/kernel/kernels/opencl/kernel_opencl_image.h
index 79af831c2fb..b6390679331 100644
--- a/intern/cycles/kernel/kernels/opencl/kernel_opencl_image.h
+++ b/intern/cycles/kernel/kernels/opencl/kernel_opencl_image.h
@@ -16,254 +16,257 @@
/* For OpenCL we do manual lookup and interpolation. */
-ccl_device_inline ccl_global TextureInfo* kernel_tex_info(KernelGlobals *kg, uint id) {
- const uint tex_offset = id
-#define KERNEL_TEX(type, name) + 1
+ccl_device_inline ccl_global TextureInfo *kernel_tex_info(KernelGlobals *kg, uint id)
+{
+ const uint tex_offset = id
+#define KERNEL_TEX(type, name) +1
#include "kernel/kernel_textures.h"
- ;
+ ;
- return &((ccl_global TextureInfo*)kg->buffers[0])[tex_offset];
+ return &((ccl_global TextureInfo *)kg->buffers[0])[tex_offset];
}
-#define tex_fetch(type, info, index) ((ccl_global type*)(kg->buffers[info->cl_buffer] + info->data))[(index)]
+#define tex_fetch(type, info, index) \
+ ((ccl_global type *)(kg->buffers[info->cl_buffer] + info->data))[(index)]
ccl_device_inline int svm_image_texture_wrap_periodic(int x, int width)
{
- x %= width;
- if(x < 0)
- x += width;
- return x;
+ x %= width;
+ if (x < 0)
+ x += width;
+ return x;
}
ccl_device_inline int svm_image_texture_wrap_clamp(int x, int width)
{
- return clamp(x, 0, width-1);
+ return clamp(x, 0, width - 1);
}
-ccl_device_inline float4 svm_image_texture_read(KernelGlobals *kg, const ccl_global TextureInfo *info, int id, int offset)
+ccl_device_inline float4 svm_image_texture_read(KernelGlobals *kg,
+ const ccl_global TextureInfo *info,
+ int id,
+ int offset)
{
- const int texture_type = kernel_tex_type(id);
-
- /* Float4 */
- if(texture_type == IMAGE_DATA_TYPE_FLOAT4) {
- return tex_fetch(float4, info, offset);
- }
- /* Byte4 */
- else if(texture_type == IMAGE_DATA_TYPE_BYTE4) {
- uchar4 r = tex_fetch(uchar4, info, offset);
- float f = 1.0f/255.0f;
- return make_float4(r.x*f, r.y*f, r.z*f, r.w*f);
- }
- /* Ushort4 */
- else if(texture_type == IMAGE_DATA_TYPE_USHORT4) {
- ushort4 r = tex_fetch(ushort4, info, offset);
- float f = 1.0f/65535.f;
- return make_float4(r.x*f, r.y*f, r.z*f, r.w*f);
- }
- /* Float */
- else if(texture_type == IMAGE_DATA_TYPE_FLOAT) {
- float f = tex_fetch(float, info, offset);
- return make_float4(f, f, f, 1.0f);
- }
- /* UShort */
- else if(texture_type == IMAGE_DATA_TYPE_USHORT) {
- ushort r = tex_fetch(ushort, info, offset);
- float f = r * (1.0f / 65535.0f);
- return make_float4(f, f, f, 1.0f);
- }
- /* Byte */
+ const int texture_type = kernel_tex_type(id);
+
+ /* Float4 */
+ if (texture_type == IMAGE_DATA_TYPE_FLOAT4) {
+ return tex_fetch(float4, info, offset);
+ }
+ /* Byte4 */
+ else if (texture_type == IMAGE_DATA_TYPE_BYTE4) {
+ uchar4 r = tex_fetch(uchar4, info, offset);
+ float f = 1.0f / 255.0f;
+ return make_float4(r.x * f, r.y * f, r.z * f, r.w * f);
+ }
+ /* Ushort4 */
+ else if (texture_type == IMAGE_DATA_TYPE_USHORT4) {
+ ushort4 r = tex_fetch(ushort4, info, offset);
+ float f = 1.0f / 65535.f;
+ return make_float4(r.x * f, r.y * f, r.z * f, r.w * f);
+ }
+ /* Float */
+ else if (texture_type == IMAGE_DATA_TYPE_FLOAT) {
+ float f = tex_fetch(float, info, offset);
+ return make_float4(f, f, f, 1.0f);
+ }
+ /* UShort */
+ else if (texture_type == IMAGE_DATA_TYPE_USHORT) {
+ ushort r = tex_fetch(ushort, info, offset);
+ float f = r * (1.0f / 65535.0f);
+ return make_float4(f, f, f, 1.0f);
+ }
+ /* Byte */
#ifdef cl_khr_fp16
- /* half and half4 are optional in OpenCL */
- else if(texture_type == IMAGE_DATA_TYPE_HALF) {
- float f = tex_fetch(half, info, offset);
- return make_float4(f, f, f, 1.0f);
- }
- else if(texture_type == IMAGE_DATA_TYPE_HALF4) {
- half4 r = tex_fetch(half4, info, offset);
- return make_float4(r.x, r.y, r.z, r.w);
- }
+ /* half and half4 are optional in OpenCL */
+ else if (texture_type == IMAGE_DATA_TYPE_HALF) {
+ float f = tex_fetch(half, info, offset);
+ return make_float4(f, f, f, 1.0f);
+ }
+ else if (texture_type == IMAGE_DATA_TYPE_HALF4) {
+ half4 r = tex_fetch(half4, info, offset);
+ return make_float4(r.x, r.y, r.z, r.w);
+ }
#endif
- else {
- uchar r = tex_fetch(uchar, info, offset);
- float f = r * (1.0f/255.0f);
- return make_float4(f, f, f, 1.0f);
- }
+ else {
+ uchar r = tex_fetch(uchar, info, offset);
+ float f = r * (1.0f / 255.0f);
+ return make_float4(f, f, f, 1.0f);
+ }
}
ccl_device_inline float4 svm_image_texture_read_2d(KernelGlobals *kg, int id, int x, int y)
{
- const ccl_global TextureInfo *info = kernel_tex_info(kg, id);
-
- /* Wrap */
- if(info->extension == EXTENSION_REPEAT) {
- x = svm_image_texture_wrap_periodic(x, info->width);
- y = svm_image_texture_wrap_periodic(y, info->height);
- }
- else {
- x = svm_image_texture_wrap_clamp(x, info->width);
- y = svm_image_texture_wrap_clamp(y, info->height);
- }
-
- int offset = x + info->width * y;
- return svm_image_texture_read(kg, info, id, offset);
+ const ccl_global TextureInfo *info = kernel_tex_info(kg, id);
+
+ /* Wrap */
+ if (info->extension == EXTENSION_REPEAT) {
+ x = svm_image_texture_wrap_periodic(x, info->width);
+ y = svm_image_texture_wrap_periodic(y, info->height);
+ }
+ else {
+ x = svm_image_texture_wrap_clamp(x, info->width);
+ y = svm_image_texture_wrap_clamp(y, info->height);
+ }
+
+ int offset = x + info->width * y;
+ return svm_image_texture_read(kg, info, id, offset);
}
ccl_device_inline float4 svm_image_texture_read_3d(KernelGlobals *kg, int id, int x, int y, int z)
{
- const ccl_global TextureInfo *info = kernel_tex_info(kg, id);
-
- /* Wrap */
- if(info->extension == EXTENSION_REPEAT) {
- x = svm_image_texture_wrap_periodic(x, info->width);
- y = svm_image_texture_wrap_periodic(y, info->height);
- z = svm_image_texture_wrap_periodic(z, info->depth);
- }
- else {
- x = svm_image_texture_wrap_clamp(x, info->width);
- y = svm_image_texture_wrap_clamp(y, info->height);
- z = svm_image_texture_wrap_clamp(z, info->depth);
- }
-
- int offset = x + info->width * y + info->width * info->height * z;
- return svm_image_texture_read(kg, info, id, offset);
+ const ccl_global TextureInfo *info = kernel_tex_info(kg, id);
+
+ /* Wrap */
+ if (info->extension == EXTENSION_REPEAT) {
+ x = svm_image_texture_wrap_periodic(x, info->width);
+ y = svm_image_texture_wrap_periodic(y, info->height);
+ z = svm_image_texture_wrap_periodic(z, info->depth);
+ }
+ else {
+ x = svm_image_texture_wrap_clamp(x, info->width);
+ y = svm_image_texture_wrap_clamp(y, info->height);
+ z = svm_image_texture_wrap_clamp(z, info->depth);
+ }
+
+ int offset = x + info->width * y + info->width * info->height * z;
+ return svm_image_texture_read(kg, info, id, offset);
}
-
ccl_device_inline float svm_image_texture_frac(float x, int *ix)
{
- int i = float_to_int(x) - ((x < 0.0f)? 1: 0);
- *ix = i;
- return x - (float)i;
+ int i = float_to_int(x) - ((x < 0.0f) ? 1 : 0);
+ *ix = i;
+ return x - (float)i;
}
#define SET_CUBIC_SPLINE_WEIGHTS(u, t) \
- { \
- u[0] = (((-1.0f/6.0f)* t + 0.5f) * t - 0.5f) * t + (1.0f/6.0f); \
- u[1] = (( 0.5f * t - 1.0f) * t ) * t + (2.0f/3.0f); \
- u[2] = (( -0.5f * t + 0.5f) * t + 0.5f) * t + (1.0f/6.0f); \
- u[3] = (1.0f / 6.0f) * t * t * t; \
- } (void) 0
+ { \
+ u[0] = (((-1.0f / 6.0f) * t + 0.5f) * t - 0.5f) * t + (1.0f / 6.0f); \
+ u[1] = ((0.5f * t - 1.0f) * t) * t + (2.0f / 3.0f); \
+ u[2] = ((-0.5f * t + 0.5f) * t + 0.5f) * t + (1.0f / 6.0f); \
+ u[3] = (1.0f / 6.0f) * t * t * t; \
+ } \
+ (void)0
ccl_device float4 kernel_tex_image_interp(KernelGlobals *kg, int id, float x, float y)
{
- const ccl_global TextureInfo *info = kernel_tex_info(kg, id);
-
- if(info->extension == EXTENSION_CLIP) {
- if(x < 0.0f || y < 0.0f || x > 1.0f || y > 1.0f) {
- return make_float4(0.0f, 0.0f, 0.0f, 0.0f);
- }
- }
-
- if(info->interpolation == INTERPOLATION_CLOSEST) {
- /* Closest interpolation. */
- int ix, iy;
- svm_image_texture_frac(x*info->width, &ix);
- svm_image_texture_frac(y*info->height, &iy);
-
- return svm_image_texture_read_2d(kg, id, ix, iy);
- }
- else if(info->interpolation == INTERPOLATION_LINEAR) {
- /* Bilinear interpolation. */
- int ix, iy;
- float tx = svm_image_texture_frac(x*info->width - 0.5f, &ix);
- float ty = svm_image_texture_frac(y*info->height - 0.5f, &iy);
-
- float4 r;
- r = (1.0f - ty)*(1.0f - tx)*svm_image_texture_read_2d(kg, id, ix, iy);
- r += (1.0f - ty)*tx*svm_image_texture_read_2d(kg, id, ix+1, iy);
- r += ty*(1.0f - tx)*svm_image_texture_read_2d(kg, id, ix, iy+1);
- r += ty*tx*svm_image_texture_read_2d(kg, id, ix+1, iy+1);
- return r;
- }
- else {
- /* Bicubic interpolation. */
- int ix, iy;
- float tx = svm_image_texture_frac(x*info->width - 0.5f, &ix);
- float ty = svm_image_texture_frac(y*info->height - 0.5f, &iy);
-
- float u[4], v[4];
- SET_CUBIC_SPLINE_WEIGHTS(u, tx);
- SET_CUBIC_SPLINE_WEIGHTS(v, ty);
-
- float4 r = make_float4(0.0f, 0.0f, 0.0f, 0.0f);
-
- for(int y = 0; y < 4; y++) {
- for(int x = 0; x < 4; x++) {
- float weight = u[x]*v[y];
- r += weight*svm_image_texture_read_2d(kg, id, ix+x-1, iy+y-1);
- }
- }
- return r;
- }
+ const ccl_global TextureInfo *info = kernel_tex_info(kg, id);
+
+ if (info->extension == EXTENSION_CLIP) {
+ if (x < 0.0f || y < 0.0f || x > 1.0f || y > 1.0f) {
+ return make_float4(0.0f, 0.0f, 0.0f, 0.0f);
+ }
+ }
+
+ if (info->interpolation == INTERPOLATION_CLOSEST) {
+ /* Closest interpolation. */
+ int ix, iy;
+ svm_image_texture_frac(x * info->width, &ix);
+ svm_image_texture_frac(y * info->height, &iy);
+
+ return svm_image_texture_read_2d(kg, id, ix, iy);
+ }
+ else if (info->interpolation == INTERPOLATION_LINEAR) {
+ /* Bilinear interpolation. */
+ int ix, iy;
+ float tx = svm_image_texture_frac(x * info->width - 0.5f, &ix);
+ float ty = svm_image_texture_frac(y * info->height - 0.5f, &iy);
+
+ float4 r;
+ r = (1.0f - ty) * (1.0f - tx) * svm_image_texture_read_2d(kg, id, ix, iy);
+ r += (1.0f - ty) * tx * svm_image_texture_read_2d(kg, id, ix + 1, iy);
+ r += ty * (1.0f - tx) * svm_image_texture_read_2d(kg, id, ix, iy + 1);
+ r += ty * tx * svm_image_texture_read_2d(kg, id, ix + 1, iy + 1);
+ return r;
+ }
+ else {
+ /* Bicubic interpolation. */
+ int ix, iy;
+ float tx = svm_image_texture_frac(x * info->width - 0.5f, &ix);
+ float ty = svm_image_texture_frac(y * info->height - 0.5f, &iy);
+
+ float u[4], v[4];
+ SET_CUBIC_SPLINE_WEIGHTS(u, tx);
+ SET_CUBIC_SPLINE_WEIGHTS(v, ty);
+
+ float4 r = make_float4(0.0f, 0.0f, 0.0f, 0.0f);
+
+ for (int y = 0; y < 4; y++) {
+ for (int x = 0; x < 4; x++) {
+ float weight = u[x] * v[y];
+ r += weight * svm_image_texture_read_2d(kg, id, ix + x - 1, iy + y - 1);
+ }
+ }
+ return r;
+ }
}
-
-ccl_device float4 kernel_tex_image_interp_3d(KernelGlobals *kg, int id, float x, float y, float z, int interp)
+ccl_device float4
+kernel_tex_image_interp_3d(KernelGlobals *kg, int id, float x, float y, float z, int interp)
{
- const ccl_global TextureInfo *info = kernel_tex_info(kg, id);
-
- if(info->extension == EXTENSION_CLIP) {
- if(x < 0.0f || y < 0.0f || z < 0.0f ||
- x > 1.0f || y > 1.0f || z > 1.0f)
- {
- return make_float4(0.0f, 0.0f, 0.0f, 0.0f);
- }
- }
-
- uint interpolation = (interp == INTERPOLATION_NONE)? info->interpolation: interp;
-
- if(interpolation == INTERPOLATION_CLOSEST) {
- /* Closest interpolation. */
- int ix, iy, iz;
- svm_image_texture_frac(x*info->width, &ix);
- svm_image_texture_frac(y*info->height, &iy);
- svm_image_texture_frac(z*info->depth, &iz);
-
- return svm_image_texture_read_3d(kg, id, ix, iy, iz);
- }
- else if(interpolation == INTERPOLATION_LINEAR) {
- /* Bilinear interpolation. */
- int ix, iy, iz;
- float tx = svm_image_texture_frac(x*info->width - 0.5f, &ix);
- float ty = svm_image_texture_frac(y*info->height - 0.5f, &iy);
- float tz = svm_image_texture_frac(z*info->depth - 0.5f, &iz);
-
- float4 r;
- r = (1.0f - tz)*(1.0f - ty)*(1.0f - tx)*svm_image_texture_read_3d(kg, id, ix, iy, iz);
- r += (1.0f - tz)*(1.0f - ty)*tx*svm_image_texture_read_3d(kg, id, ix+1, iy, iz);
- r += (1.0f - tz)*ty*(1.0f - tx)*svm_image_texture_read_3d(kg, id, ix, iy+1, iz);
- r += (1.0f - tz)*ty*tx*svm_image_texture_read_3d(kg, id, ix+1, iy+1, iz);
-
- r += tz*(1.0f - ty)*(1.0f - tx)*svm_image_texture_read_3d(kg, id, ix, iy, iz+1);
- r += tz*(1.0f - ty)*tx*svm_image_texture_read_3d(kg, id, ix+1, iy, iz+1);
- r += tz*ty*(1.0f - tx)*svm_image_texture_read_3d(kg, id, ix, iy+1, iz+1);
- r += tz*ty*tx*svm_image_texture_read_3d(kg, id, ix+1, iy+1, iz+1);
- return r;
- }
- else {
- /* Bicubic interpolation. */
- int ix, iy, iz;
- float tx = svm_image_texture_frac(x*info->width - 0.5f, &ix);
- float ty = svm_image_texture_frac(y*info->height - 0.5f, &iy);
- float tz = svm_image_texture_frac(z*info->depth - 0.5f, &iz);
-
- float u[4], v[4], w[4];
- SET_CUBIC_SPLINE_WEIGHTS(u, tx);
- SET_CUBIC_SPLINE_WEIGHTS(v, ty);
- SET_CUBIC_SPLINE_WEIGHTS(w, tz);
-
- float4 r = make_float4(0.0f, 0.0f, 0.0f, 0.0f);
-
- for(int z = 0; z < 4; z++) {
- for(int y = 0; y < 4; y++) {
- for(int x = 0; x < 4; x++) {
- float weight = u[x]*v[y]*w[z];
- r += weight*svm_image_texture_read_3d(kg, id, ix+x-1, iy+y-1, iz+z-1);
- }
- }
- }
- return r;
- }
+ const ccl_global TextureInfo *info = kernel_tex_info(kg, id);
+
+ if (info->extension == EXTENSION_CLIP) {
+ if (x < 0.0f || y < 0.0f || z < 0.0f || x > 1.0f || y > 1.0f || z > 1.0f) {
+ return make_float4(0.0f, 0.0f, 0.0f, 0.0f);
+ }
+ }
+
+ uint interpolation = (interp == INTERPOLATION_NONE) ? info->interpolation : interp;
+
+ if (interpolation == INTERPOLATION_CLOSEST) {
+ /* Closest interpolation. */
+ int ix, iy, iz;
+ svm_image_texture_frac(x * info->width, &ix);
+ svm_image_texture_frac(y * info->height, &iy);
+ svm_image_texture_frac(z * info->depth, &iz);
+
+ return svm_image_texture_read_3d(kg, id, ix, iy, iz);
+ }
+ else if (interpolation == INTERPOLATION_LINEAR) {
+ /* Bilinear interpolation. */
+ int ix, iy, iz;
+ float tx = svm_image_texture_frac(x * info->width - 0.5f, &ix);
+ float ty = svm_image_texture_frac(y * info->height - 0.5f, &iy);
+ float tz = svm_image_texture_frac(z * info->depth - 0.5f, &iz);
+
+ float4 r;
+ r = (1.0f - tz) * (1.0f - ty) * (1.0f - tx) * svm_image_texture_read_3d(kg, id, ix, iy, iz);
+ r += (1.0f - tz) * (1.0f - ty) * tx * svm_image_texture_read_3d(kg, id, ix + 1, iy, iz);
+ r += (1.0f - tz) * ty * (1.0f - tx) * svm_image_texture_read_3d(kg, id, ix, iy + 1, iz);
+ r += (1.0f - tz) * ty * tx * svm_image_texture_read_3d(kg, id, ix + 1, iy + 1, iz);
+
+ r += tz * (1.0f - ty) * (1.0f - tx) * svm_image_texture_read_3d(kg, id, ix, iy, iz + 1);
+ r += tz * (1.0f - ty) * tx * svm_image_texture_read_3d(kg, id, ix + 1, iy, iz + 1);
+ r += tz * ty * (1.0f - tx) * svm_image_texture_read_3d(kg, id, ix, iy + 1, iz + 1);
+ r += tz * ty * tx * svm_image_texture_read_3d(kg, id, ix + 1, iy + 1, iz + 1);
+ return r;
+ }
+ else {
+ /* Bicubic interpolation. */
+ int ix, iy, iz;
+ float tx = svm_image_texture_frac(x * info->width - 0.5f, &ix);
+ float ty = svm_image_texture_frac(y * info->height - 0.5f, &iy);
+ float tz = svm_image_texture_frac(z * info->depth - 0.5f, &iz);
+
+ float u[4], v[4], w[4];
+ SET_CUBIC_SPLINE_WEIGHTS(u, tx);
+ SET_CUBIC_SPLINE_WEIGHTS(v, ty);
+ SET_CUBIC_SPLINE_WEIGHTS(w, tz);
+
+ float4 r = make_float4(0.0f, 0.0f, 0.0f, 0.0f);
+
+ for (int z = 0; z < 4; z++) {
+ for (int y = 0; y < 4; y++) {
+ for (int x = 0; x < 4; x++) {
+ float weight = u[x] * v[y] * w[z];
+ r += weight * svm_image_texture_read_3d(kg, id, ix + x - 1, iy + y - 1, iz + z - 1);
+ }
+ }
+ }
+ return r;
+ }
}
#undef SET_CUBIC_SPLINE_WEIGHTS
diff --git a/intern/cycles/kernel/kernels/opencl/kernel_split_function.h b/intern/cycles/kernel/kernels/opencl/kernel_split_function.h
index 05e1ddf6da2..e123b4cd6ec 100644
--- a/intern/cycles/kernel/kernels/opencl/kernel_split_function.h
+++ b/intern/cycles/kernel/kernels/opencl/kernel_split_function.h
@@ -14,50 +14,53 @@
* limitations under the License.
*/
-#define KERNEL_NAME_JOIN(a, b) a ## _ ## b
+#define KERNEL_NAME_JOIN(a, b) a##_##b
#define KERNEL_NAME_EVAL(a, b) KERNEL_NAME_JOIN(a, b)
-__kernel void KERNEL_NAME_EVAL(kernel_ocl_path_trace, KERNEL_NAME)(
- ccl_global char *kg_global,
- ccl_constant KernelData *data,
+__kernel void KERNEL_NAME_EVAL(kernel_ocl_path_trace,
+ KERNEL_NAME)(ccl_global char *kg_global,
+ ccl_constant KernelData *data,
- ccl_global void *split_data_buffer,
- ccl_global char *ray_state,
+ ccl_global void *split_data_buffer,
+ ccl_global char *ray_state,
- KERNEL_BUFFER_PARAMS,
+ KERNEL_BUFFER_PARAMS,
- ccl_global int *queue_index,
- ccl_global char *use_queues_flag,
- ccl_global unsigned int *work_pools,
- ccl_global float *buffer
- )
+ ccl_global int *queue_index,
+ ccl_global char *use_queues_flag,
+ ccl_global unsigned int *work_pools,
+ ccl_global float *buffer)
{
#ifdef LOCALS_TYPE
- ccl_local LOCALS_TYPE locals;
+ ccl_local LOCALS_TYPE locals;
#endif
- KernelGlobals *kg = (KernelGlobals*)kg_global;
+ KernelGlobals *kg = (KernelGlobals *)kg_global;
- if(ccl_local_id(0) + ccl_local_id(1) == 0) {
- kg->data = data;
+ if (ccl_local_id(0) + ccl_local_id(1) == 0) {
+ kg->data = data;
- kernel_split_params.queue_index = queue_index;
- kernel_split_params.use_queues_flag = use_queues_flag;
- kernel_split_params.work_pools = work_pools;
- kernel_split_params.tile.buffer = buffer;
+ kernel_split_params.queue_index = queue_index;
+ kernel_split_params.use_queues_flag = use_queues_flag;
+ kernel_split_params.work_pools = work_pools;
+ kernel_split_params.tile.buffer = buffer;
- split_data_init(kg, &kernel_split_state, ccl_global_size(0)*ccl_global_size(1), split_data_buffer, ray_state);
+ split_data_init(kg,
+ &kernel_split_state,
+ ccl_global_size(0) * ccl_global_size(1),
+ split_data_buffer,
+ ray_state);
+ }
- }
+ kernel_set_buffer_pointers(kg, KERNEL_BUFFER_ARGS);
- kernel_set_buffer_pointers(kg, KERNEL_BUFFER_ARGS);
-
- KERNEL_NAME_EVAL(kernel, KERNEL_NAME)(
- kg
+ KERNEL_NAME_EVAL(kernel, KERNEL_NAME)
+ (kg
#ifdef LOCALS_TYPE
- , &locals
+ ,
+ &locals
#endif
- );
+ );
}
#undef KERNEL_NAME_JOIN
diff --git a/intern/cycles/kernel/osl/CMakeLists.txt b/intern/cycles/kernel/osl/CMakeLists.txt
index 0a3d0b974cb..28d9ca854db 100644
--- a/intern/cycles/kernel/osl/CMakeLists.txt
+++ b/intern/cycles/kernel/osl/CMakeLists.txt
@@ -1,6 +1,6 @@
set(INC
- ../..
+ ../..
)
set(INC_SYS
@@ -8,25 +8,25 @@ set(INC_SYS
)
set(SRC
- background.cpp
- bsdf_diffuse_ramp.cpp
- bsdf_phong_ramp.cpp
- emissive.cpp
- osl_bssrdf.cpp
- osl_closures.cpp
- osl_services.cpp
- osl_shader.cpp
+ background.cpp
+ bsdf_diffuse_ramp.cpp
+ bsdf_phong_ramp.cpp
+ emissive.cpp
+ osl_bssrdf.cpp
+ osl_closures.cpp
+ osl_services.cpp
+ osl_shader.cpp
)
set(HEADER_SRC
- osl_closures.h
- osl_globals.h
- osl_services.h
- osl_shader.h
+ osl_closures.h
+ osl_globals.h
+ osl_services.h
+ osl_shader.h
)
set(LIB
- cycles_render
+ cycles_render
)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${RTTI_DISABLE_FLAGS}")
diff --git a/intern/cycles/kernel/osl/background.cpp b/intern/cycles/kernel/osl/background.cpp
index 6924a4144c5..b395227845d 100644
--- a/intern/cycles/kernel/osl/background.cpp
+++ b/intern/cycles/kernel/osl/background.cpp
@@ -51,11 +51,11 @@ using namespace OSL;
/// only the weight is taking into account
///
class GenericBackgroundClosure : public CClosurePrimitive {
-public:
- void setup(ShaderData *sd, int /* path_flag */, float3 weight)
- {
- background_setup(sd, weight);
- }
+ public:
+ void setup(ShaderData *sd, int /* path_flag */, float3 weight)
+ {
+ background_setup(sd, weight);
+ }
};
/// Holdout closure
@@ -66,31 +66,28 @@ public:
/// used
///
class HoldoutClosure : CClosurePrimitive {
-public:
- void setup(ShaderData *sd, int /* path_flag */, float3 weight)
- {
- closure_alloc(sd, sizeof(ShaderClosure), CLOSURE_HOLDOUT_ID, weight);
- sd->flag |= SD_HOLDOUT;
- }
+ public:
+ void setup(ShaderData *sd, int /* path_flag */, float3 weight)
+ {
+ closure_alloc(sd, sizeof(ShaderClosure), CLOSURE_HOLDOUT_ID, weight);
+ sd->flag |= SD_HOLDOUT;
+ }
};
ClosureParam *closure_background_params()
{
- static ClosureParam params[] = {
- CLOSURE_STRING_KEYPARAM(GenericBackgroundClosure, label, "label"),
- CLOSURE_FINISH_PARAM(GenericBackgroundClosure)
- };
- return params;
+ static ClosureParam params[] = {
+ CLOSURE_STRING_KEYPARAM(GenericBackgroundClosure, label, "label"),
+ CLOSURE_FINISH_PARAM(GenericBackgroundClosure)};
+ return params;
}
CCLOSURE_PREPARE(closure_background_prepare, GenericBackgroundClosure)
ClosureParam *closure_holdout_params()
{
- static ClosureParam params[] = {
- CLOSURE_FINISH_PARAM(HoldoutClosure)
- };
- return params;
+ static ClosureParam params[] = {CLOSURE_FINISH_PARAM(HoldoutClosure)};
+ return params;
}
CCLOSURE_PREPARE(closure_holdout_prepare, HoldoutClosure)
diff --git a/intern/cycles/kernel/osl/bsdf_diffuse_ramp.cpp b/intern/cycles/kernel/osl/bsdf_diffuse_ramp.cpp
index ed5d5235a34..c5edc7c9be3 100644
--- a/intern/cycles/kernel/osl/bsdf_diffuse_ramp.cpp
+++ b/intern/cycles/kernel/osl/bsdf_diffuse_ramp.cpp
@@ -47,36 +47,35 @@ CCL_NAMESPACE_BEGIN
using namespace OSL;
class DiffuseRampClosure : public CBSDFClosure {
-public:
- DiffuseRampBsdf params;
- Color3 colors[8];
+ public:
+ DiffuseRampBsdf params;
+ Color3 colors[8];
- void setup(ShaderData *sd, int /* path_flag */, float3 weight)
- {
- DiffuseRampBsdf *bsdf = (DiffuseRampBsdf*)bsdf_alloc_osl(sd, sizeof(DiffuseRampBsdf), weight, &params);
+ void setup(ShaderData *sd, int /* path_flag */, float3 weight)
+ {
+ DiffuseRampBsdf *bsdf = (DiffuseRampBsdf *)bsdf_alloc_osl(
+ sd, sizeof(DiffuseRampBsdf), weight, &params);
- if(bsdf) {
- bsdf->colors = (float3*)closure_alloc_extra(sd, sizeof(float3)*8);
+ if (bsdf) {
+ bsdf->colors = (float3 *)closure_alloc_extra(sd, sizeof(float3) * 8);
- if(bsdf->colors) {
- for(int i = 0; i < 8; i++)
- bsdf->colors[i] = TO_FLOAT3(colors[i]);
+ if (bsdf->colors) {
+ for (int i = 0; i < 8; i++)
+ bsdf->colors[i] = TO_FLOAT3(colors[i]);
- sd->flag |= bsdf_diffuse_ramp_setup(bsdf);
- }
- }
- }
+ sd->flag |= bsdf_diffuse_ramp_setup(bsdf);
+ }
+ }
+ }
};
ClosureParam *closure_bsdf_diffuse_ramp_params()
{
- static ClosureParam params[] = {
- CLOSURE_FLOAT3_PARAM(DiffuseRampClosure, params.N),
- CLOSURE_COLOR_ARRAY_PARAM(DiffuseRampClosure, colors, 8),
- CLOSURE_STRING_KEYPARAM(DiffuseRampClosure, label, "label"),
- CLOSURE_FINISH_PARAM(DiffuseRampClosure)
- };
- return params;
+ static ClosureParam params[] = {CLOSURE_FLOAT3_PARAM(DiffuseRampClosure, params.N),
+ CLOSURE_COLOR_ARRAY_PARAM(DiffuseRampClosure, colors, 8),
+ CLOSURE_STRING_KEYPARAM(DiffuseRampClosure, label, "label"),
+ CLOSURE_FINISH_PARAM(DiffuseRampClosure)};
+ return params;
}
CCLOSURE_PREPARE(closure_bsdf_diffuse_ramp_prepare, DiffuseRampClosure)
diff --git a/intern/cycles/kernel/osl/bsdf_phong_ramp.cpp b/intern/cycles/kernel/osl/bsdf_phong_ramp.cpp
index a8acdb8e342..4b7e59ff932 100644
--- a/intern/cycles/kernel/osl/bsdf_phong_ramp.cpp
+++ b/intern/cycles/kernel/osl/bsdf_phong_ramp.cpp
@@ -46,37 +46,36 @@ CCL_NAMESPACE_BEGIN
using namespace OSL;
class PhongRampClosure : public CBSDFClosure {
-public:
- PhongRampBsdf params;
- Color3 colors[8];
+ public:
+ PhongRampBsdf params;
+ Color3 colors[8];
- void setup(ShaderData *sd, int /* path_flag */, float3 weight)
- {
- PhongRampBsdf *bsdf = (PhongRampBsdf*)bsdf_alloc_osl(sd, sizeof(PhongRampBsdf), weight, &params);
+ void setup(ShaderData *sd, int /* path_flag */, float3 weight)
+ {
+ PhongRampBsdf *bsdf = (PhongRampBsdf *)bsdf_alloc_osl(
+ sd, sizeof(PhongRampBsdf), weight, &params);
- if(bsdf) {
- bsdf->colors = (float3*)closure_alloc_extra(sd, sizeof(float3)*8);
+ if (bsdf) {
+ bsdf->colors = (float3 *)closure_alloc_extra(sd, sizeof(float3) * 8);
- if(bsdf->colors) {
- for(int i = 0; i < 8; i++)
- bsdf->colors[i] = TO_FLOAT3(colors[i]);
+ if (bsdf->colors) {
+ for (int i = 0; i < 8; i++)
+ bsdf->colors[i] = TO_FLOAT3(colors[i]);
- sd->flag |= bsdf_phong_ramp_setup(bsdf);
- }
- }
- }
+ sd->flag |= bsdf_phong_ramp_setup(bsdf);
+ }
+ }
+ }
};
ClosureParam *closure_bsdf_phong_ramp_params()
{
- static ClosureParam params[] = {
- CLOSURE_FLOAT3_PARAM(PhongRampClosure, params.N),
- CLOSURE_FLOAT_PARAM(PhongRampClosure, params.exponent),
- CLOSURE_COLOR_ARRAY_PARAM(PhongRampClosure, colors, 8),
- CLOSURE_STRING_KEYPARAM(PhongRampClosure, label, "label"),
- CLOSURE_FINISH_PARAM(PhongRampClosure)
- };
- return params;
+ static ClosureParam params[] = {CLOSURE_FLOAT3_PARAM(PhongRampClosure, params.N),
+ CLOSURE_FLOAT_PARAM(PhongRampClosure, params.exponent),
+ CLOSURE_COLOR_ARRAY_PARAM(PhongRampClosure, colors, 8),
+ CLOSURE_STRING_KEYPARAM(PhongRampClosure, label, "label"),
+ CLOSURE_FINISH_PARAM(PhongRampClosure)};
+ return params;
}
CCLOSURE_PREPARE(closure_bsdf_phong_ramp_prepare, PhongRampClosure)
diff --git a/intern/cycles/kernel/osl/emissive.cpp b/intern/cycles/kernel/osl/emissive.cpp
index c2a848231f2..c29ddb13e2e 100644
--- a/intern/cycles/kernel/osl/emissive.cpp
+++ b/intern/cycles/kernel/osl/emissive.cpp
@@ -53,20 +53,18 @@ using namespace OSL;
/// if the provided angles are PI/2, which is the default
///
class GenericEmissiveClosure : public CClosurePrimitive {
-public:
- void setup(ShaderData *sd, int /* path_flag */, float3 weight)
- {
- emission_setup(sd, weight);
- }
+ public:
+ void setup(ShaderData *sd, int /* path_flag */, float3 weight)
+ {
+ emission_setup(sd, weight);
+ }
};
ClosureParam *closure_emission_params()
{
- static ClosureParam params[] = {
- CLOSURE_STRING_KEYPARAM(GenericEmissiveClosure, label, "label"),
- CLOSURE_FINISH_PARAM(GenericEmissiveClosure)
- };
- return params;
+ static ClosureParam params[] = {CLOSURE_STRING_KEYPARAM(GenericEmissiveClosure, label, "label"),
+ CLOSURE_FINISH_PARAM(GenericEmissiveClosure)};
+ return params;
}
CCLOSURE_PREPARE(closure_emission_prepare, GenericEmissiveClosure)
diff --git a/intern/cycles/kernel/osl/osl_bssrdf.cpp b/intern/cycles/kernel/osl/osl_bssrdf.cpp
index 66ec8a996ca..dd52c33071c 100644
--- a/intern/cycles/kernel/osl/osl_bssrdf.cpp
+++ b/intern/cycles/kernel/osl/osl_bssrdf.cpp
@@ -56,77 +56,76 @@ static ustring u_random_walk("random_walk");
static ustring u_principled_random_walk("principled_random_walk");
class CBSSRDFClosure : public CClosurePrimitive {
-public:
- Bssrdf params;
- ustring method;
-
- CBSSRDFClosure()
- {
- params.texture_blur = 0.0f;
- params.sharpness = 0.0f;
- params.roughness = 0.0f;
- }
-
- void setup(ShaderData *sd, int path_flag, float3 weight)
- {
- if(method == u_cubic) {
- alloc(sd, path_flag, weight, CLOSURE_BSSRDF_CUBIC_ID);
- }
- else if(method == u_gaussian) {
- alloc(sd, path_flag, weight, CLOSURE_BSSRDF_GAUSSIAN_ID);
- }
- else if(method == u_burley) {
- alloc(sd, path_flag, weight, CLOSURE_BSSRDF_BURLEY_ID);
- }
- else if(method == u_principled) {
- alloc(sd, path_flag, weight, CLOSURE_BSSRDF_PRINCIPLED_ID);
- }
- else if(method == u_random_walk) {
- alloc(sd, path_flag, weight, CLOSURE_BSSRDF_RANDOM_WALK_ID);
- }
- else if(method == u_principled_random_walk) {
- alloc(sd, path_flag, weight, CLOSURE_BSSRDF_PRINCIPLED_RANDOM_WALK_ID);
- }
- }
-
- void alloc(ShaderData *sd, int path_flag, float3 weight, ClosureType type)
- {
- Bssrdf *bssrdf = bssrdf_alloc(sd, weight);
-
- if(bssrdf) {
- /* disable in case of diffuse ancestor, can't see it well then and
- * adds considerably noise due to probabilities of continuing path
- * getting lower and lower */
- if(path_flag & PATH_RAY_DIFFUSE_ANCESTOR) {
- params.radius = make_float3(0.0f, 0.0f, 0.0f);
- }
-
- /* create one closure per color channel */
- bssrdf->radius = params.radius;
- bssrdf->albedo = params.albedo;
- bssrdf->texture_blur = params.texture_blur;
- bssrdf->sharpness = params.sharpness;
- bssrdf->N = params.N;
- bssrdf->roughness = params.roughness;
- sd->flag |= bssrdf_setup(sd, bssrdf, (ClosureType)type);
- }
- }
+ public:
+ Bssrdf params;
+ ustring method;
+
+ CBSSRDFClosure()
+ {
+ params.texture_blur = 0.0f;
+ params.sharpness = 0.0f;
+ params.roughness = 0.0f;
+ }
+
+ void setup(ShaderData *sd, int path_flag, float3 weight)
+ {
+ if (method == u_cubic) {
+ alloc(sd, path_flag, weight, CLOSURE_BSSRDF_CUBIC_ID);
+ }
+ else if (method == u_gaussian) {
+ alloc(sd, path_flag, weight, CLOSURE_BSSRDF_GAUSSIAN_ID);
+ }
+ else if (method == u_burley) {
+ alloc(sd, path_flag, weight, CLOSURE_BSSRDF_BURLEY_ID);
+ }
+ else if (method == u_principled) {
+ alloc(sd, path_flag, weight, CLOSURE_BSSRDF_PRINCIPLED_ID);
+ }
+ else if (method == u_random_walk) {
+ alloc(sd, path_flag, weight, CLOSURE_BSSRDF_RANDOM_WALK_ID);
+ }
+ else if (method == u_principled_random_walk) {
+ alloc(sd, path_flag, weight, CLOSURE_BSSRDF_PRINCIPLED_RANDOM_WALK_ID);
+ }
+ }
+
+ void alloc(ShaderData *sd, int path_flag, float3 weight, ClosureType type)
+ {
+ Bssrdf *bssrdf = bssrdf_alloc(sd, weight);
+
+ if (bssrdf) {
+ /* disable in case of diffuse ancestor, can't see it well then and
+ * adds considerably noise due to probabilities of continuing path
+ * getting lower and lower */
+ if (path_flag & PATH_RAY_DIFFUSE_ANCESTOR) {
+ params.radius = make_float3(0.0f, 0.0f, 0.0f);
+ }
+
+ /* create one closure per color channel */
+ bssrdf->radius = params.radius;
+ bssrdf->albedo = params.albedo;
+ bssrdf->texture_blur = params.texture_blur;
+ bssrdf->sharpness = params.sharpness;
+ bssrdf->N = params.N;
+ bssrdf->roughness = params.roughness;
+ sd->flag |= bssrdf_setup(sd, bssrdf, (ClosureType)type);
+ }
+ }
};
ClosureParam *closure_bssrdf_params()
{
- static ClosureParam params[] = {
- CLOSURE_STRING_PARAM(CBSSRDFClosure, method),
- CLOSURE_FLOAT3_PARAM(CBSSRDFClosure, params.N),
- CLOSURE_FLOAT3_PARAM(CBSSRDFClosure, params.radius),
- CLOSURE_FLOAT3_PARAM(CBSSRDFClosure, params.albedo),
- CLOSURE_FLOAT_KEYPARAM(CBSSRDFClosure, params.texture_blur, "texture_blur"),
- CLOSURE_FLOAT_KEYPARAM(CBSSRDFClosure, params.sharpness, "sharpness"),
- CLOSURE_FLOAT_KEYPARAM(CBSSRDFClosure, params.roughness, "roughness"),
- CLOSURE_STRING_KEYPARAM(CBSSRDFClosure, label, "label"),
- CLOSURE_FINISH_PARAM(CBSSRDFClosure)
- };
- return params;
+ static ClosureParam params[] = {
+ CLOSURE_STRING_PARAM(CBSSRDFClosure, method),
+ CLOSURE_FLOAT3_PARAM(CBSSRDFClosure, params.N),
+ CLOSURE_FLOAT3_PARAM(CBSSRDFClosure, params.radius),
+ CLOSURE_FLOAT3_PARAM(CBSSRDFClosure, params.albedo),
+ CLOSURE_FLOAT_KEYPARAM(CBSSRDFClosure, params.texture_blur, "texture_blur"),
+ CLOSURE_FLOAT_KEYPARAM(CBSSRDFClosure, params.sharpness, "sharpness"),
+ CLOSURE_FLOAT_KEYPARAM(CBSSRDFClosure, params.roughness, "roughness"),
+ CLOSURE_STRING_KEYPARAM(CBSSRDFClosure, label, "label"),
+ CLOSURE_FINISH_PARAM(CBSSRDFClosure)};
+ return params;
}
CCLOSURE_PREPARE(closure_bssrdf_prepare, CBSSRDFClosure)
diff --git a/intern/cycles/kernel/osl/osl_closures.cpp b/intern/cycles/kernel/osl/osl_closures.cpp
index 169351d5ad9..aa7e2727577 100644
--- a/intern/cycles/kernel/osl/osl_closures.cpp
+++ b/intern/cycles/kernel/osl/osl_closures.cpp
@@ -71,706 +71,787 @@ using namespace OSL;
/* BSDF class definitions */
BSDF_CLOSURE_CLASS_BEGIN(Diffuse, diffuse, DiffuseBsdf, LABEL_DIFFUSE)
- CLOSURE_FLOAT3_PARAM(DiffuseClosure, params.N),
-BSDF_CLOSURE_CLASS_END(Diffuse, diffuse)
-
-BSDF_CLOSURE_CLASS_BEGIN(Translucent, translucent, DiffuseBsdf, LABEL_DIFFUSE)
- CLOSURE_FLOAT3_PARAM(TranslucentClosure, params.N),
-BSDF_CLOSURE_CLASS_END(Translucent, translucent)
-
-BSDF_CLOSURE_CLASS_BEGIN(OrenNayar, oren_nayar, OrenNayarBsdf, LABEL_DIFFUSE)
- CLOSURE_FLOAT3_PARAM(OrenNayarClosure, params.N),
- CLOSURE_FLOAT_PARAM(OrenNayarClosure, params.roughness),
-BSDF_CLOSURE_CLASS_END(OrenNayar, oren_nayar)
-
-BSDF_CLOSURE_CLASS_BEGIN(Reflection, reflection, MicrofacetBsdf, LABEL_SINGULAR)
- CLOSURE_FLOAT3_PARAM(ReflectionClosure, params.N),
-BSDF_CLOSURE_CLASS_END(Reflection, reflection)
-
-BSDF_CLOSURE_CLASS_BEGIN(Refraction, refraction, MicrofacetBsdf, LABEL_SINGULAR)
- CLOSURE_FLOAT3_PARAM(RefractionClosure, params.N),
- CLOSURE_FLOAT_PARAM(RefractionClosure, params.ior),
-BSDF_CLOSURE_CLASS_END(Refraction, refraction)
-
-BSDF_CLOSURE_CLASS_BEGIN(AshikhminVelvet, ashikhmin_velvet, VelvetBsdf, LABEL_DIFFUSE)
- CLOSURE_FLOAT3_PARAM(AshikhminVelvetClosure, params.N),
- CLOSURE_FLOAT_PARAM(AshikhminVelvetClosure, params.sigma),
-BSDF_CLOSURE_CLASS_END(AshikhminVelvet, ashikhmin_velvet)
-
-BSDF_CLOSURE_CLASS_BEGIN(AshikhminShirley, ashikhmin_shirley_aniso, MicrofacetBsdf, LABEL_GLOSSY|LABEL_REFLECT)
- CLOSURE_FLOAT3_PARAM(AshikhminShirleyClosure, params.N),
- CLOSURE_FLOAT3_PARAM(AshikhminShirleyClosure, params.T),
- CLOSURE_FLOAT_PARAM(AshikhminShirleyClosure, params.alpha_x),
- CLOSURE_FLOAT_PARAM(AshikhminShirleyClosure, params.alpha_y),
-BSDF_CLOSURE_CLASS_END(AshikhminShirley, ashikhmin_shirley_aniso)
-
-BSDF_CLOSURE_CLASS_BEGIN(DiffuseToon, diffuse_toon, ToonBsdf, LABEL_DIFFUSE)
- CLOSURE_FLOAT3_PARAM(DiffuseToonClosure, params.N),
- CLOSURE_FLOAT_PARAM(DiffuseToonClosure, params.size),
- CLOSURE_FLOAT_PARAM(DiffuseToonClosure, params.smooth),
-BSDF_CLOSURE_CLASS_END(DiffuseToon, diffuse_toon)
-
-BSDF_CLOSURE_CLASS_BEGIN(GlossyToon, glossy_toon, ToonBsdf, LABEL_GLOSSY)
- CLOSURE_FLOAT3_PARAM(GlossyToonClosure, params.N),
- CLOSURE_FLOAT_PARAM(GlossyToonClosure, params.size),
- CLOSURE_FLOAT_PARAM(GlossyToonClosure, params.smooth),
-BSDF_CLOSURE_CLASS_END(GlossyToon, glossy_toon)
-
-BSDF_CLOSURE_CLASS_BEGIN(MicrofacetGGX, microfacet_ggx, MicrofacetBsdf, LABEL_GLOSSY|LABEL_REFLECT)
- CLOSURE_FLOAT3_PARAM(MicrofacetGGXClosure, params.N),
- CLOSURE_FLOAT_PARAM(MicrofacetGGXClosure, params.alpha_x),
-BSDF_CLOSURE_CLASS_END(MicrofacetGGX, microfacet_ggx)
-
-BSDF_CLOSURE_CLASS_BEGIN(MicrofacetGGXAniso, microfacet_ggx_aniso, MicrofacetBsdf, LABEL_GLOSSY|LABEL_REFLECT)
- CLOSURE_FLOAT3_PARAM(MicrofacetGGXAnisoClosure, params.N),
- CLOSURE_FLOAT3_PARAM(MicrofacetGGXAnisoClosure, params.T),
- CLOSURE_FLOAT_PARAM(MicrofacetGGXAnisoClosure, params.alpha_x),
- CLOSURE_FLOAT_PARAM(MicrofacetGGXAnisoClosure, params.alpha_y),
-BSDF_CLOSURE_CLASS_END(MicrofacetGGXAniso, microfacet_ggx_aniso)
-
-BSDF_CLOSURE_CLASS_BEGIN(MicrofacetBeckmann, microfacet_beckmann, MicrofacetBsdf, LABEL_GLOSSY|LABEL_REFLECT)
- CLOSURE_FLOAT3_PARAM(MicrofacetBeckmannClosure, params.N),
- CLOSURE_FLOAT_PARAM(MicrofacetBeckmannClosure, params.alpha_x),
-BSDF_CLOSURE_CLASS_END(MicrofacetBeckmann, microfacet_beckmann)
-
-BSDF_CLOSURE_CLASS_BEGIN(MicrofacetBeckmannAniso, microfacet_beckmann_aniso, MicrofacetBsdf, LABEL_GLOSSY|LABEL_REFLECT)
- CLOSURE_FLOAT3_PARAM(MicrofacetBeckmannAnisoClosure, params.N),
- CLOSURE_FLOAT3_PARAM(MicrofacetBeckmannAnisoClosure, params.T),
- CLOSURE_FLOAT_PARAM(MicrofacetBeckmannAnisoClosure, params.alpha_x),
- CLOSURE_FLOAT_PARAM(MicrofacetBeckmannAnisoClosure, params.alpha_y),
-BSDF_CLOSURE_CLASS_END(MicrofacetBeckmannAniso, microfacet_beckmann_aniso)
-
-BSDF_CLOSURE_CLASS_BEGIN(MicrofacetGGXRefraction, microfacet_ggx_refraction, MicrofacetBsdf, LABEL_GLOSSY|LABEL_TRANSMIT)
- CLOSURE_FLOAT3_PARAM(MicrofacetGGXRefractionClosure, params.N),
- CLOSURE_FLOAT_PARAM(MicrofacetGGXRefractionClosure, params.alpha_x),
- CLOSURE_FLOAT_PARAM(MicrofacetGGXRefractionClosure, params.ior),
-BSDF_CLOSURE_CLASS_END(MicrofacetGGXRefraction, microfacet_ggx_refraction)
-
-BSDF_CLOSURE_CLASS_BEGIN(MicrofacetBeckmannRefraction, microfacet_beckmann_refraction, MicrofacetBsdf, LABEL_GLOSSY|LABEL_TRANSMIT)
- CLOSURE_FLOAT3_PARAM(MicrofacetBeckmannRefractionClosure, params.N),
- CLOSURE_FLOAT_PARAM(MicrofacetBeckmannRefractionClosure, params.alpha_x),
- CLOSURE_FLOAT_PARAM(MicrofacetBeckmannRefractionClosure, params.ior),
-BSDF_CLOSURE_CLASS_END(MicrofacetBeckmannRefraction, microfacet_beckmann_refraction)
-
-BSDF_CLOSURE_CLASS_BEGIN(HairReflection, hair_reflection, HairBsdf, LABEL_GLOSSY)
- CLOSURE_FLOAT3_PARAM(HairReflectionClosure, params.N),
- CLOSURE_FLOAT_PARAM(HairReflectionClosure, params.roughness1),
- CLOSURE_FLOAT_PARAM(HairReflectionClosure, params.roughness2),
- CLOSURE_FLOAT3_PARAM(HairReflectionClosure, params.T),
- CLOSURE_FLOAT_PARAM(HairReflectionClosure, params.offset),
-BSDF_CLOSURE_CLASS_END(HairReflection, hair_reflection)
-
-BSDF_CLOSURE_CLASS_BEGIN(HairTransmission, hair_transmission, HairBsdf, LABEL_GLOSSY)
- CLOSURE_FLOAT3_PARAM(HairTransmissionClosure, params.N),
- CLOSURE_FLOAT_PARAM(HairTransmissionClosure, params.roughness1),
- CLOSURE_FLOAT_PARAM(HairTransmissionClosure, params.roughness2),
- CLOSURE_FLOAT3_PARAM(HairReflectionClosure, params.T),
- CLOSURE_FLOAT_PARAM(HairReflectionClosure, params.offset),
-BSDF_CLOSURE_CLASS_END(HairTransmission, hair_transmission)
-
-BSDF_CLOSURE_CLASS_BEGIN(PrincipledDiffuse, principled_diffuse, PrincipledDiffuseBsdf, LABEL_DIFFUSE)
- CLOSURE_FLOAT3_PARAM(PrincipledDiffuseClosure, params.N),
- CLOSURE_FLOAT_PARAM(PrincipledDiffuseClosure, params.roughness),
-BSDF_CLOSURE_CLASS_END(PrincipledDiffuse, principled_diffuse)
-
-BSDF_CLOSURE_CLASS_BEGIN(PrincipledSheen, principled_sheen, PrincipledSheenBsdf, LABEL_DIFFUSE)
- CLOSURE_FLOAT3_PARAM(PrincipledSheenClosure, params.N),
-BSDF_CLOSURE_CLASS_END(PrincipledSheen, principled_sheen)
-
-/* PRINCIPLED HAIR BSDF */
-class PrincipledHairClosure : public CBSDFClosure {
-public:
- PrincipledHairBSDF params;
-
- PrincipledHairBSDF *alloc(ShaderData *sd, int path_flag, float3 weight)
- {
- PrincipledHairBSDF *bsdf = (PrincipledHairBSDF*)bsdf_alloc_osl(sd, sizeof(PrincipledHairBSDF), weight, &params);
- if(!bsdf) {
- return NULL;
- }
-
- PrincipledHairExtra *extra = (PrincipledHairExtra*)closure_alloc_extra(sd, sizeof(PrincipledHairExtra));
- if(!extra) {
- return NULL;
- }
-
- bsdf->extra = extra;
- return bsdf;
- }
-
- void setup(ShaderData *sd, int path_flag, float3 weight)
- {
- if(!skip(sd, path_flag, LABEL_GLOSSY)) {
- PrincipledHairBSDF *bsdf = (PrincipledHairBSDF*)alloc(sd, path_flag, weight);
- if(!bsdf) {
- return;
- }
-
- sd->flag |= (bsdf) ? bsdf_principled_hair_setup(sd, bsdf) : 0;
- }
- }
+CLOSURE_FLOAT3_PARAM(DiffuseClosure, params.N),
+ BSDF_CLOSURE_CLASS_END(Diffuse, diffuse)
+
+ BSDF_CLOSURE_CLASS_BEGIN(Translucent, translucent, DiffuseBsdf, LABEL_DIFFUSE)
+ CLOSURE_FLOAT3_PARAM(TranslucentClosure, params.N),
+ BSDF_CLOSURE_CLASS_END(Translucent, translucent)
+
+ BSDF_CLOSURE_CLASS_BEGIN(OrenNayar, oren_nayar, OrenNayarBsdf, LABEL_DIFFUSE)
+ CLOSURE_FLOAT3_PARAM(OrenNayarClosure, params.N),
+ CLOSURE_FLOAT_PARAM(OrenNayarClosure, params.roughness),
+ BSDF_CLOSURE_CLASS_END(OrenNayar, oren_nayar)
+
+ BSDF_CLOSURE_CLASS_BEGIN(Reflection, reflection, MicrofacetBsdf, LABEL_SINGULAR)
+ CLOSURE_FLOAT3_PARAM(ReflectionClosure, params.N),
+ BSDF_CLOSURE_CLASS_END(Reflection, reflection)
+
+ BSDF_CLOSURE_CLASS_BEGIN(Refraction, refraction, MicrofacetBsdf, LABEL_SINGULAR)
+ CLOSURE_FLOAT3_PARAM(RefractionClosure, params.N),
+ CLOSURE_FLOAT_PARAM(RefractionClosure, params.ior),
+ BSDF_CLOSURE_CLASS_END(Refraction, refraction)
+
+ BSDF_CLOSURE_CLASS_BEGIN(AshikhminVelvet, ashikhmin_velvet, VelvetBsdf, LABEL_DIFFUSE)
+ CLOSURE_FLOAT3_PARAM(AshikhminVelvetClosure, params.N),
+ CLOSURE_FLOAT_PARAM(AshikhminVelvetClosure, params.sigma),
+ BSDF_CLOSURE_CLASS_END(AshikhminVelvet, ashikhmin_velvet)
+
+ BSDF_CLOSURE_CLASS_BEGIN(AshikhminShirley,
+ ashikhmin_shirley_aniso,
+ MicrofacetBsdf,
+ LABEL_GLOSSY | LABEL_REFLECT)
+ CLOSURE_FLOAT3_PARAM(AshikhminShirleyClosure, params.N),
+ CLOSURE_FLOAT3_PARAM(AshikhminShirleyClosure, params.T),
+ CLOSURE_FLOAT_PARAM(AshikhminShirleyClosure, params.alpha_x),
+ CLOSURE_FLOAT_PARAM(AshikhminShirleyClosure, params.alpha_y),
+ BSDF_CLOSURE_CLASS_END(AshikhminShirley, ashikhmin_shirley_aniso)
+
+ BSDF_CLOSURE_CLASS_BEGIN(DiffuseToon, diffuse_toon, ToonBsdf, LABEL_DIFFUSE)
+ CLOSURE_FLOAT3_PARAM(DiffuseToonClosure, params.N),
+ CLOSURE_FLOAT_PARAM(DiffuseToonClosure, params.size),
+ CLOSURE_FLOAT_PARAM(DiffuseToonClosure, params.smooth),
+ BSDF_CLOSURE_CLASS_END(DiffuseToon, diffuse_toon)
+
+ BSDF_CLOSURE_CLASS_BEGIN(GlossyToon, glossy_toon, ToonBsdf, LABEL_GLOSSY)
+ CLOSURE_FLOAT3_PARAM(GlossyToonClosure, params.N),
+ CLOSURE_FLOAT_PARAM(GlossyToonClosure, params.size),
+ CLOSURE_FLOAT_PARAM(GlossyToonClosure, params.smooth),
+ BSDF_CLOSURE_CLASS_END(GlossyToon, glossy_toon)
+
+ BSDF_CLOSURE_CLASS_BEGIN(MicrofacetGGX,
+ microfacet_ggx,
+ MicrofacetBsdf,
+ LABEL_GLOSSY | LABEL_REFLECT)
+ CLOSURE_FLOAT3_PARAM(MicrofacetGGXClosure, params.N),
+ CLOSURE_FLOAT_PARAM(MicrofacetGGXClosure, params.alpha_x),
+ BSDF_CLOSURE_CLASS_END(MicrofacetGGX, microfacet_ggx)
+
+ BSDF_CLOSURE_CLASS_BEGIN(MicrofacetGGXAniso,
+ microfacet_ggx_aniso,
+ MicrofacetBsdf,
+ LABEL_GLOSSY | LABEL_REFLECT)
+ CLOSURE_FLOAT3_PARAM(MicrofacetGGXAnisoClosure, params.N),
+ CLOSURE_FLOAT3_PARAM(MicrofacetGGXAnisoClosure, params.T),
+ CLOSURE_FLOAT_PARAM(MicrofacetGGXAnisoClosure, params.alpha_x),
+ CLOSURE_FLOAT_PARAM(MicrofacetGGXAnisoClosure, params.alpha_y),
+ BSDF_CLOSURE_CLASS_END(MicrofacetGGXAniso, microfacet_ggx_aniso)
+
+ BSDF_CLOSURE_CLASS_BEGIN(MicrofacetBeckmann,
+ microfacet_beckmann,
+ MicrofacetBsdf,
+ LABEL_GLOSSY | LABEL_REFLECT)
+ CLOSURE_FLOAT3_PARAM(MicrofacetBeckmannClosure, params.N),
+ CLOSURE_FLOAT_PARAM(MicrofacetBeckmannClosure, params.alpha_x),
+ BSDF_CLOSURE_CLASS_END(MicrofacetBeckmann, microfacet_beckmann)
+
+ BSDF_CLOSURE_CLASS_BEGIN(MicrofacetBeckmannAniso,
+ microfacet_beckmann_aniso,
+ MicrofacetBsdf,
+ LABEL_GLOSSY | LABEL_REFLECT)
+ CLOSURE_FLOAT3_PARAM(MicrofacetBeckmannAnisoClosure, params.N),
+ CLOSURE_FLOAT3_PARAM(MicrofacetBeckmannAnisoClosure, params.T),
+ CLOSURE_FLOAT_PARAM(MicrofacetBeckmannAnisoClosure, params.alpha_x),
+ CLOSURE_FLOAT_PARAM(MicrofacetBeckmannAnisoClosure, params.alpha_y),
+ BSDF_CLOSURE_CLASS_END(MicrofacetBeckmannAniso, microfacet_beckmann_aniso)
+
+ BSDF_CLOSURE_CLASS_BEGIN(MicrofacetGGXRefraction,
+ microfacet_ggx_refraction,
+ MicrofacetBsdf,
+ LABEL_GLOSSY | LABEL_TRANSMIT)
+ CLOSURE_FLOAT3_PARAM(MicrofacetGGXRefractionClosure, params.N),
+ CLOSURE_FLOAT_PARAM(MicrofacetGGXRefractionClosure, params.alpha_x),
+ CLOSURE_FLOAT_PARAM(MicrofacetGGXRefractionClosure, params.ior),
+ BSDF_CLOSURE_CLASS_END(MicrofacetGGXRefraction, microfacet_ggx_refraction)
+
+ BSDF_CLOSURE_CLASS_BEGIN(MicrofacetBeckmannRefraction,
+ microfacet_beckmann_refraction,
+ MicrofacetBsdf,
+ LABEL_GLOSSY | LABEL_TRANSMIT)
+ CLOSURE_FLOAT3_PARAM(MicrofacetBeckmannRefractionClosure, params.N),
+ CLOSURE_FLOAT_PARAM(MicrofacetBeckmannRefractionClosure, params.alpha_x),
+ CLOSURE_FLOAT_PARAM(MicrofacetBeckmannRefractionClosure, params.ior),
+ BSDF_CLOSURE_CLASS_END(MicrofacetBeckmannRefraction, microfacet_beckmann_refraction)
+
+ BSDF_CLOSURE_CLASS_BEGIN(HairReflection, hair_reflection, HairBsdf, LABEL_GLOSSY)
+ CLOSURE_FLOAT3_PARAM(HairReflectionClosure, params.N),
+ CLOSURE_FLOAT_PARAM(HairReflectionClosure, params.roughness1),
+ CLOSURE_FLOAT_PARAM(HairReflectionClosure, params.roughness2),
+ CLOSURE_FLOAT3_PARAM(HairReflectionClosure, params.T),
+ CLOSURE_FLOAT_PARAM(HairReflectionClosure, params.offset),
+ BSDF_CLOSURE_CLASS_END(HairReflection, hair_reflection)
+
+ BSDF_CLOSURE_CLASS_BEGIN(HairTransmission, hair_transmission, HairBsdf, LABEL_GLOSSY)
+ CLOSURE_FLOAT3_PARAM(HairTransmissionClosure, params.N),
+ CLOSURE_FLOAT_PARAM(HairTransmissionClosure, params.roughness1),
+ CLOSURE_FLOAT_PARAM(HairTransmissionClosure, params.roughness2),
+ CLOSURE_FLOAT3_PARAM(HairReflectionClosure, params.T),
+ CLOSURE_FLOAT_PARAM(HairReflectionClosure, params.offset),
+ BSDF_CLOSURE_CLASS_END(HairTransmission, hair_transmission)
+
+ BSDF_CLOSURE_CLASS_BEGIN(PrincipledDiffuse,
+ principled_diffuse,
+ PrincipledDiffuseBsdf,
+ LABEL_DIFFUSE)
+ CLOSURE_FLOAT3_PARAM(PrincipledDiffuseClosure, params.N),
+ CLOSURE_FLOAT_PARAM(PrincipledDiffuseClosure, params.roughness),
+ BSDF_CLOSURE_CLASS_END(PrincipledDiffuse, principled_diffuse)
+
+ BSDF_CLOSURE_CLASS_BEGIN(PrincipledSheen,
+ principled_sheen,
+ PrincipledSheenBsdf,
+ LABEL_DIFFUSE)
+ CLOSURE_FLOAT3_PARAM(PrincipledSheenClosure, params.N),
+ BSDF_CLOSURE_CLASS_END(PrincipledSheen, principled_sheen)
+
+ /* PRINCIPLED HAIR BSDF */
+ class PrincipledHairClosure : public CBSDFClosure {
+ public:
+ PrincipledHairBSDF params;
+
+ PrincipledHairBSDF *alloc(ShaderData *sd, int path_flag, float3 weight)
+ {
+ PrincipledHairBSDF *bsdf = (PrincipledHairBSDF *)bsdf_alloc_osl(
+ sd, sizeof(PrincipledHairBSDF), weight, &params);
+ if (!bsdf) {
+ return NULL;
+ }
+
+ PrincipledHairExtra *extra = (PrincipledHairExtra *)closure_alloc_extra(
+ sd, sizeof(PrincipledHairExtra));
+ if (!extra) {
+ return NULL;
+ }
+
+ bsdf->extra = extra;
+ return bsdf;
+ }
+
+ void setup(ShaderData *sd, int path_flag, float3 weight)
+ {
+ if (!skip(sd, path_flag, LABEL_GLOSSY)) {
+ PrincipledHairBSDF *bsdf = (PrincipledHairBSDF *)alloc(sd, path_flag, weight);
+ if (!bsdf) {
+ return;
+ }
+
+ sd->flag |= (bsdf) ? bsdf_principled_hair_setup(sd, bsdf) : 0;
+ }
+ }
};
static ClosureParam *closure_bsdf_principled_hair_params()
{
- static ClosureParam params[] = {
- CLOSURE_FLOAT3_PARAM(PrincipledHairClosure, params.N),
- CLOSURE_FLOAT3_PARAM(PrincipledHairClosure, params.sigma),
- CLOSURE_FLOAT_PARAM(PrincipledHairClosure, params.v),
- CLOSURE_FLOAT_PARAM(PrincipledHairClosure, params.s),
- CLOSURE_FLOAT_PARAM(PrincipledHairClosure, params.m0_roughness),
- CLOSURE_FLOAT_PARAM(PrincipledHairClosure, params.alpha),
- CLOSURE_FLOAT_PARAM(PrincipledHairClosure, params.eta),
- CLOSURE_STRING_KEYPARAM(PrincipledHairClosure, label, "label"),
- CLOSURE_FINISH_PARAM(PrincipledHairClosure)
- };
-
- return params;
+ static ClosureParam params[] = {CLOSURE_FLOAT3_PARAM(PrincipledHairClosure, params.N),
+ CLOSURE_FLOAT3_PARAM(PrincipledHairClosure, params.sigma),
+ CLOSURE_FLOAT_PARAM(PrincipledHairClosure, params.v),
+ CLOSURE_FLOAT_PARAM(PrincipledHairClosure, params.s),
+ CLOSURE_FLOAT_PARAM(PrincipledHairClosure, params.m0_roughness),
+ CLOSURE_FLOAT_PARAM(PrincipledHairClosure, params.alpha),
+ CLOSURE_FLOAT_PARAM(PrincipledHairClosure, params.eta),
+ CLOSURE_STRING_KEYPARAM(PrincipledHairClosure, label, "label"),
+ CLOSURE_FINISH_PARAM(PrincipledHairClosure)};
+
+ return params;
}
CCLOSURE_PREPARE(closure_bsdf_principled_hair_prepare, PrincipledHairClosure)
/* DISNEY PRINCIPLED CLEARCOAT */
class PrincipledClearcoatClosure : public CBSDFClosure {
-public:
- MicrofacetBsdf params;
- float clearcoat, clearcoat_roughness;
-
- MicrofacetBsdf *alloc(ShaderData *sd, int path_flag, float3 weight)
- {
- MicrofacetBsdf *bsdf = (MicrofacetBsdf*)bsdf_alloc_osl(sd, sizeof(MicrofacetBsdf), weight, &params);
- if(!bsdf) {
- return NULL;
- }
-
- MicrofacetExtra *extra = (MicrofacetExtra*)closure_alloc_extra(sd, sizeof(MicrofacetExtra));
- if(!extra) {
- return NULL;
- }
-
- bsdf->T = make_float3(0.0f, 0.0f, 0.0f);
- bsdf->extra = extra;
- bsdf->ior = 1.5f;
- bsdf->alpha_x = clearcoat_roughness;
- bsdf->alpha_y = clearcoat_roughness;
- bsdf->extra->color = make_float3(0.0f, 0.0f, 0.0f);
- bsdf->extra->cspec0 = make_float3(0.04f, 0.04f, 0.04f);
- bsdf->extra->clearcoat = clearcoat;
- return bsdf;
- }
-
- void setup(ShaderData *sd, int path_flag, float3 weight)
- {
- MicrofacetBsdf *bsdf = alloc(sd, path_flag, weight);
- if(!bsdf) {
- return;
- }
-
- sd->flag |= bsdf_microfacet_ggx_clearcoat_setup(bsdf, sd);
- }
+ public:
+ MicrofacetBsdf params;
+ float clearcoat, clearcoat_roughness;
+
+ MicrofacetBsdf *alloc(ShaderData *sd, int path_flag, float3 weight)
+ {
+ MicrofacetBsdf *bsdf = (MicrofacetBsdf *)bsdf_alloc_osl(
+ sd, sizeof(MicrofacetBsdf), weight, &params);
+ if (!bsdf) {
+ return NULL;
+ }
+
+ MicrofacetExtra *extra = (MicrofacetExtra *)closure_alloc_extra(sd, sizeof(MicrofacetExtra));
+ if (!extra) {
+ return NULL;
+ }
+
+ bsdf->T = make_float3(0.0f, 0.0f, 0.0f);
+ bsdf->extra = extra;
+ bsdf->ior = 1.5f;
+ bsdf->alpha_x = clearcoat_roughness;
+ bsdf->alpha_y = clearcoat_roughness;
+ bsdf->extra->color = make_float3(0.0f, 0.0f, 0.0f);
+ bsdf->extra->cspec0 = make_float3(0.04f, 0.04f, 0.04f);
+ bsdf->extra->clearcoat = clearcoat;
+ return bsdf;
+ }
+
+ void setup(ShaderData *sd, int path_flag, float3 weight)
+ {
+ MicrofacetBsdf *bsdf = alloc(sd, path_flag, weight);
+ if (!bsdf) {
+ return;
+ }
+
+ sd->flag |= bsdf_microfacet_ggx_clearcoat_setup(bsdf, sd);
+ }
};
ClosureParam *closure_bsdf_principled_clearcoat_params()
{
- static ClosureParam params[] = {
- CLOSURE_FLOAT3_PARAM(PrincipledClearcoatClosure, params.N),
- CLOSURE_FLOAT_PARAM(PrincipledClearcoatClosure, clearcoat),
- CLOSURE_FLOAT_PARAM(PrincipledClearcoatClosure, clearcoat_roughness),
- CLOSURE_STRING_KEYPARAM(PrincipledClearcoatClosure, label, "label"),
- CLOSURE_FINISH_PARAM(PrincipledClearcoatClosure)
- };
- return params;
+ static ClosureParam params[] = {
+ CLOSURE_FLOAT3_PARAM(PrincipledClearcoatClosure, params.N),
+ CLOSURE_FLOAT_PARAM(PrincipledClearcoatClosure, clearcoat),
+ CLOSURE_FLOAT_PARAM(PrincipledClearcoatClosure, clearcoat_roughness),
+ CLOSURE_STRING_KEYPARAM(PrincipledClearcoatClosure, label, "label"),
+ CLOSURE_FINISH_PARAM(PrincipledClearcoatClosure)};
+ return params;
}
CCLOSURE_PREPARE(closure_bsdf_principled_clearcoat_prepare, PrincipledClearcoatClosure)
-
/* Registration */
-static void register_closure(OSL::ShadingSystem *ss, const char *name, int id, OSL::ClosureParam *params, OSL::PrepareClosureFunc prepare)
+static void register_closure(OSL::ShadingSystem *ss,
+ const char *name,
+ int id,
+ OSL::ClosureParam *params,
+ OSL::PrepareClosureFunc prepare)
{
- /* optimization: it's possible to not use a prepare function at all and
- * only initialize the actual class when accessing the closure component
- * data, but then we need to map the id to the class somehow */
+ /* optimization: it's possible to not use a prepare function at all and
+ * only initialize the actual class when accessing the closure component
+ * data, but then we need to map the id to the class somehow */
#if OSL_LIBRARY_VERSION_CODE >= 10900
- ss->register_closure(name, id, params, prepare, NULL);
+ ss->register_closure(name, id, params, prepare, NULL);
#else
- ss->register_closure(name, id, params, prepare, NULL, 16);
+ ss->register_closure(name, id, params, prepare, NULL, 16);
#endif
}
void OSLShader::register_closures(OSLShadingSystem *ss_)
{
- OSL::ShadingSystem *ss = (OSL::ShadingSystem*)ss_;
- int id = 0;
-
- register_closure(ss, "diffuse", id++,
- bsdf_diffuse_params(), bsdf_diffuse_prepare);
- register_closure(ss, "oren_nayar", id++,
- bsdf_oren_nayar_params(), bsdf_oren_nayar_prepare);
- register_closure(ss, "translucent", id++,
- bsdf_translucent_params(), bsdf_translucent_prepare);
- register_closure(ss, "reflection", id++,
- bsdf_reflection_params(), bsdf_reflection_prepare);
- register_closure(ss, "refraction", id++,
- bsdf_refraction_params(), bsdf_refraction_prepare);
- register_closure(ss, "transparent", id++,
- closure_bsdf_transparent_params(), closure_bsdf_transparent_prepare);
- register_closure(ss, "microfacet_ggx", id++,
- bsdf_microfacet_ggx_params(), bsdf_microfacet_ggx_prepare);
- register_closure(ss, "microfacet_ggx_aniso", id++,
- bsdf_microfacet_ggx_aniso_params(), bsdf_microfacet_ggx_aniso_prepare);
- register_closure(ss, "microfacet_ggx_refraction", id++,
- bsdf_microfacet_ggx_refraction_params(), bsdf_microfacet_ggx_refraction_prepare);
- register_closure(ss, "microfacet_multi_ggx", id++,
- closure_bsdf_microfacet_multi_ggx_params(), closure_bsdf_microfacet_multi_ggx_prepare);
- register_closure(ss, "microfacet_multi_ggx_glass", id++,
- closure_bsdf_microfacet_multi_ggx_glass_params(), closure_bsdf_microfacet_multi_ggx_glass_prepare);
- register_closure(ss, "microfacet_multi_ggx_aniso", id++,
- closure_bsdf_microfacet_multi_ggx_aniso_params(), closure_bsdf_microfacet_multi_ggx_aniso_prepare);
- register_closure(ss, "microfacet_ggx_fresnel", id++,
- closure_bsdf_microfacet_ggx_fresnel_params(), closure_bsdf_microfacet_ggx_fresnel_prepare);
- register_closure(ss, "microfacet_ggx_aniso_fresnel", id++,
- closure_bsdf_microfacet_ggx_aniso_fresnel_params(), closure_bsdf_microfacet_ggx_aniso_fresnel_prepare);
- register_closure(ss, "microfacet_multi_ggx_fresnel", id++,
- closure_bsdf_microfacet_multi_ggx_fresnel_params(), closure_bsdf_microfacet_multi_ggx_fresnel_prepare);
- register_closure(ss, "microfacet_multi_ggx_glass_fresnel", id++,
- closure_bsdf_microfacet_multi_ggx_glass_fresnel_params(), closure_bsdf_microfacet_multi_ggx_glass_fresnel_prepare);
- register_closure(ss, "microfacet_multi_ggx_aniso_fresnel", id++,
- closure_bsdf_microfacet_multi_ggx_aniso_fresnel_params(), closure_bsdf_microfacet_multi_ggx_aniso_fresnel_prepare);
- register_closure(ss, "microfacet_beckmann", id++,
- bsdf_microfacet_beckmann_params(), bsdf_microfacet_beckmann_prepare);
- register_closure(ss, "microfacet_beckmann_aniso", id++,
- bsdf_microfacet_beckmann_aniso_params(), bsdf_microfacet_beckmann_aniso_prepare);
- register_closure(ss, "microfacet_beckmann_refraction", id++,
- bsdf_microfacet_beckmann_refraction_params(), bsdf_microfacet_beckmann_refraction_prepare);
- register_closure(ss, "ashikhmin_shirley", id++,
- bsdf_ashikhmin_shirley_aniso_params(), bsdf_ashikhmin_shirley_aniso_prepare);
- register_closure(ss, "ashikhmin_velvet", id++,
- bsdf_ashikhmin_velvet_params(), bsdf_ashikhmin_velvet_prepare);
- register_closure(ss, "diffuse_toon", id++,
- bsdf_diffuse_toon_params(), bsdf_diffuse_toon_prepare);
- register_closure(ss, "glossy_toon", id++,
- bsdf_glossy_toon_params(), bsdf_glossy_toon_prepare);
- register_closure(ss, "principled_diffuse", id++,
- bsdf_principled_diffuse_params(), bsdf_principled_diffuse_prepare);
- register_closure(ss, "principled_sheen", id++,
- bsdf_principled_sheen_params(), bsdf_principled_sheen_prepare);
- register_closure(ss, "principled_clearcoat", id++,
- closure_bsdf_principled_clearcoat_params(), closure_bsdf_principled_clearcoat_prepare);
-
- register_closure(ss, "emission", id++,
- closure_emission_params(), closure_emission_prepare);
- register_closure(ss, "background", id++,
- closure_background_params(), closure_background_prepare);
- register_closure(ss, "holdout", id++,
- closure_holdout_params(), closure_holdout_prepare);
- register_closure(ss, "diffuse_ramp", id++,
- closure_bsdf_diffuse_ramp_params(), closure_bsdf_diffuse_ramp_prepare);
- register_closure(ss, "phong_ramp", id++,
- closure_bsdf_phong_ramp_params(), closure_bsdf_phong_ramp_prepare);
- register_closure(ss, "bssrdf", id++,
- closure_bssrdf_params(), closure_bssrdf_prepare);
-
- register_closure(ss, "hair_reflection", id++,
- bsdf_hair_reflection_params(), bsdf_hair_reflection_prepare);
- register_closure(ss, "hair_transmission", id++,
- bsdf_hair_transmission_params(), bsdf_hair_transmission_prepare);
-
- register_closure(ss, "principled_hair", id++,
- closure_bsdf_principled_hair_params(), closure_bsdf_principled_hair_prepare);
-
- register_closure(ss, "henyey_greenstein", id++,
- closure_henyey_greenstein_params(), closure_henyey_greenstein_prepare);
- register_closure(ss, "absorption", id++,
- closure_absorption_params(), closure_absorption_prepare);
+ OSL::ShadingSystem *ss = (OSL::ShadingSystem *)ss_;
+ int id = 0;
+
+ register_closure(ss, "diffuse", id++, bsdf_diffuse_params(), bsdf_diffuse_prepare);
+ register_closure(ss, "oren_nayar", id++, bsdf_oren_nayar_params(), bsdf_oren_nayar_prepare);
+ register_closure(ss, "translucent", id++, bsdf_translucent_params(), bsdf_translucent_prepare);
+ register_closure(ss, "reflection", id++, bsdf_reflection_params(), bsdf_reflection_prepare);
+ register_closure(ss, "refraction", id++, bsdf_refraction_params(), bsdf_refraction_prepare);
+ register_closure(ss,
+ "transparent",
+ id++,
+ closure_bsdf_transparent_params(),
+ closure_bsdf_transparent_prepare);
+ register_closure(
+ ss, "microfacet_ggx", id++, bsdf_microfacet_ggx_params(), bsdf_microfacet_ggx_prepare);
+ register_closure(ss,
+ "microfacet_ggx_aniso",
+ id++,
+ bsdf_microfacet_ggx_aniso_params(),
+ bsdf_microfacet_ggx_aniso_prepare);
+ register_closure(ss,
+ "microfacet_ggx_refraction",
+ id++,
+ bsdf_microfacet_ggx_refraction_params(),
+ bsdf_microfacet_ggx_refraction_prepare);
+ register_closure(ss,
+ "microfacet_multi_ggx",
+ id++,
+ closure_bsdf_microfacet_multi_ggx_params(),
+ closure_bsdf_microfacet_multi_ggx_prepare);
+ register_closure(ss,
+ "microfacet_multi_ggx_glass",
+ id++,
+ closure_bsdf_microfacet_multi_ggx_glass_params(),
+ closure_bsdf_microfacet_multi_ggx_glass_prepare);
+ register_closure(ss,
+ "microfacet_multi_ggx_aniso",
+ id++,
+ closure_bsdf_microfacet_multi_ggx_aniso_params(),
+ closure_bsdf_microfacet_multi_ggx_aniso_prepare);
+ register_closure(ss,
+ "microfacet_ggx_fresnel",
+ id++,
+ closure_bsdf_microfacet_ggx_fresnel_params(),
+ closure_bsdf_microfacet_ggx_fresnel_prepare);
+ register_closure(ss,
+ "microfacet_ggx_aniso_fresnel",
+ id++,
+ closure_bsdf_microfacet_ggx_aniso_fresnel_params(),
+ closure_bsdf_microfacet_ggx_aniso_fresnel_prepare);
+ register_closure(ss,
+ "microfacet_multi_ggx_fresnel",
+ id++,
+ closure_bsdf_microfacet_multi_ggx_fresnel_params(),
+ closure_bsdf_microfacet_multi_ggx_fresnel_prepare);
+ register_closure(ss,
+ "microfacet_multi_ggx_glass_fresnel",
+ id++,
+ closure_bsdf_microfacet_multi_ggx_glass_fresnel_params(),
+ closure_bsdf_microfacet_multi_ggx_glass_fresnel_prepare);
+ register_closure(ss,
+ "microfacet_multi_ggx_aniso_fresnel",
+ id++,
+ closure_bsdf_microfacet_multi_ggx_aniso_fresnel_params(),
+ closure_bsdf_microfacet_multi_ggx_aniso_fresnel_prepare);
+ register_closure(ss,
+ "microfacet_beckmann",
+ id++,
+ bsdf_microfacet_beckmann_params(),
+ bsdf_microfacet_beckmann_prepare);
+ register_closure(ss,
+ "microfacet_beckmann_aniso",
+ id++,
+ bsdf_microfacet_beckmann_aniso_params(),
+ bsdf_microfacet_beckmann_aniso_prepare);
+ register_closure(ss,
+ "microfacet_beckmann_refraction",
+ id++,
+ bsdf_microfacet_beckmann_refraction_params(),
+ bsdf_microfacet_beckmann_refraction_prepare);
+ register_closure(ss,
+ "ashikhmin_shirley",
+ id++,
+ bsdf_ashikhmin_shirley_aniso_params(),
+ bsdf_ashikhmin_shirley_aniso_prepare);
+ register_closure(
+ ss, "ashikhmin_velvet", id++, bsdf_ashikhmin_velvet_params(), bsdf_ashikhmin_velvet_prepare);
+ register_closure(
+ ss, "diffuse_toon", id++, bsdf_diffuse_toon_params(), bsdf_diffuse_toon_prepare);
+ register_closure(ss, "glossy_toon", id++, bsdf_glossy_toon_params(), bsdf_glossy_toon_prepare);
+ register_closure(ss,
+ "principled_diffuse",
+ id++,
+ bsdf_principled_diffuse_params(),
+ bsdf_principled_diffuse_prepare);
+ register_closure(
+ ss, "principled_sheen", id++, bsdf_principled_sheen_params(), bsdf_principled_sheen_prepare);
+ register_closure(ss,
+ "principled_clearcoat",
+ id++,
+ closure_bsdf_principled_clearcoat_params(),
+ closure_bsdf_principled_clearcoat_prepare);
+
+ register_closure(ss, "emission", id++, closure_emission_params(), closure_emission_prepare);
+ register_closure(
+ ss, "background", id++, closure_background_params(), closure_background_prepare);
+ register_closure(ss, "holdout", id++, closure_holdout_params(), closure_holdout_prepare);
+ register_closure(ss,
+ "diffuse_ramp",
+ id++,
+ closure_bsdf_diffuse_ramp_params(),
+ closure_bsdf_diffuse_ramp_prepare);
+ register_closure(
+ ss, "phong_ramp", id++, closure_bsdf_phong_ramp_params(), closure_bsdf_phong_ramp_prepare);
+ register_closure(ss, "bssrdf", id++, closure_bssrdf_params(), closure_bssrdf_prepare);
+
+ register_closure(
+ ss, "hair_reflection", id++, bsdf_hair_reflection_params(), bsdf_hair_reflection_prepare);
+ register_closure(ss,
+ "hair_transmission",
+ id++,
+ bsdf_hair_transmission_params(),
+ bsdf_hair_transmission_prepare);
+
+ register_closure(ss,
+ "principled_hair",
+ id++,
+ closure_bsdf_principled_hair_params(),
+ closure_bsdf_principled_hair_prepare);
+
+ register_closure(ss,
+ "henyey_greenstein",
+ id++,
+ closure_henyey_greenstein_params(),
+ closure_henyey_greenstein_prepare);
+ register_closure(
+ ss, "absorption", id++, closure_absorption_params(), closure_absorption_prepare);
}
/* BSDF Closure */
bool CBSDFClosure::skip(const ShaderData *sd, int path_flag, int scattering)
{
- /* caustic options */
- if((scattering & LABEL_GLOSSY) && (path_flag & PATH_RAY_DIFFUSE)) {
- KernelGlobals *kg = sd->osl_globals;
-
- if((!kernel_data.integrator.caustics_reflective && (scattering & LABEL_REFLECT)) ||
- (!kernel_data.integrator.caustics_refractive && (scattering & LABEL_TRANSMIT)))
- {
- return true;
- }
- }
-
- return false;
-}
+ /* caustic options */
+ if ((scattering & LABEL_GLOSSY) && (path_flag & PATH_RAY_DIFFUSE)) {
+ KernelGlobals *kg = sd->osl_globals;
+ if ((!kernel_data.integrator.caustics_reflective && (scattering & LABEL_REFLECT)) ||
+ (!kernel_data.integrator.caustics_refractive && (scattering & LABEL_TRANSMIT))) {
+ return true;
+ }
+ }
+
+ return false;
+}
/* GGX closures with Fresnel */
class MicrofacetFresnelClosure : public CBSDFClosure {
-public:
- MicrofacetBsdf params;
- float3 color;
- float3 cspec0;
-
- MicrofacetBsdf *alloc(ShaderData *sd, int path_flag, float3 weight)
- {
- /* Technically, the MultiGGX Glass closure may also transmit. However,
- * since this is set statically and only used for caustic flags, this
- * is probably as good as it gets. */
- if(skip(sd, path_flag, LABEL_GLOSSY | LABEL_REFLECT)) {
- return NULL;
- }
-
- MicrofacetBsdf *bsdf = (MicrofacetBsdf*)bsdf_alloc_osl(sd, sizeof(MicrofacetBsdf), weight, &params);
- if(!bsdf) {
- return NULL;
- }
-
- MicrofacetExtra *extra = (MicrofacetExtra*)closure_alloc_extra(sd, sizeof(MicrofacetExtra));
- if(!extra) {
- return NULL;
- }
-
- bsdf->extra = extra;
- bsdf->extra->color = color;
- bsdf->extra->cspec0 = cspec0;
- bsdf->extra->clearcoat = 0.0f;
- return bsdf;
- }
+ public:
+ MicrofacetBsdf params;
+ float3 color;
+ float3 cspec0;
+
+ MicrofacetBsdf *alloc(ShaderData *sd, int path_flag, float3 weight)
+ {
+ /* Technically, the MultiGGX Glass closure may also transmit. However,
+ * since this is set statically and only used for caustic flags, this
+ * is probably as good as it gets. */
+ if (skip(sd, path_flag, LABEL_GLOSSY | LABEL_REFLECT)) {
+ return NULL;
+ }
+
+ MicrofacetBsdf *bsdf = (MicrofacetBsdf *)bsdf_alloc_osl(
+ sd, sizeof(MicrofacetBsdf), weight, &params);
+ if (!bsdf) {
+ return NULL;
+ }
+
+ MicrofacetExtra *extra = (MicrofacetExtra *)closure_alloc_extra(sd, sizeof(MicrofacetExtra));
+ if (!extra) {
+ return NULL;
+ }
+
+ bsdf->extra = extra;
+ bsdf->extra->color = color;
+ bsdf->extra->cspec0 = cspec0;
+ bsdf->extra->clearcoat = 0.0f;
+ return bsdf;
+ }
};
class MicrofacetGGXFresnelClosure : public MicrofacetFresnelClosure {
-public:
- void setup(ShaderData *sd, int path_flag, float3 weight)
- {
- MicrofacetBsdf *bsdf = alloc(sd, path_flag, weight);
- if(!bsdf) {
- return;
- }
-
- bsdf->T = make_float3(0.0f, 0.0f, 0.0f);
- bsdf->alpha_y = bsdf->alpha_x;
- sd->flag |= bsdf_microfacet_ggx_fresnel_setup(bsdf, sd);
- }
+ public:
+ void setup(ShaderData *sd, int path_flag, float3 weight)
+ {
+ MicrofacetBsdf *bsdf = alloc(sd, path_flag, weight);
+ if (!bsdf) {
+ return;
+ }
+
+ bsdf->T = make_float3(0.0f, 0.0f, 0.0f);
+ bsdf->alpha_y = bsdf->alpha_x;
+ sd->flag |= bsdf_microfacet_ggx_fresnel_setup(bsdf, sd);
+ }
};
ClosureParam *closure_bsdf_microfacet_ggx_fresnel_params()
{
- static ClosureParam params[] = {
- CLOSURE_FLOAT3_PARAM(MicrofacetGGXFresnelClosure, params.N),
- CLOSURE_FLOAT_PARAM(MicrofacetGGXFresnelClosure, params.alpha_x),
- CLOSURE_FLOAT_PARAM(MicrofacetGGXFresnelClosure, params.ior),
- CLOSURE_FLOAT3_PARAM(MicrofacetGGXFresnelClosure, color),
- CLOSURE_FLOAT3_PARAM(MicrofacetGGXFresnelClosure, cspec0),
- CLOSURE_STRING_KEYPARAM(MicrofacetGGXFresnelClosure, label, "label"),
- CLOSURE_FINISH_PARAM(MicrofacetGGXFresnelClosure)
- };
- return params;
+ static ClosureParam params[] = {
+ CLOSURE_FLOAT3_PARAM(MicrofacetGGXFresnelClosure, params.N),
+ CLOSURE_FLOAT_PARAM(MicrofacetGGXFresnelClosure, params.alpha_x),
+ CLOSURE_FLOAT_PARAM(MicrofacetGGXFresnelClosure, params.ior),
+ CLOSURE_FLOAT3_PARAM(MicrofacetGGXFresnelClosure, color),
+ CLOSURE_FLOAT3_PARAM(MicrofacetGGXFresnelClosure, cspec0),
+ CLOSURE_STRING_KEYPARAM(MicrofacetGGXFresnelClosure, label, "label"),
+ CLOSURE_FINISH_PARAM(MicrofacetGGXFresnelClosure)};
+ return params;
}
CCLOSURE_PREPARE(closure_bsdf_microfacet_ggx_fresnel_prepare, MicrofacetGGXFresnelClosure);
class MicrofacetGGXAnisoFresnelClosure : public MicrofacetFresnelClosure {
-public:
- void setup(ShaderData *sd, int path_flag, float3 weight)
- {
- MicrofacetBsdf *bsdf = alloc(sd, path_flag, weight);
- if(!bsdf) {
- return;
- }
-
- sd->flag |= bsdf_microfacet_ggx_aniso_fresnel_setup(bsdf, sd);
- }
+ public:
+ void setup(ShaderData *sd, int path_flag, float3 weight)
+ {
+ MicrofacetBsdf *bsdf = alloc(sd, path_flag, weight);
+ if (!bsdf) {
+ return;
+ }
+
+ sd->flag |= bsdf_microfacet_ggx_aniso_fresnel_setup(bsdf, sd);
+ }
};
ClosureParam *closure_bsdf_microfacet_ggx_aniso_fresnel_params()
{
- static ClosureParam params[] = {
- CLOSURE_FLOAT3_PARAM(MicrofacetGGXFresnelClosure, params.N),
- CLOSURE_FLOAT3_PARAM(MicrofacetGGXFresnelClosure, params.T),
- CLOSURE_FLOAT_PARAM(MicrofacetGGXFresnelClosure, params.alpha_x),
- CLOSURE_FLOAT_PARAM(MicrofacetGGXFresnelClosure, params.alpha_y),
- CLOSURE_FLOAT_PARAM(MicrofacetGGXFresnelClosure, params.ior),
- CLOSURE_FLOAT3_PARAM(MicrofacetGGXFresnelClosure, color),
- CLOSURE_FLOAT3_PARAM(MicrofacetGGXFresnelClosure, cspec0),
- CLOSURE_STRING_KEYPARAM(MicrofacetGGXFresnelClosure, label, "label"),
- CLOSURE_FINISH_PARAM(MicrofacetGGXFresnelClosure)
- };
- return params;
+ static ClosureParam params[] = {
+ CLOSURE_FLOAT3_PARAM(MicrofacetGGXFresnelClosure, params.N),
+ CLOSURE_FLOAT3_PARAM(MicrofacetGGXFresnelClosure, params.T),
+ CLOSURE_FLOAT_PARAM(MicrofacetGGXFresnelClosure, params.alpha_x),
+ CLOSURE_FLOAT_PARAM(MicrofacetGGXFresnelClosure, params.alpha_y),
+ CLOSURE_FLOAT_PARAM(MicrofacetGGXFresnelClosure, params.ior),
+ CLOSURE_FLOAT3_PARAM(MicrofacetGGXFresnelClosure, color),
+ CLOSURE_FLOAT3_PARAM(MicrofacetGGXFresnelClosure, cspec0),
+ CLOSURE_STRING_KEYPARAM(MicrofacetGGXFresnelClosure, label, "label"),
+ CLOSURE_FINISH_PARAM(MicrofacetGGXFresnelClosure)};
+ return params;
}
-CCLOSURE_PREPARE(closure_bsdf_microfacet_ggx_aniso_fresnel_prepare, MicrofacetGGXAnisoFresnelClosure);
-
+CCLOSURE_PREPARE(closure_bsdf_microfacet_ggx_aniso_fresnel_prepare,
+ MicrofacetGGXAnisoFresnelClosure);
/* Multiscattering GGX closures */
class MicrofacetMultiClosure : public CBSDFClosure {
-public:
- MicrofacetBsdf params;
- float3 color;
-
- MicrofacetBsdf *alloc(ShaderData *sd, int path_flag, float3 weight)
- {
- /* Technically, the MultiGGX closure may also transmit. However,
- * since this is set statically and only used for caustic flags, this
- * is probably as good as it gets. */
- if(skip(sd, path_flag, LABEL_GLOSSY|LABEL_REFLECT)) {
- return NULL;
- }
-
- MicrofacetBsdf *bsdf = (MicrofacetBsdf*)bsdf_alloc_osl(sd, sizeof(MicrofacetBsdf), weight, &params);
- if(!bsdf) {
- return NULL;
- }
-
- MicrofacetExtra *extra = (MicrofacetExtra*)closure_alloc_extra(sd, sizeof(MicrofacetExtra));
- if(!extra) {
- return NULL;
- }
-
- bsdf->extra = extra;
- bsdf->extra->color = color;
- bsdf->extra->cspec0 = make_float3(0.0f, 0.0f, 0.0f);
- bsdf->extra->clearcoat = 0.0f;
- return bsdf;
- }
+ public:
+ MicrofacetBsdf params;
+ float3 color;
+
+ MicrofacetBsdf *alloc(ShaderData *sd, int path_flag, float3 weight)
+ {
+ /* Technically, the MultiGGX closure may also transmit. However,
+ * since this is set statically and only used for caustic flags, this
+ * is probably as good as it gets. */
+ if (skip(sd, path_flag, LABEL_GLOSSY | LABEL_REFLECT)) {
+ return NULL;
+ }
+
+ MicrofacetBsdf *bsdf = (MicrofacetBsdf *)bsdf_alloc_osl(
+ sd, sizeof(MicrofacetBsdf), weight, &params);
+ if (!bsdf) {
+ return NULL;
+ }
+
+ MicrofacetExtra *extra = (MicrofacetExtra *)closure_alloc_extra(sd, sizeof(MicrofacetExtra));
+ if (!extra) {
+ return NULL;
+ }
+
+ bsdf->extra = extra;
+ bsdf->extra->color = color;
+ bsdf->extra->cspec0 = make_float3(0.0f, 0.0f, 0.0f);
+ bsdf->extra->clearcoat = 0.0f;
+ return bsdf;
+ }
};
class MicrofacetMultiGGXClosure : public MicrofacetMultiClosure {
-public:
- void setup(ShaderData *sd, int path_flag, float3 weight)
- {
- MicrofacetBsdf *bsdf = alloc(sd, path_flag, weight);
- if(!bsdf) {
- return;
- }
-
- bsdf->ior = 0.0f;
- bsdf->T = make_float3(0.0f, 0.0f, 0.0f);
- bsdf->alpha_y = bsdf->alpha_x;
- sd->flag |= bsdf_microfacet_multi_ggx_setup(bsdf);
- }
+ public:
+ void setup(ShaderData *sd, int path_flag, float3 weight)
+ {
+ MicrofacetBsdf *bsdf = alloc(sd, path_flag, weight);
+ if (!bsdf) {
+ return;
+ }
+
+ bsdf->ior = 0.0f;
+ bsdf->T = make_float3(0.0f, 0.0f, 0.0f);
+ bsdf->alpha_y = bsdf->alpha_x;
+ sd->flag |= bsdf_microfacet_multi_ggx_setup(bsdf);
+ }
};
ClosureParam *closure_bsdf_microfacet_multi_ggx_params()
{
- static ClosureParam params[] = {
- CLOSURE_FLOAT3_PARAM(MicrofacetMultiGGXClosure, params.N),
- CLOSURE_FLOAT_PARAM(MicrofacetMultiGGXClosure, params.alpha_x),
- CLOSURE_FLOAT3_PARAM(MicrofacetMultiGGXClosure, color),
- CLOSURE_STRING_KEYPARAM(MicrofacetMultiGGXClosure, label, "label"),
- CLOSURE_FINISH_PARAM(MicrofacetMultiGGXClosure)
- };
- return params;
+ static ClosureParam params[] = {
+ CLOSURE_FLOAT3_PARAM(MicrofacetMultiGGXClosure, params.N),
+ CLOSURE_FLOAT_PARAM(MicrofacetMultiGGXClosure, params.alpha_x),
+ CLOSURE_FLOAT3_PARAM(MicrofacetMultiGGXClosure, color),
+ CLOSURE_STRING_KEYPARAM(MicrofacetMultiGGXClosure, label, "label"),
+ CLOSURE_FINISH_PARAM(MicrofacetMultiGGXClosure)};
+ return params;
}
CCLOSURE_PREPARE(closure_bsdf_microfacet_multi_ggx_prepare, MicrofacetMultiGGXClosure);
class MicrofacetMultiGGXAnisoClosure : public MicrofacetMultiClosure {
-public:
- void setup(ShaderData *sd, int path_flag, float3 weight)
- {
- MicrofacetBsdf *bsdf = alloc(sd, path_flag, weight);
- if(!bsdf) {
- return;
- }
-
- bsdf->ior = 0.0f;
- sd->flag |= bsdf_microfacet_multi_ggx_aniso_setup(bsdf);
- }
+ public:
+ void setup(ShaderData *sd, int path_flag, float3 weight)
+ {
+ MicrofacetBsdf *bsdf = alloc(sd, path_flag, weight);
+ if (!bsdf) {
+ return;
+ }
+
+ bsdf->ior = 0.0f;
+ sd->flag |= bsdf_microfacet_multi_ggx_aniso_setup(bsdf);
+ }
};
ClosureParam *closure_bsdf_microfacet_multi_ggx_aniso_params()
{
- static ClosureParam params[] = {
- CLOSURE_FLOAT3_PARAM(MicrofacetMultiGGXClosure, params.N),
- CLOSURE_FLOAT3_PARAM(MicrofacetMultiGGXClosure, params.T),
- CLOSURE_FLOAT_PARAM(MicrofacetMultiGGXClosure, params.alpha_x),
- CLOSURE_FLOAT_PARAM(MicrofacetMultiGGXClosure, params.alpha_y),
- CLOSURE_FLOAT3_PARAM(MicrofacetMultiGGXClosure, color),
- CLOSURE_STRING_KEYPARAM(MicrofacetMultiGGXClosure, label, "label"),
- CLOSURE_FINISH_PARAM(MicrofacetMultiGGXClosure)
- };
- return params;
+ static ClosureParam params[] = {
+ CLOSURE_FLOAT3_PARAM(MicrofacetMultiGGXClosure, params.N),
+ CLOSURE_FLOAT3_PARAM(MicrofacetMultiGGXClosure, params.T),
+ CLOSURE_FLOAT_PARAM(MicrofacetMultiGGXClosure, params.alpha_x),
+ CLOSURE_FLOAT_PARAM(MicrofacetMultiGGXClosure, params.alpha_y),
+ CLOSURE_FLOAT3_PARAM(MicrofacetMultiGGXClosure, color),
+ CLOSURE_STRING_KEYPARAM(MicrofacetMultiGGXClosure, label, "label"),
+ CLOSURE_FINISH_PARAM(MicrofacetMultiGGXClosure)};
+ return params;
}
CCLOSURE_PREPARE(closure_bsdf_microfacet_multi_ggx_aniso_prepare, MicrofacetMultiGGXAnisoClosure);
class MicrofacetMultiGGXGlassClosure : public MicrofacetMultiClosure {
-public:
- MicrofacetMultiGGXGlassClosure() : MicrofacetMultiClosure() {}
-
- void setup(ShaderData *sd, int path_flag, float3 weight)
- {
- MicrofacetBsdf *bsdf = alloc(sd, path_flag, weight);
- if(!bsdf) {
- return;
- }
-
- bsdf->T = make_float3(0.0f, 0.0f, 0.0f);
- bsdf->alpha_y = bsdf->alpha_x;
- sd->flag |= bsdf_microfacet_multi_ggx_glass_setup(bsdf);
- }
+ public:
+ MicrofacetMultiGGXGlassClosure() : MicrofacetMultiClosure()
+ {
+ }
+
+ void setup(ShaderData *sd, int path_flag, float3 weight)
+ {
+ MicrofacetBsdf *bsdf = alloc(sd, path_flag, weight);
+ if (!bsdf) {
+ return;
+ }
+
+ bsdf->T = make_float3(0.0f, 0.0f, 0.0f);
+ bsdf->alpha_y = bsdf->alpha_x;
+ sd->flag |= bsdf_microfacet_multi_ggx_glass_setup(bsdf);
+ }
};
ClosureParam *closure_bsdf_microfacet_multi_ggx_glass_params()
{
- static ClosureParam params[] = {
- CLOSURE_FLOAT3_PARAM(MicrofacetMultiGGXClosure, params.N),
- CLOSURE_FLOAT_PARAM(MicrofacetMultiGGXClosure, params.alpha_x),
- CLOSURE_FLOAT_PARAM(MicrofacetMultiGGXClosure, params.ior),
- CLOSURE_FLOAT3_PARAM(MicrofacetMultiGGXClosure, color),
- CLOSURE_STRING_KEYPARAM(MicrofacetMultiGGXClosure, label, "label"),
- CLOSURE_FINISH_PARAM(MicrofacetMultiGGXClosure)
- };
- return params;
+ static ClosureParam params[] = {
+ CLOSURE_FLOAT3_PARAM(MicrofacetMultiGGXClosure, params.N),
+ CLOSURE_FLOAT_PARAM(MicrofacetMultiGGXClosure, params.alpha_x),
+ CLOSURE_FLOAT_PARAM(MicrofacetMultiGGXClosure, params.ior),
+ CLOSURE_FLOAT3_PARAM(MicrofacetMultiGGXClosure, color),
+ CLOSURE_STRING_KEYPARAM(MicrofacetMultiGGXClosure, label, "label"),
+ CLOSURE_FINISH_PARAM(MicrofacetMultiGGXClosure)};
+ return params;
}
CCLOSURE_PREPARE(closure_bsdf_microfacet_multi_ggx_glass_prepare, MicrofacetMultiGGXGlassClosure);
-
/* Multiscattering GGX closures with Fresnel */
class MicrofacetMultiFresnelClosure : public CBSDFClosure {
-public:
- MicrofacetBsdf params;
- float3 color;
- float3 cspec0;
-
- MicrofacetBsdf *alloc(ShaderData *sd, int path_flag, float3 weight)
- {
- /* Technically, the MultiGGX closure may also transmit. However,
- * since this is set statically and only used for caustic flags, this
- * is probably as good as it gets. */
- if(skip(sd, path_flag, LABEL_GLOSSY | LABEL_REFLECT)) {
- return NULL;
- }
-
- MicrofacetBsdf *bsdf = (MicrofacetBsdf*)bsdf_alloc_osl(sd, sizeof(MicrofacetBsdf), weight, &params);
- if(!bsdf) {
- return NULL;
- }
-
- MicrofacetExtra *extra = (MicrofacetExtra*)closure_alloc_extra(sd, sizeof(MicrofacetExtra));
- if(!extra) {
- return NULL;
- }
-
- bsdf->extra = extra;
- bsdf->extra->color = color;
- bsdf->extra->cspec0 = cspec0;
- bsdf->extra->clearcoat = 0.0f;
- return bsdf;
- }
+ public:
+ MicrofacetBsdf params;
+ float3 color;
+ float3 cspec0;
+
+ MicrofacetBsdf *alloc(ShaderData *sd, int path_flag, float3 weight)
+ {
+ /* Technically, the MultiGGX closure may also transmit. However,
+ * since this is set statically and only used for caustic flags, this
+ * is probably as good as it gets. */
+ if (skip(sd, path_flag, LABEL_GLOSSY | LABEL_REFLECT)) {
+ return NULL;
+ }
+
+ MicrofacetBsdf *bsdf = (MicrofacetBsdf *)bsdf_alloc_osl(
+ sd, sizeof(MicrofacetBsdf), weight, &params);
+ if (!bsdf) {
+ return NULL;
+ }
+
+ MicrofacetExtra *extra = (MicrofacetExtra *)closure_alloc_extra(sd, sizeof(MicrofacetExtra));
+ if (!extra) {
+ return NULL;
+ }
+
+ bsdf->extra = extra;
+ bsdf->extra->color = color;
+ bsdf->extra->cspec0 = cspec0;
+ bsdf->extra->clearcoat = 0.0f;
+ return bsdf;
+ }
};
class MicrofacetMultiGGXFresnelClosure : public MicrofacetMultiFresnelClosure {
-public:
- void setup(ShaderData *sd, int path_flag, float3 weight)
- {
- MicrofacetBsdf *bsdf = alloc(sd, path_flag, weight);
- if(!bsdf) {
- return;
- }
-
- bsdf->T = make_float3(0.0f, 0.0f, 0.0f);
- bsdf->alpha_y = bsdf->alpha_x;
- sd->flag |= bsdf_microfacet_multi_ggx_fresnel_setup(bsdf, sd);
- }
+ public:
+ void setup(ShaderData *sd, int path_flag, float3 weight)
+ {
+ MicrofacetBsdf *bsdf = alloc(sd, path_flag, weight);
+ if (!bsdf) {
+ return;
+ }
+
+ bsdf->T = make_float3(0.0f, 0.0f, 0.0f);
+ bsdf->alpha_y = bsdf->alpha_x;
+ sd->flag |= bsdf_microfacet_multi_ggx_fresnel_setup(bsdf, sd);
+ }
};
ClosureParam *closure_bsdf_microfacet_multi_ggx_fresnel_params()
{
- static ClosureParam params[] = {
- CLOSURE_FLOAT3_PARAM(MicrofacetMultiGGXFresnelClosure, params.N),
- CLOSURE_FLOAT_PARAM(MicrofacetMultiGGXFresnelClosure, params.alpha_x),
- CLOSURE_FLOAT_PARAM(MicrofacetMultiGGXFresnelClosure, params.ior),
- CLOSURE_FLOAT3_PARAM(MicrofacetMultiGGXFresnelClosure, color),
- CLOSURE_FLOAT3_PARAM(MicrofacetMultiGGXFresnelClosure, cspec0),
- CLOSURE_STRING_KEYPARAM(MicrofacetMultiGGXFresnelClosure, label, "label"),
- CLOSURE_FINISH_PARAM(MicrofacetMultiGGXFresnelClosure)
- };
- return params;
+ static ClosureParam params[] = {
+ CLOSURE_FLOAT3_PARAM(MicrofacetMultiGGXFresnelClosure, params.N),
+ CLOSURE_FLOAT_PARAM(MicrofacetMultiGGXFresnelClosure, params.alpha_x),
+ CLOSURE_FLOAT_PARAM(MicrofacetMultiGGXFresnelClosure, params.ior),
+ CLOSURE_FLOAT3_PARAM(MicrofacetMultiGGXFresnelClosure, color),
+ CLOSURE_FLOAT3_PARAM(MicrofacetMultiGGXFresnelClosure, cspec0),
+ CLOSURE_STRING_KEYPARAM(MicrofacetMultiGGXFresnelClosure, label, "label"),
+ CLOSURE_FINISH_PARAM(MicrofacetMultiGGXFresnelClosure)};
+ return params;
}
-CCLOSURE_PREPARE(closure_bsdf_microfacet_multi_ggx_fresnel_prepare, MicrofacetMultiGGXFresnelClosure);
+CCLOSURE_PREPARE(closure_bsdf_microfacet_multi_ggx_fresnel_prepare,
+ MicrofacetMultiGGXFresnelClosure);
class MicrofacetMultiGGXAnisoFresnelClosure : public MicrofacetMultiFresnelClosure {
-public:
- void setup(ShaderData *sd, int path_flag, float3 weight)
- {
- MicrofacetBsdf *bsdf = alloc(sd, path_flag, weight);
- if(!bsdf) {
- return;
- }
-
- sd->flag |= bsdf_microfacet_multi_ggx_aniso_fresnel_setup(bsdf, sd);
- }
+ public:
+ void setup(ShaderData *sd, int path_flag, float3 weight)
+ {
+ MicrofacetBsdf *bsdf = alloc(sd, path_flag, weight);
+ if (!bsdf) {
+ return;
+ }
+
+ sd->flag |= bsdf_microfacet_multi_ggx_aniso_fresnel_setup(bsdf, sd);
+ }
};
ClosureParam *closure_bsdf_microfacet_multi_ggx_aniso_fresnel_params()
{
- static ClosureParam params[] = {
- CLOSURE_FLOAT3_PARAM(MicrofacetMultiGGXFresnelClosure, params.N),
- CLOSURE_FLOAT3_PARAM(MicrofacetMultiGGXFresnelClosure, params.T),
- CLOSURE_FLOAT_PARAM(MicrofacetMultiGGXFresnelClosure, params.alpha_x),
- CLOSURE_FLOAT_PARAM(MicrofacetMultiGGXFresnelClosure, params.alpha_y),
- CLOSURE_FLOAT_PARAM(MicrofacetMultiGGXFresnelClosure, params.ior),
- CLOSURE_FLOAT3_PARAM(MicrofacetMultiGGXFresnelClosure, color),
- CLOSURE_FLOAT3_PARAM(MicrofacetMultiGGXFresnelClosure, cspec0),
- CLOSURE_STRING_KEYPARAM(MicrofacetMultiGGXFresnelClosure, label, "label"),
- CLOSURE_FINISH_PARAM(MicrofacetMultiGGXFresnelClosure)
- };
- return params;
+ static ClosureParam params[] = {
+ CLOSURE_FLOAT3_PARAM(MicrofacetMultiGGXFresnelClosure, params.N),
+ CLOSURE_FLOAT3_PARAM(MicrofacetMultiGGXFresnelClosure, params.T),
+ CLOSURE_FLOAT_PARAM(MicrofacetMultiGGXFresnelClosure, params.alpha_x),
+ CLOSURE_FLOAT_PARAM(MicrofacetMultiGGXFresnelClosure, params.alpha_y),
+ CLOSURE_FLOAT_PARAM(MicrofacetMultiGGXFresnelClosure, params.ior),
+ CLOSURE_FLOAT3_PARAM(MicrofacetMultiGGXFresnelClosure, color),
+ CLOSURE_FLOAT3_PARAM(MicrofacetMultiGGXFresnelClosure, cspec0),
+ CLOSURE_STRING_KEYPARAM(MicrofacetMultiGGXFresnelClosure, label, "label"),
+ CLOSURE_FINISH_PARAM(MicrofacetMultiGGXFresnelClosure)};
+ return params;
}
-CCLOSURE_PREPARE(closure_bsdf_microfacet_multi_ggx_aniso_fresnel_prepare, MicrofacetMultiGGXAnisoFresnelClosure);
+CCLOSURE_PREPARE(closure_bsdf_microfacet_multi_ggx_aniso_fresnel_prepare,
+ MicrofacetMultiGGXAnisoFresnelClosure);
class MicrofacetMultiGGXGlassFresnelClosure : public MicrofacetMultiFresnelClosure {
-public:
- MicrofacetMultiGGXGlassFresnelClosure() : MicrofacetMultiFresnelClosure() {}
-
- void setup(ShaderData *sd, int path_flag, float3 weight)
- {
- MicrofacetBsdf *bsdf = alloc(sd, path_flag, weight);
- if(!bsdf) {
- return;
- }
-
- bsdf->T = make_float3(0.0f, 0.0f, 0.0f);
- bsdf->alpha_y = bsdf->alpha_x;
- sd->flag |= bsdf_microfacet_multi_ggx_glass_fresnel_setup(bsdf, sd);
- }
+ public:
+ MicrofacetMultiGGXGlassFresnelClosure() : MicrofacetMultiFresnelClosure()
+ {
+ }
+
+ void setup(ShaderData *sd, int path_flag, float3 weight)
+ {
+ MicrofacetBsdf *bsdf = alloc(sd, path_flag, weight);
+ if (!bsdf) {
+ return;
+ }
+
+ bsdf->T = make_float3(0.0f, 0.0f, 0.0f);
+ bsdf->alpha_y = bsdf->alpha_x;
+ sd->flag |= bsdf_microfacet_multi_ggx_glass_fresnel_setup(bsdf, sd);
+ }
};
ClosureParam *closure_bsdf_microfacet_multi_ggx_glass_fresnel_params()
{
- static ClosureParam params[] = {
- CLOSURE_FLOAT3_PARAM(MicrofacetMultiGGXFresnelClosure, params.N),
- CLOSURE_FLOAT_PARAM(MicrofacetMultiGGXFresnelClosure, params.alpha_x),
- CLOSURE_FLOAT_PARAM(MicrofacetMultiGGXFresnelClosure, params.ior),
- CLOSURE_FLOAT3_PARAM(MicrofacetMultiGGXFresnelClosure, color),
- CLOSURE_FLOAT3_PARAM(MicrofacetMultiGGXFresnelClosure, cspec0),
- CLOSURE_STRING_KEYPARAM(MicrofacetMultiGGXFresnelClosure, label, "label"),
- CLOSURE_FINISH_PARAM(MicrofacetMultiGGXFresnelClosure)
- };
- return params;
+ static ClosureParam params[] = {
+ CLOSURE_FLOAT3_PARAM(MicrofacetMultiGGXFresnelClosure, params.N),
+ CLOSURE_FLOAT_PARAM(MicrofacetMultiGGXFresnelClosure, params.alpha_x),
+ CLOSURE_FLOAT_PARAM(MicrofacetMultiGGXFresnelClosure, params.ior),
+ CLOSURE_FLOAT3_PARAM(MicrofacetMultiGGXFresnelClosure, color),
+ CLOSURE_FLOAT3_PARAM(MicrofacetMultiGGXFresnelClosure, cspec0),
+ CLOSURE_STRING_KEYPARAM(MicrofacetMultiGGXFresnelClosure, label, "label"),
+ CLOSURE_FINISH_PARAM(MicrofacetMultiGGXFresnelClosure)};
+ return params;
}
-CCLOSURE_PREPARE(closure_bsdf_microfacet_multi_ggx_glass_fresnel_prepare, MicrofacetMultiGGXGlassFresnelClosure);
+CCLOSURE_PREPARE(closure_bsdf_microfacet_multi_ggx_glass_fresnel_prepare,
+ MicrofacetMultiGGXGlassFresnelClosure);
/* Transparent */
class TransparentClosure : public CBSDFClosure {
-public:
- ShaderClosure params;
- float3 unused;
-
- void setup(ShaderData *sd, int path_flag, float3 weight)
- {
- bsdf_transparent_setup(sd, weight, path_flag);
- }
+ public:
+ ShaderClosure params;
+ float3 unused;
+
+ void setup(ShaderData *sd, int path_flag, float3 weight)
+ {
+ bsdf_transparent_setup(sd, weight, path_flag);
+ }
};
ClosureParam *closure_bsdf_transparent_params()
{
- static ClosureParam params[] = {
- CLOSURE_STRING_KEYPARAM(TransparentClosure, label, "label"),
- CLOSURE_FINISH_PARAM(TransparentClosure)
- };
- return params;
+ static ClosureParam params[] = {CLOSURE_STRING_KEYPARAM(TransparentClosure, label, "label"),
+ CLOSURE_FINISH_PARAM(TransparentClosure)};
+ return params;
}
CCLOSURE_PREPARE(closure_bsdf_transparent_prepare, TransparentClosure)
@@ -778,52 +859,49 @@ CCLOSURE_PREPARE(closure_bsdf_transparent_prepare, TransparentClosure)
/* Volume */
class VolumeAbsorptionClosure : public CBSDFClosure {
-public:
- void setup(ShaderData *sd, int path_flag, float3 weight)
- {
- volume_extinction_setup(sd, weight);
- }
+ public:
+ void setup(ShaderData *sd, int path_flag, float3 weight)
+ {
+ volume_extinction_setup(sd, weight);
+ }
};
ClosureParam *closure_absorption_params()
{
- static ClosureParam params[] = {
- CLOSURE_STRING_KEYPARAM(VolumeAbsorptionClosure, label, "label"),
- CLOSURE_FINISH_PARAM(VolumeAbsorptionClosure)
- };
- return params;
+ static ClosureParam params[] = {CLOSURE_STRING_KEYPARAM(VolumeAbsorptionClosure, label, "label"),
+ CLOSURE_FINISH_PARAM(VolumeAbsorptionClosure)};
+ return params;
}
CCLOSURE_PREPARE(closure_absorption_prepare, VolumeAbsorptionClosure)
class VolumeHenyeyGreensteinClosure : public CBSDFClosure {
-public:
- HenyeyGreensteinVolume params;
+ public:
+ HenyeyGreensteinVolume params;
- void setup(ShaderData *sd, int path_flag, float3 weight)
- {
- volume_extinction_setup(sd, weight);
+ void setup(ShaderData *sd, int path_flag, float3 weight)
+ {
+ volume_extinction_setup(sd, weight);
- HenyeyGreensteinVolume *volume = (HenyeyGreensteinVolume*)bsdf_alloc_osl(sd, sizeof(HenyeyGreensteinVolume), weight, &params);
- if(!volume) {
- return;
- }
+ HenyeyGreensteinVolume *volume = (HenyeyGreensteinVolume *)bsdf_alloc_osl(
+ sd, sizeof(HenyeyGreensteinVolume), weight, &params);
+ if (!volume) {
+ return;
+ }
- sd->flag |= volume_henyey_greenstein_setup(volume);
- }
+ sd->flag |= volume_henyey_greenstein_setup(volume);
+ }
};
ClosureParam *closure_henyey_greenstein_params()
{
- static ClosureParam params[] = {
- CLOSURE_FLOAT_PARAM(VolumeHenyeyGreensteinClosure, params.g),
- CLOSURE_STRING_KEYPARAM(VolumeHenyeyGreensteinClosure, label, "label"),
- CLOSURE_FINISH_PARAM(VolumeHenyeyGreensteinClosure)
- };
- return params;
+ static ClosureParam params[] = {
+ CLOSURE_FLOAT_PARAM(VolumeHenyeyGreensteinClosure, params.g),
+ CLOSURE_STRING_KEYPARAM(VolumeHenyeyGreensteinClosure, label, "label"),
+ CLOSURE_FINISH_PARAM(VolumeHenyeyGreensteinClosure)};
+ return params;
}
CCLOSURE_PREPARE(closure_henyey_greenstein_prepare, VolumeHenyeyGreensteinClosure)
-
CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/osl/osl_closures.h b/intern/cycles/kernel/osl/osl_closures.h
index 2a50704b569..d3db6b71f5c 100644
--- a/intern/cycles/kernel/osl/osl_closures.h
+++ b/intern/cycles/kernel/osl/osl_closures.h
@@ -74,24 +74,34 @@ void closure_bsdf_microfacet_multi_ggx_prepare(OSL::RendererServices *, int id,
void closure_bsdf_microfacet_multi_ggx_glass_prepare(OSL::RendererServices *, int id, void *data);
void closure_bsdf_microfacet_multi_ggx_aniso_prepare(OSL::RendererServices *, int id, void *data);
void closure_bsdf_microfacet_ggx_fresnel_prepare(OSL::RendererServices *, int id, void *data);
-void closure_bsdf_microfacet_ggx_aniso_fresnel_prepare(OSL::RendererServices *, int id, void *data);
-void closure_bsdf_microfacet_multi_ggx_fresnel_prepare(OSL::RendererServices *, int id, void *data);
-void closure_bsdf_microfacet_multi_ggx_glass_fresnel_prepare(OSL::RendererServices *, int id, void *data);
-void closure_bsdf_microfacet_multi_ggx_aniso_fresnel_prepare(OSL::RendererServices *, int id, void *data);
+void closure_bsdf_microfacet_ggx_aniso_fresnel_prepare(OSL::RendererServices *,
+ int id,
+ void *data);
+void closure_bsdf_microfacet_multi_ggx_fresnel_prepare(OSL::RendererServices *,
+ int id,
+ void *data);
+void closure_bsdf_microfacet_multi_ggx_glass_fresnel_prepare(OSL::RendererServices *,
+ int id,
+ void *data);
+void closure_bsdf_microfacet_multi_ggx_aniso_fresnel_prepare(OSL::RendererServices *,
+ int id,
+ void *data);
void closure_bsdf_principled_clearcoat_prepare(OSL::RendererServices *, int id, void *data);
void closure_bsdf_principled_hair_prepare(OSL::RendererServices *, int id, void *data);
-#define CCLOSURE_PREPARE(name, classname) \
-void name(RendererServices *, int id, void *data) \
-{ \
- memset(data, 0, sizeof(classname)); \
- new (data) classname(); \
-}
+#define CCLOSURE_PREPARE(name, classname) \
+ void name(RendererServices *, int id, void *data) \
+ { \
+ memset(data, 0, sizeof(classname)); \
+ new (data) classname(); \
+ }
#define CCLOSURE_PREPARE_STATIC(name, classname) static CCLOSURE_PREPARE(name, classname)
#define CLOSURE_FLOAT3_PARAM(st, fld) \
- { TypeDesc::TypeVector, (int)reckless_offsetof(st, fld), NULL, sizeof(OSL::Vec3) }
+ { \
+ TypeDesc::TypeVector, (int)reckless_offsetof(st, fld), NULL, sizeof(OSL::Vec3) \
+ }
#define TO_VEC3(v) OSL::Vec3(v.x, v.y, v.z)
#define TO_COLOR3(v) OSL::Color3(v.x, v.y, v.z)
@@ -100,50 +110,50 @@ void name(RendererServices *, int id, void *data) \
/* Closure */
class CClosurePrimitive {
-public:
- virtual void setup(ShaderData *sd, int path_flag, float3 weight) = 0;
+ public:
+ virtual void setup(ShaderData *sd, int path_flag, float3 weight) = 0;
- OSL::ustring label;
+ OSL::ustring label;
};
/* BSDF */
class CBSDFClosure : public CClosurePrimitive {
-public:
- bool skip(const ShaderData *sd, int path_flag, int scattering);
+ public:
+ bool skip(const ShaderData *sd, int path_flag, int scattering);
};
#define BSDF_CLOSURE_CLASS_BEGIN(Upper, lower, structname, TYPE) \
\
-class Upper##Closure : public CBSDFClosure { \
-public: \
- structname params; \
- float3 unused; \
+ class Upper##Closure : public CBSDFClosure { \
+ public: \
+ structname params; \
+ float3 unused; \
\
- void setup(ShaderData *sd, int path_flag, float3 weight) \
- { \
- if(!skip(sd, path_flag, TYPE)) { \
- structname *bsdf = (structname*)bsdf_alloc_osl(sd, sizeof(structname), weight, &params); \
- sd->flag |= (bsdf) ? bsdf_##lower##_setup(bsdf) : 0; \
- } \
- } \
-}; \
+ void setup(ShaderData *sd, int path_flag, float3 weight) \
+ { \
+ if (!skip(sd, path_flag, TYPE)) { \
+ structname *bsdf = (structname *)bsdf_alloc_osl(sd, sizeof(structname), weight, &params); \
+ sd->flag |= (bsdf) ? bsdf_##lower##_setup(bsdf) : 0; \
+ } \
+ } \
+ }; \
\
-static ClosureParam *bsdf_##lower##_params() \
-{ \
- static ClosureParam params[] = {
+ static ClosureParam *bsdf_##lower##_params() \
+ { \
+ static ClosureParam params[] = {
/* parameters */
#define BSDF_CLOSURE_CLASS_END(Upper, lower) \
- CLOSURE_STRING_KEYPARAM(Upper##Closure, label, "label"), \
- CLOSURE_FINISH_PARAM(Upper##Closure) \
- }; \
- return params; \
-} \
+ CLOSURE_STRING_KEYPARAM(Upper##Closure, label, "label"), CLOSURE_FINISH_PARAM(Upper##Closure) \
+ } \
+ ; \
+ return params; \
+ } \
\
-CCLOSURE_PREPARE_STATIC(bsdf_##lower##_prepare, Upper##Closure)
+ CCLOSURE_PREPARE_STATIC(bsdf_##lower##_prepare, Upper##Closure)
CCL_NAMESPACE_END
-#endif /* __OSL_CLOSURES_H__ */
+#endif /* __OSL_CLOSURES_H__ */
diff --git a/intern/cycles/kernel/osl/osl_globals.h b/intern/cycles/kernel/osl/osl_globals.h
index 88192fbcccb..641c9967586 100644
--- a/intern/cycles/kernel/osl/osl_globals.h
+++ b/intern/cycles/kernel/osl/osl_globals.h
@@ -19,79 +19,79 @@
#ifdef WITH_OSL
-#include <OSL/oslexec.h>
+# include <OSL/oslexec.h>
-#include "util/util_map.h"
-#include "util/util_param.h"
-#include "util/util_thread.h"
-#include "util/util_vector.h"
+# include "util/util_map.h"
+# include "util/util_param.h"
+# include "util/util_thread.h"
+# include "util/util_vector.h"
-#ifndef WIN32
+# ifndef WIN32
using std::isfinite;
-#endif
+# endif
CCL_NAMESPACE_BEGIN
class OSLRenderServices;
struct OSLGlobals {
- OSLGlobals()
- {
- ss = NULL;
- ts = NULL;
- services = NULL;
- use = false;
- }
-
- bool use;
-
- /* shading system */
- OSL::ShadingSystem *ss;
- OSL::TextureSystem *ts;
- OSLRenderServices *services;
-
- /* shader states */
- vector<OSL::ShaderGroupRef> surface_state;
- vector<OSL::ShaderGroupRef> volume_state;
- vector<OSL::ShaderGroupRef> displacement_state;
- vector<OSL::ShaderGroupRef> bump_state;
- OSL::ShaderGroupRef background_state;
-
- /* attributes */
- struct Attribute {
- TypeDesc type;
- AttributeDescriptor desc;
- ParamValue value;
- };
-
- typedef unordered_map<ustring, Attribute, ustringHash> AttributeMap;
- typedef unordered_map<ustring, int, ustringHash> ObjectNameMap;
-
- vector<AttributeMap> attribute_map;
- ObjectNameMap object_name_map;
- vector<ustring> object_names;
+ OSLGlobals()
+ {
+ ss = NULL;
+ ts = NULL;
+ services = NULL;
+ use = false;
+ }
+
+ bool use;
+
+ /* shading system */
+ OSL::ShadingSystem *ss;
+ OSL::TextureSystem *ts;
+ OSLRenderServices *services;
+
+ /* shader states */
+ vector<OSL::ShaderGroupRef> surface_state;
+ vector<OSL::ShaderGroupRef> volume_state;
+ vector<OSL::ShaderGroupRef> displacement_state;
+ vector<OSL::ShaderGroupRef> bump_state;
+ OSL::ShaderGroupRef background_state;
+
+ /* attributes */
+ struct Attribute {
+ TypeDesc type;
+ AttributeDescriptor desc;
+ ParamValue value;
+ };
+
+ typedef unordered_map<ustring, Attribute, ustringHash> AttributeMap;
+ typedef unordered_map<ustring, int, ustringHash> ObjectNameMap;
+
+ vector<AttributeMap> attribute_map;
+ ObjectNameMap object_name_map;
+ vector<ustring> object_names;
};
/* trace() call result */
struct OSLTraceData {
- Ray ray;
- Intersection isect;
- ShaderData sd;
- bool setup;
- bool init;
+ Ray ray;
+ Intersection isect;
+ ShaderData sd;
+ bool setup;
+ bool init;
};
/* thread key for thread specific data lookup */
struct OSLThreadData {
- OSL::ShaderGlobals globals;
- OSL::PerThreadInfo *osl_thread_info;
- OSLTraceData tracedata;
- OSL::ShadingContext *context;
- OIIO::TextureSystem::Perthread *oiio_thread_info;
+ OSL::ShaderGlobals globals;
+ OSL::PerThreadInfo *osl_thread_info;
+ OSLTraceData tracedata;
+ OSL::ShadingContext *context;
+ OIIO::TextureSystem::Perthread *oiio_thread_info;
};
CCL_NAMESPACE_END
#endif
-#endif /* __OSL_GLOBALS_H__ */
+#endif /* __OSL_GLOBALS_H__ */
diff --git a/intern/cycles/kernel/osl/osl_services.cpp b/intern/cycles/kernel/osl/osl_services.cpp
index 6464d382634..eb9f672fd8a 100644
--- a/intern/cycles/kernel/osl/osl_services.cpp
+++ b/intern/cycles/kernel/osl/osl_services.cpp
@@ -63,16 +63,16 @@ CCL_NAMESPACE_BEGIN
/* RenderServices implementation */
-static void copy_matrix(OSL::Matrix44& m, const Transform& tfm)
+static void copy_matrix(OSL::Matrix44 &m, const Transform &tfm)
{
- ProjectionTransform t = projection_transpose(ProjectionTransform(tfm));
- memcpy((void *)&m, &t, sizeof(m));
+ ProjectionTransform t = projection_transpose(ProjectionTransform(tfm));
+ memcpy((void *)&m, &t, sizeof(m));
}
-static void copy_matrix(OSL::Matrix44& m, const ProjectionTransform& tfm)
+static void copy_matrix(OSL::Matrix44 &m, const ProjectionTransform &tfm)
{
- ProjectionTransform t = projection_transpose(tfm);
- memcpy((void *)&m, &t, sizeof(m));
+ ProjectionTransform t = projection_transpose(tfm);
+ memcpy((void *)&m, &t, sizeof(m));
}
/* static ustrings */
@@ -129,815 +129,846 @@ ustring OSLRenderServices::u_at_ao("@ao");
OSLRenderServices::OSLRenderServices()
{
- kernel_globals = NULL;
- osl_ts = NULL;
+ kernel_globals = NULL;
+ osl_ts = NULL;
#ifdef WITH_PTEX
- size_t maxmem = 16384 * 1024;
- ptex_cache = PtexCache::create(0, maxmem);
+ size_t maxmem = 16384 * 1024;
+ ptex_cache = PtexCache::create(0, maxmem);
#endif
}
OSLRenderServices::~OSLRenderServices()
{
- if(osl_ts) {
- VLOG(2) << "OSL texture system stats:\n"
- << osl_ts->getstats();
- }
+ if (osl_ts) {
+ VLOG(2) << "OSL texture system stats:\n" << osl_ts->getstats();
+ }
#ifdef WITH_PTEX
- ptex_cache->release();
+ ptex_cache->release();
#endif
}
void OSLRenderServices::thread_init(KernelGlobals *kernel_globals_, OSL::TextureSystem *osl_ts_)
{
- kernel_globals = kernel_globals_;
- osl_ts = osl_ts_;
+ kernel_globals = kernel_globals_;
+ osl_ts = osl_ts_;
}
-bool OSLRenderServices::get_matrix(OSL::ShaderGlobals *sg, OSL::Matrix44 &result, OSL::TransformationPtr xform, float time)
+bool OSLRenderServices::get_matrix(OSL::ShaderGlobals *sg,
+ OSL::Matrix44 &result,
+ OSL::TransformationPtr xform,
+ float time)
{
- /* this is only used for shader and object space, we don't really have
- * a concept of shader space, so we just use object space for both. */
- if(xform) {
- const ShaderData *sd = (const ShaderData *)xform;
- KernelGlobals *kg = sd->osl_globals;
- int object = sd->object;
-
- if(object != OBJECT_NONE) {
+ /* this is only used for shader and object space, we don't really have
+ * a concept of shader space, so we just use object space for both. */
+ if (xform) {
+ const ShaderData *sd = (const ShaderData *)xform;
+ KernelGlobals *kg = sd->osl_globals;
+ int object = sd->object;
+
+ if (object != OBJECT_NONE) {
#ifdef __OBJECT_MOTION__
- Transform tfm;
+ Transform tfm;
- if(time == sd->time)
- tfm = sd->ob_tfm;
- else
- tfm = object_fetch_transform_motion_test(kg, object, time, NULL);
+ if (time == sd->time)
+ tfm = sd->ob_tfm;
+ else
+ tfm = object_fetch_transform_motion_test(kg, object, time, NULL);
#else
- Transform tfm = object_fetch_transform(kg, object, OBJECT_TRANSFORM);
+ Transform tfm = object_fetch_transform(kg, object, OBJECT_TRANSFORM);
#endif
- copy_matrix(result, tfm);
+ copy_matrix(result, tfm);
- return true;
- }
- else if(sd->type == PRIMITIVE_LAMP) {
- copy_matrix(result, sd->ob_tfm);
+ return true;
+ }
+ else if (sd->type == PRIMITIVE_LAMP) {
+ copy_matrix(result, sd->ob_tfm);
- return true;
- }
- }
+ return true;
+ }
+ }
- return false;
+ return false;
}
-bool OSLRenderServices::get_inverse_matrix(OSL::ShaderGlobals *sg, OSL::Matrix44 &result, OSL::TransformationPtr xform, float time)
+bool OSLRenderServices::get_inverse_matrix(OSL::ShaderGlobals *sg,
+ OSL::Matrix44 &result,
+ OSL::TransformationPtr xform,
+ float time)
{
- /* this is only used for shader and object space, we don't really have
- * a concept of shader space, so we just use object space for both. */
- if(xform) {
- const ShaderData *sd = (const ShaderData *)xform;
- KernelGlobals *kg = sd->osl_globals;
- int object = sd->object;
-
- if(object != OBJECT_NONE) {
+ /* this is only used for shader and object space, we don't really have
+ * a concept of shader space, so we just use object space for both. */
+ if (xform) {
+ const ShaderData *sd = (const ShaderData *)xform;
+ KernelGlobals *kg = sd->osl_globals;
+ int object = sd->object;
+
+ if (object != OBJECT_NONE) {
#ifdef __OBJECT_MOTION__
- Transform itfm;
+ Transform itfm;
- if(time == sd->time)
- itfm = sd->ob_itfm;
- else
- object_fetch_transform_motion_test(kg, object, time, &itfm);
+ if (time == sd->time)
+ itfm = sd->ob_itfm;
+ else
+ object_fetch_transform_motion_test(kg, object, time, &itfm);
#else
- Transform itfm = object_fetch_transform(kg, object, OBJECT_INVERSE_TRANSFORM);
+ Transform itfm = object_fetch_transform(kg, object, OBJECT_INVERSE_TRANSFORM);
#endif
- copy_matrix(result, itfm);
+ copy_matrix(result, itfm);
- return true;
- }
- else if(sd->type == PRIMITIVE_LAMP) {
- copy_matrix(result, sd->ob_itfm);
+ return true;
+ }
+ else if (sd->type == PRIMITIVE_LAMP) {
+ copy_matrix(result, sd->ob_itfm);
- return true;
- }
- }
+ return true;
+ }
+ }
- return false;
+ return false;
}
-bool OSLRenderServices::get_matrix(OSL::ShaderGlobals *sg, OSL::Matrix44 &result, ustring from, float time)
+bool OSLRenderServices::get_matrix(OSL::ShaderGlobals *sg,
+ OSL::Matrix44 &result,
+ ustring from,
+ float time)
{
- KernelGlobals *kg = kernel_globals;
-
- if(from == u_ndc) {
- copy_matrix(result, kernel_data.cam.ndctoworld);
- return true;
- }
- else if(from == u_raster) {
- copy_matrix(result, kernel_data.cam.rastertoworld);
- return true;
- }
- else if(from == u_screen) {
- copy_matrix(result, kernel_data.cam.screentoworld);
- return true;
- }
- else if(from == u_camera) {
- copy_matrix(result, kernel_data.cam.cameratoworld);
- return true;
- }
- else if(from == u_world) {
- result.makeIdentity();
- return true;
- }
-
- return false;
+ KernelGlobals *kg = kernel_globals;
+
+ if (from == u_ndc) {
+ copy_matrix(result, kernel_data.cam.ndctoworld);
+ return true;
+ }
+ else if (from == u_raster) {
+ copy_matrix(result, kernel_data.cam.rastertoworld);
+ return true;
+ }
+ else if (from == u_screen) {
+ copy_matrix(result, kernel_data.cam.screentoworld);
+ return true;
+ }
+ else if (from == u_camera) {
+ copy_matrix(result, kernel_data.cam.cameratoworld);
+ return true;
+ }
+ else if (from == u_world) {
+ result.makeIdentity();
+ return true;
+ }
+
+ return false;
}
-bool OSLRenderServices::get_inverse_matrix(OSL::ShaderGlobals *sg, OSL::Matrix44 &result, ustring to, float time)
+bool OSLRenderServices::get_inverse_matrix(OSL::ShaderGlobals *sg,
+ OSL::Matrix44 &result,
+ ustring to,
+ float time)
{
- KernelGlobals *kg = kernel_globals;
-
- if(to == u_ndc) {
- copy_matrix(result, kernel_data.cam.worldtondc);
- return true;
- }
- else if(to == u_raster) {
- copy_matrix(result, kernel_data.cam.worldtoraster);
- return true;
- }
- else if(to == u_screen) {
- copy_matrix(result, kernel_data.cam.worldtoscreen);
- return true;
- }
- else if(to == u_camera) {
- copy_matrix(result, kernel_data.cam.worldtocamera);
- return true;
- }
- else if(to == u_world) {
- result.makeIdentity();
- return true;
- }
-
- return false;
+ KernelGlobals *kg = kernel_globals;
+
+ if (to == u_ndc) {
+ copy_matrix(result, kernel_data.cam.worldtondc);
+ return true;
+ }
+ else if (to == u_raster) {
+ copy_matrix(result, kernel_data.cam.worldtoraster);
+ return true;
+ }
+ else if (to == u_screen) {
+ copy_matrix(result, kernel_data.cam.worldtoscreen);
+ return true;
+ }
+ else if (to == u_camera) {
+ copy_matrix(result, kernel_data.cam.worldtocamera);
+ return true;
+ }
+ else if (to == u_world) {
+ result.makeIdentity();
+ return true;
+ }
+
+ return false;
}
-bool OSLRenderServices::get_matrix(OSL::ShaderGlobals *sg, OSL::Matrix44 &result, OSL::TransformationPtr xform)
+bool OSLRenderServices::get_matrix(OSL::ShaderGlobals *sg,
+ OSL::Matrix44 &result,
+ OSL::TransformationPtr xform)
{
- /* this is only used for shader and object space, we don't really have
- * a concept of shader space, so we just use object space for both. */
- if(xform) {
- const ShaderData *sd = (const ShaderData *)xform;
- int object = sd->object;
+ /* this is only used for shader and object space, we don't really have
+ * a concept of shader space, so we just use object space for both. */
+ if (xform) {
+ const ShaderData *sd = (const ShaderData *)xform;
+ int object = sd->object;
- if(object != OBJECT_NONE) {
+ if (object != OBJECT_NONE) {
#ifdef __OBJECT_MOTION__
- Transform tfm = sd->ob_tfm;
+ Transform tfm = sd->ob_tfm;
#else
- KernelGlobals *kg = sd->osl_globals;
- Transform tfm = object_fetch_transform(kg, object, OBJECT_TRANSFORM);
+ KernelGlobals *kg = sd->osl_globals;
+ Transform tfm = object_fetch_transform(kg, object, OBJECT_TRANSFORM);
#endif
- copy_matrix(result, tfm);
+ copy_matrix(result, tfm);
- return true;
- }
- else if(sd->type == PRIMITIVE_LAMP) {
- copy_matrix(result, sd->ob_tfm);
+ return true;
+ }
+ else if (sd->type == PRIMITIVE_LAMP) {
+ copy_matrix(result, sd->ob_tfm);
- return true;
- }
- }
+ return true;
+ }
+ }
- return false;
+ return false;
}
-bool OSLRenderServices::get_inverse_matrix(OSL::ShaderGlobals *sg, OSL::Matrix44 &result, OSL::TransformationPtr xform)
+bool OSLRenderServices::get_inverse_matrix(OSL::ShaderGlobals *sg,
+ OSL::Matrix44 &result,
+ OSL::TransformationPtr xform)
{
- /* this is only used for shader and object space, we don't really have
- * a concept of shader space, so we just use object space for both. */
- if(xform) {
- const ShaderData *sd = (const ShaderData *)xform;
- int object = sd->object;
+ /* this is only used for shader and object space, we don't really have
+ * a concept of shader space, so we just use object space for both. */
+ if (xform) {
+ const ShaderData *sd = (const ShaderData *)xform;
+ int object = sd->object;
- if(object != OBJECT_NONE) {
+ if (object != OBJECT_NONE) {
#ifdef __OBJECT_MOTION__
- Transform tfm = sd->ob_itfm;
+ Transform tfm = sd->ob_itfm;
#else
- KernelGlobals *kg = sd->osl_globals;
- Transform tfm = object_fetch_transform(kg, object, OBJECT_INVERSE_TRANSFORM);
+ KernelGlobals *kg = sd->osl_globals;
+ Transform tfm = object_fetch_transform(kg, object, OBJECT_INVERSE_TRANSFORM);
#endif
- copy_matrix(result, tfm);
+ copy_matrix(result, tfm);
- return true;
- }
- else if(sd->type == PRIMITIVE_LAMP) {
- copy_matrix(result, sd->ob_itfm);
+ return true;
+ }
+ else if (sd->type == PRIMITIVE_LAMP) {
+ copy_matrix(result, sd->ob_itfm);
- return true;
- }
- }
+ return true;
+ }
+ }
- return false;
+ return false;
}
bool OSLRenderServices::get_matrix(OSL::ShaderGlobals *sg, OSL::Matrix44 &result, ustring from)
{
- KernelGlobals *kg = kernel_globals;
-
- if(from == u_ndc) {
- copy_matrix(result, kernel_data.cam.ndctoworld);
- return true;
- }
- else if(from == u_raster) {
- copy_matrix(result, kernel_data.cam.rastertoworld);
- return true;
- }
- else if(from == u_screen) {
- copy_matrix(result, kernel_data.cam.screentoworld);
- return true;
- }
- else if(from == u_camera) {
- copy_matrix(result, kernel_data.cam.cameratoworld);
- return true;
- }
-
- return false;
+ KernelGlobals *kg = kernel_globals;
+
+ if (from == u_ndc) {
+ copy_matrix(result, kernel_data.cam.ndctoworld);
+ return true;
+ }
+ else if (from == u_raster) {
+ copy_matrix(result, kernel_data.cam.rastertoworld);
+ return true;
+ }
+ else if (from == u_screen) {
+ copy_matrix(result, kernel_data.cam.screentoworld);
+ return true;
+ }
+ else if (from == u_camera) {
+ copy_matrix(result, kernel_data.cam.cameratoworld);
+ return true;
+ }
+
+ return false;
}
-bool OSLRenderServices::get_inverse_matrix(OSL::ShaderGlobals *sg, OSL::Matrix44 &result, ustring to)
+bool OSLRenderServices::get_inverse_matrix(OSL::ShaderGlobals *sg,
+ OSL::Matrix44 &result,
+ ustring to)
{
- KernelGlobals *kg = kernel_globals;
-
- if(to == u_ndc) {
- copy_matrix(result, kernel_data.cam.worldtondc);
- return true;
- }
- else if(to == u_raster) {
- copy_matrix(result, kernel_data.cam.worldtoraster);
- return true;
- }
- else if(to == u_screen) {
- copy_matrix(result, kernel_data.cam.worldtoscreen);
- return true;
- }
- else if(to == u_camera) {
- copy_matrix(result, kernel_data.cam.worldtocamera);
- return true;
- }
-
- return false;
+ KernelGlobals *kg = kernel_globals;
+
+ if (to == u_ndc) {
+ copy_matrix(result, kernel_data.cam.worldtondc);
+ return true;
+ }
+ else if (to == u_raster) {
+ copy_matrix(result, kernel_data.cam.worldtoraster);
+ return true;
+ }
+ else if (to == u_screen) {
+ copy_matrix(result, kernel_data.cam.worldtoscreen);
+ return true;
+ }
+ else if (to == u_camera) {
+ copy_matrix(result, kernel_data.cam.worldtocamera);
+ return true;
+ }
+
+ return false;
}
-bool OSLRenderServices::get_array_attribute(OSL::ShaderGlobals *sg, bool derivatives,
- ustring object, TypeDesc type, ustring name,
- int index, void *val)
+bool OSLRenderServices::get_array_attribute(OSL::ShaderGlobals *sg,
+ bool derivatives,
+ ustring object,
+ TypeDesc type,
+ ustring name,
+ int index,
+ void *val)
{
- return false;
+ return false;
}
static bool set_attribute_float2(float2 f[3], TypeDesc type, bool derivatives, void *val)
{
- if(type == TypeDesc::TypePoint || type == TypeDesc::TypeVector ||
- type == TypeDesc::TypeNormal || type == TypeDesc::TypeColor)
- {
- float *fval = (float *)val;
-
- fval[0] = f[0].x;
- fval[1] = f[0].y;
- fval[2] = 0.0f;
-
- if(derivatives) {
- fval[3] = f[1].x;
- fval[4] = f[1].y;
- fval[5] = 0.0f;
-
- fval[6] = f[2].x;
- fval[7] = f[2].y;
- fval[8] = 0.0f;
- }
-
- return true;
- }
- else if(type == TypeDesc::TypeFloat) {
- float *fval = (float *)val;
- fval[0] = average(f[0]);
-
- if(derivatives) {
- fval[1] = average(f[1]);
- fval[2] = average(f[2]);
- }
-
- return true;
- }
-
- return false;
+ if (type == TypeDesc::TypePoint || type == TypeDesc::TypeVector ||
+ type == TypeDesc::TypeNormal || type == TypeDesc::TypeColor) {
+ float *fval = (float *)val;
+
+ fval[0] = f[0].x;
+ fval[1] = f[0].y;
+ fval[2] = 0.0f;
+
+ if (derivatives) {
+ fval[3] = f[1].x;
+ fval[4] = f[1].y;
+ fval[5] = 0.0f;
+
+ fval[6] = f[2].x;
+ fval[7] = f[2].y;
+ fval[8] = 0.0f;
+ }
+
+ return true;
+ }
+ else if (type == TypeDesc::TypeFloat) {
+ float *fval = (float *)val;
+ fval[0] = average(f[0]);
+
+ if (derivatives) {
+ fval[1] = average(f[1]);
+ fval[2] = average(f[2]);
+ }
+
+ return true;
+ }
+
+ return false;
}
static bool set_attribute_float3(float3 f[3], TypeDesc type, bool derivatives, void *val)
{
- if(type == TypeDesc::TypePoint || type == TypeDesc::TypeVector ||
- type == TypeDesc::TypeNormal || type == TypeDesc::TypeColor)
- {
- float *fval = (float *)val;
-
- fval[0] = f[0].x;
- fval[1] = f[0].y;
- fval[2] = f[0].z;
-
- if(derivatives) {
- fval[3] = f[1].x;
- fval[4] = f[1].y;
- fval[5] = f[1].z;
-
- fval[6] = f[2].x;
- fval[7] = f[2].y;
- fval[8] = f[2].z;
- }
-
- return true;
- }
- else if(type == TypeDesc::TypeFloat) {
- float *fval = (float *)val;
- fval[0] = average(f[0]);
-
- if(derivatives) {
- fval[1] = average(f[1]);
- fval[2] = average(f[2]);
- }
-
- return true;
- }
-
- return false;
+ if (type == TypeDesc::TypePoint || type == TypeDesc::TypeVector ||
+ type == TypeDesc::TypeNormal || type == TypeDesc::TypeColor) {
+ float *fval = (float *)val;
+
+ fval[0] = f[0].x;
+ fval[1] = f[0].y;
+ fval[2] = f[0].z;
+
+ if (derivatives) {
+ fval[3] = f[1].x;
+ fval[4] = f[1].y;
+ fval[5] = f[1].z;
+
+ fval[6] = f[2].x;
+ fval[7] = f[2].y;
+ fval[8] = f[2].z;
+ }
+
+ return true;
+ }
+ else if (type == TypeDesc::TypeFloat) {
+ float *fval = (float *)val;
+ fval[0] = average(f[0]);
+
+ if (derivatives) {
+ fval[1] = average(f[1]);
+ fval[2] = average(f[2]);
+ }
+
+ return true;
+ }
+
+ return false;
}
static bool set_attribute_float3(float3 f, TypeDesc type, bool derivatives, void *val)
{
- float3 fv[3];
+ float3 fv[3];
- fv[0] = f;
- fv[1] = make_float3(0.0f, 0.0f, 0.0f);
- fv[2] = make_float3(0.0f, 0.0f, 0.0f);
+ fv[0] = f;
+ fv[1] = make_float3(0.0f, 0.0f, 0.0f);
+ fv[2] = make_float3(0.0f, 0.0f, 0.0f);
- return set_attribute_float3(fv, type, derivatives, val);
+ return set_attribute_float3(fv, type, derivatives, val);
}
static bool set_attribute_float(float f[3], TypeDesc type, bool derivatives, void *val)
{
- if(type == TypeDesc::TypePoint || type == TypeDesc::TypeVector ||
- type == TypeDesc::TypeNormal || type == TypeDesc::TypeColor)
- {
- float *fval = (float *)val;
- fval[0] = f[0];
- fval[1] = f[1];
- fval[2] = f[2];
-
- if(derivatives) {
- fval[3] = f[1];
- fval[4] = f[1];
- fval[5] = f[1];
-
- fval[6] = f[2];
- fval[7] = f[2];
- fval[8] = f[2];
- }
-
- return true;
- }
- else if(type == TypeDesc::TypeFloat) {
- float *fval = (float *)val;
- fval[0] = f[0];
-
- if(derivatives) {
- fval[1] = f[1];
- fval[2] = f[2];
- }
-
- return true;
- }
-
- return false;
+ if (type == TypeDesc::TypePoint || type == TypeDesc::TypeVector ||
+ type == TypeDesc::TypeNormal || type == TypeDesc::TypeColor) {
+ float *fval = (float *)val;
+ fval[0] = f[0];
+ fval[1] = f[1];
+ fval[2] = f[2];
+
+ if (derivatives) {
+ fval[3] = f[1];
+ fval[4] = f[1];
+ fval[5] = f[1];
+
+ fval[6] = f[2];
+ fval[7] = f[2];
+ fval[8] = f[2];
+ }
+
+ return true;
+ }
+ else if (type == TypeDesc::TypeFloat) {
+ float *fval = (float *)val;
+ fval[0] = f[0];
+
+ if (derivatives) {
+ fval[1] = f[1];
+ fval[2] = f[2];
+ }
+
+ return true;
+ }
+
+ return false;
}
static bool set_attribute_float(float f, TypeDesc type, bool derivatives, void *val)
{
- float fv[3];
+ float fv[3];
- fv[0] = f;
- fv[1] = 0.0f;
- fv[2] = 0.0f;
+ fv[0] = f;
+ fv[1] = 0.0f;
+ fv[2] = 0.0f;
- return set_attribute_float(fv, type, derivatives, val);
+ return set_attribute_float(fv, type, derivatives, val);
}
static bool set_attribute_int(int i, TypeDesc type, bool derivatives, void *val)
{
- if(type.basetype == TypeDesc::INT && type.aggregate == TypeDesc::SCALAR && type.arraylen == 0) {
- int *ival = (int *)val;
- ival[0] = i;
+ if (type.basetype == TypeDesc::INT && type.aggregate == TypeDesc::SCALAR && type.arraylen == 0) {
+ int *ival = (int *)val;
+ ival[0] = i;
- if(derivatives) {
- ival[1] = 0;
- ival[2] = 0;
- }
+ if (derivatives) {
+ ival[1] = 0;
+ ival[2] = 0;
+ }
- return true;
- }
+ return true;
+ }
- return false;
+ return false;
}
static bool set_attribute_string(ustring str, TypeDesc type, bool derivatives, void *val)
{
- if(type.basetype == TypeDesc::STRING && type.aggregate == TypeDesc::SCALAR && type.arraylen == 0) {
- ustring *sval = (ustring *)val;
- sval[0] = str;
+ if (type.basetype == TypeDesc::STRING && type.aggregate == TypeDesc::SCALAR &&
+ type.arraylen == 0) {
+ ustring *sval = (ustring *)val;
+ sval[0] = str;
- if(derivatives) {
- sval[1] = OSLRenderServices::u_empty;
- sval[2] = OSLRenderServices::u_empty;
- }
+ if (derivatives) {
+ sval[1] = OSLRenderServices::u_empty;
+ sval[2] = OSLRenderServices::u_empty;
+ }
- return true;
- }
+ return true;
+ }
- return false;
+ return false;
}
static bool set_attribute_float3_3(float3 P[3], TypeDesc type, bool derivatives, void *val)
{
- if(type.vecsemantics == TypeDesc::POINT && type.arraylen >= 3) {
- float *fval = (float *)val;
+ if (type.vecsemantics == TypeDesc::POINT && type.arraylen >= 3) {
+ float *fval = (float *)val;
- fval[0] = P[0].x;
- fval[1] = P[0].y;
- fval[2] = P[0].z;
+ fval[0] = P[0].x;
+ fval[1] = P[0].y;
+ fval[2] = P[0].z;
- fval[3] = P[1].x;
- fval[4] = P[1].y;
- fval[5] = P[1].z;
+ fval[3] = P[1].x;
+ fval[4] = P[1].y;
+ fval[5] = P[1].z;
- fval[6] = P[2].x;
- fval[7] = P[2].y;
- fval[8] = P[2].z;
+ fval[6] = P[2].x;
+ fval[7] = P[2].y;
+ fval[8] = P[2].z;
- if(type.arraylen > 3)
- memset(fval + 3*3, 0, sizeof(float)*3*(type.arraylen - 3));
- if(derivatives)
- memset(fval + type.arraylen*3, 0, sizeof(float)*2*3*type.arraylen);
+ if (type.arraylen > 3)
+ memset(fval + 3 * 3, 0, sizeof(float) * 3 * (type.arraylen - 3));
+ if (derivatives)
+ memset(fval + type.arraylen * 3, 0, sizeof(float) * 2 * 3 * type.arraylen);
- return true;
- }
+ return true;
+ }
- return false;
+ return false;
}
-static bool set_attribute_matrix(const Transform& tfm, TypeDesc type, void *val)
+static bool set_attribute_matrix(const Transform &tfm, TypeDesc type, void *val)
{
- if(type == TypeDesc::TypeMatrix) {
- copy_matrix(*(OSL::Matrix44*)val, tfm);
- return true;
- }
+ if (type == TypeDesc::TypeMatrix) {
+ copy_matrix(*(OSL::Matrix44 *)val, tfm);
+ return true;
+ }
- return false;
+ return false;
}
-static bool get_primitive_attribute(KernelGlobals *kg, const ShaderData *sd, const OSLGlobals::Attribute& attr,
- const TypeDesc& type, bool derivatives, void *val)
+static bool get_primitive_attribute(KernelGlobals *kg,
+ const ShaderData *sd,
+ const OSLGlobals::Attribute &attr,
+ const TypeDesc &type,
+ bool derivatives,
+ void *val)
{
- if(attr.type == TypeDesc::TypePoint || attr.type == TypeDesc::TypeVector ||
- attr.type == TypeDesc::TypeNormal || attr.type == TypeDesc::TypeColor)
- {
- float3 fval[3];
- fval[0] = primitive_attribute_float3(kg, sd, attr.desc,
- (derivatives) ? &fval[1] : NULL, (derivatives) ? &fval[2] : NULL);
- return set_attribute_float3(fval, type, derivatives, val);
- }
- else if(attr.type == TypeFloat2) {
- float2 fval[2];
- fval[0] = primitive_attribute_float2(kg, sd, attr.desc,
- (derivatives) ? &fval[1] : NULL, (derivatives) ? &fval[2] : NULL);
- return set_attribute_float2(fval, type, derivatives, val);
- }
- else if(attr.type == TypeDesc::TypeFloat) {
- float fval[3];
- fval[0] = primitive_attribute_float(kg, sd, attr.desc,
- (derivatives) ? &fval[1] : NULL, (derivatives) ? &fval[2] : NULL);
- return set_attribute_float(fval, type, derivatives, val);
- }
- else {
- return false;
- }
+ if (attr.type == TypeDesc::TypePoint || attr.type == TypeDesc::TypeVector ||
+ attr.type == TypeDesc::TypeNormal || attr.type == TypeDesc::TypeColor) {
+ float3 fval[3];
+ fval[0] = primitive_attribute_float3(
+ kg, sd, attr.desc, (derivatives) ? &fval[1] : NULL, (derivatives) ? &fval[2] : NULL);
+ return set_attribute_float3(fval, type, derivatives, val);
+ }
+ else if (attr.type == TypeFloat2) {
+ float2 fval[2];
+ fval[0] = primitive_attribute_float2(
+ kg, sd, attr.desc, (derivatives) ? &fval[1] : NULL, (derivatives) ? &fval[2] : NULL);
+ return set_attribute_float2(fval, type, derivatives, val);
+ }
+ else if (attr.type == TypeDesc::TypeFloat) {
+ float fval[3];
+ fval[0] = primitive_attribute_float(
+ kg, sd, attr.desc, (derivatives) ? &fval[1] : NULL, (derivatives) ? &fval[2] : NULL);
+ return set_attribute_float(fval, type, derivatives, val);
+ }
+ else {
+ return false;
+ }
}
-static bool get_mesh_attribute(KernelGlobals *kg, const ShaderData *sd, const OSLGlobals::Attribute& attr,
- const TypeDesc& type, bool derivatives, void *val)
+static bool get_mesh_attribute(KernelGlobals *kg,
+ const ShaderData *sd,
+ const OSLGlobals::Attribute &attr,
+ const TypeDesc &type,
+ bool derivatives,
+ void *val)
{
- if(attr.type == TypeDesc::TypeMatrix) {
- Transform tfm = primitive_attribute_matrix(kg, sd, attr.desc);
- return set_attribute_matrix(tfm, type, val);
- }
- else {
- return false;
- }
+ if (attr.type == TypeDesc::TypeMatrix) {
+ Transform tfm = primitive_attribute_matrix(kg, sd, attr.desc);
+ return set_attribute_matrix(tfm, type, val);
+ }
+ else {
+ return false;
+ }
}
-static void get_object_attribute(const OSLGlobals::Attribute& attr, bool derivatives, void *val)
+static void get_object_attribute(const OSLGlobals::Attribute &attr, bool derivatives, void *val)
{
- size_t datasize = attr.value.datasize();
+ size_t datasize = attr.value.datasize();
- memcpy(val, attr.value.data(), datasize);
- if(derivatives)
- memset((char *)val + datasize, 0, datasize * 2);
+ memcpy(val, attr.value.data(), datasize);
+ if (derivatives)
+ memset((char *)val + datasize, 0, datasize * 2);
}
-bool OSLRenderServices::get_object_standard_attribute(KernelGlobals *kg, ShaderData *sd, ustring name,
- TypeDesc type, bool derivatives, void *val)
+bool OSLRenderServices::get_object_standard_attribute(
+ KernelGlobals *kg, ShaderData *sd, ustring name, TypeDesc type, bool derivatives, void *val)
{
- /* todo: turn this into hash table? */
-
- /* Object Attributes */
- if(name == u_object_location) {
- float3 f = object_location(kg, sd);
- return set_attribute_float3(f, type, derivatives, val);
- }
- else if(name == u_object_index) {
- float f = object_pass_id(kg, sd->object);
- return set_attribute_float(f, type, derivatives, val);
- }
- else if(name == u_geom_dupli_generated) {
- float3 f = object_dupli_generated(kg, sd->object);
- return set_attribute_float3(f, type, derivatives, val);
- }
- else if(name == u_geom_dupli_uv) {
- float3 f = object_dupli_uv(kg, sd->object);
- return set_attribute_float3(f, type, derivatives, val);
- }
- else if(name == u_material_index) {
- float f = shader_pass_id(kg, sd);
- return set_attribute_float(f, type, derivatives, val);
- }
- else if(name == u_object_random) {
- float f = object_random_number(kg, sd->object);
- return set_attribute_float(f, type, derivatives, val);
- }
-
- /* Particle Attributes */
- else if(name == u_particle_index) {
- int particle_id = object_particle_id(kg, sd->object);
- float f = particle_index(kg, particle_id);
- return set_attribute_float(f, type, derivatives, val);
- }
- else if(name == u_particle_random) {
- int particle_id = object_particle_id(kg, sd->object);
- float f = hash_int_01(particle_index(kg, particle_id));
- return set_attribute_float(f, type, derivatives, val);
- }
-
- else if(name == u_particle_age) {
- int particle_id = object_particle_id(kg, sd->object);
- float f = particle_age(kg, particle_id);
- return set_attribute_float(f, type, derivatives, val);
- }
- else if(name == u_particle_lifetime) {
- int particle_id = object_particle_id(kg, sd->object);
- float f = particle_lifetime(kg, particle_id);
- return set_attribute_float(f, type, derivatives, val);
- }
- else if(name == u_particle_location) {
- int particle_id = object_particle_id(kg, sd->object);
- float3 f = particle_location(kg, particle_id);
- return set_attribute_float3(f, type, derivatives, val);
- }
-#if 0 /* unsupported */
- else if(name == u_particle_rotation) {
- int particle_id = object_particle_id(kg, sd->object);
- float4 f = particle_rotation(kg, particle_id);
- return set_attribute_float4(f, type, derivatives, val);
- }
+ /* todo: turn this into hash table? */
+
+ /* Object Attributes */
+ if (name == u_object_location) {
+ float3 f = object_location(kg, sd);
+ return set_attribute_float3(f, type, derivatives, val);
+ }
+ else if (name == u_object_index) {
+ float f = object_pass_id(kg, sd->object);
+ return set_attribute_float(f, type, derivatives, val);
+ }
+ else if (name == u_geom_dupli_generated) {
+ float3 f = object_dupli_generated(kg, sd->object);
+ return set_attribute_float3(f, type, derivatives, val);
+ }
+ else if (name == u_geom_dupli_uv) {
+ float3 f = object_dupli_uv(kg, sd->object);
+ return set_attribute_float3(f, type, derivatives, val);
+ }
+ else if (name == u_material_index) {
+ float f = shader_pass_id(kg, sd);
+ return set_attribute_float(f, type, derivatives, val);
+ }
+ else if (name == u_object_random) {
+ float f = object_random_number(kg, sd->object);
+ return set_attribute_float(f, type, derivatives, val);
+ }
+
+ /* Particle Attributes */
+ else if (name == u_particle_index) {
+ int particle_id = object_particle_id(kg, sd->object);
+ float f = particle_index(kg, particle_id);
+ return set_attribute_float(f, type, derivatives, val);
+ }
+ else if (name == u_particle_random) {
+ int particle_id = object_particle_id(kg, sd->object);
+ float f = hash_int_01(particle_index(kg, particle_id));
+ return set_attribute_float(f, type, derivatives, val);
+ }
+
+ else if (name == u_particle_age) {
+ int particle_id = object_particle_id(kg, sd->object);
+ float f = particle_age(kg, particle_id);
+ return set_attribute_float(f, type, derivatives, val);
+ }
+ else if (name == u_particle_lifetime) {
+ int particle_id = object_particle_id(kg, sd->object);
+ float f = particle_lifetime(kg, particle_id);
+ return set_attribute_float(f, type, derivatives, val);
+ }
+ else if (name == u_particle_location) {
+ int particle_id = object_particle_id(kg, sd->object);
+ float3 f = particle_location(kg, particle_id);
+ return set_attribute_float3(f, type, derivatives, val);
+ }
+#if 0 /* unsupported */
+ else if(name == u_particle_rotation) {
+ int particle_id = object_particle_id(kg, sd->object);
+ float4 f = particle_rotation(kg, particle_id);
+ return set_attribute_float4(f, type, derivatives, val);
+ }
#endif
- else if(name == u_particle_size) {
- int particle_id = object_particle_id(kg, sd->object);
- float f = particle_size(kg, particle_id);
- return set_attribute_float(f, type, derivatives, val);
- }
- else if(name == u_particle_velocity) {
- int particle_id = object_particle_id(kg, sd->object);
- float3 f = particle_velocity(kg, particle_id);
- return set_attribute_float3(f, type, derivatives, val);
- }
- else if(name == u_particle_angular_velocity) {
- int particle_id = object_particle_id(kg, sd->object);
- float3 f = particle_angular_velocity(kg, particle_id);
- return set_attribute_float3(f, type, derivatives, val);
- }
-
- /* Geometry Attributes */
- else if(name == u_geom_numpolyvertices) {
- return set_attribute_int(3, type, derivatives, val);
- }
- else if((name == u_geom_trianglevertices || name == u_geom_polyvertices)
- && sd->type & PRIMITIVE_ALL_TRIANGLE)
- {
- float3 P[3];
-
- if(sd->type & PRIMITIVE_TRIANGLE)
- triangle_vertices(kg, sd->prim, P);
- else
- motion_triangle_vertices(kg, sd->object, sd->prim, sd->time, P);
-
- if(!(sd->object_flag & SD_OBJECT_TRANSFORM_APPLIED)) {
- object_position_transform(kg, sd, &P[0]);
- object_position_transform(kg, sd, &P[1]);
- object_position_transform(kg, sd, &P[2]);
- }
-
- return set_attribute_float3_3(P, type, derivatives, val);
- }
- else if(name == u_geom_name) {
- ustring object_name = kg->osl->object_names[sd->object];
- return set_attribute_string(object_name, type, derivatives, val);
- }
- else if(name == u_is_smooth) {
- float f = ((sd->shader & SHADER_SMOOTH_NORMAL) != 0);
- return set_attribute_float(f, type, derivatives, val);
- }
- /* Hair Attributes */
- else if(name == u_is_curve) {
- float f = (sd->type & PRIMITIVE_ALL_CURVE) != 0;
- return set_attribute_float(f, type, derivatives, val);
- }
- else if(name == u_curve_thickness) {
- float f = curve_thickness(kg, sd);
- return set_attribute_float(f, type, derivatives, val);
- }
- else if(name == u_curve_tangent_normal) {
- float3 f = curve_tangent_normal(kg, sd);
- return set_attribute_float3(f, type, derivatives, val);
- }
- else
- return false;
+ else if (name == u_particle_size) {
+ int particle_id = object_particle_id(kg, sd->object);
+ float f = particle_size(kg, particle_id);
+ return set_attribute_float(f, type, derivatives, val);
+ }
+ else if (name == u_particle_velocity) {
+ int particle_id = object_particle_id(kg, sd->object);
+ float3 f = particle_velocity(kg, particle_id);
+ return set_attribute_float3(f, type, derivatives, val);
+ }
+ else if (name == u_particle_angular_velocity) {
+ int particle_id = object_particle_id(kg, sd->object);
+ float3 f = particle_angular_velocity(kg, particle_id);
+ return set_attribute_float3(f, type, derivatives, val);
+ }
+
+ /* Geometry Attributes */
+ else if (name == u_geom_numpolyvertices) {
+ return set_attribute_int(3, type, derivatives, val);
+ }
+ else if ((name == u_geom_trianglevertices || name == u_geom_polyvertices) &&
+ sd->type & PRIMITIVE_ALL_TRIANGLE) {
+ float3 P[3];
+
+ if (sd->type & PRIMITIVE_TRIANGLE)
+ triangle_vertices(kg, sd->prim, P);
+ else
+ motion_triangle_vertices(kg, sd->object, sd->prim, sd->time, P);
+
+ if (!(sd->object_flag & SD_OBJECT_TRANSFORM_APPLIED)) {
+ object_position_transform(kg, sd, &P[0]);
+ object_position_transform(kg, sd, &P[1]);
+ object_position_transform(kg, sd, &P[2]);
+ }
+
+ return set_attribute_float3_3(P, type, derivatives, val);
+ }
+ else if (name == u_geom_name) {
+ ustring object_name = kg->osl->object_names[sd->object];
+ return set_attribute_string(object_name, type, derivatives, val);
+ }
+ else if (name == u_is_smooth) {
+ float f = ((sd->shader & SHADER_SMOOTH_NORMAL) != 0);
+ return set_attribute_float(f, type, derivatives, val);
+ }
+ /* Hair Attributes */
+ else if (name == u_is_curve) {
+ float f = (sd->type & PRIMITIVE_ALL_CURVE) != 0;
+ return set_attribute_float(f, type, derivatives, val);
+ }
+ else if (name == u_curve_thickness) {
+ float f = curve_thickness(kg, sd);
+ return set_attribute_float(f, type, derivatives, val);
+ }
+ else if (name == u_curve_tangent_normal) {
+ float3 f = curve_tangent_normal(kg, sd);
+ return set_attribute_float3(f, type, derivatives, val);
+ }
+ else
+ return false;
}
-bool OSLRenderServices::get_background_attribute(KernelGlobals *kg, ShaderData *sd, ustring name,
- TypeDesc type, bool derivatives, void *val)
+bool OSLRenderServices::get_background_attribute(
+ KernelGlobals *kg, ShaderData *sd, ustring name, TypeDesc type, bool derivatives, void *val)
{
- if(name == u_path_ray_length) {
- /* Ray Length */
- float f = sd->ray_length;
- return set_attribute_float(f, type, derivatives, val);
- }
- else if(name == u_path_ray_depth) {
- /* Ray Depth */
- PathState *state = sd->osl_path_state;
- int f = state->bounce;
- return set_attribute_int(f, type, derivatives, val);
- }
- else if(name == u_path_diffuse_depth) {
- /* Diffuse Ray Depth */
- PathState *state = sd->osl_path_state;
- int f = state->diffuse_bounce;
- return set_attribute_int(f, type, derivatives, val);
- }
- else if(name == u_path_glossy_depth) {
- /* Glossy Ray Depth */
- PathState *state = sd->osl_path_state;
- int f = state->glossy_bounce;
- return set_attribute_int(f, type, derivatives, val);
- }
- else if(name == u_path_transmission_depth) {
- /* Transmission Ray Depth */
- PathState *state = sd->osl_path_state;
- int f = state->transmission_bounce;
- return set_attribute_int(f, type, derivatives, val);
- }
- else if(name == u_path_transparent_depth) {
- /* Transparent Ray Depth */
- PathState *state = sd->osl_path_state;
- int f = state->transparent_bounce;
- return set_attribute_int(f, type, derivatives, val);
- }
- else if(name == u_path_transmission_depth) {
- /* Transmission Ray Depth */
- PathState *state = sd->osl_path_state;
- int f = state->transmission_bounce;
- return set_attribute_int(f, type, derivatives, val);
- }
- else if(name == u_ndc) {
- /* NDC coordinates with special exception for otho */
- OSLThreadData *tdata = kg->osl_tdata;
- OSL::ShaderGlobals *globals = &tdata->globals;
- float3 ndc[3];
-
- if((globals->raytype & PATH_RAY_CAMERA) && sd->object == OBJECT_NONE && kernel_data.cam.type == CAMERA_ORTHOGRAPHIC) {
- ndc[0] = camera_world_to_ndc(kg, sd, sd->ray_P);
-
- if(derivatives) {
- ndc[1] = camera_world_to_ndc(kg, sd, sd->ray_P + sd->ray_dP.dx) - ndc[0];
- ndc[2] = camera_world_to_ndc(kg, sd, sd->ray_P + sd->ray_dP.dy) - ndc[0];
- }
- }
- else {
- ndc[0] = camera_world_to_ndc(kg, sd, sd->P);
-
- if(derivatives) {
- ndc[1] = camera_world_to_ndc(kg, sd, sd->P + sd->dP.dx) - ndc[0];
- ndc[2] = camera_world_to_ndc(kg, sd, sd->P + sd->dP.dy) - ndc[0];
- }
- }
-
- return set_attribute_float3(ndc, type, derivatives, val);
- }
- else
- return false;
+ if (name == u_path_ray_length) {
+ /* Ray Length */
+ float f = sd->ray_length;
+ return set_attribute_float(f, type, derivatives, val);
+ }
+ else if (name == u_path_ray_depth) {
+ /* Ray Depth */
+ PathState *state = sd->osl_path_state;
+ int f = state->bounce;
+ return set_attribute_int(f, type, derivatives, val);
+ }
+ else if (name == u_path_diffuse_depth) {
+ /* Diffuse Ray Depth */
+ PathState *state = sd->osl_path_state;
+ int f = state->diffuse_bounce;
+ return set_attribute_int(f, type, derivatives, val);
+ }
+ else if (name == u_path_glossy_depth) {
+ /* Glossy Ray Depth */
+ PathState *state = sd->osl_path_state;
+ int f = state->glossy_bounce;
+ return set_attribute_int(f, type, derivatives, val);
+ }
+ else if (name == u_path_transmission_depth) {
+ /* Transmission Ray Depth */
+ PathState *state = sd->osl_path_state;
+ int f = state->transmission_bounce;
+ return set_attribute_int(f, type, derivatives, val);
+ }
+ else if (name == u_path_transparent_depth) {
+ /* Transparent Ray Depth */
+ PathState *state = sd->osl_path_state;
+ int f = state->transparent_bounce;
+ return set_attribute_int(f, type, derivatives, val);
+ }
+ else if (name == u_path_transmission_depth) {
+ /* Transmission Ray Depth */
+ PathState *state = sd->osl_path_state;
+ int f = state->transmission_bounce;
+ return set_attribute_int(f, type, derivatives, val);
+ }
+ else if (name == u_ndc) {
+ /* NDC coordinates with special exception for otho */
+ OSLThreadData *tdata = kg->osl_tdata;
+ OSL::ShaderGlobals *globals = &tdata->globals;
+ float3 ndc[3];
+
+ if ((globals->raytype & PATH_RAY_CAMERA) && sd->object == OBJECT_NONE &&
+ kernel_data.cam.type == CAMERA_ORTHOGRAPHIC) {
+ ndc[0] = camera_world_to_ndc(kg, sd, sd->ray_P);
+
+ if (derivatives) {
+ ndc[1] = camera_world_to_ndc(kg, sd, sd->ray_P + sd->ray_dP.dx) - ndc[0];
+ ndc[2] = camera_world_to_ndc(kg, sd, sd->ray_P + sd->ray_dP.dy) - ndc[0];
+ }
+ }
+ else {
+ ndc[0] = camera_world_to_ndc(kg, sd, sd->P);
+
+ if (derivatives) {
+ ndc[1] = camera_world_to_ndc(kg, sd, sd->P + sd->dP.dx) - ndc[0];
+ ndc[2] = camera_world_to_ndc(kg, sd, sd->P + sd->dP.dy) - ndc[0];
+ }
+ }
+
+ return set_attribute_float3(ndc, type, derivatives, val);
+ }
+ else
+ return false;
}
-bool OSLRenderServices::get_attribute(OSL::ShaderGlobals *sg, bool derivatives, ustring object_name,
- TypeDesc type, ustring name, void *val)
+bool OSLRenderServices::get_attribute(OSL::ShaderGlobals *sg,
+ bool derivatives,
+ ustring object_name,
+ TypeDesc type,
+ ustring name,
+ void *val)
{
- if(sg == NULL || sg->renderstate == NULL)
- return false;
+ if (sg == NULL || sg->renderstate == NULL)
+ return false;
- ShaderData *sd = (ShaderData *)(sg->renderstate);
- return get_attribute(sd, derivatives, object_name, type, name, val);
+ ShaderData *sd = (ShaderData *)(sg->renderstate);
+ return get_attribute(sd, derivatives, object_name, type, name, val);
}
-bool OSLRenderServices::get_attribute(ShaderData *sd, bool derivatives, ustring object_name,
- TypeDesc type, ustring name, void *val)
+bool OSLRenderServices::get_attribute(
+ ShaderData *sd, bool derivatives, ustring object_name, TypeDesc type, ustring name, void *val)
{
- KernelGlobals *kg = sd->osl_globals;
- int prim_type = 0;
- int object;
-
- /* lookup of attribute on another object */
- if(object_name != u_empty) {
- OSLGlobals::ObjectNameMap::iterator it = kg->osl->object_name_map.find(object_name);
-
- if(it == kg->osl->object_name_map.end())
- return false;
-
- object = it->second;
- }
- else {
- object = sd->object;
- prim_type = attribute_primitive_type(kg, sd);
-
- if(object == OBJECT_NONE)
- return get_background_attribute(kg, sd, name, type, derivatives, val);
- }
-
- /* find attribute on object */
- object = object*ATTR_PRIM_TYPES + prim_type;
- OSLGlobals::AttributeMap& attribute_map = kg->osl->attribute_map[object];
- OSLGlobals::AttributeMap::iterator it = attribute_map.find(name);
-
- if(it != attribute_map.end()) {
- const OSLGlobals::Attribute& attr = it->second;
-
- if(attr.desc.element != ATTR_ELEMENT_OBJECT) {
- /* triangle and vertex attributes */
- if(get_primitive_attribute(kg, sd, attr, type, derivatives, val))
- return true;
- else
- return get_mesh_attribute(kg, sd, attr, type, derivatives, val);
- }
- else {
- /* object attribute */
- get_object_attribute(attr, derivatives, val);
- return true;
- }
- }
- else {
- /* not found in attribute, check standard object info */
- bool is_std_object_attribute = get_object_standard_attribute(kg, sd, name, type, derivatives, val);
-
- if(is_std_object_attribute)
- return true;
-
- return get_background_attribute(kg, sd, name, type, derivatives, val);
- }
-
- return false;
+ KernelGlobals *kg = sd->osl_globals;
+ int prim_type = 0;
+ int object;
+
+ /* lookup of attribute on another object */
+ if (object_name != u_empty) {
+ OSLGlobals::ObjectNameMap::iterator it = kg->osl->object_name_map.find(object_name);
+
+ if (it == kg->osl->object_name_map.end())
+ return false;
+
+ object = it->second;
+ }
+ else {
+ object = sd->object;
+ prim_type = attribute_primitive_type(kg, sd);
+
+ if (object == OBJECT_NONE)
+ return get_background_attribute(kg, sd, name, type, derivatives, val);
+ }
+
+ /* find attribute on object */
+ object = object * ATTR_PRIM_TYPES + prim_type;
+ OSLGlobals::AttributeMap &attribute_map = kg->osl->attribute_map[object];
+ OSLGlobals::AttributeMap::iterator it = attribute_map.find(name);
+
+ if (it != attribute_map.end()) {
+ const OSLGlobals::Attribute &attr = it->second;
+
+ if (attr.desc.element != ATTR_ELEMENT_OBJECT) {
+ /* triangle and vertex attributes */
+ if (get_primitive_attribute(kg, sd, attr, type, derivatives, val))
+ return true;
+ else
+ return get_mesh_attribute(kg, sd, attr, type, derivatives, val);
+ }
+ else {
+ /* object attribute */
+ get_object_attribute(attr, derivatives, val);
+ return true;
+ }
+ }
+ else {
+ /* not found in attribute, check standard object info */
+ bool is_std_object_attribute = get_object_standard_attribute(
+ kg, sd, name, type, derivatives, val);
+
+ if (is_std_object_attribute)
+ return true;
+
+ return get_background_attribute(kg, sd, name, type, derivatives, val);
+ }
+
+ return false;
}
-bool OSLRenderServices::get_userdata(bool derivatives, ustring name, TypeDesc type,
- OSL::ShaderGlobals *sg, void *val)
+bool OSLRenderServices::get_userdata(
+ bool derivatives, ustring name, TypeDesc type, OSL::ShaderGlobals *sg, void *val)
{
- return false; /* disabled by lockgeom */
+ return false; /* disabled by lockgeom */
}
TextureSystem::TextureHandle *OSLRenderServices::get_texture_handle(ustring filename)
{
- if(filename.length() && filename[0] == '@') {
- /* Dummy, we don't use texture handles for builtin textures but need
- * to tell the OSL runtime optimizer that this is a valid texture. */
- return NULL;
- }
- else {
- return texturesys()->get_texture_handle(filename);
- }
+ if (filename.length() && filename[0] == '@') {
+ /* Dummy, we don't use texture handles for builtin textures but need
+ * to tell the OSL runtime optimizer that this is a valid texture. */
+ return NULL;
+ }
+ else {
+ return texturesys()->get_texture_handle(filename);
+ }
}
bool OSLRenderServices::good(TextureSystem::TextureHandle *texture_handle)
{
- return texturesys()->good(texture_handle);
+ return texturesys()->good(texture_handle);
}
bool OSLRenderServices::texture(ustring filename,
@@ -945,157 +976,169 @@ bool OSLRenderServices::texture(ustring filename,
TexturePerthread *texture_thread_info,
TextureOpt &options,
OSL::ShaderGlobals *sg,
- float s, float t,
- float dsdx, float dtdx, float dsdy, float dtdy,
+ float s,
+ float t,
+ float dsdx,
+ float dtdx,
+ float dsdy,
+ float dtdy,
int nchannels,
float *result,
float *dresultds,
float *dresultdt,
ustring *errormessage)
{
- OSL::TextureSystem *ts = osl_ts;
- ShaderData *sd = (ShaderData *)(sg->renderstate);
- KernelGlobals *kg = sd->osl_globals;
+ OSL::TextureSystem *ts = osl_ts;
+ ShaderData *sd = (ShaderData *)(sg->renderstate);
+ KernelGlobals *kg = sd->osl_globals;
- if(texture_thread_info == NULL) {
- OSLThreadData *tdata = kg->osl_tdata;
- texture_thread_info = tdata->oiio_thread_info;
- }
+ if (texture_thread_info == NULL) {
+ OSLThreadData *tdata = kg->osl_tdata;
+ texture_thread_info = tdata->oiio_thread_info;
+ }
#ifdef WITH_PTEX
- /* todo: this is just a quick hack, only works with particular files and options */
- if(string_endswith(filename.string(), ".ptx")) {
- float2 uv;
- int faceid;
+ /* todo: this is just a quick hack, only works with particular files and options */
+ if (string_endswith(filename.string(), ".ptx")) {
+ float2 uv;
+ int faceid;
- if(!primitive_ptex(kg, sd, &uv, &faceid))
- return false;
+ if (!primitive_ptex(kg, sd, &uv, &faceid))
+ return false;
- float u = uv.x;
- float v = uv.y;
- float dudx = 0.0f;
- float dvdx = 0.0f;
- float dudy = 0.0f;
- float dvdy = 0.0f;
+ float u = uv.x;
+ float v = uv.y;
+ float dudx = 0.0f;
+ float dvdx = 0.0f;
+ float dudy = 0.0f;
+ float dvdy = 0.0f;
- Ptex::String error;
- PtexPtr<PtexTexture> r(ptex_cache->get(filename.c_str(), error));
+ Ptex::String error;
+ PtexPtr<PtexTexture> r(ptex_cache->get(filename.c_str(), error));
- if(!r) {
- //std::cerr << error.c_str() << std::endl;
- return false;
- }
+ if (!r) {
+ //std::cerr << error.c_str() << std::endl;
+ return false;
+ }
- bool mipmaplerp = false;
- float sharpness = 1.0f;
- PtexFilter::Options opts(PtexFilter::f_bicubic, mipmaplerp, sharpness);
- PtexPtr<PtexFilter> f(PtexFilter::getFilter(r, opts));
+ bool mipmaplerp = false;
+ float sharpness = 1.0f;
+ PtexFilter::Options opts(PtexFilter::f_bicubic, mipmaplerp, sharpness);
+ PtexPtr<PtexFilter> f(PtexFilter::getFilter(r, opts));
- f->eval(result, options.firstchannel, nchannels, faceid, u, v, dudx, dvdx, dudy, dvdy);
+ f->eval(result, options.firstchannel, nchannels, faceid, u, v, dudx, dvdx, dudy, dvdy);
- for(int c = r->numChannels(); c < nchannels; c++)
- result[c] = result[0];
+ for (int c = r->numChannels(); c < nchannels; c++)
+ result[c] = result[0];
- return true;
- }
+ return true;
+ }
#endif
- bool status = false;
-
- if(filename.length() && filename[0] == '@') {
- if(filename == u_at_bevel) {
- /* Bevel shader hack. */
- if(nchannels >= 3) {
- PathState *state = sd->osl_path_state;
- int num_samples = (int)s;
- float radius = t;
- float3 N = svm_bevel(kg, sd, state, radius, num_samples);
- result[0] = N.x;
- result[1] = N.y;
- result[2] = N.z;
- status = true;
- }
- }
- else if(filename == u_at_ao) {
- /* AO shader hack. */
- PathState *state = sd->osl_path_state;
- int num_samples = (int)s;
- float radius = t;
- float3 N = make_float3(dsdx, dtdx, dsdy);
- int flags = 0;
- if((int)dtdy) {
- flags |= NODE_AO_INSIDE;
- }
- if((int)options.sblur) {
- flags |= NODE_AO_ONLY_LOCAL;
- }
- if((int)options.tblur) {
- flags |= NODE_AO_GLOBAL_RADIUS;
- }
- result[0] = svm_ao(kg, sd, N, state, radius, num_samples, flags);
- status = true;
- }
- else if(filename[1] == 'l') {
- /* IES light. */
- int slot = atoi(filename.c_str() + 2);
- result[0] = kernel_ies_interp(kg, slot, s, t);
- status = true;
- }
- else {
- /* Packed texture. */
- int slot = atoi(filename.c_str() + 2);
- float4 rgba = kernel_tex_image_interp(kg, slot, s, 1.0f - t);
-
- result[0] = rgba[0];
- if(nchannels > 1)
- result[1] = rgba[1];
- if(nchannels > 2)
- result[2] = rgba[2];
- if(nchannels > 3)
- result[3] = rgba[3];
- status = true;
- }
- }
- else {
- if(texture_handle != NULL) {
- status = ts->texture(texture_handle,
- texture_thread_info,
- options,
- s, t,
- dsdx, dtdx,
- dsdy, dtdy,
- nchannels,
- result,
- dresultds, dresultdt);
- }
- else {
- status = ts->texture(filename,
- options,
- s, t,
- dsdx, dtdx,
- dsdy, dtdy,
- nchannels,
- result,
- dresultds, dresultdt);
- }
- }
-
- if(!status) {
- if(nchannels == 3 || nchannels == 4) {
- result[0] = 1.0f;
- result[1] = 0.0f;
- result[2] = 1.0f;
-
- if(nchannels == 4)
- result[3] = 1.0f;
- }
- /* This might be slow, but prevents error messages leak and
- * other nasty stuff happening.
- */
- string err = ts->geterror();
- (void) err;
- }
-
- return status;
+ bool status = false;
+
+ if (filename.length() && filename[0] == '@') {
+ if (filename == u_at_bevel) {
+ /* Bevel shader hack. */
+ if (nchannels >= 3) {
+ PathState *state = sd->osl_path_state;
+ int num_samples = (int)s;
+ float radius = t;
+ float3 N = svm_bevel(kg, sd, state, radius, num_samples);
+ result[0] = N.x;
+ result[1] = N.y;
+ result[2] = N.z;
+ status = true;
+ }
+ }
+ else if (filename == u_at_ao) {
+ /* AO shader hack. */
+ PathState *state = sd->osl_path_state;
+ int num_samples = (int)s;
+ float radius = t;
+ float3 N = make_float3(dsdx, dtdx, dsdy);
+ int flags = 0;
+ if ((int)dtdy) {
+ flags |= NODE_AO_INSIDE;
+ }
+ if ((int)options.sblur) {
+ flags |= NODE_AO_ONLY_LOCAL;
+ }
+ if ((int)options.tblur) {
+ flags |= NODE_AO_GLOBAL_RADIUS;
+ }
+ result[0] = svm_ao(kg, sd, N, state, radius, num_samples, flags);
+ status = true;
+ }
+ else if (filename[1] == 'l') {
+ /* IES light. */
+ int slot = atoi(filename.c_str() + 2);
+ result[0] = kernel_ies_interp(kg, slot, s, t);
+ status = true;
+ }
+ else {
+ /* Packed texture. */
+ int slot = atoi(filename.c_str() + 2);
+ float4 rgba = kernel_tex_image_interp(kg, slot, s, 1.0f - t);
+
+ result[0] = rgba[0];
+ if (nchannels > 1)
+ result[1] = rgba[1];
+ if (nchannels > 2)
+ result[2] = rgba[2];
+ if (nchannels > 3)
+ result[3] = rgba[3];
+ status = true;
+ }
+ }
+ else {
+ if (texture_handle != NULL) {
+ status = ts->texture(texture_handle,
+ texture_thread_info,
+ options,
+ s,
+ t,
+ dsdx,
+ dtdx,
+ dsdy,
+ dtdy,
+ nchannels,
+ result,
+ dresultds,
+ dresultdt);
+ }
+ else {
+ status = ts->texture(filename,
+ options,
+ s,
+ t,
+ dsdx,
+ dtdx,
+ dsdy,
+ dtdy,
+ nchannels,
+ result,
+ dresultds,
+ dresultdt);
+ }
+ }
+
+ if (!status) {
+ if (nchannels == 3 || nchannels == 4) {
+ result[0] = 1.0f;
+ result[1] = 0.0f;
+ result[2] = 1.0f;
+
+ if (nchannels == 4)
+ result[3] = 1.0f;
+ }
+ /* This might be slow, but prevents error messages leak and
+ * other nasty stuff happening.
+ */
+ string err = ts->geterror();
+ (void)err;
+ }
+
+ return status;
}
bool OSLRenderServices::texture3d(ustring filename,
@@ -1114,68 +1157,76 @@ bool OSLRenderServices::texture3d(ustring filename,
float *dresultdr,
ustring *errormessage)
{
- OSL::TextureSystem *ts = osl_ts;
- ShaderData *sd = (ShaderData *)(sg->renderstate);
- KernelGlobals *kg = sd->osl_globals;
-
- if(texture_thread_info == NULL) {
- OSLThreadData *tdata = kg->osl_tdata;
- texture_thread_info = tdata->oiio_thread_info;
- }
-
- bool status;
- if(filename.length() && filename[0] == '@') {
- int slot = atoi(filename.c_str() + 1);
- float4 rgba = kernel_tex_image_interp_3d(kg, slot, P.x, P.y, P.z, INTERPOLATION_NONE);
-
- result[0] = rgba[0];
- if(nchannels > 1)
- result[1] = rgba[1];
- if(nchannels > 2)
- result[2] = rgba[2];
- if(nchannels > 3)
- result[3] = rgba[3];
- status = true;
- }
- else {
- if(texture_handle != NULL) {
- status = ts->texture3d(texture_handle,
- texture_thread_info,
- options,
- P,
- dPdx, dPdy, dPdz,
- nchannels,
- result,
- dresultds, dresultdt, dresultdr);
- }
- else {
- status = ts->texture3d(filename,
- options,
- P,
- dPdx, dPdy, dPdz,
- nchannels,
- result,
- dresultds, dresultdt, dresultdr);
- }
- }
-
- if(!status) {
- if(nchannels == 3 || nchannels == 4) {
- result[0] = 1.0f;
- result[1] = 0.0f;
- result[2] = 1.0f;
-
- if(nchannels == 4)
- result[3] = 1.0f;
- }
- /* This might be slow, but prevents error messages leak and
- * other nasty stuff happening.
- */
- string err = ts->geterror();
- (void) err;
- }
-
- return status;
+ OSL::TextureSystem *ts = osl_ts;
+ ShaderData *sd = (ShaderData *)(sg->renderstate);
+ KernelGlobals *kg = sd->osl_globals;
+
+ if (texture_thread_info == NULL) {
+ OSLThreadData *tdata = kg->osl_tdata;
+ texture_thread_info = tdata->oiio_thread_info;
+ }
+
+ bool status;
+ if (filename.length() && filename[0] == '@') {
+ int slot = atoi(filename.c_str() + 1);
+ float4 rgba = kernel_tex_image_interp_3d(kg, slot, P.x, P.y, P.z, INTERPOLATION_NONE);
+
+ result[0] = rgba[0];
+ if (nchannels > 1)
+ result[1] = rgba[1];
+ if (nchannels > 2)
+ result[2] = rgba[2];
+ if (nchannels > 3)
+ result[3] = rgba[3];
+ status = true;
+ }
+ else {
+ if (texture_handle != NULL) {
+ status = ts->texture3d(texture_handle,
+ texture_thread_info,
+ options,
+ P,
+ dPdx,
+ dPdy,
+ dPdz,
+ nchannels,
+ result,
+ dresultds,
+ dresultdt,
+ dresultdr);
+ }
+ else {
+ status = ts->texture3d(filename,
+ options,
+ P,
+ dPdx,
+ dPdy,
+ dPdz,
+ nchannels,
+ result,
+ dresultds,
+ dresultdt,
+ dresultdr);
+ }
+ }
+
+ if (!status) {
+ if (nchannels == 3 || nchannels == 4) {
+ result[0] = 1.0f;
+ result[1] = 0.0f;
+ result[2] = 1.0f;
+
+ if (nchannels == 4)
+ result[3] = 1.0f;
+ }
+ /* This might be slow, but prevents error messages leak and
+ * other nasty stuff happening.
+ */
+ string err = ts->geterror();
+ (void)err;
+ }
+
+ return status;
}
bool OSLRenderServices::environment(ustring filename,
@@ -1192,35 +1243,34 @@ bool OSLRenderServices::environment(ustring filename,
float *dresultdt,
ustring *errormessage)
{
- OSL::TextureSystem *ts = osl_ts;
-
- if (thread_info == NULL) {
- ShaderData *sd = (ShaderData *)(sg->renderstate);
- KernelGlobals *kg = sd->osl_globals;
- OSLThreadData *tdata = kg->osl_tdata;
- thread_info = tdata->oiio_thread_info;
- }
-
- if (th == NULL) {
- th = ts->get_texture_handle(filename, thread_info);
- }
-
- bool status = ts->environment(th, thread_info,
- options, R, dRdx, dRdy,
- nchannels, result, dresultds, dresultdt);
-
- if(!status) {
- if(nchannels == 3 || nchannels == 4) {
- result[0] = 1.0f;
- result[1] = 0.0f;
- result[2] = 1.0f;
-
- if(nchannels == 4)
- result[3] = 1.0f;
- }
- }
-
- return status;
+ OSL::TextureSystem *ts = osl_ts;
+
+ if (thread_info == NULL) {
+ ShaderData *sd = (ShaderData *)(sg->renderstate);
+ KernelGlobals *kg = sd->osl_globals;
+ OSLThreadData *tdata = kg->osl_tdata;
+ thread_info = tdata->oiio_thread_info;
+ }
+
+ if (th == NULL) {
+ th = ts->get_texture_handle(filename, thread_info);
+ }
+
+ bool status = ts->environment(
+ th, thread_info, options, R, dRdx, dRdy, nchannels, result, dresultds, dresultdt);
+
+ if (!status) {
+ if (nchannels == 3 || nchannels == 4) {
+ result[0] = 1.0f;
+ result[1] = 0.0f;
+ result[2] = 1.0f;
+
+ if (nchannels == 4)
+ result[3] = 1.0f;
+ }
+ }
+
+ return status;
}
bool OSLRenderServices::get_texture_info(OSL::ShaderGlobals *sg,
@@ -1231,138 +1281,158 @@ bool OSLRenderServices::get_texture_info(OSL::ShaderGlobals *sg,
TypeDesc datatype,
void *data)
{
- OSL::TextureSystem *ts = osl_ts;
- if(filename.length() && filename[0] == '@') {
- /* Special builtin textures. */
- return false;
- }
- else {
- return ts->get_texture_info(filename, subimage, dataname, datatype, data);
- }
+ OSL::TextureSystem *ts = osl_ts;
+ if (filename.length() && filename[0] == '@') {
+ /* Special builtin textures. */
+ return false;
+ }
+ else {
+ return ts->get_texture_info(filename, subimage, dataname, datatype, data);
+ }
}
-int OSLRenderServices::pointcloud_search(OSL::ShaderGlobals *sg, ustring filename, const OSL::Vec3 &center,
- float radius, int max_points, bool sort,
- size_t *out_indices, float *out_distances, int derivs_offset)
+int OSLRenderServices::pointcloud_search(OSL::ShaderGlobals *sg,
+ ustring filename,
+ const OSL::Vec3 &center,
+ float radius,
+ int max_points,
+ bool sort,
+ size_t *out_indices,
+ float *out_distances,
+ int derivs_offset)
{
- return 0;
+ return 0;
}
-int OSLRenderServices::pointcloud_get(OSL::ShaderGlobals *sg, ustring filename, size_t *indices, int count,
- ustring attr_name, TypeDesc attr_type, void *out_data)
+int OSLRenderServices::pointcloud_get(OSL::ShaderGlobals *sg,
+ ustring filename,
+ size_t *indices,
+ int count,
+ ustring attr_name,
+ TypeDesc attr_type,
+ void *out_data)
{
- return 0;
+ return 0;
}
bool OSLRenderServices::pointcloud_write(OSL::ShaderGlobals *sg,
- ustring filename, const OSL::Vec3 &pos,
- int nattribs, const ustring *names,
+ ustring filename,
+ const OSL::Vec3 &pos,
+ int nattribs,
+ const ustring *names,
const TypeDesc *types,
const void **data)
{
- return false;
+ return false;
}
-bool OSLRenderServices::trace(TraceOpt &options, OSL::ShaderGlobals *sg,
- const OSL::Vec3 &P, const OSL::Vec3 &dPdx,
- const OSL::Vec3 &dPdy, const OSL::Vec3 &R,
- const OSL::Vec3 &dRdx, const OSL::Vec3 &dRdy)
+bool OSLRenderServices::trace(TraceOpt &options,
+ OSL::ShaderGlobals *sg,
+ const OSL::Vec3 &P,
+ const OSL::Vec3 &dPdx,
+ const OSL::Vec3 &dPdy,
+ const OSL::Vec3 &R,
+ const OSL::Vec3 &dRdx,
+ const OSL::Vec3 &dRdy)
{
- /* todo: options.shader support, maybe options.traceset */
- ShaderData *sd = (ShaderData *)(sg->renderstate);
-
- /* setup ray */
- Ray ray;
-
- ray.P = TO_FLOAT3(P);
- ray.D = TO_FLOAT3(R);
- ray.t = (options.maxdist == 1.0e30f)? FLT_MAX: options.maxdist - options.mindist;
- ray.time = sd->time;
-
- if(options.mindist == 0.0f) {
- /* avoid self-intersections */
- if(ray.P == sd->P) {
- bool transmit = (dot(sd->Ng, ray.D) < 0.0f);
- ray.P = ray_offset(sd->P, (transmit)? -sd->Ng: sd->Ng);
- }
- }
- else {
- /* offset for minimum distance */
- ray.P += options.mindist*ray.D;
- }
-
- /* ray differentials */
- ray.dP.dx = TO_FLOAT3(dPdx);
- ray.dP.dy = TO_FLOAT3(dPdy);
- ray.dD.dx = TO_FLOAT3(dRdx);
- ray.dD.dy = TO_FLOAT3(dRdy);
-
- /* allocate trace data */
- OSLTraceData *tracedata = (OSLTraceData*)sg->tracedata;
- tracedata->ray = ray;
- tracedata->setup = false;
- tracedata->init = true;
- tracedata->sd.osl_globals = sd->osl_globals;
-
- /* Raytrace, leaving out shadow opaque to avoid early exit. */
- uint visibility = PATH_RAY_ALL_VISIBILITY - PATH_RAY_SHADOW_OPAQUE;
- return scene_intersect(sd->osl_globals, ray, visibility, &tracedata->isect, NULL, 0.0f, 0.0f);
+ /* todo: options.shader support, maybe options.traceset */
+ ShaderData *sd = (ShaderData *)(sg->renderstate);
+
+ /* setup ray */
+ Ray ray;
+
+ ray.P = TO_FLOAT3(P);
+ ray.D = TO_FLOAT3(R);
+ ray.t = (options.maxdist == 1.0e30f) ? FLT_MAX : options.maxdist - options.mindist;
+ ray.time = sd->time;
+
+ if (options.mindist == 0.0f) {
+ /* avoid self-intersections */
+ if (ray.P == sd->P) {
+ bool transmit = (dot(sd->Ng, ray.D) < 0.0f);
+ ray.P = ray_offset(sd->P, (transmit) ? -sd->Ng : sd->Ng);
+ }
+ }
+ else {
+ /* offset for minimum distance */
+ ray.P += options.mindist * ray.D;
+ }
+
+ /* ray differentials */
+ ray.dP.dx = TO_FLOAT3(dPdx);
+ ray.dP.dy = TO_FLOAT3(dPdy);
+ ray.dD.dx = TO_FLOAT3(dRdx);
+ ray.dD.dy = TO_FLOAT3(dRdy);
+
+ /* allocate trace data */
+ OSLTraceData *tracedata = (OSLTraceData *)sg->tracedata;
+ tracedata->ray = ray;
+ tracedata->setup = false;
+ tracedata->init = true;
+ tracedata->sd.osl_globals = sd->osl_globals;
+
+ /* Raytrace, leaving out shadow opaque to avoid early exit. */
+ uint visibility = PATH_RAY_ALL_VISIBILITY - PATH_RAY_SHADOW_OPAQUE;
+ return scene_intersect(sd->osl_globals, ray, visibility, &tracedata->isect, NULL, 0.0f, 0.0f);
}
-
-bool OSLRenderServices::getmessage(OSL::ShaderGlobals *sg, ustring source, ustring name,
- TypeDesc type, void *val, bool derivatives)
+bool OSLRenderServices::getmessage(OSL::ShaderGlobals *sg,
+ ustring source,
+ ustring name,
+ TypeDesc type,
+ void *val,
+ bool derivatives)
{
- OSLTraceData *tracedata = (OSLTraceData*)sg->tracedata;
-
- if(source == u_trace && tracedata->init) {
- if(name == u_hit) {
- return set_attribute_int((tracedata->isect.prim != PRIM_NONE), type, derivatives, val);
- }
- else if(tracedata->isect.prim != PRIM_NONE) {
- if(name == u_hitdist) {
- float f[3] = {tracedata->isect.t, 0.0f, 0.0f};
- return set_attribute_float(f, type, derivatives, val);
- }
- else {
- ShaderData *sd = &tracedata->sd;
- KernelGlobals *kg = sd->osl_globals;
-
- if(!tracedata->setup) {
- /* lazy shader data setup */
- shader_setup_from_ray(kg, sd, &tracedata->isect, &tracedata->ray);
- tracedata->setup = true;
- }
-
- if(name == u_N) {
- return set_attribute_float3(sd->N, type, derivatives, val);
- }
- else if(name == u_Ng) {
- return set_attribute_float3(sd->Ng, type, derivatives, val);
- }
- else if(name == u_P) {
- float3 f[3] = {sd->P, sd->dP.dx, sd->dP.dy};
- return set_attribute_float3(f, type, derivatives, val);
- }
- else if(name == u_I) {
- float3 f[3] = {sd->I, sd->dI.dx, sd->dI.dy};
- return set_attribute_float3(f, type, derivatives, val);
- }
- else if(name == u_u) {
- float f[3] = {sd->u, sd->du.dx, sd->du.dy};
- return set_attribute_float(f, type, derivatives, val);
- }
- else if(name == u_v) {
- float f[3] = {sd->v, sd->dv.dx, sd->dv.dy};
- return set_attribute_float(f, type, derivatives, val);
- }
-
- return get_attribute(sd, derivatives, u_empty, type, name, val);
- }
- }
- }
-
- return false;
+ OSLTraceData *tracedata = (OSLTraceData *)sg->tracedata;
+
+ if (source == u_trace && tracedata->init) {
+ if (name == u_hit) {
+ return set_attribute_int((tracedata->isect.prim != PRIM_NONE), type, derivatives, val);
+ }
+ else if (tracedata->isect.prim != PRIM_NONE) {
+ if (name == u_hitdist) {
+ float f[3] = {tracedata->isect.t, 0.0f, 0.0f};
+ return set_attribute_float(f, type, derivatives, val);
+ }
+ else {
+ ShaderData *sd = &tracedata->sd;
+ KernelGlobals *kg = sd->osl_globals;
+
+ if (!tracedata->setup) {
+ /* lazy shader data setup */
+ shader_setup_from_ray(kg, sd, &tracedata->isect, &tracedata->ray);
+ tracedata->setup = true;
+ }
+
+ if (name == u_N) {
+ return set_attribute_float3(sd->N, type, derivatives, val);
+ }
+ else if (name == u_Ng) {
+ return set_attribute_float3(sd->Ng, type, derivatives, val);
+ }
+ else if (name == u_P) {
+ float3 f[3] = {sd->P, sd->dP.dx, sd->dP.dy};
+ return set_attribute_float3(f, type, derivatives, val);
+ }
+ else if (name == u_I) {
+ float3 f[3] = {sd->I, sd->dI.dx, sd->dI.dy};
+ return set_attribute_float3(f, type, derivatives, val);
+ }
+ else if (name == u_u) {
+ float f[3] = {sd->u, sd->du.dx, sd->du.dy};
+ return set_attribute_float(f, type, derivatives, val);
+ }
+ else if (name == u_v) {
+ float f[3] = {sd->v, sd->dv.dx, sd->dv.dy};
+ return set_attribute_float(f, type, derivatives, val);
+ }
+
+ return get_attribute(sd, derivatives, u_empty, type, name, val);
+ }
+ }
+ }
+
+ return false;
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/osl/osl_services.h b/intern/cycles/kernel/osl/osl_services.h
index 3990a22aefd..2fad5833fc9 100644
--- a/intern/cycles/kernel/osl/osl_services.h
+++ b/intern/cycles/kernel/osl/osl_services.h
@@ -40,177 +40,229 @@ class Shader;
struct ShaderData;
struct float3;
struct KernelGlobals;
-class OSLRenderServices : public OSL::RendererServices
-{
-public:
- OSLRenderServices();
- ~OSLRenderServices();
-
- void thread_init(KernelGlobals *kernel_globals, OSL::TextureSystem *ts);
-
- bool get_matrix(OSL::ShaderGlobals *sg, OSL::Matrix44 &result, OSL::TransformationPtr xform, float time) override;
- bool get_inverse_matrix(OSL::ShaderGlobals *sg, OSL::Matrix44 &result, OSL::TransformationPtr xform, float time) override;
-
- bool get_matrix(OSL::ShaderGlobals *sg, OSL::Matrix44 &result, ustring from, float time) override;
- bool get_inverse_matrix(OSL::ShaderGlobals *sg, OSL::Matrix44 &result, ustring to, float time) override;
-
- bool get_matrix(OSL::ShaderGlobals *sg, OSL::Matrix44 &result, OSL::TransformationPtr xform) override;
- bool get_inverse_matrix(OSL::ShaderGlobals *sg, OSL::Matrix44 &result, OSL::TransformationPtr xform) override;
-
- bool get_matrix(OSL::ShaderGlobals *sg, OSL::Matrix44 &result, ustring from) override;
- bool get_inverse_matrix(OSL::ShaderGlobals *sg, OSL::Matrix44 &result, ustring from) override;
-
- bool get_array_attribute(OSL::ShaderGlobals *sg, bool derivatives,
- ustring object, TypeDesc type, ustring name,
- int index, void *val) override;
- bool get_attribute(OSL::ShaderGlobals *sg, bool derivatives, ustring object,
- TypeDesc type, ustring name, void *val) override;
- bool get_attribute(ShaderData *sd, bool derivatives, ustring object_name,
- TypeDesc type, ustring name, void *val);
-
- bool get_userdata(bool derivatives, ustring name, TypeDesc type,
- OSL::ShaderGlobals *sg, void *val) override;
-
- int pointcloud_search(OSL::ShaderGlobals *sg, ustring filename, const OSL::Vec3 &center,
- float radius, int max_points, bool sort, size_t *out_indices,
- float *out_distances, int derivs_offset) override;
-
- int pointcloud_get(OSL::ShaderGlobals *sg, ustring filename, size_t *indices, int count,
- ustring attr_name, TypeDesc attr_type, void *out_data) override;
-
- bool pointcloud_write(OSL::ShaderGlobals *sg,
- ustring filename, const OSL::Vec3 &pos,
- int nattribs, const ustring *names,
- const TypeDesc *types,
- const void **data) override;
-
- bool trace(TraceOpt &options, OSL::ShaderGlobals *sg,
- const OSL::Vec3 &P, const OSL::Vec3 &dPdx,
- const OSL::Vec3 &dPdy, const OSL::Vec3 &R,
- const OSL::Vec3 &dRdx, const OSL::Vec3 &dRdy) override;
-
- bool getmessage(OSL::ShaderGlobals *sg, ustring source, ustring name,
- TypeDesc type, void *val, bool derivatives) override;
-
- TextureSystem::TextureHandle *get_texture_handle(ustring filename) override;
-
- bool good(TextureSystem::TextureHandle *texture_handle) override;
-
- bool texture(ustring filename,
- TextureSystem::TextureHandle *texture_handle,
- TexturePerthread *texture_thread_info,
- TextureOpt &options,
- OSL::ShaderGlobals *sg,
- float s, float t,
- float dsdx, float dtdx, float dsdy, float dtdy,
- int nchannels,
- float *result,
- float *dresultds,
- float *dresultdt,
- ustring *errormessage) override;
-
- bool texture3d(ustring filename,
- TextureHandle *texture_handle,
- TexturePerthread *texture_thread_info,
- TextureOpt &options,
- OSL::ShaderGlobals *sg,
- const OSL::Vec3 &P,
- const OSL::Vec3 &dPdx,
- const OSL::Vec3 &dPdy,
- const OSL::Vec3 &dPdz,
- int nchannels,
- float *result,
- float *dresultds,
- float *dresultdt,
- float *dresultdr,
- ustring *errormessage) override;
-
- bool environment(ustring filename,
- TextureHandle *texture_handle,
- TexturePerthread *texture_thread_info,
- TextureOpt &options,
- OSL::ShaderGlobals *sg,
- const OSL::Vec3 &R,
- const OSL::Vec3 &dRdx,
- const OSL::Vec3 &dRdy,
- int nchannels,
- float *result,
- float *dresultds,
- float *dresultdt,
- ustring *errormessage) override;
-
- bool get_texture_info(OSL::ShaderGlobals *sg,
- ustring filename,
- TextureHandle *texture_handle,
- int subimage,
- ustring dataname,
- TypeDesc datatype,
- void *data) override;
-
- static bool get_background_attribute(KernelGlobals *kg, ShaderData *sd, ustring name,
- TypeDesc type, bool derivatives, void *val);
- static bool get_object_standard_attribute(KernelGlobals *kg, ShaderData *sd, ustring name,
- TypeDesc type, bool derivatives, void *val);
-
- static ustring u_distance;
- static ustring u_index;
- static ustring u_world;
- static ustring u_camera;
- static ustring u_screen;
- static ustring u_raster;
- static ustring u_ndc;
- static ustring u_object_location;
- static ustring u_object_index;
- static ustring u_geom_dupli_generated;
- static ustring u_geom_dupli_uv;
- static ustring u_material_index;
- static ustring u_object_random;
- static ustring u_particle_index;
- static ustring u_particle_random;
- static ustring u_particle_age;
- static ustring u_particle_lifetime;
- static ustring u_particle_location;
- static ustring u_particle_rotation;
- static ustring u_particle_size;
- static ustring u_particle_velocity;
- static ustring u_particle_angular_velocity;
- static ustring u_geom_numpolyvertices;
- static ustring u_geom_trianglevertices;
- static ustring u_geom_polyvertices;
- static ustring u_geom_name;
- static ustring u_geom_undisplaced;
- static ustring u_is_smooth;
- static ustring u_is_curve;
- static ustring u_curve_thickness;
- static ustring u_curve_tangent_normal;
- static ustring u_curve_random;
- static ustring u_path_ray_length;
- static ustring u_path_ray_depth;
- static ustring u_path_diffuse_depth;
- static ustring u_path_glossy_depth;
- static ustring u_path_transparent_depth;
- static ustring u_path_transmission_depth;
- static ustring u_trace;
- static ustring u_hit;
- static ustring u_hitdist;
- static ustring u_N;
- static ustring u_Ng;
- static ustring u_P;
- static ustring u_I;
- static ustring u_u;
- static ustring u_v;
- static ustring u_empty;
- static ustring u_at_bevel;
- static ustring u_at_ao;
-
-private:
- KernelGlobals *kernel_globals;
- OSL::TextureSystem *osl_ts;
+class OSLRenderServices : public OSL::RendererServices {
+ public:
+ OSLRenderServices();
+ ~OSLRenderServices();
+
+ void thread_init(KernelGlobals *kernel_globals, OSL::TextureSystem *ts);
+
+ bool get_matrix(OSL::ShaderGlobals *sg,
+ OSL::Matrix44 &result,
+ OSL::TransformationPtr xform,
+ float time) override;
+ bool get_inverse_matrix(OSL::ShaderGlobals *sg,
+ OSL::Matrix44 &result,
+ OSL::TransformationPtr xform,
+ float time) override;
+
+ bool get_matrix(OSL::ShaderGlobals *sg,
+ OSL::Matrix44 &result,
+ ustring from,
+ float time) override;
+ bool get_inverse_matrix(OSL::ShaderGlobals *sg,
+ OSL::Matrix44 &result,
+ ustring to,
+ float time) override;
+
+ bool get_matrix(OSL::ShaderGlobals *sg,
+ OSL::Matrix44 &result,
+ OSL::TransformationPtr xform) override;
+ bool get_inverse_matrix(OSL::ShaderGlobals *sg,
+ OSL::Matrix44 &result,
+ OSL::TransformationPtr xform) override;
+
+ bool get_matrix(OSL::ShaderGlobals *sg, OSL::Matrix44 &result, ustring from) override;
+ bool get_inverse_matrix(OSL::ShaderGlobals *sg, OSL::Matrix44 &result, ustring from) override;
+
+ bool get_array_attribute(OSL::ShaderGlobals *sg,
+ bool derivatives,
+ ustring object,
+ TypeDesc type,
+ ustring name,
+ int index,
+ void *val) override;
+ bool get_attribute(OSL::ShaderGlobals *sg,
+ bool derivatives,
+ ustring object,
+ TypeDesc type,
+ ustring name,
+ void *val) override;
+ bool get_attribute(ShaderData *sd,
+ bool derivatives,
+ ustring object_name,
+ TypeDesc type,
+ ustring name,
+ void *val);
+
+ bool get_userdata(
+ bool derivatives, ustring name, TypeDesc type, OSL::ShaderGlobals *sg, void *val) override;
+
+ int pointcloud_search(OSL::ShaderGlobals *sg,
+ ustring filename,
+ const OSL::Vec3 &center,
+ float radius,
+ int max_points,
+ bool sort,
+ size_t *out_indices,
+ float *out_distances,
+ int derivs_offset) override;
+
+ int pointcloud_get(OSL::ShaderGlobals *sg,
+ ustring filename,
+ size_t *indices,
+ int count,
+ ustring attr_name,
+ TypeDesc attr_type,
+ void *out_data) override;
+
+ bool pointcloud_write(OSL::ShaderGlobals *sg,
+ ustring filename,
+ const OSL::Vec3 &pos,
+ int nattribs,
+ const ustring *names,
+ const TypeDesc *types,
+ const void **data) override;
+
+ bool trace(TraceOpt &options,
+ OSL::ShaderGlobals *sg,
+ const OSL::Vec3 &P,
+ const OSL::Vec3 &dPdx,
+ const OSL::Vec3 &dPdy,
+ const OSL::Vec3 &R,
+ const OSL::Vec3 &dRdx,
+ const OSL::Vec3 &dRdy) override;
+
+ bool getmessage(OSL::ShaderGlobals *sg,
+ ustring source,
+ ustring name,
+ TypeDesc type,
+ void *val,
+ bool derivatives) override;
+
+ TextureSystem::TextureHandle *get_texture_handle(ustring filename) override;
+
+ bool good(TextureSystem::TextureHandle *texture_handle) override;
+
+ bool texture(ustring filename,
+ TextureSystem::TextureHandle *texture_handle,
+ TexturePerthread *texture_thread_info,
+ TextureOpt &options,
+ OSL::ShaderGlobals *sg,
+ float s,
+ float t,
+ float dsdx,
+ float dtdx,
+ float dsdy,
+ float dtdy,
+ int nchannels,
+ float *result,
+ float *dresultds,
+ float *dresultdt,
+ ustring *errormessage) override;
+
+ bool texture3d(ustring filename,
+ TextureHandle *texture_handle,
+ TexturePerthread *texture_thread_info,
+ TextureOpt &options,
+ OSL::ShaderGlobals *sg,
+ const OSL::Vec3 &P,
+ const OSL::Vec3 &dPdx,
+ const OSL::Vec3 &dPdy,
+ const OSL::Vec3 &dPdz,
+ int nchannels,
+ float *result,
+ float *dresultds,
+ float *dresultdt,
+ float *dresultdr,
+ ustring *errormessage) override;
+
+ bool environment(ustring filename,
+ TextureHandle *texture_handle,
+ TexturePerthread *texture_thread_info,
+ TextureOpt &options,
+ OSL::ShaderGlobals *sg,
+ const OSL::Vec3 &R,
+ const OSL::Vec3 &dRdx,
+ const OSL::Vec3 &dRdy,
+ int nchannels,
+ float *result,
+ float *dresultds,
+ float *dresultdt,
+ ustring *errormessage) override;
+
+ bool get_texture_info(OSL::ShaderGlobals *sg,
+ ustring filename,
+ TextureHandle *texture_handle,
+ int subimage,
+ ustring dataname,
+ TypeDesc datatype,
+ void *data) override;
+
+ static bool get_background_attribute(
+ KernelGlobals *kg, ShaderData *sd, ustring name, TypeDesc type, bool derivatives, void *val);
+ static bool get_object_standard_attribute(
+ KernelGlobals *kg, ShaderData *sd, ustring name, TypeDesc type, bool derivatives, void *val);
+
+ static ustring u_distance;
+ static ustring u_index;
+ static ustring u_world;
+ static ustring u_camera;
+ static ustring u_screen;
+ static ustring u_raster;
+ static ustring u_ndc;
+ static ustring u_object_location;
+ static ustring u_object_index;
+ static ustring u_geom_dupli_generated;
+ static ustring u_geom_dupli_uv;
+ static ustring u_material_index;
+ static ustring u_object_random;
+ static ustring u_particle_index;
+ static ustring u_particle_random;
+ static ustring u_particle_age;
+ static ustring u_particle_lifetime;
+ static ustring u_particle_location;
+ static ustring u_particle_rotation;
+ static ustring u_particle_size;
+ static ustring u_particle_velocity;
+ static ustring u_particle_angular_velocity;
+ static ustring u_geom_numpolyvertices;
+ static ustring u_geom_trianglevertices;
+ static ustring u_geom_polyvertices;
+ static ustring u_geom_name;
+ static ustring u_geom_undisplaced;
+ static ustring u_is_smooth;
+ static ustring u_is_curve;
+ static ustring u_curve_thickness;
+ static ustring u_curve_tangent_normal;
+ static ustring u_curve_random;
+ static ustring u_path_ray_length;
+ static ustring u_path_ray_depth;
+ static ustring u_path_diffuse_depth;
+ static ustring u_path_glossy_depth;
+ static ustring u_path_transparent_depth;
+ static ustring u_path_transmission_depth;
+ static ustring u_trace;
+ static ustring u_hit;
+ static ustring u_hitdist;
+ static ustring u_N;
+ static ustring u_Ng;
+ static ustring u_P;
+ static ustring u_I;
+ static ustring u_u;
+ static ustring u_v;
+ static ustring u_empty;
+ static ustring u_at_bevel;
+ static ustring u_at_ao;
+
+ private:
+ KernelGlobals *kernel_globals;
+ OSL::TextureSystem *osl_ts;
#ifdef WITH_PTEX
- PtexCache *ptex_cache;
+ PtexCache *ptex_cache;
#endif
};
CCL_NAMESPACE_END
-#endif /* __OSL_SERVICES_H__ */
+#endif /* __OSL_SERVICES_H__ */
diff --git a/intern/cycles/kernel/osl/osl_shader.cpp b/intern/cycles/kernel/osl/osl_shader.cpp
index a89bb3fd1a3..3d9c579c9ff 100644
--- a/intern/cycles/kernel/osl/osl_shader.cpp
+++ b/intern/cycles/kernel/osl/osl_shader.cpp
@@ -33,103 +33,104 @@
#include "render/attribute.h"
-
CCL_NAMESPACE_BEGIN
/* Threads */
-void OSLShader::thread_init(KernelGlobals *kg, KernelGlobals *kernel_globals, OSLGlobals *osl_globals)
+void OSLShader::thread_init(KernelGlobals *kg,
+ KernelGlobals *kernel_globals,
+ OSLGlobals *osl_globals)
{
- /* no osl used? */
- if(!osl_globals->use) {
- kg->osl = NULL;
- return;
- }
+ /* no osl used? */
+ if (!osl_globals->use) {
+ kg->osl = NULL;
+ return;
+ }
- /* per thread kernel data init*/
- kg->osl = osl_globals;
- kg->osl->services->thread_init(kernel_globals, osl_globals->ts);
+ /* per thread kernel data init*/
+ kg->osl = osl_globals;
+ kg->osl->services->thread_init(kernel_globals, osl_globals->ts);
- OSL::ShadingSystem *ss = kg->osl->ss;
- OSLThreadData *tdata = new OSLThreadData();
+ OSL::ShadingSystem *ss = kg->osl->ss;
+ OSLThreadData *tdata = new OSLThreadData();
- memset((void *)&tdata->globals, 0, sizeof(OSL::ShaderGlobals));
- tdata->globals.tracedata = &tdata->tracedata;
- tdata->globals.flipHandedness = false;
- tdata->osl_thread_info = ss->create_thread_info();
- tdata->context = ss->get_context(tdata->osl_thread_info);
+ memset((void *)&tdata->globals, 0, sizeof(OSL::ShaderGlobals));
+ tdata->globals.tracedata = &tdata->tracedata;
+ tdata->globals.flipHandedness = false;
+ tdata->osl_thread_info = ss->create_thread_info();
+ tdata->context = ss->get_context(tdata->osl_thread_info);
- tdata->oiio_thread_info = osl_globals->ts->get_perthread_info();
+ tdata->oiio_thread_info = osl_globals->ts->get_perthread_info();
- kg->osl_ss = (OSLShadingSystem*)ss;
- kg->osl_tdata = tdata;
+ kg->osl_ss = (OSLShadingSystem *)ss;
+ kg->osl_tdata = tdata;
}
void OSLShader::thread_free(KernelGlobals *kg)
{
- if(!kg->osl)
- return;
+ if (!kg->osl)
+ return;
- OSL::ShadingSystem *ss = (OSL::ShadingSystem*)kg->osl_ss;
- OSLThreadData *tdata = kg->osl_tdata;
- ss->release_context(tdata->context);
+ OSL::ShadingSystem *ss = (OSL::ShadingSystem *)kg->osl_ss;
+ OSLThreadData *tdata = kg->osl_tdata;
+ ss->release_context(tdata->context);
- ss->destroy_thread_info(tdata->osl_thread_info);
+ ss->destroy_thread_info(tdata->osl_thread_info);
- delete tdata;
+ delete tdata;
- kg->osl = NULL;
- kg->osl_ss = NULL;
- kg->osl_tdata = NULL;
+ kg->osl = NULL;
+ kg->osl_ss = NULL;
+ kg->osl_tdata = NULL;
}
/* Globals */
-static void shaderdata_to_shaderglobals(KernelGlobals *kg, ShaderData *sd, PathState *state,
- int path_flag, OSLThreadData *tdata)
+static void shaderdata_to_shaderglobals(
+ KernelGlobals *kg, ShaderData *sd, PathState *state, int path_flag, OSLThreadData *tdata)
{
- OSL::ShaderGlobals *globals = &tdata->globals;
-
- /* copy from shader data to shader globals */
- globals->P = TO_VEC3(sd->P);
- globals->dPdx = TO_VEC3(sd->dP.dx);
- globals->dPdy = TO_VEC3(sd->dP.dy);
- globals->I = TO_VEC3(sd->I);
- globals->dIdx = TO_VEC3(sd->dI.dx);
- globals->dIdy = TO_VEC3(sd->dI.dy);
- globals->N = TO_VEC3(sd->N);
- globals->Ng = TO_VEC3(sd->Ng);
- globals->u = sd->u;
- globals->dudx = sd->du.dx;
- globals->dudy = sd->du.dy;
- globals->v = sd->v;
- globals->dvdx = sd->dv.dx;
- globals->dvdy = sd->dv.dy;
- globals->dPdu = TO_VEC3(sd->dPdu);
- globals->dPdv = TO_VEC3(sd->dPdv);
- globals->surfacearea = (sd->object == OBJECT_NONE) ? 1.0f : object_surface_area(kg, sd->object);
- globals->time = sd->time;
-
- /* booleans */
- globals->raytype = path_flag;
- globals->backfacing = (sd->flag & SD_BACKFACING);
-
- /* shader data to be used in services callbacks */
- globals->renderstate = sd;
-
- /* hacky, we leave it to services to fetch actual object matrix */
- globals->shader2common = sd;
- globals->object2common = sd;
-
- /* must be set to NULL before execute */
- globals->Ci = NULL;
-
- /* clear trace data */
- tdata->tracedata.init = false;
-
- /* used by renderservices */
- sd->osl_globals = kg;
- sd->osl_path_state = state;
+ OSL::ShaderGlobals *globals = &tdata->globals;
+
+ /* copy from shader data to shader globals */
+ globals->P = TO_VEC3(sd->P);
+ globals->dPdx = TO_VEC3(sd->dP.dx);
+ globals->dPdy = TO_VEC3(sd->dP.dy);
+ globals->I = TO_VEC3(sd->I);
+ globals->dIdx = TO_VEC3(sd->dI.dx);
+ globals->dIdy = TO_VEC3(sd->dI.dy);
+ globals->N = TO_VEC3(sd->N);
+ globals->Ng = TO_VEC3(sd->Ng);
+ globals->u = sd->u;
+ globals->dudx = sd->du.dx;
+ globals->dudy = sd->du.dy;
+ globals->v = sd->v;
+ globals->dvdx = sd->dv.dx;
+ globals->dvdy = sd->dv.dy;
+ globals->dPdu = TO_VEC3(sd->dPdu);
+ globals->dPdv = TO_VEC3(sd->dPdv);
+ globals->surfacearea = (sd->object == OBJECT_NONE) ? 1.0f : object_surface_area(kg, sd->object);
+ globals->time = sd->time;
+
+ /* booleans */
+ globals->raytype = path_flag;
+ globals->backfacing = (sd->flag & SD_BACKFACING);
+
+ /* shader data to be used in services callbacks */
+ globals->renderstate = sd;
+
+ /* hacky, we leave it to services to fetch actual object matrix */
+ globals->shader2common = sd;
+ globals->object2common = sd;
+
+ /* must be set to NULL before execute */
+ globals->Ci = NULL;
+
+ /* clear trace data */
+ tdata->tracedata.init = false;
+
+ /* used by renderservices */
+ sd->osl_globals = kg;
+ sd->osl_path_state = state;
}
/* Surface */
@@ -139,97 +140,101 @@ static void flatten_surface_closure_tree(ShaderData *sd,
const OSL::ClosureColor *closure,
float3 weight = make_float3(1.0f, 1.0f, 1.0f))
{
- /* OSL gives us a closure tree, we flatten it into arrays per
- * closure type, for evaluation, sampling, etc later on. */
-
- switch(closure->id) {
- case OSL::ClosureColor::MUL: {
- OSL::ClosureMul *mul = (OSL::ClosureMul *)closure;
- flatten_surface_closure_tree(sd, path_flag, mul->closure, TO_FLOAT3(mul->weight) * weight);
- break;
- }
- case OSL::ClosureColor::ADD: {
- OSL::ClosureAdd *add = (OSL::ClosureAdd *)closure;
- flatten_surface_closure_tree(sd, path_flag, add->closureA, weight);
- flatten_surface_closure_tree(sd, path_flag, add->closureB, weight);
- break;
- }
- default: {
- OSL::ClosureComponent *comp = (OSL::ClosureComponent *)closure;
- CClosurePrimitive *prim = (CClosurePrimitive *)comp->data();
-
- if(prim) {
+ /* OSL gives us a closure tree, we flatten it into arrays per
+ * closure type, for evaluation, sampling, etc later on. */
+
+ switch (closure->id) {
+ case OSL::ClosureColor::MUL: {
+ OSL::ClosureMul *mul = (OSL::ClosureMul *)closure;
+ flatten_surface_closure_tree(sd, path_flag, mul->closure, TO_FLOAT3(mul->weight) * weight);
+ break;
+ }
+ case OSL::ClosureColor::ADD: {
+ OSL::ClosureAdd *add = (OSL::ClosureAdd *)closure;
+ flatten_surface_closure_tree(sd, path_flag, add->closureA, weight);
+ flatten_surface_closure_tree(sd, path_flag, add->closureB, weight);
+ break;
+ }
+ default: {
+ OSL::ClosureComponent *comp = (OSL::ClosureComponent *)closure;
+ CClosurePrimitive *prim = (CClosurePrimitive *)comp->data();
+
+ if (prim) {
#ifdef OSL_SUPPORTS_WEIGHTED_CLOSURE_COMPONENTS
- weight = weight*TO_FLOAT3(comp->w);
+ weight = weight * TO_FLOAT3(comp->w);
#endif
- prim->setup(sd, path_flag, weight);
- }
- break;
- }
- }
+ prim->setup(sd, path_flag, weight);
+ }
+ break;
+ }
+ }
}
void OSLShader::eval_surface(KernelGlobals *kg, ShaderData *sd, PathState *state, int path_flag)
{
- /* setup shader globals from shader data */
- OSLThreadData *tdata = kg->osl_tdata;
- shaderdata_to_shaderglobals(kg, sd, state, path_flag, tdata);
-
- /* execute shader for this point */
- OSL::ShadingSystem *ss = (OSL::ShadingSystem*)kg->osl_ss;
- OSL::ShaderGlobals *globals = &tdata->globals;
- OSL::ShadingContext *octx = tdata->context;
- int shader = sd->shader & SHADER_MASK;
-
- /* automatic bump shader */
- if(kg->osl->bump_state[shader]) {
- /* save state */
- float3 P = sd->P;
- float3 dPdx = sd->dP.dx;
- float3 dPdy = sd->dP.dy;
-
- /* set state as if undisplaced */
- if(sd->flag & SD_HAS_DISPLACEMENT) {
- float data[9];
- bool found = kg->osl->services->get_attribute(sd, true, OSLRenderServices::u_empty, TypeDesc::TypeVector,
- OSLRenderServices::u_geom_undisplaced, data);
- (void) found;
- assert(found);
-
- memcpy(&sd->P, data, sizeof(float)*3);
- memcpy(&sd->dP.dx, data+3, sizeof(float)*3);
- memcpy(&sd->dP.dy, data+6, sizeof(float)*3);
-
- object_position_transform(kg, sd, &sd->P);
- object_dir_transform(kg, sd, &sd->dP.dx);
- object_dir_transform(kg, sd, &sd->dP.dy);
-
- globals->P = TO_VEC3(sd->P);
- globals->dPdx = TO_VEC3(sd->dP.dx);
- globals->dPdy = TO_VEC3(sd->dP.dy);
- }
-
- /* execute bump shader */
- ss->execute(octx, *(kg->osl->bump_state[shader]), *globals);
-
- /* reset state */
- sd->P = P;
- sd->dP.dx = dPdx;
- sd->dP.dy = dPdy;
-
- globals->P = TO_VEC3(P);
- globals->dPdx = TO_VEC3(dPdx);
- globals->dPdy = TO_VEC3(dPdy);
- }
-
- /* surface shader */
- if(kg->osl->surface_state[shader]) {
- ss->execute(octx, *(kg->osl->surface_state[shader]), *globals);
- }
-
- /* flatten closure tree */
- if(globals->Ci)
- flatten_surface_closure_tree(sd, path_flag, globals->Ci);
+ /* setup shader globals from shader data */
+ OSLThreadData *tdata = kg->osl_tdata;
+ shaderdata_to_shaderglobals(kg, sd, state, path_flag, tdata);
+
+ /* execute shader for this point */
+ OSL::ShadingSystem *ss = (OSL::ShadingSystem *)kg->osl_ss;
+ OSL::ShaderGlobals *globals = &tdata->globals;
+ OSL::ShadingContext *octx = tdata->context;
+ int shader = sd->shader & SHADER_MASK;
+
+ /* automatic bump shader */
+ if (kg->osl->bump_state[shader]) {
+ /* save state */
+ float3 P = sd->P;
+ float3 dPdx = sd->dP.dx;
+ float3 dPdy = sd->dP.dy;
+
+ /* set state as if undisplaced */
+ if (sd->flag & SD_HAS_DISPLACEMENT) {
+ float data[9];
+ bool found = kg->osl->services->get_attribute(sd,
+ true,
+ OSLRenderServices::u_empty,
+ TypeDesc::TypeVector,
+ OSLRenderServices::u_geom_undisplaced,
+ data);
+ (void)found;
+ assert(found);
+
+ memcpy(&sd->P, data, sizeof(float) * 3);
+ memcpy(&sd->dP.dx, data + 3, sizeof(float) * 3);
+ memcpy(&sd->dP.dy, data + 6, sizeof(float) * 3);
+
+ object_position_transform(kg, sd, &sd->P);
+ object_dir_transform(kg, sd, &sd->dP.dx);
+ object_dir_transform(kg, sd, &sd->dP.dy);
+
+ globals->P = TO_VEC3(sd->P);
+ globals->dPdx = TO_VEC3(sd->dP.dx);
+ globals->dPdy = TO_VEC3(sd->dP.dy);
+ }
+
+ /* execute bump shader */
+ ss->execute(octx, *(kg->osl->bump_state[shader]), *globals);
+
+ /* reset state */
+ sd->P = P;
+ sd->dP.dx = dPdx;
+ sd->dP.dy = dPdy;
+
+ globals->P = TO_VEC3(P);
+ globals->dPdx = TO_VEC3(dPdx);
+ globals->dPdy = TO_VEC3(dPdy);
+ }
+
+ /* surface shader */
+ if (kg->osl->surface_state[shader]) {
+ ss->execute(octx, *(kg->osl->surface_state[shader]), *globals);
+ }
+
+ /* flatten closure tree */
+ if (globals->Ci)
+ flatten_surface_closure_tree(sd, path_flag, globals->Ci);
}
/* Background */
@@ -238,56 +243,56 @@ static void flatten_background_closure_tree(ShaderData *sd,
const OSL::ClosureColor *closure,
float3 weight = make_float3(1.0f, 1.0f, 1.0f))
{
- /* OSL gives us a closure tree, if we are shading for background there
- * is only one supported closure type at the moment, which has no evaluation
- * functions, so we just sum the weights */
-
- switch(closure->id) {
- case OSL::ClosureColor::MUL: {
- OSL::ClosureMul *mul = (OSL::ClosureMul *)closure;
- flatten_background_closure_tree(sd, mul->closure, weight * TO_FLOAT3(mul->weight));
- break;
- }
- case OSL::ClosureColor::ADD: {
- OSL::ClosureAdd *add = (OSL::ClosureAdd *)closure;
-
- flatten_background_closure_tree(sd, add->closureA, weight);
- flatten_background_closure_tree(sd, add->closureB, weight);
- break;
- }
- default: {
- OSL::ClosureComponent *comp = (OSL::ClosureComponent *)closure;
- CClosurePrimitive *prim = (CClosurePrimitive *)comp->data();
-
- if(prim) {
+ /* OSL gives us a closure tree, if we are shading for background there
+ * is only one supported closure type at the moment, which has no evaluation
+ * functions, so we just sum the weights */
+
+ switch (closure->id) {
+ case OSL::ClosureColor::MUL: {
+ OSL::ClosureMul *mul = (OSL::ClosureMul *)closure;
+ flatten_background_closure_tree(sd, mul->closure, weight * TO_FLOAT3(mul->weight));
+ break;
+ }
+ case OSL::ClosureColor::ADD: {
+ OSL::ClosureAdd *add = (OSL::ClosureAdd *)closure;
+
+ flatten_background_closure_tree(sd, add->closureA, weight);
+ flatten_background_closure_tree(sd, add->closureB, weight);
+ break;
+ }
+ default: {
+ OSL::ClosureComponent *comp = (OSL::ClosureComponent *)closure;
+ CClosurePrimitive *prim = (CClosurePrimitive *)comp->data();
+
+ if (prim) {
#ifdef OSL_SUPPORTS_WEIGHTED_CLOSURE_COMPONENTS
- weight = weight*TO_FLOAT3(comp->w);
+ weight = weight * TO_FLOAT3(comp->w);
#endif
- prim->setup(sd, 0, weight);
- }
- break;
- }
- }
+ prim->setup(sd, 0, weight);
+ }
+ break;
+ }
+ }
}
void OSLShader::eval_background(KernelGlobals *kg, ShaderData *sd, PathState *state, int path_flag)
{
- /* setup shader globals from shader data */
- OSLThreadData *tdata = kg->osl_tdata;
- shaderdata_to_shaderglobals(kg, sd, state, path_flag, tdata);
-
- /* execute shader for this point */
- OSL::ShadingSystem *ss = (OSL::ShadingSystem*)kg->osl_ss;
- OSL::ShaderGlobals *globals = &tdata->globals;
- OSL::ShadingContext *octx = tdata->context;
-
- if(kg->osl->background_state) {
- ss->execute(octx, *(kg->osl->background_state), *globals);
- }
-
- /* return background color immediately */
- if(globals->Ci)
- flatten_background_closure_tree(sd, globals->Ci);
+ /* setup shader globals from shader data */
+ OSLThreadData *tdata = kg->osl_tdata;
+ shaderdata_to_shaderglobals(kg, sd, state, path_flag, tdata);
+
+ /* execute shader for this point */
+ OSL::ShadingSystem *ss = (OSL::ShadingSystem *)kg->osl_ss;
+ OSL::ShaderGlobals *globals = &tdata->globals;
+ OSL::ShadingContext *octx = tdata->context;
+
+ if (kg->osl->background_state) {
+ ss->execute(octx, *(kg->osl->background_state), *globals);
+ }
+
+ /* return background color immediately */
+ if (globals->Ci)
+ flatten_background_closure_tree(sd, globals->Ci);
}
/* Volume */
@@ -296,112 +301,117 @@ static void flatten_volume_closure_tree(ShaderData *sd,
const OSL::ClosureColor *closure,
float3 weight = make_float3(1.0f, 1.0f, 1.0f))
{
- /* OSL gives us a closure tree, we flatten it into arrays per
- * closure type, for evaluation, sampling, etc later on. */
-
- switch(closure->id) {
- case OSL::ClosureColor::MUL: {
- OSL::ClosureMul *mul = (OSL::ClosureMul *)closure;
- flatten_volume_closure_tree(sd, mul->closure, TO_FLOAT3(mul->weight) * weight);
- break;
- }
- case OSL::ClosureColor::ADD: {
- OSL::ClosureAdd *add = (OSL::ClosureAdd *)closure;
- flatten_volume_closure_tree(sd, add->closureA, weight);
- flatten_volume_closure_tree(sd, add->closureB, weight);
- break;
- }
- default: {
- OSL::ClosureComponent *comp = (OSL::ClosureComponent *)closure;
- CClosurePrimitive *prim = (CClosurePrimitive *)comp->data();
-
- if(prim) {
+ /* OSL gives us a closure tree, we flatten it into arrays per
+ * closure type, for evaluation, sampling, etc later on. */
+
+ switch (closure->id) {
+ case OSL::ClosureColor::MUL: {
+ OSL::ClosureMul *mul = (OSL::ClosureMul *)closure;
+ flatten_volume_closure_tree(sd, mul->closure, TO_FLOAT3(mul->weight) * weight);
+ break;
+ }
+ case OSL::ClosureColor::ADD: {
+ OSL::ClosureAdd *add = (OSL::ClosureAdd *)closure;
+ flatten_volume_closure_tree(sd, add->closureA, weight);
+ flatten_volume_closure_tree(sd, add->closureB, weight);
+ break;
+ }
+ default: {
+ OSL::ClosureComponent *comp = (OSL::ClosureComponent *)closure;
+ CClosurePrimitive *prim = (CClosurePrimitive *)comp->data();
+
+ if (prim) {
#ifdef OSL_SUPPORTS_WEIGHTED_CLOSURE_COMPONENTS
- weight = weight*TO_FLOAT3(comp->w);
+ weight = weight * TO_FLOAT3(comp->w);
#endif
- prim->setup(sd, 0, weight);
- }
- }
- }
+ prim->setup(sd, 0, weight);
+ }
+ }
+ }
}
void OSLShader::eval_volume(KernelGlobals *kg, ShaderData *sd, PathState *state, int path_flag)
{
- /* setup shader globals from shader data */
- OSLThreadData *tdata = kg->osl_tdata;
- shaderdata_to_shaderglobals(kg, sd, state, path_flag, tdata);
-
- /* execute shader */
- OSL::ShadingSystem *ss = (OSL::ShadingSystem*)kg->osl_ss;
- OSL::ShaderGlobals *globals = &tdata->globals;
- OSL::ShadingContext *octx = tdata->context;
- int shader = sd->shader & SHADER_MASK;
-
- if(kg->osl->volume_state[shader]) {
- ss->execute(octx, *(kg->osl->volume_state[shader]), *globals);
- }
-
- /* flatten closure tree */
- if(globals->Ci)
- flatten_volume_closure_tree(sd, globals->Ci);
+ /* setup shader globals from shader data */
+ OSLThreadData *tdata = kg->osl_tdata;
+ shaderdata_to_shaderglobals(kg, sd, state, path_flag, tdata);
+
+ /* execute shader */
+ OSL::ShadingSystem *ss = (OSL::ShadingSystem *)kg->osl_ss;
+ OSL::ShaderGlobals *globals = &tdata->globals;
+ OSL::ShadingContext *octx = tdata->context;
+ int shader = sd->shader & SHADER_MASK;
+
+ if (kg->osl->volume_state[shader]) {
+ ss->execute(octx, *(kg->osl->volume_state[shader]), *globals);
+ }
+
+ /* flatten closure tree */
+ if (globals->Ci)
+ flatten_volume_closure_tree(sd, globals->Ci);
}
/* Displacement */
void OSLShader::eval_displacement(KernelGlobals *kg, ShaderData *sd, PathState *state)
{
- /* setup shader globals from shader data */
- OSLThreadData *tdata = kg->osl_tdata;
+ /* setup shader globals from shader data */
+ OSLThreadData *tdata = kg->osl_tdata;
- shaderdata_to_shaderglobals(kg, sd, state, 0, tdata);
+ shaderdata_to_shaderglobals(kg, sd, state, 0, tdata);
- /* execute shader */
- OSL::ShadingSystem *ss = (OSL::ShadingSystem*)kg->osl_ss;
- OSL::ShaderGlobals *globals = &tdata->globals;
- OSL::ShadingContext *octx = tdata->context;
- int shader = sd->shader & SHADER_MASK;
+ /* execute shader */
+ OSL::ShadingSystem *ss = (OSL::ShadingSystem *)kg->osl_ss;
+ OSL::ShaderGlobals *globals = &tdata->globals;
+ OSL::ShadingContext *octx = tdata->context;
+ int shader = sd->shader & SHADER_MASK;
- if(kg->osl->displacement_state[shader]) {
- ss->execute(octx, *(kg->osl->displacement_state[shader]), *globals);
- }
+ if (kg->osl->displacement_state[shader]) {
+ ss->execute(octx, *(kg->osl->displacement_state[shader]), *globals);
+ }
- /* get back position */
- sd->P = TO_FLOAT3(globals->P);
+ /* get back position */
+ sd->P = TO_FLOAT3(globals->P);
}
/* Attributes */
-int OSLShader::find_attribute(KernelGlobals *kg, const ShaderData *sd, uint id, AttributeDescriptor *desc)
+int OSLShader::find_attribute(KernelGlobals *kg,
+ const ShaderData *sd,
+ uint id,
+ AttributeDescriptor *desc)
{
- /* for OSL, a hash map is used to lookup the attribute by name. */
- int object = sd->object*ATTR_PRIM_TYPES;
+ /* for OSL, a hash map is used to lookup the attribute by name. */
+ int object = sd->object * ATTR_PRIM_TYPES;
#ifdef __HAIR__
- if(sd->type & PRIMITIVE_ALL_CURVE) object += ATTR_PRIM_CURVE;
+ if (sd->type & PRIMITIVE_ALL_CURVE)
+ object += ATTR_PRIM_CURVE;
#endif
- OSLGlobals::AttributeMap &attr_map = kg->osl->attribute_map[object];
- ustring stdname(std::string("geom:") + std::string(Attribute::standard_name((AttributeStandard)id)));
- OSLGlobals::AttributeMap::const_iterator it = attr_map.find(stdname);
-
- if(it != attr_map.end()) {
- const OSLGlobals::Attribute &osl_attr = it->second;
- *desc = osl_attr.desc;
-
- if(sd->prim == PRIM_NONE && (AttributeElement)osl_attr.desc.element != ATTR_ELEMENT_MESH) {
- desc->offset = ATTR_STD_NOT_FOUND;
- return ATTR_STD_NOT_FOUND;
- }
-
- /* return result */
- if(osl_attr.desc.element == ATTR_ELEMENT_NONE) {
- desc->offset = ATTR_STD_NOT_FOUND;
- }
- return desc->offset;
- }
- else {
- desc->offset = ATTR_STD_NOT_FOUND;
- return (int)ATTR_STD_NOT_FOUND;
- }
+ OSLGlobals::AttributeMap &attr_map = kg->osl->attribute_map[object];
+ ustring stdname(std::string("geom:") +
+ std::string(Attribute::standard_name((AttributeStandard)id)));
+ OSLGlobals::AttributeMap::const_iterator it = attr_map.find(stdname);
+
+ if (it != attr_map.end()) {
+ const OSLGlobals::Attribute &osl_attr = it->second;
+ *desc = osl_attr.desc;
+
+ if (sd->prim == PRIM_NONE && (AttributeElement)osl_attr.desc.element != ATTR_ELEMENT_MESH) {
+ desc->offset = ATTR_STD_NOT_FOUND;
+ return ATTR_STD_NOT_FOUND;
+ }
+
+ /* return result */
+ if (osl_attr.desc.element == ATTR_ELEMENT_NONE) {
+ desc->offset = ATTR_STD_NOT_FOUND;
+ }
+ return desc->offset;
+ }
+ else {
+ desc->offset = ATTR_STD_NOT_FOUND;
+ return (int)ATTR_STD_NOT_FOUND;
+ }
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/osl/osl_shader.h b/intern/cycles/kernel/osl/osl_shader.h
index 9824f966a44..a4fa24d0a90 100644
--- a/intern/cycles/kernel/osl/osl_shader.h
+++ b/intern/cycles/kernel/osl/osl_shader.h
@@ -29,7 +29,7 @@
* This means no thread state must be passed along in the kernel itself.
*/
-#include "kernel/kernel_types.h"
+# include "kernel/kernel_types.h"
CCL_NAMESPACE_BEGIN
@@ -44,26 +44,31 @@ struct OSLGlobals;
struct OSLShadingSystem;
class OSLShader {
-public:
- /* init */
- static void register_closures(OSLShadingSystem *ss);
+ public:
+ /* init */
+ static void register_closures(OSLShadingSystem *ss);
- /* per thread data */
- static void thread_init(KernelGlobals *kg, KernelGlobals *kernel_globals, OSLGlobals *osl_globals);
- static void thread_free(KernelGlobals *kg);
+ /* per thread data */
+ static void thread_init(KernelGlobals *kg,
+ KernelGlobals *kernel_globals,
+ OSLGlobals *osl_globals);
+ static void thread_free(KernelGlobals *kg);
- /* eval */
- static void eval_surface(KernelGlobals *kg, ShaderData *sd, PathState *state, int path_flag);
- static void eval_background(KernelGlobals *kg, ShaderData *sd, PathState *state, int path_flag);
- static void eval_volume(KernelGlobals *kg, ShaderData *sd, PathState *state, int path_flag);
- static void eval_displacement(KernelGlobals *kg, ShaderData *sd, PathState *state);
+ /* eval */
+ static void eval_surface(KernelGlobals *kg, ShaderData *sd, PathState *state, int path_flag);
+ static void eval_background(KernelGlobals *kg, ShaderData *sd, PathState *state, int path_flag);
+ static void eval_volume(KernelGlobals *kg, ShaderData *sd, PathState *state, int path_flag);
+ static void eval_displacement(KernelGlobals *kg, ShaderData *sd, PathState *state);
- /* attributes */
- static int find_attribute(KernelGlobals *kg, const ShaderData *sd, uint id, AttributeDescriptor *desc);
+ /* attributes */
+ static int find_attribute(KernelGlobals *kg,
+ const ShaderData *sd,
+ uint id,
+ AttributeDescriptor *desc);
};
CCL_NAMESPACE_END
#endif
-#endif /* __OSL_SHADER_H__ */
+#endif /* __OSL_SHADER_H__ */
diff --git a/intern/cycles/kernel/shaders/CMakeLists.txt b/intern/cycles/kernel/shaders/CMakeLists.txt
index 4740db27d4e..b42b9b2fe64 100644
--- a/intern/cycles/kernel/shaders/CMakeLists.txt
+++ b/intern/cycles/kernel/shaders/CMakeLists.txt
@@ -2,102 +2,102 @@
# OSL node shaders
set(SRC_OSL
- node_add_closure.osl
- node_ambient_occlusion.osl
- node_anisotropic_bsdf.osl
- node_attribute.osl
- node_background.osl
- node_bevel.osl
- node_brick_texture.osl
- node_brightness.osl
- node_bump.osl
- node_camera.osl
- node_checker_texture.osl
- node_combine_rgb.osl
- node_combine_hsv.osl
- node_combine_xyz.osl
- node_convert_from_color.osl
- node_convert_from_float.osl
- node_convert_from_int.osl
- node_convert_from_normal.osl
- node_convert_from_point.osl
- node_convert_from_vector.osl
- node_diffuse_bsdf.osl
- node_displacement.osl
- node_vector_displacement.osl
- node_emission.osl
- node_environment_texture.osl
- node_fresnel.osl
- node_gamma.osl
- node_geometry.osl
- node_glass_bsdf.osl
- node_glossy_bsdf.osl
- node_gradient_texture.osl
- node_hair_info.osl
- node_scatter_volume.osl
- node_absorption_volume.osl
- node_principled_volume.osl
- node_holdout.osl
- node_hsv.osl
- node_ies_light.osl
- node_image_texture.osl
- node_invert.osl
- node_layer_weight.osl
- node_light_falloff.osl
- node_light_path.osl
- node_magic_texture.osl
- node_mapping.osl
- node_math.osl
- node_mix.osl
- node_mix_closure.osl
- node_musgrave_texture.osl
- node_noise_texture.osl
- node_normal.osl
- node_normal_map.osl
- node_object_info.osl
- node_output_displacement.osl
- node_output_surface.osl
- node_output_volume.osl
- node_particle_info.osl
- node_refraction_bsdf.osl
- node_rgb_curves.osl
- node_rgb_ramp.osl
- node_separate_rgb.osl
- node_separate_hsv.osl
- node_separate_xyz.osl
- node_set_normal.osl
- node_sky_texture.osl
- node_subsurface_scattering.osl
- node_tangent.osl
- node_texture_coordinate.osl
- node_toon_bsdf.osl
- node_translucent_bsdf.osl
- node_transparent_bsdf.osl
- node_value.osl
- node_vector_curves.osl
- node_vector_math.osl
- node_vector_transform.osl
- node_velvet_bsdf.osl
- node_voronoi_texture.osl
- node_voxel_texture.osl
- node_wavelength.osl
- node_blackbody.osl
- node_wave_texture.osl
- node_wireframe.osl
- node_hair_bsdf.osl
- node_principled_hair_bsdf.osl
- node_uv_map.osl
- node_principled_bsdf.osl
- node_rgb_to_bw.osl
+ node_add_closure.osl
+ node_ambient_occlusion.osl
+ node_anisotropic_bsdf.osl
+ node_attribute.osl
+ node_background.osl
+ node_bevel.osl
+ node_brick_texture.osl
+ node_brightness.osl
+ node_bump.osl
+ node_camera.osl
+ node_checker_texture.osl
+ node_combine_rgb.osl
+ node_combine_hsv.osl
+ node_combine_xyz.osl
+ node_convert_from_color.osl
+ node_convert_from_float.osl
+ node_convert_from_int.osl
+ node_convert_from_normal.osl
+ node_convert_from_point.osl
+ node_convert_from_vector.osl
+ node_diffuse_bsdf.osl
+ node_displacement.osl
+ node_vector_displacement.osl
+ node_emission.osl
+ node_environment_texture.osl
+ node_fresnel.osl
+ node_gamma.osl
+ node_geometry.osl
+ node_glass_bsdf.osl
+ node_glossy_bsdf.osl
+ node_gradient_texture.osl
+ node_hair_info.osl
+ node_scatter_volume.osl
+ node_absorption_volume.osl
+ node_principled_volume.osl
+ node_holdout.osl
+ node_hsv.osl
+ node_ies_light.osl
+ node_image_texture.osl
+ node_invert.osl
+ node_layer_weight.osl
+ node_light_falloff.osl
+ node_light_path.osl
+ node_magic_texture.osl
+ node_mapping.osl
+ node_math.osl
+ node_mix.osl
+ node_mix_closure.osl
+ node_musgrave_texture.osl
+ node_noise_texture.osl
+ node_normal.osl
+ node_normal_map.osl
+ node_object_info.osl
+ node_output_displacement.osl
+ node_output_surface.osl
+ node_output_volume.osl
+ node_particle_info.osl
+ node_refraction_bsdf.osl
+ node_rgb_curves.osl
+ node_rgb_ramp.osl
+ node_separate_rgb.osl
+ node_separate_hsv.osl
+ node_separate_xyz.osl
+ node_set_normal.osl
+ node_sky_texture.osl
+ node_subsurface_scattering.osl
+ node_tangent.osl
+ node_texture_coordinate.osl
+ node_toon_bsdf.osl
+ node_translucent_bsdf.osl
+ node_transparent_bsdf.osl
+ node_value.osl
+ node_vector_curves.osl
+ node_vector_math.osl
+ node_vector_transform.osl
+ node_velvet_bsdf.osl
+ node_voronoi_texture.osl
+ node_voxel_texture.osl
+ node_wavelength.osl
+ node_blackbody.osl
+ node_wave_texture.osl
+ node_wireframe.osl
+ node_hair_bsdf.osl
+ node_principled_hair_bsdf.osl
+ node_uv_map.osl
+ node_principled_bsdf.osl
+ node_rgb_to_bw.osl
)
set(SRC_OSL_HEADERS
- node_color.h
- node_fresnel.h
- node_ramp_util.h
- node_texture.h
- stdosl.h
- oslutil.h
+ node_color.h
+ node_fresnel.h
+ node_ramp_util.h
+ node_texture.h
+ stdosl.h
+ oslutil.h
)
set(SRC_OSO
@@ -106,20 +106,20 @@ set(SRC_OSO
# TODO, add a module to compile OSL
foreach(_file ${SRC_OSL})
- set(_OSL_FILE ${CMAKE_CURRENT_SOURCE_DIR}/${_file})
- set_source_files_properties(${_file} PROPERTIES HEADER_FILE_ONLY TRUE)
- string(REPLACE ".osl" ".oso" _OSO_FILE ${_OSL_FILE})
- string(REPLACE ${CMAKE_SOURCE_DIR} ${CMAKE_BINARY_DIR} _OSO_FILE ${_OSO_FILE})
- add_custom_command(
- OUTPUT ${_OSO_FILE}
- COMMAND ${OSL_COMPILER} -q -O2 -I"${CMAKE_CURRENT_SOURCE_DIR}" -o ${_OSO_FILE} ${_OSL_FILE}
- DEPENDS ${_OSL_FILE} ${SRC_OSL_HEADERS} ${OSL_COMPILER})
- list(APPEND SRC_OSO
- ${_OSO_FILE}
- )
+ set(_OSL_FILE ${CMAKE_CURRENT_SOURCE_DIR}/${_file})
+ set_source_files_properties(${_file} PROPERTIES HEADER_FILE_ONLY TRUE)
+ string(REPLACE ".osl" ".oso" _OSO_FILE ${_OSL_FILE})
+ string(REPLACE ${CMAKE_SOURCE_DIR} ${CMAKE_BINARY_DIR} _OSO_FILE ${_OSO_FILE})
+ add_custom_command(
+ OUTPUT ${_OSO_FILE}
+ COMMAND ${OSL_COMPILER} -q -O2 -I"${CMAKE_CURRENT_SOURCE_DIR}" -o ${_OSO_FILE} ${_OSL_FILE}
+ DEPENDS ${_OSL_FILE} ${SRC_OSL_HEADERS} ${OSL_COMPILER})
+ list(APPEND SRC_OSO
+ ${_OSO_FILE}
+ )
- unset(_OSL_FILE)
- unset(_OSO_FILE)
+ unset(_OSL_FILE)
+ unset(_OSO_FILE)
endforeach()
add_custom_target(cycles_osl_shaders ALL DEPENDS ${SRC_OSO} ${SRC_OSL_HEADERS} ${OSL_COMPILER} SOURCES ${SRC_OSL})
diff --git a/intern/cycles/kernel/shaders/node_absorption_volume.osl b/intern/cycles/kernel/shaders/node_absorption_volume.osl
index 18f662ebbbd..e99bd254666 100644
--- a/intern/cycles/kernel/shaders/node_absorption_volume.osl
+++ b/intern/cycles/kernel/shaders/node_absorption_volume.osl
@@ -16,11 +16,9 @@
#include "stdosl.h"
-shader node_absorption_volume(
- color Color = color(0.8, 0.8, 0.8),
- float Density = 1.0,
- output closure color Volume = 0)
+shader node_absorption_volume(color Color = color(0.8, 0.8, 0.8),
+ float Density = 1.0,
+ output closure color Volume = 0)
{
- Volume = ((color(1.0, 1.0, 1.0) - Color) * max(Density, 0.0)) * absorption();
+ Volume = ((color(1.0, 1.0, 1.0) - Color) * max(Density, 0.0)) * absorption();
}
-
diff --git a/intern/cycles/kernel/shaders/node_add_closure.osl b/intern/cycles/kernel/shaders/node_add_closure.osl
index b6596e0b6bd..077e2735e61 100644
--- a/intern/cycles/kernel/shaders/node_add_closure.osl
+++ b/intern/cycles/kernel/shaders/node_add_closure.osl
@@ -16,11 +16,9 @@
#include "stdosl.h"
-shader node_add_closure(
- closure color Closure1 = 0,
- closure color Closure2 = 0,
- output closure color Closure = 0)
+shader node_add_closure(closure color Closure1 = 0,
+ closure color Closure2 = 0,
+ output closure color Closure = 0)
{
- Closure = Closure1 + Closure2;
+ Closure = Closure1 + Closure2;
}
-
diff --git a/intern/cycles/kernel/shaders/node_ambient_occlusion.osl b/intern/cycles/kernel/shaders/node_ambient_occlusion.osl
index 825cccd59ce..7bf28719e78 100644
--- a/intern/cycles/kernel/shaders/node_ambient_occlusion.osl
+++ b/intern/cycles/kernel/shaders/node_ambient_occlusion.osl
@@ -16,20 +16,28 @@
#include "stdosl.h"
-shader node_ambient_occlusion(
- color ColorIn = color(1.0, 1.0, 1.0),
- int samples = 16,
- float Distance = 1.0,
- normal Normal = N,
- int inside = 0,
- int only_local = 0,
- output color ColorOut = color(1.0, 1.0, 1.0),
- output float AO = 1.0)
+shader node_ambient_occlusion(color ColorIn = color(1.0, 1.0, 1.0),
+ int samples = 16,
+ float Distance = 1.0,
+ normal Normal = N,
+ int inside = 0,
+ int only_local = 0,
+ output color ColorOut = color(1.0, 1.0, 1.0),
+ output float AO = 1.0)
{
- int global_radius = (Distance == 0.0 && !isconnected(Distance));
+ int global_radius = (Distance == 0.0 && !isconnected(Distance));
- /* Abuse texture call with special @ao token. */
- AO = texture("@ao", samples, Distance, Normal[0], Normal[1], Normal[2], inside, "sblur", only_local, "tblur", global_radius);
- ColorOut = ColorIn * AO;
+ /* Abuse texture call with special @ao token. */
+ AO = texture("@ao",
+ samples,
+ Distance,
+ Normal[0],
+ Normal[1],
+ Normal[2],
+ inside,
+ "sblur",
+ only_local,
+ "tblur",
+ global_radius);
+ ColorOut = ColorIn * AO;
}
-
diff --git a/intern/cycles/kernel/shaders/node_anisotropic_bsdf.osl b/intern/cycles/kernel/shaders/node_anisotropic_bsdf.osl
index 21e28ece65d..165c09eb8e0 100644
--- a/intern/cycles/kernel/shaders/node_anisotropic_bsdf.osl
+++ b/intern/cycles/kernel/shaders/node_anisotropic_bsdf.osl
@@ -16,45 +16,43 @@
#include "stdosl.h"
-shader node_anisotropic_bsdf(
- color Color = 0.0,
- string distribution = "GGX",
- float Roughness = 0.0,
- float Anisotropy = 0.0,
- float Rotation = 0.0,
- normal Normal = N,
- normal Tangent = normalize(dPdu),
- output closure color BSDF = 0)
+shader node_anisotropic_bsdf(color Color = 0.0,
+ string distribution = "GGX",
+ float Roughness = 0.0,
+ float Anisotropy = 0.0,
+ float Rotation = 0.0,
+ normal Normal = N,
+ normal Tangent = normalize(dPdu),
+ output closure color BSDF = 0)
{
- /* rotate tangent around normal */
- vector T = Tangent;
+ /* rotate tangent around normal */
+ vector T = Tangent;
- if (Rotation != 0.0)
- T = rotate(T, Rotation * M_2PI, point(0.0, 0.0, 0.0), Normal);
+ if (Rotation != 0.0)
+ T = rotate(T, Rotation * M_2PI, point(0.0, 0.0, 0.0), Normal);
- /* compute roughness */
- float roughness = Roughness * Roughness;
- float roughness_u, roughness_v;
- float aniso = clamp(Anisotropy, -0.99, 0.99);
+ /* compute roughness */
+ float roughness = Roughness * Roughness;
+ float roughness_u, roughness_v;
+ float aniso = clamp(Anisotropy, -0.99, 0.99);
- if (aniso < 0.0) {
- roughness_u = roughness / (1.0 + aniso);
- roughness_v = roughness * (1.0 + aniso);
- }
- else {
- roughness_u = roughness * (1.0 - aniso);
- roughness_v = roughness / (1.0 - aniso);
- }
+ if (aniso < 0.0) {
+ roughness_u = roughness / (1.0 + aniso);
+ roughness_v = roughness * (1.0 + aniso);
+ }
+ else {
+ roughness_u = roughness * (1.0 - aniso);
+ roughness_v = roughness / (1.0 - aniso);
+ }
- if (distribution == "sharp")
- BSDF = Color * reflection(Normal);
- else if (distribution == "beckmann")
- BSDF = Color * microfacet_beckmann_aniso(Normal, T, roughness_u, roughness_v);
- else if (distribution == "GGX")
- BSDF = Color * microfacet_ggx_aniso(Normal, T, roughness_u, roughness_v);
- else if (distribution == "Multiscatter GGX")
- BSDF = Color * microfacet_multi_ggx_aniso(Normal, T, roughness_u, roughness_v, Color);
- else
- BSDF = Color * ashikhmin_shirley(Normal, T, roughness_u, roughness_v);
+ if (distribution == "sharp")
+ BSDF = Color * reflection(Normal);
+ else if (distribution == "beckmann")
+ BSDF = Color * microfacet_beckmann_aniso(Normal, T, roughness_u, roughness_v);
+ else if (distribution == "GGX")
+ BSDF = Color * microfacet_ggx_aniso(Normal, T, roughness_u, roughness_v);
+ else if (distribution == "Multiscatter GGX")
+ BSDF = Color * microfacet_multi_ggx_aniso(Normal, T, roughness_u, roughness_v, Color);
+ else
+ BSDF = Color * ashikhmin_shirley(Normal, T, roughness_u, roughness_v);
}
-
diff --git a/intern/cycles/kernel/shaders/node_attribute.osl b/intern/cycles/kernel/shaders/node_attribute.osl
index 67183e9ffe0..336543cc130 100644
--- a/intern/cycles/kernel/shaders/node_attribute.osl
+++ b/intern/cycles/kernel/shaders/node_attribute.osl
@@ -16,26 +16,24 @@
#include "stdosl.h"
-shader node_attribute(
- string bump_offset = "center",
- string name = "",
- output point Vector = point(0.0, 0.0, 0.0),
- output color Color = 0.0,
- output float Fac = 0.0)
+shader node_attribute(string bump_offset = "center",
+ string name = "",
+ output point Vector = point(0.0, 0.0, 0.0),
+ output color Color = 0.0,
+ output float Fac = 0.0)
{
- getattribute(name, Color);
- Vector = point(Color);
- getattribute(name, Fac);
+ getattribute(name, Color);
+ Vector = point(Color);
+ getattribute(name, Fac);
- if (bump_offset == "dx") {
- Color += Dx(Color);
- Vector += Dx(Vector);
- Fac += Dx(Fac);
- }
- else if (bump_offset == "dy") {
- Color += Dy(Color);
- Vector += Dy(Vector);
- Fac += Dy(Fac);
- }
+ if (bump_offset == "dx") {
+ Color += Dx(Color);
+ Vector += Dx(Vector);
+ Fac += Dx(Fac);
+ }
+ else if (bump_offset == "dy") {
+ Color += Dy(Color);
+ Vector += Dy(Vector);
+ Fac += Dy(Fac);
+ }
}
-
diff --git a/intern/cycles/kernel/shaders/node_background.osl b/intern/cycles/kernel/shaders/node_background.osl
index 613d4e360fa..6ded0d2c65c 100644
--- a/intern/cycles/kernel/shaders/node_background.osl
+++ b/intern/cycles/kernel/shaders/node_background.osl
@@ -16,11 +16,9 @@
#include "stdosl.h"
-shader node_background(
- color Color = 0.8,
- float Strength = 1.0,
- output closure color Background = 0)
+shader node_background(color Color = 0.8,
+ float Strength = 1.0,
+ output closure color Background = 0)
{
- Background = Color * Strength * background();
+ Background = Color * Strength * background();
}
-
diff --git a/intern/cycles/kernel/shaders/node_bevel.osl b/intern/cycles/kernel/shaders/node_bevel.osl
index 9c4ca15be17..189c20c52e7 100644
--- a/intern/cycles/kernel/shaders/node_bevel.osl
+++ b/intern/cycles/kernel/shaders/node_bevel.osl
@@ -16,16 +16,14 @@
#include "stdosl.h"
-shader node_bevel(
- int samples = 4,
- float Radius = 0.05,
- normal NormalIn = N,
- output normal NormalOut = N)
+shader node_bevel(int samples = 4,
+ float Radius = 0.05,
+ normal NormalIn = N,
+ output normal NormalOut = N)
{
- /* Abuse texture call with special @bevel token. */
- vector bevel_N = (normal)(color)texture("@bevel", samples, Radius);
+ /* Abuse texture call with special @bevel token. */
+ vector bevel_N = (normal)(color)texture("@bevel", samples, Radius);
- /* Preserve input normal. */
- NormalOut = normalize(NormalIn + (bevel_N - N));
+ /* Preserve input normal. */
+ NormalOut = normalize(NormalIn + (bevel_N - N));
}
-
diff --git a/intern/cycles/kernel/shaders/node_blackbody.osl b/intern/cycles/kernel/shaders/node_blackbody.osl
index 1da6894d0f0..8a24bf1e28b 100644
--- a/intern/cycles/kernel/shaders/node_blackbody.osl
+++ b/intern/cycles/kernel/shaders/node_blackbody.osl
@@ -16,16 +16,13 @@
#include "stdosl.h"
-shader node_blackbody(
- float Temperature = 1200.0,
- output color Color = 0.0)
+shader node_blackbody(float Temperature = 1200.0, output color Color = 0.0)
{
- color rgb = blackbody(Temperature);
-
- /* Scale by luminance */
- float l = luminance(rgb);
- if (l != 0.0)
- rgb /= l;
- Color = rgb;
-}
+ color rgb = blackbody(Temperature);
+ /* Scale by luminance */
+ float l = luminance(rgb);
+ if (l != 0.0)
+ rgb /= l;
+ Color = rgb;
+}
diff --git a/intern/cycles/kernel/shaders/node_brick_texture.osl b/intern/cycles/kernel/shaders/node_brick_texture.osl
index 9d2e5b74ce6..0abc3574c48 100644
--- a/intern/cycles/kernel/shaders/node_brick_texture.osl
+++ b/intern/cycles/kernel/shaders/node_brick_texture.osl
@@ -21,85 +21,100 @@
float brick_noise(int ns) /* fast integer noise */
{
- int nn;
- int n = (ns + 1013) & 2147483647;
- n = (n >> 13) ^ n;
- nn = (n * (n * n * 60493 + 19990303) + 1376312589) & 2147483647;
- return 0.5 * ((float)nn / 1073741824.0);
+ int nn;
+ int n = (ns + 1013) & 2147483647;
+ n = (n >> 13) ^ n;
+ nn = (n * (n * n * 60493 + 19990303) + 1376312589) & 2147483647;
+ return 0.5 * ((float)nn / 1073741824.0);
}
-float brick(point p, float mortar_size, float mortar_smooth, float bias,
- float BrickWidth, float row_height, float offset_amount, int offset_frequency,
- float squash_amount, int squash_frequency, output float tint)
+float brick(point p,
+ float mortar_size,
+ float mortar_smooth,
+ float bias,
+ float BrickWidth,
+ float row_height,
+ float offset_amount,
+ int offset_frequency,
+ float squash_amount,
+ int squash_frequency,
+ output float tint)
{
- int bricknum, rownum;
- float offset = 0.0;
- float brick_width = BrickWidth;
- float x, y;
-
- rownum = (int)floor(p[1] / row_height);
-
- if (offset_frequency && squash_frequency) {
- brick_width *= (rownum % squash_frequency) ? 1.0 : squash_amount; /* squash */
- offset = (rownum % offset_frequency) ? 0.0 : (brick_width * offset_amount); /* offset */
- }
-
- bricknum = (int)floor((p[0] + offset) / brick_width);
-
- x = (p[0] + offset) - brick_width * bricknum;
- y = p[1] - row_height * rownum;
-
- tint = clamp((brick_noise((rownum << 16) + (bricknum & 65535)) + bias), 0.0, 1.0);
-
- float min_dist = min(min(x, y), min(brick_width - x, row_height - y));
- if(min_dist >= mortar_size) {
- return 0.0;
- }
- else if(mortar_smooth == 0.0) {
- return 1.0;
- }
- else {
- min_dist = 1.0 - min_dist/mortar_size;
- return smoothstep(0.0, mortar_smooth, min_dist);
- }
+ int bricknum, rownum;
+ float offset = 0.0;
+ float brick_width = BrickWidth;
+ float x, y;
+
+ rownum = (int)floor(p[1] / row_height);
+
+ if (offset_frequency && squash_frequency) {
+ brick_width *= (rownum % squash_frequency) ? 1.0 : squash_amount; /* squash */
+ offset = (rownum % offset_frequency) ? 0.0 : (brick_width * offset_amount); /* offset */
+ }
+
+ bricknum = (int)floor((p[0] + offset) / brick_width);
+
+ x = (p[0] + offset) - brick_width * bricknum;
+ y = p[1] - row_height * rownum;
+
+ tint = clamp((brick_noise((rownum << 16) + (bricknum & 65535)) + bias), 0.0, 1.0);
+
+ float min_dist = min(min(x, y), min(brick_width - x, row_height - y));
+ if (min_dist >= mortar_size) {
+ return 0.0;
+ }
+ else if (mortar_smooth == 0.0) {
+ return 1.0;
+ }
+ else {
+ min_dist = 1.0 - min_dist / mortar_size;
+ return smoothstep(0.0, mortar_smooth, min_dist);
+ }
}
-shader node_brick_texture(
- int use_mapping = 0,
- matrix mapping = matrix(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
- float offset = 0.5,
- int offset_frequency = 2,
- float squash = 1.0,
- int squash_frequency = 1,
- point Vector = P,
- color Color1 = 0.2,
- color Color2 = 0.8,
- color Mortar = 0.0,
- float Scale = 5.0,
- float MortarSize = 0.02,
- float MortarSmooth = 0.0,
- float Bias = 0.0,
- float BrickWidth = 0.5,
- float RowHeight = 0.25,
- output float Fac = 0.0,
- output color Color = 0.2)
+shader node_brick_texture(int use_mapping = 0,
+ matrix mapping = matrix(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
+ float offset = 0.5,
+ int offset_frequency = 2,
+ float squash = 1.0,
+ int squash_frequency = 1,
+ point Vector = P,
+ color Color1 = 0.2,
+ color Color2 = 0.8,
+ color Mortar = 0.0,
+ float Scale = 5.0,
+ float MortarSize = 0.02,
+ float MortarSmooth = 0.0,
+ float Bias = 0.0,
+ float BrickWidth = 0.5,
+ float RowHeight = 0.25,
+ output float Fac = 0.0,
+ output color Color = 0.2)
{
- point p = Vector;
-
- if (use_mapping)
- p = transform(mapping, p);
-
- float tint = 0.0;
- color Col = Color1;
-
- Fac = brick(p * Scale, MortarSize, MortarSmooth, Bias, BrickWidth, RowHeight,
- offset, offset_frequency, squash, squash_frequency, tint);
-
- if (Fac != 1.0) {
- float facm = 1.0 - tint;
- Col = facm * Color1 + tint * Color2;
- }
-
- Color = mix(Col, Mortar, Fac);
-}
+ point p = Vector;
+
+ if (use_mapping)
+ p = transform(mapping, p);
+
+ float tint = 0.0;
+ color Col = Color1;
+ Fac = brick(p * Scale,
+ MortarSize,
+ MortarSmooth,
+ Bias,
+ BrickWidth,
+ RowHeight,
+ offset,
+ offset_frequency,
+ squash,
+ squash_frequency,
+ tint);
+
+ if (Fac != 1.0) {
+ float facm = 1.0 - tint;
+ Col = facm * Color1 + tint * Color2;
+ }
+
+ Color = mix(Col, Mortar, Fac);
+}
diff --git a/intern/cycles/kernel/shaders/node_brightness.osl b/intern/cycles/kernel/shaders/node_brightness.osl
index 00cfb167885..2defbc4b1db 100644
--- a/intern/cycles/kernel/shaders/node_brightness.osl
+++ b/intern/cycles/kernel/shaders/node_brightness.osl
@@ -16,17 +16,15 @@
#include "stdosl.h"
-shader node_brightness(
- color ColorIn = 0.8,
- float Bright = 0.0,
- float Contrast = 0.0,
- output color ColorOut = 0.8)
+shader node_brightness(color ColorIn = 0.8,
+ float Bright = 0.0,
+ float Contrast = 0.0,
+ output color ColorOut = 0.8)
{
- float a = 1.0 + Contrast;
- float b = Bright - Contrast * 0.5;
+ float a = 1.0 + Contrast;
+ float b = Bright - Contrast * 0.5;
- ColorOut[0] = max(a * ColorIn[0] + b, 0.0);
- ColorOut[1] = max(a * ColorIn[1] + b, 0.0);
- ColorOut[2] = max(a * ColorIn[2] + b, 0.0);
+ ColorOut[0] = max(a * ColorIn[0] + b, 0.0);
+ ColorOut[1] = max(a * ColorIn[1] + b, 0.0);
+ ColorOut[2] = max(a * ColorIn[2] + b, 0.0);
}
-
diff --git a/intern/cycles/kernel/shaders/node_bump.osl b/intern/cycles/kernel/shaders/node_bump.osl
index a2a4468d5f3..3697bb37fd9 100644
--- a/intern/cycles/kernel/shaders/node_bump.osl
+++ b/intern/cycles/kernel/shaders/node_bump.osl
@@ -19,52 +19,50 @@
/* "Bump Mapping Unparameterized Surfaces on the GPU"
* Morten S. Mikkelsen, 2010 */
-surface node_bump(
- int invert = 0,
- int use_object_space = 0,
- normal NormalIn = N,
- float Strength = 0.1,
- float Distance = 1.0,
- float SampleCenter = 0.0,
- float SampleX = 0.0,
- float SampleY = 0.0,
- output normal NormalOut = N)
+surface node_bump(int invert = 0,
+ int use_object_space = 0,
+ normal NormalIn = N,
+ float Strength = 0.1,
+ float Distance = 1.0,
+ float SampleCenter = 0.0,
+ float SampleX = 0.0,
+ float SampleY = 0.0,
+ output normal NormalOut = N)
{
- point Ptmp = P;
- normal Normal = NormalIn;
+ point Ptmp = P;
+ normal Normal = NormalIn;
- if (use_object_space) {
- Ptmp = transform("object", Ptmp);
- Normal = normalize(transform("object", Normal));
- }
+ if (use_object_space) {
+ Ptmp = transform("object", Ptmp);
+ Normal = normalize(transform("object", Normal));
+ }
- /* get surface tangents from normal */
- vector dPdx = Dx(Ptmp);
- vector dPdy = Dy(Ptmp);
+ /* get surface tangents from normal */
+ vector dPdx = Dx(Ptmp);
+ vector dPdy = Dy(Ptmp);
- vector Rx = cross(dPdy, Normal);
- vector Ry = cross(Normal, dPdx);
+ vector Rx = cross(dPdy, Normal);
+ vector Ry = cross(Normal, dPdx);
- /* compute surface gradient and determinant */
- float det = dot(dPdx, Rx);
- vector surfgrad = (SampleX - SampleCenter) * Rx + (SampleY - SampleCenter) * Ry;
+ /* compute surface gradient and determinant */
+ float det = dot(dPdx, Rx);
+ vector surfgrad = (SampleX - SampleCenter) * Rx + (SampleY - SampleCenter) * Ry;
- float absdet = fabs(det);
+ float absdet = fabs(det);
- float strength = max(Strength, 0.0);
- float dist = Distance;
+ float strength = max(Strength, 0.0);
+ float dist = Distance;
- if (invert)
- dist *= -1.0;
-
- /* compute and output perturbed normal */
- NormalOut = normalize(absdet * Normal - dist * sign(det) * surfgrad);
- NormalOut = normalize(strength * NormalOut + (1.0 - strength) * Normal);
+ if (invert)
+ dist *= -1.0;
- if (use_object_space) {
- NormalOut = normalize(transform("object", "world", NormalOut));
- }
+ /* compute and output perturbed normal */
+ NormalOut = normalize(absdet * Normal - dist * sign(det) * surfgrad);
+ NormalOut = normalize(strength * NormalOut + (1.0 - strength) * Normal);
- NormalOut = ensure_valid_reflection(Ng, I, NormalOut);
-}
+ if (use_object_space) {
+ NormalOut = normalize(transform("object", "world", NormalOut));
+ }
+ NormalOut = ensure_valid_reflection(Ng, I, NormalOut);
+}
diff --git a/intern/cycles/kernel/shaders/node_camera.osl b/intern/cycles/kernel/shaders/node_camera.osl
index 5e90cb8b8ee..833e9e775fe 100644
--- a/intern/cycles/kernel/shaders/node_camera.osl
+++ b/intern/cycles/kernel/shaders/node_camera.osl
@@ -16,16 +16,14 @@
#include "stdosl.h"
-shader node_camera(
- output vector ViewVector = vector(0.0, 0.0, 0.0),
- output float ViewZDepth = 0.0,
- output float ViewDistance = 0.0)
+shader node_camera(output vector ViewVector = vector(0.0, 0.0, 0.0),
+ output float ViewZDepth = 0.0,
+ output float ViewDistance = 0.0)
{
- ViewVector = (vector)transform("world", "camera", P);
+ ViewVector = (vector)transform("world", "camera", P);
- ViewZDepth = fabs(ViewVector[2]);
- ViewDistance = length(ViewVector);
+ ViewZDepth = fabs(ViewVector[2]);
+ ViewDistance = length(ViewVector);
- ViewVector = normalize(ViewVector);
+ ViewVector = normalize(ViewVector);
}
-
diff --git a/intern/cycles/kernel/shaders/node_checker_texture.osl b/intern/cycles/kernel/shaders/node_checker_texture.osl
index e745cfaee06..e068f7952ed 100644
--- a/intern/cycles/kernel/shaders/node_checker_texture.osl
+++ b/intern/cycles/kernel/shaders/node_checker_texture.osl
@@ -21,44 +21,43 @@
float checker(point ip)
{
- point p;
- p[0] = (ip[0] + 0.000001) * 0.999999;
- p[1] = (ip[1] + 0.000001) * 0.999999;
- p[2] = (ip[2] + 0.000001) * 0.999999;
-
- int xi = (int)fabs(floor(p[0]));
- int yi = (int)fabs(floor(p[1]));
- int zi = (int)fabs(floor(p[2]));
-
- if ((xi % 2 == yi % 2) == (zi % 2)) {
- return 1.0;
- }
- else {
- return 0.0;
- }
+ point p;
+ p[0] = (ip[0] + 0.000001) * 0.999999;
+ p[1] = (ip[1] + 0.000001) * 0.999999;
+ p[2] = (ip[2] + 0.000001) * 0.999999;
+
+ int xi = (int)fabs(floor(p[0]));
+ int yi = (int)fabs(floor(p[1]));
+ int zi = (int)fabs(floor(p[2]));
+
+ if ((xi % 2 == yi % 2) == (zi % 2)) {
+ return 1.0;
+ }
+ else {
+ return 0.0;
+ }
}
shader node_checker_texture(
- int use_mapping = 0,
- matrix mapping = matrix(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
- float Scale = 5.0,
- point Vector = P,
- color Color1 = 0.8,
- color Color2 = 0.2,
- output float Fac = 0.0,
- output color Color = 0.0)
+ int use_mapping = 0,
+ matrix mapping = matrix(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
+ float Scale = 5.0,
+ point Vector = P,
+ color Color1 = 0.8,
+ color Color2 = 0.2,
+ output float Fac = 0.0,
+ output color Color = 0.0)
{
- point p = Vector;
-
- if (use_mapping)
- p = transform(mapping, p);
-
- Fac = checker(p * Scale);
- if (Fac == 1.0) {
- Color = Color1;
- }
- else {
- Color = Color2;
- }
+ point p = Vector;
+
+ if (use_mapping)
+ p = transform(mapping, p);
+
+ Fac = checker(p * Scale);
+ if (Fac == 1.0) {
+ Color = Color1;
+ }
+ else {
+ Color = Color2;
+ }
}
-
diff --git a/intern/cycles/kernel/shaders/node_color.h b/intern/cycles/kernel/shaders/node_color.h
index fc758bef1fa..276c91843e8 100644
--- a/intern/cycles/kernel/shaders/node_color.h
+++ b/intern/cycles/kernel/shaders/node_color.h
@@ -18,135 +18,146 @@
float color_srgb_to_scene_linear(float c)
{
- if (c < 0.04045)
- return (c < 0.0) ? 0.0 : c * (1.0 / 12.92);
- else
- return pow((c + 0.055) * (1.0 / 1.055), 2.4);
+ if (c < 0.04045)
+ return (c < 0.0) ? 0.0 : c * (1.0 / 12.92);
+ else
+ return pow((c + 0.055) * (1.0 / 1.055), 2.4);
}
float color_scene_linear_to_srgb(float c)
{
- if (c < 0.0031308)
- return (c < 0.0) ? 0.0 : c * 12.92;
- else
- return 1.055 * pow(c, 1.0 / 2.4) - 0.055;
+ if (c < 0.0031308)
+ return (c < 0.0) ? 0.0 : c * 12.92;
+ else
+ return 1.055 * pow(c, 1.0 / 2.4) - 0.055;
}
color color_srgb_to_scene_linear(color c)
{
- return color(
- color_srgb_to_scene_linear(c[0]),
- color_srgb_to_scene_linear(c[1]),
- color_srgb_to_scene_linear(c[2]));
+ return color(color_srgb_to_scene_linear(c[0]),
+ color_srgb_to_scene_linear(c[1]),
+ color_srgb_to_scene_linear(c[2]));
}
color color_scene_linear_to_srgb(color c)
{
- return color(
- color_scene_linear_to_srgb(c[0]),
- color_scene_linear_to_srgb(c[1]),
- color_scene_linear_to_srgb(c[2]));
+ return color(color_scene_linear_to_srgb(c[0]),
+ color_scene_linear_to_srgb(c[1]),
+ color_scene_linear_to_srgb(c[2]));
}
color color_unpremultiply(color c, float alpha)
{
- if (alpha != 1.0 && alpha != 0.0)
- return c / alpha;
+ if (alpha != 1.0 && alpha != 0.0)
+ return c / alpha;
- return c;
+ return c;
}
/* Color Operations */
color xyY_to_xyz(float x, float y, float Y)
{
- float X, Z;
+ float X, Z;
- if (y != 0.0) X = (x / y) * Y;
- else X = 0.0;
+ if (y != 0.0)
+ X = (x / y) * Y;
+ else
+ X = 0.0;
- if (y != 0.0 && Y != 0.0) Z = ((1.0 - x - y) / y) * Y;
- else Z = 0.0;
+ if (y != 0.0 && Y != 0.0)
+ Z = ((1.0 - x - y) / y) * Y;
+ else
+ Z = 0.0;
- return color(X, Y, Z);
+ return color(X, Y, Z);
}
color xyz_to_rgb(float x, float y, float z)
{
- return color( 3.240479 * x + -1.537150 * y + -0.498535 * z,
- -0.969256 * x + 1.875991 * y + 0.041556 * z,
- 0.055648 * x + -0.204043 * y + 1.057311 * z);
+ return color(3.240479 * x + -1.537150 * y + -0.498535 * z,
+ -0.969256 * x + 1.875991 * y + 0.041556 * z,
+ 0.055648 * x + -0.204043 * y + 1.057311 * z);
}
color rgb_to_hsv(color rgb)
{
- float cmax, cmin, h, s, v, cdelta;
- color c;
-
- cmax = max(rgb[0], max(rgb[1], rgb[2]));
- cmin = min(rgb[0], min(rgb[1], rgb[2]));
- cdelta = cmax - cmin;
-
- v = cmax;
-
- if (cmax != 0.0) {
- s = cdelta / cmax;
- }
- else {
- s = 0.0;
- h = 0.0;
- }
-
- if (s == 0.0) {
- h = 0.0;
- }
- else {
- c = (color(cmax, cmax, cmax) - rgb) / cdelta;
-
- if (rgb[0] == cmax) h = c[2] - c[1];
- else if (rgb[1] == cmax) h = 2.0 + c[0] - c[2];
- else h = 4.0 + c[1] - c[0];
-
- h /= 6.0;
-
- if (h < 0.0)
- h += 1.0;
- }
-
- return color(h, s, v);
+ float cmax, cmin, h, s, v, cdelta;
+ color c;
+
+ cmax = max(rgb[0], max(rgb[1], rgb[2]));
+ cmin = min(rgb[0], min(rgb[1], rgb[2]));
+ cdelta = cmax - cmin;
+
+ v = cmax;
+
+ if (cmax != 0.0) {
+ s = cdelta / cmax;
+ }
+ else {
+ s = 0.0;
+ h = 0.0;
+ }
+
+ if (s == 0.0) {
+ h = 0.0;
+ }
+ else {
+ c = (color(cmax, cmax, cmax) - rgb) / cdelta;
+
+ if (rgb[0] == cmax)
+ h = c[2] - c[1];
+ else if (rgb[1] == cmax)
+ h = 2.0 + c[0] - c[2];
+ else
+ h = 4.0 + c[1] - c[0];
+
+ h /= 6.0;
+
+ if (h < 0.0)
+ h += 1.0;
+ }
+
+ return color(h, s, v);
}
color hsv_to_rgb(color hsv)
{
- float i, f, p, q, t, h, s, v;
- color rgb;
-
- h = hsv[0];
- s = hsv[1];
- v = hsv[2];
-
- if (s == 0.0) {
- rgb = color(v, v, v);
- }
- else {
- if (h == 1.0)
- h = 0.0;
-
- h *= 6.0;
- i = floor(h);
- f = h - i;
- rgb = color(f, f, f);
- p = v * (1.0 - s);
- q = v * (1.0 - (s * f));
- t = v * (1.0 - (s * (1.0 - f)));
-
- if (i == 0.0) rgb = color(v, t, p);
- else if (i == 1.0) rgb = color(q, v, p);
- else if (i == 2.0) rgb = color(p, v, t);
- else if (i == 3.0) rgb = color(p, q, v);
- else if (i == 4.0) rgb = color(t, p, v);
- else rgb = color(v, p, q);
- }
-
- return rgb;
+ float i, f, p, q, t, h, s, v;
+ color rgb;
+
+ h = hsv[0];
+ s = hsv[1];
+ v = hsv[2];
+
+ if (s == 0.0) {
+ rgb = color(v, v, v);
+ }
+ else {
+ if (h == 1.0)
+ h = 0.0;
+
+ h *= 6.0;
+ i = floor(h);
+ f = h - i;
+ rgb = color(f, f, f);
+ p = v * (1.0 - s);
+ q = v * (1.0 - (s * f));
+ t = v * (1.0 - (s * (1.0 - f)));
+
+ if (i == 0.0)
+ rgb = color(v, t, p);
+ else if (i == 1.0)
+ rgb = color(q, v, p);
+ else if (i == 2.0)
+ rgb = color(p, v, t);
+ else if (i == 3.0)
+ rgb = color(p, q, v);
+ else if (i == 4.0)
+ rgb = color(t, p, v);
+ else
+ rgb = color(v, p, q);
+ }
+
+ return rgb;
}
diff --git a/intern/cycles/kernel/shaders/node_combine_hsv.osl b/intern/cycles/kernel/shaders/node_combine_hsv.osl
index 6b922bf4e6b..1658cf3d774 100644
--- a/intern/cycles/kernel/shaders/node_combine_hsv.osl
+++ b/intern/cycles/kernel/shaders/node_combine_hsv.osl
@@ -16,12 +16,7 @@
#include "stdosl.h"
-shader node_combine_hsv(
- float H = 0.0,
- float S = 0.0,
- float V = 0.0,
- output color Color = 0.8)
+shader node_combine_hsv(float H = 0.0, float S = 0.0, float V = 0.0, output color Color = 0.8)
{
- Color = color("hsv", H, S, V);
+ Color = color("hsv", H, S, V);
}
-
diff --git a/intern/cycles/kernel/shaders/node_combine_rgb.osl b/intern/cycles/kernel/shaders/node_combine_rgb.osl
index f343fdefd84..aaa95e9c5af 100644
--- a/intern/cycles/kernel/shaders/node_combine_rgb.osl
+++ b/intern/cycles/kernel/shaders/node_combine_rgb.osl
@@ -16,12 +16,7 @@
#include "stdosl.h"
-shader node_combine_rgb(
- float R = 0.0,
- float G = 0.0,
- float B = 0.0,
- output color Image = 0.8)
+shader node_combine_rgb(float R = 0.0, float G = 0.0, float B = 0.0, output color Image = 0.8)
{
- Image = color(R, G, B);
+ Image = color(R, G, B);
}
-
diff --git a/intern/cycles/kernel/shaders/node_combine_xyz.osl b/intern/cycles/kernel/shaders/node_combine_xyz.osl
index 86182056b09..4ab49168704 100644
--- a/intern/cycles/kernel/shaders/node_combine_xyz.osl
+++ b/intern/cycles/kernel/shaders/node_combine_xyz.osl
@@ -16,12 +16,7 @@
#include "stdosl.h"
-shader node_combine_xyz(
- float X = 0.0,
- float Y = 0.0,
- float Z = 0.0,
- output vector Vector = 0.8)
+shader node_combine_xyz(float X = 0.0, float Y = 0.0, float Z = 0.0, output vector Vector = 0.8)
{
- Vector = vector(X, Y, Z);
+ Vector = vector(X, Y, Z);
}
-
diff --git a/intern/cycles/kernel/shaders/node_convert_from_color.osl b/intern/cycles/kernel/shaders/node_convert_from_color.osl
index e95a17f6fa1..7ea9a1e4fb3 100644
--- a/intern/cycles/kernel/shaders/node_convert_from_color.osl
+++ b/intern/cycles/kernel/shaders/node_convert_from_color.osl
@@ -16,19 +16,17 @@
#include "stdosl.h"
-shader node_convert_from_color(
- color value_color = 0.0,
- output string value_string = "",
- output float value_float = 0.0,
- output int value_int = 0,
- output vector value_vector = vector(0.0, 0.0, 0.0),
- output point value_point = point(0.0, 0.0, 0.0),
- output normal value_normal = normal(0.0, 0.0, 0.0))
+shader node_convert_from_color(color value_color = 0.0,
+ output string value_string = "",
+ output float value_float = 0.0,
+ output int value_int = 0,
+ output vector value_vector = vector(0.0, 0.0, 0.0),
+ output point value_point = point(0.0, 0.0, 0.0),
+ output normal value_normal = normal(0.0, 0.0, 0.0))
{
- value_float = value_color[0] * 0.2126 + value_color[1] * 0.7152 + value_color[2] * 0.0722;
- value_int = (int)(value_color[0] * 0.2126 + value_color[1] * 0.7152 + value_color[2] * 0.0722);
- value_vector = vector(value_color[0], value_color[1], value_color[2]);
- value_point = point(value_color[0], value_color[1], value_color[2]);
- value_normal = normal(value_color[0], value_color[1], value_color[2]);
+ value_float = value_color[0] * 0.2126 + value_color[1] * 0.7152 + value_color[2] * 0.0722;
+ value_int = (int)(value_color[0] * 0.2126 + value_color[1] * 0.7152 + value_color[2] * 0.0722);
+ value_vector = vector(value_color[0], value_color[1], value_color[2]);
+ value_point = point(value_color[0], value_color[1], value_color[2]);
+ value_normal = normal(value_color[0], value_color[1], value_color[2]);
}
-
diff --git a/intern/cycles/kernel/shaders/node_convert_from_float.osl b/intern/cycles/kernel/shaders/node_convert_from_float.osl
index a5c2e3b26ad..13b5dea0838 100644
--- a/intern/cycles/kernel/shaders/node_convert_from_float.osl
+++ b/intern/cycles/kernel/shaders/node_convert_from_float.osl
@@ -16,19 +16,17 @@
#include "stdosl.h"
-shader node_convert_from_float(
- float value_float = 0.0,
- output string value_string = "",
- output int value_int = 0,
- output color value_color = 0.0,
- output vector value_vector = vector(0.0, 0.0, 0.0),
- output point value_point = point(0.0, 0.0, 0.0),
- output normal value_normal = normal(0.0, 0.0, 0.0))
+shader node_convert_from_float(float value_float = 0.0,
+ output string value_string = "",
+ output int value_int = 0,
+ output color value_color = 0.0,
+ output vector value_vector = vector(0.0, 0.0, 0.0),
+ output point value_point = point(0.0, 0.0, 0.0),
+ output normal value_normal = normal(0.0, 0.0, 0.0))
{
- value_int = (int)value_float;
- value_color = color(value_float, value_float, value_float);
- value_vector = vector(value_float, value_float, value_float);
- value_point = point(value_float, value_float, value_float);
- value_normal = normal(value_float, value_float, value_float);
+ value_int = (int)value_float;
+ value_color = color(value_float, value_float, value_float);
+ value_vector = vector(value_float, value_float, value_float);
+ value_point = point(value_float, value_float, value_float);
+ value_normal = normal(value_float, value_float, value_float);
}
-
diff --git a/intern/cycles/kernel/shaders/node_convert_from_int.osl b/intern/cycles/kernel/shaders/node_convert_from_int.osl
index 0e6ae711210..a59e025d822 100644
--- a/intern/cycles/kernel/shaders/node_convert_from_int.osl
+++ b/intern/cycles/kernel/shaders/node_convert_from_int.osl
@@ -16,20 +16,18 @@
#include "stdosl.h"
-shader node_convert_from_int(
- int value_int = 0,
- output string value_string = "",
- output float value_float = 0.0,
- output color value_color = 0.0,
- output vector value_vector = vector(0.0, 0.0, 0.0),
- output point value_point = point(0.0, 0.0, 0.0),
- output normal value_normal = normal(0.0, 0.0, 0.0))
+shader node_convert_from_int(int value_int = 0,
+ output string value_string = "",
+ output float value_float = 0.0,
+ output color value_color = 0.0,
+ output vector value_vector = vector(0.0, 0.0, 0.0),
+ output point value_point = point(0.0, 0.0, 0.0),
+ output normal value_normal = normal(0.0, 0.0, 0.0))
{
- float f = (float)value_int;
- value_float = f;
- value_color = color(f, f, f);
- value_vector = vector(f, f, f);
- value_point = point(f, f, f);
- value_normal = normal(f, f, f);
+ float f = (float)value_int;
+ value_float = f;
+ value_color = color(f, f, f);
+ value_vector = vector(f, f, f);
+ value_point = point(f, f, f);
+ value_normal = normal(f, f, f);
}
-
diff --git a/intern/cycles/kernel/shaders/node_convert_from_normal.osl b/intern/cycles/kernel/shaders/node_convert_from_normal.osl
index 7fffa7f6169..7bdd94d1941 100644
--- a/intern/cycles/kernel/shaders/node_convert_from_normal.osl
+++ b/intern/cycles/kernel/shaders/node_convert_from_normal.osl
@@ -16,19 +16,17 @@
#include "stdosl.h"
-shader node_convert_from_normal(
- normal value_normal = normal(0.0, 0.0, 0.0),
- output string value_string = "",
- output float value_float = 0.0,
- output int value_int = 0,
- output vector value_vector = vector(0.0, 0.0, 0.0),
- output color value_color = 0.0,
- output point value_point = point(0.0, 0.0, 0.0))
+shader node_convert_from_normal(normal value_normal = normal(0.0, 0.0, 0.0),
+ output string value_string = "",
+ output float value_float = 0.0,
+ output int value_int = 0,
+ output vector value_vector = vector(0.0, 0.0, 0.0),
+ output color value_color = 0.0,
+ output point value_point = point(0.0, 0.0, 0.0))
{
- value_float = (value_normal[0] + value_normal[1] + value_normal[2]) * (1.0 / 3.0);
- value_int = (int)((value_normal[0] + value_normal[1] + value_normal[2]) * (1.0 / 3.0));
- value_vector = vector(value_normal[0], value_normal[1], value_normal[2]);
- value_color = color(value_normal[0], value_normal[1], value_normal[2]);
- value_point = point(value_normal[0], value_normal[1], value_normal[2]);
+ value_float = (value_normal[0] + value_normal[1] + value_normal[2]) * (1.0 / 3.0);
+ value_int = (int)((value_normal[0] + value_normal[1] + value_normal[2]) * (1.0 / 3.0));
+ value_vector = vector(value_normal[0], value_normal[1], value_normal[2]);
+ value_color = color(value_normal[0], value_normal[1], value_normal[2]);
+ value_point = point(value_normal[0], value_normal[1], value_normal[2]);
}
-
diff --git a/intern/cycles/kernel/shaders/node_convert_from_point.osl b/intern/cycles/kernel/shaders/node_convert_from_point.osl
index 9e4930296bb..79c1719e7a7 100644
--- a/intern/cycles/kernel/shaders/node_convert_from_point.osl
+++ b/intern/cycles/kernel/shaders/node_convert_from_point.osl
@@ -16,19 +16,17 @@
#include "stdosl.h"
-shader node_convert_from_point(
- point value_point = point(0.0, 0.0, 0.0),
- output string value_string = "",
- output float value_float = 0.0,
- output int value_int = 0,
- output vector value_vector = vector(0.0, 0.0, 0.0),
- output color value_color = 0.0,
- output normal value_normal = normal(0.0, 0.0, 0.0))
+shader node_convert_from_point(point value_point = point(0.0, 0.0, 0.0),
+ output string value_string = "",
+ output float value_float = 0.0,
+ output int value_int = 0,
+ output vector value_vector = vector(0.0, 0.0, 0.0),
+ output color value_color = 0.0,
+ output normal value_normal = normal(0.0, 0.0, 0.0))
{
- value_float = (value_point[0] + value_point[1] + value_point[2]) * (1.0 / 3.0);
- value_int = (int)((value_normal[0] + value_normal[1] + value_normal[2]) * (1.0 / 3.0));
- value_vector = vector(value_point[0], value_point[1], value_point[2]);
- value_color = color(value_point[0], value_point[1], value_point[2]);
- value_normal = normal(value_point[0], value_point[1], value_point[2]);
+ value_float = (value_point[0] + value_point[1] + value_point[2]) * (1.0 / 3.0);
+ value_int = (int)((value_normal[0] + value_normal[1] + value_normal[2]) * (1.0 / 3.0));
+ value_vector = vector(value_point[0], value_point[1], value_point[2]);
+ value_color = color(value_point[0], value_point[1], value_point[2]);
+ value_normal = normal(value_point[0], value_point[1], value_point[2]);
}
-
diff --git a/intern/cycles/kernel/shaders/node_convert_from_string.osl b/intern/cycles/kernel/shaders/node_convert_from_string.osl
index cbc6653eada..48d894a6b3e 100644
--- a/intern/cycles/kernel/shaders/node_convert_from_string.osl
+++ b/intern/cycles/kernel/shaders/node_convert_from_string.osl
@@ -16,14 +16,12 @@
#include "stdosl.h"
-shader node_convert_from_string(
- string value_string = "",
- output color value_color = color(0.0, 0.0, 0.0),
- output float value_float = 0.0,
- output int value_int = 0,
- output vector value_vector = vector(0.0, 0.0, 0.0),
- output point value_point = point(0.0, 0.0, 0.0),
- output normal value_normal = normal(0.0, 0.0, 0.0))
+shader node_convert_from_string(string value_string = "",
+ output color value_color = color(0.0, 0.0, 0.0),
+ output float value_float = 0.0,
+ output int value_int = 0,
+ output vector value_vector = vector(0.0, 0.0, 0.0),
+ output point value_point = point(0.0, 0.0, 0.0),
+ output normal value_normal = normal(0.0, 0.0, 0.0))
{
}
-
diff --git a/intern/cycles/kernel/shaders/node_convert_from_vector.osl b/intern/cycles/kernel/shaders/node_convert_from_vector.osl
index 8bdca469b90..92ab2313bcb 100644
--- a/intern/cycles/kernel/shaders/node_convert_from_vector.osl
+++ b/intern/cycles/kernel/shaders/node_convert_from_vector.osl
@@ -16,19 +16,17 @@
#include "stdosl.h"
-shader node_convert_from_vector(
- vector value_vector = vector(0.0, 0.0, 0.0),
- output string value_string = "",
- output float value_float = 0.0,
- output int value_int = 0,
- output color value_color = color(0.0, 0.0, 0.0),
- output point value_point = point(0.0, 0.0, 0.0),
- output normal value_normal = normal(0.0, 0.0, 0.0))
+shader node_convert_from_vector(vector value_vector = vector(0.0, 0.0, 0.0),
+ output string value_string = "",
+ output float value_float = 0.0,
+ output int value_int = 0,
+ output color value_color = color(0.0, 0.0, 0.0),
+ output point value_point = point(0.0, 0.0, 0.0),
+ output normal value_normal = normal(0.0, 0.0, 0.0))
{
- value_float = (value_vector[0] + value_vector[1] + value_vector[2]) * (1.0 / 3.0);
- value_int = (int)((value_normal[0] + value_normal[1] + value_normal[2]) * (1.0 / 3.0));
- value_color = color(value_vector[0], value_vector[1], value_vector[2]);
- value_point = point(value_vector[0], value_vector[1], value_vector[2]);
- value_normal = normal(value_vector[0], value_vector[1], value_vector[2]);
+ value_float = (value_vector[0] + value_vector[1] + value_vector[2]) * (1.0 / 3.0);
+ value_int = (int)((value_normal[0] + value_normal[1] + value_normal[2]) * (1.0 / 3.0));
+ value_color = color(value_vector[0], value_vector[1], value_vector[2]);
+ value_point = point(value_vector[0], value_vector[1], value_vector[2]);
+ value_normal = normal(value_vector[0], value_vector[1], value_vector[2]);
}
-
diff --git a/intern/cycles/kernel/shaders/node_diffuse_bsdf.osl b/intern/cycles/kernel/shaders/node_diffuse_bsdf.osl
index 2bef2d65baa..bd5554b838a 100644
--- a/intern/cycles/kernel/shaders/node_diffuse_bsdf.osl
+++ b/intern/cycles/kernel/shaders/node_diffuse_bsdf.osl
@@ -16,15 +16,13 @@
#include "stdosl.h"
-shader node_diffuse_bsdf(
- color Color = 0.8,
- float Roughness = 0.0,
- normal Normal = N,
- output closure color BSDF = 0)
+shader node_diffuse_bsdf(color Color = 0.8,
+ float Roughness = 0.0,
+ normal Normal = N,
+ output closure color BSDF = 0)
{
- if (Roughness == 0.0)
- BSDF = Color * diffuse(Normal);
- else
- BSDF = Color * oren_nayar(Normal, Roughness);
+ if (Roughness == 0.0)
+ BSDF = Color * diffuse(Normal);
+ else
+ BSDF = Color * oren_nayar(Normal, Roughness);
}
-
diff --git a/intern/cycles/kernel/shaders/node_displacement.osl b/intern/cycles/kernel/shaders/node_displacement.osl
index 89f35841527..a1f3b7b7737 100644
--- a/intern/cycles/kernel/shaders/node_displacement.osl
+++ b/intern/cycles/kernel/shaders/node_displacement.osl
@@ -16,23 +16,21 @@
#include "stdosl.h"
-shader node_displacement(
- string space = "object",
- float Height = 0.0,
- float Midlevel = 0.5,
- float Scale = 1.0,
- normal Normal = N,
- output vector Displacement = vector(0.0, 0.0, 0.0))
+shader node_displacement(string space = "object",
+ float Height = 0.0,
+ float Midlevel = 0.5,
+ float Scale = 1.0,
+ normal Normal = N,
+ output vector Displacement = vector(0.0, 0.0, 0.0))
{
- Displacement = Normal;
- if(space == "object") {
- Displacement = transform("object", Displacement);
- }
+ Displacement = Normal;
+ if (space == "object") {
+ Displacement = transform("object", Displacement);
+ }
- Displacement = normalize(Displacement) * (Height - Midlevel) * Scale;
+ Displacement = normalize(Displacement) * (Height - Midlevel) * Scale;
- if(space == "object") {
- Displacement = transform("object", "world", Displacement);
- }
+ if (space == "object") {
+ Displacement = transform("object", "world", Displacement);
+ }
}
-
diff --git a/intern/cycles/kernel/shaders/node_emission.osl b/intern/cycles/kernel/shaders/node_emission.osl
index c36e2a4c0f3..57973f57ac6 100644
--- a/intern/cycles/kernel/shaders/node_emission.osl
+++ b/intern/cycles/kernel/shaders/node_emission.osl
@@ -16,11 +16,7 @@
#include "stdosl.h"
-shader node_emission(
- color Color = 0.8,
- float Strength = 1.0,
- output closure color Emission = 0)
+shader node_emission(color Color = 0.8, float Strength = 1.0, output closure color Emission = 0)
{
- Emission = (Strength * Color) * emission();
+ Emission = (Strength * Color) * emission();
}
-
diff --git a/intern/cycles/kernel/shaders/node_environment_texture.osl b/intern/cycles/kernel/shaders/node_environment_texture.osl
index 95d9d813969..eb32dad392f 100644
--- a/intern/cycles/kernel/shaders/node_environment_texture.osl
+++ b/intern/cycles/kernel/shaders/node_environment_texture.osl
@@ -19,63 +19,63 @@
vector environment_texture_direction_to_equirectangular(vector dir)
{
- float u = -atan2(dir[1], dir[0]) / (M_2PI) + 0.5;
- float v = atan2(dir[2], hypot(dir[0], dir[1])) / M_PI + 0.5;
+ float u = -atan2(dir[1], dir[0]) / (M_2PI) + 0.5;
+ float v = atan2(dir[2], hypot(dir[0], dir[1])) / M_PI + 0.5;
- return vector(u, v, 0.0);
+ return vector(u, v, 0.0);
}
vector environment_texture_direction_to_mirrorball(vector idir)
{
- vector dir = idir;
- dir[1] -= 1.0;
+ vector dir = idir;
+ dir[1] -= 1.0;
- float div = 2.0 * sqrt(max(-0.5 * dir[1], 0.0));
- if (div > 0.0)
- dir /= div;
+ float div = 2.0 * sqrt(max(-0.5 * dir[1], 0.0));
+ if (div > 0.0)
+ dir /= div;
- float u = 0.5 * (dir[0] + 1.0);
- float v = 0.5 * (dir[2] + 1.0);
+ float u = 0.5 * (dir[0] + 1.0);
+ float v = 0.5 * (dir[2] + 1.0);
- return vector(u, v, 0.0);
+ return vector(u, v, 0.0);
}
shader node_environment_texture(
- int use_mapping = 0,
- matrix mapping = matrix(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
- vector Vector = P,
- string filename = "",
- string projection = "equirectangular",
- string interpolation = "linear",
- string color_space = "sRGB",
- int is_float = 1,
- int use_alpha = 1,
- output color Color = 0.0,
- output float Alpha = 1.0)
+ int use_mapping = 0,
+ matrix mapping = matrix(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
+ vector Vector = P,
+ string filename = "",
+ string projection = "equirectangular",
+ string interpolation = "linear",
+ string color_space = "sRGB",
+ int is_float = 1,
+ int use_alpha = 1,
+ output color Color = 0.0,
+ output float Alpha = 1.0)
{
- vector p = Vector;
+ vector p = Vector;
- if (use_mapping)
- p = transform(mapping, p);
-
- p = normalize(p);
+ if (use_mapping)
+ p = transform(mapping, p);
- if (projection == "equirectangular")
- p = environment_texture_direction_to_equirectangular(p);
- else
- p = environment_texture_direction_to_mirrorball(p);
+ p = normalize(p);
- /* todo: use environment for better texture filtering of equirectangular */
- Color = (color)texture(filename, p[0], 1.0 - p[1], "wrap", "periodic", "interp", interpolation, "alpha", Alpha);
+ if (projection == "equirectangular")
+ p = environment_texture_direction_to_equirectangular(p);
+ else
+ p = environment_texture_direction_to_mirrorball(p);
- if (use_alpha) {
- Color = color_unpremultiply(Color, Alpha);
+ /* todo: use environment for better texture filtering of equirectangular */
+ Color = (color)texture(
+ filename, p[0], 1.0 - p[1], "wrap", "periodic", "interp", interpolation, "alpha", Alpha);
- if (!is_float)
- Color = min(Color, 1.0);
- }
+ if (use_alpha) {
+ Color = color_unpremultiply(Color, Alpha);
- if (color_space == "sRGB")
- Color = color_srgb_to_scene_linear(Color);
-}
+ if (!is_float)
+ Color = min(Color, 1.0);
+ }
+ if (color_space == "sRGB")
+ Color = color_srgb_to_scene_linear(Color);
+}
diff --git a/intern/cycles/kernel/shaders/node_fresnel.h b/intern/cycles/kernel/shaders/node_fresnel.h
index 40793479d8a..ade1d4c6207 100644
--- a/intern/cycles/kernel/shaders/node_fresnel.h
+++ b/intern/cycles/kernel/shaders/node_fresnel.h
@@ -32,33 +32,31 @@
float fresnel_dielectric_cos(float cosi, float eta)
{
- /* compute fresnel reflectance without explicitly computing
- * the refracted direction */
- float c = fabs(cosi);
- float g = eta * eta - 1 + c * c;
- float result;
+ /* compute fresnel reflectance without explicitly computing
+ * the refracted direction */
+ float c = fabs(cosi);
+ float g = eta * eta - 1 + c * c;
+ float result;
- if (g > 0) {
- g = sqrt(g);
- float A = (g - c) / (g + c);
- float B = (c * (g + c) - 1) / (c * (g - c) + 1);
- result = 0.5 * A * A * (1 + B * B);
- }
- else
- result = 1.0; /* TIR (no refracted component) */
+ if (g > 0) {
+ g = sqrt(g);
+ float A = (g - c) / (g + c);
+ float B = (c * (g + c) - 1) / (c * (g - c) + 1);
+ result = 0.5 * A * A * (1 + B * B);
+ }
+ else
+ result = 1.0; /* TIR (no refracted component) */
- return result;
+ return result;
}
color fresnel_conductor(float cosi, color eta, color k)
{
- color cosi2 = color(cosi * cosi);
- color one = color(1, 1, 1);
- color tmp_f = eta * eta + k * k;
- color tmp = tmp_f * cosi2;
- color Rparl2 = (tmp - (2.0 * eta * cosi) + one) /
- (tmp + (2.0 * eta * cosi) + one);
- color Rperp2 = (tmp_f - (2.0 * eta * cosi) + cosi2) /
- (tmp_f + (2.0 * eta * cosi) + cosi2);
- return (Rparl2 + Rperp2) * 0.5;
+ color cosi2 = color(cosi * cosi);
+ color one = color(1, 1, 1);
+ color tmp_f = eta * eta + k * k;
+ color tmp = tmp_f * cosi2;
+ color Rparl2 = (tmp - (2.0 * eta * cosi) + one) / (tmp + (2.0 * eta * cosi) + one);
+ color Rperp2 = (tmp_f - (2.0 * eta * cosi) + cosi2) / (tmp_f + (2.0 * eta * cosi) + cosi2);
+ return (Rparl2 + Rperp2) * 0.5;
}
diff --git a/intern/cycles/kernel/shaders/node_fresnel.osl b/intern/cycles/kernel/shaders/node_fresnel.osl
index 8bec7b432f5..89250db40f3 100644
--- a/intern/cycles/kernel/shaders/node_fresnel.osl
+++ b/intern/cycles/kernel/shaders/node_fresnel.osl
@@ -17,14 +17,10 @@
#include "stdosl.h"
#include "node_fresnel.h"
-shader node_fresnel(
- float IOR = 1.45,
- normal Normal = N,
- output float Fac = 0.0)
+shader node_fresnel(float IOR = 1.45, normal Normal = N, output float Fac = 0.0)
{
- float f = max(IOR, 1e-5);
- float eta = backfacing() ? 1.0 / f : f;
- float cosi = dot(I, Normal);
- Fac = fresnel_dielectric_cos(cosi, eta);
+ float f = max(IOR, 1e-5);
+ float eta = backfacing() ? 1.0 / f : f;
+ float cosi = dot(I, Normal);
+ Fac = fresnel_dielectric_cos(cosi, eta);
}
-
diff --git a/intern/cycles/kernel/shaders/node_gamma.osl b/intern/cycles/kernel/shaders/node_gamma.osl
index bc4c1b34266..9b9c17dc8af 100644
--- a/intern/cycles/kernel/shaders/node_gamma.osl
+++ b/intern/cycles/kernel/shaders/node_gamma.osl
@@ -16,10 +16,7 @@
#include "stdosl.h"
-shader node_gamma(
- color ColorIn = 0.8,
- float Gamma = 1.0,
- output color ColorOut = 0.0)
+shader node_gamma(color ColorIn = 0.8, float Gamma = 1.0, output color ColorOut = 0.0)
{
- ColorOut = pow(ColorIn, Gamma);
+ ColorOut = pow(ColorIn, Gamma);
}
diff --git a/intern/cycles/kernel/shaders/node_geometry.osl b/intern/cycles/kernel/shaders/node_geometry.osl
index b0bd7692489..b5c1c6611c1 100644
--- a/intern/cycles/kernel/shaders/node_geometry.osl
+++ b/intern/cycles/kernel/shaders/node_geometry.osl
@@ -16,55 +16,53 @@
#include "stdosl.h"
-shader node_geometry(
- normal NormalIn = N,
- string bump_offset = "center",
+shader node_geometry(normal NormalIn = N,
+ string bump_offset = "center",
- output point Position = point(0.0, 0.0, 0.0),
- output normal Normal = normal(0.0, 0.0, 0.0),
- output normal Tangent = normal(0.0, 0.0, 0.0),
- output normal TrueNormal = normal(0.0, 0.0, 0.0),
- output vector Incoming = vector(0.0, 0.0, 0.0),
- output point Parametric = point(0.0, 0.0, 0.0),
- output float Backfacing = 0.0,
- output float Pointiness = 0.0)
+ output point Position = point(0.0, 0.0, 0.0),
+ output normal Normal = normal(0.0, 0.0, 0.0),
+ output normal Tangent = normal(0.0, 0.0, 0.0),
+ output normal TrueNormal = normal(0.0, 0.0, 0.0),
+ output vector Incoming = vector(0.0, 0.0, 0.0),
+ output point Parametric = point(0.0, 0.0, 0.0),
+ output float Backfacing = 0.0,
+ output float Pointiness = 0.0)
{
- Position = P;
- Normal = NormalIn;
- TrueNormal = Ng;
- Incoming = I;
- Parametric = point(u, v, 0.0);
- Backfacing = backfacing();
+ Position = P;
+ Normal = NormalIn;
+ TrueNormal = Ng;
+ Incoming = I;
+ Parametric = point(u, v, 0.0);
+ Backfacing = backfacing();
- if (bump_offset == "dx") {
- Position += Dx(Position);
- Parametric += Dx(Parametric);
- }
- else if (bump_offset == "dy") {
- Position += Dy(Position);
- Parametric += Dy(Parametric);
- }
+ if (bump_offset == "dx") {
+ Position += Dx(Position);
+ Parametric += Dx(Parametric);
+ }
+ else if (bump_offset == "dy") {
+ Position += Dy(Position);
+ Parametric += Dy(Parametric);
+ }
- /* first try to get tangent attribute */
- point generated;
+ /* first try to get tangent attribute */
+ point generated;
- /* try to create spherical tangent from generated coordinates */
- if (getattribute("geom:generated", generated)) {
- normal data = normal(-(generated[1] - 0.5), (generated[0] - 0.5), 0.0);
- vector T = transform("object", "world", data);
- Tangent = cross(Normal, normalize(cross(T, Normal)));
- }
- else {
- /* otherwise use surface derivatives */
- Tangent = normalize(dPdu);
- }
+ /* try to create spherical tangent from generated coordinates */
+ if (getattribute("geom:generated", generated)) {
+ normal data = normal(-(generated[1] - 0.5), (generated[0] - 0.5), 0.0);
+ vector T = transform("object", "world", data);
+ Tangent = cross(Normal, normalize(cross(T, Normal)));
+ }
+ else {
+ /* otherwise use surface derivatives */
+ Tangent = normalize(dPdu);
+ }
- getattribute("geom:pointiness", Pointiness);
- if (bump_offset == "dx") {
- Pointiness += Dx(Pointiness);
- }
- else if (bump_offset == "dy") {
- Pointiness += Dy(Pointiness);
- }
+ getattribute("geom:pointiness", Pointiness);
+ if (bump_offset == "dx") {
+ Pointiness += Dx(Pointiness);
+ }
+ else if (bump_offset == "dy") {
+ Pointiness += Dy(Pointiness);
+ }
}
-
diff --git a/intern/cycles/kernel/shaders/node_glass_bsdf.osl b/intern/cycles/kernel/shaders/node_glass_bsdf.osl
index 2e713861c58..c0b8a002536 100644
--- a/intern/cycles/kernel/shaders/node_glass_bsdf.osl
+++ b/intern/cycles/kernel/shaders/node_glass_bsdf.osl
@@ -17,29 +17,27 @@
#include "stdosl.h"
#include "node_fresnel.h"
-shader node_glass_bsdf(
- color Color = 0.8,
- string distribution = "sharp",
- float Roughness = 0.2,
- float IOR = 1.45,
- normal Normal = N,
- output closure color BSDF = 0)
+shader node_glass_bsdf(color Color = 0.8,
+ string distribution = "sharp",
+ float Roughness = 0.2,
+ float IOR = 1.45,
+ normal Normal = N,
+ output closure color BSDF = 0)
{
- float f = max(IOR, 1e-5);
- float eta = backfacing() ? 1.0 / f : f;
- float cosi = dot(I, Normal);
- float Fr = fresnel_dielectric_cos(cosi, eta);
- float roughness = Roughness * Roughness;
+ float f = max(IOR, 1e-5);
+ float eta = backfacing() ? 1.0 / f : f;
+ float cosi = dot(I, Normal);
+ float Fr = fresnel_dielectric_cos(cosi, eta);
+ float roughness = Roughness * Roughness;
- if (distribution == "sharp")
- BSDF = Color * (Fr * reflection(Normal) + (1.0 - Fr) * refraction(Normal, eta));
- else if (distribution == "beckmann")
- BSDF = Color * (Fr * microfacet_beckmann(Normal, roughness) +
- (1.0 - Fr) * microfacet_beckmann_refraction(Normal, roughness, eta));
- else if (distribution == "Multiscatter GGX")
- BSDF = Color * microfacet_multi_ggx_glass(Normal, roughness, eta, Color);
- else if (distribution == "GGX")
- BSDF = Color * (Fr * microfacet_ggx(Normal, roughness) +
- (1.0 - Fr) * microfacet_ggx_refraction(Normal, roughness, eta));
+ if (distribution == "sharp")
+ BSDF = Color * (Fr * reflection(Normal) + (1.0 - Fr) * refraction(Normal, eta));
+ else if (distribution == "beckmann")
+ BSDF = Color * (Fr * microfacet_beckmann(Normal, roughness) +
+ (1.0 - Fr) * microfacet_beckmann_refraction(Normal, roughness, eta));
+ else if (distribution == "Multiscatter GGX")
+ BSDF = Color * microfacet_multi_ggx_glass(Normal, roughness, eta, Color);
+ else if (distribution == "GGX")
+ BSDF = Color * (Fr * microfacet_ggx(Normal, roughness) +
+ (1.0 - Fr) * microfacet_ggx_refraction(Normal, roughness, eta));
}
-
diff --git a/intern/cycles/kernel/shaders/node_glossy_bsdf.osl b/intern/cycles/kernel/shaders/node_glossy_bsdf.osl
index 7415211b56d..2d40ee8d3f6 100644
--- a/intern/cycles/kernel/shaders/node_glossy_bsdf.osl
+++ b/intern/cycles/kernel/shaders/node_glossy_bsdf.osl
@@ -17,25 +17,22 @@
#include "stdosl.h"
#include "node_fresnel.h"
-shader node_glossy_bsdf(
- color Color = 0.8,
- string distribution = "GGX",
- float Roughness = 0.2,
- normal Normal = N,
- output closure color BSDF = 0)
+shader node_glossy_bsdf(color Color = 0.8,
+ string distribution = "GGX",
+ float Roughness = 0.2,
+ normal Normal = N,
+ output closure color BSDF = 0)
{
- float roughness = Roughness * Roughness;
-
- if (distribution == "sharp")
- BSDF = Color * reflection(Normal);
- else if (distribution == "beckmann")
- BSDF = Color * microfacet_beckmann(Normal, roughness);
- else if (distribution == "GGX")
- BSDF = Color * microfacet_ggx(Normal, roughness);
- else if (distribution == "Multiscatter GGX")
- BSDF = Color * microfacet_multi_ggx(Normal, roughness, Color);
- else
- BSDF = Color * ashikhmin_shirley(Normal, vector(0, 0, 0), roughness, roughness);
+ float roughness = Roughness * Roughness;
+ if (distribution == "sharp")
+ BSDF = Color * reflection(Normal);
+ else if (distribution == "beckmann")
+ BSDF = Color * microfacet_beckmann(Normal, roughness);
+ else if (distribution == "GGX")
+ BSDF = Color * microfacet_ggx(Normal, roughness);
+ else if (distribution == "Multiscatter GGX")
+ BSDF = Color * microfacet_multi_ggx(Normal, roughness, Color);
+ else
+ BSDF = Color * ashikhmin_shirley(Normal, vector(0, 0, 0), roughness, roughness);
}
-
diff --git a/intern/cycles/kernel/shaders/node_gradient_texture.osl b/intern/cycles/kernel/shaders/node_gradient_texture.osl
index f458937a18f..52bf466673d 100644
--- a/intern/cycles/kernel/shaders/node_gradient_texture.osl
+++ b/intern/cycles/kernel/shaders/node_gradient_texture.osl
@@ -21,59 +21,58 @@
float gradient(point p, string type)
{
- float x, y, z;
-
- x = p[0];
- y = p[1];
- z = p[2];
+ float x, y, z;
- float result = 0.0;
+ x = p[0];
+ y = p[1];
+ z = p[2];
- if (type == "linear") {
- result = x;
- }
- else if (type == "quadratic") {
- float r = max(x, 0.0);
- result = r * r;
- }
- else if (type == "easing") {
- float r = min(max(x, 0.0), 1.0);
- float t = r * r;
-
- result = (3.0 * t - 2.0 * t * r);
- }
- else if (type == "diagonal") {
- result = (x + y) * 0.5;
- }
- else if (type == "radial") {
- result = atan2(y, x) / M_2PI + 0.5;
- }
- else {
- float r = max(1.0 - sqrt(x * x + y * y + z * z), 0.0);
+ float result = 0.0;
- if (type == "quadratic_sphere")
- result = r * r;
- else if (type == "spherical")
- result = r;
- }
+ if (type == "linear") {
+ result = x;
+ }
+ else if (type == "quadratic") {
+ float r = max(x, 0.0);
+ result = r * r;
+ }
+ else if (type == "easing") {
+ float r = min(max(x, 0.0), 1.0);
+ float t = r * r;
- return result;
+ result = (3.0 * t - 2.0 * t * r);
+ }
+ else if (type == "diagonal") {
+ result = (x + y) * 0.5;
+ }
+ else if (type == "radial") {
+ result = atan2(y, x) / M_2PI + 0.5;
+ }
+ else {
+ float r = max(1.0 - sqrt(x * x + y * y + z * z), 0.0);
+
+ if (type == "quadratic_sphere")
+ result = r * r;
+ else if (type == "spherical")
+ result = r;
+ }
+
+ return result;
}
shader node_gradient_texture(
- int use_mapping = 0,
- matrix mapping = matrix(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
- string type = "linear",
- point Vector = P,
- output float Fac = 0.0,
- output color Color = 0.0)
+ int use_mapping = 0,
+ matrix mapping = matrix(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
+ string type = "linear",
+ point Vector = P,
+ output float Fac = 0.0,
+ output color Color = 0.0)
{
- point p = Vector;
+ point p = Vector;
- if (use_mapping)
- p = transform(mapping, p);
+ if (use_mapping)
+ p = transform(mapping, p);
- Fac = gradient(p, type);
- Color = color(Fac, Fac, Fac);
+ Fac = gradient(p, type);
+ Color = color(Fac, Fac, Fac);
}
-
diff --git a/intern/cycles/kernel/shaders/node_hair_bsdf.osl b/intern/cycles/kernel/shaders/node_hair_bsdf.osl
index ef8f2fae894..bc912087666 100644
--- a/intern/cycles/kernel/shaders/node_hair_bsdf.osl
+++ b/intern/cycles/kernel/shaders/node_hair_bsdf.osl
@@ -18,41 +18,40 @@
#include "stdosl.h"
-shader node_hair_bsdf(
- color Color = 0.8,
- string component = "reflection",
- float Offset = 0.0,
- float RoughnessU = 0.1,
- float RoughnessV = 1.0,
- normal Tangent = normal(0, 0, 0),
- output closure color BSDF = 0)
+shader node_hair_bsdf(color Color = 0.8,
+ string component = "reflection",
+ float Offset = 0.0,
+ float RoughnessU = 0.1,
+ float RoughnessV = 1.0,
+ normal Tangent = normal(0, 0, 0),
+ output closure color BSDF = 0)
{
- float roughnessh = clamp(RoughnessU, 0.001, 1.0);
- float roughnessv = clamp(RoughnessV, 0.001, 1.0);
- float offset = -Offset;
+ float roughnessh = clamp(RoughnessU, 0.001, 1.0);
+ float roughnessv = clamp(RoughnessV, 0.001, 1.0);
+ float offset = -Offset;
- normal T;
- float IsCurve = 0;
- getattribute("geom:is_curve", IsCurve);
+ normal T;
+ float IsCurve = 0;
+ getattribute("geom:is_curve", IsCurve);
- if (isconnected(Tangent)) {
- T = Tangent;
- }
- else if(!IsCurve) {
- T = normalize(dPdv);
- offset = 0.0;
- }
- else {
- T = normalize(dPdu);
- }
+ if (isconnected(Tangent)) {
+ T = Tangent;
+ }
+ else if (!IsCurve) {
+ T = normalize(dPdv);
+ offset = 0.0;
+ }
+ else {
+ T = normalize(dPdu);
+ }
- if (backfacing() && IsCurve) {
- BSDF = transparent();
- }
- else {
- if (component == "reflection")
- BSDF = Color * hair_reflection(Ng, roughnessh, roughnessv, T, offset);
- else
- BSDF = Color * hair_transmission(Ng, roughnessh, roughnessv, T, offset);
- }
+ if (backfacing() && IsCurve) {
+ BSDF = transparent();
+ }
+ else {
+ if (component == "reflection")
+ BSDF = Color * hair_reflection(Ng, roughnessh, roughnessv, T, offset);
+ else
+ BSDF = Color * hair_transmission(Ng, roughnessh, roughnessv, T, offset);
+ }
}
diff --git a/intern/cycles/kernel/shaders/node_hair_info.osl b/intern/cycles/kernel/shaders/node_hair_info.osl
index 19216f67579..991a27c4103 100644
--- a/intern/cycles/kernel/shaders/node_hair_info.osl
+++ b/intern/cycles/kernel/shaders/node_hair_info.osl
@@ -16,17 +16,15 @@
#include "stdosl.h"
-shader node_hair_info(
- output float IsStrand = 0.0,
- output float Intercept = 0.0,
- output float Thickness = 0.0,
- output normal TangentNormal = N,
- output float Random = 0)
+shader node_hair_info(output float IsStrand = 0.0,
+ output float Intercept = 0.0,
+ output float Thickness = 0.0,
+ output normal TangentNormal = N,
+ output float Random = 0)
{
- getattribute("geom:is_curve", IsStrand);
- getattribute("geom:curve_intercept", Intercept);
- getattribute("geom:curve_thickness", Thickness);
- getattribute("geom:curve_tangent_normal", TangentNormal);
- getattribute("geom:curve_random", Random);
+ getattribute("geom:is_curve", IsStrand);
+ getattribute("geom:curve_intercept", Intercept);
+ getattribute("geom:curve_thickness", Thickness);
+ getattribute("geom:curve_tangent_normal", TangentNormal);
+ getattribute("geom:curve_random", Random);
}
-
diff --git a/intern/cycles/kernel/shaders/node_holdout.osl b/intern/cycles/kernel/shaders/node_holdout.osl
index 78a9f46fd15..b51bc0543a5 100644
--- a/intern/cycles/kernel/shaders/node_holdout.osl
+++ b/intern/cycles/kernel/shaders/node_holdout.osl
@@ -16,9 +16,6 @@
#include "stdosl.h"
-shader node_holdout(
- output closure color Holdout = holdout())
+shader node_holdout(output closure color Holdout = holdout())
{
-
}
-
diff --git a/intern/cycles/kernel/shaders/node_hsv.osl b/intern/cycles/kernel/shaders/node_hsv.osl
index d72a87a951f..30c56a20a92 100644
--- a/intern/cycles/kernel/shaders/node_hsv.osl
+++ b/intern/cycles/kernel/shaders/node_hsv.osl
@@ -17,28 +17,26 @@
#include "stdosl.h"
#include "node_color.h"
-shader node_hsv(
- float Hue = 0.5,
- float Saturation = 1.0,
- float Value = 1.0,
- float Fac = 0.5,
- color ColorIn = 0.0,
- output color ColorOut = 0.0)
+shader node_hsv(float Hue = 0.5,
+ float Saturation = 1.0,
+ float Value = 1.0,
+ float Fac = 0.5,
+ color ColorIn = 0.0,
+ output color ColorOut = 0.0)
{
- color Color = rgb_to_hsv(ColorIn);
+ color Color = rgb_to_hsv(ColorIn);
- // remember: fmod doesn't work for negative numbers
- Color[0] = fmod(Color[0] + Hue + 0.5, 1.0);
- Color[1] = clamp(Color[1] * Saturation, 0.0, 1.0);
- Color[2] *= Value;
+ // remember: fmod doesn't work for negative numbers
+ Color[0] = fmod(Color[0] + Hue + 0.5, 1.0);
+ Color[1] = clamp(Color[1] * Saturation, 0.0, 1.0);
+ Color[2] *= Value;
- Color = hsv_to_rgb(Color);
+ Color = hsv_to_rgb(Color);
- // Clamp color to prevent negative values cauzed by oversaturation.
- Color[0] = max(Color[0], 0.0);
- Color[1] = max(Color[1], 0.0);
- Color[2] = max(Color[2], 0.0);
+ // Clamp color to prevent negative values cauzed by oversaturation.
+ Color[0] = max(Color[0], 0.0);
+ Color[1] = max(Color[1], 0.0);
+ Color[2] = max(Color[2], 0.0);
- ColorOut = mix(ColorIn, Color, Fac);
+ ColorOut = mix(ColorIn, Color, Fac);
}
-
diff --git a/intern/cycles/kernel/shaders/node_ies_light.osl b/intern/cycles/kernel/shaders/node_ies_light.osl
index a0954e3a444..ea8c44e09de 100644
--- a/intern/cycles/kernel/shaders/node_ies_light.osl
+++ b/intern/cycles/kernel/shaders/node_ies_light.osl
@@ -19,24 +19,23 @@
/* IES Light */
-shader node_ies_light(
- int use_mapping = 0,
- matrix mapping = matrix(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
- int slot = 0,
- float Strength = 1.0,
- point Vector = I,
- output float Fac = 0.0)
+shader node_ies_light(int use_mapping = 0,
+ matrix mapping = matrix(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
+ int slot = 0,
+ float Strength = 1.0,
+ point Vector = I,
+ output float Fac = 0.0)
{
- point p = Vector;
+ point p = Vector;
- if (use_mapping) {
- p = transform(mapping, p);
- }
+ if (use_mapping) {
+ p = transform(mapping, p);
+ }
- p = normalize(p);
+ p = normalize(p);
- float v_angle = acos(-p[2]);
- float h_angle = atan2(p[0], p[1]) + M_PI;
+ float v_angle = acos(-p[2]);
+ float h_angle = atan2(p[0], p[1]) + M_PI;
- Fac = Strength * texture(format("@l%d", slot), h_angle, v_angle);
+ Fac = Strength * texture(format("@l%d", slot), h_angle, v_angle);
}
diff --git a/intern/cycles/kernel/shaders/node_image_texture.osl b/intern/cycles/kernel/shaders/node_image_texture.osl
index 7cd2922dd4f..df5eda39985 100644
--- a/intern/cycles/kernel/shaders/node_image_texture.osl
+++ b/intern/cycles/kernel/shaders/node_image_texture.osl
@@ -19,217 +19,217 @@
point texco_remap_square(point co)
{
- return (co - point(0.5, 0.5, 0.5)) * 2.0;
+ return (co - point(0.5, 0.5, 0.5)) * 2.0;
}
point map_to_tube(vector dir)
{
- float u, v;
- v = (dir[2] + 1.0) * 0.5;
- float len = sqrt(dir[0] * dir[0] + dir[1] * dir[1]);
- if (len > 0.0) {
- u = (1.0 - (atan2(dir[0] / len, dir[1] / len) / M_PI)) * 0.5;
- }
- else {
- v = u = 0.0; /* To avoid un-initialized variables. */
- }
- return point(u, v, 0.0);
+ float u, v;
+ v = (dir[2] + 1.0) * 0.5;
+ float len = sqrt(dir[0] * dir[0] + dir[1] * dir[1]);
+ if (len > 0.0) {
+ u = (1.0 - (atan2(dir[0] / len, dir[1] / len) / M_PI)) * 0.5;
+ }
+ else {
+ v = u = 0.0; /* To avoid un-initialized variables. */
+ }
+ return point(u, v, 0.0);
}
point map_to_sphere(vector dir)
{
- float len = length(dir);
- float v, u;
- if (len > 0.0) {
- if (dir[0] == 0.0 && dir[1] == 0.0) {
- u = 0.0; /* Othwise domain error. */
- }
- else {
- u = (1.0 - atan2(dir[0], dir[1]) / M_PI) / 2.0;
- }
- v = 1.0 - acos(dir[2] / len) / M_PI;
- }
- else {
- v = u = 0.0; /* To avoid un-initialized variables. */
- }
- return point(u, v, 0.0);
+ float len = length(dir);
+ float v, u;
+ if (len > 0.0) {
+ if (dir[0] == 0.0 && dir[1] == 0.0) {
+ u = 0.0; /* Othwise domain error. */
+ }
+ else {
+ u = (1.0 - atan2(dir[0], dir[1]) / M_PI) / 2.0;
+ }
+ v = 1.0 - acos(dir[2] / len) / M_PI;
+ }
+ else {
+ v = u = 0.0; /* To avoid un-initialized variables. */
+ }
+ return point(u, v, 0.0);
}
color image_texture_lookup(string filename,
string color_space,
- float u, float v,
+ float u,
+ float v,
output float Alpha,
int use_alpha,
int is_float,
string interpolation,
string extension)
{
- color rgb = (color)texture(filename, u, 1.0 - v, "wrap", extension, "interp", interpolation, "alpha", Alpha);
+ color rgb = (color)texture(
+ filename, u, 1.0 - v, "wrap", extension, "interp", interpolation, "alpha", Alpha);
- if (use_alpha) {
- rgb = color_unpremultiply(rgb, Alpha);
-
- if (!is_float)
- rgb = min(rgb, 1.0);
- }
+ if (use_alpha) {
+ rgb = color_unpremultiply(rgb, Alpha);
- if (color_space == "sRGB") {
- rgb = color_srgb_to_scene_linear(rgb);
- }
+ if (!is_float)
+ rgb = min(rgb, 1.0);
+ }
- return rgb;
+ if (color_space == "sRGB") {
+ rgb = color_srgb_to_scene_linear(rgb);
+ }
+
+ return rgb;
}
-shader node_image_texture(
- int use_mapping = 0,
- matrix mapping = matrix(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
- point Vector = P,
- string filename = "",
- string color_space = "sRGB",
- string projection = "flat",
- string interpolation = "smartcubic",
- string extension = "periodic",
- float projection_blend = 0.0,
- int is_float = 1,
- int use_alpha = 1,
- output color Color = 0.0,
- output float Alpha = 1.0)
+shader node_image_texture(int use_mapping = 0,
+ matrix mapping = matrix(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
+ point Vector = P,
+ string filename = "",
+ string color_space = "sRGB",
+ string projection = "flat",
+ string interpolation = "smartcubic",
+ string extension = "periodic",
+ float projection_blend = 0.0,
+ int is_float = 1,
+ int use_alpha = 1,
+ output color Color = 0.0,
+ output float Alpha = 1.0)
{
- point p = Vector;
-
- if (use_mapping)
- p = transform(mapping, p);
-
- if (projection == "flat") {
- Color = image_texture_lookup(filename,
- color_space,
- p[0], p[1],
- Alpha,
- use_alpha,
- is_float,
- interpolation,
- extension);
- }
- else if (projection == "box") {
- /* object space normal */
- vector Nob = transform("world", "object", N);
-
- /* project from direction vector to barycentric coordinates in triangles */
- Nob = vector(fabs(Nob[0]), fabs(Nob[1]), fabs(Nob[2]));
- Nob /= (Nob[0] + Nob[1] + Nob[2]);
-
- /* basic idea is to think of this as a triangle, each corner representing
- * one of the 3 faces of the cube. in the corners we have single textures,
- * in between we blend between two textures, and in the middle we a blend
- * between three textures.
- *
- * the Nxyz values are the barycentric coordinates in an equilateral
- * triangle, which in case of blending, in the middle has a smaller
- * equilateral triangle where 3 textures blend. this divides things into
- * 7 zones, with an if () test for each zone */
-
- vector weight = vector(0.0, 0.0, 0.0);
- float blend = projection_blend;
- float limit = 0.5 * (1.0 + blend);
-
- /* first test for corners with single texture */
- if (Nob[0] > limit * (Nob[0] + Nob[1]) && Nob[0] > limit * (Nob[0] + Nob[2])) {
- weight[0] = 1.0;
- }
- else if (Nob[1] > limit * (Nob[0] + Nob[1]) && Nob[1] > limit * (Nob[1] + Nob[2])) {
- weight[1] = 1.0;
- }
- else if (Nob[2] > limit * (Nob[0] + Nob[2]) && Nob[2] > limit * (Nob[1] + Nob[2])) {
- weight[2] = 1.0;
- }
- else if (blend > 0.0) {
- /* in case of blending, test for mixes between two textures */
- if (Nob[2] < (1.0 - limit) * (Nob[1] + Nob[0])) {
- weight[0] = Nob[0] / (Nob[0] + Nob[1]);
- weight[0] = clamp((weight[0] - 0.5 * (1.0 - blend)) / blend, 0.0, 1.0);
- weight[1] = 1.0 - weight[0];
- }
- else if (Nob[0] < (1.0 - limit) * (Nob[1] + Nob[2])) {
- weight[1] = Nob[1] / (Nob[1] + Nob[2]);
- weight[1] = clamp((weight[1] - 0.5 * (1.0 - blend)) / blend, 0.0, 1.0);
- weight[2] = 1.0 - weight[1];
- }
- else if (Nob[1] < (1.0 - limit) * (Nob[0] + Nob[2])) {
- weight[0] = Nob[0] / (Nob[0] + Nob[2]);
- weight[0] = clamp((weight[0] - 0.5 * (1.0 - blend)) / blend, 0.0, 1.0);
- weight[2] = 1.0 - weight[0];
- }
- else {
- /* last case, we have a mix between three */
- weight[0] = ((2.0 - limit) * Nob[0] + (limit - 1.0)) / (2.0 * limit - 1.0);
- weight[1] = ((2.0 - limit) * Nob[1] + (limit - 1.0)) / (2.0 * limit - 1.0);
- weight[2] = ((2.0 - limit) * Nob[2] + (limit - 1.0)) / (2.0 * limit - 1.0);
- }
- }
- else {
- /* Desperate mode, no valid choice anyway, fallback to one side.*/
- weight[0] = 1.0;
- }
-
- Color = color(0.0, 0.0, 0.0);
- Alpha = 0.0;
-
- float tmp_alpha;
-
- if (weight[0] > 0.0) {
- Color += weight[0] * image_texture_lookup(filename,
- color_space,
- p[1], p[2],
- tmp_alpha,
- use_alpha,
- is_float,
- interpolation,
- extension);
- Alpha += weight[0] * tmp_alpha;
- }
- if (weight[1] > 0.0) {
- Color += weight[1] * image_texture_lookup(filename,
- color_space,
- p[0], p[2],
- tmp_alpha,
- use_alpha,
- is_float,
- interpolation,
- extension);
- Alpha += weight[1] * tmp_alpha;
- }
- if (weight[2] > 0.0) {
- Color += weight[2] * image_texture_lookup(filename,
- color_space,
- p[1], p[0],
- tmp_alpha,
- use_alpha,
- is_float,
- interpolation,
- extension);
- Alpha += weight[2] * tmp_alpha;
- }
- }
- else if (projection == "sphere") {
- point projected = map_to_sphere(texco_remap_square(p));
- Color = image_texture_lookup(filename,
- color_space,
- projected[0], projected[1],
- Alpha,
- use_alpha,
- is_float,
- interpolation,
- extension);
- }
- else if (projection == "tube") {
- point projected = map_to_tube(texco_remap_square(p));
- Color = image_texture_lookup(filename,
- color_space,
- projected[0], projected[1],
- Alpha,
- use_alpha,
- is_float,
- interpolation,
- extension);
- }
+ point p = Vector;
+
+ if (use_mapping)
+ p = transform(mapping, p);
+
+ if (projection == "flat") {
+ Color = image_texture_lookup(
+ filename, color_space, p[0], p[1], Alpha, use_alpha, is_float, interpolation, extension);
+ }
+ else if (projection == "box") {
+ /* object space normal */
+ vector Nob = transform("world", "object", N);
+
+ /* project from direction vector to barycentric coordinates in triangles */
+ Nob = vector(fabs(Nob[0]), fabs(Nob[1]), fabs(Nob[2]));
+ Nob /= (Nob[0] + Nob[1] + Nob[2]);
+
+ /* basic idea is to think of this as a triangle, each corner representing
+ * one of the 3 faces of the cube. in the corners we have single textures,
+ * in between we blend between two textures, and in the middle we a blend
+ * between three textures.
+ *
+ * the Nxyz values are the barycentric coordinates in an equilateral
+ * triangle, which in case of blending, in the middle has a smaller
+ * equilateral triangle where 3 textures blend. this divides things into
+ * 7 zones, with an if () test for each zone */
+
+ vector weight = vector(0.0, 0.0, 0.0);
+ float blend = projection_blend;
+ float limit = 0.5 * (1.0 + blend);
+
+ /* first test for corners with single texture */
+ if (Nob[0] > limit * (Nob[0] + Nob[1]) && Nob[0] > limit * (Nob[0] + Nob[2])) {
+ weight[0] = 1.0;
+ }
+ else if (Nob[1] > limit * (Nob[0] + Nob[1]) && Nob[1] > limit * (Nob[1] + Nob[2])) {
+ weight[1] = 1.0;
+ }
+ else if (Nob[2] > limit * (Nob[0] + Nob[2]) && Nob[2] > limit * (Nob[1] + Nob[2])) {
+ weight[2] = 1.0;
+ }
+ else if (blend > 0.0) {
+ /* in case of blending, test for mixes between two textures */
+ if (Nob[2] < (1.0 - limit) * (Nob[1] + Nob[0])) {
+ weight[0] = Nob[0] / (Nob[0] + Nob[1]);
+ weight[0] = clamp((weight[0] - 0.5 * (1.0 - blend)) / blend, 0.0, 1.0);
+ weight[1] = 1.0 - weight[0];
+ }
+ else if (Nob[0] < (1.0 - limit) * (Nob[1] + Nob[2])) {
+ weight[1] = Nob[1] / (Nob[1] + Nob[2]);
+ weight[1] = clamp((weight[1] - 0.5 * (1.0 - blend)) / blend, 0.0, 1.0);
+ weight[2] = 1.0 - weight[1];
+ }
+ else if (Nob[1] < (1.0 - limit) * (Nob[0] + Nob[2])) {
+ weight[0] = Nob[0] / (Nob[0] + Nob[2]);
+ weight[0] = clamp((weight[0] - 0.5 * (1.0 - blend)) / blend, 0.0, 1.0);
+ weight[2] = 1.0 - weight[0];
+ }
+ else {
+ /* last case, we have a mix between three */
+ weight[0] = ((2.0 - limit) * Nob[0] + (limit - 1.0)) / (2.0 * limit - 1.0);
+ weight[1] = ((2.0 - limit) * Nob[1] + (limit - 1.0)) / (2.0 * limit - 1.0);
+ weight[2] = ((2.0 - limit) * Nob[2] + (limit - 1.0)) / (2.0 * limit - 1.0);
+ }
+ }
+ else {
+ /* Desperate mode, no valid choice anyway, fallback to one side.*/
+ weight[0] = 1.0;
+ }
+
+ Color = color(0.0, 0.0, 0.0);
+ Alpha = 0.0;
+
+ float tmp_alpha;
+
+ if (weight[0] > 0.0) {
+ Color += weight[0] * image_texture_lookup(filename,
+ color_space,
+ p[1],
+ p[2],
+ tmp_alpha,
+ use_alpha,
+ is_float,
+ interpolation,
+ extension);
+ Alpha += weight[0] * tmp_alpha;
+ }
+ if (weight[1] > 0.0) {
+ Color += weight[1] * image_texture_lookup(filename,
+ color_space,
+ p[0],
+ p[2],
+ tmp_alpha,
+ use_alpha,
+ is_float,
+ interpolation,
+ extension);
+ Alpha += weight[1] * tmp_alpha;
+ }
+ if (weight[2] > 0.0) {
+ Color += weight[2] * image_texture_lookup(filename,
+ color_space,
+ p[1],
+ p[0],
+ tmp_alpha,
+ use_alpha,
+ is_float,
+ interpolation,
+ extension);
+ Alpha += weight[2] * tmp_alpha;
+ }
+ }
+ else if (projection == "sphere") {
+ point projected = map_to_sphere(texco_remap_square(p));
+ Color = image_texture_lookup(filename,
+ color_space,
+ projected[0],
+ projected[1],
+ Alpha,
+ use_alpha,
+ is_float,
+ interpolation,
+ extension);
+ }
+ else if (projection == "tube") {
+ point projected = map_to_tube(texco_remap_square(p));
+ Color = image_texture_lookup(filename,
+ color_space,
+ projected[0],
+ projected[1],
+ Alpha,
+ use_alpha,
+ is_float,
+ interpolation,
+ extension);
+ }
}
diff --git a/intern/cycles/kernel/shaders/node_invert.osl b/intern/cycles/kernel/shaders/node_invert.osl
index b33b0a43d63..c7d41e4e129 100644
--- a/intern/cycles/kernel/shaders/node_invert.osl
+++ b/intern/cycles/kernel/shaders/node_invert.osl
@@ -16,12 +16,8 @@
#include "stdosl.h"
-shader node_invert(
- float Fac = 1.0,
- color ColorIn = 0.8,
- output color ColorOut = 0.8)
+shader node_invert(float Fac = 1.0, color ColorIn = 0.8, output color ColorOut = 0.8)
{
- color ColorInv = color(1.0) - ColorIn;
- ColorOut = mix(ColorIn, ColorInv, Fac);
+ color ColorInv = color(1.0) - ColorIn;
+ ColorOut = mix(ColorIn, ColorInv, Fac);
}
-
diff --git a/intern/cycles/kernel/shaders/node_layer_weight.osl b/intern/cycles/kernel/shaders/node_layer_weight.osl
index f583df25773..7c46f28b41b 100644
--- a/intern/cycles/kernel/shaders/node_layer_weight.osl
+++ b/intern/cycles/kernel/shaders/node_layer_weight.osl
@@ -17,29 +17,28 @@
#include "stdosl.h"
#include "node_fresnel.h"
-shader node_layer_weight(
- float Blend = 0.5,
- normal Normal = N,
- output float Fresnel = 0.0,
- output float Facing = 0.0)
+shader node_layer_weight(float Blend = 0.5,
+ normal Normal = N,
+ output float Fresnel = 0.0,
+ output float Facing = 0.0)
{
- float blend = Blend;
- float cosi = dot(I, Normal);
+ float blend = Blend;
+ float cosi = dot(I, Normal);
- /* Fresnel */
- float eta = max(1.0 - Blend, 1e-5);
- eta = backfacing() ? eta : 1.0 / eta;
- Fresnel = fresnel_dielectric_cos(cosi, eta);
+ /* Fresnel */
+ float eta = max(1.0 - Blend, 1e-5);
+ eta = backfacing() ? eta : 1.0 / eta;
+ Fresnel = fresnel_dielectric_cos(cosi, eta);
- /* Facing */
- Facing = fabs(cosi);
+ /* Facing */
+ Facing = fabs(cosi);
- if (blend != 0.5) {
- blend = clamp(blend, 0.0, 1.0 - 1e-5);
- blend = (blend < 0.5) ? 2.0 * blend : 0.5 / (1.0 - blend);
+ if (blend != 0.5) {
+ blend = clamp(blend, 0.0, 1.0 - 1e-5);
+ blend = (blend < 0.5) ? 2.0 * blend : 0.5 / (1.0 - blend);
- Facing = pow(Facing, blend);
- }
+ Facing = pow(Facing, blend);
+ }
- Facing = 1.0 - Facing;
+ Facing = 1.0 - Facing;
}
diff --git a/intern/cycles/kernel/shaders/node_light_falloff.osl b/intern/cycles/kernel/shaders/node_light_falloff.osl
index a594e33d643..d0d7dd9c5aa 100644
--- a/intern/cycles/kernel/shaders/node_light_falloff.osl
+++ b/intern/cycles/kernel/shaders/node_light_falloff.osl
@@ -16,29 +16,27 @@
#include "stdosl.h"
-shader node_light_falloff(
- float Strength = 0.0,
- float Smooth = 0.0,
- output float Quadratic = 0.0,
- output float Linear = 0.0,
- output float Constant = 0.0)
+shader node_light_falloff(float Strength = 0.0,
+ float Smooth = 0.0,
+ output float Quadratic = 0.0,
+ output float Linear = 0.0,
+ output float Constant = 0.0)
{
- float ray_length = 0.0;
- float strength = Strength;
- getattribute("path:ray_length", ray_length);
+ float ray_length = 0.0;
+ float strength = Strength;
+ getattribute("path:ray_length", ray_length);
- if (Smooth > 0.0) {
- float squared = ray_length * ray_length;
- strength *= squared / (Smooth + squared);
- }
+ if (Smooth > 0.0) {
+ float squared = ray_length * ray_length;
+ strength *= squared / (Smooth + squared);
+ }
- /* Quadratic */
- Quadratic = strength;
-
- /* Linear */
- Linear = (strength * ray_length);
+ /* Quadratic */
+ Quadratic = strength;
- /* Constant */
- Constant = (strength * ray_length * ray_length);
-}
+ /* Linear */
+ Linear = (strength * ray_length);
+ /* Constant */
+ Constant = (strength * ray_length * ray_length);
+}
diff --git a/intern/cycles/kernel/shaders/node_light_path.osl b/intern/cycles/kernel/shaders/node_light_path.osl
index 64fe4c20132..c4a3624a67f 100644
--- a/intern/cycles/kernel/shaders/node_light_path.osl
+++ b/intern/cycles/kernel/shaders/node_light_path.osl
@@ -16,51 +16,49 @@
#include "stdosl.h"
-shader node_light_path(
- output float IsCameraRay = 0.0,
- output float IsShadowRay = 0.0,
- output float IsDiffuseRay = 0.0,
- output float IsGlossyRay = 0.0,
- output float IsSingularRay = 0.0,
- output float IsReflectionRay = 0.0,
- output float IsTransmissionRay = 0.0,
- output float IsVolumeScatterRay = 0.0,
- output float RayLength = 0.0,
- output float RayDepth = 0.0,
- output float DiffuseDepth = 0.0,
- output float GlossyDepth = 0.0,
- output float TransparentDepth = 0.0,
- output float TransmissionDepth = 0.0)
+shader node_light_path(output float IsCameraRay = 0.0,
+ output float IsShadowRay = 0.0,
+ output float IsDiffuseRay = 0.0,
+ output float IsGlossyRay = 0.0,
+ output float IsSingularRay = 0.0,
+ output float IsReflectionRay = 0.0,
+ output float IsTransmissionRay = 0.0,
+ output float IsVolumeScatterRay = 0.0,
+ output float RayLength = 0.0,
+ output float RayDepth = 0.0,
+ output float DiffuseDepth = 0.0,
+ output float GlossyDepth = 0.0,
+ output float TransparentDepth = 0.0,
+ output float TransmissionDepth = 0.0)
{
- IsCameraRay = raytype("camera");
- IsShadowRay = raytype("shadow");
- IsDiffuseRay = raytype("diffuse");
- IsGlossyRay = raytype("glossy");
- IsSingularRay = raytype("singular");
- IsReflectionRay = raytype("reflection");
- IsTransmissionRay = raytype("refraction");
- IsVolumeScatterRay = raytype("volume_scatter");
+ IsCameraRay = raytype("camera");
+ IsShadowRay = raytype("shadow");
+ IsDiffuseRay = raytype("diffuse");
+ IsGlossyRay = raytype("glossy");
+ IsSingularRay = raytype("singular");
+ IsReflectionRay = raytype("reflection");
+ IsTransmissionRay = raytype("refraction");
+ IsVolumeScatterRay = raytype("volume_scatter");
- getattribute("path:ray_length", RayLength);
+ getattribute("path:ray_length", RayLength);
- int ray_depth;
- getattribute("path:ray_depth", ray_depth);
- RayDepth = (float)ray_depth;
+ int ray_depth;
+ getattribute("path:ray_depth", ray_depth);
+ RayDepth = (float)ray_depth;
- int diffuse_depth;
- getattribute("path:diffuse_depth", diffuse_depth);
- DiffuseDepth = (float)diffuse_depth;
+ int diffuse_depth;
+ getattribute("path:diffuse_depth", diffuse_depth);
+ DiffuseDepth = (float)diffuse_depth;
- int glossy_depth;
- getattribute("path:glossy_depth", glossy_depth);
- GlossyDepth = (float)glossy_depth;
+ int glossy_depth;
+ getattribute("path:glossy_depth", glossy_depth);
+ GlossyDepth = (float)glossy_depth;
- int transparent_depth;
- getattribute("path:transparent_depth", transparent_depth);
- TransparentDepth = (float)transparent_depth;
+ int transparent_depth;
+ getattribute("path:transparent_depth", transparent_depth);
+ TransparentDepth = (float)transparent_depth;
- int transmission_depth;
- getattribute("path:transmission_depth", transmission_depth);
- TransmissionDepth = (float)transmission_depth;
+ int transmission_depth;
+ getattribute("path:transmission_depth", transmission_depth);
+ TransmissionDepth = (float)transmission_depth;
}
-
diff --git a/intern/cycles/kernel/shaders/node_magic_texture.osl b/intern/cycles/kernel/shaders/node_magic_texture.osl
index 8d6af391e04..aa700e575ef 100644
--- a/intern/cycles/kernel/shaders/node_magic_texture.osl
+++ b/intern/cycles/kernel/shaders/node_magic_texture.osl
@@ -21,91 +21,89 @@
color magic(point p, int n, float distortion)
{
- float dist = distortion;
-
- float x = sin(( p[0] + p[1] + p[2]) * 5.0);
- float y = cos((-p[0] + p[1] - p[2]) * 5.0);
- float z = -cos((-p[0] - p[1] + p[2]) * 5.0);
-
- if (n > 0) {
- x *= dist;
- y *= dist;
- z *= dist;
- y = -cos(x - y + z);
- y *= dist;
-
- if (n > 1) {
- x = cos(x - y - z);
- x *= dist;
-
- if (n > 2) {
- z = sin(-x - y - z);
- z *= dist;
-
- if (n > 3) {
- x = -cos(-x + y - z);
- x *= dist;
-
- if (n > 4) {
- y = -sin(-x + y + z);
- y *= dist;
-
- if (n > 5) {
- y = -cos(-x + y + z);
- y *= dist;
-
- if (n > 6) {
- x = cos(x + y + z);
- x *= dist;
-
- if (n > 7) {
- z = sin(x + y - z);
- z *= dist;
-
- if (n > 8) {
- x = -cos(-x - y + z);
- x *= dist;
-
- if (n > 9) {
- y = -sin(x - y + z);
- y *= dist;
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
-
- if (dist != 0.0) {
- dist *= 2.0;
- x /= dist;
- y /= dist;
- z /= dist;
- }
-
- return color(0.5 - x, 0.5 - y, 0.5 - z);
+ float dist = distortion;
+
+ float x = sin((p[0] + p[1] + p[2]) * 5.0);
+ float y = cos((-p[0] + p[1] - p[2]) * 5.0);
+ float z = -cos((-p[0] - p[1] + p[2]) * 5.0);
+
+ if (n > 0) {
+ x *= dist;
+ y *= dist;
+ z *= dist;
+ y = -cos(x - y + z);
+ y *= dist;
+
+ if (n > 1) {
+ x = cos(x - y - z);
+ x *= dist;
+
+ if (n > 2) {
+ z = sin(-x - y - z);
+ z *= dist;
+
+ if (n > 3) {
+ x = -cos(-x + y - z);
+ x *= dist;
+
+ if (n > 4) {
+ y = -sin(-x + y + z);
+ y *= dist;
+
+ if (n > 5) {
+ y = -cos(-x + y + z);
+ y *= dist;
+
+ if (n > 6) {
+ x = cos(x + y + z);
+ x *= dist;
+
+ if (n > 7) {
+ z = sin(x + y - z);
+ z *= dist;
+
+ if (n > 8) {
+ x = -cos(-x - y + z);
+ x *= dist;
+
+ if (n > 9) {
+ y = -sin(x - y + z);
+ y *= dist;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if (dist != 0.0) {
+ dist *= 2.0;
+ x /= dist;
+ y /= dist;
+ z /= dist;
+ }
+
+ return color(0.5 - x, 0.5 - y, 0.5 - z);
}
-shader node_magic_texture(
- int use_mapping = 0,
- matrix mapping = matrix(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
- int depth = 2,
- float Distortion = 5.0,
- float Scale = 5.0,
- point Vector = P,
- output float Fac = 0.0,
- output color Color = 0.0)
+shader node_magic_texture(int use_mapping = 0,
+ matrix mapping = matrix(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
+ int depth = 2,
+ float Distortion = 5.0,
+ float Scale = 5.0,
+ point Vector = P,
+ output float Fac = 0.0,
+ output color Color = 0.0)
{
- point p = Vector;
+ point p = Vector;
- if (use_mapping)
- p = transform(mapping, p);
+ if (use_mapping)
+ p = transform(mapping, p);
- Color = magic(p * Scale, depth, Distortion);
- Fac = (Color[0] + Color[1] + Color[2]) * (1.0 / 3.0);
+ Color = magic(p * Scale, depth, Distortion);
+ Fac = (Color[0] + Color[1] + Color[2]) * (1.0 / 3.0);
}
-
diff --git a/intern/cycles/kernel/shaders/node_mapping.osl b/intern/cycles/kernel/shaders/node_mapping.osl
index 69106957ee4..f5cc2d1c5dd 100644
--- a/intern/cycles/kernel/shaders/node_mapping.osl
+++ b/intern/cycles/kernel/shaders/node_mapping.osl
@@ -16,18 +16,17 @@
#include "stdosl.h"
-shader node_mapping(
- matrix Matrix = matrix(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
- point mapping_min = point(0.0, 0.0, 0.0),
- point mapping_max = point(0.0, 0.0, 0.0),
- int use_minmax = 0,
- point VectorIn = point(0.0, 0.0, 0.0),
- output point VectorOut = point(0.0, 0.0, 0.0))
+shader node_mapping(matrix Matrix = matrix(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
+ point mapping_min = point(0.0, 0.0, 0.0),
+ point mapping_max = point(0.0, 0.0, 0.0),
+ int use_minmax = 0,
+ point VectorIn = point(0.0, 0.0, 0.0),
+ output point VectorOut = point(0.0, 0.0, 0.0))
{
- point p = transform(Matrix, VectorIn);
+ point p = transform(Matrix, VectorIn);
- if (use_minmax)
- p = min(max(mapping_min, p), mapping_max);
-
- VectorOut = p;
+ if (use_minmax)
+ p = min(max(mapping_min, p), mapping_max);
+
+ VectorOut = p;
}
diff --git a/intern/cycles/kernel/shaders/node_math.osl b/intern/cycles/kernel/shaders/node_math.osl
index aa9f6e671c3..8830339e05f 100644
--- a/intern/cycles/kernel/shaders/node_math.osl
+++ b/intern/cycles/kernel/shaders/node_math.osl
@@ -18,107 +18,105 @@
float safe_divide(float a, float b)
{
- float result;
+ float result;
- if (b == 0.0)
- result = 0.0;
- else
- result = a / b;
-
- return result;
+ if (b == 0.0)
+ result = 0.0;
+ else
+ result = a / b;
+
+ return result;
}
float safe_modulo(float a, float b)
{
- float result;
+ float result;
+
+ if (b == 0.0)
+ result = 0.0;
+ else
+ result = fmod(a, b);
- if (b == 0.0)
- result = 0.0;
- else
- result = fmod(a, b);
-
- return result;
+ return result;
}
float safe_sqrt(float a)
{
- float result;
+ float result;
- if (a > 0.0)
- result = sqrt(a);
- else
- result = 0.0;
+ if (a > 0.0)
+ result = sqrt(a);
+ else
+ result = 0.0;
- return result;
+ return result;
}
float safe_log(float a, float b)
{
- if (a < 0.0 || b < 0.0)
- return 0.0;
-
- return log(a) / log(b);
+ if (a < 0.0 || b < 0.0)
+ return 0.0;
+
+ return log(a) / log(b);
}
-shader node_math(
- string type = "add",
- int use_clamp = 0,
- float Value1 = 0.0,
- float Value2 = 0.0,
- output float Value = 0.0)
+shader node_math(string type = "add",
+ int use_clamp = 0,
+ float Value1 = 0.0,
+ float Value2 = 0.0,
+ output float Value = 0.0)
{
- /* OSL asin, acos, pow check for values that could give rise to nan */
+ /* OSL asin, acos, pow check for values that could give rise to nan */
- if (type == "add")
- Value = Value1 + Value2;
- else if (type == "subtract")
- Value = Value1 - Value2;
- else if (type == "multiply")
- Value = Value1 * Value2;
- else if (type == "divide")
- Value = safe_divide(Value1, Value2);
- else if (type == "sine")
- Value = sin(Value1);
- else if (type == "cosine")
- Value = cos(Value1);
- else if (type == "tangent")
- Value = tan(Value1);
- else if (type == "arcsine")
- Value = asin(Value1);
- else if (type == "arccosine")
- Value = acos(Value1);
- else if (type == "arctangent")
- Value = atan(Value1);
- else if (type == "power")
- Value = pow(Value1, Value2);
- else if (type == "logarithm")
- Value = safe_log(Value1, Value2);
- else if (type == "minimum")
- Value = min(Value1, Value2);
- else if (type == "maximum")
- Value = max(Value1, Value2);
- else if (type == "round")
- Value = floor(Value1 + 0.5);
- else if (type == "less_than")
- Value = Value1 < Value2;
- else if (type == "greater_than")
- Value = Value1 > Value2;
- else if (type == "modulo")
- Value = safe_modulo(Value1, Value2);
- else if (type == "absolute")
- Value = fabs(Value1);
- else if (type == "arctan2")
- Value = atan2(Value1, Value2);
- else if (type == "floor")
- Value = floor(Value1);
- else if (type == "ceil")
- Value = ceil(Value1);
- else if (type == "fract")
- Value = Value1 - floor(Value1);
- else if (type == "sqrt")
- Value = safe_sqrt(Value1);
+ if (type == "add")
+ Value = Value1 + Value2;
+ else if (type == "subtract")
+ Value = Value1 - Value2;
+ else if (type == "multiply")
+ Value = Value1 * Value2;
+ else if (type == "divide")
+ Value = safe_divide(Value1, Value2);
+ else if (type == "sine")
+ Value = sin(Value1);
+ else if (type == "cosine")
+ Value = cos(Value1);
+ else if (type == "tangent")
+ Value = tan(Value1);
+ else if (type == "arcsine")
+ Value = asin(Value1);
+ else if (type == "arccosine")
+ Value = acos(Value1);
+ else if (type == "arctangent")
+ Value = atan(Value1);
+ else if (type == "power")
+ Value = pow(Value1, Value2);
+ else if (type == "logarithm")
+ Value = safe_log(Value1, Value2);
+ else if (type == "minimum")
+ Value = min(Value1, Value2);
+ else if (type == "maximum")
+ Value = max(Value1, Value2);
+ else if (type == "round")
+ Value = floor(Value1 + 0.5);
+ else if (type == "less_than")
+ Value = Value1 < Value2;
+ else if (type == "greater_than")
+ Value = Value1 > Value2;
+ else if (type == "modulo")
+ Value = safe_modulo(Value1, Value2);
+ else if (type == "absolute")
+ Value = fabs(Value1);
+ else if (type == "arctan2")
+ Value = atan2(Value1, Value2);
+ else if (type == "floor")
+ Value = floor(Value1);
+ else if (type == "ceil")
+ Value = ceil(Value1);
+ else if (type == "fract")
+ Value = Value1 - floor(Value1);
+ else if (type == "sqrt")
+ Value = safe_sqrt(Value1);
- if (use_clamp)
- Value = clamp(Value, 0.0, 1.0);
+ if (use_clamp)
+ Value = clamp(Value, 0.0, 1.0);
}
-
diff --git a/intern/cycles/kernel/shaders/node_mix.osl b/intern/cycles/kernel/shaders/node_mix.osl
index 0862c34b6e1..8caea6803ed 100644
--- a/intern/cycles/kernel/shaders/node_mix.osl
+++ b/intern/cycles/kernel/shaders/node_mix.osl
@@ -19,311 +19,312 @@
color node_mix_blend(float t, color col1, color col2)
{
- return mix(col1, col2, t);
+ return mix(col1, col2, t);
}
color node_mix_add(float t, color col1, color col2)
{
- return mix(col1, col1 + col2, t);
+ return mix(col1, col1 + col2, t);
}
color node_mix_mul(float t, color col1, color col2)
{
- return mix(col1, col1 * col2, t);
+ return mix(col1, col1 * col2, t);
}
color node_mix_screen(float t, color col1, color col2)
{
- float tm = 1.0 - t;
+ float tm = 1.0 - t;
- return color(1.0) - (color(tm) + t * (color(1.0) - col2)) * (color(1.0) - col1);
+ return color(1.0) - (color(tm) + t * (color(1.0) - col2)) * (color(1.0) - col1);
}
color node_mix_overlay(float t, color col1, color col2)
{
- float tm = 1.0 - t;
-
- color outcol = col1;
-
- if (outcol[0] < 0.5)
- outcol[0] *= tm + 2.0 * t * col2[0];
- else
- outcol[0] = 1.0 - (tm + 2.0 * t * (1.0 - col2[0])) * (1.0 - outcol[0]);
-
- if (outcol[1] < 0.5)
- outcol[1] *= tm + 2.0 * t * col2[1];
- else
- outcol[1] = 1.0 - (tm + 2.0 * t * (1.0 - col2[1])) * (1.0 - outcol[1]);
-
- if (outcol[2] < 0.5)
- outcol[2] *= tm + 2.0 * t * col2[2];
- else
- outcol[2] = 1.0 - (tm + 2.0 * t * (1.0 - col2[2])) * (1.0 - outcol[2]);
-
- return outcol;
+ float tm = 1.0 - t;
+
+ color outcol = col1;
+
+ if (outcol[0] < 0.5)
+ outcol[0] *= tm + 2.0 * t * col2[0];
+ else
+ outcol[0] = 1.0 - (tm + 2.0 * t * (1.0 - col2[0])) * (1.0 - outcol[0]);
+
+ if (outcol[1] < 0.5)
+ outcol[1] *= tm + 2.0 * t * col2[1];
+ else
+ outcol[1] = 1.0 - (tm + 2.0 * t * (1.0 - col2[1])) * (1.0 - outcol[1]);
+
+ if (outcol[2] < 0.5)
+ outcol[2] *= tm + 2.0 * t * col2[2];
+ else
+ outcol[2] = 1.0 - (tm + 2.0 * t * (1.0 - col2[2])) * (1.0 - outcol[2]);
+
+ return outcol;
}
color node_mix_sub(float t, color col1, color col2)
{
- return mix(col1, col1 - col2, t);
+ return mix(col1, col1 - col2, t);
}
color node_mix_div(float t, color col1, color col2)
{
- float tm = 1.0 - t;
+ float tm = 1.0 - t;
- color outcol = col1;
+ color outcol = col1;
- if (col2[0] != 0.0) outcol[0] = tm * outcol[0] + t * outcol[0] / col2[0];
- if (col2[1] != 0.0) outcol[1] = tm * outcol[1] + t * outcol[1] / col2[1];
- if (col2[2] != 0.0) outcol[2] = tm * outcol[2] + t * outcol[2] / col2[2];
+ if (col2[0] != 0.0)
+ outcol[0] = tm * outcol[0] + t * outcol[0] / col2[0];
+ if (col2[1] != 0.0)
+ outcol[1] = tm * outcol[1] + t * outcol[1] / col2[1];
+ if (col2[2] != 0.0)
+ outcol[2] = tm * outcol[2] + t * outcol[2] / col2[2];
- return outcol;
+ return outcol;
}
color node_mix_diff(float t, color col1, color col2)
{
- return mix(col1, abs(col1 - col2), t);
+ return mix(col1, abs(col1 - col2), t);
}
color node_mix_dark(float t, color col1, color col2)
{
- return min(col1, col2) * t + col1 * (1.0 - t);
+ return min(col1, col2) * t + col1 * (1.0 - t);
}
color node_mix_light(float t, color col1, color col2)
{
- return max(col1, col2 * t);
+ return max(col1, col2 * t);
}
color node_mix_dodge(float t, color col1, color col2)
{
- color outcol = col1;
-
- if (outcol[0] != 0.0) {
- float tmp = 1.0 - t * col2[0];
- if (tmp <= 0.0)
- outcol[0] = 1.0;
- else if ((tmp = outcol[0] / tmp) > 1.0)
- outcol[0] = 1.0;
- else
- outcol[0] = tmp;
- }
- if (outcol[1] != 0.0) {
- float tmp = 1.0 - t * col2[1];
- if (tmp <= 0.0)
- outcol[1] = 1.0;
- else if ((tmp = outcol[1] / tmp) > 1.0)
- outcol[1] = 1.0;
- else
- outcol[1] = tmp;
- }
- if (outcol[2] != 0.0) {
- float tmp = 1.0 - t * col2[2];
- if (tmp <= 0.0)
- outcol[2] = 1.0;
- else if ((tmp = outcol[2] / tmp) > 1.0)
- outcol[2] = 1.0;
- else
- outcol[2] = tmp;
- }
-
- return outcol;
+ color outcol = col1;
+
+ if (outcol[0] != 0.0) {
+ float tmp = 1.0 - t * col2[0];
+ if (tmp <= 0.0)
+ outcol[0] = 1.0;
+ else if ((tmp = outcol[0] / tmp) > 1.0)
+ outcol[0] = 1.0;
+ else
+ outcol[0] = tmp;
+ }
+ if (outcol[1] != 0.0) {
+ float tmp = 1.0 - t * col2[1];
+ if (tmp <= 0.0)
+ outcol[1] = 1.0;
+ else if ((tmp = outcol[1] / tmp) > 1.0)
+ outcol[1] = 1.0;
+ else
+ outcol[1] = tmp;
+ }
+ if (outcol[2] != 0.0) {
+ float tmp = 1.0 - t * col2[2];
+ if (tmp <= 0.0)
+ outcol[2] = 1.0;
+ else if ((tmp = outcol[2] / tmp) > 1.0)
+ outcol[2] = 1.0;
+ else
+ outcol[2] = tmp;
+ }
+
+ return outcol;
}
color node_mix_burn(float t, color col1, color col2)
{
- float tmp, tm = 1.0 - t;
-
- color outcol = col1;
-
- tmp = tm + t * col2[0];
- if (tmp <= 0.0)
- outcol[0] = 0.0;
- else if ((tmp = (1.0 - (1.0 - outcol[0]) / tmp)) < 0.0)
- outcol[0] = 0.0;
- else if (tmp > 1.0)
- outcol[0] = 1.0;
- else
- outcol[0] = tmp;
-
- tmp = tm + t * col2[1];
- if (tmp <= 0.0)
- outcol[1] = 0.0;
- else if ((tmp = (1.0 - (1.0 - outcol[1]) / tmp)) < 0.0)
- outcol[1] = 0.0;
- else if (tmp > 1.0)
- outcol[1] = 1.0;
- else
- outcol[1] = tmp;
-
- tmp = tm + t * col2[2];
- if (tmp <= 0.0)
- outcol[2] = 0.0;
- else if ((tmp = (1.0 - (1.0 - outcol[2]) / tmp)) < 0.0)
- outcol[2] = 0.0;
- else if (tmp > 1.0)
- outcol[2] = 1.0;
- else
- outcol[2] = tmp;
-
- return outcol;
+ float tmp, tm = 1.0 - t;
+
+ color outcol = col1;
+
+ tmp = tm + t * col2[0];
+ if (tmp <= 0.0)
+ outcol[0] = 0.0;
+ else if ((tmp = (1.0 - (1.0 - outcol[0]) / tmp)) < 0.0)
+ outcol[0] = 0.0;
+ else if (tmp > 1.0)
+ outcol[0] = 1.0;
+ else
+ outcol[0] = tmp;
+
+ tmp = tm + t * col2[1];
+ if (tmp <= 0.0)
+ outcol[1] = 0.0;
+ else if ((tmp = (1.0 - (1.0 - outcol[1]) / tmp)) < 0.0)
+ outcol[1] = 0.0;
+ else if (tmp > 1.0)
+ outcol[1] = 1.0;
+ else
+ outcol[1] = tmp;
+
+ tmp = tm + t * col2[2];
+ if (tmp <= 0.0)
+ outcol[2] = 0.0;
+ else if ((tmp = (1.0 - (1.0 - outcol[2]) / tmp)) < 0.0)
+ outcol[2] = 0.0;
+ else if (tmp > 1.0)
+ outcol[2] = 1.0;
+ else
+ outcol[2] = tmp;
+
+ return outcol;
}
color node_mix_hue(float t, color col1, color col2)
{
- color outcol = col1;
- color hsv2 = rgb_to_hsv(col2);
+ color outcol = col1;
+ color hsv2 = rgb_to_hsv(col2);
- if (hsv2[1] != 0.0) {
- color hsv = rgb_to_hsv(outcol);
- hsv[0] = hsv2[0];
- color tmp = hsv_to_rgb(hsv);
+ if (hsv2[1] != 0.0) {
+ color hsv = rgb_to_hsv(outcol);
+ hsv[0] = hsv2[0];
+ color tmp = hsv_to_rgb(hsv);
- outcol = mix(outcol, tmp, t);
- }
+ outcol = mix(outcol, tmp, t);
+ }
- return outcol;
+ return outcol;
}
color node_mix_sat(float t, color col1, color col2)
{
- float tm = 1.0 - t;
+ float tm = 1.0 - t;
- color outcol = col1;
+ color outcol = col1;
- color hsv = rgb_to_hsv(outcol);
+ color hsv = rgb_to_hsv(outcol);
- if (hsv[1] != 0.0) {
- color hsv2 = rgb_to_hsv(col2);
+ if (hsv[1] != 0.0) {
+ color hsv2 = rgb_to_hsv(col2);
- hsv[1] = tm * hsv[1] + t * hsv2[1];
- outcol = hsv_to_rgb(hsv);
- }
+ hsv[1] = tm * hsv[1] + t * hsv2[1];
+ outcol = hsv_to_rgb(hsv);
+ }
- return outcol;
+ return outcol;
}
color node_mix_val(float t, color col1, color col2)
{
- float tm = 1.0 - t;
+ float tm = 1.0 - t;
- color hsv = rgb_to_hsv(col1);
- color hsv2 = rgb_to_hsv(col2);
+ color hsv = rgb_to_hsv(col1);
+ color hsv2 = rgb_to_hsv(col2);
- hsv[2] = tm * hsv[2] + t * hsv2[2];
+ hsv[2] = tm * hsv[2] + t * hsv2[2];
- return hsv_to_rgb(hsv);
+ return hsv_to_rgb(hsv);
}
color node_mix_color(float t, color col1, color col2)
{
- color outcol = col1;
- color hsv2 = rgb_to_hsv(col2);
+ color outcol = col1;
+ color hsv2 = rgb_to_hsv(col2);
- if (hsv2[1] != 0.0) {
- color hsv = rgb_to_hsv(outcol);
- hsv[0] = hsv2[0];
- hsv[1] = hsv2[1];
- color tmp = hsv_to_rgb(hsv);
+ if (hsv2[1] != 0.0) {
+ color hsv = rgb_to_hsv(outcol);
+ hsv[0] = hsv2[0];
+ hsv[1] = hsv2[1];
+ color tmp = hsv_to_rgb(hsv);
- outcol = mix(outcol, tmp, t);
- }
+ outcol = mix(outcol, tmp, t);
+ }
- return outcol;
+ return outcol;
}
color node_mix_soft(float t, color col1, color col2)
{
- float tm = 1.0 - t;
+ float tm = 1.0 - t;
- color one = color(1.0);
- color scr = one - (one - col2) * (one - col1);
+ color one = color(1.0);
+ color scr = one - (one - col2) * (one - col1);
- return tm * col1 + t * ((one - col1) * col2 * col1 + col1 * scr);
+ return tm * col1 + t * ((one - col1) * col2 * col1 + col1 * scr);
}
color node_mix_linear(float t, color col1, color col2)
{
- color outcol = col1;
-
- if (col2[0] > 0.5)
- outcol[0] = col1[0] + t * (2.0 * (col2[0] - 0.5));
- else
- outcol[0] = col1[0] + t * (2.0 * (col2[0]) - 1.0);
-
- if (col2[1] > 0.5)
- outcol[1] = col1[1] + t * (2.0 * (col2[1] - 0.5));
- else
- outcol[1] = col1[1] + t * (2.0 * (col2[1]) - 1.0);
-
- if (col2[2] > 0.5)
- outcol[2] = col1[2] + t * (2.0 * (col2[2] - 0.5));
- else
- outcol[2] = col1[2] + t * (2.0 * (col2[2]) - 1.0);
-
- return outcol;
+ color outcol = col1;
+
+ if (col2[0] > 0.5)
+ outcol[0] = col1[0] + t * (2.0 * (col2[0] - 0.5));
+ else
+ outcol[0] = col1[0] + t * (2.0 * (col2[0]) - 1.0);
+
+ if (col2[1] > 0.5)
+ outcol[1] = col1[1] + t * (2.0 * (col2[1] - 0.5));
+ else
+ outcol[1] = col1[1] + t * (2.0 * (col2[1]) - 1.0);
+
+ if (col2[2] > 0.5)
+ outcol[2] = col1[2] + t * (2.0 * (col2[2] - 0.5));
+ else
+ outcol[2] = col1[2] + t * (2.0 * (col2[2]) - 1.0);
+
+ return outcol;
}
color node_mix_clamp(color col)
{
- color outcol = col;
+ color outcol = col;
- outcol[0] = clamp(col[0], 0.0, 1.0);
- outcol[1] = clamp(col[1], 0.0, 1.0);
- outcol[2] = clamp(col[2], 0.0, 1.0);
+ outcol[0] = clamp(col[0], 0.0, 1.0);
+ outcol[1] = clamp(col[1], 0.0, 1.0);
+ outcol[2] = clamp(col[2], 0.0, 1.0);
- return outcol;
+ return outcol;
}
-shader node_mix(
- string type = "mix",
- int use_clamp = 0,
- float Fac = 0.5,
- color Color1 = 0.0,
- color Color2 = 0.0,
- output color Color = 0.0)
+shader node_mix(string type = "mix",
+ int use_clamp = 0,
+ float Fac = 0.5,
+ color Color1 = 0.0,
+ color Color2 = 0.0,
+ output color Color = 0.0)
{
- float t = clamp(Fac, 0.0, 1.0);
-
- if (type == "mix")
- Color = node_mix_blend(t, Color1, Color2);
- if (type == "add")
- Color = node_mix_add(t, Color1, Color2);
- if (type == "multiply")
- Color = node_mix_mul(t, Color1, Color2);
- if (type == "screen")
- Color = node_mix_screen(t, Color1, Color2);
- if (type == "overlay")
- Color = node_mix_overlay(t, Color1, Color2);
- if (type == "subtract")
- Color = node_mix_sub(t, Color1, Color2);
- if (type == "divide")
- Color = node_mix_div(t, Color1, Color2);
- if (type == "difference")
- Color = node_mix_diff(t, Color1, Color2);
- if (type == "darken")
- Color = node_mix_dark(t, Color1, Color2);
- if (type == "lighten")
- Color = node_mix_light(t, Color1, Color2);
- if (type == "dodge")
- Color = node_mix_dodge(t, Color1, Color2);
- if (type == "burn")
- Color = node_mix_burn(t, Color1, Color2);
- if (type == "hue")
- Color = node_mix_hue(t, Color1, Color2);
- if (type == "saturation")
- Color = node_mix_sat(t, Color1, Color2);
- if (type == "value")
- Color = node_mix_val (t, Color1, Color2);
- if (type == "color")
- Color = node_mix_color(t, Color1, Color2);
- if (type == "soft_light")
- Color = node_mix_soft(t, Color1, Color2);
- if (type == "linear_light")
- Color = node_mix_linear(t, Color1, Color2);
-
- if (use_clamp)
- Color = node_mix_clamp(Color);
+ float t = clamp(Fac, 0.0, 1.0);
+
+ if (type == "mix")
+ Color = node_mix_blend(t, Color1, Color2);
+ if (type == "add")
+ Color = node_mix_add(t, Color1, Color2);
+ if (type == "multiply")
+ Color = node_mix_mul(t, Color1, Color2);
+ if (type == "screen")
+ Color = node_mix_screen(t, Color1, Color2);
+ if (type == "overlay")
+ Color = node_mix_overlay(t, Color1, Color2);
+ if (type == "subtract")
+ Color = node_mix_sub(t, Color1, Color2);
+ if (type == "divide")
+ Color = node_mix_div(t, Color1, Color2);
+ if (type == "difference")
+ Color = node_mix_diff(t, Color1, Color2);
+ if (type == "darken")
+ Color = node_mix_dark(t, Color1, Color2);
+ if (type == "lighten")
+ Color = node_mix_light(t, Color1, Color2);
+ if (type == "dodge")
+ Color = node_mix_dodge(t, Color1, Color2);
+ if (type == "burn")
+ Color = node_mix_burn(t, Color1, Color2);
+ if (type == "hue")
+ Color = node_mix_hue(t, Color1, Color2);
+ if (type == "saturation")
+ Color = node_mix_sat(t, Color1, Color2);
+ if (type == "value")
+ Color = node_mix_val(t, Color1, Color2);
+ if (type == "color")
+ Color = node_mix_color(t, Color1, Color2);
+ if (type == "soft_light")
+ Color = node_mix_soft(t, Color1, Color2);
+ if (type == "linear_light")
+ Color = node_mix_linear(t, Color1, Color2);
+
+ if (use_clamp)
+ Color = node_mix_clamp(Color);
}
-
diff --git a/intern/cycles/kernel/shaders/node_mix_closure.osl b/intern/cycles/kernel/shaders/node_mix_closure.osl
index 5946dfdaaba..517c59c8786 100644
--- a/intern/cycles/kernel/shaders/node_mix_closure.osl
+++ b/intern/cycles/kernel/shaders/node_mix_closure.osl
@@ -16,13 +16,11 @@
#include "stdosl.h"
-shader node_mix_closure(
- float Fac = 0.5,
- closure color Closure1 = 0,
- closure color Closure2 = 0,
- output closure color Closure = 0)
+shader node_mix_closure(float Fac = 0.5,
+ closure color Closure1 = 0,
+ closure color Closure2 = 0,
+ output closure color Closure = 0)
{
- float t = clamp(Fac, 0.0, 1.0);
- Closure = (1.0 - t) * Closure1 + t * Closure2;
+ float t = clamp(Fac, 0.0, 1.0);
+ Closure = (1.0 - t) * Closure1 + t * Closure2;
}
-
diff --git a/intern/cycles/kernel/shaders/node_musgrave_texture.osl b/intern/cycles/kernel/shaders/node_musgrave_texture.osl
index 454b3834081..a7877c43d46 100644
--- a/intern/cycles/kernel/shaders/node_musgrave_texture.osl
+++ b/intern/cycles/kernel/shaders/node_musgrave_texture.osl
@@ -28,24 +28,24 @@
float noise_musgrave_fBm(point ip, float H, float lacunarity, float octaves)
{
- float rmd;
- float value = 0.0;
- float pwr = 1.0;
- float pwHL = pow(lacunarity, -H);
- int i;
- point p = ip;
-
- for (i = 0; i < (int)octaves; i++) {
- value += safe_noise(p, "signed") * pwr;
- pwr *= pwHL;
- p *= lacunarity;
- }
-
- rmd = octaves - floor(octaves);
- if (rmd != 0.0)
- value += rmd * safe_noise(p, "signed") * pwr;
-
- return value;
+ float rmd;
+ float value = 0.0;
+ float pwr = 1.0;
+ float pwHL = pow(lacunarity, -H);
+ int i;
+ point p = ip;
+
+ for (i = 0; i < (int)octaves; i++) {
+ value += safe_noise(p, "signed") * pwr;
+ pwr *= pwHL;
+ p *= lacunarity;
+ }
+
+ rmd = octaves - floor(octaves);
+ if (rmd != 0.0)
+ value += rmd * safe_noise(p, "signed") * pwr;
+
+ return value;
}
/* Musgrave Multifractal
@@ -57,24 +57,24 @@ float noise_musgrave_fBm(point ip, float H, float lacunarity, float octaves)
float noise_musgrave_multi_fractal(point ip, float H, float lacunarity, float octaves)
{
- float rmd;
- float value = 1.0;
- float pwr = 1.0;
- float pwHL = pow(lacunarity, -H);
- int i;
- point p = ip;
-
- for (i = 0; i < (int)octaves; i++) {
- value *= (pwr * safe_noise(p, "signed") + 1.0);
- pwr *= pwHL;
- p *= lacunarity;
- }
-
- rmd = octaves - floor(octaves);
- if (rmd != 0.0)
- value *= (rmd * pwr * safe_noise(p, "signed") + 1.0); /* correct? */
-
- return value;
+ float rmd;
+ float value = 1.0;
+ float pwr = 1.0;
+ float pwHL = pow(lacunarity, -H);
+ int i;
+ point p = ip;
+
+ for (i = 0; i < (int)octaves; i++) {
+ value *= (pwr * safe_noise(p, "signed") + 1.0);
+ pwr *= pwHL;
+ p *= lacunarity;
+ }
+
+ rmd = octaves - floor(octaves);
+ if (rmd != 0.0)
+ value *= (rmd * pwr * safe_noise(p, "signed") + 1.0); /* correct? */
+
+ return value;
}
/* Musgrave Heterogeneous Terrain
@@ -85,32 +85,33 @@ float noise_musgrave_multi_fractal(point ip, float H, float lacunarity, float oc
* offset: raises the terrain from `sea level'
*/
-float noise_musgrave_hetero_terrain(point ip, float H, float lacunarity, float octaves, float offset)
+float noise_musgrave_hetero_terrain(
+ point ip, float H, float lacunarity, float octaves, float offset)
{
- float value, increment, rmd;
- float pwHL = pow(lacunarity, -H);
- float pwr = pwHL;
- int i;
- point p = ip;
-
- /* first unscaled octave of function; later octaves are scaled */
- value = offset + safe_noise(p, "signed");
- p *= lacunarity;
-
- for (i = 1; i < (int)octaves; i++) {
- increment = (safe_noise(p, "signed") + offset) * pwr * value;
- value += increment;
- pwr *= pwHL;
- p *= lacunarity;
- }
-
- rmd = octaves - floor(octaves);
- if (rmd != 0.0) {
- increment = (safe_noise(p, "signed") + offset) * pwr * value;
- value += rmd * increment;
- }
-
- return value;
+ float value, increment, rmd;
+ float pwHL = pow(lacunarity, -H);
+ float pwr = pwHL;
+ int i;
+ point p = ip;
+
+ /* first unscaled octave of function; later octaves are scaled */
+ value = offset + safe_noise(p, "signed");
+ p *= lacunarity;
+
+ for (i = 1; i < (int)octaves; i++) {
+ increment = (safe_noise(p, "signed") + offset) * pwr * value;
+ value += increment;
+ pwr *= pwHL;
+ p *= lacunarity;
+ }
+
+ rmd = octaves - floor(octaves);
+ if (rmd != 0.0) {
+ increment = (safe_noise(p, "signed") + offset) * pwr * value;
+ value += rmd * increment;
+ }
+
+ return value;
}
/* Hybrid Additive/Multiplicative Multifractal Terrain
@@ -121,35 +122,35 @@ float noise_musgrave_hetero_terrain(point ip, float H, float lacunarity, float o
* offset: raises the terrain from `sea level'
*/
-float noise_musgrave_hybrid_multi_fractal(point ip, float H, float lacunarity,
- float octaves, float offset, float gain)
+float noise_musgrave_hybrid_multi_fractal(
+ point ip, float H, float lacunarity, float octaves, float offset, float gain)
{
- float result, signal, weight, rmd;
- float pwHL = pow(lacunarity, -H);
- float pwr = pwHL;
- int i;
- point p = ip;
-
- result = safe_noise(p, "signed") + offset;
- weight = gain * result;
- p *= lacunarity;
-
- for (i = 1; (weight > 0.001) && (i < (int)octaves); i++) {
- if (weight > 1.0)
- weight = 1.0;
-
- signal = (safe_noise(p, "signed") + offset) * pwr;
- pwr *= pwHL;
- result += weight * signal;
- weight *= gain * signal;
- p *= lacunarity;
- }
-
- rmd = octaves - floor(octaves);
- if (rmd != 0.0)
- result += rmd * ((safe_noise(p, "signed") + offset) * pwr);
-
- return result;
+ float result, signal, weight, rmd;
+ float pwHL = pow(lacunarity, -H);
+ float pwr = pwHL;
+ int i;
+ point p = ip;
+
+ result = safe_noise(p, "signed") + offset;
+ weight = gain * result;
+ p *= lacunarity;
+
+ for (i = 1; (weight > 0.001) && (i < (int)octaves); i++) {
+ if (weight > 1.0)
+ weight = 1.0;
+
+ signal = (safe_noise(p, "signed") + offset) * pwr;
+ pwr *= pwHL;
+ result += weight * signal;
+ weight *= gain * signal;
+ p *= lacunarity;
+ }
+
+ rmd = octaves - floor(octaves);
+ if (rmd != 0.0)
+ result += rmd * ((safe_noise(p, "signed") + offset) * pwr);
+
+ return result;
}
/* Ridged Multifractal Terrain
@@ -160,72 +161,73 @@ float noise_musgrave_hybrid_multi_fractal(point ip, float H, float lacunarity,
* offset: raises the terrain from `sea level'
*/
-float noise_musgrave_ridged_multi_fractal(point ip, float H, float lacunarity,
- float octaves, float offset, float gain)
+float noise_musgrave_ridged_multi_fractal(
+ point ip, float H, float lacunarity, float octaves, float offset, float gain)
{
- float result, signal, weight;
- float pwHL = pow(lacunarity, -H);
- float pwr = pwHL;
- int i;
- point p = ip;
-
- signal = offset - fabs(safe_noise(p, "signed"));
- signal *= signal;
- result = signal;
- weight = 1.0;
-
- for (i = 1; i < (int)octaves; i++) {
- p *= lacunarity;
- weight = clamp(signal * gain, 0.0, 1.0);
- signal = offset - fabs(safe_noise(p, "signed"));
- signal *= signal;
- signal *= weight;
- result += signal * pwr;
- pwr *= pwHL;
- }
-
- return result;
+ float result, signal, weight;
+ float pwHL = pow(lacunarity, -H);
+ float pwr = pwHL;
+ int i;
+ point p = ip;
+
+ signal = offset - fabs(safe_noise(p, "signed"));
+ signal *= signal;
+ result = signal;
+ weight = 1.0;
+
+ for (i = 1; i < (int)octaves; i++) {
+ p *= lacunarity;
+ weight = clamp(signal * gain, 0.0, 1.0);
+ signal = offset - fabs(safe_noise(p, "signed"));
+ signal *= signal;
+ signal *= weight;
+ result += signal * pwr;
+ pwr *= pwHL;
+ }
+
+ return result;
}
/* Shader */
shader node_musgrave_texture(
- int use_mapping = 0,
- matrix mapping = matrix(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
- string type = "fBM",
- float Dimension = 2.0,
- float Lacunarity = 1.0,
- float Detail = 2.0,
- float Offset = 0.0,
- float Gain = 1.0,
- float Scale = 5.0,
- point Vector = P,
- output float Fac = 0.0,
- output color Color = 0.0)
+ int use_mapping = 0,
+ matrix mapping = matrix(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
+ string type = "fBM",
+ float Dimension = 2.0,
+ float Lacunarity = 1.0,
+ float Detail = 2.0,
+ float Offset = 0.0,
+ float Gain = 1.0,
+ float Scale = 5.0,
+ point Vector = P,
+ output float Fac = 0.0,
+ output color Color = 0.0)
{
- float dimension = max(Dimension, 1e-5);
- float octaves = clamp(Detail, 0.0, 16.0);
- float lacunarity = max(Lacunarity, 1e-5);
- float intensity = 1.0;
-
- point p = Vector;
-
- if (use_mapping)
- p = transform(mapping, p);
-
- p = p * Scale;
-
- if (type == "multifractal")
- Fac = intensity * noise_musgrave_multi_fractal(p, dimension, lacunarity, octaves);
- else if (type == "fBM")
- Fac = intensity * noise_musgrave_fBm(p, dimension, lacunarity, octaves);
- else if (type == "hybrid_multifractal")
- Fac = intensity * noise_musgrave_hybrid_multi_fractal(p, dimension, lacunarity, octaves, Offset, Gain);
- else if (type == "ridged_multifractal")
- Fac = intensity * noise_musgrave_ridged_multi_fractal(p, dimension, lacunarity, octaves, Offset, Gain);
- else if (type == "hetero_terrain")
- Fac = intensity * noise_musgrave_hetero_terrain(p, dimension, lacunarity, octaves, Offset);
-
- Color = color(Fac, Fac, Fac);
+ float dimension = max(Dimension, 1e-5);
+ float octaves = clamp(Detail, 0.0, 16.0);
+ float lacunarity = max(Lacunarity, 1e-5);
+ float intensity = 1.0;
+
+ point p = Vector;
+
+ if (use_mapping)
+ p = transform(mapping, p);
+
+ p = p * Scale;
+
+ if (type == "multifractal")
+ Fac = intensity * noise_musgrave_multi_fractal(p, dimension, lacunarity, octaves);
+ else if (type == "fBM")
+ Fac = intensity * noise_musgrave_fBm(p, dimension, lacunarity, octaves);
+ else if (type == "hybrid_multifractal")
+ Fac = intensity *
+ noise_musgrave_hybrid_multi_fractal(p, dimension, lacunarity, octaves, Offset, Gain);
+ else if (type == "ridged_multifractal")
+ Fac = intensity *
+ noise_musgrave_ridged_multi_fractal(p, dimension, lacunarity, octaves, Offset, Gain);
+ else if (type == "hetero_terrain")
+ Fac = intensity * noise_musgrave_hetero_terrain(p, dimension, lacunarity, octaves, Offset);
+
+ Color = color(Fac, Fac, Fac);
}
-
diff --git a/intern/cycles/kernel/shaders/node_noise_texture.osl b/intern/cycles/kernel/shaders/node_noise_texture.osl
index 42a30897341..2cbd571e206 100644
--- a/intern/cycles/kernel/shaders/node_noise_texture.osl
+++ b/intern/cycles/kernel/shaders/node_noise_texture.osl
@@ -21,41 +21,40 @@
float noise(point ip, float distortion, float detail, output color Color)
{
- point r;
- point p = ip;
- int hard = 0;
-
- if (distortion != 0.0) {
- r[0] = safe_noise(p + point(13.5), "unsigned") * distortion;
- r[1] = safe_noise(p, "unsigned") * distortion;
- r[2] = safe_noise(p - point(13.5), "unsigned") * distortion;
-
- p += r;
- }
-
- float fac = noise_turbulence(p, detail, hard);
-
- Color = color(fac, noise_turbulence(point(p[1], p[0], p[2]), detail, hard),
- noise_turbulence(point(p[1], p[2], p[0]), detail, hard));
-
- return fac;
+ point r;
+ point p = ip;
+ int hard = 0;
+
+ if (distortion != 0.0) {
+ r[0] = safe_noise(p + point(13.5), "unsigned") * distortion;
+ r[1] = safe_noise(p, "unsigned") * distortion;
+ r[2] = safe_noise(p - point(13.5), "unsigned") * distortion;
+
+ p += r;
+ }
+
+ float fac = noise_turbulence(p, detail, hard);
+
+ Color = color(fac,
+ noise_turbulence(point(p[1], p[0], p[2]), detail, hard),
+ noise_turbulence(point(p[1], p[2], p[0]), detail, hard));
+
+ return fac;
}
-shader node_noise_texture(
- int use_mapping = 0,
- matrix mapping = matrix(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
- float Distortion = 0.0,
- float Scale = 5.0,
- float Detail = 2.0,
- point Vector = P,
- output float Fac = 0.0,
- output color Color = 0.0)
+shader node_noise_texture(int use_mapping = 0,
+ matrix mapping = matrix(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
+ float Distortion = 0.0,
+ float Scale = 5.0,
+ float Detail = 2.0,
+ point Vector = P,
+ output float Fac = 0.0,
+ output color Color = 0.0)
{
- point p = Vector;
+ point p = Vector;
- if (use_mapping)
- p = transform(mapping, p);
+ if (use_mapping)
+ p = transform(mapping, p);
- Fac = noise(p * Scale, Distortion, Detail, Color);
+ Fac = noise(p * Scale, Distortion, Detail, Color);
}
-
diff --git a/intern/cycles/kernel/shaders/node_normal.osl b/intern/cycles/kernel/shaders/node_normal.osl
index 7307971eddd..1d20c3e7cac 100644
--- a/intern/cycles/kernel/shaders/node_normal.osl
+++ b/intern/cycles/kernel/shaders/node_normal.osl
@@ -16,13 +16,11 @@
#include "stdosl.h"
-shader node_normal(
- normal direction = normal(0.0, 0.0, 0.0),
- normal NormalIn = normal(0.0, 0.0, 0.0),
- output normal NormalOut = normal(0.0, 0.0, 0.0),
- output float Dot = 1.0)
+shader node_normal(normal direction = normal(0.0, 0.0, 0.0),
+ normal NormalIn = normal(0.0, 0.0, 0.0),
+ output normal NormalOut = normal(0.0, 0.0, 0.0),
+ output float Dot = 1.0)
{
- NormalOut = normalize(direction);
- Dot = dot(NormalOut, normalize(NormalIn));
+ NormalOut = normalize(direction);
+ Dot = dot(NormalOut, normalize(NormalIn));
}
-
diff --git a/intern/cycles/kernel/shaders/node_normal_map.osl b/intern/cycles/kernel/shaders/node_normal_map.osl
index fda6f12a5da..90b593d00bc 100644
--- a/intern/cycles/kernel/shaders/node_normal_map.osl
+++ b/intern/cycles/kernel/shaders/node_normal_map.osl
@@ -16,79 +16,75 @@
#include "stdosl.h"
-shader node_normal_map(
- normal NormalIn = N,
- float Strength = 1.0,
- color Color = color(0.5, 0.5, 1.0),
- string space = "tangent",
- string attr_name = "geom:tangent",
- string attr_sign_name = "geom:tangent_sign",
- output normal Normal = NormalIn)
+shader node_normal_map(normal NormalIn = N,
+ float Strength = 1.0,
+ color Color = color(0.5, 0.5, 1.0),
+ string space = "tangent",
+ string attr_name = "geom:tangent",
+ string attr_sign_name = "geom:tangent_sign",
+ output normal Normal = NormalIn)
{
- color mcolor = 2.0 * color(Color[0] - 0.5, Color[1] - 0.5, Color[2] - 0.5);
- int is_backfacing = backfacing();
+ color mcolor = 2.0 * color(Color[0] - 0.5, Color[1] - 0.5, Color[2] - 0.5);
+ int is_backfacing = backfacing();
- if (space == "tangent") {
- vector tangent;
- vector ninterp;
- float tangent_sign;
- float is_smooth;
+ if (space == "tangent") {
+ vector tangent;
+ vector ninterp;
+ float tangent_sign;
+ float is_smooth;
- getattribute("geom:is_smooth", is_smooth);
- if (!is_smooth) {
- ninterp = normalize(transform("world", "object", Ng));
+ getattribute("geom:is_smooth", is_smooth);
+ if (!is_smooth) {
+ ninterp = normalize(transform("world", "object", Ng));
- /* the normal is already inverted, which is too soon for the math here */
- if (is_backfacing) {
- ninterp = -ninterp;
- }
- }
+ /* the normal is already inverted, which is too soon for the math here */
+ if (is_backfacing) {
+ ninterp = -ninterp;
+ }
+ }
- // get _unnormalized_ interpolated normal and tangent
- if (getattribute(attr_name, tangent) &&
- getattribute(attr_sign_name, tangent_sign) &&
- (!is_smooth || getattribute("geom:N", ninterp)))
- {
- // apply normal map
- vector B = tangent_sign * cross(ninterp, tangent);
- Normal = normalize(mcolor[0] * tangent + mcolor[1] * B + mcolor[2] * ninterp);
+ // get _unnormalized_ interpolated normal and tangent
+ if (getattribute(attr_name, tangent) && getattribute(attr_sign_name, tangent_sign) &&
+ (!is_smooth || getattribute("geom:N", ninterp))) {
+ // apply normal map
+ vector B = tangent_sign * cross(ninterp, tangent);
+ Normal = normalize(mcolor[0] * tangent + mcolor[1] * B + mcolor[2] * ninterp);
- // transform to world space
- Normal = normalize(transform("object", "world", Normal));
- }
- else {
- Normal = normal(0, 0, 0);
- }
- }
- else if (space == "object") {
- Normal = normalize(transform("object", "world", vector(mcolor)));
- }
- else if (space == "world") {
- Normal = normalize(vector(mcolor));
- }
- else if (space == "blender_object") {
- /* strange blender convention */
- mcolor[1] = -mcolor[1];
- mcolor[2] = -mcolor[2];
-
- Normal = normalize(transform("object", "world", vector(mcolor)));
- }
- else if (space == "blender_world") {
- /* strange blender convention */
- mcolor[1] = -mcolor[1];
- mcolor[2] = -mcolor[2];
-
- Normal = normalize(vector(mcolor));
- }
+ // transform to world space
+ Normal = normalize(transform("object", "world", Normal));
+ }
+ else {
+ Normal = normal(0, 0, 0);
+ }
+ }
+ else if (space == "object") {
+ Normal = normalize(transform("object", "world", vector(mcolor)));
+ }
+ else if (space == "world") {
+ Normal = normalize(vector(mcolor));
+ }
+ else if (space == "blender_object") {
+ /* strange blender convention */
+ mcolor[1] = -mcolor[1];
+ mcolor[2] = -mcolor[2];
- /* invert normal for backfacing polygons */
- if (is_backfacing) {
- Normal = -Normal;
- }
+ Normal = normalize(transform("object", "world", vector(mcolor)));
+ }
+ else if (space == "blender_world") {
+ /* strange blender convention */
+ mcolor[1] = -mcolor[1];
+ mcolor[2] = -mcolor[2];
- if (Strength != 1.0)
- Normal = normalize(NormalIn + (Normal - NormalIn) * max(Strength, 0.0));
+ Normal = normalize(vector(mcolor));
+ }
- Normal = ensure_valid_reflection(Ng, I, Normal);
-}
+ /* invert normal for backfacing polygons */
+ if (is_backfacing) {
+ Normal = -Normal;
+ }
+
+ if (Strength != 1.0)
+ Normal = normalize(NormalIn + (Normal - NormalIn) * max(Strength, 0.0));
+ Normal = ensure_valid_reflection(Ng, I, Normal);
+}
diff --git a/intern/cycles/kernel/shaders/node_object_info.osl b/intern/cycles/kernel/shaders/node_object_info.osl
index dd7c663b8d8..0904a30a53f 100644
--- a/intern/cycles/kernel/shaders/node_object_info.osl
+++ b/intern/cycles/kernel/shaders/node_object_info.osl
@@ -16,15 +16,13 @@
#include "stdosl.h"
-shader node_object_info(
- output point Location = point(0.0, 0.0, 0.0),
- output float ObjectIndex = 0.0,
- output float MaterialIndex = 0.0,
- output float Random = 0.0)
+shader node_object_info(output point Location = point(0.0, 0.0, 0.0),
+ output float ObjectIndex = 0.0,
+ output float MaterialIndex = 0.0,
+ output float Random = 0.0)
{
- getattribute("object:location", Location);
- getattribute("object:index", ObjectIndex);
- getattribute("material:index", MaterialIndex);
- getattribute("object:random", Random);
+ getattribute("object:location", Location);
+ getattribute("object:index", ObjectIndex);
+ getattribute("material:index", MaterialIndex);
+ getattribute("object:random", Random);
}
-
diff --git a/intern/cycles/kernel/shaders/node_output_displacement.osl b/intern/cycles/kernel/shaders/node_output_displacement.osl
index 5dbef0244fe..fa7f603980b 100644
--- a/intern/cycles/kernel/shaders/node_output_displacement.osl
+++ b/intern/cycles/kernel/shaders/node_output_displacement.osl
@@ -18,6 +18,5 @@
displacement node_output_displacement(vector Displacement = 0.0)
{
- P += Displacement;
+ P += Displacement;
}
-
diff --git a/intern/cycles/kernel/shaders/node_output_surface.osl b/intern/cycles/kernel/shaders/node_output_surface.osl
index 2cc4575a8c8..013666145da 100644
--- a/intern/cycles/kernel/shaders/node_output_surface.osl
+++ b/intern/cycles/kernel/shaders/node_output_surface.osl
@@ -18,6 +18,5 @@
surface node_output_surface(closure color Surface = 0)
{
- Ci = Surface;
+ Ci = Surface;
}
-
diff --git a/intern/cycles/kernel/shaders/node_output_volume.osl b/intern/cycles/kernel/shaders/node_output_volume.osl
index f220ba866e3..dd479e751b3 100644
--- a/intern/cycles/kernel/shaders/node_output_volume.osl
+++ b/intern/cycles/kernel/shaders/node_output_volume.osl
@@ -18,6 +18,5 @@
volume node_output_volume(closure color Volume = 0)
{
- Ci = Volume;
+ Ci = Volume;
}
-
diff --git a/intern/cycles/kernel/shaders/node_particle_info.osl b/intern/cycles/kernel/shaders/node_particle_info.osl
index 2a0252d5e45..e286c33a1ff 100644
--- a/intern/cycles/kernel/shaders/node_particle_info.osl
+++ b/intern/cycles/kernel/shaders/node_particle_info.osl
@@ -16,23 +16,21 @@
#include "stdosl.h"
-shader node_particle_info(
- output float Index = 0.0,
- output float Random = 0.0,
- output float Age = 0.0,
- output float Lifetime = 0.0,
- output point Location = point(0.0, 0.0, 0.0),
- output float Size = 0.0,
- output vector Velocity = point(0.0, 0.0, 0.0),
- output vector AngularVelocity = point(0.0, 0.0, 0.0))
+shader node_particle_info(output float Index = 0.0,
+ output float Random = 0.0,
+ output float Age = 0.0,
+ output float Lifetime = 0.0,
+ output point Location = point(0.0, 0.0, 0.0),
+ output float Size = 0.0,
+ output vector Velocity = point(0.0, 0.0, 0.0),
+ output vector AngularVelocity = point(0.0, 0.0, 0.0))
{
- getattribute("particle:index", Index);
- getattribute("particle:random", Random);
- getattribute("particle:age", Age);
- getattribute("particle:lifetime", Lifetime);
- getattribute("particle:location", Location);
- getattribute("particle:size", Size);
- getattribute("particle:velocity", Velocity);
- getattribute("particle:angular_velocity", AngularVelocity);
+ getattribute("particle:index", Index);
+ getattribute("particle:random", Random);
+ getattribute("particle:age", Age);
+ getattribute("particle:lifetime", Lifetime);
+ getattribute("particle:location", Location);
+ getattribute("particle:size", Size);
+ getattribute("particle:velocity", Velocity);
+ getattribute("particle:angular_velocity", AngularVelocity);
}
-
diff --git a/intern/cycles/kernel/shaders/node_principled_bsdf.osl b/intern/cycles/kernel/shaders/node_principled_bsdf.osl
index 6f54ba3a462..657ced9b6e6 100644
--- a/intern/cycles/kernel/shaders/node_principled_bsdf.osl
+++ b/intern/cycles/kernel/shaders/node_principled_bsdf.osl
@@ -17,111 +17,144 @@
#include "stdosl.h"
#include "node_fresnel.h"
-shader node_principled_bsdf(
- string distribution = "Multiscatter GGX",
- string subsurface_method = "burley",
- color BaseColor = color(0.8, 0.8, 0.8),
- float Subsurface = 0.0,
- vector SubsurfaceRadius = vector(1.0, 1.0, 1.0),
- color SubsurfaceColor = color(0.7, 0.1, 0.1),
- float Metallic = 0.0,
- float Specular = 0.5,
- float SpecularTint = 0.0,
- float Roughness = 0.5,
- float Anisotropic = 0.0,
- float AnisotropicRotation = 0.0,
- float Sheen = 0.0,
- float SheenTint = 0.5,
- float Clearcoat = 0.0,
- float ClearcoatRoughness = 0.03,
- float IOR = 1.45,
- float Transmission = 0.0,
- float TransmissionRoughness = 0.0,
- normal Normal = N,
- normal ClearcoatNormal = N,
- normal Tangent = normalize(dPdu),
- output closure color BSDF = 0)
+shader node_principled_bsdf(string distribution = "Multiscatter GGX",
+ string subsurface_method = "burley",
+ color BaseColor = color(0.8, 0.8, 0.8),
+ float Subsurface = 0.0,
+ vector SubsurfaceRadius = vector(1.0, 1.0, 1.0),
+ color SubsurfaceColor = color(0.7, 0.1, 0.1),
+ float Metallic = 0.0,
+ float Specular = 0.5,
+ float SpecularTint = 0.0,
+ float Roughness = 0.5,
+ float Anisotropic = 0.0,
+ float AnisotropicRotation = 0.0,
+ float Sheen = 0.0,
+ float SheenTint = 0.5,
+ float Clearcoat = 0.0,
+ float ClearcoatRoughness = 0.03,
+ float IOR = 1.45,
+ float Transmission = 0.0,
+ float TransmissionRoughness = 0.0,
+ normal Normal = N,
+ normal ClearcoatNormal = N,
+ normal Tangent = normalize(dPdu),
+ output closure color BSDF = 0)
{
- float f = max(IOR, 1e-5);
- float diffuse_weight = (1.0 - clamp(Metallic, 0.0, 1.0)) * (1.0 - clamp(Transmission, 0.0, 1.0));
- float final_transmission = clamp(Transmission, 0.0, 1.0) * (1.0 - clamp(Metallic, 0.0, 1.0));
- float specular_weight = (1.0 - final_transmission);
-
- vector T = Tangent;
-
- float m_cdlum = luminance(BaseColor);
- color m_ctint = m_cdlum > 0.0 ? BaseColor / m_cdlum : color(0.0, 0.0, 0.0); // normalize lum. to isolate hue+sat
-
- /* rotate tangent */
- if (AnisotropicRotation != 0.0)
- T = rotate(T, AnisotropicRotation * M_2PI, point(0.0, 0.0, 0.0), Normal);
-
- if (diffuse_weight > 1e-5) {
- if (Subsurface > 1e-5) {
- color mixed_ss_base_color = SubsurfaceColor * Subsurface + BaseColor * (1.0 - Subsurface);
- if (subsurface_method == "burley") {
- BSDF = mixed_ss_base_color * bssrdf("principled", Normal, Subsurface * SubsurfaceRadius, SubsurfaceColor, "roughness", Roughness);
- }
- else {
- BSDF = mixed_ss_base_color * bssrdf("principled_random_walk", Normal, Subsurface * SubsurfaceRadius, mixed_ss_base_color, "roughness", Roughness);
- }
- }
- else {
- BSDF = BaseColor * principled_diffuse(Normal, Roughness);
- }
-
- if (Sheen > 1e-5) {
- color sheen_color = color(1.0, 1.0, 1.0) * (1.0 - SheenTint) + m_ctint * SheenTint;
-
- BSDF = BSDF + sheen_color * Sheen * principled_sheen(Normal);
- }
-
- BSDF = BSDF * diffuse_weight;
- }
-
- if (specular_weight > 1e-5) {
- float aspect = sqrt(1.0 - Anisotropic * 0.9);
- float r2 = Roughness * Roughness;
-
- float alpha_x = r2 / aspect;
- float alpha_y = r2 * aspect;
-
- color tmp_col = color(1.0, 1.0, 1.0) * (1.0 - SpecularTint) + m_ctint * SpecularTint;
-
- color Cspec0 = (Specular * 0.08 * tmp_col) * (1.0 - Metallic) + BaseColor * Metallic;
-
- if (distribution == "GGX" || Roughness <= 0.075) {
- BSDF = BSDF + specular_weight * microfacet_ggx_aniso_fresnel(Normal, T, alpha_x, alpha_y, (2.0 / (1.0 - sqrt(0.08 * Specular))) - 1.0, BaseColor, Cspec0);
- } else {
- BSDF = BSDF + specular_weight * microfacet_multi_ggx_aniso_fresnel(Normal, T, alpha_x, alpha_y, (2.0 / (1.0 - sqrt(0.08 * Specular))) - 1.0, BaseColor, Cspec0);
- }
- }
-
- if (final_transmission > 1e-5) {
- color Cspec0 = BaseColor * SpecularTint + color(1.0, 1.0, 1.0) * (1.0 - SpecularTint);
- float eta = backfacing() ? 1.0 / f : f;
-
- if (distribution == "GGX" || Roughness <= 5e-2) {
- float cosNO = dot(Normal, I);
- float Fr = fresnel_dielectric_cos(cosNO, eta);
-
- float refl_roughness = Roughness;
- if (Roughness <= 1e-2)
- refl_roughness = 0.0;
-
- float transmission_roughness = refl_roughness;
- if (distribution == "GGX")
- transmission_roughness = 1.0 - (1.0 - refl_roughness) * (1.0 - TransmissionRoughness);
-
- BSDF = BSDF + final_transmission * (Fr * microfacet_ggx_fresnel(Normal, refl_roughness * refl_roughness, eta, BaseColor, Cspec0) +
- (1.0 - Fr) * BaseColor * microfacet_ggx_refraction(Normal, transmission_roughness * transmission_roughness, eta));
- } else {
- BSDF = BSDF + final_transmission * microfacet_multi_ggx_glass_fresnel(Normal, Roughness * Roughness, eta, BaseColor, Cspec0);
- }
- }
-
- if (Clearcoat > 1e-5) {
- BSDF = BSDF + principled_clearcoat(ClearcoatNormal, Clearcoat, ClearcoatRoughness * ClearcoatRoughness);
- }
+ float f = max(IOR, 1e-5);
+ float diffuse_weight = (1.0 - clamp(Metallic, 0.0, 1.0)) * (1.0 - clamp(Transmission, 0.0, 1.0));
+ float final_transmission = clamp(Transmission, 0.0, 1.0) * (1.0 - clamp(Metallic, 0.0, 1.0));
+ float specular_weight = (1.0 - final_transmission);
+
+ vector T = Tangent;
+
+ float m_cdlum = luminance(BaseColor);
+ color m_ctint = m_cdlum > 0.0 ? BaseColor / m_cdlum :
+ color(0.0, 0.0, 0.0); // normalize lum. to isolate hue+sat
+
+ /* rotate tangent */
+ if (AnisotropicRotation != 0.0)
+ T = rotate(T, AnisotropicRotation * M_2PI, point(0.0, 0.0, 0.0), Normal);
+
+ if (diffuse_weight > 1e-5) {
+ if (Subsurface > 1e-5) {
+ color mixed_ss_base_color = SubsurfaceColor * Subsurface + BaseColor * (1.0 - Subsurface);
+ if (subsurface_method == "burley") {
+ BSDF = mixed_ss_base_color * bssrdf("principled",
+ Normal,
+ Subsurface * SubsurfaceRadius,
+ SubsurfaceColor,
+ "roughness",
+ Roughness);
+ }
+ else {
+ BSDF = mixed_ss_base_color * bssrdf("principled_random_walk",
+ Normal,
+ Subsurface * SubsurfaceRadius,
+ mixed_ss_base_color,
+ "roughness",
+ Roughness);
+ }
+ }
+ else {
+ BSDF = BaseColor * principled_diffuse(Normal, Roughness);
+ }
+
+ if (Sheen > 1e-5) {
+ color sheen_color = color(1.0, 1.0, 1.0) * (1.0 - SheenTint) + m_ctint * SheenTint;
+
+ BSDF = BSDF + sheen_color * Sheen * principled_sheen(Normal);
+ }
+
+ BSDF = BSDF * diffuse_weight;
+ }
+
+ if (specular_weight > 1e-5) {
+ float aspect = sqrt(1.0 - Anisotropic * 0.9);
+ float r2 = Roughness * Roughness;
+
+ float alpha_x = r2 / aspect;
+ float alpha_y = r2 * aspect;
+
+ color tmp_col = color(1.0, 1.0, 1.0) * (1.0 - SpecularTint) + m_ctint * SpecularTint;
+
+ color Cspec0 = (Specular * 0.08 * tmp_col) * (1.0 - Metallic) + BaseColor * Metallic;
+
+ if (distribution == "GGX" || Roughness <= 0.075) {
+ BSDF = BSDF + specular_weight *
+ microfacet_ggx_aniso_fresnel(Normal,
+ T,
+ alpha_x,
+ alpha_y,
+ (2.0 / (1.0 - sqrt(0.08 * Specular))) - 1.0,
+ BaseColor,
+ Cspec0);
+ }
+ else {
+ BSDF = BSDF + specular_weight * microfacet_multi_ggx_aniso_fresnel(
+ Normal,
+ T,
+ alpha_x,
+ alpha_y,
+ (2.0 / (1.0 - sqrt(0.08 * Specular))) - 1.0,
+ BaseColor,
+ Cspec0);
+ }
+ }
+
+ if (final_transmission > 1e-5) {
+ color Cspec0 = BaseColor * SpecularTint + color(1.0, 1.0, 1.0) * (1.0 - SpecularTint);
+ float eta = backfacing() ? 1.0 / f : f;
+
+ if (distribution == "GGX" || Roughness <= 5e-2) {
+ float cosNO = dot(Normal, I);
+ float Fr = fresnel_dielectric_cos(cosNO, eta);
+
+ float refl_roughness = Roughness;
+ if (Roughness <= 1e-2)
+ refl_roughness = 0.0;
+
+ float transmission_roughness = refl_roughness;
+ if (distribution == "GGX")
+ transmission_roughness = 1.0 - (1.0 - refl_roughness) * (1.0 - TransmissionRoughness);
+
+ BSDF = BSDF +
+ final_transmission *
+ (Fr * microfacet_ggx_fresnel(
+ Normal, refl_roughness * refl_roughness, eta, BaseColor, Cspec0) +
+ (1.0 - Fr) * BaseColor *
+ microfacet_ggx_refraction(
+ Normal, transmission_roughness * transmission_roughness, eta));
+ }
+ else {
+ BSDF = BSDF +
+ final_transmission * microfacet_multi_ggx_glass_fresnel(
+ Normal, Roughness * Roughness, eta, BaseColor, Cspec0);
+ }
+ }
+
+ if (Clearcoat > 1e-5) {
+ BSDF = BSDF + principled_clearcoat(
+ ClearcoatNormal, Clearcoat, ClearcoatRoughness * ClearcoatRoughness);
+ }
}
-
diff --git a/intern/cycles/kernel/shaders/node_principled_hair_bsdf.osl b/intern/cycles/kernel/shaders/node_principled_hair_bsdf.osl
index 757a88f8ece..bf986438fca 100644
--- a/intern/cycles/kernel/shaders/node_principled_hair_bsdf.osl
+++ b/intern/cycles/kernel/shaders/node_principled_hair_bsdf.osl
@@ -18,88 +18,88 @@
color log3(color a)
{
- return color(log(a[0]), log(a[1]), log(a[2]));
+ return color(log(a[0]), log(a[1]), log(a[2]));
}
color sigma_from_concentration(float eumelanin, float pheomelanin)
{
- return eumelanin*color(0.506, 0.841, 1.653) + pheomelanin*color(0.343, 0.733, 1.924);
+ return eumelanin * color(0.506, 0.841, 1.653) + pheomelanin * color(0.343, 0.733, 1.924);
}
color sigma_from_reflectance(color c, float azimuthal_roughness)
{
- float x = azimuthal_roughness;
- float roughness_fac = (((((0.245*x) + 5.574)*x - 10.73)*x + 2.532)*x - 0.215)*x + 5.969;
- color sigma = log3(c) / roughness_fac;
- return sigma * sigma;
+ float x = azimuthal_roughness;
+ float roughness_fac = (((((0.245 * x) + 5.574) * x - 10.73) * x + 2.532) * x - 0.215) * x +
+ 5.969;
+ color sigma = log3(c) / roughness_fac;
+ return sigma * sigma;
}
-shader node_principled_hair_bsdf(
- color Color = color(0.017513, 0.005763, 0.002059),
- float Melanin = 0.8,
- float MelaninRedness = 1.0,
- float RandomColor = 0.0,
- color Tint = 1.0,
- color AbsorptionCoefficient = color(0.245531, 0.52, 1.365),
- normal Normal = Ng,
- string parametrization = "Absorption coefficient",
- float Offset = radians(2),
- float Roughness = 0.3,
- float RadialRoughness = 0.3,
- float RandomRoughness = 0.0,
- float Coat = 0.0,
- float IOR = 1.55,
- string AttrRandom = "geom:curve_random",
- float Random = 0.0,
+shader node_principled_hair_bsdf(color Color = color(0.017513, 0.005763, 0.002059),
+ float Melanin = 0.8,
+ float MelaninRedness = 1.0,
+ float RandomColor = 0.0,
+ color Tint = 1.0,
+ color AbsorptionCoefficient = color(0.245531, 0.52, 1.365),
+ normal Normal = Ng,
+ string parametrization = "Absorption coefficient",
+ float Offset = radians(2),
+ float Roughness = 0.3,
+ float RadialRoughness = 0.3,
+ float RandomRoughness = 0.0,
+ float Coat = 0.0,
+ float IOR = 1.55,
+ string AttrRandom = "geom:curve_random",
+ float Random = 0.0,
- output closure color BSDF = 0)
+ output closure color BSDF = 0)
{
- /* Get random value from curve in none is specified. */
- float random_value = 0.0;
+ /* Get random value from curve in none is specified. */
+ float random_value = 0.0;
- if (isconnected(Random)) {
- random_value = Random;
- }
- else {
- getattribute(AttrRandom, random_value);
- }
+ if (isconnected(Random)) {
+ random_value = Random;
+ }
+ else {
+ getattribute(AttrRandom, random_value);
+ }
- /* Compute roughness. */
- float factor_random_roughness = 1.0 + 2.0*(random_value - 0.5)*RandomRoughness;
- float m0_roughness = 1.0 - clamp(Coat, 0.0, 1.0);
- float roughness = Roughness*factor_random_roughness;
- float radial_roughness = RadialRoughness*factor_random_roughness;
+ /* Compute roughness. */
+ float factor_random_roughness = 1.0 + 2.0 * (random_value - 0.5) * RandomRoughness;
+ float m0_roughness = 1.0 - clamp(Coat, 0.0, 1.0);
+ float roughness = Roughness * factor_random_roughness;
+ float radial_roughness = RadialRoughness * factor_random_roughness;
- /* Compute absorption. */
- color sigma;
+ /* Compute absorption. */
+ color sigma;
- if (parametrization == "Absorption coefficient") {
- sigma = AbsorptionCoefficient;
- }
- else if (parametrization == "Melanin concentration") {
- /* Randomize melanin. */
- float factor_random_color = 1.0 + 2.0*(random_value - 0.5) * RandomColor;
- float melanin = Melanin * factor_random_color;
+ if (parametrization == "Absorption coefficient") {
+ sigma = AbsorptionCoefficient;
+ }
+ else if (parametrization == "Melanin concentration") {
+ /* Randomize melanin. */
+ float factor_random_color = 1.0 + 2.0 * (random_value - 0.5) * RandomColor;
+ float melanin = Melanin * factor_random_color;
- /* Map melanin 0..inf from more perceptually linear 0..1. */
- melanin = -log(max(1.0 - melanin, 0.0001));
+ /* Map melanin 0..inf from more perceptually linear 0..1. */
+ melanin = -log(max(1.0 - melanin, 0.0001));
- /* Benedikt Bitterli's melanin ratio remapping. */
- float eumelanin = melanin * (1.0 - MelaninRedness);
- float pheomelanin = melanin * MelaninRedness;
- color melanin_sigma = sigma_from_concentration(eumelanin, pheomelanin);
+ /* Benedikt Bitterli's melanin ratio remapping. */
+ float eumelanin = melanin * (1.0 - MelaninRedness);
+ float pheomelanin = melanin * MelaninRedness;
+ color melanin_sigma = sigma_from_concentration(eumelanin, pheomelanin);
- /* Optional tint. */
- color tint_sigma = sigma_from_reflectance(Tint, radial_roughness);
- sigma = melanin_sigma + tint_sigma;
- }
- else if (parametrization == "Direct coloring"){
- sigma = sigma_from_reflectance(Color, radial_roughness);
- }
- else {
- /* Fallback to brownish hair, same as defaults for melanin. */
- sigma = sigma_from_concentration(0.0, 0.8054375);
- }
+ /* Optional tint. */
+ color tint_sigma = sigma_from_reflectance(Tint, radial_roughness);
+ sigma = melanin_sigma + tint_sigma;
+ }
+ else if (parametrization == "Direct coloring") {
+ sigma = sigma_from_reflectance(Color, radial_roughness);
+ }
+ else {
+ /* Fallback to brownish hair, same as defaults for melanin. */
+ sigma = sigma_from_concentration(0.0, 0.8054375);
+ }
- BSDF = principled_hair(Normal, sigma, roughness, radial_roughness, m0_roughness, Offset, IOR);
+ BSDF = principled_hair(Normal, sigma, roughness, radial_roughness, m0_roughness, Offset, IOR);
}
diff --git a/intern/cycles/kernel/shaders/node_principled_volume.osl b/intern/cycles/kernel/shaders/node_principled_volume.osl
index ea8d6ab12c5..39cf6837eb2 100644
--- a/intern/cycles/kernel/shaders/node_principled_volume.osl
+++ b/intern/cycles/kernel/shaders/node_principled_volume.osl
@@ -16,80 +16,78 @@
#include "stdosl.h"
-shader node_principled_volume(
- color Color = color(0.5, 0.5, 0.5),
- float Density = 1.0,
- float Anisotropy = 0.0,
- color AbsorptionColor = color(0.0, 0.0, 0.0),
- float EmissionStrength = 0.0,
- color EmissionColor = color(1.0, 1.0, 1.0),
- float BlackbodyIntensity = 0.0,
- color BlackbodyTint = color(1.0, 1.0, 1.0),
- float Temperature = 1500.0,
- string DensityAttribute = "geom:density",
- string ColorAttribute = "geom:color",
- string TemperatureAttribute = "geom:temperature",
- output closure color Volume = 0)
+shader node_principled_volume(color Color = color(0.5, 0.5, 0.5),
+ float Density = 1.0,
+ float Anisotropy = 0.0,
+ color AbsorptionColor = color(0.0, 0.0, 0.0),
+ float EmissionStrength = 0.0,
+ color EmissionColor = color(1.0, 1.0, 1.0),
+ float BlackbodyIntensity = 0.0,
+ color BlackbodyTint = color(1.0, 1.0, 1.0),
+ float Temperature = 1500.0,
+ string DensityAttribute = "geom:density",
+ string ColorAttribute = "geom:color",
+ string TemperatureAttribute = "geom:temperature",
+ output closure color Volume = 0)
{
- /* Compute density. */
- float primitive_density = 1.0;
- float density = max(Density, 0.0);
+ /* Compute density. */
+ float primitive_density = 1.0;
+ float density = max(Density, 0.0);
- if(density > 1e-5) {
- if(getattribute(DensityAttribute, primitive_density)) {
- density = max(density * primitive_density, 0.0);
- }
- }
+ if (density > 1e-5) {
+ if (getattribute(DensityAttribute, primitive_density)) {
+ density = max(density * primitive_density, 0.0);
+ }
+ }
- if(density > 1e-5) {
- /* Compute scattering color. */
- color scatter_color = Color;
- color primitive_color;
- if(getattribute(ColorAttribute, primitive_color)) {
- scatter_color *= primitive_color;
- }
+ if (density > 1e-5) {
+ /* Compute scattering color. */
+ color scatter_color = Color;
+ color primitive_color;
+ if (getattribute(ColorAttribute, primitive_color)) {
+ scatter_color *= primitive_color;
+ }
- /* Add scattering and absorption closures. */
- color scatter_coeff = scatter_color;
- color absorption_color = sqrt(max(AbsorptionColor, 0.0));
- color absorption_coeff = max(1.0 - scatter_color, 0.0) * max(1.0 - absorption_color, 0.0);
- Volume = scatter_coeff * density * henyey_greenstein(Anisotropy) +
- absorption_coeff * density * absorption();
- }
+ /* Add scattering and absorption closures. */
+ color scatter_coeff = scatter_color;
+ color absorption_color = sqrt(max(AbsorptionColor, 0.0));
+ color absorption_coeff = max(1.0 - scatter_color, 0.0) * max(1.0 - absorption_color, 0.0);
+ Volume = scatter_coeff * density * henyey_greenstein(Anisotropy) +
+ absorption_coeff * density * absorption();
+ }
- /* Compute emission. */
- float emission_strength = max(EmissionStrength, 0.0);
- float blackbody_intensity = BlackbodyIntensity;
+ /* Compute emission. */
+ float emission_strength = max(EmissionStrength, 0.0);
+ float blackbody_intensity = BlackbodyIntensity;
- if(emission_strength > 1e-5) {
- Volume += emission_strength * EmissionColor * emission();
- }
+ if (emission_strength > 1e-5) {
+ Volume += emission_strength * EmissionColor * emission();
+ }
- if(blackbody_intensity > 1e-3) {
- float T = Temperature;
+ if (blackbody_intensity > 1e-3) {
+ float T = Temperature;
- /* Add temperature from attribute if available. */
- float temperature;
- if(getattribute(TemperatureAttribute, temperature)) {
- T *= max(temperature, 0.0);
- }
+ /* Add temperature from attribute if available. */
+ float temperature;
+ if (getattribute(TemperatureAttribute, temperature)) {
+ T *= max(temperature, 0.0);
+ }
- T = max(T, 0.0);
+ T = max(T, 0.0);
- /* Stefan-Boltzman law. */
- float T4 = (T * T) * (T * T);
- float sigma = 5.670373e-8 * 1e-6 / M_PI;
- float intensity = sigma * mix(1.0, T4, blackbody_intensity);
+ /* Stefan-Boltzman law. */
+ float T4 = (T * T) * (T * T);
+ float sigma = 5.670373e-8 * 1e-6 / M_PI;
+ float intensity = sigma * mix(1.0, T4, blackbody_intensity);
- if(intensity > 1e-5) {
- color bb = blackbody(T);
- float l = luminance(bb);
+ if (intensity > 1e-5) {
+ color bb = blackbody(T);
+ float l = luminance(bb);
- if(l != 0.0) {
- bb *= BlackbodyTint * intensity / l;
- Volume += bb * emission();
- }
- }
- }
+ if (l != 0.0) {
+ bb *= BlackbodyTint * intensity / l;
+ Volume += bb * emission();
+ }
+ }
+ }
}
-
diff --git a/intern/cycles/kernel/shaders/node_ramp_util.h b/intern/cycles/kernel/shaders/node_ramp_util.h
index d07d5a98316..f7fb07b257d 100644
--- a/intern/cycles/kernel/shaders/node_ramp_util.h
+++ b/intern/cycles/kernel/shaders/node_ramp_util.h
@@ -18,72 +18,76 @@
color rgb_ramp_lookup(color ramp[], float at, int interpolate, int extrapolate)
{
- float f = at;
- int table_size = arraylength(ramp);
+ float f = at;
+ int table_size = arraylength(ramp);
- if ((f < 0.0 || f > 1.0) && extrapolate) {
- color t0, dy;
- if (f < 0.0) {
- t0 = ramp[0];
- dy = t0 - ramp[1];
- f = -f;
- }
- else {
- t0 = ramp[table_size - 1];
- dy = t0 - ramp[table_size - 2];
- f = f - 1.0;
- }
- return t0 + dy * f * (table_size - 1);
- }
+ if ((f < 0.0 || f > 1.0) && extrapolate) {
+ color t0, dy;
+ if (f < 0.0) {
+ t0 = ramp[0];
+ dy = t0 - ramp[1];
+ f = -f;
+ }
+ else {
+ t0 = ramp[table_size - 1];
+ dy = t0 - ramp[table_size - 2];
+ f = f - 1.0;
+ }
+ return t0 + dy * f * (table_size - 1);
+ }
- f = clamp(at, 0.0, 1.0) * (table_size - 1);
+ f = clamp(at, 0.0, 1.0) * (table_size - 1);
- /* clamp int as well in case of NaN */
- int i = (int)f;
- if (i < 0) i = 0;
- if (i >= table_size) i = table_size - 1;
- float t = f - (float)i;
+ /* clamp int as well in case of NaN */
+ int i = (int)f;
+ if (i < 0)
+ i = 0;
+ if (i >= table_size)
+ i = table_size - 1;
+ float t = f - (float)i;
- color result = ramp[i];
+ color result = ramp[i];
- if (interpolate && t > 0.0)
- result = (1.0 - t) * result + t * ramp[i + 1];
+ if (interpolate && t > 0.0)
+ result = (1.0 - t) * result + t * ramp[i + 1];
- return result;
+ return result;
}
float rgb_ramp_lookup(float ramp[], float at, int interpolate, int extrapolate)
{
- float f = at;
- int table_size = arraylength(ramp);
+ float f = at;
+ int table_size = arraylength(ramp);
- if ((f < 0.0 || f > 1.0) && extrapolate) {
- float t0, dy;
- if (f < 0.0) {
- t0 = ramp[0];
- dy = t0 - ramp[1];
- f = -f;
- }
- else {
- t0 = ramp[table_size - 1];
- dy = t0 - ramp[table_size - 2];
- f = f - 1.0;
- }
- return t0 + dy * f * (table_size - 1);
- }
+ if ((f < 0.0 || f > 1.0) && extrapolate) {
+ float t0, dy;
+ if (f < 0.0) {
+ t0 = ramp[0];
+ dy = t0 - ramp[1];
+ f = -f;
+ }
+ else {
+ t0 = ramp[table_size - 1];
+ dy = t0 - ramp[table_size - 2];
+ f = f - 1.0;
+ }
+ return t0 + dy * f * (table_size - 1);
+ }
- f = clamp(at, 0.0, 1.0) * (table_size - 1);
+ f = clamp(at, 0.0, 1.0) * (table_size - 1);
- /* clamp int as well in case of NaN */
- int i = (int)f;
- if (i < 0) i = 0;
- if (i >= table_size) i = table_size - 1;
- float t = f - (float)i;
+ /* clamp int as well in case of NaN */
+ int i = (int)f;
+ if (i < 0)
+ i = 0;
+ if (i >= table_size)
+ i = table_size - 1;
+ float t = f - (float)i;
- float result = ramp[i];
+ float result = ramp[i];
- if (interpolate && t > 0.0)
- result = (1.0 - t) * result + t * ramp[i + 1];
+ if (interpolate && t > 0.0)
+ result = (1.0 - t) * result + t * ramp[i + 1];
- return result;
+ return result;
}
diff --git a/intern/cycles/kernel/shaders/node_refraction_bsdf.osl b/intern/cycles/kernel/shaders/node_refraction_bsdf.osl
index eaab7282243..941d99dd44d 100644
--- a/intern/cycles/kernel/shaders/node_refraction_bsdf.osl
+++ b/intern/cycles/kernel/shaders/node_refraction_bsdf.osl
@@ -16,23 +16,21 @@
#include "stdosl.h"
-shader node_refraction_bsdf(
- color Color = 0.8,
- string distribution = "sharp",
- float Roughness = 0.2,
- float IOR = 1.45,
- normal Normal = N,
- output closure color BSDF = 0)
+shader node_refraction_bsdf(color Color = 0.8,
+ string distribution = "sharp",
+ float Roughness = 0.2,
+ float IOR = 1.45,
+ normal Normal = N,
+ output closure color BSDF = 0)
{
- float f = max(IOR, 1e-5);
- float eta = backfacing() ? 1.0 / f : f;
- float roughness = Roughness * Roughness;
+ float f = max(IOR, 1e-5);
+ float eta = backfacing() ? 1.0 / f : f;
+ float roughness = Roughness * Roughness;
- if (distribution == "sharp")
- BSDF = Color * refraction(Normal, eta);
- else if (distribution == "beckmann")
- BSDF = Color * microfacet_beckmann_refraction(Normal, roughness, eta);
- else if (distribution == "GGX")
- BSDF = Color * microfacet_ggx_refraction(Normal, roughness, eta);
+ if (distribution == "sharp")
+ BSDF = Color * refraction(Normal, eta);
+ else if (distribution == "beckmann")
+ BSDF = Color * microfacet_beckmann_refraction(Normal, roughness, eta);
+ else if (distribution == "GGX")
+ BSDF = Color * microfacet_ggx_refraction(Normal, roughness, eta);
}
-
diff --git a/intern/cycles/kernel/shaders/node_rgb_curves.osl b/intern/cycles/kernel/shaders/node_rgb_curves.osl
index 0d5eeea5c43..e34eb027cc3 100644
--- a/intern/cycles/kernel/shaders/node_rgb_curves.osl
+++ b/intern/cycles/kernel/shaders/node_rgb_curves.osl
@@ -17,25 +17,23 @@
#include "stdosl.h"
#include "node_ramp_util.h"
-shader node_rgb_curves(
- color ramp[] = {0.0},
- float min_x = 0.0,
- float max_x = 1.0,
+shader node_rgb_curves(color ramp[] = {0.0},
+ float min_x = 0.0,
+ float max_x = 1.0,
- color ColorIn = 0.0,
- float Fac = 0.0,
- output color ColorOut = 0.0)
+ color ColorIn = 0.0,
+ float Fac = 0.0,
+ output color ColorOut = 0.0)
{
- color c = (ColorIn - color(min_x, min_x, min_x)) / (max_x - min_x);
+ color c = (ColorIn - color(min_x, min_x, min_x)) / (max_x - min_x);
- color r = rgb_ramp_lookup(ramp, c[0], 1, 1);
- color g = rgb_ramp_lookup(ramp, c[1], 1, 1);
- color b = rgb_ramp_lookup(ramp, c[2], 1, 1);
+ color r = rgb_ramp_lookup(ramp, c[0], 1, 1);
+ color g = rgb_ramp_lookup(ramp, c[1], 1, 1);
+ color b = rgb_ramp_lookup(ramp, c[2], 1, 1);
- ColorOut[0] = r[0];
- ColorOut[1] = g[1];
- ColorOut[2] = b[2];
+ ColorOut[0] = r[0];
+ ColorOut[1] = g[1];
+ ColorOut[2] = b[2];
- ColorOut = mix(ColorIn, ColorOut, Fac);
+ ColorOut = mix(ColorIn, ColorOut, Fac);
}
-
diff --git a/intern/cycles/kernel/shaders/node_rgb_ramp.osl b/intern/cycles/kernel/shaders/node_rgb_ramp.osl
index 4e7d8fdcf65..c9f9746a4fb 100644
--- a/intern/cycles/kernel/shaders/node_rgb_ramp.osl
+++ b/intern/cycles/kernel/shaders/node_rgb_ramp.osl
@@ -17,16 +17,14 @@
#include "stdosl.h"
#include "node_ramp_util.h"
-shader node_rgb_ramp(
- color ramp_color[] = {0.0},
- float ramp_alpha[] = {0.0},
- int interpolate = 1,
+shader node_rgb_ramp(color ramp_color[] = {0.0},
+ float ramp_alpha[] = {0.0},
+ int interpolate = 1,
- float Fac = 0.0,
- output color Color = 0.0,
- output float Alpha = 1.0)
+ float Fac = 0.0,
+ output color Color = 0.0,
+ output float Alpha = 1.0)
{
- Color = rgb_ramp_lookup(ramp_color, Fac, interpolate, 0);
- Alpha = rgb_ramp_lookup(ramp_alpha, Fac, interpolate, 0);
+ Color = rgb_ramp_lookup(ramp_color, Fac, interpolate, 0);
+ Alpha = rgb_ramp_lookup(ramp_alpha, Fac, interpolate, 0);
}
-
diff --git a/intern/cycles/kernel/shaders/node_rgb_to_bw.osl b/intern/cycles/kernel/shaders/node_rgb_to_bw.osl
index 903dfcdc881..837d6caf5fc 100644
--- a/intern/cycles/kernel/shaders/node_rgb_to_bw.osl
+++ b/intern/cycles/kernel/shaders/node_rgb_to_bw.osl
@@ -16,10 +16,7 @@
#include "stdosl.h"
-shader node_rgb_to_bw(
- color Color = 0.0,
- output float Val = 0.0)
+shader node_rgb_to_bw(color Color = 0.0, output float Val = 0.0)
{
- Val = Color[0] * 0.2126 + Color[1] * 0.7152 + Color[2] * 0.0722;
+ Val = Color[0] * 0.2126 + Color[1] * 0.7152 + Color[2] * 0.0722;
}
-
diff --git a/intern/cycles/kernel/shaders/node_scatter_volume.osl b/intern/cycles/kernel/shaders/node_scatter_volume.osl
index 002e2750fca..fce5716f372 100644
--- a/intern/cycles/kernel/shaders/node_scatter_volume.osl
+++ b/intern/cycles/kernel/shaders/node_scatter_volume.osl
@@ -16,12 +16,10 @@
#include "stdosl.h"
-shader node_scatter_volume(
- color Color = color(0.8, 0.8, 0.8),
- float Density = 1.0,
- float Anisotropy = 0.0,
- output closure color Volume = 0)
+shader node_scatter_volume(color Color = color(0.8, 0.8, 0.8),
+ float Density = 1.0,
+ float Anisotropy = 0.0,
+ output closure color Volume = 0)
{
- Volume = (Color * max(Density, 0.0)) * henyey_greenstein(Anisotropy);
+ Volume = (Color * max(Density, 0.0)) * henyey_greenstein(Anisotropy);
}
-
diff --git a/intern/cycles/kernel/shaders/node_separate_hsv.osl b/intern/cycles/kernel/shaders/node_separate_hsv.osl
index 2a804040294..c77ed1f3755 100644
--- a/intern/cycles/kernel/shaders/node_separate_hsv.osl
+++ b/intern/cycles/kernel/shaders/node_separate_hsv.osl
@@ -17,15 +17,14 @@
#include "stdosl.h"
#include "node_color.h"
-shader node_separate_hsv(
- color Color = 0.8,
- output float H = 0.0,
- output float S = 0.0,
- output float V = 0.0)
+shader node_separate_hsv(color Color = 0.8,
+ output float H = 0.0,
+ output float S = 0.0,
+ output float V = 0.0)
{
- color col = rgb_to_hsv(Color);
-
- H = col[0];
- S = col[1];
- V = col[2];
+ color col = rgb_to_hsv(Color);
+
+ H = col[0];
+ S = col[1];
+ V = col[2];
}
diff --git a/intern/cycles/kernel/shaders/node_separate_rgb.osl b/intern/cycles/kernel/shaders/node_separate_rgb.osl
index 43d9e3aa4b1..ee64add27e2 100644
--- a/intern/cycles/kernel/shaders/node_separate_rgb.osl
+++ b/intern/cycles/kernel/shaders/node_separate_rgb.osl
@@ -16,13 +16,12 @@
#include "stdosl.h"
-shader node_separate_rgb(
- color Image = 0.8,
- output float R = 0.0,
- output float G = 0.0,
- output float B = 0.0)
+shader node_separate_rgb(color Image = 0.8,
+ output float R = 0.0,
+ output float G = 0.0,
+ output float B = 0.0)
{
- R = Image[0];
- G = Image[1];
- B = Image[2];
+ R = Image[0];
+ G = Image[1];
+ B = Image[2];
}
diff --git a/intern/cycles/kernel/shaders/node_separate_xyz.osl b/intern/cycles/kernel/shaders/node_separate_xyz.osl
index e1963a1902f..8a563f5e920 100644
--- a/intern/cycles/kernel/shaders/node_separate_xyz.osl
+++ b/intern/cycles/kernel/shaders/node_separate_xyz.osl
@@ -16,13 +16,12 @@
#include "stdosl.h"
-shader node_separate_xyz(
- vector Vector = 0.8,
- output float X = 0.0,
- output float Y = 0.0,
- output float Z = 0.0)
+shader node_separate_xyz(vector Vector = 0.8,
+ output float X = 0.0,
+ output float Y = 0.0,
+ output float Z = 0.0)
{
- X = Vector[0];
- Y = Vector[1];
- Z = Vector[2];
+ X = Vector[0];
+ Y = Vector[1];
+ Z = Vector[2];
}
diff --git a/intern/cycles/kernel/shaders/node_set_normal.osl b/intern/cycles/kernel/shaders/node_set_normal.osl
index 7ca7ac9350c..9541b829ef7 100644
--- a/intern/cycles/kernel/shaders/node_set_normal.osl
+++ b/intern/cycles/kernel/shaders/node_set_normal.osl
@@ -16,11 +16,8 @@
#include "stdosl.h"
-surface node_set_normal(
- normal Direction = N,
- output normal Normal = N)
+surface node_set_normal(normal Direction = N, output normal Normal = N)
{
- N = Direction;
- Normal = Direction;
+ N = Direction;
+ Normal = Direction;
}
-
diff --git a/intern/cycles/kernel/shaders/node_sky_texture.osl b/intern/cycles/kernel/shaders/node_sky_texture.osl
index a6c187d15f2..9b29e5489c2 100644
--- a/intern/cycles/kernel/shaders/node_sky_texture.osl
+++ b/intern/cycles/kernel/shaders/node_sky_texture.osl
@@ -19,115 +19,122 @@
float sky_angle_between(float thetav, float phiv, float theta, float phi)
{
- float cospsi = sin(thetav) * sin(theta) * cos(phi - phiv) + cos(thetav) * cos(theta);
+ float cospsi = sin(thetav) * sin(theta) * cos(phi - phiv) + cos(thetav) * cos(theta);
- if (cospsi > 1.0)
- return 0.0;
- if (cospsi < -1.0)
- return M_PI;
+ if (cospsi > 1.0)
+ return 0.0;
+ if (cospsi < -1.0)
+ return M_PI;
- return acos(cospsi);
+ return acos(cospsi);
}
vector sky_spherical_coordinates(vector dir)
{
- return vector(acos(dir[2]), atan2(dir[0], dir[1]), 0);
+ return vector(acos(dir[2]), atan2(dir[0], dir[1]), 0);
}
/* Preetham */
float sky_perez_function(float lam[9], float theta, float gamma)
{
- float ctheta = cos(theta);
- float cgamma = cos(gamma);
+ float ctheta = cos(theta);
+ float cgamma = cos(gamma);
- return (1.0 + lam[0] * exp(lam[1] / ctheta)) * (1.0 + lam[2] * exp(lam[3] * gamma) + lam[4] * cgamma * cgamma);
+ return (1.0 + lam[0] * exp(lam[1] / ctheta)) *
+ (1.0 + lam[2] * exp(lam[3] * gamma) + lam[4] * cgamma * cgamma);
}
color sky_radiance_old(normal dir,
- float sunphi, float suntheta, color radiance,
- float config_x[9], float config_y[9], float config_z[9])
+ float sunphi,
+ float suntheta,
+ color radiance,
+ float config_x[9],
+ float config_y[9],
+ float config_z[9])
{
- /* convert vector to spherical coordinates */
- vector spherical = sky_spherical_coordinates(dir);
- float theta = spherical[0];
- float phi = spherical[1];
+ /* convert vector to spherical coordinates */
+ vector spherical = sky_spherical_coordinates(dir);
+ float theta = spherical[0];
+ float phi = spherical[1];
- /* angle between sun direction and dir */
- float gamma = sky_angle_between(theta, phi, suntheta, sunphi);
+ /* angle between sun direction and dir */
+ float gamma = sky_angle_between(theta, phi, suntheta, sunphi);
- /* clamp theta to horizon */
- theta = min(theta, M_PI_2 - 0.001);
+ /* clamp theta to horizon */
+ theta = min(theta, M_PI_2 - 0.001);
- /* compute xyY color space values */
- float x = radiance[1] * sky_perez_function(config_y, theta, gamma);
- float y = radiance[2] * sky_perez_function(config_z, theta, gamma);
- float Y = radiance[0] * sky_perez_function(config_x, theta, gamma);
+ /* compute xyY color space values */
+ float x = radiance[1] * sky_perez_function(config_y, theta, gamma);
+ float y = radiance[2] * sky_perez_function(config_z, theta, gamma);
+ float Y = radiance[0] * sky_perez_function(config_x, theta, gamma);
- /* convert to RGB */
- color xyz = xyY_to_xyz(x, y, Y);
- return xyz_to_rgb(xyz[0], xyz[1], xyz[2]);
+ /* convert to RGB */
+ color xyz = xyY_to_xyz(x, y, Y);
+ return xyz_to_rgb(xyz[0], xyz[1], xyz[2]);
}
/* Hosek / Wilkie */
float sky_radiance_internal(float config[9], float theta, float gamma)
{
- float ctheta = cos(theta);
- float cgamma = cos(gamma);
-
- float expM = exp(config[4] * gamma);
- float rayM = cgamma * cgamma;
- float mieM = (1.0 + rayM) / pow((1.0 + config[8] * config[8] - 2.0 * config[8] * cgamma), 1.5);
- float zenith = sqrt(ctheta);
-
- return (1.0 + config[0] * exp(config[1] / (ctheta + 0.01))) *
- (config[2] + config[3] * expM + config[5] * rayM + config[6] * mieM + config[7] * zenith);
+ float ctheta = cos(theta);
+ float cgamma = cos(gamma);
+
+ float expM = exp(config[4] * gamma);
+ float rayM = cgamma * cgamma;
+ float mieM = (1.0 + rayM) / pow((1.0 + config[8] * config[8] - 2.0 * config[8] * cgamma), 1.5);
+ float zenith = sqrt(ctheta);
+
+ return (1.0 + config[0] * exp(config[1] / (ctheta + 0.01))) *
+ (config[2] + config[3] * expM + config[5] * rayM + config[6] * mieM + config[7] * zenith);
}
color sky_radiance_new(normal dir,
- float sunphi, float suntheta, color radiance,
- float config_x[9], float config_y[9], float config_z[9])
+ float sunphi,
+ float suntheta,
+ color radiance,
+ float config_x[9],
+ float config_y[9],
+ float config_z[9])
{
- /* convert vector to spherical coordinates */
- vector spherical = sky_spherical_coordinates(dir);
- float theta = spherical[0];
- float phi = spherical[1];
+ /* convert vector to spherical coordinates */
+ vector spherical = sky_spherical_coordinates(dir);
+ float theta = spherical[0];
+ float phi = spherical[1];
- /* angle between sun direction and dir */
- float gamma = sky_angle_between(theta, phi, suntheta, sunphi);
+ /* angle between sun direction and dir */
+ float gamma = sky_angle_between(theta, phi, suntheta, sunphi);
- /* clamp theta to horizon */
- theta = min(theta, M_PI_2 - 0.001);
+ /* clamp theta to horizon */
+ theta = min(theta, M_PI_2 - 0.001);
- /* compute xyz color space values */
- float x = sky_radiance_internal(config_x, theta, gamma) * radiance[0];
- float y = sky_radiance_internal(config_y, theta, gamma) * radiance[1];
- float z = sky_radiance_internal(config_z, theta, gamma) * radiance[2];
+ /* compute xyz color space values */
+ float x = sky_radiance_internal(config_x, theta, gamma) * radiance[0];
+ float y = sky_radiance_internal(config_y, theta, gamma) * radiance[1];
+ float z = sky_radiance_internal(config_z, theta, gamma) * radiance[2];
- /* convert to RGB and adjust strength */
- return xyz_to_rgb(x, y, z) * (M_2PI / 683);
+ /* convert to RGB and adjust strength */
+ return xyz_to_rgb(x, y, z) * (M_2PI / 683);
}
-shader node_sky_texture(
- int use_mapping = 0,
- matrix mapping = matrix(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
- vector Vector = P,
- string type = "hosek_wilkie",
- float theta = 0.0,
- float phi = 0.0,
- color radiance = color(0.0, 0.0, 0.0),
- float config_x[9] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
- float config_y[9] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
- float config_z[9] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
- output color Color = color(0.0, 0.0, 0.0))
+shader node_sky_texture(int use_mapping = 0,
+ matrix mapping = matrix(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
+ vector Vector = P,
+ string type = "hosek_wilkie",
+ float theta = 0.0,
+ float phi = 0.0,
+ color radiance = color(0.0, 0.0, 0.0),
+ float config_x[9] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
+ float config_y[9] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
+ float config_z[9] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
+ output color Color = color(0.0, 0.0, 0.0))
{
- vector p = Vector;
-
- if (use_mapping)
- p = transform(mapping, p);
-
- if (type == "hosek_wilkie")
- Color = sky_radiance_new(p, phi, theta, radiance, config_x, config_y, config_z);
- else
- Color = sky_radiance_old(p, phi, theta, radiance, config_x, config_y, config_z);
-}
+ vector p = Vector;
+ if (use_mapping)
+ p = transform(mapping, p);
+
+ if (type == "hosek_wilkie")
+ Color = sky_radiance_new(p, phi, theta, radiance, config_x, config_y, config_z);
+ else
+ Color = sky_radiance_old(p, phi, theta, radiance, config_x, config_y, config_z);
+}
diff --git a/intern/cycles/kernel/shaders/node_subsurface_scattering.osl b/intern/cycles/kernel/shaders/node_subsurface_scattering.osl
index 0df3256e1fd..e12199d8c3d 100644
--- a/intern/cycles/kernel/shaders/node_subsurface_scattering.osl
+++ b/intern/cycles/kernel/shaders/node_subsurface_scattering.osl
@@ -16,23 +16,30 @@
#include "stdosl.h"
-shader node_subsurface_scattering(
- color Color = 0.8,
- float Scale = 1.0,
- vector Radius = vector(0.1, 0.1, 0.1),
- float TextureBlur = 0.0,
- float Sharpness = 0.0,
- string falloff = "cubic",
- normal Normal = N,
- output closure color BSSRDF = 0)
+shader node_subsurface_scattering(color Color = 0.8,
+ float Scale = 1.0,
+ vector Radius = vector(0.1, 0.1, 0.1),
+ float TextureBlur = 0.0,
+ float Sharpness = 0.0,
+ string falloff = "cubic",
+ normal Normal = N,
+ output closure color BSSRDF = 0)
{
- if (falloff == "gaussian")
- BSSRDF = Color * bssrdf("gaussian", Normal, Scale * Radius, Color, "texture_blur", TextureBlur);
- else if (falloff == "cubic")
- BSSRDF = Color * bssrdf("cubic", Normal, Scale * Radius, Color, "texture_blur", TextureBlur, "sharpness", Sharpness);
- else if (falloff == "burley")
- BSSRDF = Color * bssrdf("burley", Normal, Scale * Radius, Color, "texture_blur", TextureBlur);
- else
- BSSRDF = Color * bssrdf("random_walk", Normal, Scale * Radius, Color, "texture_blur", TextureBlur);
+ if (falloff == "gaussian")
+ BSSRDF = Color *
+ bssrdf("gaussian", Normal, Scale * Radius, Color, "texture_blur", TextureBlur);
+ else if (falloff == "cubic")
+ BSSRDF = Color * bssrdf("cubic",
+ Normal,
+ Scale * Radius,
+ Color,
+ "texture_blur",
+ TextureBlur,
+ "sharpness",
+ Sharpness);
+ else if (falloff == "burley")
+ BSSRDF = Color * bssrdf("burley", Normal, Scale * Radius, Color, "texture_blur", TextureBlur);
+ else
+ BSSRDF = Color *
+ bssrdf("random_walk", Normal, Scale * Radius, Color, "texture_blur", TextureBlur);
}
-
diff --git a/intern/cycles/kernel/shaders/node_tangent.osl b/intern/cycles/kernel/shaders/node_tangent.osl
index c527070a2c8..44eb9973f3d 100644
--- a/intern/cycles/kernel/shaders/node_tangent.osl
+++ b/intern/cycles/kernel/shaders/node_tangent.osl
@@ -16,33 +16,31 @@
#include "stdosl.h"
-shader node_tangent(
- normal NormalIn = N,
- string attr_name = "geom:tangent",
- string direction_type = "radial",
- string axis = "z",
- output normal Tangent = normalize(dPdu))
+shader node_tangent(normal NormalIn = N,
+ string attr_name = "geom:tangent",
+ string direction_type = "radial",
+ string axis = "z",
+ output normal Tangent = normalize(dPdu))
{
- vector T;
+ vector T;
- if (direction_type == "uv_map") {
- getattribute(attr_name, T);
- }
- else if (direction_type == "radial") {
- point generated;
+ if (direction_type == "uv_map") {
+ getattribute(attr_name, T);
+ }
+ else if (direction_type == "radial") {
+ point generated;
- if (!getattribute("geom:generated", generated))
- generated = P;
+ if (!getattribute("geom:generated", generated))
+ generated = P;
- if (axis == "x")
- T = vector(0.0, -(generated[2] - 0.5), (generated[1] - 0.5));
- else if (axis == "y")
- T = vector(-(generated[2] - 0.5), 0.0, (generated[0] - 0.5));
- else
- T = vector(-(generated[1] - 0.5), (generated[0] - 0.5), 0.0);
- }
+ if (axis == "x")
+ T = vector(0.0, -(generated[2] - 0.5), (generated[1] - 0.5));
+ else if (axis == "y")
+ T = vector(-(generated[2] - 0.5), 0.0, (generated[0] - 0.5));
+ else
+ T = vector(-(generated[1] - 0.5), (generated[0] - 0.5), 0.0);
+ }
- T = transform("object", "world", T);
- Tangent = cross(NormalIn, normalize(cross(T, NormalIn)));
+ T = transform("object", "world", T);
+ Tangent = cross(NormalIn, normalize(cross(T, NormalIn)));
}
-
diff --git a/intern/cycles/kernel/shaders/node_texture.h b/intern/cycles/kernel/shaders/node_texture.h
index 88305fb320f..e1f3b900ee5 100644
--- a/intern/cycles/kernel/shaders/node_texture.h
+++ b/intern/cycles/kernel/shaders/node_texture.h
@@ -18,148 +18,148 @@
color cellnoise_color(point p)
{
- float r = cellnoise(p);
- float g = cellnoise(point(p[1], p[0], p[2]));
- float b = cellnoise(point(p[1], p[2], p[0]));
+ float r = cellnoise(p);
+ float g = cellnoise(point(p[1], p[0], p[2]));
+ float b = cellnoise(point(p[1], p[2], p[0]));
- return color(r, g, b);
+ return color(r, g, b);
}
void voronoi(point p, float e, float da[4], point pa[4])
{
- /* returns distances in da and point coords in pa */
- int xx, yy, zz, xi, yi, zi;
-
- xi = (int)floor(p[0]);
- yi = (int)floor(p[1]);
- zi = (int)floor(p[2]);
-
- da[0] = 1e10;
- da[1] = 1e10;
- da[2] = 1e10;
- da[3] = 1e10;
-
- for (xx = xi - 1; xx <= xi + 1; xx++) {
- for (yy = yi - 1; yy <= yi + 1; yy++) {
- for (zz = zi - 1; zz <= zi + 1; zz++) {
- point ip = point(xx, yy, zz);
- point vp = (point)cellnoise_color(ip);
- point pd = p - (vp + ip);
- float d = dot(pd, pd);
-
- vp += point(xx, yy, zz);
-
- if (d < da[0]) {
- da[3] = da[2];
- da[2] = da[1];
- da[1] = da[0];
- da[0] = d;
-
- pa[3] = pa[2];
- pa[2] = pa[1];
- pa[1] = pa[0];
- pa[0] = vp;
- }
- else if (d < da[1]) {
- da[3] = da[2];
- da[2] = da[1];
- da[1] = d;
-
- pa[3] = pa[2];
- pa[2] = pa[1];
- pa[1] = vp;
- }
- else if (d < da[2]) {
- da[3] = da[2];
- da[2] = d;
-
- pa[3] = pa[2];
- pa[2] = vp;
- }
- else if (d < da[3]) {
- da[3] = d;
- pa[3] = vp;
- }
- }
- }
- }
+ /* returns distances in da and point coords in pa */
+ int xx, yy, zz, xi, yi, zi;
+
+ xi = (int)floor(p[0]);
+ yi = (int)floor(p[1]);
+ zi = (int)floor(p[2]);
+
+ da[0] = 1e10;
+ da[1] = 1e10;
+ da[2] = 1e10;
+ da[3] = 1e10;
+
+ for (xx = xi - 1; xx <= xi + 1; xx++) {
+ for (yy = yi - 1; yy <= yi + 1; yy++) {
+ for (zz = zi - 1; zz <= zi + 1; zz++) {
+ point ip = point(xx, yy, zz);
+ point vp = (point)cellnoise_color(ip);
+ point pd = p - (vp + ip);
+ float d = dot(pd, pd);
+
+ vp += point(xx, yy, zz);
+
+ if (d < da[0]) {
+ da[3] = da[2];
+ da[2] = da[1];
+ da[1] = da[0];
+ da[0] = d;
+
+ pa[3] = pa[2];
+ pa[2] = pa[1];
+ pa[1] = pa[0];
+ pa[0] = vp;
+ }
+ else if (d < da[1]) {
+ da[3] = da[2];
+ da[2] = da[1];
+ da[1] = d;
+
+ pa[3] = pa[2];
+ pa[2] = pa[1];
+ pa[1] = vp;
+ }
+ else if (d < da[2]) {
+ da[3] = da[2];
+ da[2] = d;
+
+ pa[3] = pa[2];
+ pa[2] = vp;
+ }
+ else if (d < da[3]) {
+ da[3] = d;
+ pa[3] = vp;
+ }
+ }
+ }
+ }
}
/* Noise Bases */
float safe_noise(point p, string type)
{
- float f = 0.0;
+ float f = 0.0;
- /* Perlin noise in range -1..1 */
- if (type == "signed")
- f = noise("perlin", p);
+ /* Perlin noise in range -1..1 */
+ if (type == "signed")
+ f = noise("perlin", p);
- /* Perlin noise in range 0..1 */
- else
- f = noise(p);
+ /* Perlin noise in range 0..1 */
+ else
+ f = noise(p);
- /* can happen for big coordinates, things even out to 0.5 then anyway */
- if (!isfinite(f))
- return 0.5;
+ /* can happen for big coordinates, things even out to 0.5 then anyway */
+ if (!isfinite(f))
+ return 0.5;
- return f;
+ return f;
}
/* Turbulence */
float noise_turbulence(point p, float details, int hard)
{
- float fscale = 1.0;
- float amp = 1.0;
- float sum = 0.0;
- int i, n;
+ float fscale = 1.0;
+ float amp = 1.0;
+ float sum = 0.0;
+ int i, n;
- float octaves = clamp(details, 0.0, 16.0);
- n = (int)octaves;
+ float octaves = clamp(details, 0.0, 16.0);
+ n = (int)octaves;
- for (i = 0; i <= n; i++) {
- float t = safe_noise(fscale * p, "unsigned");
+ for (i = 0; i <= n; i++) {
+ float t = safe_noise(fscale * p, "unsigned");
- if (hard)
- t = fabs(2.0 * t - 1.0);
+ if (hard)
+ t = fabs(2.0 * t - 1.0);
- sum += t * amp;
- amp *= 0.5;
- fscale *= 2.0;
- }
+ sum += t * amp;
+ amp *= 0.5;
+ fscale *= 2.0;
+ }
- float rmd = octaves - floor(octaves);
+ float rmd = octaves - floor(octaves);
- if (rmd != 0.0) {
- float t = safe_noise(fscale * p, "unsigned");
+ if (rmd != 0.0) {
+ float t = safe_noise(fscale * p, "unsigned");
- if (hard)
- t = fabs(2.0 * t - 1.0);
+ if (hard)
+ t = fabs(2.0 * t - 1.0);
- float sum2 = sum + t * amp;
+ float sum2 = sum + t * amp;
- sum *= ((float)(1 << n) / (float)((1 << (n + 1)) - 1));
- sum2 *= ((float)(1 << (n + 1)) / (float)((1 << (n + 2)) - 1));
+ sum *= ((float)(1 << n) / (float)((1 << (n + 1)) - 1));
+ sum2 *= ((float)(1 << (n + 1)) / (float)((1 << (n + 2)) - 1));
- return (1.0 - rmd) * sum + rmd * sum2;
- }
- else {
- sum *= ((float)(1 << n) / (float)((1 << (n + 1)) - 1));
- return sum;
- }
+ return (1.0 - rmd) * sum + rmd * sum2;
+ }
+ else {
+ sum *= ((float)(1 << n) / (float)((1 << (n + 1)) - 1));
+ return sum;
+ }
}
/* Utility */
float nonzero(float f, float eps)
{
- float r;
+ float r;
- if (abs(f) < eps)
- r = sign(f) * eps;
- else
- r = f;
+ if (abs(f) < eps)
+ r = sign(f) * eps;
+ else
+ r = f;
- return r;
+ return r;
}
diff --git a/intern/cycles/kernel/shaders/node_texture_coordinate.osl b/intern/cycles/kernel/shaders/node_texture_coordinate.osl
index 9e2109fa082..13861653d04 100644
--- a/intern/cycles/kernel/shaders/node_texture_coordinate.osl
+++ b/intern/cycles/kernel/shaders/node_texture_coordinate.osl
@@ -17,82 +17,81 @@
#include "stdosl.h"
shader node_texture_coordinate(
- normal NormalIn = N,
- int is_background = 0,
- int is_volume = 0,
- int from_dupli = 0,
- int use_transform = 0,
- string bump_offset = "center",
- matrix object_itfm = matrix(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
+ normal NormalIn = N,
+ int is_background = 0,
+ int is_volume = 0,
+ int from_dupli = 0,
+ int use_transform = 0,
+ string bump_offset = "center",
+ matrix object_itfm = matrix(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
- output point Generated = point(0.0, 0.0, 0.0),
- output point UV = point(0.0, 0.0, 0.0),
- output point Object = point(0.0, 0.0, 0.0),
- output point Camera = point(0.0, 0.0, 0.0),
- output point Window = point(0.0, 0.0, 0.0),
- output normal Normal = normal(0.0, 0.0, 0.0),
- output point Reflection = point(0.0, 0.0, 0.0))
+ output point Generated = point(0.0, 0.0, 0.0),
+ output point UV = point(0.0, 0.0, 0.0),
+ output point Object = point(0.0, 0.0, 0.0),
+ output point Camera = point(0.0, 0.0, 0.0),
+ output point Window = point(0.0, 0.0, 0.0),
+ output normal Normal = normal(0.0, 0.0, 0.0),
+ output point Reflection = point(0.0, 0.0, 0.0))
{
- if (is_background) {
- Generated = P;
- UV = point(0.0, 0.0, 0.0);
- Object = P;
- point Pcam = transform("camera", "world", point(0, 0, 0));
- Camera = transform("camera", P + Pcam);
- getattribute("NDC", Window);
- Normal = NormalIn;
- Reflection = I;
- }
- else {
- if (from_dupli) {
- getattribute("geom:dupli_generated", Generated);
- getattribute("geom:dupli_uv", UV);
- }
- else if (is_volume) {
- Generated = transform("object", P);
+ if (is_background) {
+ Generated = P;
+ UV = point(0.0, 0.0, 0.0);
+ Object = P;
+ point Pcam = transform("camera", "world", point(0, 0, 0));
+ Camera = transform("camera", P + Pcam);
+ getattribute("NDC", Window);
+ Normal = NormalIn;
+ Reflection = I;
+ }
+ else {
+ if (from_dupli) {
+ getattribute("geom:dupli_generated", Generated);
+ getattribute("geom:dupli_uv", UV);
+ }
+ else if (is_volume) {
+ Generated = transform("object", P);
- matrix tfm;
- if (getattribute("geom:generated_transform", tfm))
- Generated = transform(tfm, Generated);
+ matrix tfm;
+ if (getattribute("geom:generated_transform", tfm))
+ Generated = transform(tfm, Generated);
- getattribute("geom:uv", UV);
- }
- else {
- getattribute("geom:generated", Generated);
- getattribute("geom:uv", UV);
- }
+ getattribute("geom:uv", UV);
+ }
+ else {
+ getattribute("geom:generated", Generated);
+ getattribute("geom:uv", UV);
+ }
- if (use_transform) {
- Object = transform(object_itfm, P);
- }
- else {
- Object = transform("object", P);
- }
- Camera = transform("camera", P);
- Window = transform("NDC", P);
- Normal = transform("world", "object", NormalIn);
- Reflection = -reflect(I, NormalIn);
- }
+ if (use_transform) {
+ Object = transform(object_itfm, P);
+ }
+ else {
+ Object = transform("object", P);
+ }
+ Camera = transform("camera", P);
+ Window = transform("NDC", P);
+ Normal = transform("world", "object", NormalIn);
+ Reflection = -reflect(I, NormalIn);
+ }
- if (bump_offset == "dx") {
- if (!from_dupli) {
- Generated += Dx(Generated);
- UV += Dx(UV);
- }
- Object += Dx(Object);
- Camera += Dx(Camera);
- Window += Dx(Window);
- }
- else if (bump_offset == "dy") {
- if (!from_dupli) {
- Generated += Dy(Generated);
- UV += Dy(UV);
- }
- Object += Dy(Object);
- Camera += Dy(Camera);
- Window += Dy(Window);
- }
+ if (bump_offset == "dx") {
+ if (!from_dupli) {
+ Generated += Dx(Generated);
+ UV += Dx(UV);
+ }
+ Object += Dx(Object);
+ Camera += Dx(Camera);
+ Window += Dx(Window);
+ }
+ else if (bump_offset == "dy") {
+ if (!from_dupli) {
+ Generated += Dy(Generated);
+ UV += Dy(UV);
+ }
+ Object += Dy(Object);
+ Camera += Dy(Camera);
+ Window += Dy(Window);
+ }
- Window[2] = 0.0;
+ Window[2] = 0.0;
}
-
diff --git a/intern/cycles/kernel/shaders/node_toon_bsdf.osl b/intern/cycles/kernel/shaders/node_toon_bsdf.osl
index ae68a463e46..ed3a0b25c60 100644
--- a/intern/cycles/kernel/shaders/node_toon_bsdf.osl
+++ b/intern/cycles/kernel/shaders/node_toon_bsdf.osl
@@ -16,17 +16,15 @@
#include "stdosl.h"
-shader node_toon_bsdf(
- color Color = 0.8,
- string component = "diffuse",
- float Size = 0.5,
- float Smooth = 0.0,
- normal Normal = N,
- output closure color BSDF = 0)
+shader node_toon_bsdf(color Color = 0.8,
+ string component = "diffuse",
+ float Size = 0.5,
+ float Smooth = 0.0,
+ normal Normal = N,
+ output closure color BSDF = 0)
{
- if (component == "diffuse")
- BSDF = Color * diffuse_toon(Normal, Size, Smooth);
- else if (component == "glossy")
- BSDF = Color * glossy_toon(Normal, Size, Smooth);
+ if (component == "diffuse")
+ BSDF = Color * diffuse_toon(Normal, Size, Smooth);
+ else if (component == "glossy")
+ BSDF = Color * glossy_toon(Normal, Size, Smooth);
}
-
diff --git a/intern/cycles/kernel/shaders/node_translucent_bsdf.osl b/intern/cycles/kernel/shaders/node_translucent_bsdf.osl
index 94d23d35326..7ce1ab08c59 100644
--- a/intern/cycles/kernel/shaders/node_translucent_bsdf.osl
+++ b/intern/cycles/kernel/shaders/node_translucent_bsdf.osl
@@ -16,11 +16,7 @@
#include "stdosl.h"
-shader node_translucent_bsdf(
- color Color = 0.8,
- normal Normal = N,
- output closure color BSDF = 0)
+shader node_translucent_bsdf(color Color = 0.8, normal Normal = N, output closure color BSDF = 0)
{
- BSDF = Color * translucent(Normal);
+ BSDF = Color * translucent(Normal);
}
-
diff --git a/intern/cycles/kernel/shaders/node_transparent_bsdf.osl b/intern/cycles/kernel/shaders/node_transparent_bsdf.osl
index 5d6798f19a6..a735513ba89 100644
--- a/intern/cycles/kernel/shaders/node_transparent_bsdf.osl
+++ b/intern/cycles/kernel/shaders/node_transparent_bsdf.osl
@@ -16,11 +16,7 @@
#include "stdosl.h"
-shader node_transparent_bsdf(
- color Color = 0.8,
- normal Normal = N,
- output closure color BSDF = 0)
+shader node_transparent_bsdf(color Color = 0.8, normal Normal = N, output closure color BSDF = 0)
{
- BSDF = Color * transparent();
+ BSDF = Color * transparent();
}
-
diff --git a/intern/cycles/kernel/shaders/node_uv_map.osl b/intern/cycles/kernel/shaders/node_uv_map.osl
index b46b2e73457..6f2887be63c 100644
--- a/intern/cycles/kernel/shaders/node_uv_map.osl
+++ b/intern/cycles/kernel/shaders/node_uv_map.osl
@@ -16,30 +16,29 @@
#include "stdosl.h"
-shader node_uv_map(
- int from_dupli = 0,
- string attribute = "",
- string bump_offset = "center",
- output point UV = point(0.0, 0.0, 0.0))
+shader node_uv_map(int from_dupli = 0,
+ string attribute = "",
+ string bump_offset = "center",
+ output point UV = point(0.0, 0.0, 0.0))
{
- if (from_dupli) {
- getattribute("geom:dupli_uv", UV);
- }
- else {
- if (attribute == "")
- getattribute("geom:uv", UV);
- else
- getattribute(attribute, UV);
- }
+ if (from_dupli) {
+ getattribute("geom:dupli_uv", UV);
+ }
+ else {
+ if (attribute == "")
+ getattribute("geom:uv", UV);
+ else
+ getattribute(attribute, UV);
+ }
- if (bump_offset == "dx") {
- if (!from_dupli) {
- UV += Dx(UV);
- }
- }
- else if (bump_offset == "dy") {
- if (!from_dupli) {
- UV += Dy(UV);
- }
- }
+ if (bump_offset == "dx") {
+ if (!from_dupli) {
+ UV += Dx(UV);
+ }
+ }
+ else if (bump_offset == "dy") {
+ if (!from_dupli) {
+ UV += Dy(UV);
+ }
+ }
}
diff --git a/intern/cycles/kernel/shaders/node_value.osl b/intern/cycles/kernel/shaders/node_value.osl
index f75388d1f76..398e2c0e392 100644
--- a/intern/cycles/kernel/shaders/node_value.osl
+++ b/intern/cycles/kernel/shaders/node_value.osl
@@ -16,16 +16,14 @@
#include "stdosl.h"
-shader node_value(
- float value_value = 0.0,
- vector vector_value = vector(0.0, 0.0, 0.0),
- color color_value = 0.0,
- output float Value = 0.0,
- output vector Vector = vector(0.0, 0.0, 0.0),
- output color Color = 0.0)
+shader node_value(float value_value = 0.0,
+ vector vector_value = vector(0.0, 0.0, 0.0),
+ color color_value = 0.0,
+ output float Value = 0.0,
+ output vector Vector = vector(0.0, 0.0, 0.0),
+ output color Color = 0.0)
{
- Value = value_value;
- Vector = vector_value;
- Color = color_value;
+ Value = value_value;
+ Vector = vector_value;
+ Color = color_value;
}
-
diff --git a/intern/cycles/kernel/shaders/node_vector_curves.osl b/intern/cycles/kernel/shaders/node_vector_curves.osl
index ff284c48e0a..e8c8036b550 100644
--- a/intern/cycles/kernel/shaders/node_vector_curves.osl
+++ b/intern/cycles/kernel/shaders/node_vector_curves.osl
@@ -17,25 +17,23 @@
#include "stdosl.h"
#include "node_ramp_util.h"
-shader node_vector_curves(
- color ramp[] = {0.0},
- float min_x = 0.0,
- float max_x = 1.0,
+shader node_vector_curves(color ramp[] = {0.0},
+ float min_x = 0.0,
+ float max_x = 1.0,
- vector VectorIn = vector(0.0, 0.0, 0.0),
- float Fac = 0.0,
- output vector VectorOut = vector(0.0, 0.0, 0.0))
+ vector VectorIn = vector(0.0, 0.0, 0.0),
+ float Fac = 0.0,
+ output vector VectorOut = vector(0.0, 0.0, 0.0))
{
- vector c = (VectorIn - vector(min_x, min_x, min_x)) / (max_x - min_x);
+ vector c = (VectorIn - vector(min_x, min_x, min_x)) / (max_x - min_x);
- color r = rgb_ramp_lookup(ramp, c[0], 1, 1);
- color g = rgb_ramp_lookup(ramp, c[0], 1, 1);
- color b = rgb_ramp_lookup(ramp, c[0], 1, 1);
+ color r = rgb_ramp_lookup(ramp, c[0], 1, 1);
+ color g = rgb_ramp_lookup(ramp, c[0], 1, 1);
+ color b = rgb_ramp_lookup(ramp, c[0], 1, 1);
- VectorOut[0] = r[0];
- VectorOut[1] = g[1];
- VectorOut[2] = b[2];
+ VectorOut[0] = r[0];
+ VectorOut[1] = g[1];
+ VectorOut[2] = b[2];
- VectorOut = mix(VectorIn, VectorOut, Fac);
+ VectorOut = mix(VectorIn, VectorOut, Fac);
}
-
diff --git a/intern/cycles/kernel/shaders/node_vector_displacement.osl b/intern/cycles/kernel/shaders/node_vector_displacement.osl
index b19bc228e37..e9bd336347f 100644
--- a/intern/cycles/kernel/shaders/node_vector_displacement.osl
+++ b/intern/cycles/kernel/shaders/node_vector_displacement.osl
@@ -16,45 +16,43 @@
#include "stdosl.h"
-shader node_vector_displacement(
- color Vector = color(0.0, 0.0, 0.0),
- float Midlevel = 0.0,
- float Scale = 1.0,
- string space = "tangent",
- string attr_name = "geom:tangent",
- string attr_sign_name = "geom:tangent_sign",
- output vector Displacement = vector(0.0, 0.0, 0.0))
+shader node_vector_displacement(color Vector = color(0.0, 0.0, 0.0),
+ float Midlevel = 0.0,
+ float Scale = 1.0,
+ string space = "tangent",
+ string attr_name = "geom:tangent",
+ string attr_sign_name = "geom:tangent_sign",
+ output vector Displacement = vector(0.0, 0.0, 0.0))
{
- vector offset = (Vector - vector(Midlevel)) * Scale;
-
- if(space == "tangent") {
- /* Tangent space. */
- vector N_object = normalize(transform("world", "object", N));
-
- vector T_object;
- if(getattribute(attr_name, T_object)) {
- T_object = normalize(T_object);
- }
- else {
- T_object = normalize(dPdu);
- }
-
- vector B_object = normalize(cross(N_object, T_object));
- float tangent_sign;
- if(getattribute(attr_sign_name, tangent_sign)) {
- B_object *= tangent_sign;
- }
-
- Displacement = T_object*offset[0] + N_object*offset[1] + B_object*offset[2];
- }
- else {
- /* Object or world space. */
- Displacement = offset;
- }
-
- if(space != "world") {
- /* Tangent or object space. */
- Displacement = transform("object", "world", Displacement);
- }
+ vector offset = (Vector - vector(Midlevel)) * Scale;
+
+ if (space == "tangent") {
+ /* Tangent space. */
+ vector N_object = normalize(transform("world", "object", N));
+
+ vector T_object;
+ if (getattribute(attr_name, T_object)) {
+ T_object = normalize(T_object);
+ }
+ else {
+ T_object = normalize(dPdu);
+ }
+
+ vector B_object = normalize(cross(N_object, T_object));
+ float tangent_sign;
+ if (getattribute(attr_sign_name, tangent_sign)) {
+ B_object *= tangent_sign;
+ }
+
+ Displacement = T_object * offset[0] + N_object * offset[1] + B_object * offset[2];
+ }
+ else {
+ /* Object or world space. */
+ Displacement = offset;
+ }
+
+ if (space != "world") {
+ /* Tangent or object space. */
+ Displacement = transform("object", "world", Displacement);
+ }
}
-
diff --git a/intern/cycles/kernel/shaders/node_vector_math.osl b/intern/cycles/kernel/shaders/node_vector_math.osl
index a7e3637402e..10bb0c7283c 100644
--- a/intern/cycles/kernel/shaders/node_vector_math.osl
+++ b/intern/cycles/kernel/shaders/node_vector_math.osl
@@ -16,36 +16,34 @@
#include "stdosl.h"
-shader node_vector_math(
- string type = "add",
- vector Vector1 = vector(0.0, 0.0, 0.0),
- vector Vector2 = vector(0.0, 0.0, 0.0),
- output float Value = 0.0,
- output vector Vector = vector(0.0, 0.0, 0.0))
+shader node_vector_math(string type = "add",
+ vector Vector1 = vector(0.0, 0.0, 0.0),
+ vector Vector2 = vector(0.0, 0.0, 0.0),
+ output float Value = 0.0,
+ output vector Vector = vector(0.0, 0.0, 0.0))
{
- if (type == "add") {
- Vector = Vector1 + Vector2;
- Value = (abs(Vector[0]) + abs(Vector[1]) + abs(Vector[2])) / 3.0;
- }
- else if (type == "subtract") {
- Vector = Vector1 - Vector2;
- Value = (abs(Vector[0]) + abs(Vector[1]) + abs(Vector[2])) / 3.0;
- }
- else if (type == "average") {
- Value = length(Vector1 + Vector2);
- Vector = normalize(Vector1 + Vector2);
- }
- else if (type == "dot_product") {
- Value = dot(Vector1, Vector2);
- }
- else if (type == "cross_product") {
- vector c = cross(Vector1, Vector2);
- Value = length(c);
- Vector = normalize(c);
- }
- else if (type == "normalize") {
- Value = length(Vector1);
- Vector = normalize(Vector1);
- }
+ if (type == "add") {
+ Vector = Vector1 + Vector2;
+ Value = (abs(Vector[0]) + abs(Vector[1]) + abs(Vector[2])) / 3.0;
+ }
+ else if (type == "subtract") {
+ Vector = Vector1 - Vector2;
+ Value = (abs(Vector[0]) + abs(Vector[1]) + abs(Vector[2])) / 3.0;
+ }
+ else if (type == "average") {
+ Value = length(Vector1 + Vector2);
+ Vector = normalize(Vector1 + Vector2);
+ }
+ else if (type == "dot_product") {
+ Value = dot(Vector1, Vector2);
+ }
+ else if (type == "cross_product") {
+ vector c = cross(Vector1, Vector2);
+ Value = length(c);
+ Vector = normalize(c);
+ }
+ else if (type == "normalize") {
+ Value = length(Vector1);
+ Vector = normalize(Vector1);
+ }
}
-
diff --git a/intern/cycles/kernel/shaders/node_vector_transform.osl b/intern/cycles/kernel/shaders/node_vector_transform.osl
index afb95b340d1..22939577be0 100644
--- a/intern/cycles/kernel/shaders/node_vector_transform.osl
+++ b/intern/cycles/kernel/shaders/node_vector_transform.osl
@@ -16,21 +16,19 @@
#include "stdosl.h"
-shader node_vector_transform(
- string type = "vector",
- string convert_from = "world",
- string convert_to = "object",
- vector VectorIn = vector(0.0, 0.0, 0.0),
- output vector VectorOut = vector(0.0, 0.0, 0.0))
+shader node_vector_transform(string type = "vector",
+ string convert_from = "world",
+ string convert_to = "object",
+ vector VectorIn = vector(0.0, 0.0, 0.0),
+ output vector VectorOut = vector(0.0, 0.0, 0.0))
{
- if (type == "vector" || type == "normal") {
- VectorOut = transform(convert_from, convert_to, VectorIn);
- if (type == "normal")
- VectorOut = normalize(VectorOut);
- }
- else if (type == "point") {
- point Point = (point)VectorIn;
- VectorOut = transform(convert_from, convert_to, Point);
- }
+ if (type == "vector" || type == "normal") {
+ VectorOut = transform(convert_from, convert_to, VectorIn);
+ if (type == "normal")
+ VectorOut = normalize(VectorOut);
+ }
+ else if (type == "point") {
+ point Point = (point)VectorIn;
+ VectorOut = transform(convert_from, convert_to, Point);
+ }
}
-
diff --git a/intern/cycles/kernel/shaders/node_velvet_bsdf.osl b/intern/cycles/kernel/shaders/node_velvet_bsdf.osl
index 456c26998c8..9290b845325 100644
--- a/intern/cycles/kernel/shaders/node_velvet_bsdf.osl
+++ b/intern/cycles/kernel/shaders/node_velvet_bsdf.osl
@@ -17,14 +17,12 @@
#include "stdosl.h"
#include "node_fresnel.h"
-shader node_velvet_bsdf(
- color Color = 0.8,
- float Sigma = 0.0,
- normal Normal = N,
- output closure color BSDF = 0)
+shader node_velvet_bsdf(color Color = 0.8,
+ float Sigma = 0.0,
+ normal Normal = N,
+ output closure color BSDF = 0)
{
- float sigma = clamp(Sigma, 0.0, 1.0);
+ float sigma = clamp(Sigma, 0.0, 1.0);
- BSDF = Color * ashikhmin_velvet(Normal, sigma);
+ BSDF = Color * ashikhmin_velvet(Normal, sigma);
}
-
diff --git a/intern/cycles/kernel/shaders/node_voronoi_texture.osl b/intern/cycles/kernel/shaders/node_voronoi_texture.osl
index 2e47d74a414..34c86d5b98d 100644
--- a/intern/cycles/kernel/shaders/node_voronoi_texture.osl
+++ b/intern/cycles/kernel/shaders/node_voronoi_texture.osl
@@ -19,147 +19,146 @@
void voronoi_m(point p, string metric, float e, float da[4], point pa[4])
{
- /* Compute the distance to and the position of the four closest neighbors to p.
- *
- * The neighbors are randomly placed, 1 each in a 3x3x3 grid (Worley pattern).
- * The distances and points are returned in ascending order, i.e. da[0] and pa[0] will
- * contain the distance to the closest point and its coordinates respectively.
- */
- int xx, yy, zz, xi, yi, zi;
-
- xi = (int)floor(p[0]);
- yi = (int)floor(p[1]);
- zi = (int)floor(p[2]);
-
- da[0] = 1e10;
- da[1] = 1e10;
- da[2] = 1e10;
- da[3] = 1e10;
-
- for (xx = xi - 1; xx <= xi + 1; xx++) {
- for (yy = yi - 1; yy <= yi + 1; yy++) {
- for (zz = zi - 1; zz <= zi + 1; zz++) {
- point ip = point(xx, yy, zz);
- point vp = (point)cellnoise_color(ip);
- point pd = p - (vp + ip);
-
- float d = 0.0;
- if (metric == "distance") {
- d = dot(pd, pd);
- }
- else if (metric == "manhattan") {
- d = fabs(pd[0]) + fabs(pd[1]) + fabs(pd[2]);
- }
- else if (metric == "chebychev") {
- d = max(fabs(pd[0]), max(fabs(pd[1]), fabs(pd[2])));
- }
- else if (metric == "minkowski") {
- d = pow(pow(fabs(pd[0]), e) + pow(fabs(pd[1]), e) + pow(fabs(pd[2]), e), 1.0/e);
- }
-
- vp += point(xx, yy, zz);
-
- if (d < da[0]) {
- da[3] = da[2];
- da[2] = da[1];
- da[1] = da[0];
- da[0] = d;
-
- pa[3] = pa[2];
- pa[2] = pa[1];
- pa[1] = pa[0];
- pa[0] = vp;
- }
- else if (d < da[1]) {
- da[3] = da[2];
- da[2] = da[1];
- da[1] = d;
-
- pa[3] = pa[2];
- pa[2] = pa[1];
- pa[1] = vp;
- }
- else if (d < da[2]) {
- da[3] = da[2];
- da[2] = d;
-
- pa[3] = pa[2];
- pa[2] = vp;
- }
- else if (d < da[3]) {
- da[3] = d;
- pa[3] = vp;
- }
- }
- }
- }
+ /* Compute the distance to and the position of the four closest neighbors to p.
+ *
+ * The neighbors are randomly placed, 1 each in a 3x3x3 grid (Worley pattern).
+ * The distances and points are returned in ascending order, i.e. da[0] and pa[0] will
+ * contain the distance to the closest point and its coordinates respectively.
+ */
+ int xx, yy, zz, xi, yi, zi;
+
+ xi = (int)floor(p[0]);
+ yi = (int)floor(p[1]);
+ zi = (int)floor(p[2]);
+
+ da[0] = 1e10;
+ da[1] = 1e10;
+ da[2] = 1e10;
+ da[3] = 1e10;
+
+ for (xx = xi - 1; xx <= xi + 1; xx++) {
+ for (yy = yi - 1; yy <= yi + 1; yy++) {
+ for (zz = zi - 1; zz <= zi + 1; zz++) {
+ point ip = point(xx, yy, zz);
+ point vp = (point)cellnoise_color(ip);
+ point pd = p - (vp + ip);
+
+ float d = 0.0;
+ if (metric == "distance") {
+ d = dot(pd, pd);
+ }
+ else if (metric == "manhattan") {
+ d = fabs(pd[0]) + fabs(pd[1]) + fabs(pd[2]);
+ }
+ else if (metric == "chebychev") {
+ d = max(fabs(pd[0]), max(fabs(pd[1]), fabs(pd[2])));
+ }
+ else if (metric == "minkowski") {
+ d = pow(pow(fabs(pd[0]), e) + pow(fabs(pd[1]), e) + pow(fabs(pd[2]), e), 1.0 / e);
+ }
+
+ vp += point(xx, yy, zz);
+
+ if (d < da[0]) {
+ da[3] = da[2];
+ da[2] = da[1];
+ da[1] = da[0];
+ da[0] = d;
+
+ pa[3] = pa[2];
+ pa[2] = pa[1];
+ pa[1] = pa[0];
+ pa[0] = vp;
+ }
+ else if (d < da[1]) {
+ da[3] = da[2];
+ da[2] = da[1];
+ da[1] = d;
+
+ pa[3] = pa[2];
+ pa[2] = pa[1];
+ pa[1] = vp;
+ }
+ else if (d < da[2]) {
+ da[3] = da[2];
+ da[2] = d;
+
+ pa[3] = pa[2];
+ pa[2] = vp;
+ }
+ else if (d < da[3]) {
+ da[3] = d;
+ pa[3] = vp;
+ }
+ }
+ }
+ }
}
/* Voronoi */
shader node_voronoi_texture(
- int use_mapping = 0,
- matrix mapping = matrix(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
- string coloring = "intensity",
- string metric = "distance",
- string feature = "F1",
- float Exponent = 1.0,
- float Scale = 5.0,
- point Vector = P,
- output float Fac = 0.0,
- output color Color = 0.0)
+ int use_mapping = 0,
+ matrix mapping = matrix(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
+ string coloring = "intensity",
+ string metric = "distance",
+ string feature = "F1",
+ float Exponent = 1.0,
+ float Scale = 5.0,
+ point Vector = P,
+ output float Fac = 0.0,
+ output color Color = 0.0)
{
- point p = Vector;
-
- if (use_mapping)
- p = transform(mapping, p);
-
- /* compute distance and point coordinate of 4 nearest neighbours */
- float da[4];
- point pa[4];
-
- /* compute distance and point coordinate of 4 nearest neighbours */
- voronoi_m(p * Scale, metric, Exponent, da, pa);
-
- if (coloring == "intensity") {
- /* Intensity output */
- if (feature == "F1") {
- Fac = fabs(da[0]);
- }
- else if (feature == "F2") {
- Fac = fabs(da[1]);
- }
- else if (feature == "F3") {
- Fac = fabs(da[2]);
- }
- else if (feature == "F4") {
- Fac = fabs(da[3]);
- }
- else if (feature == "F2F1") {
- Fac = fabs(da[1] - da[0]);
- }
- Color = color(Fac);
- }
- else {
- /* Color output */
- if (feature == "F1") {
- Color = pa[0];
- }
- else if (feature == "F2") {
- Color = pa[1];
- }
- else if (feature == "F3") {
- Color = pa[2];
- }
- else if (feature == "F4") {
- Color = pa[3];
- }
- else if (feature == "F2F1") {
- Color = fabs(pa[1] - pa[0]);
- }
-
- Color = cellnoise_color(Color);
- Fac = (Color[0] + Color[1] + Color[2]) * (1.0 / 3.0);
- }
+ point p = Vector;
+
+ if (use_mapping)
+ p = transform(mapping, p);
+
+ /* compute distance and point coordinate of 4 nearest neighbours */
+ float da[4];
+ point pa[4];
+
+ /* compute distance and point coordinate of 4 nearest neighbours */
+ voronoi_m(p * Scale, metric, Exponent, da, pa);
+
+ if (coloring == "intensity") {
+ /* Intensity output */
+ if (feature == "F1") {
+ Fac = fabs(da[0]);
+ }
+ else if (feature == "F2") {
+ Fac = fabs(da[1]);
+ }
+ else if (feature == "F3") {
+ Fac = fabs(da[2]);
+ }
+ else if (feature == "F4") {
+ Fac = fabs(da[3]);
+ }
+ else if (feature == "F2F1") {
+ Fac = fabs(da[1] - da[0]);
+ }
+ Color = color(Fac);
+ }
+ else {
+ /* Color output */
+ if (feature == "F1") {
+ Color = pa[0];
+ }
+ else if (feature == "F2") {
+ Color = pa[1];
+ }
+ else if (feature == "F3") {
+ Color = pa[2];
+ }
+ else if (feature == "F4") {
+ Color = pa[3];
+ }
+ else if (feature == "F2F1") {
+ Color = fabs(pa[1] - pa[0]);
+ }
+
+ Color = cellnoise_color(Color);
+ Fac = (Color[0] + Color[1] + Color[2]) * (1.0 / 3.0);
+ }
}
-
diff --git a/intern/cycles/kernel/shaders/node_voxel_texture.osl b/intern/cycles/kernel/shaders/node_voxel_texture.osl
index 9253febd64a..0e4484561d8 100644
--- a/intern/cycles/kernel/shaders/node_voxel_texture.osl
+++ b/intern/cycles/kernel/shaders/node_voxel_texture.osl
@@ -16,32 +16,30 @@
#include "stdosl.h"
-shader node_voxel_texture(
- string filename = "",
- string interpolation = "linear",
- int use_mapping = 0,
- matrix mapping = matrix(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
- point Vector = P,
- output float Density = 0,
- output color Color = 0)
+shader node_voxel_texture(string filename = "",
+ string interpolation = "linear",
+ int use_mapping = 0,
+ matrix mapping = matrix(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
+ point Vector = P,
+ output float Density = 0,
+ output color Color = 0)
{
- point p = Vector;
- if (use_mapping) {
- p = transform(mapping, p);
- }
- else {
- p = transform("object", Vector);
- matrix tfm;
- if (getattribute("geom:generated_transform", tfm))
- p = transform(tfm, p);
- }
- if (p[0] < 0.0 || p[1] < 0.0 || p[2] < 0.0 ||
- p[0] > 1.0 || p[1] > 1.0 || p[2] > 1.0)
- {
- Density = 0;
- Color = color(0, 0, 0);
- }
- else {
- Color = (color)texture3d(filename, p, "wrap", "periodic", "interp", interpolation, "alpha", Density);
- }
+ point p = Vector;
+ if (use_mapping) {
+ p = transform(mapping, p);
+ }
+ else {
+ p = transform("object", Vector);
+ matrix tfm;
+ if (getattribute("geom:generated_transform", tfm))
+ p = transform(tfm, p);
+ }
+ if (p[0] < 0.0 || p[1] < 0.0 || p[2] < 0.0 || p[0] > 1.0 || p[1] > 1.0 || p[2] > 1.0) {
+ Density = 0;
+ Color = color(0, 0, 0);
+ }
+ else {
+ Color = (color)texture3d(
+ filename, p, "wrap", "periodic", "interp", interpolation, "alpha", Density);
+ }
}
diff --git a/intern/cycles/kernel/shaders/node_wave_texture.osl b/intern/cycles/kernel/shaders/node_wave_texture.osl
index 71bc9324705..dfc2dbfb800 100644
--- a/intern/cycles/kernel/shaders/node_wave_texture.osl
+++ b/intern/cycles/kernel/shaders/node_wave_texture.osl
@@ -21,49 +21,47 @@
float wave(point p, string type, string profile, float detail, float distortion, float dscale)
{
- float n = 0.0;
+ float n = 0.0;
- if (type == "bands") {
- n = (p[0] + p[1] + p[2]) * 10.0;
- }
- else if (type == "rings") {
- n = length(p) * 20.0;
- }
+ if (type == "bands") {
+ n = (p[0] + p[1] + p[2]) * 10.0;
+ }
+ else if (type == "rings") {
+ n = length(p) * 20.0;
+ }
- if (distortion != 0.0) {
- n = n + (distortion * noise_turbulence(p * dscale, detail, 0));
- }
+ if (distortion != 0.0) {
+ n = n + (distortion * noise_turbulence(p * dscale, detail, 0));
+ }
- if (profile == "sine") {
- return 0.5 + 0.5 * sin(n);
- }
- else {
- /* Saw profile */
- n /= M_2PI;
- n -= (int) n;
- return (n < 0.0) ? n + 1.0 : n;
- }
+ if (profile == "sine") {
+ return 0.5 + 0.5 * sin(n);
+ }
+ else {
+ /* Saw profile */
+ n /= M_2PI;
+ n -= (int)n;
+ return (n < 0.0) ? n + 1.0 : n;
+ }
}
-shader node_wave_texture(
- int use_mapping = 0,
- matrix mapping = matrix(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
- string type = "bands",
- string profile = "sine",
- float Scale = 5.0,
- float Distortion = 0.0,
- float Detail = 2.0,
- float DetailScale = 1.0,
- point Vector = P,
- output float Fac = 0.0,
- output color Color = 0.0)
+shader node_wave_texture(int use_mapping = 0,
+ matrix mapping = matrix(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
+ string type = "bands",
+ string profile = "sine",
+ float Scale = 5.0,
+ float Distortion = 0.0,
+ float Detail = 2.0,
+ float DetailScale = 1.0,
+ point Vector = P,
+ output float Fac = 0.0,
+ output color Color = 0.0)
{
- point p = Vector;
+ point p = Vector;
- if (use_mapping)
- p = transform(mapping, p);
+ if (use_mapping)
+ p = transform(mapping, p);
- Fac = wave(p * Scale, type, profile, Detail, Distortion, DetailScale);
- Color = Fac;
+ Fac = wave(p * Scale, type, profile, Detail, Distortion, DetailScale);
+ Color = Fac;
}
-
diff --git a/intern/cycles/kernel/shaders/node_wavelength.osl b/intern/cycles/kernel/shaders/node_wavelength.osl
index 79e7043d4bf..c8c6eecb171 100644
--- a/intern/cycles/kernel/shaders/node_wavelength.osl
+++ b/intern/cycles/kernel/shaders/node_wavelength.osl
@@ -16,10 +16,7 @@
#include "stdosl.h"
-shader node_wavelength(
- float Wavelength = 500.0,
- output color Color = 0.0)
+shader node_wavelength(float Wavelength = 500.0, output color Color = 0.0)
{
- Color = wavelength_color(Wavelength);
+ Color = wavelength_color(Wavelength);
}
-
diff --git a/intern/cycles/kernel/shaders/node_wireframe.osl b/intern/cycles/kernel/shaders/node_wireframe.osl
index 5cc214495dd..ea4bd3a4c87 100644
--- a/intern/cycles/kernel/shaders/node_wireframe.osl
+++ b/intern/cycles/kernel/shaders/node_wireframe.osl
@@ -17,25 +17,24 @@
#include "stdosl.h"
#include "oslutil.h"
-shader node_wireframe(
- string bump_offset = "center",
- int use_pixel_size = 0,
- float Size = 0.01,
- output float Fac = 0.0)
+shader node_wireframe(string bump_offset = "center",
+ int use_pixel_size = 0,
+ float Size = 0.01,
+ output float Fac = 0.0)
{
- Fac = wireframe("triangles", Size, use_pixel_size);
- /* TODO(sergey): Since we can't use autodiff here we do algebraic
- * calculation of derivatives by definition. We could probably
- * optimize this a bit by doing some extra calculation in wireframe().
- */
- if (bump_offset == "dx") {
- point dx = Dx(P);
- P -= dx;
- Fac += (Fac - wireframe("triangles", Size, use_pixel_size)) / length(dx);
- }
- else if (bump_offset == "dy") {
- point dy = Dy(P);
- P -= dy;
- Fac += (Fac - wireframe("triangles", Size, use_pixel_size)) / length(dy);
- }
+ Fac = wireframe("triangles", Size, use_pixel_size);
+ /* TODO(sergey): Since we can't use autodiff here we do algebraic
+ * calculation of derivatives by definition. We could probably
+ * optimize this a bit by doing some extra calculation in wireframe().
+ */
+ if (bump_offset == "dx") {
+ point dx = Dx(P);
+ P -= dx;
+ Fac += (Fac - wireframe("triangles", Size, use_pixel_size)) / length(dx);
+ }
+ else if (bump_offset == "dy") {
+ point dy = Dy(P);
+ P -= dy;
+ Fac += (Fac - wireframe("triangles", Size, use_pixel_size)) / length(dy);
+ }
}
diff --git a/intern/cycles/kernel/shaders/oslutil.h b/intern/cycles/kernel/shaders/oslutil.h
index 592a8ad12d9..d48bfa4a665 100644
--- a/intern/cycles/kernel/shaders/oslutil.h
+++ b/intern/cycles/kernel/shaders/oslutil.h
@@ -39,57 +39,63 @@
//
float wireframe(string edge_type, float line_width, int raster)
{
- // ray differentials are so big in diffuse context that this function would always return "wire"
- if (raytype("path:diffuse")) return 0.0;
+ // ray differentials are so big in diffuse context that this function would always return "wire"
+ if (raytype("path:diffuse"))
+ return 0.0;
- int np = 0;
- point p[64];
- float pixelWidth = 1;
+ int np = 0;
+ point p[64];
+ float pixelWidth = 1;
- if (edge_type == "triangles")
- {
- np = 3;
- if (!getattribute("geom:trianglevertices", p))
- return 0.0;
- }
- else if (edge_type == "polygons" || edge_type == "patches")
- {
- getattribute("geom:numpolyvertices", np);
- if (np < 3 || !getattribute("geom:polyvertices", p))
- return 0.0;
- }
+ if (edge_type == "triangles") {
+ np = 3;
+ if (!getattribute("geom:trianglevertices", p))
+ return 0.0;
+ }
+ else if (edge_type == "polygons" || edge_type == "patches") {
+ getattribute("geom:numpolyvertices", np);
+ if (np < 3 || !getattribute("geom:polyvertices", p))
+ return 0.0;
+ }
- if (raster)
- {
- // Project the derivatives of P to the viewing plane defined
- // by I so we have a measure of how big is a pixel at this point
- float pixelWidthX = length(Dx(P) - dot(Dx(P), I) * I);
- float pixelWidthY = length(Dy(P) - dot(Dy(P), I) * I);
- // Take the average of both axis' length
- pixelWidth = (pixelWidthX + pixelWidthY) / 2;
- }
+ if (raster) {
+ // Project the derivatives of P to the viewing plane defined
+ // by I so we have a measure of how big is a pixel at this point
+ float pixelWidthX = length(Dx(P) - dot(Dx(P), I) * I);
+ float pixelWidthY = length(Dy(P) - dot(Dy(P), I) * I);
+ // Take the average of both axis' length
+ pixelWidth = (pixelWidthX + pixelWidthY) / 2;
+ }
- // Use half the width as the neighbor face will render the
- // other half. And take the square for fast comparison
- pixelWidth *= 0.5 * line_width;
- pixelWidth *= pixelWidth;
- for (int i = 0; i < np; i++)
- {
- int i2 = i ? i - 1 : np - 1;
- vector dir = P - p[i];
- vector edge = p[i] - p[i2];
- vector crs = cross(edge, dir);
- // At this point dot(crs, crs) / dot(edge, edge) is
- // the square of area / length(edge) == square of the
- // distance to the edge.
- if (dot(crs, crs) < (dot(edge, edge) * pixelWidth))
- return 1;
- }
- return 0;
+ // Use half the width as the neighbor face will render the
+ // other half. And take the square for fast comparison
+ pixelWidth *= 0.5 * line_width;
+ pixelWidth *= pixelWidth;
+ for (int i = 0; i < np; i++) {
+ int i2 = i ? i - 1 : np - 1;
+ vector dir = P - p[i];
+ vector edge = p[i] - p[i2];
+ vector crs = cross(edge, dir);
+ // At this point dot(crs, crs) / dot(edge, edge) is
+ // the square of area / length(edge) == square of the
+ // distance to the edge.
+ if (dot(crs, crs) < (dot(edge, edge) * pixelWidth))
+ return 1;
+ }
+ return 0;
}
-float wireframe(string edge_type, float line_width) { return wireframe(edge_type, line_width, 1); }
-float wireframe(string edge_type) { return wireframe(edge_type, 1.0, 1); }
-float wireframe() { return wireframe("polygons", 1.0, 1); }
+float wireframe(string edge_type, float line_width)
+{
+ return wireframe(edge_type, line_width, 1);
+}
+float wireframe(string edge_type)
+{
+ return wireframe(edge_type, 1.0, 1);
+}
+float wireframe()
+{
+ return wireframe("polygons", 1.0, 1);
+}
-#endif /* CCL_OSLUTIL_H */
+#endif /* CCL_OSLUTIL_H */
diff --git a/intern/cycles/kernel/shaders/stdosl.h b/intern/cycles/kernel/shaders/stdosl.h
index 7136c746321..9b9720ffff9 100644
--- a/intern/cycles/kernel/shaders/stdosl.h
+++ b/intern/cycles/kernel/shaders/stdosl.h
@@ -25,124 +25,215 @@
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
/////////////////////////////////////////////////////////////////////////////
-
#ifndef CCL_STDOSL_H
#define CCL_STDOSL_H
-
#ifndef M_PI
-#define M_PI 3.1415926535897932 /* pi */
-#define M_PI_2 1.5707963267948966 /* pi/2 */
-#define M_PI_4 0.7853981633974483 /* pi/4 */
-#define M_2_PI 0.6366197723675813 /* 2/pi */
-#define M_2PI 6.2831853071795865 /* 2*pi */
-#define M_4PI 12.566370614359173 /* 4*pi */
-#define M_2_SQRTPI 1.1283791670955126 /* 2/sqrt(pi) */
-#define M_E 2.7182818284590452 /* e (Euler's number) */
-#define M_LN2 0.6931471805599453 /* ln(2) */
-#define M_LN10 2.3025850929940457 /* ln(10) */
-#define M_LOG2E 1.4426950408889634 /* log_2(e) */
-#define M_LOG10E 0.4342944819032518 /* log_10(e) */
-#define M_SQRT2 1.4142135623730950 /* sqrt(2) */
-#define M_SQRT1_2 0.7071067811865475 /* 1/sqrt(2) */
+# define M_PI 3.1415926535897932 /* pi */
+# define M_PI_2 1.5707963267948966 /* pi/2 */
+# define M_PI_4 0.7853981633974483 /* pi/4 */
+# define M_2_PI 0.6366197723675813 /* 2/pi */
+# define M_2PI 6.2831853071795865 /* 2*pi */
+# define M_4PI 12.566370614359173 /* 4*pi */
+# define M_2_SQRTPI 1.1283791670955126 /* 2/sqrt(pi) */
+# define M_E 2.7182818284590452 /* e (Euler's number) */
+# define M_LN2 0.6931471805599453 /* ln(2) */
+# define M_LN10 2.3025850929940457 /* ln(10) */
+# define M_LOG2E 1.4426950408889634 /* log_2(e) */
+# define M_LOG10E 0.4342944819032518 /* log_10(e) */
+# define M_SQRT2 1.4142135623730950 /* sqrt(2) */
+# define M_SQRT1_2 0.7071067811865475 /* 1/sqrt(2) */
#endif
-
-
// Declaration of built-in functions and closures
-#define BUILTIN [[ int builtin = 1 ]]
+#define BUILTIN [[int builtin = 1]]
#define BUILTIN_DERIV [[ int builtin = 1, int deriv = 1 ]]
-#define PERCOMP1(name) \
- normal name (normal x) BUILTIN; \
- vector name (vector x) BUILTIN; \
- point name (point x) BUILTIN; \
- color name (color x) BUILTIN; \
- float name (float x) BUILTIN;
-
-#define PERCOMP2(name) \
- normal name (normal x, normal y) BUILTIN; \
- vector name (vector x, vector y) BUILTIN; \
- point name (point x, point y) BUILTIN; \
- color name (color x, color y) BUILTIN; \
- float name (float x, float y) BUILTIN;
-
-#define PERCOMP2F(name) \
- normal name (normal x, float y) BUILTIN; \
- vector name (vector x, float y) BUILTIN; \
- point name (point x, float y) BUILTIN; \
- color name (color x, float y) BUILTIN; \
- float name (float x, float y) BUILTIN;
-
+#define PERCOMP1(name) \
+ normal name(normal x) BUILTIN; \
+ vector name(vector x) BUILTIN; \
+ point name(point x) BUILTIN; \
+ color name(color x) BUILTIN; \
+ float name(float x) BUILTIN;
+
+#define PERCOMP2(name) \
+ normal name(normal x, normal y) BUILTIN; \
+ vector name(vector x, vector y) BUILTIN; \
+ point name(point x, point y) BUILTIN; \
+ color name(color x, color y) BUILTIN; \
+ float name(float x, float y) BUILTIN;
+
+#define PERCOMP2F(name) \
+ normal name(normal x, float y) BUILTIN; \
+ vector name(vector x, float y) BUILTIN; \
+ point name(point x, float y) BUILTIN; \
+ color name(color x, float y) BUILTIN; \
+ float name(float x, float y) BUILTIN;
// Basic math
-normal degrees (normal x) { return x*(180.0/M_PI); }
-vector degrees (vector x) { return x*(180.0/M_PI); }
-point degrees (point x) { return x*(180.0/M_PI); }
-color degrees (color x) { return x*(180.0/M_PI); }
-float degrees (float x) { return x*(180.0/M_PI); }
-normal radians (normal x) { return x*(M_PI/180.0); }
-vector radians (vector x) { return x*(M_PI/180.0); }
-point radians (point x) { return x*(M_PI/180.0); }
-color radians (color x) { return x*(M_PI/180.0); }
-float radians (float x) { return x*(M_PI/180.0); }
-PERCOMP1 (cos)
-PERCOMP1 (sin)
-PERCOMP1 (tan)
-PERCOMP1 (acos)
-PERCOMP1 (asin)
-PERCOMP1 (atan)
-PERCOMP2 (atan2)
-PERCOMP1 (cosh)
-PERCOMP1 (sinh)
-PERCOMP1 (tanh)
-PERCOMP2F (pow)
-PERCOMP1 (exp)
-PERCOMP1 (exp2)
-PERCOMP1 (expm1)
-PERCOMP1 (log)
-point log (point a, float b) { return log(a)/log(b); }
-vector log (vector a, float b) { return log(a)/log(b); }
-color log (color a, float b) { return log(a)/log(b); }
-float log (float a, float b) { return log(a)/log(b); }
-PERCOMP1 (log2)
-PERCOMP1 (log10)
-PERCOMP1 (logb)
-PERCOMP1 (sqrt)
-PERCOMP1 (inversesqrt)
-float hypot (float a, float b) { return sqrt (a*a + b*b); }
-float hypot (float a, float b, float c) { return sqrt (a*a + b*b + c*c); }
-PERCOMP1 (abs)
-int abs (int x) BUILTIN;
-PERCOMP1 (fabs)
-int fabs (int x) BUILTIN;
-PERCOMP1 (sign)
-PERCOMP1 (floor)
-PERCOMP1 (ceil)
-PERCOMP1 (round)
-PERCOMP1 (trunc)
-PERCOMP2 (fmod)
-PERCOMP2F (fmod)
-int mod (int a, int b) { return a - b*(int)floor(a/b); }
-point mod (point a, point b) { return a - b*floor(a/b); }
-vector mod (vector a, vector b) { return a - b*floor(a/b); }
-normal mod (normal a, normal b) { return a - b*floor(a/b); }
-color mod (color a, color b) { return a - b*floor(a/b); }
-point mod (point a, float b) { return a - b*floor(a/b); }
-vector mod (vector a, float b) { return a - b*floor(a/b); }
-normal mod (normal a, float b) { return a - b*floor(a/b); }
-color mod (color a, float b) { return a - b*floor(a/b); }
-float mod (float a, float b) { return a - b*floor(a/b); }
-PERCOMP2 (min)
-int min (int a, int b) BUILTIN;
-PERCOMP2 (max)
-int max (int a, int b) BUILTIN;
-normal clamp (normal x, normal minval, normal maxval) { return max(min(x,maxval),minval); }
-vector clamp (vector x, vector minval, vector maxval) { return max(min(x,maxval),minval); }
-point clamp (point x, point minval, point maxval) { return max(min(x,maxval),minval); }
-color clamp (color x, color minval, color maxval) { return max(min(x,maxval),minval); }
-float clamp (float x, float minval, float maxval) { return max(min(x,maxval),minval); }
-int clamp (int x, int minval, int maxval) { return max(min(x,maxval),minval); }
+normal degrees(normal x)
+{
+ return x * (180.0 / M_PI);
+}
+vector degrees(vector x)
+{
+ return x * (180.0 / M_PI);
+}
+point degrees(point x)
+{
+ return x * (180.0 / M_PI);
+}
+color degrees(color x)
+{
+ return x * (180.0 / M_PI);
+}
+float degrees(float x)
+{
+ return x * (180.0 / M_PI);
+}
+normal radians(normal x)
+{
+ return x * (M_PI / 180.0);
+}
+vector radians(vector x)
+{
+ return x * (M_PI / 180.0);
+}
+point radians(point x)
+{
+ return x * (M_PI / 180.0);
+}
+color radians(color x)
+{
+ return x * (M_PI / 180.0);
+}
+float radians(float x)
+{
+ return x * (M_PI / 180.0);
+}
+PERCOMP1(cos)
+PERCOMP1(sin)
+PERCOMP1(tan)
+PERCOMP1(acos)
+PERCOMP1(asin)
+PERCOMP1(atan)
+PERCOMP2(atan2)
+PERCOMP1(cosh)
+PERCOMP1(sinh)
+PERCOMP1(tanh)
+PERCOMP2F(pow)
+PERCOMP1(exp)
+PERCOMP1(exp2)
+PERCOMP1(expm1)
+PERCOMP1(log)
+point log(point a, float b)
+{
+ return log(a) / log(b);
+}
+vector log(vector a, float b)
+{
+ return log(a) / log(b);
+}
+color log(color a, float b)
+{
+ return log(a) / log(b);
+}
+float log(float a, float b)
+{
+ return log(a) / log(b);
+}
+PERCOMP1(log2)
+PERCOMP1(log10)
+PERCOMP1(logb)
+PERCOMP1(sqrt)
+PERCOMP1(inversesqrt)
+float hypot(float a, float b)
+{
+ return sqrt(a * a + b * b);
+}
+float hypot(float a, float b, float c)
+{
+ return sqrt(a * a + b * b + c * c);
+}
+PERCOMP1(abs)
+int abs(int x) BUILTIN;
+PERCOMP1(fabs)
+int fabs(int x) BUILTIN;
+PERCOMP1(sign)
+PERCOMP1(floor)
+PERCOMP1(ceil)
+PERCOMP1(round)
+PERCOMP1(trunc)
+PERCOMP2(fmod)
+PERCOMP2F(fmod)
+int mod(int a, int b)
+{
+ return a - b * (int)floor(a / b);
+}
+point mod(point a, point b)
+{
+ return a - b * floor(a / b);
+}
+vector mod(vector a, vector b)
+{
+ return a - b * floor(a / b);
+}
+normal mod(normal a, normal b)
+{
+ return a - b * floor(a / b);
+}
+color mod(color a, color b)
+{
+ return a - b * floor(a / b);
+}
+point mod(point a, float b)
+{
+ return a - b * floor(a / b);
+}
+vector mod(vector a, float b)
+{
+ return a - b * floor(a / b);
+}
+normal mod(normal a, float b)
+{
+ return a - b * floor(a / b);
+}
+color mod(color a, float b)
+{
+ return a - b * floor(a / b);
+}
+float mod(float a, float b)
+{
+ return a - b * floor(a / b);
+}
+PERCOMP2(min)
+int min(int a, int b) BUILTIN;
+PERCOMP2(max)
+int max(int a, int b) BUILTIN;
+normal clamp(normal x, normal minval, normal maxval)
+{
+ return max(min(x, maxval), minval);
+}
+vector clamp(vector x, vector minval, vector maxval)
+{
+ return max(min(x, maxval), minval);
+}
+point clamp(point x, point minval, point maxval)
+{
+ return max(min(x, maxval), minval);
+}
+color clamp(color x, color minval, color maxval)
+{
+ return max(min(x, maxval), minval);
+}
+float clamp(float x, float minval, float maxval)
+{
+ return max(min(x, maxval), minval);
+}
+int clamp(int x, int minval, int maxval)
+{
+ return max(min(x, maxval), minval);
+}
#if 0
normal mix (normal x, normal y, normal a) { return x*(1-a) + y*a; }
normal mix (normal x, normal y, float a) { return x*(1-a) + y*a; }
@@ -154,102 +245,121 @@ color mix (color x, color y, color a) { return x*(1-a) + y*a; }
color mix (color x, color y, float a) { return x*(1-a) + y*a; }
float mix (float x, float y, float a) { return x*(1-a) + y*a; }
#else
-normal mix (normal x, normal y, normal a) BUILTIN;
-normal mix (normal x, normal y, float a) BUILTIN;
-vector mix (vector x, vector y, vector a) BUILTIN;
-vector mix (vector x, vector y, float a) BUILTIN;
-point mix (point x, point y, point a) BUILTIN;
-point mix (point x, point y, float a) BUILTIN;
-color mix (color x, color y, color a) BUILTIN;
-color mix (color x, color y, float a) BUILTIN;
-float mix (float x, float y, float a) BUILTIN;
+normal mix(normal x, normal y, normal a) BUILTIN;
+normal mix(normal x, normal y, float a) BUILTIN;
+vector mix(vector x, vector y, vector a) BUILTIN;
+vector mix(vector x, vector y, float a) BUILTIN;
+point mix(point x, point y, point a) BUILTIN;
+point mix(point x, point y, float a) BUILTIN;
+color mix(color x, color y, color a) BUILTIN;
+color mix(color x, color y, float a) BUILTIN;
+float mix(float x, float y, float a) BUILTIN;
#endif
-int isnan (float x) BUILTIN;
-int isinf (float x) BUILTIN;
-int isfinite (float x) BUILTIN;
-float erf (float x) BUILTIN;
-float erfc (float x) BUILTIN;
+int isnan(float x) BUILTIN;
+int isinf(float x) BUILTIN;
+int isfinite(float x) BUILTIN;
+float erf(float x) BUILTIN;
+float erfc(float x) BUILTIN;
// Vector functions
-vector cross (vector a, vector b) BUILTIN;
-float dot (vector a, vector b) BUILTIN;
-float length (vector v) BUILTIN;
-float distance (point a, point b) BUILTIN;
-float distance (point a, point b, point q)
-{
- vector d = b - a;
- float dd = dot(d, d);
- if(dd == 0.0)
- return distance(q, a);
- float t = dot(q - a, d)/dd;
- return distance(q, a + clamp(t, 0.0, 1.0)*d);
-}
-normal normalize (normal v) BUILTIN;
-vector normalize (vector v) BUILTIN;
-vector faceforward (vector N, vector I, vector Nref) BUILTIN;
-vector faceforward (vector N, vector I) BUILTIN;
-vector reflect (vector I, vector N) { return I - 2*dot(N,I)*N; }
-vector refract (vector I, vector N, float eta) {
- float IdotN = dot (I, N);
- float k = 1 - eta*eta * (1 - IdotN*IdotN);
- return (k < 0) ? vector(0,0,0) : (eta*I - N * (eta*IdotN + sqrt(k)));
-}
-void fresnel (vector I, normal N, float eta,
- output float Kr, output float Kt,
- output vector R, output vector T)
-{
- float sqr(float x) { return x*x; }
- float c = dot(I, N);
- if (c < 0)
- c = -c;
- R = reflect(I, N);
- float g = 1.0 / sqr(eta) - 1.0 + c * c;
- if (g >= 0.0) {
- g = sqrt (g);
- float beta = g - c;
- float F = (c * (g+c) - 1.0) / (c * beta + 1.0);
- F = 0.5 * (1.0 + sqr(F));
- F *= sqr (beta / (g+c));
- Kr = F;
- Kt = (1.0 - Kr) * eta*eta;
- // OPT: the following recomputes some of the above values, but it
- // gives us the same result as if the shader-writer called refract()
- T = refract(I, N, eta);
- } else {
- // total internal reflection
- Kr = 1.0;
- Kt = 0.0;
- T = vector (0,0,0);
- }
+vector cross(vector a, vector b) BUILTIN;
+float dot(vector a, vector b) BUILTIN;
+float length(vector v) BUILTIN;
+float distance(point a, point b) BUILTIN;
+float distance(point a, point b, point q)
+{
+ vector d = b - a;
+ float dd = dot(d, d);
+ if (dd == 0.0)
+ return distance(q, a);
+ float t = dot(q - a, d) / dd;
+ return distance(q, a + clamp(t, 0.0, 1.0) * d);
}
-
-void fresnel (vector I, normal N, float eta,
- output float Kr, output float Kt)
+normal normalize(normal v) BUILTIN;
+vector normalize(vector v) BUILTIN;
+vector faceforward(vector N, vector I, vector Nref) BUILTIN;
+vector faceforward(vector N, vector I) BUILTIN;
+vector reflect(vector I, vector N)
{
- vector R, T;
- fresnel(I, N, eta, Kr, Kt, R, T);
+ return I - 2 * dot(N, I) * N;
+}
+vector refract(vector I, vector N, float eta)
+{
+ float IdotN = dot(I, N);
+ float k = 1 - eta * eta * (1 - IdotN * IdotN);
+ return (k < 0) ? vector(0, 0, 0) : (eta * I - N * (eta * IdotN + sqrt(k)));
+}
+void fresnel(vector I,
+ normal N,
+ float eta,
+ output float Kr,
+ output float Kt,
+ output vector R,
+ output vector T)
+{
+ float sqr(float x)
+ {
+ return x * x;
+ }
+ float c = dot(I, N);
+ if (c < 0)
+ c = -c;
+ R = reflect(I, N);
+ float g = 1.0 / sqr(eta) - 1.0 + c * c;
+ if (g >= 0.0) {
+ g = sqrt(g);
+ float beta = g - c;
+ float F = (c * (g + c) - 1.0) / (c * beta + 1.0);
+ F = 0.5 * (1.0 + sqr(F));
+ F *= sqr(beta / (g + c));
+ Kr = F;
+ Kt = (1.0 - Kr) * eta * eta;
+ // OPT: the following recomputes some of the above values, but it
+ // gives us the same result as if the shader-writer called refract()
+ T = refract(I, N, eta);
+ }
+ else {
+ // total internal reflection
+ Kr = 1.0;
+ Kt = 0.0;
+ T = vector(0, 0, 0);
+ }
}
+void fresnel(vector I, normal N, float eta, output float Kr, output float Kt)
+{
+ vector R, T;
+ fresnel(I, N, eta, Kr, Kt, R, T);
+}
-normal transform (matrix Mto, normal p) BUILTIN;
-vector transform (matrix Mto, vector p) BUILTIN;
-point transform (matrix Mto, point p) BUILTIN;
-normal transform (string from, string to, normal p) BUILTIN;
-vector transform (string from, string to, vector p) BUILTIN;
-point transform (string from, string to, point p) BUILTIN;
-normal transform (string to, normal p) { return transform("common",to,p); }
-vector transform (string to, vector p) { return transform("common",to,p); }
-point transform (string to, point p) { return transform("common",to,p); }
+normal transform(matrix Mto, normal p) BUILTIN;
+vector transform(matrix Mto, vector p) BUILTIN;
+point transform(matrix Mto, point p) BUILTIN;
+normal transform(string from, string to, normal p) BUILTIN;
+vector transform(string from, string to, vector p) BUILTIN;
+point transform(string from, string to, point p) BUILTIN;
+normal transform(string to, normal p)
+{
+ return transform("common", to, p);
+}
+vector transform(string to, vector p)
+{
+ return transform("common", to, p);
+}
+point transform(string to, point p)
+{
+ return transform("common", to, p);
+}
-float transformu (string tounits, float x) BUILTIN;
-float transformu (string fromunits, string tounits, float x) BUILTIN;
+float transformu(string tounits, float x) BUILTIN;
+float transformu(string fromunits, string tounits, float x) BUILTIN;
-point rotate (point p, float angle, point a, point b)
+point rotate(point p, float angle, point a, point b)
{
- vector axis = normalize (b - a);
- float cosang, sinang;
- /* Older OSX has major issues with sincos() function,
+ vector axis = normalize(b - a);
+ float cosang, sinang;
+ /* Older OSX has major issues with sincos() function,
* it's likely a big in OSL or LLVM. For until we've
* updated to new versions of this libraries we'll
* use a workaround to prevent possible crashes on all
@@ -261,317 +371,348 @@ point rotate (point p, float angle, point a, point b)
#if 0
sincos (angle, sinang, cosang);
#else
- sinang = sin (angle);
- cosang = cos (angle);
+ sinang = sin(angle);
+ cosang = cos(angle);
#endif
- float cosang1 = 1.0 - cosang;
- float x = axis[0], y = axis[1], z = axis[2];
- matrix M = matrix (x * x + (1.0 - x * x) * cosang,
- x * y * cosang1 + z * sinang,
- x * z * cosang1 - y * sinang,
- 0.0,
- x * y * cosang1 - z * sinang,
- y * y + (1.0 - y * y) * cosang,
- y * z * cosang1 + x * sinang,
- 0.0,
- x * z * cosang1 + y * sinang,
- y * z * cosang1 - x * sinang,
- z * z + (1.0 - z * z) * cosang,
- 0.0,
- 0.0, 0.0, 0.0, 1.0);
- return transform (M, p-a) + a;
+ float cosang1 = 1.0 - cosang;
+ float x = axis[0], y = axis[1], z = axis[2];
+ matrix M = matrix(x * x + (1.0 - x * x) * cosang,
+ x * y * cosang1 + z * sinang,
+ x * z * cosang1 - y * sinang,
+ 0.0,
+ x * y * cosang1 - z * sinang,
+ y * y + (1.0 - y * y) * cosang,
+ y * z * cosang1 + x * sinang,
+ 0.0,
+ x * z * cosang1 + y * sinang,
+ y * z * cosang1 - x * sinang,
+ z * z + (1.0 - z * z) * cosang,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ 1.0);
+ return transform(M, p - a) + a;
}
normal ensure_valid_reflection(normal Ng, vector I, normal N)
{
- /* The implementation here mirrors the one in kernel_montecarlo.h,
+ /* The implementation here mirrors the one in kernel_montecarlo.h,
* check there for an explanation of the algorithm. */
- float sqr(float x) { return x*x; }
-
- vector R = 2*dot(N, I)*N - I;
+ float sqr(float x)
+ {
+ return x * x;
+ }
- float threshold = min(0.9*dot(Ng, I), 0.01);
- if(dot(Ng, R) >= threshold) {
- return N;
- }
+ vector R = 2 * dot(N, I) * N - I;
- float NdotNg = dot(N, Ng);
- vector X = normalize(N - NdotNg*Ng);
+ float threshold = min(0.9 * dot(Ng, I), 0.01);
+ if (dot(Ng, R) >= threshold) {
+ return N;
+ }
- float Ix = dot(I, X), Iz = dot(I, Ng);
- float Ix2 = sqr(Ix), Iz2 = sqr(Iz);
- float a = Ix2 + Iz2;
+ float NdotNg = dot(N, Ng);
+ vector X = normalize(N - NdotNg * Ng);
- float b = sqrt(Ix2*(a - sqr(threshold)));
- float c = Iz*threshold + a;
+ float Ix = dot(I, X), Iz = dot(I, Ng);
+ float Ix2 = sqr(Ix), Iz2 = sqr(Iz);
+ float a = Ix2 + Iz2;
- float fac = 0.5/a;
- float N1_z2 = fac*(b+c), N2_z2 = fac*(-b+c);
- int valid1 = (N1_z2 > 1e-5) && (N1_z2 <= (1.0 + 1e-5));
- int valid2 = (N2_z2 > 1e-5) && (N2_z2 <= (1.0 + 1e-5));
+ float b = sqrt(Ix2 * (a - sqr(threshold)));
+ float c = Iz * threshold + a;
- float N_new_x, N_new_z;
- if(valid1 && valid2) {
- float N1_x = sqrt(1.0 - N1_z2), N1_z = sqrt(N1_z2);
- float N2_x = sqrt(1.0 - N2_z2), N2_z = sqrt(N2_z2);
+ float fac = 0.5 / a;
+ float N1_z2 = fac * (b + c), N2_z2 = fac * (-b + c);
+ int valid1 = (N1_z2 > 1e-5) && (N1_z2 <= (1.0 + 1e-5));
+ int valid2 = (N2_z2 > 1e-5) && (N2_z2 <= (1.0 + 1e-5));
- float R1 = 2*(N1_x*Ix + N1_z*Iz)*N1_z - Iz;
- float R2 = 2*(N2_x*Ix + N2_z*Iz)*N2_z - Iz;
+ float N_new_x, N_new_z;
+ if (valid1 && valid2) {
+ float N1_x = sqrt(1.0 - N1_z2), N1_z = sqrt(N1_z2);
+ float N2_x = sqrt(1.0 - N2_z2), N2_z = sqrt(N2_z2);
- valid1 = (R1 >= 1e-5);
- valid2 = (R2 >= 1e-5);
- if(valid1 && valid2) {
- N_new_x = (R1 < R2)? N1_x : N2_x;
- N_new_z = (R1 < R2)? N1_z : N2_z;
- }
- else {
- N_new_x = (R1 > R2)? N1_x : N2_x;
- N_new_z = (R1 > R2)? N1_z : N2_z;
- }
+ float R1 = 2 * (N1_x * Ix + N1_z * Iz) * N1_z - Iz;
+ float R2 = 2 * (N2_x * Ix + N2_z * Iz) * N2_z - Iz;
- }
- else if(valid1 || valid2) {
- float Nz2 = valid1? N1_z2 : N2_z2;
- N_new_x = sqrt(1.0 - Nz2);
- N_new_z = sqrt(Nz2);
+ valid1 = (R1 >= 1e-5);
+ valid2 = (R2 >= 1e-5);
+ if (valid1 && valid2) {
+ N_new_x = (R1 < R2) ? N1_x : N2_x;
+ N_new_z = (R1 < R2) ? N1_z : N2_z;
}
else {
- return Ng;
+ N_new_x = (R1 > R2) ? N1_x : N2_x;
+ N_new_z = (R1 > R2) ? N1_z : N2_z;
}
-
- return N_new_x*X + N_new_z*Ng;
+ }
+ else if (valid1 || valid2) {
+ float Nz2 = valid1 ? N1_z2 : N2_z2;
+ N_new_x = sqrt(1.0 - Nz2);
+ N_new_z = sqrt(Nz2);
+ }
+ else {
+ return Ng;
+ }
+
+ return N_new_x * X + N_new_z * Ng;
}
-
// Color functions
-float luminance (color c) BUILTIN;
-color blackbody (float temperatureK) BUILTIN;
-color wavelength_color (float wavelength_nm) BUILTIN;
-
-
-color transformc (string to, color x)
-{
- color rgb_to_hsv (color rgb) { // See Foley & van Dam
- float r = rgb[0], g = rgb[1], b = rgb[2];
- float mincomp = min (r, min (g, b));
- float maxcomp = max (r, max (g, b));
- float delta = maxcomp - mincomp; // chroma
- float h, s, v;
- v = maxcomp;
- if (maxcomp > 0)
- s = delta / maxcomp;
- else s = 0;
- if (s <= 0)
- h = 0;
- else {
- if (r >= maxcomp) h = (g-b) / delta;
- else if (g >= maxcomp) h = 2 + (b-r) / delta;
- else h = 4 + (r-g) / delta;
- h /= 6;
- if (h < 0)
- h += 1;
- }
- return color (h, s, v);
- }
-
- color rgb_to_hsl (color rgb) { // See Foley & van Dam
- // First convert rgb to hsv, then to hsl
- float minval = min (rgb[0], min (rgb[1], rgb[2]));
- color hsv = rgb_to_hsv (rgb);
- float maxval = hsv[2]; // v == maxval
- float h = hsv[0], s, l = (minval+maxval) / 2;
- if (minval == maxval)
- s = 0; // special 'achromatic' case, hue is 0
- else if (l <= 0.5)
- s = (maxval - minval) / (maxval + minval);
- else
- s = (maxval - minval) / (2 - maxval - minval);
- return color (h, s, l);
- }
+float luminance(color c) BUILTIN;
+color blackbody(float temperatureK) BUILTIN;
+color wavelength_color(float wavelength_nm) BUILTIN;
- color r;
- if (to == "rgb" || to == "RGB")
- r = x;
- else if (to == "hsv")
- r = rgb_to_hsv (x);
- else if (to == "hsl")
- r = rgb_to_hsl (x);
- else if (to == "YIQ")
- r = color (dot (vector(0.299, 0.587, 0.114), (vector)x),
- dot (vector(0.596, -0.275, -0.321), (vector)x),
- dot (vector(0.212, -0.523, 0.311), (vector)x));
- else if (to == "XYZ")
- r = color (dot (vector(0.412453, 0.357580, 0.180423), (vector)x),
- dot (vector(0.212671, 0.715160, 0.072169), (vector)x),
- dot (vector(0.019334, 0.119193, 0.950227), (vector)x));
+color transformc(string to, color x)
+{
+ color rgb_to_hsv(color rgb)
+ { // See Foley & van Dam
+ float r = rgb[0], g = rgb[1], b = rgb[2];
+ float mincomp = min(r, min(g, b));
+ float maxcomp = max(r, max(g, b));
+ float delta = maxcomp - mincomp; // chroma
+ float h, s, v;
+ v = maxcomp;
+ if (maxcomp > 0)
+ s = delta / maxcomp;
+ else
+ s = 0;
+ if (s <= 0)
+ h = 0;
else {
- error ("Unknown color space \"%s\"", to);
- r = x;
+ if (r >= maxcomp)
+ h = (g - b) / delta;
+ else if (g >= maxcomp)
+ h = 2 + (b - r) / delta;
+ else
+ h = 4 + (r - g) / delta;
+ h /= 6;
+ if (h < 0)
+ h += 1;
}
- return r;
+ return color(h, s, v);
+ }
+
+ color rgb_to_hsl(color rgb)
+ { // See Foley & van Dam
+ // First convert rgb to hsv, then to hsl
+ float minval = min(rgb[0], min(rgb[1], rgb[2]));
+ color hsv = rgb_to_hsv(rgb);
+ float maxval = hsv[2]; // v == maxval
+ float h = hsv[0], s, l = (minval + maxval) / 2;
+ if (minval == maxval)
+ s = 0; // special 'achromatic' case, hue is 0
+ else if (l <= 0.5)
+ s = (maxval - minval) / (maxval + minval);
+ else
+ s = (maxval - minval) / (2 - maxval - minval);
+ return color(h, s, l);
+ }
+
+ color r;
+ if (to == "rgb" || to == "RGB")
+ r = x;
+ else if (to == "hsv")
+ r = rgb_to_hsv(x);
+ else if (to == "hsl")
+ r = rgb_to_hsl(x);
+ else if (to == "YIQ")
+ r = color(dot(vector(0.299, 0.587, 0.114), (vector)x),
+ dot(vector(0.596, -0.275, -0.321), (vector)x),
+ dot(vector(0.212, -0.523, 0.311), (vector)x));
+ else if (to == "XYZ")
+ r = color(dot(vector(0.412453, 0.357580, 0.180423), (vector)x),
+ dot(vector(0.212671, 0.715160, 0.072169), (vector)x),
+ dot(vector(0.019334, 0.119193, 0.950227), (vector)x));
+ else {
+ error("Unknown color space \"%s\"", to);
+ r = x;
+ }
+ return r;
}
-
-color transformc (string from, string to, color x)
-{
- color hsv_to_rgb (color c) { // Reference: Foley & van Dam
- float h = c[0], s = c[1], v = c[2];
- color r;
- if (s < 0.0001) {
- r = v;
- } else {
- h = 6 * (h - floor(h)); // expand to [0..6)
- int hi = (int)h;
- float f = h - hi;
- float p = v * (1-s);
- float q = v * (1-s*f);
- float t = v * (1-s*(1-f));
- if (hi == 0) r = color (v, t, p);
- else if (hi == 1) r = color (q, v, p);
- else if (hi == 2) r = color (p, v, t);
- else if (hi == 3) r = color (p, q, v);
- else if (hi == 4) r = color (t, p, v);
- else r = color (v, p, q);
- }
- return r;
+color transformc(string from, string to, color x)
+{
+ color hsv_to_rgb(color c)
+ { // Reference: Foley & van Dam
+ float h = c[0], s = c[1], v = c[2];
+ color r;
+ if (s < 0.0001) {
+ r = v;
}
-
- color hsl_to_rgb (color c) {
- float h = c[0], s = c[1], l = c[2];
- // Easiest to convert hsl -> hsv, then hsv -> RGB (per Foley & van Dam)
- float v = (l <= 0.5) ? (l * (1 + s)) : (l * (1 - s) + s);
- color r;
- if (v <= 0) {
- r = 0;
- } else {
- float min = 2 * l - v;
- s = (v - min) / v;
- r = hsv_to_rgb (color (h, s, v));
- }
- return r;
+ else {
+ h = 6 * (h - floor(h)); // expand to [0..6)
+ int hi = (int)h;
+ float f = h - hi;
+ float p = v * (1 - s);
+ float q = v * (1 - s * f);
+ float t = v * (1 - s * (1 - f));
+ if (hi == 0)
+ r = color(v, t, p);
+ else if (hi == 1)
+ r = color(q, v, p);
+ else if (hi == 2)
+ r = color(p, v, t);
+ else if (hi == 3)
+ r = color(p, q, v);
+ else if (hi == 4)
+ r = color(t, p, v);
+ else
+ r = color(v, p, q);
}
+ return r;
+ }
+ color hsl_to_rgb(color c)
+ {
+ float h = c[0], s = c[1], l = c[2];
+ // Easiest to convert hsl -> hsv, then hsv -> RGB (per Foley & van Dam)
+ float v = (l <= 0.5) ? (l * (1 + s)) : (l * (1 - s) + s);
color r;
- if (from == "rgb" || from == "RGB")
- r = x;
- else if (from == "hsv")
- r = hsv_to_rgb (x);
- else if (from == "hsl")
- r = hsl_to_rgb (x);
- else if (from == "YIQ")
- r = color (dot (vector(1, 0.9557, 0.6199), (vector)x),
- dot (vector(1, -0.2716, -0.6469), (vector)x),
- dot (vector(1, -1.1082, 1.7051), (vector)x));
- else if (from == "XYZ")
- r = color (dot (vector( 3.240479, -1.537150, -0.498535), (vector)x),
- dot (vector(-0.969256, 1.875991, 0.041556), (vector)x),
- dot (vector( 0.055648, -0.204043, 1.057311), (vector)x));
+ if (v <= 0) {
+ r = 0;
+ }
else {
- error ("Unknown color space \"%s\"", to);
- r = x;
+ float min = 2 * l - v;
+ s = (v - min) / v;
+ r = hsv_to_rgb(color(h, s, v));
}
- return transformc (to, r);
+ return r;
+ }
+
+ color r;
+ if (from == "rgb" || from == "RGB")
+ r = x;
+ else if (from == "hsv")
+ r = hsv_to_rgb(x);
+ else if (from == "hsl")
+ r = hsl_to_rgb(x);
+ else if (from == "YIQ")
+ r = color(dot(vector(1, 0.9557, 0.6199), (vector)x),
+ dot(vector(1, -0.2716, -0.6469), (vector)x),
+ dot(vector(1, -1.1082, 1.7051), (vector)x));
+ else if (from == "XYZ")
+ r = color(dot(vector(3.240479, -1.537150, -0.498535), (vector)x),
+ dot(vector(-0.969256, 1.875991, 0.041556), (vector)x),
+ dot(vector(0.055648, -0.204043, 1.057311), (vector)x));
+ else {
+ error("Unknown color space \"%s\"", to);
+ r = x;
+ }
+ return transformc(to, r);
}
-
-
// Matrix functions
-float determinant (matrix m) BUILTIN;
-matrix transpose (matrix m) BUILTIN;
+float determinant(matrix m) BUILTIN;
+matrix transpose(matrix m) BUILTIN;
+// Pattern generation
+color step(color edge, color x) BUILTIN;
+point step(point edge, point x) BUILTIN;
+vector step(vector edge, vector x) BUILTIN;
+normal step(normal edge, normal x) BUILTIN;
+float step(float edge, float x) BUILTIN;
+float smoothstep(float edge0, float edge1, float x) BUILTIN;
-// Pattern generation
+float linearstep(float edge0, float edge1, float x)
+{
+ float result;
+ if (edge0 != edge1) {
+ float xclamped = clamp(x, edge0, edge1);
+ result = (xclamped - edge0) / (edge1 - edge0);
+ }
+ else { // special case: edges coincide
+ result = step(edge0, x);
+ }
+ return result;
+}
-color step (color edge, color x) BUILTIN;
-point step (point edge, point x) BUILTIN;
-vector step (vector edge, vector x) BUILTIN;
-normal step (normal edge, normal x) BUILTIN;
-float step (float edge, float x) BUILTIN;
-float smoothstep (float edge0, float edge1, float x) BUILTIN;
-
-float linearstep (float edge0, float edge1, float x) {
- float result;
- if (edge0 != edge1) {
- float xclamped = clamp (x, edge0, edge1);
- result = (xclamped - edge0) / (edge1 - edge0);
- } else { // special case: edges coincide
- result = step (edge0, x);
- }
- return result;
-}
-
-float smooth_linearstep (float edge0, float edge1, float x_, float eps_) {
- float result;
- if (edge0 != edge1) {
- float rampup (float x, float r) { return 0.5/r * x*x; }
- float width_inv = 1.0 / (edge1 - edge0);
- float eps = eps_ * width_inv;
- float x = (x_ - edge0) * width_inv;
- if (x <= -eps) result = 0;
- else if (x >= eps && x <= 1.0-eps) result = x;
- else if (x >= 1.0+eps) result = 1;
- else if (x < eps) result = rampup (x+eps, 2.0*eps);
- else /* if (x < 1.0+eps) */ result = 1.0 - rampup (1.0+eps - x, 2.0*eps);
- } else {
- result = step (edge0, x_);
+float smooth_linearstep(float edge0, float edge1, float x_, float eps_)
+{
+ float result;
+ if (edge0 != edge1) {
+ float rampup(float x, float r)
+ {
+ return 0.5 / r * x * x;
}
- return result;
+ float width_inv = 1.0 / (edge1 - edge0);
+ float eps = eps_ * width_inv;
+ float x = (x_ - edge0) * width_inv;
+ if (x <= -eps)
+ result = 0;
+ else if (x >= eps && x <= 1.0 - eps)
+ result = x;
+ else if (x >= 1.0 + eps)
+ result = 1;
+ else if (x < eps)
+ result = rampup(x + eps, 2.0 * eps);
+ else /* if (x < 1.0+eps) */
+ result = 1.0 - rampup(1.0 + eps - x, 2.0 * eps);
+ }
+ else {
+ result = step(edge0, x_);
+ }
+ return result;
}
-float aastep (float edge, float s, float dedge, float ds) {
- // Box filtered AA step
- float width = fabs(dedge) + fabs(ds);
- float halfwidth = 0.5*width;
- float e1 = edge-halfwidth;
- return (s <= e1) ? 0.0 : ((s >= (edge+halfwidth)) ? 1.0 : (s-e1)/width);
+float aastep(float edge, float s, float dedge, float ds)
+{
+ // Box filtered AA step
+ float width = fabs(dedge) + fabs(ds);
+ float halfwidth = 0.5 * width;
+ float e1 = edge - halfwidth;
+ return (s <= e1) ? 0.0 : ((s >= (edge + halfwidth)) ? 1.0 : (s - e1) / width);
}
-float aastep (float edge, float s, float ds) {
- return aastep (edge, s, filterwidth(edge), ds);
+float aastep(float edge, float s, float ds)
+{
+ return aastep(edge, s, filterwidth(edge), ds);
}
-float aastep (float edge, float s) {
- return aastep (edge, s, filterwidth(edge), filterwidth(s));
+float aastep(float edge, float s)
+{
+ return aastep(edge, s, filterwidth(edge), filterwidth(s));
}
-
// Derivatives and area operators
-
// Displacement functions
-
// String functions
-int strlen (string s) BUILTIN;
-int hash (string s) BUILTIN;
-int getchar (string s, int index) BUILTIN;
-int startswith (string s, string prefix) BUILTIN;
-int endswith (string s, string suffix) BUILTIN;
-string substr (string s, int start, int len) BUILTIN;
-string substr (string s, int start) { return substr (s, start, strlen(s)); }
-float stof (string str) BUILTIN;
-int stoi (string str) BUILTIN;
+int strlen(string s) BUILTIN;
+int hash(string s) BUILTIN;
+int getchar(string s, int index) BUILTIN;
+int startswith(string s, string prefix) BUILTIN;
+int endswith(string s, string suffix) BUILTIN;
+string substr(string s, int start, int len) BUILTIN;
+string substr(string s, int start)
+{
+ return substr(s, start, strlen(s));
+}
+float stof(string str) BUILTIN;
+int stoi(string str) BUILTIN;
// Define concat in terms of shorter concat
-string concat (string a, string b, string c) {
- return concat(concat(a,b), c);
+string concat(string a, string b, string c)
+{
+ return concat(concat(a, b), c);
}
-string concat (string a, string b, string c, string d) {
- return concat(concat(a,b,c), d);
+string concat(string a, string b, string c, string d)
+{
+ return concat(concat(a, b, c), d);
}
-string concat (string a, string b, string c, string d, string e) {
- return concat(concat(a,b,c,d), e);
+string concat(string a, string b, string c, string d, string e)
+{
+ return concat(concat(a, b, c, d), e);
}
-string concat (string a, string b, string c, string d, string e, string f) {
- return concat(concat(a,b,c,d,e), f);
+string concat(string a, string b, string c, string d, string e, string f)
+{
+ return concat(concat(a, b, c, d, e), f);
}
-
// Texture
-
// Closures
closure color diffuse(normal N) BUILTIN;
@@ -591,14 +732,18 @@ closure color microfacet_multi_ggx(normal N, float ag, color C) BUILTIN;
closure color microfacet_multi_ggx_aniso(normal N, vector T, float ax, float ay, color C) BUILTIN;
closure color microfacet_multi_ggx_glass(normal N, float ag, float eta, color C) BUILTIN;
closure color microfacet_ggx_fresnel(normal N, float ag, float eta, color C, color Cspec0) BUILTIN;
-closure color microfacet_ggx_aniso_fresnel(normal N, vector T, float ax, float ay, float eta, color C, color Cspec0) BUILTIN;
-closure color microfacet_multi_ggx_fresnel(normal N, float ag, float eta, color C, color Cspec0) BUILTIN;
-closure color microfacet_multi_ggx_aniso_fresnel(normal N, vector T, float ax, float ay, float eta, color C, color Cspec0) BUILTIN;
-closure color microfacet_multi_ggx_glass_fresnel(normal N, float ag, float eta, color C, color Cspec0) BUILTIN;
+closure color microfacet_ggx_aniso_fresnel(
+ normal N, vector T, float ax, float ay, float eta, color C, color Cspec0) BUILTIN;
+closure color
+microfacet_multi_ggx_fresnel(normal N, float ag, float eta, color C, color Cspec0) BUILTIN;
+closure color microfacet_multi_ggx_aniso_fresnel(
+ normal N, vector T, float ax, float ay, float eta, color C, color Cspec0) BUILTIN;
+closure color
+microfacet_multi_ggx_glass_fresnel(normal N, float ag, float eta, color C, color Cspec0) BUILTIN;
closure color microfacet_beckmann(normal N, float ab) BUILTIN;
closure color microfacet_beckmann_aniso(normal N, vector T, float ax, float ay) BUILTIN;
closure color microfacet_beckmann_refraction(normal N, float ab, float eta) BUILTIN;
-closure color ashikhmin_shirley(normal N, vector T,float ax, float ay) BUILTIN;
+closure color ashikhmin_shirley(normal N, vector T, float ax, float ay) BUILTIN;
closure color ashikhmin_velvet(normal N, float sigma) BUILTIN;
closure color emission() BUILTIN;
closure color background() BUILTIN;
@@ -612,78 +757,97 @@ closure color principled_clearcoat(normal N, float clearcoat, float clearcoat_ro
closure color bssrdf(string method, normal N, vector radius, color albedo) BUILTIN;
// Hair
-closure color hair_reflection(normal N, float roughnessu, float roughnessv, vector T, float offset) BUILTIN;
-closure color hair_transmission(normal N, float roughnessu, float roughnessv, vector T, float offset) BUILTIN;
-closure color principled_hair(normal N, color sigma, float roughnessu, float roughnessv, float coat, float alpha, float eta) BUILTIN;
+closure color
+hair_reflection(normal N, float roughnessu, float roughnessv, vector T, float offset) BUILTIN;
+closure color
+hair_transmission(normal N, float roughnessu, float roughnessv, vector T, float offset) BUILTIN;
+closure color principled_hair(normal N,
+ color sigma,
+ float roughnessu,
+ float roughnessv,
+ float coat,
+ float alpha,
+ float eta) BUILTIN;
// Volume
closure color henyey_greenstein(float g) BUILTIN;
closure color absorption() BUILTIN;
// OSL 1.5 Microfacet functions
-closure color microfacet(string distribution, normal N, vector U, float xalpha, float yalpha, float eta, int refract) {
- /* GGX */
- if (distribution == "ggx" || distribution == "default") {
- if (!refract) {
- if (xalpha == yalpha) {
- /* Isotropic */
- return microfacet_ggx(N, xalpha);
- }
- else {
- /* Anisotropic */
- return microfacet_ggx_aniso(N, U, xalpha, yalpha);
- }
- }
- else {
- return microfacet_ggx_refraction(N, xalpha, eta);
- }
- }
- /* Beckmann */
- else {
- if (!refract) {
- if (xalpha == yalpha) {
- /* Isotropic */
- return microfacet_beckmann(N, xalpha);
- }
- else {
- /* Anisotropic */
- return microfacet_beckmann_aniso(N, U, xalpha, yalpha);
- }
- }
- else {
- return microfacet_beckmann_refraction(N, xalpha, eta);
- }
- }
-}
-
-closure color microfacet (string distribution, normal N, float alpha, float eta, int refract) {
- return microfacet(distribution, N, vector(0), alpha, alpha, eta, refract);
+closure color microfacet(
+ string distribution, normal N, vector U, float xalpha, float yalpha, float eta, int refract)
+{
+ /* GGX */
+ if (distribution == "ggx" || distribution == "default") {
+ if (!refract) {
+ if (xalpha == yalpha) {
+ /* Isotropic */
+ return microfacet_ggx(N, xalpha);
+ }
+ else {
+ /* Anisotropic */
+ return microfacet_ggx_aniso(N, U, xalpha, yalpha);
+ }
+ }
+ else {
+ return microfacet_ggx_refraction(N, xalpha, eta);
+ }
+ }
+ /* Beckmann */
+ else {
+ if (!refract) {
+ if (xalpha == yalpha) {
+ /* Isotropic */
+ return microfacet_beckmann(N, xalpha);
+ }
+ else {
+ /* Anisotropic */
+ return microfacet_beckmann_aniso(N, U, xalpha, yalpha);
+ }
+ }
+ else {
+ return microfacet_beckmann_refraction(N, xalpha, eta);
+ }
+ }
}
+closure color microfacet(string distribution, normal N, float alpha, float eta, int refract)
+{
+ return microfacet(distribution, N, vector(0), alpha, alpha, eta, refract);
+}
// Renderer state
-int backfacing () BUILTIN;
-int raytype (string typename) BUILTIN;
+int backfacing() BUILTIN;
+int raytype(string typename) BUILTIN;
// the individual 'isFOOray' functions are deprecated
-int iscameraray () { return raytype("camera"); }
-int isdiffuseray () { return raytype("diffuse"); }
-int isglossyray () { return raytype("glossy"); }
-int isshadowray () { return raytype("shadow"); }
-int getmatrix (string fromspace, string tospace, output matrix M) BUILTIN;
-int getmatrix (string fromspace, output matrix M) {
- return getmatrix (fromspace, "common", M);
+int iscameraray()
+{
+ return raytype("camera");
+}
+int isdiffuseray()
+{
+ return raytype("diffuse");
+}
+int isglossyray()
+{
+ return raytype("glossy");
+}
+int isshadowray()
+{
+ return raytype("shadow");
+}
+int getmatrix(string fromspace, string tospace, output matrix M) BUILTIN;
+int getmatrix(string fromspace, output matrix M)
+{
+ return getmatrix(fromspace, "common", M);
}
-
// Miscellaneous
-
-
-
#undef BUILTIN
#undef BUILTIN_DERIV
#undef PERCOMP1
#undef PERCOMP2
#undef PERCOMP2F
-#endif /* CCL_STDOSL_H */
+#endif /* CCL_STDOSL_H */
diff --git a/intern/cycles/kernel/split/kernel_branched.h b/intern/cycles/kernel/split/kernel_branched.h
index ed0a82067f1..e08d87ab618 100644
--- a/intern/cycles/kernel/split/kernel_branched.h
+++ b/intern/cycles/kernel/split/kernel_branched.h
@@ -19,215 +19,213 @@ 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)
+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];
+ 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];
+ /* 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(isect);
- BRANCHED_STORE(ray_state);
+ BRANCHED_STORE(path_state);
+ BRANCHED_STORE(throughput);
+ BRANCHED_STORE(ray);
+ BRANCHED_STORE(isect);
+ BRANCHED_STORE(ray_state);
- *kernel_split_sd(branched_state_sd, ray_index) = *kernel_split_sd(sd, ray_index);
- for(int i = 0; i < kernel_split_sd(branched_state_sd, ray_index)->num_closure; i++) {
- kernel_split_sd(branched_state_sd, ray_index)->closure[i] = kernel_split_sd(sd, ray_index)->closure[i];
- }
+ *kernel_split_sd(branched_state_sd, ray_index) = *kernel_split_sd(sd, ray_index);
+ for (int i = 0; i < kernel_split_sd(branched_state_sd, ray_index)->num_closure; i++) {
+ kernel_split_sd(branched_state_sd, ray_index)->closure[i] =
+ kernel_split_sd(sd, ray_index)->closure[i];
+ }
-#undef BRANCHED_STORE
+# undef BRANCHED_STORE
- /* set loop counters to intial position */
- branched_state->next_closure = 0;
- branched_state->next_sample = 0;
+ /* 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)
+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];
+ 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;
+ /* 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(isect);
- BRANCHED_RESTORE(ray_state);
+ BRANCHED_RESTORE(path_state);
+ BRANCHED_RESTORE(throughput);
+ BRANCHED_RESTORE(ray);
+ BRANCHED_RESTORE(isect);
+ BRANCHED_RESTORE(ray_state);
- *kernel_split_sd(sd, ray_index) = *kernel_split_sd(branched_state_sd, ray_index);
- for(int i = 0; i < kernel_split_sd(branched_state_sd, ray_index)->num_closure; i++) {
- kernel_split_sd(sd, ray_index)->closure[i] = kernel_split_sd(branched_state_sd, ray_index)->closure[i];
- }
+ *kernel_split_sd(sd, ray_index) = *kernel_split_sd(branched_state_sd, ray_index);
+ for (int i = 0; i < kernel_split_sd(branched_state_sd, ray_index)->num_closure; i++) {
+ kernel_split_sd(sd, ray_index)->closure[i] =
+ kernel_split_sd(branched_state_sd, ray_index)->closure[i];
+ }
-#undef BRANCHED_RESTORE
+# undef BRANCHED_RESTORE
- /* leave indirect loop */
- REMOVE_RAY_FLAG(kernel_split_state.ray_state, ray_index, RAY_BRANCHED_INDIRECT);
+ /* leave indirect loop */
+ REMOVE_RAY_FLAG(kernel_split_state.ray_state, ray_index, RAY_BRANCHED_INDIRECT);
}
-ccl_device_inline bool kernel_split_branched_indirect_start_shared(KernelGlobals *kg, int ray_index)
+ccl_device_inline bool kernel_split_branched_indirect_start_shared(KernelGlobals *kg,
+ int ray_index)
{
- ccl_global char *ray_state = kernel_split_state.ray_state;
+ ccl_global char *ray_state = kernel_split_state.ray_state;
- int inactive_ray = dequeue_ray_index(QUEUE_INACTIVE_RAYS,
- kernel_split_state.queue_data, kernel_split_params.queue_size, kernel_split_params.queue_index);
+ int inactive_ray = dequeue_ray_index(QUEUE_INACTIVE_RAYS,
+ kernel_split_state.queue_data,
+ kernel_split_params.queue_size,
+ kernel_split_params.queue_index);
- if(!IS_STATE(ray_state, inactive_ray, RAY_INACTIVE)) {
- return false;
- }
+ if (!IS_STATE(ray_state, inactive_ray, RAY_INACTIVE)) {
+ return false;
+ }
-#define SPLIT_DATA_ENTRY(type, name, num) \
- if(num) { \
- kernel_split_state.name[inactive_ray] = kernel_split_state.name[ray_index]; \
- }
- SPLIT_DATA_ENTRIES_BRANCHED_SHARED
-#undef SPLIT_DATA_ENTRY
+# define SPLIT_DATA_ENTRY(type, name, num) \
+ if (num) { \
+ kernel_split_state.name[inactive_ray] = kernel_split_state.name[ray_index]; \
+ }
+ SPLIT_DATA_ENTRIES_BRANCHED_SHARED
+# undef SPLIT_DATA_ENTRY
- *kernel_split_sd(sd, inactive_ray) = *kernel_split_sd(sd, ray_index);
- for(int i = 0; i < kernel_split_sd(sd, ray_index)->num_closure; i++) {
- kernel_split_sd(sd, inactive_ray)->closure[i] = kernel_split_sd(sd, ray_index)->closure[i];
- }
+ *kernel_split_sd(sd, inactive_ray) = *kernel_split_sd(sd, ray_index);
+ for (int i = 0; i < kernel_split_sd(sd, ray_index)->num_closure; i++) {
+ kernel_split_sd(sd, inactive_ray)->closure[i] = kernel_split_sd(sd, ray_index)->closure[i];
+ }
- kernel_split_state.branched_state[inactive_ray].shared_sample_count = 0;
- kernel_split_state.branched_state[inactive_ray].original_ray = ray_index;
- kernel_split_state.branched_state[inactive_ray].waiting_on_shared_samples = false;
+ kernel_split_state.branched_state[inactive_ray].shared_sample_count = 0;
+ kernel_split_state.branched_state[inactive_ray].original_ray = ray_index;
+ kernel_split_state.branched_state[inactive_ray].waiting_on_shared_samples = false;
- PathRadiance *L = &kernel_split_state.path_radiance[ray_index];
- PathRadiance *inactive_L = &kernel_split_state.path_radiance[inactive_ray];
+ PathRadiance *L = &kernel_split_state.path_radiance[ray_index];
+ PathRadiance *inactive_L = &kernel_split_state.path_radiance[inactive_ray];
- path_radiance_init(inactive_L, kernel_data.film.use_light_pass);
- path_radiance_copy_indirect(inactive_L, L);
+ path_radiance_init(inactive_L, kernel_data.film.use_light_pass);
+ path_radiance_copy_indirect(inactive_L, L);
- ray_state[inactive_ray] = RAY_REGENERATED;
- ADD_RAY_FLAG(ray_state, inactive_ray, RAY_BRANCHED_INDIRECT_SHARED);
- ADD_RAY_FLAG(ray_state, inactive_ray, IS_FLAG(ray_state, ray_index, RAY_BRANCHED_INDIRECT));
+ ray_state[inactive_ray] = RAY_REGENERATED;
+ ADD_RAY_FLAG(ray_state, inactive_ray, RAY_BRANCHED_INDIRECT_SHARED);
+ ADD_RAY_FLAG(ray_state, inactive_ray, IS_FLAG(ray_state, ray_index, RAY_BRANCHED_INDIRECT));
- atomic_fetch_and_inc_uint32((ccl_global uint*)&kernel_split_state.branched_state[ray_index].shared_sample_count);
+ atomic_fetch_and_inc_uint32(
+ (ccl_global uint *)&kernel_split_state.branched_state[ray_index].shared_sample_count);
- return true;
+ return true;
}
/* 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,
- bool wait_for_shared)
+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,
+ bool wait_for_shared)
{
- SplitBranchedState *branched_state = &kernel_split_state.branched_state[ray_index];
-
- ShaderData *sd = saved_sd;
- PathRadiance *L = &kernel_split_state.path_radiance[ray_index];
- float3 throughput = branched_state->throughput;
- ccl_global PathState *ps = &kernel_split_state.path_state[ray_index];
-
- float sum_sample_weight = 0.0f;
-#ifdef __DENOISING_FEATURES__
- if(ps->denoising_feature_weight > 0.0f) {
- for(int i = 0; i < sd->num_closure; i++) {
- const ShaderClosure *sc = &sd->closure[i];
-
- /* transparency is not handled here, but in outer loop */
- if(!CLOSURE_IS_BSDF(sc->type) || CLOSURE_IS_BSDF_TRANSPARENT(sc->type)) {
- continue;
- }
-
- sum_sample_weight += sc->sample_weight;
- }
- }
- else {
- sum_sample_weight = 1.0f;
- }
-#endif /* __DENOISING_FEATURES__ */
-
- 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;
-
- for(int j = branched_state->next_sample; j < num_samples; j++) {
- if(reset_path_state) {
- *ps = branched_state->path_state;
- }
-
- ps->rng_hash = cmj_hash(branched_state->path_state.rng_hash, i);
-
- 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,
- sd,
- sc,
- j,
- num_samples,
- tp,
- ps,
- &L->state,
- bsdf_ray,
- sum_sample_weight))
- {
- continue;
- }
-
- ps->rng_hash = branched_state->path_state.rng_hash;
-
- /* update state for next iteration */
- branched_state->next_closure = i;
- branched_state->next_sample = j+1;
-
- /* start the indirect path */
- *tp *= num_samples_inv;
-
- if(kernel_split_branched_indirect_start_shared(kg, ray_index)) {
- continue;
- }
-
- return true;
- }
-
- branched_state->next_sample = 0;
- }
-
- branched_state->next_closure = sd->num_closure;
-
- if(wait_for_shared) {
- branched_state->waiting_on_shared_samples = (branched_state->shared_sample_count > 0);
- if(branched_state->waiting_on_shared_samples) {
- return true;
- }
- }
-
- return false;
+ SplitBranchedState *branched_state = &kernel_split_state.branched_state[ray_index];
+
+ ShaderData *sd = saved_sd;
+ PathRadiance *L = &kernel_split_state.path_radiance[ray_index];
+ float3 throughput = branched_state->throughput;
+ ccl_global PathState *ps = &kernel_split_state.path_state[ray_index];
+
+ float sum_sample_weight = 0.0f;
+# ifdef __DENOISING_FEATURES__
+ if (ps->denoising_feature_weight > 0.0f) {
+ for (int i = 0; i < sd->num_closure; i++) {
+ const ShaderClosure *sc = &sd->closure[i];
+
+ /* transparency is not handled here, but in outer loop */
+ if (!CLOSURE_IS_BSDF(sc->type) || CLOSURE_IS_BSDF_TRANSPARENT(sc->type)) {
+ continue;
+ }
+
+ sum_sample_weight += sc->sample_weight;
+ }
+ }
+ else {
+ sum_sample_weight = 1.0f;
+ }
+# endif /* __DENOISING_FEATURES__ */
+
+ 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;
+
+ for (int j = branched_state->next_sample; j < num_samples; j++) {
+ if (reset_path_state) {
+ *ps = branched_state->path_state;
+ }
+
+ ps->rng_hash = cmj_hash(branched_state->path_state.rng_hash, i);
+
+ 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, sd, sc, j, num_samples, tp, ps, &L->state, bsdf_ray, sum_sample_weight)) {
+ continue;
+ }
+
+ ps->rng_hash = branched_state->path_state.rng_hash;
+
+ /* update state for next iteration */
+ branched_state->next_closure = i;
+ branched_state->next_sample = j + 1;
+
+ /* start the indirect path */
+ *tp *= num_samples_inv;
+
+ if (kernel_split_branched_indirect_start_shared(kg, ray_index)) {
+ continue;
+ }
+
+ return true;
+ }
+
+ branched_state->next_sample = 0;
+ }
+
+ branched_state->next_closure = sd->num_closure;
+
+ if (wait_for_shared) {
+ branched_state->waiting_on_shared_samples = (branched_state->shared_sample_count > 0);
+ if (branched_state->waiting_on_shared_samples) {
+ return true;
+ }
+ }
+
+ return false;
}
-#endif /* __BRANCHED_PATH__ */
+#endif /* __BRANCHED_PATH__ */
CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/split/kernel_buffer_update.h b/intern/cycles/kernel/split/kernel_buffer_update.h
index 18eec6372f1..e77743350dc 100644
--- a/intern/cycles/kernel/split/kernel_buffer_update.h
+++ b/intern/cycles/kernel/split/kernel_buffer_update.h
@@ -41,132 +41,133 @@ CCL_NAMESPACE_BEGIN
ccl_device void kernel_buffer_update(KernelGlobals *kg,
ccl_local_param unsigned int *local_queue_atomics)
{
- 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);
- if(ray_index == 0) {
- /* We will empty this queue in this kernel. */
- kernel_split_params.queue_index[QUEUE_HITBG_BUFF_UPDATE_TOREGEN_RAYS] = 0;
- }
- char enqueue_flag = 0;
- ray_index = get_ray_index(kg, ray_index,
- QUEUE_HITBG_BUFF_UPDATE_TOREGEN_RAYS,
- kernel_split_state.queue_data,
- kernel_split_params.queue_size,
- 1);
+ 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);
+ if (ray_index == 0) {
+ /* We will empty this queue in this kernel. */
+ kernel_split_params.queue_index[QUEUE_HITBG_BUFF_UPDATE_TOREGEN_RAYS] = 0;
+ }
+ char enqueue_flag = 0;
+ ray_index = get_ray_index(kg,
+ ray_index,
+ QUEUE_HITBG_BUFF_UPDATE_TOREGEN_RAYS,
+ kernel_split_state.queue_data,
+ kernel_split_params.queue_size,
+ 1);
#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;
- }
+ /* 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) {
+ if (ray_index != QUEUE_EMPTY_SLOT) {
#endif
- 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];
- ccl_global Ray *ray = &kernel_split_state.ray[ray_index];
- ccl_global float3 *throughput = &kernel_split_state.throughput[ray_index];
- bool ray_was_updated = false;
-
- if(IS_STATE(ray_state, ray_index, RAY_UPDATE_BUFFER)) {
- ray_was_updated = true;
- uint sample = state->sample;
- uint buffer_offset = kernel_split_state.buffer_offset[ray_index];
- ccl_global float *buffer = kernel_split_params.tile.buffer + buffer_offset;
-
- /* accumulate result in output buffer */
- kernel_write_result(kg, buffer, sample, L);
-
- ASSIGN_RAY_STATE(ray_state, ray_index, RAY_TO_REGENERATE);
- }
-
- if(kernel_data.film.cryptomatte_passes) {
- /* Make sure no thread is writing to the buffers. */
- ccl_barrier(CCL_LOCAL_MEM_FENCE);
- if(ray_was_updated && state->sample - 1 == kernel_data.integrator.aa_samples) {
- uint buffer_offset = kernel_split_state.buffer_offset[ray_index];
- ccl_global float *buffer = kernel_split_params.tile.buffer + buffer_offset;
- ccl_global float *cryptomatte_buffer = buffer + kernel_data.film.pass_cryptomatte;
- kernel_sort_id_slots(cryptomatte_buffer, 2 * kernel_data.film.cryptomatte_depth);
- }
- }
-
- if(IS_STATE(ray_state, ray_index, RAY_TO_REGENERATE)) {
- /* We have completed current work; So get next work */
- ccl_global uint *work_pools = kernel_split_params.work_pools;
- uint total_work_size = kernel_split_params.total_work_size;
- uint work_index;
-
- if(!get_next_work(kg, work_pools, total_work_size, ray_index, &work_index)) {
- /* If work is invalid, this means no more work is available and the thread may exit */
- ASSIGN_RAY_STATE(ray_state, ray_index, RAY_INACTIVE);
- }
-
- if(IS_STATE(ray_state, ray_index, RAY_TO_REGENERATE)) {
- ccl_global WorkTile *tile = &kernel_split_params.tile;
- uint x, y, sample;
- get_work_pixel(tile, work_index, &x, &y, &sample);
-
- /* Store buffer offset for writing to passes. */
- uint buffer_offset = (tile->offset + x + y*tile->stride) * kernel_data.film.pass_stride;
- kernel_split_state.buffer_offset[ray_index] = buffer_offset;
-
- /* Initialize random numbers and ray. */
- uint rng_hash;
- kernel_path_trace_setup(kg, sample, x, y, &rng_hash, ray);
-
- if(ray->t != 0.0f) {
- /* Initialize throughput, path radiance, Ray, PathState;
- * These rays proceed with path-iteration.
- */
- *throughput = make_float3(1.0f, 1.0f, 1.0f);
- path_radiance_init(L, kernel_data.film.use_light_pass);
- path_state_init(kg,
- AS_SHADER_DATA(&kernel_split_state.sd_DL_shadow[ray_index]),
- state,
- rng_hash,
- sample,
- ray);
+ 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];
+ ccl_global Ray *ray = &kernel_split_state.ray[ray_index];
+ ccl_global float3 *throughput = &kernel_split_state.throughput[ray_index];
+ bool ray_was_updated = false;
+
+ if (IS_STATE(ray_state, ray_index, RAY_UPDATE_BUFFER)) {
+ ray_was_updated = true;
+ uint sample = state->sample;
+ uint buffer_offset = kernel_split_state.buffer_offset[ray_index];
+ ccl_global float *buffer = kernel_split_params.tile.buffer + buffer_offset;
+
+ /* accumulate result in output buffer */
+ kernel_write_result(kg, buffer, sample, L);
+
+ ASSIGN_RAY_STATE(ray_state, ray_index, RAY_TO_REGENERATE);
+ }
+
+ if (kernel_data.film.cryptomatte_passes) {
+ /* Make sure no thread is writing to the buffers. */
+ ccl_barrier(CCL_LOCAL_MEM_FENCE);
+ if (ray_was_updated && state->sample - 1 == kernel_data.integrator.aa_samples) {
+ uint buffer_offset = kernel_split_state.buffer_offset[ray_index];
+ ccl_global float *buffer = kernel_split_params.tile.buffer + buffer_offset;
+ ccl_global float *cryptomatte_buffer = buffer + kernel_data.film.pass_cryptomatte;
+ kernel_sort_id_slots(cryptomatte_buffer, 2 * kernel_data.film.cryptomatte_depth);
+ }
+ }
+
+ if (IS_STATE(ray_state, ray_index, RAY_TO_REGENERATE)) {
+ /* We have completed current work; So get next work */
+ ccl_global uint *work_pools = kernel_split_params.work_pools;
+ uint total_work_size = kernel_split_params.total_work_size;
+ uint work_index;
+
+ if (!get_next_work(kg, work_pools, total_work_size, ray_index, &work_index)) {
+ /* If work is invalid, this means no more work is available and the thread may exit */
+ ASSIGN_RAY_STATE(ray_state, ray_index, RAY_INACTIVE);
+ }
+
+ if (IS_STATE(ray_state, ray_index, RAY_TO_REGENERATE)) {
+ ccl_global WorkTile *tile = &kernel_split_params.tile;
+ uint x, y, sample;
+ get_work_pixel(tile, work_index, &x, &y, &sample);
+
+ /* Store buffer offset for writing to passes. */
+ uint buffer_offset = (tile->offset + x + y * tile->stride) * kernel_data.film.pass_stride;
+ kernel_split_state.buffer_offset[ray_index] = buffer_offset;
+
+ /* Initialize random numbers and ray. */
+ uint rng_hash;
+ kernel_path_trace_setup(kg, sample, x, y, &rng_hash, ray);
+
+ if (ray->t != 0.0f) {
+ /* Initialize throughput, path radiance, Ray, PathState;
+ * These rays proceed with path-iteration.
+ */
+ *throughput = make_float3(1.0f, 1.0f, 1.0f);
+ path_radiance_init(L, kernel_data.film.use_light_pass);
+ path_state_init(kg,
+ AS_SHADER_DATA(&kernel_split_state.sd_DL_shadow[ray_index]),
+ state,
+ rng_hash,
+ sample,
+ ray);
#ifdef __SUBSURFACE__
- kernel_path_subsurface_init_indirect(&kernel_split_state.ss_rays[ray_index]);
+ kernel_path_subsurface_init_indirect(&kernel_split_state.ss_rays[ray_index]);
#endif
- ASSIGN_RAY_STATE(ray_state, ray_index, RAY_REGENERATED);
- enqueue_flag = 1;
- }
- else {
- ASSIGN_RAY_STATE(ray_state, ray_index, RAY_TO_REGENERATE);
- }
- }
- }
+ ASSIGN_RAY_STATE(ray_state, ray_index, RAY_REGENERATED);
+ enqueue_flag = 1;
+ }
+ else {
+ ASSIGN_RAY_STATE(ray_state, ray_index, RAY_TO_REGENERATE);
+ }
+ }
+ }
#ifndef __COMPUTE_DEVICE_GPU__
- }
+ }
#endif
- /* Enqueue RAY_REGENERATED rays into QUEUE_ACTIVE_AND_REGENERATED_RAYS;
- * These rays will be made active during next SceneIntersectkernel.
- */
- enqueue_ray_index_local(ray_index,
- QUEUE_ACTIVE_AND_REGENERATED_RAYS,
- enqueue_flag,
- kernel_split_params.queue_size,
- local_queue_atomics,
- kernel_split_state.queue_data,
- kernel_split_params.queue_index);
+ /* Enqueue RAY_REGENERATED rays into QUEUE_ACTIVE_AND_REGENERATED_RAYS;
+ * These rays will be made active during next SceneIntersectkernel.
+ */
+ enqueue_ray_index_local(ray_index,
+ QUEUE_ACTIVE_AND_REGENERATED_RAYS,
+ enqueue_flag,
+ kernel_split_params.queue_size,
+ local_queue_atomics,
+ kernel_split_state.queue_data,
+ kernel_split_params.queue_index);
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/split/kernel_data_init.h b/intern/cycles/kernel/split/kernel_data_init.h
index 77fb61b80a8..52930843f56 100644
--- a/intern/cycles/kernel/split/kernel_data_init.h
+++ b/intern/cycles/kernel/split/kernel_data_init.h
@@ -28,82 +28,88 @@ ccl_device void kernel_data_init(
#else
void KERNEL_FUNCTION_FULL_NAME(data_init)(
#endif
- KernelGlobals *kg,
- ccl_constant KernelData *data,
- ccl_global void *split_data_buffer,
- int num_elements,
- ccl_global char *ray_state,
+ KernelGlobals *kg,
+ ccl_constant KernelData *data,
+ ccl_global void *split_data_buffer,
+ int num_elements,
+ ccl_global char *ray_state,
#ifdef __KERNEL_OPENCL__
- KERNEL_BUFFER_PARAMS,
+ KERNEL_BUFFER_PARAMS,
#endif
- int start_sample,
- int end_sample,
- int sx, int sy, int sw, int sh, int offset, int stride,
- ccl_global int *Queue_index, /* Tracks the number of elements in queues */
- int queuesize, /* size (capacity) of the queue */
- ccl_global char *use_queues_flag, /* flag to decide if scene-intersect kernel should use queues to fetch ray index */
- ccl_global unsigned int *work_pools, /* Work pool for each work group */
- unsigned int num_samples,
- ccl_global float *buffer)
+ int start_sample,
+ int end_sample,
+ int sx,
+ int sy,
+ int sw,
+ int sh,
+ int offset,
+ int stride,
+ ccl_global int *Queue_index, /* Tracks the number of elements in queues */
+ int queuesize, /* size (capacity) of the queue */
+ ccl_global char *
+ use_queues_flag, /* flag to decide if scene-intersect kernel should use queues to fetch ray index */
+ ccl_global unsigned int *work_pools, /* Work pool for each work group */
+ unsigned int num_samples,
+ ccl_global float *buffer)
{
#ifdef KERNEL_STUB
- STUB_ASSERT(KERNEL_ARCH, data_init);
+ STUB_ASSERT(KERNEL_ARCH, data_init);
#else
-#ifdef __KERNEL_OPENCL__
- kg->data = data;
-#endif
+# ifdef __KERNEL_OPENCL__
+ kg->data = data;
+# endif
- kernel_split_params.tile.x = sx;
- kernel_split_params.tile.y = sy;
- kernel_split_params.tile.w = sw;
- kernel_split_params.tile.h = sh;
+ kernel_split_params.tile.x = sx;
+ kernel_split_params.tile.y = sy;
+ kernel_split_params.tile.w = sw;
+ kernel_split_params.tile.h = sh;
- kernel_split_params.tile.start_sample = start_sample;
- kernel_split_params.tile.num_samples = num_samples;
+ kernel_split_params.tile.start_sample = start_sample;
+ kernel_split_params.tile.num_samples = num_samples;
- kernel_split_params.tile.offset = offset;
- kernel_split_params.tile.stride = stride;
+ kernel_split_params.tile.offset = offset;
+ kernel_split_params.tile.stride = stride;
- kernel_split_params.tile.buffer = buffer;
+ kernel_split_params.tile.buffer = buffer;
- kernel_split_params.total_work_size = sw * sh * num_samples;
+ kernel_split_params.total_work_size = sw * sh * num_samples;
- kernel_split_params.work_pools = work_pools;
+ kernel_split_params.work_pools = work_pools;
- kernel_split_params.queue_index = Queue_index;
- kernel_split_params.queue_size = queuesize;
- kernel_split_params.use_queues_flag = use_queues_flag;
+ kernel_split_params.queue_index = Queue_index;
+ kernel_split_params.queue_size = queuesize;
+ kernel_split_params.use_queues_flag = use_queues_flag;
- split_data_init(kg, &kernel_split_state, num_elements, split_data_buffer, ray_state);
+ split_data_init(kg, &kernel_split_state, num_elements, split_data_buffer, ray_state);
-#ifdef __KERNEL_OPENCL__
- kernel_set_buffer_pointers(kg, KERNEL_BUFFER_ARGS);
- kernel_set_buffer_info(kg);
-#endif
+# ifdef __KERNEL_OPENCL__
+ kernel_set_buffer_pointers(kg, KERNEL_BUFFER_ARGS);
+ kernel_set_buffer_info(kg);
+# endif
+
+ int thread_index = ccl_global_id(1) * ccl_global_size(0) + ccl_global_id(0);
+
+ /* Initialize queue data and queue index. */
+ if (thread_index < queuesize) {
+ for (int i = 0; i < NUM_QUEUES; i++) {
+ kernel_split_state.queue_data[i * queuesize + thread_index] = QUEUE_EMPTY_SLOT;
+ }
+ }
+
+ if (thread_index == 0) {
+ for (int i = 0; i < NUM_QUEUES; i++) {
+ Queue_index[i] = 0;
+ }
- int thread_index = ccl_global_id(1) * ccl_global_size(0) + ccl_global_id(0);
-
- /* Initialize queue data and queue index. */
- if(thread_index < queuesize) {
- for(int i = 0; i < NUM_QUEUES; i++) {
- kernel_split_state.queue_data[i * queuesize + thread_index] = QUEUE_EMPTY_SLOT;
- }
- }
-
- if(thread_index == 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.
- */
- *use_queues_flag = 0;
- }
-#endif /* KERENL_STUB */
+ /* The scene-intersect kernel should not use the queues very first time.
+ * since the queue would be empty.
+ */
+ *use_queues_flag = 0;
+ }
+#endif /* KERENL_STUB */
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/split/kernel_direct_lighting.h b/intern/cycles/kernel/split/kernel_direct_lighting.h
index ca79602c565..b2ca59d60cc 100644
--- a/intern/cycles/kernel/split/kernel_direct_lighting.h
+++ b/intern/cycles/kernel/split/kernel_direct_lighting.h
@@ -43,116 +43,111 @@ CCL_NAMESPACE_BEGIN
ccl_device void kernel_direct_lighting(KernelGlobals *kg,
ccl_local_param unsigned int *local_queue_atomics)
{
- if(ccl_local_id(0) == 0 && ccl_local_id(1) == 0) {
- *local_queue_atomics = 0;
- }
- ccl_barrier(CCL_LOCAL_MEM_FENCE);
-
- 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,
- kernel_split_state.queue_data,
- kernel_split_params.queue_size,
- 0);
-
- 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_sd(sd, ray_index);
-
- /* direct lighting */
+ if (ccl_local_id(0) == 0 && ccl_local_id(1) == 0) {
+ *local_queue_atomics = 0;
+ }
+ ccl_barrier(CCL_LOCAL_MEM_FENCE);
+
+ 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,
+ kernel_split_state.queue_data,
+ kernel_split_params.queue_size,
+ 0);
+
+ 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_sd(sd, ray_index);
+
+ /* direct lighting */
#ifdef __EMISSION__
- bool flag = (kernel_data.integrator.use_direct_light &&
- (sd->flag & SD_BSDF_HAS_EVAL));
+ 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__ */
+ 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;
- enqueue_flag = 1;
- }
-# endif /* __SHADOW_TRICKS__ */
-
- if(flag) {
- /* Sample illumination from lights to find path contribution. */
- float light_u, light_v;
- path_state_rng_2D(kg, state, PRNG_LIGHT_U, &light_u, &light_v);
- float terminate = path_state_rng_light_termination(kg, state);
-
- LightSample ls;
- if(light_sample(kg,
- light_u, light_v,
- sd->time,
- sd->P,
- state->bounce,
- &ls)) {
-
- Ray light_ray;
- light_ray.time = sd->time;
-
- BsdfEval L_light;
- bool is_lamp;
- if(direct_emission(kg,
- sd,
- AS_SHADER_DATA(&kernel_split_state.sd_DL_shadow[ray_index]),
- &ls,
- state,
- &light_ray,
- &L_light,
- &is_lamp,
- terminate))
- {
- /* Write intermediate data to global memory to access from
- * the next kernel.
- */
- kernel_split_state.light_ray[ray_index] = light_ray;
- 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. */
- enqueue_flag = 1;
- }
- }
- }
-#endif /* __EMISSION__ */
- }
+ if (flag && state->flag & PATH_RAY_SHADOW_CATCHER) {
+ flag = false;
+ enqueue_flag = 1;
+ }
+# endif /* __SHADOW_TRICKS__ */
+
+ if (flag) {
+ /* Sample illumination from lights to find path contribution. */
+ float light_u, light_v;
+ path_state_rng_2D(kg, state, PRNG_LIGHT_U, &light_u, &light_v);
+ float terminate = path_state_rng_light_termination(kg, state);
+
+ LightSample ls;
+ if (light_sample(kg, light_u, light_v, sd->time, sd->P, state->bounce, &ls)) {
+
+ Ray light_ray;
+ light_ray.time = sd->time;
+
+ BsdfEval L_light;
+ bool is_lamp;
+ if (direct_emission(kg,
+ sd,
+ AS_SHADER_DATA(&kernel_split_state.sd_DL_shadow[ray_index]),
+ &ls,
+ state,
+ &light_ray,
+ &L_light,
+ &is_lamp,
+ terminate)) {
+ /* Write intermediate data to global memory to access from
+ * the next kernel.
+ */
+ kernel_split_state.light_ray[ray_index] = light_ray;
+ 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. */
+ enqueue_flag = 1;
+ }
+ }
+ }
+#endif /* __EMISSION__ */
+ }
#ifdef __EMISSION__
- /* Enqueue RAY_SHADOW_RAY_CAST_DL rays. */
- enqueue_ray_index_local(ray_index,
- QUEUE_SHADOW_RAY_CAST_DL_RAYS,
- enqueue_flag,
- kernel_split_params.queue_size,
- local_queue_atomics,
- kernel_split_state.queue_data,
- kernel_split_params.queue_index);
+ /* Enqueue RAY_SHADOW_RAY_CAST_DL rays. */
+ enqueue_ray_index_local(ray_index,
+ QUEUE_SHADOW_RAY_CAST_DL_RAYS,
+ enqueue_flag,
+ kernel_split_params.queue_size,
+ local_queue_atomics,
+ 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__ */
+ /* 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 fb5bd3d48dd..45b839db05f 100644
--- a/intern/cycles/kernel/split/kernel_do_volume.h
+++ b/intern/cycles/kernel/split/kernel_do_volume.h
@@ -18,203 +18,210 @@ 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)
+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);
+ kernel_split_branched_path_indirect_loop_init(kg, ray_index);
- ADD_RAY_FLAG(kernel_split_state.ray_state, ray_index, RAY_BRANCHED_VOLUME_INDIRECT);
+ 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)
+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];
+ SplitBranchedState *branched_state = &kernel_split_state.branched_state[ray_index];
- ShaderData *sd = kernel_split_sd(sd, ray_index);
- PathRadiance *L = &kernel_split_state.path_radiance[ray_index];
- ShaderData *emission_sd = AS_SHADER_DATA(&kernel_split_state.sd_DL_shadow[ray_index]);
+ ShaderData *sd = kernel_split_sd(sd, ray_index);
+ PathRadiance *L = &kernel_split_state.path_radiance[ray_index];
+ ShaderData *emission_sd = AS_SHADER_DATA(&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;
+ /* 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;
+ 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);
+ 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;
+ 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 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;
+ 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);
+ /* 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, heterogeneous);
+ /* integrate along volume segment with distance sampling */
+ VolumeIntegrateResult result = kernel_volume_integrate(
+ kg, ps, sd, &volume_ray, L, tp, heterogeneous);
# ifdef __VOLUME_SCATTER__
- if(result == VOLUME_PATH_SCATTERED) {
- /* direct lighting */
- kernel_path_volume_connect_light(kg, sd, emission_sd, *tp, &branched_state->path_state, L);
-
- /* indirect light bounce */
- if(!kernel_path_volume_bounce(kg, sd, tp, ps, &L->state, pray)) {
- continue;
- }
-
- /* start the indirect path */
- branched_state->next_closure = 0;
- branched_state->next_sample = j+1;
-
- /* Attempting to share too many samples is slow for volumes as it causes us to
- * loop here more and have many calls to kernel_volume_integrate which evaluates
- * shaders. The many expensive shader evaluations cause the work load to become
- * unbalanced and many threads to become idle in this kernel. Limiting the
- * number of shared samples here helps quite a lot.
- */
- if(branched_state->shared_sample_count < 2) {
- if(kernel_split_branched_indirect_start_shared(kg, ray_index)) {
- continue;
- }
- }
-
- return true;
- }
+ if (result == VOLUME_PATH_SCATTERED) {
+ /* direct lighting */
+ kernel_path_volume_connect_light(kg, sd, emission_sd, *tp, &branched_state->path_state, L);
+
+ /* indirect light bounce */
+ if (!kernel_path_volume_bounce(kg, sd, tp, ps, &L->state, pray)) {
+ continue;
+ }
+
+ /* start the indirect path */
+ branched_state->next_closure = 0;
+ branched_state->next_sample = j + 1;
+
+ /* Attempting to share too many samples is slow for volumes as it causes us to
+ * loop here more and have many calls to kernel_volume_integrate which evaluates
+ * shaders. The many expensive shader evaluations cause the work load to become
+ * unbalanced and many threads to become idle in this kernel. Limiting the
+ * number of shared samples here helps quite a lot.
+ */
+ if (branched_state->shared_sample_count < 2) {
+ if (kernel_split_branched_indirect_start_shared(kg, ray_index)) {
+ continue;
+ }
+ }
+
+ return true;
+ }
# endif
- }
+ }
- branched_state->next_sample = num_samples;
+ branched_state->next_sample = num_samples;
- branched_state->waiting_on_shared_samples = (branched_state->shared_sample_count > 0);
- if(branched_state->waiting_on_shared_samples) {
- return true;
- }
+ branched_state->waiting_on_shared_samples = (branched_state->shared_sample_count > 0);
+ if (branched_state->waiting_on_shared_samples) {
+ return true;
+ }
- kernel_split_branched_path_indirect_loop_end(kg, ray_index);
+ 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;
+ /* 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;
+ return false;
}
-#endif /* __BRANCHED_PATH__ && __VOLUME__ */
+#endif /* __BRANCHED_PATH__ && __VOLUME__ */
ccl_device void kernel_do_volume(KernelGlobals *kg)
{
#ifdef __VOLUME__
- /* 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;
+ /* 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__ */
- }
-
- int ray_index = ccl_global_id(1) * ccl_global_size(0) + ccl_global_id(0);
-
- 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);
- }
-
- ccl_global char *ray_state = kernel_split_state.ray_state;
-
- PathRadiance *L = &kernel_split_state.path_radiance[ray_index];
- ccl_global PathState *state = &kernel_split_state.path_state[ray_index];
-
- if(IS_STATE(ray_state, ray_index, RAY_ACTIVE) ||
- IS_STATE(ray_state, ray_index, RAY_HIT_BACKGROUND)) {
- ccl_global float3 *throughput = &kernel_split_state.throughput[ray_index];
- ccl_global Ray *ray = &kernel_split_state.ray[ray_index];
- ccl_global Intersection *isect = &kernel_split_state.isect[ray_index];
- ShaderData *sd = kernel_split_sd(sd, ray_index);
- ShaderData *emission_sd = AS_SHADER_DATA(&kernel_split_state.sd_DL_shadow[ray_index]);
-
- bool hit = ! IS_STATE(ray_state, ray_index, RAY_HIT_BACKGROUND);
-
- /* Sanitize volume stack. */
- if(!hit) {
- kernel_volume_clean_stack(kg, state->volume_stack);
- }
- /* volume attenuation, emission, scatter */
- if(state->volume_stack[0].shader != SHADER_NONE) {
- Ray volume_ray = *ray;
- volume_ray.t = (hit)? isect->t: FLT_MAX;
+ kernel_split_params.queue_index[QUEUE_VOLUME_INDIRECT_ITER] = 0;
+# endif /* __BRANCHED_PATH__ */
+ }
+
+ int ray_index = ccl_global_id(1) * ccl_global_size(0) + ccl_global_id(0);
+
+ 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);
+ }
+
+ ccl_global char *ray_state = kernel_split_state.ray_state;
+
+ PathRadiance *L = &kernel_split_state.path_radiance[ray_index];
+ ccl_global PathState *state = &kernel_split_state.path_state[ray_index];
+
+ if (IS_STATE(ray_state, ray_index, RAY_ACTIVE) ||
+ IS_STATE(ray_state, ray_index, RAY_HIT_BACKGROUND)) {
+ ccl_global float3 *throughput = &kernel_split_state.throughput[ray_index];
+ ccl_global Ray *ray = &kernel_split_state.ray[ray_index];
+ ccl_global Intersection *isect = &kernel_split_state.isect[ray_index];
+ ShaderData *sd = kernel_split_sd(sd, ray_index);
+ ShaderData *emission_sd = AS_SHADER_DATA(&kernel_split_state.sd_DL_shadow[ray_index]);
+
+ bool hit = !IS_STATE(ray_state, ray_index, RAY_HIT_BACKGROUND);
+
+ /* Sanitize volume stack. */
+ if (!hit) {
+ kernel_volume_clean_stack(kg, state->volume_stack);
+ }
+ /* volume attenuation, emission, scatter */
+ if (state->volume_stack[0].shader != SHADER_NONE) {
+ Ray volume_ray = *ray;
+ volume_ray.t = (hit) ? isect->t : FLT_MAX;
# 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);
+ 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, heterogeneous);
+ {
+ /* integrate along volume segment with distance sampling */
+ VolumeIntegrateResult result = kernel_volume_integrate(
+ kg, state, sd, &volume_ray, L, throughput, heterogeneous);
# ifdef __VOLUME_SCATTER__
- if(result == VOLUME_PATH_SCATTERED) {
- /* direct lighting */
- kernel_path_volume_connect_light(kg, sd, emission_sd, *throughput, state, L);
-
- /* indirect light bounce */
- if(kernel_path_volume_bounce(kg, sd, throughput, state, &L->state, ray)) {
- ASSIGN_RAY_STATE(ray_state, ray_index, RAY_REGENERATED);
- }
- else {
- kernel_split_path_end(kg, ray_index);
- }
- }
-# endif /* __VOLUME_SCATTER__ */
- }
+ if (result == VOLUME_PATH_SCATTERED) {
+ /* direct lighting */
+ kernel_path_volume_connect_light(kg, sd, emission_sd, *throughput, state, L);
+
+ /* indirect light bounce */
+ if (kernel_path_volume_bounce(kg, sd, throughput, state, &L->state, 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 /* __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 /* __BRANCHED_PATH__ */
+ }
+ }
# 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__ */
+ /* 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__ */
}
-
CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/split/kernel_enqueue_inactive.h b/intern/cycles/kernel/split/kernel_enqueue_inactive.h
index 496355bbc3a..31d2daef616 100644
--- a/intern/cycles/kernel/split/kernel_enqueue_inactive.h
+++ b/intern/cycles/kernel/split/kernel_enqueue_inactive.h
@@ -20,27 +20,27 @@ ccl_device void kernel_enqueue_inactive(KernelGlobals *kg,
ccl_local_param unsigned int *local_queue_atomics)
{
#ifdef __BRANCHED_PATH__
- /* Enqeueue RAY_INACTIVE rays into QUEUE_INACTIVE_RAYS queue. */
- if(ccl_local_id(0) == 0 && ccl_local_id(1) == 0) {
- *local_queue_atomics = 0;
- }
- ccl_barrier(CCL_LOCAL_MEM_FENCE);
+ /* Enqeueue RAY_INACTIVE rays into QUEUE_INACTIVE_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 ray_index = ccl_global_id(1) * ccl_global_size(0) + ccl_global_id(0);
- char enqueue_flag = 0;
- if(IS_STATE(kernel_split_state.ray_state, ray_index, RAY_INACTIVE)) {
- enqueue_flag = 1;
- }
+ char enqueue_flag = 0;
+ if (IS_STATE(kernel_split_state.ray_state, ray_index, RAY_INACTIVE)) {
+ enqueue_flag = 1;
+ }
- enqueue_ray_index_local(ray_index,
- QUEUE_INACTIVE_RAYS,
- enqueue_flag,
- kernel_split_params.queue_size,
- local_queue_atomics,
- kernel_split_state.queue_data,
- kernel_split_params.queue_index);
-#endif /* __BRANCHED_PATH__ */
+ enqueue_ray_index_local(ray_index,
+ QUEUE_INACTIVE_RAYS,
+ enqueue_flag,
+ 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_holdout_emission_blurring_pathtermination_ao.h b/intern/cycles/kernel/split/kernel_holdout_emission_blurring_pathtermination_ao.h
index f14eecec2f2..63bc5a8e0ce 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
@@ -54,120 +54,112 @@ CCL_NAMESPACE_BEGIN
*/
ccl_device void kernel_holdout_emission_blurring_pathtermination_ao(
- KernelGlobals *kg,
- ccl_local_param BackgroundAOLocals *locals)
+ KernelGlobals *kg, ccl_local_param BackgroundAOLocals *locals)
{
- if(ccl_local_id(0) == 0 && ccl_local_id(1) == 0) {
- locals->queue_atomics_bg = 0;
- locals->queue_atomics_ao = 0;
- }
- ccl_barrier(CCL_LOCAL_MEM_FENCE);
+ if (ccl_local_id(0) == 0 && ccl_local_id(1) == 0) {
+ locals->queue_atomics_bg = 0;
+ locals->queue_atomics_ao = 0;
+ }
+ ccl_barrier(CCL_LOCAL_MEM_FENCE);
#ifdef __AO__
- char enqueue_flag = 0;
+ char enqueue_flag = 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,
- kernel_split_state.queue_data,
- kernel_split_params.queue_size,
- 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,
+ 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 /* __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 /* __COMPUTE_DEVICE_GPU__ */
#ifndef __COMPUTE_DEVICE_GPU__
- if(ray_index != QUEUE_EMPTY_SLOT) {
+ if (ray_index != QUEUE_EMPTY_SLOT) {
#endif
- ccl_global PathState *state = 0x0;
- float3 throughput;
-
- ccl_global char *ray_state = kernel_split_state.ray_state;
- ShaderData *sd = kernel_split_sd(sd, ray_index);
-
- if(IS_STATE(ray_state, ray_index, RAY_ACTIVE)) {
- uint buffer_offset = kernel_split_state.buffer_offset[ray_index];
- ccl_global float *buffer = kernel_split_params.tile.buffer + buffer_offset;
-
- ccl_global Ray *ray = &kernel_split_state.ray[ray_index];
- ShaderData *emission_sd = AS_SHADER_DATA(&kernel_split_state.sd_DL_shadow[ray_index]);
- PathRadiance *L = &kernel_split_state.path_radiance[ray_index];
-
- throughput = kernel_split_state.throughput[ray_index];
- state = &kernel_split_state.path_state[ray_index];
-
- if(!kernel_path_shader_apply(kg,
- sd,
- state,
- ray,
- throughput,
- emission_sd,
- L,
- buffer))
- {
- kernel_split_path_end(kg, ray_index);
- }
- }
-
- if(IS_STATE(ray_state, ray_index, RAY_ACTIVE)) {
- /* Path termination. this is a strange place to put the termination, it's
- * 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.
- */
- float probability = path_state_continuation_probability(kg, state, throughput);
-
- if(probability == 0.0f) {
- kernel_split_path_end(kg, ray_index);
- }
- else if(probability < 1.0f) {
- float terminate = path_state_rng_1D(kg, state, PRNG_TERMINATE);
- if(terminate >= probability) {
- kernel_split_path_end(kg, ray_index);
- }
- else {
- kernel_split_state.throughput[ray_index] = throughput/probability;
- }
- }
-
- if(IS_STATE(ray_state, ray_index, RAY_ACTIVE)) {
- PathRadiance *L = &kernel_split_state.path_radiance[ray_index];
- kernel_update_denoising_features(kg, sd, state, L);
- }
- }
+ ccl_global PathState *state = 0x0;
+ float3 throughput;
+
+ ccl_global char *ray_state = kernel_split_state.ray_state;
+ ShaderData *sd = kernel_split_sd(sd, ray_index);
+
+ if (IS_STATE(ray_state, ray_index, RAY_ACTIVE)) {
+ uint buffer_offset = kernel_split_state.buffer_offset[ray_index];
+ ccl_global float *buffer = kernel_split_params.tile.buffer + buffer_offset;
+
+ ccl_global Ray *ray = &kernel_split_state.ray[ray_index];
+ ShaderData *emission_sd = AS_SHADER_DATA(&kernel_split_state.sd_DL_shadow[ray_index]);
+ PathRadiance *L = &kernel_split_state.path_radiance[ray_index];
+
+ throughput = kernel_split_state.throughput[ray_index];
+ state = &kernel_split_state.path_state[ray_index];
+
+ if (!kernel_path_shader_apply(kg, sd, state, ray, throughput, emission_sd, L, buffer)) {
+ kernel_split_path_end(kg, ray_index);
+ }
+ }
+
+ if (IS_STATE(ray_state, ray_index, RAY_ACTIVE)) {
+ /* Path termination. this is a strange place to put the termination, it's
+ * 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.
+ */
+ float probability = path_state_continuation_probability(kg, state, throughput);
+
+ if (probability == 0.0f) {
+ kernel_split_path_end(kg, ray_index);
+ }
+ else if (probability < 1.0f) {
+ float terminate = path_state_rng_1D(kg, state, PRNG_TERMINATE);
+ if (terminate >= probability) {
+ kernel_split_path_end(kg, ray_index);
+ }
+ else {
+ kernel_split_state.throughput[ray_index] = throughput / probability;
+ }
+ }
+
+ if (IS_STATE(ray_state, ray_index, RAY_ACTIVE)) {
+ PathRadiance *L = &kernel_split_state.path_radiance[ray_index];
+ kernel_update_denoising_features(kg, sd, state, L);
+ }
+ }
#ifdef __AO__
- if(IS_STATE(ray_state, ray_index, RAY_ACTIVE)) {
- /* ambient occlusion */
- if(kernel_data.integrator.use_ambient_occlusion) {
- enqueue_flag = 1;
- }
- }
-#endif /* __AO__ */
+ if (IS_STATE(ray_state, ray_index, RAY_ACTIVE)) {
+ /* ambient occlusion */
+ if (kernel_data.integrator.use_ambient_occlusion) {
+ enqueue_flag = 1;
+ }
+ }
+#endif /* __AO__ */
#ifndef __COMPUTE_DEVICE_GPU__
- }
+ }
#endif
#ifdef __AO__
- /* Enqueue to-shadow-ray-cast rays. */
- enqueue_ray_index_local(ray_index,
- QUEUE_SHADOW_RAY_CAST_AO_RAYS,
- enqueue_flag,
- kernel_split_params.queue_size,
- &locals->queue_atomics_ao,
- kernel_split_state.queue_data,
- kernel_split_params.queue_index);
+ /* Enqueue to-shadow-ray-cast rays. */
+ enqueue_ray_index_local(ray_index,
+ QUEUE_SHADOW_RAY_CAST_AO_RAYS,
+ enqueue_flag,
+ kernel_split_params.queue_size,
+ &locals->queue_atomics_ao,
+ kernel_split_state.queue_data,
+ kernel_split_params.queue_index);
#endif
}
diff --git a/intern/cycles/kernel/split/kernel_indirect_background.h b/intern/cycles/kernel/split/kernel_indirect_background.h
index 4cf88a02590..b1c65f61e2c 100644
--- a/intern/cycles/kernel/split/kernel_indirect_background.h
+++ b/intern/cycles/kernel/split/kernel_indirect_background.h
@@ -18,48 +18,50 @@ CCL_NAMESPACE_BEGIN
ccl_device void kernel_indirect_background(KernelGlobals *kg)
{
- ccl_global char *ray_state = kernel_split_state.ray_state;
+ ccl_global char *ray_state = kernel_split_state.ray_state;
- int thread_index = ccl_global_id(1) * ccl_global_size(0) + ccl_global_id(0);
- int ray_index;
+ int thread_index = ccl_global_id(1) * ccl_global_size(0) + ccl_global_id(0);
+ int ray_index;
- if(kernel_data.integrator.ao_bounces != INT_MAX) {
- ray_index = get_ray_index(kg, thread_index,
- QUEUE_ACTIVE_AND_REGENERATED_RAYS,
- kernel_split_state.queue_data,
- kernel_split_params.queue_size,
- 0);
+ if (kernel_data.integrator.ao_bounces != INT_MAX) {
+ ray_index = get_ray_index(kg,
+ thread_index,
+ QUEUE_ACTIVE_AND_REGENERATED_RAYS,
+ kernel_split_state.queue_data,
+ kernel_split_params.queue_size,
+ 0);
- if(ray_index != QUEUE_EMPTY_SLOT) {
- if(IS_STATE(ray_state, ray_index, RAY_ACTIVE)) {
- ccl_global PathState *state = &kernel_split_state.path_state[ray_index];
- if(path_state_ao_bounce(kg, state)) {
- kernel_split_path_end(kg, ray_index);
- }
- }
- }
- }
+ if (ray_index != QUEUE_EMPTY_SLOT) {
+ if (IS_STATE(ray_state, ray_index, RAY_ACTIVE)) {
+ ccl_global PathState *state = &kernel_split_state.path_state[ray_index];
+ if (path_state_ao_bounce(kg, state)) {
+ kernel_split_path_end(kg, ray_index);
+ }
+ }
+ }
+ }
- ray_index = get_ray_index(kg, thread_index,
- QUEUE_HITBG_BUFF_UPDATE_TOREGEN_RAYS,
- kernel_split_state.queue_data,
- kernel_split_params.queue_size,
- 0);
+ ray_index = get_ray_index(kg,
+ thread_index,
+ QUEUE_HITBG_BUFF_UPDATE_TOREGEN_RAYS,
+ kernel_split_state.queue_data,
+ kernel_split_params.queue_size,
+ 0);
- if(ray_index == QUEUE_EMPTY_SLOT) {
- return;
- }
+ if (ray_index == QUEUE_EMPTY_SLOT) {
+ return;
+ }
- if(IS_STATE(ray_state, ray_index, RAY_HIT_BACKGROUND)) {
- ccl_global PathState *state = &kernel_split_state.path_state[ray_index];
- PathRadiance *L = &kernel_split_state.path_radiance[ray_index];
- ccl_global Ray *ray = &kernel_split_state.ray[ray_index];
- float3 throughput = kernel_split_state.throughput[ray_index];
- ShaderData *sd = kernel_split_sd(sd, ray_index);
+ if (IS_STATE(ray_state, ray_index, RAY_HIT_BACKGROUND)) {
+ ccl_global PathState *state = &kernel_split_state.path_state[ray_index];
+ PathRadiance *L = &kernel_split_state.path_radiance[ray_index];
+ ccl_global Ray *ray = &kernel_split_state.ray[ray_index];
+ float3 throughput = kernel_split_state.throughput[ray_index];
+ ShaderData *sd = kernel_split_sd(sd, ray_index);
- kernel_path_background(kg, state, ray, throughput, sd, L);
- kernel_split_path_end(kg, ray_index);
- }
+ kernel_path_background(kg, state, ray, throughput, sd, L);
+ kernel_split_path_end(kg, ray_index);
+ }
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/split/kernel_indirect_subsurface.h b/intern/cycles/kernel/split/kernel_indirect_subsurface.h
index 236c94e983c..3f48f8d6f56 100644
--- a/intern/cycles/kernel/split/kernel_indirect_subsurface.h
+++ b/intern/cycles/kernel/split/kernel_indirect_subsurface.h
@@ -18,53 +18,50 @@ CCL_NAMESPACE_BEGIN
ccl_device void kernel_indirect_subsurface(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;
- }
+ 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;
+ }
- int ray_index;
- get_ray_index(kg, thread_index,
- QUEUE_ACTIVE_AND_REGENERATED_RAYS,
- kernel_split_state.queue_data,
- kernel_split_params.queue_size,
- 1);
- ray_index = get_ray_index(kg, thread_index,
- QUEUE_HITBG_BUFF_UPDATE_TOREGEN_RAYS,
- kernel_split_state.queue_data,
- kernel_split_params.queue_size,
- 1);
+ int ray_index;
+ get_ray_index(kg,
+ thread_index,
+ QUEUE_ACTIVE_AND_REGENERATED_RAYS,
+ kernel_split_state.queue_data,
+ kernel_split_params.queue_size,
+ 1);
+ ray_index = 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__
- if(ray_index == QUEUE_EMPTY_SLOT) {
- return;
- }
+ if (ray_index == QUEUE_EMPTY_SLOT) {
+ return;
+ }
- 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];
- ccl_global Ray *ray = &kernel_split_state.ray[ray_index];
- ccl_global float3 *throughput = &kernel_split_state.throughput[ray_index];
+ 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];
+ 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];
+ if (IS_STATE(ray_state, ray_index, RAY_UPDATE_BUFFER)) {
+ ccl_addr_space SubsurfaceIndirectRays *ss_indirect = &kernel_split_state.ss_rays[ray_index];
- /* 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);
- }
- }
-#endif /* __SUBSURFACE__ */
+ /* 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);
+ }
+ }
+#endif /* __SUBSURFACE__ */
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/split/kernel_lamp_emission.h b/intern/cycles/kernel/split/kernel_lamp_emission.h
index 5b2c554b922..7ecb099208d 100644
--- a/intern/cycles/kernel/split/kernel_lamp_emission.h
+++ b/intern/cycles/kernel/split/kernel_lamp_emission.h
@@ -23,45 +23,45 @@ CCL_NAMESPACE_BEGIN
ccl_device void kernel_lamp_emission(KernelGlobals *kg)
{
#ifndef __VOLUME__
- /* 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;
- }
+ /* 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;
+ }
#endif
- /* Fetch use_queues_flag. */
- char local_use_queues_flag = *kernel_split_params.use_queues_flag;
- ccl_barrier(CCL_LOCAL_MEM_FENCE);
+ /* 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) {
- ray_index = get_ray_index(kg, ray_index,
- QUEUE_ACTIVE_AND_REGENERATED_RAYS,
- kernel_split_state.queue_data,
- kernel_split_params.queue_size,
+ int ray_index = ccl_global_id(1) * ccl_global_size(0) + ccl_global_id(0);
+ if (local_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,
#ifndef __VOLUME__
- 1
+ 1
#else
- 0
+ 0
#endif
- );
- if(ray_index == QUEUE_EMPTY_SLOT) {
- return;
- }
- }
+ );
+ 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))
- {
- PathRadiance *L = &kernel_split_state.path_radiance[ray_index];
- ccl_global PathState *state = &kernel_split_state.path_state[ray_index];
+ if (IS_STATE(kernel_split_state.ray_state, ray_index, RAY_ACTIVE) ||
+ 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];
- float3 throughput = kernel_split_state.throughput[ray_index];
- Ray ray = kernel_split_state.ray[ray_index];
- ccl_global Intersection *isect = &kernel_split_state.isect[ray_index];
- ShaderData *sd = kernel_split_sd(sd, ray_index);
+ float3 throughput = kernel_split_state.throughput[ray_index];
+ Ray ray = kernel_split_state.ray[ray_index];
+ ccl_global Intersection *isect = &kernel_split_state.isect[ray_index];
+ ShaderData *sd = kernel_split_sd(sd, ray_index);
- kernel_path_lamp_emission(kg, state, &ray, throughput, isect, sd, L);
- }
+ kernel_path_lamp_emission(kg, state, &ray, throughput, isect, sd, L);
+ }
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/split/kernel_next_iteration_setup.h b/intern/cycles/kernel/split/kernel_next_iteration_setup.h
index e388955f1af..781ce869374 100644
--- a/intern/cycles/kernel/split/kernel_next_iteration_setup.h
+++ b/intern/cycles/kernel/split/kernel_next_iteration_setup.h
@@ -48,217 +48,211 @@ CCL_NAMESPACE_BEGIN
#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);
+ kernel_split_branched_path_indirect_loop_init(kg, ray_index);
- ADD_RAY_FLAG(kernel_split_state.ray_state, ray_index, RAY_BRANCHED_LIGHT_INDIRECT);
+ ADD_RAY_FLAG(kernel_split_state.ray_state, ray_index, RAY_BRANCHED_LIGHT_INDIRECT);
}
ccl_device void kernel_split_branched_transparent_bounce(KernelGlobals *kg, int ray_index)
{
- ccl_global float3 *throughput = &kernel_split_state.throughput[ray_index];
- ShaderData *sd = kernel_split_sd(sd, ray_index);
- ccl_global PathState *state = &kernel_split_state.path_state[ray_index];
- ccl_global Ray *ray = &kernel_split_state.ray[ray_index];
+ ccl_global float3 *throughput = &kernel_split_state.throughput[ray_index];
+ ShaderData *sd = kernel_split_sd(sd, ray_index);
+ ccl_global PathState *state = &kernel_split_state.path_state[ray_index];
+ ccl_global Ray *ray = &kernel_split_state.ray[ray_index];
# ifdef __VOLUME__
- if(!(sd->flag & SD_HAS_ONLY_VOLUME)) {
+ if (!(sd->flag & SD_HAS_ONLY_VOLUME)) {
# endif
- /* continue in case of transparency */
- *throughput *= shader_bsdf_transparency(kg, sd);
+ /* continue in case of transparency */
+ *throughput *= shader_bsdf_transparency(kg, sd);
- if(is_zero(*throughput)) {
- kernel_split_path_end(kg, ray_index);
- return;
- }
+ if (is_zero(*throughput)) {
+ kernel_split_path_end(kg, ray_index);
+ return;
+ }
- /* Update Path State */
- path_state_next(kg, state, LABEL_TRANSPARENT);
+ /* Update Path State */
+ path_state_next(kg, state, LABEL_TRANSPARENT);
# ifdef __VOLUME__
- }
- else {
- if(!path_state_volume_next(kg, state)) {
- kernel_split_path_end(kg, ray_index);
- return;
- }
- }
+ }
+ else {
+ if (!path_state_volume_next(kg, state)) {
+ kernel_split_path_end(kg, ray_index);
+ return;
+ }
+ }
# endif
- ray->P = ray_offset(sd->P, -sd->Ng);
- ray->t -= sd->ray_length; /* clipping works through transparent */
+ 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__ */
+ 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__ */
+ /* enter/exit volume */
+ kernel_volume_stack_enter_exit(kg, sd, state->volume_stack);
+# endif /* __VOLUME__ */
}
-#endif /* __BRANCHED_PATH__ */
+#endif /* __BRANCHED_PATH__ */
ccl_device void kernel_next_iteration_setup(KernelGlobals *kg,
ccl_local_param unsigned int *local_queue_atomics)
{
- if(ccl_local_id(0) == 0 && ccl_local_id(1) == 0) {
- *local_queue_atomics = 0;
- }
- ccl_barrier(CCL_LOCAL_MEM_FENCE);
-
- if(ccl_global_id(0) == 0 && ccl_global_id(1) == 0) {
- /* If we are here, then it means that scene-intersect kernel
- * has already been executed atleast once. From the next time,
- * scene-intersect kernel may operate on queues to fetch ray index
- */
- *kernel_split_params.use_queues_flag = 1;
-
- /* Mark queue indices of QUEUE_SHADOW_RAY_CAST_AO_RAYS and
- * QUEUE_SHADOW_RAY_CAST_DL_RAYS queues that were made empty during the
- * previous kernel.
- */
- kernel_split_params.queue_index[QUEUE_SHADOW_RAY_CAST_AO_RAYS] = 0;
- kernel_split_params.queue_index[QUEUE_SHADOW_RAY_CAST_DL_RAYS] = 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,
- kernel_split_state.queue_data,
- kernel_split_params.queue_size,
- 0);
-
- ccl_global char *ray_state = kernel_split_state.ray_state;
-
-# ifdef __VOLUME__
- /* Reactivate only volume rays here, most surface work was skipped. */
- if(IS_STATE(ray_state, ray_index, RAY_HAS_ONLY_VOLUME)) {
- ASSIGN_RAY_STATE(ray_state, ray_index, RAY_ACTIVE);
- }
-# endif
+ if (ccl_local_id(0) == 0 && ccl_local_id(1) == 0) {
+ *local_queue_atomics = 0;
+ }
+ ccl_barrier(CCL_LOCAL_MEM_FENCE);
+
+ if (ccl_global_id(0) == 0 && ccl_global_id(1) == 0) {
+ /* If we are here, then it means that scene-intersect kernel
+ * has already been executed atleast once. From the next time,
+ * scene-intersect kernel may operate on queues to fetch ray index
+ */
+ *kernel_split_params.use_queues_flag = 1;
+
+ /* Mark queue indices of QUEUE_SHADOW_RAY_CAST_AO_RAYS and
+ * QUEUE_SHADOW_RAY_CAST_DL_RAYS queues that were made empty during the
+ * previous kernel.
+ */
+ kernel_split_params.queue_index[QUEUE_SHADOW_RAY_CAST_AO_RAYS] = 0;
+ kernel_split_params.queue_index[QUEUE_SHADOW_RAY_CAST_DL_RAYS] = 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,
+ kernel_split_state.queue_data,
+ kernel_split_params.queue_size,
+ 0);
+
+ ccl_global char *ray_state = kernel_split_state.ray_state;
+
+#ifdef __VOLUME__
+ /* Reactivate only volume rays here, most surface work was skipped. */
+ if (IS_STATE(ray_state, ray_index, RAY_HAS_ONLY_VOLUME)) {
+ ASSIGN_RAY_STATE(ray_state, ray_index, RAY_ACTIVE);
+ }
+#endif
- 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];
- ShaderData *sd = kernel_split_sd(sd, ray_index);
- ccl_global PathState *state = &kernel_split_state.path_state[ray_index];
- PathRadiance *L = &kernel_split_state.path_radiance[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];
+ ShaderData *sd = kernel_split_sd(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)) {
+ 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, sd, throughput, state, &L->state, ray)) {
- kernel_split_path_end(kg, ray_index);
- }
+ /* Compute direct lighting and next bounce. */
+ if (!kernel_path_surface_bounce(kg, sd, throughput, state, &L->state, ray)) {
+ kernel_split_path_end(kg, ray_index);
+ }
#ifdef __BRANCHED_PATH__
- }
- else if(sd->flag & SD_HAS_ONLY_VOLUME) {
- kernel_split_branched_transparent_bounce(kg, 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_sd(branched_state_sd, ray_index),
- true,
- true))
- {
- ASSIGN_RAY_STATE(ray_state, ray_index, RAY_REGENERATED);
- }
- else {
- kernel_split_branched_path_indirect_loop_end(kg, ray_index);
- kernel_split_branched_transparent_bounce(kg, ray_index);
- }
- }
-#endif /* __BRANCHED_PATH__ */
- }
-
- /* 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);
+ }
+ else if (sd->flag & SD_HAS_ONLY_VOLUME) {
+ kernel_split_branched_transparent_bounce(kg, 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_sd(branched_state_sd, ray_index), true, true)) {
+ ASSIGN_RAY_STATE(ray_state, ray_index, RAY_REGENERATED);
+ }
+ else {
+ kernel_split_branched_path_indirect_loop_end(kg, ray_index);
+ kernel_split_branched_transparent_bounce(kg, ray_index);
+ }
+ }
+#endif /* __BRANCHED_PATH__ */
+ }
+
+ /* 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;
- }
-
- 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_sd(branched_state_sd, ray_index),
- true,
- true))
- {
- ASSIGN_RAY_STATE(ray_state, ray_index, RAY_REGENERATED);
- }
- else {
- kernel_split_branched_path_indirect_loop_end(kg, ray_index);
- kernel_split_branched_transparent_bounce(kg, ray_index);
- }
- }
+ /* iter loop */
+ if (ccl_global_id(0) == 0 && ccl_global_id(1) == 0) {
+ kernel_split_params.queue_index[QUEUE_LIGHT_INDIRECT_ITER] = 0;
+ }
+
+ 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_sd(branched_state_sd, ray_index), true, true)) {
+ ASSIGN_RAY_STATE(ray_state, ray_index, RAY_REGENERATED);
+ }
+ else {
+ kernel_split_branched_path_indirect_loop_end(kg, ray_index);
+ kernel_split_branched_transparent_bounce(kg, ray_index);
+ }
+ }
# 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;
- }
- 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_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__ */
+ /* 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;
+ }
+ 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_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__ */
+ /* 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_path_init.h b/intern/cycles/kernel/split/kernel_path_init.h
index fdd54225b07..3faa3208341 100644
--- a/intern/cycles/kernel/split/kernel_path_init.h
+++ b/intern/cycles/kernel/split/kernel_path_init.h
@@ -21,61 +21,59 @@ CCL_NAMESPACE_BEGIN
*
* Ray state of rays outside the tile-boundary will be marked RAY_INACTIVE
*/
-ccl_device void kernel_path_init(KernelGlobals *kg) {
- int ray_index = ccl_global_id(0) + ccl_global_id(1) * ccl_global_size(0);
+ccl_device void kernel_path_init(KernelGlobals *kg)
+{
+ int ray_index = ccl_global_id(0) + ccl_global_id(1) * ccl_global_size(0);
- /* This is the first assignment to ray_state;
- * So we dont use ASSIGN_RAY_STATE macro.
- */
- kernel_split_state.ray_state[ray_index] = RAY_ACTIVE;
+ /* This is the first assignment to ray_state;
+ * So we dont use ASSIGN_RAY_STATE macro.
+ */
+ kernel_split_state.ray_state[ray_index] = RAY_ACTIVE;
- /* Get work. */
- ccl_global uint *work_pools = kernel_split_params.work_pools;
- uint total_work_size = kernel_split_params.total_work_size;
- uint work_index;
+ /* Get work. */
+ ccl_global uint *work_pools = kernel_split_params.work_pools;
+ uint total_work_size = kernel_split_params.total_work_size;
+ uint work_index;
- if(!get_next_work(kg, work_pools, total_work_size, ray_index, &work_index)) {
- /* No more work, mark ray as inactive */
- kernel_split_state.ray_state[ray_index] = RAY_INACTIVE;
+ if (!get_next_work(kg, work_pools, total_work_size, ray_index, &work_index)) {
+ /* No more work, mark ray as inactive */
+ kernel_split_state.ray_state[ray_index] = RAY_INACTIVE;
- return;
- }
+ return;
+ }
- ccl_global WorkTile *tile = &kernel_split_params.tile;
- uint x, y, sample;
- get_work_pixel(tile, work_index, &x, &y, &sample);
+ ccl_global WorkTile *tile = &kernel_split_params.tile;
+ uint x, y, sample;
+ get_work_pixel(tile, work_index, &x, &y, &sample);
- /* Store buffer offset for writing to passes. */
- uint buffer_offset = (tile->offset + x + y*tile->stride) * kernel_data.film.pass_stride;
- kernel_split_state.buffer_offset[ray_index] = buffer_offset;
+ /* Store buffer offset for writing to passes. */
+ uint buffer_offset = (tile->offset + x + y * tile->stride) * kernel_data.film.pass_stride;
+ kernel_split_state.buffer_offset[ray_index] = buffer_offset;
- /* Initialize random numbers and ray. */
- uint rng_hash;
- kernel_path_trace_setup(kg,
- sample,
- x, y,
- &rng_hash,
- &kernel_split_state.ray[ray_index]);
+ /* Initialize random numbers and ray. */
+ uint rng_hash;
+ kernel_path_trace_setup(kg, sample, x, y, &rng_hash, &kernel_split_state.ray[ray_index]);
- if(kernel_split_state.ray[ray_index].t != 0.0f) {
- /* Initialize throughput, path radiance, Ray, PathState;
- * These rays proceed with path-iteration.
- */
- kernel_split_state.throughput[ray_index] = make_float3(1.0f, 1.0f, 1.0f);
- path_radiance_init(&kernel_split_state.path_radiance[ray_index], kernel_data.film.use_light_pass);
- path_state_init(kg,
- AS_SHADER_DATA(&kernel_split_state.sd_DL_shadow[ray_index]),
- &kernel_split_state.path_state[ray_index],
- rng_hash,
- sample,
- &kernel_split_state.ray[ray_index]);
+ if (kernel_split_state.ray[ray_index].t != 0.0f) {
+ /* Initialize throughput, path radiance, Ray, PathState;
+ * These rays proceed with path-iteration.
+ */
+ kernel_split_state.throughput[ray_index] = make_float3(1.0f, 1.0f, 1.0f);
+ path_radiance_init(&kernel_split_state.path_radiance[ray_index],
+ kernel_data.film.use_light_pass);
+ path_state_init(kg,
+ AS_SHADER_DATA(&kernel_split_state.sd_DL_shadow[ray_index]),
+ &kernel_split_state.path_state[ray_index],
+ rng_hash,
+ sample,
+ &kernel_split_state.ray[ray_index]);
#ifdef __SUBSURFACE__
- kernel_path_subsurface_init_indirect(&kernel_split_state.ss_rays[ray_index]);
+ kernel_path_subsurface_init_indirect(&kernel_split_state.ss_rays[ray_index]);
#endif
- }
- else {
- ASSIGN_RAY_STATE(kernel_split_state.ray_state, ray_index, RAY_TO_REGENERATE);
- }
+ }
+ else {
+ ASSIGN_RAY_STATE(kernel_split_state.ray_state, ray_index, RAY_TO_REGENERATE);
+ }
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/split/kernel_queue_enqueue.h b/intern/cycles/kernel/split/kernel_queue_enqueue.h
index df67fabab19..2db87f7a671 100644
--- a/intern/cycles/kernel/split/kernel_queue_enqueue.h
+++ b/intern/cycles/kernel/split/kernel_queue_enqueue.h
@@ -35,58 +35,53 @@ CCL_NAMESPACE_BEGIN
* - QUEUE_HITBG_BUFF_UPDATE_TOREGEN_RAYS will be filled with
* RAY_TO_REGENERATE, RAY_UPDATE_BUFFER, RAY_HIT_BACKGROUND rays.
*/
-ccl_device void kernel_queue_enqueue(KernelGlobals *kg,
- ccl_local_param QueueEnqueueLocals *locals)
+ccl_device void kernel_queue_enqueue(KernelGlobals *kg, ccl_local_param QueueEnqueueLocals *locals)
{
- /* We have only 2 cases (Hit/Not-Hit) */
- int lidx = ccl_local_id(1) * ccl_local_size(0) + ccl_local_id(0);
- int ray_index = ccl_global_id(1) * ccl_global_size(0) + ccl_global_id(0);
+ /* We have only 2 cases (Hit/Not-Hit) */
+ int lidx = ccl_local_id(1) * ccl_local_size(0) + ccl_local_id(0);
+ int ray_index = ccl_global_id(1) * ccl_global_size(0) + ccl_global_id(0);
- if(lidx == 0) {
- locals->queue_atomics[0] = 0;
- locals->queue_atomics[1] = 0;
- }
- ccl_barrier(CCL_LOCAL_MEM_FENCE);
+ if (lidx == 0) {
+ locals->queue_atomics[0] = 0;
+ locals->queue_atomics[1] = 0;
+ }
+ ccl_barrier(CCL_LOCAL_MEM_FENCE);
- int queue_number = -1;
+ int queue_number = -1;
- if(IS_STATE(kernel_split_state.ray_state, ray_index, RAY_HIT_BACKGROUND) ||
- IS_STATE(kernel_split_state.ray_state, ray_index, RAY_UPDATE_BUFFER) ||
- IS_STATE(kernel_split_state.ray_state, ray_index, RAY_TO_REGENERATE)) {
- queue_number = QUEUE_HITBG_BUFF_UPDATE_TOREGEN_RAYS;
- }
- else if(IS_STATE(kernel_split_state.ray_state, ray_index, RAY_ACTIVE) ||
- IS_STATE(kernel_split_state.ray_state, ray_index, RAY_HAS_ONLY_VOLUME) ||
- IS_STATE(kernel_split_state.ray_state, ray_index, RAY_REGENERATED)) {
- queue_number = QUEUE_ACTIVE_AND_REGENERATED_RAYS;
- }
+ if (IS_STATE(kernel_split_state.ray_state, ray_index, RAY_HIT_BACKGROUND) ||
+ IS_STATE(kernel_split_state.ray_state, ray_index, RAY_UPDATE_BUFFER) ||
+ IS_STATE(kernel_split_state.ray_state, ray_index, RAY_TO_REGENERATE)) {
+ queue_number = QUEUE_HITBG_BUFF_UPDATE_TOREGEN_RAYS;
+ }
+ else if (IS_STATE(kernel_split_state.ray_state, ray_index, RAY_ACTIVE) ||
+ IS_STATE(kernel_split_state.ray_state, ray_index, RAY_HAS_ONLY_VOLUME) ||
+ IS_STATE(kernel_split_state.ray_state, ray_index, RAY_REGENERATED)) {
+ queue_number = QUEUE_ACTIVE_AND_REGENERATED_RAYS;
+ }
- unsigned int my_lqidx;
- if(queue_number != -1) {
- my_lqidx = get_local_queue_index(queue_number, locals->queue_atomics);
- }
- ccl_barrier(CCL_LOCAL_MEM_FENCE);
+ unsigned int my_lqidx;
+ if (queue_number != -1) {
+ my_lqidx = get_local_queue_index(queue_number, locals->queue_atomics);
+ }
+ ccl_barrier(CCL_LOCAL_MEM_FENCE);
- if(lidx == 0) {
- locals->queue_atomics[QUEUE_ACTIVE_AND_REGENERATED_RAYS] =
- get_global_per_queue_offset(QUEUE_ACTIVE_AND_REGENERATED_RAYS,
- locals->queue_atomics,
- kernel_split_params.queue_index);
- locals->queue_atomics[QUEUE_HITBG_BUFF_UPDATE_TOREGEN_RAYS] =
- get_global_per_queue_offset(QUEUE_HITBG_BUFF_UPDATE_TOREGEN_RAYS,
- locals->queue_atomics,
- kernel_split_params.queue_index);
- }
- ccl_barrier(CCL_LOCAL_MEM_FENCE);
+ if (lidx == 0) {
+ locals->queue_atomics[QUEUE_ACTIVE_AND_REGENERATED_RAYS] = get_global_per_queue_offset(
+ QUEUE_ACTIVE_AND_REGENERATED_RAYS, locals->queue_atomics, kernel_split_params.queue_index);
+ locals->queue_atomics[QUEUE_HITBG_BUFF_UPDATE_TOREGEN_RAYS] = get_global_per_queue_offset(
+ QUEUE_HITBG_BUFF_UPDATE_TOREGEN_RAYS,
+ locals->queue_atomics,
+ kernel_split_params.queue_index);
+ }
+ ccl_barrier(CCL_LOCAL_MEM_FENCE);
- unsigned int my_gqidx;
- if(queue_number != -1) {
- my_gqidx = get_global_queue_index(queue_number,
- kernel_split_params.queue_size,
- my_lqidx,
- locals->queue_atomics);
- kernel_split_state.queue_data[my_gqidx] = ray_index;
- }
+ unsigned int my_gqidx;
+ if (queue_number != -1) {
+ my_gqidx = get_global_queue_index(
+ queue_number, kernel_split_params.queue_size, my_lqidx, locals->queue_atomics);
+ kernel_split_state.queue_data[my_gqidx] = ray_index;
+ }
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/split/kernel_scene_intersect.h b/intern/cycles/kernel/split/kernel_scene_intersect.h
index f5378bc172b..5fef3e045f8 100644
--- a/intern/cycles/kernel/split/kernel_scene_intersect.h
+++ b/intern/cycles/kernel/split/kernel_scene_intersect.h
@@ -25,55 +25,56 @@ CCL_NAMESPACE_BEGIN
*/
ccl_device void kernel_scene_intersect(KernelGlobals *kg)
{
- /* Fetch use_queues_flag */
- char local_use_queues_flag = *kernel_split_params.use_queues_flag;
- ccl_barrier(CCL_LOCAL_MEM_FENCE);
+ /* 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) {
- ray_index = get_ray_index(kg, ray_index,
- QUEUE_ACTIVE_AND_REGENERATED_RAYS,
- kernel_split_state.queue_data,
- kernel_split_params.queue_size,
- 0);
+ int ray_index = ccl_global_id(1) * ccl_global_size(0) + ccl_global_id(0);
+ if (local_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,
+ 0);
- if(ray_index == QUEUE_EMPTY_SLOT) {
- return;
- }
- }
+ if (ray_index == QUEUE_EMPTY_SLOT) {
+ return;
+ }
+ }
- /* All regenerated rays become active here */
- if(IS_STATE(kernel_split_state.ray_state, ray_index, RAY_REGENERATED)) {
+ /* All regenerated rays become active here */
+ if (IS_STATE(kernel_split_state.ray_state, ray_index, RAY_REGENERATED)) {
#ifdef __BRANCHED_PATH__
- if(kernel_split_state.branched_state[ray_index].waiting_on_shared_samples) {
- kernel_split_path_end(kg, ray_index);
- }
- else
-#endif /* __BRANCHED_PATH__ */
- {
- ASSIGN_RAY_STATE(kernel_split_state.ray_state, ray_index, RAY_ACTIVE);
- }
- }
+ if (kernel_split_state.branched_state[ray_index].waiting_on_shared_samples) {
+ kernel_split_path_end(kg, ray_index);
+ }
+ else
+#endif /* __BRANCHED_PATH__ */
+ {
+ ASSIGN_RAY_STATE(kernel_split_state.ray_state, ray_index, RAY_ACTIVE);
+ }
+ }
- if(!IS_STATE(kernel_split_state.ray_state, ray_index, RAY_ACTIVE)) {
- return;
- }
+ if (!IS_STATE(kernel_split_state.ray_state, ray_index, RAY_ACTIVE)) {
+ return;
+ }
- ccl_global PathState *state = &kernel_split_state.path_state[ray_index];
- Ray ray = kernel_split_state.ray[ray_index];
- PathRadiance *L = &kernel_split_state.path_radiance[ray_index];
+ ccl_global PathState *state = &kernel_split_state.path_state[ray_index];
+ Ray ray = kernel_split_state.ray[ray_index];
+ PathRadiance *L = &kernel_split_state.path_radiance[ray_index];
- Intersection isect;
- bool hit = kernel_path_scene_intersect(kg, state, &ray, &isect, L);
- kernel_split_state.isect[ray_index] = isect;
+ Intersection isect;
+ bool hit = kernel_path_scene_intersect(kg, state, &ray, &isect, L);
+ kernel_split_state.isect[ray_index] = isect;
- if(!hit) {
- /* Change the state of rays that hit the background;
- * These rays undergo special processing in the
- * background_bufferUpdate kernel.
- */
- ASSIGN_RAY_STATE(kernel_split_state.ray_state, ray_index, RAY_HIT_BACKGROUND);
- }
+ if (!hit) {
+ /* Change the state of rays that hit the background;
+ * These rays undergo special processing in the
+ * background_bufferUpdate kernel.
+ */
+ ASSIGN_RAY_STATE(kernel_split_state.ray_state, ray_index, RAY_HIT_BACKGROUND);
+ }
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/split/kernel_shader_eval.h b/intern/cycles/kernel/split/kernel_shader_eval.h
index 2bc2d300699..8e39c9797e5 100644
--- a/intern/cycles/kernel/split/kernel_shader_eval.h
+++ b/intern/cycles/kernel/split/kernel_shader_eval.h
@@ -22,45 +22,46 @@ CCL_NAMESPACE_BEGIN
ccl_device void kernel_shader_eval(KernelGlobals *kg)
{
- int ray_index = ccl_global_id(1) * ccl_global_size(0) + ccl_global_id(0);
- /* Sorting on cuda split is not implemented */
+ 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];
+ 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];
+ 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,
+ if (ray_index >= queue_index) {
+ return;
+ }
+ ray_index = get_ray_index(kg,
+ ray_index,
#ifdef __KERNEL_CUDA__
- QUEUE_ACTIVE_AND_REGENERATED_RAYS,
+ QUEUE_ACTIVE_AND_REGENERATED_RAYS,
#else
- QUEUE_SHADER_SORTED_RAYS,
+ QUEUE_SHADER_SORTED_RAYS,
#endif
- kernel_split_state.queue_data,
- kernel_split_params.queue_size,
- 0);
+ kernel_split_state.queue_data,
+ kernel_split_params.queue_size,
+ 0);
- if(ray_index == QUEUE_EMPTY_SLOT) {
- return;
- }
+ if (ray_index == QUEUE_EMPTY_SLOT) {
+ return;
+ }
- ccl_global char *ray_state = kernel_split_state.ray_state;
- if(IS_STATE(ray_state, ray_index, RAY_ACTIVE)) {
- ccl_global PathState *state = &kernel_split_state.path_state[ray_index];
+ ccl_global char *ray_state = kernel_split_state.ray_state;
+ if (IS_STATE(ray_state, ray_index, RAY_ACTIVE)) {
+ ccl_global PathState *state = &kernel_split_state.path_state[ray_index];
- shader_eval_surface(kg, kernel_split_sd(sd, ray_index), state, state->flag);
+ shader_eval_surface(kg, kernel_split_sd(sd, ray_index), state, state->flag);
#ifdef __BRANCHED_PATH__
- if(kernel_data.integrator.branched) {
- shader_merge_closures(kernel_split_sd(sd, ray_index));
- }
- else
+ if (kernel_data.integrator.branched) {
+ shader_merge_closures(kernel_split_sd(sd, ray_index));
+ }
+ else
#endif
- {
- shader_prepare_closures(kernel_split_sd(sd, ray_index), state);
- }
- }
+ {
+ shader_prepare_closures(kernel_split_sd(sd, ray_index), state);
+ }
+ }
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/split/kernel_shader_setup.h b/intern/cycles/kernel/split/kernel_shader_setup.h
index ea3ec2ec83f..da332db2c98 100644
--- a/intern/cycles/kernel/split/kernel_shader_setup.h
+++ b/intern/cycles/kernel/split/kernel_shader_setup.h
@@ -25,54 +25,52 @@ CCL_NAMESPACE_BEGIN
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);
+ /* 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);
+ 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;
- }
+ 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);
+ 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];
- ShaderData *sd = kernel_split_sd(sd, ray_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];
+ ShaderData *sd = kernel_split_sd(sd, ray_index);
- shader_setup_from_ray(kg,
- sd,
- &isect,
- &ray);
+ shader_setup_from_ray(kg, sd, &isect, &ray);
#ifdef __VOLUME__
- if(sd->flag & SD_HAS_ONLY_VOLUME) {
- ASSIGN_RAY_STATE(kernel_split_state.ray_state, ray_index, RAY_HAS_ONLY_VOLUME);
- }
+ if (sd->flag & SD_HAS_ONLY_VOLUME) {
+ ASSIGN_RAY_STATE(kernel_split_state.ray_state, ray_index, RAY_HAS_ONLY_VOLUME);
+ }
#endif
- }
-
+ }
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/split/kernel_shader_sort.h b/intern/cycles/kernel/split/kernel_shader_sort.h
index 666355de334..95d33a42014 100644
--- a/intern/cycles/kernel/split/kernel_shader_sort.h
+++ b/intern/cycles/kernel/split/kernel_shader_sort.h
@@ -16,82 +16,82 @@
CCL_NAMESPACE_BEGIN
-
-ccl_device void kernel_shader_sort(KernelGlobals *kg,
- ccl_local_param ShaderSortLocals *locals)
+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;
- }
+ 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;
- }
+ 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];
+ 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_sd(sd, ray_index)->shader & SHADER_MASK;
- }
- }
- local_value[i + lid] = value;
- local_index[i + lid] = i + lid;
- }
- ccl_barrier(CCL_LOCAL_MEM_FENCE);
+ /* 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_sd(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 */
+ /* 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__ */
+ /* 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__ */
+ /* 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 fb08112503a..5d772fc597b 100644
--- a/intern/cycles/kernel/split/kernel_shadow_blocked_ao.h
+++ b/intern/cycles/kernel/split/kernel_shadow_blocked_ao.h
@@ -19,35 +19,40 @@ CCL_NAMESPACE_BEGIN
/* Shadow ray cast for AO. */
ccl_device void kernel_shadow_blocked_ao(KernelGlobals *kg)
{
- unsigned int ao_queue_length = kernel_split_params.queue_index[QUEUE_SHADOW_RAY_CAST_AO_RAYS];
- ccl_barrier(CCL_LOCAL_MEM_FENCE);
+ unsigned int ao_queue_length = kernel_split_params.queue_index[QUEUE_SHADOW_RAY_CAST_AO_RAYS];
+ ccl_barrier(CCL_LOCAL_MEM_FENCE);
- int ray_index = QUEUE_EMPTY_SLOT;
- int thread_index = ccl_global_id(1) * ccl_global_size(0) + ccl_global_id(0);
- if(thread_index < ao_queue_length) {
- ray_index = get_ray_index(kg, thread_index, QUEUE_SHADOW_RAY_CAST_AO_RAYS,
- kernel_split_state.queue_data, kernel_split_params.queue_size, 1);
- }
+ int ray_index = QUEUE_EMPTY_SLOT;
+ int thread_index = ccl_global_id(1) * ccl_global_size(0) + ccl_global_id(0);
+ if (thread_index < ao_queue_length) {
+ ray_index = get_ray_index(kg,
+ thread_index,
+ QUEUE_SHADOW_RAY_CAST_AO_RAYS,
+ kernel_split_state.queue_data,
+ kernel_split_params.queue_size,
+ 1);
+ }
- if(ray_index == QUEUE_EMPTY_SLOT) {
- return;
- }
+ if (ray_index == QUEUE_EMPTY_SLOT) {
+ return;
+ }
- ShaderData *sd = kernel_split_sd(sd, ray_index);
- ShaderData *emission_sd = AS_SHADER_DATA(&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];
- float3 throughput = kernel_split_state.throughput[ray_index];
+ ShaderData *sd = kernel_split_sd(sd, ray_index);
+ ShaderData *emission_sd = AS_SHADER_DATA(&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];
+ 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)) {
+ 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, throughput, shader_bsdf_alpha(kg, sd));
+ kernel_path_ao(kg, sd, emission_sd, L, state, throughput, shader_bsdf_alpha(kg, sd));
#ifdef __BRANCHED_PATH__
- }
- else {
- kernel_branched_path_ao(kg, sd, emission_sd, L, state, throughput);
- }
+ }
+ else {
+ kernel_branched_path_ao(kg, sd, emission_sd, L, state, throughput);
+ }
#endif
}
diff --git a/intern/cycles/kernel/split/kernel_shadow_blocked_dl.h b/intern/cycles/kernel/split/kernel_shadow_blocked_dl.h
index da072fd5f1a..82990ce9fae 100644
--- a/intern/cycles/kernel/split/kernel_shadow_blocked_dl.h
+++ b/intern/cycles/kernel/split/kernel_shadow_blocked_dl.h
@@ -19,89 +19,80 @@ CCL_NAMESPACE_BEGIN
/* Shadow ray cast for direct visible light. */
ccl_device void kernel_shadow_blocked_dl(KernelGlobals *kg)
{
- unsigned int dl_queue_length = kernel_split_params.queue_index[QUEUE_SHADOW_RAY_CAST_DL_RAYS];
- ccl_barrier(CCL_LOCAL_MEM_FENCE);
+ unsigned int dl_queue_length = kernel_split_params.queue_index[QUEUE_SHADOW_RAY_CAST_DL_RAYS];
+ ccl_barrier(CCL_LOCAL_MEM_FENCE);
- int ray_index = QUEUE_EMPTY_SLOT;
- int thread_index = ccl_global_id(1) * ccl_global_size(0) + ccl_global_id(0);
- if(thread_index < dl_queue_length) {
- ray_index = get_ray_index(kg, thread_index, QUEUE_SHADOW_RAY_CAST_DL_RAYS,
- kernel_split_state.queue_data, kernel_split_params.queue_size, 1);
- }
+ int ray_index = QUEUE_EMPTY_SLOT;
+ int thread_index = ccl_global_id(1) * ccl_global_size(0) + ccl_global_id(0);
+ if (thread_index < dl_queue_length) {
+ ray_index = get_ray_index(kg,
+ thread_index,
+ QUEUE_SHADOW_RAY_CAST_DL_RAYS,
+ kernel_split_state.queue_data,
+ kernel_split_params.queue_size,
+ 1);
+ }
#ifdef __BRANCHED_PATH__
- /* TODO(mai): move this somewhere else? */
- if(thread_index == 0) {
- /* Clear QUEUE_INACTIVE_RAYS before next kernel. */
- kernel_split_params.queue_index[QUEUE_INACTIVE_RAYS] = 0;
- }
-#endif /* __BRANCHED_PATH__ */
+ /* TODO(mai): move this somewhere else? */
+ if (thread_index == 0) {
+ /* Clear QUEUE_INACTIVE_RAYS before next kernel. */
+ kernel_split_params.queue_index[QUEUE_INACTIVE_RAYS] = 0;
+ }
+#endif /* __BRANCHED_PATH__ */
- if(ray_index == QUEUE_EMPTY_SLOT)
- return;
+ if (ray_index == QUEUE_EMPTY_SLOT)
+ return;
- 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_sd(sd, ray_index);
- float3 throughput = kernel_split_state.throughput[ray_index];
+ 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_sd(sd, ray_index);
+ float3 throughput = kernel_split_state.throughput[ray_index];
- BsdfEval L_light = kernel_split_state.bsdf_eval[ray_index];
- ShaderData *emission_sd = AS_SHADER_DATA(&kernel_split_state.sd_DL_shadow[ray_index]);
- bool is_lamp = kernel_split_state.is_lamp[ray_index];
+ BsdfEval L_light = kernel_split_state.bsdf_eval[ray_index];
+ ShaderData *emission_sd = AS_SHADER_DATA(&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 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 (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 (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,
- sd,
- emission_sd,
- state,
- throughput,
- 1.0f,
- L,
- all);
- }
- else
-# endif /* defined(__BRANCHED_PATH__) || defined(__SHADOW_TRICKS__)*/
- {
- /* trace shadow ray */
- float3 shadow;
+ if (use_branched) {
+ kernel_branched_path_surface_connect_light(
+ kg, sd, emission_sd, state, throughput, 1.0f, L, all);
+ }
+ else
+#endif /* defined(__BRANCHED_PATH__) || defined(__SHADOW_TRICKS__)*/
+ {
+ /* trace shadow ray */
+ float3 shadow;
- if(!shadow_blocked(kg,
- sd,
- emission_sd,
- state,
- &ray,
- &shadow))
- {
- /* accumulate */
- path_radiance_accum_light(L, state, throughput, &L_light, shadow, 1.0f, is_lamp);
- }
- else {
- path_radiance_accum_total_light(L, state, throughput, &L_light);
- }
- }
+ if (!shadow_blocked(kg, sd, emission_sd, state, &ray, &shadow)) {
+ /* accumulate */
+ path_radiance_accum_light(L, state, throughput, &L_light, shadow, 1.0f, is_lamp);
+ }
+ else {
+ path_radiance_accum_total_light(L, state, throughput, &L_light);
+ }
+ }
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/split/kernel_split_common.h b/intern/cycles/kernel/split/kernel_split_common.h
index 4b86696691a..384bc952460 100644
--- a/intern/cycles/kernel/split/kernel_split_common.h
+++ b/intern/cycles/kernel/split/kernel_split_common.h
@@ -14,8 +14,8 @@
* limitations under the License.
*/
-#ifndef __KERNEL_SPLIT_H__
-#define __KERNEL_SPLIT_H__
+#ifndef __KERNEL_SPLIT_H__
+#define __KERNEL_SPLIT_H__
#include "kernel/kernel_math.h"
#include "kernel/kernel_types.h"
@@ -57,47 +57,48 @@ 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;
+ ccl_global char *ray_state = kernel_split_state.ray_state;
#ifdef __BRANCHED_PATH__
# ifdef __SUBSURFACE__
- ccl_addr_space SubsurfaceIndirectRays *ss_indirect = &kernel_split_state.ss_rays[ray_index];
-
- if(ss_indirect->num_rays) {
- ASSIGN_RAY_STATE(ray_state, ray_index, RAY_UPDATE_BUFFER);
- }
- else
-# endif /* __SUBSURFACE__ */
- if(IS_FLAG(ray_state, ray_index, RAY_BRANCHED_INDIRECT_SHARED)) {
- int orig_ray = kernel_split_state.branched_state[ray_index].original_ray;
-
- PathRadiance *L = &kernel_split_state.path_radiance[ray_index];
- PathRadiance *orig_ray_L = &kernel_split_state.path_radiance[orig_ray];
-
- path_radiance_sum_indirect(L);
- path_radiance_accum_sample(orig_ray_L, L);
-
- atomic_fetch_and_dec_uint32((ccl_global uint*)&kernel_split_state.branched_state[orig_ray].shared_sample_count);
-
- ASSIGN_RAY_STATE(ray_state, ray_index, RAY_INACTIVE);
- }
- else 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);
- }
+ ccl_addr_space SubsurfaceIndirectRays *ss_indirect = &kernel_split_state.ss_rays[ray_index];
+
+ if (ss_indirect->num_rays) {
+ ASSIGN_RAY_STATE(ray_state, ray_index, RAY_UPDATE_BUFFER);
+ }
+ else
+# endif /* __SUBSURFACE__ */
+ if (IS_FLAG(ray_state, ray_index, RAY_BRANCHED_INDIRECT_SHARED)) {
+ int orig_ray = kernel_split_state.branched_state[ray_index].original_ray;
+
+ PathRadiance *L = &kernel_split_state.path_radiance[ray_index];
+ PathRadiance *orig_ray_L = &kernel_split_state.path_radiance[orig_ray];
+
+ path_radiance_sum_indirect(L);
+ path_radiance_accum_sample(orig_ray_L, L);
+
+ atomic_fetch_and_dec_uint32(
+ (ccl_global uint *)&kernel_split_state.branched_state[orig_ray].shared_sample_count);
+
+ ASSIGN_RAY_STATE(ray_state, ray_index, RAY_INACTIVE);
+ }
+ else 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);
+ ASSIGN_RAY_STATE(ray_state, ray_index, RAY_UPDATE_BUFFER);
#endif
}
CCL_NAMESPACE_END
-#endif /* __KERNEL_SPLIT_H__ */
+#endif /* __KERNEL_SPLIT_H__ */
diff --git a/intern/cycles/kernel/split/kernel_split_data.h b/intern/cycles/kernel/split/kernel_split_data.h
index 3f6b3977d79..433b1221a37 100644
--- a/intern/cycles/kernel/split/kernel_split_data.h
+++ b/intern/cycles/kernel/split/kernel_split_data.h
@@ -24,22 +24,22 @@ CCL_NAMESPACE_BEGIN
ccl_device_inline uint64_t split_data_buffer_size(KernelGlobals *kg, size_t num_elements)
{
- (void) kg; /* Unused on CPU. */
+ (void)kg; /* Unused on CPU. */
- uint64_t size = 0;
-#define SPLIT_DATA_ENTRY(type, name, num) + align_up(num_elements * num * sizeof(type), 16)
- size = size SPLIT_DATA_ENTRIES;
+ uint64_t size = 0;
+#define SPLIT_DATA_ENTRY(type, name, num) +align_up(num_elements *num * sizeof(type), 16)
+ size = size SPLIT_DATA_ENTRIES;
#undef SPLIT_DATA_ENTRY
- uint64_t closure_size = sizeof(ShaderClosure) * (kernel_data.integrator.max_closures-1);
+ uint64_t closure_size = sizeof(ShaderClosure) * (kernel_data.integrator.max_closures - 1);
#ifdef __BRANCHED_PATH__
- size += align_up(num_elements * (sizeof(ShaderData) + closure_size), 16);
+ size += align_up(num_elements * (sizeof(ShaderData) + closure_size), 16);
#endif
- size += align_up(num_elements * (sizeof(ShaderData) + closure_size), 16);
+ size += align_up(num_elements * (sizeof(ShaderData) + closure_size), 16);
- return size;
+ return size;
}
ccl_device_inline void split_data_init(KernelGlobals *kg,
@@ -48,28 +48,29 @@ ccl_device_inline void split_data_init(KernelGlobals *kg,
ccl_global void *data,
ccl_global char *ray_state)
{
- (void) kg; /* Unused on CPU. */
+ (void)kg; /* Unused on CPU. */
- ccl_global char *p = (ccl_global char*)data;
+ ccl_global char *p = (ccl_global char *)data;
#define SPLIT_DATA_ENTRY(type, name, num) \
- split_data->name = (type*)p; p += align_up(num_elements * num * sizeof(type), 16);
- SPLIT_DATA_ENTRIES;
+ split_data->name = (type *)p; \
+ p += align_up(num_elements * num * sizeof(type), 16);
+ SPLIT_DATA_ENTRIES;
#undef SPLIT_DATA_ENTRY
- uint64_t closure_size = sizeof(ShaderClosure) * (kernel_data.integrator.max_closures-1);
+ uint64_t closure_size = sizeof(ShaderClosure) * (kernel_data.integrator.max_closures - 1);
#ifdef __BRANCHED_PATH__
- split_data->_branched_state_sd = (ShaderData*)p;
- p += align_up(num_elements * (sizeof(ShaderData) + closure_size), 16);
+ split_data->_branched_state_sd = (ShaderData *)p;
+ p += align_up(num_elements * (sizeof(ShaderData) + closure_size), 16);
#endif
- split_data->_sd = (ShaderData*)p;
- p += align_up(num_elements * (sizeof(ShaderData) + closure_size), 16);
+ split_data->_sd = (ShaderData *)p;
+ p += align_up(num_elements * (sizeof(ShaderData) + closure_size), 16);
- split_data->ray_state = ray_state;
+ split_data->ray_state = ray_state;
}
CCL_NAMESPACE_END
-#endif /* __KERNEL_SPLIT_DATA_H__ */
+#endif /* __KERNEL_SPLIT_DATA_H__ */
diff --git a/intern/cycles/kernel/split/kernel_split_data_types.h b/intern/cycles/kernel/split/kernel_split_data_types.h
index 83df1e2a0a6..6ff3f5bdb55 100644
--- a/intern/cycles/kernel/split/kernel_split_data_types.h
+++ b/intern/cycles/kernel/split/kernel_split_data_types.h
@@ -22,17 +22,17 @@ CCL_NAMESPACE_BEGIN
/* parameters used by the split kernels, we use a single struct to avoid passing these to each kernel */
typedef struct SplitParams {
- WorkTile tile;
- uint total_work_size;
+ WorkTile tile;
+ uint total_work_size;
- ccl_global unsigned int *work_pools;
+ ccl_global unsigned int *work_pools;
- ccl_global int *queue_index;
- int queue_size;
- ccl_global char *use_queues_flag;
+ ccl_global int *queue_index;
+ int queue_size;
+ ccl_global char *use_queues_flag;
- /* Place for storing sd->flag. AMD GPU OpenCL compiler workaround */
- int dummy_sd_flag;
+ /* Place for storing sd->flag. AMD GPU OpenCL compiler workaround */
+ int dummy_sd_flag;
} SplitParams;
/* Global memory variables [porting]; These memory is used for
@@ -46,98 +46,98 @@ typedef struct SplitParams {
#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;
+ /* various state that must be kept and restored after an indirect loop */
+ PathState path_state;
+ float3 throughput;
+ Ray ray;
- Intersection isect;
+ Intersection isect;
- char ray_state;
+ char ray_state;
- /* indirect loop state */
- int next_closure;
- int next_sample;
+ /* indirect loop state */
+ int next_closure;
+ int next_sample;
-#ifdef __SUBSURFACE__
- int ss_next_closure;
- int ss_next_sample;
- int next_hit;
- int num_hits;
-
- uint lcg_state;
- LocalIntersection ss_isect;
-#endif /*__SUBSURFACE__ */
-
- int shared_sample_count; /* number of branched samples shared with other threads */
- int original_ray; /* index of original ray when sharing branched samples */
- bool waiting_on_shared_samples;
+# ifdef __SUBSURFACE__
+ int ss_next_closure;
+ int ss_next_sample;
+ int next_hit;
+ int num_hits;
+
+ uint lcg_state;
+ LocalIntersection ss_isect;
+# endif /*__SUBSURFACE__ */
+
+ int shared_sample_count; /* number of branched samples shared with other threads */
+ int original_ray; /* index of original ray when sharing branched samples */
+ bool waiting_on_shared_samples;
} SplitBranchedState;
-#define SPLIT_DATA_BRANCHED_ENTRIES \
- SPLIT_DATA_ENTRY( SplitBranchedState, branched_state, 1) \
- SPLIT_DATA_ENTRY(ShaderData, _branched_state_sd, 0)
+# define SPLIT_DATA_BRANCHED_ENTRIES \
+ SPLIT_DATA_ENTRY(SplitBranchedState, branched_state, 1) \
+ SPLIT_DATA_ENTRY(ShaderData, _branched_state_sd, 0)
#else
-#define SPLIT_DATA_BRANCHED_ENTRIES
-#endif /* __BRANCHED_PATH__ */
+# define SPLIT_DATA_BRANCHED_ENTRIES
+#endif /* __BRANCHED_PATH__ */
#ifdef __SUBSURFACE__
# define SPLIT_DATA_SUBSURFACE_ENTRIES \
- SPLIT_DATA_ENTRY(ccl_global SubsurfaceIndirectRays, ss_rays, 1)
+ SPLIT_DATA_ENTRY(ccl_global SubsurfaceIndirectRays, ss_rays, 1)
#else
# define SPLIT_DATA_SUBSURFACE_ENTRIES
-#endif /* __SUBSURFACE__ */
+#endif /* __SUBSURFACE__ */
#ifdef __VOLUME__
-# define SPLIT_DATA_VOLUME_ENTRIES \
- SPLIT_DATA_ENTRY(ccl_global PathState, state_shadow, 1)
+# define SPLIT_DATA_VOLUME_ENTRIES SPLIT_DATA_ENTRY(ccl_global PathState, state_shadow, 1)
#else
# define SPLIT_DATA_VOLUME_ENTRIES
-#endif /* __VOLUME__ */
+#endif /* __VOLUME__ */
#define SPLIT_DATA_ENTRIES \
- SPLIT_DATA_ENTRY(ccl_global float3, throughput, 1) \
- SPLIT_DATA_ENTRY(PathRadiance, path_radiance, 1) \
- 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 BsdfEval, bsdf_eval, 1) \
- SPLIT_DATA_ENTRY(ccl_global int, is_lamp, 1) \
- SPLIT_DATA_ENTRY(ccl_global Ray, light_ray, 1) \
- SPLIT_DATA_ENTRY(ccl_global int, queue_data, (NUM_QUEUES*2)) /* TODO(mai): this is too large? */ \
- SPLIT_DATA_ENTRY(ccl_global uint, buffer_offset, 1) \
- SPLIT_DATA_ENTRY(ShaderDataTinyStorage, sd_DL_shadow, 1) \
- SPLIT_DATA_SUBSURFACE_ENTRIES \
- SPLIT_DATA_VOLUME_ENTRIES \
- SPLIT_DATA_BRANCHED_ENTRIES \
- SPLIT_DATA_ENTRY(ShaderData, _sd, 0)
+ SPLIT_DATA_ENTRY(ccl_global float3, throughput, 1) \
+ SPLIT_DATA_ENTRY(PathRadiance, path_radiance, 1) \
+ 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 BsdfEval, bsdf_eval, 1) \
+ SPLIT_DATA_ENTRY(ccl_global int, is_lamp, 1) \
+ SPLIT_DATA_ENTRY(ccl_global Ray, light_ray, 1) \
+ SPLIT_DATA_ENTRY( \
+ ccl_global int, queue_data, (NUM_QUEUES * 2)) /* TODO(mai): this is too large? */ \
+ SPLIT_DATA_ENTRY(ccl_global uint, buffer_offset, 1) \
+ SPLIT_DATA_ENTRY(ShaderDataTinyStorage, sd_DL_shadow, 1) \
+ SPLIT_DATA_SUBSURFACE_ENTRIES \
+ SPLIT_DATA_VOLUME_ENTRIES \
+ SPLIT_DATA_BRANCHED_ENTRIES \
+ SPLIT_DATA_ENTRY(ShaderData, _sd, 0)
/* entries to be copied to inactive rays when sharing branched samples (TODO: which are actually needed?) */
#define SPLIT_DATA_ENTRIES_BRANCHED_SHARED \
- SPLIT_DATA_ENTRY(ccl_global float3, throughput, 1) \
- SPLIT_DATA_ENTRY(PathRadiance, path_radiance, 1) \
- 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 BsdfEval, bsdf_eval, 1) \
- SPLIT_DATA_ENTRY(ccl_global int, is_lamp, 1) \
- SPLIT_DATA_ENTRY(ccl_global Ray, light_ray, 1) \
- SPLIT_DATA_ENTRY(ShaderDataTinyStorage, sd_DL_shadow, 1) \
- SPLIT_DATA_SUBSURFACE_ENTRIES \
- SPLIT_DATA_VOLUME_ENTRIES \
- SPLIT_DATA_BRANCHED_ENTRIES \
- SPLIT_DATA_ENTRY(ShaderData, _sd, 0)
+ SPLIT_DATA_ENTRY(ccl_global float3, throughput, 1) \
+ SPLIT_DATA_ENTRY(PathRadiance, path_radiance, 1) \
+ 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 BsdfEval, bsdf_eval, 1) \
+ SPLIT_DATA_ENTRY(ccl_global int, is_lamp, 1) \
+ SPLIT_DATA_ENTRY(ccl_global Ray, light_ray, 1) \
+ SPLIT_DATA_ENTRY(ShaderDataTinyStorage, sd_DL_shadow, 1) \
+ SPLIT_DATA_SUBSURFACE_ENTRIES \
+ SPLIT_DATA_VOLUME_ENTRIES \
+ SPLIT_DATA_BRANCHED_ENTRIES \
+ SPLIT_DATA_ENTRY(ShaderData, _sd, 0)
/* struct that holds pointers to data in the shared state buffer */
typedef struct SplitData {
#define SPLIT_DATA_ENTRY(type, name, num) type *name;
- SPLIT_DATA_ENTRIES
+ SPLIT_DATA_ENTRIES
#undef SPLIT_DATA_ENTRY
- /* this is actually in a separate buffer from the rest of the split state data (so it can be read back from
- * the host easily) but is still used the same as the other data so we have it here in this struct as well
- */
- ccl_global char *ray_state;
+ /* this is actually in a separate buffer from the rest of the split state data (so it can be read back from
+ * the host easily) but is still used the same as the other data so we have it here in this struct as well
+ */
+ ccl_global char *ray_state;
} SplitData;
#ifndef __KERNEL_CUDA__
@@ -148,30 +148,30 @@ __device__ SplitData __split_data;
# define kernel_split_state (__split_data)
__device__ SplitParams __split_param_data;
# define kernel_split_params (__split_param_data)
-#endif /* __KERNEL_CUDA__ */
+#endif /* __KERNEL_CUDA__ */
-#define kernel_split_sd(sd, ray_index) ((ShaderData*) \
- ( \
- ((ccl_global char*)kernel_split_state._##sd) + \
- (sizeof(ShaderData) + sizeof(ShaderClosure)*(kernel_data.integrator.max_closures-1)) * (ray_index) \
- ))
+#define kernel_split_sd(sd, ray_index) \
+ ((ShaderData *)(((ccl_global char *)kernel_split_state._##sd) + \
+ (sizeof(ShaderData) + \
+ sizeof(ShaderClosure) * (kernel_data.integrator.max_closures - 1)) * \
+ (ray_index)))
/* Local storage for queue_enqueue kernel. */
typedef struct QueueEnqueueLocals {
- uint queue_atomics[2];
+ uint queue_atomics[2];
} QueueEnqueueLocals;
/* Local storage for holdout_emission_blurring_pathtermination_ao kernel. */
typedef struct BackgroundAOLocals {
- uint queue_atomics_bg;
- uint queue_atomics_ao;
+ uint queue_atomics_bg;
+ uint queue_atomics_ao;
} BackgroundAOLocals;
typedef struct ShaderSortLocals {
- uint local_value[SHADER_SORT_BLOCK_SIZE];
- ushort local_index[SHADER_SORT_BLOCK_SIZE];
+ uint local_value[SHADER_SORT_BLOCK_SIZE];
+ ushort local_index[SHADER_SORT_BLOCK_SIZE];
} ShaderSortLocals;
CCL_NAMESPACE_END
-#endif /* __KERNEL_SPLIT_DATA_TYPES_H__ */
+#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 08769fe303b..ba06ae3bc53 100644
--- a/intern/cycles/kernel/split/kernel_subsurface_scatter.h
+++ b/intern/cycles/kernel/split/kernel_subsurface_scatter.h
@@ -18,276 +18,247 @@ CCL_NAMESPACE_BEGIN
#if defined(__BRANCHED_PATH__) && defined(__SUBSURFACE__)
-ccl_device_inline void kernel_split_branched_path_subsurface_indirect_light_init(KernelGlobals *kg, int ray_index)
+ccl_device_inline void kernel_split_branched_path_subsurface_indirect_light_init(KernelGlobals *kg,
+ int ray_index)
{
- kernel_split_branched_path_indirect_loop_init(kg, ray_index);
+ kernel_split_branched_path_indirect_loop_init(kg, ray_index);
- SplitBranchedState *branched_state = &kernel_split_state.branched_state[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->ss_next_closure = 0;
+ branched_state->ss_next_sample = 0;
- branched_state->num_hits = 0;
- branched_state->next_hit = 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);
+ 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)
+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 = kernel_split_sd(branched_state_sd, ray_index);
- PathRadiance *L = &kernel_split_state.path_radiance[ray_index];
- ShaderData *emission_sd = AS_SHADER_DATA(&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;
-
- /* Closure memory will be overwritten, so read required variables now. */
- Bssrdf *bssrdf = (Bssrdf *)sc;
- ClosureType bssrdf_type = sc->type;
- float bssrdf_roughness = bssrdf->roughness;
-
- /* 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_addrspace(&branched_state->path_state,
- 0x68bc21eb);
- }
- int num_samples = kernel_data.integrator.subsurface_samples * 3;
- float num_samples_inv = 1.0f/num_samples;
- uint bssrdf_rng_hash = cmj_hash(branched_state->path_state.rng_hash, 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 PathState *hit_state = &kernel_split_state.path_state[ray_index];
- *hit_state = branched_state->path_state;
- hit_state->rng_hash = bssrdf_rng_hash;
- path_state_branch(hit_state, j, num_samples);
-
- ccl_global LocalIntersection *ss_isect = &branched_state->ss_isect;
- float bssrdf_u, bssrdf_v;
- path_branched_rng_2D(kg,
- bssrdf_rng_hash,
- hit_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) {
- uint lcg_state = branched_state->lcg_state;
- LocalIntersection ss_isect_private;
-
- branched_state->num_hits = subsurface_scatter_multi_intersect(kg,
- &ss_isect_private,
- sd,
- hit_state,
- sc,
- &lcg_state,
- bssrdf_u, bssrdf_v,
- true);
-
- branched_state->lcg_state = lcg_state;
- *ss_isect = ss_isect_private;
- }
-
- hit_state->rng_offset += PRNG_BOUNCE_NUM;
-
-#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_sd(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 */
-
- LocalIntersection ss_isect_private = *ss_isect;
- subsurface_scatter_multi_setup(kg,
- &ss_isect_private,
- hit,
- bssrdf_sd,
- hit_state,
- bssrdf_type,
- bssrdf_roughness);
- *ss_isect = ss_isect_private;
-
-#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);
-
- for(int k = 0; k < VOLUME_STACK_SIZE; k++) {
- hit_state->volume_stack[k] = branched_state->path_state.volume_stack[k];
- }
-
- kernel_volume_stack_update_for_subsurface(kg,
- emission_sd,
- &volume_ray,
- hit_state->volume_stack);
- }
-#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) ||
- (hit_state->flag & PATH_RAY_SHADOW_CATCHER);
- kernel_branched_path_surface_connect_light(kg,
- 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,
- 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;
- }
-
- branched_state->ss_next_closure = sd->num_closure;
-
- branched_state->waiting_on_shared_samples = (branched_state->shared_sample_count > 0);
- if(branched_state->waiting_on_shared_samples) {
- return true;
- }
-
- kernel_split_branched_path_indirect_loop_end(kg, ray_index);
-
- return false;
+ SplitBranchedState *branched_state = &kernel_split_state.branched_state[ray_index];
+
+ ShaderData *sd = kernel_split_sd(branched_state_sd, ray_index);
+ PathRadiance *L = &kernel_split_state.path_radiance[ray_index];
+ ShaderData *emission_sd = AS_SHADER_DATA(&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;
+
+ /* Closure memory will be overwritten, so read required variables now. */
+ Bssrdf *bssrdf = (Bssrdf *)sc;
+ ClosureType bssrdf_type = sc->type;
+ float bssrdf_roughness = bssrdf->roughness;
+
+ /* 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_addrspace(&branched_state->path_state,
+ 0x68bc21eb);
+ }
+ int num_samples = kernel_data.integrator.subsurface_samples * 3;
+ float num_samples_inv = 1.0f / num_samples;
+ uint bssrdf_rng_hash = cmj_hash(branched_state->path_state.rng_hash, 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 PathState *hit_state = &kernel_split_state.path_state[ray_index];
+ *hit_state = branched_state->path_state;
+ hit_state->rng_hash = bssrdf_rng_hash;
+ path_state_branch(hit_state, j, num_samples);
+
+ ccl_global LocalIntersection *ss_isect = &branched_state->ss_isect;
+ float bssrdf_u, bssrdf_v;
+ path_branched_rng_2D(
+ kg, bssrdf_rng_hash, hit_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) {
+ uint lcg_state = branched_state->lcg_state;
+ LocalIntersection ss_isect_private;
+
+ branched_state->num_hits = subsurface_scatter_multi_intersect(
+ kg, &ss_isect_private, sd, hit_state, sc, &lcg_state, bssrdf_u, bssrdf_v, true);
+
+ branched_state->lcg_state = lcg_state;
+ *ss_isect = ss_isect_private;
+ }
+
+ hit_state->rng_offset += PRNG_BOUNCE_NUM;
+
+# 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_sd(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 */
+
+ LocalIntersection ss_isect_private = *ss_isect;
+ subsurface_scatter_multi_setup(
+ kg, &ss_isect_private, hit, bssrdf_sd, hit_state, bssrdf_type, bssrdf_roughness);
+ *ss_isect = ss_isect_private;
+
+# 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);
+
+ for (int k = 0; k < VOLUME_STACK_SIZE; k++) {
+ hit_state->volume_stack[k] = branched_state->path_state.volume_stack[k];
+ }
+
+ kernel_volume_stack_update_for_subsurface(
+ kg, emission_sd, &volume_ray, hit_state->volume_stack);
+ }
+# 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) ||
+ (hit_state->flag & PATH_RAY_SHADOW_CATCHER);
+ kernel_branched_path_surface_connect_light(kg,
+ 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, 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;
+ }
+
+ branched_state->ss_next_closure = sd->num_closure;
+
+ branched_state->waiting_on_shared_samples = (branched_state->shared_sample_count > 0);
+ if (branched_state->waiting_on_shared_samples) {
+ return true;
+ }
+
+ kernel_split_branched_path_indirect_loop_end(kg, ray_index);
+
+ return false;
}
-#endif /* __BRANCHED_PATH__ && __SUBSURFACE__ */
+#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;
- }
-
- 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,
- 1);
- get_ray_index(kg, thread_index,
- QUEUE_HITBG_BUFF_UPDATE_TOREGEN_RAYS,
- kernel_split_state.queue_data,
- kernel_split_params.queue_size,
- 1);
+ 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;
+ }
+
+ 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,
+ 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;
-
- if(IS_STATE(ray_state, ray_index, RAY_ACTIVE)) {
- ccl_global PathState *state = &kernel_split_state.path_state[ray_index];
- PathRadiance *L = &kernel_split_state.path_radiance[ray_index];
- ccl_global Ray *ray = &kernel_split_state.ray[ray_index];
- ccl_global float3 *throughput = &kernel_split_state.throughput[ray_index];
- ccl_global SubsurfaceIndirectRays *ss_indirect = &kernel_split_state.ss_rays[ray_index];
- ShaderData *sd = kernel_split_sd(sd, ray_index);
- ShaderData *emission_sd = AS_SHADER_DATA(&kernel_split_state.sd_DL_shadow[ray_index]);
-
- if(sd->flag & SD_BSSRDF) {
-
-#ifdef __BRANCHED_PATH__
- if(!kernel_data.integrator.branched ||
- IS_FLAG(ray_state, ray_index, RAY_BRANCHED_INDIRECT))
- {
-#endif
- if(kernel_path_subsurface_scatter(kg,
- sd,
- emission_sd,
- L,
- state,
- ray,
- throughput,
- ss_indirect))
- {
- kernel_split_path_end(kg, ray_index);
- }
-#ifdef __BRANCHED_PATH__
- }
- 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
- }
- }
+ ccl_global char *ray_state = kernel_split_state.ray_state;
+
+ if (IS_STATE(ray_state, ray_index, RAY_ACTIVE)) {
+ ccl_global PathState *state = &kernel_split_state.path_state[ray_index];
+ PathRadiance *L = &kernel_split_state.path_radiance[ray_index];
+ ccl_global Ray *ray = &kernel_split_state.ray[ray_index];
+ ccl_global float3 *throughput = &kernel_split_state.throughput[ray_index];
+ ccl_global SubsurfaceIndirectRays *ss_indirect = &kernel_split_state.ss_rays[ray_index];
+ ShaderData *sd = kernel_split_sd(sd, ray_index);
+ ShaderData *emission_sd = AS_SHADER_DATA(&kernel_split_state.sd_DL_shadow[ray_index]);
+
+ if (sd->flag & SD_BSSRDF) {
# ifdef __BRANCHED_PATH__
- if(ccl_global_id(0) == 0 && ccl_global_id(1) == 0) {
- kernel_split_params.queue_index[QUEUE_SUBSURFACE_INDIRECT_ITER] = 0;
- }
-
- /* 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__ */
+ if (!kernel_data.integrator.branched ||
+ IS_FLAG(ray_state, ray_index, RAY_BRANCHED_INDIRECT)) {
+# endif
+ if (kernel_path_subsurface_scatter(
+ kg, sd, emission_sd, L, state, ray, throughput, ss_indirect)) {
+ kernel_split_path_end(kg, ray_index);
+ }
+# ifdef __BRANCHED_PATH__
+ }
+ 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
+ }
+ }
+# ifdef __BRANCHED_PATH__
+ if (ccl_global_id(0) == 0 && ccl_global_id(1) == 0) {
+ kernel_split_params.queue_index[QUEUE_SUBSURFACE_INDIRECT_ITER] = 0;
+ }
+
+ /* 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__ */
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/svm/svm.h b/intern/cycles/kernel/svm/svm.h
index ccb9aef7a5b..4a386afa5de 100644
--- a/intern/cycles/kernel/svm/svm.h
+++ b/intern/cycles/kernel/svm/svm.h
@@ -46,92 +46,102 @@ CCL_NAMESPACE_BEGIN
ccl_device_inline float3 stack_load_float3(float *stack, uint a)
{
- kernel_assert(a+2 < SVM_STACK_SIZE);
+ kernel_assert(a + 2 < SVM_STACK_SIZE);
- return make_float3(stack[a+0], stack[a+1], stack[a+2]);
+ return make_float3(stack[a + 0], stack[a + 1], stack[a + 2]);
}
ccl_device_inline void stack_store_float3(float *stack, uint a, float3 f)
{
- kernel_assert(a+2 < SVM_STACK_SIZE);
+ kernel_assert(a + 2 < SVM_STACK_SIZE);
- stack[a+0] = f.x;
- stack[a+1] = f.y;
- stack[a+2] = f.z;
+ stack[a + 0] = f.x;
+ stack[a + 1] = f.y;
+ stack[a + 2] = f.z;
}
ccl_device_inline float stack_load_float(float *stack, uint a)
{
- kernel_assert(a < SVM_STACK_SIZE);
+ kernel_assert(a < SVM_STACK_SIZE);
- return stack[a];
+ return stack[a];
}
ccl_device_inline float stack_load_float_default(float *stack, uint a, uint value)
{
- return (a == (uint)SVM_STACK_INVALID)? __uint_as_float(value): stack_load_float(stack, a);
+ return (a == (uint)SVM_STACK_INVALID) ? __uint_as_float(value) : stack_load_float(stack, a);
}
ccl_device_inline void stack_store_float(float *stack, uint a, float f)
{
- kernel_assert(a < SVM_STACK_SIZE);
+ kernel_assert(a < SVM_STACK_SIZE);
- stack[a] = f;
+ stack[a] = f;
}
ccl_device_inline int stack_load_int(float *stack, uint a)
{
- kernel_assert(a < SVM_STACK_SIZE);
+ kernel_assert(a < SVM_STACK_SIZE);
- return __float_as_int(stack[a]);
+ return __float_as_int(stack[a]);
}
ccl_device_inline int stack_load_int_default(float *stack, uint a, uint value)
{
- return (a == (uint)SVM_STACK_INVALID)? (int)value: stack_load_int(stack, a);
+ return (a == (uint)SVM_STACK_INVALID) ? (int)value : stack_load_int(stack, a);
}
ccl_device_inline void stack_store_int(float *stack, uint a, int i)
{
- kernel_assert(a < SVM_STACK_SIZE);
+ kernel_assert(a < SVM_STACK_SIZE);
- stack[a] = __int_as_float(i);
+ stack[a] = __int_as_float(i);
}
ccl_device_inline bool stack_valid(uint a)
{
- return a != (uint)SVM_STACK_INVALID;
+ return a != (uint)SVM_STACK_INVALID;
}
/* Reading Nodes */
ccl_device_inline uint4 read_node(KernelGlobals *kg, int *offset)
{
- uint4 node = kernel_tex_fetch(__svm_nodes, *offset);
- (*offset)++;
- return node;
+ uint4 node = kernel_tex_fetch(__svm_nodes, *offset);
+ (*offset)++;
+ return node;
}
ccl_device_inline float4 read_node_float(KernelGlobals *kg, int *offset)
{
- uint4 node = kernel_tex_fetch(__svm_nodes, *offset);
- float4 f = make_float4(__uint_as_float(node.x), __uint_as_float(node.y), __uint_as_float(node.z), __uint_as_float(node.w));
- (*offset)++;
- return f;
+ uint4 node = kernel_tex_fetch(__svm_nodes, *offset);
+ float4 f = make_float4(__uint_as_float(node.x),
+ __uint_as_float(node.y),
+ __uint_as_float(node.z),
+ __uint_as_float(node.w));
+ (*offset)++;
+ return f;
}
ccl_device_inline float4 fetch_node_float(KernelGlobals *kg, int offset)
{
- uint4 node = kernel_tex_fetch(__svm_nodes, offset);
- return make_float4(__uint_as_float(node.x), __uint_as_float(node.y), __uint_as_float(node.z), __uint_as_float(node.w));
+ uint4 node = kernel_tex_fetch(__svm_nodes, offset);
+ return make_float4(__uint_as_float(node.x),
+ __uint_as_float(node.y),
+ __uint_as_float(node.z),
+ __uint_as_float(node.w));
}
ccl_device_inline void decode_node_uchar4(uint i, uint *x, uint *y, uint *z, uint *w)
{
- if(x) *x = (i & 0xFF);
- if(y) *y = ((i >> 8) & 0xFF);
- if(z) *z = ((i >> 16) & 0xFF);
- if(w) *w = ((i >> 24) & 0xFF);
+ if (x)
+ *x = (i & 0xFF);
+ if (y)
+ *y = ((i >> 8) & 0xFF);
+ if (z)
+ *z = ((i >> 16) & 0xFF);
+ if (w)
+ *w = ((i >> 24) & 0xFF);
}
CCL_NAMESPACE_END
@@ -194,302 +204,310 @@ CCL_NAMESPACE_BEGIN
#define NODES_FEATURE(feature) ((__NODES_FEATURES__ & (feature)) != 0)
/* Main Interpreter Loop */
-ccl_device_noinline void svm_eval_nodes(KernelGlobals *kg, ShaderData *sd, ccl_addr_space PathState *state, ShaderType type, int path_flag)
+ccl_device_noinline void svm_eval_nodes(KernelGlobals *kg,
+ ShaderData *sd,
+ ccl_addr_space PathState *state,
+ ShaderType type,
+ int path_flag)
{
- float stack[SVM_STACK_SIZE];
- int offset = sd->shader & SHADER_MASK;
+ float stack[SVM_STACK_SIZE];
+ int offset = sd->shader & SHADER_MASK;
- while(1) {
- uint4 node = read_node(kg, &offset);
+ while (1) {
+ uint4 node = read_node(kg, &offset);
- switch(node.x) {
+ switch (node.x) {
#if NODES_GROUP(NODE_GROUP_LEVEL_0)
- case NODE_SHADER_JUMP: {
- if(type == SHADER_TYPE_SURFACE) offset = node.y;
- else if(type == SHADER_TYPE_VOLUME) offset = node.z;
- else if(type == SHADER_TYPE_DISPLACEMENT) offset = node.w;
- else return;
- break;
- }
- case NODE_CLOSURE_BSDF:
- svm_node_closure_bsdf(kg, sd, stack, node, type, path_flag, &offset);
- break;
- case NODE_CLOSURE_EMISSION:
- svm_node_closure_emission(sd, stack, node);
- break;
- case NODE_CLOSURE_BACKGROUND:
- svm_node_closure_background(sd, stack, node);
- break;
- case NODE_CLOSURE_SET_WEIGHT:
- svm_node_closure_set_weight(sd, node.y, node.z, node.w);
- break;
- case NODE_CLOSURE_WEIGHT:
- svm_node_closure_weight(sd, stack, node.y);
- break;
- case NODE_EMISSION_WEIGHT:
- svm_node_emission_weight(kg, sd, stack, node);
- break;
- case NODE_MIX_CLOSURE:
- svm_node_mix_closure(sd, stack, node);
- break;
- case NODE_JUMP_IF_ZERO:
- if(stack_load_float(stack, node.z) == 0.0f)
- offset += node.y;
- break;
- case NODE_JUMP_IF_ONE:
- if(stack_load_float(stack, node.z) == 1.0f)
- offset += node.y;
- break;
- case NODE_GEOMETRY:
- svm_node_geometry(kg, sd, stack, node.y, node.z);
- break;
- case NODE_CONVERT:
- svm_node_convert(kg, sd, stack, node.y, node.z, node.w);
- break;
- case NODE_TEX_COORD:
- svm_node_tex_coord(kg, sd, path_flag, stack, node, &offset);
- break;
- case NODE_VALUE_F:
- svm_node_value_f(kg, sd, stack, node.y, node.z);
- break;
- case NODE_VALUE_V:
- svm_node_value_v(kg, sd, stack, node.y, &offset);
- break;
- case NODE_ATTR:
- svm_node_attr(kg, sd, stack, node);
- break;
+ case NODE_SHADER_JUMP: {
+ if (type == SHADER_TYPE_SURFACE)
+ offset = node.y;
+ else if (type == SHADER_TYPE_VOLUME)
+ offset = node.z;
+ else if (type == SHADER_TYPE_DISPLACEMENT)
+ offset = node.w;
+ else
+ return;
+ break;
+ }
+ case NODE_CLOSURE_BSDF:
+ svm_node_closure_bsdf(kg, sd, stack, node, type, path_flag, &offset);
+ break;
+ case NODE_CLOSURE_EMISSION:
+ svm_node_closure_emission(sd, stack, node);
+ break;
+ case NODE_CLOSURE_BACKGROUND:
+ svm_node_closure_background(sd, stack, node);
+ break;
+ case NODE_CLOSURE_SET_WEIGHT:
+ svm_node_closure_set_weight(sd, node.y, node.z, node.w);
+ break;
+ case NODE_CLOSURE_WEIGHT:
+ svm_node_closure_weight(sd, stack, node.y);
+ break;
+ case NODE_EMISSION_WEIGHT:
+ svm_node_emission_weight(kg, sd, stack, node);
+ break;
+ case NODE_MIX_CLOSURE:
+ svm_node_mix_closure(sd, stack, node);
+ break;
+ case NODE_JUMP_IF_ZERO:
+ if (stack_load_float(stack, node.z) == 0.0f)
+ offset += node.y;
+ break;
+ case NODE_JUMP_IF_ONE:
+ if (stack_load_float(stack, node.z) == 1.0f)
+ offset += node.y;
+ break;
+ case NODE_GEOMETRY:
+ svm_node_geometry(kg, sd, stack, node.y, node.z);
+ break;
+ case NODE_CONVERT:
+ svm_node_convert(kg, sd, stack, node.y, node.z, node.w);
+ break;
+ case NODE_TEX_COORD:
+ svm_node_tex_coord(kg, sd, path_flag, stack, node, &offset);
+ break;
+ case NODE_VALUE_F:
+ svm_node_value_f(kg, sd, stack, node.y, node.z);
+ break;
+ case NODE_VALUE_V:
+ svm_node_value_v(kg, sd, stack, node.y, &offset);
+ break;
+ case NODE_ATTR:
+ svm_node_attr(kg, sd, stack, node);
+ break;
# if NODES_FEATURE(NODE_FEATURE_BUMP)
- case NODE_GEOMETRY_BUMP_DX:
- svm_node_geometry_bump_dx(kg, sd, stack, node.y, node.z);
- break;
- case NODE_GEOMETRY_BUMP_DY:
- svm_node_geometry_bump_dy(kg, sd, stack, node.y, node.z);
- break;
- case NODE_SET_DISPLACEMENT:
- svm_node_set_displacement(kg, sd, stack, node.y);
- break;
- case NODE_DISPLACEMENT:
- svm_node_displacement(kg, sd, stack, node);
- break;
- case NODE_VECTOR_DISPLACEMENT:
- svm_node_vector_displacement(kg, sd, stack, node, &offset);
- break;
-# endif /* NODES_FEATURE(NODE_FEATURE_BUMP) */
+ case NODE_GEOMETRY_BUMP_DX:
+ svm_node_geometry_bump_dx(kg, sd, stack, node.y, node.z);
+ break;
+ case NODE_GEOMETRY_BUMP_DY:
+ svm_node_geometry_bump_dy(kg, sd, stack, node.y, node.z);
+ break;
+ case NODE_SET_DISPLACEMENT:
+ svm_node_set_displacement(kg, sd, stack, node.y);
+ break;
+ case NODE_DISPLACEMENT:
+ svm_node_displacement(kg, sd, stack, node);
+ break;
+ case NODE_VECTOR_DISPLACEMENT:
+ svm_node_vector_displacement(kg, sd, stack, node, &offset);
+ break;
+# endif /* NODES_FEATURE(NODE_FEATURE_BUMP) */
# ifdef __TEXTURES__
- case NODE_TEX_IMAGE:
- svm_node_tex_image(kg, sd, stack, node);
- break;
- case NODE_TEX_IMAGE_BOX:
- svm_node_tex_image_box(kg, sd, stack, node);
- break;
- case NODE_TEX_NOISE:
- svm_node_tex_noise(kg, sd, stack, node, &offset);
- break;
-# endif /* __TEXTURES__ */
+ case NODE_TEX_IMAGE:
+ svm_node_tex_image(kg, sd, stack, node);
+ break;
+ case NODE_TEX_IMAGE_BOX:
+ svm_node_tex_image_box(kg, sd, stack, node);
+ break;
+ case NODE_TEX_NOISE:
+ svm_node_tex_noise(kg, sd, stack, node, &offset);
+ break;
+# endif /* __TEXTURES__ */
# ifdef __EXTRA_NODES__
# if NODES_FEATURE(NODE_FEATURE_BUMP)
- case NODE_SET_BUMP:
- svm_node_set_bump(kg, sd, stack, node);
- break;
- case NODE_ATTR_BUMP_DX:
- svm_node_attr_bump_dx(kg, sd, stack, node);
- break;
- case NODE_ATTR_BUMP_DY:
- svm_node_attr_bump_dy(kg, sd, stack, node);
- break;
- case NODE_TEX_COORD_BUMP_DX:
- svm_node_tex_coord_bump_dx(kg, sd, path_flag, stack, node, &offset);
- break;
- case NODE_TEX_COORD_BUMP_DY:
- svm_node_tex_coord_bump_dy(kg, sd, path_flag, stack, node, &offset);
- break;
- case NODE_CLOSURE_SET_NORMAL:
- svm_node_set_normal(kg, sd, stack, node.y, node.z);
- break;
+ case NODE_SET_BUMP:
+ svm_node_set_bump(kg, sd, stack, node);
+ break;
+ case NODE_ATTR_BUMP_DX:
+ svm_node_attr_bump_dx(kg, sd, stack, node);
+ break;
+ case NODE_ATTR_BUMP_DY:
+ svm_node_attr_bump_dy(kg, sd, stack, node);
+ break;
+ case NODE_TEX_COORD_BUMP_DX:
+ svm_node_tex_coord_bump_dx(kg, sd, path_flag, stack, node, &offset);
+ break;
+ case NODE_TEX_COORD_BUMP_DY:
+ svm_node_tex_coord_bump_dy(kg, sd, path_flag, stack, node, &offset);
+ break;
+ case NODE_CLOSURE_SET_NORMAL:
+ svm_node_set_normal(kg, sd, stack, node.y, node.z);
+ break;
# if NODES_FEATURE(NODE_FEATURE_BUMP_STATE)
- case NODE_ENTER_BUMP_EVAL:
- svm_node_enter_bump_eval(kg, sd, stack, node.y);
- break;
- case NODE_LEAVE_BUMP_EVAL:
- svm_node_leave_bump_eval(kg, sd, stack, node.y);
- break;
-# endif /* NODES_FEATURE(NODE_FEATURE_BUMP_STATE) */
-# endif /* NODES_FEATURE(NODE_FEATURE_BUMP) */
- case NODE_HSV:
- svm_node_hsv(kg, sd, stack, node, &offset);
- break;
-# endif /* __EXTRA_NODES__ */
-#endif /* NODES_GROUP(NODE_GROUP_LEVEL_0) */
+ case NODE_ENTER_BUMP_EVAL:
+ svm_node_enter_bump_eval(kg, sd, stack, node.y);
+ break;
+ case NODE_LEAVE_BUMP_EVAL:
+ svm_node_leave_bump_eval(kg, sd, stack, node.y);
+ break;
+# endif /* NODES_FEATURE(NODE_FEATURE_BUMP_STATE) */
+# endif /* NODES_FEATURE(NODE_FEATURE_BUMP) */
+ case NODE_HSV:
+ svm_node_hsv(kg, sd, stack, node, &offset);
+ break;
+# endif /* __EXTRA_NODES__ */
+#endif /* NODES_GROUP(NODE_GROUP_LEVEL_0) */
#if NODES_GROUP(NODE_GROUP_LEVEL_1)
- case NODE_CLOSURE_HOLDOUT:
- svm_node_closure_holdout(sd, stack, node);
- break;
- case NODE_FRESNEL:
- svm_node_fresnel(sd, stack, node.y, node.z, node.w);
- break;
- case NODE_LAYER_WEIGHT:
- svm_node_layer_weight(sd, stack, node);
- break;
+ case NODE_CLOSURE_HOLDOUT:
+ svm_node_closure_holdout(sd, stack, node);
+ break;
+ case NODE_FRESNEL:
+ svm_node_fresnel(sd, stack, node.y, node.z, node.w);
+ break;
+ case NODE_LAYER_WEIGHT:
+ svm_node_layer_weight(sd, stack, node);
+ break;
# if NODES_FEATURE(NODE_FEATURE_VOLUME)
- case NODE_CLOSURE_VOLUME:
- svm_node_closure_volume(kg, sd, stack, node, type);
- break;
- case NODE_PRINCIPLED_VOLUME:
- svm_node_principled_volume(kg, sd, stack, node, type, path_flag, &offset);
- break;
-# endif /* NODES_FEATURE(NODE_FEATURE_VOLUME) */
+ case NODE_CLOSURE_VOLUME:
+ svm_node_closure_volume(kg, sd, stack, node, type);
+ break;
+ case NODE_PRINCIPLED_VOLUME:
+ svm_node_principled_volume(kg, sd, stack, node, type, path_flag, &offset);
+ break;
+# endif /* NODES_FEATURE(NODE_FEATURE_VOLUME) */
# ifdef __EXTRA_NODES__
- case NODE_MATH:
- svm_node_math(kg, sd, stack, node.y, node.z, node.w, &offset);
- break;
- case NODE_VECTOR_MATH:
- svm_node_vector_math(kg, sd, stack, node.y, node.z, node.w, &offset);
- break;
- case NODE_RGB_RAMP:
- svm_node_rgb_ramp(kg, sd, stack, node, &offset);
- break;
- case NODE_GAMMA:
- svm_node_gamma(sd, stack, node.y, node.z, node.w);
- break;
- case NODE_BRIGHTCONTRAST:
- svm_node_brightness(sd, stack, node.y, node.z, node.w);
- break;
- case NODE_LIGHT_PATH:
- svm_node_light_path(sd, state, stack, node.y, node.z, path_flag);
- break;
- case NODE_OBJECT_INFO:
- svm_node_object_info(kg, sd, stack, node.y, node.z);
- break;
- case NODE_PARTICLE_INFO:
- svm_node_particle_info(kg, sd, stack, node.y, node.z);
- break;
+ case NODE_MATH:
+ svm_node_math(kg, sd, stack, node.y, node.z, node.w, &offset);
+ break;
+ case NODE_VECTOR_MATH:
+ svm_node_vector_math(kg, sd, stack, node.y, node.z, node.w, &offset);
+ break;
+ case NODE_RGB_RAMP:
+ svm_node_rgb_ramp(kg, sd, stack, node, &offset);
+ break;
+ case NODE_GAMMA:
+ svm_node_gamma(sd, stack, node.y, node.z, node.w);
+ break;
+ case NODE_BRIGHTCONTRAST:
+ svm_node_brightness(sd, stack, node.y, node.z, node.w);
+ break;
+ case NODE_LIGHT_PATH:
+ svm_node_light_path(sd, state, stack, node.y, node.z, path_flag);
+ break;
+ case NODE_OBJECT_INFO:
+ svm_node_object_info(kg, sd, stack, node.y, node.z);
+ break;
+ case NODE_PARTICLE_INFO:
+ svm_node_particle_info(kg, sd, stack, node.y, node.z);
+ break;
# ifdef __HAIR__
# if NODES_FEATURE(NODE_FEATURE_HAIR)
- case NODE_HAIR_INFO:
- svm_node_hair_info(kg, sd, stack, node.y, node.z);
- break;
-# endif /* NODES_FEATURE(NODE_FEATURE_HAIR) */
-# endif /* __HAIR__ */
-# endif /* __EXTRA_NODES__ */
-#endif /* NODES_GROUP(NODE_GROUP_LEVEL_1) */
+ case NODE_HAIR_INFO:
+ svm_node_hair_info(kg, sd, stack, node.y, node.z);
+ break;
+# endif /* NODES_FEATURE(NODE_FEATURE_HAIR) */
+# endif /* __HAIR__ */
+# endif /* __EXTRA_NODES__ */
+#endif /* NODES_GROUP(NODE_GROUP_LEVEL_1) */
#if NODES_GROUP(NODE_GROUP_LEVEL_2)
- case NODE_MAPPING:
- svm_node_mapping(kg, sd, stack, node.y, node.z, &offset);
- break;
- case NODE_MIN_MAX:
- svm_node_min_max(kg, sd, stack, node.y, node.z, &offset);
- break;
- case NODE_CAMERA:
- svm_node_camera(kg, sd, stack, node.y, node.z, node.w);
- break;
+ case NODE_MAPPING:
+ svm_node_mapping(kg, sd, stack, node.y, node.z, &offset);
+ break;
+ case NODE_MIN_MAX:
+ svm_node_min_max(kg, sd, stack, node.y, node.z, &offset);
+ break;
+ case NODE_CAMERA:
+ svm_node_camera(kg, sd, stack, node.y, node.z, node.w);
+ break;
# ifdef __TEXTURES__
- case NODE_TEX_ENVIRONMENT:
- svm_node_tex_environment(kg, sd, stack, node);
- break;
- case NODE_TEX_SKY:
- svm_node_tex_sky(kg, sd, stack, node, &offset);
- break;
- case NODE_TEX_GRADIENT:
- svm_node_tex_gradient(sd, stack, node);
- break;
- case NODE_TEX_VORONOI:
- svm_node_tex_voronoi(kg, sd, stack, node, &offset);
- break;
- case NODE_TEX_MUSGRAVE:
- svm_node_tex_musgrave(kg, sd, stack, node, &offset);
- break;
- case NODE_TEX_WAVE:
- svm_node_tex_wave(kg, sd, stack, node, &offset);
- break;
- case NODE_TEX_MAGIC:
- svm_node_tex_magic(kg, sd, stack, node, &offset);
- break;
- case NODE_TEX_CHECKER:
- svm_node_tex_checker(kg, sd, stack, node);
- break;
- case NODE_TEX_BRICK:
- svm_node_tex_brick(kg, sd, stack, node, &offset);
- break;
-# endif /* __TEXTURES__ */
+ case NODE_TEX_ENVIRONMENT:
+ svm_node_tex_environment(kg, sd, stack, node);
+ break;
+ case NODE_TEX_SKY:
+ svm_node_tex_sky(kg, sd, stack, node, &offset);
+ break;
+ case NODE_TEX_GRADIENT:
+ svm_node_tex_gradient(sd, stack, node);
+ break;
+ case NODE_TEX_VORONOI:
+ svm_node_tex_voronoi(kg, sd, stack, node, &offset);
+ break;
+ case NODE_TEX_MUSGRAVE:
+ svm_node_tex_musgrave(kg, sd, stack, node, &offset);
+ break;
+ case NODE_TEX_WAVE:
+ svm_node_tex_wave(kg, sd, stack, node, &offset);
+ break;
+ case NODE_TEX_MAGIC:
+ svm_node_tex_magic(kg, sd, stack, node, &offset);
+ break;
+ case NODE_TEX_CHECKER:
+ svm_node_tex_checker(kg, sd, stack, node);
+ break;
+ case NODE_TEX_BRICK:
+ svm_node_tex_brick(kg, sd, stack, node, &offset);
+ break;
+# endif /* __TEXTURES__ */
# ifdef __EXTRA_NODES__
- case NODE_NORMAL:
- svm_node_normal(kg, sd, stack, node.y, node.z, node.w, &offset);
- break;
- case NODE_LIGHT_FALLOFF:
- svm_node_light_falloff(sd, stack, node);
- break;
- case NODE_IES:
- svm_node_ies(kg, sd, stack, node, &offset);
- break;
-# endif /* __EXTRA_NODES__ */
-#endif /* NODES_GROUP(NODE_GROUP_LEVEL_2) */
+ case NODE_NORMAL:
+ svm_node_normal(kg, sd, stack, node.y, node.z, node.w, &offset);
+ break;
+ case NODE_LIGHT_FALLOFF:
+ svm_node_light_falloff(sd, stack, node);
+ break;
+ case NODE_IES:
+ svm_node_ies(kg, sd, stack, node, &offset);
+ break;
+# endif /* __EXTRA_NODES__ */
+#endif /* NODES_GROUP(NODE_GROUP_LEVEL_2) */
#if NODES_GROUP(NODE_GROUP_LEVEL_3)
- case NODE_RGB_CURVES:
- case NODE_VECTOR_CURVES:
- svm_node_curves(kg, sd, stack, node, &offset);
- break;
- case NODE_TANGENT:
- svm_node_tangent(kg, sd, stack, node);
- break;
- case NODE_NORMAL_MAP:
- svm_node_normal_map(kg, sd, stack, node);
- break;
+ case NODE_RGB_CURVES:
+ case NODE_VECTOR_CURVES:
+ svm_node_curves(kg, sd, stack, node, &offset);
+ break;
+ case NODE_TANGENT:
+ svm_node_tangent(kg, sd, stack, node);
+ break;
+ case NODE_NORMAL_MAP:
+ svm_node_normal_map(kg, sd, stack, node);
+ break;
# ifdef __EXTRA_NODES__
- case NODE_INVERT:
- svm_node_invert(sd, stack, node.y, node.z, node.w);
- break;
- case NODE_MIX:
- svm_node_mix(kg, sd, stack, node.y, node.z, node.w, &offset);
- break;
- case NODE_SEPARATE_VECTOR:
- svm_node_separate_vector(sd, stack, node.y, node.z, node.w);
- break;
- case NODE_COMBINE_VECTOR:
- svm_node_combine_vector(sd, stack, node.y, node.z, node.w);
- break;
- case NODE_SEPARATE_HSV:
- svm_node_separate_hsv(kg, sd, stack, node.y, node.z, node.w, &offset);
- break;
- case NODE_COMBINE_HSV:
- svm_node_combine_hsv(kg, sd, stack, node.y, node.z, node.w, &offset);
- break;
- case NODE_VECTOR_TRANSFORM:
- svm_node_vector_transform(kg, sd, stack, node);
- break;
- case NODE_WIREFRAME:
- svm_node_wireframe(kg, sd, stack, node);
- break;
- case NODE_WAVELENGTH:
- svm_node_wavelength(kg, sd, stack, node.y, node.z);
- break;
- case NODE_BLACKBODY:
- svm_node_blackbody(kg, sd, stack, node.y, node.z);
- break;
-# endif /* __EXTRA_NODES__ */
+ case NODE_INVERT:
+ svm_node_invert(sd, stack, node.y, node.z, node.w);
+ break;
+ case NODE_MIX:
+ svm_node_mix(kg, sd, stack, node.y, node.z, node.w, &offset);
+ break;
+ case NODE_SEPARATE_VECTOR:
+ svm_node_separate_vector(sd, stack, node.y, node.z, node.w);
+ break;
+ case NODE_COMBINE_VECTOR:
+ svm_node_combine_vector(sd, stack, node.y, node.z, node.w);
+ break;
+ case NODE_SEPARATE_HSV:
+ svm_node_separate_hsv(kg, sd, stack, node.y, node.z, node.w, &offset);
+ break;
+ case NODE_COMBINE_HSV:
+ svm_node_combine_hsv(kg, sd, stack, node.y, node.z, node.w, &offset);
+ break;
+ case NODE_VECTOR_TRANSFORM:
+ svm_node_vector_transform(kg, sd, stack, node);
+ break;
+ case NODE_WIREFRAME:
+ svm_node_wireframe(kg, sd, stack, node);
+ break;
+ case NODE_WAVELENGTH:
+ svm_node_wavelength(kg, sd, stack, node.y, node.z);
+ break;
+ case NODE_BLACKBODY:
+ svm_node_blackbody(kg, sd, stack, node.y, node.z);
+ break;
+# endif /* __EXTRA_NODES__ */
# if NODES_FEATURE(NODE_FEATURE_VOLUME)
- case NODE_TEX_VOXEL:
- svm_node_tex_voxel(kg, sd, stack, node, &offset);
- break;
-# endif /* NODES_FEATURE(NODE_FEATURE_VOLUME) */
+ case NODE_TEX_VOXEL:
+ svm_node_tex_voxel(kg, sd, stack, node, &offset);
+ break;
+# endif /* NODES_FEATURE(NODE_FEATURE_VOLUME) */
# ifdef __SHADER_RAYTRACE__
- case NODE_BEVEL:
- svm_node_bevel(kg, sd, state, stack, node);
- break;
- case NODE_AMBIENT_OCCLUSION:
- svm_node_ao(kg, sd, state, stack, node);
- break;
-# endif /* __SHADER_RAYTRACE__ */
-#endif /* NODES_GROUP(NODE_GROUP_LEVEL_3) */
- case NODE_END:
- return;
- default:
- kernel_assert(!"Unknown node type was passed to the SVM machine");
- return;
- }
- }
+ case NODE_BEVEL:
+ svm_node_bevel(kg, sd, state, stack, node);
+ break;
+ case NODE_AMBIENT_OCCLUSION:
+ svm_node_ao(kg, sd, state, stack, node);
+ break;
+# endif /* __SHADER_RAYTRACE__ */
+#endif /* NODES_GROUP(NODE_GROUP_LEVEL_3) */
+ case NODE_END:
+ return;
+ default:
+ kernel_assert(!"Unknown node type was passed to the SVM machine");
+ return;
+ }
+ }
}
#undef NODES_GROUP
@@ -497,4 +515,4 @@ ccl_device_noinline void svm_eval_nodes(KernelGlobals *kg, ShaderData *sd, ccl_a
CCL_NAMESPACE_END
-#endif /* __SVM_H__ */
+#endif /* __SVM_H__ */
diff --git a/intern/cycles/kernel/svm/svm_ao.h b/intern/cycles/kernel/svm/svm_ao.h
index 0744ec1768f..06076175c40 100644
--- a/intern/cycles/kernel/svm/svm_ao.h
+++ b/intern/cycles/kernel/svm/svm_ao.h
@@ -24,95 +24,82 @@ ccl_device_noinline float svm_ao(KernelGlobals *kg,
int num_samples,
int flags)
{
- if(flags & NODE_AO_GLOBAL_RADIUS) {
- max_dist = kernel_data.background.ao_distance;
- }
-
- /* Early out if no sampling needed. */
- if(max_dist <= 0.0f || num_samples < 1 || sd->object == OBJECT_NONE) {
- return 1.0f;
- }
-
- /* Can't raytrace from shaders like displacement, before BVH exists. */
- if (kernel_data.bvh.bvh_layout == BVH_LAYOUT_NONE) {
- return 1.0f;
- }
-
- if(flags & NODE_AO_INSIDE) {
- N = -N;
- }
-
- float3 T, B;
- make_orthonormals(N, &T, &B);
-
- int unoccluded = 0;
- for(int sample = 0; sample < num_samples; sample++) {
- float disk_u, disk_v;
- path_branched_rng_2D(kg, state->rng_hash, state, sample, num_samples,
- PRNG_BEVEL_U, &disk_u, &disk_v);
-
- float2 d = concentric_sample_disk(disk_u, disk_v);
- float3 D = make_float3(d.x, d.y, safe_sqrtf(1.0f - dot(d, d)));
-
- /* Create ray. */
- Ray ray;
- ray.P = ray_offset(sd->P, N);
- ray.D = D.x*T + D.y*B + D.z*N;
- ray.t = max_dist;
- ray.time = sd->time;
- ray.dP = sd->dP;
- ray.dD = differential3_zero();
-
- if(flags & NODE_AO_ONLY_LOCAL) {
- if(!scene_intersect_local(kg,
- ray,
- NULL,
- sd->object,
- NULL,
- 0)) {
- unoccluded++;
- }
- }
- else {
- Intersection isect;
- if(!scene_intersect(kg,
- ray,
- PATH_RAY_SHADOW_OPAQUE,
- &isect,
- NULL,
- 0.0f, 0.0f)) {
- unoccluded++;
- }
- }
- }
-
- return ((float) unoccluded) / num_samples;
+ if (flags & NODE_AO_GLOBAL_RADIUS) {
+ max_dist = kernel_data.background.ao_distance;
+ }
+
+ /* Early out if no sampling needed. */
+ if (max_dist <= 0.0f || num_samples < 1 || sd->object == OBJECT_NONE) {
+ return 1.0f;
+ }
+
+ /* Can't raytrace from shaders like displacement, before BVH exists. */
+ if (kernel_data.bvh.bvh_layout == BVH_LAYOUT_NONE) {
+ return 1.0f;
+ }
+
+ if (flags & NODE_AO_INSIDE) {
+ N = -N;
+ }
+
+ float3 T, B;
+ make_orthonormals(N, &T, &B);
+
+ int unoccluded = 0;
+ for (int sample = 0; sample < num_samples; sample++) {
+ float disk_u, disk_v;
+ path_branched_rng_2D(
+ kg, state->rng_hash, state, sample, num_samples, PRNG_BEVEL_U, &disk_u, &disk_v);
+
+ float2 d = concentric_sample_disk(disk_u, disk_v);
+ float3 D = make_float3(d.x, d.y, safe_sqrtf(1.0f - dot(d, d)));
+
+ /* Create ray. */
+ Ray ray;
+ ray.P = ray_offset(sd->P, N);
+ ray.D = D.x * T + D.y * B + D.z * N;
+ ray.t = max_dist;
+ ray.time = sd->time;
+ ray.dP = sd->dP;
+ ray.dD = differential3_zero();
+
+ if (flags & NODE_AO_ONLY_LOCAL) {
+ if (!scene_intersect_local(kg, ray, NULL, sd->object, NULL, 0)) {
+ unoccluded++;
+ }
+ }
+ else {
+ Intersection isect;
+ if (!scene_intersect(kg, ray, PATH_RAY_SHADOW_OPAQUE, &isect, NULL, 0.0f, 0.0f)) {
+ unoccluded++;
+ }
+ }
+ }
+
+ return ((float)unoccluded) / num_samples;
}
-ccl_device void svm_node_ao(KernelGlobals *kg,
- ShaderData *sd,
- ccl_addr_space PathState *state,
- float *stack,
- uint4 node)
+ccl_device void svm_node_ao(
+ KernelGlobals *kg, ShaderData *sd, ccl_addr_space PathState *state, float *stack, uint4 node)
{
- uint flags, dist_offset, normal_offset, out_ao_offset;
- decode_node_uchar4(node.y, &flags, &dist_offset, &normal_offset, &out_ao_offset);
+ uint flags, dist_offset, normal_offset, out_ao_offset;
+ decode_node_uchar4(node.y, &flags, &dist_offset, &normal_offset, &out_ao_offset);
- uint color_offset, out_color_offset, samples;
- decode_node_uchar4(node.z, &color_offset, &out_color_offset, &samples, NULL);
+ uint color_offset, out_color_offset, samples;
+ decode_node_uchar4(node.z, &color_offset, &out_color_offset, &samples, NULL);
- float dist = stack_load_float_default(stack, dist_offset, node.w);
- float3 normal = stack_valid(normal_offset)? stack_load_float3(stack, normal_offset): sd->N;
- float ao = svm_ao(kg, sd, normal, state, dist, samples, flags);
+ float dist = stack_load_float_default(stack, dist_offset, node.w);
+ float3 normal = stack_valid(normal_offset) ? stack_load_float3(stack, normal_offset) : sd->N;
+ float ao = svm_ao(kg, sd, normal, state, dist, samples, flags);
- if(stack_valid(out_ao_offset)) {
- stack_store_float(stack, out_ao_offset, ao);
- }
+ if (stack_valid(out_ao_offset)) {
+ stack_store_float(stack, out_ao_offset, ao);
+ }
- if(stack_valid(out_color_offset)) {
- float3 color = stack_load_float3(stack, color_offset);
- stack_store_float3(stack, out_color_offset, ao * color);
- }
+ if (stack_valid(out_color_offset)) {
+ float3 color = stack_load_float3(stack, color_offset);
+ stack_store_float3(stack, out_color_offset, ao * color);
+ }
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/svm/svm_attribute.h b/intern/cycles/kernel/svm/svm_attribute.h
index c2366df71d0..a67cfe91a30 100644
--- a/intern/cycles/kernel/svm/svm_attribute.h
+++ b/intern/cycles/kernel/svm/svm_attribute.h
@@ -18,67 +18,66 @@ CCL_NAMESPACE_BEGIN
/* Attribute Node */
-ccl_device AttributeDescriptor svm_node_attr_init(KernelGlobals *kg, ShaderData *sd,
- uint4 node, NodeAttributeType *type,
- uint *out_offset)
+ccl_device AttributeDescriptor svm_node_attr_init(
+ KernelGlobals *kg, ShaderData *sd, uint4 node, NodeAttributeType *type, uint *out_offset)
{
- *out_offset = node.z;
- *type = (NodeAttributeType)node.w;
+ *out_offset = node.z;
+ *type = (NodeAttributeType)node.w;
- AttributeDescriptor desc;
+ AttributeDescriptor desc;
- if(sd->object != OBJECT_NONE) {
- desc = find_attribute(kg, sd, node.y);
- if(desc.offset == ATTR_STD_NOT_FOUND) {
- desc = attribute_not_found();
- desc.offset = 0;
- desc.type = (NodeAttributeType)node.w;
- }
- }
- else {
- /* background */
- desc = attribute_not_found();
- desc.offset = 0;
- desc.type = (NodeAttributeType)node.w;
- }
+ if (sd->object != OBJECT_NONE) {
+ desc = find_attribute(kg, sd, node.y);
+ if (desc.offset == ATTR_STD_NOT_FOUND) {
+ desc = attribute_not_found();
+ desc.offset = 0;
+ desc.type = (NodeAttributeType)node.w;
+ }
+ }
+ else {
+ /* background */
+ desc = attribute_not_found();
+ desc.offset = 0;
+ desc.type = (NodeAttributeType)node.w;
+ }
- return desc;
+ return desc;
}
ccl_device void svm_node_attr(KernelGlobals *kg, ShaderData *sd, float *stack, uint4 node)
{
- NodeAttributeType type;
- uint out_offset;
- AttributeDescriptor desc = svm_node_attr_init(kg, sd, node, &type, &out_offset);
+ NodeAttributeType type;
+ uint out_offset;
+ AttributeDescriptor desc = svm_node_attr_init(kg, sd, node, &type, &out_offset);
- /* fetch and store attribute */
- if(desc.type == NODE_ATTR_FLOAT) {
- float f = primitive_attribute_float(kg, sd, desc, NULL, NULL);
- if(type == NODE_ATTR_FLOAT) {
- stack_store_float(stack, out_offset, f);
- }
- else {
- stack_store_float3(stack, out_offset, make_float3(f, f, f));
- }
- }
- else if(desc.type == NODE_ATTR_FLOAT2) {
- float2 f = primitive_attribute_float2(kg, sd, desc, NULL, NULL);
- if(type == NODE_ATTR_FLOAT) {
- stack_store_float(stack, out_offset, f.x);
- }
- else {
- stack_store_float3(stack, out_offset, make_float3(f.x, f.y, 0.0f));
- }
- }
- else {
- float3 f = primitive_attribute_float3(kg, sd, desc, NULL, NULL);
- if(type == NODE_ATTR_FLOAT) {
- stack_store_float(stack, out_offset, average(f));
- }
- else {
- stack_store_float3(stack, out_offset, f);
- }
- }
+ /* fetch and store attribute */
+ if (desc.type == NODE_ATTR_FLOAT) {
+ float f = primitive_attribute_float(kg, sd, desc, NULL, NULL);
+ if (type == NODE_ATTR_FLOAT) {
+ stack_store_float(stack, out_offset, f);
+ }
+ else {
+ stack_store_float3(stack, out_offset, make_float3(f, f, f));
+ }
+ }
+ else if (desc.type == NODE_ATTR_FLOAT2) {
+ float2 f = primitive_attribute_float2(kg, sd, desc, NULL, NULL);
+ if (type == NODE_ATTR_FLOAT) {
+ stack_store_float(stack, out_offset, f.x);
+ }
+ else {
+ stack_store_float3(stack, out_offset, make_float3(f.x, f.y, 0.0f));
+ }
+ }
+ else {
+ float3 f = primitive_attribute_float3(kg, sd, desc, NULL, NULL);
+ if (type == NODE_ATTR_FLOAT) {
+ stack_store_float(stack, out_offset, average(f));
+ }
+ else {
+ stack_store_float3(stack, out_offset, f);
+ }
+ }
}
#ifndef __KERNEL_CUDA__
@@ -86,43 +85,44 @@ ccl_device
#else
ccl_device_noinline
#endif
-void svm_node_attr_bump_dx(KernelGlobals *kg, ShaderData *sd, float *stack, uint4 node)
+ void
+ svm_node_attr_bump_dx(KernelGlobals *kg, ShaderData *sd, float *stack, uint4 node)
{
- NodeAttributeType type;
- uint out_offset;
- AttributeDescriptor desc = svm_node_attr_init(kg, sd, node, &type, &out_offset);
+ NodeAttributeType type;
+ uint out_offset;
+ AttributeDescriptor desc = svm_node_attr_init(kg, sd, node, &type, &out_offset);
- /* fetch and store attribute */
- if(desc.type == NODE_ATTR_FLOAT) {
- float dx;
- float f = primitive_surface_attribute_float(kg, sd, desc, &dx, NULL);
- if(type == NODE_ATTR_FLOAT) {
- stack_store_float(stack, out_offset, f+dx);
- }
- else {
- stack_store_float3(stack, out_offset, make_float3(f+dx, f+dx, f+dx));
- }
- }
- else if(desc.type == NODE_ATTR_FLOAT2) {
- float2 dx;
- float2 f = primitive_attribute_float2(kg, sd, desc, &dx, NULL);
- if (type == NODE_ATTR_FLOAT) {
- stack_store_float(stack, out_offset, f.x + dx.x);
- }
- else {
- stack_store_float3(stack, out_offset, make_float3(f.x+dx.x, f.y+dx.y, 0.0f));
- }
- }
- else {
- float3 dx;
- float3 f = primitive_surface_attribute_float3(kg, sd, desc, &dx, NULL);
- if(type == NODE_ATTR_FLOAT) {
- stack_store_float(stack, out_offset, average(f+dx));
- }
- else {
- stack_store_float3(stack, out_offset, f+dx);
- }
- }
+ /* fetch and store attribute */
+ if (desc.type == NODE_ATTR_FLOAT) {
+ float dx;
+ float f = primitive_surface_attribute_float(kg, sd, desc, &dx, NULL);
+ if (type == NODE_ATTR_FLOAT) {
+ stack_store_float(stack, out_offset, f + dx);
+ }
+ else {
+ stack_store_float3(stack, out_offset, make_float3(f + dx, f + dx, f + dx));
+ }
+ }
+ else if (desc.type == NODE_ATTR_FLOAT2) {
+ float2 dx;
+ float2 f = primitive_attribute_float2(kg, sd, desc, &dx, NULL);
+ if (type == NODE_ATTR_FLOAT) {
+ stack_store_float(stack, out_offset, f.x + dx.x);
+ }
+ else {
+ stack_store_float3(stack, out_offset, make_float3(f.x + dx.x, f.y + dx.y, 0.0f));
+ }
+ }
+ else {
+ float3 dx;
+ float3 f = primitive_surface_attribute_float3(kg, sd, desc, &dx, NULL);
+ if (type == NODE_ATTR_FLOAT) {
+ stack_store_float(stack, out_offset, average(f + dx));
+ }
+ else {
+ stack_store_float3(stack, out_offset, f + dx);
+ }
+ }
}
#ifndef __KERNEL_CUDA__
@@ -130,46 +130,44 @@ ccl_device
#else
ccl_device_noinline
#endif
-void svm_node_attr_bump_dy(KernelGlobals *kg,
- ShaderData *sd,
- float *stack,
- uint4 node)
+ void
+ svm_node_attr_bump_dy(KernelGlobals *kg, ShaderData *sd, float *stack, uint4 node)
{
- NodeAttributeType type;
- uint out_offset;
- AttributeDescriptor desc = svm_node_attr_init(kg, sd, node, &type, &out_offset);
+ NodeAttributeType type;
+ uint out_offset;
+ AttributeDescriptor desc = svm_node_attr_init(kg, sd, node, &type, &out_offset);
- /* fetch and store attribute */
- if(desc.type == NODE_ATTR_FLOAT) {
- float dy;
- float f = primitive_surface_attribute_float(kg, sd, desc, NULL, &dy);
- if(type == NODE_ATTR_FLOAT) {
- stack_store_float(stack, out_offset, f+dy);
- }
- else {
- stack_store_float3(stack, out_offset, make_float3(f+dy, f+dy, f+dy));
- }
- }
- else if(desc.type == NODE_ATTR_FLOAT2) {
- float2 dy;
- float2 f = primitive_attribute_float2(kg, sd, desc, NULL, &dy);
- if(type == NODE_ATTR_FLOAT) {
- stack_store_float(stack, out_offset, f.x + dy.x);
- }
- else {
- stack_store_float3(stack, out_offset, make_float3(f.x+dy.x, f.y+dy.y, 0.0f));
- }
- }
- else {
- float3 dy;
- float3 f = primitive_surface_attribute_float3(kg, sd, desc, NULL, &dy);
- if(type == NODE_ATTR_FLOAT) {
- stack_store_float(stack, out_offset, average(f+dy));
- }
- else {
- stack_store_float3(stack, out_offset, f+dy);
- }
- }
+ /* fetch and store attribute */
+ if (desc.type == NODE_ATTR_FLOAT) {
+ float dy;
+ float f = primitive_surface_attribute_float(kg, sd, desc, NULL, &dy);
+ if (type == NODE_ATTR_FLOAT) {
+ stack_store_float(stack, out_offset, f + dy);
+ }
+ else {
+ stack_store_float3(stack, out_offset, make_float3(f + dy, f + dy, f + dy));
+ }
+ }
+ else if (desc.type == NODE_ATTR_FLOAT2) {
+ float2 dy;
+ float2 f = primitive_attribute_float2(kg, sd, desc, NULL, &dy);
+ if (type == NODE_ATTR_FLOAT) {
+ stack_store_float(stack, out_offset, f.x + dy.x);
+ }
+ else {
+ stack_store_float3(stack, out_offset, make_float3(f.x + dy.x, f.y + dy.y, 0.0f));
+ }
+ }
+ else {
+ float3 dy;
+ float3 f = primitive_surface_attribute_float3(kg, sd, desc, NULL, &dy);
+ if (type == NODE_ATTR_FLOAT) {
+ stack_store_float(stack, out_offset, average(f + dy));
+ }
+ else {
+ stack_store_float3(stack, out_offset, f + dy);
+ }
+ }
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/svm/svm_bevel.h b/intern/cycles/kernel/svm/svm_bevel.h
index b5bb9df422b..fcf28e96e98 100644
--- a/intern/cycles/kernel/svm/svm_bevel.h
+++ b/intern/cycles/kernel/svm/svm_bevel.h
@@ -22,215 +22,196 @@ CCL_NAMESPACE_BEGIN
* http://library.imageworks.com/pdfs/imageworks-library-BSSRDF-sampling.pdf
*/
-ccl_device_noinline float3 svm_bevel(
- KernelGlobals *kg,
- ShaderData *sd,
- ccl_addr_space PathState *state,
- float radius,
- int num_samples)
+ccl_device_noinline float3 svm_bevel(KernelGlobals *kg,
+ ShaderData *sd,
+ ccl_addr_space PathState *state,
+ float radius,
+ int num_samples)
{
- /* Early out if no sampling needed. */
- if(radius <= 0.0f || num_samples < 1 || sd->object == OBJECT_NONE) {
- return sd->N;
- }
-
- /* Can't raytrace from shaders like displacement, before BVH exists. */
- if (kernel_data.bvh.bvh_layout == BVH_LAYOUT_NONE) {
- return sd->N;
- }
-
- /* Don't bevel for blurry indirect rays. */
- if(state->min_ray_pdf < 8.0f) {
- return sd->N;
- }
-
- /* Setup for multi intersection. */
- LocalIntersection isect;
- uint lcg_state = lcg_state_init_addrspace(state, 0x64c6a40e);
-
- /* Sample normals from surrounding points on surface. */
- float3 sum_N = make_float3(0.0f, 0.0f, 0.0f);
-
- for(int sample = 0; sample < num_samples; sample++) {
- float disk_u, disk_v;
- path_branched_rng_2D(kg, state->rng_hash, state, sample, num_samples,
- PRNG_BEVEL_U, &disk_u, &disk_v);
-
- /* Pick random axis in local frame and point on disk. */
- float3 disk_N, disk_T, disk_B;
- float pick_pdf_N, pick_pdf_T, pick_pdf_B;
-
- disk_N = sd->Ng;
- make_orthonormals(disk_N, &disk_T, &disk_B);
-
- float axisu = disk_u;
-
- if(axisu < 0.5f) {
- pick_pdf_N = 0.5f;
- pick_pdf_T = 0.25f;
- pick_pdf_B = 0.25f;
- disk_u *= 2.0f;
- }
- else if(axisu < 0.75f) {
- float3 tmp = disk_N;
- disk_N = disk_T;
- disk_T = tmp;
- pick_pdf_N = 0.25f;
- pick_pdf_T = 0.5f;
- pick_pdf_B = 0.25f;
- disk_u = (disk_u - 0.5f)*4.0f;
- }
- else {
- float3 tmp = disk_N;
- disk_N = disk_B;
- disk_B = tmp;
- pick_pdf_N = 0.25f;
- pick_pdf_T = 0.25f;
- pick_pdf_B = 0.5f;
- disk_u = (disk_u - 0.75f)*4.0f;
- }
-
- /* Sample point on disk. */
- float phi = M_2PI_F * disk_u;
- float disk_r = disk_v;
- float disk_height;
-
- /* Perhaps find something better than Cubic BSSRDF, but happens to work well. */
- bssrdf_cubic_sample(radius, 0.0f, disk_r, &disk_r, &disk_height);
-
- float3 disk_P = (disk_r*cosf(phi)) * disk_T + (disk_r*sinf(phi)) * disk_B;
-
- /* Create ray. */
- Ray *ray = &isect.ray;
- ray->P = sd->P + disk_N*disk_height + disk_P;
- ray->D = -disk_N;
- ray->t = 2.0f*disk_height;
- ray->dP = sd->dP;
- ray->dD = differential3_zero();
- ray->time = sd->time;
-
- /* Intersect with the same object. if multiple intersections are found it
- * will use at most LOCAL_MAX_HITS hits, a random subset of all hits. */
- scene_intersect_local(kg,
- *ray,
- &isect,
- sd->object,
- &lcg_state,
- LOCAL_MAX_HITS);
-
- int num_eval_hits = min(isect.num_hits, LOCAL_MAX_HITS);
-
- for(int hit = 0; hit < num_eval_hits; hit++) {
- /* Quickly retrieve P and Ng without setting up ShaderData. */
- float3 hit_P;
- if(sd->type & PRIMITIVE_TRIANGLE) {
- hit_P = triangle_refine_local(kg,
- sd,
- &isect.hits[hit],
- ray);
- }
+ /* Early out if no sampling needed. */
+ if (radius <= 0.0f || num_samples < 1 || sd->object == OBJECT_NONE) {
+ return sd->N;
+ }
+
+ /* Can't raytrace from shaders like displacement, before BVH exists. */
+ if (kernel_data.bvh.bvh_layout == BVH_LAYOUT_NONE) {
+ return sd->N;
+ }
+
+ /* Don't bevel for blurry indirect rays. */
+ if (state->min_ray_pdf < 8.0f) {
+ return sd->N;
+ }
+
+ /* Setup for multi intersection. */
+ LocalIntersection isect;
+ uint lcg_state = lcg_state_init_addrspace(state, 0x64c6a40e);
+
+ /* Sample normals from surrounding points on surface. */
+ float3 sum_N = make_float3(0.0f, 0.0f, 0.0f);
+
+ for (int sample = 0; sample < num_samples; sample++) {
+ float disk_u, disk_v;
+ path_branched_rng_2D(
+ kg, state->rng_hash, state, sample, num_samples, PRNG_BEVEL_U, &disk_u, &disk_v);
+
+ /* Pick random axis in local frame and point on disk. */
+ float3 disk_N, disk_T, disk_B;
+ float pick_pdf_N, pick_pdf_T, pick_pdf_B;
+
+ disk_N = sd->Ng;
+ make_orthonormals(disk_N, &disk_T, &disk_B);
+
+ float axisu = disk_u;
+
+ if (axisu < 0.5f) {
+ pick_pdf_N = 0.5f;
+ pick_pdf_T = 0.25f;
+ pick_pdf_B = 0.25f;
+ disk_u *= 2.0f;
+ }
+ else if (axisu < 0.75f) {
+ float3 tmp = disk_N;
+ disk_N = disk_T;
+ disk_T = tmp;
+ pick_pdf_N = 0.25f;
+ pick_pdf_T = 0.5f;
+ pick_pdf_B = 0.25f;
+ disk_u = (disk_u - 0.5f) * 4.0f;
+ }
+ else {
+ float3 tmp = disk_N;
+ disk_N = disk_B;
+ disk_B = tmp;
+ pick_pdf_N = 0.25f;
+ pick_pdf_T = 0.25f;
+ pick_pdf_B = 0.5f;
+ disk_u = (disk_u - 0.75f) * 4.0f;
+ }
+
+ /* Sample point on disk. */
+ float phi = M_2PI_F * disk_u;
+ float disk_r = disk_v;
+ float disk_height;
+
+ /* Perhaps find something better than Cubic BSSRDF, but happens to work well. */
+ bssrdf_cubic_sample(radius, 0.0f, disk_r, &disk_r, &disk_height);
+
+ float3 disk_P = (disk_r * cosf(phi)) * disk_T + (disk_r * sinf(phi)) * disk_B;
+
+ /* Create ray. */
+ Ray *ray = &isect.ray;
+ ray->P = sd->P + disk_N * disk_height + disk_P;
+ ray->D = -disk_N;
+ ray->t = 2.0f * disk_height;
+ ray->dP = sd->dP;
+ ray->dD = differential3_zero();
+ ray->time = sd->time;
+
+ /* Intersect with the same object. if multiple intersections are found it
+ * will use at most LOCAL_MAX_HITS hits, a random subset of all hits. */
+ scene_intersect_local(kg, *ray, &isect, sd->object, &lcg_state, LOCAL_MAX_HITS);
+
+ int num_eval_hits = min(isect.num_hits, LOCAL_MAX_HITS);
+
+ for (int hit = 0; hit < num_eval_hits; hit++) {
+ /* Quickly retrieve P and Ng without setting up ShaderData. */
+ float3 hit_P;
+ if (sd->type & PRIMITIVE_TRIANGLE) {
+ hit_P = triangle_refine_local(kg, sd, &isect.hits[hit], ray);
+ }
#ifdef __OBJECT_MOTION__
- else if(sd->type & PRIMITIVE_MOTION_TRIANGLE) {
- float3 verts[3];
- motion_triangle_vertices(
- kg,
- sd->object,
- kernel_tex_fetch(__prim_index, isect.hits[hit].prim),
- sd->time,
- verts);
- hit_P = motion_triangle_refine_local(kg,
- sd,
- &isect.hits[hit],
- ray,
- verts);
- }
-#endif /* __OBJECT_MOTION__ */
-
- /* Get geometric normal. */
- float3 hit_Ng = isect.Ng[hit];
- int object = (isect.hits[hit].object == OBJECT_NONE)? kernel_tex_fetch(__prim_object, isect.hits[hit].prim): isect.hits[hit].object;
- int object_flag = kernel_tex_fetch(__object_flag, object);
- if(object_flag & SD_OBJECT_NEGATIVE_SCALE_APPLIED) {
- hit_Ng = -hit_Ng;
- }
-
- /* Compute smooth normal. */
- float3 N = hit_Ng;
- int prim = kernel_tex_fetch(__prim_index, isect.hits[hit].prim);
- int shader = kernel_tex_fetch(__tri_shader, prim);
-
- if(shader & SHADER_SMOOTH_NORMAL) {
- float u = isect.hits[hit].u;
- float v = isect.hits[hit].v;
-
- if(sd->type & PRIMITIVE_TRIANGLE) {
- N = triangle_smooth_normal(kg, N, prim, u, v);
- }
+ else if (sd->type & PRIMITIVE_MOTION_TRIANGLE) {
+ float3 verts[3];
+ motion_triangle_vertices(
+ kg, sd->object, kernel_tex_fetch(__prim_index, isect.hits[hit].prim), sd->time, verts);
+ hit_P = motion_triangle_refine_local(kg, sd, &isect.hits[hit], ray, verts);
+ }
+#endif /* __OBJECT_MOTION__ */
+
+ /* Get geometric normal. */
+ float3 hit_Ng = isect.Ng[hit];
+ int object = (isect.hits[hit].object == OBJECT_NONE) ?
+ kernel_tex_fetch(__prim_object, isect.hits[hit].prim) :
+ isect.hits[hit].object;
+ int object_flag = kernel_tex_fetch(__object_flag, object);
+ if (object_flag & SD_OBJECT_NEGATIVE_SCALE_APPLIED) {
+ hit_Ng = -hit_Ng;
+ }
+
+ /* Compute smooth normal. */
+ float3 N = hit_Ng;
+ int prim = kernel_tex_fetch(__prim_index, isect.hits[hit].prim);
+ int shader = kernel_tex_fetch(__tri_shader, prim);
+
+ if (shader & SHADER_SMOOTH_NORMAL) {
+ float u = isect.hits[hit].u;
+ float v = isect.hits[hit].v;
+
+ if (sd->type & PRIMITIVE_TRIANGLE) {
+ N = triangle_smooth_normal(kg, N, prim, u, v);
+ }
#ifdef __OBJECT_MOTION__
- else if(sd->type & PRIMITIVE_MOTION_TRIANGLE) {
- N = motion_triangle_smooth_normal(kg, N, sd->object, prim, u, v, sd->time);
- }
-#endif /* __OBJECT_MOTION__ */
- }
-
- /* Transform normals to world space. */
- if(!(object_flag & SD_OBJECT_TRANSFORM_APPLIED)) {
- object_normal_transform(kg, sd, &N);
- object_normal_transform(kg, sd, &hit_Ng);
- }
-
- /* Probability densities for local frame axes. */
- float pdf_N = pick_pdf_N * fabsf(dot(disk_N, hit_Ng));
- float pdf_T = pick_pdf_T * fabsf(dot(disk_T, hit_Ng));
- float pdf_B = pick_pdf_B * fabsf(dot(disk_B, hit_Ng));
-
- /* Multiple importance sample between 3 axes, power heuristic
- * found to be slightly better than balance heuristic. pdf_N
- * in the MIS weight and denominator cancelled out. */
- float w = pdf_N / (sqr(pdf_N) + sqr(pdf_T) + sqr(pdf_B));
- if(isect.num_hits > LOCAL_MAX_HITS) {
- w *= isect.num_hits/(float)LOCAL_MAX_HITS;
- }
-
- /* Real distance to sampled point. */
- float r = len(hit_P - sd->P);
-
- /* Compute weight. */
- float pdf = bssrdf_cubic_pdf(radius, 0.0f, r);
- float disk_pdf = bssrdf_cubic_pdf(radius, 0.0f, disk_r);
-
- w *= pdf / disk_pdf;
-
- /* Sum normal and weight. */
- sum_N += w * N;
- }
- }
-
- /* Normalize. */
- float3 N = safe_normalize(sum_N);
- return is_zero(N) ? sd->N : (sd->flag & SD_BACKFACING) ? -N : N;
+ else if (sd->type & PRIMITIVE_MOTION_TRIANGLE) {
+ N = motion_triangle_smooth_normal(kg, N, sd->object, prim, u, v, sd->time);
+ }
+#endif /* __OBJECT_MOTION__ */
+ }
+
+ /* Transform normals to world space. */
+ if (!(object_flag & SD_OBJECT_TRANSFORM_APPLIED)) {
+ object_normal_transform(kg, sd, &N);
+ object_normal_transform(kg, sd, &hit_Ng);
+ }
+
+ /* Probability densities for local frame axes. */
+ float pdf_N = pick_pdf_N * fabsf(dot(disk_N, hit_Ng));
+ float pdf_T = pick_pdf_T * fabsf(dot(disk_T, hit_Ng));
+ float pdf_B = pick_pdf_B * fabsf(dot(disk_B, hit_Ng));
+
+ /* Multiple importance sample between 3 axes, power heuristic
+ * found to be slightly better than balance heuristic. pdf_N
+ * in the MIS weight and denominator cancelled out. */
+ float w = pdf_N / (sqr(pdf_N) + sqr(pdf_T) + sqr(pdf_B));
+ if (isect.num_hits > LOCAL_MAX_HITS) {
+ w *= isect.num_hits / (float)LOCAL_MAX_HITS;
+ }
+
+ /* Real distance to sampled point. */
+ float r = len(hit_P - sd->P);
+
+ /* Compute weight. */
+ float pdf = bssrdf_cubic_pdf(radius, 0.0f, r);
+ float disk_pdf = bssrdf_cubic_pdf(radius, 0.0f, disk_r);
+
+ w *= pdf / disk_pdf;
+
+ /* Sum normal and weight. */
+ sum_N += w * N;
+ }
+ }
+
+ /* Normalize. */
+ float3 N = safe_normalize(sum_N);
+ return is_zero(N) ? sd->N : (sd->flag & SD_BACKFACING) ? -N : N;
}
ccl_device void svm_node_bevel(
- KernelGlobals *kg,
- ShaderData *sd,
- ccl_addr_space PathState *state,
- float *stack,
- uint4 node)
+ KernelGlobals *kg, ShaderData *sd, ccl_addr_space PathState *state, float *stack, uint4 node)
{
- uint num_samples, radius_offset, normal_offset, out_offset;
- decode_node_uchar4(node.y, &num_samples, &radius_offset, &normal_offset, &out_offset);
+ uint num_samples, radius_offset, normal_offset, out_offset;
+ decode_node_uchar4(node.y, &num_samples, &radius_offset, &normal_offset, &out_offset);
- float radius = stack_load_float(stack, radius_offset);
- float3 bevel_N = svm_bevel(kg, sd, state, radius, num_samples);
+ float radius = stack_load_float(stack, radius_offset);
+ float3 bevel_N = svm_bevel(kg, sd, state, radius, num_samples);
- if(stack_valid(normal_offset)) {
- /* Preserve input normal. */
- float3 ref_N = stack_load_float3(stack, normal_offset);
- bevel_N = normalize(ref_N + (bevel_N - sd->N));
- }
+ if (stack_valid(normal_offset)) {
+ /* Preserve input normal. */
+ float3 ref_N = stack_load_float3(stack, normal_offset);
+ bevel_N = normalize(ref_N + (bevel_N - sd->N));
+ }
- stack_store_float3(stack, out_offset, bevel_N);
+ stack_store_float3(stack, out_offset, bevel_N);
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/svm/svm_blackbody.h b/intern/cycles/kernel/svm/svm_blackbody.h
index 51590b18505..adfc50d961e 100644
--- a/intern/cycles/kernel/svm/svm_blackbody.h
+++ b/intern/cycles/kernel/svm/svm_blackbody.h
@@ -34,14 +34,15 @@ CCL_NAMESPACE_BEGIN
/* Blackbody Node */
-ccl_device void svm_node_blackbody(KernelGlobals *kg, ShaderData *sd, float *stack, uint temperature_offset, uint col_offset)
+ccl_device void svm_node_blackbody(
+ KernelGlobals *kg, ShaderData *sd, float *stack, uint temperature_offset, uint col_offset)
{
- /* Input */
- float temperature = stack_load_float(stack, temperature_offset);
+ /* Input */
+ float temperature = stack_load_float(stack, temperature_offset);
- float3 color_rgb = svm_math_blackbody_color(temperature);
+ float3 color_rgb = svm_math_blackbody_color(temperature);
- stack_store_float3(stack, col_offset, color_rgb);
+ stack_store_float3(stack, col_offset, color_rgb);
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/svm/svm_brick.h b/intern/cycles/kernel/svm/svm_brick.h
index 744d9ff16c5..b5cbfcc72df 100644
--- a/intern/cycles/kernel/svm/svm_brick.h
+++ b/intern/cycles/kernel/svm/svm_brick.h
@@ -20,101 +20,119 @@ CCL_NAMESPACE_BEGIN
ccl_device_noinline float brick_noise(uint n) /* fast integer noise */
{
- uint nn;
- n = (n + 1013) & 0x7fffffff;
- n = (n >> 13) ^ n;
- nn = (n * (n * n * 60493 + 19990303) + 1376312589) & 0x7fffffff;
- return 0.5f * ((float)nn / 1073741824.0f);
+ uint nn;
+ n = (n + 1013) & 0x7fffffff;
+ n = (n >> 13) ^ n;
+ nn = (n * (n * n * 60493 + 19990303) + 1376312589) & 0x7fffffff;
+ return 0.5f * ((float)nn / 1073741824.0f);
}
-ccl_device_noinline float2 svm_brick(float3 p, float mortar_size, float mortar_smooth, float bias,
- float brick_width, float row_height, float offset_amount, int offset_frequency,
- float squash_amount, int squash_frequency)
+ccl_device_noinline float2 svm_brick(float3 p,
+ float mortar_size,
+ float mortar_smooth,
+ float bias,
+ float brick_width,
+ float row_height,
+ float offset_amount,
+ int offset_frequency,
+ float squash_amount,
+ int squash_frequency)
{
- int bricknum, rownum;
- float offset = 0.0f;
- float x, y;
-
- rownum = floor_to_int(p.y / row_height);
-
- if(offset_frequency && squash_frequency) {
- brick_width *= (rownum % squash_frequency) ? 1.0f : squash_amount; /* squash */
- offset = (rownum % offset_frequency) ? 0.0f : (brick_width*offset_amount); /* offset */
- }
-
- bricknum = floor_to_int((p.x+offset) / brick_width);
-
- x = (p.x+offset) - brick_width*bricknum;
- y = p.y - row_height*rownum;
-
- float tint = saturate((brick_noise((rownum << 16) + (bricknum & 0xFFFF)) + bias));
- float min_dist = min(min(x, y), min(brick_width - x, row_height - y));
-
- float mortar;
- if(min_dist >= mortar_size) {
- mortar = 0.0f;
- }
- else if(mortar_smooth == 0.0f) {
- mortar = 1.0f;
- }
- else {
- min_dist = 1.0f - min_dist/mortar_size;
- mortar = (min_dist < mortar_smooth)? smoothstepf(min_dist / mortar_smooth) : 1.0f;
- }
-
- return make_float2(tint, mortar);
+ int bricknum, rownum;
+ float offset = 0.0f;
+ float x, y;
+
+ rownum = floor_to_int(p.y / row_height);
+
+ if (offset_frequency && squash_frequency) {
+ brick_width *= (rownum % squash_frequency) ? 1.0f : squash_amount; /* squash */
+ offset = (rownum % offset_frequency) ? 0.0f : (brick_width * offset_amount); /* offset */
+ }
+
+ bricknum = floor_to_int((p.x + offset) / brick_width);
+
+ x = (p.x + offset) - brick_width * bricknum;
+ y = p.y - row_height * rownum;
+
+ float tint = saturate((brick_noise((rownum << 16) + (bricknum & 0xFFFF)) + bias));
+ float min_dist = min(min(x, y), min(brick_width - x, row_height - y));
+
+ float mortar;
+ if (min_dist >= mortar_size) {
+ mortar = 0.0f;
+ }
+ else if (mortar_smooth == 0.0f) {
+ mortar = 1.0f;
+ }
+ else {
+ min_dist = 1.0f - min_dist / mortar_size;
+ mortar = (min_dist < mortar_smooth) ? smoothstepf(min_dist / mortar_smooth) : 1.0f;
+ }
+
+ return make_float2(tint, mortar);
}
-ccl_device void svm_node_tex_brick(KernelGlobals *kg, ShaderData *sd, float *stack, uint4 node, int *offset)
+ccl_device void svm_node_tex_brick(
+ KernelGlobals *kg, ShaderData *sd, float *stack, uint4 node, int *offset)
{
- uint4 node2 = read_node(kg, offset);
- uint4 node3 = read_node(kg, offset);
- uint4 node4 = read_node(kg, offset);
-
- /* Input and Output Sockets */
- uint co_offset, color1_offset, color2_offset, mortar_offset, scale_offset;
- uint mortar_size_offset, bias_offset, brick_width_offset, row_height_offset;
- uint color_offset, fac_offset, mortar_smooth_offset;
-
- /* RNA properties */
- uint offset_frequency, squash_frequency;
-
- decode_node_uchar4(node.y, &co_offset, &color1_offset, &color2_offset, &mortar_offset);
- decode_node_uchar4(node.z, &scale_offset, &mortar_size_offset, &bias_offset, &brick_width_offset);
- decode_node_uchar4(node.w, &row_height_offset, &color_offset, &fac_offset, &mortar_smooth_offset);
-
- decode_node_uchar4(node2.x, &offset_frequency, &squash_frequency, NULL, NULL);
-
- float3 co = stack_load_float3(stack, co_offset);
-
- float3 color1 = stack_load_float3(stack, color1_offset);
- float3 color2 = stack_load_float3(stack, color2_offset);
- float3 mortar = stack_load_float3(stack, mortar_offset);
-
- float scale = stack_load_float_default(stack, scale_offset, node2.y);
- float mortar_size = stack_load_float_default(stack, mortar_size_offset, node2.z);
- float mortar_smooth = stack_load_float_default(stack, mortar_smooth_offset, node4.x);
- float bias = stack_load_float_default(stack, bias_offset, node2.w);
- float brick_width = stack_load_float_default(stack, brick_width_offset, node3.x);
- float row_height = stack_load_float_default(stack, row_height_offset, node3.y);
- float offset_amount = __int_as_float(node3.z);
- float squash_amount = __int_as_float(node3.w);
-
- float2 f2 = svm_brick(co*scale, mortar_size, mortar_smooth, bias, brick_width, row_height,
- offset_amount, offset_frequency, squash_amount, squash_frequency);
-
- float tint = f2.x;
- float f = f2.y;
-
- if(f != 1.0f) {
- float facm = 1.0f - tint;
- color1 = facm * color1 + tint * color2;
- }
-
- if(stack_valid(color_offset))
- stack_store_float3(stack, color_offset, color1*(1.0f-f) + mortar*f);
- if(stack_valid(fac_offset))
- stack_store_float(stack, fac_offset, f);
+ uint4 node2 = read_node(kg, offset);
+ uint4 node3 = read_node(kg, offset);
+ uint4 node4 = read_node(kg, offset);
+
+ /* Input and Output Sockets */
+ uint co_offset, color1_offset, color2_offset, mortar_offset, scale_offset;
+ uint mortar_size_offset, bias_offset, brick_width_offset, row_height_offset;
+ uint color_offset, fac_offset, mortar_smooth_offset;
+
+ /* RNA properties */
+ uint offset_frequency, squash_frequency;
+
+ decode_node_uchar4(node.y, &co_offset, &color1_offset, &color2_offset, &mortar_offset);
+ decode_node_uchar4(
+ node.z, &scale_offset, &mortar_size_offset, &bias_offset, &brick_width_offset);
+ decode_node_uchar4(
+ node.w, &row_height_offset, &color_offset, &fac_offset, &mortar_smooth_offset);
+
+ decode_node_uchar4(node2.x, &offset_frequency, &squash_frequency, NULL, NULL);
+
+ float3 co = stack_load_float3(stack, co_offset);
+
+ float3 color1 = stack_load_float3(stack, color1_offset);
+ float3 color2 = stack_load_float3(stack, color2_offset);
+ float3 mortar = stack_load_float3(stack, mortar_offset);
+
+ float scale = stack_load_float_default(stack, scale_offset, node2.y);
+ float mortar_size = stack_load_float_default(stack, mortar_size_offset, node2.z);
+ float mortar_smooth = stack_load_float_default(stack, mortar_smooth_offset, node4.x);
+ float bias = stack_load_float_default(stack, bias_offset, node2.w);
+ float brick_width = stack_load_float_default(stack, brick_width_offset, node3.x);
+ float row_height = stack_load_float_default(stack, row_height_offset, node3.y);
+ float offset_amount = __int_as_float(node3.z);
+ float squash_amount = __int_as_float(node3.w);
+
+ float2 f2 = svm_brick(co * scale,
+ mortar_size,
+ mortar_smooth,
+ bias,
+ brick_width,
+ row_height,
+ offset_amount,
+ offset_frequency,
+ squash_amount,
+ squash_frequency);
+
+ float tint = f2.x;
+ float f = f2.y;
+
+ if (f != 1.0f) {
+ float facm = 1.0f - tint;
+ color1 = facm * color1 + tint * color2;
+ }
+
+ if (stack_valid(color_offset))
+ stack_store_float3(stack, color_offset, color1 * (1.0f - f) + mortar * f);
+ if (stack_valid(fac_offset))
+ stack_store_float(stack, fac_offset, f);
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/svm/svm_brightness.h b/intern/cycles/kernel/svm/svm_brightness.h
index d71b0ee0b61..dcd75a2fe8f 100644
--- a/intern/cycles/kernel/svm/svm_brightness.h
+++ b/intern/cycles/kernel/svm/svm_brightness.h
@@ -16,19 +16,20 @@
CCL_NAMESPACE_BEGIN
-ccl_device void svm_node_brightness(ShaderData *sd, float *stack, uint in_color, uint out_color, uint node)
+ccl_device void svm_node_brightness(
+ ShaderData *sd, float *stack, uint in_color, uint out_color, uint node)
{
- uint bright_offset, contrast_offset;
- float3 color = stack_load_float3(stack, in_color);
+ uint bright_offset, contrast_offset;
+ float3 color = stack_load_float3(stack, in_color);
- decode_node_uchar4(node, &bright_offset, &contrast_offset, NULL, NULL);
- float brightness = stack_load_float(stack, bright_offset);
- float contrast = stack_load_float(stack, contrast_offset);
+ decode_node_uchar4(node, &bright_offset, &contrast_offset, NULL, NULL);
+ float brightness = stack_load_float(stack, bright_offset);
+ float contrast = stack_load_float(stack, contrast_offset);
- color = svm_brightness_contrast(color, brightness, contrast);
+ color = svm_brightness_contrast(color, brightness, contrast);
- if(stack_valid(out_color))
- stack_store_float3(stack, out_color, color);
+ if (stack_valid(out_color))
+ stack_store_float3(stack, out_color, color);
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/svm/svm_bump.h b/intern/cycles/kernel/svm/svm_bump.h
index 35aac174409..c9d430a2bba 100644
--- a/intern/cycles/kernel/svm/svm_bump.h
+++ b/intern/cycles/kernel/svm/svm_bump.h
@@ -18,36 +18,42 @@ CCL_NAMESPACE_BEGIN
/* Bump Eval Nodes */
-ccl_device void svm_node_enter_bump_eval(KernelGlobals *kg, ShaderData *sd, float *stack, uint offset)
+ccl_device void svm_node_enter_bump_eval(KernelGlobals *kg,
+ ShaderData *sd,
+ float *stack,
+ uint offset)
{
- /* save state */
- stack_store_float3(stack, offset+0, sd->P);
- stack_store_float3(stack, offset+3, sd->dP.dx);
- stack_store_float3(stack, offset+6, sd->dP.dy);
-
- /* set state as if undisplaced */
- const AttributeDescriptor desc = find_attribute(kg, sd, ATTR_STD_POSITION_UNDISPLACED);
-
- if(desc.offset != ATTR_STD_NOT_FOUND) {
- float3 P, dPdx, dPdy;
- P = primitive_surface_attribute_float3(kg, sd, desc, &dPdx, &dPdy);
-
- object_position_transform(kg, sd, &P);
- object_dir_transform(kg, sd, &dPdx);
- object_dir_transform(kg, sd, &dPdy);
-
- sd->P = P;
- sd->dP.dx = dPdx;
- sd->dP.dy = dPdy;
- }
+ /* save state */
+ stack_store_float3(stack, offset + 0, sd->P);
+ stack_store_float3(stack, offset + 3, sd->dP.dx);
+ stack_store_float3(stack, offset + 6, sd->dP.dy);
+
+ /* set state as if undisplaced */
+ const AttributeDescriptor desc = find_attribute(kg, sd, ATTR_STD_POSITION_UNDISPLACED);
+
+ if (desc.offset != ATTR_STD_NOT_FOUND) {
+ float3 P, dPdx, dPdy;
+ P = primitive_surface_attribute_float3(kg, sd, desc, &dPdx, &dPdy);
+
+ object_position_transform(kg, sd, &P);
+ object_dir_transform(kg, sd, &dPdx);
+ object_dir_transform(kg, sd, &dPdy);
+
+ sd->P = P;
+ sd->dP.dx = dPdx;
+ sd->dP.dy = dPdy;
+ }
}
-ccl_device void svm_node_leave_bump_eval(KernelGlobals *kg, ShaderData *sd, float *stack, uint offset)
+ccl_device void svm_node_leave_bump_eval(KernelGlobals *kg,
+ ShaderData *sd,
+ float *stack,
+ uint offset)
{
- /* restore state */
- sd->P = stack_load_float3(stack, offset+0);
- sd->dP.dx = stack_load_float3(stack, offset+3);
- sd->dP.dy = stack_load_float3(stack, offset+6);
+ /* restore state */
+ sd->P = stack_load_float3(stack, offset + 0);
+ sd->dP.dx = stack_load_float3(stack, offset + 3);
+ sd->dP.dy = stack_load_float3(stack, offset + 6);
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/svm/svm_camera.h b/intern/cycles/kernel/svm/svm_camera.h
index cf90229b53b..21a17acf5f1 100644
--- a/intern/cycles/kernel/svm/svm_camera.h
+++ b/intern/cycles/kernel/svm/svm_camera.h
@@ -16,25 +16,30 @@
CCL_NAMESPACE_BEGIN
-ccl_device void svm_node_camera(KernelGlobals *kg, ShaderData *sd, float *stack, uint out_vector, uint out_zdepth, uint out_distance)
+ccl_device void svm_node_camera(KernelGlobals *kg,
+ ShaderData *sd,
+ float *stack,
+ uint out_vector,
+ uint out_zdepth,
+ uint out_distance)
{
- float distance;
- float zdepth;
- float3 vector;
+ float distance;
+ float zdepth;
+ float3 vector;
- Transform tfm = kernel_data.cam.worldtocamera;
- vector = transform_point(&tfm, sd->P);
- zdepth = vector.z;
- distance = len(vector);
+ Transform tfm = kernel_data.cam.worldtocamera;
+ vector = transform_point(&tfm, sd->P);
+ zdepth = vector.z;
+ distance = len(vector);
- if(stack_valid(out_vector))
- stack_store_float3(stack, out_vector, normalize(vector));
+ if (stack_valid(out_vector))
+ stack_store_float3(stack, out_vector, normalize(vector));
- if(stack_valid(out_zdepth))
- stack_store_float(stack, out_zdepth, zdepth);
+ if (stack_valid(out_zdepth))
+ stack_store_float(stack, out_zdepth, zdepth);
- if(stack_valid(out_distance))
- stack_store_float(stack, out_distance, distance);
+ if (stack_valid(out_distance))
+ stack_store_float(stack, out_distance, distance);
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/svm/svm_checker.h b/intern/cycles/kernel/svm/svm_checker.h
index 45e6c181e9e..63b4d1e149b 100644
--- a/intern/cycles/kernel/svm/svm_checker.h
+++ b/intern/cycles/kernel/svm/svm_checker.h
@@ -20,37 +20,37 @@ CCL_NAMESPACE_BEGIN
ccl_device_noinline float svm_checker(float3 p)
{
- /* avoid precision issues on unit coordinates */
- p.x = (p.x + 0.000001f)*0.999999f;
- p.y = (p.y + 0.000001f)*0.999999f;
- p.z = (p.z + 0.000001f)*0.999999f;
+ /* avoid precision issues on unit coordinates */
+ p.x = (p.x + 0.000001f) * 0.999999f;
+ p.y = (p.y + 0.000001f) * 0.999999f;
+ p.z = (p.z + 0.000001f) * 0.999999f;
- int xi = abs(float_to_int(floorf(p.x)));
- int yi = abs(float_to_int(floorf(p.y)));
- int zi = abs(float_to_int(floorf(p.z)));
+ int xi = abs(float_to_int(floorf(p.x)));
+ int yi = abs(float_to_int(floorf(p.y)));
+ int zi = abs(float_to_int(floorf(p.z)));
- return ((xi % 2 == yi % 2) == (zi % 2))? 1.0f: 0.0f;
+ return ((xi % 2 == yi % 2) == (zi % 2)) ? 1.0f : 0.0f;
}
ccl_device void svm_node_tex_checker(KernelGlobals *kg, ShaderData *sd, float *stack, uint4 node)
{
- uint co_offset, color1_offset, color2_offset, scale_offset;
- uint color_offset, fac_offset;
+ uint co_offset, color1_offset, color2_offset, scale_offset;
+ uint color_offset, fac_offset;
- decode_node_uchar4(node.y, &co_offset, &color1_offset, &color2_offset, &scale_offset);
- decode_node_uchar4(node.z, &color_offset, &fac_offset, NULL, NULL);
+ decode_node_uchar4(node.y, &co_offset, &color1_offset, &color2_offset, &scale_offset);
+ decode_node_uchar4(node.z, &color_offset, &fac_offset, NULL, NULL);
- float3 co = stack_load_float3(stack, co_offset);
- float3 color1 = stack_load_float3(stack, color1_offset);
- float3 color2 = stack_load_float3(stack, color2_offset);
- float scale = stack_load_float_default(stack, scale_offset, node.w);
+ float3 co = stack_load_float3(stack, co_offset);
+ float3 color1 = stack_load_float3(stack, color1_offset);
+ float3 color2 = stack_load_float3(stack, color2_offset);
+ float scale = stack_load_float_default(stack, scale_offset, node.w);
- float f = svm_checker(co*scale);
+ float f = svm_checker(co * scale);
- if(stack_valid(color_offset))
- stack_store_float3(stack, color_offset, (f == 1.0f)? color1: color2);
- if(stack_valid(fac_offset))
- stack_store_float(stack, fac_offset, f);
+ if (stack_valid(color_offset))
+ stack_store_float3(stack, color_offset, (f == 1.0f) ? color1 : color2);
+ if (stack_valid(fac_offset))
+ stack_store_float(stack, fac_offset, f);
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/svm/svm_closure.h b/intern/cycles/kernel/svm/svm_closure.h
index a7e87715ed4..270fe4c8615 100644
--- a/intern/cycles/kernel/svm/svm_closure.h
+++ b/intern/cycles/kernel/svm/svm_closure.h
@@ -20,1140 +20,1237 @@ CCL_NAMESPACE_BEGIN
ccl_device_inline float3 sigma_from_concentration(float eumelanin, float pheomelanin)
{
- return eumelanin*make_float3(0.506f, 0.841f, 1.653f) + pheomelanin*make_float3(0.343f, 0.733f, 1.924f);
+ return eumelanin * make_float3(0.506f, 0.841f, 1.653f) +
+ pheomelanin * make_float3(0.343f, 0.733f, 1.924f);
}
ccl_device_inline float3 sigma_from_reflectance(float3 color, float azimuthal_roughness)
{
- float x = azimuthal_roughness;
- float roughness_fac = (((((0.245f*x) + 5.574f)*x - 10.73f)*x + 2.532f)*x - 0.215f)*x + 5.969f;
- float3 sigma = log3(color) / roughness_fac;
- return sigma * sigma;
+ float x = azimuthal_roughness;
+ float roughness_fac = (((((0.245f * x) + 5.574f) * x - 10.73f) * x + 2.532f) * x - 0.215f) * x +
+ 5.969f;
+ float3 sigma = log3(color) / roughness_fac;
+ return sigma * sigma;
}
/* Closure Nodes */
-ccl_device void svm_node_glass_setup(ShaderData *sd, MicrofacetBsdf *bsdf, int type, float eta, float roughness, bool refract)
+ccl_device void svm_node_glass_setup(
+ ShaderData *sd, MicrofacetBsdf *bsdf, int type, float eta, float roughness, bool refract)
{
- if(type == CLOSURE_BSDF_SHARP_GLASS_ID) {
- if(refract) {
- bsdf->alpha_y = 0.0f;
- bsdf->alpha_x = 0.0f;
- bsdf->ior = eta;
- sd->flag |= bsdf_refraction_setup(bsdf);
- }
- else {
- bsdf->alpha_y = 0.0f;
- bsdf->alpha_x = 0.0f;
- bsdf->ior = 0.0f;
- sd->flag |= bsdf_reflection_setup(bsdf);
- }
- }
- else if(type == CLOSURE_BSDF_MICROFACET_BECKMANN_GLASS_ID) {
- bsdf->alpha_x = roughness;
- bsdf->alpha_y = roughness;
- bsdf->ior = eta;
-
- if(refract)
- sd->flag |= bsdf_microfacet_beckmann_refraction_setup(bsdf);
- else
- sd->flag |= bsdf_microfacet_beckmann_setup(bsdf);
- }
- else {
- bsdf->alpha_x = roughness;
- bsdf->alpha_y = roughness;
- bsdf->ior = eta;
-
- if(refract)
- sd->flag |= bsdf_microfacet_ggx_refraction_setup(bsdf);
- else
- sd->flag |= bsdf_microfacet_ggx_setup(bsdf);
- }
+ if (type == CLOSURE_BSDF_SHARP_GLASS_ID) {
+ if (refract) {
+ bsdf->alpha_y = 0.0f;
+ bsdf->alpha_x = 0.0f;
+ bsdf->ior = eta;
+ sd->flag |= bsdf_refraction_setup(bsdf);
+ }
+ else {
+ bsdf->alpha_y = 0.0f;
+ bsdf->alpha_x = 0.0f;
+ bsdf->ior = 0.0f;
+ sd->flag |= bsdf_reflection_setup(bsdf);
+ }
+ }
+ else if (type == CLOSURE_BSDF_MICROFACET_BECKMANN_GLASS_ID) {
+ bsdf->alpha_x = roughness;
+ bsdf->alpha_y = roughness;
+ bsdf->ior = eta;
+
+ if (refract)
+ sd->flag |= bsdf_microfacet_beckmann_refraction_setup(bsdf);
+ else
+ sd->flag |= bsdf_microfacet_beckmann_setup(bsdf);
+ }
+ else {
+ bsdf->alpha_x = roughness;
+ bsdf->alpha_y = roughness;
+ bsdf->ior = eta;
+
+ if (refract)
+ sd->flag |= bsdf_microfacet_ggx_refraction_setup(bsdf);
+ else
+ sd->flag |= bsdf_microfacet_ggx_setup(bsdf);
+ }
}
-ccl_device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *stack, uint4 node, ShaderType shader_type, int path_flag, int *offset)
+ccl_device void svm_node_closure_bsdf(KernelGlobals *kg,
+ ShaderData *sd,
+ float *stack,
+ uint4 node,
+ ShaderType shader_type,
+ int path_flag,
+ int *offset)
{
- uint type, param1_offset, param2_offset;
+ uint type, param1_offset, param2_offset;
- uint mix_weight_offset;
- decode_node_uchar4(node.y, &type, &param1_offset, &param2_offset, &mix_weight_offset);
- float mix_weight = (stack_valid(mix_weight_offset)? stack_load_float(stack, mix_weight_offset): 1.0f);
+ uint mix_weight_offset;
+ decode_node_uchar4(node.y, &type, &param1_offset, &param2_offset, &mix_weight_offset);
+ float mix_weight = (stack_valid(mix_weight_offset) ? stack_load_float(stack, mix_weight_offset) :
+ 1.0f);
- /* note we read this extra node before weight check, so offset is added */
- uint4 data_node = read_node(kg, offset);
+ /* note we read this extra node before weight check, so offset is added */
+ uint4 data_node = read_node(kg, offset);
- /* Only compute BSDF for surfaces, transparent variable is shared with volume extinction. */
- if(mix_weight == 0.0f || shader_type != SHADER_TYPE_SURFACE) {
- if(type == CLOSURE_BSDF_PRINCIPLED_ID) {
- /* Read all principled BSDF extra data to get the right offset. */
- read_node(kg, offset);
- read_node(kg, offset);
- read_node(kg, offset);
- read_node(kg, offset);
- }
+ /* Only compute BSDF for surfaces, transparent variable is shared with volume extinction. */
+ if (mix_weight == 0.0f || shader_type != SHADER_TYPE_SURFACE) {
+ if (type == CLOSURE_BSDF_PRINCIPLED_ID) {
+ /* Read all principled BSDF extra data to get the right offset. */
+ read_node(kg, offset);
+ read_node(kg, offset);
+ read_node(kg, offset);
+ read_node(kg, offset);
+ }
- return;
- }
+ return;
+ }
- float3 N = stack_valid(data_node.x)? stack_load_float3(stack, data_node.x): sd->N;
+ float3 N = stack_valid(data_node.x) ? stack_load_float3(stack, data_node.x) : sd->N;
- float param1 = (stack_valid(param1_offset))? stack_load_float(stack, param1_offset): __uint_as_float(node.z);
- float param2 = (stack_valid(param2_offset))? stack_load_float(stack, param2_offset): __uint_as_float(node.w);
+ float param1 = (stack_valid(param1_offset)) ? stack_load_float(stack, param1_offset) :
+ __uint_as_float(node.z);
+ float param2 = (stack_valid(param2_offset)) ? stack_load_float(stack, param2_offset) :
+ __uint_as_float(node.w);
- switch(type) {
+ switch (type) {
#ifdef __PRINCIPLED__
- case CLOSURE_BSDF_PRINCIPLED_ID: {
- uint specular_offset, roughness_offset, specular_tint_offset, anisotropic_offset, sheen_offset,
- sheen_tint_offset, clearcoat_offset, clearcoat_roughness_offset, eta_offset, transmission_offset,
- anisotropic_rotation_offset, transmission_roughness_offset;
- uint4 data_node2 = read_node(kg, offset);
-
- float3 T = stack_load_float3(stack, data_node.y);
- decode_node_uchar4(data_node.z, &specular_offset, &roughness_offset, &specular_tint_offset, &anisotropic_offset);
- decode_node_uchar4(data_node.w, &sheen_offset, &sheen_tint_offset, &clearcoat_offset, &clearcoat_roughness_offset);
- decode_node_uchar4(data_node2.x, &eta_offset, &transmission_offset, &anisotropic_rotation_offset, &transmission_roughness_offset);
-
- // get Disney principled parameters
- float metallic = param1;
- float subsurface = param2;
- float specular = stack_load_float(stack, specular_offset);
- float roughness = stack_load_float(stack, roughness_offset);
- float specular_tint = stack_load_float(stack, specular_tint_offset);
- float anisotropic = stack_load_float(stack, anisotropic_offset);
- float sheen = stack_load_float(stack, sheen_offset);
- float sheen_tint = stack_load_float(stack, sheen_tint_offset);
- float clearcoat = stack_load_float(stack, clearcoat_offset);
- float clearcoat_roughness = stack_load_float(stack, clearcoat_roughness_offset);
- float transmission = stack_load_float(stack, transmission_offset);
- float anisotropic_rotation = stack_load_float(stack, anisotropic_rotation_offset);
- float transmission_roughness = stack_load_float(stack, transmission_roughness_offset);
- float eta = fmaxf(stack_load_float(stack, eta_offset), 1e-5f);
-
- ClosureType distribution = (ClosureType) data_node2.y;
- ClosureType subsurface_method = (ClosureType) data_node2.z;
-
- /* rotate tangent */
- if(anisotropic_rotation != 0.0f)
- T = rotate_around_axis(T, N, anisotropic_rotation * M_2PI_F);
-
- /* calculate ior */
- float ior = (sd->flag & SD_BACKFACING) ? 1.0f / eta : eta;
-
- // calculate fresnel for refraction
- float cosNO = dot(N, sd->I);
- float fresnel = fresnel_dielectric_cos(cosNO, ior);
-
- // calculate weights of the diffuse and specular part
- float diffuse_weight = (1.0f - saturate(metallic)) * (1.0f - saturate(transmission));
-
- float final_transmission = saturate(transmission) * (1.0f - saturate(metallic));
- float specular_weight = (1.0f - final_transmission);
-
- // get the base color
- uint4 data_base_color = read_node(kg, offset);
- float3 base_color = stack_valid(data_base_color.x) ? stack_load_float3(stack, data_base_color.x) :
- make_float3(__uint_as_float(data_base_color.y), __uint_as_float(data_base_color.z), __uint_as_float(data_base_color.w));
-
- // get the additional clearcoat normal and subsurface scattering radius
- uint4 data_cn_ssr = read_node(kg, offset);
- float3 clearcoat_normal = stack_valid(data_cn_ssr.x) ? stack_load_float3(stack, data_cn_ssr.x) : sd->N;
- float3 subsurface_radius = stack_valid(data_cn_ssr.y) ? stack_load_float3(stack, data_cn_ssr.y) : make_float3(1.0f, 1.0f, 1.0f);
-
- // get the subsurface color
- uint4 data_subsurface_color = read_node(kg, offset);
- float3 subsurface_color = stack_valid(data_subsurface_color.x) ? stack_load_float3(stack, data_subsurface_color.x) :
- make_float3(__uint_as_float(data_subsurface_color.y), __uint_as_float(data_subsurface_color.z), __uint_as_float(data_subsurface_color.w));
-
- float3 weight = sd->svm_closure_weight * mix_weight;
-
-#ifdef __SUBSURFACE__
- float3 mixed_ss_base_color = subsurface_color * subsurface + base_color * (1.0f - subsurface);
- float3 subsurf_weight = weight * mixed_ss_base_color * diffuse_weight;
-
- /* disable in case of diffuse ancestor, can't see it well then and
- * adds considerably noise due to probabilities of continuing path
- * getting lower and lower */
- if(path_flag & PATH_RAY_DIFFUSE_ANCESTOR) {
- subsurface = 0.0f;
-
- /* need to set the base color in this case such that the
- * rays get the correctly mixed color after transmitting
- * the object */
- base_color = mixed_ss_base_color;
- }
-
- /* diffuse */
- if(fabsf(average(mixed_ss_base_color)) > CLOSURE_WEIGHT_CUTOFF) {
- if(subsurface <= CLOSURE_WEIGHT_CUTOFF && diffuse_weight > CLOSURE_WEIGHT_CUTOFF) {
- float3 diff_weight = weight * base_color * diffuse_weight;
-
- PrincipledDiffuseBsdf *bsdf = (PrincipledDiffuseBsdf*)bsdf_alloc(sd, sizeof(PrincipledDiffuseBsdf), diff_weight);
-
- if(bsdf) {
- bsdf->N = N;
- bsdf->roughness = roughness;
-
- /* setup bsdf */
- sd->flag |= bsdf_principled_diffuse_setup(bsdf);
- }
- }
- else if(subsurface > CLOSURE_WEIGHT_CUTOFF) {
- Bssrdf *bssrdf = bssrdf_alloc(sd, subsurf_weight);
-
- if(bssrdf) {
- bssrdf->radius = subsurface_radius * subsurface;
- bssrdf->albedo = (subsurface_method == CLOSURE_BSSRDF_PRINCIPLED_ID)? subsurface_color: mixed_ss_base_color;
- bssrdf->texture_blur = 0.0f;
- bssrdf->sharpness = 0.0f;
- bssrdf->N = N;
- bssrdf->roughness = roughness;
-
- /* setup bsdf */
- sd->flag |= bssrdf_setup(sd, bssrdf, subsurface_method);
- }
- }
- }
-#else
- /* diffuse */
- if(diffuse_weight > CLOSURE_WEIGHT_CUTOFF) {
- float3 diff_weight = weight * base_color * diffuse_weight;
-
- PrincipledDiffuseBsdf *bsdf = (PrincipledDiffuseBsdf*)bsdf_alloc(sd, sizeof(PrincipledDiffuseBsdf), diff_weight);
-
- if(bsdf) {
- bsdf->N = N;
- bsdf->roughness = roughness;
-
- /* setup bsdf */
- sd->flag |= bsdf_principled_diffuse_setup(bsdf);
- }
- }
-#endif
-
- /* sheen */
- if(diffuse_weight > CLOSURE_WEIGHT_CUTOFF && sheen > CLOSURE_WEIGHT_CUTOFF) {
- float m_cdlum = linear_rgb_to_gray(kg, base_color);
- float3 m_ctint = m_cdlum > 0.0f ? base_color / m_cdlum : make_float3(1.0f, 1.0f, 1.0f); // normalize lum. to isolate hue+sat
-
- /* color of the sheen component */
- float3 sheen_color = make_float3(1.0f, 1.0f, 1.0f) * (1.0f - sheen_tint) + m_ctint * sheen_tint;
-
- float3 sheen_weight = weight * sheen * sheen_color * diffuse_weight;
-
- PrincipledSheenBsdf *bsdf = (PrincipledSheenBsdf*)bsdf_alloc(sd, sizeof(PrincipledSheenBsdf), sheen_weight);
-
- if(bsdf) {
- bsdf->N = N;
-
- /* setup bsdf */
- sd->flag |= bsdf_principled_sheen_setup(bsdf);
- }
- }
-
- /* specular reflection */
+ case CLOSURE_BSDF_PRINCIPLED_ID: {
+ uint specular_offset, roughness_offset, specular_tint_offset, anisotropic_offset,
+ sheen_offset, sheen_tint_offset, clearcoat_offset, clearcoat_roughness_offset,
+ eta_offset, transmission_offset, anisotropic_rotation_offset,
+ transmission_roughness_offset;
+ uint4 data_node2 = read_node(kg, offset);
+
+ float3 T = stack_load_float3(stack, data_node.y);
+ decode_node_uchar4(data_node.z,
+ &specular_offset,
+ &roughness_offset,
+ &specular_tint_offset,
+ &anisotropic_offset);
+ decode_node_uchar4(data_node.w,
+ &sheen_offset,
+ &sheen_tint_offset,
+ &clearcoat_offset,
+ &clearcoat_roughness_offset);
+ decode_node_uchar4(data_node2.x,
+ &eta_offset,
+ &transmission_offset,
+ &anisotropic_rotation_offset,
+ &transmission_roughness_offset);
+
+ // get Disney principled parameters
+ float metallic = param1;
+ float subsurface = param2;
+ float specular = stack_load_float(stack, specular_offset);
+ float roughness = stack_load_float(stack, roughness_offset);
+ float specular_tint = stack_load_float(stack, specular_tint_offset);
+ float anisotropic = stack_load_float(stack, anisotropic_offset);
+ float sheen = stack_load_float(stack, sheen_offset);
+ float sheen_tint = stack_load_float(stack, sheen_tint_offset);
+ float clearcoat = stack_load_float(stack, clearcoat_offset);
+ float clearcoat_roughness = stack_load_float(stack, clearcoat_roughness_offset);
+ float transmission = stack_load_float(stack, transmission_offset);
+ float anisotropic_rotation = stack_load_float(stack, anisotropic_rotation_offset);
+ float transmission_roughness = stack_load_float(stack, transmission_roughness_offset);
+ float eta = fmaxf(stack_load_float(stack, eta_offset), 1e-5f);
+
+ ClosureType distribution = (ClosureType)data_node2.y;
+ ClosureType subsurface_method = (ClosureType)data_node2.z;
+
+ /* rotate tangent */
+ if (anisotropic_rotation != 0.0f)
+ T = rotate_around_axis(T, N, anisotropic_rotation * M_2PI_F);
+
+ /* calculate ior */
+ float ior = (sd->flag & SD_BACKFACING) ? 1.0f / eta : eta;
+
+ // calculate fresnel for refraction
+ float cosNO = dot(N, sd->I);
+ float fresnel = fresnel_dielectric_cos(cosNO, ior);
+
+ // calculate weights of the diffuse and specular part
+ float diffuse_weight = (1.0f - saturate(metallic)) * (1.0f - saturate(transmission));
+
+ float final_transmission = saturate(transmission) * (1.0f - saturate(metallic));
+ float specular_weight = (1.0f - final_transmission);
+
+ // get the base color
+ uint4 data_base_color = read_node(kg, offset);
+ float3 base_color = stack_valid(data_base_color.x) ?
+ stack_load_float3(stack, data_base_color.x) :
+ make_float3(__uint_as_float(data_base_color.y),
+ __uint_as_float(data_base_color.z),
+ __uint_as_float(data_base_color.w));
+
+ // get the additional clearcoat normal and subsurface scattering radius
+ uint4 data_cn_ssr = read_node(kg, offset);
+ float3 clearcoat_normal = stack_valid(data_cn_ssr.x) ?
+ stack_load_float3(stack, data_cn_ssr.x) :
+ sd->N;
+ float3 subsurface_radius = stack_valid(data_cn_ssr.y) ?
+ stack_load_float3(stack, data_cn_ssr.y) :
+ make_float3(1.0f, 1.0f, 1.0f);
+
+ // get the subsurface color
+ uint4 data_subsurface_color = read_node(kg, offset);
+ float3 subsurface_color = stack_valid(data_subsurface_color.x) ?
+ stack_load_float3(stack, data_subsurface_color.x) :
+ make_float3(__uint_as_float(data_subsurface_color.y),
+ __uint_as_float(data_subsurface_color.z),
+ __uint_as_float(data_subsurface_color.w));
+
+ float3 weight = sd->svm_closure_weight * mix_weight;
+
+# ifdef __SUBSURFACE__
+ float3 mixed_ss_base_color = subsurface_color * subsurface +
+ base_color * (1.0f - subsurface);
+ float3 subsurf_weight = weight * mixed_ss_base_color * diffuse_weight;
+
+ /* disable in case of diffuse ancestor, can't see it well then and
+ * adds considerably noise due to probabilities of continuing path
+ * getting lower and lower */
+ if (path_flag & PATH_RAY_DIFFUSE_ANCESTOR) {
+ subsurface = 0.0f;
+
+ /* need to set the base color in this case such that the
+ * rays get the correctly mixed color after transmitting
+ * the object */
+ base_color = mixed_ss_base_color;
+ }
+
+ /* diffuse */
+ if (fabsf(average(mixed_ss_base_color)) > CLOSURE_WEIGHT_CUTOFF) {
+ if (subsurface <= CLOSURE_WEIGHT_CUTOFF && diffuse_weight > CLOSURE_WEIGHT_CUTOFF) {
+ float3 diff_weight = weight * base_color * diffuse_weight;
+
+ PrincipledDiffuseBsdf *bsdf = (PrincipledDiffuseBsdf *)bsdf_alloc(
+ sd, sizeof(PrincipledDiffuseBsdf), diff_weight);
+
+ if (bsdf) {
+ bsdf->N = N;
+ bsdf->roughness = roughness;
+
+ /* setup bsdf */
+ sd->flag |= bsdf_principled_diffuse_setup(bsdf);
+ }
+ }
+ else if (subsurface > CLOSURE_WEIGHT_CUTOFF) {
+ Bssrdf *bssrdf = bssrdf_alloc(sd, subsurf_weight);
+
+ if (bssrdf) {
+ bssrdf->radius = subsurface_radius * subsurface;
+ bssrdf->albedo = (subsurface_method == CLOSURE_BSSRDF_PRINCIPLED_ID) ?
+ subsurface_color :
+ mixed_ss_base_color;
+ bssrdf->texture_blur = 0.0f;
+ bssrdf->sharpness = 0.0f;
+ bssrdf->N = N;
+ bssrdf->roughness = roughness;
+
+ /* setup bsdf */
+ sd->flag |= bssrdf_setup(sd, bssrdf, subsurface_method);
+ }
+ }
+ }
+# else
+ /* diffuse */
+ if (diffuse_weight > CLOSURE_WEIGHT_CUTOFF) {
+ float3 diff_weight = weight * base_color * diffuse_weight;
+
+ PrincipledDiffuseBsdf *bsdf = (PrincipledDiffuseBsdf *)bsdf_alloc(
+ sd, sizeof(PrincipledDiffuseBsdf), diff_weight);
+
+ if (bsdf) {
+ bsdf->N = N;
+ bsdf->roughness = roughness;
+
+ /* setup bsdf */
+ sd->flag |= bsdf_principled_diffuse_setup(bsdf);
+ }
+ }
+# endif
+
+ /* sheen */
+ if (diffuse_weight > CLOSURE_WEIGHT_CUTOFF && sheen > CLOSURE_WEIGHT_CUTOFF) {
+ float m_cdlum = linear_rgb_to_gray(kg, base_color);
+ float3 m_ctint = m_cdlum > 0.0f ?
+ base_color / m_cdlum :
+ make_float3(1.0f, 1.0f, 1.0f); // normalize lum. to isolate hue+sat
+
+ /* color of the sheen component */
+ float3 sheen_color = make_float3(1.0f, 1.0f, 1.0f) * (1.0f - sheen_tint) +
+ m_ctint * sheen_tint;
+
+ float3 sheen_weight = weight * sheen * sheen_color * diffuse_weight;
+
+ PrincipledSheenBsdf *bsdf = (PrincipledSheenBsdf *)bsdf_alloc(
+ sd, sizeof(PrincipledSheenBsdf), sheen_weight);
+
+ if (bsdf) {
+ bsdf->N = N;
+
+ /* setup bsdf */
+ sd->flag |= bsdf_principled_sheen_setup(bsdf);
+ }
+ }
+
+ /* specular reflection */
+# ifdef __CAUSTICS_TRICKS__
+ if (kernel_data.integrator.caustics_reflective || (path_flag & PATH_RAY_DIFFUSE) == 0) {
+# endif
+ if (specular_weight > CLOSURE_WEIGHT_CUTOFF &&
+ (specular > CLOSURE_WEIGHT_CUTOFF || metallic > CLOSURE_WEIGHT_CUTOFF)) {
+ float3 spec_weight = weight * specular_weight;
+
+ MicrofacetBsdf *bsdf = (MicrofacetBsdf *)bsdf_alloc(
+ sd, sizeof(MicrofacetBsdf), spec_weight);
+ MicrofacetExtra *extra = (bsdf != NULL) ? (MicrofacetExtra *)closure_alloc_extra(
+ sd, sizeof(MicrofacetExtra)) :
+ NULL;
+
+ if (bsdf && extra) {
+ bsdf->N = N;
+ bsdf->ior = (2.0f / (1.0f - safe_sqrtf(0.08f * specular))) - 1.0f;
+ bsdf->T = T;
+ bsdf->extra = extra;
+
+ float aspect = safe_sqrtf(1.0f - anisotropic * 0.9f);
+ float r2 = roughness * roughness;
+
+ bsdf->alpha_x = r2 / aspect;
+ bsdf->alpha_y = r2 * aspect;
+
+ float m_cdlum = 0.3f * base_color.x + 0.6f * base_color.y +
+ 0.1f * base_color.z; // luminance approx.
+ float3 m_ctint = m_cdlum > 0.0f ?
+ base_color / m_cdlum :
+ make_float3(
+ 0.0f, 0.0f, 0.0f); // normalize lum. to isolate hue+sat
+ float3 tmp_col = make_float3(1.0f, 1.0f, 1.0f) * (1.0f - specular_tint) +
+ m_ctint * specular_tint;
+
+ bsdf->extra->cspec0 = (specular * 0.08f * tmp_col) * (1.0f - metallic) +
+ base_color * metallic;
+ bsdf->extra->color = base_color;
+ bsdf->extra->clearcoat = 0.0f;
+
+ /* setup bsdf */
+ if (distribution == CLOSURE_BSDF_MICROFACET_GGX_GLASS_ID ||
+ roughness <= 0.075f) /* use single-scatter GGX */
+ sd->flag |= bsdf_microfacet_ggx_aniso_fresnel_setup(bsdf, sd);
+ else /* use multi-scatter GGX */
+ sd->flag |= bsdf_microfacet_multi_ggx_aniso_fresnel_setup(bsdf, sd);
+ }
+ }
+# ifdef __CAUSTICS_TRICKS__
+ }
+# endif
+
+ /* BSDF */
+# ifdef __CAUSTICS_TRICKS__
+ if (kernel_data.integrator.caustics_reflective ||
+ kernel_data.integrator.caustics_refractive || (path_flag & PATH_RAY_DIFFUSE) == 0) {
+# endif
+ if (final_transmission > CLOSURE_WEIGHT_CUTOFF) {
+ float3 glass_weight = weight * final_transmission;
+ float3 cspec0 = base_color * specular_tint +
+ make_float3(1.0f, 1.0f, 1.0f) * (1.0f - specular_tint);
+
+ if (roughness <= 5e-2f ||
+ distribution == CLOSURE_BSDF_MICROFACET_GGX_GLASS_ID) { /* use single-scatter GGX */
+ float refl_roughness = roughness;
+
+ /* reflection */
+# ifdef __CAUSTICS_TRICKS__
+ if (kernel_data.integrator.caustics_reflective || (path_flag & PATH_RAY_DIFFUSE) == 0)
+# endif
+ {
+ MicrofacetBsdf *bsdf = (MicrofacetBsdf *)bsdf_alloc(
+ sd, sizeof(MicrofacetBsdf), glass_weight * fresnel);
+ MicrofacetExtra *extra = (bsdf != NULL) ? (MicrofacetExtra *)closure_alloc_extra(
+ sd, sizeof(MicrofacetExtra)) :
+ NULL;
+
+ if (bsdf && extra) {
+ bsdf->N = N;
+ bsdf->T = make_float3(0.0f, 0.0f, 0.0f);
+ bsdf->extra = extra;
+
+ bsdf->alpha_x = refl_roughness * refl_roughness;
+ bsdf->alpha_y = refl_roughness * refl_roughness;
+ bsdf->ior = ior;
+
+ bsdf->extra->color = base_color;
+ bsdf->extra->cspec0 = cspec0;
+ bsdf->extra->clearcoat = 0.0f;
+
+ /* setup bsdf */
+ sd->flag |= bsdf_microfacet_ggx_fresnel_setup(bsdf, sd);
+ }
+ }
+
+ /* refraction */
+# ifdef __CAUSTICS_TRICKS__
+ if (kernel_data.integrator.caustics_refractive || (path_flag & PATH_RAY_DIFFUSE) == 0)
+# endif
+ {
+ MicrofacetBsdf *bsdf = (MicrofacetBsdf *)bsdf_alloc(
+ sd, sizeof(MicrofacetBsdf), base_color * glass_weight * (1.0f - fresnel));
+ if (bsdf) {
+ bsdf->N = N;
+ bsdf->T = make_float3(0.0f, 0.0f, 0.0f);
+ bsdf->extra = NULL;
+
+ if (distribution == CLOSURE_BSDF_MICROFACET_GGX_GLASS_ID)
+ transmission_roughness = 1.0f - (1.0f - refl_roughness) *
+ (1.0f - transmission_roughness);
+ else
+ transmission_roughness = refl_roughness;
+
+ bsdf->alpha_x = transmission_roughness * transmission_roughness;
+ bsdf->alpha_y = transmission_roughness * transmission_roughness;
+ bsdf->ior = ior;
+
+ /* setup bsdf */
+ sd->flag |= bsdf_microfacet_ggx_refraction_setup(bsdf);
+ }
+ }
+ }
+ else { /* use multi-scatter GGX */
+ MicrofacetBsdf *bsdf = (MicrofacetBsdf *)bsdf_alloc(
+ sd, sizeof(MicrofacetBsdf), glass_weight);
+ MicrofacetExtra *extra = (bsdf != NULL) ? (MicrofacetExtra *)closure_alloc_extra(
+ sd, sizeof(MicrofacetExtra)) :
+ NULL;
+
+ if (bsdf && extra) {
+ bsdf->N = N;
+ bsdf->extra = extra;
+ bsdf->T = make_float3(0.0f, 0.0f, 0.0f);
+
+ bsdf->alpha_x = roughness * roughness;
+ bsdf->alpha_y = roughness * roughness;
+ bsdf->ior = ior;
+
+ bsdf->extra->color = base_color;
+ bsdf->extra->cspec0 = cspec0;
+ bsdf->extra->clearcoat = 0.0f;
+
+ /* setup bsdf */
+ sd->flag |= bsdf_microfacet_multi_ggx_glass_fresnel_setup(bsdf, sd);
+ }
+ }
+ }
+# ifdef __CAUSTICS_TRICKS__
+ }
+# endif
+
+ /* clearcoat */
+# ifdef __CAUSTICS_TRICKS__
+ if (kernel_data.integrator.caustics_reflective || (path_flag & PATH_RAY_DIFFUSE) == 0) {
+# endif
+ if (clearcoat > CLOSURE_WEIGHT_CUTOFF) {
+ MicrofacetBsdf *bsdf = (MicrofacetBsdf *)bsdf_alloc(sd, sizeof(MicrofacetBsdf), weight);
+ MicrofacetExtra *extra = (bsdf != NULL) ? (MicrofacetExtra *)closure_alloc_extra(
+ sd, sizeof(MicrofacetExtra)) :
+ NULL;
+
+ if (bsdf && extra) {
+ bsdf->N = clearcoat_normal;
+ bsdf->T = make_float3(0.0f, 0.0f, 0.0f);
+ bsdf->ior = 1.5f;
+ bsdf->extra = extra;
+
+ bsdf->alpha_x = clearcoat_roughness * clearcoat_roughness;
+ bsdf->alpha_y = clearcoat_roughness * clearcoat_roughness;
+
+ bsdf->extra->color = make_float3(0.0f, 0.0f, 0.0f);
+ bsdf->extra->cspec0 = make_float3(0.04f, 0.04f, 0.04f);
+ bsdf->extra->clearcoat = clearcoat;
+
+ /* setup bsdf */
+ sd->flag |= bsdf_microfacet_ggx_clearcoat_setup(bsdf, sd);
+ }
+ }
+# ifdef __CAUSTICS_TRICKS__
+ }
+# endif
+
+ break;
+ }
+#endif /* __PRINCIPLED__ */
+ case CLOSURE_BSDF_DIFFUSE_ID: {
+ float3 weight = sd->svm_closure_weight * mix_weight;
+ OrenNayarBsdf *bsdf = (OrenNayarBsdf *)bsdf_alloc(sd, sizeof(OrenNayarBsdf), weight);
+
+ if (bsdf) {
+ bsdf->N = N;
+
+ float roughness = param1;
+
+ if (roughness == 0.0f) {
+ sd->flag |= bsdf_diffuse_setup((DiffuseBsdf *)bsdf);
+ }
+ else {
+ bsdf->roughness = roughness;
+ sd->flag |= bsdf_oren_nayar_setup(bsdf);
+ }
+ }
+ break;
+ }
+ case CLOSURE_BSDF_TRANSLUCENT_ID: {
+ float3 weight = sd->svm_closure_weight * mix_weight;
+ DiffuseBsdf *bsdf = (DiffuseBsdf *)bsdf_alloc(sd, sizeof(DiffuseBsdf), weight);
+
+ if (bsdf) {
+ bsdf->N = N;
+ sd->flag |= bsdf_translucent_setup(bsdf);
+ }
+ break;
+ }
+ case CLOSURE_BSDF_TRANSPARENT_ID: {
+ float3 weight = sd->svm_closure_weight * mix_weight;
+ bsdf_transparent_setup(sd, weight, path_flag);
+ break;
+ }
+ case CLOSURE_BSDF_REFLECTION_ID:
+ case CLOSURE_BSDF_MICROFACET_GGX_ID:
+ case CLOSURE_BSDF_MICROFACET_BECKMANN_ID:
+ case CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ID:
+ case CLOSURE_BSDF_MICROFACET_MULTI_GGX_ID: {
#ifdef __CAUSTICS_TRICKS__
- if(kernel_data.integrator.caustics_reflective || (path_flag & PATH_RAY_DIFFUSE) == 0) {
+ if (!kernel_data.integrator.caustics_reflective && (path_flag & PATH_RAY_DIFFUSE))
+ break;
#endif
- if(specular_weight > CLOSURE_WEIGHT_CUTOFF && (specular > CLOSURE_WEIGHT_CUTOFF || metallic > CLOSURE_WEIGHT_CUTOFF)) {
- float3 spec_weight = weight * specular_weight;
-
- MicrofacetBsdf *bsdf = (MicrofacetBsdf*)bsdf_alloc(sd, sizeof(MicrofacetBsdf), spec_weight);
- MicrofacetExtra *extra = (bsdf != NULL)
- ? (MicrofacetExtra*)closure_alloc_extra(sd, sizeof(MicrofacetExtra))
- : NULL;
-
- if(bsdf && extra) {
- bsdf->N = N;
- bsdf->ior = (2.0f / (1.0f - safe_sqrtf(0.08f * specular))) - 1.0f;
- bsdf->T = T;
- bsdf->extra = extra;
-
- float aspect = safe_sqrtf(1.0f - anisotropic * 0.9f);
- float r2 = roughness * roughness;
-
- bsdf->alpha_x = r2 / aspect;
- bsdf->alpha_y = r2 * aspect;
-
- float m_cdlum = 0.3f * base_color.x + 0.6f * base_color.y + 0.1f * base_color.z; // luminance approx.
- float3 m_ctint = m_cdlum > 0.0f ? base_color / m_cdlum : make_float3(0.0f, 0.0f, 0.0f); // normalize lum. to isolate hue+sat
- float3 tmp_col = make_float3(1.0f, 1.0f, 1.0f) * (1.0f - specular_tint) + m_ctint * specular_tint;
-
- bsdf->extra->cspec0 = (specular * 0.08f * tmp_col) * (1.0f - metallic) + base_color * metallic;
- bsdf->extra->color = base_color;
- bsdf->extra->clearcoat = 0.0f;
-
- /* setup bsdf */
- if(distribution == CLOSURE_BSDF_MICROFACET_GGX_GLASS_ID || roughness <= 0.075f) /* use single-scatter GGX */
- sd->flag |= bsdf_microfacet_ggx_aniso_fresnel_setup(bsdf, sd);
- else /* use multi-scatter GGX */
- sd->flag |= bsdf_microfacet_multi_ggx_aniso_fresnel_setup(bsdf, sd);
- }
- }
+ float3 weight = sd->svm_closure_weight * mix_weight;
+ MicrofacetBsdf *bsdf = (MicrofacetBsdf *)bsdf_alloc(sd, sizeof(MicrofacetBsdf), weight);
+
+ if (!bsdf) {
+ break;
+ }
+
+ float roughness = sqr(param1);
+
+ bsdf->N = N;
+ bsdf->T = make_float3(0.0f, 0.0f, 0.0f);
+ bsdf->alpha_x = roughness;
+ bsdf->alpha_y = roughness;
+ bsdf->ior = 0.0f;
+ bsdf->extra = NULL;
+
+ /* setup bsdf */
+ if (type == CLOSURE_BSDF_REFLECTION_ID)
+ sd->flag |= bsdf_reflection_setup(bsdf);
+ else if (type == CLOSURE_BSDF_MICROFACET_BECKMANN_ID)
+ sd->flag |= bsdf_microfacet_beckmann_setup(bsdf);
+ else if (type == CLOSURE_BSDF_MICROFACET_GGX_ID)
+ sd->flag |= bsdf_microfacet_ggx_setup(bsdf);
+ else if (type == CLOSURE_BSDF_MICROFACET_MULTI_GGX_ID) {
+ kernel_assert(stack_valid(data_node.z));
+ bsdf->extra = (MicrofacetExtra *)closure_alloc_extra(sd, sizeof(MicrofacetExtra));
+ if (bsdf->extra) {
+ bsdf->extra->color = stack_load_float3(stack, data_node.z);
+ bsdf->extra->cspec0 = make_float3(0.0f, 0.0f, 0.0f);
+ bsdf->extra->clearcoat = 0.0f;
+ sd->flag |= bsdf_microfacet_multi_ggx_setup(bsdf);
+ }
+ }
+ else {
+ sd->flag |= bsdf_ashikhmin_shirley_setup(bsdf);
+ }
+
+ break;
+ }
+ case CLOSURE_BSDF_REFRACTION_ID:
+ case CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID:
+ case CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID: {
#ifdef __CAUSTICS_TRICKS__
- }
+ if (!kernel_data.integrator.caustics_refractive && (path_flag & PATH_RAY_DIFFUSE))
+ break;
#endif
-
- /* BSDF */
+ float3 weight = sd->svm_closure_weight * mix_weight;
+ MicrofacetBsdf *bsdf = (MicrofacetBsdf *)bsdf_alloc(sd, sizeof(MicrofacetBsdf), weight);
+
+ if (bsdf) {
+ bsdf->N = N;
+ bsdf->T = make_float3(0.0f, 0.0f, 0.0f);
+ bsdf->extra = NULL;
+
+ float eta = fmaxf(param2, 1e-5f);
+ eta = (sd->flag & SD_BACKFACING) ? 1.0f / eta : eta;
+
+ /* setup bsdf */
+ if (type == CLOSURE_BSDF_REFRACTION_ID) {
+ bsdf->alpha_x = 0.0f;
+ bsdf->alpha_y = 0.0f;
+ bsdf->ior = eta;
+
+ sd->flag |= bsdf_refraction_setup(bsdf);
+ }
+ else {
+ float roughness = sqr(param1);
+ bsdf->alpha_x = roughness;
+ bsdf->alpha_y = roughness;
+ bsdf->ior = eta;
+
+ if (type == CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID)
+ sd->flag |= bsdf_microfacet_beckmann_refraction_setup(bsdf);
+ else
+ sd->flag |= bsdf_microfacet_ggx_refraction_setup(bsdf);
+ }
+ }
+
+ break;
+ }
+ case CLOSURE_BSDF_SHARP_GLASS_ID:
+ case CLOSURE_BSDF_MICROFACET_GGX_GLASS_ID:
+ case CLOSURE_BSDF_MICROFACET_BECKMANN_GLASS_ID: {
#ifdef __CAUSTICS_TRICKS__
- if(kernel_data.integrator.caustics_reflective || kernel_data.integrator.caustics_refractive || (path_flag & PATH_RAY_DIFFUSE) == 0) {
+ if (!kernel_data.integrator.caustics_reflective &&
+ !kernel_data.integrator.caustics_refractive && (path_flag & PATH_RAY_DIFFUSE)) {
+ break;
+ }
#endif
- if(final_transmission > CLOSURE_WEIGHT_CUTOFF) {
- float3 glass_weight = weight * final_transmission;
- float3 cspec0 = base_color * specular_tint + make_float3(1.0f, 1.0f, 1.0f) * (1.0f - specular_tint);
+ float3 weight = sd->svm_closure_weight * mix_weight;
- if(roughness <= 5e-2f || distribution == CLOSURE_BSDF_MICROFACET_GGX_GLASS_ID) { /* use single-scatter GGX */
- float refl_roughness = roughness;
+ /* index of refraction */
+ float eta = fmaxf(param2, 1e-5f);
+ eta = (sd->flag & SD_BACKFACING) ? 1.0f / eta : eta;
- /* reflection */
-#ifdef __CAUSTICS_TRICKS__
- if(kernel_data.integrator.caustics_reflective || (path_flag & PATH_RAY_DIFFUSE) == 0)
-#endif
- {
- MicrofacetBsdf *bsdf = (MicrofacetBsdf*)bsdf_alloc(sd, sizeof(MicrofacetBsdf), glass_weight*fresnel);
- MicrofacetExtra *extra = (bsdf != NULL)
- ? (MicrofacetExtra*)closure_alloc_extra(sd, sizeof(MicrofacetExtra))
- : NULL;
-
- if(bsdf && extra) {
- bsdf->N = N;
- bsdf->T = make_float3(0.0f, 0.0f, 0.0f);
- bsdf->extra = extra;
-
- bsdf->alpha_x = refl_roughness * refl_roughness;
- bsdf->alpha_y = refl_roughness * refl_roughness;
- bsdf->ior = ior;
-
- bsdf->extra->color = base_color;
- bsdf->extra->cspec0 = cspec0;
- bsdf->extra->clearcoat = 0.0f;
-
- /* setup bsdf */
- sd->flag |= bsdf_microfacet_ggx_fresnel_setup(bsdf, sd);
- }
- }
-
- /* refraction */
-#ifdef __CAUSTICS_TRICKS__
- if(kernel_data.integrator.caustics_refractive || (path_flag & PATH_RAY_DIFFUSE) == 0)
-#endif
- {
- MicrofacetBsdf *bsdf = (MicrofacetBsdf*)bsdf_alloc(sd, sizeof(MicrofacetBsdf), base_color*glass_weight*(1.0f - fresnel));
- if(bsdf) {
- bsdf->N = N;
- bsdf->T = make_float3(0.0f, 0.0f, 0.0f);
- bsdf->extra = NULL;
-
- if(distribution == CLOSURE_BSDF_MICROFACET_GGX_GLASS_ID)
- transmission_roughness = 1.0f - (1.0f - refl_roughness) * (1.0f - transmission_roughness);
- else
- transmission_roughness = refl_roughness;
-
- bsdf->alpha_x = transmission_roughness * transmission_roughness;
- bsdf->alpha_y = transmission_roughness * transmission_roughness;
- bsdf->ior = ior;
-
- /* setup bsdf */
- sd->flag |= bsdf_microfacet_ggx_refraction_setup(bsdf);
- }
- }
- }
- else { /* use multi-scatter GGX */
- MicrofacetBsdf *bsdf = (MicrofacetBsdf*)bsdf_alloc(sd, sizeof(MicrofacetBsdf), glass_weight);
- MicrofacetExtra *extra = (bsdf != NULL)
- ? (MicrofacetExtra*)closure_alloc_extra(sd, sizeof(MicrofacetExtra))
- : NULL;
-
- if(bsdf && extra) {
- bsdf->N = N;
- bsdf->extra = extra;
- bsdf->T = make_float3(0.0f, 0.0f, 0.0f);
-
- bsdf->alpha_x = roughness * roughness;
- bsdf->alpha_y = roughness * roughness;
- bsdf->ior = ior;
-
- bsdf->extra->color = base_color;
- bsdf->extra->cspec0 = cspec0;
- bsdf->extra->clearcoat = 0.0f;
-
- /* setup bsdf */
- sd->flag |= bsdf_microfacet_multi_ggx_glass_fresnel_setup(bsdf, sd);
- }
- }
- }
-#ifdef __CAUSTICS_TRICKS__
- }
-#endif
+ /* fresnel */
+ float cosNO = dot(N, sd->I);
+ float fresnel = fresnel_dielectric_cos(cosNO, eta);
+ float roughness = sqr(param1);
- /* clearcoat */
+ /* reflection */
#ifdef __CAUSTICS_TRICKS__
- if(kernel_data.integrator.caustics_reflective || (path_flag & PATH_RAY_DIFFUSE) == 0) {
+ if (kernel_data.integrator.caustics_reflective || (path_flag & PATH_RAY_DIFFUSE) == 0)
#endif
- if(clearcoat > CLOSURE_WEIGHT_CUTOFF) {
- MicrofacetBsdf *bsdf = (MicrofacetBsdf*)bsdf_alloc(sd, sizeof(MicrofacetBsdf), weight);
- MicrofacetExtra *extra = (bsdf != NULL)
- ? (MicrofacetExtra*)closure_alloc_extra(sd, sizeof(MicrofacetExtra))
- : NULL;
-
- if(bsdf && extra) {
- bsdf->N = clearcoat_normal;
- bsdf->T = make_float3(0.0f, 0.0f, 0.0f);
- bsdf->ior = 1.5f;
- bsdf->extra = extra;
-
- bsdf->alpha_x = clearcoat_roughness * clearcoat_roughness;
- bsdf->alpha_y = clearcoat_roughness * clearcoat_roughness;
-
- bsdf->extra->color = make_float3(0.0f, 0.0f, 0.0f);
- bsdf->extra->cspec0 = make_float3(0.04f, 0.04f, 0.04f);
- bsdf->extra->clearcoat = clearcoat;
-
- /* setup bsdf */
- sd->flag |= bsdf_microfacet_ggx_clearcoat_setup(bsdf, sd);
- }
- }
+ {
+ MicrofacetBsdf *bsdf = (MicrofacetBsdf *)bsdf_alloc(
+ sd, sizeof(MicrofacetBsdf), weight * fresnel);
+
+ if (bsdf) {
+ bsdf->N = N;
+ bsdf->T = make_float3(0.0f, 0.0f, 0.0f);
+ bsdf->extra = NULL;
+ svm_node_glass_setup(sd, bsdf, type, eta, roughness, false);
+ }
+ }
+
+ /* refraction */
#ifdef __CAUSTICS_TRICKS__
- }
+ if (kernel_data.integrator.caustics_refractive || (path_flag & PATH_RAY_DIFFUSE) == 0)
#endif
-
- break;
- }
-#endif /* __PRINCIPLED__ */
- case CLOSURE_BSDF_DIFFUSE_ID: {
- float3 weight = sd->svm_closure_weight * mix_weight;
- OrenNayarBsdf *bsdf = (OrenNayarBsdf*)bsdf_alloc(sd, sizeof(OrenNayarBsdf), weight);
-
- if(bsdf) {
- bsdf->N = N;
-
- float roughness = param1;
-
- if(roughness == 0.0f) {
- sd->flag |= bsdf_diffuse_setup((DiffuseBsdf*)bsdf);
- }
- else {
- bsdf->roughness = roughness;
- sd->flag |= bsdf_oren_nayar_setup(bsdf);
- }
- }
- break;
- }
- case CLOSURE_BSDF_TRANSLUCENT_ID: {
- float3 weight = sd->svm_closure_weight * mix_weight;
- DiffuseBsdf *bsdf = (DiffuseBsdf*)bsdf_alloc(sd, sizeof(DiffuseBsdf), weight);
-
- if(bsdf) {
- bsdf->N = N;
- sd->flag |= bsdf_translucent_setup(bsdf);
- }
- break;
- }
- case CLOSURE_BSDF_TRANSPARENT_ID: {
- float3 weight = sd->svm_closure_weight * mix_weight;
- bsdf_transparent_setup(sd, weight, path_flag);
- break;
- }
- case CLOSURE_BSDF_REFLECTION_ID:
- case CLOSURE_BSDF_MICROFACET_GGX_ID:
- case CLOSURE_BSDF_MICROFACET_BECKMANN_ID:
- case CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ID:
- case CLOSURE_BSDF_MICROFACET_MULTI_GGX_ID: {
+ {
+ MicrofacetBsdf *bsdf = (MicrofacetBsdf *)bsdf_alloc(
+ sd, sizeof(MicrofacetBsdf), weight * (1.0f - fresnel));
+
+ if (bsdf) {
+ bsdf->N = N;
+ bsdf->T = make_float3(0.0f, 0.0f, 0.0f);
+ bsdf->extra = NULL;
+ svm_node_glass_setup(sd, bsdf, type, eta, roughness, true);
+ }
+ }
+
+ break;
+ }
+ case CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID: {
#ifdef __CAUSTICS_TRICKS__
- if(!kernel_data.integrator.caustics_reflective && (path_flag & PATH_RAY_DIFFUSE))
- break;
+ if (!kernel_data.integrator.caustics_reflective &&
+ !kernel_data.integrator.caustics_refractive && (path_flag & PATH_RAY_DIFFUSE))
+ break;
#endif
- float3 weight = sd->svm_closure_weight * mix_weight;
- MicrofacetBsdf *bsdf = (MicrofacetBsdf*)bsdf_alloc(sd, sizeof(MicrofacetBsdf), weight);
-
- if(!bsdf) {
- break;
- }
-
- float roughness = sqr(param1);
-
- bsdf->N = N;
- bsdf->T = make_float3(0.0f, 0.0f, 0.0f);
- bsdf->alpha_x = roughness;
- bsdf->alpha_y = roughness;
- bsdf->ior = 0.0f;
- bsdf->extra = NULL;
-
- /* setup bsdf */
- if(type == CLOSURE_BSDF_REFLECTION_ID)
- sd->flag |= bsdf_reflection_setup(bsdf);
- else if(type == CLOSURE_BSDF_MICROFACET_BECKMANN_ID)
- sd->flag |= bsdf_microfacet_beckmann_setup(bsdf);
- else if(type == CLOSURE_BSDF_MICROFACET_GGX_ID)
- sd->flag |= bsdf_microfacet_ggx_setup(bsdf);
- else if(type == CLOSURE_BSDF_MICROFACET_MULTI_GGX_ID) {
- kernel_assert(stack_valid(data_node.z));
- bsdf->extra = (MicrofacetExtra*)closure_alloc_extra(sd, sizeof(MicrofacetExtra));
- if(bsdf->extra) {
- bsdf->extra->color = stack_load_float3(stack, data_node.z);
- bsdf->extra->cspec0 = make_float3(0.0f, 0.0f, 0.0f);
- bsdf->extra->clearcoat = 0.0f;
- sd->flag |= bsdf_microfacet_multi_ggx_setup(bsdf);
- }
- }
- else {
- sd->flag |= bsdf_ashikhmin_shirley_setup(bsdf);
- }
-
- break;
- }
- case CLOSURE_BSDF_REFRACTION_ID:
- case CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID:
- case CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID: {
+ float3 weight = sd->svm_closure_weight * mix_weight;
+ MicrofacetBsdf *bsdf = (MicrofacetBsdf *)bsdf_alloc(sd, sizeof(MicrofacetBsdf), weight);
+ if (!bsdf) {
+ break;
+ }
+
+ MicrofacetExtra *extra = (MicrofacetExtra *)closure_alloc_extra(sd, sizeof(MicrofacetExtra));
+ if (!extra) {
+ break;
+ }
+
+ bsdf->N = N;
+ bsdf->extra = extra;
+ bsdf->T = make_float3(0.0f, 0.0f, 0.0f);
+
+ float roughness = sqr(param1);
+ bsdf->alpha_x = roughness;
+ bsdf->alpha_y = roughness;
+ float eta = fmaxf(param2, 1e-5f);
+ bsdf->ior = (sd->flag & SD_BACKFACING) ? 1.0f / eta : eta;
+
+ kernel_assert(stack_valid(data_node.z));
+ bsdf->extra->color = stack_load_float3(stack, data_node.z);
+ bsdf->extra->cspec0 = make_float3(0.0f, 0.0f, 0.0f);
+ bsdf->extra->clearcoat = 0.0f;
+
+ /* setup bsdf */
+ sd->flag |= bsdf_microfacet_multi_ggx_glass_setup(bsdf);
+ break;
+ }
+ case CLOSURE_BSDF_MICROFACET_BECKMANN_ANISO_ID:
+ case CLOSURE_BSDF_MICROFACET_GGX_ANISO_ID:
+ case CLOSURE_BSDF_MICROFACET_MULTI_GGX_ANISO_ID:
+ case CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ANISO_ID: {
#ifdef __CAUSTICS_TRICKS__
- if(!kernel_data.integrator.caustics_refractive && (path_flag & PATH_RAY_DIFFUSE))
- break;
+ if (!kernel_data.integrator.caustics_reflective && (path_flag & PATH_RAY_DIFFUSE))
+ break;
#endif
- float3 weight = sd->svm_closure_weight * mix_weight;
- MicrofacetBsdf *bsdf = (MicrofacetBsdf*)bsdf_alloc(sd, sizeof(MicrofacetBsdf), weight);
-
- if(bsdf) {
- bsdf->N = N;
- bsdf->T = make_float3(0.0f, 0.0f, 0.0f);
- bsdf->extra = NULL;
-
- float eta = fmaxf(param2, 1e-5f);
- eta = (sd->flag & SD_BACKFACING)? 1.0f/eta: eta;
-
- /* setup bsdf */
- if(type == CLOSURE_BSDF_REFRACTION_ID) {
- bsdf->alpha_x = 0.0f;
- bsdf->alpha_y = 0.0f;
- bsdf->ior = eta;
-
- sd->flag |= bsdf_refraction_setup(bsdf);
- }
- else {
- float roughness = sqr(param1);
- bsdf->alpha_x = roughness;
- bsdf->alpha_y = roughness;
- bsdf->ior = eta;
-
- if(type == CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID)
- sd->flag |= bsdf_microfacet_beckmann_refraction_setup(bsdf);
- else
- sd->flag |= bsdf_microfacet_ggx_refraction_setup(bsdf);
- }
- }
-
- break;
- }
- case CLOSURE_BSDF_SHARP_GLASS_ID:
- case CLOSURE_BSDF_MICROFACET_GGX_GLASS_ID:
- case CLOSURE_BSDF_MICROFACET_BECKMANN_GLASS_ID: {
+ float3 weight = sd->svm_closure_weight * mix_weight;
+ MicrofacetBsdf *bsdf = (MicrofacetBsdf *)bsdf_alloc(sd, sizeof(MicrofacetBsdf), weight);
+
+ if (bsdf) {
+ bsdf->N = N;
+ bsdf->extra = NULL;
+ bsdf->T = stack_load_float3(stack, data_node.y);
+
+ /* rotate tangent */
+ float rotation = stack_load_float(stack, data_node.z);
+
+ if (rotation != 0.0f)
+ bsdf->T = rotate_around_axis(bsdf->T, bsdf->N, rotation * M_2PI_F);
+
+ /* compute roughness */
+ float roughness = sqr(param1);
+ float anisotropy = clamp(param2, -0.99f, 0.99f);
+
+ if (anisotropy < 0.0f) {
+ bsdf->alpha_x = roughness / (1.0f + anisotropy);
+ bsdf->alpha_y = roughness * (1.0f + anisotropy);
+ }
+ else {
+ bsdf->alpha_x = roughness * (1.0f - anisotropy);
+ bsdf->alpha_y = roughness / (1.0f - anisotropy);
+ }
+
+ bsdf->ior = 0.0f;
+
+ if (type == CLOSURE_BSDF_MICROFACET_BECKMANN_ANISO_ID) {
+ sd->flag |= bsdf_microfacet_beckmann_aniso_setup(bsdf);
+ }
+ else if (type == CLOSURE_BSDF_MICROFACET_GGX_ANISO_ID) {
+ sd->flag |= bsdf_microfacet_ggx_aniso_setup(bsdf);
+ }
+ else if (type == CLOSURE_BSDF_MICROFACET_MULTI_GGX_ANISO_ID) {
+ kernel_assert(stack_valid(data_node.w));
+ bsdf->extra = (MicrofacetExtra *)closure_alloc_extra(sd, sizeof(MicrofacetExtra));
+ if (bsdf->extra) {
+ bsdf->extra->color = stack_load_float3(stack, data_node.w);
+ bsdf->extra->cspec0 = make_float3(0.0f, 0.0f, 0.0f);
+ bsdf->extra->clearcoat = 0.0f;
+ sd->flag |= bsdf_microfacet_multi_ggx_aniso_setup(bsdf);
+ }
+ }
+ else
+ sd->flag |= bsdf_ashikhmin_shirley_aniso_setup(bsdf);
+ }
+ break;
+ }
+ case CLOSURE_BSDF_ASHIKHMIN_VELVET_ID: {
+ float3 weight = sd->svm_closure_weight * mix_weight;
+ VelvetBsdf *bsdf = (VelvetBsdf *)bsdf_alloc(sd, sizeof(VelvetBsdf), weight);
+
+ if (bsdf) {
+ bsdf->N = N;
+
+ bsdf->sigma = saturate(param1);
+ sd->flag |= bsdf_ashikhmin_velvet_setup(bsdf);
+ }
+ break;
+ }
+ case CLOSURE_BSDF_GLOSSY_TOON_ID:
#ifdef __CAUSTICS_TRICKS__
- if(!kernel_data.integrator.caustics_reflective &&
- !kernel_data.integrator.caustics_refractive && (path_flag & PATH_RAY_DIFFUSE))
- {
- break;
- }
+ if (!kernel_data.integrator.caustics_reflective && (path_flag & PATH_RAY_DIFFUSE))
+ break;
+ ATTR_FALLTHROUGH;
#endif
- float3 weight = sd->svm_closure_weight * mix_weight;
-
- /* index of refraction */
- float eta = fmaxf(param2, 1e-5f);
- eta = (sd->flag & SD_BACKFACING)? 1.0f/eta: eta;
-
- /* fresnel */
- float cosNO = dot(N, sd->I);
- float fresnel = fresnel_dielectric_cos(cosNO, eta);
- float roughness = sqr(param1);
-
- /* reflection */
-#ifdef __CAUSTICS_TRICKS__
- if(kernel_data.integrator.caustics_reflective || (path_flag & PATH_RAY_DIFFUSE) == 0)
-#endif
- {
- MicrofacetBsdf *bsdf = (MicrofacetBsdf*)bsdf_alloc(sd, sizeof(MicrofacetBsdf), weight*fresnel);
-
- if(bsdf) {
- bsdf->N = N;
- bsdf->T = make_float3(0.0f, 0.0f, 0.0f);
- bsdf->extra = NULL;
- svm_node_glass_setup(sd, bsdf, type, eta, roughness, false);
- }
- }
-
- /* refraction */
-#ifdef __CAUSTICS_TRICKS__
- if(kernel_data.integrator.caustics_refractive || (path_flag & PATH_RAY_DIFFUSE) == 0)
-#endif
- {
- MicrofacetBsdf *bsdf = (MicrofacetBsdf*)bsdf_alloc(sd, sizeof(MicrofacetBsdf), weight*(1.0f - fresnel));
-
- if(bsdf) {
- bsdf->N = N;
- bsdf->T = make_float3(0.0f, 0.0f, 0.0f);
- bsdf->extra = NULL;
- svm_node_glass_setup(sd, bsdf, type, eta, roughness, true);
- }
- }
-
- break;
- }
- case CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID: {
-#ifdef __CAUSTICS_TRICKS__
- if(!kernel_data.integrator.caustics_reflective && !kernel_data.integrator.caustics_refractive && (path_flag & PATH_RAY_DIFFUSE))
- break;
-#endif
- float3 weight = sd->svm_closure_weight * mix_weight;
- MicrofacetBsdf *bsdf = (MicrofacetBsdf*)bsdf_alloc(sd, sizeof(MicrofacetBsdf), weight);
- if(!bsdf) {
- break;
- }
-
- MicrofacetExtra *extra = (MicrofacetExtra*)closure_alloc_extra(sd, sizeof(MicrofacetExtra));
- if(!extra) {
- break;
- }
-
- bsdf->N = N;
- bsdf->extra = extra;
- bsdf->T = make_float3(0.0f, 0.0f, 0.0f);
-
- float roughness = sqr(param1);
- bsdf->alpha_x = roughness;
- bsdf->alpha_y = roughness;
- float eta = fmaxf(param2, 1e-5f);
- bsdf->ior = (sd->flag & SD_BACKFACING)? 1.0f/eta: eta;
-
- kernel_assert(stack_valid(data_node.z));
- bsdf->extra->color = stack_load_float3(stack, data_node.z);
- bsdf->extra->cspec0 = make_float3(0.0f, 0.0f, 0.0f);
- bsdf->extra->clearcoat = 0.0f;
-
- /* setup bsdf */
- sd->flag |= bsdf_microfacet_multi_ggx_glass_setup(bsdf);
- break;
- }
- case CLOSURE_BSDF_MICROFACET_BECKMANN_ANISO_ID:
- case CLOSURE_BSDF_MICROFACET_GGX_ANISO_ID:
- case CLOSURE_BSDF_MICROFACET_MULTI_GGX_ANISO_ID:
- case CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ANISO_ID: {
-#ifdef __CAUSTICS_TRICKS__
- if(!kernel_data.integrator.caustics_reflective && (path_flag & PATH_RAY_DIFFUSE))
- break;
-#endif
- float3 weight = sd->svm_closure_weight * mix_weight;
- MicrofacetBsdf *bsdf = (MicrofacetBsdf*)bsdf_alloc(sd, sizeof(MicrofacetBsdf), weight);
-
- if(bsdf) {
- bsdf->N = N;
- bsdf->extra = NULL;
- bsdf->T = stack_load_float3(stack, data_node.y);
-
- /* rotate tangent */
- float rotation = stack_load_float(stack, data_node.z);
-
- if(rotation != 0.0f)
- bsdf->T = rotate_around_axis(bsdf->T, bsdf->N, rotation * M_2PI_F);
-
- /* compute roughness */
- float roughness = sqr(param1);
- float anisotropy = clamp(param2, -0.99f, 0.99f);
-
- if(anisotropy < 0.0f) {
- bsdf->alpha_x = roughness/(1.0f + anisotropy);
- bsdf->alpha_y = roughness*(1.0f + anisotropy);
- }
- else {
- bsdf->alpha_x = roughness*(1.0f - anisotropy);
- bsdf->alpha_y = roughness/(1.0f - anisotropy);
- }
-
- bsdf->ior = 0.0f;
-
- if(type == CLOSURE_BSDF_MICROFACET_BECKMANN_ANISO_ID) {
- sd->flag |= bsdf_microfacet_beckmann_aniso_setup(bsdf);
- }
- else if(type == CLOSURE_BSDF_MICROFACET_GGX_ANISO_ID) {
- sd->flag |= bsdf_microfacet_ggx_aniso_setup(bsdf);
- }
- else if(type == CLOSURE_BSDF_MICROFACET_MULTI_GGX_ANISO_ID) {
- kernel_assert(stack_valid(data_node.w));
- bsdf->extra = (MicrofacetExtra*)closure_alloc_extra(sd, sizeof(MicrofacetExtra));
- if(bsdf->extra) {
- bsdf->extra->color = stack_load_float3(stack, data_node.w);
- bsdf->extra->cspec0 = make_float3(0.0f, 0.0f, 0.0f);
- bsdf->extra->clearcoat = 0.0f;
- sd->flag |= bsdf_microfacet_multi_ggx_aniso_setup(bsdf);
- }
- }
- else
- sd->flag |= bsdf_ashikhmin_shirley_aniso_setup(bsdf);
- }
- break;
- }
- case CLOSURE_BSDF_ASHIKHMIN_VELVET_ID: {
- float3 weight = sd->svm_closure_weight * mix_weight;
- VelvetBsdf *bsdf = (VelvetBsdf*)bsdf_alloc(sd, sizeof(VelvetBsdf), weight);
-
- if(bsdf) {
- bsdf->N = N;
-
- bsdf->sigma = saturate(param1);
- sd->flag |= bsdf_ashikhmin_velvet_setup(bsdf);
- }
- break;
- }
- case CLOSURE_BSDF_GLOSSY_TOON_ID:
-#ifdef __CAUSTICS_TRICKS__
- if(!kernel_data.integrator.caustics_reflective && (path_flag & PATH_RAY_DIFFUSE))
- break;
- ATTR_FALLTHROUGH;
-#endif
- case CLOSURE_BSDF_DIFFUSE_TOON_ID: {
- float3 weight = sd->svm_closure_weight * mix_weight;
- ToonBsdf *bsdf = (ToonBsdf*)bsdf_alloc(sd, sizeof(ToonBsdf), weight);
-
- if(bsdf) {
- bsdf->N = N;
- bsdf->size = param1;
- bsdf->smooth = param2;
-
- if(type == CLOSURE_BSDF_DIFFUSE_TOON_ID)
- sd->flag |= bsdf_diffuse_toon_setup(bsdf);
- else
- sd->flag |= bsdf_glossy_toon_setup(bsdf);
- }
- break;
- }
+ case CLOSURE_BSDF_DIFFUSE_TOON_ID: {
+ float3 weight = sd->svm_closure_weight * mix_weight;
+ ToonBsdf *bsdf = (ToonBsdf *)bsdf_alloc(sd, sizeof(ToonBsdf), weight);
+
+ if (bsdf) {
+ bsdf->N = N;
+ bsdf->size = param1;
+ bsdf->smooth = param2;
+
+ if (type == CLOSURE_BSDF_DIFFUSE_TOON_ID)
+ sd->flag |= bsdf_diffuse_toon_setup(bsdf);
+ else
+ sd->flag |= bsdf_glossy_toon_setup(bsdf);
+ }
+ break;
+ }
#ifdef __HAIR__
- case CLOSURE_BSDF_HAIR_PRINCIPLED_ID: {
- uint4 data_node2 = read_node(kg, offset);
- uint4 data_node3 = read_node(kg, offset);
- uint4 data_node4 = read_node(kg, offset);
-
- float3 weight = sd->svm_closure_weight * mix_weight;
-
- uint offset_ofs, ior_ofs, color_ofs, parametrization;
- decode_node_uchar4(data_node.y, &offset_ofs, &ior_ofs, &color_ofs, &parametrization);
- float alpha = stack_load_float_default(stack, offset_ofs, data_node.z);
- float ior = stack_load_float_default(stack, ior_ofs, data_node.w);
-
- uint coat_ofs, melanin_ofs, melanin_redness_ofs, absorption_coefficient_ofs;
- decode_node_uchar4(data_node2.x, &coat_ofs, &melanin_ofs, &melanin_redness_ofs, &absorption_coefficient_ofs);
-
- uint tint_ofs, random_ofs, random_color_ofs, random_roughness_ofs;
- decode_node_uchar4(data_node3.x, &tint_ofs, &random_ofs, &random_color_ofs, &random_roughness_ofs);
-
- const AttributeDescriptor attr_descr_random = find_attribute(kg, sd, data_node4.y);
- float random = 0.0f;
- if(attr_descr_random.offset != ATTR_STD_NOT_FOUND) {
- random = primitive_surface_attribute_float(kg, sd, attr_descr_random, NULL, NULL);
- }
- else {
- random = stack_load_float_default(stack, random_ofs, data_node3.y);
- }
-
-
- PrincipledHairBSDF *bsdf = (PrincipledHairBSDF*)bsdf_alloc(sd, sizeof(PrincipledHairBSDF), weight);
- if(bsdf) {
- PrincipledHairExtra *extra = (PrincipledHairExtra*)closure_alloc_extra(sd, sizeof(PrincipledHairExtra));
-
- if(!extra)
- break;
-
- /* Random factors range: [-randomization/2, +randomization/2]. */
- float random_roughness = stack_load_float_default(stack, random_roughness_ofs, data_node3.w);
- float factor_random_roughness = 1.0f + 2.0f*(random - 0.5f)*random_roughness;
- float roughness = param1 * factor_random_roughness;
- float radial_roughness = param2 * factor_random_roughness;
-
- /* Remap Coat value to [0, 100]% of Roughness. */
- float coat = stack_load_float_default(stack, coat_ofs, data_node2.y);
- float m0_roughness = 1.0f - clamp(coat, 0.0f, 1.0f);
-
- bsdf->N = N;
- bsdf->v = roughness;
- bsdf->s = radial_roughness;
- bsdf->m0_roughness = m0_roughness;
- bsdf->alpha = alpha;
- bsdf->eta = ior;
- bsdf->extra = extra;
-
- switch(parametrization) {
- case NODE_PRINCIPLED_HAIR_DIRECT_ABSORPTION: {
- float3 absorption_coefficient = stack_load_float3(stack, absorption_coefficient_ofs);
- bsdf->sigma = absorption_coefficient;
- break;
- }
- case NODE_PRINCIPLED_HAIR_PIGMENT_CONCENTRATION: {
- float melanin = stack_load_float_default(stack, melanin_ofs, data_node2.z);
- float melanin_redness = stack_load_float_default(stack, melanin_redness_ofs, data_node2.w);
-
- /* Randomize melanin. */
- float random_color = stack_load_float_default(stack, random_color_ofs, data_node3.z);
- random_color = clamp(random_color, 0.0f, 1.0f);
- float factor_random_color = 1.0f + 2.0f * (random - 0.5f) * random_color;
- melanin *= factor_random_color;
-
- /* Map melanin 0..inf from more perceptually linear 0..1. */
- melanin = -logf(fmaxf(1.0f - melanin, 0.0001f));
-
- /* Benedikt Bitterli's melanin ratio remapping. */
- float eumelanin = melanin * (1.0f - melanin_redness);
- float pheomelanin = melanin * melanin_redness;
- float3 melanin_sigma = sigma_from_concentration(eumelanin, pheomelanin);
-
- /* Optional tint. */
- float3 tint = stack_load_float3(stack, tint_ofs);
- float3 tint_sigma = sigma_from_reflectance(tint, radial_roughness);
-
- bsdf->sigma = melanin_sigma + tint_sigma;
- break;
- }
- case NODE_PRINCIPLED_HAIR_REFLECTANCE: {
- float3 color = stack_load_float3(stack, color_ofs);
- bsdf->sigma = sigma_from_reflectance(color, radial_roughness);
- break;
- }
- default: {
- /* Fallback to brownish hair, same as defaults for melanin. */
- kernel_assert(!"Invalid Principled Hair parametrization!");
- bsdf->sigma = sigma_from_concentration(0.0f, 0.8054375f);
- break;
- }
- }
-
- sd->flag |= bsdf_principled_hair_setup(sd, bsdf);
- }
- break;
- }
- case CLOSURE_BSDF_HAIR_REFLECTION_ID:
- case CLOSURE_BSDF_HAIR_TRANSMISSION_ID: {
- float3 weight = sd->svm_closure_weight * mix_weight;
-
- if(sd->flag & SD_BACKFACING && sd->type & PRIMITIVE_ALL_CURVE) {
- /* todo: giving a fixed weight here will cause issues when
- * mixing multiple BSDFS. energy will not be conserved and
- * the throughput can blow up after multiple bounces. we
- * better figure out a way to skip backfaces from rays
- * spawned by transmission from the front */
- bsdf_transparent_setup(sd, make_float3(1.0f, 1.0f, 1.0f), path_flag);
- }
- else {
- HairBsdf *bsdf = (HairBsdf*)bsdf_alloc(sd, sizeof(HairBsdf), weight);
-
- if(bsdf) {
- bsdf->N = N;
- bsdf->roughness1 = param1;
- bsdf->roughness2 = param2;
- bsdf->offset = -stack_load_float(stack, data_node.z);
-
- if(stack_valid(data_node.y)) {
- bsdf->T = normalize(stack_load_float3(stack, data_node.y));
- }
- else if(!(sd->type & PRIMITIVE_ALL_CURVE)) {
- bsdf->T = normalize(sd->dPdv);
- bsdf->offset = 0.0f;
- }
- else
- bsdf->T = normalize(sd->dPdu);
-
- if(type == CLOSURE_BSDF_HAIR_REFLECTION_ID) {
- sd->flag |= bsdf_hair_reflection_setup(bsdf);
- }
- else {
- sd->flag |= bsdf_hair_transmission_setup(bsdf);
- }
- }
- }
-
- break;
- }
-#endif /* __HAIR__ */
+ case CLOSURE_BSDF_HAIR_PRINCIPLED_ID: {
+ uint4 data_node2 = read_node(kg, offset);
+ uint4 data_node3 = read_node(kg, offset);
+ uint4 data_node4 = read_node(kg, offset);
+
+ float3 weight = sd->svm_closure_weight * mix_weight;
+
+ uint offset_ofs, ior_ofs, color_ofs, parametrization;
+ decode_node_uchar4(data_node.y, &offset_ofs, &ior_ofs, &color_ofs, &parametrization);
+ float alpha = stack_load_float_default(stack, offset_ofs, data_node.z);
+ float ior = stack_load_float_default(stack, ior_ofs, data_node.w);
+
+ uint coat_ofs, melanin_ofs, melanin_redness_ofs, absorption_coefficient_ofs;
+ decode_node_uchar4(data_node2.x,
+ &coat_ofs,
+ &melanin_ofs,
+ &melanin_redness_ofs,
+ &absorption_coefficient_ofs);
+
+ uint tint_ofs, random_ofs, random_color_ofs, random_roughness_ofs;
+ decode_node_uchar4(
+ data_node3.x, &tint_ofs, &random_ofs, &random_color_ofs, &random_roughness_ofs);
+
+ const AttributeDescriptor attr_descr_random = find_attribute(kg, sd, data_node4.y);
+ float random = 0.0f;
+ if (attr_descr_random.offset != ATTR_STD_NOT_FOUND) {
+ random = primitive_surface_attribute_float(kg, sd, attr_descr_random, NULL, NULL);
+ }
+ else {
+ random = stack_load_float_default(stack, random_ofs, data_node3.y);
+ }
+
+ PrincipledHairBSDF *bsdf = (PrincipledHairBSDF *)bsdf_alloc(
+ sd, sizeof(PrincipledHairBSDF), weight);
+ if (bsdf) {
+ PrincipledHairExtra *extra = (PrincipledHairExtra *)closure_alloc_extra(
+ sd, sizeof(PrincipledHairExtra));
+
+ if (!extra)
+ break;
+
+ /* Random factors range: [-randomization/2, +randomization/2]. */
+ float random_roughness = stack_load_float_default(
+ stack, random_roughness_ofs, data_node3.w);
+ float factor_random_roughness = 1.0f + 2.0f * (random - 0.5f) * random_roughness;
+ float roughness = param1 * factor_random_roughness;
+ float radial_roughness = param2 * factor_random_roughness;
+
+ /* Remap Coat value to [0, 100]% of Roughness. */
+ float coat = stack_load_float_default(stack, coat_ofs, data_node2.y);
+ float m0_roughness = 1.0f - clamp(coat, 0.0f, 1.0f);
+
+ bsdf->N = N;
+ bsdf->v = roughness;
+ bsdf->s = radial_roughness;
+ bsdf->m0_roughness = m0_roughness;
+ bsdf->alpha = alpha;
+ bsdf->eta = ior;
+ bsdf->extra = extra;
+
+ switch (parametrization) {
+ case NODE_PRINCIPLED_HAIR_DIRECT_ABSORPTION: {
+ float3 absorption_coefficient = stack_load_float3(stack, absorption_coefficient_ofs);
+ bsdf->sigma = absorption_coefficient;
+ break;
+ }
+ case NODE_PRINCIPLED_HAIR_PIGMENT_CONCENTRATION: {
+ float melanin = stack_load_float_default(stack, melanin_ofs, data_node2.z);
+ float melanin_redness = stack_load_float_default(
+ stack, melanin_redness_ofs, data_node2.w);
+
+ /* Randomize melanin. */
+ float random_color = stack_load_float_default(stack, random_color_ofs, data_node3.z);
+ random_color = clamp(random_color, 0.0f, 1.0f);
+ float factor_random_color = 1.0f + 2.0f * (random - 0.5f) * random_color;
+ melanin *= factor_random_color;
+
+ /* Map melanin 0..inf from more perceptually linear 0..1. */
+ melanin = -logf(fmaxf(1.0f - melanin, 0.0001f));
+
+ /* Benedikt Bitterli's melanin ratio remapping. */
+ float eumelanin = melanin * (1.0f - melanin_redness);
+ float pheomelanin = melanin * melanin_redness;
+ float3 melanin_sigma = sigma_from_concentration(eumelanin, pheomelanin);
+
+ /* Optional tint. */
+ float3 tint = stack_load_float3(stack, tint_ofs);
+ float3 tint_sigma = sigma_from_reflectance(tint, radial_roughness);
+
+ bsdf->sigma = melanin_sigma + tint_sigma;
+ break;
+ }
+ case NODE_PRINCIPLED_HAIR_REFLECTANCE: {
+ float3 color = stack_load_float3(stack, color_ofs);
+ bsdf->sigma = sigma_from_reflectance(color, radial_roughness);
+ break;
+ }
+ default: {
+ /* Fallback to brownish hair, same as defaults for melanin. */
+ kernel_assert(!"Invalid Principled Hair parametrization!");
+ bsdf->sigma = sigma_from_concentration(0.0f, 0.8054375f);
+ break;
+ }
+ }
+
+ sd->flag |= bsdf_principled_hair_setup(sd, bsdf);
+ }
+ break;
+ }
+ case CLOSURE_BSDF_HAIR_REFLECTION_ID:
+ case CLOSURE_BSDF_HAIR_TRANSMISSION_ID: {
+ float3 weight = sd->svm_closure_weight * mix_weight;
+
+ if (sd->flag & SD_BACKFACING && sd->type & PRIMITIVE_ALL_CURVE) {
+ /* todo: giving a fixed weight here will cause issues when
+ * mixing multiple BSDFS. energy will not be conserved and
+ * the throughput can blow up after multiple bounces. we
+ * better figure out a way to skip backfaces from rays
+ * spawned by transmission from the front */
+ bsdf_transparent_setup(sd, make_float3(1.0f, 1.0f, 1.0f), path_flag);
+ }
+ else {
+ HairBsdf *bsdf = (HairBsdf *)bsdf_alloc(sd, sizeof(HairBsdf), weight);
+
+ if (bsdf) {
+ bsdf->N = N;
+ bsdf->roughness1 = param1;
+ bsdf->roughness2 = param2;
+ bsdf->offset = -stack_load_float(stack, data_node.z);
+
+ if (stack_valid(data_node.y)) {
+ bsdf->T = normalize(stack_load_float3(stack, data_node.y));
+ }
+ else if (!(sd->type & PRIMITIVE_ALL_CURVE)) {
+ bsdf->T = normalize(sd->dPdv);
+ bsdf->offset = 0.0f;
+ }
+ else
+ bsdf->T = normalize(sd->dPdu);
+
+ if (type == CLOSURE_BSDF_HAIR_REFLECTION_ID) {
+ sd->flag |= bsdf_hair_reflection_setup(bsdf);
+ }
+ else {
+ sd->flag |= bsdf_hair_transmission_setup(bsdf);
+ }
+ }
+ }
+
+ break;
+ }
+#endif /* __HAIR__ */
#ifdef __SUBSURFACE__
- case CLOSURE_BSSRDF_CUBIC_ID:
- case CLOSURE_BSSRDF_GAUSSIAN_ID:
- case CLOSURE_BSSRDF_BURLEY_ID:
- case CLOSURE_BSSRDF_RANDOM_WALK_ID: {
- float3 weight = sd->svm_closure_weight * mix_weight;
- Bssrdf *bssrdf = bssrdf_alloc(sd, weight);
-
- if(bssrdf) {
- /* disable in case of diffuse ancestor, can't see it well then and
- * adds considerably noise due to probabilities of continuing path
- * getting lower and lower */
- if(path_flag & PATH_RAY_DIFFUSE_ANCESTOR)
- param1 = 0.0f;
-
- bssrdf->radius = stack_load_float3(stack, data_node.z)*param1;
- bssrdf->albedo = sd->svm_closure_weight;
- bssrdf->texture_blur = param2;
- bssrdf->sharpness = stack_load_float(stack, data_node.w);
- bssrdf->N = N;
- bssrdf->roughness = 0.0f;
- sd->flag |= bssrdf_setup(sd, bssrdf, (ClosureType)type);
- }
-
- break;
- }
+ case CLOSURE_BSSRDF_CUBIC_ID:
+ case CLOSURE_BSSRDF_GAUSSIAN_ID:
+ case CLOSURE_BSSRDF_BURLEY_ID:
+ case CLOSURE_BSSRDF_RANDOM_WALK_ID: {
+ float3 weight = sd->svm_closure_weight * mix_weight;
+ Bssrdf *bssrdf = bssrdf_alloc(sd, weight);
+
+ if (bssrdf) {
+ /* disable in case of diffuse ancestor, can't see it well then and
+ * adds considerably noise due to probabilities of continuing path
+ * getting lower and lower */
+ if (path_flag & PATH_RAY_DIFFUSE_ANCESTOR)
+ param1 = 0.0f;
+
+ bssrdf->radius = stack_load_float3(stack, data_node.z) * param1;
+ bssrdf->albedo = sd->svm_closure_weight;
+ bssrdf->texture_blur = param2;
+ bssrdf->sharpness = stack_load_float(stack, data_node.w);
+ bssrdf->N = N;
+ bssrdf->roughness = 0.0f;
+ sd->flag |= bssrdf_setup(sd, bssrdf, (ClosureType)type);
+ }
+
+ break;
+ }
#endif
- default:
- break;
- }
+ default:
+ break;
+ }
}
-ccl_device void svm_node_closure_volume(KernelGlobals *kg, ShaderData *sd, float *stack, uint4 node, ShaderType shader_type)
+ccl_device void svm_node_closure_volume(
+ KernelGlobals *kg, ShaderData *sd, float *stack, uint4 node, ShaderType shader_type)
{
#ifdef __VOLUME__
- /* Only sum extinction for volumes, variable is shared with surface transparency. */
- if(shader_type != SHADER_TYPE_VOLUME) {
- return;
- }
-
- uint type, density_offset, anisotropy_offset;
-
- uint mix_weight_offset;
- decode_node_uchar4(node.y, &type, &density_offset, &anisotropy_offset, &mix_weight_offset);
- float mix_weight = (stack_valid(mix_weight_offset)? stack_load_float(stack, mix_weight_offset): 1.0f);
-
- if(mix_weight == 0.0f) {
- return;
- }
-
- float density = (stack_valid(density_offset))? stack_load_float(stack, density_offset): __uint_as_float(node.z);
- density = mix_weight * fmaxf(density, 0.0f);
-
- /* Compute scattering coefficient. */
- float3 weight = sd->svm_closure_weight;
-
- if(type == CLOSURE_VOLUME_ABSORPTION_ID) {
- weight = make_float3(1.0f, 1.0f, 1.0f) - weight;
- }
-
- weight *= density;
-
- /* Add closure for volume scattering. */
- if(type == CLOSURE_VOLUME_HENYEY_GREENSTEIN_ID) {
- HenyeyGreensteinVolume *volume = (HenyeyGreensteinVolume*)bsdf_alloc(sd, sizeof(HenyeyGreensteinVolume), weight);
-
- if(volume) {
- float anisotropy = (stack_valid(anisotropy_offset))? stack_load_float(stack, anisotropy_offset): __uint_as_float(node.w);
- volume->g = anisotropy; /* g */
- sd->flag |= volume_henyey_greenstein_setup(volume);
- }
- }
-
- /* Sum total extinction weight. */
- volume_extinction_setup(sd, weight);
+ /* Only sum extinction for volumes, variable is shared with surface transparency. */
+ if (shader_type != SHADER_TYPE_VOLUME) {
+ return;
+ }
+
+ uint type, density_offset, anisotropy_offset;
+
+ uint mix_weight_offset;
+ decode_node_uchar4(node.y, &type, &density_offset, &anisotropy_offset, &mix_weight_offset);
+ float mix_weight = (stack_valid(mix_weight_offset) ? stack_load_float(stack, mix_weight_offset) :
+ 1.0f);
+
+ if (mix_weight == 0.0f) {
+ return;
+ }
+
+ float density = (stack_valid(density_offset)) ? stack_load_float(stack, density_offset) :
+ __uint_as_float(node.z);
+ density = mix_weight * fmaxf(density, 0.0f);
+
+ /* Compute scattering coefficient. */
+ float3 weight = sd->svm_closure_weight;
+
+ if (type == CLOSURE_VOLUME_ABSORPTION_ID) {
+ weight = make_float3(1.0f, 1.0f, 1.0f) - weight;
+ }
+
+ weight *= density;
+
+ /* Add closure for volume scattering. */
+ if (type == CLOSURE_VOLUME_HENYEY_GREENSTEIN_ID) {
+ HenyeyGreensteinVolume *volume = (HenyeyGreensteinVolume *)bsdf_alloc(
+ sd, sizeof(HenyeyGreensteinVolume), weight);
+
+ if (volume) {
+ float anisotropy = (stack_valid(anisotropy_offset)) ?
+ stack_load_float(stack, anisotropy_offset) :
+ __uint_as_float(node.w);
+ volume->g = anisotropy; /* g */
+ sd->flag |= volume_henyey_greenstein_setup(volume);
+ }
+ }
+
+ /* Sum total extinction weight. */
+ volume_extinction_setup(sd, weight);
#endif
}
-ccl_device void svm_node_principled_volume(KernelGlobals *kg, ShaderData *sd, float *stack, uint4 node, ShaderType shader_type, int path_flag, int *offset)
+ccl_device void svm_node_principled_volume(KernelGlobals *kg,
+ ShaderData *sd,
+ float *stack,
+ uint4 node,
+ ShaderType shader_type,
+ int path_flag,
+ int *offset)
{
#ifdef __VOLUME__
- uint4 value_node = read_node(kg, offset);
- uint4 attr_node = read_node(kg, offset);
-
- /* Only sum extinction for volumes, variable is shared with surface transparency. */
- if(shader_type != SHADER_TYPE_VOLUME) {
- return;
- }
-
- uint density_offset, anisotropy_offset, absorption_color_offset, mix_weight_offset;
- decode_node_uchar4(node.y, &density_offset, &anisotropy_offset, &absorption_color_offset, &mix_weight_offset);
- float mix_weight = (stack_valid(mix_weight_offset)? stack_load_float(stack, mix_weight_offset): 1.0f);
-
- if(mix_weight == 0.0f) {
- return;
- }
-
- /* Compute density. */
- float primitive_density = 1.0f;
- float density = (stack_valid(density_offset))? stack_load_float(stack, density_offset): __uint_as_float(value_node.x);
- density = mix_weight * fmaxf(density, 0.0f);
-
- if(density > CLOSURE_WEIGHT_CUTOFF) {
- /* Density and color attribute lookup if available. */
- const AttributeDescriptor attr_density = find_attribute(kg, sd, attr_node.x);
- if(attr_density.offset != ATTR_STD_NOT_FOUND) {
- primitive_density = primitive_volume_attribute_float(kg, sd, attr_density);
- density = fmaxf(density * primitive_density, 0.0f);
- }
- }
-
- if(density > CLOSURE_WEIGHT_CUTOFF) {
- /* Compute scattering color. */
- float3 color = sd->svm_closure_weight;
-
- const AttributeDescriptor attr_color = find_attribute(kg, sd, attr_node.y);
- if(attr_color.offset != ATTR_STD_NOT_FOUND) {
- color *= primitive_volume_attribute_float3(kg, sd, attr_color);
- }
-
- /* Add closure for volume scattering. */
- HenyeyGreensteinVolume *volume = (HenyeyGreensteinVolume*)bsdf_alloc(sd, sizeof(HenyeyGreensteinVolume), color * density);
- if(volume) {
- float anisotropy = (stack_valid(anisotropy_offset))? stack_load_float(stack, anisotropy_offset): __uint_as_float(value_node.y);
- volume->g = anisotropy;
- sd->flag |= volume_henyey_greenstein_setup(volume);
- }
-
- /* Add extinction weight. */
- float3 zero = make_float3(0.0f, 0.0f, 0.0f);
- float3 one = make_float3(1.0f, 1.0f, 1.0f);
- float3 absorption_color = max(sqrt(stack_load_float3(stack, absorption_color_offset)), zero);
- float3 absorption = max(one - color, zero) * max(one - absorption_color, zero);
- volume_extinction_setup(sd, (color + absorption) * density);
- }
-
- /* Compute emission. */
- if(path_flag & PATH_RAY_SHADOW) {
- /* Don't need emission for shadows. */
- return;
- }
-
- uint emission_offset, emission_color_offset, blackbody_offset, temperature_offset;
- decode_node_uchar4(node.z, &emission_offset, &emission_color_offset, &blackbody_offset, &temperature_offset);
- float emission = (stack_valid(emission_offset))? stack_load_float(stack, emission_offset): __uint_as_float(value_node.z);
- float blackbody = (stack_valid(blackbody_offset))? stack_load_float(stack, blackbody_offset): __uint_as_float(value_node.w);
-
- if(emission > CLOSURE_WEIGHT_CUTOFF) {
- float3 emission_color = stack_load_float3(stack, emission_color_offset);
- emission_setup(sd, emission * emission_color);
- }
-
- if(blackbody > CLOSURE_WEIGHT_CUTOFF) {
- float T = stack_load_float(stack, temperature_offset);
-
- /* Add flame temperature from attribute if available. */
- const AttributeDescriptor attr_temperature = find_attribute(kg, sd, attr_node.z);
- if(attr_temperature.offset != ATTR_STD_NOT_FOUND) {
- float temperature = primitive_volume_attribute_float(kg, sd, attr_temperature);
- T *= fmaxf(temperature, 0.0f);
- }
-
- T = fmaxf(T, 0.0f);
-
- /* Stefan-Boltzmann law. */
- float T4 = sqr(sqr(T));
- float sigma = 5.670373e-8f * 1e-6f / M_PI_F;
- float intensity = sigma * mix(1.0f, T4, blackbody);
-
- if(intensity > CLOSURE_WEIGHT_CUTOFF) {
- float3 blackbody_tint = stack_load_float3(stack, node.w);
- float3 bb = blackbody_tint * intensity * svm_math_blackbody_color(T);
- emission_setup(sd, bb);
- }
- }
+ uint4 value_node = read_node(kg, offset);
+ uint4 attr_node = read_node(kg, offset);
+
+ /* Only sum extinction for volumes, variable is shared with surface transparency. */
+ if (shader_type != SHADER_TYPE_VOLUME) {
+ return;
+ }
+
+ uint density_offset, anisotropy_offset, absorption_color_offset, mix_weight_offset;
+ decode_node_uchar4(
+ node.y, &density_offset, &anisotropy_offset, &absorption_color_offset, &mix_weight_offset);
+ float mix_weight = (stack_valid(mix_weight_offset) ? stack_load_float(stack, mix_weight_offset) :
+ 1.0f);
+
+ if (mix_weight == 0.0f) {
+ return;
+ }
+
+ /* Compute density. */
+ float primitive_density = 1.0f;
+ float density = (stack_valid(density_offset)) ? stack_load_float(stack, density_offset) :
+ __uint_as_float(value_node.x);
+ density = mix_weight * fmaxf(density, 0.0f);
+
+ if (density > CLOSURE_WEIGHT_CUTOFF) {
+ /* Density and color attribute lookup if available. */
+ const AttributeDescriptor attr_density = find_attribute(kg, sd, attr_node.x);
+ if (attr_density.offset != ATTR_STD_NOT_FOUND) {
+ primitive_density = primitive_volume_attribute_float(kg, sd, attr_density);
+ density = fmaxf(density * primitive_density, 0.0f);
+ }
+ }
+
+ if (density > CLOSURE_WEIGHT_CUTOFF) {
+ /* Compute scattering color. */
+ float3 color = sd->svm_closure_weight;
+
+ const AttributeDescriptor attr_color = find_attribute(kg, sd, attr_node.y);
+ if (attr_color.offset != ATTR_STD_NOT_FOUND) {
+ color *= primitive_volume_attribute_float3(kg, sd, attr_color);
+ }
+
+ /* Add closure for volume scattering. */
+ HenyeyGreensteinVolume *volume = (HenyeyGreensteinVolume *)bsdf_alloc(
+ sd, sizeof(HenyeyGreensteinVolume), color * density);
+ if (volume) {
+ float anisotropy = (stack_valid(anisotropy_offset)) ?
+ stack_load_float(stack, anisotropy_offset) :
+ __uint_as_float(value_node.y);
+ volume->g = anisotropy;
+ sd->flag |= volume_henyey_greenstein_setup(volume);
+ }
+
+ /* Add extinction weight. */
+ float3 zero = make_float3(0.0f, 0.0f, 0.0f);
+ float3 one = make_float3(1.0f, 1.0f, 1.0f);
+ float3 absorption_color = max(sqrt(stack_load_float3(stack, absorption_color_offset)), zero);
+ float3 absorption = max(one - color, zero) * max(one - absorption_color, zero);
+ volume_extinction_setup(sd, (color + absorption) * density);
+ }
+
+ /* Compute emission. */
+ if (path_flag & PATH_RAY_SHADOW) {
+ /* Don't need emission for shadows. */
+ return;
+ }
+
+ uint emission_offset, emission_color_offset, blackbody_offset, temperature_offset;
+ decode_node_uchar4(
+ node.z, &emission_offset, &emission_color_offset, &blackbody_offset, &temperature_offset);
+ float emission = (stack_valid(emission_offset)) ? stack_load_float(stack, emission_offset) :
+ __uint_as_float(value_node.z);
+ float blackbody = (stack_valid(blackbody_offset)) ? stack_load_float(stack, blackbody_offset) :
+ __uint_as_float(value_node.w);
+
+ if (emission > CLOSURE_WEIGHT_CUTOFF) {
+ float3 emission_color = stack_load_float3(stack, emission_color_offset);
+ emission_setup(sd, emission * emission_color);
+ }
+
+ if (blackbody > CLOSURE_WEIGHT_CUTOFF) {
+ float T = stack_load_float(stack, temperature_offset);
+
+ /* Add flame temperature from attribute if available. */
+ const AttributeDescriptor attr_temperature = find_attribute(kg, sd, attr_node.z);
+ if (attr_temperature.offset != ATTR_STD_NOT_FOUND) {
+ float temperature = primitive_volume_attribute_float(kg, sd, attr_temperature);
+ T *= fmaxf(temperature, 0.0f);
+ }
+
+ T = fmaxf(T, 0.0f);
+
+ /* Stefan-Boltzmann law. */
+ float T4 = sqr(sqr(T));
+ float sigma = 5.670373e-8f * 1e-6f / M_PI_F;
+ float intensity = sigma * mix(1.0f, T4, blackbody);
+
+ if (intensity > CLOSURE_WEIGHT_CUTOFF) {
+ float3 blackbody_tint = stack_load_float3(stack, node.w);
+ float3 bb = blackbody_tint * intensity * svm_math_blackbody_color(T);
+ emission_setup(sd, bb);
+ }
+ }
#endif
}
ccl_device void svm_node_closure_emission(ShaderData *sd, float *stack, uint4 node)
{
- uint mix_weight_offset = node.y;
- float3 weight = sd->svm_closure_weight;
+ uint mix_weight_offset = node.y;
+ float3 weight = sd->svm_closure_weight;
- if(stack_valid(mix_weight_offset)) {
- float mix_weight = stack_load_float(stack, mix_weight_offset);
+ if (stack_valid(mix_weight_offset)) {
+ float mix_weight = stack_load_float(stack, mix_weight_offset);
- if(mix_weight == 0.0f)
- return;
+ if (mix_weight == 0.0f)
+ return;
- weight *= mix_weight;
- }
+ weight *= mix_weight;
+ }
- emission_setup(sd, weight);
+ emission_setup(sd, weight);
}
ccl_device void svm_node_closure_background(ShaderData *sd, float *stack, uint4 node)
{
- uint mix_weight_offset = node.y;
- float3 weight = sd->svm_closure_weight;
+ uint mix_weight_offset = node.y;
+ float3 weight = sd->svm_closure_weight;
- if(stack_valid(mix_weight_offset)) {
- float mix_weight = stack_load_float(stack, mix_weight_offset);
+ if (stack_valid(mix_weight_offset)) {
+ float mix_weight = stack_load_float(stack, mix_weight_offset);
- if(mix_weight == 0.0f)
- return;
+ if (mix_weight == 0.0f)
+ return;
- weight *= mix_weight;
- }
+ weight *= mix_weight;
+ }
- background_setup(sd, weight);
+ background_setup(sd, weight);
}
ccl_device void svm_node_closure_holdout(ShaderData *sd, float *stack, uint4 node)
{
- uint mix_weight_offset = node.y;
+ uint mix_weight_offset = node.y;
- if(stack_valid(mix_weight_offset)) {
- float mix_weight = stack_load_float(stack, mix_weight_offset);
+ if (stack_valid(mix_weight_offset)) {
+ float mix_weight = stack_load_float(stack, mix_weight_offset);
- if(mix_weight == 0.0f)
- return;
+ if (mix_weight == 0.0f)
+ return;
- closure_alloc(sd, sizeof(ShaderClosure), CLOSURE_HOLDOUT_ID, sd->svm_closure_weight * mix_weight);
- }
- else
- closure_alloc(sd, sizeof(ShaderClosure), CLOSURE_HOLDOUT_ID, sd->svm_closure_weight);
+ closure_alloc(
+ sd, sizeof(ShaderClosure), CLOSURE_HOLDOUT_ID, sd->svm_closure_weight * mix_weight);
+ }
+ else
+ closure_alloc(sd, sizeof(ShaderClosure), CLOSURE_HOLDOUT_ID, sd->svm_closure_weight);
- sd->flag |= SD_HOLDOUT;
+ sd->flag |= SD_HOLDOUT;
}
/* Closure Nodes */
ccl_device_inline void svm_node_closure_store_weight(ShaderData *sd, float3 weight)
{
- sd->svm_closure_weight = weight;
+ sd->svm_closure_weight = weight;
}
ccl_device void svm_node_closure_set_weight(ShaderData *sd, uint r, uint g, uint b)
{
- float3 weight = make_float3(__uint_as_float(r), __uint_as_float(g), __uint_as_float(b));
- svm_node_closure_store_weight(sd, weight);
+ float3 weight = make_float3(__uint_as_float(r), __uint_as_float(g), __uint_as_float(b));
+ svm_node_closure_store_weight(sd, weight);
}
ccl_device void svm_node_closure_weight(ShaderData *sd, float *stack, uint weight_offset)
{
- float3 weight = stack_load_float3(stack, weight_offset);
+ float3 weight = stack_load_float3(stack, weight_offset);
- svm_node_closure_store_weight(sd, weight);
+ svm_node_closure_store_weight(sd, weight);
}
-ccl_device void svm_node_emission_weight(KernelGlobals *kg, ShaderData *sd, float *stack, uint4 node)
+ccl_device void svm_node_emission_weight(KernelGlobals *kg,
+ ShaderData *sd,
+ float *stack,
+ uint4 node)
{
- uint color_offset = node.y;
- uint strength_offset = node.z;
+ uint color_offset = node.y;
+ uint strength_offset = node.z;
- float strength = stack_load_float(stack, strength_offset);
- float3 weight = stack_load_float3(stack, color_offset)*strength;
+ float strength = stack_load_float(stack, strength_offset);
+ float3 weight = stack_load_float3(stack, color_offset) * strength;
- svm_node_closure_store_weight(sd, weight);
+ svm_node_closure_store_weight(sd, weight);
}
ccl_device void svm_node_mix_closure(ShaderData *sd, float *stack, uint4 node)
{
- /* fetch weight from blend input, previous mix closures,
- * and write to stack to be used by closure nodes later */
- uint weight_offset, in_weight_offset, weight1_offset, weight2_offset;
- decode_node_uchar4(node.y, &weight_offset, &in_weight_offset, &weight1_offset, &weight2_offset);
+ /* fetch weight from blend input, previous mix closures,
+ * and write to stack to be used by closure nodes later */
+ uint weight_offset, in_weight_offset, weight1_offset, weight2_offset;
+ decode_node_uchar4(node.y, &weight_offset, &in_weight_offset, &weight1_offset, &weight2_offset);
- float weight = stack_load_float(stack, weight_offset);
- weight = saturate(weight);
+ float weight = stack_load_float(stack, weight_offset);
+ weight = saturate(weight);
- float in_weight = (stack_valid(in_weight_offset))? stack_load_float(stack, in_weight_offset): 1.0f;
+ float in_weight = (stack_valid(in_weight_offset)) ? stack_load_float(stack, in_weight_offset) :
+ 1.0f;
- if(stack_valid(weight1_offset))
- stack_store_float(stack, weight1_offset, in_weight*(1.0f - weight));
- if(stack_valid(weight2_offset))
- stack_store_float(stack, weight2_offset, in_weight*weight);
+ if (stack_valid(weight1_offset))
+ stack_store_float(stack, weight1_offset, in_weight * (1.0f - weight));
+ if (stack_valid(weight2_offset))
+ stack_store_float(stack, weight2_offset, in_weight * weight);
}
/* (Bump) normal */
-ccl_device void svm_node_set_normal(KernelGlobals *kg, ShaderData *sd, float *stack, uint in_direction, uint out_normal)
+ccl_device void svm_node_set_normal(
+ KernelGlobals *kg, ShaderData *sd, float *stack, uint in_direction, uint out_normal)
{
- float3 normal = stack_load_float3(stack, in_direction);
- sd->N = normal;
- stack_store_float3(stack, out_normal, normal);
+ float3 normal = stack_load_float3(stack, in_direction);
+ sd->N = normal;
+ stack_store_float3(stack, out_normal, normal);
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/svm/svm_color_util.h b/intern/cycles/kernel/svm/svm_color_util.h
index d5945f915c6..12b59d2616b 100644
--- a/intern/cycles/kernel/svm/svm_color_util.h
+++ b/intern/cycles/kernel/svm/svm_color_util.h
@@ -18,288 +18,310 @@ CCL_NAMESPACE_BEGIN
ccl_device float3 svm_mix_blend(float t, float3 col1, float3 col2)
{
- return interp(col1, col2, t);
+ return interp(col1, col2, t);
}
ccl_device float3 svm_mix_add(float t, float3 col1, float3 col2)
{
- return interp(col1, col1 + col2, t);
+ return interp(col1, col1 + col2, t);
}
ccl_device float3 svm_mix_mul(float t, float3 col1, float3 col2)
{
- return interp(col1, col1 * col2, t);
+ return interp(col1, col1 * col2, t);
}
ccl_device float3 svm_mix_screen(float t, float3 col1, float3 col2)
{
- float tm = 1.0f - t;
- float3 one = make_float3(1.0f, 1.0f, 1.0f);
- float3 tm3 = make_float3(tm, tm, tm);
+ float tm = 1.0f - t;
+ float3 one = make_float3(1.0f, 1.0f, 1.0f);
+ float3 tm3 = make_float3(tm, tm, tm);
- return one - (tm3 + t*(one - col2))*(one - col1);
+ return one - (tm3 + t * (one - col2)) * (one - col1);
}
ccl_device float3 svm_mix_overlay(float t, float3 col1, float3 col2)
{
- float tm = 1.0f - t;
+ float tm = 1.0f - t;
- float3 outcol = col1;
+ float3 outcol = col1;
- if(outcol.x < 0.5f)
- outcol.x *= tm + 2.0f*t*col2.x;
- else
- outcol.x = 1.0f - (tm + 2.0f*t*(1.0f - col2.x))*(1.0f - outcol.x);
+ if (outcol.x < 0.5f)
+ outcol.x *= tm + 2.0f * t * col2.x;
+ else
+ outcol.x = 1.0f - (tm + 2.0f * t * (1.0f - col2.x)) * (1.0f - outcol.x);
- if(outcol.y < 0.5f)
- outcol.y *= tm + 2.0f*t*col2.y;
- else
- outcol.y = 1.0f - (tm + 2.0f*t*(1.0f - col2.y))*(1.0f - outcol.y);
+ if (outcol.y < 0.5f)
+ outcol.y *= tm + 2.0f * t * col2.y;
+ else
+ outcol.y = 1.0f - (tm + 2.0f * t * (1.0f - col2.y)) * (1.0f - outcol.y);
- if(outcol.z < 0.5f)
- outcol.z *= tm + 2.0f*t*col2.z;
- else
- outcol.z = 1.0f - (tm + 2.0f*t*(1.0f - col2.z))*(1.0f - outcol.z);
+ if (outcol.z < 0.5f)
+ outcol.z *= tm + 2.0f * t * col2.z;
+ else
+ outcol.z = 1.0f - (tm + 2.0f * t * (1.0f - col2.z)) * (1.0f - outcol.z);
- return outcol;
+ return outcol;
}
ccl_device float3 svm_mix_sub(float t, float3 col1, float3 col2)
{
- return interp(col1, col1 - col2, t);
+ return interp(col1, col1 - col2, t);
}
ccl_device float3 svm_mix_div(float t, float3 col1, float3 col2)
{
- float tm = 1.0f - t;
+ float tm = 1.0f - t;
- float3 outcol = col1;
+ float3 outcol = col1;
- if(col2.x != 0.0f) outcol.x = tm*outcol.x + t*outcol.x/col2.x;
- if(col2.y != 0.0f) outcol.y = tm*outcol.y + t*outcol.y/col2.y;
- if(col2.z != 0.0f) outcol.z = tm*outcol.z + t*outcol.z/col2.z;
+ if (col2.x != 0.0f)
+ outcol.x = tm * outcol.x + t * outcol.x / col2.x;
+ if (col2.y != 0.0f)
+ outcol.y = tm * outcol.y + t * outcol.y / col2.y;
+ if (col2.z != 0.0f)
+ outcol.z = tm * outcol.z + t * outcol.z / col2.z;
- return outcol;
+ return outcol;
}
ccl_device float3 svm_mix_diff(float t, float3 col1, float3 col2)
{
- return interp(col1, fabs(col1 - col2), t);
+ return interp(col1, fabs(col1 - col2), t);
}
ccl_device float3 svm_mix_dark(float t, float3 col1, float3 col2)
{
- return min(col1, col2)*t + col1*(1.0f - t);
+ return min(col1, col2) * t + col1 * (1.0f - t);
}
ccl_device float3 svm_mix_light(float t, float3 col1, float3 col2)
{
- return max(col1, col2*t);
+ return max(col1, col2 * t);
}
ccl_device float3 svm_mix_dodge(float t, float3 col1, float3 col2)
{
- float3 outcol = col1;
-
- if(outcol.x != 0.0f) {
- float tmp = 1.0f - t*col2.x;
- if(tmp <= 0.0f)
- outcol.x = 1.0f;
- else if((tmp = outcol.x/tmp) > 1.0f)
- outcol.x = 1.0f;
- else
- outcol.x = tmp;
- }
- if(outcol.y != 0.0f) {
- float tmp = 1.0f - t*col2.y;
- if(tmp <= 0.0f)
- outcol.y = 1.0f;
- else if((tmp = outcol.y/tmp) > 1.0f)
- outcol.y = 1.0f;
- else
- outcol.y = tmp;
- }
- if(outcol.z != 0.0f) {
- float tmp = 1.0f - t*col2.z;
- if(tmp <= 0.0f)
- outcol.z = 1.0f;
- else if((tmp = outcol.z/tmp) > 1.0f)
- outcol.z = 1.0f;
- else
- outcol.z = tmp;
- }
-
- return outcol;
+ float3 outcol = col1;
+
+ if (outcol.x != 0.0f) {
+ float tmp = 1.0f - t * col2.x;
+ if (tmp <= 0.0f)
+ outcol.x = 1.0f;
+ else if ((tmp = outcol.x / tmp) > 1.0f)
+ outcol.x = 1.0f;
+ else
+ outcol.x = tmp;
+ }
+ if (outcol.y != 0.0f) {
+ float tmp = 1.0f - t * col2.y;
+ if (tmp <= 0.0f)
+ outcol.y = 1.0f;
+ else if ((tmp = outcol.y / tmp) > 1.0f)
+ outcol.y = 1.0f;
+ else
+ outcol.y = tmp;
+ }
+ if (outcol.z != 0.0f) {
+ float tmp = 1.0f - t * col2.z;
+ if (tmp <= 0.0f)
+ outcol.z = 1.0f;
+ else if ((tmp = outcol.z / tmp) > 1.0f)
+ outcol.z = 1.0f;
+ else
+ outcol.z = tmp;
+ }
+
+ return outcol;
}
ccl_device float3 svm_mix_burn(float t, float3 col1, float3 col2)
{
- float tmp, tm = 1.0f - t;
-
- float3 outcol = col1;
-
- tmp = tm + t*col2.x;
- if(tmp <= 0.0f)
- outcol.x = 0.0f;
- else if((tmp = (1.0f - (1.0f - outcol.x)/tmp)) < 0.0f)
- outcol.x = 0.0f;
- else if(tmp > 1.0f)
- outcol.x = 1.0f;
- else
- outcol.x = tmp;
-
- tmp = tm + t*col2.y;
- if(tmp <= 0.0f)
- outcol.y = 0.0f;
- else if((tmp = (1.0f - (1.0f - outcol.y)/tmp)) < 0.0f)
- outcol.y = 0.0f;
- else if(tmp > 1.0f)
- outcol.y = 1.0f;
- else
- outcol.y = tmp;
-
- tmp = tm + t*col2.z;
- if(tmp <= 0.0f)
- outcol.z = 0.0f;
- else if((tmp = (1.0f - (1.0f - outcol.z)/tmp)) < 0.0f)
- outcol.z = 0.0f;
- else if(tmp > 1.0f)
- outcol.z = 1.0f;
- else
- outcol.z = tmp;
-
- return outcol;
+ float tmp, tm = 1.0f - t;
+
+ float3 outcol = col1;
+
+ tmp = tm + t * col2.x;
+ if (tmp <= 0.0f)
+ outcol.x = 0.0f;
+ else if ((tmp = (1.0f - (1.0f - outcol.x) / tmp)) < 0.0f)
+ outcol.x = 0.0f;
+ else if (tmp > 1.0f)
+ outcol.x = 1.0f;
+ else
+ outcol.x = tmp;
+
+ tmp = tm + t * col2.y;
+ if (tmp <= 0.0f)
+ outcol.y = 0.0f;
+ else if ((tmp = (1.0f - (1.0f - outcol.y) / tmp)) < 0.0f)
+ outcol.y = 0.0f;
+ else if (tmp > 1.0f)
+ outcol.y = 1.0f;
+ else
+ outcol.y = tmp;
+
+ tmp = tm + t * col2.z;
+ if (tmp <= 0.0f)
+ outcol.z = 0.0f;
+ else if ((tmp = (1.0f - (1.0f - outcol.z) / tmp)) < 0.0f)
+ outcol.z = 0.0f;
+ else if (tmp > 1.0f)
+ outcol.z = 1.0f;
+ else
+ outcol.z = tmp;
+
+ return outcol;
}
ccl_device float3 svm_mix_hue(float t, float3 col1, float3 col2)
{
- float3 outcol = col1;
+ float3 outcol = col1;
- float3 hsv2 = rgb_to_hsv(col2);
+ float3 hsv2 = rgb_to_hsv(col2);
- if(hsv2.y != 0.0f) {
- float3 hsv = rgb_to_hsv(outcol);
- hsv.x = hsv2.x;
- float3 tmp = hsv_to_rgb(hsv);
+ if (hsv2.y != 0.0f) {
+ float3 hsv = rgb_to_hsv(outcol);
+ hsv.x = hsv2.x;
+ float3 tmp = hsv_to_rgb(hsv);
- outcol = interp(outcol, tmp, t);
- }
+ outcol = interp(outcol, tmp, t);
+ }
- return outcol;
+ return outcol;
}
ccl_device float3 svm_mix_sat(float t, float3 col1, float3 col2)
{
- float tm = 1.0f - t;
+ float tm = 1.0f - t;
- float3 outcol = col1;
+ float3 outcol = col1;
- float3 hsv = rgb_to_hsv(outcol);
+ float3 hsv = rgb_to_hsv(outcol);
- if(hsv.y != 0.0f) {
- float3 hsv2 = rgb_to_hsv(col2);
+ if (hsv.y != 0.0f) {
+ float3 hsv2 = rgb_to_hsv(col2);
- hsv.y = tm*hsv.y + t*hsv2.y;
- outcol = hsv_to_rgb(hsv);
- }
+ hsv.y = tm * hsv.y + t * hsv2.y;
+ outcol = hsv_to_rgb(hsv);
+ }
- return outcol;
+ return outcol;
}
ccl_device float3 svm_mix_val(float t, float3 col1, float3 col2)
{
- float tm = 1.0f - t;
+ float tm = 1.0f - t;
- float3 hsv = rgb_to_hsv(col1);
- float3 hsv2 = rgb_to_hsv(col2);
+ float3 hsv = rgb_to_hsv(col1);
+ float3 hsv2 = rgb_to_hsv(col2);
- hsv.z = tm*hsv.z + t*hsv2.z;
+ hsv.z = tm * hsv.z + t * hsv2.z;
- return hsv_to_rgb(hsv);
+ return hsv_to_rgb(hsv);
}
ccl_device float3 svm_mix_color(float t, float3 col1, float3 col2)
{
- float3 outcol = col1;
- float3 hsv2 = rgb_to_hsv(col2);
+ float3 outcol = col1;
+ float3 hsv2 = rgb_to_hsv(col2);
- if(hsv2.y != 0.0f) {
- float3 hsv = rgb_to_hsv(outcol);
- hsv.x = hsv2.x;
- hsv.y = hsv2.y;
- float3 tmp = hsv_to_rgb(hsv);
+ if (hsv2.y != 0.0f) {
+ float3 hsv = rgb_to_hsv(outcol);
+ hsv.x = hsv2.x;
+ hsv.y = hsv2.y;
+ float3 tmp = hsv_to_rgb(hsv);
- outcol = interp(outcol, tmp, t);
- }
+ outcol = interp(outcol, tmp, t);
+ }
- return outcol;
+ return outcol;
}
ccl_device float3 svm_mix_soft(float t, float3 col1, float3 col2)
{
- float tm = 1.0f - t;
+ float tm = 1.0f - t;
- float3 one = make_float3(1.0f, 1.0f, 1.0f);
- float3 scr = one - (one - col2)*(one - col1);
+ float3 one = make_float3(1.0f, 1.0f, 1.0f);
+ float3 scr = one - (one - col2) * (one - col1);
- return tm*col1 + t*((one - col1)*col2*col1 + col1*scr);
+ return tm * col1 + t * ((one - col1) * col2 * col1 + col1 * scr);
}
ccl_device float3 svm_mix_linear(float t, float3 col1, float3 col2)
{
- return col1 + t*(2.0f*col2 + make_float3(-1.0f, -1.0f, -1.0f));
+ return col1 + t * (2.0f * col2 + make_float3(-1.0f, -1.0f, -1.0f));
}
ccl_device float3 svm_mix_clamp(float3 col)
{
- float3 outcol = col;
+ float3 outcol = col;
- outcol.x = saturate(col.x);
- outcol.y = saturate(col.y);
- outcol.z = saturate(col.z);
+ outcol.x = saturate(col.x);
+ outcol.y = saturate(col.y);
+ outcol.z = saturate(col.z);
- return outcol;
+ return outcol;
}
ccl_device_noinline float3 svm_mix(NodeMix type, float fac, float3 c1, float3 c2)
{
- float t = saturate(fac);
-
- switch(type) {
- case NODE_MIX_BLEND: return svm_mix_blend(t, c1, c2);
- case NODE_MIX_ADD: return svm_mix_add(t, c1, c2);
- case NODE_MIX_MUL: return svm_mix_mul(t, c1, c2);
- case NODE_MIX_SCREEN: return svm_mix_screen(t, c1, c2);
- case NODE_MIX_OVERLAY: return svm_mix_overlay(t, c1, c2);
- case NODE_MIX_SUB: return svm_mix_sub(t, c1, c2);
- case NODE_MIX_DIV: return svm_mix_div(t, c1, c2);
- case NODE_MIX_DIFF: return svm_mix_diff(t, c1, c2);
- case NODE_MIX_DARK: return svm_mix_dark(t, c1, c2);
- case NODE_MIX_LIGHT: return svm_mix_light(t, c1, c2);
- case NODE_MIX_DODGE: return svm_mix_dodge(t, c1, c2);
- case NODE_MIX_BURN: return svm_mix_burn(t, c1, c2);
- case NODE_MIX_HUE: return svm_mix_hue(t, c1, c2);
- case NODE_MIX_SAT: return svm_mix_sat(t, c1, c2);
- case NODE_MIX_VAL: return svm_mix_val (t, c1, c2);
- case NODE_MIX_COLOR: return svm_mix_color(t, c1, c2);
- case NODE_MIX_SOFT: return svm_mix_soft(t, c1, c2);
- case NODE_MIX_LINEAR: return svm_mix_linear(t, c1, c2);
- case NODE_MIX_CLAMP: return svm_mix_clamp(c1);
- }
-
- return make_float3(0.0f, 0.0f, 0.0f);
+ float t = saturate(fac);
+
+ switch (type) {
+ case NODE_MIX_BLEND:
+ return svm_mix_blend(t, c1, c2);
+ case NODE_MIX_ADD:
+ return svm_mix_add(t, c1, c2);
+ case NODE_MIX_MUL:
+ return svm_mix_mul(t, c1, c2);
+ case NODE_MIX_SCREEN:
+ return svm_mix_screen(t, c1, c2);
+ case NODE_MIX_OVERLAY:
+ return svm_mix_overlay(t, c1, c2);
+ case NODE_MIX_SUB:
+ return svm_mix_sub(t, c1, c2);
+ case NODE_MIX_DIV:
+ return svm_mix_div(t, c1, c2);
+ case NODE_MIX_DIFF:
+ return svm_mix_diff(t, c1, c2);
+ case NODE_MIX_DARK:
+ return svm_mix_dark(t, c1, c2);
+ case NODE_MIX_LIGHT:
+ return svm_mix_light(t, c1, c2);
+ case NODE_MIX_DODGE:
+ return svm_mix_dodge(t, c1, c2);
+ case NODE_MIX_BURN:
+ return svm_mix_burn(t, c1, c2);
+ case NODE_MIX_HUE:
+ return svm_mix_hue(t, c1, c2);
+ case NODE_MIX_SAT:
+ return svm_mix_sat(t, c1, c2);
+ case NODE_MIX_VAL:
+ return svm_mix_val(t, c1, c2);
+ case NODE_MIX_COLOR:
+ return svm_mix_color(t, c1, c2);
+ case NODE_MIX_SOFT:
+ return svm_mix_soft(t, c1, c2);
+ case NODE_MIX_LINEAR:
+ return svm_mix_linear(t, c1, c2);
+ case NODE_MIX_CLAMP:
+ return svm_mix_clamp(c1);
+ }
+
+ return make_float3(0.0f, 0.0f, 0.0f);
}
ccl_device_inline float3 svm_brightness_contrast(float3 color, float brightness, float contrast)
{
- float a = 1.0f + contrast;
- float b = brightness - contrast*0.5f;
+ float a = 1.0f + contrast;
+ float b = brightness - contrast * 0.5f;
- color.x = max(a*color.x + b, 0.0f);
- color.y = max(a*color.y + b, 0.0f);
- color.z = max(a*color.z + b, 0.0f);
+ color.x = max(a * color.x + b, 0.0f);
+ color.y = max(a * color.y + b, 0.0f);
+ color.z = max(a * color.z + b, 0.0f);
- return color;
+ return color;
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/svm/svm_convert.h b/intern/cycles/kernel/svm/svm_convert.h
index 63b1dc6865e..5df6c9fb755 100644
--- a/intern/cycles/kernel/svm/svm_convert.h
+++ b/intern/cycles/kernel/svm/svm_convert.h
@@ -18,54 +18,55 @@ CCL_NAMESPACE_BEGIN
/* Conversion Nodes */
-ccl_device void svm_node_convert(KernelGlobals *kg, ShaderData *sd, float *stack, uint type, uint from, uint to)
+ccl_device void svm_node_convert(
+ KernelGlobals *kg, ShaderData *sd, float *stack, uint type, uint from, uint to)
{
- switch(type) {
- case NODE_CONVERT_FI: {
- float f = stack_load_float(stack, from);
- stack_store_int(stack, to, float_to_int(f));
- break;
- }
- case NODE_CONVERT_FV: {
- float f = stack_load_float(stack, from);
- stack_store_float3(stack, to, make_float3(f, f, f));
- break;
- }
- case NODE_CONVERT_CF: {
- float3 f = stack_load_float3(stack, from);
- float g = linear_rgb_to_gray(kg, f);
- stack_store_float(stack, to, g);
- break;
- }
- case NODE_CONVERT_CI: {
- float3 f = stack_load_float3(stack, from);
- int i = (int)linear_rgb_to_gray(kg, f);
- stack_store_int(stack, to, i);
- break;
- }
- case NODE_CONVERT_VF: {
- float3 f = stack_load_float3(stack, from);
- float g = average(f);
- stack_store_float(stack, to, g);
- break;
- }
- case NODE_CONVERT_VI: {
- float3 f = stack_load_float3(stack, from);
- int i = (int)average(f);
- stack_store_int(stack, to, i);
- break;
- }
- case NODE_CONVERT_IF: {
- float f = (float)stack_load_int(stack, from);
- stack_store_float(stack, to, f);
- break;
- }
- case NODE_CONVERT_IV: {
- float f = (float)stack_load_int(stack, from);
- stack_store_float3(stack, to, make_float3(f, f, f));
- break;
- }
- }
+ switch (type) {
+ case NODE_CONVERT_FI: {
+ float f = stack_load_float(stack, from);
+ stack_store_int(stack, to, float_to_int(f));
+ break;
+ }
+ case NODE_CONVERT_FV: {
+ float f = stack_load_float(stack, from);
+ stack_store_float3(stack, to, make_float3(f, f, f));
+ break;
+ }
+ case NODE_CONVERT_CF: {
+ float3 f = stack_load_float3(stack, from);
+ float g = linear_rgb_to_gray(kg, f);
+ stack_store_float(stack, to, g);
+ break;
+ }
+ case NODE_CONVERT_CI: {
+ float3 f = stack_load_float3(stack, from);
+ int i = (int)linear_rgb_to_gray(kg, f);
+ stack_store_int(stack, to, i);
+ break;
+ }
+ case NODE_CONVERT_VF: {
+ float3 f = stack_load_float3(stack, from);
+ float g = average(f);
+ stack_store_float(stack, to, g);
+ break;
+ }
+ case NODE_CONVERT_VI: {
+ float3 f = stack_load_float3(stack, from);
+ int i = (int)average(f);
+ stack_store_int(stack, to, i);
+ break;
+ }
+ case NODE_CONVERT_IF: {
+ float f = (float)stack_load_int(stack, from);
+ stack_store_float(stack, to, f);
+ break;
+ }
+ case NODE_CONVERT_IV: {
+ float f = (float)stack_load_int(stack, from);
+ stack_store_float3(stack, to, make_float3(f, f, f));
+ break;
+ }
+ }
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/svm/svm_displace.h b/intern/cycles/kernel/svm/svm_displace.h
index a69c9fe81f9..f16664a684c 100644
--- a/intern/cycles/kernel/svm/svm_displace.h
+++ b/intern/cycles/kernel/svm/svm_displace.h
@@ -21,144 +21,149 @@ CCL_NAMESPACE_BEGIN
ccl_device void svm_node_set_bump(KernelGlobals *kg, ShaderData *sd, float *stack, uint4 node)
{
#ifdef __RAY_DIFFERENTIALS__
- /* get normal input */
- uint normal_offset, scale_offset, invert, use_object_space;
- decode_node_uchar4(node.y, &normal_offset, &scale_offset, &invert, &use_object_space);
+ /* get normal input */
+ uint normal_offset, scale_offset, invert, use_object_space;
+ decode_node_uchar4(node.y, &normal_offset, &scale_offset, &invert, &use_object_space);
- float3 normal_in = stack_valid(normal_offset)? stack_load_float3(stack, normal_offset): sd->N;
+ float3 normal_in = stack_valid(normal_offset) ? stack_load_float3(stack, normal_offset) : sd->N;
- float3 dPdx = sd->dP.dx;
- float3 dPdy = sd->dP.dy;
+ float3 dPdx = sd->dP.dx;
+ float3 dPdy = sd->dP.dy;
- if(use_object_space) {
- object_inverse_normal_transform(kg, sd, &normal_in);
- object_inverse_dir_transform(kg, sd, &dPdx);
- object_inverse_dir_transform(kg, sd, &dPdy);
- }
+ if (use_object_space) {
+ object_inverse_normal_transform(kg, sd, &normal_in);
+ object_inverse_dir_transform(kg, sd, &dPdx);
+ object_inverse_dir_transform(kg, sd, &dPdy);
+ }
- /* get surface tangents from normal */
- float3 Rx = cross(dPdy, normal_in);
- float3 Ry = cross(normal_in, dPdx);
+ /* get surface tangents from normal */
+ float3 Rx = cross(dPdy, normal_in);
+ float3 Ry = cross(normal_in, dPdx);
- /* get bump values */
- uint c_offset, x_offset, y_offset, strength_offset;
- decode_node_uchar4(node.z, &c_offset, &x_offset, &y_offset, &strength_offset);
+ /* get bump values */
+ uint c_offset, x_offset, y_offset, strength_offset;
+ decode_node_uchar4(node.z, &c_offset, &x_offset, &y_offset, &strength_offset);
- float h_c = stack_load_float(stack, c_offset);
- float h_x = stack_load_float(stack, x_offset);
- float h_y = stack_load_float(stack, y_offset);
+ float h_c = stack_load_float(stack, c_offset);
+ float h_x = stack_load_float(stack, x_offset);
+ float h_y = stack_load_float(stack, y_offset);
- /* compute surface gradient and determinant */
- float det = dot(dPdx, Rx);
- float3 surfgrad = (h_x - h_c)*Rx + (h_y - h_c)*Ry;
+ /* compute surface gradient and determinant */
+ float det = dot(dPdx, Rx);
+ float3 surfgrad = (h_x - h_c) * Rx + (h_y - h_c) * Ry;
- float absdet = fabsf(det);
+ float absdet = fabsf(det);
- float strength = stack_load_float(stack, strength_offset);
- float scale = stack_load_float(stack, scale_offset);
+ float strength = stack_load_float(stack, strength_offset);
+ float scale = stack_load_float(stack, scale_offset);
- if(invert)
- scale *= -1.0f;
+ if (invert)
+ scale *= -1.0f;
- strength = max(strength, 0.0f);
+ strength = max(strength, 0.0f);
- /* compute and output perturbed normal */
- float3 normal_out = safe_normalize(absdet*normal_in - scale*signf(det)*surfgrad);
- if(is_zero(normal_out)) {
- normal_out = normal_in;
- }
- else {
- normal_out = normalize(strength*normal_out + (1.0f - strength)*normal_in);
- }
+ /* compute and output perturbed normal */
+ float3 normal_out = safe_normalize(absdet * normal_in - scale * signf(det) * surfgrad);
+ if (is_zero(normal_out)) {
+ normal_out = normal_in;
+ }
+ else {
+ normal_out = normalize(strength * normal_out + (1.0f - strength) * normal_in);
+ }
- if(use_object_space) {
- object_normal_transform(kg, sd, &normal_out);
- }
+ if (use_object_space) {
+ object_normal_transform(kg, sd, &normal_out);
+ }
- normal_out = ensure_valid_reflection(sd->Ng, sd->I, normal_out);
+ normal_out = ensure_valid_reflection(sd->Ng, sd->I, normal_out);
- stack_store_float3(stack, node.w, normal_out);
+ stack_store_float3(stack, node.w, normal_out);
#endif
}
/* Displacement Node */
-ccl_device void svm_node_set_displacement(KernelGlobals *kg, ShaderData *sd, float *stack, uint fac_offset)
+ccl_device void svm_node_set_displacement(KernelGlobals *kg,
+ ShaderData *sd,
+ float *stack,
+ uint fac_offset)
{
- float3 dP = stack_load_float3(stack, fac_offset);
- sd->P += dP;
+ float3 dP = stack_load_float3(stack, fac_offset);
+ sd->P += dP;
}
ccl_device void svm_node_displacement(KernelGlobals *kg, ShaderData *sd, float *stack, uint4 node)
{
- uint height_offset, midlevel_offset, scale_offset, normal_offset;
- decode_node_uchar4(node.y, &height_offset, &midlevel_offset, &scale_offset, &normal_offset);
-
- float height = stack_load_float(stack, height_offset);
- float midlevel = stack_load_float(stack, midlevel_offset);
- float scale = stack_load_float(stack, scale_offset);
- float3 normal = stack_valid(normal_offset)? stack_load_float3(stack, normal_offset): sd->N;
- uint space = node.w;
-
- float3 dP = normal;
-
- if(space == NODE_NORMAL_MAP_OBJECT) {
- /* Object space. */
- object_inverse_normal_transform(kg, sd, &dP);
- dP *= (height - midlevel) * scale;
- object_dir_transform(kg, sd, &dP);
- }
- else {
- /* World space. */
- dP *= (height - midlevel) * scale;
- }
-
- stack_store_float3(stack, node.z, dP);
+ uint height_offset, midlevel_offset, scale_offset, normal_offset;
+ decode_node_uchar4(node.y, &height_offset, &midlevel_offset, &scale_offset, &normal_offset);
+
+ float height = stack_load_float(stack, height_offset);
+ float midlevel = stack_load_float(stack, midlevel_offset);
+ float scale = stack_load_float(stack, scale_offset);
+ float3 normal = stack_valid(normal_offset) ? stack_load_float3(stack, normal_offset) : sd->N;
+ uint space = node.w;
+
+ float3 dP = normal;
+
+ if (space == NODE_NORMAL_MAP_OBJECT) {
+ /* Object space. */
+ object_inverse_normal_transform(kg, sd, &dP);
+ dP *= (height - midlevel) * scale;
+ object_dir_transform(kg, sd, &dP);
+ }
+ else {
+ /* World space. */
+ dP *= (height - midlevel) * scale;
+ }
+
+ stack_store_float3(stack, node.z, dP);
}
-ccl_device void svm_node_vector_displacement(KernelGlobals *kg, ShaderData *sd, float *stack, uint4 node, int *offset)
+ccl_device void svm_node_vector_displacement(
+ KernelGlobals *kg, ShaderData *sd, float *stack, uint4 node, int *offset)
{
- uint4 data_node = read_node(kg, offset);
- uint space = data_node.x;
-
- uint vector_offset, midlevel_offset,scale_offset, displacement_offset;
- decode_node_uchar4(node.y, &vector_offset, &midlevel_offset, &scale_offset, &displacement_offset);
-
- float3 vector = stack_load_float3(stack, vector_offset);
- float midlevel = stack_load_float(stack, midlevel_offset);
- float scale = stack_load_float(stack, scale_offset);
- float3 dP = (vector - make_float3(midlevel, midlevel, midlevel)) * scale;
-
- if(space == NODE_NORMAL_MAP_TANGENT) {
- /* Tangent space. */
- float3 normal = sd->N;
- object_inverse_normal_transform(kg, sd, &normal);
-
- const AttributeDescriptor attr = find_attribute(kg, sd, node.z);
- float3 tangent;
- if(attr.offset != ATTR_STD_NOT_FOUND) {
- tangent = primitive_surface_attribute_float3(kg, sd, attr, NULL, NULL);
- }
- else {
- tangent = normalize(sd->dPdu);
- }
-
- float3 bitangent = normalize(cross(normal, tangent));
- const AttributeDescriptor attr_sign = find_attribute(kg, sd, node.w);
- if(attr_sign.offset != ATTR_STD_NOT_FOUND) {
- float sign = primitive_surface_attribute_float(kg, sd, attr_sign, NULL, NULL);
- bitangent *= sign;
- }
-
- dP = tangent*dP.x + normal*dP.y + bitangent*dP.z;
- }
-
- if(space != NODE_NORMAL_MAP_WORLD) {
- /* Tangent or object space. */
- object_dir_transform(kg, sd, &dP);
- }
-
- stack_store_float3(stack, displacement_offset, dP);
+ uint4 data_node = read_node(kg, offset);
+ uint space = data_node.x;
+
+ uint vector_offset, midlevel_offset, scale_offset, displacement_offset;
+ decode_node_uchar4(
+ node.y, &vector_offset, &midlevel_offset, &scale_offset, &displacement_offset);
+
+ float3 vector = stack_load_float3(stack, vector_offset);
+ float midlevel = stack_load_float(stack, midlevel_offset);
+ float scale = stack_load_float(stack, scale_offset);
+ float3 dP = (vector - make_float3(midlevel, midlevel, midlevel)) * scale;
+
+ if (space == NODE_NORMAL_MAP_TANGENT) {
+ /* Tangent space. */
+ float3 normal = sd->N;
+ object_inverse_normal_transform(kg, sd, &normal);
+
+ const AttributeDescriptor attr = find_attribute(kg, sd, node.z);
+ float3 tangent;
+ if (attr.offset != ATTR_STD_NOT_FOUND) {
+ tangent = primitive_surface_attribute_float3(kg, sd, attr, NULL, NULL);
+ }
+ else {
+ tangent = normalize(sd->dPdu);
+ }
+
+ float3 bitangent = normalize(cross(normal, tangent));
+ const AttributeDescriptor attr_sign = find_attribute(kg, sd, node.w);
+ if (attr_sign.offset != ATTR_STD_NOT_FOUND) {
+ float sign = primitive_surface_attribute_float(kg, sd, attr_sign, NULL, NULL);
+ bitangent *= sign;
+ }
+
+ dP = tangent * dP.x + normal * dP.y + bitangent * dP.z;
+ }
+
+ if (space != NODE_NORMAL_MAP_WORLD) {
+ /* Tangent or object space. */
+ object_dir_transform(kg, sd, &dP);
+ }
+
+ stack_store_float3(stack, displacement_offset, dP);
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/svm/svm_fresnel.h b/intern/cycles/kernel/svm/svm_fresnel.h
index 99dda5fb170..03119991597 100644
--- a/intern/cycles/kernel/svm/svm_fresnel.h
+++ b/intern/cycles/kernel/svm/svm_fresnel.h
@@ -18,56 +18,60 @@ CCL_NAMESPACE_BEGIN
/* Fresnel Node */
-ccl_device void svm_node_fresnel(ShaderData *sd, float *stack, uint ior_offset, uint ior_value, uint node)
+ccl_device void svm_node_fresnel(
+ ShaderData *sd, float *stack, uint ior_offset, uint ior_value, uint node)
{
- uint normal_offset, out_offset;
- decode_node_uchar4(node, &normal_offset, &out_offset, NULL, NULL);
- float eta = (stack_valid(ior_offset))? stack_load_float(stack, ior_offset): __uint_as_float(ior_value);
- float3 normal_in = stack_valid(normal_offset)? stack_load_float3(stack, normal_offset): sd->N;
+ uint normal_offset, out_offset;
+ decode_node_uchar4(node, &normal_offset, &out_offset, NULL, NULL);
+ float eta = (stack_valid(ior_offset)) ? stack_load_float(stack, ior_offset) :
+ __uint_as_float(ior_value);
+ float3 normal_in = stack_valid(normal_offset) ? stack_load_float3(stack, normal_offset) : sd->N;
- eta = fmaxf(eta, 1e-5f);
- eta = (sd->flag & SD_BACKFACING)? 1.0f/eta: eta;
+ eta = fmaxf(eta, 1e-5f);
+ eta = (sd->flag & SD_BACKFACING) ? 1.0f / eta : eta;
- float f = fresnel_dielectric_cos(dot(sd->I, normal_in), eta);
+ float f = fresnel_dielectric_cos(dot(sd->I, normal_in), eta);
- stack_store_float(stack, out_offset, f);
+ stack_store_float(stack, out_offset, f);
}
/* Layer Weight Node */
ccl_device void svm_node_layer_weight(ShaderData *sd, float *stack, uint4 node)
{
- uint blend_offset = node.y;
- uint blend_value = node.z;
+ uint blend_offset = node.y;
+ uint blend_value = node.z;
- uint type, normal_offset, out_offset;
- decode_node_uchar4(node.w, &type, &normal_offset, &out_offset, NULL);
+ uint type, normal_offset, out_offset;
+ decode_node_uchar4(node.w, &type, &normal_offset, &out_offset, NULL);
- float blend = (stack_valid(blend_offset))? stack_load_float(stack, blend_offset): __uint_as_float(blend_value);
- float3 normal_in = (stack_valid(normal_offset))? stack_load_float3(stack, normal_offset): sd->N;
+ float blend = (stack_valid(blend_offset)) ? stack_load_float(stack, blend_offset) :
+ __uint_as_float(blend_value);
+ float3 normal_in = (stack_valid(normal_offset)) ? stack_load_float3(stack, normal_offset) :
+ sd->N;
- float f;
+ float f;
- if(type == NODE_LAYER_WEIGHT_FRESNEL) {
- float eta = fmaxf(1.0f - blend, 1e-5f);
- eta = (sd->flag & SD_BACKFACING)? eta: 1.0f/eta;
+ if (type == NODE_LAYER_WEIGHT_FRESNEL) {
+ float eta = fmaxf(1.0f - blend, 1e-5f);
+ eta = (sd->flag & SD_BACKFACING) ? eta : 1.0f / eta;
- f = fresnel_dielectric_cos(dot(sd->I, normal_in), eta);
- }
- else {
- f = fabsf(dot(sd->I, normal_in));
+ f = fresnel_dielectric_cos(dot(sd->I, normal_in), eta);
+ }
+ else {
+ f = fabsf(dot(sd->I, normal_in));
- if(blend != 0.5f) {
- blend = clamp(blend, 0.0f, 1.0f-1e-5f);
- blend = (blend < 0.5f)? 2.0f*blend: 0.5f/(1.0f - blend);
+ if (blend != 0.5f) {
+ blend = clamp(blend, 0.0f, 1.0f - 1e-5f);
+ blend = (blend < 0.5f) ? 2.0f * blend : 0.5f / (1.0f - blend);
- f = powf(f, blend);
- }
+ f = powf(f, blend);
+ }
- f = 1.0f - f;
- }
+ f = 1.0f - f;
+ }
- stack_store_float(stack, out_offset, f);
+ stack_store_float(stack, out_offset, f);
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/svm/svm_gamma.h b/intern/cycles/kernel/svm/svm_gamma.h
index 171945a60bc..65eb08eb0eb 100644
--- a/intern/cycles/kernel/svm/svm_gamma.h
+++ b/intern/cycles/kernel/svm/svm_gamma.h
@@ -16,15 +16,16 @@
CCL_NAMESPACE_BEGIN
-ccl_device void svm_node_gamma(ShaderData *sd, float *stack, uint in_gamma, uint in_color, uint out_color)
+ccl_device void svm_node_gamma(
+ ShaderData *sd, float *stack, uint in_gamma, uint in_color, uint out_color)
{
- float3 color = stack_load_float3(stack, in_color);
- float gamma = stack_load_float(stack, in_gamma);
+ float3 color = stack_load_float3(stack, in_color);
+ float gamma = stack_load_float(stack, in_gamma);
- color = svm_math_gamma_color(color, gamma);
+ color = svm_math_gamma_color(color, gamma);
- if(stack_valid(out_color))
- stack_store_float3(stack, out_color, color);
+ if (stack_valid(out_color))
+ stack_store_float3(stack, out_color, color);
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/svm/svm_geometry.h b/intern/cycles/kernel/svm/svm_geometry.h
index 05443772505..a9104643299 100644
--- a/intern/cycles/kernel/svm/svm_geometry.h
+++ b/intern/cycles/kernel/svm/svm_geometry.h
@@ -18,192 +18,217 @@ CCL_NAMESPACE_BEGIN
/* Geometry Node */
-ccl_device_inline void svm_node_geometry(KernelGlobals *kg,
- ShaderData *sd,
- float *stack,
- uint type,
- uint out_offset)
+ccl_device_inline void svm_node_geometry(
+ KernelGlobals *kg, ShaderData *sd, float *stack, uint type, uint out_offset)
{
- float3 data;
-
- switch(type) {
- case NODE_GEOM_P: data = sd->P; break;
- case NODE_GEOM_N: data = sd->N; break;
+ float3 data;
+
+ switch (type) {
+ case NODE_GEOM_P:
+ data = sd->P;
+ break;
+ case NODE_GEOM_N:
+ data = sd->N;
+ break;
#ifdef __DPDU__
- case NODE_GEOM_T: data = primitive_tangent(kg, sd); break;
+ case NODE_GEOM_T:
+ data = primitive_tangent(kg, sd);
+ break;
#endif
- case NODE_GEOM_I: data = sd->I; break;
- case NODE_GEOM_Ng: data = sd->Ng; break;
+ case NODE_GEOM_I:
+ data = sd->I;
+ break;
+ case NODE_GEOM_Ng:
+ data = sd->Ng;
+ break;
#ifdef __UV__
- case NODE_GEOM_uv: data = make_float3(sd->u, sd->v, 0.0f); break;
+ case NODE_GEOM_uv:
+ data = make_float3(sd->u, sd->v, 0.0f);
+ break;
#endif
- default: data = make_float3(0.0f, 0.0f, 0.0f);
- }
+ default:
+ data = make_float3(0.0f, 0.0f, 0.0f);
+ }
- stack_store_float3(stack, out_offset, data);
+ stack_store_float3(stack, out_offset, data);
}
-ccl_device void svm_node_geometry_bump_dx(KernelGlobals *kg, ShaderData *sd, float *stack, uint type, uint out_offset)
+ccl_device void svm_node_geometry_bump_dx(
+ KernelGlobals *kg, ShaderData *sd, float *stack, uint type, uint out_offset)
{
#ifdef __RAY_DIFFERENTIALS__
- float3 data;
-
- switch(type) {
- case NODE_GEOM_P: data = sd->P + sd->dP.dx; break;
- case NODE_GEOM_uv: data = make_float3(sd->u + sd->du.dx, sd->v + sd->dv.dx, 0.0f); break;
- default: svm_node_geometry(kg, sd, stack, type, out_offset); return;
- }
-
- stack_store_float3(stack, out_offset, data);
+ float3 data;
+
+ switch (type) {
+ case NODE_GEOM_P:
+ data = sd->P + sd->dP.dx;
+ break;
+ case NODE_GEOM_uv:
+ data = make_float3(sd->u + sd->du.dx, sd->v + sd->dv.dx, 0.0f);
+ break;
+ default:
+ svm_node_geometry(kg, sd, stack, type, out_offset);
+ return;
+ }
+
+ stack_store_float3(stack, out_offset, data);
#else
- svm_node_geometry(kg, sd, stack, type, out_offset);
+ svm_node_geometry(kg, sd, stack, type, out_offset);
#endif
}
-ccl_device void svm_node_geometry_bump_dy(KernelGlobals *kg, ShaderData *sd, float *stack, uint type, uint out_offset)
+ccl_device void svm_node_geometry_bump_dy(
+ KernelGlobals *kg, ShaderData *sd, float *stack, uint type, uint out_offset)
{
#ifdef __RAY_DIFFERENTIALS__
- float3 data;
-
- switch(type) {
- case NODE_GEOM_P: data = sd->P + sd->dP.dy; break;
- case NODE_GEOM_uv: data = make_float3(sd->u + sd->du.dy, sd->v + sd->dv.dy, 0.0f); break;
- default: svm_node_geometry(kg, sd, stack, type, out_offset); return;
- }
-
- stack_store_float3(stack, out_offset, data);
+ float3 data;
+
+ switch (type) {
+ case NODE_GEOM_P:
+ data = sd->P + sd->dP.dy;
+ break;
+ case NODE_GEOM_uv:
+ data = make_float3(sd->u + sd->du.dy, sd->v + sd->dv.dy, 0.0f);
+ break;
+ default:
+ svm_node_geometry(kg, sd, stack, type, out_offset);
+ return;
+ }
+
+ stack_store_float3(stack, out_offset, data);
#else
- svm_node_geometry(kg, sd, stack, type, out_offset);
+ svm_node_geometry(kg, sd, stack, type, out_offset);
#endif
}
/* Object Info */
-ccl_device void svm_node_object_info(KernelGlobals *kg, ShaderData *sd, float *stack, uint type, uint out_offset)
+ccl_device void svm_node_object_info(
+ KernelGlobals *kg, ShaderData *sd, float *stack, uint type, uint out_offset)
{
- float data;
-
- switch(type) {
- case NODE_INFO_OB_LOCATION: {
- stack_store_float3(stack, out_offset, object_location(kg, sd));
- return;
- }
- case NODE_INFO_OB_INDEX: data = object_pass_id(kg, sd->object); break;
- case NODE_INFO_MAT_INDEX: data = shader_pass_id(kg, sd); break;
- case NODE_INFO_OB_RANDOM: {
- if(sd->lamp != LAMP_NONE) {
- data = lamp_random_number(kg, sd->lamp);
- }
- else {
- data = object_random_number(kg, sd->object);
- }
- break;
- }
- default: data = 0.0f; break;
- }
-
- stack_store_float(stack, out_offset, data);
+ float data;
+
+ switch (type) {
+ case NODE_INFO_OB_LOCATION: {
+ stack_store_float3(stack, out_offset, object_location(kg, sd));
+ return;
+ }
+ case NODE_INFO_OB_INDEX:
+ data = object_pass_id(kg, sd->object);
+ break;
+ case NODE_INFO_MAT_INDEX:
+ data = shader_pass_id(kg, sd);
+ break;
+ case NODE_INFO_OB_RANDOM: {
+ if (sd->lamp != LAMP_NONE) {
+ data = lamp_random_number(kg, sd->lamp);
+ }
+ else {
+ data = object_random_number(kg, sd->object);
+ }
+ break;
+ }
+ default:
+ data = 0.0f;
+ break;
+ }
+
+ stack_store_float(stack, out_offset, data);
}
/* Particle Info */
-ccl_device void svm_node_particle_info(KernelGlobals *kg,
- ShaderData *sd,
- float *stack,
- uint type,
- uint out_offset)
+ccl_device void svm_node_particle_info(
+ KernelGlobals *kg, ShaderData *sd, float *stack, uint type, uint out_offset)
{
- switch(type) {
- case NODE_INFO_PAR_INDEX: {
- int particle_id = object_particle_id(kg, sd->object);
- stack_store_float(stack, out_offset, particle_index(kg, particle_id));
- break;
- }
- case NODE_INFO_PAR_RANDOM: {
- int particle_id = object_particle_id(kg, sd->object);
- float random = hash_int_01(particle_index(kg, particle_id));
- stack_store_float(stack, out_offset, random);
- break;
- }
- case NODE_INFO_PAR_AGE: {
- int particle_id = object_particle_id(kg, sd->object);
- stack_store_float(stack, out_offset, particle_age(kg, particle_id));
- break;
- }
- case NODE_INFO_PAR_LIFETIME: {
- int particle_id = object_particle_id(kg, sd->object);
- stack_store_float(stack, out_offset, particle_lifetime(kg, particle_id));
- break;
- }
- case NODE_INFO_PAR_LOCATION: {
- int particle_id = object_particle_id(kg, sd->object);
- stack_store_float3(stack, out_offset, particle_location(kg, particle_id));
- break;
- }
-#if 0 /* XXX float4 currently not supported in SVM stack */
- case NODE_INFO_PAR_ROTATION: {
- int particle_id = object_particle_id(kg, sd->object);
- stack_store_float4(stack, out_offset, particle_rotation(kg, particle_id));
- break;
- }
+ switch (type) {
+ case NODE_INFO_PAR_INDEX: {
+ int particle_id = object_particle_id(kg, sd->object);
+ stack_store_float(stack, out_offset, particle_index(kg, particle_id));
+ break;
+ }
+ case NODE_INFO_PAR_RANDOM: {
+ int particle_id = object_particle_id(kg, sd->object);
+ float random = hash_int_01(particle_index(kg, particle_id));
+ stack_store_float(stack, out_offset, random);
+ break;
+ }
+ case NODE_INFO_PAR_AGE: {
+ int particle_id = object_particle_id(kg, sd->object);
+ stack_store_float(stack, out_offset, particle_age(kg, particle_id));
+ break;
+ }
+ case NODE_INFO_PAR_LIFETIME: {
+ int particle_id = object_particle_id(kg, sd->object);
+ stack_store_float(stack, out_offset, particle_lifetime(kg, particle_id));
+ break;
+ }
+ case NODE_INFO_PAR_LOCATION: {
+ int particle_id = object_particle_id(kg, sd->object);
+ stack_store_float3(stack, out_offset, particle_location(kg, particle_id));
+ break;
+ }
+#if 0 /* XXX float4 currently not supported in SVM stack */
+ case NODE_INFO_PAR_ROTATION: {
+ int particle_id = object_particle_id(kg, sd->object);
+ stack_store_float4(stack, out_offset, particle_rotation(kg, particle_id));
+ break;
+ }
#endif
- case NODE_INFO_PAR_SIZE: {
- int particle_id = object_particle_id(kg, sd->object);
- stack_store_float(stack, out_offset, particle_size(kg, particle_id));
- break;
- }
- case NODE_INFO_PAR_VELOCITY: {
- int particle_id = object_particle_id(kg, sd->object);
- stack_store_float3(stack, out_offset, particle_velocity(kg, particle_id));
- break;
- }
- case NODE_INFO_PAR_ANGULAR_VELOCITY: {
- int particle_id = object_particle_id(kg, sd->object);
- stack_store_float3(stack, out_offset, particle_angular_velocity(kg, particle_id));
- break;
- }
- }
+ case NODE_INFO_PAR_SIZE: {
+ int particle_id = object_particle_id(kg, sd->object);
+ stack_store_float(stack, out_offset, particle_size(kg, particle_id));
+ break;
+ }
+ case NODE_INFO_PAR_VELOCITY: {
+ int particle_id = object_particle_id(kg, sd->object);
+ stack_store_float3(stack, out_offset, particle_velocity(kg, particle_id));
+ break;
+ }
+ case NODE_INFO_PAR_ANGULAR_VELOCITY: {
+ int particle_id = object_particle_id(kg, sd->object);
+ stack_store_float3(stack, out_offset, particle_angular_velocity(kg, particle_id));
+ break;
+ }
+ }
}
#ifdef __HAIR__
/* Hair Info */
-ccl_device void svm_node_hair_info(KernelGlobals *kg,
- ShaderData *sd,
- float *stack,
- uint type,
- uint out_offset)
+ccl_device void svm_node_hair_info(
+ KernelGlobals *kg, ShaderData *sd, float *stack, uint type, uint out_offset)
{
- float data;
- float3 data3;
-
- switch(type) {
- case NODE_INFO_CURVE_IS_STRAND: {
- data = (sd->type & PRIMITIVE_ALL_CURVE) != 0;
- stack_store_float(stack, out_offset, data);
- break;
- }
- case NODE_INFO_CURVE_INTERCEPT:
- break; /* handled as attribute */
- case NODE_INFO_CURVE_RANDOM:
- break; /* handled as attribute */
- case NODE_INFO_CURVE_THICKNESS: {
- data = curve_thickness(kg, sd);
- stack_store_float(stack, out_offset, data);
- break;
- }
- /*case NODE_INFO_CURVE_FADE: {
- data = sd->curve_transparency;
- stack_store_float(stack, out_offset, data);
- break;
- }*/
- case NODE_INFO_CURVE_TANGENT_NORMAL: {
- data3 = curve_tangent_normal(kg, sd);
- stack_store_float3(stack, out_offset, data3);
- break;
- }
- }
+ float data;
+ float3 data3;
+
+ switch (type) {
+ case NODE_INFO_CURVE_IS_STRAND: {
+ data = (sd->type & PRIMITIVE_ALL_CURVE) != 0;
+ stack_store_float(stack, out_offset, data);
+ break;
+ }
+ case NODE_INFO_CURVE_INTERCEPT:
+ break; /* handled as attribute */
+ case NODE_INFO_CURVE_RANDOM:
+ break; /* handled as attribute */
+ case NODE_INFO_CURVE_THICKNESS: {
+ data = curve_thickness(kg, sd);
+ stack_store_float(stack, out_offset, data);
+ break;
+ }
+ /*case NODE_INFO_CURVE_FADE: {
+ data = sd->curve_transparency;
+ stack_store_float(stack, out_offset, data);
+ break;
+ }*/
+ case NODE_INFO_CURVE_TANGENT_NORMAL: {
+ data3 = curve_tangent_normal(kg, sd);
+ stack_store_float3(stack, out_offset, data3);
+ break;
+ }
+ }
}
#endif
diff --git a/intern/cycles/kernel/svm/svm_gradient.h b/intern/cycles/kernel/svm/svm_gradient.h
index 177e0506dee..c315564fbc2 100644
--- a/intern/cycles/kernel/svm/svm_gradient.h
+++ b/intern/cycles/kernel/svm/svm_gradient.h
@@ -20,61 +20,61 @@ CCL_NAMESPACE_BEGIN
ccl_device float svm_gradient(float3 p, NodeGradientType type)
{
- float x, y, z;
+ float x, y, z;
- x = p.x;
- y = p.y;
- z = p.z;
+ x = p.x;
+ y = p.y;
+ z = p.z;
- if(type == NODE_BLEND_LINEAR) {
- return x;
- }
- else if(type == NODE_BLEND_QUADRATIC) {
- float r = fmaxf(x, 0.0f);
- return r*r;
- }
- else if(type == NODE_BLEND_EASING) {
- float r = fminf(fmaxf(x, 0.0f), 1.0f);
- float t = r*r;
+ if (type == NODE_BLEND_LINEAR) {
+ return x;
+ }
+ else if (type == NODE_BLEND_QUADRATIC) {
+ float r = fmaxf(x, 0.0f);
+ return r * r;
+ }
+ else if (type == NODE_BLEND_EASING) {
+ float r = fminf(fmaxf(x, 0.0f), 1.0f);
+ float t = r * r;
- return (3.0f*t - 2.0f*t*r);
- }
- else if(type == NODE_BLEND_DIAGONAL) {
- return (x + y) * 0.5f;
- }
- else if(type == NODE_BLEND_RADIAL) {
- return atan2f(y, x) / M_2PI_F + 0.5f;
- }
- else {
- /* Bias a little bit for the case where p is a unit length vector,
- * to get exactly zero instead of a small random value depending
- * on float precision. */
- float r = fmaxf(0.999999f - sqrtf(x*x + y*y + z*z), 0.0f);
+ return (3.0f * t - 2.0f * t * r);
+ }
+ else if (type == NODE_BLEND_DIAGONAL) {
+ return (x + y) * 0.5f;
+ }
+ else if (type == NODE_BLEND_RADIAL) {
+ return atan2f(y, x) / M_2PI_F + 0.5f;
+ }
+ else {
+ /* Bias a little bit for the case where p is a unit length vector,
+ * to get exactly zero instead of a small random value depending
+ * on float precision. */
+ float r = fmaxf(0.999999f - sqrtf(x * x + y * y + z * z), 0.0f);
- if(type == NODE_BLEND_QUADRATIC_SPHERE)
- return r*r;
- else if(type == NODE_BLEND_SPHERICAL)
- return r;
- }
+ if (type == NODE_BLEND_QUADRATIC_SPHERE)
+ return r * r;
+ else if (type == NODE_BLEND_SPHERICAL)
+ return r;
+ }
- return 0.0f;
+ return 0.0f;
}
ccl_device void svm_node_tex_gradient(ShaderData *sd, float *stack, uint4 node)
{
- uint type, co_offset, color_offset, fac_offset;
+ uint type, co_offset, color_offset, fac_offset;
- decode_node_uchar4(node.y, &type, &co_offset, &fac_offset, &color_offset);
+ decode_node_uchar4(node.y, &type, &co_offset, &fac_offset, &color_offset);
- float3 co = stack_load_float3(stack, co_offset);
+ float3 co = stack_load_float3(stack, co_offset);
- float f = svm_gradient(co, (NodeGradientType)type);
- f = saturate(f);
+ float f = svm_gradient(co, (NodeGradientType)type);
+ f = saturate(f);
- if(stack_valid(fac_offset))
- stack_store_float(stack, fac_offset, f);
- if(stack_valid(color_offset))
- stack_store_float3(stack, color_offset, make_float3(f, f, f));
+ if (stack_valid(fac_offset))
+ stack_store_float(stack, fac_offset, f);
+ if (stack_valid(color_offset))
+ stack_store_float3(stack, color_offset, make_float3(f, f, f));
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/svm/svm_hsv.h b/intern/cycles/kernel/svm/svm_hsv.h
index 6f3efa639e2..72379fba870 100644
--- a/intern/cycles/kernel/svm/svm_hsv.h
+++ b/intern/cycles/kernel/svm/svm_hsv.h
@@ -19,43 +19,44 @@
CCL_NAMESPACE_BEGIN
-ccl_device void svm_node_hsv(KernelGlobals *kg, ShaderData *sd, float *stack, uint4 node, int *offset)
+ccl_device void svm_node_hsv(
+ KernelGlobals *kg, ShaderData *sd, float *stack, uint4 node, int *offset)
{
- uint in_color_offset, fac_offset, out_color_offset;
- uint hue_offset, sat_offset, val_offset;
- decode_node_uchar4(node.y, &in_color_offset, &fac_offset, &out_color_offset, NULL);
- decode_node_uchar4(node.z, &hue_offset, &sat_offset, &val_offset, NULL);
+ uint in_color_offset, fac_offset, out_color_offset;
+ uint hue_offset, sat_offset, val_offset;
+ decode_node_uchar4(node.y, &in_color_offset, &fac_offset, &out_color_offset, NULL);
+ decode_node_uchar4(node.z, &hue_offset, &sat_offset, &val_offset, NULL);
- float fac = stack_load_float(stack, fac_offset);
- float3 in_color = stack_load_float3(stack, in_color_offset);
- float3 color = in_color;
+ float fac = stack_load_float(stack, fac_offset);
+ float3 in_color = stack_load_float3(stack, in_color_offset);
+ float3 color = in_color;
- float hue = stack_load_float(stack, hue_offset);
- float sat = stack_load_float(stack, sat_offset);
- float val = stack_load_float(stack, val_offset);
+ float hue = stack_load_float(stack, hue_offset);
+ float sat = stack_load_float(stack, sat_offset);
+ float val = stack_load_float(stack, val_offset);
- color = rgb_to_hsv(color);
+ color = rgb_to_hsv(color);
- /* remember: fmod doesn't work for negative numbers here */
- color.x = fmodf(color.x + hue + 0.5f, 1.0f);
- color.y = saturate(color.y * sat);
- color.z *= val;
+ /* remember: fmod doesn't work for negative numbers here */
+ color.x = fmodf(color.x + hue + 0.5f, 1.0f);
+ color.y = saturate(color.y * sat);
+ color.z *= val;
- color = hsv_to_rgb(color);
+ color = hsv_to_rgb(color);
- color.x = fac*color.x + (1.0f - fac)*in_color.x;
- color.y = fac*color.y + (1.0f - fac)*in_color.y;
- color.z = fac*color.z + (1.0f - fac)*in_color.z;
+ color.x = fac * color.x + (1.0f - fac) * in_color.x;
+ color.y = fac * color.y + (1.0f - fac) * in_color.y;
+ color.z = fac * color.z + (1.0f - fac) * in_color.z;
- /* Clamp color to prevent negative values caused by oversaturation. */
- color.x = max(color.x, 0.0f);
- color.y = max(color.y, 0.0f);
- color.z = max(color.z, 0.0f);
+ /* Clamp color to prevent negative values caused by oversaturation. */
+ color.x = max(color.x, 0.0f);
+ color.y = max(color.y, 0.0f);
+ color.z = max(color.z, 0.0f);
- if(stack_valid(out_color_offset))
- stack_store_float3(stack, out_color_offset, color);
+ if (stack_valid(out_color_offset))
+ stack_store_float3(stack, out_color_offset, color);
}
CCL_NAMESPACE_END
-#endif /* __SVM_HSV_H__ */
+#endif /* __SVM_HSV_H__ */
diff --git a/intern/cycles/kernel/svm/svm_ies.h b/intern/cycles/kernel/svm/svm_ies.h
index 6130c3348b0..9434c0c5505 100644
--- a/intern/cycles/kernel/svm/svm_ies.h
+++ b/intern/cycles/kernel/svm/svm_ies.h
@@ -18,93 +18,102 @@ CCL_NAMESPACE_BEGIN
/* IES Light */
-ccl_device_inline float interpolate_ies_vertical(KernelGlobals *kg, int ofs, int v, int v_num, float v_frac, int h)
+ccl_device_inline float interpolate_ies_vertical(
+ KernelGlobals *kg, int ofs, int v, int v_num, float v_frac, int h)
{
- /* Since lookups are performed in spherical coordinates, clamping the coordinates at the low end of v
- * (corresponding to the north pole) would result in artifacts.
- * The proper way of dealing with this would be to lookup the corresponding value on the other side of the pole,
- * but since the horizontal coordinates might be nonuniform, this would require yet another interpolation.
- * Therefore, the assumtion is made that the light is going to be symmetrical, which means that we can just take
- * the corresponding value at the current horizontal coordinate. */
-
-#define IES_LOOKUP(v) kernel_tex_fetch(__ies, ofs+h*v_num+(v))
- /* If v is zero, assume symmetry and read at v=1 instead of v=-1. */
- float a = IES_LOOKUP((v == 0)? 1 : v-1);
- float b = IES_LOOKUP(v);
- float c = IES_LOOKUP(v+1);
- float d = IES_LOOKUP(min(v+2, v_num-1));
+ /* Since lookups are performed in spherical coordinates, clamping the coordinates at the low end of v
+ * (corresponding to the north pole) would result in artifacts.
+ * The proper way of dealing with this would be to lookup the corresponding value on the other side of the pole,
+ * but since the horizontal coordinates might be nonuniform, this would require yet another interpolation.
+ * Therefore, the assumtion is made that the light is going to be symmetrical, which means that we can just take
+ * the corresponding value at the current horizontal coordinate. */
+
+#define IES_LOOKUP(v) kernel_tex_fetch(__ies, ofs + h * v_num + (v))
+ /* If v is zero, assume symmetry and read at v=1 instead of v=-1. */
+ float a = IES_LOOKUP((v == 0) ? 1 : v - 1);
+ float b = IES_LOOKUP(v);
+ float c = IES_LOOKUP(v + 1);
+ float d = IES_LOOKUP(min(v + 2, v_num - 1));
#undef IES_LOOKUP
- return cubic_interp(a, b, c, d, v_frac);
+ return cubic_interp(a, b, c, d, v_frac);
}
-ccl_device_inline float kernel_ies_interp(KernelGlobals *kg, int slot, float h_angle, float v_angle)
+ccl_device_inline float kernel_ies_interp(KernelGlobals *kg,
+ int slot,
+ float h_angle,
+ float v_angle)
{
- /* Find offset of the IES data in the table. */
- int ofs = __float_as_int(kernel_tex_fetch(__ies, slot));
- if(ofs == -1) {
- return 100.0f;
- }
-
- int h_num = __float_as_int(kernel_tex_fetch(__ies, ofs++));
- int v_num = __float_as_int(kernel_tex_fetch(__ies, ofs++));
-
-#define IES_LOOKUP_ANGLE_H(h) kernel_tex_fetch(__ies, ofs+(h))
-#define IES_LOOKUP_ANGLE_V(v) kernel_tex_fetch(__ies, ofs+h_num+(v))
-
- /* Check whether the angle is within the bounds of the IES texture. */
- if(v_angle >= IES_LOOKUP_ANGLE_V(v_num-1)) {
- return 0.0f;
- }
- kernel_assert(v_angle >= IES_LOOKUP_ANGLE_V(0));
- kernel_assert(h_angle >= IES_LOOKUP_ANGLE_H(0));
- kernel_assert(h_angle <= IES_LOOKUP_ANGLE_H(h_num-1));
-
- /* Lookup the angles to find the table position. */
- int h_i, v_i;
- /* TODO(lukas): Consider using bisection. Probably not worth it for the vast majority of IES files. */
- for(h_i = 0; IES_LOOKUP_ANGLE_H(h_i+1) < h_angle; h_i++);
- for(v_i = 0; IES_LOOKUP_ANGLE_V(v_i+1) < v_angle; v_i++);
-
- float h_frac = inverse_lerp(IES_LOOKUP_ANGLE_H(h_i), IES_LOOKUP_ANGLE_H(h_i+1), h_angle);
- float v_frac = inverse_lerp(IES_LOOKUP_ANGLE_V(v_i), IES_LOOKUP_ANGLE_V(v_i+1), v_angle);
+ /* Find offset of the IES data in the table. */
+ int ofs = __float_as_int(kernel_tex_fetch(__ies, slot));
+ if (ofs == -1) {
+ return 100.0f;
+ }
+
+ int h_num = __float_as_int(kernel_tex_fetch(__ies, ofs++));
+ int v_num = __float_as_int(kernel_tex_fetch(__ies, ofs++));
+
+#define IES_LOOKUP_ANGLE_H(h) kernel_tex_fetch(__ies, ofs + (h))
+#define IES_LOOKUP_ANGLE_V(v) kernel_tex_fetch(__ies, ofs + h_num + (v))
+
+ /* Check whether the angle is within the bounds of the IES texture. */
+ if (v_angle >= IES_LOOKUP_ANGLE_V(v_num - 1)) {
+ return 0.0f;
+ }
+ kernel_assert(v_angle >= IES_LOOKUP_ANGLE_V(0));
+ kernel_assert(h_angle >= IES_LOOKUP_ANGLE_H(0));
+ kernel_assert(h_angle <= IES_LOOKUP_ANGLE_H(h_num - 1));
+
+ /* Lookup the angles to find the table position. */
+ int h_i, v_i;
+ /* TODO(lukas): Consider using bisection. Probably not worth it for the vast majority of IES files. */
+ for (h_i = 0; IES_LOOKUP_ANGLE_H(h_i + 1) < h_angle; h_i++)
+ ;
+ for (v_i = 0; IES_LOOKUP_ANGLE_V(v_i + 1) < v_angle; v_i++)
+ ;
+
+ float h_frac = inverse_lerp(IES_LOOKUP_ANGLE_H(h_i), IES_LOOKUP_ANGLE_H(h_i + 1), h_angle);
+ float v_frac = inverse_lerp(IES_LOOKUP_ANGLE_V(v_i), IES_LOOKUP_ANGLE_V(v_i + 1), v_angle);
#undef IES_LOOKUP_ANGLE_H
#undef IES_LOOKUP_ANGLE_V
- /* Skip forward to the actual intensity data. */
- ofs += h_num+v_num;
-
- /* Perform cubic interpolation along the horizontal coordinate to get the intensity value.
- * If h_i is zero, just wrap around since the horizontal angles always go over the full circle.
- * However, the last entry (360°) equals the first one, so we need to wrap around to the one before that. */
- float a = interpolate_ies_vertical(kg, ofs, v_i, v_num, v_frac, (h_i == 0)? h_num-2 : h_i-1);
- float b = interpolate_ies_vertical(kg, ofs, v_i, v_num, v_frac, h_i);
- float c = interpolate_ies_vertical(kg, ofs, v_i, v_num, v_frac, h_i+1);
- /* Same logic here, wrap around to the second element if necessary. */
- float d = interpolate_ies_vertical(kg, ofs, v_i, v_num, v_frac, (h_i+2 == h_num)? 1 : h_i+2);
-
- /* Cubic interpolation can result in negative values, so get rid of them. */
- return max(cubic_interp(a, b, c, d, h_frac), 0.0f);
+ /* Skip forward to the actual intensity data. */
+ ofs += h_num + v_num;
+
+ /* Perform cubic interpolation along the horizontal coordinate to get the intensity value.
+ * If h_i is zero, just wrap around since the horizontal angles always go over the full circle.
+ * However, the last entry (360°) equals the first one, so we need to wrap around to the one before that. */
+ float a = interpolate_ies_vertical(
+ kg, ofs, v_i, v_num, v_frac, (h_i == 0) ? h_num - 2 : h_i - 1);
+ float b = interpolate_ies_vertical(kg, ofs, v_i, v_num, v_frac, h_i);
+ float c = interpolate_ies_vertical(kg, ofs, v_i, v_num, v_frac, h_i + 1);
+ /* Same logic here, wrap around to the second element if necessary. */
+ float d = interpolate_ies_vertical(
+ kg, ofs, v_i, v_num, v_frac, (h_i + 2 == h_num) ? 1 : h_i + 2);
+
+ /* Cubic interpolation can result in negative values, so get rid of them. */
+ return max(cubic_interp(a, b, c, d, h_frac), 0.0f);
}
-ccl_device void svm_node_ies(KernelGlobals *kg, ShaderData *sd, float *stack, uint4 node, int *offset)
+ccl_device void svm_node_ies(
+ KernelGlobals *kg, ShaderData *sd, float *stack, uint4 node, int *offset)
{
- uint vector_offset, strength_offset, fac_offset, dummy, slot = node.z;
- decode_node_uchar4(node.y, &strength_offset, &vector_offset, &fac_offset, &dummy);
+ uint vector_offset, strength_offset, fac_offset, dummy, slot = node.z;
+ decode_node_uchar4(node.y, &strength_offset, &vector_offset, &fac_offset, &dummy);
- float3 vector = stack_load_float3(stack, vector_offset);
- float strength = stack_load_float_default(stack, strength_offset, node.w);
+ float3 vector = stack_load_float3(stack, vector_offset);
+ float strength = stack_load_float_default(stack, strength_offset, node.w);
- vector = normalize(vector);
- float v_angle = safe_acosf(-vector.z);
- float h_angle = atan2f(vector.x, vector.y) + M_PI_F;
+ vector = normalize(vector);
+ float v_angle = safe_acosf(-vector.z);
+ float h_angle = atan2f(vector.x, vector.y) + M_PI_F;
- float fac = strength * kernel_ies_interp(kg, slot, h_angle, v_angle);
+ float fac = strength * kernel_ies_interp(kg, slot, h_angle, v_angle);
- if(stack_valid(fac_offset)) {
- stack_store_float(stack, fac_offset, fac);
- }
+ if (stack_valid(fac_offset)) {
+ stack_store_float(stack, fac_offset, fac);
+ }
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/svm/svm_image.h b/intern/cycles/kernel/svm/svm_image.h
index 81ee79c984e..ee4b8b6e50c 100644
--- a/intern/cycles/kernel/svm/svm_image.h
+++ b/intern/cycles/kernel/svm/svm_image.h
@@ -16,190 +16,192 @@
CCL_NAMESPACE_BEGIN
-ccl_device float4 svm_image_texture(KernelGlobals *kg, int id, float x, float y, uint srgb, uint use_alpha)
+ccl_device float4
+svm_image_texture(KernelGlobals *kg, int id, float x, float y, uint srgb, uint use_alpha)
{
- float4 r = kernel_tex_image_interp(kg, id, x, y);
- const float alpha = r.w;
-
- if(use_alpha && alpha != 1.0f && alpha != 0.0f) {
- r /= alpha;
- const int texture_type = kernel_tex_type(id);
- 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) {
- /* TODO(lukas): Implement proper conversion for image textures. */
- r = color_srgb_to_linear_v4(r);
- }
-
- return r;
+ float4 r = kernel_tex_image_interp(kg, id, x, y);
+ const float alpha = r.w;
+
+ if (use_alpha && alpha != 1.0f && alpha != 0.0f) {
+ r /= alpha;
+ const int texture_type = kernel_tex_type(id);
+ 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) {
+ /* TODO(lukas): Implement proper conversion for image textures. */
+ r = color_srgb_to_linear_v4(r);
+ }
+
+ return r;
}
/* Remap coordnate from 0..1 box to -1..-1 */
ccl_device_inline float3 texco_remap_square(float3 co)
{
- return (co - make_float3(0.5f, 0.5f, 0.5f)) * 2.0f;
+ return (co - make_float3(0.5f, 0.5f, 0.5f)) * 2.0f;
}
ccl_device void svm_node_tex_image(KernelGlobals *kg, ShaderData *sd, float *stack, uint4 node)
{
- uint id = node.y;
- uint co_offset, out_offset, alpha_offset, srgb;
-
- decode_node_uchar4(node.z, &co_offset, &out_offset, &alpha_offset, &srgb);
-
- float3 co = stack_load_float3(stack, co_offset);
- float2 tex_co;
- uint use_alpha = stack_valid(alpha_offset);
- if(node.w == NODE_IMAGE_PROJ_SPHERE) {
- co = texco_remap_square(co);
- tex_co = map_to_sphere(co);
- }
- else if(node.w == NODE_IMAGE_PROJ_TUBE) {
- co = texco_remap_square(co);
- tex_co = map_to_tube(co);
- }
- else {
- tex_co = make_float2(co.x, co.y);
- }
- float4 f = svm_image_texture(kg, id, tex_co.x, tex_co.y, srgb, use_alpha);
-
- if(stack_valid(out_offset))
- stack_store_float3(stack, out_offset, make_float3(f.x, f.y, f.z));
- if(stack_valid(alpha_offset))
- stack_store_float(stack, alpha_offset, f.w);
+ uint id = node.y;
+ uint co_offset, out_offset, alpha_offset, srgb;
+
+ decode_node_uchar4(node.z, &co_offset, &out_offset, &alpha_offset, &srgb);
+
+ float3 co = stack_load_float3(stack, co_offset);
+ float2 tex_co;
+ uint use_alpha = stack_valid(alpha_offset);
+ if (node.w == NODE_IMAGE_PROJ_SPHERE) {
+ co = texco_remap_square(co);
+ tex_co = map_to_sphere(co);
+ }
+ else if (node.w == NODE_IMAGE_PROJ_TUBE) {
+ co = texco_remap_square(co);
+ tex_co = map_to_tube(co);
+ }
+ else {
+ tex_co = make_float2(co.x, co.y);
+ }
+ float4 f = svm_image_texture(kg, id, tex_co.x, tex_co.y, srgb, use_alpha);
+
+ if (stack_valid(out_offset))
+ stack_store_float3(stack, out_offset, make_float3(f.x, f.y, f.z));
+ if (stack_valid(alpha_offset))
+ stack_store_float(stack, alpha_offset, f.w);
}
ccl_device void svm_node_tex_image_box(KernelGlobals *kg, ShaderData *sd, float *stack, uint4 node)
{
- /* get object space normal */
- float3 N = sd->N;
-
- N = sd->N;
- object_inverse_normal_transform(kg, sd, &N);
-
- /* project from direction vector to barycentric coordinates in triangles */
- float3 signed_N = N;
-
- N.x = fabsf(N.x);
- N.y = fabsf(N.y);
- N.z = fabsf(N.z);
-
- N /= (N.x + N.y + N.z);
-
- /* basic idea is to think of this as a triangle, each corner representing
- * one of the 3 faces of the cube. in the corners we have single textures,
- * in between we blend between two textures, and in the middle we a blend
- * between three textures.
- *
- * the Nxyz values are the barycentric coordinates in an equilateral
- * triangle, which in case of blending, in the middle has a smaller
- * equilateral triangle where 3 textures blend. this divides things into
- * 7 zones, with an if() test for each zone */
-
- float3 weight = make_float3(0.0f, 0.0f, 0.0f);
- float blend = __int_as_float(node.w);
- float limit = 0.5f*(1.0f + blend);
-
- /* first test for corners with single texture */
- if(N.x > limit*(N.x + N.y) && N.x > limit*(N.x + N.z)) {
- weight.x = 1.0f;
- }
- else if(N.y > limit*(N.x + N.y) && N.y > limit*(N.y + N.z)) {
- weight.y = 1.0f;
- }
- else if(N.z > limit*(N.x + N.z) && N.z > limit*(N.y + N.z)) {
- weight.z = 1.0f;
- }
- else if(blend > 0.0f) {
- /* in case of blending, test for mixes between two textures */
- if(N.z < (1.0f - limit)*(N.y + N.x)) {
- weight.x = N.x/(N.x + N.y);
- weight.x = saturate((weight.x - 0.5f*(1.0f - blend))/blend);
- weight.y = 1.0f - weight.x;
- }
- else if(N.x < (1.0f - limit)*(N.y + N.z)) {
- weight.y = N.y/(N.y + N.z);
- weight.y = saturate((weight.y - 0.5f*(1.0f - blend))/blend);
- weight.z = 1.0f - weight.y;
- }
- else if(N.y < (1.0f - limit)*(N.x + N.z)) {
- weight.x = N.x/(N.x + N.z);
- weight.x = saturate((weight.x - 0.5f*(1.0f - blend))/blend);
- weight.z = 1.0f - weight.x;
- }
- else {
- /* last case, we have a mix between three */
- weight.x = ((2.0f - limit)*N.x + (limit - 1.0f))/(2.0f*limit - 1.0f);
- weight.y = ((2.0f - limit)*N.y + (limit - 1.0f))/(2.0f*limit - 1.0f);
- weight.z = ((2.0f - limit)*N.z + (limit - 1.0f))/(2.0f*limit - 1.0f);
- }
- }
- else {
- /* Desperate mode, no valid choice anyway, fallback to one side.*/
- weight.x = 1.0f;
- }
-
- /* now fetch textures */
- uint co_offset, out_offset, alpha_offset, srgb;
- decode_node_uchar4(node.z, &co_offset, &out_offset, &alpha_offset, &srgb);
-
- float3 co = stack_load_float3(stack, co_offset);
- uint id = node.y;
-
- float4 f = make_float4(0.0f, 0.0f, 0.0f, 0.0f);
- uint use_alpha = stack_valid(alpha_offset);
-
- /* Map so that no textures are flipped, rotation is somewhat arbitrary. */
- if(weight.x > 0.0f) {
- float2 uv = make_float2((signed_N.x < 0.0f)? 1.0f - co.y: co.y, co.z);
- f += weight.x*svm_image_texture(kg, id, uv.x, uv.y, srgb, use_alpha);
- }
- if(weight.y > 0.0f) {
- float2 uv = make_float2((signed_N.y > 0.0f)? 1.0f - co.x: co.x, co.z);
- f += weight.y*svm_image_texture(kg, id, uv.x, uv.y, srgb, use_alpha);
- }
- if(weight.z > 0.0f) {
- float2 uv = make_float2((signed_N.z > 0.0f)? 1.0f - co.y: co.y, co.x);
- f += weight.z*svm_image_texture(kg, id, uv.x, uv.y, srgb, use_alpha);
- }
-
- if(stack_valid(out_offset))
- stack_store_float3(stack, out_offset, make_float3(f.x, f.y, f.z));
- if(stack_valid(alpha_offset))
- stack_store_float(stack, alpha_offset, f.w);
+ /* get object space normal */
+ float3 N = sd->N;
+
+ N = sd->N;
+ object_inverse_normal_transform(kg, sd, &N);
+
+ /* project from direction vector to barycentric coordinates in triangles */
+ float3 signed_N = N;
+
+ N.x = fabsf(N.x);
+ N.y = fabsf(N.y);
+ N.z = fabsf(N.z);
+
+ N /= (N.x + N.y + N.z);
+
+ /* basic idea is to think of this as a triangle, each corner representing
+ * one of the 3 faces of the cube. in the corners we have single textures,
+ * in between we blend between two textures, and in the middle we a blend
+ * between three textures.
+ *
+ * the Nxyz values are the barycentric coordinates in an equilateral
+ * triangle, which in case of blending, in the middle has a smaller
+ * equilateral triangle where 3 textures blend. this divides things into
+ * 7 zones, with an if() test for each zone */
+
+ float3 weight = make_float3(0.0f, 0.0f, 0.0f);
+ float blend = __int_as_float(node.w);
+ float limit = 0.5f * (1.0f + blend);
+
+ /* first test for corners with single texture */
+ if (N.x > limit * (N.x + N.y) && N.x > limit * (N.x + N.z)) {
+ weight.x = 1.0f;
+ }
+ else if (N.y > limit * (N.x + N.y) && N.y > limit * (N.y + N.z)) {
+ weight.y = 1.0f;
+ }
+ else if (N.z > limit * (N.x + N.z) && N.z > limit * (N.y + N.z)) {
+ weight.z = 1.0f;
+ }
+ else if (blend > 0.0f) {
+ /* in case of blending, test for mixes between two textures */
+ if (N.z < (1.0f - limit) * (N.y + N.x)) {
+ weight.x = N.x / (N.x + N.y);
+ weight.x = saturate((weight.x - 0.5f * (1.0f - blend)) / blend);
+ weight.y = 1.0f - weight.x;
+ }
+ else if (N.x < (1.0f - limit) * (N.y + N.z)) {
+ weight.y = N.y / (N.y + N.z);
+ weight.y = saturate((weight.y - 0.5f * (1.0f - blend)) / blend);
+ weight.z = 1.0f - weight.y;
+ }
+ else if (N.y < (1.0f - limit) * (N.x + N.z)) {
+ weight.x = N.x / (N.x + N.z);
+ weight.x = saturate((weight.x - 0.5f * (1.0f - blend)) / blend);
+ weight.z = 1.0f - weight.x;
+ }
+ else {
+ /* last case, we have a mix between three */
+ weight.x = ((2.0f - limit) * N.x + (limit - 1.0f)) / (2.0f * limit - 1.0f);
+ weight.y = ((2.0f - limit) * N.y + (limit - 1.0f)) / (2.0f * limit - 1.0f);
+ weight.z = ((2.0f - limit) * N.z + (limit - 1.0f)) / (2.0f * limit - 1.0f);
+ }
+ }
+ else {
+ /* Desperate mode, no valid choice anyway, fallback to one side.*/
+ weight.x = 1.0f;
+ }
+
+ /* now fetch textures */
+ uint co_offset, out_offset, alpha_offset, srgb;
+ decode_node_uchar4(node.z, &co_offset, &out_offset, &alpha_offset, &srgb);
+
+ float3 co = stack_load_float3(stack, co_offset);
+ uint id = node.y;
+
+ float4 f = make_float4(0.0f, 0.0f, 0.0f, 0.0f);
+ uint use_alpha = stack_valid(alpha_offset);
+
+ /* Map so that no textures are flipped, rotation is somewhat arbitrary. */
+ if (weight.x > 0.0f) {
+ float2 uv = make_float2((signed_N.x < 0.0f) ? 1.0f - co.y : co.y, co.z);
+ f += weight.x * svm_image_texture(kg, id, uv.x, uv.y, srgb, use_alpha);
+ }
+ if (weight.y > 0.0f) {
+ float2 uv = make_float2((signed_N.y > 0.0f) ? 1.0f - co.x : co.x, co.z);
+ f += weight.y * svm_image_texture(kg, id, uv.x, uv.y, srgb, use_alpha);
+ }
+ if (weight.z > 0.0f) {
+ float2 uv = make_float2((signed_N.z > 0.0f) ? 1.0f - co.y : co.y, co.x);
+ f += weight.z * svm_image_texture(kg, id, uv.x, uv.y, srgb, use_alpha);
+ }
+
+ if (stack_valid(out_offset))
+ stack_store_float3(stack, out_offset, make_float3(f.x, f.y, f.z));
+ if (stack_valid(alpha_offset))
+ stack_store_float(stack, alpha_offset, f.w);
}
-ccl_device void svm_node_tex_environment(KernelGlobals *kg, ShaderData *sd, float *stack, uint4 node)
+ccl_device void svm_node_tex_environment(KernelGlobals *kg,
+ ShaderData *sd,
+ float *stack,
+ uint4 node)
{
- uint id = node.y;
- uint co_offset, out_offset, alpha_offset, srgb;
- uint projection = node.w;
+ uint id = node.y;
+ uint co_offset, out_offset, alpha_offset, srgb;
+ uint projection = node.w;
- decode_node_uchar4(node.z, &co_offset, &out_offset, &alpha_offset, &srgb);
+ decode_node_uchar4(node.z, &co_offset, &out_offset, &alpha_offset, &srgb);
- float3 co = stack_load_float3(stack, co_offset);
- float2 uv;
+ float3 co = stack_load_float3(stack, co_offset);
+ float2 uv;
- co = safe_normalize(co);
+ co = safe_normalize(co);
- if(projection == 0)
- uv = direction_to_equirectangular(co);
- else
- uv = direction_to_mirrorball(co);
+ if (projection == 0)
+ uv = direction_to_equirectangular(co);
+ else
+ uv = direction_to_mirrorball(co);
- uint use_alpha = stack_valid(alpha_offset);
- float4 f = svm_image_texture(kg, id, uv.x, uv.y, srgb, use_alpha);
+ uint use_alpha = stack_valid(alpha_offset);
+ float4 f = svm_image_texture(kg, id, uv.x, uv.y, srgb, use_alpha);
- if(stack_valid(out_offset))
- stack_store_float3(stack, out_offset, make_float3(f.x, f.y, f.z));
- if(stack_valid(alpha_offset))
- stack_store_float(stack, alpha_offset, f.w);
+ if (stack_valid(out_offset))
+ stack_store_float3(stack, out_offset, make_float3(f.x, f.y, f.z));
+ if (stack_valid(alpha_offset))
+ stack_store_float(stack, alpha_offset, f.w);
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/svm/svm_invert.h b/intern/cycles/kernel/svm/svm_invert.h
index 57cc4281101..02024742b13 100644
--- a/intern/cycles/kernel/svm/svm_invert.h
+++ b/intern/cycles/kernel/svm/svm_invert.h
@@ -18,20 +18,21 @@ CCL_NAMESPACE_BEGIN
ccl_device float invert(float color, float factor)
{
- return factor*(1.0f - color) + (1.0f - factor) * color;
+ return factor * (1.0f - color) + (1.0f - factor) * color;
}
-ccl_device void svm_node_invert(ShaderData *sd, float *stack, uint in_fac, uint in_color, uint out_color)
+ccl_device void svm_node_invert(
+ ShaderData *sd, float *stack, uint in_fac, uint in_color, uint out_color)
{
- float factor = stack_load_float(stack, in_fac);
- float3 color = stack_load_float3(stack, in_color);
+ float factor = stack_load_float(stack, in_fac);
+ float3 color = stack_load_float3(stack, in_color);
- color.x = invert(color.x, factor);
- color.y = invert(color.y, factor);
- color.z = invert(color.z, factor);
+ color.x = invert(color.x, factor);
+ color.y = invert(color.y, factor);
+ color.z = invert(color.z, factor);
- if(stack_valid(out_color))
- stack_store_float3(stack, out_color, color);
+ if (stack_valid(out_color))
+ stack_store_float3(stack, out_color, color);
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/svm/svm_light_path.h b/intern/cycles/kernel/svm/svm_light_path.h
index dd4390057cf..65a9a284a17 100644
--- a/intern/cycles/kernel/svm/svm_light_path.h
+++ b/intern/cycles/kernel/svm/svm_light_path.h
@@ -18,59 +18,99 @@ CCL_NAMESPACE_BEGIN
/* Light Path Node */
-ccl_device void svm_node_light_path(ShaderData *sd, ccl_addr_space PathState *state, float *stack, uint type, uint out_offset, int path_flag)
+ccl_device void svm_node_light_path(ShaderData *sd,
+ ccl_addr_space PathState *state,
+ float *stack,
+ uint type,
+ uint out_offset,
+ int path_flag)
{
- float info = 0.0f;
+ float info = 0.0f;
- switch(type) {
- case NODE_LP_camera: info = (path_flag & PATH_RAY_CAMERA)? 1.0f: 0.0f; break;
- case NODE_LP_shadow: info = (path_flag & PATH_RAY_SHADOW)? 1.0f: 0.0f; break;
- case NODE_LP_diffuse: info = (path_flag & PATH_RAY_DIFFUSE)? 1.0f: 0.0f; break;
- case NODE_LP_glossy: info = (path_flag & PATH_RAY_GLOSSY)? 1.0f: 0.0f; break;
- case NODE_LP_singular: info = (path_flag & PATH_RAY_SINGULAR)? 1.0f: 0.0f; break;
- case NODE_LP_reflection: info = (path_flag & PATH_RAY_REFLECT)? 1.0f: 0.0f; break;
- case NODE_LP_transmission: info = (path_flag & PATH_RAY_TRANSMIT)? 1.0f: 0.0f; break;
- case NODE_LP_volume_scatter: info = (path_flag & PATH_RAY_VOLUME_SCATTER)? 1.0f: 0.0f; break;
- case NODE_LP_backfacing: info = (sd->flag & SD_BACKFACING)? 1.0f: 0.0f; break;
- case NODE_LP_ray_length: info = sd->ray_length; break;
- case NODE_LP_ray_depth: info = (float)state->bounce; break;
- case NODE_LP_ray_diffuse: info = (float)state->diffuse_bounce; break;
- case NODE_LP_ray_glossy: info = (float)state->glossy_bounce; break;
- case NODE_LP_ray_transparent: info = (float)state->transparent_bounce; break;
- case NODE_LP_ray_transmission: info = (float)state->transmission_bounce; break;
- }
+ switch (type) {
+ case NODE_LP_camera:
+ info = (path_flag & PATH_RAY_CAMERA) ? 1.0f : 0.0f;
+ break;
+ case NODE_LP_shadow:
+ info = (path_flag & PATH_RAY_SHADOW) ? 1.0f : 0.0f;
+ break;
+ case NODE_LP_diffuse:
+ info = (path_flag & PATH_RAY_DIFFUSE) ? 1.0f : 0.0f;
+ break;
+ case NODE_LP_glossy:
+ info = (path_flag & PATH_RAY_GLOSSY) ? 1.0f : 0.0f;
+ break;
+ case NODE_LP_singular:
+ info = (path_flag & PATH_RAY_SINGULAR) ? 1.0f : 0.0f;
+ break;
+ case NODE_LP_reflection:
+ info = (path_flag & PATH_RAY_REFLECT) ? 1.0f : 0.0f;
+ break;
+ case NODE_LP_transmission:
+ info = (path_flag & PATH_RAY_TRANSMIT) ? 1.0f : 0.0f;
+ break;
+ case NODE_LP_volume_scatter:
+ info = (path_flag & PATH_RAY_VOLUME_SCATTER) ? 1.0f : 0.0f;
+ break;
+ case NODE_LP_backfacing:
+ info = (sd->flag & SD_BACKFACING) ? 1.0f : 0.0f;
+ break;
+ case NODE_LP_ray_length:
+ info = sd->ray_length;
+ break;
+ case NODE_LP_ray_depth:
+ info = (float)state->bounce;
+ break;
+ case NODE_LP_ray_diffuse:
+ info = (float)state->diffuse_bounce;
+ break;
+ case NODE_LP_ray_glossy:
+ info = (float)state->glossy_bounce;
+ break;
+ case NODE_LP_ray_transparent:
+ info = (float)state->transparent_bounce;
+ break;
+ case NODE_LP_ray_transmission:
+ info = (float)state->transmission_bounce;
+ break;
+ }
- stack_store_float(stack, out_offset, info);
+ stack_store_float(stack, out_offset, info);
}
/* Light Falloff Node */
ccl_device void svm_node_light_falloff(ShaderData *sd, float *stack, uint4 node)
{
- uint strength_offset, out_offset, smooth_offset;
+ uint strength_offset, out_offset, smooth_offset;
- decode_node_uchar4(node.z, &strength_offset, &smooth_offset, &out_offset, NULL);
+ decode_node_uchar4(node.z, &strength_offset, &smooth_offset, &out_offset, NULL);
- float strength = stack_load_float(stack, strength_offset);
- uint type = node.y;
+ float strength = stack_load_float(stack, strength_offset);
+ uint type = node.y;
- switch(type) {
- case NODE_LIGHT_FALLOFF_QUADRATIC: break;
- case NODE_LIGHT_FALLOFF_LINEAR: strength *= sd->ray_length; break;
- case NODE_LIGHT_FALLOFF_CONSTANT: strength *= sd->ray_length*sd->ray_length; break;
- }
+ switch (type) {
+ case NODE_LIGHT_FALLOFF_QUADRATIC:
+ break;
+ case NODE_LIGHT_FALLOFF_LINEAR:
+ strength *= sd->ray_length;
+ break;
+ case NODE_LIGHT_FALLOFF_CONSTANT:
+ strength *= sd->ray_length * sd->ray_length;
+ break;
+ }
- float smooth = stack_load_float(stack, smooth_offset);
+ float smooth = stack_load_float(stack, smooth_offset);
- if(smooth > 0.0f) {
- float squared = sd->ray_length*sd->ray_length;
- /* Distant lamps set the ray length to FLT_MAX, which causes squared to overflow. */
- if(isfinite(squared)) {
- strength *= squared/(smooth + squared);
- }
- }
+ if (smooth > 0.0f) {
+ float squared = sd->ray_length * sd->ray_length;
+ /* Distant lamps set the ray length to FLT_MAX, which causes squared to overflow. */
+ if (isfinite(squared)) {
+ strength *= squared / (smooth + squared);
+ }
+ }
- stack_store_float(stack, out_offset, strength);
+ stack_store_float(stack, out_offset, strength);
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/svm/svm_magic.h b/intern/cycles/kernel/svm/svm_magic.h
index 6afaff37acd..115d2e2fe4b 100644
--- a/intern/cycles/kernel/svm/svm_magic.h
+++ b/intern/cycles/kernel/svm/svm_magic.h
@@ -20,92 +20,93 @@ CCL_NAMESPACE_BEGIN
ccl_device_noinline float3 svm_magic(float3 p, int n, float distortion)
{
- float x = sinf((p.x + p.y + p.z)*5.0f);
- float y = cosf((-p.x + p.y - p.z)*5.0f);
- float z = -cosf((-p.x - p.y + p.z)*5.0f);
-
- if(n > 0) {
- x *= distortion;
- y *= distortion;
- z *= distortion;
- y = -cosf(x-y+z);
- y *= distortion;
-
- if(n > 1) {
- x = cosf(x-y-z);
- x *= distortion;
-
- if(n > 2) {
- z = sinf(-x-y-z);
- z *= distortion;
-
- if(n > 3) {
- x = -cosf(-x+y-z);
- x *= distortion;
-
- if(n > 4) {
- y = -sinf(-x+y+z);
- y *= distortion;
-
- if(n > 5) {
- y = -cosf(-x+y+z);
- y *= distortion;
-
- if(n > 6) {
- x = cosf(x+y+z);
- x *= distortion;
-
- if(n > 7) {
- z = sinf(x+y-z);
- z *= distortion;
-
- if(n > 8) {
- x = -cosf(-x-y+z);
- x *= distortion;
-
- if(n > 9) {
- y = -sinf(x-y+z);
- y *= distortion;
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
-
- if(distortion != 0.0f) {
- distortion *= 2.0f;
- x /= distortion;
- y /= distortion;
- z /= distortion;
- }
-
- return make_float3(0.5f - x, 0.5f - y, 0.5f - z);
+ float x = sinf((p.x + p.y + p.z) * 5.0f);
+ float y = cosf((-p.x + p.y - p.z) * 5.0f);
+ float z = -cosf((-p.x - p.y + p.z) * 5.0f);
+
+ if (n > 0) {
+ x *= distortion;
+ y *= distortion;
+ z *= distortion;
+ y = -cosf(x - y + z);
+ y *= distortion;
+
+ if (n > 1) {
+ x = cosf(x - y - z);
+ x *= distortion;
+
+ if (n > 2) {
+ z = sinf(-x - y - z);
+ z *= distortion;
+
+ if (n > 3) {
+ x = -cosf(-x + y - z);
+ x *= distortion;
+
+ if (n > 4) {
+ y = -sinf(-x + y + z);
+ y *= distortion;
+
+ if (n > 5) {
+ y = -cosf(-x + y + z);
+ y *= distortion;
+
+ if (n > 6) {
+ x = cosf(x + y + z);
+ x *= distortion;
+
+ if (n > 7) {
+ z = sinf(x + y - z);
+ z *= distortion;
+
+ if (n > 8) {
+ x = -cosf(-x - y + z);
+ x *= distortion;
+
+ if (n > 9) {
+ y = -sinf(x - y + z);
+ y *= distortion;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if (distortion != 0.0f) {
+ distortion *= 2.0f;
+ x /= distortion;
+ y /= distortion;
+ z /= distortion;
+ }
+
+ return make_float3(0.5f - x, 0.5f - y, 0.5f - z);
}
-ccl_device void svm_node_tex_magic(KernelGlobals *kg, ShaderData *sd, float *stack, uint4 node, int *offset)
+ccl_device void svm_node_tex_magic(
+ KernelGlobals *kg, ShaderData *sd, float *stack, uint4 node, int *offset)
{
- uint depth;
- uint scale_offset, distortion_offset, co_offset, fac_offset, color_offset;
+ uint depth;
+ uint scale_offset, distortion_offset, co_offset, fac_offset, color_offset;
- decode_node_uchar4(node.y, &depth, &color_offset, &fac_offset, NULL);
- decode_node_uchar4(node.z, &co_offset, &scale_offset, &distortion_offset, NULL);
+ decode_node_uchar4(node.y, &depth, &color_offset, &fac_offset, NULL);
+ decode_node_uchar4(node.z, &co_offset, &scale_offset, &distortion_offset, NULL);
- uint4 node2 = read_node(kg, offset);
- float3 co = stack_load_float3(stack, co_offset);
- float scale = stack_load_float_default(stack, scale_offset, node2.x);
- float distortion = stack_load_float_default(stack, distortion_offset, node2.y);
+ uint4 node2 = read_node(kg, offset);
+ float3 co = stack_load_float3(stack, co_offset);
+ float scale = stack_load_float_default(stack, scale_offset, node2.x);
+ float distortion = stack_load_float_default(stack, distortion_offset, node2.y);
- float3 color = svm_magic(co*scale, depth, distortion);
+ float3 color = svm_magic(co * scale, depth, distortion);
- if(stack_valid(fac_offset))
- stack_store_float(stack, fac_offset, average(color));
- if(stack_valid(color_offset))
- stack_store_float3(stack, color_offset, color);
+ if (stack_valid(fac_offset))
+ stack_store_float(stack, fac_offset, average(color));
+ if (stack_valid(color_offset))
+ stack_store_float3(stack, color_offset, color);
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/svm/svm_mapping.h b/intern/cycles/kernel/svm/svm_mapping.h
index 86181283821..998a29912d4 100644
--- a/intern/cycles/kernel/svm/svm_mapping.h
+++ b/intern/cycles/kernel/svm/svm_mapping.h
@@ -18,28 +18,30 @@ CCL_NAMESPACE_BEGIN
/* Mapping Node */
-ccl_device void svm_node_mapping(KernelGlobals *kg, ShaderData *sd, float *stack, uint vec_offset, uint out_offset, int *offset)
+ccl_device void svm_node_mapping(
+ KernelGlobals *kg, ShaderData *sd, float *stack, uint vec_offset, uint out_offset, int *offset)
{
- float3 v = stack_load_float3(stack, vec_offset);
+ float3 v = stack_load_float3(stack, vec_offset);
- Transform tfm;
- tfm.x = read_node_float(kg, offset);
- tfm.y = read_node_float(kg, offset);
- tfm.z = read_node_float(kg, offset);
+ Transform tfm;
+ tfm.x = read_node_float(kg, offset);
+ tfm.y = read_node_float(kg, offset);
+ tfm.z = read_node_float(kg, offset);
- float3 r = transform_point(&tfm, v);
- stack_store_float3(stack, out_offset, r);
+ float3 r = transform_point(&tfm, v);
+ stack_store_float3(stack, out_offset, r);
}
-ccl_device void svm_node_min_max(KernelGlobals *kg, ShaderData *sd, float *stack, uint vec_offset, uint out_offset, int *offset)
+ccl_device void svm_node_min_max(
+ KernelGlobals *kg, ShaderData *sd, float *stack, uint vec_offset, uint out_offset, int *offset)
{
- float3 v = stack_load_float3(stack, vec_offset);
+ float3 v = stack_load_float3(stack, vec_offset);
- float3 mn = float4_to_float3(read_node_float(kg, offset));
- float3 mx = float4_to_float3(read_node_float(kg, offset));
+ float3 mn = float4_to_float3(read_node_float(kg, offset));
+ float3 mx = float4_to_float3(read_node_float(kg, offset));
- float3 r = min(max(mn, v), mx);
- stack_store_float3(stack, out_offset, r);
+ float3 r = min(max(mn, v), mx);
+ stack_store_float3(stack, out_offset, r);
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/svm/svm_math.h b/intern/cycles/kernel/svm/svm_math.h
index c9a838361cd..5920913825b 100644
--- a/intern/cycles/kernel/svm/svm_math.h
+++ b/intern/cycles/kernel/svm/svm_math.h
@@ -18,32 +18,46 @@ CCL_NAMESPACE_BEGIN
/* Nodes */
-ccl_device void svm_node_math(KernelGlobals *kg, ShaderData *sd, float *stack, uint itype, uint f1_offset, uint f2_offset, int *offset)
+ccl_device void svm_node_math(KernelGlobals *kg,
+ ShaderData *sd,
+ float *stack,
+ uint itype,
+ uint f1_offset,
+ uint f2_offset,
+ int *offset)
{
- NodeMath type = (NodeMath)itype;
- float f1 = stack_load_float(stack, f1_offset);
- float f2 = stack_load_float(stack, f2_offset);
- float f = svm_math(type, f1, f2);
+ NodeMath type = (NodeMath)itype;
+ float f1 = stack_load_float(stack, f1_offset);
+ float f2 = stack_load_float(stack, f2_offset);
+ float f = svm_math(type, f1, f2);
- uint4 node1 = read_node(kg, offset);
+ uint4 node1 = read_node(kg, offset);
- stack_store_float(stack, node1.y, f);
+ stack_store_float(stack, node1.y, f);
}
-ccl_device void svm_node_vector_math(KernelGlobals *kg, ShaderData *sd, float *stack, uint itype, uint v1_offset, uint v2_offset, int *offset)
+ccl_device void svm_node_vector_math(KernelGlobals *kg,
+ ShaderData *sd,
+ float *stack,
+ uint itype,
+ uint v1_offset,
+ uint v2_offset,
+ int *offset)
{
- NodeVectorMath type = (NodeVectorMath)itype;
- float3 v1 = stack_load_float3(stack, v1_offset);
- float3 v2 = stack_load_float3(stack, v2_offset);
- float f;
- float3 v;
+ NodeVectorMath type = (NodeVectorMath)itype;
+ float3 v1 = stack_load_float3(stack, v1_offset);
+ float3 v2 = stack_load_float3(stack, v2_offset);
+ float f;
+ float3 v;
- svm_vector_math(&f, &v, type, v1, v2);
+ svm_vector_math(&f, &v, type, v1, v2);
- uint4 node1 = read_node(kg, offset);
+ uint4 node1 = read_node(kg, offset);
- if(stack_valid(node1.y)) stack_store_float(stack, node1.y, f);
- if(stack_valid(node1.z)) stack_store_float3(stack, node1.z, v);
+ if (stack_valid(node1.y))
+ stack_store_float(stack, node1.y, f);
+ if (stack_valid(node1.z))
+ stack_store_float3(stack, node1.z, v);
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/svm/svm_math_util.h b/intern/cycles/kernel/svm/svm_math_util.h
index 669b174e4a3..e3544515f1b 100644
--- a/intern/cycles/kernel/svm/svm_math_util.h
+++ b/intern/cycles/kernel/svm/svm_math_util.h
@@ -18,96 +18,97 @@ CCL_NAMESPACE_BEGIN
ccl_device float average_fac(float3 v)
{
- return (fabsf(v.x) + fabsf(v.y) + fabsf(v.z))/3.0f;
+ return (fabsf(v.x) + fabsf(v.y) + fabsf(v.z)) / 3.0f;
}
-ccl_device void svm_vector_math(float *Fac, float3 *Vector, NodeVectorMath type, float3 Vector1, float3 Vector2)
+ccl_device void svm_vector_math(
+ float *Fac, float3 *Vector, NodeVectorMath type, float3 Vector1, float3 Vector2)
{
- if(type == NODE_VECTOR_MATH_ADD) {
- *Vector = Vector1 + Vector2;
- *Fac = average_fac(*Vector);
- }
- else if(type == NODE_VECTOR_MATH_SUBTRACT) {
- *Vector = Vector1 - Vector2;
- *Fac = average_fac(*Vector);
- }
- else if(type == NODE_VECTOR_MATH_AVERAGE) {
- *Vector = safe_normalize_len(Vector1 + Vector2, Fac);
- }
- else if(type == NODE_VECTOR_MATH_DOT_PRODUCT) {
- *Fac = dot(Vector1, Vector2);
- *Vector = make_float3(0.0f, 0.0f, 0.0f);
- }
- else if(type == NODE_VECTOR_MATH_CROSS_PRODUCT) {
- *Vector = safe_normalize_len(cross(Vector1, Vector2), Fac);
- }
- else if(type == NODE_VECTOR_MATH_NORMALIZE) {
- *Vector = safe_normalize_len(Vector1, Fac);
- }
- else {
- *Fac = 0.0f;
- *Vector = make_float3(0.0f, 0.0f, 0.0f);
- }
+ if (type == NODE_VECTOR_MATH_ADD) {
+ *Vector = Vector1 + Vector2;
+ *Fac = average_fac(*Vector);
+ }
+ else if (type == NODE_VECTOR_MATH_SUBTRACT) {
+ *Vector = Vector1 - Vector2;
+ *Fac = average_fac(*Vector);
+ }
+ else if (type == NODE_VECTOR_MATH_AVERAGE) {
+ *Vector = safe_normalize_len(Vector1 + Vector2, Fac);
+ }
+ else if (type == NODE_VECTOR_MATH_DOT_PRODUCT) {
+ *Fac = dot(Vector1, Vector2);
+ *Vector = make_float3(0.0f, 0.0f, 0.0f);
+ }
+ else if (type == NODE_VECTOR_MATH_CROSS_PRODUCT) {
+ *Vector = safe_normalize_len(cross(Vector1, Vector2), Fac);
+ }
+ else if (type == NODE_VECTOR_MATH_NORMALIZE) {
+ *Vector = safe_normalize_len(Vector1, Fac);
+ }
+ else {
+ *Fac = 0.0f;
+ *Vector = make_float3(0.0f, 0.0f, 0.0f);
+ }
}
ccl_device float svm_math(NodeMath type, float Fac1, float Fac2)
{
- float Fac;
-
- if(type == NODE_MATH_ADD)
- Fac = Fac1 + Fac2;
- else if(type == NODE_MATH_SUBTRACT)
- Fac = Fac1 - Fac2;
- else if(type == NODE_MATH_MULTIPLY)
- Fac = Fac1*Fac2;
- else if(type == NODE_MATH_DIVIDE)
- Fac = safe_divide(Fac1, Fac2);
- else if(type == NODE_MATH_SINE)
- Fac = sinf(Fac1);
- else if(type == NODE_MATH_COSINE)
- Fac = cosf(Fac1);
- else if(type == NODE_MATH_TANGENT)
- Fac = tanf(Fac1);
- else if(type == NODE_MATH_ARCSINE)
- Fac = safe_asinf(Fac1);
- else if(type == NODE_MATH_ARCCOSINE)
- Fac = safe_acosf(Fac1);
- else if(type == NODE_MATH_ARCTANGENT)
- Fac = atanf(Fac1);
- else if(type == NODE_MATH_POWER)
- Fac = safe_powf(Fac1, Fac2);
- else if(type == NODE_MATH_LOGARITHM)
- Fac = safe_logf(Fac1, Fac2);
- else if(type == NODE_MATH_MINIMUM)
- Fac = fminf(Fac1, Fac2);
- else if(type == NODE_MATH_MAXIMUM)
- Fac = fmaxf(Fac1, Fac2);
- else if(type == NODE_MATH_ROUND)
- Fac = floorf(Fac1 + 0.5f);
- else if(type == NODE_MATH_LESS_THAN)
- Fac = Fac1 < Fac2;
- else if(type == NODE_MATH_GREATER_THAN)
- Fac = Fac1 > Fac2;
- else if(type == NODE_MATH_MODULO)
- Fac = safe_modulo(Fac1, Fac2);
- else if(type == NODE_MATH_ABSOLUTE)
- Fac = fabsf(Fac1);
- else if(type == NODE_MATH_ARCTAN2)
- Fac = atan2f(Fac1, Fac2);
- else if(type == NODE_MATH_FLOOR)
- Fac = floorf(Fac1);
- else if(type == NODE_MATH_CEIL)
- Fac = ceilf(Fac1);
- else if(type == NODE_MATH_FRACT)
- Fac = Fac1 - floorf(Fac1);
- else if(type == NODE_MATH_SQRT)
- Fac = safe_sqrtf(Fac1);
- else if(type == NODE_MATH_CLAMP)
- Fac = saturate(Fac1);
- else
- Fac = 0.0f;
-
- return Fac;
+ float Fac;
+
+ if (type == NODE_MATH_ADD)
+ Fac = Fac1 + Fac2;
+ else if (type == NODE_MATH_SUBTRACT)
+ Fac = Fac1 - Fac2;
+ else if (type == NODE_MATH_MULTIPLY)
+ Fac = Fac1 * Fac2;
+ else if (type == NODE_MATH_DIVIDE)
+ Fac = safe_divide(Fac1, Fac2);
+ else if (type == NODE_MATH_SINE)
+ Fac = sinf(Fac1);
+ else if (type == NODE_MATH_COSINE)
+ Fac = cosf(Fac1);
+ else if (type == NODE_MATH_TANGENT)
+ Fac = tanf(Fac1);
+ else if (type == NODE_MATH_ARCSINE)
+ Fac = safe_asinf(Fac1);
+ else if (type == NODE_MATH_ARCCOSINE)
+ Fac = safe_acosf(Fac1);
+ else if (type == NODE_MATH_ARCTANGENT)
+ Fac = atanf(Fac1);
+ else if (type == NODE_MATH_POWER)
+ Fac = safe_powf(Fac1, Fac2);
+ else if (type == NODE_MATH_LOGARITHM)
+ Fac = safe_logf(Fac1, Fac2);
+ else if (type == NODE_MATH_MINIMUM)
+ Fac = fminf(Fac1, Fac2);
+ else if (type == NODE_MATH_MAXIMUM)
+ Fac = fmaxf(Fac1, Fac2);
+ else if (type == NODE_MATH_ROUND)
+ Fac = floorf(Fac1 + 0.5f);
+ else if (type == NODE_MATH_LESS_THAN)
+ Fac = Fac1 < Fac2;
+ else if (type == NODE_MATH_GREATER_THAN)
+ Fac = Fac1 > Fac2;
+ else if (type == NODE_MATH_MODULO)
+ Fac = safe_modulo(Fac1, Fac2);
+ else if (type == NODE_MATH_ABSOLUTE)
+ Fac = fabsf(Fac1);
+ else if (type == NODE_MATH_ARCTAN2)
+ Fac = atan2f(Fac1, Fac2);
+ else if (type == NODE_MATH_FLOOR)
+ Fac = floorf(Fac1);
+ else if (type == NODE_MATH_CEIL)
+ Fac = ceilf(Fac1);
+ else if (type == NODE_MATH_FRACT)
+ Fac = Fac1 - floorf(Fac1);
+ else if (type == NODE_MATH_SQRT)
+ Fac = safe_sqrtf(Fac1);
+ else if (type == NODE_MATH_CLAMP)
+ Fac = saturate(Fac1);
+ else
+ Fac = 0.0f;
+
+ return Fac;
}
/* Calculate color in range 800..12000 using an approximation
@@ -117,74 +118,72 @@ ccl_device float svm_math(NodeMath type, float Fac1, float Fac2)
*/
ccl_static_constant float blackbody_table_r[6][3] = {
- { 2.52432244e+03f, -1.06185848e-03f, 3.11067539e+00f },
- { 3.37763626e+03f, -4.34581697e-04f, 1.64843306e+00f },
- { 4.10671449e+03f, -8.61949938e-05f, 6.41423749e-01f },
- { 4.66849800e+03f, 2.85655028e-05f, 1.29075375e-01f },
- { 4.60124770e+03f, 2.89727618e-05f, 1.48001316e-01f },
- { 3.78765709e+03f, 9.36026367e-06f, 3.98995841e-01f },
+ {2.52432244e+03f, -1.06185848e-03f, 3.11067539e+00f},
+ {3.37763626e+03f, -4.34581697e-04f, 1.64843306e+00f},
+ {4.10671449e+03f, -8.61949938e-05f, 6.41423749e-01f},
+ {4.66849800e+03f, 2.85655028e-05f, 1.29075375e-01f},
+ {4.60124770e+03f, 2.89727618e-05f, 1.48001316e-01f},
+ {3.78765709e+03f, 9.36026367e-06f, 3.98995841e-01f},
};
ccl_static_constant float blackbody_table_g[6][3] = {
- { -7.50343014e+02f, 3.15679613e-04f, 4.73464526e-01f },
- { -1.00402363e+03f, 1.29189794e-04f, 9.08181524e-01f },
- { -1.22075471e+03f, 2.56245413e-05f, 1.20753416e+00f },
- { -1.42546105e+03f, -4.01730887e-05f, 1.44002695e+00f },
- { -1.18134453e+03f, -2.18913373e-05f, 1.30656109e+00f },
- { -5.00279505e+02f, -4.59745390e-06f, 1.09090465e+00f },
+ {-7.50343014e+02f, 3.15679613e-04f, 4.73464526e-01f},
+ {-1.00402363e+03f, 1.29189794e-04f, 9.08181524e-01f},
+ {-1.22075471e+03f, 2.56245413e-05f, 1.20753416e+00f},
+ {-1.42546105e+03f, -4.01730887e-05f, 1.44002695e+00f},
+ {-1.18134453e+03f, -2.18913373e-05f, 1.30656109e+00f},
+ {-5.00279505e+02f, -4.59745390e-06f, 1.09090465e+00f},
};
ccl_static_constant float blackbody_table_b[6][4] = {
- { 0.0f, 0.0f, 0.0f, 0.0f }, /* zeros should be optimized by compiler */
- { 0.0f, 0.0f, 0.0f, 0.0f },
- { 0.0f, 0.0f, 0.0f, 0.0f },
- { -2.02524603e-11f, 1.79435860e-07f, -2.60561875e-04f, -1.41761141e-02f },
- { -2.22463426e-13f, -1.55078698e-08f, 3.81675160e-04f, -7.30646033e-01f },
- { 6.72595954e-13f, -2.73059993e-08f, 4.24068546e-04f, -7.52204323e-01f },
+ {0.0f, 0.0f, 0.0f, 0.0f}, /* zeros should be optimized by compiler */
+ {0.0f, 0.0f, 0.0f, 0.0f},
+ {0.0f, 0.0f, 0.0f, 0.0f},
+ {-2.02524603e-11f, 1.79435860e-07f, -2.60561875e-04f, -1.41761141e-02f},
+ {-2.22463426e-13f, -1.55078698e-08f, 3.81675160e-04f, -7.30646033e-01f},
+ {6.72595954e-13f, -2.73059993e-08f, 4.24068546e-04f, -7.52204323e-01f},
};
-
ccl_device float3 svm_math_blackbody_color(float t)
{
- /* TODO(lukas): Reimplement in XYZ. */
-
- if(t >= 12000.0f) {
- return make_float3(0.826270103f, 0.994478524f, 1.56626022f);
- }
- else if(t < 965.0f) {
- /* For 800 <= t < 965 color does not change in OSL implementation, so keep color the same */
- return make_float3(4.70366907f, 0.0f, 0.0f);
- }
-
- int i = (t >= 6365.0f)? 5:
- (t >= 3315.0f)? 4:
- (t >= 1902.0f)? 3:
- (t >= 1449.0f)? 2:
- (t >= 1167.0f)? 1: 0;
-
- ccl_constant float *r = blackbody_table_r[i];
- ccl_constant float *g = blackbody_table_g[i];
- ccl_constant float *b = blackbody_table_b[i];
-
- const float t_inv = 1.0f / t;
- return make_float3(r[0] * t_inv + r[1] * t + r[2],
- g[0] * t_inv + g[1] * t + g[2],
- ((b[0] * t + b[1]) * t + b[2]) * t + b[3]);
+ /* TODO(lukas): Reimplement in XYZ. */
+
+ if (t >= 12000.0f) {
+ return make_float3(0.826270103f, 0.994478524f, 1.56626022f);
+ }
+ else if (t < 965.0f) {
+ /* For 800 <= t < 965 color does not change in OSL implementation, so keep color the same */
+ return make_float3(4.70366907f, 0.0f, 0.0f);
+ }
+
+ int i = (t >= 6365.0f) ?
+ 5 :
+ (t >= 3315.0f) ? 4 :
+ (t >= 1902.0f) ? 3 : (t >= 1449.0f) ? 2 : (t >= 1167.0f) ? 1 : 0;
+
+ ccl_constant float *r = blackbody_table_r[i];
+ ccl_constant float *g = blackbody_table_g[i];
+ ccl_constant float *b = blackbody_table_b[i];
+
+ const float t_inv = 1.0f / t;
+ return make_float3(r[0] * t_inv + r[1] * t + r[2],
+ g[0] * t_inv + g[1] * t + g[2],
+ ((b[0] * t + b[1]) * t + b[2]) * t + b[3]);
}
ccl_device_inline float3 svm_math_gamma_color(float3 color, float gamma)
{
- if(gamma == 0.0f)
- return make_float3(1.0f, 1.0f, 1.0f);
+ if (gamma == 0.0f)
+ return make_float3(1.0f, 1.0f, 1.0f);
- if(color.x > 0.0f)
- color.x = powf(color.x, gamma);
- if(color.y > 0.0f)
- color.y = powf(color.y, gamma);
- if(color.z > 0.0f)
- color.z = powf(color.z, gamma);
+ if (color.x > 0.0f)
+ color.x = powf(color.x, gamma);
+ if (color.y > 0.0f)
+ color.y = powf(color.y, gamma);
+ if (color.z > 0.0f)
+ color.z = powf(color.z, gamma);
- return color;
+ return color;
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/svm/svm_mix.h b/intern/cycles/kernel/svm/svm_mix.h
index 903a4dacebf..15114bfd5e4 100644
--- a/intern/cycles/kernel/svm/svm_mix.h
+++ b/intern/cycles/kernel/svm/svm_mix.h
@@ -18,17 +18,23 @@ CCL_NAMESPACE_BEGIN
/* Node */
-ccl_device void svm_node_mix(KernelGlobals *kg, ShaderData *sd, float *stack, uint fac_offset, uint c1_offset, uint c2_offset, int *offset)
+ccl_device void svm_node_mix(KernelGlobals *kg,
+ ShaderData *sd,
+ float *stack,
+ uint fac_offset,
+ uint c1_offset,
+ uint c2_offset,
+ int *offset)
{
- /* read extra data */
- uint4 node1 = read_node(kg, offset);
+ /* read extra data */
+ uint4 node1 = read_node(kg, offset);
- float fac = stack_load_float(stack, fac_offset);
- float3 c1 = stack_load_float3(stack, c1_offset);
- float3 c2 = stack_load_float3(stack, c2_offset);
- float3 result = svm_mix((NodeMix)node1.y, fac, c1, c2);
+ float fac = stack_load_float(stack, fac_offset);
+ float3 c1 = stack_load_float3(stack, c1_offset);
+ float3 c2 = stack_load_float3(stack, c2_offset);
+ float3 result = svm_mix((NodeMix)node1.y, fac, c1, c2);
- stack_store_float3(stack, node1.z, result);
+ stack_store_float3(stack, node1.z, result);
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/svm/svm_musgrave.h b/intern/cycles/kernel/svm/svm_musgrave.h
index 5d9e12628ca..67fb5ca6241 100644
--- a/intern/cycles/kernel/svm/svm_musgrave.h
+++ b/intern/cycles/kernel/svm/svm_musgrave.h
@@ -27,23 +27,23 @@ CCL_NAMESPACE_BEGIN
ccl_device_noinline float noise_musgrave_fBm(float3 p, float H, float lacunarity, float octaves)
{
- float rmd;
- float value = 0.0f;
- float pwr = 1.0f;
- float pwHL = powf(lacunarity, -H);
- int i;
-
- for(i = 0; i < float_to_int(octaves); i++) {
- value += snoise(p) * pwr;
- pwr *= pwHL;
- p *= lacunarity;
- }
-
- rmd = octaves - floorf(octaves);
- if(rmd != 0.0f)
- value += rmd * snoise(p) * pwr;
-
- return value;
+ float rmd;
+ float value = 0.0f;
+ float pwr = 1.0f;
+ float pwHL = powf(lacunarity, -H);
+ int i;
+
+ for (i = 0; i < float_to_int(octaves); i++) {
+ value += snoise(p) * pwr;
+ pwr *= pwHL;
+ p *= lacunarity;
+ }
+
+ rmd = octaves - floorf(octaves);
+ if (rmd != 0.0f)
+ value += rmd * snoise(p) * pwr;
+
+ return value;
}
/* Musgrave Multifractal
@@ -53,25 +53,28 @@ ccl_device_noinline float noise_musgrave_fBm(float3 p, float H, float lacunarity
* octaves: number of frequencies in the fBm
*/
-ccl_device_noinline float noise_musgrave_multi_fractal(float3 p, float H, float lacunarity, float octaves)
+ccl_device_noinline float noise_musgrave_multi_fractal(float3 p,
+ float H,
+ float lacunarity,
+ float octaves)
{
- float rmd;
- float value = 1.0f;
- float pwr = 1.0f;
- float pwHL = powf(lacunarity, -H);
- int i;
-
- for(i = 0; i < float_to_int(octaves); i++) {
- value *= (pwr * snoise(p) + 1.0f);
- pwr *= pwHL;
- p *= lacunarity;
- }
-
- rmd = octaves - floorf(octaves);
- if(rmd != 0.0f)
- value *= (rmd * pwr * snoise(p) + 1.0f); /* correct? */
-
- return value;
+ float rmd;
+ float value = 1.0f;
+ float pwr = 1.0f;
+ float pwHL = powf(lacunarity, -H);
+ int i;
+
+ for (i = 0; i < float_to_int(octaves); i++) {
+ value *= (pwr * snoise(p) + 1.0f);
+ pwr *= pwHL;
+ p *= lacunarity;
+ }
+
+ rmd = octaves - floorf(octaves);
+ if (rmd != 0.0f)
+ value *= (rmd * pwr * snoise(p) + 1.0f); /* correct? */
+
+ return value;
}
/* Musgrave Heterogeneous Terrain
@@ -82,31 +85,32 @@ ccl_device_noinline float noise_musgrave_multi_fractal(float3 p, float H, float
* offset: raises the terrain from `sea level'
*/
-ccl_device_noinline float noise_musgrave_hetero_terrain(float3 p, float H, float lacunarity, float octaves, float offset)
+ccl_device_noinline float noise_musgrave_hetero_terrain(
+ float3 p, float H, float lacunarity, float octaves, float offset)
{
- float value, increment, rmd;
- float pwHL = powf(lacunarity, -H);
- float pwr = pwHL;
- int i;
-
- /* first unscaled octave of function; later octaves are scaled */
- value = offset + snoise(p);
- p *= lacunarity;
-
- for(i = 1; i < float_to_int(octaves); i++) {
- increment = (snoise(p) + offset) * pwr * value;
- value += increment;
- pwr *= pwHL;
- p *= lacunarity;
- }
-
- rmd = octaves - floorf(octaves);
- if(rmd != 0.0f) {
- increment = (snoise(p) + offset) * pwr * value;
- value += rmd * increment;
- }
-
- return value;
+ float value, increment, rmd;
+ float pwHL = powf(lacunarity, -H);
+ float pwr = pwHL;
+ int i;
+
+ /* first unscaled octave of function; later octaves are scaled */
+ value = offset + snoise(p);
+ p *= lacunarity;
+
+ for (i = 1; i < float_to_int(octaves); i++) {
+ increment = (snoise(p) + offset) * pwr * value;
+ value += increment;
+ pwr *= pwHL;
+ p *= lacunarity;
+ }
+
+ rmd = octaves - floorf(octaves);
+ if (rmd != 0.0f) {
+ increment = (snoise(p) + offset) * pwr * value;
+ value += rmd * increment;
+ }
+
+ return value;
}
/* Hybrid Additive/Multiplicative Multifractal Terrain
@@ -117,33 +121,34 @@ ccl_device_noinline float noise_musgrave_hetero_terrain(float3 p, float H, float
* offset: raises the terrain from `sea level'
*/
-ccl_device_noinline float noise_musgrave_hybrid_multi_fractal(float3 p, float H, float lacunarity, float octaves, float offset, float gain)
+ccl_device_noinline float noise_musgrave_hybrid_multi_fractal(
+ float3 p, float H, float lacunarity, float octaves, float offset, float gain)
{
- float result, signal, weight, rmd;
- float pwHL = powf(lacunarity, -H);
- float pwr = pwHL;
- int i;
-
- result = snoise(p) + offset;
- weight = gain * result;
- p *= lacunarity;
-
- for(i = 1; (weight > 0.001f) && (i < float_to_int(octaves)); i++) {
- if(weight > 1.0f)
- weight = 1.0f;
-
- signal = (snoise(p) + offset) * pwr;
- pwr *= pwHL;
- result += weight * signal;
- weight *= gain * signal;
- p *= lacunarity;
- }
-
- rmd = octaves - floorf(octaves);
- if(rmd != 0.0f)
- result += rmd * ((snoise(p) + offset) * pwr);
-
- return result;
+ float result, signal, weight, rmd;
+ float pwHL = powf(lacunarity, -H);
+ float pwr = pwHL;
+ int i;
+
+ result = snoise(p) + offset;
+ weight = gain * result;
+ p *= lacunarity;
+
+ for (i = 1; (weight > 0.001f) && (i < float_to_int(octaves)); i++) {
+ if (weight > 1.0f)
+ weight = 1.0f;
+
+ signal = (snoise(p) + offset) * pwr;
+ pwr *= pwHL;
+ result += weight * signal;
+ weight *= gain * signal;
+ p *= lacunarity;
+ }
+
+ rmd = octaves - floorf(octaves);
+ if (rmd != 0.0f)
+ result += rmd * ((snoise(p) + offset) * pwr);
+
+ return result;
}
/* Ridged Multifractal Terrain
@@ -154,81 +159,93 @@ ccl_device_noinline float noise_musgrave_hybrid_multi_fractal(float3 p, float H,
* offset: raises the terrain from `sea level'
*/
-ccl_device_noinline float noise_musgrave_ridged_multi_fractal(float3 p, float H, float lacunarity, float octaves, float offset, float gain)
+ccl_device_noinline float noise_musgrave_ridged_multi_fractal(
+ float3 p, float H, float lacunarity, float octaves, float offset, float gain)
{
- float result, signal, weight;
- float pwHL = powf(lacunarity, -H);
- float pwr = pwHL;
- int i;
-
- signal = offset - fabsf(snoise(p));
- signal *= signal;
- result = signal;
- weight = 1.0f;
-
- for(i = 1; i < float_to_int(octaves); i++) {
- p *= lacunarity;
- weight = saturate(signal * gain);
- signal = offset - fabsf(snoise(p));
- signal *= signal;
- signal *= weight;
- result += signal * pwr;
- pwr *= pwHL;
- }
-
- return result;
+ float result, signal, weight;
+ float pwHL = powf(lacunarity, -H);
+ float pwr = pwHL;
+ int i;
+
+ signal = offset - fabsf(snoise(p));
+ signal *= signal;
+ result = signal;
+ weight = 1.0f;
+
+ for (i = 1; i < float_to_int(octaves); i++) {
+ p *= lacunarity;
+ weight = saturate(signal * gain);
+ signal = offset - fabsf(snoise(p));
+ signal *= signal;
+ signal *= weight;
+ result += signal * pwr;
+ pwr *= pwHL;
+ }
+
+ return result;
}
/* Shader */
-ccl_device float svm_musgrave(NodeMusgraveType type, float dimension, float lacunarity, float octaves, float offset, float intensity, float gain, float3 p)
+ccl_device float svm_musgrave(NodeMusgraveType type,
+ float dimension,
+ float lacunarity,
+ float octaves,
+ float offset,
+ float intensity,
+ float gain,
+ float3 p)
{
- if(type == NODE_MUSGRAVE_MULTIFRACTAL)
- return intensity*noise_musgrave_multi_fractal(p, dimension, lacunarity, octaves);
- else if(type == NODE_MUSGRAVE_FBM)
- return intensity*noise_musgrave_fBm(p, dimension, lacunarity, octaves);
- else if(type == NODE_MUSGRAVE_HYBRID_MULTIFRACTAL)
- return intensity*noise_musgrave_hybrid_multi_fractal(p, dimension, lacunarity, octaves, offset, gain);
- else if(type == NODE_MUSGRAVE_RIDGED_MULTIFRACTAL)
- return intensity*noise_musgrave_ridged_multi_fractal(p, dimension, lacunarity, octaves, offset, gain);
- else if(type == NODE_MUSGRAVE_HETERO_TERRAIN)
- return intensity*noise_musgrave_hetero_terrain(p, dimension, lacunarity, octaves, offset);
-
- return 0.0f;
+ if (type == NODE_MUSGRAVE_MULTIFRACTAL)
+ return intensity * noise_musgrave_multi_fractal(p, dimension, lacunarity, octaves);
+ else if (type == NODE_MUSGRAVE_FBM)
+ return intensity * noise_musgrave_fBm(p, dimension, lacunarity, octaves);
+ else if (type == NODE_MUSGRAVE_HYBRID_MULTIFRACTAL)
+ return intensity *
+ noise_musgrave_hybrid_multi_fractal(p, dimension, lacunarity, octaves, offset, gain);
+ else if (type == NODE_MUSGRAVE_RIDGED_MULTIFRACTAL)
+ return intensity *
+ noise_musgrave_ridged_multi_fractal(p, dimension, lacunarity, octaves, offset, gain);
+ else if (type == NODE_MUSGRAVE_HETERO_TERRAIN)
+ return intensity * noise_musgrave_hetero_terrain(p, dimension, lacunarity, octaves, offset);
+
+ return 0.0f;
}
-ccl_device void svm_node_tex_musgrave(KernelGlobals *kg, ShaderData *sd, float *stack, uint4 node, int *offset)
+ccl_device void svm_node_tex_musgrave(
+ KernelGlobals *kg, ShaderData *sd, float *stack, uint4 node, int *offset)
{
- uint4 node2 = read_node(kg, offset);
- uint4 node3 = read_node(kg, offset);
-
- uint type, co_offset, color_offset, fac_offset;
- uint dimension_offset, lacunarity_offset, detail_offset, offset_offset;
- uint gain_offset, scale_offset;
-
- decode_node_uchar4(node.y, &type, &co_offset, &color_offset, &fac_offset);
- decode_node_uchar4(node.z, &dimension_offset, &lacunarity_offset, &detail_offset, &offset_offset);
- decode_node_uchar4(node.w, &gain_offset, &scale_offset, NULL, NULL);
-
- float3 co = stack_load_float3(stack, co_offset);
- float dimension = stack_load_float_default(stack, dimension_offset, node2.x);
- float lacunarity = stack_load_float_default(stack, lacunarity_offset, node2.y);
- float detail = stack_load_float_default(stack, detail_offset, node2.z);
- float foffset = stack_load_float_default(stack, offset_offset, node2.w);
- float gain = stack_load_float_default(stack, gain_offset, node3.x);
- float scale = stack_load_float_default(stack, scale_offset, node3.y);
-
- dimension = fmaxf(dimension, 1e-5f);
- detail = clamp(detail, 0.0f, 16.0f);
- lacunarity = fmaxf(lacunarity, 1e-5f);
-
- float f = svm_musgrave((NodeMusgraveType)type,
- dimension, lacunarity, detail, foffset, 1.0f, gain, co*scale);
-
- if(stack_valid(fac_offset))
- stack_store_float(stack, fac_offset, f);
- if(stack_valid(color_offset))
- stack_store_float3(stack, color_offset, make_float3(f, f, f));
+ uint4 node2 = read_node(kg, offset);
+ uint4 node3 = read_node(kg, offset);
+
+ uint type, co_offset, color_offset, fac_offset;
+ uint dimension_offset, lacunarity_offset, detail_offset, offset_offset;
+ uint gain_offset, scale_offset;
+
+ decode_node_uchar4(node.y, &type, &co_offset, &color_offset, &fac_offset);
+ decode_node_uchar4(
+ node.z, &dimension_offset, &lacunarity_offset, &detail_offset, &offset_offset);
+ decode_node_uchar4(node.w, &gain_offset, &scale_offset, NULL, NULL);
+
+ float3 co = stack_load_float3(stack, co_offset);
+ float dimension = stack_load_float_default(stack, dimension_offset, node2.x);
+ float lacunarity = stack_load_float_default(stack, lacunarity_offset, node2.y);
+ float detail = stack_load_float_default(stack, detail_offset, node2.z);
+ float foffset = stack_load_float_default(stack, offset_offset, node2.w);
+ float gain = stack_load_float_default(stack, gain_offset, node3.x);
+ float scale = stack_load_float_default(stack, scale_offset, node3.y);
+
+ dimension = fmaxf(dimension, 1e-5f);
+ detail = clamp(detail, 0.0f, 16.0f);
+ lacunarity = fmaxf(lacunarity, 1e-5f);
+
+ float f = svm_musgrave(
+ (NodeMusgraveType)type, dimension, lacunarity, detail, foffset, 1.0f, gain, co * scale);
+
+ if (stack_valid(fac_offset))
+ stack_store_float(stack, fac_offset, f);
+ if (stack_valid(color_offset))
+ stack_store_float3(stack, color_offset, make_float3(f, f, f));
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/svm/svm_noise.h b/intern/cycles/kernel/svm/svm_noise.h
index 8c425ecf326..322579ccfe3 100644
--- a/intern/cycles/kernel/svm/svm_noise.h
+++ b/intern/cycles/kernel/svm/svm_noise.h
@@ -33,280 +33,302 @@
CCL_NAMESPACE_BEGIN
#ifdef __KERNEL_SSE2__
-ccl_device_inline ssei quick_floor_sse(const ssef& x)
+ccl_device_inline ssei quick_floor_sse(const ssef &x)
{
- ssei b = truncatei(x);
- ssei isneg = cast((x < ssef(0.0f)).m128);
- return b + isneg; // unsaturated add 0xffffffff is the same as subtract -1
+ ssei b = truncatei(x);
+ ssei isneg = cast((x < ssef(0.0f)).m128);
+ return b + isneg; // unsaturated add 0xffffffff is the same as subtract -1
}
#endif
ccl_device uint hash(uint kx, uint ky, uint kz)
{
- // define some handy macros
-#define rot(x,k) (((x)<<(k)) | ((x)>>(32-(k))))
-#define final(a,b,c) \
-{ \
- c ^= b; c -= rot(b,14); \
- a ^= c; a -= rot(c,11); \
- b ^= a; b -= rot(a,25); \
- c ^= b; c -= rot(b,16); \
- a ^= c; a -= rot(c,4); \
- b ^= a; b -= rot(a,14); \
- c ^= b; c -= rot(b,24); \
-}
- // now hash the data!
- uint a, b, c, len = 3;
- a = b = c = 0xdeadbeef + (len << 2) + 13;
-
- c += kz;
- b += ky;
- a += kx;
- final(a, b, c);
-
- return c;
- // macros not needed anymore
+ // define some handy macros
+#define rot(x, k) (((x) << (k)) | ((x) >> (32 - (k))))
+#define final(a, b, c) \
+ { \
+ c ^= b; \
+ c -= rot(b, 14); \
+ a ^= c; \
+ a -= rot(c, 11); \
+ b ^= a; \
+ b -= rot(a, 25); \
+ c ^= b; \
+ c -= rot(b, 16); \
+ a ^= c; \
+ a -= rot(c, 4); \
+ b ^= a; \
+ b -= rot(a, 14); \
+ c ^= b; \
+ c -= rot(b, 24); \
+ }
+ // now hash the data!
+ uint a, b, c, len = 3;
+ a = b = c = 0xdeadbeef + (len << 2) + 13;
+
+ c += kz;
+ b += ky;
+ a += kx;
+ final(a, b, c);
+
+ return c;
+ // macros not needed anymore
#undef rot
#undef final
}
#ifdef __KERNEL_SSE2__
-ccl_device_inline ssei hash_sse(const ssei& kx, const ssei& ky, const ssei& kz)
+ccl_device_inline ssei hash_sse(const ssei &kx, const ssei &ky, const ssei &kz)
{
-# define rot(x,k) (((x)<<(k)) | (srl(x, 32-(k))))
-# define xor_rot(a, b, c) do {a = a^b; a = a - rot(b, c);} while(0)
-
- uint len = 3;
- ssei magic = ssei(0xdeadbeef + (len << 2) + 13);
- ssei a = magic + kx;
- ssei b = magic + ky;
- ssei c = magic + kz;
-
- xor_rot(c, b, 14);
- xor_rot(a, c, 11);
- xor_rot(b, a, 25);
- xor_rot(c, b, 16);
- xor_rot(a, c, 4);
- xor_rot(b, a, 14);
- xor_rot(c, b, 24);
-
- return c;
+# define rot(x, k) (((x) << (k)) | (srl(x, 32 - (k))))
+# define xor_rot(a, b, c) \
+ do { \
+ a = a ^ b; \
+ a = a - rot(b, c); \
+ } while (0)
+
+ uint len = 3;
+ ssei magic = ssei(0xdeadbeef + (len << 2) + 13);
+ ssei a = magic + kx;
+ ssei b = magic + ky;
+ ssei c = magic + kz;
+
+ xor_rot(c, b, 14);
+ xor_rot(a, c, 11);
+ xor_rot(b, a, 25);
+ xor_rot(c, b, 16);
+ xor_rot(a, c, 4);
+ xor_rot(b, a, 14);
+ xor_rot(c, b, 24);
+
+ return c;
# undef rot
# undef xor_rot
}
#endif
-#if 0 // unused
+#if 0 // unused
ccl_device int imod(int a, int b)
{
- a %= b;
- return a < 0 ? a + b : a;
+ a %= b;
+ return a < 0 ? a + b : a;
}
ccl_device uint phash(int kx, int ky, int kz, int3 p)
{
- return hash(imod(kx, p.x), imod(ky, p.y), imod(kz, p.z));
+ return hash(imod(kx, p.x), imod(ky, p.y), imod(kz, p.z));
}
#endif
#ifndef __KERNEL_SSE2__
-ccl_device float floorfrac(float x, int* i)
+ccl_device float floorfrac(float x, int *i)
{
- *i = quick_floor_to_int(x);
- return x - *i;
+ *i = quick_floor_to_int(x);
+ return x - *i;
}
#else
-ccl_device_inline ssef floorfrac_sse(const ssef& x, ssei *i)
+ccl_device_inline ssef floorfrac_sse(const ssef &x, ssei *i)
{
- *i = quick_floor_sse(x);
- return x - ssef(*i);
+ *i = quick_floor_sse(x);
+ return x - ssef(*i);
}
#endif
#ifndef __KERNEL_SSE2__
ccl_device float fade(float t)
{
- return t * t * t * (t * (t * 6.0f - 15.0f) + 10.0f);
+ return t * t * t * (t * (t * 6.0f - 15.0f) + 10.0f);
}
#else
ccl_device_inline ssef fade_sse(const ssef *t)
{
- ssef a = madd(*t, ssef(6.0f), ssef(-15.0f));
- ssef b = madd(*t, a, ssef(10.0f));
- return ((*t) * (*t)) * ((*t) * b);
+ ssef a = madd(*t, ssef(6.0f), ssef(-15.0f));
+ ssef b = madd(*t, a, ssef(10.0f));
+ return ((*t) * (*t)) * ((*t) * b);
}
#endif
#ifndef __KERNEL_SSE2__
ccl_device float nerp(float t, float a, float b)
{
- return (1.0f - t) * a + t * b;
+ return (1.0f - t) * a + t * b;
}
#else
-ccl_device_inline ssef nerp_sse(const ssef& t, const ssef& a, const ssef& b)
+ccl_device_inline ssef nerp_sse(const ssef &t, const ssef &a, const ssef &b)
{
- ssef x1 = (ssef(1.0f) - t) * a;
- return madd(t, b, x1);
+ ssef x1 = (ssef(1.0f) - t) * a;
+ return madd(t, b, x1);
}
#endif
#ifndef __KERNEL_SSE2__
ccl_device float grad(int hash, float x, float y, float z)
{
- // use vectors pointing to the edges of the cube
- int h = hash & 15;
- float u = h<8 ? x : y;
- float vt = ((h == 12) | (h == 14)) ? x : z;
- float v = h < 4 ? y : vt;
- return ((h&1) ? -u : u) + ((h&2) ? -v : v);
+ // use vectors pointing to the edges of the cube
+ int h = hash & 15;
+ float u = h < 8 ? x : y;
+ float vt = ((h == 12) | (h == 14)) ? x : z;
+ float v = h < 4 ? y : vt;
+ return ((h & 1) ? -u : u) + ((h & 2) ? -v : v);
}
#else
-ccl_device_inline ssef grad_sse(const ssei& hash, const ssef& x, const ssef& y, const ssef& z)
+ccl_device_inline ssef grad_sse(const ssei &hash, const ssef &x, const ssef &y, const ssef &z)
{
- ssei c1 = ssei(1);
- ssei c2 = ssei(2);
+ ssei c1 = ssei(1);
+ ssei c2 = ssei(2);
- ssei h = hash & ssei(15); // h = hash & 15
+ ssei h = hash & ssei(15); // h = hash & 15
- sseb case_ux = h < ssei(8); // 0xffffffff if h < 8 else 0
+ sseb case_ux = h < ssei(8); // 0xffffffff if h < 8 else 0
- ssef u = select(case_ux, x, y); // u = h<8 ? x : y
+ ssef u = select(case_ux, x, y); // u = h<8 ? x : y
- sseb case_vy = h < ssei(4); // 0xffffffff if h < 4 else 0
+ sseb case_vy = h < ssei(4); // 0xffffffff if h < 4 else 0
- sseb case_h12 = h == ssei(12); // 0xffffffff if h == 12 else 0
- sseb case_h14 = h == ssei(14); // 0xffffffff if h == 14 else 0
+ sseb case_h12 = h == ssei(12); // 0xffffffff if h == 12 else 0
+ sseb case_h14 = h == ssei(14); // 0xffffffff if h == 14 else 0
- sseb case_vx = case_h12 | case_h14; // 0xffffffff if h == 12 or h == 14 else 0
+ sseb case_vx = case_h12 | case_h14; // 0xffffffff if h == 12 or h == 14 else 0
- ssef v = select(case_vy, y, select(case_vx, x, z)); // v = h<4 ? y : h == 12 || h == 14 ? x : z
+ ssef v = select(case_vy, y, select(case_vx, x, z)); // v = h<4 ? y : h == 12 || h == 14 ? x : z
- ssei case_uneg = (h & c1) << 31; // 1<<31 if h&1 else 0
- ssef case_uneg_mask = cast(case_uneg); // -0.0 if h&1 else +0.0
- ssef ru = u ^ case_uneg_mask; // -u if h&1 else u (copy float sign)
+ ssei case_uneg = (h & c1) << 31; // 1<<31 if h&1 else 0
+ ssef case_uneg_mask = cast(case_uneg); // -0.0 if h&1 else +0.0
+ ssef ru = u ^ case_uneg_mask; // -u if h&1 else u (copy float sign)
- ssei case_vneg = (h & c2) << 30; // 2<<30 if h&2 else 0
- ssef case_vneg_mask = cast(case_vneg); // -0.0 if h&2 else +0.0
- ssef rv = v ^ case_vneg_mask; // -v if h&2 else v (copy float sign)
+ ssei case_vneg = (h & c2) << 30; // 2<<30 if h&2 else 0
+ ssef case_vneg_mask = cast(case_vneg); // -0.0 if h&2 else +0.0
+ ssef rv = v ^ case_vneg_mask; // -v if h&2 else v (copy float sign)
- ssef r = ru + rv; // ((h&1) ? -u : u) + ((h&2) ? -v : v)
- return r;
+ ssef r = ru + rv; // ((h&1) ? -u : u) + ((h&2) ? -v : v)
+ return r;
}
#endif
#ifndef __KERNEL_SSE2__
ccl_device float scale3(float result)
{
- return 0.9820f * result;
+ return 0.9820f * result;
}
#else
-ccl_device_inline ssef scale3_sse(const ssef& result)
+ccl_device_inline ssef scale3_sse(const ssef &result)
{
- return ssef(0.9820f) * result;
+ return ssef(0.9820f) * result;
}
#endif
#ifndef __KERNEL_SSE2__
ccl_device_noinline float perlin(float x, float y, float z)
{
- int X; float fx = floorfrac(x, &X);
- int Y; float fy = floorfrac(y, &Y);
- int Z; float fz = floorfrac(z, &Z);
-
- float u = fade(fx);
- float v = fade(fy);
- float w = fade(fz);
-
- float result;
-
- result = nerp (w, nerp (v, nerp (u, grad (hash (X , Y , Z ), fx , fy , fz ),
- grad (hash (X+1, Y , Z ), fx-1.0f, fy , fz )),
- nerp (u, grad (hash (X , Y+1, Z ), fx , fy-1.0f, fz ),
- grad (hash (X+1, Y+1, Z ), fx-1.0f, fy-1.0f, fz ))),
- nerp (v, nerp (u, grad (hash (X , Y , Z+1), fx , fy , fz-1.0f ),
- grad (hash (X+1, Y , Z+1), fx-1.0f, fy , fz-1.0f )),
- nerp (u, grad (hash (X , Y+1, Z+1), fx , fy-1.0f, fz-1.0f ),
- grad (hash (X+1, Y+1, Z+1), fx-1.0f, fy-1.0f, fz-1.0f ))));
- float r = scale3(result);
-
- /* can happen for big coordinates, things even out to 0.0 then anyway */
- return (isfinite(r))? r: 0.0f;
+ int X;
+ float fx = floorfrac(x, &X);
+ int Y;
+ float fy = floorfrac(y, &Y);
+ int Z;
+ float fz = floorfrac(z, &Z);
+
+ float u = fade(fx);
+ float v = fade(fy);
+ float w = fade(fz);
+
+ float result;
+
+ result = nerp(
+ w,
+ nerp(v,
+ nerp(u, grad(hash(X, Y, Z), fx, fy, fz), grad(hash(X + 1, Y, Z), fx - 1.0f, fy, fz)),
+ nerp(u,
+ grad(hash(X, Y + 1, Z), fx, fy - 1.0f, fz),
+ grad(hash(X + 1, Y + 1, Z), fx - 1.0f, fy - 1.0f, fz))),
+ nerp(v,
+ nerp(u,
+ grad(hash(X, Y, Z + 1), fx, fy, fz - 1.0f),
+ grad(hash(X + 1, Y, Z + 1), fx - 1.0f, fy, fz - 1.0f)),
+ nerp(u,
+ grad(hash(X, Y + 1, Z + 1), fx, fy - 1.0f, fz - 1.0f),
+ grad(hash(X + 1, Y + 1, Z + 1), fx - 1.0f, fy - 1.0f, fz - 1.0f))));
+ float r = scale3(result);
+
+ /* can happen for big coordinates, things even out to 0.0 then anyway */
+ return (isfinite(r)) ? r : 0.0f;
}
#else
ccl_device_noinline float perlin(float x, float y, float z)
{
- ssef xyz = ssef(x, y, z, 0.0f);
- ssei XYZ;
+ ssef xyz = ssef(x, y, z, 0.0f);
+ ssei XYZ;
- ssef fxyz = floorfrac_sse(xyz, &XYZ);
+ ssef fxyz = floorfrac_sse(xyz, &XYZ);
- ssef uvw = fade_sse(&fxyz);
- ssef u = shuffle<0>(uvw), v = shuffle<1>(uvw), w = shuffle<2>(uvw);
+ ssef uvw = fade_sse(&fxyz);
+ ssef u = shuffle<0>(uvw), v = shuffle<1>(uvw), w = shuffle<2>(uvw);
- ssei XYZ_ofc = XYZ + ssei(1);
- ssei vdy = shuffle<1, 1, 1, 1>(XYZ, XYZ_ofc); // +0, +0, +1, +1
- ssei vdz = shuffle<0, 2, 0, 2>(shuffle<2, 2, 2, 2>(XYZ, XYZ_ofc)); // +0, +1, +0, +1
+ ssei XYZ_ofc = XYZ + ssei(1);
+ ssei vdy = shuffle<1, 1, 1, 1>(XYZ, XYZ_ofc); // +0, +0, +1, +1
+ ssei vdz = shuffle<0, 2, 0, 2>(shuffle<2, 2, 2, 2>(XYZ, XYZ_ofc)); // +0, +1, +0, +1
- ssei h1 = hash_sse(shuffle<0>(XYZ), vdy, vdz); // hash directions 000, 001, 010, 011
- ssei h2 = hash_sse(shuffle<0>(XYZ_ofc), vdy, vdz); // hash directions 100, 101, 110, 111
+ ssei h1 = hash_sse(shuffle<0>(XYZ), vdy, vdz); // hash directions 000, 001, 010, 011
+ ssei h2 = hash_sse(shuffle<0>(XYZ_ofc), vdy, vdz); // hash directions 100, 101, 110, 111
- ssef fxyz_ofc = fxyz - ssef(1.0f);
- ssef vfy = shuffle<1, 1, 1, 1>(fxyz, fxyz_ofc);
- ssef vfz = shuffle<0, 2, 0, 2>(shuffle<2, 2, 2, 2>(fxyz, fxyz_ofc));
+ ssef fxyz_ofc = fxyz - ssef(1.0f);
+ ssef vfy = shuffle<1, 1, 1, 1>(fxyz, fxyz_ofc);
+ ssef vfz = shuffle<0, 2, 0, 2>(shuffle<2, 2, 2, 2>(fxyz, fxyz_ofc));
- ssef g1 = grad_sse(h1, shuffle<0>(fxyz), vfy, vfz);
- ssef g2 = grad_sse(h2, shuffle<0>(fxyz_ofc), vfy, vfz);
- ssef n1 = nerp_sse(u, g1, g2);
+ ssef g1 = grad_sse(h1, shuffle<0>(fxyz), vfy, vfz);
+ ssef g2 = grad_sse(h2, shuffle<0>(fxyz_ofc), vfy, vfz);
+ ssef n1 = nerp_sse(u, g1, g2);
- ssef n1_half = shuffle<2, 3, 2, 3>(n1); // extract 2 floats to a separate vector
- ssef n2 = nerp_sse(v, n1, n1_half); // process nerp([a, b, _, _], [c, d, _, _]) -> [a', b', _, _]
+ ssef n1_half = shuffle<2, 3, 2, 3>(n1); // extract 2 floats to a separate vector
+ ssef n2 = nerp_sse(
+ v, n1, n1_half); // process nerp([a, b, _, _], [c, d, _, _]) -> [a', b', _, _]
- ssef n2_second = shuffle<1>(n2); // extract b to a separate vector
- ssef result = nerp_sse(w, n2, n2_second); // process nerp([a', _, _, _], [b', _, _, _]) -> [a'', _, _, _]
+ ssef n2_second = shuffle<1>(n2); // extract b to a separate vector
+ ssef result = nerp_sse(
+ w, n2, n2_second); // process nerp([a', _, _, _], [b', _, _, _]) -> [a'', _, _, _]
- ssef r = scale3_sse(result);
+ ssef r = scale3_sse(result);
- ssef infmask = cast(ssei(0x7f800000));
- ssef rinfmask = ((r & infmask) == infmask).m128; // 0xffffffff if r is inf/-inf/nan else 0
- ssef rfinite = andnot(rinfmask, r); // 0 if r is inf/-inf/nan else r
- return extract<0>(rfinite);
+ ssef infmask = cast(ssei(0x7f800000));
+ ssef rinfmask = ((r & infmask) == infmask).m128; // 0xffffffff if r is inf/-inf/nan else 0
+ ssef rfinite = andnot(rinfmask, r); // 0 if r is inf/-inf/nan else r
+ return extract<0>(rfinite);
}
#endif
/* perlin noise in range 0..1 */
ccl_device float noise(float3 p)
{
- float r = perlin(p.x, p.y, p.z);
- return 0.5f*r + 0.5f;
+ float r = perlin(p.x, p.y, p.z);
+ return 0.5f * r + 0.5f;
}
/* perlin noise in range -1..1 */
ccl_device float snoise(float3 p)
{
- return perlin(p.x, p.y, p.z);
+ return perlin(p.x, p.y, p.z);
}
/* cell noise */
ccl_device float cellnoise(float3 p)
{
- int3 ip = quick_floor_to_int3(p);
- return bits_to_01(hash(ip.x, ip.y, ip.z));
+ int3 ip = quick_floor_to_int3(p);
+ return bits_to_01(hash(ip.x, ip.y, ip.z));
}
ccl_device float3 cellnoise3(float3 p)
{
- int3 ip = quick_floor_to_int3(p);
+ int3 ip = quick_floor_to_int3(p);
#ifndef __KERNEL_SSE__
- float r = bits_to_01(hash(ip.x, ip.y, ip.z));
- float g = bits_to_01(hash(ip.y, ip.x, ip.z));
- float b = bits_to_01(hash(ip.y, ip.z, ip.x));
- return make_float3(r, g, b);
+ float r = bits_to_01(hash(ip.x, ip.y, ip.z));
+ float g = bits_to_01(hash(ip.y, ip.x, ip.z));
+ float b = bits_to_01(hash(ip.y, ip.z, ip.x));
+ return make_float3(r, g, b);
#else
- ssei ip_yxz = shuffle<1, 0, 2, 3>(ssei(ip.m128));
- ssei ip_xyy = shuffle<0, 1, 1, 3>(ssei(ip.m128));
- ssei ip_zzx = shuffle<2, 2, 0, 3>(ssei(ip.m128));
- ssei bits = hash_sse(ip_xyy, ip_yxz, ip_zzx);
- return float3(uint32_to_float(bits) * ssef(1.0f/(float)0xFFFFFFFF));
+ ssei ip_yxz = shuffle<1, 0, 2, 3>(ssei(ip.m128));
+ ssei ip_xyy = shuffle<0, 1, 1, 3>(ssei(ip.m128));
+ ssei ip_zzx = shuffle<2, 2, 0, 3>(ssei(ip.m128));
+ ssei bits = hash_sse(ip_xyy, ip_yxz, ip_zzx);
+ return float3(uint32_to_float(bits) * ssef(1.0f / (float)0xFFFFFFFF));
#endif
}
diff --git a/intern/cycles/kernel/svm/svm_noisetex.h b/intern/cycles/kernel/svm/svm_noisetex.h
index c02940f96d6..3324e86fcd8 100644
--- a/intern/cycles/kernel/svm/svm_noisetex.h
+++ b/intern/cycles/kernel/svm/svm_noisetex.h
@@ -18,42 +18,43 @@ CCL_NAMESPACE_BEGIN
/* Noise */
-ccl_device void svm_node_tex_noise(KernelGlobals *kg, ShaderData *sd, float *stack, uint4 node, int *offset)
+ccl_device void svm_node_tex_noise(
+ KernelGlobals *kg, ShaderData *sd, float *stack, uint4 node, int *offset)
{
- uint co_offset, scale_offset, detail_offset, distortion_offset, fac_offset, color_offset;
+ uint co_offset, scale_offset, detail_offset, distortion_offset, fac_offset, color_offset;
- decode_node_uchar4(node.y, &co_offset, &scale_offset, &detail_offset, &distortion_offset);
- decode_node_uchar4(node.z, &color_offset, &fac_offset, NULL, NULL);
+ decode_node_uchar4(node.y, &co_offset, &scale_offset, &detail_offset, &distortion_offset);
+ decode_node_uchar4(node.z, &color_offset, &fac_offset, NULL, NULL);
- uint4 node2 = read_node(kg, offset);
+ uint4 node2 = read_node(kg, offset);
- float scale = stack_load_float_default(stack, scale_offset, node2.x);
- float detail = stack_load_float_default(stack, detail_offset, node2.y);
- float distortion = stack_load_float_default(stack, distortion_offset, node2.z);
- float3 p = stack_load_float3(stack, co_offset) * scale;
- int hard = 0;
+ float scale = stack_load_float_default(stack, scale_offset, node2.x);
+ float detail = stack_load_float_default(stack, detail_offset, node2.y);
+ float distortion = stack_load_float_default(stack, distortion_offset, node2.z);
+ float3 p = stack_load_float3(stack, co_offset) * scale;
+ int hard = 0;
- if(distortion != 0.0f) {
- float3 r, offset = make_float3(13.5f, 13.5f, 13.5f);
+ if (distortion != 0.0f) {
+ float3 r, offset = make_float3(13.5f, 13.5f, 13.5f);
- r.x = noise(p + offset) * distortion;
- r.y = noise(p) * distortion;
- r.z = noise(p - offset) * distortion;
+ r.x = noise(p + offset) * distortion;
+ r.y = noise(p) * distortion;
+ r.z = noise(p - offset) * distortion;
- p += r;
- }
+ p += r;
+ }
- float f = noise_turbulence(p, detail, hard);
+ float f = noise_turbulence(p, detail, hard);
- if(stack_valid(fac_offset)) {
- stack_store_float(stack, fac_offset, f);
- }
- if(stack_valid(color_offset)) {
- float3 color = make_float3(f,
- noise_turbulence(make_float3(p.y, p.x, p.z), detail, hard),
- noise_turbulence(make_float3(p.y, p.z, p.x), detail, hard));
- stack_store_float3(stack, color_offset, color);
- }
+ if (stack_valid(fac_offset)) {
+ stack_store_float(stack, fac_offset, f);
+ }
+ if (stack_valid(color_offset)) {
+ float3 color = make_float3(f,
+ noise_turbulence(make_float3(p.y, p.x, p.z), detail, hard),
+ noise_turbulence(make_float3(p.y, p.z, p.x), detail, hard));
+ stack_store_float3(stack, color_offset, color);
+ }
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/svm/svm_normal.h b/intern/cycles/kernel/svm/svm_normal.h
index fe46d79fe15..4cd3eab0ed2 100644
--- a/intern/cycles/kernel/svm/svm_normal.h
+++ b/intern/cycles/kernel/svm/svm_normal.h
@@ -16,23 +16,29 @@
CCL_NAMESPACE_BEGIN
-ccl_device void svm_node_normal(KernelGlobals *kg, ShaderData *sd, float *stack, uint in_normal_offset, uint out_normal_offset, uint out_dot_offset, int *offset)
+ccl_device void svm_node_normal(KernelGlobals *kg,
+ ShaderData *sd,
+ float *stack,
+ uint in_normal_offset,
+ uint out_normal_offset,
+ uint out_dot_offset,
+ int *offset)
{
- /* read extra data */
- uint4 node1 = read_node(kg, offset);
- float3 normal = stack_load_float3(stack, in_normal_offset);
+ /* read extra data */
+ uint4 node1 = read_node(kg, offset);
+ float3 normal = stack_load_float3(stack, in_normal_offset);
- float3 direction;
- direction.x = __int_as_float(node1.x);
- direction.y = __int_as_float(node1.y);
- direction.z = __int_as_float(node1.z);
- direction = normalize(direction);
+ float3 direction;
+ direction.x = __int_as_float(node1.x);
+ direction.y = __int_as_float(node1.y);
+ direction.z = __int_as_float(node1.z);
+ direction = normalize(direction);
- if(stack_valid(out_normal_offset))
- stack_store_float3(stack, out_normal_offset, direction);
+ if (stack_valid(out_normal_offset))
+ stack_store_float3(stack, out_normal_offset, direction);
- if(stack_valid(out_dot_offset))
- stack_store_float(stack, out_dot_offset, dot(direction, normalize(normal)));
+ if (stack_valid(out_dot_offset))
+ stack_store_float(stack, out_dot_offset, dot(direction, normalize(normal)));
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/svm/svm_ramp.h b/intern/cycles/kernel/svm/svm_ramp.h
index 6f39391057e..6084ee35a1f 100644
--- a/intern/cycles/kernel/svm/svm_ramp.h
+++ b/intern/cycles/kernel/svm/svm_ramp.h
@@ -21,91 +21,84 @@ CCL_NAMESPACE_BEGIN
/* NOTE: svm_ramp.h, svm_ramp_util.h and node_ramp_util.h must stay consistent */
-ccl_device_inline float4 rgb_ramp_lookup(KernelGlobals *kg,
- int offset,
- float f,
- bool interpolate,
- bool extrapolate,
- int table_size)
+ccl_device_inline float4 rgb_ramp_lookup(
+ KernelGlobals *kg, int offset, float f, bool interpolate, bool extrapolate, int table_size)
{
- if((f < 0.0f || f > 1.0f) && extrapolate) {
- float4 t0, dy;
- if(f < 0.0f) {
- t0 = fetch_node_float(kg, offset);
- dy = t0 - fetch_node_float(kg, offset + 1);
- f = -f;
- }
- else {
- t0 = fetch_node_float(kg, offset + table_size - 1);
- dy = t0 - fetch_node_float(kg, offset + table_size - 2);
- f = f - 1.0f;
- }
- return t0 + dy * f * (table_size-1);
- }
-
- f = saturate(f)*(table_size-1);
-
- /* clamp int as well in case of NaN */
- int i = clamp(float_to_int(f), 0, table_size-1);
- float t = f - (float)i;
-
- float4 a = fetch_node_float(kg, offset+i);
-
- if(interpolate && t > 0.0f)
- a = (1.0f - t)*a + t*fetch_node_float(kg, offset+i+1);
-
- return a;
+ if ((f < 0.0f || f > 1.0f) && extrapolate) {
+ float4 t0, dy;
+ if (f < 0.0f) {
+ t0 = fetch_node_float(kg, offset);
+ dy = t0 - fetch_node_float(kg, offset + 1);
+ f = -f;
+ }
+ else {
+ t0 = fetch_node_float(kg, offset + table_size - 1);
+ dy = t0 - fetch_node_float(kg, offset + table_size - 2);
+ f = f - 1.0f;
+ }
+ return t0 + dy * f * (table_size - 1);
+ }
+
+ f = saturate(f) * (table_size - 1);
+
+ /* clamp int as well in case of NaN */
+ int i = clamp(float_to_int(f), 0, table_size - 1);
+ float t = f - (float)i;
+
+ float4 a = fetch_node_float(kg, offset + i);
+
+ if (interpolate && t > 0.0f)
+ a = (1.0f - t) * a + t * fetch_node_float(kg, offset + i + 1);
+
+ return a;
}
-ccl_device void svm_node_rgb_ramp(KernelGlobals *kg, ShaderData *sd, float *stack, uint4 node, int *offset)
+ccl_device void svm_node_rgb_ramp(
+ KernelGlobals *kg, ShaderData *sd, float *stack, uint4 node, int *offset)
{
- uint fac_offset, color_offset, alpha_offset;
- uint interpolate = node.z;
+ uint fac_offset, color_offset, alpha_offset;
+ uint interpolate = node.z;
- decode_node_uchar4(node.y, &fac_offset, &color_offset, &alpha_offset, NULL);
+ decode_node_uchar4(node.y, &fac_offset, &color_offset, &alpha_offset, NULL);
- uint table_size = read_node(kg, offset).x;
+ uint table_size = read_node(kg, offset).x;
- float fac = stack_load_float(stack, fac_offset);
- float4 color = rgb_ramp_lookup(kg, *offset, fac, interpolate, false, table_size);
+ float fac = stack_load_float(stack, fac_offset);
+ float4 color = rgb_ramp_lookup(kg, *offset, fac, interpolate, false, table_size);
- if(stack_valid(color_offset))
- stack_store_float3(stack, color_offset, float4_to_float3(color));
- if(stack_valid(alpha_offset))
- stack_store_float(stack, alpha_offset, color.w);
+ if (stack_valid(color_offset))
+ stack_store_float3(stack, color_offset, float4_to_float3(color));
+ if (stack_valid(alpha_offset))
+ stack_store_float(stack, alpha_offset, color.w);
- *offset += table_size;
+ *offset += table_size;
}
-ccl_device void svm_node_curves(KernelGlobals *kg, ShaderData *sd, float *stack, uint4 node, int *offset)
+ccl_device void svm_node_curves(
+ KernelGlobals *kg, ShaderData *sd, float *stack, uint4 node, int *offset)
{
- uint fac_offset, color_offset, out_offset;
- decode_node_uchar4(node.y,
- &fac_offset,
- &color_offset,
- &out_offset,
- NULL);
+ uint fac_offset, color_offset, out_offset;
+ decode_node_uchar4(node.y, &fac_offset, &color_offset, &out_offset, NULL);
- uint table_size = read_node(kg, offset).x;
+ uint table_size = read_node(kg, offset).x;
- float fac = stack_load_float(stack, fac_offset);
- float3 color = stack_load_float3(stack, color_offset);
+ float fac = stack_load_float(stack, fac_offset);
+ float3 color = stack_load_float3(stack, color_offset);
- const float min_x = __int_as_float(node.z),
- max_x = __int_as_float(node.w);
- const float range_x = max_x - min_x;
- const float3 relpos = (color - make_float3(min_x, min_x, min_x)) / range_x;
+ const float min_x = __int_as_float(node.z), max_x = __int_as_float(node.w);
+ const float range_x = max_x - min_x;
+ const float3 relpos = (color - make_float3(min_x, min_x, min_x)) / range_x;
- float r = rgb_ramp_lookup(kg, *offset, relpos.x, true, true, table_size).x;
- float g = rgb_ramp_lookup(kg, *offset, relpos.y, true, true, table_size).y;
- float b = rgb_ramp_lookup(kg, *offset, relpos.z, true, true, table_size).z;
+ float r = rgb_ramp_lookup(kg, *offset, relpos.x, true, true, table_size).x;
+ float g = rgb_ramp_lookup(kg, *offset, relpos.y, true, true, table_size).y;
+ float b = rgb_ramp_lookup(kg, *offset, relpos.z, true, true, table_size).z;
- color = (1.0f - fac)*color + fac*make_float3(r, g, b);
- stack_store_float3(stack, out_offset, color);
+ color = (1.0f - fac) * color + fac * make_float3(r, g, b);
+ stack_store_float3(stack, out_offset, color);
- *offset += table_size;
+ *offset += table_size;
}
CCL_NAMESPACE_END
-#endif /* __SVM_RAMP_H__ */
+#endif /* __SVM_RAMP_H__ */
diff --git a/intern/cycles/kernel/svm/svm_ramp_util.h b/intern/cycles/kernel/svm/svm_ramp_util.h
index 847108ff1c2..202596c1fe3 100644
--- a/intern/cycles/kernel/svm/svm_ramp_util.h
+++ b/intern/cycles/kernel/svm/svm_ramp_util.h
@@ -21,78 +21,70 @@ CCL_NAMESPACE_BEGIN
/* NOTE: svm_ramp.h, svm_ramp_util.h and node_ramp_util.h must stay consistent */
-ccl_device_inline float3 rgb_ramp_lookup(const float3 *ramp,
- float f,
- bool interpolate,
- bool extrapolate,
- int table_size)
+ccl_device_inline float3
+rgb_ramp_lookup(const float3 *ramp, float f, bool interpolate, bool extrapolate, int table_size)
{
- if((f < 0.0f || f > 1.0f) && extrapolate) {
- float3 t0, dy;
- if(f < 0.0f) {
- t0 = ramp[0];
- dy = t0 - ramp[1],
- f = -f;
- }
- else {
- t0 = ramp[table_size - 1];
- dy = t0 - ramp[table_size - 2];
- f = f - 1.0f;
- }
- return t0 + dy * f * (table_size - 1);
- }
-
- f = clamp(f, 0.0f, 1.0f) * (table_size - 1);
-
- /* clamp int as well in case of NaN */
- int i = clamp(float_to_int(f), 0, table_size-1);
- float t = f - (float)i;
-
- float3 result = ramp[i];
-
- if(interpolate && t > 0.0f) {
- result = (1.0f - t) * result + t * ramp[i + 1];
- }
-
- return result;
+ if ((f < 0.0f || f > 1.0f) && extrapolate) {
+ float3 t0, dy;
+ if (f < 0.0f) {
+ t0 = ramp[0];
+ dy = t0 - ramp[1], f = -f;
+ }
+ else {
+ t0 = ramp[table_size - 1];
+ dy = t0 - ramp[table_size - 2];
+ f = f - 1.0f;
+ }
+ return t0 + dy * f * (table_size - 1);
+ }
+
+ f = clamp(f, 0.0f, 1.0f) * (table_size - 1);
+
+ /* clamp int as well in case of NaN */
+ int i = clamp(float_to_int(f), 0, table_size - 1);
+ float t = f - (float)i;
+
+ float3 result = ramp[i];
+
+ if (interpolate && t > 0.0f) {
+ result = (1.0f - t) * result + t * ramp[i + 1];
+ }
+
+ return result;
}
-ccl_device float float_ramp_lookup(const float *ramp,
- float f,
- bool interpolate,
- bool extrapolate,
- int table_size)
+ccl_device float float_ramp_lookup(
+ const float *ramp, float f, bool interpolate, bool extrapolate, int table_size)
{
- if((f < 0.0f || f > 1.0f) && extrapolate) {
- float t0, dy;
- if(f < 0.0f) {
- t0 = ramp[0];
- dy = t0 - ramp[1],
- f = -f;
- }
- else {
- t0 = ramp[table_size - 1];
- dy = t0 - ramp[table_size - 2];
- f = f - 1.0f;
- }
- return t0 + dy * f * (table_size - 1);
- }
-
- f = clamp(f, 0.0f, 1.0f) * (table_size - 1);
-
- /* clamp int as well in case of NaN */
- int i = clamp(float_to_int(f), 0, table_size-1);
- float t = f - (float)i;
-
- float result = ramp[i];
-
- if(interpolate && t > 0.0f) {
- result = (1.0f - t) * result + t * ramp[i + 1];
- }
-
- return result;
+ if ((f < 0.0f || f > 1.0f) && extrapolate) {
+ float t0, dy;
+ if (f < 0.0f) {
+ t0 = ramp[0];
+ dy = t0 - ramp[1], f = -f;
+ }
+ else {
+ t0 = ramp[table_size - 1];
+ dy = t0 - ramp[table_size - 2];
+ f = f - 1.0f;
+ }
+ return t0 + dy * f * (table_size - 1);
+ }
+
+ f = clamp(f, 0.0f, 1.0f) * (table_size - 1);
+
+ /* clamp int as well in case of NaN */
+ int i = clamp(float_to_int(f), 0, table_size - 1);
+ float t = f - (float)i;
+
+ float result = ramp[i];
+
+ if (interpolate && t > 0.0f) {
+ result = (1.0f - t) * result + t * ramp[i + 1];
+ }
+
+ return result;
}
CCL_NAMESPACE_END
-#endif /* __SVM_RAMP_UTIL_H__ */
+#endif /* __SVM_RAMP_UTIL_H__ */
diff --git a/intern/cycles/kernel/svm/svm_sepcomb_hsv.h b/intern/cycles/kernel/svm/svm_sepcomb_hsv.h
index 1096aed2d97..f501252062e 100644
--- a/intern/cycles/kernel/svm/svm_sepcomb_hsv.h
+++ b/intern/cycles/kernel/svm/svm_sepcomb_hsv.h
@@ -16,38 +16,50 @@
CCL_NAMESPACE_BEGIN
-ccl_device void svm_node_combine_hsv(KernelGlobals *kg, ShaderData *sd, float *stack, uint hue_in, uint saturation_in, uint value_in, int *offset)
+ccl_device void svm_node_combine_hsv(KernelGlobals *kg,
+ ShaderData *sd,
+ float *stack,
+ uint hue_in,
+ uint saturation_in,
+ uint value_in,
+ int *offset)
{
- uint4 node1 = read_node(kg, offset);
- uint color_out = node1.y;
+ uint4 node1 = read_node(kg, offset);
+ uint color_out = node1.y;
- float hue = stack_load_float(stack, hue_in);
- float saturation = stack_load_float(stack, saturation_in);
- float value = stack_load_float(stack, value_in);
+ float hue = stack_load_float(stack, hue_in);
+ float saturation = stack_load_float(stack, saturation_in);
+ float value = stack_load_float(stack, value_in);
- /* Combine, and convert back to RGB */
- float3 color = hsv_to_rgb(make_float3(hue, saturation, value));
+ /* Combine, and convert back to RGB */
+ float3 color = hsv_to_rgb(make_float3(hue, saturation, value));
- if(stack_valid(color_out))
- stack_store_float3(stack, color_out, color);
+ if (stack_valid(color_out))
+ stack_store_float3(stack, color_out, color);
}
-ccl_device void svm_node_separate_hsv(KernelGlobals *kg, ShaderData *sd, float *stack, uint color_in, uint hue_out, uint saturation_out, int *offset)
+ccl_device void svm_node_separate_hsv(KernelGlobals *kg,
+ ShaderData *sd,
+ float *stack,
+ uint color_in,
+ uint hue_out,
+ uint saturation_out,
+ int *offset)
{
- uint4 node1 = read_node(kg, offset);
- uint value_out = node1.y;
+ uint4 node1 = read_node(kg, offset);
+ uint value_out = node1.y;
- float3 color = stack_load_float3(stack, color_in);
+ float3 color = stack_load_float3(stack, color_in);
- /* Convert to HSV */
- color = rgb_to_hsv(color);
+ /* Convert to HSV */
+ color = rgb_to_hsv(color);
- if(stack_valid(hue_out))
- stack_store_float(stack, hue_out, color.x);
- if(stack_valid(saturation_out))
- stack_store_float(stack, saturation_out, color.y);
- if(stack_valid(value_out))
- stack_store_float(stack, value_out, color.z);
+ if (stack_valid(hue_out))
+ stack_store_float(stack, hue_out, color.x);
+ if (stack_valid(saturation_out))
+ stack_store_float(stack, saturation_out, color.y);
+ if (stack_valid(value_out))
+ stack_store_float(stack, value_out, color.z);
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/svm/svm_sepcomb_vector.h b/intern/cycles/kernel/svm/svm_sepcomb_vector.h
index 0d85c0d6f1d..cbf77f1e640 100644
--- a/intern/cycles/kernel/svm/svm_sepcomb_vector.h
+++ b/intern/cycles/kernel/svm/svm_sepcomb_vector.h
@@ -18,26 +18,28 @@ CCL_NAMESPACE_BEGIN
/* Vector combine / separate, used for the RGB and XYZ nodes */
-ccl_device void svm_node_combine_vector(ShaderData *sd, float *stack, uint in_offset, uint vector_index, uint out_offset)
+ccl_device void svm_node_combine_vector(
+ ShaderData *sd, float *stack, uint in_offset, uint vector_index, uint out_offset)
{
- float vector = stack_load_float(stack, in_offset);
+ float vector = stack_load_float(stack, in_offset);
- if(stack_valid(out_offset))
- stack_store_float(stack, out_offset+vector_index, vector);
+ if (stack_valid(out_offset))
+ stack_store_float(stack, out_offset + vector_index, vector);
}
-ccl_device void svm_node_separate_vector(ShaderData *sd, float *stack, uint ivector_offset, uint vector_index, uint out_offset)
+ccl_device void svm_node_separate_vector(
+ ShaderData *sd, float *stack, uint ivector_offset, uint vector_index, uint out_offset)
{
- float3 vector = stack_load_float3(stack, ivector_offset);
+ float3 vector = stack_load_float3(stack, ivector_offset);
- if(stack_valid(out_offset)) {
- if(vector_index == 0)
- stack_store_float(stack, out_offset, vector.x);
- else if(vector_index == 1)
- stack_store_float(stack, out_offset, vector.y);
- else
- stack_store_float(stack, out_offset, vector.z);
- }
+ if (stack_valid(out_offset)) {
+ if (vector_index == 0)
+ stack_store_float(stack, out_offset, vector.x);
+ else if (vector_index == 1)
+ stack_store_float(stack, out_offset, vector.y);
+ else
+ stack_store_float(stack, out_offset, vector.z);
+ }
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/svm/svm_sky.h b/intern/cycles/kernel/svm/svm_sky.h
index 092f6e045d6..50fe0c8232f 100644
--- a/intern/cycles/kernel/svm/svm_sky.h
+++ b/intern/cycles/kernel/svm/svm_sky.h
@@ -20,8 +20,8 @@ CCL_NAMESPACE_BEGIN
ccl_device float sky_angle_between(float thetav, float phiv, float theta, float phi)
{
- float cospsi = sinf(thetav)*sinf(theta)*cosf(phi - phiv) + cosf(thetav)*cosf(theta);
- return safe_acosf(cospsi);
+ float cospsi = sinf(thetav) * sinf(theta) * cosf(phi - phiv) + cosf(thetav) * cosf(theta);
+ return safe_acosf(cospsi);
}
/*
@@ -30,36 +30,43 @@ ccl_device float sky_angle_between(float thetav, float phiv, float theta, float
*/
ccl_device float sky_perez_function(float *lam, float theta, float gamma)
{
- float ctheta = cosf(theta);
- float cgamma = cosf(gamma);
+ float ctheta = cosf(theta);
+ float cgamma = cosf(gamma);
- return (1.0f + lam[0]*expf(lam[1]/ctheta)) * (1.0f + lam[2]*expf(lam[3]*gamma) + lam[4]*cgamma*cgamma);
+ return (1.0f + lam[0] * expf(lam[1] / ctheta)) *
+ (1.0f + lam[2] * expf(lam[3] * gamma) + lam[4] * cgamma * cgamma);
}
-ccl_device float3 sky_radiance_old(KernelGlobals *kg, float3 dir,
- float sunphi, float suntheta,
- float radiance_x, float radiance_y, float radiance_z,
- float *config_x, float *config_y, float *config_z)
+ccl_device float3 sky_radiance_old(KernelGlobals *kg,
+ float3 dir,
+ float sunphi,
+ float suntheta,
+ float radiance_x,
+ float radiance_y,
+ float radiance_z,
+ float *config_x,
+ float *config_y,
+ float *config_z)
{
- /* convert vector to spherical coordinates */
- float2 spherical = direction_to_spherical(dir);
- float theta = spherical.x;
- float phi = spherical.y;
+ /* convert vector to spherical coordinates */
+ float2 spherical = direction_to_spherical(dir);
+ float theta = spherical.x;
+ float phi = spherical.y;
- /* angle between sun direction and dir */
- float gamma = sky_angle_between(theta, phi, suntheta, sunphi);
+ /* angle between sun direction and dir */
+ float gamma = sky_angle_between(theta, phi, suntheta, sunphi);
- /* clamp theta to horizon */
- theta = min(theta, M_PI_2_F - 0.001f);
+ /* clamp theta to horizon */
+ theta = min(theta, M_PI_2_F - 0.001f);
- /* compute xyY color space values */
- float x = radiance_y * sky_perez_function(config_y, theta, gamma);
- float y = radiance_z * sky_perez_function(config_z, theta, gamma);
- float Y = radiance_x * sky_perez_function(config_x, theta, gamma);
+ /* compute xyY color space values */
+ float x = radiance_y * sky_perez_function(config_y, theta, gamma);
+ float y = radiance_z * sky_perez_function(config_z, theta, gamma);
+ float Y = radiance_x * sky_perez_function(config_x, theta, gamma);
- /* convert to RGB */
- float3 xyz = xyY_to_xyz(x, y, Y);
- return xyz_to_rgb(kg, xyz);
+ /* convert to RGB */
+ float3 xyz = xyY_to_xyz(x, y, Y);
+ return xyz_to_rgb(kg, xyz);
}
/*
@@ -68,118 +75,142 @@ ccl_device float3 sky_radiance_old(KernelGlobals *kg, float3 dir,
*/
ccl_device float sky_radiance_internal(float *configuration, float theta, float gamma)
{
- float ctheta = cosf(theta);
- float cgamma = cosf(gamma);
-
- float expM = expf(configuration[4] * gamma);
- float rayM = cgamma * cgamma;
- float mieM = (1.0f + rayM) / powf((1.0f + configuration[8]*configuration[8] - 2.0f*configuration[8]*cgamma), 1.5f);
- float zenith = sqrtf(ctheta);
-
- return (1.0f + configuration[0] * expf(configuration[1] / (ctheta + 0.01f))) *
- (configuration[2] + configuration[3] * expM + configuration[5] * rayM + configuration[6] * mieM + configuration[7] * zenith);
+ float ctheta = cosf(theta);
+ float cgamma = cosf(gamma);
+
+ float expM = expf(configuration[4] * gamma);
+ float rayM = cgamma * cgamma;
+ float mieM = (1.0f + rayM) / powf((1.0f + configuration[8] * configuration[8] -
+ 2.0f * configuration[8] * cgamma),
+ 1.5f);
+ float zenith = sqrtf(ctheta);
+
+ return (1.0f + configuration[0] * expf(configuration[1] / (ctheta + 0.01f))) *
+ (configuration[2] + configuration[3] * expM + configuration[5] * rayM +
+ configuration[6] * mieM + configuration[7] * zenith);
}
-ccl_device float3 sky_radiance_new(KernelGlobals *kg, float3 dir,
- float sunphi, float suntheta,
- float radiance_x, float radiance_y, float radiance_z,
- float *config_x, float *config_y, float *config_z)
+ccl_device float3 sky_radiance_new(KernelGlobals *kg,
+ float3 dir,
+ float sunphi,
+ float suntheta,
+ float radiance_x,
+ float radiance_y,
+ float radiance_z,
+ float *config_x,
+ float *config_y,
+ float *config_z)
{
- /* convert vector to spherical coordinates */
- float2 spherical = direction_to_spherical(dir);
- float theta = spherical.x;
- float phi = spherical.y;
+ /* convert vector to spherical coordinates */
+ float2 spherical = direction_to_spherical(dir);
+ float theta = spherical.x;
+ float phi = spherical.y;
- /* angle between sun direction and dir */
- float gamma = sky_angle_between(theta, phi, suntheta, sunphi);
+ /* angle between sun direction and dir */
+ float gamma = sky_angle_between(theta, phi, suntheta, sunphi);
- /* clamp theta to horizon */
- theta = min(theta, M_PI_2_F - 0.001f);
+ /* clamp theta to horizon */
+ theta = min(theta, M_PI_2_F - 0.001f);
- /* compute xyz color space values */
- float x = sky_radiance_internal(config_x, theta, gamma) * radiance_x;
- float y = sky_radiance_internal(config_y, theta, gamma) * radiance_y;
- float z = sky_radiance_internal(config_z, theta, gamma) * radiance_z;
+ /* compute xyz color space values */
+ float x = sky_radiance_internal(config_x, theta, gamma) * radiance_x;
+ float y = sky_radiance_internal(config_y, theta, gamma) * radiance_y;
+ float z = sky_radiance_internal(config_z, theta, gamma) * radiance_z;
- /* convert to RGB and adjust strength */
- return xyz_to_rgb(kg, make_float3(x, y, z)) * (M_2PI_F/683);
+ /* convert to RGB and adjust strength */
+ return xyz_to_rgb(kg, make_float3(x, y, z)) * (M_2PI_F / 683);
}
-ccl_device void svm_node_tex_sky(KernelGlobals *kg, ShaderData *sd, float *stack, uint4 node, int *offset)
+ccl_device void svm_node_tex_sky(
+ KernelGlobals *kg, ShaderData *sd, float *stack, uint4 node, int *offset)
{
- /* Define variables */
- float sunphi, suntheta, radiance_x, radiance_y, radiance_z;
- float config_x[9], config_y[9], config_z[9];
-
- /* Load data */
- uint dir_offset = node.y;
- uint out_offset = node.z;
- int sky_model = node.w;
-
- float4 data = read_node_float(kg, offset);
- sunphi = data.x;
- suntheta = data.y;
- radiance_x = data.z;
- radiance_y = data.w;
-
- data = read_node_float(kg, offset);
- radiance_z = data.x;
- config_x[0] = data.y;
- config_x[1] = data.z;
- config_x[2] = data.w;
-
- data = read_node_float(kg, offset);
- config_x[3] = data.x;
- config_x[4] = data.y;
- config_x[5] = data.z;
- config_x[6] = data.w;
-
- data = read_node_float(kg, offset);
- config_x[7] = data.x;
- config_x[8] = data.y;
- config_y[0] = data.z;
- config_y[1] = data.w;
-
- data = read_node_float(kg, offset);
- config_y[2] = data.x;
- config_y[3] = data.y;
- config_y[4] = data.z;
- config_y[5] = data.w;
-
- data = read_node_float(kg, offset);
- config_y[6] = data.x;
- config_y[7] = data.y;
- config_y[8] = data.z;
- config_z[0] = data.w;
-
- data = read_node_float(kg, offset);
- config_z[1] = data.x;
- config_z[2] = data.y;
- config_z[3] = data.z;
- config_z[4] = data.w;
-
- data = read_node_float(kg, offset);
- config_z[5] = data.x;
- config_z[6] = data.y;
- config_z[7] = data.z;
- config_z[8] = data.w;
-
- float3 dir = stack_load_float3(stack, dir_offset);
- float3 f;
-
- /* Compute Sky */
- if(sky_model == 0) {
- f = sky_radiance_old(kg, dir, sunphi, suntheta,
- radiance_x, radiance_y, radiance_z,
- config_x, config_y, config_z);
- }
- else {
- f = sky_radiance_new(kg, dir, sunphi, suntheta,
- radiance_x, radiance_y, radiance_z,
- config_x, config_y, config_z);
- }
-
- stack_store_float3(stack, out_offset, f);
+ /* Define variables */
+ float sunphi, suntheta, radiance_x, radiance_y, radiance_z;
+ float config_x[9], config_y[9], config_z[9];
+
+ /* Load data */
+ uint dir_offset = node.y;
+ uint out_offset = node.z;
+ int sky_model = node.w;
+
+ float4 data = read_node_float(kg, offset);
+ sunphi = data.x;
+ suntheta = data.y;
+ radiance_x = data.z;
+ radiance_y = data.w;
+
+ data = read_node_float(kg, offset);
+ radiance_z = data.x;
+ config_x[0] = data.y;
+ config_x[1] = data.z;
+ config_x[2] = data.w;
+
+ data = read_node_float(kg, offset);
+ config_x[3] = data.x;
+ config_x[4] = data.y;
+ config_x[5] = data.z;
+ config_x[6] = data.w;
+
+ data = read_node_float(kg, offset);
+ config_x[7] = data.x;
+ config_x[8] = data.y;
+ config_y[0] = data.z;
+ config_y[1] = data.w;
+
+ data = read_node_float(kg, offset);
+ config_y[2] = data.x;
+ config_y[3] = data.y;
+ config_y[4] = data.z;
+ config_y[5] = data.w;
+
+ data = read_node_float(kg, offset);
+ config_y[6] = data.x;
+ config_y[7] = data.y;
+ config_y[8] = data.z;
+ config_z[0] = data.w;
+
+ data = read_node_float(kg, offset);
+ config_z[1] = data.x;
+ config_z[2] = data.y;
+ config_z[3] = data.z;
+ config_z[4] = data.w;
+
+ data = read_node_float(kg, offset);
+ config_z[5] = data.x;
+ config_z[6] = data.y;
+ config_z[7] = data.z;
+ config_z[8] = data.w;
+
+ float3 dir = stack_load_float3(stack, dir_offset);
+ float3 f;
+
+ /* Compute Sky */
+ if (sky_model == 0) {
+ f = sky_radiance_old(kg,
+ dir,
+ sunphi,
+ suntheta,
+ radiance_x,
+ radiance_y,
+ radiance_z,
+ config_x,
+ config_y,
+ config_z);
+ }
+ else {
+ f = sky_radiance_new(kg,
+ dir,
+ sunphi,
+ suntheta,
+ radiance_x,
+ radiance_y,
+ radiance_z,
+ config_x,
+ config_y,
+ config_z);
+ }
+
+ stack_store_float3(stack, out_offset, f);
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/svm/svm_tex_coord.h b/intern/cycles/kernel/svm/svm_tex_coord.h
index fe61292d0b0..1fb3e20f9e0 100644
--- a/intern/cycles/kernel/svm/svm_tex_coord.h
+++ b/intern/cycles/kernel/svm/svm_tex_coord.h
@@ -18,390 +18,381 @@ CCL_NAMESPACE_BEGIN
/* Texture Coordinate Node */
-ccl_device void svm_node_tex_coord(KernelGlobals *kg,
- ShaderData *sd,
- int path_flag,
- float *stack,
- uint4 node,
- int *offset)
+ccl_device void svm_node_tex_coord(
+ KernelGlobals *kg, ShaderData *sd, int path_flag, float *stack, uint4 node, int *offset)
{
- float3 data;
- uint type = node.y;
- uint out_offset = node.z;
-
- switch(type) {
- case NODE_TEXCO_OBJECT: {
- data = sd->P;
- if(node.w == 0) {
- if(sd->object != OBJECT_NONE) {
- object_inverse_position_transform(kg, sd, &data);
- }
- }
- else {
- Transform tfm;
- tfm.x = read_node_float(kg, offset);
- tfm.y = read_node_float(kg, offset);
- tfm.z = read_node_float(kg, offset);
- data = transform_point(&tfm, data);
- }
- break;
- }
- case NODE_TEXCO_NORMAL: {
- data = sd->N;
- object_inverse_normal_transform(kg, sd, &data);
- break;
- }
- case NODE_TEXCO_CAMERA: {
- Transform tfm = kernel_data.cam.worldtocamera;
-
- if(sd->object != OBJECT_NONE)
- data = transform_point(&tfm, sd->P);
- else
- data = transform_point(&tfm, sd->P + camera_position(kg));
- break;
- }
- case NODE_TEXCO_WINDOW: {
- if((path_flag & PATH_RAY_CAMERA) && sd->object == OBJECT_NONE && kernel_data.cam.type == CAMERA_ORTHOGRAPHIC)
- data = camera_world_to_ndc(kg, sd, sd->ray_P);
- else
- data = camera_world_to_ndc(kg, sd, sd->P);
- data.z = 0.0f;
- break;
- }
- case NODE_TEXCO_REFLECTION: {
- if(sd->object != OBJECT_NONE)
- data = 2.0f*dot(sd->N, sd->I)*sd->N - sd->I;
- else
- data = sd->I;
- break;
- }
- case NODE_TEXCO_DUPLI_GENERATED: {
- data = object_dupli_generated(kg, sd->object);
- break;
- }
- case NODE_TEXCO_DUPLI_UV: {
- data = object_dupli_uv(kg, sd->object);
- break;
- }
- case NODE_TEXCO_VOLUME_GENERATED: {
- data = sd->P;
+ float3 data;
+ uint type = node.y;
+ uint out_offset = node.z;
+
+ switch (type) {
+ case NODE_TEXCO_OBJECT: {
+ data = sd->P;
+ if (node.w == 0) {
+ if (sd->object != OBJECT_NONE) {
+ object_inverse_position_transform(kg, sd, &data);
+ }
+ }
+ else {
+ Transform tfm;
+ tfm.x = read_node_float(kg, offset);
+ tfm.y = read_node_float(kg, offset);
+ tfm.z = read_node_float(kg, offset);
+ data = transform_point(&tfm, data);
+ }
+ break;
+ }
+ case NODE_TEXCO_NORMAL: {
+ data = sd->N;
+ object_inverse_normal_transform(kg, sd, &data);
+ break;
+ }
+ case NODE_TEXCO_CAMERA: {
+ Transform tfm = kernel_data.cam.worldtocamera;
+
+ if (sd->object != OBJECT_NONE)
+ data = transform_point(&tfm, sd->P);
+ else
+ data = transform_point(&tfm, sd->P + camera_position(kg));
+ break;
+ }
+ case NODE_TEXCO_WINDOW: {
+ if ((path_flag & PATH_RAY_CAMERA) && sd->object == OBJECT_NONE &&
+ kernel_data.cam.type == CAMERA_ORTHOGRAPHIC)
+ data = camera_world_to_ndc(kg, sd, sd->ray_P);
+ else
+ data = camera_world_to_ndc(kg, sd, sd->P);
+ data.z = 0.0f;
+ break;
+ }
+ case NODE_TEXCO_REFLECTION: {
+ if (sd->object != OBJECT_NONE)
+ data = 2.0f * dot(sd->N, sd->I) * sd->N - sd->I;
+ else
+ data = sd->I;
+ break;
+ }
+ case NODE_TEXCO_DUPLI_GENERATED: {
+ data = object_dupli_generated(kg, sd->object);
+ break;
+ }
+ case NODE_TEXCO_DUPLI_UV: {
+ data = object_dupli_uv(kg, sd->object);
+ break;
+ }
+ case NODE_TEXCO_VOLUME_GENERATED: {
+ data = sd->P;
#ifdef __VOLUME__
- if(sd->object != OBJECT_NONE)
- data = volume_normalized_position(kg, sd, data);
+ if (sd->object != OBJECT_NONE)
+ data = volume_normalized_position(kg, sd, data);
#endif
- break;
- }
- }
+ break;
+ }
+ }
- stack_store_float3(stack, out_offset, data);
+ stack_store_float3(stack, out_offset, data);
}
-ccl_device void svm_node_tex_coord_bump_dx(KernelGlobals *kg,
- ShaderData *sd,
- int path_flag,
- float *stack,
- uint4 node,
- int *offset)
+ccl_device void svm_node_tex_coord_bump_dx(
+ KernelGlobals *kg, ShaderData *sd, int path_flag, float *stack, uint4 node, int *offset)
{
#ifdef __RAY_DIFFERENTIALS__
- float3 data;
- uint type = node.y;
- uint out_offset = node.z;
-
- switch(type) {
- case NODE_TEXCO_OBJECT: {
- data = sd->P + sd->dP.dx;
- if(node.w == 0) {
- if(sd->object != OBJECT_NONE) {
- object_inverse_position_transform(kg, sd, &data);
- }
- }
- else {
- Transform tfm;
- tfm.x = read_node_float(kg, offset);
- tfm.y = read_node_float(kg, offset);
- tfm.z = read_node_float(kg, offset);
- data = transform_point(&tfm, data);
- }
- break;
- }
- case NODE_TEXCO_NORMAL: {
- data = sd->N;
- object_inverse_normal_transform(kg, sd, &data);
- break;
- }
- case NODE_TEXCO_CAMERA: {
- Transform tfm = kernel_data.cam.worldtocamera;
-
- if(sd->object != OBJECT_NONE)
- data = transform_point(&tfm, sd->P + sd->dP.dx);
- else
- data = transform_point(&tfm, sd->P + sd->dP.dx + camera_position(kg));
- break;
- }
- case NODE_TEXCO_WINDOW: {
- if((path_flag & PATH_RAY_CAMERA) && sd->object == OBJECT_NONE && kernel_data.cam.type == CAMERA_ORTHOGRAPHIC)
- data = camera_world_to_ndc(kg, sd, sd->ray_P + sd->ray_dP.dx);
- else
- data = camera_world_to_ndc(kg, sd, sd->P + sd->dP.dx);
- data.z = 0.0f;
- break;
- }
- case NODE_TEXCO_REFLECTION: {
- if(sd->object != OBJECT_NONE)
- data = 2.0f*dot(sd->N, sd->I)*sd->N - sd->I;
- else
- data = sd->I;
- break;
- }
- case NODE_TEXCO_DUPLI_GENERATED: {
- data = object_dupli_generated(kg, sd->object);
- break;
- }
- case NODE_TEXCO_DUPLI_UV: {
- data = object_dupli_uv(kg, sd->object);
- break;
- }
- case NODE_TEXCO_VOLUME_GENERATED: {
- data = sd->P + sd->dP.dx;
-
-#ifdef __VOLUME__
- if(sd->object != OBJECT_NONE)
- data = volume_normalized_position(kg, sd, data);
-#endif
- break;
- }
- }
-
- stack_store_float3(stack, out_offset, data);
+ float3 data;
+ uint type = node.y;
+ uint out_offset = node.z;
+
+ switch (type) {
+ case NODE_TEXCO_OBJECT: {
+ data = sd->P + sd->dP.dx;
+ if (node.w == 0) {
+ if (sd->object != OBJECT_NONE) {
+ object_inverse_position_transform(kg, sd, &data);
+ }
+ }
+ else {
+ Transform tfm;
+ tfm.x = read_node_float(kg, offset);
+ tfm.y = read_node_float(kg, offset);
+ tfm.z = read_node_float(kg, offset);
+ data = transform_point(&tfm, data);
+ }
+ break;
+ }
+ case NODE_TEXCO_NORMAL: {
+ data = sd->N;
+ object_inverse_normal_transform(kg, sd, &data);
+ break;
+ }
+ case NODE_TEXCO_CAMERA: {
+ Transform tfm = kernel_data.cam.worldtocamera;
+
+ if (sd->object != OBJECT_NONE)
+ data = transform_point(&tfm, sd->P + sd->dP.dx);
+ else
+ data = transform_point(&tfm, sd->P + sd->dP.dx + camera_position(kg));
+ break;
+ }
+ case NODE_TEXCO_WINDOW: {
+ if ((path_flag & PATH_RAY_CAMERA) && sd->object == OBJECT_NONE &&
+ kernel_data.cam.type == CAMERA_ORTHOGRAPHIC)
+ data = camera_world_to_ndc(kg, sd, sd->ray_P + sd->ray_dP.dx);
+ else
+ data = camera_world_to_ndc(kg, sd, sd->P + sd->dP.dx);
+ data.z = 0.0f;
+ break;
+ }
+ case NODE_TEXCO_REFLECTION: {
+ if (sd->object != OBJECT_NONE)
+ data = 2.0f * dot(sd->N, sd->I) * sd->N - sd->I;
+ else
+ data = sd->I;
+ break;
+ }
+ case NODE_TEXCO_DUPLI_GENERATED: {
+ data = object_dupli_generated(kg, sd->object);
+ break;
+ }
+ case NODE_TEXCO_DUPLI_UV: {
+ data = object_dupli_uv(kg, sd->object);
+ break;
+ }
+ case NODE_TEXCO_VOLUME_GENERATED: {
+ data = sd->P + sd->dP.dx;
+
+# ifdef __VOLUME__
+ if (sd->object != OBJECT_NONE)
+ data = volume_normalized_position(kg, sd, data);
+# endif
+ break;
+ }
+ }
+
+ stack_store_float3(stack, out_offset, data);
#else
- svm_node_tex_coord(kg, sd, path_flag, stack, node, offset);
+ svm_node_tex_coord(kg, sd, path_flag, stack, node, offset);
#endif
}
-ccl_device void svm_node_tex_coord_bump_dy(KernelGlobals *kg,
- ShaderData *sd,
- int path_flag,
- float *stack,
- uint4 node,
- int *offset)
+ccl_device void svm_node_tex_coord_bump_dy(
+ KernelGlobals *kg, ShaderData *sd, int path_flag, float *stack, uint4 node, int *offset)
{
#ifdef __RAY_DIFFERENTIALS__
- float3 data;
- uint type = node.y;
- uint out_offset = node.z;
-
- switch(type) {
- case NODE_TEXCO_OBJECT: {
- data = sd->P + sd->dP.dy;
- if(node.w == 0) {
- if(sd->object != OBJECT_NONE) {
- object_inverse_position_transform(kg, sd, &data);
- }
- }
- else {
- Transform tfm;
- tfm.x = read_node_float(kg, offset);
- tfm.y = read_node_float(kg, offset);
- tfm.z = read_node_float(kg, offset);
- data = transform_point(&tfm, data);
- }
- break;
- }
- case NODE_TEXCO_NORMAL: {
- data = sd->N;
- object_inverse_normal_transform(kg, sd, &data);
- break;
- }
- case NODE_TEXCO_CAMERA: {
- Transform tfm = kernel_data.cam.worldtocamera;
-
- if(sd->object != OBJECT_NONE)
- data = transform_point(&tfm, sd->P + sd->dP.dy);
- else
- data = transform_point(&tfm, sd->P + sd->dP.dy + camera_position(kg));
- break;
- }
- case NODE_TEXCO_WINDOW: {
- if((path_flag & PATH_RAY_CAMERA) && sd->object == OBJECT_NONE && kernel_data.cam.type == CAMERA_ORTHOGRAPHIC)
- data = camera_world_to_ndc(kg, sd, sd->ray_P + sd->ray_dP.dy);
- else
- data = camera_world_to_ndc(kg, sd, sd->P + sd->dP.dy);
- data.z = 0.0f;
- break;
- }
- case NODE_TEXCO_REFLECTION: {
- if(sd->object != OBJECT_NONE)
- data = 2.0f*dot(sd->N, sd->I)*sd->N - sd->I;
- else
- data = sd->I;
- break;
- }
- case NODE_TEXCO_DUPLI_GENERATED: {
- data = object_dupli_generated(kg, sd->object);
- break;
- }
- case NODE_TEXCO_DUPLI_UV: {
- data = object_dupli_uv(kg, sd->object);
- break;
- }
- case NODE_TEXCO_VOLUME_GENERATED: {
- data = sd->P + sd->dP.dy;
-
-#ifdef __VOLUME__
- if(sd->object != OBJECT_NONE)
- data = volume_normalized_position(kg, sd, data);
-#endif
- break;
- }
- }
-
- stack_store_float3(stack, out_offset, data);
+ float3 data;
+ uint type = node.y;
+ uint out_offset = node.z;
+
+ switch (type) {
+ case NODE_TEXCO_OBJECT: {
+ data = sd->P + sd->dP.dy;
+ if (node.w == 0) {
+ if (sd->object != OBJECT_NONE) {
+ object_inverse_position_transform(kg, sd, &data);
+ }
+ }
+ else {
+ Transform tfm;
+ tfm.x = read_node_float(kg, offset);
+ tfm.y = read_node_float(kg, offset);
+ tfm.z = read_node_float(kg, offset);
+ data = transform_point(&tfm, data);
+ }
+ break;
+ }
+ case NODE_TEXCO_NORMAL: {
+ data = sd->N;
+ object_inverse_normal_transform(kg, sd, &data);
+ break;
+ }
+ case NODE_TEXCO_CAMERA: {
+ Transform tfm = kernel_data.cam.worldtocamera;
+
+ if (sd->object != OBJECT_NONE)
+ data = transform_point(&tfm, sd->P + sd->dP.dy);
+ else
+ data = transform_point(&tfm, sd->P + sd->dP.dy + camera_position(kg));
+ break;
+ }
+ case NODE_TEXCO_WINDOW: {
+ if ((path_flag & PATH_RAY_CAMERA) && sd->object == OBJECT_NONE &&
+ kernel_data.cam.type == CAMERA_ORTHOGRAPHIC)
+ data = camera_world_to_ndc(kg, sd, sd->ray_P + sd->ray_dP.dy);
+ else
+ data = camera_world_to_ndc(kg, sd, sd->P + sd->dP.dy);
+ data.z = 0.0f;
+ break;
+ }
+ case NODE_TEXCO_REFLECTION: {
+ if (sd->object != OBJECT_NONE)
+ data = 2.0f * dot(sd->N, sd->I) * sd->N - sd->I;
+ else
+ data = sd->I;
+ break;
+ }
+ case NODE_TEXCO_DUPLI_GENERATED: {
+ data = object_dupli_generated(kg, sd->object);
+ break;
+ }
+ case NODE_TEXCO_DUPLI_UV: {
+ data = object_dupli_uv(kg, sd->object);
+ break;
+ }
+ case NODE_TEXCO_VOLUME_GENERATED: {
+ data = sd->P + sd->dP.dy;
+
+# ifdef __VOLUME__
+ if (sd->object != OBJECT_NONE)
+ data = volume_normalized_position(kg, sd, data);
+# endif
+ break;
+ }
+ }
+
+ stack_store_float3(stack, out_offset, data);
#else
- svm_node_tex_coord(kg, sd, path_flag, stack, node, offset);
+ svm_node_tex_coord(kg, sd, path_flag, stack, node, offset);
#endif
}
ccl_device void svm_node_normal_map(KernelGlobals *kg, ShaderData *sd, float *stack, uint4 node)
{
- uint color_offset, strength_offset, normal_offset, space;
- decode_node_uchar4(node.y, &color_offset, &strength_offset, &normal_offset, &space);
-
- float3 color = stack_load_float3(stack, color_offset);
- color = 2.0f*make_float3(color.x - 0.5f, color.y - 0.5f, color.z - 0.5f);
-
- bool is_backfacing = (sd->flag & SD_BACKFACING) != 0;
- float3 N;
-
- if(space == NODE_NORMAL_MAP_TANGENT) {
- /* tangent space */
- if(sd->object == OBJECT_NONE) {
- stack_store_float3(stack, normal_offset, make_float3(0.0f, 0.0f, 0.0f));
- return;
- }
-
- /* first try to get tangent attribute */
- const AttributeDescriptor attr = find_attribute(kg, sd, node.z);
- const AttributeDescriptor attr_sign = find_attribute(kg, sd, node.w);
- const AttributeDescriptor attr_normal = find_attribute(kg, sd, ATTR_STD_VERTEX_NORMAL);
-
- if(attr.offset == ATTR_STD_NOT_FOUND || attr_sign.offset == ATTR_STD_NOT_FOUND || attr_normal.offset == ATTR_STD_NOT_FOUND) {
- stack_store_float3(stack, normal_offset, make_float3(0.0f, 0.0f, 0.0f));
- return;
- }
-
- /* get _unnormalized_ interpolated normal and tangent */
- float3 tangent = primitive_surface_attribute_float3(kg, sd, attr, NULL, NULL);
- float sign = primitive_surface_attribute_float(kg, sd, attr_sign, NULL, NULL);
- float3 normal;
-
- if(sd->shader & SHADER_SMOOTH_NORMAL) {
- normal = primitive_surface_attribute_float3(kg, sd, attr_normal, NULL, NULL);
- }
- else {
- normal = sd->Ng;
-
- /* the normal is already inverted, which is too soon for the math here */
- if(is_backfacing) {
- normal = -normal;
- }
-
- object_inverse_normal_transform(kg, sd, &normal);
- }
-
- /* apply normal map */
- float3 B = sign * cross(normal, tangent);
- N = safe_normalize(color.x * tangent + color.y * B + color.z * normal);
-
- /* transform to world space */
- object_normal_transform(kg, sd, &N);
- }
- else {
- /* strange blender convention */
- if(space == NODE_NORMAL_MAP_BLENDER_OBJECT || space == NODE_NORMAL_MAP_BLENDER_WORLD) {
- color.y = -color.y;
- color.z = -color.z;
- }
-
- /* object, world space */
- N = color;
-
- if(space == NODE_NORMAL_MAP_OBJECT || space == NODE_NORMAL_MAP_BLENDER_OBJECT)
- object_normal_transform(kg, sd, &N);
- else
- N = safe_normalize(N);
- }
-
- /* invert normal for backfacing polygons */
- if(is_backfacing) {
- N = -N;
- }
-
- float strength = stack_load_float(stack, strength_offset);
-
- if(strength != 1.0f) {
- strength = max(strength, 0.0f);
- N = safe_normalize(sd->N + (N - sd->N)*strength);
- }
-
- N = ensure_valid_reflection(sd->Ng, sd->I, N);
-
- if(is_zero(N)) {
- N = sd->N;
- }
-
- stack_store_float3(stack, normal_offset, N);
+ uint color_offset, strength_offset, normal_offset, space;
+ decode_node_uchar4(node.y, &color_offset, &strength_offset, &normal_offset, &space);
+
+ float3 color = stack_load_float3(stack, color_offset);
+ color = 2.0f * make_float3(color.x - 0.5f, color.y - 0.5f, color.z - 0.5f);
+
+ bool is_backfacing = (sd->flag & SD_BACKFACING) != 0;
+ float3 N;
+
+ if (space == NODE_NORMAL_MAP_TANGENT) {
+ /* tangent space */
+ if (sd->object == OBJECT_NONE) {
+ stack_store_float3(stack, normal_offset, make_float3(0.0f, 0.0f, 0.0f));
+ return;
+ }
+
+ /* first try to get tangent attribute */
+ const AttributeDescriptor attr = find_attribute(kg, sd, node.z);
+ const AttributeDescriptor attr_sign = find_attribute(kg, sd, node.w);
+ const AttributeDescriptor attr_normal = find_attribute(kg, sd, ATTR_STD_VERTEX_NORMAL);
+
+ if (attr.offset == ATTR_STD_NOT_FOUND || attr_sign.offset == ATTR_STD_NOT_FOUND ||
+ attr_normal.offset == ATTR_STD_NOT_FOUND) {
+ stack_store_float3(stack, normal_offset, make_float3(0.0f, 0.0f, 0.0f));
+ return;
+ }
+
+ /* get _unnormalized_ interpolated normal and tangent */
+ float3 tangent = primitive_surface_attribute_float3(kg, sd, attr, NULL, NULL);
+ float sign = primitive_surface_attribute_float(kg, sd, attr_sign, NULL, NULL);
+ float3 normal;
+
+ if (sd->shader & SHADER_SMOOTH_NORMAL) {
+ normal = primitive_surface_attribute_float3(kg, sd, attr_normal, NULL, NULL);
+ }
+ else {
+ normal = sd->Ng;
+
+ /* the normal is already inverted, which is too soon for the math here */
+ if (is_backfacing) {
+ normal = -normal;
+ }
+
+ object_inverse_normal_transform(kg, sd, &normal);
+ }
+
+ /* apply normal map */
+ float3 B = sign * cross(normal, tangent);
+ N = safe_normalize(color.x * tangent + color.y * B + color.z * normal);
+
+ /* transform to world space */
+ object_normal_transform(kg, sd, &N);
+ }
+ else {
+ /* strange blender convention */
+ if (space == NODE_NORMAL_MAP_BLENDER_OBJECT || space == NODE_NORMAL_MAP_BLENDER_WORLD) {
+ color.y = -color.y;
+ color.z = -color.z;
+ }
+
+ /* object, world space */
+ N = color;
+
+ if (space == NODE_NORMAL_MAP_OBJECT || space == NODE_NORMAL_MAP_BLENDER_OBJECT)
+ object_normal_transform(kg, sd, &N);
+ else
+ N = safe_normalize(N);
+ }
+
+ /* invert normal for backfacing polygons */
+ if (is_backfacing) {
+ N = -N;
+ }
+
+ float strength = stack_load_float(stack, strength_offset);
+
+ if (strength != 1.0f) {
+ strength = max(strength, 0.0f);
+ N = safe_normalize(sd->N + (N - sd->N) * strength);
+ }
+
+ N = ensure_valid_reflection(sd->Ng, sd->I, N);
+
+ if (is_zero(N)) {
+ N = sd->N;
+ }
+
+ stack_store_float3(stack, normal_offset, N);
}
ccl_device void svm_node_tangent(KernelGlobals *kg, ShaderData *sd, float *stack, uint4 node)
{
- uint tangent_offset, direction_type, axis;
- decode_node_uchar4(node.y, &tangent_offset, &direction_type, &axis, NULL);
-
- float3 tangent;
- float3 attribute_value;
- const AttributeDescriptor desc = find_attribute(kg, sd, node.z);
- if (desc.offset != ATTR_STD_NOT_FOUND) {
- if(desc.type == NODE_ATTR_FLOAT2) {
- float2 value = primitive_surface_attribute_float2(kg, sd, desc, NULL, NULL);
- attribute_value.x = value.x;
- attribute_value.y = value.y;
- attribute_value.z = 0.0f;
- }
- else {
- attribute_value = primitive_surface_attribute_float3(kg, sd, desc, NULL, NULL);
- }
- }
-
-
- if(direction_type == NODE_TANGENT_UVMAP) {
- /* UV map */
- if(desc.offset == ATTR_STD_NOT_FOUND)
- tangent = make_float3(0.0f, 0.0f, 0.0f);
- else
- tangent = attribute_value;
- }
- else {
- /* radial */
- float3 generated;
-
- if(desc.offset == ATTR_STD_NOT_FOUND)
- generated = sd->P;
- else
- generated = attribute_value;
-
- if(axis == NODE_TANGENT_AXIS_X)
- tangent = make_float3(0.0f, -(generated.z - 0.5f), (generated.y - 0.5f));
- else if(axis == NODE_TANGENT_AXIS_Y)
- tangent = make_float3(-(generated.z - 0.5f), 0.0f, (generated.x - 0.5f));
- else
- tangent = make_float3(-(generated.y - 0.5f), (generated.x - 0.5f), 0.0f);
- }
-
- object_normal_transform(kg, sd, &tangent);
- tangent = cross(sd->N, normalize(cross(tangent, sd->N)));
- stack_store_float3(stack, tangent_offset, tangent);
+ uint tangent_offset, direction_type, axis;
+ decode_node_uchar4(node.y, &tangent_offset, &direction_type, &axis, NULL);
+
+ float3 tangent;
+ float3 attribute_value;
+ const AttributeDescriptor desc = find_attribute(kg, sd, node.z);
+ if (desc.offset != ATTR_STD_NOT_FOUND) {
+ if (desc.type == NODE_ATTR_FLOAT2) {
+ float2 value = primitive_surface_attribute_float2(kg, sd, desc, NULL, NULL);
+ attribute_value.x = value.x;
+ attribute_value.y = value.y;
+ attribute_value.z = 0.0f;
+ }
+ else {
+ attribute_value = primitive_surface_attribute_float3(kg, sd, desc, NULL, NULL);
+ }
+ }
+
+ if (direction_type == NODE_TANGENT_UVMAP) {
+ /* UV map */
+ if (desc.offset == ATTR_STD_NOT_FOUND)
+ tangent = make_float3(0.0f, 0.0f, 0.0f);
+ else
+ tangent = attribute_value;
+ }
+ else {
+ /* radial */
+ float3 generated;
+
+ if (desc.offset == ATTR_STD_NOT_FOUND)
+ generated = sd->P;
+ else
+ generated = attribute_value;
+
+ if (axis == NODE_TANGENT_AXIS_X)
+ tangent = make_float3(0.0f, -(generated.z - 0.5f), (generated.y - 0.5f));
+ else if (axis == NODE_TANGENT_AXIS_Y)
+ tangent = make_float3(-(generated.z - 0.5f), 0.0f, (generated.x - 0.5f));
+ else
+ tangent = make_float3(-(generated.y - 0.5f), (generated.x - 0.5f), 0.0f);
+ }
+
+ object_normal_transform(kg, sd, &tangent);
+ tangent = cross(sd->N, normalize(cross(tangent, sd->N)));
+ stack_store_float3(stack, tangent_offset, tangent);
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/svm/svm_texture.h b/intern/cycles/kernel/svm/svm_texture.h
index 57729817bdc..290aa85c831 100644
--- a/intern/cycles/kernel/svm/svm_texture.h
+++ b/intern/cycles/kernel/svm/svm_texture.h
@@ -20,44 +20,44 @@ CCL_NAMESPACE_BEGIN
ccl_device_noinline float noise_turbulence(float3 p, float octaves, int hard)
{
- float fscale = 1.0f;
- float amp = 1.0f;
- float sum = 0.0f;
- int i, n;
+ float fscale = 1.0f;
+ float amp = 1.0f;
+ float sum = 0.0f;
+ int i, n;
- octaves = clamp(octaves, 0.0f, 16.0f);
- n = float_to_int(octaves);
+ octaves = clamp(octaves, 0.0f, 16.0f);
+ n = float_to_int(octaves);
- for(i = 0; i <= n; i++) {
- float t = noise(fscale*p);
+ for (i = 0; i <= n; i++) {
+ float t = noise(fscale * p);
- if(hard)
- t = fabsf(2.0f*t - 1.0f);
+ if (hard)
+ t = fabsf(2.0f * t - 1.0f);
- sum += t*amp;
- amp *= 0.5f;
- fscale *= 2.0f;
- }
+ sum += t * amp;
+ amp *= 0.5f;
+ fscale *= 2.0f;
+ }
- float rmd = octaves - floorf(octaves);
+ float rmd = octaves - floorf(octaves);
- if(rmd != 0.0f) {
- float t = noise(fscale*p);
+ if (rmd != 0.0f) {
+ float t = noise(fscale * p);
- if(hard)
- t = fabsf(2.0f*t - 1.0f);
+ if (hard)
+ t = fabsf(2.0f * t - 1.0f);
- float sum2 = sum + t*amp;
+ float sum2 = sum + t * amp;
- sum *= ((float)(1 << n)/(float)((1 << (n+1)) - 1));
- sum2 *= ((float)(1 << (n+1))/(float)((1 << (n+2)) - 1));
+ sum *= ((float)(1 << n) / (float)((1 << (n + 1)) - 1));
+ sum2 *= ((float)(1 << (n + 1)) / (float)((1 << (n + 2)) - 1));
- return (1.0f - rmd)*sum + rmd*sum2;
- }
- else {
- sum *= ((float)(1 << n)/(float)((1 << (n+1)) - 1));
- return sum;
- }
+ return (1.0f - rmd) * sum + rmd * sum2;
+ }
+ else {
+ sum *= ((float)(1 << n) / (float)((1 << (n + 1)) - 1));
+ return sum;
+ }
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/svm/svm_types.h b/intern/cycles/kernel/svm/svm_types.h
index 8b15d7bf9f4..d31e4f93696 100644
--- a/intern/cycles/kernel/svm/svm_types.h
+++ b/intern/cycles/kernel/svm/svm_types.h
@@ -38,498 +38,505 @@ CCL_NAMESPACE_BEGIN
*
* Lower the number of group more often the node is used.
*/
-#define NODE_GROUP_LEVEL_0 0
-#define NODE_GROUP_LEVEL_1 1
-#define NODE_GROUP_LEVEL_2 2
-#define NODE_GROUP_LEVEL_3 3
-#define NODE_GROUP_LEVEL_MAX NODE_GROUP_LEVEL_3
-
-#define NODE_FEATURE_VOLUME (1 << 0)
-#define NODE_FEATURE_HAIR (1 << 1)
-#define NODE_FEATURE_BUMP (1 << 2)
+#define NODE_GROUP_LEVEL_0 0
+#define NODE_GROUP_LEVEL_1 1
+#define NODE_GROUP_LEVEL_2 2
+#define NODE_GROUP_LEVEL_3 3
+#define NODE_GROUP_LEVEL_MAX NODE_GROUP_LEVEL_3
+
+#define NODE_FEATURE_VOLUME (1 << 0)
+#define NODE_FEATURE_HAIR (1 << 1)
+#define NODE_FEATURE_BUMP (1 << 2)
#define NODE_FEATURE_BUMP_STATE (1 << 3)
/* TODO(sergey): Consider using something like ((uint)(-1)).
* Need to check carefully operand types around usage of this
* define first.
*/
-#define NODE_FEATURE_ALL (NODE_FEATURE_VOLUME|NODE_FEATURE_HAIR|NODE_FEATURE_BUMP|NODE_FEATURE_BUMP_STATE)
+#define NODE_FEATURE_ALL \
+ (NODE_FEATURE_VOLUME | NODE_FEATURE_HAIR | NODE_FEATURE_BUMP | NODE_FEATURE_BUMP_STATE)
typedef enum ShaderNodeType {
- NODE_END = 0,
- NODE_CLOSURE_BSDF,
- NODE_CLOSURE_EMISSION,
- NODE_CLOSURE_BACKGROUND,
- NODE_CLOSURE_SET_WEIGHT,
- NODE_CLOSURE_WEIGHT,
- NODE_MIX_CLOSURE,
- NODE_JUMP_IF_ZERO,
- NODE_JUMP_IF_ONE,
- NODE_TEX_IMAGE,
- NODE_TEX_IMAGE_BOX,
- NODE_TEX_SKY,
- NODE_GEOMETRY,
- NODE_GEOMETRY_DUPLI,
- NODE_LIGHT_PATH,
- NODE_VALUE_F,
- NODE_VALUE_V,
- NODE_MIX,
- NODE_ATTR,
- NODE_CONVERT,
- NODE_FRESNEL,
- NODE_WIREFRAME,
- NODE_WAVELENGTH,
- NODE_BLACKBODY,
- NODE_EMISSION_WEIGHT,
- NODE_TEX_GRADIENT,
- NODE_TEX_VORONOI,
- NODE_TEX_MUSGRAVE,
- NODE_TEX_WAVE,
- NODE_TEX_MAGIC,
- NODE_TEX_NOISE,
- NODE_SHADER_JUMP,
- NODE_SET_DISPLACEMENT,
- NODE_GEOMETRY_BUMP_DX,
- NODE_GEOMETRY_BUMP_DY,
- NODE_SET_BUMP,
- NODE_MATH,
- NODE_VECTOR_MATH,
- NODE_VECTOR_TRANSFORM,
- NODE_MAPPING,
- NODE_TEX_COORD,
- NODE_TEX_COORD_BUMP_DX,
- NODE_TEX_COORD_BUMP_DY,
- NODE_ATTR_BUMP_DX,
- NODE_ATTR_BUMP_DY,
- NODE_TEX_ENVIRONMENT,
- NODE_CLOSURE_HOLDOUT,
- NODE_LAYER_WEIGHT,
- NODE_CLOSURE_VOLUME,
- NODE_SEPARATE_VECTOR,
- NODE_COMBINE_VECTOR,
- NODE_SEPARATE_HSV,
- NODE_COMBINE_HSV,
- NODE_HSV,
- NODE_CAMERA,
- NODE_INVERT,
- NODE_NORMAL,
- NODE_GAMMA,
- NODE_TEX_CHECKER,
- NODE_BRIGHTCONTRAST,
- NODE_RGB_RAMP,
- NODE_RGB_CURVES,
- NODE_VECTOR_CURVES,
- NODE_MIN_MAX,
- NODE_LIGHT_FALLOFF,
- NODE_OBJECT_INFO,
- NODE_PARTICLE_INFO,
- NODE_TEX_BRICK,
- NODE_CLOSURE_SET_NORMAL,
- NODE_AMBIENT_OCCLUSION,
- NODE_TANGENT,
- NODE_NORMAL_MAP,
- NODE_HAIR_INFO,
- NODE_UVMAP,
- NODE_TEX_VOXEL,
- NODE_ENTER_BUMP_EVAL,
- NODE_LEAVE_BUMP_EVAL,
- NODE_BEVEL,
- NODE_DISPLACEMENT,
- NODE_VECTOR_DISPLACEMENT,
- NODE_PRINCIPLED_VOLUME,
- NODE_IES,
+ NODE_END = 0,
+ NODE_CLOSURE_BSDF,
+ NODE_CLOSURE_EMISSION,
+ NODE_CLOSURE_BACKGROUND,
+ NODE_CLOSURE_SET_WEIGHT,
+ NODE_CLOSURE_WEIGHT,
+ NODE_MIX_CLOSURE,
+ NODE_JUMP_IF_ZERO,
+ NODE_JUMP_IF_ONE,
+ NODE_TEX_IMAGE,
+ NODE_TEX_IMAGE_BOX,
+ NODE_TEX_SKY,
+ NODE_GEOMETRY,
+ NODE_GEOMETRY_DUPLI,
+ NODE_LIGHT_PATH,
+ NODE_VALUE_F,
+ NODE_VALUE_V,
+ NODE_MIX,
+ NODE_ATTR,
+ NODE_CONVERT,
+ NODE_FRESNEL,
+ NODE_WIREFRAME,
+ NODE_WAVELENGTH,
+ NODE_BLACKBODY,
+ NODE_EMISSION_WEIGHT,
+ NODE_TEX_GRADIENT,
+ NODE_TEX_VORONOI,
+ NODE_TEX_MUSGRAVE,
+ NODE_TEX_WAVE,
+ NODE_TEX_MAGIC,
+ NODE_TEX_NOISE,
+ NODE_SHADER_JUMP,
+ NODE_SET_DISPLACEMENT,
+ NODE_GEOMETRY_BUMP_DX,
+ NODE_GEOMETRY_BUMP_DY,
+ NODE_SET_BUMP,
+ NODE_MATH,
+ NODE_VECTOR_MATH,
+ NODE_VECTOR_TRANSFORM,
+ NODE_MAPPING,
+ NODE_TEX_COORD,
+ NODE_TEX_COORD_BUMP_DX,
+ NODE_TEX_COORD_BUMP_DY,
+ NODE_ATTR_BUMP_DX,
+ NODE_ATTR_BUMP_DY,
+ NODE_TEX_ENVIRONMENT,
+ NODE_CLOSURE_HOLDOUT,
+ NODE_LAYER_WEIGHT,
+ NODE_CLOSURE_VOLUME,
+ NODE_SEPARATE_VECTOR,
+ NODE_COMBINE_VECTOR,
+ NODE_SEPARATE_HSV,
+ NODE_COMBINE_HSV,
+ NODE_HSV,
+ NODE_CAMERA,
+ NODE_INVERT,
+ NODE_NORMAL,
+ NODE_GAMMA,
+ NODE_TEX_CHECKER,
+ NODE_BRIGHTCONTRAST,
+ NODE_RGB_RAMP,
+ NODE_RGB_CURVES,
+ NODE_VECTOR_CURVES,
+ NODE_MIN_MAX,
+ NODE_LIGHT_FALLOFF,
+ NODE_OBJECT_INFO,
+ NODE_PARTICLE_INFO,
+ NODE_TEX_BRICK,
+ NODE_CLOSURE_SET_NORMAL,
+ NODE_AMBIENT_OCCLUSION,
+ NODE_TANGENT,
+ NODE_NORMAL_MAP,
+ NODE_HAIR_INFO,
+ NODE_UVMAP,
+ NODE_TEX_VOXEL,
+ NODE_ENTER_BUMP_EVAL,
+ NODE_LEAVE_BUMP_EVAL,
+ NODE_BEVEL,
+ NODE_DISPLACEMENT,
+ NODE_VECTOR_DISPLACEMENT,
+ NODE_PRINCIPLED_VOLUME,
+ NODE_IES,
} ShaderNodeType;
typedef enum NodeAttributeType {
- NODE_ATTR_FLOAT = 0,
- NODE_ATTR_FLOAT2,
- NODE_ATTR_FLOAT3,
- NODE_ATTR_MATRIX
+ NODE_ATTR_FLOAT = 0,
+ NODE_ATTR_FLOAT2,
+ NODE_ATTR_FLOAT3,
+ NODE_ATTR_MATRIX
} NodeAttributeType;
typedef enum NodeGeometry {
- NODE_GEOM_P = 0,
- NODE_GEOM_N,
- NODE_GEOM_T,
- NODE_GEOM_I,
- NODE_GEOM_Ng,
- NODE_GEOM_uv
+ NODE_GEOM_P = 0,
+ NODE_GEOM_N,
+ NODE_GEOM_T,
+ NODE_GEOM_I,
+ NODE_GEOM_Ng,
+ NODE_GEOM_uv
} NodeGeometry;
typedef enum NodeObjectInfo {
- NODE_INFO_OB_LOCATION,
- NODE_INFO_OB_INDEX,
- NODE_INFO_MAT_INDEX,
- NODE_INFO_OB_RANDOM
+ NODE_INFO_OB_LOCATION,
+ NODE_INFO_OB_INDEX,
+ NODE_INFO_MAT_INDEX,
+ NODE_INFO_OB_RANDOM
} NodeObjectInfo;
typedef enum NodeParticleInfo {
- NODE_INFO_PAR_INDEX,
- NODE_INFO_PAR_RANDOM,
- NODE_INFO_PAR_AGE,
- NODE_INFO_PAR_LIFETIME,
- NODE_INFO_PAR_LOCATION,
- NODE_INFO_PAR_ROTATION,
- NODE_INFO_PAR_SIZE,
- NODE_INFO_PAR_VELOCITY,
- NODE_INFO_PAR_ANGULAR_VELOCITY
+ NODE_INFO_PAR_INDEX,
+ NODE_INFO_PAR_RANDOM,
+ NODE_INFO_PAR_AGE,
+ NODE_INFO_PAR_LIFETIME,
+ NODE_INFO_PAR_LOCATION,
+ NODE_INFO_PAR_ROTATION,
+ NODE_INFO_PAR_SIZE,
+ NODE_INFO_PAR_VELOCITY,
+ NODE_INFO_PAR_ANGULAR_VELOCITY
} NodeParticleInfo;
typedef enum NodeHairInfo {
- NODE_INFO_CURVE_IS_STRAND,
- NODE_INFO_CURVE_INTERCEPT,
- NODE_INFO_CURVE_THICKNESS,
- /*fade for minimum hair width transpency*/
- /*NODE_INFO_CURVE_FADE,*/
- NODE_INFO_CURVE_TANGENT_NORMAL,
- NODE_INFO_CURVE_RANDOM,
+ NODE_INFO_CURVE_IS_STRAND,
+ NODE_INFO_CURVE_INTERCEPT,
+ NODE_INFO_CURVE_THICKNESS,
+ /*fade for minimum hair width transpency*/
+ /*NODE_INFO_CURVE_FADE,*/
+ NODE_INFO_CURVE_TANGENT_NORMAL,
+ NODE_INFO_CURVE_RANDOM,
} NodeHairInfo;
typedef enum NodeLightPath {
- NODE_LP_camera = 0,
- NODE_LP_shadow,
- NODE_LP_diffuse,
- NODE_LP_glossy,
- NODE_LP_singular,
- NODE_LP_reflection,
- NODE_LP_transmission,
- NODE_LP_volume_scatter,
- NODE_LP_backfacing,
- NODE_LP_ray_length,
- NODE_LP_ray_depth,
- NODE_LP_ray_diffuse,
- NODE_LP_ray_glossy,
- NODE_LP_ray_transparent,
- NODE_LP_ray_transmission,
+ NODE_LP_camera = 0,
+ NODE_LP_shadow,
+ NODE_LP_diffuse,
+ NODE_LP_glossy,
+ NODE_LP_singular,
+ NODE_LP_reflection,
+ NODE_LP_transmission,
+ NODE_LP_volume_scatter,
+ NODE_LP_backfacing,
+ NODE_LP_ray_length,
+ NODE_LP_ray_depth,
+ NODE_LP_ray_diffuse,
+ NODE_LP_ray_glossy,
+ NODE_LP_ray_transparent,
+ NODE_LP_ray_transmission,
} NodeLightPath;
typedef enum NodeLightFalloff {
- NODE_LIGHT_FALLOFF_QUADRATIC,
- NODE_LIGHT_FALLOFF_LINEAR,
- NODE_LIGHT_FALLOFF_CONSTANT
+ NODE_LIGHT_FALLOFF_QUADRATIC,
+ NODE_LIGHT_FALLOFF_LINEAR,
+ NODE_LIGHT_FALLOFF_CONSTANT
} NodeLightFalloff;
typedef enum NodeTexCoord {
- NODE_TEXCO_NORMAL,
- NODE_TEXCO_OBJECT,
- NODE_TEXCO_CAMERA,
- NODE_TEXCO_WINDOW,
- NODE_TEXCO_REFLECTION,
- NODE_TEXCO_DUPLI_GENERATED,
- NODE_TEXCO_DUPLI_UV,
- NODE_TEXCO_VOLUME_GENERATED
+ NODE_TEXCO_NORMAL,
+ NODE_TEXCO_OBJECT,
+ NODE_TEXCO_CAMERA,
+ NODE_TEXCO_WINDOW,
+ NODE_TEXCO_REFLECTION,
+ NODE_TEXCO_DUPLI_GENERATED,
+ NODE_TEXCO_DUPLI_UV,
+ NODE_TEXCO_VOLUME_GENERATED
} NodeTexCoord;
typedef enum NodeMix {
- NODE_MIX_BLEND = 0,
- NODE_MIX_ADD,
- NODE_MIX_MUL,
- NODE_MIX_SUB,
- NODE_MIX_SCREEN,
- NODE_MIX_DIV,
- NODE_MIX_DIFF,
- NODE_MIX_DARK,
- NODE_MIX_LIGHT,
- NODE_MIX_OVERLAY,
- NODE_MIX_DODGE,
- NODE_MIX_BURN,
- NODE_MIX_HUE,
- NODE_MIX_SAT,
- NODE_MIX_VAL,
- NODE_MIX_COLOR,
- NODE_MIX_SOFT,
- NODE_MIX_LINEAR,
- NODE_MIX_CLAMP /* used for the clamp UI option */
+ NODE_MIX_BLEND = 0,
+ NODE_MIX_ADD,
+ NODE_MIX_MUL,
+ NODE_MIX_SUB,
+ NODE_MIX_SCREEN,
+ NODE_MIX_DIV,
+ NODE_MIX_DIFF,
+ NODE_MIX_DARK,
+ NODE_MIX_LIGHT,
+ NODE_MIX_OVERLAY,
+ NODE_MIX_DODGE,
+ NODE_MIX_BURN,
+ NODE_MIX_HUE,
+ NODE_MIX_SAT,
+ NODE_MIX_VAL,
+ NODE_MIX_COLOR,
+ NODE_MIX_SOFT,
+ NODE_MIX_LINEAR,
+ NODE_MIX_CLAMP /* used for the clamp UI option */
} NodeMix;
typedef enum NodeMath {
- NODE_MATH_ADD,
- NODE_MATH_SUBTRACT,
- NODE_MATH_MULTIPLY,
- NODE_MATH_DIVIDE,
- NODE_MATH_SINE,
- NODE_MATH_COSINE,
- NODE_MATH_TANGENT,
- NODE_MATH_ARCSINE,
- NODE_MATH_ARCCOSINE,
- NODE_MATH_ARCTANGENT,
- NODE_MATH_POWER,
- NODE_MATH_LOGARITHM,
- NODE_MATH_MINIMUM,
- NODE_MATH_MAXIMUM,
- NODE_MATH_ROUND,
- NODE_MATH_LESS_THAN,
- NODE_MATH_GREATER_THAN,
- NODE_MATH_MODULO,
- NODE_MATH_ABSOLUTE,
- NODE_MATH_ARCTAN2,
- NODE_MATH_FLOOR,
- NODE_MATH_CEIL,
- NODE_MATH_FRACT,
- NODE_MATH_SQRT,
- NODE_MATH_CLAMP /* used for the clamp UI option */
+ NODE_MATH_ADD,
+ NODE_MATH_SUBTRACT,
+ NODE_MATH_MULTIPLY,
+ NODE_MATH_DIVIDE,
+ NODE_MATH_SINE,
+ NODE_MATH_COSINE,
+ NODE_MATH_TANGENT,
+ NODE_MATH_ARCSINE,
+ NODE_MATH_ARCCOSINE,
+ NODE_MATH_ARCTANGENT,
+ NODE_MATH_POWER,
+ NODE_MATH_LOGARITHM,
+ NODE_MATH_MINIMUM,
+ NODE_MATH_MAXIMUM,
+ NODE_MATH_ROUND,
+ NODE_MATH_LESS_THAN,
+ NODE_MATH_GREATER_THAN,
+ NODE_MATH_MODULO,
+ NODE_MATH_ABSOLUTE,
+ NODE_MATH_ARCTAN2,
+ NODE_MATH_FLOOR,
+ NODE_MATH_CEIL,
+ NODE_MATH_FRACT,
+ NODE_MATH_SQRT,
+ NODE_MATH_CLAMP /* used for the clamp UI option */
} NodeMath;
typedef enum NodeVectorMath {
- NODE_VECTOR_MATH_ADD,
- NODE_VECTOR_MATH_SUBTRACT,
- NODE_VECTOR_MATH_AVERAGE,
- NODE_VECTOR_MATH_DOT_PRODUCT,
- NODE_VECTOR_MATH_CROSS_PRODUCT,
- NODE_VECTOR_MATH_NORMALIZE
+ NODE_VECTOR_MATH_ADD,
+ NODE_VECTOR_MATH_SUBTRACT,
+ NODE_VECTOR_MATH_AVERAGE,
+ NODE_VECTOR_MATH_DOT_PRODUCT,
+ NODE_VECTOR_MATH_CROSS_PRODUCT,
+ NODE_VECTOR_MATH_NORMALIZE
} NodeVectorMath;
typedef enum NodeVectorTransformType {
- NODE_VECTOR_TRANSFORM_TYPE_VECTOR,
- NODE_VECTOR_TRANSFORM_TYPE_POINT,
- NODE_VECTOR_TRANSFORM_TYPE_NORMAL
+ NODE_VECTOR_TRANSFORM_TYPE_VECTOR,
+ NODE_VECTOR_TRANSFORM_TYPE_POINT,
+ NODE_VECTOR_TRANSFORM_TYPE_NORMAL
} NodeVectorTransformType;
typedef enum NodeVectorTransformConvertSpace {
- NODE_VECTOR_TRANSFORM_CONVERT_SPACE_WORLD,
- NODE_VECTOR_TRANSFORM_CONVERT_SPACE_OBJECT,
- NODE_VECTOR_TRANSFORM_CONVERT_SPACE_CAMERA
+ NODE_VECTOR_TRANSFORM_CONVERT_SPACE_WORLD,
+ NODE_VECTOR_TRANSFORM_CONVERT_SPACE_OBJECT,
+ NODE_VECTOR_TRANSFORM_CONVERT_SPACE_CAMERA
} NodeVectorTransformConvertSpace;
typedef enum NodeConvert {
- NODE_CONVERT_FV,
- NODE_CONVERT_FI,
- NODE_CONVERT_CF,
- NODE_CONVERT_CI,
- NODE_CONVERT_VF,
- NODE_CONVERT_VI,
- NODE_CONVERT_IF,
- NODE_CONVERT_IV
+ NODE_CONVERT_FV,
+ NODE_CONVERT_FI,
+ NODE_CONVERT_CF,
+ NODE_CONVERT_CI,
+ NODE_CONVERT_VF,
+ NODE_CONVERT_VI,
+ NODE_CONVERT_IF,
+ NODE_CONVERT_IV
} NodeConvert;
typedef enum NodeMusgraveType {
- NODE_MUSGRAVE_MULTIFRACTAL,
- NODE_MUSGRAVE_FBM,
- NODE_MUSGRAVE_HYBRID_MULTIFRACTAL,
- NODE_MUSGRAVE_RIDGED_MULTIFRACTAL,
- NODE_MUSGRAVE_HETERO_TERRAIN
+ NODE_MUSGRAVE_MULTIFRACTAL,
+ NODE_MUSGRAVE_FBM,
+ NODE_MUSGRAVE_HYBRID_MULTIFRACTAL,
+ NODE_MUSGRAVE_RIDGED_MULTIFRACTAL,
+ NODE_MUSGRAVE_HETERO_TERRAIN
} NodeMusgraveType;
-typedef enum NodeWaveType {
- NODE_WAVE_BANDS,
- NODE_WAVE_RINGS
-} NodeWaveType;
+typedef enum NodeWaveType { NODE_WAVE_BANDS, NODE_WAVE_RINGS } NodeWaveType;
typedef enum NodeWaveProfiles {
- NODE_WAVE_PROFILE_SIN,
- NODE_WAVE_PROFILE_SAW,
+ NODE_WAVE_PROFILE_SIN,
+ NODE_WAVE_PROFILE_SAW,
} NodeWaveProfile;
-typedef enum NodeSkyType {
- NODE_SKY_OLD,
- NODE_SKY_NEW
-} NodeSkyType;
+typedef enum NodeSkyType { NODE_SKY_OLD, NODE_SKY_NEW } NodeSkyType;
typedef enum NodeGradientType {
- NODE_BLEND_LINEAR,
- NODE_BLEND_QUADRATIC,
- NODE_BLEND_EASING,
- NODE_BLEND_DIAGONAL,
- NODE_BLEND_RADIAL,
- NODE_BLEND_QUADRATIC_SPHERE,
- NODE_BLEND_SPHERICAL
+ NODE_BLEND_LINEAR,
+ NODE_BLEND_QUADRATIC,
+ NODE_BLEND_EASING,
+ NODE_BLEND_DIAGONAL,
+ NODE_BLEND_RADIAL,
+ NODE_BLEND_QUADRATIC_SPHERE,
+ NODE_BLEND_SPHERICAL
} NodeGradientType;
typedef enum NodeVoronoiColoring {
- NODE_VORONOI_INTENSITY,
- NODE_VORONOI_CELLS
+ NODE_VORONOI_INTENSITY,
+ NODE_VORONOI_CELLS
} NodeVoronoiColoring;
typedef enum NodeVoronoiDistanceMetric {
- NODE_VORONOI_DISTANCE,
- NODE_VORONOI_MANHATTAN,
- NODE_VORONOI_CHEBYCHEV,
- NODE_VORONOI_MINKOWSKI
+ NODE_VORONOI_DISTANCE,
+ NODE_VORONOI_MANHATTAN,
+ NODE_VORONOI_CHEBYCHEV,
+ NODE_VORONOI_MINKOWSKI
} NodeVoronoiDistanceMetric;
typedef enum NodeVoronoiFeature {
- NODE_VORONOI_F1,
- NODE_VORONOI_F2,
- NODE_VORONOI_F3,
- NODE_VORONOI_F4,
- NODE_VORONOI_F2F1
+ NODE_VORONOI_F1,
+ NODE_VORONOI_F2,
+ NODE_VORONOI_F3,
+ NODE_VORONOI_F4,
+ NODE_VORONOI_F2F1
} NodeVoronoiFeature;
typedef enum NodeBlendWeightType {
- NODE_LAYER_WEIGHT_FRESNEL,
- NODE_LAYER_WEIGHT_FACING
+ NODE_LAYER_WEIGHT_FRESNEL,
+ NODE_LAYER_WEIGHT_FACING
} NodeBlendWeightType;
typedef enum NodeTangentDirectionType {
- NODE_TANGENT_RADIAL,
- NODE_TANGENT_UVMAP
+ NODE_TANGENT_RADIAL,
+ NODE_TANGENT_UVMAP
} NodeTangentDirectionType;
typedef enum NodeTangentAxis {
- NODE_TANGENT_AXIS_X,
- NODE_TANGENT_AXIS_Y,
- NODE_TANGENT_AXIS_Z
+ NODE_TANGENT_AXIS_X,
+ NODE_TANGENT_AXIS_Y,
+ NODE_TANGENT_AXIS_Z
} NodeTangentAxis;
typedef enum NodeNormalMapSpace {
- NODE_NORMAL_MAP_TANGENT,
- NODE_NORMAL_MAP_OBJECT,
- NODE_NORMAL_MAP_WORLD,
- NODE_NORMAL_MAP_BLENDER_OBJECT,
- NODE_NORMAL_MAP_BLENDER_WORLD,
+ NODE_NORMAL_MAP_TANGENT,
+ NODE_NORMAL_MAP_OBJECT,
+ NODE_NORMAL_MAP_WORLD,
+ NODE_NORMAL_MAP_BLENDER_OBJECT,
+ NODE_NORMAL_MAP_BLENDER_WORLD,
} NodeNormalMapSpace;
typedef enum NodeImageColorSpace {
- NODE_COLOR_SPACE_NONE = 0,
- NODE_COLOR_SPACE_COLOR = 1,
+ NODE_COLOR_SPACE_NONE = 0,
+ NODE_COLOR_SPACE_COLOR = 1,
} NodeImageColorSpace;
typedef enum NodeImageProjection {
- NODE_IMAGE_PROJ_FLAT = 0,
- NODE_IMAGE_PROJ_BOX = 1,
- NODE_IMAGE_PROJ_SPHERE = 2,
- NODE_IMAGE_PROJ_TUBE = 3,
+ NODE_IMAGE_PROJ_FLAT = 0,
+ NODE_IMAGE_PROJ_BOX = 1,
+ NODE_IMAGE_PROJ_SPHERE = 2,
+ NODE_IMAGE_PROJ_TUBE = 3,
} NodeImageProjection;
typedef enum NodeEnvironmentProjection {
- NODE_ENVIRONMENT_EQUIRECTANGULAR = 0,
- NODE_ENVIRONMENT_MIRROR_BALL = 1,
+ NODE_ENVIRONMENT_EQUIRECTANGULAR = 0,
+ NODE_ENVIRONMENT_MIRROR_BALL = 1,
} NodeEnvironmentProjection;
typedef enum NodeBumpOffset {
- NODE_BUMP_OFFSET_CENTER,
- NODE_BUMP_OFFSET_DX,
- NODE_BUMP_OFFSET_DY,
+ NODE_BUMP_OFFSET_CENTER,
+ NODE_BUMP_OFFSET_DX,
+ NODE_BUMP_OFFSET_DY,
} NodeBumpOffset;
typedef enum NodeTexVoxelSpace {
- NODE_TEX_VOXEL_SPACE_OBJECT = 0,
- NODE_TEX_VOXEL_SPACE_WORLD = 1,
+ NODE_TEX_VOXEL_SPACE_OBJECT = 0,
+ NODE_TEX_VOXEL_SPACE_WORLD = 1,
} NodeTexVoxelSpace;
typedef enum NodeAO {
- NODE_AO_ONLY_LOCAL = (1 << 0),
- NODE_AO_INSIDE = (1 << 1),
- NODE_AO_GLOBAL_RADIUS = (1 << 2),
+ NODE_AO_ONLY_LOCAL = (1 << 0),
+ NODE_AO_INSIDE = (1 << 1),
+ NODE_AO_GLOBAL_RADIUS = (1 << 2),
} NodeAO;
typedef enum ShaderType {
- SHADER_TYPE_SURFACE,
- SHADER_TYPE_VOLUME,
- SHADER_TYPE_DISPLACEMENT,
- SHADER_TYPE_BUMP,
+ SHADER_TYPE_SURFACE,
+ SHADER_TYPE_VOLUME,
+ SHADER_TYPE_DISPLACEMENT,
+ SHADER_TYPE_BUMP,
} ShaderType;
typedef enum NodePrincipledHairParametrization {
- NODE_PRINCIPLED_HAIR_REFLECTANCE = 0,
- NODE_PRINCIPLED_HAIR_PIGMENT_CONCENTRATION = 1,
- NODE_PRINCIPLED_HAIR_DIRECT_ABSORPTION = 2,
- NODE_PRINCIPLED_HAIR_NUM,
+ NODE_PRINCIPLED_HAIR_REFLECTANCE = 0,
+ NODE_PRINCIPLED_HAIR_PIGMENT_CONCENTRATION = 1,
+ NODE_PRINCIPLED_HAIR_DIRECT_ABSORPTION = 2,
+ NODE_PRINCIPLED_HAIR_NUM,
} NodePrincipledHairParametrization;
/* Closure */
typedef enum ClosureType {
- /* Special type, flags generic node as a non-BSDF. */
- CLOSURE_NONE_ID,
-
- CLOSURE_BSDF_ID,
-
- /* Diffuse */
- CLOSURE_BSDF_DIFFUSE_ID,
- CLOSURE_BSDF_OREN_NAYAR_ID,
- CLOSURE_BSDF_DIFFUSE_RAMP_ID,
- CLOSURE_BSDF_PRINCIPLED_DIFFUSE_ID,
- CLOSURE_BSDF_PRINCIPLED_SHEEN_ID,
- CLOSURE_BSDF_DIFFUSE_TOON_ID,
-
- /* Glossy */
- CLOSURE_BSDF_REFLECTION_ID,
- CLOSURE_BSDF_MICROFACET_GGX_ID,
- CLOSURE_BSDF_MICROFACET_GGX_FRESNEL_ID,
- CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_ID,
- CLOSURE_BSDF_MICROFACET_BECKMANN_ID,
- CLOSURE_BSDF_MICROFACET_MULTI_GGX_ID,
- CLOSURE_BSDF_MICROFACET_MULTI_GGX_FRESNEL_ID,
- CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ID,
- CLOSURE_BSDF_MICROFACET_GGX_ANISO_ID,
- CLOSURE_BSDF_MICROFACET_GGX_ANISO_FRESNEL_ID,
- CLOSURE_BSDF_MICROFACET_MULTI_GGX_ANISO_ID,
- CLOSURE_BSDF_MICROFACET_MULTI_GGX_ANISO_FRESNEL_ID,
- CLOSURE_BSDF_MICROFACET_BECKMANN_ANISO_ID,
- CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ANISO_ID,
- CLOSURE_BSDF_ASHIKHMIN_VELVET_ID,
- CLOSURE_BSDF_PHONG_RAMP_ID,
- CLOSURE_BSDF_GLOSSY_TOON_ID,
- CLOSURE_BSDF_HAIR_REFLECTION_ID,
-
- /* Transmission */
- CLOSURE_BSDF_TRANSLUCENT_ID,
- CLOSURE_BSDF_REFRACTION_ID,
- CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID,
- CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID,
- CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID,
- CLOSURE_BSDF_MICROFACET_BECKMANN_GLASS_ID,
- CLOSURE_BSDF_MICROFACET_GGX_GLASS_ID,
- CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_FRESNEL_ID,
- CLOSURE_BSDF_SHARP_GLASS_ID,
- CLOSURE_BSDF_HAIR_PRINCIPLED_ID,
- CLOSURE_BSDF_HAIR_TRANSMISSION_ID,
-
- /* Special cases */
- CLOSURE_BSDF_BSSRDF_ID,
- CLOSURE_BSDF_BSSRDF_PRINCIPLED_ID,
- CLOSURE_BSDF_TRANSPARENT_ID,
-
- /* BSSRDF */
- CLOSURE_BSSRDF_CUBIC_ID,
- CLOSURE_BSSRDF_GAUSSIAN_ID,
- CLOSURE_BSSRDF_PRINCIPLED_ID,
- CLOSURE_BSSRDF_BURLEY_ID,
- CLOSURE_BSSRDF_RANDOM_WALK_ID,
- CLOSURE_BSSRDF_PRINCIPLED_RANDOM_WALK_ID,
-
- /* Other */
- CLOSURE_HOLDOUT_ID,
-
- /* Volume */
- CLOSURE_VOLUME_ID,
- CLOSURE_VOLUME_ABSORPTION_ID,
- CLOSURE_VOLUME_HENYEY_GREENSTEIN_ID,
-
- CLOSURE_BSDF_PRINCIPLED_ID,
-
- NBUILTIN_CLOSURES
+ /* Special type, flags generic node as a non-BSDF. */
+ CLOSURE_NONE_ID,
+
+ CLOSURE_BSDF_ID,
+
+ /* Diffuse */
+ CLOSURE_BSDF_DIFFUSE_ID,
+ CLOSURE_BSDF_OREN_NAYAR_ID,
+ CLOSURE_BSDF_DIFFUSE_RAMP_ID,
+ CLOSURE_BSDF_PRINCIPLED_DIFFUSE_ID,
+ CLOSURE_BSDF_PRINCIPLED_SHEEN_ID,
+ CLOSURE_BSDF_DIFFUSE_TOON_ID,
+
+ /* Glossy */
+ CLOSURE_BSDF_REFLECTION_ID,
+ CLOSURE_BSDF_MICROFACET_GGX_ID,
+ CLOSURE_BSDF_MICROFACET_GGX_FRESNEL_ID,
+ CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_ID,
+ CLOSURE_BSDF_MICROFACET_BECKMANN_ID,
+ CLOSURE_BSDF_MICROFACET_MULTI_GGX_ID,
+ CLOSURE_BSDF_MICROFACET_MULTI_GGX_FRESNEL_ID,
+ CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ID,
+ CLOSURE_BSDF_MICROFACET_GGX_ANISO_ID,
+ CLOSURE_BSDF_MICROFACET_GGX_ANISO_FRESNEL_ID,
+ CLOSURE_BSDF_MICROFACET_MULTI_GGX_ANISO_ID,
+ CLOSURE_BSDF_MICROFACET_MULTI_GGX_ANISO_FRESNEL_ID,
+ CLOSURE_BSDF_MICROFACET_BECKMANN_ANISO_ID,
+ CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ANISO_ID,
+ CLOSURE_BSDF_ASHIKHMIN_VELVET_ID,
+ CLOSURE_BSDF_PHONG_RAMP_ID,
+ CLOSURE_BSDF_GLOSSY_TOON_ID,
+ CLOSURE_BSDF_HAIR_REFLECTION_ID,
+
+ /* Transmission */
+ CLOSURE_BSDF_TRANSLUCENT_ID,
+ CLOSURE_BSDF_REFRACTION_ID,
+ CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID,
+ CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID,
+ CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID,
+ CLOSURE_BSDF_MICROFACET_BECKMANN_GLASS_ID,
+ CLOSURE_BSDF_MICROFACET_GGX_GLASS_ID,
+ CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_FRESNEL_ID,
+ CLOSURE_BSDF_SHARP_GLASS_ID,
+ CLOSURE_BSDF_HAIR_PRINCIPLED_ID,
+ CLOSURE_BSDF_HAIR_TRANSMISSION_ID,
+
+ /* Special cases */
+ CLOSURE_BSDF_BSSRDF_ID,
+ CLOSURE_BSDF_BSSRDF_PRINCIPLED_ID,
+ CLOSURE_BSDF_TRANSPARENT_ID,
+
+ /* BSSRDF */
+ CLOSURE_BSSRDF_CUBIC_ID,
+ CLOSURE_BSSRDF_GAUSSIAN_ID,
+ CLOSURE_BSSRDF_PRINCIPLED_ID,
+ CLOSURE_BSSRDF_BURLEY_ID,
+ CLOSURE_BSSRDF_RANDOM_WALK_ID,
+ CLOSURE_BSSRDF_PRINCIPLED_RANDOM_WALK_ID,
+
+ /* Other */
+ CLOSURE_HOLDOUT_ID,
+
+ /* Volume */
+ CLOSURE_VOLUME_ID,
+ CLOSURE_VOLUME_ABSORPTION_ID,
+ CLOSURE_VOLUME_HENYEY_GREENSTEIN_ID,
+
+ CLOSURE_BSDF_PRINCIPLED_ID,
+
+ NBUILTIN_CLOSURES
} ClosureType;
/* watch this, being lazy with memory usage */
#define CLOSURE_IS_BSDF(type) (type <= CLOSURE_BSDF_TRANSPARENT_ID)
-#define CLOSURE_IS_BSDF_DIFFUSE(type) (type >= CLOSURE_BSDF_DIFFUSE_ID && type <= CLOSURE_BSDF_DIFFUSE_TOON_ID)
-#define CLOSURE_IS_BSDF_GLOSSY(type) ((type >= CLOSURE_BSDF_REFLECTION_ID && type <= CLOSURE_BSDF_HAIR_REFLECTION_ID )|| (type == CLOSURE_BSDF_HAIR_PRINCIPLED_ID))
-#define CLOSURE_IS_BSDF_TRANSMISSION(type) (type >= CLOSURE_BSDF_TRANSLUCENT_ID && type <= CLOSURE_BSDF_HAIR_TRANSMISSION_ID)
-#define CLOSURE_IS_BSDF_BSSRDF(type) (type == CLOSURE_BSDF_BSSRDF_ID || type == CLOSURE_BSDF_BSSRDF_PRINCIPLED_ID)
-#define CLOSURE_IS_BSDF_SINGULAR(type) (type == CLOSURE_BSDF_REFLECTION_ID || \
- type == CLOSURE_BSDF_REFRACTION_ID || \
- type == CLOSURE_BSDF_TRANSPARENT_ID)
+#define CLOSURE_IS_BSDF_DIFFUSE(type) \
+ (type >= CLOSURE_BSDF_DIFFUSE_ID && type <= CLOSURE_BSDF_DIFFUSE_TOON_ID)
+#define CLOSURE_IS_BSDF_GLOSSY(type) \
+ ((type >= CLOSURE_BSDF_REFLECTION_ID && type <= CLOSURE_BSDF_HAIR_REFLECTION_ID) || \
+ (type == CLOSURE_BSDF_HAIR_PRINCIPLED_ID))
+#define CLOSURE_IS_BSDF_TRANSMISSION(type) \
+ (type >= CLOSURE_BSDF_TRANSLUCENT_ID && type <= CLOSURE_BSDF_HAIR_TRANSMISSION_ID)
+#define CLOSURE_IS_BSDF_BSSRDF(type) \
+ (type == CLOSURE_BSDF_BSSRDF_ID || type == CLOSURE_BSDF_BSSRDF_PRINCIPLED_ID)
+#define CLOSURE_IS_BSDF_SINGULAR(type) \
+ (type == CLOSURE_BSDF_REFLECTION_ID || type == CLOSURE_BSDF_REFRACTION_ID || \
+ type == CLOSURE_BSDF_TRANSPARENT_ID)
#define CLOSURE_IS_BSDF_TRANSPARENT(type) (type == CLOSURE_BSDF_TRANSPARENT_ID)
-#define CLOSURE_IS_BSDF_MULTISCATTER(type) (type == CLOSURE_BSDF_MICROFACET_MULTI_GGX_ID ||\
- type == CLOSURE_BSDF_MICROFACET_MULTI_GGX_ANISO_ID || \
- type == CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID)
-#define CLOSURE_IS_BSDF_MICROFACET(type) ((type >= CLOSURE_BSDF_MICROFACET_GGX_ID && type <= CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ANISO_ID) ||\
- (type >= CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID && type <= CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID) ||\
- (type == CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_FRESNEL_ID))
+#define CLOSURE_IS_BSDF_MULTISCATTER(type) \
+ (type == CLOSURE_BSDF_MICROFACET_MULTI_GGX_ID || \
+ type == CLOSURE_BSDF_MICROFACET_MULTI_GGX_ANISO_ID || \
+ type == CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID)
+#define CLOSURE_IS_BSDF_MICROFACET(type) \
+ ((type >= CLOSURE_BSDF_MICROFACET_GGX_ID && type <= CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ANISO_ID) || \
+ (type >= CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID && \
+ type <= CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID) || \
+ (type == CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_FRESNEL_ID))
#define CLOSURE_IS_BSDF_OR_BSSRDF(type) (type <= CLOSURE_BSSRDF_PRINCIPLED_RANDOM_WALK_ID)
-#define CLOSURE_IS_BSSRDF(type) (type >= CLOSURE_BSSRDF_CUBIC_ID && type <= CLOSURE_BSSRDF_PRINCIPLED_RANDOM_WALK_ID)
-#define CLOSURE_IS_DISK_BSSRDF(type) (type >= CLOSURE_BSSRDF_CUBIC_ID && type <= CLOSURE_BSSRDF_BURLEY_ID)
-#define CLOSURE_IS_VOLUME(type) (type >= CLOSURE_VOLUME_ID && type <= CLOSURE_VOLUME_HENYEY_GREENSTEIN_ID)
+#define CLOSURE_IS_BSSRDF(type) \
+ (type >= CLOSURE_BSSRDF_CUBIC_ID && type <= CLOSURE_BSSRDF_PRINCIPLED_RANDOM_WALK_ID)
+#define CLOSURE_IS_DISK_BSSRDF(type) \
+ (type >= CLOSURE_BSSRDF_CUBIC_ID && type <= CLOSURE_BSSRDF_BURLEY_ID)
+#define CLOSURE_IS_VOLUME(type) \
+ (type >= CLOSURE_VOLUME_ID && type <= CLOSURE_VOLUME_HENYEY_GREENSTEIN_ID)
#define CLOSURE_IS_VOLUME_SCATTER(type) (type == CLOSURE_VOLUME_HENYEY_GREENSTEIN_ID)
#define CLOSURE_IS_VOLUME_ABSORPTION(type) (type == CLOSURE_VOLUME_ABSORPTION_ID)
#define CLOSURE_IS_HOLDOUT(type) (type == CLOSURE_HOLDOUT_ID)
#define CLOSURE_IS_PHASE(type) (type == CLOSURE_VOLUME_HENYEY_GREENSTEIN_ID)
-#define CLOSURE_IS_GLASS(type) (type >= CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID && type <= CLOSURE_BSDF_SHARP_GLASS_ID)
+#define CLOSURE_IS_GLASS(type) \
+ (type >= CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID && type <= CLOSURE_BSDF_SHARP_GLASS_ID)
#define CLOSURE_IS_PRINCIPLED(type) (type == CLOSURE_BSDF_PRINCIPLED_ID)
#define CLOSURE_WEIGHT_CUTOFF 1e-5f
CCL_NAMESPACE_END
-#endif /* __SVM_TYPES_H__ */
+#endif /* __SVM_TYPES_H__ */
diff --git a/intern/cycles/kernel/svm/svm_value.h b/intern/cycles/kernel/svm/svm_value.h
index 062aee2956e..5b76f2c8832 100644
--- a/intern/cycles/kernel/svm/svm_value.h
+++ b/intern/cycles/kernel/svm/svm_value.h
@@ -18,18 +18,21 @@ CCL_NAMESPACE_BEGIN
/* Value Nodes */
-ccl_device void svm_node_value_f(KernelGlobals *kg, ShaderData *sd, float *stack, uint ivalue, uint out_offset)
+ccl_device void svm_node_value_f(
+ KernelGlobals *kg, ShaderData *sd, float *stack, uint ivalue, uint out_offset)
{
- stack_store_float(stack, out_offset, __uint_as_float(ivalue));
+ stack_store_float(stack, out_offset, __uint_as_float(ivalue));
}
-ccl_device void svm_node_value_v(KernelGlobals *kg, ShaderData *sd, float *stack, uint out_offset, int *offset)
+ccl_device void svm_node_value_v(
+ KernelGlobals *kg, ShaderData *sd, float *stack, uint out_offset, int *offset)
{
- /* read extra data */
- uint4 node1 = read_node(kg, offset);
- float3 p = make_float3(__uint_as_float(node1.y), __uint_as_float(node1.z), __uint_as_float(node1.w));
+ /* read extra data */
+ uint4 node1 = read_node(kg, offset);
+ float3 p = make_float3(
+ __uint_as_float(node1.y), __uint_as_float(node1.z), __uint_as_float(node1.w));
- stack_store_float3(stack, out_offset, p);
+ stack_store_float3(stack, out_offset, p);
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/svm/svm_vector_transform.h b/intern/cycles/kernel/svm/svm_vector_transform.h
index f6ec36ba41f..7ec0f07f2e4 100644
--- a/intern/cycles/kernel/svm/svm_vector_transform.h
+++ b/intern/cycles/kernel/svm/svm_vector_transform.h
@@ -18,83 +18,90 @@ CCL_NAMESPACE_BEGIN
/* Vector Transform */
-ccl_device void svm_node_vector_transform(KernelGlobals *kg, ShaderData *sd, float *stack, uint4 node)
+ccl_device void svm_node_vector_transform(KernelGlobals *kg,
+ ShaderData *sd,
+ float *stack,
+ uint4 node)
{
- uint itype, ifrom, ito;
- uint vector_in, vector_out;
+ uint itype, ifrom, ito;
+ uint vector_in, vector_out;
- decode_node_uchar4(node.y, &itype, &ifrom, &ito, NULL);
- decode_node_uchar4(node.z, &vector_in, &vector_out, NULL, NULL);
+ decode_node_uchar4(node.y, &itype, &ifrom, &ito, NULL);
+ decode_node_uchar4(node.z, &vector_in, &vector_out, NULL, NULL);
- float3 in = stack_load_float3(stack, vector_in);
+ float3 in = stack_load_float3(stack, vector_in);
- NodeVectorTransformType type = (NodeVectorTransformType)itype;
- NodeVectorTransformConvertSpace from = (NodeVectorTransformConvertSpace)ifrom;
- NodeVectorTransformConvertSpace to = (NodeVectorTransformConvertSpace)ito;
+ NodeVectorTransformType type = (NodeVectorTransformType)itype;
+ NodeVectorTransformConvertSpace from = (NodeVectorTransformConvertSpace)ifrom;
+ NodeVectorTransformConvertSpace to = (NodeVectorTransformConvertSpace)ito;
- Transform tfm;
- bool is_object = (sd->object != OBJECT_NONE);
- bool is_direction = (type == NODE_VECTOR_TRANSFORM_TYPE_VECTOR || type == NODE_VECTOR_TRANSFORM_TYPE_NORMAL);
+ Transform tfm;
+ bool is_object = (sd->object != OBJECT_NONE);
+ bool is_direction = (type == NODE_VECTOR_TRANSFORM_TYPE_VECTOR ||
+ type == NODE_VECTOR_TRANSFORM_TYPE_NORMAL);
- /* From world */
- if(from == NODE_VECTOR_TRANSFORM_CONVERT_SPACE_WORLD) {
- if(to == NODE_VECTOR_TRANSFORM_CONVERT_SPACE_CAMERA) {
- tfm = kernel_data.cam.worldtocamera;
- if(is_direction)
- in = transform_direction(&tfm, in);
- else
- in = transform_point(&tfm, in);
- }
- else if(to == NODE_VECTOR_TRANSFORM_CONVERT_SPACE_OBJECT && is_object) {
- if(is_direction)
- object_inverse_dir_transform(kg, sd, &in);
- else
- object_inverse_position_transform(kg, sd, &in);
- }
- }
+ /* From world */
+ if (from == NODE_VECTOR_TRANSFORM_CONVERT_SPACE_WORLD) {
+ if (to == NODE_VECTOR_TRANSFORM_CONVERT_SPACE_CAMERA) {
+ tfm = kernel_data.cam.worldtocamera;
+ if (is_direction)
+ in = transform_direction(&tfm, in);
+ else
+ in = transform_point(&tfm, in);
+ }
+ else if (to == NODE_VECTOR_TRANSFORM_CONVERT_SPACE_OBJECT && is_object) {
+ if (is_direction)
+ object_inverse_dir_transform(kg, sd, &in);
+ else
+ object_inverse_position_transform(kg, sd, &in);
+ }
+ }
- /* From camera */
- else if(from == NODE_VECTOR_TRANSFORM_CONVERT_SPACE_CAMERA) {
- if(to == NODE_VECTOR_TRANSFORM_CONVERT_SPACE_WORLD || to == NODE_VECTOR_TRANSFORM_CONVERT_SPACE_OBJECT) {
- tfm = kernel_data.cam.cameratoworld;
- if(is_direction)
- in = transform_direction(&tfm, in);
- else
- in = transform_point(&tfm, in);
- }
- if(to == NODE_VECTOR_TRANSFORM_CONVERT_SPACE_OBJECT && is_object) {
- if(is_direction)
- object_inverse_dir_transform(kg, sd, &in);
- else
- object_inverse_position_transform(kg, sd, &in);
- }
- }
+ /* From camera */
+ else if (from == NODE_VECTOR_TRANSFORM_CONVERT_SPACE_CAMERA) {
+ if (to == NODE_VECTOR_TRANSFORM_CONVERT_SPACE_WORLD ||
+ to == NODE_VECTOR_TRANSFORM_CONVERT_SPACE_OBJECT) {
+ tfm = kernel_data.cam.cameratoworld;
+ if (is_direction)
+ in = transform_direction(&tfm, in);
+ else
+ in = transform_point(&tfm, in);
+ }
+ if (to == NODE_VECTOR_TRANSFORM_CONVERT_SPACE_OBJECT && is_object) {
+ if (is_direction)
+ object_inverse_dir_transform(kg, sd, &in);
+ else
+ object_inverse_position_transform(kg, sd, &in);
+ }
+ }
- /* From object */
- else if(from == NODE_VECTOR_TRANSFORM_CONVERT_SPACE_OBJECT) {
- if((to == NODE_VECTOR_TRANSFORM_CONVERT_SPACE_WORLD || to == NODE_VECTOR_TRANSFORM_CONVERT_SPACE_CAMERA) && is_object) {
- if(is_direction)
- object_dir_transform(kg, sd, &in);
- else
- object_position_transform(kg, sd, &in);
- }
- if(to == NODE_VECTOR_TRANSFORM_CONVERT_SPACE_CAMERA) {
- tfm = kernel_data.cam.worldtocamera;
- if(is_direction)
- in = transform_direction(&tfm, in);
- else
- in = transform_point(&tfm, in);
- }
- }
+ /* From object */
+ else if (from == NODE_VECTOR_TRANSFORM_CONVERT_SPACE_OBJECT) {
+ if ((to == NODE_VECTOR_TRANSFORM_CONVERT_SPACE_WORLD ||
+ to == NODE_VECTOR_TRANSFORM_CONVERT_SPACE_CAMERA) &&
+ is_object) {
+ if (is_direction)
+ object_dir_transform(kg, sd, &in);
+ else
+ object_position_transform(kg, sd, &in);
+ }
+ if (to == NODE_VECTOR_TRANSFORM_CONVERT_SPACE_CAMERA) {
+ tfm = kernel_data.cam.worldtocamera;
+ if (is_direction)
+ in = transform_direction(&tfm, in);
+ else
+ in = transform_point(&tfm, in);
+ }
+ }
- /* Normalize Normal */
- if(type == NODE_VECTOR_TRANSFORM_TYPE_NORMAL)
- in = normalize(in);
+ /* Normalize Normal */
+ if (type == NODE_VECTOR_TRANSFORM_TYPE_NORMAL)
+ in = normalize(in);
- /* Output */
- if(stack_valid(vector_out)) {
- stack_store_float3(stack, vector_out, in);
- }
+ /* Output */
+ if (stack_valid(vector_out)) {
+ stack_store_float3(stack, vector_out, in);
+ }
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/svm/svm_voronoi.h b/intern/cycles/kernel/svm/svm_voronoi.h
index d661df54ead..c311aefaf38 100644
--- a/intern/cycles/kernel/svm/svm_voronoi.h
+++ b/intern/cycles/kernel/svm/svm_voronoi.h
@@ -18,143 +18,167 @@ CCL_NAMESPACE_BEGIN
/* Voronoi */
-ccl_device void voronoi_neighbors(float3 p, NodeVoronoiDistanceMetric distance, float e, float da[4], float3 pa[4])
+ccl_device void voronoi_neighbors(
+ float3 p, NodeVoronoiDistanceMetric distance, float e, float da[4], float3 pa[4])
{
- /* Compute the distance to and the position of the closest neighbors to p.
- *
- * The neighbors are randomly placed, 1 each in a 3x3x3 grid (Worley pattern).
- * The distances and points are returned in ascending order, i.e. da[0] and pa[0] will
- * contain the distance to the closest point and its coordinates respectively.
- */
-
- da[0] = 1e10f;
- da[1] = 1e10f;
- da[2] = 1e10f;
- da[3] = 1e10f;
-
- pa[0] = make_float3(0.0f, 0.0f, 0.0f);
- pa[1] = make_float3(0.0f, 0.0f, 0.0f);
- pa[2] = make_float3(0.0f, 0.0f, 0.0f);
- pa[3] = make_float3(0.0f, 0.0f, 0.0f);
-
- int3 xyzi = quick_floor_to_int3(p);
-
- for(int xx = -1; xx <= 1; xx++) {
- for(int yy = -1; yy <= 1; yy++) {
- for(int zz = -1; zz <= 1; zz++) {
- int3 ip = xyzi + make_int3(xx, yy, zz);
- float3 fp = make_float3(ip.x, ip.y, ip.z);
- float3 vp = fp + cellnoise3(fp);
-
- float d;
- switch(distance) {
- case NODE_VORONOI_DISTANCE:
- d = len_squared(p - vp);
- break;
- case NODE_VORONOI_MANHATTAN:
- d = reduce_add(fabs(vp - p));
- break;
- case NODE_VORONOI_CHEBYCHEV:
- d = max3(fabs(vp - p));
- break;
- case NODE_VORONOI_MINKOWSKI: {
- float3 n = fabs(vp - p);
- if(e == 0.5f) {
- d = sqr(reduce_add(sqrt(n)));
- }
- else {
- d = powf(reduce_add(pow3(n, e)), 1.0f/e);
- }
- break;
- }
- }
-
- /* To keep the shortest four distances and associated points we have to keep them in sorted order. */
- if(d < da[0]) {
- da[3] = da[2];
- da[2] = da[1];
- da[1] = da[0];
- da[0] = d;
-
- pa[3] = pa[2];
- pa[2] = pa[1];
- pa[1] = pa[0];
- pa[0] = vp;
- }
- else if(d < da[1]) {
- da[3] = da[2];
- da[2] = da[1];
- da[1] = d;
-
- pa[3] = pa[2];
- pa[2] = pa[1];
- pa[1] = vp;
- }
- else if(d < da[2]) {
- da[3] = da[2];
- da[2] = d;
-
- pa[3] = pa[2];
- pa[2] = vp;
- }
- else if(d < da[3]) {
- da[3] = d;
- pa[3] = vp;
- }
- }
- }
- }
+ /* Compute the distance to and the position of the closest neighbors to p.
+ *
+ * The neighbors are randomly placed, 1 each in a 3x3x3 grid (Worley pattern).
+ * The distances and points are returned in ascending order, i.e. da[0] and pa[0] will
+ * contain the distance to the closest point and its coordinates respectively.
+ */
+
+ da[0] = 1e10f;
+ da[1] = 1e10f;
+ da[2] = 1e10f;
+ da[3] = 1e10f;
+
+ pa[0] = make_float3(0.0f, 0.0f, 0.0f);
+ pa[1] = make_float3(0.0f, 0.0f, 0.0f);
+ pa[2] = make_float3(0.0f, 0.0f, 0.0f);
+ pa[3] = make_float3(0.0f, 0.0f, 0.0f);
+
+ int3 xyzi = quick_floor_to_int3(p);
+
+ for (int xx = -1; xx <= 1; xx++) {
+ for (int yy = -1; yy <= 1; yy++) {
+ for (int zz = -1; zz <= 1; zz++) {
+ int3 ip = xyzi + make_int3(xx, yy, zz);
+ float3 fp = make_float3(ip.x, ip.y, ip.z);
+ float3 vp = fp + cellnoise3(fp);
+
+ float d;
+ switch (distance) {
+ case NODE_VORONOI_DISTANCE:
+ d = len_squared(p - vp);
+ break;
+ case NODE_VORONOI_MANHATTAN:
+ d = reduce_add(fabs(vp - p));
+ break;
+ case NODE_VORONOI_CHEBYCHEV:
+ d = max3(fabs(vp - p));
+ break;
+ case NODE_VORONOI_MINKOWSKI: {
+ float3 n = fabs(vp - p);
+ if (e == 0.5f) {
+ d = sqr(reduce_add(sqrt(n)));
+ }
+ else {
+ d = powf(reduce_add(pow3(n, e)), 1.0f / e);
+ }
+ break;
+ }
+ }
+
+ /* To keep the shortest four distances and associated points we have to keep them in sorted order. */
+ if (d < da[0]) {
+ da[3] = da[2];
+ da[2] = da[1];
+ da[1] = da[0];
+ da[0] = d;
+
+ pa[3] = pa[2];
+ pa[2] = pa[1];
+ pa[1] = pa[0];
+ pa[0] = vp;
+ }
+ else if (d < da[1]) {
+ da[3] = da[2];
+ da[2] = da[1];
+ da[1] = d;
+
+ pa[3] = pa[2];
+ pa[2] = pa[1];
+ pa[1] = vp;
+ }
+ else if (d < da[2]) {
+ da[3] = da[2];
+ da[2] = d;
+
+ pa[3] = pa[2];
+ pa[2] = vp;
+ }
+ else if (d < da[3]) {
+ da[3] = d;
+ pa[3] = vp;
+ }
+ }
+ }
+ }
}
-ccl_device void svm_node_tex_voronoi(KernelGlobals *kg, ShaderData *sd, float *stack, uint4 node, int *offset)
+ccl_device void svm_node_tex_voronoi(
+ KernelGlobals *kg, ShaderData *sd, float *stack, uint4 node, int *offset)
{
- uint4 node2 = read_node(kg, offset);
-
- uint co_offset, coloring, distance, feature;
- uint scale_offset, e_offset, fac_offset, color_offset;
-
- decode_node_uchar4(node.y, &co_offset, &coloring, &distance, &feature);
- decode_node_uchar4(node.z, &scale_offset, &e_offset, &fac_offset, &color_offset);
-
- float3 co = stack_load_float3(stack, co_offset);
- float scale = stack_load_float_default(stack, scale_offset, node2.x);
- float exponent = stack_load_float_default(stack, e_offset, node2.y);
-
- float dist[4];
- float3 neighbor[4];
- voronoi_neighbors(co*scale, (NodeVoronoiDistanceMetric)distance, exponent, dist, neighbor);
-
- float3 color;
- float fac;
- if(coloring == NODE_VORONOI_INTENSITY) {
- switch(feature) {
- case NODE_VORONOI_F1: fac = dist[0]; break;
- case NODE_VORONOI_F2: fac = dist[1]; break;
- case NODE_VORONOI_F3: fac = dist[2]; break;
- case NODE_VORONOI_F4: fac = dist[3]; break;
- case NODE_VORONOI_F2F1: fac = dist[1] - dist[0]; break;
- }
-
- color = make_float3(fac, fac, fac);
- }
- else {
- /* NODE_VORONOI_CELLS */
- switch(feature) {
- case NODE_VORONOI_F1: color = neighbor[0]; break;
- case NODE_VORONOI_F2: color = neighbor[1]; break;
- case NODE_VORONOI_F3: color = neighbor[2]; break;
- case NODE_VORONOI_F4: color = neighbor[3]; break;
- /* Usefulness of this vector is questionable. Note F2 >= F1 but the
- * individual vector components might not be. */
- case NODE_VORONOI_F2F1: color = fabs(neighbor[1] - neighbor[0]); break;
- }
-
- color = cellnoise3(color);
- fac = average(color);
- }
-
- if(stack_valid(fac_offset)) stack_store_float(stack, fac_offset, fac);
- if(stack_valid(color_offset)) stack_store_float3(stack, color_offset, color);
+ uint4 node2 = read_node(kg, offset);
+
+ uint co_offset, coloring, distance, feature;
+ uint scale_offset, e_offset, fac_offset, color_offset;
+
+ decode_node_uchar4(node.y, &co_offset, &coloring, &distance, &feature);
+ decode_node_uchar4(node.z, &scale_offset, &e_offset, &fac_offset, &color_offset);
+
+ float3 co = stack_load_float3(stack, co_offset);
+ float scale = stack_load_float_default(stack, scale_offset, node2.x);
+ float exponent = stack_load_float_default(stack, e_offset, node2.y);
+
+ float dist[4];
+ float3 neighbor[4];
+ voronoi_neighbors(co * scale, (NodeVoronoiDistanceMetric)distance, exponent, dist, neighbor);
+
+ float3 color;
+ float fac;
+ if (coloring == NODE_VORONOI_INTENSITY) {
+ switch (feature) {
+ case NODE_VORONOI_F1:
+ fac = dist[0];
+ break;
+ case NODE_VORONOI_F2:
+ fac = dist[1];
+ break;
+ case NODE_VORONOI_F3:
+ fac = dist[2];
+ break;
+ case NODE_VORONOI_F4:
+ fac = dist[3];
+ break;
+ case NODE_VORONOI_F2F1:
+ fac = dist[1] - dist[0];
+ break;
+ }
+
+ color = make_float3(fac, fac, fac);
+ }
+ else {
+ /* NODE_VORONOI_CELLS */
+ switch (feature) {
+ case NODE_VORONOI_F1:
+ color = neighbor[0];
+ break;
+ case NODE_VORONOI_F2:
+ color = neighbor[1];
+ break;
+ case NODE_VORONOI_F3:
+ color = neighbor[2];
+ break;
+ case NODE_VORONOI_F4:
+ color = neighbor[3];
+ break;
+ /* Usefulness of this vector is questionable. Note F2 >= F1 but the
+ * individual vector components might not be. */
+ case NODE_VORONOI_F2F1:
+ color = fabs(neighbor[1] - neighbor[0]);
+ break;
+ }
+
+ color = cellnoise3(color);
+ fac = average(color);
+ }
+
+ if (stack_valid(fac_offset))
+ stack_store_float(stack, fac_offset, fac);
+ if (stack_valid(color_offset))
+ stack_store_float3(stack, color_offset, color);
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/svm/svm_voxel.h b/intern/cycles/kernel/svm/svm_voxel.h
index 43b433683e0..26d8cc71d3b 100644
--- a/intern/cycles/kernel/svm/svm_voxel.h
+++ b/intern/cycles/kernel/svm/svm_voxel.h
@@ -19,37 +19,34 @@ CCL_NAMESPACE_BEGIN
/* TODO(sergey): Think of making it more generic volume-type attribute
* sampler.
*/
-ccl_device void svm_node_tex_voxel(KernelGlobals *kg,
- ShaderData *sd,
- float *stack,
- uint4 node,
- int *offset)
+ccl_device void svm_node_tex_voxel(
+ KernelGlobals *kg, ShaderData *sd, float *stack, uint4 node, int *offset)
{
- uint co_offset, density_out_offset, color_out_offset, space;
- decode_node_uchar4(node.z, &co_offset, &density_out_offset, &color_out_offset, &space);
+ uint co_offset, density_out_offset, color_out_offset, space;
+ decode_node_uchar4(node.z, &co_offset, &density_out_offset, &color_out_offset, &space);
#ifdef __VOLUME__
- int id = node.y;
- float3 co = stack_load_float3(stack, co_offset);
- if(space == NODE_TEX_VOXEL_SPACE_OBJECT) {
- co = volume_normalized_position(kg, sd, co);
- }
- else {
- kernel_assert(space == NODE_TEX_VOXEL_SPACE_WORLD);
- Transform tfm;
- tfm.x = read_node_float(kg, offset);
- tfm.y = read_node_float(kg, offset);
- tfm.z = read_node_float(kg, offset);
- co = transform_point(&tfm, co);
- }
+ int id = node.y;
+ float3 co = stack_load_float3(stack, co_offset);
+ if (space == NODE_TEX_VOXEL_SPACE_OBJECT) {
+ co = volume_normalized_position(kg, sd, co);
+ }
+ else {
+ kernel_assert(space == NODE_TEX_VOXEL_SPACE_WORLD);
+ Transform tfm;
+ tfm.x = read_node_float(kg, offset);
+ tfm.y = read_node_float(kg, offset);
+ tfm.z = read_node_float(kg, offset);
+ co = transform_point(&tfm, co);
+ }
- float4 r = kernel_tex_image_interp_3d(kg, id, co.x, co.y, co.z, INTERPOLATION_NONE);
+ float4 r = kernel_tex_image_interp_3d(kg, id, co.x, co.y, co.z, INTERPOLATION_NONE);
#else
- float4 r = make_float4(0.0f, 0.0f, 0.0f, 0.0f);
+ float4 r = make_float4(0.0f, 0.0f, 0.0f, 0.0f);
#endif
- if(stack_valid(density_out_offset))
- stack_store_float(stack, density_out_offset, r.w);
- if(stack_valid(color_out_offset))
- stack_store_float3(stack, color_out_offset, make_float3(r.x, r.y, r.z));
+ if (stack_valid(density_out_offset))
+ stack_store_float(stack, density_out_offset, r.w);
+ if (stack_valid(color_out_offset))
+ stack_store_float3(stack, color_out_offset, make_float3(r.x, r.y, r.z));
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/svm/svm_wave.h b/intern/cycles/kernel/svm/svm_wave.h
index 80b63dc80cd..003ad7dc63a 100644
--- a/intern/cycles/kernel/svm/svm_wave.h
+++ b/intern/cycles/kernel/svm/svm_wave.h
@@ -18,48 +18,58 @@ CCL_NAMESPACE_BEGIN
/* Wave */
-ccl_device_noinline float svm_wave(NodeWaveType type, NodeWaveProfile profile, float3 p, float detail, float distortion, float dscale)
+ccl_device_noinline float svm_wave(NodeWaveType type,
+ NodeWaveProfile profile,
+ float3 p,
+ float detail,
+ float distortion,
+ float dscale)
{
- float n;
+ float n;
- if(type == NODE_WAVE_BANDS)
- n = (p.x + p.y + p.z) * 10.0f;
- else /* NODE_WAVE_RINGS */
- n = len(p) * 20.0f;
+ if (type == NODE_WAVE_BANDS)
+ n = (p.x + p.y + p.z) * 10.0f;
+ else /* NODE_WAVE_RINGS */
+ n = len(p) * 20.0f;
- if(distortion != 0.0f)
- n += distortion * noise_turbulence(p*dscale, detail, 0);
+ if (distortion != 0.0f)
+ n += distortion * noise_turbulence(p * dscale, detail, 0);
- if(profile == NODE_WAVE_PROFILE_SIN) {
- return 0.5f + 0.5f * sinf(n);
- }
- else { /* NODE_WAVE_PROFILE_SAW */
- n /= M_2PI_F;
- n -= (int) n;
- return (n < 0.0f)? n + 1.0f: n;
- }
+ if (profile == NODE_WAVE_PROFILE_SIN) {
+ return 0.5f + 0.5f * sinf(n);
+ }
+ else { /* NODE_WAVE_PROFILE_SAW */
+ n /= M_2PI_F;
+ n -= (int)n;
+ return (n < 0.0f) ? n + 1.0f : n;
+ }
}
-ccl_device void svm_node_tex_wave(KernelGlobals *kg, ShaderData *sd, float *stack, uint4 node, int *offset)
+ccl_device void svm_node_tex_wave(
+ KernelGlobals *kg, ShaderData *sd, float *stack, uint4 node, int *offset)
{
- uint4 node2 = read_node(kg, offset);
+ uint4 node2 = read_node(kg, offset);
- uint type;
- uint co_offset, scale_offset, detail_offset, dscale_offset, distortion_offset, color_offset, fac_offset;
+ uint type;
+ uint co_offset, scale_offset, detail_offset, dscale_offset, distortion_offset, color_offset,
+ fac_offset;
- decode_node_uchar4(node.y, &type, &color_offset, &fac_offset, &dscale_offset);
- decode_node_uchar4(node.z, &co_offset, &scale_offset, &detail_offset, &distortion_offset);
+ decode_node_uchar4(node.y, &type, &color_offset, &fac_offset, &dscale_offset);
+ decode_node_uchar4(node.z, &co_offset, &scale_offset, &detail_offset, &distortion_offset);
- float3 co = stack_load_float3(stack, co_offset);
- float scale = stack_load_float_default(stack, scale_offset, node2.x);
- float detail = stack_load_float_default(stack, detail_offset, node2.y);
- float distortion = stack_load_float_default(stack, distortion_offset, node2.z);
- float dscale = stack_load_float_default(stack, dscale_offset, node2.w);
+ float3 co = stack_load_float3(stack, co_offset);
+ float scale = stack_load_float_default(stack, scale_offset, node2.x);
+ float detail = stack_load_float_default(stack, detail_offset, node2.y);
+ float distortion = stack_load_float_default(stack, distortion_offset, node2.z);
+ float dscale = stack_load_float_default(stack, dscale_offset, node2.w);
- float f = svm_wave((NodeWaveType)type, (NodeWaveProfile)node.w, co*scale, detail, distortion, dscale);
+ float f = svm_wave(
+ (NodeWaveType)type, (NodeWaveProfile)node.w, co * scale, detail, distortion, dscale);
- if(stack_valid(fac_offset)) stack_store_float(stack, fac_offset, f);
- if(stack_valid(color_offset)) stack_store_float3(stack, color_offset, make_float3(f, f, f));
+ if (stack_valid(fac_offset))
+ stack_store_float(stack, fac_offset, f);
+ if (stack_valid(color_offset))
+ stack_store_float3(stack, color_offset, make_float3(f, f, f));
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/svm/svm_wavelength.h b/intern/cycles/kernel/svm/svm_wavelength.h
index e935fd20690..d6144802559 100644
--- a/intern/cycles/kernel/svm/svm_wavelength.h
+++ b/intern/cycles/kernel/svm/svm_wavelength.h
@@ -10,13 +10,13 @@
* modification, are permitted provided that the following conditions are
* met:
* * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
+ * notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
* * Neither the name of Sony Pictures Imageworks nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
@@ -35,64 +35,64 @@ CCL_NAMESPACE_BEGIN
/* Wavelength to RGB */
// CIE colour matching functions xBar, yBar, and zBar for
-// wavelengths from 380 through 780 nanometers, every 5
-// nanometers. For a wavelength lambda in this range:
-// cie_colour_match[(lambda - 380) / 5][0] = xBar
-// cie_colour_match[(lambda - 380) / 5][1] = yBar
-// cie_colour_match[(lambda - 380) / 5][2] = zBar
+// wavelengths from 380 through 780 nanometers, every 5
+// nanometers. For a wavelength lambda in this range:
+// cie_colour_match[(lambda - 380) / 5][0] = xBar
+// cie_colour_match[(lambda - 380) / 5][1] = yBar
+// cie_colour_match[(lambda - 380) / 5][2] = zBar
ccl_static_constant float cie_colour_match[81][3] = {
- {0.0014f,0.0000f,0.0065f}, {0.0022f,0.0001f,0.0105f}, {0.0042f,0.0001f,0.0201f},
- {0.0076f,0.0002f,0.0362f}, {0.0143f,0.0004f,0.0679f}, {0.0232f,0.0006f,0.1102f},
- {0.0435f,0.0012f,0.2074f}, {0.0776f,0.0022f,0.3713f}, {0.1344f,0.0040f,0.6456f},
- {0.2148f,0.0073f,1.0391f}, {0.2839f,0.0116f,1.3856f}, {0.3285f,0.0168f,1.6230f},
- {0.3483f,0.0230f,1.7471f}, {0.3481f,0.0298f,1.7826f}, {0.3362f,0.0380f,1.7721f},
- {0.3187f,0.0480f,1.7441f}, {0.2908f,0.0600f,1.6692f}, {0.2511f,0.0739f,1.5281f},
- {0.1954f,0.0910f,1.2876f}, {0.1421f,0.1126f,1.0419f}, {0.0956f,0.1390f,0.8130f},
- {0.0580f,0.1693f,0.6162f}, {0.0320f,0.2080f,0.4652f}, {0.0147f,0.2586f,0.3533f},
- {0.0049f,0.3230f,0.2720f}, {0.0024f,0.4073f,0.2123f}, {0.0093f,0.5030f,0.1582f},
- {0.0291f,0.6082f,0.1117f}, {0.0633f,0.7100f,0.0782f}, {0.1096f,0.7932f,0.0573f},
- {0.1655f,0.8620f,0.0422f}, {0.2257f,0.9149f,0.0298f}, {0.2904f,0.9540f,0.0203f},
- {0.3597f,0.9803f,0.0134f}, {0.4334f,0.9950f,0.0087f}, {0.5121f,1.0000f,0.0057f},
- {0.5945f,0.9950f,0.0039f}, {0.6784f,0.9786f,0.0027f}, {0.7621f,0.9520f,0.0021f},
- {0.8425f,0.9154f,0.0018f}, {0.9163f,0.8700f,0.0017f}, {0.9786f,0.8163f,0.0014f},
- {1.0263f,0.7570f,0.0011f}, {1.0567f,0.6949f,0.0010f}, {1.0622f,0.6310f,0.0008f},
- {1.0456f,0.5668f,0.0006f}, {1.0026f,0.5030f,0.0003f}, {0.9384f,0.4412f,0.0002f},
- {0.8544f,0.3810f,0.0002f}, {0.7514f,0.3210f,0.0001f}, {0.6424f,0.2650f,0.0000f},
- {0.5419f,0.2170f,0.0000f}, {0.4479f,0.1750f,0.0000f}, {0.3608f,0.1382f,0.0000f},
- {0.2835f,0.1070f,0.0000f}, {0.2187f,0.0816f,0.0000f}, {0.1649f,0.0610f,0.0000f},
- {0.1212f,0.0446f,0.0000f}, {0.0874f,0.0320f,0.0000f}, {0.0636f,0.0232f,0.0000f},
- {0.0468f,0.0170f,0.0000f}, {0.0329f,0.0119f,0.0000f}, {0.0227f,0.0082f,0.0000f},
- {0.0158f,0.0057f,0.0000f}, {0.0114f,0.0041f,0.0000f}, {0.0081f,0.0029f,0.0000f},
- {0.0058f,0.0021f,0.0000f}, {0.0041f,0.0015f,0.0000f}, {0.0029f,0.0010f,0.0000f},
- {0.0020f,0.0007f,0.0000f}, {0.0014f,0.0005f,0.0000f}, {0.0010f,0.0004f,0.0000f},
- {0.0007f,0.0002f,0.0000f}, {0.0005f,0.0002f,0.0000f}, {0.0003f,0.0001f,0.0000f},
- {0.0002f,0.0001f,0.0000f}, {0.0002f,0.0001f,0.0000f}, {0.0001f,0.0000f,0.0000f},
- {0.0001f,0.0000f,0.0000f}, {0.0001f,0.0000f,0.0000f}, {0.0000f,0.0000f,0.0000f}
-};
+ {0.0014f, 0.0000f, 0.0065f}, {0.0022f, 0.0001f, 0.0105f}, {0.0042f, 0.0001f, 0.0201f},
+ {0.0076f, 0.0002f, 0.0362f}, {0.0143f, 0.0004f, 0.0679f}, {0.0232f, 0.0006f, 0.1102f},
+ {0.0435f, 0.0012f, 0.2074f}, {0.0776f, 0.0022f, 0.3713f}, {0.1344f, 0.0040f, 0.6456f},
+ {0.2148f, 0.0073f, 1.0391f}, {0.2839f, 0.0116f, 1.3856f}, {0.3285f, 0.0168f, 1.6230f},
+ {0.3483f, 0.0230f, 1.7471f}, {0.3481f, 0.0298f, 1.7826f}, {0.3362f, 0.0380f, 1.7721f},
+ {0.3187f, 0.0480f, 1.7441f}, {0.2908f, 0.0600f, 1.6692f}, {0.2511f, 0.0739f, 1.5281f},
+ {0.1954f, 0.0910f, 1.2876f}, {0.1421f, 0.1126f, 1.0419f}, {0.0956f, 0.1390f, 0.8130f},
+ {0.0580f, 0.1693f, 0.6162f}, {0.0320f, 0.2080f, 0.4652f}, {0.0147f, 0.2586f, 0.3533f},
+ {0.0049f, 0.3230f, 0.2720f}, {0.0024f, 0.4073f, 0.2123f}, {0.0093f, 0.5030f, 0.1582f},
+ {0.0291f, 0.6082f, 0.1117f}, {0.0633f, 0.7100f, 0.0782f}, {0.1096f, 0.7932f, 0.0573f},
+ {0.1655f, 0.8620f, 0.0422f}, {0.2257f, 0.9149f, 0.0298f}, {0.2904f, 0.9540f, 0.0203f},
+ {0.3597f, 0.9803f, 0.0134f}, {0.4334f, 0.9950f, 0.0087f}, {0.5121f, 1.0000f, 0.0057f},
+ {0.5945f, 0.9950f, 0.0039f}, {0.6784f, 0.9786f, 0.0027f}, {0.7621f, 0.9520f, 0.0021f},
+ {0.8425f, 0.9154f, 0.0018f}, {0.9163f, 0.8700f, 0.0017f}, {0.9786f, 0.8163f, 0.0014f},
+ {1.0263f, 0.7570f, 0.0011f}, {1.0567f, 0.6949f, 0.0010f}, {1.0622f, 0.6310f, 0.0008f},
+ {1.0456f, 0.5668f, 0.0006f}, {1.0026f, 0.5030f, 0.0003f}, {0.9384f, 0.4412f, 0.0002f},
+ {0.8544f, 0.3810f, 0.0002f}, {0.7514f, 0.3210f, 0.0001f}, {0.6424f, 0.2650f, 0.0000f},
+ {0.5419f, 0.2170f, 0.0000f}, {0.4479f, 0.1750f, 0.0000f}, {0.3608f, 0.1382f, 0.0000f},
+ {0.2835f, 0.1070f, 0.0000f}, {0.2187f, 0.0816f, 0.0000f}, {0.1649f, 0.0610f, 0.0000f},
+ {0.1212f, 0.0446f, 0.0000f}, {0.0874f, 0.0320f, 0.0000f}, {0.0636f, 0.0232f, 0.0000f},
+ {0.0468f, 0.0170f, 0.0000f}, {0.0329f, 0.0119f, 0.0000f}, {0.0227f, 0.0082f, 0.0000f},
+ {0.0158f, 0.0057f, 0.0000f}, {0.0114f, 0.0041f, 0.0000f}, {0.0081f, 0.0029f, 0.0000f},
+ {0.0058f, 0.0021f, 0.0000f}, {0.0041f, 0.0015f, 0.0000f}, {0.0029f, 0.0010f, 0.0000f},
+ {0.0020f, 0.0007f, 0.0000f}, {0.0014f, 0.0005f, 0.0000f}, {0.0010f, 0.0004f, 0.0000f},
+ {0.0007f, 0.0002f, 0.0000f}, {0.0005f, 0.0002f, 0.0000f}, {0.0003f, 0.0001f, 0.0000f},
+ {0.0002f, 0.0001f, 0.0000f}, {0.0002f, 0.0001f, 0.0000f}, {0.0001f, 0.0000f, 0.0000f},
+ {0.0001f, 0.0000f, 0.0000f}, {0.0001f, 0.0000f, 0.0000f}, {0.0000f, 0.0000f, 0.0000f}};
-ccl_device void svm_node_wavelength(KernelGlobals *kg, ShaderData *sd, float *stack, uint wavelength, uint color_out)
+ccl_device void svm_node_wavelength(
+ KernelGlobals *kg, ShaderData *sd, float *stack, uint wavelength, uint color_out)
{
- float lambda_nm = stack_load_float(stack, wavelength);
- float ii = (lambda_nm-380.0f) * (1.0f/5.0f); // scaled 0..80
- int i = float_to_int(ii);
- float3 color;
+ float lambda_nm = stack_load_float(stack, wavelength);
+ float ii = (lambda_nm - 380.0f) * (1.0f / 5.0f); // scaled 0..80
+ int i = float_to_int(ii);
+ float3 color;
- if(i < 0 || i >= 80) {
- color = make_float3(0.0f, 0.0f, 0.0f);
- }
- else {
- ii -= i;
- ccl_constant float *c = cie_colour_match[i];
- color = interp(make_float3(c[0], c[1], c[2]), make_float3(c[3], c[4], c[5]), ii);
- }
+ if (i < 0 || i >= 80) {
+ color = make_float3(0.0f, 0.0f, 0.0f);
+ }
+ else {
+ ii -= i;
+ ccl_constant float *c = cie_colour_match[i];
+ color = interp(make_float3(c[0], c[1], c[2]), make_float3(c[3], c[4], c[5]), ii);
+ }
- color = xyz_to_rgb(kg, color);
- color *= 1.0f/2.52f; // Empirical scale from lg to make all comps <= 1
+ color = xyz_to_rgb(kg, color);
+ color *= 1.0f / 2.52f; // Empirical scale from lg to make all comps <= 1
- /* Clamp to zero if values are smaller */
- color = max(color, make_float3(0.0f, 0.0f, 0.0f));
+ /* Clamp to zero if values are smaller */
+ color = max(color, make_float3(0.0f, 0.0f, 0.0f));
- stack_store_float3(stack, color_out, color);
+ stack_store_float3(stack, color_out, color);
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/svm/svm_wireframe.h b/intern/cycles/kernel/svm/svm_wireframe.h
index 35df9e8a0e7..55e61d0e8c7 100644
--- a/intern/cycles/kernel/svm/svm_wireframe.h
+++ b/intern/cycles/kernel/svm/svm_wireframe.h
@@ -34,103 +34,97 @@ CCL_NAMESPACE_BEGIN
/* Wireframe Node */
-ccl_device_inline float wireframe(KernelGlobals *kg,
- ShaderData *sd,
- float size,
- int pixel_size,
- float3 *P)
+ccl_device_inline float wireframe(
+ KernelGlobals *kg, ShaderData *sd, float size, int pixel_size, float3 *P)
{
#ifdef __HAIR__
- if(sd->prim != PRIM_NONE && sd->type & PRIMITIVE_ALL_TRIANGLE)
+ if (sd->prim != PRIM_NONE && sd->type & PRIMITIVE_ALL_TRIANGLE)
#else
- if(sd->prim != PRIM_NONE)
+ if (sd->prim != PRIM_NONE)
#endif
- {
- float3 Co[3];
- float pixelwidth = 1.0f;
+ {
+ float3 Co[3];
+ float pixelwidth = 1.0f;
- /* Triangles */
- int np = 3;
+ /* Triangles */
+ int np = 3;
- if(sd->type & PRIMITIVE_TRIANGLE)
- triangle_vertices(kg, sd->prim, Co);
- else
- motion_triangle_vertices(kg, sd->object, sd->prim, sd->time, Co);
+ if (sd->type & PRIMITIVE_TRIANGLE)
+ triangle_vertices(kg, sd->prim, Co);
+ else
+ motion_triangle_vertices(kg, sd->object, sd->prim, sd->time, Co);
- if(!(sd->object_flag & SD_OBJECT_TRANSFORM_APPLIED)) {
- object_position_transform(kg, sd, &Co[0]);
- object_position_transform(kg, sd, &Co[1]);
- object_position_transform(kg, sd, &Co[2]);
- }
+ if (!(sd->object_flag & SD_OBJECT_TRANSFORM_APPLIED)) {
+ object_position_transform(kg, sd, &Co[0]);
+ object_position_transform(kg, sd, &Co[1]);
+ object_position_transform(kg, sd, &Co[2]);
+ }
- if(pixel_size) {
- // Project the derivatives of P to the viewing plane defined
- // by I so we have a measure of how big is a pixel at this point
- float pixelwidth_x = len(sd->dP.dx - dot(sd->dP.dx, sd->I) * sd->I);
- float pixelwidth_y = len(sd->dP.dy - dot(sd->dP.dy, sd->I) * sd->I);
- // Take the average of both axis' length
- pixelwidth = (pixelwidth_x + pixelwidth_y) * 0.5f;
- }
+ if (pixel_size) {
+ // Project the derivatives of P to the viewing plane defined
+ // by I so we have a measure of how big is a pixel at this point
+ float pixelwidth_x = len(sd->dP.dx - dot(sd->dP.dx, sd->I) * sd->I);
+ float pixelwidth_y = len(sd->dP.dy - dot(sd->dP.dy, sd->I) * sd->I);
+ // Take the average of both axis' length
+ pixelwidth = (pixelwidth_x + pixelwidth_y) * 0.5f;
+ }
- // Use half the width as the neighbor face will render the
- // other half. And take the square for fast comparison
- pixelwidth *= 0.5f * size;
- pixelwidth *= pixelwidth;
- for(int i = 0; i < np; i++) {
- int i2 = i ? i - 1 : np - 1;
- float3 dir = *P - Co[i];
- float3 edge = Co[i] - Co[i2];
- float3 crs = cross(edge, dir);
- // At this point dot(crs, crs) / dot(edge, edge) is
- // the square of area / length(edge) == square of the
- // distance to the edge.
- if(dot(crs, crs) < (dot(edge, edge) * pixelwidth))
- return 1.0f;
- }
- }
- return 0.0f;
+ // Use half the width as the neighbor face will render the
+ // other half. And take the square for fast comparison
+ pixelwidth *= 0.5f * size;
+ pixelwidth *= pixelwidth;
+ for (int i = 0; i < np; i++) {
+ int i2 = i ? i - 1 : np - 1;
+ float3 dir = *P - Co[i];
+ float3 edge = Co[i] - Co[i2];
+ float3 crs = cross(edge, dir);
+ // At this point dot(crs, crs) / dot(edge, edge) is
+ // the square of area / length(edge) == square of the
+ // distance to the edge.
+ if (dot(crs, crs) < (dot(edge, edge) * pixelwidth))
+ return 1.0f;
+ }
+ }
+ return 0.0f;
}
-ccl_device void svm_node_wireframe(KernelGlobals *kg,
- ShaderData *sd,
- float *stack,
- uint4 node)
+ccl_device void svm_node_wireframe(KernelGlobals *kg, ShaderData *sd, float *stack, uint4 node)
{
- uint in_size = node.y;
- uint out_fac = node.z;
- uint use_pixel_size, bump_offset;
- decode_node_uchar4(node.w, &use_pixel_size, &bump_offset, NULL, NULL);
+ uint in_size = node.y;
+ uint out_fac = node.z;
+ uint use_pixel_size, bump_offset;
+ decode_node_uchar4(node.w, &use_pixel_size, &bump_offset, NULL, NULL);
- /* Input Data */
- float size = stack_load_float(stack, in_size);
- int pixel_size = (int)use_pixel_size;
+ /* Input Data */
+ float size = stack_load_float(stack, in_size);
+ int pixel_size = (int)use_pixel_size;
- /* Calculate wireframe */
+ /* Calculate wireframe */
#ifdef __SPLIT_KERNEL__
- /* TODO(sergey): This is because sd is actually a global space,
- * which makes it difficult to re-use same wireframe() function.
- *
- * With OpenCL 2.0 it's possible to avoid this change, but for until
- * then we'll be living with such an exception.
- */
- float3 P = sd->P;
- float f = wireframe(kg, sd, size, pixel_size, &P);
+ /* TODO(sergey): This is because sd is actually a global space,
+ * which makes it difficult to re-use same wireframe() function.
+ *
+ * With OpenCL 2.0 it's possible to avoid this change, but for until
+ * then we'll be living with such an exception.
+ */
+ float3 P = sd->P;
+ float f = wireframe(kg, sd, size, pixel_size, &P);
#else
- float f = wireframe(kg, sd, size, pixel_size, &sd->P);
+ float f = wireframe(kg, sd, size, pixel_size, &sd->P);
#endif
- /* TODO(sergey): Think of faster way to calculate derivatives. */
- if(bump_offset == NODE_BUMP_OFFSET_DX) {
- float3 Px = sd->P - sd->dP.dx;
- f += (f - wireframe(kg, sd, size, pixel_size, &Px)) / len(sd->dP.dx);
- }
- else if(bump_offset == NODE_BUMP_OFFSET_DY) {
- float3 Py = sd->P - sd->dP.dy;
- f += (f - wireframe(kg, sd, size, pixel_size, &Py)) / len(sd->dP.dy);
- }
+ /* TODO(sergey): Think of faster way to calculate derivatives. */
+ if (bump_offset == NODE_BUMP_OFFSET_DX) {
+ float3 Px = sd->P - sd->dP.dx;
+ f += (f - wireframe(kg, sd, size, pixel_size, &Px)) / len(sd->dP.dx);
+ }
+ else if (bump_offset == NODE_BUMP_OFFSET_DY) {
+ float3 Py = sd->P - sd->dP.dy;
+ f += (f - wireframe(kg, sd, size, pixel_size, &Py)) / len(sd->dP.dy);
+ }
- if(stack_valid(out_fac))
- stack_store_float(stack, out_fac, f);
+ if (stack_valid(out_fac))
+ stack_store_float(stack, out_fac, f);
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/render/CMakeLists.txt b/intern/cycles/render/CMakeLists.txt
index 140fcb206dc..378957d21f4 100644
--- a/intern/cycles/render/CMakeLists.txt
+++ b/intern/cycles/render/CMakeLists.txt
@@ -1,86 +1,86 @@
set(INC
- ..
- ../../glew-mx
+ ..
+ ../../glew-mx
)
set(INC_SYS
- ${GLEW_INCLUDE_DIR}
+ ${GLEW_INCLUDE_DIR}
)
set(SRC
- attribute.cpp
- background.cpp
- bake.cpp
- buffers.cpp
- camera.cpp
- constant_fold.cpp
- coverage.cpp
- denoising.cpp
- film.cpp
- graph.cpp
- image.cpp
- integrator.cpp
- light.cpp
- merge.cpp
- mesh.cpp
- mesh_displace.cpp
- mesh_subdivision.cpp
- mesh_volume.cpp
- nodes.cpp
- object.cpp
- osl.cpp
- particles.cpp
- curves.cpp
- scene.cpp
- session.cpp
- shader.cpp
- sobol.cpp
- stats.cpp
- svm.cpp
- tables.cpp
- tile.cpp
+ attribute.cpp
+ background.cpp
+ bake.cpp
+ buffers.cpp
+ camera.cpp
+ constant_fold.cpp
+ coverage.cpp
+ denoising.cpp
+ film.cpp
+ graph.cpp
+ image.cpp
+ integrator.cpp
+ light.cpp
+ merge.cpp
+ mesh.cpp
+ mesh_displace.cpp
+ mesh_subdivision.cpp
+ mesh_volume.cpp
+ nodes.cpp
+ object.cpp
+ osl.cpp
+ particles.cpp
+ curves.cpp
+ scene.cpp
+ session.cpp
+ shader.cpp
+ sobol.cpp
+ stats.cpp
+ svm.cpp
+ tables.cpp
+ tile.cpp
)
set(SRC_HEADERS
- attribute.h
- bake.h
- background.h
- buffers.h
- camera.h
- constant_fold.h
- coverage.h
- denoising.h
- film.h
- graph.h
- image.h
- integrator.h
- light.h
- merge.h
- mesh.h
- nodes.h
- object.h
- osl.h
- particles.h
- curves.h
- scene.h
- session.h
- shader.h
- sobol.h
- stats.h
- svm.h
- tables.h
- tile.h
+ attribute.h
+ bake.h
+ background.h
+ buffers.h
+ camera.h
+ constant_fold.h
+ coverage.h
+ denoising.h
+ film.h
+ graph.h
+ image.h
+ integrator.h
+ light.h
+ merge.h
+ mesh.h
+ nodes.h
+ object.h
+ osl.h
+ particles.h
+ curves.h
+ scene.h
+ session.h
+ shader.h
+ sobol.h
+ stats.h
+ svm.h
+ tables.h
+ tile.h
)
set(LIB
- cycles_bvh
+ cycles_bvh
)
if(WITH_CYCLES_OSL)
- list(APPEND LIB
- cycles_kernel_osl
- )
+ list(APPEND LIB
+ cycles_kernel_osl
+ )
endif()
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${RTTI_DISABLE_FLAGS}")
diff --git a/intern/cycles/render/attribute.cpp b/intern/cycles/render/attribute.cpp
index f7788b6a490..dad6cb4fe6d 100644
--- a/intern/cycles/render/attribute.cpp
+++ b/intern/cycles/render/attribute.cpp
@@ -27,319 +27,316 @@ CCL_NAMESPACE_BEGIN
Attribute::~Attribute()
{
- /* for voxel data, we need to remove the image from the image manager */
- if(element == ATTR_ELEMENT_VOXEL) {
- VoxelAttribute *voxel_data = data_voxel();
+ /* for voxel data, we need to remove the image from the image manager */
+ if (element == ATTR_ELEMENT_VOXEL) {
+ VoxelAttribute *voxel_data = data_voxel();
- if(voxel_data && voxel_data->slot != -1) {
- voxel_data->manager->remove_image(voxel_data->slot);
- }
- }
+ if (voxel_data && voxel_data->slot != -1) {
+ voxel_data->manager->remove_image(voxel_data->slot);
+ }
+ }
}
void Attribute::set(ustring name_, TypeDesc type_, AttributeElement element_)
{
- name = name_;
- type = type_;
- element = element_;
- std = ATTR_STD_NONE;
- flags = 0;
+ name = name_;
+ type = type_;
+ element = element_;
+ std = ATTR_STD_NONE;
+ flags = 0;
- /* string and matrix not supported! */
- assert(type == TypeDesc::TypeFloat || type == TypeDesc::TypeColor ||
- type == TypeDesc::TypePoint || type == TypeDesc::TypeVector ||
- type == TypeDesc::TypeNormal || type == TypeDesc::TypeMatrix ||
- type == TypeFloat2);
+ /* string and matrix not supported! */
+ assert(type == TypeDesc::TypeFloat || type == TypeDesc::TypeColor ||
+ type == TypeDesc::TypePoint || type == TypeDesc::TypeVector ||
+ type == TypeDesc::TypeNormal || type == TypeDesc::TypeMatrix || type == TypeFloat2);
}
void Attribute::resize(Mesh *mesh, AttributePrimitive prim, bool reserve_only)
{
- if(reserve_only) {
- buffer.reserve(buffer_size(mesh, prim));
- }
- else {
- buffer.resize(buffer_size(mesh, prim), 0);
- }
+ if (reserve_only) {
+ buffer.reserve(buffer_size(mesh, prim));
+ }
+ else {
+ buffer.resize(buffer_size(mesh, prim), 0);
+ }
}
void Attribute::resize(size_t num_elements)
{
- buffer.resize(num_elements * data_sizeof(), 0);
+ buffer.resize(num_elements * data_sizeof(), 0);
}
-void Attribute::add(const float& f)
+void Attribute::add(const float &f)
{
- assert(data_sizeof() == sizeof(float));
+ assert(data_sizeof() == sizeof(float));
- char *data = (char*)&f;
- size_t size = sizeof(f);
+ char *data = (char *)&f;
+ size_t size = sizeof(f);
- for(size_t i = 0; i < size; i++)
- buffer.push_back(data[i]);
+ for (size_t i = 0; i < size; i++)
+ buffer.push_back(data[i]);
}
-void Attribute::add(const uchar4& f)
+void Attribute::add(const uchar4 &f)
{
- assert(data_sizeof() == sizeof(uchar4));
+ assert(data_sizeof() == sizeof(uchar4));
- char *data = (char*)&f;
- size_t size = sizeof(f);
+ char *data = (char *)&f;
+ size_t size = sizeof(f);
- for(size_t i = 0; i < size; i++)
- buffer.push_back(data[i]);
+ for (size_t i = 0; i < size; i++)
+ buffer.push_back(data[i]);
}
-void Attribute::add(const float2& f)
+void Attribute::add(const float2 &f)
{
- assert(data_sizeof() == sizeof(float2));
+ assert(data_sizeof() == sizeof(float2));
- char *data = (char*)&f;
- size_t size = sizeof(f);
+ char *data = (char *)&f;
+ size_t size = sizeof(f);
- for(size_t i = 0; i < size; i++)
- buffer.push_back(data[i]);
+ for (size_t i = 0; i < size; i++)
+ buffer.push_back(data[i]);
}
-void Attribute::add(const float3& f)
+void Attribute::add(const float3 &f)
{
- assert(data_sizeof() == sizeof(float3));
+ assert(data_sizeof() == sizeof(float3));
- char *data = (char*)&f;
- size_t size = sizeof(f);
+ char *data = (char *)&f;
+ size_t size = sizeof(f);
- for(size_t i = 0; i < size; i++)
- buffer.push_back(data[i]);
+ for (size_t i = 0; i < size; i++)
+ buffer.push_back(data[i]);
}
-void Attribute::add(const Transform& f)
+void Attribute::add(const Transform &f)
{
- assert(data_sizeof() == sizeof(Transform));
+ assert(data_sizeof() == sizeof(Transform));
- char *data = (char*)&f;
- size_t size = sizeof(f);
+ char *data = (char *)&f;
+ size_t size = sizeof(f);
- for(size_t i = 0; i < size; i++)
- buffer.push_back(data[i]);
+ for (size_t i = 0; i < size; i++)
+ buffer.push_back(data[i]);
}
-void Attribute::add(const VoxelAttribute& f)
+void Attribute::add(const VoxelAttribute &f)
{
- assert(data_sizeof() == sizeof(VoxelAttribute));
+ assert(data_sizeof() == sizeof(VoxelAttribute));
- char *data = (char*)&f;
- size_t size = sizeof(f);
+ char *data = (char *)&f;
+ size_t size = sizeof(f);
- for(size_t i = 0; i < size; i++)
- buffer.push_back(data[i]);
+ for (size_t i = 0; i < size; i++)
+ buffer.push_back(data[i]);
}
void Attribute::add(const char *data)
{
- size_t size = data_sizeof();
+ size_t size = data_sizeof();
- for(size_t i = 0; i < size; i++)
- buffer.push_back(data[i]);
+ for (size_t i = 0; i < size; i++)
+ buffer.push_back(data[i]);
}
size_t Attribute::data_sizeof() const
{
- if(element == ATTR_ELEMENT_VOXEL)
- return sizeof(VoxelAttribute);
- else if(element == ATTR_ELEMENT_CORNER_BYTE)
- return sizeof(uchar4);
- else if(type == TypeDesc::TypeFloat)
- return sizeof(float);
- else if(type == TypeFloat2)
- return sizeof(float2);
- else if(type == TypeDesc::TypeMatrix)
- return sizeof(Transform);
- else
- return sizeof(float3);
+ if (element == ATTR_ELEMENT_VOXEL)
+ return sizeof(VoxelAttribute);
+ else if (element == ATTR_ELEMENT_CORNER_BYTE)
+ return sizeof(uchar4);
+ else if (type == TypeDesc::TypeFloat)
+ return sizeof(float);
+ else if (type == TypeFloat2)
+ return sizeof(float2);
+ else if (type == TypeDesc::TypeMatrix)
+ return sizeof(Transform);
+ else
+ return sizeof(float3);
}
size_t Attribute::element_size(Mesh *mesh, AttributePrimitive prim) const
{
- if(flags & ATTR_FINAL_SIZE) {
- return buffer.size() / data_sizeof();
- }
-
- size_t size;
-
- switch(element) {
- case ATTR_ELEMENT_OBJECT:
- case ATTR_ELEMENT_MESH:
- case ATTR_ELEMENT_VOXEL:
- size = 1;
- break;
- case ATTR_ELEMENT_VERTEX:
- size = mesh->verts.size() + mesh->num_ngons;
- if(prim == ATTR_PRIM_SUBD) {
- size -= mesh->num_subd_verts;
- }
- break;
- case ATTR_ELEMENT_VERTEX_MOTION:
- size = (mesh->verts.size() + mesh->num_ngons) * (mesh->motion_steps - 1);
- if(prim == ATTR_PRIM_SUBD) {
- size -= mesh->num_subd_verts * (mesh->motion_steps - 1);
- }
- break;
- case ATTR_ELEMENT_FACE:
- if(prim == ATTR_PRIM_TRIANGLE) {
- size = mesh->num_triangles();
- }
- else {
- size = mesh->subd_faces.size() + mesh->num_ngons;
- }
- break;
- case ATTR_ELEMENT_CORNER:
- case ATTR_ELEMENT_CORNER_BYTE:
- if(prim == ATTR_PRIM_TRIANGLE) {
- size = mesh->num_triangles()*3;
- }
- else {
- size = mesh->subd_face_corners.size() + mesh->num_ngons;
- }
- break;
- case ATTR_ELEMENT_CURVE:
- size = mesh->num_curves();
- break;
- case ATTR_ELEMENT_CURVE_KEY:
- size = mesh->curve_keys.size();
- break;
- case ATTR_ELEMENT_CURVE_KEY_MOTION:
- size = mesh->curve_keys.size() * (mesh->motion_steps - 1);
- break;
- default:
- size = 0;
- break;
- }
-
- return size;
+ if (flags & ATTR_FINAL_SIZE) {
+ return buffer.size() / data_sizeof();
+ }
+
+ size_t size;
+
+ switch (element) {
+ case ATTR_ELEMENT_OBJECT:
+ case ATTR_ELEMENT_MESH:
+ case ATTR_ELEMENT_VOXEL:
+ size = 1;
+ break;
+ case ATTR_ELEMENT_VERTEX:
+ size = mesh->verts.size() + mesh->num_ngons;
+ if (prim == ATTR_PRIM_SUBD) {
+ size -= mesh->num_subd_verts;
+ }
+ break;
+ case ATTR_ELEMENT_VERTEX_MOTION:
+ size = (mesh->verts.size() + mesh->num_ngons) * (mesh->motion_steps - 1);
+ if (prim == ATTR_PRIM_SUBD) {
+ size -= mesh->num_subd_verts * (mesh->motion_steps - 1);
+ }
+ break;
+ case ATTR_ELEMENT_FACE:
+ if (prim == ATTR_PRIM_TRIANGLE) {
+ size = mesh->num_triangles();
+ }
+ else {
+ size = mesh->subd_faces.size() + mesh->num_ngons;
+ }
+ break;
+ case ATTR_ELEMENT_CORNER:
+ case ATTR_ELEMENT_CORNER_BYTE:
+ if (prim == ATTR_PRIM_TRIANGLE) {
+ size = mesh->num_triangles() * 3;
+ }
+ else {
+ size = mesh->subd_face_corners.size() + mesh->num_ngons;
+ }
+ break;
+ case ATTR_ELEMENT_CURVE:
+ size = mesh->num_curves();
+ break;
+ case ATTR_ELEMENT_CURVE_KEY:
+ size = mesh->curve_keys.size();
+ break;
+ case ATTR_ELEMENT_CURVE_KEY_MOTION:
+ size = mesh->curve_keys.size() * (mesh->motion_steps - 1);
+ break;
+ default:
+ size = 0;
+ break;
+ }
+
+ return size;
}
size_t Attribute::buffer_size(Mesh *mesh, AttributePrimitive prim) const
{
- return element_size(mesh, prim)*data_sizeof();
+ return element_size(mesh, prim) * data_sizeof();
}
bool Attribute::same_storage(TypeDesc a, TypeDesc b)
{
- if(a == b)
- return true;
+ if (a == b)
+ return true;
- if(a == TypeDesc::TypeColor || a == TypeDesc::TypePoint ||
- a == TypeDesc::TypeVector || a == TypeDesc::TypeNormal)
- {
- if(b == TypeDesc::TypeColor || b == TypeDesc::TypePoint ||
- b == TypeDesc::TypeVector || b == TypeDesc::TypeNormal)
- {
- return true;
- }
- }
- return false;
+ if (a == TypeDesc::TypeColor || a == TypeDesc::TypePoint || a == TypeDesc::TypeVector ||
+ a == TypeDesc::TypeNormal) {
+ if (b == TypeDesc::TypeColor || b == TypeDesc::TypePoint || b == TypeDesc::TypeVector ||
+ b == TypeDesc::TypeNormal) {
+ return true;
+ }
+ }
+ return false;
}
-void Attribute::zero_data(void* dst)
+void Attribute::zero_data(void *dst)
{
- memset(dst, 0, data_sizeof());
+ memset(dst, 0, data_sizeof());
}
-void Attribute::add_with_weight(void* dst, void* src, float weight)
+void Attribute::add_with_weight(void *dst, void *src, float weight)
{
- if(element == ATTR_ELEMENT_CORNER_BYTE) {
- for(int i = 0; i < 4; i++) {
- ((uchar*)dst)[i] += uchar(((uchar*)src)[i] * weight);
- }
- }
- else if(same_storage(type, TypeDesc::TypeFloat)) {
- *((float*)dst) += *((float*)src) * weight;
- }
- else if(same_storage(type, TypeDesc::TypeVector)) {
- *((float4*)dst) += *((float4*)src) * weight;
- }
- else {
- assert(!"not implemented for this type");
- }
+ if (element == ATTR_ELEMENT_CORNER_BYTE) {
+ for (int i = 0; i < 4; i++) {
+ ((uchar *)dst)[i] += uchar(((uchar *)src)[i] * weight);
+ }
+ }
+ else if (same_storage(type, TypeDesc::TypeFloat)) {
+ *((float *)dst) += *((float *)src) * weight;
+ }
+ else if (same_storage(type, TypeDesc::TypeVector)) {
+ *((float4 *)dst) += *((float4 *)src) * weight;
+ }
+ else {
+ assert(!"not implemented for this type");
+ }
}
const char *Attribute::standard_name(AttributeStandard std)
{
- switch(std) {
- case ATTR_STD_VERTEX_NORMAL:
- return "N";
- case ATTR_STD_FACE_NORMAL:
- return "Ng";
- case ATTR_STD_UV:
- return "uv";
- case ATTR_STD_GENERATED:
- return "generated";
- case ATTR_STD_GENERATED_TRANSFORM:
- return "generated_transform";
- case ATTR_STD_UV_TANGENT:
- return "tangent";
- case ATTR_STD_UV_TANGENT_SIGN:
- return "tangent_sign";
- case ATTR_STD_POSITION_UNDEFORMED:
- return "undeformed";
- case ATTR_STD_POSITION_UNDISPLACED:
- return "undisplaced";
- case ATTR_STD_MOTION_VERTEX_POSITION:
- return "motion_P";
- case ATTR_STD_MOTION_VERTEX_NORMAL:
- return "motion_N";
- case ATTR_STD_PARTICLE:
- return "particle";
- case ATTR_STD_CURVE_INTERCEPT:
- return "curve_intercept";
- case ATTR_STD_CURVE_RANDOM:
- return "curve_random";
- case ATTR_STD_PTEX_FACE_ID:
- return "ptex_face_id";
- case ATTR_STD_PTEX_UV:
- return "ptex_uv";
- case ATTR_STD_VOLUME_DENSITY:
- return "density";
- case ATTR_STD_VOLUME_COLOR:
- return "color";
- case ATTR_STD_VOLUME_FLAME:
- return "flame";
- case ATTR_STD_VOLUME_HEAT:
- return "heat";
- case ATTR_STD_VOLUME_TEMPERATURE:
- return "temperature";
- case ATTR_STD_VOLUME_VELOCITY:
- return "velocity";
- case ATTR_STD_POINTINESS:
- return "pointiness";
- case ATTR_STD_NOT_FOUND:
- case ATTR_STD_NONE:
- case ATTR_STD_NUM:
- return "";
- }
-
- return "";
+ switch (std) {
+ case ATTR_STD_VERTEX_NORMAL:
+ return "N";
+ case ATTR_STD_FACE_NORMAL:
+ return "Ng";
+ case ATTR_STD_UV:
+ return "uv";
+ case ATTR_STD_GENERATED:
+ return "generated";
+ case ATTR_STD_GENERATED_TRANSFORM:
+ return "generated_transform";
+ case ATTR_STD_UV_TANGENT:
+ return "tangent";
+ case ATTR_STD_UV_TANGENT_SIGN:
+ return "tangent_sign";
+ case ATTR_STD_POSITION_UNDEFORMED:
+ return "undeformed";
+ case ATTR_STD_POSITION_UNDISPLACED:
+ return "undisplaced";
+ case ATTR_STD_MOTION_VERTEX_POSITION:
+ return "motion_P";
+ case ATTR_STD_MOTION_VERTEX_NORMAL:
+ return "motion_N";
+ case ATTR_STD_PARTICLE:
+ return "particle";
+ case ATTR_STD_CURVE_INTERCEPT:
+ return "curve_intercept";
+ case ATTR_STD_CURVE_RANDOM:
+ return "curve_random";
+ case ATTR_STD_PTEX_FACE_ID:
+ return "ptex_face_id";
+ case ATTR_STD_PTEX_UV:
+ return "ptex_uv";
+ case ATTR_STD_VOLUME_DENSITY:
+ return "density";
+ case ATTR_STD_VOLUME_COLOR:
+ return "color";
+ case ATTR_STD_VOLUME_FLAME:
+ return "flame";
+ case ATTR_STD_VOLUME_HEAT:
+ return "heat";
+ case ATTR_STD_VOLUME_TEMPERATURE:
+ return "temperature";
+ case ATTR_STD_VOLUME_VELOCITY:
+ return "velocity";
+ case ATTR_STD_POINTINESS:
+ return "pointiness";
+ case ATTR_STD_NOT_FOUND:
+ case ATTR_STD_NONE:
+ case ATTR_STD_NUM:
+ return "";
+ }
+
+ return "";
}
AttributeStandard Attribute::name_standard(const char *name)
{
- if(name) {
- for(int std = ATTR_STD_NONE; std < ATTR_STD_NUM; std++) {
- if(strcmp(name, Attribute::standard_name((AttributeStandard)std)) == 0) {
- return (AttributeStandard)std;
- }
- }
- }
+ if (name) {
+ for (int std = ATTR_STD_NONE; std < ATTR_STD_NUM; std++) {
+ if (strcmp(name, Attribute::standard_name((AttributeStandard)std)) == 0) {
+ return (AttributeStandard)std;
+ }
+ }
+ }
- return ATTR_STD_NONE;
+ return ATTR_STD_NONE;
}
/* Attribute Set */
AttributeSet::AttributeSet()
{
- triangle_mesh = NULL;
- curve_mesh = NULL;
- subd_mesh = NULL;
+ triangle_mesh = NULL;
+ curve_mesh = NULL;
+ subd_mesh = NULL;
}
AttributeSet::~AttributeSet()
@@ -348,280 +345,280 @@ AttributeSet::~AttributeSet()
Attribute *AttributeSet::add(ustring name, TypeDesc type, AttributeElement element)
{
- Attribute *attr = find(name);
+ Attribute *attr = find(name);
- if(attr) {
- /* return if same already exists */
- if(attr->type == type && attr->element == element)
- return attr;
+ if (attr) {
+ /* return if same already exists */
+ if (attr->type == type && attr->element == element)
+ return attr;
- /* overwrite attribute with same name but different type/element */
- remove(name);
- }
+ /* overwrite attribute with same name but different type/element */
+ remove(name);
+ }
#if __cplusplus >= 201103L
- attributes.emplace_back();
- attr = &attributes.back();
- attr->set(name, type, element);
+ attributes.emplace_back();
+ attr = &attributes.back();
+ attr->set(name, type, element);
#else
- {
- Attribute attr_temp;
- attr_temp.set(name, type, element);
- attributes.push_back(attr_temp);
- attr = &attributes.back();
- }
+ {
+ Attribute attr_temp;
+ attr_temp.set(name, type, element);
+ attributes.push_back(attr_temp);
+ attr = &attributes.back();
+ }
#endif
- /* this is weak .. */
- if(triangle_mesh)
- attr->resize(triangle_mesh, ATTR_PRIM_TRIANGLE, false);
- if(curve_mesh)
- attr->resize(curve_mesh, ATTR_PRIM_CURVE, false);
- if(subd_mesh)
- attr->resize(subd_mesh, ATTR_PRIM_SUBD, false);
+ /* this is weak .. */
+ if (triangle_mesh)
+ attr->resize(triangle_mesh, ATTR_PRIM_TRIANGLE, false);
+ if (curve_mesh)
+ attr->resize(curve_mesh, ATTR_PRIM_CURVE, false);
+ if (subd_mesh)
+ attr->resize(subd_mesh, ATTR_PRIM_SUBD, false);
- return attr;
+ return attr;
}
Attribute *AttributeSet::find(ustring name) const
{
- foreach(const Attribute& attr, attributes)
- if(attr.name == name)
- return (Attribute*)&attr;
+ foreach (const Attribute &attr, attributes)
+ if (attr.name == name)
+ return (Attribute *)&attr;
- return NULL;
+ return NULL;
}
void AttributeSet::remove(ustring name)
{
- Attribute *attr = find(name);
+ Attribute *attr = find(name);
- if(attr) {
- list<Attribute>::iterator it;
+ if (attr) {
+ list<Attribute>::iterator it;
- for(it = attributes.begin(); it != attributes.end(); it++) {
- if(&*it == attr) {
- attributes.erase(it);
- return;
- }
- }
- }
+ for (it = attributes.begin(); it != attributes.end(); it++) {
+ if (&*it == attr) {
+ attributes.erase(it);
+ return;
+ }
+ }
+ }
}
Attribute *AttributeSet::add(AttributeStandard std, ustring name)
{
- Attribute *attr = NULL;
-
- if(name == ustring())
- name = Attribute::standard_name(std);
-
- if(triangle_mesh || subd_mesh) {
- switch(std) {
- case ATTR_STD_VERTEX_NORMAL:
- attr = add(name, TypeDesc::TypeNormal, ATTR_ELEMENT_VERTEX);
- break;
- case ATTR_STD_FACE_NORMAL:
- attr = add(name, TypeDesc::TypeNormal, ATTR_ELEMENT_FACE);
- break;
- case ATTR_STD_UV:
- attr = add(name, TypeFloat2, ATTR_ELEMENT_CORNER);
- break;
- case ATTR_STD_UV_TANGENT:
- attr = add(name, TypeDesc::TypeVector, ATTR_ELEMENT_CORNER);
- break;
- case ATTR_STD_UV_TANGENT_SIGN:
- attr = add(name, TypeDesc::TypeFloat, ATTR_ELEMENT_CORNER);
- break;
- case ATTR_STD_GENERATED:
- case ATTR_STD_POSITION_UNDEFORMED:
- case ATTR_STD_POSITION_UNDISPLACED:
- attr = add(name, TypeDesc::TypePoint, ATTR_ELEMENT_VERTEX);
- break;
- case ATTR_STD_MOTION_VERTEX_POSITION:
- attr = add(name, TypeDesc::TypePoint, ATTR_ELEMENT_VERTEX_MOTION);
- break;
- case ATTR_STD_MOTION_VERTEX_NORMAL:
- attr = add(name, TypeDesc::TypeNormal, ATTR_ELEMENT_VERTEX_MOTION);
- break;
- case ATTR_STD_PTEX_FACE_ID:
- attr = add(name, TypeDesc::TypeFloat, ATTR_ELEMENT_FACE);
- break;
- case ATTR_STD_PTEX_UV:
- attr = add(name, TypeDesc::TypePoint, ATTR_ELEMENT_VERTEX);
- break;
- case ATTR_STD_GENERATED_TRANSFORM:
- attr = add(name, TypeDesc::TypeMatrix, ATTR_ELEMENT_MESH);
- break;
- case ATTR_STD_VOLUME_DENSITY:
- case ATTR_STD_VOLUME_FLAME:
- case ATTR_STD_VOLUME_HEAT:
- case ATTR_STD_VOLUME_TEMPERATURE:
- attr = add(name, TypeDesc::TypeFloat, ATTR_ELEMENT_VOXEL);
- break;
- case ATTR_STD_VOLUME_COLOR:
- attr = add(name, TypeDesc::TypeColor, ATTR_ELEMENT_VOXEL);
- break;
- case ATTR_STD_VOLUME_VELOCITY:
- attr = add(name, TypeDesc::TypeVector, ATTR_ELEMENT_VOXEL);
- break;
- case ATTR_STD_POINTINESS:
- attr = add(name, TypeDesc::TypeFloat, ATTR_ELEMENT_VERTEX);
- break;
- default:
- assert(0);
- break;
- }
- }
- else if(curve_mesh) {
- switch(std) {
- case ATTR_STD_UV:
- attr = add(name, TypeFloat2, ATTR_ELEMENT_CURVE);
- break;
- case ATTR_STD_GENERATED:
- attr = add(name, TypeDesc::TypePoint, ATTR_ELEMENT_CURVE);
- break;
- case ATTR_STD_MOTION_VERTEX_POSITION:
- attr = add(name, TypeDesc::TypePoint, ATTR_ELEMENT_CURVE_KEY_MOTION);
- break;
- case ATTR_STD_CURVE_INTERCEPT:
- attr = add(name, TypeDesc::TypeFloat, ATTR_ELEMENT_CURVE_KEY);
- break;
- case ATTR_STD_CURVE_RANDOM:
- attr = add(name, TypeDesc::TypeFloat, ATTR_ELEMENT_CURVE);
- break;
- case ATTR_STD_GENERATED_TRANSFORM:
- attr = add(name, TypeDesc::TypeMatrix, ATTR_ELEMENT_MESH);
- break;
- case ATTR_STD_POINTINESS:
- attr = add(name, TypeDesc::TypeFloat, ATTR_ELEMENT_VERTEX);
- break;
- default:
- assert(0);
- break;
- }
- }
-
- attr->std = std;
-
- return attr;
+ Attribute *attr = NULL;
+
+ if (name == ustring())
+ name = Attribute::standard_name(std);
+
+ if (triangle_mesh || subd_mesh) {
+ switch (std) {
+ case ATTR_STD_VERTEX_NORMAL:
+ attr = add(name, TypeDesc::TypeNormal, ATTR_ELEMENT_VERTEX);
+ break;
+ case ATTR_STD_FACE_NORMAL:
+ attr = add(name, TypeDesc::TypeNormal, ATTR_ELEMENT_FACE);
+ break;
+ case ATTR_STD_UV:
+ attr = add(name, TypeFloat2, ATTR_ELEMENT_CORNER);
+ break;
+ case ATTR_STD_UV_TANGENT:
+ attr = add(name, TypeDesc::TypeVector, ATTR_ELEMENT_CORNER);
+ break;
+ case ATTR_STD_UV_TANGENT_SIGN:
+ attr = add(name, TypeDesc::TypeFloat, ATTR_ELEMENT_CORNER);
+ break;
+ case ATTR_STD_GENERATED:
+ case ATTR_STD_POSITION_UNDEFORMED:
+ case ATTR_STD_POSITION_UNDISPLACED:
+ attr = add(name, TypeDesc::TypePoint, ATTR_ELEMENT_VERTEX);
+ break;
+ case ATTR_STD_MOTION_VERTEX_POSITION:
+ attr = add(name, TypeDesc::TypePoint, ATTR_ELEMENT_VERTEX_MOTION);
+ break;
+ case ATTR_STD_MOTION_VERTEX_NORMAL:
+ attr = add(name, TypeDesc::TypeNormal, ATTR_ELEMENT_VERTEX_MOTION);
+ break;
+ case ATTR_STD_PTEX_FACE_ID:
+ attr = add(name, TypeDesc::TypeFloat, ATTR_ELEMENT_FACE);
+ break;
+ case ATTR_STD_PTEX_UV:
+ attr = add(name, TypeDesc::TypePoint, ATTR_ELEMENT_VERTEX);
+ break;
+ case ATTR_STD_GENERATED_TRANSFORM:
+ attr = add(name, TypeDesc::TypeMatrix, ATTR_ELEMENT_MESH);
+ break;
+ case ATTR_STD_VOLUME_DENSITY:
+ case ATTR_STD_VOLUME_FLAME:
+ case ATTR_STD_VOLUME_HEAT:
+ case ATTR_STD_VOLUME_TEMPERATURE:
+ attr = add(name, TypeDesc::TypeFloat, ATTR_ELEMENT_VOXEL);
+ break;
+ case ATTR_STD_VOLUME_COLOR:
+ attr = add(name, TypeDesc::TypeColor, ATTR_ELEMENT_VOXEL);
+ break;
+ case ATTR_STD_VOLUME_VELOCITY:
+ attr = add(name, TypeDesc::TypeVector, ATTR_ELEMENT_VOXEL);
+ break;
+ case ATTR_STD_POINTINESS:
+ attr = add(name, TypeDesc::TypeFloat, ATTR_ELEMENT_VERTEX);
+ break;
+ default:
+ assert(0);
+ break;
+ }
+ }
+ else if (curve_mesh) {
+ switch (std) {
+ case ATTR_STD_UV:
+ attr = add(name, TypeFloat2, ATTR_ELEMENT_CURVE);
+ break;
+ case ATTR_STD_GENERATED:
+ attr = add(name, TypeDesc::TypePoint, ATTR_ELEMENT_CURVE);
+ break;
+ case ATTR_STD_MOTION_VERTEX_POSITION:
+ attr = add(name, TypeDesc::TypePoint, ATTR_ELEMENT_CURVE_KEY_MOTION);
+ break;
+ case ATTR_STD_CURVE_INTERCEPT:
+ attr = add(name, TypeDesc::TypeFloat, ATTR_ELEMENT_CURVE_KEY);
+ break;
+ case ATTR_STD_CURVE_RANDOM:
+ attr = add(name, TypeDesc::TypeFloat, ATTR_ELEMENT_CURVE);
+ break;
+ case ATTR_STD_GENERATED_TRANSFORM:
+ attr = add(name, TypeDesc::TypeMatrix, ATTR_ELEMENT_MESH);
+ break;
+ case ATTR_STD_POINTINESS:
+ attr = add(name, TypeDesc::TypeFloat, ATTR_ELEMENT_VERTEX);
+ break;
+ default:
+ assert(0);
+ break;
+ }
+ }
+
+ attr->std = std;
+
+ return attr;
}
Attribute *AttributeSet::find(AttributeStandard std) const
{
- foreach(const Attribute& attr, attributes)
- if(attr.std == std)
- return (Attribute*)&attr;
+ foreach (const Attribute &attr, attributes)
+ if (attr.std == std)
+ return (Attribute *)&attr;
- return NULL;
+ return NULL;
}
void AttributeSet::remove(AttributeStandard std)
{
- Attribute *attr = find(std);
+ Attribute *attr = find(std);
- if(attr) {
- list<Attribute>::iterator it;
+ if (attr) {
+ list<Attribute>::iterator it;
- for(it = attributes.begin(); it != attributes.end(); it++) {
- if(&*it == attr) {
- attributes.erase(it);
- return;
- }
- }
- }
+ for (it = attributes.begin(); it != attributes.end(); it++) {
+ if (&*it == attr) {
+ attributes.erase(it);
+ return;
+ }
+ }
+ }
}
-Attribute *AttributeSet::find(AttributeRequest& req)
+Attribute *AttributeSet::find(AttributeRequest &req)
{
- if(req.std == ATTR_STD_NONE)
- return find(req.name);
- else
- return find(req.std);
+ if (req.std == ATTR_STD_NONE)
+ return find(req.name);
+ else
+ return find(req.std);
}
void AttributeSet::remove(Attribute *attribute)
{
- if(attribute->std == ATTR_STD_NONE) {
- remove(attribute->name);
- }
- else {
- remove(attribute->std);
- }
+ if (attribute->std == ATTR_STD_NONE) {
+ remove(attribute->name);
+ }
+ else {
+ remove(attribute->std);
+ }
}
void AttributeSet::resize(bool reserve_only)
{
- foreach(Attribute& attr, attributes) {
- if(triangle_mesh)
- attr.resize(triangle_mesh, ATTR_PRIM_TRIANGLE, reserve_only);
- if(curve_mesh)
- attr.resize(curve_mesh, ATTR_PRIM_CURVE, reserve_only);
- if(subd_mesh)
- attr.resize(subd_mesh, ATTR_PRIM_SUBD, reserve_only);
- }
+ foreach (Attribute &attr, attributes) {
+ if (triangle_mesh)
+ attr.resize(triangle_mesh, ATTR_PRIM_TRIANGLE, reserve_only);
+ if (curve_mesh)
+ attr.resize(curve_mesh, ATTR_PRIM_CURVE, reserve_only);
+ if (subd_mesh)
+ attr.resize(subd_mesh, ATTR_PRIM_SUBD, reserve_only);
+ }
}
void AttributeSet::clear(bool preserve_voxel_data)
{
- if(preserve_voxel_data) {
- list<Attribute>::iterator it;
+ if (preserve_voxel_data) {
+ list<Attribute>::iterator it;
- for(it = attributes.begin(); it != attributes.end();) {
- if(it->element == ATTR_ELEMENT_VOXEL || it->std == ATTR_STD_GENERATED_TRANSFORM) {
- it++;
- }
- else {
- attributes.erase(it++);
- }
- }
- }
- else {
- attributes.clear();
- }
+ for (it = attributes.begin(); it != attributes.end();) {
+ if (it->element == ATTR_ELEMENT_VOXEL || it->std == ATTR_STD_GENERATED_TRANSFORM) {
+ it++;
+ }
+ else {
+ attributes.erase(it++);
+ }
+ }
+ }
+ else {
+ attributes.clear();
+ }
}
/* AttributeRequest */
AttributeRequest::AttributeRequest(ustring name_)
{
- name = name_;
- std = ATTR_STD_NONE;
+ name = name_;
+ std = ATTR_STD_NONE;
- triangle_type = TypeDesc::TypeFloat;
- triangle_desc.element = ATTR_ELEMENT_NONE;
- triangle_desc.offset = 0;
- triangle_desc.type = NODE_ATTR_FLOAT;
+ triangle_type = TypeDesc::TypeFloat;
+ triangle_desc.element = ATTR_ELEMENT_NONE;
+ triangle_desc.offset = 0;
+ triangle_desc.type = NODE_ATTR_FLOAT;
- curve_type = TypeDesc::TypeFloat;
- curve_desc.element = ATTR_ELEMENT_NONE;
- curve_desc.offset = 0;
- curve_desc.type = NODE_ATTR_FLOAT;
+ curve_type = TypeDesc::TypeFloat;
+ curve_desc.element = ATTR_ELEMENT_NONE;
+ curve_desc.offset = 0;
+ curve_desc.type = NODE_ATTR_FLOAT;
- subd_type = TypeDesc::TypeFloat;
- subd_desc.element = ATTR_ELEMENT_NONE;
- subd_desc.offset = 0;
- subd_desc.type = NODE_ATTR_FLOAT;
+ subd_type = TypeDesc::TypeFloat;
+ subd_desc.element = ATTR_ELEMENT_NONE;
+ subd_desc.offset = 0;
+ subd_desc.type = NODE_ATTR_FLOAT;
}
AttributeRequest::AttributeRequest(AttributeStandard std_)
{
- name = ustring();
- std = std_;
+ name = ustring();
+ std = std_;
- triangle_type = TypeDesc::TypeFloat;
- triangle_desc.element = ATTR_ELEMENT_NONE;
- triangle_desc.offset = 0;
- triangle_desc.type = NODE_ATTR_FLOAT;
+ triangle_type = TypeDesc::TypeFloat;
+ triangle_desc.element = ATTR_ELEMENT_NONE;
+ triangle_desc.offset = 0;
+ triangle_desc.type = NODE_ATTR_FLOAT;
- curve_type = TypeDesc::TypeFloat;
- curve_desc.element = ATTR_ELEMENT_NONE;
- curve_desc.offset = 0;
- curve_desc.type = NODE_ATTR_FLOAT;
+ curve_type = TypeDesc::TypeFloat;
+ curve_desc.element = ATTR_ELEMENT_NONE;
+ curve_desc.offset = 0;
+ curve_desc.type = NODE_ATTR_FLOAT;
- subd_type = TypeDesc::TypeFloat;
- subd_desc.element = ATTR_ELEMENT_NONE;
- subd_desc.offset = 0;
- subd_desc.type = NODE_ATTR_FLOAT;
+ subd_type = TypeDesc::TypeFloat;
+ subd_desc.element = ATTR_ELEMENT_NONE;
+ subd_desc.offset = 0;
+ subd_desc.type = NODE_ATTR_FLOAT;
}
/* AttributeRequestSet */
@@ -634,101 +631,99 @@ AttributeRequestSet::~AttributeRequestSet()
{
}
-bool AttributeRequestSet::modified(const AttributeRequestSet& other)
+bool AttributeRequestSet::modified(const AttributeRequestSet &other)
{
- if(requests.size() != other.requests.size())
- return true;
+ if (requests.size() != other.requests.size())
+ return true;
- for(size_t i = 0; i < requests.size(); i++) {
- bool found = false;
+ for (size_t i = 0; i < requests.size(); i++) {
+ bool found = false;
- for(size_t j = 0; j < requests.size() && !found; j++)
- if(requests[i].name == other.requests[j].name &&
- requests[i].std == other.requests[j].std)
- {
- found = true;
- }
+ for (size_t j = 0; j < requests.size() && !found; j++)
+ if (requests[i].name == other.requests[j].name && requests[i].std == other.requests[j].std) {
+ found = true;
+ }
- if(!found) {
- return true;
- }
- }
+ if (!found) {
+ return true;
+ }
+ }
- return false;
+ return false;
}
void AttributeRequestSet::add(ustring name)
{
- foreach(AttributeRequest& req, requests) {
- if(req.name == name) {
- return;
- }
- }
+ foreach (AttributeRequest &req, requests) {
+ if (req.name == name) {
+ return;
+ }
+ }
- requests.push_back(AttributeRequest(name));
+ requests.push_back(AttributeRequest(name));
}
void AttributeRequestSet::add(AttributeStandard std)
{
- foreach(AttributeRequest& req, requests)
- if(req.std == std)
- return;
+ foreach (AttributeRequest &req, requests)
+ if (req.std == std)
+ return;
- requests.push_back(AttributeRequest(std));
+ requests.push_back(AttributeRequest(std));
}
-void AttributeRequestSet::add(AttributeRequestSet& reqs)
+void AttributeRequestSet::add(AttributeRequestSet &reqs)
{
- foreach(AttributeRequest& req, reqs.requests) {
- if(req.std == ATTR_STD_NONE)
- add(req.name);
- else
- add(req.std);
- }
+ foreach (AttributeRequest &req, reqs.requests) {
+ if (req.std == ATTR_STD_NONE)
+ add(req.name);
+ else
+ add(req.std);
+ }
}
void AttributeRequestSet::add_standard(ustring name)
{
- if(name.empty()) {
- return;
- }
+ if (name.empty()) {
+ return;
+ }
- AttributeStandard std = Attribute::name_standard(name.c_str());
+ AttributeStandard std = Attribute::name_standard(name.c_str());
- if(std) {
- add(std);
- }
- else {
- add(name);
- }
+ if (std) {
+ add(std);
+ }
+ else {
+ add(name);
+ }
}
bool AttributeRequestSet::find(ustring name)
{
- foreach(AttributeRequest& req, requests)
- if(req.name == name)
- return true;
+ foreach (AttributeRequest &req, requests)
+ if (req.name == name)
+ return true;
- return false;
+ return false;
}
bool AttributeRequestSet::find(AttributeStandard std)
{
- foreach(AttributeRequest& req, requests)
- if(req.std == std)
- return true;
+ foreach (AttributeRequest &req, requests)
+ if (req.std == std)
+ return true;
- return false;
+ return false;
}
size_t AttributeRequestSet::size()
{
- return requests.size();
+ return requests.size();
}
void AttributeRequestSet::clear()
{
- requests.clear();
+ requests.clear();
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/render/attribute.h b/intern/cycles/render/attribute.h
index ed9e9fe76d6..ebab0fe7f88 100644
--- a/intern/cycles/render/attribute.h
+++ b/intern/cycles/render/attribute.h
@@ -37,8 +37,8 @@ struct Transform;
/* Attributes for voxels are images */
struct VoxelAttribute {
- ImageManager *manager;
- int slot;
+ ImageManager *manager;
+ int slot;
};
/* Attribute
@@ -47,114 +47,116 @@ struct VoxelAttribute {
* Supported types: Float, Color, Vector, Normal, Point */
class Attribute {
-public:
- ustring name;
- AttributeStandard std;
-
- TypeDesc type;
- vector<char> buffer;
- AttributeElement element;
- uint flags; /* enum AttributeFlag */
-
- Attribute() {}
- ~Attribute();
- void set(ustring name, TypeDesc type, AttributeElement element);
- void resize(Mesh *mesh, AttributePrimitive prim, bool reserve_only);
- void resize(size_t num_elements);
-
- size_t data_sizeof() const;
- size_t element_size(Mesh *mesh, AttributePrimitive prim) const;
- size_t buffer_size(Mesh *mesh, AttributePrimitive prim) const;
-
- char *data()
- {
- return (buffer.size())? &buffer[0]: NULL;
- }
- float2 *data_float2()
- {
- assert(data_sizeof() == sizeof(float2));
- return (float2*)data();
- }
- float3 *data_float3()
- {
- assert(data_sizeof() == sizeof(float3));
- return (float3*)data();
- }
- float4 *data_float4()
- {
- assert(data_sizeof() == sizeof(float4));
- return (float4*)data();
- }
- float *data_float()
- {
- assert(data_sizeof() == sizeof(float));
- return (float*)data();
- }
- uchar4 *data_uchar4()
- {
- assert(data_sizeof() == sizeof(uchar4));
- return (uchar4*)data();
- }
- Transform *data_transform()
- {
- assert(data_sizeof() == sizeof(Transform));
- return (Transform*)data();
- }
- VoxelAttribute *data_voxel()
- {
- assert(data_sizeof() == sizeof(VoxelAttribute));
- return ( VoxelAttribute*)data();
- }
-
- const char *data() const
- {
- return (buffer.size())? &buffer[0]: NULL;
- }
- const float2 *data_float2() const
- {
- assert(data_sizeof() == sizeof(float2));
- return (const float2*)data();
- }
- const float3 *data_float3() const
- {
- assert(data_sizeof() == sizeof(float3));
- return (const float3*)data();
- }
- const float4 *data_float4() const
- {
- assert(data_sizeof() == sizeof(float4));
- return (const float4*)data();
- }
- const float *data_float() const
- {
- assert(data_sizeof() == sizeof(float));
- return (const float*)data();
- }
- const Transform *data_transform() const
- {
- assert(data_sizeof() == sizeof(Transform));
- return (const Transform*)data();
- }
- const VoxelAttribute *data_voxel() const
- {
- assert(data_sizeof() == sizeof(VoxelAttribute));
- return (const VoxelAttribute*)data();
- }
-
- void zero_data(void* dst);
- void add_with_weight(void* dst, void* src, float weight);
-
- void add(const float& f);
- void add(const float2& f);
- void add(const float3& f);
- void add(const uchar4& f);
- void add(const Transform& f);
- void add(const VoxelAttribute& f);
- void add(const char *data);
-
- static bool same_storage(TypeDesc a, TypeDesc b);
- static const char *standard_name(AttributeStandard std);
- static AttributeStandard name_standard(const char *name);
+ public:
+ ustring name;
+ AttributeStandard std;
+
+ TypeDesc type;
+ vector<char> buffer;
+ AttributeElement element;
+ uint flags; /* enum AttributeFlag */
+
+ Attribute()
+ {
+ }
+ ~Attribute();
+ void set(ustring name, TypeDesc type, AttributeElement element);
+ void resize(Mesh *mesh, AttributePrimitive prim, bool reserve_only);
+ void resize(size_t num_elements);
+
+ size_t data_sizeof() const;
+ size_t element_size(Mesh *mesh, AttributePrimitive prim) const;
+ size_t buffer_size(Mesh *mesh, AttributePrimitive prim) const;
+
+ char *data()
+ {
+ return (buffer.size()) ? &buffer[0] : NULL;
+ }
+ float2 *data_float2()
+ {
+ assert(data_sizeof() == sizeof(float2));
+ return (float2 *)data();
+ }
+ float3 *data_float3()
+ {
+ assert(data_sizeof() == sizeof(float3));
+ return (float3 *)data();
+ }
+ float4 *data_float4()
+ {
+ assert(data_sizeof() == sizeof(float4));
+ return (float4 *)data();
+ }
+ float *data_float()
+ {
+ assert(data_sizeof() == sizeof(float));
+ return (float *)data();
+ }
+ uchar4 *data_uchar4()
+ {
+ assert(data_sizeof() == sizeof(uchar4));
+ return (uchar4 *)data();
+ }
+ Transform *data_transform()
+ {
+ assert(data_sizeof() == sizeof(Transform));
+ return (Transform *)data();
+ }
+ VoxelAttribute *data_voxel()
+ {
+ assert(data_sizeof() == sizeof(VoxelAttribute));
+ return (VoxelAttribute *)data();
+ }
+
+ const char *data() const
+ {
+ return (buffer.size()) ? &buffer[0] : NULL;
+ }
+ const float2 *data_float2() const
+ {
+ assert(data_sizeof() == sizeof(float2));
+ return (const float2 *)data();
+ }
+ const float3 *data_float3() const
+ {
+ assert(data_sizeof() == sizeof(float3));
+ return (const float3 *)data();
+ }
+ const float4 *data_float4() const
+ {
+ assert(data_sizeof() == sizeof(float4));
+ return (const float4 *)data();
+ }
+ const float *data_float() const
+ {
+ assert(data_sizeof() == sizeof(float));
+ return (const float *)data();
+ }
+ const Transform *data_transform() const
+ {
+ assert(data_sizeof() == sizeof(Transform));
+ return (const Transform *)data();
+ }
+ const VoxelAttribute *data_voxel() const
+ {
+ assert(data_sizeof() == sizeof(VoxelAttribute));
+ return (const VoxelAttribute *)data();
+ }
+
+ void zero_data(void *dst);
+ void add_with_weight(void *dst, void *src, float weight);
+
+ void add(const float &f);
+ void add(const float2 &f);
+ void add(const float3 &f);
+ void add(const uchar4 &f);
+ void add(const Transform &f);
+ void add(const VoxelAttribute &f);
+ void add(const char *data);
+
+ static bool same_storage(TypeDesc a, TypeDesc b);
+ static const char *standard_name(AttributeStandard std);
+ static AttributeStandard name_standard(const char *name);
};
/* Attribute Set
@@ -162,29 +164,29 @@ public:
* Set of attributes on a mesh. */
class AttributeSet {
-public:
- Mesh *triangle_mesh;
- Mesh *curve_mesh;
- Mesh *subd_mesh;
- list<Attribute> attributes;
+ public:
+ Mesh *triangle_mesh;
+ Mesh *curve_mesh;
+ Mesh *subd_mesh;
+ list<Attribute> attributes;
- AttributeSet();
- ~AttributeSet();
+ AttributeSet();
+ ~AttributeSet();
- Attribute *add(ustring name, TypeDesc type, AttributeElement element);
- Attribute *find(ustring name) const;
- void remove(ustring name);
+ Attribute *add(ustring name, TypeDesc type, AttributeElement element);
+ Attribute *find(ustring name) const;
+ void remove(ustring name);
- Attribute *add(AttributeStandard std, ustring name = ustring());
- Attribute *find(AttributeStandard std) const;
- void remove(AttributeStandard std);
+ Attribute *add(AttributeStandard std, ustring name = ustring());
+ Attribute *find(AttributeStandard std) const;
+ void remove(AttributeStandard std);
- Attribute *find(AttributeRequest& req);
+ Attribute *find(AttributeRequest &req);
- void remove(Attribute *attribute);
+ void remove(Attribute *attribute);
- void resize(bool reserve_only = false);
- void clear(bool preserve_voxel_data = false);
+ void resize(bool reserve_only = false);
+ void clear(bool preserve_voxel_data = false);
};
/* AttributeRequest
@@ -194,16 +196,16 @@ public:
* The attribute is found either by name or by standard attribute type. */
class AttributeRequest {
-public:
- ustring name;
- AttributeStandard std;
+ public:
+ ustring name;
+ AttributeStandard std;
- /* temporary variables used by MeshManager */
- TypeDesc triangle_type, curve_type, subd_type;
- AttributeDescriptor triangle_desc, curve_desc, subd_desc;
+ /* temporary variables used by MeshManager */
+ TypeDesc triangle_type, curve_type, subd_type;
+ AttributeDescriptor triangle_desc, curve_desc, subd_desc;
- explicit AttributeRequest(ustring name_);
- explicit AttributeRequest(AttributeStandard std);
+ explicit AttributeRequest(ustring name_);
+ explicit AttributeRequest(AttributeStandard std);
};
/* AttributeRequestSet
@@ -211,26 +213,26 @@ public:
* Set of attributes requested by a shader. */
class AttributeRequestSet {
-public:
- vector<AttributeRequest> requests;
+ public:
+ vector<AttributeRequest> requests;
- AttributeRequestSet();
- ~AttributeRequestSet();
+ AttributeRequestSet();
+ ~AttributeRequestSet();
- void add(ustring name);
- void add(AttributeStandard std);
- void add(AttributeRequestSet& reqs);
- void add_standard(ustring name);
+ void add(ustring name);
+ void add(AttributeStandard std);
+ void add(AttributeRequestSet &reqs);
+ void add_standard(ustring name);
- bool find(ustring name);
- bool find(AttributeStandard std);
+ bool find(ustring name);
+ bool find(AttributeStandard std);
- size_t size();
- void clear();
+ size_t size();
+ void clear();
- bool modified(const AttributeRequestSet& other);
+ bool modified(const AttributeRequestSet &other);
};
CCL_NAMESPACE_END
-#endif /* __ATTRIBUTE_H__ */
+#endif /* __ATTRIBUTE_H__ */
diff --git a/intern/cycles/render/background.cpp b/intern/cycles/render/background.cpp
index d8a49bf6a5e..b32cc55903d 100644
--- a/intern/cycles/render/background.cpp
+++ b/intern/cycles/render/background.cpp
@@ -30,28 +30,27 @@ CCL_NAMESPACE_BEGIN
NODE_DEFINE(Background)
{
- NodeType* type = NodeType::add("background", create);
+ NodeType *type = NodeType::add("background", create);
- SOCKET_FLOAT(ao_factor, "AO Factor", 0.0f);
- SOCKET_FLOAT(ao_distance, "AO Distance", FLT_MAX);
+ SOCKET_FLOAT(ao_factor, "AO Factor", 0.0f);
+ SOCKET_FLOAT(ao_distance, "AO Distance", FLT_MAX);
- SOCKET_BOOLEAN(use_shader, "Use Shader", true);
- SOCKET_BOOLEAN(use_ao, "Use AO", false);
- SOCKET_UINT(visibility, "Visibility", PATH_RAY_ALL_VISIBILITY);
+ SOCKET_BOOLEAN(use_shader, "Use Shader", true);
+ SOCKET_BOOLEAN(use_ao, "Use AO", false);
+ SOCKET_UINT(visibility, "Visibility", PATH_RAY_ALL_VISIBILITY);
- SOCKET_BOOLEAN(transparent, "Transparent", false);
- SOCKET_BOOLEAN(transparent_glass, "Transparent Glass", false);
- SOCKET_FLOAT(transparent_roughness_threshold, "Transparent Roughness Threshold", 0.0f);
+ SOCKET_BOOLEAN(transparent, "Transparent", false);
+ SOCKET_BOOLEAN(transparent_glass, "Transparent Glass", false);
+ SOCKET_FLOAT(transparent_roughness_threshold, "Transparent Roughness Threshold", 0.0f);
- SOCKET_NODE(shader, "Shader", &Shader::node_type);
+ SOCKET_NODE(shader, "Shader", &Shader::node_type);
- return type;
+ return type;
}
-Background::Background()
-: Node(node_type)
+Background::Background() : Node(node_type)
{
- need_update = true;
+ need_update = true;
}
Background::~Background()
@@ -60,78 +59,79 @@ Background::~Background()
void Background::device_update(Device *device, DeviceScene *dscene, Scene *scene)
{
- if(!need_update)
- return;
-
- device_free(device, dscene);
-
- Shader *bg_shader = shader;
-
- if(use_shader) {
- if(!bg_shader)
- bg_shader = scene->default_background;
- }
- else
- bg_shader = scene->default_empty;
-
- /* set shader index and transparent option */
- KernelBackground *kbackground = &dscene->data.background;
-
- kbackground->ao_factor = (use_ao)? ao_factor: 0.0f;
- kbackground->ao_bounces_factor = ao_factor;
- kbackground->ao_distance = ao_distance;
-
- kbackground->transparent = transparent;
- kbackground->surface_shader = scene->shader_manager->get_shader_id(bg_shader);
-
- if(transparent && transparent_glass) {
- /* Square twice, once for principled BSDF convention, and once for
- * faster comparison in kernel with anisotropic roughness. */
- kbackground->transparent_roughness_squared_threshold = sqr(sqr(transparent_roughness_threshold));
- }
- else {
- kbackground->transparent_roughness_squared_threshold = -1.0f;
- }
-
- if(bg_shader->has_volume)
- kbackground->volume_shader = kbackground->surface_shader;
- else
- kbackground->volume_shader = SHADER_NONE;
-
- /* No background node, make world shader invisible to all rays, to skip evaluation in kernel. */
- if(bg_shader->graph->nodes.size() <= 1) {
- kbackground->surface_shader |= SHADER_EXCLUDE_ANY;
- }
- /* Background present, check visibilities */
- else {
- if(!(visibility & PATH_RAY_DIFFUSE))
- kbackground->surface_shader |= SHADER_EXCLUDE_DIFFUSE;
- if(!(visibility & PATH_RAY_GLOSSY))
- kbackground->surface_shader |= SHADER_EXCLUDE_GLOSSY;
- if(!(visibility & PATH_RAY_TRANSMIT))
- kbackground->surface_shader |= SHADER_EXCLUDE_TRANSMIT;
- if(!(visibility & PATH_RAY_VOLUME_SCATTER))
- kbackground->surface_shader |= SHADER_EXCLUDE_SCATTER;
- if(!(visibility & PATH_RAY_CAMERA))
- kbackground->surface_shader |= SHADER_EXCLUDE_CAMERA;
- }
-
- need_update = false;
+ if (!need_update)
+ return;
+
+ device_free(device, dscene);
+
+ Shader *bg_shader = shader;
+
+ if (use_shader) {
+ if (!bg_shader)
+ bg_shader = scene->default_background;
+ }
+ else
+ bg_shader = scene->default_empty;
+
+ /* set shader index and transparent option */
+ KernelBackground *kbackground = &dscene->data.background;
+
+ kbackground->ao_factor = (use_ao) ? ao_factor : 0.0f;
+ kbackground->ao_bounces_factor = ao_factor;
+ kbackground->ao_distance = ao_distance;
+
+ kbackground->transparent = transparent;
+ kbackground->surface_shader = scene->shader_manager->get_shader_id(bg_shader);
+
+ if (transparent && transparent_glass) {
+ /* Square twice, once for principled BSDF convention, and once for
+ * faster comparison in kernel with anisotropic roughness. */
+ kbackground->transparent_roughness_squared_threshold = sqr(
+ sqr(transparent_roughness_threshold));
+ }
+ else {
+ kbackground->transparent_roughness_squared_threshold = -1.0f;
+ }
+
+ if (bg_shader->has_volume)
+ kbackground->volume_shader = kbackground->surface_shader;
+ else
+ kbackground->volume_shader = SHADER_NONE;
+
+ /* No background node, make world shader invisible to all rays, to skip evaluation in kernel. */
+ if (bg_shader->graph->nodes.size() <= 1) {
+ kbackground->surface_shader |= SHADER_EXCLUDE_ANY;
+ }
+ /* Background present, check visibilities */
+ else {
+ if (!(visibility & PATH_RAY_DIFFUSE))
+ kbackground->surface_shader |= SHADER_EXCLUDE_DIFFUSE;
+ if (!(visibility & PATH_RAY_GLOSSY))
+ kbackground->surface_shader |= SHADER_EXCLUDE_GLOSSY;
+ if (!(visibility & PATH_RAY_TRANSMIT))
+ kbackground->surface_shader |= SHADER_EXCLUDE_TRANSMIT;
+ if (!(visibility & PATH_RAY_VOLUME_SCATTER))
+ kbackground->surface_shader |= SHADER_EXCLUDE_SCATTER;
+ if (!(visibility & PATH_RAY_CAMERA))
+ kbackground->surface_shader |= SHADER_EXCLUDE_CAMERA;
+ }
+
+ need_update = false;
}
void Background::device_free(Device * /*device*/, DeviceScene * /*dscene*/)
{
}
-bool Background::modified(const Background& background)
+bool Background::modified(const Background &background)
{
- return !Node::equals(background);
+ return !Node::equals(background);
}
void Background::tag_update(Scene *scene)
{
- scene->integrator->tag_update(scene);
- need_update = true;
+ scene->integrator->tag_update(scene);
+ need_update = true;
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/render/background.h b/intern/cycles/render/background.h
index 17c3eaaaaf5..020db7bf6aa 100644
--- a/intern/cycles/render/background.h
+++ b/intern/cycles/render/background.h
@@ -29,34 +29,34 @@ class Scene;
class Shader;
class Background : public Node {
-public:
- NODE_DECLARE
+ public:
+ NODE_DECLARE
- float ao_factor;
- float ao_distance;
+ float ao_factor;
+ float ao_distance;
- bool use_shader;
- bool use_ao;
+ bool use_shader;
+ bool use_ao;
- uint visibility;
- Shader *shader;
+ uint visibility;
+ Shader *shader;
- bool transparent;
- bool transparent_glass;
- float transparent_roughness_threshold;
+ bool transparent;
+ bool transparent_glass;
+ float transparent_roughness_threshold;
- bool need_update;
+ bool need_update;
- Background();
- ~Background();
+ Background();
+ ~Background();
- void device_update(Device *device, DeviceScene *dscene, Scene *scene);
- void device_free(Device *device, DeviceScene *dscene);
+ void device_update(Device *device, DeviceScene *dscene, Scene *scene);
+ void device_free(Device *device, DeviceScene *dscene);
- bool modified(const Background& background);
- void tag_update(Scene *scene);
+ bool modified(const Background &background);
+ void tag_update(Scene *scene);
};
CCL_NAMESPACE_END
-#endif /* __BACKGROUND_H__ */
+#endif /* __BACKGROUND_H__ */
diff --git a/intern/cycles/render/bake.cpp b/intern/cycles/render/bake.cpp
index 927e04abc7f..73893921500 100644
--- a/intern/cycles/render/bake.cpp
+++ b/intern/cycles/render/bake.cpp
@@ -24,221 +24,220 @@
CCL_NAMESPACE_BEGIN
-BakeData::BakeData(const int object, const size_t tri_offset, const size_t num_pixels):
-m_object(object),
-m_tri_offset(tri_offset),
-m_num_pixels(num_pixels)
+BakeData::BakeData(const int object, const size_t tri_offset, const size_t num_pixels)
+ : m_object(object), m_tri_offset(tri_offset), m_num_pixels(num_pixels)
{
- m_primitive.resize(num_pixels);
- m_u.resize(num_pixels);
- m_v.resize(num_pixels);
- m_dudx.resize(num_pixels);
- m_dudy.resize(num_pixels);
- m_dvdx.resize(num_pixels);
- m_dvdy.resize(num_pixels);
+ m_primitive.resize(num_pixels);
+ m_u.resize(num_pixels);
+ m_v.resize(num_pixels);
+ m_dudx.resize(num_pixels);
+ m_dudy.resize(num_pixels);
+ m_dvdx.resize(num_pixels);
+ m_dvdy.resize(num_pixels);
}
BakeData::~BakeData()
{
- m_primitive.clear();
- m_u.clear();
- m_v.clear();
- m_dudx.clear();
- m_dudy.clear();
- m_dvdx.clear();
- m_dvdy.clear();
+ m_primitive.clear();
+ m_u.clear();
+ m_v.clear();
+ m_dudx.clear();
+ m_dudy.clear();
+ m_dvdx.clear();
+ m_dvdy.clear();
}
void BakeData::set(int i, int prim, float uv[2], float dudx, float dudy, float dvdx, float dvdy)
{
- m_primitive[i] = (prim == -1 ? -1 : m_tri_offset + prim);
- m_u[i] = uv[0];
- m_v[i] = uv[1];
- m_dudx[i] = dudx;
- m_dudy[i] = dudy;
- m_dvdx[i] = dvdx;
- m_dvdy[i] = dvdy;
+ m_primitive[i] = (prim == -1 ? -1 : m_tri_offset + prim);
+ m_u[i] = uv[0];
+ m_v[i] = uv[1];
+ m_dudx[i] = dudx;
+ m_dudy[i] = dudy;
+ m_dvdx[i] = dvdx;
+ m_dvdy[i] = dvdy;
}
void BakeData::set_null(int i)
{
- m_primitive[i] = -1;
+ m_primitive[i] = -1;
}
int BakeData::object()
{
- return m_object;
+ return m_object;
}
size_t BakeData::size()
{
- return m_num_pixels;
+ return m_num_pixels;
}
bool BakeData::is_valid(int i)
{
- return m_primitive[i] != -1;
+ return m_primitive[i] != -1;
}
uint4 BakeData::data(int i)
{
- return make_uint4(
- m_object,
- m_primitive[i],
- __float_as_int(m_u[i]),
- __float_as_int(m_v[i])
- );
+ return make_uint4(m_object, m_primitive[i], __float_as_int(m_u[i]), __float_as_int(m_v[i]));
}
uint4 BakeData::differentials(int i)
{
- return make_uint4(
- __float_as_int(m_dudx[i]),
- __float_as_int(m_dudy[i]),
- __float_as_int(m_dvdx[i]),
- __float_as_int(m_dvdy[i])
- );
+ return make_uint4(__float_as_int(m_dudx[i]),
+ __float_as_int(m_dudy[i]),
+ __float_as_int(m_dvdx[i]),
+ __float_as_int(m_dvdy[i]));
}
BakeManager::BakeManager()
{
- m_bake_data = NULL;
- m_is_baking = false;
- need_update = true;
- m_shader_limit = 512 * 512;
+ m_bake_data = NULL;
+ m_is_baking = false;
+ need_update = true;
+ m_shader_limit = 512 * 512;
}
BakeManager::~BakeManager()
{
- if(m_bake_data)
- delete m_bake_data;
+ if (m_bake_data)
+ delete m_bake_data;
}
bool BakeManager::get_baking()
{
- return m_is_baking;
+ return m_is_baking;
}
void BakeManager::set_baking(const bool value)
{
- m_is_baking = value;
+ m_is_baking = value;
}
BakeData *BakeManager::init(const int object, const size_t tri_offset, const size_t num_pixels)
{
- m_bake_data = new BakeData(object, tri_offset, num_pixels);
- return m_bake_data;
+ m_bake_data = new BakeData(object, tri_offset, num_pixels);
+ return m_bake_data;
}
void BakeManager::set_shader_limit(const size_t x, const size_t y)
{
- m_shader_limit = x * y;
- m_shader_limit = (size_t)pow(2, ceil(log(m_shader_limit)/log(2)));
+ m_shader_limit = x * y;
+ m_shader_limit = (size_t)pow(2, ceil(log(m_shader_limit) / log(2)));
}
-bool BakeManager::bake(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress, ShaderEvalType shader_type, const int pass_filter, BakeData *bake_data, float result[])
+bool BakeManager::bake(Device *device,
+ DeviceScene *dscene,
+ Scene *scene,
+ Progress &progress,
+ ShaderEvalType shader_type,
+ const int pass_filter,
+ BakeData *bake_data,
+ float result[])
{
- size_t num_pixels = bake_data->size();
-
- int num_samples = aa_samples(scene, bake_data, shader_type);
-
- /* calculate the total pixel samples for the progress bar */
- total_pixel_samples = 0;
- for(size_t shader_offset = 0; shader_offset < num_pixels; shader_offset += m_shader_limit) {
- size_t shader_size = (size_t)fminf(num_pixels - shader_offset, m_shader_limit);
- total_pixel_samples += shader_size * num_samples;
- }
- progress.reset_sample();
- progress.set_total_pixel_samples(total_pixel_samples);
-
- /* needs to be up to date for baking specific AA samples */
- dscene->data.integrator.aa_samples = num_samples;
- device->const_copy_to("__data", &dscene->data, sizeof(dscene->data));
-
- for(size_t shader_offset = 0; shader_offset < num_pixels; shader_offset += m_shader_limit) {
- size_t shader_size = (size_t)fminf(num_pixels - shader_offset, m_shader_limit);
-
- /* setup input for device task */
- device_vector<uint4> d_input(device, "bake_input", MEM_READ_ONLY);
- uint4 *d_input_data = d_input.alloc(shader_size * 2);
- size_t d_input_size = 0;
-
- for(size_t i = shader_offset; i < (shader_offset + shader_size); i++) {
- d_input_data[d_input_size++] = bake_data->data(i);
- d_input_data[d_input_size++] = bake_data->differentials(i);
- }
-
- if(d_input_size == 0) {
- m_is_baking = false;
- return false;
- }
-
- /* run device task */
- device_vector<float4> d_output(device, "bake_output", MEM_READ_WRITE);
- d_output.alloc(shader_size);
- d_output.zero_to_device();
- d_input.copy_to_device();
-
- DeviceTask task(DeviceTask::SHADER);
- task.shader_input = d_input.device_pointer;
- task.shader_output = d_output.device_pointer;
- task.shader_eval_type = shader_type;
- task.shader_filter = pass_filter;
- task.shader_x = 0;
- task.offset = shader_offset;
- task.shader_w = d_output.size();
- task.num_samples = num_samples;
- task.get_cancel = function_bind(&Progress::get_cancel, &progress);
- task.update_progress_sample = function_bind(&Progress::add_samples_update, &progress, _1, _2);
-
- device->task_add(task);
- device->task_wait();
-
- if(progress.get_cancel()) {
- d_input.free();
- d_output.free();
- m_is_baking = false;
- return false;
- }
-
- d_output.copy_from_device(0, 1, d_output.size());
- d_input.free();
-
- /* read result */
- int k = 0;
-
- float4 *offset = d_output.data();
-
- size_t depth = 4;
- for(size_t i=shader_offset; i < (shader_offset + shader_size); i++) {
- size_t index = i * depth;
- float4 out = offset[k++];
-
- if(bake_data->is_valid(i)) {
- for(size_t j=0; j < 4; j++) {
- result[index + j] = out[j];
- }
- }
- }
-
- d_output.free();
- }
-
- m_is_baking = false;
- return true;
+ size_t num_pixels = bake_data->size();
+
+ int num_samples = aa_samples(scene, bake_data, shader_type);
+
+ /* calculate the total pixel samples for the progress bar */
+ total_pixel_samples = 0;
+ for (size_t shader_offset = 0; shader_offset < num_pixels; shader_offset += m_shader_limit) {
+ size_t shader_size = (size_t)fminf(num_pixels - shader_offset, m_shader_limit);
+ total_pixel_samples += shader_size * num_samples;
+ }
+ progress.reset_sample();
+ progress.set_total_pixel_samples(total_pixel_samples);
+
+ /* needs to be up to date for baking specific AA samples */
+ dscene->data.integrator.aa_samples = num_samples;
+ device->const_copy_to("__data", &dscene->data, sizeof(dscene->data));
+
+ for (size_t shader_offset = 0; shader_offset < num_pixels; shader_offset += m_shader_limit) {
+ size_t shader_size = (size_t)fminf(num_pixels - shader_offset, m_shader_limit);
+
+ /* setup input for device task */
+ device_vector<uint4> d_input(device, "bake_input", MEM_READ_ONLY);
+ uint4 *d_input_data = d_input.alloc(shader_size * 2);
+ size_t d_input_size = 0;
+
+ for (size_t i = shader_offset; i < (shader_offset + shader_size); i++) {
+ d_input_data[d_input_size++] = bake_data->data(i);
+ d_input_data[d_input_size++] = bake_data->differentials(i);
+ }
+
+ if (d_input_size == 0) {
+ m_is_baking = false;
+ return false;
+ }
+
+ /* run device task */
+ device_vector<float4> d_output(device, "bake_output", MEM_READ_WRITE);
+ d_output.alloc(shader_size);
+ d_output.zero_to_device();
+ d_input.copy_to_device();
+
+ DeviceTask task(DeviceTask::SHADER);
+ task.shader_input = d_input.device_pointer;
+ task.shader_output = d_output.device_pointer;
+ task.shader_eval_type = shader_type;
+ task.shader_filter = pass_filter;
+ task.shader_x = 0;
+ task.offset = shader_offset;
+ task.shader_w = d_output.size();
+ task.num_samples = num_samples;
+ task.get_cancel = function_bind(&Progress::get_cancel, &progress);
+ task.update_progress_sample = function_bind(&Progress::add_samples_update, &progress, _1, _2);
+
+ device->task_add(task);
+ device->task_wait();
+
+ if (progress.get_cancel()) {
+ d_input.free();
+ d_output.free();
+ m_is_baking = false;
+ return false;
+ }
+
+ d_output.copy_from_device(0, 1, d_output.size());
+ d_input.free();
+
+ /* read result */
+ int k = 0;
+
+ float4 *offset = d_output.data();
+
+ size_t depth = 4;
+ for (size_t i = shader_offset; i < (shader_offset + shader_size); i++) {
+ size_t index = i * depth;
+ float4 out = offset[k++];
+
+ if (bake_data->is_valid(i)) {
+ for (size_t j = 0; j < 4; j++) {
+ result[index + j] = out[j];
+ }
+ }
+ }
+
+ d_output.free();
+ }
+
+ m_is_baking = false;
+ return true;
}
void BakeManager::device_update(Device * /*device*/,
DeviceScene * /*dscene*/,
Scene * /*scene*/,
- Progress& progress)
+ Progress &progress)
{
- if(!need_update)
- return;
+ if (!need_update)
+ return;
- if(progress.get_cancel()) return;
+ if (progress.get_cancel())
+ return;
- need_update = false;
+ need_update = false;
}
void BakeManager::device_free(Device * /*device*/, DeviceScene * /*dscene*/)
@@ -247,51 +246,52 @@ void BakeManager::device_free(Device * /*device*/, DeviceScene * /*dscene*/)
int BakeManager::aa_samples(Scene *scene, BakeData *bake_data, ShaderEvalType type)
{
- if(type == SHADER_EVAL_UV || type == SHADER_EVAL_ROUGHNESS) {
- return 1;
- }
- else if(type == SHADER_EVAL_NORMAL) {
- /* Only antialias normal if mesh has bump mapping. */
- Object *object = scene->objects[bake_data->object()];
-
- if(object->mesh) {
- foreach(Shader *shader, object->mesh->used_shaders) {
- if(shader->has_bump) {
- return scene->integrator->aa_samples;
- }
- }
- }
-
- return 1;
- }
- else {
- return scene->integrator->aa_samples;
- }
+ if (type == SHADER_EVAL_UV || type == SHADER_EVAL_ROUGHNESS) {
+ return 1;
+ }
+ else if (type == SHADER_EVAL_NORMAL) {
+ /* Only antialias normal if mesh has bump mapping. */
+ Object *object = scene->objects[bake_data->object()];
+
+ if (object->mesh) {
+ foreach (Shader *shader, object->mesh->used_shaders) {
+ if (shader->has_bump) {
+ return scene->integrator->aa_samples;
+ }
+ }
+ }
+
+ return 1;
+ }
+ else {
+ return scene->integrator->aa_samples;
+ }
}
/* Keep it synced with kernel_bake.h logic */
int BakeManager::shader_type_to_pass_filter(ShaderEvalType type, const int pass_filter)
{
- const int component_flags = pass_filter & (BAKE_FILTER_DIRECT | BAKE_FILTER_INDIRECT | BAKE_FILTER_COLOR);
-
- switch(type) {
- case SHADER_EVAL_AO:
- return BAKE_FILTER_AO;
- case SHADER_EVAL_SHADOW:
- return BAKE_FILTER_DIRECT;
- case SHADER_EVAL_DIFFUSE:
- return BAKE_FILTER_DIFFUSE | component_flags;
- case SHADER_EVAL_GLOSSY:
- return BAKE_FILTER_GLOSSY | component_flags;
- case SHADER_EVAL_TRANSMISSION:
- return BAKE_FILTER_TRANSMISSION | component_flags;
- case SHADER_EVAL_SUBSURFACE:
- return BAKE_FILTER_SUBSURFACE | component_flags;
- case SHADER_EVAL_COMBINED:
- return pass_filter;
- default:
- return 0;
- }
+ const int component_flags = pass_filter &
+ (BAKE_FILTER_DIRECT | BAKE_FILTER_INDIRECT | BAKE_FILTER_COLOR);
+
+ switch (type) {
+ case SHADER_EVAL_AO:
+ return BAKE_FILTER_AO;
+ case SHADER_EVAL_SHADOW:
+ return BAKE_FILTER_DIRECT;
+ case SHADER_EVAL_DIFFUSE:
+ return BAKE_FILTER_DIFFUSE | component_flags;
+ case SHADER_EVAL_GLOSSY:
+ return BAKE_FILTER_GLOSSY | component_flags;
+ case SHADER_EVAL_TRANSMISSION:
+ return BAKE_FILTER_TRANSMISSION | component_flags;
+ case SHADER_EVAL_SUBSURFACE:
+ return BAKE_FILTER_SUBSURFACE | component_flags;
+ case SHADER_EVAL_COMBINED:
+ return pass_filter;
+ default:
+ return 0;
+ }
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/render/bake.h b/intern/cycles/render/bake.h
index fce8f2fa606..88537623efb 100644
--- a/intern/cycles/render/bake.h
+++ b/intern/cycles/render/bake.h
@@ -26,61 +26,68 @@
CCL_NAMESPACE_BEGIN
class BakeData {
-public:
- BakeData(const int object, const size_t tri_offset, const size_t num_pixels);
- ~BakeData();
-
- void set(int i, int prim, float uv[2], float dudx, float dudy, float dvdx, float dvdy);
- void set_null(int i);
- int object();
- size_t size();
- uint4 data(int i);
- uint4 differentials(int i);
- bool is_valid(int i);
-
-private:
- int m_object;
- size_t m_tri_offset;
- size_t m_num_pixels;
- vector<int>m_primitive;
- vector<float>m_u;
- vector<float>m_v;
- vector<float>m_dudx;
- vector<float>m_dudy;
- vector<float>m_dvdx;
- vector<float>m_dvdy;
+ public:
+ BakeData(const int object, const size_t tri_offset, const size_t num_pixels);
+ ~BakeData();
+
+ void set(int i, int prim, float uv[2], float dudx, float dudy, float dvdx, float dvdy);
+ void set_null(int i);
+ int object();
+ size_t size();
+ uint4 data(int i);
+ uint4 differentials(int i);
+ bool is_valid(int i);
+
+ private:
+ int m_object;
+ size_t m_tri_offset;
+ size_t m_num_pixels;
+ vector<int> m_primitive;
+ vector<float> m_u;
+ vector<float> m_v;
+ vector<float> m_dudx;
+ vector<float> m_dudy;
+ vector<float> m_dvdx;
+ vector<float> m_dvdy;
};
class BakeManager {
-public:
- BakeManager();
- ~BakeManager();
+ public:
+ BakeManager();
+ ~BakeManager();
- bool get_baking();
- void set_baking(const bool value);
+ bool get_baking();
+ void set_baking(const bool value);
- BakeData *init(const int object, const size_t tri_offset, const size_t num_pixels);
+ BakeData *init(const int object, const size_t tri_offset, const size_t num_pixels);
- void set_shader_limit(const size_t x, const size_t y);
+ void set_shader_limit(const size_t x, const size_t y);
- bool bake(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress, ShaderEvalType shader_type, const int pass_filter, BakeData *bake_data, float result[]);
+ bool bake(Device *device,
+ DeviceScene *dscene,
+ Scene *scene,
+ Progress &progress,
+ ShaderEvalType shader_type,
+ const int pass_filter,
+ BakeData *bake_data,
+ float result[]);
- void device_update(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress);
- void device_free(Device *device, DeviceScene *dscene);
+ void device_update(Device *device, DeviceScene *dscene, Scene *scene, Progress &progress);
+ void device_free(Device *device, DeviceScene *dscene);
- static int shader_type_to_pass_filter(ShaderEvalType type, const int pass_filter);
- static int aa_samples(Scene *scene, BakeData *bake_data, ShaderEvalType type);
+ static int shader_type_to_pass_filter(ShaderEvalType type, const int pass_filter);
+ static int aa_samples(Scene *scene, BakeData *bake_data, ShaderEvalType type);
- bool need_update;
+ bool need_update;
- size_t total_pixel_samples;
+ size_t total_pixel_samples;
-private:
- BakeData *m_bake_data;
- bool m_is_baking;
- size_t m_shader_limit;
+ private:
+ BakeData *m_bake_data;
+ bool m_is_baking;
+ size_t m_shader_limit;
};
CCL_NAMESPACE_END
-#endif /* __BAKE_H__ */
+#endif /* __BAKE_H__ */
diff --git a/intern/cycles/render/buffers.cpp b/intern/cycles/render/buffers.cpp
index 678105aeeb1..5405aaefc1d 100644
--- a/intern/cycles/render/buffers.cpp
+++ b/intern/cycles/render/buffers.cpp
@@ -32,455 +32,458 @@ CCL_NAMESPACE_BEGIN
BufferParams::BufferParams()
{
- width = 0;
- height = 0;
+ width = 0;
+ height = 0;
- full_x = 0;
- full_y = 0;
- full_width = 0;
- full_height = 0;
+ full_x = 0;
+ full_y = 0;
+ full_width = 0;
+ full_height = 0;
- denoising_data_pass = false;
- denoising_clean_pass = false;
- denoising_prefiltered_pass = false;
+ denoising_data_pass = false;
+ denoising_clean_pass = false;
+ denoising_prefiltered_pass = false;
- Pass::add(PASS_COMBINED, passes);
+ Pass::add(PASS_COMBINED, passes);
}
-void BufferParams::get_offset_stride(int& offset, int& stride)
+void BufferParams::get_offset_stride(int &offset, int &stride)
{
- offset = -(full_x + full_y*width);
- stride = width;
+ offset = -(full_x + full_y * width);
+ stride = width;
}
-bool BufferParams::modified(const BufferParams& params)
+bool BufferParams::modified(const BufferParams &params)
{
- return !(full_x == params.full_x
- && full_y == params.full_y
- && width == params.width
- && height == params.height
- && full_width == params.full_width
- && full_height == params.full_height
- && Pass::equals(passes, params.passes));
+ return !(full_x == params.full_x && full_y == params.full_y && width == params.width &&
+ height == params.height && full_width == params.full_width &&
+ full_height == params.full_height && Pass::equals(passes, params.passes));
}
int BufferParams::get_passes_size()
{
- int size = 0;
+ int size = 0;
- for(size_t i = 0; i < passes.size(); i++)
- size += passes[i].components;
+ for (size_t i = 0; i < passes.size(); i++)
+ size += passes[i].components;
- if(denoising_data_pass) {
- size += DENOISING_PASS_SIZE_BASE;
- if(denoising_clean_pass) size += DENOISING_PASS_SIZE_CLEAN;
- if(denoising_prefiltered_pass) size += DENOISING_PASS_SIZE_PREFILTERED;
- }
+ if (denoising_data_pass) {
+ size += DENOISING_PASS_SIZE_BASE;
+ if (denoising_clean_pass)
+ size += DENOISING_PASS_SIZE_CLEAN;
+ if (denoising_prefiltered_pass)
+ size += DENOISING_PASS_SIZE_PREFILTERED;
+ }
- return align_up(size, 4);
+ return align_up(size, 4);
}
int BufferParams::get_denoising_offset()
{
- int offset = 0;
+ int offset = 0;
- for(size_t i = 0; i < passes.size(); i++)
- offset += passes[i].components;
+ for (size_t i = 0; i < passes.size(); i++)
+ offset += passes[i].components;
- return offset;
+ return offset;
}
int BufferParams::get_denoising_prefiltered_offset()
{
- assert(denoising_prefiltered_pass);
+ assert(denoising_prefiltered_pass);
- int offset = get_denoising_offset();
+ int offset = get_denoising_offset();
- offset += DENOISING_PASS_SIZE_BASE;
- if(denoising_clean_pass) {
- offset += DENOISING_PASS_SIZE_CLEAN;
- }
+ offset += DENOISING_PASS_SIZE_BASE;
+ if (denoising_clean_pass) {
+ offset += DENOISING_PASS_SIZE_CLEAN;
+ }
- return offset;
+ return offset;
}
/* Render Buffer Task */
RenderTile::RenderTile()
{
- x = 0;
- y = 0;
- w = 0;
- h = 0;
+ x = 0;
+ y = 0;
+ w = 0;
+ h = 0;
- sample = 0;
- start_sample = 0;
- num_samples = 0;
- resolution = 0;
+ sample = 0;
+ start_sample = 0;
+ num_samples = 0;
+ resolution = 0;
- offset = 0;
- stride = 0;
+ offset = 0;
+ stride = 0;
- buffer = 0;
+ buffer = 0;
- buffers = NULL;
+ buffers = NULL;
}
/* Render Buffers */
RenderBuffers::RenderBuffers(Device *device)
-: buffer(device, "RenderBuffers", MEM_READ_WRITE),
- map_neighbor_copied(false), render_time(0.0f)
+ : buffer(device, "RenderBuffers", MEM_READ_WRITE),
+ map_neighbor_copied(false),
+ render_time(0.0f)
{
}
RenderBuffers::~RenderBuffers()
{
- buffer.free();
+ buffer.free();
}
-void RenderBuffers::reset(BufferParams& params_)
+void RenderBuffers::reset(BufferParams &params_)
{
- params = params_;
+ params = params_;
- /* re-allocate buffer */
- buffer.alloc(params.width*params.height*params.get_passes_size());
- buffer.zero_to_device();
+ /* re-allocate buffer */
+ buffer.alloc(params.width * params.height * params.get_passes_size());
+ buffer.zero_to_device();
}
void RenderBuffers::zero()
{
- buffer.zero_to_device();
+ buffer.zero_to_device();
}
bool RenderBuffers::copy_from_device()
{
- if(!buffer.device_pointer)
- return false;
+ if (!buffer.device_pointer)
+ return false;
- buffer.copy_from_device(0, params.width * params.get_passes_size(), params.height);
+ buffer.copy_from_device(0, params.width * params.get_passes_size(), params.height);
- return true;
+ return true;
}
-bool RenderBuffers::get_denoising_pass_rect(int type, float exposure, int sample, int components, float *pixels)
+bool RenderBuffers::get_denoising_pass_rect(
+ int type, float exposure, int sample, int components, float *pixels)
{
- if(buffer.data() == NULL) {
- return false;
- }
-
- float scale = 1.0f;
- float alpha_scale = 1.0f/sample;
- if(type == DENOISING_PASS_PREFILTERED_COLOR ||
- type == DENOISING_PASS_CLEAN ||
- type == DENOISING_PASS_PREFILTERED_INTENSITY) {
- scale *= exposure;
- }
- else if(type == DENOISING_PASS_PREFILTERED_VARIANCE) {
- scale *= exposure*exposure * (sample - 1);
- }
-
- int offset;
- if(type == DENOISING_PASS_CLEAN) {
- /* The clean pass isn't changed by prefiltering, so we use the original one there. */
- offset = type + params.get_denoising_offset();
- scale /= sample;
- }
- else if (type == DENOISING_PASS_PREFILTERED_COLOR && !params.denoising_prefiltered_pass) {
- /* If we're not saving the prefiltering result, return the original noisy pass. */
- offset = params.get_denoising_offset() + DENOISING_PASS_COLOR;
- scale /= sample;
- }
- else {
- offset = type + params.get_denoising_prefiltered_offset();
- }
-
- int pass_stride = params.get_passes_size();
- int size = params.width*params.height;
-
- float *in = buffer.data() + offset;
-
- if(components == 1) {
- for(int i = 0; i < size; i++, in += pass_stride, pixels++) {
- pixels[0] = in[0]*scale;
- }
- }
- else if(components == 3) {
- for(int i = 0; i < size; i++, in += pass_stride, pixels += 3) {
- pixels[0] = in[0]*scale;
- pixels[1] = in[1]*scale;
- pixels[2] = in[2]*scale;
- }
- }
- else if(components == 4) {
- /* Since the alpha channel is not involved in denoising, output the Combined alpha channel. */
- assert(params.passes[0].type == PASS_COMBINED);
- float *in_combined = buffer.data();
-
- for(int i = 0; i < size; i++, in += pass_stride, in_combined += pass_stride, pixels += 4) {
- pixels[0] = in[0]*scale;
- pixels[1] = in[1]*scale;
- pixels[2] = in[2]*scale;
- pixels[3] = saturate(in_combined[3]*alpha_scale);
- }
- }
- else {
- return false;
- }
-
- return true;
+ if (buffer.data() == NULL) {
+ return false;
+ }
+
+ float scale = 1.0f;
+ float alpha_scale = 1.0f / sample;
+ if (type == DENOISING_PASS_PREFILTERED_COLOR || type == DENOISING_PASS_CLEAN ||
+ type == DENOISING_PASS_PREFILTERED_INTENSITY) {
+ scale *= exposure;
+ }
+ else if (type == DENOISING_PASS_PREFILTERED_VARIANCE) {
+ scale *= exposure * exposure * (sample - 1);
+ }
+
+ int offset;
+ if (type == DENOISING_PASS_CLEAN) {
+ /* The clean pass isn't changed by prefiltering, so we use the original one there. */
+ offset = type + params.get_denoising_offset();
+ scale /= sample;
+ }
+ else if (type == DENOISING_PASS_PREFILTERED_COLOR && !params.denoising_prefiltered_pass) {
+ /* If we're not saving the prefiltering result, return the original noisy pass. */
+ offset = params.get_denoising_offset() + DENOISING_PASS_COLOR;
+ scale /= sample;
+ }
+ else {
+ offset = type + params.get_denoising_prefiltered_offset();
+ }
+
+ int pass_stride = params.get_passes_size();
+ int size = params.width * params.height;
+
+ float *in = buffer.data() + offset;
+
+ if (components == 1) {
+ for (int i = 0; i < size; i++, in += pass_stride, pixels++) {
+ pixels[0] = in[0] * scale;
+ }
+ }
+ else if (components == 3) {
+ for (int i = 0; i < size; i++, in += pass_stride, pixels += 3) {
+ pixels[0] = in[0] * scale;
+ pixels[1] = in[1] * scale;
+ pixels[2] = in[2] * scale;
+ }
+ }
+ else if (components == 4) {
+ /* Since the alpha channel is not involved in denoising, output the Combined alpha channel. */
+ assert(params.passes[0].type == PASS_COMBINED);
+ float *in_combined = buffer.data();
+
+ for (int i = 0; i < size; i++, in += pass_stride, in_combined += pass_stride, pixels += 4) {
+ pixels[0] = in[0] * scale;
+ pixels[1] = in[1] * scale;
+ pixels[2] = in[2] * scale;
+ pixels[3] = saturate(in_combined[3] * alpha_scale);
+ }
+ }
+ else {
+ return false;
+ }
+
+ return true;
}
-bool RenderBuffers::get_pass_rect(PassType type, float exposure, int sample, int components, float *pixels, const string &name)
+bool RenderBuffers::get_pass_rect(
+ PassType type, float exposure, int sample, int components, float *pixels, const string &name)
{
- if(buffer.data() == NULL) {
- return false;
- }
-
- int pass_offset = 0;
-
- for(size_t j = 0; j < params.passes.size(); j++) {
- Pass& pass = params.passes[j];
-
- if(pass.type != type) {
- pass_offset += pass.components;
- continue;
- }
-
- /* Tell Cryptomatte passes apart by their name. */
- if(pass.type == PASS_CRYPTOMATTE) {
- if(pass.name != name) {
- pass_offset += pass.components;
- continue;
- }
- }
-
- float *in = buffer.data() + pass_offset;
- int pass_stride = params.get_passes_size();
-
- float scale = (pass.filter)? 1.0f/(float)sample: 1.0f;
- float scale_exposure = (pass.exposure)? scale*exposure: scale;
-
- int size = params.width*params.height;
-
- if(components == 1 && type == PASS_RENDER_TIME) {
- /* Render time is not stored by kernel, but measured per tile. */
- float val = (float) (1000.0 * render_time/(params.width * params.height * sample));
- for(int i = 0; i < size; i++, pixels++) {
- pixels[0] = val;
- }
- }
- else if(components == 1) {
- assert(pass.components == components);
-
- /* Scalar */
- if(type == PASS_DEPTH) {
- for(int i = 0; i < size; i++, in += pass_stride, pixels++) {
- float f = *in;
- pixels[0] = (f == 0.0f)? 1e10f: f*scale_exposure;
- }
- }
- else if(type == PASS_MIST) {
- for(int i = 0; i < size; i++, in += pass_stride, pixels++) {
- float f = *in;
- pixels[0] = saturate(f*scale_exposure);
- }
- }
+ if (buffer.data() == NULL) {
+ return false;
+ }
+
+ int pass_offset = 0;
+
+ for (size_t j = 0; j < params.passes.size(); j++) {
+ Pass &pass = params.passes[j];
+
+ if (pass.type != type) {
+ pass_offset += pass.components;
+ continue;
+ }
+
+ /* Tell Cryptomatte passes apart by their name. */
+ if (pass.type == PASS_CRYPTOMATTE) {
+ if (pass.name != name) {
+ pass_offset += pass.components;
+ continue;
+ }
+ }
+
+ float *in = buffer.data() + pass_offset;
+ int pass_stride = params.get_passes_size();
+
+ float scale = (pass.filter) ? 1.0f / (float)sample : 1.0f;
+ float scale_exposure = (pass.exposure) ? scale * exposure : scale;
+
+ int size = params.width * params.height;
+
+ if (components == 1 && type == PASS_RENDER_TIME) {
+ /* Render time is not stored by kernel, but measured per tile. */
+ float val = (float)(1000.0 * render_time / (params.width * params.height * sample));
+ for (int i = 0; i < size; i++, pixels++) {
+ pixels[0] = val;
+ }
+ }
+ else if (components == 1) {
+ assert(pass.components == components);
+
+ /* Scalar */
+ if (type == PASS_DEPTH) {
+ for (int i = 0; i < size; i++, in += pass_stride, pixels++) {
+ float f = *in;
+ pixels[0] = (f == 0.0f) ? 1e10f : f * scale_exposure;
+ }
+ }
+ else if (type == PASS_MIST) {
+ for (int i = 0; i < size; i++, in += pass_stride, pixels++) {
+ float f = *in;
+ pixels[0] = saturate(f * scale_exposure);
+ }
+ }
#ifdef WITH_CYCLES_DEBUG
- else if(type == PASS_BVH_TRAVERSED_NODES ||
- type == PASS_BVH_TRAVERSED_INSTANCES ||
- type == PASS_BVH_INTERSECTIONS ||
- type == PASS_RAY_BOUNCES)
- {
- for(int i = 0; i < size; i++, in += pass_stride, pixels++) {
- float f = *in;
- pixels[0] = f*scale;
- }
- }
+ else if (type == PASS_BVH_TRAVERSED_NODES || type == PASS_BVH_TRAVERSED_INSTANCES ||
+ type == PASS_BVH_INTERSECTIONS || type == PASS_RAY_BOUNCES) {
+ for (int i = 0; i < size; i++, in += pass_stride, pixels++) {
+ float f = *in;
+ pixels[0] = f * scale;
+ }
+ }
#endif
- else {
- for(int i = 0; i < size; i++, in += pass_stride, pixels++) {
- float f = *in;
- pixels[0] = f*scale_exposure;
- }
- }
- }
- else if(components == 3) {
- assert(pass.components == 4);
-
- /* RGBA */
- if(type == PASS_SHADOW) {
- for(int i = 0; i < size; i++, in += pass_stride, pixels += 3) {
- float4 f = make_float4(in[0], in[1], in[2], in[3]);
- float invw = (f.w > 0.0f)? 1.0f/f.w: 1.0f;
-
- pixels[0] = f.x*invw;
- pixels[1] = f.y*invw;
- pixels[2] = f.z*invw;
- }
- }
- else if(pass.divide_type != PASS_NONE) {
- /* RGB lighting passes that need to divide out color */
- pass_offset = 0;
- for(size_t k = 0; k < params.passes.size(); k++) {
- Pass& color_pass = params.passes[k];
- if(color_pass.type == pass.divide_type)
- break;
- pass_offset += color_pass.components;
- }
-
- float *in_divide = buffer.data() + pass_offset;
-
- for(int i = 0; i < size; i++, in += pass_stride, in_divide += pass_stride, pixels += 3) {
- float3 f = make_float3(in[0], in[1], in[2]);
- float3 f_divide = make_float3(in_divide[0], in_divide[1], in_divide[2]);
-
- f = safe_divide_even_color(f*exposure, f_divide);
-
- pixels[0] = f.x;
- pixels[1] = f.y;
- pixels[2] = f.z;
- }
- }
- else {
- /* RGB/vector */
- for(int i = 0; i < size; i++, in += pass_stride, pixels += 3) {
- float3 f = make_float3(in[0], in[1], in[2]);
-
- pixels[0] = f.x*scale_exposure;
- pixels[1] = f.y*scale_exposure;
- pixels[2] = f.z*scale_exposure;
- }
- }
- }
- else if(components == 4) {
- assert(pass.components == components);
-
- /* RGBA */
- if(type == PASS_SHADOW) {
- for(int i = 0; i < size; i++, in += pass_stride, pixels += 4) {
- float4 f = make_float4(in[0], in[1], in[2], in[3]);
- float invw = (f.w > 0.0f)? 1.0f/f.w: 1.0f;
-
- pixels[0] = f.x*invw;
- pixels[1] = f.y*invw;
- pixels[2] = f.z*invw;
- pixels[3] = 1.0f;
- }
- }
- else if(type == PASS_MOTION) {
- /* need to normalize by number of samples accumulated for motion */
- pass_offset = 0;
- for(size_t k = 0; k < params.passes.size(); k++) {
- Pass& color_pass = params.passes[k];
- if(color_pass.type == PASS_MOTION_WEIGHT)
- break;
- pass_offset += color_pass.components;
- }
-
- float *in_weight = buffer.data() + pass_offset;
-
- for(int i = 0; i < size; i++, in += pass_stride, in_weight += pass_stride, pixels += 4) {
- float4 f = make_float4(in[0], in[1], in[2], in[3]);
- float w = in_weight[0];
- float invw = (w > 0.0f)? 1.0f/w: 0.0f;
-
- pixels[0] = f.x*invw;
- pixels[1] = f.y*invw;
- pixels[2] = f.z*invw;
- pixels[3] = f.w*invw;
- }
- }
- else if(type == PASS_CRYPTOMATTE) {
- for(int i = 0; i < size; i++, in += pass_stride, pixels += 4) {
- float4 f = make_float4(in[0], in[1], in[2], in[3]);
- /* x and z contain integer IDs, don't rescale them.
- y and w contain matte weights, they get scaled. */
- pixels[0] = f.x;
- pixels[1] = f.y * scale;
- pixels[2] = f.z;
- pixels[3] = f.w * scale;
- }
- }
- else {
- for(int i = 0; i < size; i++, in += pass_stride, pixels += 4) {
- float4 f = make_float4(in[0], in[1], in[2], in[3]);
-
- pixels[0] = f.x*scale_exposure;
- pixels[1] = f.y*scale_exposure;
- pixels[2] = f.z*scale_exposure;
-
- /* clamp since alpha might be > 1.0 due to russian roulette */
- pixels[3] = saturate(f.w*scale);
- }
- }
- }
-
- return true;
- }
-
- return false;
+ else {
+ for (int i = 0; i < size; i++, in += pass_stride, pixels++) {
+ float f = *in;
+ pixels[0] = f * scale_exposure;
+ }
+ }
+ }
+ else if (components == 3) {
+ assert(pass.components == 4);
+
+ /* RGBA */
+ if (type == PASS_SHADOW) {
+ for (int i = 0; i < size; i++, in += pass_stride, pixels += 3) {
+ float4 f = make_float4(in[0], in[1], in[2], in[3]);
+ float invw = (f.w > 0.0f) ? 1.0f / f.w : 1.0f;
+
+ pixels[0] = f.x * invw;
+ pixels[1] = f.y * invw;
+ pixels[2] = f.z * invw;
+ }
+ }
+ else if (pass.divide_type != PASS_NONE) {
+ /* RGB lighting passes that need to divide out color */
+ pass_offset = 0;
+ for (size_t k = 0; k < params.passes.size(); k++) {
+ Pass &color_pass = params.passes[k];
+ if (color_pass.type == pass.divide_type)
+ break;
+ pass_offset += color_pass.components;
+ }
+
+ float *in_divide = buffer.data() + pass_offset;
+
+ for (int i = 0; i < size; i++, in += pass_stride, in_divide += pass_stride, pixels += 3) {
+ float3 f = make_float3(in[0], in[1], in[2]);
+ float3 f_divide = make_float3(in_divide[0], in_divide[1], in_divide[2]);
+
+ f = safe_divide_even_color(f * exposure, f_divide);
+
+ pixels[0] = f.x;
+ pixels[1] = f.y;
+ pixels[2] = f.z;
+ }
+ }
+ else {
+ /* RGB/vector */
+ for (int i = 0; i < size; i++, in += pass_stride, pixels += 3) {
+ float3 f = make_float3(in[0], in[1], in[2]);
+
+ pixels[0] = f.x * scale_exposure;
+ pixels[1] = f.y * scale_exposure;
+ pixels[2] = f.z * scale_exposure;
+ }
+ }
+ }
+ else if (components == 4) {
+ assert(pass.components == components);
+
+ /* RGBA */
+ if (type == PASS_SHADOW) {
+ for (int i = 0; i < size; i++, in += pass_stride, pixels += 4) {
+ float4 f = make_float4(in[0], in[1], in[2], in[3]);
+ float invw = (f.w > 0.0f) ? 1.0f / f.w : 1.0f;
+
+ pixels[0] = f.x * invw;
+ pixels[1] = f.y * invw;
+ pixels[2] = f.z * invw;
+ pixels[3] = 1.0f;
+ }
+ }
+ else if (type == PASS_MOTION) {
+ /* need to normalize by number of samples accumulated for motion */
+ pass_offset = 0;
+ for (size_t k = 0; k < params.passes.size(); k++) {
+ Pass &color_pass = params.passes[k];
+ if (color_pass.type == PASS_MOTION_WEIGHT)
+ break;
+ pass_offset += color_pass.components;
+ }
+
+ float *in_weight = buffer.data() + pass_offset;
+
+ for (int i = 0; i < size; i++, in += pass_stride, in_weight += pass_stride, pixels += 4) {
+ float4 f = make_float4(in[0], in[1], in[2], in[3]);
+ float w = in_weight[0];
+ float invw = (w > 0.0f) ? 1.0f / w : 0.0f;
+
+ pixels[0] = f.x * invw;
+ pixels[1] = f.y * invw;
+ pixels[2] = f.z * invw;
+ pixels[3] = f.w * invw;
+ }
+ }
+ else if (type == PASS_CRYPTOMATTE) {
+ for (int i = 0; i < size; i++, in += pass_stride, pixels += 4) {
+ float4 f = make_float4(in[0], in[1], in[2], in[3]);
+ /* x and z contain integer IDs, don't rescale them.
+ y and w contain matte weights, they get scaled. */
+ pixels[0] = f.x;
+ pixels[1] = f.y * scale;
+ pixels[2] = f.z;
+ pixels[3] = f.w * scale;
+ }
+ }
+ else {
+ for (int i = 0; i < size; i++, in += pass_stride, pixels += 4) {
+ float4 f = make_float4(in[0], in[1], in[2], in[3]);
+
+ pixels[0] = f.x * scale_exposure;
+ pixels[1] = f.y * scale_exposure;
+ pixels[2] = f.z * scale_exposure;
+
+ /* clamp since alpha might be > 1.0 due to russian roulette */
+ pixels[3] = saturate(f.w * scale);
+ }
+ }
+ }
+
+ return true;
+ }
+
+ return false;
}
/* Display Buffer */
DisplayBuffer::DisplayBuffer(Device *device, bool linear)
-: draw_width(0),
- draw_height(0),
- transparent(true), /* todo: determine from background */
- half_float(linear),
- rgba_byte(device, "display buffer byte"),
- rgba_half(device, "display buffer half")
+ : draw_width(0),
+ draw_height(0),
+ transparent(true), /* todo: determine from background */
+ half_float(linear),
+ rgba_byte(device, "display buffer byte"),
+ rgba_half(device, "display buffer half")
{
}
DisplayBuffer::~DisplayBuffer()
{
- rgba_byte.free();
- rgba_half.free();
+ rgba_byte.free();
+ rgba_half.free();
}
-void DisplayBuffer::reset(BufferParams& params_)
+void DisplayBuffer::reset(BufferParams &params_)
{
- draw_width = 0;
- draw_height = 0;
-
- params = params_;
-
- /* allocate display pixels */
- if(half_float) {
- rgba_half.alloc_to_device(params.width, params.height);
- }
- else {
- rgba_byte.alloc_to_device(params.width, params.height);
- }
+ draw_width = 0;
+ draw_height = 0;
+
+ params = params_;
+
+ /* allocate display pixels */
+ if (half_float) {
+ rgba_half.alloc_to_device(params.width, params.height);
+ }
+ else {
+ rgba_byte.alloc_to_device(params.width, params.height);
+ }
}
void DisplayBuffer::draw_set(int width, int height)
{
- assert(width <= params.width && height <= params.height);
+ assert(width <= params.width && height <= params.height);
- draw_width = width;
- draw_height = height;
+ draw_width = width;
+ draw_height = height;
}
-void DisplayBuffer::draw(Device *device, const DeviceDrawParams& draw_params)
+void DisplayBuffer::draw(Device *device, const DeviceDrawParams &draw_params)
{
- if(draw_width != 0 && draw_height != 0) {
- device_memory& rgba = (half_float)? (device_memory&)rgba_half:
- (device_memory&)rgba_byte;
-
- device->draw_pixels(
- rgba, 0,
- draw_width, draw_height, params.width, params.height,
- params.full_x, params.full_y, params.full_width, params.full_height,
- transparent, draw_params);
- }
+ if (draw_width != 0 && draw_height != 0) {
+ device_memory &rgba = (half_float) ? (device_memory &)rgba_half : (device_memory &)rgba_byte;
+
+ device->draw_pixels(rgba,
+ 0,
+ draw_width,
+ draw_height,
+ params.width,
+ params.height,
+ params.full_x,
+ params.full_y,
+ params.full_width,
+ params.full_height,
+ transparent,
+ draw_params);
+ }
}
bool DisplayBuffer::draw_ready()
{
- return (draw_width != 0 && draw_height != 0);
+ return (draw_width != 0 && draw_height != 0);
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/render/buffers.h b/intern/cycles/render/buffers.h
index 0a010718d6d..1c49038cd4b 100644
--- a/intern/cycles/render/buffers.h
+++ b/intern/cycles/render/buffers.h
@@ -38,59 +38,65 @@ struct float4;
* Size of render buffer and how it fits in the full image (border render). */
class BufferParams {
-public:
- /* width/height of the physical buffer */
- int width;
- int height;
-
- /* offset into and width/height of the full buffer */
- int full_x;
- int full_y;
- int full_width;
- int full_height;
-
- /* passes */
- vector<Pass> passes;
- bool denoising_data_pass;
- /* If only some light path types should be denoised, an additional pass is needed. */
- bool denoising_clean_pass;
- /* When we're prefiltering the passes during rendering, we need to keep both the
- * original and the prefiltered data around because neighboring tiles might still
- * need the original data. */
- bool denoising_prefiltered_pass;
-
- /* functions */
- BufferParams();
-
- void get_offset_stride(int& offset, int& stride);
- bool modified(const BufferParams& params);
- void add_pass(PassType type);
- int get_passes_size();
- int get_denoising_offset();
- int get_denoising_prefiltered_offset();
+ public:
+ /* width/height of the physical buffer */
+ int width;
+ int height;
+
+ /* offset into and width/height of the full buffer */
+ int full_x;
+ int full_y;
+ int full_width;
+ int full_height;
+
+ /* passes */
+ vector<Pass> passes;
+ bool denoising_data_pass;
+ /* If only some light path types should be denoised, an additional pass is needed. */
+ bool denoising_clean_pass;
+ /* When we're prefiltering the passes during rendering, we need to keep both the
+ * original and the prefiltered data around because neighboring tiles might still
+ * need the original data. */
+ bool denoising_prefiltered_pass;
+
+ /* functions */
+ BufferParams();
+
+ void get_offset_stride(int &offset, int &stride);
+ bool modified(const BufferParams &params);
+ void add_pass(PassType type);
+ int get_passes_size();
+ int get_denoising_offset();
+ int get_denoising_prefiltered_offset();
};
/* Render Buffers */
class RenderBuffers {
-public:
- /* buffer parameters */
- BufferParams params;
-
- /* float buffer */
- device_vector<float> buffer;
- bool map_neighbor_copied;
- double render_time;
-
- explicit RenderBuffers(Device *device);
- ~RenderBuffers();
-
- void reset(BufferParams& params);
- void zero();
-
- bool copy_from_device();
- bool get_pass_rect(PassType type, float exposure, int sample, int components, float *pixels, const string &name);
- bool get_denoising_pass_rect(int offset, float exposure, int sample, int components, float *pixels);
+ public:
+ /* buffer parameters */
+ BufferParams params;
+
+ /* float buffer */
+ device_vector<float> buffer;
+ bool map_neighbor_copied;
+ double render_time;
+
+ explicit RenderBuffers(Device *device);
+ ~RenderBuffers();
+
+ void reset(BufferParams &params);
+ void zero();
+
+ bool copy_from_device();
+ bool get_pass_rect(PassType type,
+ float exposure,
+ int sample,
+ int components,
+ float *pixels,
+ const string &name);
+ bool get_denoising_pass_rect(
+ int offset, float exposure, int sample, int components, float *pixels);
};
/* Display Buffer
@@ -99,56 +105,56 @@ public:
* buffers to byte of half float storage */
class DisplayBuffer {
-public:
- /* buffer parameters */
- BufferParams params;
- /* dimensions for how much of the buffer is actually ready for display.
- * with progressive render we can be using only a subset of the buffer.
- * if these are zero, it means nothing can be drawn yet */
- int draw_width, draw_height;
- /* draw alpha channel? */
- bool transparent;
- /* use half float? */
- bool half_float;
- /* byte buffer for converted result */
- device_pixels<uchar4> rgba_byte;
- device_pixels<half4> rgba_half;
-
- DisplayBuffer(Device *device, bool linear = false);
- ~DisplayBuffer();
-
- void reset(BufferParams& params);
-
- void draw_set(int width, int height);
- void draw(Device *device, const DeviceDrawParams& draw_params);
- bool draw_ready();
+ public:
+ /* buffer parameters */
+ BufferParams params;
+ /* dimensions for how much of the buffer is actually ready for display.
+ * with progressive render we can be using only a subset of the buffer.
+ * if these are zero, it means nothing can be drawn yet */
+ int draw_width, draw_height;
+ /* draw alpha channel? */
+ bool transparent;
+ /* use half float? */
+ bool half_float;
+ /* byte buffer for converted result */
+ device_pixels<uchar4> rgba_byte;
+ device_pixels<half4> rgba_half;
+
+ DisplayBuffer(Device *device, bool linear = false);
+ ~DisplayBuffer();
+
+ void reset(BufferParams &params);
+
+ void draw_set(int width, int height);
+ void draw(Device *device, const DeviceDrawParams &draw_params);
+ bool draw_ready();
};
/* Render Tile
* Rendering task on a buffer */
class RenderTile {
-public:
- typedef enum { PATH_TRACE, DENOISE } Task;
+ public:
+ typedef enum { PATH_TRACE, DENOISE } Task;
- Task task;
- int x, y, w, h;
- int start_sample;
- int num_samples;
- int sample;
- int resolution;
- int offset;
- int stride;
- int tile_index;
+ Task task;
+ int x, y, w, h;
+ int start_sample;
+ int num_samples;
+ int sample;
+ int resolution;
+ int offset;
+ int stride;
+ int tile_index;
- device_ptr buffer;
- int device_size;
+ device_ptr buffer;
+ int device_size;
- RenderBuffers *buffers;
+ RenderBuffers *buffers;
- RenderTile();
+ RenderTile();
};
CCL_NAMESPACE_END
-#endif /* __BUFFERS_H__ */
+#endif /* __BUFFERS_H__ */
diff --git a/intern/cycles/render/camera.cpp b/intern/cycles/render/camera.cpp
index 82aeb324a00..9c9070c8a90 100644
--- a/intern/cycles/render/camera.cpp
+++ b/intern/cycles/render/camera.cpp
@@ -39,147 +39,148 @@
CCL_NAMESPACE_BEGIN
-static float shutter_curve_eval(float x,
- array<float>& shutter_curve)
+static float shutter_curve_eval(float x, array<float> &shutter_curve)
{
- if(shutter_curve.size() == 0) {
- return 1.0f;
- }
-
- x *= shutter_curve.size();
- int index = (int)x;
- float frac = x - index;
- if(index < shutter_curve.size() - 1) {
- return lerp(shutter_curve[index], shutter_curve[index + 1], frac);
- }
- else {
- return shutter_curve[shutter_curve.size() - 1];
- }
+ if (shutter_curve.size() == 0) {
+ return 1.0f;
+ }
+
+ x *= shutter_curve.size();
+ int index = (int)x;
+ float frac = x - index;
+ if (index < shutter_curve.size() - 1) {
+ return lerp(shutter_curve[index], shutter_curve[index + 1], frac);
+ }
+ else {
+ return shutter_curve[shutter_curve.size() - 1];
+ }
}
NODE_DEFINE(Camera)
{
- NodeType* type = NodeType::add("camera", create);
-
- SOCKET_FLOAT(shuttertime, "Shutter Time", 1.0f);
-
- static NodeEnum motion_position_enum;
- motion_position_enum.insert("start", MOTION_POSITION_START);
- motion_position_enum.insert("center", MOTION_POSITION_CENTER);
- motion_position_enum.insert("end", MOTION_POSITION_END);
- SOCKET_ENUM(motion_position, "Motion Position", motion_position_enum, MOTION_POSITION_CENTER);
-
- static NodeEnum rolling_shutter_type_enum;
- rolling_shutter_type_enum.insert("none", ROLLING_SHUTTER_NONE);
- rolling_shutter_type_enum.insert("top", ROLLING_SHUTTER_TOP);
- SOCKET_ENUM(rolling_shutter_type, "Rolling Shutter Type", rolling_shutter_type_enum, ROLLING_SHUTTER_NONE);
- SOCKET_FLOAT(rolling_shutter_duration, "Rolling Shutter Duration", 0.1f);
-
- SOCKET_FLOAT_ARRAY(shutter_curve, "Shutter Curve", array<float>());
-
- SOCKET_FLOAT(aperturesize, "Aperture Size", 0.0f);
- SOCKET_FLOAT(focaldistance, "Focal Distance", 10.0f);
- SOCKET_UINT(blades, "Blades", 0);
- SOCKET_FLOAT(bladesrotation, "Blades Rotation", 0.0f);
-
- SOCKET_TRANSFORM(matrix, "Matrix", transform_identity());
- SOCKET_TRANSFORM_ARRAY(motion, "Motion", array<Transform>());
-
- SOCKET_FLOAT(aperture_ratio, "Aperture Ratio", 1.0f);
-
- static NodeEnum type_enum;
- type_enum.insert("perspective", CAMERA_PERSPECTIVE);
- type_enum.insert("orthograph", CAMERA_ORTHOGRAPHIC);
- type_enum.insert("panorama", CAMERA_PANORAMA);
- SOCKET_ENUM(type, "Type", type_enum, CAMERA_PERSPECTIVE);
-
- static NodeEnum panorama_type_enum;
- panorama_type_enum.insert("equirectangular", PANORAMA_EQUIRECTANGULAR);
- panorama_type_enum.insert("mirrorball", PANORAMA_MIRRORBALL);
- panorama_type_enum.insert("fisheye_equidistant", PANORAMA_FISHEYE_EQUIDISTANT);
- panorama_type_enum.insert("fisheye_equisolid", PANORAMA_FISHEYE_EQUISOLID);
- SOCKET_ENUM(panorama_type, "Panorama Type", panorama_type_enum, PANORAMA_EQUIRECTANGULAR);
-
- SOCKET_FLOAT(fisheye_fov, "Fisheye FOV", M_PI_F);
- SOCKET_FLOAT(fisheye_lens, "Fisheye Lens", 10.5f);
- SOCKET_FLOAT(latitude_min, "Latitude Min", -M_PI_2_F);
- SOCKET_FLOAT(latitude_max, "Latitude Max", M_PI_2_F);
- SOCKET_FLOAT(longitude_min, "Longitude Min", -M_PI_F);
- SOCKET_FLOAT(longitude_max, "Longitude Max", M_PI_F);
- SOCKET_FLOAT(fov, "FOV", M_PI_4_F);
- SOCKET_FLOAT(fov_pre, "FOV Pre", M_PI_4_F);
- SOCKET_FLOAT(fov_post, "FOV Post", M_PI_4_F);
-
- static NodeEnum stereo_eye_enum;
- stereo_eye_enum.insert("none", STEREO_NONE);
- stereo_eye_enum.insert("left", STEREO_LEFT);
- stereo_eye_enum.insert("right", STEREO_RIGHT);
- SOCKET_ENUM(stereo_eye, "Stereo Eye", stereo_eye_enum, STEREO_NONE);
-
- SOCKET_FLOAT(interocular_distance, "Interocular Distance", 0.065f);
- SOCKET_FLOAT(convergence_distance, "Convergence Distance", 30.0f * 0.065f);
-
- SOCKET_BOOLEAN(use_pole_merge, "Use Pole Merge", false);
- SOCKET_FLOAT(pole_merge_angle_from, "Pole Merge Angle From", 60.0f * M_PI_F / 180.0f);
- SOCKET_FLOAT(pole_merge_angle_to, "Pole Merge Angle To", 75.0f * M_PI_F / 180.0f);
-
- SOCKET_FLOAT(sensorwidth, "Sensor Width", 0.036f);
- SOCKET_FLOAT(sensorheight, "Sensor Height", 0.024f);
-
- SOCKET_FLOAT(nearclip, "Near Clip", 1e-5f);
- SOCKET_FLOAT(farclip, "Far Clip", 1e5f);
-
- SOCKET_FLOAT(viewplane.left, "Viewplane Left", 0);
- SOCKET_FLOAT(viewplane.right, "Viewplane Right", 0);
- SOCKET_FLOAT(viewplane.bottom, "Viewplane Bottom", 0);
- SOCKET_FLOAT(viewplane.top, "Viewplane Top", 0);
-
- SOCKET_FLOAT(border.left, "Border Left", 0);
- SOCKET_FLOAT(border.right, "Border Right", 0);
- SOCKET_FLOAT(border.bottom, "Border Bottom", 0);
- SOCKET_FLOAT(border.top, "Border Top", 0);
-
- SOCKET_FLOAT(offscreen_dicing_scale, "Offscreen Dicing Scale", 1.0f);
-
- return type;
+ NodeType *type = NodeType::add("camera", create);
+
+ SOCKET_FLOAT(shuttertime, "Shutter Time", 1.0f);
+
+ static NodeEnum motion_position_enum;
+ motion_position_enum.insert("start", MOTION_POSITION_START);
+ motion_position_enum.insert("center", MOTION_POSITION_CENTER);
+ motion_position_enum.insert("end", MOTION_POSITION_END);
+ SOCKET_ENUM(motion_position, "Motion Position", motion_position_enum, MOTION_POSITION_CENTER);
+
+ static NodeEnum rolling_shutter_type_enum;
+ rolling_shutter_type_enum.insert("none", ROLLING_SHUTTER_NONE);
+ rolling_shutter_type_enum.insert("top", ROLLING_SHUTTER_TOP);
+ SOCKET_ENUM(rolling_shutter_type,
+ "Rolling Shutter Type",
+ rolling_shutter_type_enum,
+ ROLLING_SHUTTER_NONE);
+ SOCKET_FLOAT(rolling_shutter_duration, "Rolling Shutter Duration", 0.1f);
+
+ SOCKET_FLOAT_ARRAY(shutter_curve, "Shutter Curve", array<float>());
+
+ SOCKET_FLOAT(aperturesize, "Aperture Size", 0.0f);
+ SOCKET_FLOAT(focaldistance, "Focal Distance", 10.0f);
+ SOCKET_UINT(blades, "Blades", 0);
+ SOCKET_FLOAT(bladesrotation, "Blades Rotation", 0.0f);
+
+ SOCKET_TRANSFORM(matrix, "Matrix", transform_identity());
+ SOCKET_TRANSFORM_ARRAY(motion, "Motion", array<Transform>());
+
+ SOCKET_FLOAT(aperture_ratio, "Aperture Ratio", 1.0f);
+
+ static NodeEnum type_enum;
+ type_enum.insert("perspective", CAMERA_PERSPECTIVE);
+ type_enum.insert("orthograph", CAMERA_ORTHOGRAPHIC);
+ type_enum.insert("panorama", CAMERA_PANORAMA);
+ SOCKET_ENUM(type, "Type", type_enum, CAMERA_PERSPECTIVE);
+
+ static NodeEnum panorama_type_enum;
+ panorama_type_enum.insert("equirectangular", PANORAMA_EQUIRECTANGULAR);
+ panorama_type_enum.insert("mirrorball", PANORAMA_MIRRORBALL);
+ panorama_type_enum.insert("fisheye_equidistant", PANORAMA_FISHEYE_EQUIDISTANT);
+ panorama_type_enum.insert("fisheye_equisolid", PANORAMA_FISHEYE_EQUISOLID);
+ SOCKET_ENUM(panorama_type, "Panorama Type", panorama_type_enum, PANORAMA_EQUIRECTANGULAR);
+
+ SOCKET_FLOAT(fisheye_fov, "Fisheye FOV", M_PI_F);
+ SOCKET_FLOAT(fisheye_lens, "Fisheye Lens", 10.5f);
+ SOCKET_FLOAT(latitude_min, "Latitude Min", -M_PI_2_F);
+ SOCKET_FLOAT(latitude_max, "Latitude Max", M_PI_2_F);
+ SOCKET_FLOAT(longitude_min, "Longitude Min", -M_PI_F);
+ SOCKET_FLOAT(longitude_max, "Longitude Max", M_PI_F);
+ SOCKET_FLOAT(fov, "FOV", M_PI_4_F);
+ SOCKET_FLOAT(fov_pre, "FOV Pre", M_PI_4_F);
+ SOCKET_FLOAT(fov_post, "FOV Post", M_PI_4_F);
+
+ static NodeEnum stereo_eye_enum;
+ stereo_eye_enum.insert("none", STEREO_NONE);
+ stereo_eye_enum.insert("left", STEREO_LEFT);
+ stereo_eye_enum.insert("right", STEREO_RIGHT);
+ SOCKET_ENUM(stereo_eye, "Stereo Eye", stereo_eye_enum, STEREO_NONE);
+
+ SOCKET_FLOAT(interocular_distance, "Interocular Distance", 0.065f);
+ SOCKET_FLOAT(convergence_distance, "Convergence Distance", 30.0f * 0.065f);
+
+ SOCKET_BOOLEAN(use_pole_merge, "Use Pole Merge", false);
+ SOCKET_FLOAT(pole_merge_angle_from, "Pole Merge Angle From", 60.0f * M_PI_F / 180.0f);
+ SOCKET_FLOAT(pole_merge_angle_to, "Pole Merge Angle To", 75.0f * M_PI_F / 180.0f);
+
+ SOCKET_FLOAT(sensorwidth, "Sensor Width", 0.036f);
+ SOCKET_FLOAT(sensorheight, "Sensor Height", 0.024f);
+
+ SOCKET_FLOAT(nearclip, "Near Clip", 1e-5f);
+ SOCKET_FLOAT(farclip, "Far Clip", 1e5f);
+
+ SOCKET_FLOAT(viewplane.left, "Viewplane Left", 0);
+ SOCKET_FLOAT(viewplane.right, "Viewplane Right", 0);
+ SOCKET_FLOAT(viewplane.bottom, "Viewplane Bottom", 0);
+ SOCKET_FLOAT(viewplane.top, "Viewplane Top", 0);
+
+ SOCKET_FLOAT(border.left, "Border Left", 0);
+ SOCKET_FLOAT(border.right, "Border Right", 0);
+ SOCKET_FLOAT(border.bottom, "Border Bottom", 0);
+ SOCKET_FLOAT(border.top, "Border Top", 0);
+
+ SOCKET_FLOAT(offscreen_dicing_scale, "Offscreen Dicing Scale", 1.0f);
+
+ return type;
}
-Camera::Camera()
-: Node(node_type)
+Camera::Camera() : Node(node_type)
{
- shutter_table_offset = TABLE_OFFSET_INVALID;
+ shutter_table_offset = TABLE_OFFSET_INVALID;
- width = 1024;
- height = 512;
- resolution = 1;
+ width = 1024;
+ height = 512;
+ resolution = 1;
- use_perspective_motion = false;
+ use_perspective_motion = false;
- shutter_curve.resize(RAMP_TABLE_SIZE);
- for(int i = 0; i < shutter_curve.size(); ++i) {
- shutter_curve[i] = 1.0f;
- }
+ shutter_curve.resize(RAMP_TABLE_SIZE);
+ for (int i = 0; i < shutter_curve.size(); ++i) {
+ shutter_curve[i] = 1.0f;
+ }
- compute_auto_viewplane();
+ compute_auto_viewplane();
- screentoworld = projection_identity();
- rastertoworld = projection_identity();
- ndctoworld = projection_identity();
- rastertocamera = projection_identity();
- cameratoworld = transform_identity();
- worldtoraster = projection_identity();
+ screentoworld = projection_identity();
+ rastertoworld = projection_identity();
+ ndctoworld = projection_identity();
+ rastertocamera = projection_identity();
+ cameratoworld = transform_identity();
+ worldtoraster = projection_identity();
- full_rastertocamera = projection_identity();
+ full_rastertocamera = projection_identity();
- dx = make_float3(0.0f, 0.0f, 0.0f);
- dy = make_float3(0.0f, 0.0f, 0.0f);
+ dx = make_float3(0.0f, 0.0f, 0.0f);
+ dy = make_float3(0.0f, 0.0f, 0.0f);
- need_update = true;
- need_device_update = true;
- need_flags_update = true;
- previous_need_motion = -1;
+ need_update = true;
+ need_device_update = true;
+ need_flags_update = true;
+ previous_need_motion = -1;
- memset((void *)&kernel_camera, 0, sizeof(kernel_camera));
+ memset((void *)&kernel_camera, 0, sizeof(kernel_camera));
}
Camera::~Camera()
@@ -188,589 +189,577 @@ Camera::~Camera()
void Camera::compute_auto_viewplane()
{
- if(type == CAMERA_PANORAMA) {
- viewplane.left = 0.0f;
- viewplane.right = 1.0f;
- viewplane.bottom = 0.0f;
- viewplane.top = 1.0f;
- }
- else {
- float aspect = (float)width/(float)height;
- if(width >= height) {
- viewplane.left = -aspect;
- viewplane.right = aspect;
- viewplane.bottom = -1.0f;
- viewplane.top = 1.0f;
- }
- else {
- viewplane.left = -1.0f;
- viewplane.right = 1.0f;
- viewplane.bottom = -1.0f/aspect;
- viewplane.top = 1.0f/aspect;
- }
- }
+ if (type == CAMERA_PANORAMA) {
+ viewplane.left = 0.0f;
+ viewplane.right = 1.0f;
+ viewplane.bottom = 0.0f;
+ viewplane.top = 1.0f;
+ }
+ else {
+ float aspect = (float)width / (float)height;
+ if (width >= height) {
+ viewplane.left = -aspect;
+ viewplane.right = aspect;
+ viewplane.bottom = -1.0f;
+ viewplane.top = 1.0f;
+ }
+ else {
+ viewplane.left = -1.0f;
+ viewplane.right = 1.0f;
+ viewplane.bottom = -1.0f / aspect;
+ viewplane.top = 1.0f / aspect;
+ }
+ }
}
void Camera::update(Scene *scene)
{
- Scene::MotionType need_motion = scene->need_motion();
-
- if(previous_need_motion != need_motion) {
- /* scene's motion model could have been changed since previous device
- * camera update this could happen for example in case when one render
- * layer has got motion pass and another not */
- need_device_update = true;
- }
-
- if(!need_update)
- return;
-
- /* Full viewport to camera border in the viewport. */
- Transform fulltoborder = transform_from_viewplane(viewport_camera_border);
- Transform bordertofull = transform_inverse(fulltoborder);
-
- /* ndc to raster */
- Transform ndctoraster = transform_scale(width, height, 1.0f) * bordertofull;
- Transform full_ndctoraster = transform_scale(full_width, full_height, 1.0f) * bordertofull;
-
- /* raster to screen */
- Transform screentondc = fulltoborder * transform_from_viewplane(viewplane);
-
- Transform screentoraster = ndctoraster * screentondc;
- Transform rastertoscreen = transform_inverse(screentoraster);
- Transform full_screentoraster = full_ndctoraster * screentondc;
- Transform full_rastertoscreen = transform_inverse(full_screentoraster);
-
- /* screen to camera */
- ProjectionTransform cameratoscreen;
- if(type == CAMERA_PERSPECTIVE)
- cameratoscreen = projection_perspective(fov, nearclip, farclip);
- else if(type == CAMERA_ORTHOGRAPHIC)
- cameratoscreen = projection_orthographic(nearclip, farclip);
- else
- cameratoscreen = projection_identity();
-
- ProjectionTransform screentocamera = projection_inverse(cameratoscreen);
-
- rastertocamera = screentocamera * rastertoscreen;
- full_rastertocamera = screentocamera * full_rastertoscreen;
- cameratoraster = screentoraster * cameratoscreen;
-
- cameratoworld = matrix;
- screentoworld = cameratoworld * screentocamera;
- rastertoworld = cameratoworld * rastertocamera;
- ndctoworld = rastertoworld * ndctoraster;
-
- /* note we recompose matrices instead of taking inverses of the above, this
- * is needed to avoid inverting near degenerate matrices that happen due to
- * precision issues with large scenes */
- worldtocamera = transform_inverse(matrix);
- worldtoscreen = cameratoscreen * worldtocamera;
- worldtondc = screentondc * worldtoscreen;
- worldtoraster = ndctoraster * worldtondc;
-
- /* differentials */
- if(type == CAMERA_ORTHOGRAPHIC) {
- dx = transform_perspective_direction(&rastertocamera, make_float3(1, 0, 0));
- dy = transform_perspective_direction(&rastertocamera, make_float3(0, 1, 0));
- full_dx = transform_perspective_direction(&full_rastertocamera, make_float3(1, 0, 0));
- full_dy = transform_perspective_direction(&full_rastertocamera, make_float3(0, 1, 0));
- }
- else if(type == CAMERA_PERSPECTIVE) {
- dx = transform_perspective(&rastertocamera, make_float3(1, 0, 0)) -
- transform_perspective(&rastertocamera, make_float3(0, 0, 0));
- dy = transform_perspective(&rastertocamera, make_float3(0, 1, 0)) -
- transform_perspective(&rastertocamera, make_float3(0, 0, 0));
- full_dx = transform_perspective(&full_rastertocamera, make_float3(1, 0, 0)) -
- transform_perspective(&full_rastertocamera, make_float3(0, 0, 0));
- full_dy = transform_perspective(&full_rastertocamera, make_float3(0, 1, 0)) -
- transform_perspective(&full_rastertocamera, make_float3(0, 0, 0));
- }
- else {
- dx = make_float3(0.0f, 0.0f, 0.0f);
- dy = make_float3(0.0f, 0.0f, 0.0f);
- }
-
- dx = transform_direction(&cameratoworld, dx);
- dy = transform_direction(&cameratoworld, dy);
- full_dx = transform_direction(&cameratoworld, full_dx);
- full_dy = transform_direction(&cameratoworld, full_dy);
-
- if(type == CAMERA_PERSPECTIVE) {
- float3 v = transform_perspective(&full_rastertocamera, make_float3(full_width, full_height, 1.0f));
-
- frustum_right_normal = normalize(make_float3(v.z, 0.0f, -v.x));
- frustum_top_normal = normalize(make_float3(0.0f, v.z, -v.y));
- }
-
- /* Compute kernel camera data. */
- KernelCamera *kcam = &kernel_camera;
-
- /* store matrices */
- kcam->screentoworld = screentoworld;
- kcam->rastertoworld = rastertoworld;
- kcam->rastertocamera = rastertocamera;
- kcam->cameratoworld = cameratoworld;
- kcam->worldtocamera = worldtocamera;
- kcam->worldtoscreen = worldtoscreen;
- kcam->worldtoraster = worldtoraster;
- kcam->worldtondc = worldtondc;
- kcam->ndctoworld = ndctoworld;
-
- /* camera motion */
- kcam->num_motion_steps = 0;
- kcam->have_perspective_motion = 0;
- kernel_camera_motion.clear();
-
- /* Test if any of the transforms are actually different. */
- bool have_motion = false;
- for(size_t i = 0; i < motion.size(); i++) {
- have_motion = have_motion || motion[i] != matrix;
- }
-
- if(need_motion == Scene::MOTION_PASS) {
- /* TODO(sergey): Support perspective (zoom, fov) motion. */
- if(type == CAMERA_PANORAMA) {
- if(have_motion) {
- kcam->motion_pass_pre = transform_inverse(motion[0]);
- kcam->motion_pass_post = transform_inverse(motion[motion.size()-1]);
- }
- else {
- kcam->motion_pass_pre = kcam->worldtocamera;
- kcam->motion_pass_post = kcam->worldtocamera;
- }
- }
- else {
- if(have_motion) {
- kcam->perspective_pre = cameratoraster * transform_inverse(motion[0]);
- kcam->perspective_post = cameratoraster * transform_inverse(motion[motion.size()-1]);
- }
- else {
- kcam->perspective_pre = worldtoraster;
- kcam->perspective_post = worldtoraster;
- }
- }
- }
- else if(need_motion == Scene::MOTION_BLUR) {
- if(have_motion) {
- kernel_camera_motion.resize(motion.size());
- transform_motion_decompose(kernel_camera_motion.data(), motion.data(), motion.size());
- kcam->num_motion_steps = motion.size();
- }
-
- /* TODO(sergey): Support other types of camera. */
- if(use_perspective_motion && type == CAMERA_PERSPECTIVE) {
- /* TODO(sergey): Move to an utility function and de-duplicate with
- * calculation above.
- */
- ProjectionTransform screentocamera_pre =
- projection_inverse(projection_perspective(fov_pre,
- nearclip,
- farclip));
- ProjectionTransform screentocamera_post =
- projection_inverse(projection_perspective(fov_post,
- nearclip,
- farclip));
-
- kcam->perspective_pre = screentocamera_pre * rastertoscreen;
- kcam->perspective_post = screentocamera_post * rastertoscreen;
- kcam->have_perspective_motion = 1;
- }
- }
-
- /* depth of field */
- kcam->aperturesize = aperturesize;
- kcam->focaldistance = focaldistance;
- kcam->blades = (blades < 3)? 0.0f: blades;
- kcam->bladesrotation = bladesrotation;
-
- /* motion blur */
- kcam->shuttertime = (need_motion == Scene::MOTION_BLUR) ? shuttertime: -1.0f;
-
- /* type */
- kcam->type = type;
-
- /* anamorphic lens bokeh */
- kcam->inv_aperture_ratio = 1.0f / aperture_ratio;
-
- /* panorama */
- kcam->panorama_type = panorama_type;
- kcam->fisheye_fov = fisheye_fov;
- kcam->fisheye_lens = fisheye_lens;
- kcam->equirectangular_range = make_float4(longitude_min - longitude_max, -longitude_min,
- latitude_min - latitude_max, -latitude_min + M_PI_2_F);
-
- switch(stereo_eye) {
- case STEREO_LEFT:
- kcam->interocular_offset = -interocular_distance * 0.5f;
- break;
- case STEREO_RIGHT:
- kcam->interocular_offset = interocular_distance * 0.5f;
- break;
- case STEREO_NONE:
- default:
- kcam->interocular_offset = 0.0f;
- break;
- }
-
- kcam->convergence_distance = convergence_distance;
- if(use_pole_merge) {
- kcam->pole_merge_angle_from = pole_merge_angle_from;
- kcam->pole_merge_angle_to = pole_merge_angle_to;
- }
- else {
- kcam->pole_merge_angle_from = -1.0f;
- kcam->pole_merge_angle_to = -1.0f;
- }
-
- /* sensor size */
- kcam->sensorwidth = sensorwidth;
- kcam->sensorheight = sensorheight;
-
- /* render size */
- kcam->width = width;
- kcam->height = height;
- kcam->resolution = resolution;
-
- /* store differentials */
- kcam->dx = float3_to_float4(dx);
- kcam->dy = float3_to_float4(dy);
-
- /* clipping */
- kcam->nearclip = nearclip;
- kcam->cliplength = (farclip == FLT_MAX)? FLT_MAX: farclip - nearclip;
-
- /* Camera in volume. */
- kcam->is_inside_volume = 0;
-
- /* Rolling shutter effect */
- kcam->rolling_shutter_type = rolling_shutter_type;
- kcam->rolling_shutter_duration = rolling_shutter_duration;
-
- /* Set further update flags */
- need_update = false;
- need_device_update = true;
- need_flags_update = true;
- previous_need_motion = need_motion;
+ Scene::MotionType need_motion = scene->need_motion();
+
+ if (previous_need_motion != need_motion) {
+ /* scene's motion model could have been changed since previous device
+ * camera update this could happen for example in case when one render
+ * layer has got motion pass and another not */
+ need_device_update = true;
+ }
+
+ if (!need_update)
+ return;
+
+ /* Full viewport to camera border in the viewport. */
+ Transform fulltoborder = transform_from_viewplane(viewport_camera_border);
+ Transform bordertofull = transform_inverse(fulltoborder);
+
+ /* ndc to raster */
+ Transform ndctoraster = transform_scale(width, height, 1.0f) * bordertofull;
+ Transform full_ndctoraster = transform_scale(full_width, full_height, 1.0f) * bordertofull;
+
+ /* raster to screen */
+ Transform screentondc = fulltoborder * transform_from_viewplane(viewplane);
+
+ Transform screentoraster = ndctoraster * screentondc;
+ Transform rastertoscreen = transform_inverse(screentoraster);
+ Transform full_screentoraster = full_ndctoraster * screentondc;
+ Transform full_rastertoscreen = transform_inverse(full_screentoraster);
+
+ /* screen to camera */
+ ProjectionTransform cameratoscreen;
+ if (type == CAMERA_PERSPECTIVE)
+ cameratoscreen = projection_perspective(fov, nearclip, farclip);
+ else if (type == CAMERA_ORTHOGRAPHIC)
+ cameratoscreen = projection_orthographic(nearclip, farclip);
+ else
+ cameratoscreen = projection_identity();
+
+ ProjectionTransform screentocamera = projection_inverse(cameratoscreen);
+
+ rastertocamera = screentocamera * rastertoscreen;
+ full_rastertocamera = screentocamera * full_rastertoscreen;
+ cameratoraster = screentoraster * cameratoscreen;
+
+ cameratoworld = matrix;
+ screentoworld = cameratoworld * screentocamera;
+ rastertoworld = cameratoworld * rastertocamera;
+ ndctoworld = rastertoworld * ndctoraster;
+
+ /* note we recompose matrices instead of taking inverses of the above, this
+ * is needed to avoid inverting near degenerate matrices that happen due to
+ * precision issues with large scenes */
+ worldtocamera = transform_inverse(matrix);
+ worldtoscreen = cameratoscreen * worldtocamera;
+ worldtondc = screentondc * worldtoscreen;
+ worldtoraster = ndctoraster * worldtondc;
+
+ /* differentials */
+ if (type == CAMERA_ORTHOGRAPHIC) {
+ dx = transform_perspective_direction(&rastertocamera, make_float3(1, 0, 0));
+ dy = transform_perspective_direction(&rastertocamera, make_float3(0, 1, 0));
+ full_dx = transform_perspective_direction(&full_rastertocamera, make_float3(1, 0, 0));
+ full_dy = transform_perspective_direction(&full_rastertocamera, make_float3(0, 1, 0));
+ }
+ else if (type == CAMERA_PERSPECTIVE) {
+ dx = transform_perspective(&rastertocamera, make_float3(1, 0, 0)) -
+ transform_perspective(&rastertocamera, make_float3(0, 0, 0));
+ dy = transform_perspective(&rastertocamera, make_float3(0, 1, 0)) -
+ transform_perspective(&rastertocamera, make_float3(0, 0, 0));
+ full_dx = transform_perspective(&full_rastertocamera, make_float3(1, 0, 0)) -
+ transform_perspective(&full_rastertocamera, make_float3(0, 0, 0));
+ full_dy = transform_perspective(&full_rastertocamera, make_float3(0, 1, 0)) -
+ transform_perspective(&full_rastertocamera, make_float3(0, 0, 0));
+ }
+ else {
+ dx = make_float3(0.0f, 0.0f, 0.0f);
+ dy = make_float3(0.0f, 0.0f, 0.0f);
+ }
+
+ dx = transform_direction(&cameratoworld, dx);
+ dy = transform_direction(&cameratoworld, dy);
+ full_dx = transform_direction(&cameratoworld, full_dx);
+ full_dy = transform_direction(&cameratoworld, full_dy);
+
+ if (type == CAMERA_PERSPECTIVE) {
+ float3 v = transform_perspective(&full_rastertocamera,
+ make_float3(full_width, full_height, 1.0f));
+
+ frustum_right_normal = normalize(make_float3(v.z, 0.0f, -v.x));
+ frustum_top_normal = normalize(make_float3(0.0f, v.z, -v.y));
+ }
+
+ /* Compute kernel camera data. */
+ KernelCamera *kcam = &kernel_camera;
+
+ /* store matrices */
+ kcam->screentoworld = screentoworld;
+ kcam->rastertoworld = rastertoworld;
+ kcam->rastertocamera = rastertocamera;
+ kcam->cameratoworld = cameratoworld;
+ kcam->worldtocamera = worldtocamera;
+ kcam->worldtoscreen = worldtoscreen;
+ kcam->worldtoraster = worldtoraster;
+ kcam->worldtondc = worldtondc;
+ kcam->ndctoworld = ndctoworld;
+
+ /* camera motion */
+ kcam->num_motion_steps = 0;
+ kcam->have_perspective_motion = 0;
+ kernel_camera_motion.clear();
+
+ /* Test if any of the transforms are actually different. */
+ bool have_motion = false;
+ for (size_t i = 0; i < motion.size(); i++) {
+ have_motion = have_motion || motion[i] != matrix;
+ }
+
+ if (need_motion == Scene::MOTION_PASS) {
+ /* TODO(sergey): Support perspective (zoom, fov) motion. */
+ if (type == CAMERA_PANORAMA) {
+ if (have_motion) {
+ kcam->motion_pass_pre = transform_inverse(motion[0]);
+ kcam->motion_pass_post = transform_inverse(motion[motion.size() - 1]);
+ }
+ else {
+ kcam->motion_pass_pre = kcam->worldtocamera;
+ kcam->motion_pass_post = kcam->worldtocamera;
+ }
+ }
+ else {
+ if (have_motion) {
+ kcam->perspective_pre = cameratoraster * transform_inverse(motion[0]);
+ kcam->perspective_post = cameratoraster * transform_inverse(motion[motion.size() - 1]);
+ }
+ else {
+ kcam->perspective_pre = worldtoraster;
+ kcam->perspective_post = worldtoraster;
+ }
+ }
+ }
+ else if (need_motion == Scene::MOTION_BLUR) {
+ if (have_motion) {
+ kernel_camera_motion.resize(motion.size());
+ transform_motion_decompose(kernel_camera_motion.data(), motion.data(), motion.size());
+ kcam->num_motion_steps = motion.size();
+ }
+
+ /* TODO(sergey): Support other types of camera. */
+ if (use_perspective_motion && type == CAMERA_PERSPECTIVE) {
+ /* TODO(sergey): Move to an utility function and de-duplicate with
+ * calculation above.
+ */
+ ProjectionTransform screentocamera_pre = projection_inverse(
+ projection_perspective(fov_pre, nearclip, farclip));
+ ProjectionTransform screentocamera_post = projection_inverse(
+ projection_perspective(fov_post, nearclip, farclip));
+
+ kcam->perspective_pre = screentocamera_pre * rastertoscreen;
+ kcam->perspective_post = screentocamera_post * rastertoscreen;
+ kcam->have_perspective_motion = 1;
+ }
+ }
+
+ /* depth of field */
+ kcam->aperturesize = aperturesize;
+ kcam->focaldistance = focaldistance;
+ kcam->blades = (blades < 3) ? 0.0f : blades;
+ kcam->bladesrotation = bladesrotation;
+
+ /* motion blur */
+ kcam->shuttertime = (need_motion == Scene::MOTION_BLUR) ? shuttertime : -1.0f;
+
+ /* type */
+ kcam->type = type;
+
+ /* anamorphic lens bokeh */
+ kcam->inv_aperture_ratio = 1.0f / aperture_ratio;
+
+ /* panorama */
+ kcam->panorama_type = panorama_type;
+ kcam->fisheye_fov = fisheye_fov;
+ kcam->fisheye_lens = fisheye_lens;
+ kcam->equirectangular_range = make_float4(longitude_min - longitude_max,
+ -longitude_min,
+ latitude_min - latitude_max,
+ -latitude_min + M_PI_2_F);
+
+ switch (stereo_eye) {
+ case STEREO_LEFT:
+ kcam->interocular_offset = -interocular_distance * 0.5f;
+ break;
+ case STEREO_RIGHT:
+ kcam->interocular_offset = interocular_distance * 0.5f;
+ break;
+ case STEREO_NONE:
+ default:
+ kcam->interocular_offset = 0.0f;
+ break;
+ }
+
+ kcam->convergence_distance = convergence_distance;
+ if (use_pole_merge) {
+ kcam->pole_merge_angle_from = pole_merge_angle_from;
+ kcam->pole_merge_angle_to = pole_merge_angle_to;
+ }
+ else {
+ kcam->pole_merge_angle_from = -1.0f;
+ kcam->pole_merge_angle_to = -1.0f;
+ }
+
+ /* sensor size */
+ kcam->sensorwidth = sensorwidth;
+ kcam->sensorheight = sensorheight;
+
+ /* render size */
+ kcam->width = width;
+ kcam->height = height;
+ kcam->resolution = resolution;
+
+ /* store differentials */
+ kcam->dx = float3_to_float4(dx);
+ kcam->dy = float3_to_float4(dy);
+
+ /* clipping */
+ kcam->nearclip = nearclip;
+ kcam->cliplength = (farclip == FLT_MAX) ? FLT_MAX : farclip - nearclip;
+
+ /* Camera in volume. */
+ kcam->is_inside_volume = 0;
+
+ /* Rolling shutter effect */
+ kcam->rolling_shutter_type = rolling_shutter_type;
+ kcam->rolling_shutter_duration = rolling_shutter_duration;
+
+ /* Set further update flags */
+ need_update = false;
+ need_device_update = true;
+ need_flags_update = true;
+ previous_need_motion = need_motion;
}
-void Camera::device_update(Device * /* device */,
- DeviceScene *dscene,
- Scene *scene)
+void Camera::device_update(Device * /* device */, DeviceScene *dscene, Scene *scene)
{
- update(scene);
-
- if(!need_device_update)
- return;
-
- scene->lookup_tables->remove_table(&shutter_table_offset);
- if(kernel_camera.shuttertime != -1.0f) {
- vector<float> shutter_table;
- util_cdf_inverted(SHUTTER_TABLE_SIZE,
- 0.0f,
- 1.0f,
- function_bind(shutter_curve_eval, _1, shutter_curve),
- false,
- shutter_table);
- shutter_table_offset = scene->lookup_tables->add_table(dscene,
- shutter_table);
- kernel_camera.shutter_table_offset = (int)shutter_table_offset;
- }
-
- dscene->data.cam = kernel_camera;
-
- size_t num_motion_steps = kernel_camera_motion.size();
- if(num_motion_steps) {
- DecomposedTransform *camera_motion = dscene->camera_motion.alloc(num_motion_steps);
- memcpy(camera_motion, kernel_camera_motion.data(), sizeof(*camera_motion) * num_motion_steps);
- dscene->camera_motion.copy_to_device();
- }
- else {
- dscene->camera_motion.free();
- }
+ update(scene);
+
+ if (!need_device_update)
+ return;
+
+ scene->lookup_tables->remove_table(&shutter_table_offset);
+ if (kernel_camera.shuttertime != -1.0f) {
+ vector<float> shutter_table;
+ util_cdf_inverted(SHUTTER_TABLE_SIZE,
+ 0.0f,
+ 1.0f,
+ function_bind(shutter_curve_eval, _1, shutter_curve),
+ false,
+ shutter_table);
+ shutter_table_offset = scene->lookup_tables->add_table(dscene, shutter_table);
+ kernel_camera.shutter_table_offset = (int)shutter_table_offset;
+ }
+
+ dscene->data.cam = kernel_camera;
+
+ size_t num_motion_steps = kernel_camera_motion.size();
+ if (num_motion_steps) {
+ DecomposedTransform *camera_motion = dscene->camera_motion.alloc(num_motion_steps);
+ memcpy(camera_motion, kernel_camera_motion.data(), sizeof(*camera_motion) * num_motion_steps);
+ dscene->camera_motion.copy_to_device();
+ }
+ else {
+ dscene->camera_motion.free();
+ }
}
-void Camera::device_update_volume(Device * /*device*/,
- DeviceScene *dscene,
- Scene *scene)
+void Camera::device_update_volume(Device * /*device*/, DeviceScene *dscene, Scene *scene)
{
- if(!need_device_update && !need_flags_update) {
- return;
- }
- KernelCamera *kcam = &dscene->data.cam;
- BoundBox viewplane_boundbox = viewplane_bounds_get();
- for(size_t i = 0; i < scene->objects.size(); ++i) {
- Object *object = scene->objects[i];
- if(object->mesh->has_volume &&
- viewplane_boundbox.intersects(object->bounds))
- {
- /* TODO(sergey): Consider adding more grained check. */
- VLOG(1) << "Detected camera inside volume.";
- kcam->is_inside_volume = 1;
- break;
- }
- }
- if(!kcam->is_inside_volume) {
- VLOG(1) << "Camera is outside of the volume.";
- }
- need_device_update = false;
- need_flags_update = false;
+ if (!need_device_update && !need_flags_update) {
+ return;
+ }
+ KernelCamera *kcam = &dscene->data.cam;
+ BoundBox viewplane_boundbox = viewplane_bounds_get();
+ for (size_t i = 0; i < scene->objects.size(); ++i) {
+ Object *object = scene->objects[i];
+ if (object->mesh->has_volume && viewplane_boundbox.intersects(object->bounds)) {
+ /* TODO(sergey): Consider adding more grained check. */
+ VLOG(1) << "Detected camera inside volume.";
+ kcam->is_inside_volume = 1;
+ break;
+ }
+ }
+ if (!kcam->is_inside_volume) {
+ VLOG(1) << "Camera is outside of the volume.";
+ }
+ need_device_update = false;
+ need_flags_update = false;
}
-void Camera::device_free(Device * /*device*/,
- DeviceScene *dscene,
- Scene *scene)
+void Camera::device_free(Device * /*device*/, DeviceScene *dscene, Scene *scene)
{
- scene->lookup_tables->remove_table(&shutter_table_offset);
- dscene->camera_motion.free();
+ scene->lookup_tables->remove_table(&shutter_table_offset);
+ dscene->camera_motion.free();
}
-bool Camera::modified(const Camera& cam)
+bool Camera::modified(const Camera &cam)
{
- return !Node::equals(cam);
+ return !Node::equals(cam);
}
-bool Camera::motion_modified(const Camera& cam)
+bool Camera::motion_modified(const Camera &cam)
{
- return !((motion == cam.motion) &&
- (use_perspective_motion == cam.use_perspective_motion));
+ return !((motion == cam.motion) && (use_perspective_motion == cam.use_perspective_motion));
}
void Camera::tag_update()
{
- need_update = true;
+ need_update = true;
}
float3 Camera::transform_raster_to_world(float raster_x, float raster_y)
{
- float3 D, P;
- if(type == CAMERA_PERSPECTIVE) {
- D = transform_perspective(&rastertocamera,
- make_float3(raster_x, raster_y, 0.0f));
- float3 Pclip = normalize(D);
- P = make_float3(0.0f, 0.0f, 0.0f);
- /* TODO(sergey): Aperture support? */
- P = transform_point(&cameratoworld, P);
- D = normalize(transform_direction(&cameratoworld, D));
- /* TODO(sergey): Clipping is conditional in kernel, and hence it could
- * be mistakes in here, currently leading to wrong camera-in-volume
- * detection.
- */
- P += nearclip * D / Pclip.z;
- }
- else if(type == CAMERA_ORTHOGRAPHIC) {
- D = make_float3(0.0f, 0.0f, 1.0f);
- /* TODO(sergey): Aperture support? */
- P = transform_perspective(&rastertocamera,
- make_float3(raster_x, raster_y, 0.0f));
- P = transform_point(&cameratoworld, P);
- D = normalize(transform_direction(&cameratoworld, D));
- }
- else {
- assert(!"unsupported camera type");
- }
- return P;
+ float3 D, P;
+ if (type == CAMERA_PERSPECTIVE) {
+ D = transform_perspective(&rastertocamera, make_float3(raster_x, raster_y, 0.0f));
+ float3 Pclip = normalize(D);
+ P = make_float3(0.0f, 0.0f, 0.0f);
+ /* TODO(sergey): Aperture support? */
+ P = transform_point(&cameratoworld, P);
+ D = normalize(transform_direction(&cameratoworld, D));
+ /* TODO(sergey): Clipping is conditional in kernel, and hence it could
+ * be mistakes in here, currently leading to wrong camera-in-volume
+ * detection.
+ */
+ P += nearclip * D / Pclip.z;
+ }
+ else if (type == CAMERA_ORTHOGRAPHIC) {
+ D = make_float3(0.0f, 0.0f, 1.0f);
+ /* TODO(sergey): Aperture support? */
+ P = transform_perspective(&rastertocamera, make_float3(raster_x, raster_y, 0.0f));
+ P = transform_point(&cameratoworld, P);
+ D = normalize(transform_direction(&cameratoworld, D));
+ }
+ else {
+ assert(!"unsupported camera type");
+ }
+ return P;
}
BoundBox Camera::viewplane_bounds_get()
{
- /* TODO(sergey): This is all rather stupid, but is there a way to perform
- * checks we need in a more clear and smart fasion?
- */
- BoundBox bounds = BoundBox::empty;
-
- if(type == CAMERA_PANORAMA) {
- if(use_spherical_stereo == false) {
- bounds.grow(make_float3(cameratoworld.x.w,
- cameratoworld.y.w,
- cameratoworld.z.w));
- }
- else {
- float half_eye_distance = interocular_distance * 0.5f;
-
- bounds.grow(make_float3(cameratoworld.x.w + half_eye_distance,
- cameratoworld.y.w,
- cameratoworld.z.w));
-
- bounds.grow(make_float3(cameratoworld.z.w,
- cameratoworld.y.w + half_eye_distance,
- cameratoworld.z.w));
-
- bounds.grow(make_float3(cameratoworld.x.w - half_eye_distance,
- cameratoworld.y.w,
- cameratoworld.z.w));
-
- bounds.grow(make_float3(cameratoworld.x.w,
- cameratoworld.y.w - half_eye_distance,
- cameratoworld.z.w));
- }
- }
- else {
- bounds.grow(transform_raster_to_world(0.0f, 0.0f));
- bounds.grow(transform_raster_to_world(0.0f, (float)height));
- bounds.grow(transform_raster_to_world((float)width, (float)height));
- bounds.grow(transform_raster_to_world((float)width, 0.0f));
- if(type == CAMERA_PERSPECTIVE) {
- /* Center point has the most distance in local Z axis,
- * use it to construct bounding box/
- */
- bounds.grow(transform_raster_to_world(0.5f*width, 0.5f*height));
- }
- }
- return bounds;
+ /* TODO(sergey): This is all rather stupid, but is there a way to perform
+ * checks we need in a more clear and smart fasion?
+ */
+ BoundBox bounds = BoundBox::empty;
+
+ if (type == CAMERA_PANORAMA) {
+ if (use_spherical_stereo == false) {
+ bounds.grow(make_float3(cameratoworld.x.w, cameratoworld.y.w, cameratoworld.z.w));
+ }
+ else {
+ float half_eye_distance = interocular_distance * 0.5f;
+
+ bounds.grow(make_float3(
+ cameratoworld.x.w + half_eye_distance, cameratoworld.y.w, cameratoworld.z.w));
+
+ bounds.grow(make_float3(
+ cameratoworld.z.w, cameratoworld.y.w + half_eye_distance, cameratoworld.z.w));
+
+ bounds.grow(make_float3(
+ cameratoworld.x.w - half_eye_distance, cameratoworld.y.w, cameratoworld.z.w));
+
+ bounds.grow(make_float3(
+ cameratoworld.x.w, cameratoworld.y.w - half_eye_distance, cameratoworld.z.w));
+ }
+ }
+ else {
+ bounds.grow(transform_raster_to_world(0.0f, 0.0f));
+ bounds.grow(transform_raster_to_world(0.0f, (float)height));
+ bounds.grow(transform_raster_to_world((float)width, (float)height));
+ bounds.grow(transform_raster_to_world((float)width, 0.0f));
+ if (type == CAMERA_PERSPECTIVE) {
+ /* Center point has the most distance in local Z axis,
+ * use it to construct bounding box/
+ */
+ bounds.grow(transform_raster_to_world(0.5f * width, 0.5f * height));
+ }
+ }
+ return bounds;
}
float Camera::world_to_raster_size(float3 P)
{
- float res = 1.0f;
-
- if(type == CAMERA_ORTHOGRAPHIC) {
- res = min(len(full_dx), len(full_dy));
-
- if(offscreen_dicing_scale > 1.0f) {
- float3 p = transform_point(&worldtocamera, P);
- float3 v = transform_perspective(&full_rastertocamera, make_float3(full_width, full_height, 0.0f));
-
- /* Create point clamped to frustum */
- float3 c;
- c.x = max(-v.x, min(v.x, p.x));
- c.y = max(-v.y, min(v.y, p.y));
- c.z = max(0.0f, p.z);
-
- float f_dist = len(p - c) / sqrtf((v.x*v.x+v.y*v.y)*0.5f);
-
- if(f_dist > 0.0f) {
- res += res * f_dist * (offscreen_dicing_scale - 1.0f);
- }
- }
- }
- else if(type == CAMERA_PERSPECTIVE) {
- /* Calculate as if point is directly ahead of the camera. */
- float3 raster = make_float3(0.5f*full_width, 0.5f*full_height, 0.0f);
- float3 Pcamera = transform_perspective(&full_rastertocamera, raster);
-
- /* dDdx */
- float3 Ddiff = transform_direction(&cameratoworld, Pcamera);
- float3 dx = len_squared(full_dx) < len_squared(full_dy) ? full_dx : full_dy;
- float3 dDdx = normalize(Ddiff + dx) - normalize(Ddiff);
-
- /* dPdx */
- float dist = len(transform_point(&worldtocamera, P));
- float3 D = normalize(Ddiff);
- res = len(dist*dDdx - dot(dist*dDdx, D)*D);
-
- /* Decent approx distance to frustum (doesn't handle corners correctly, but not that big of a deal) */
- float f_dist = 0.0f;
-
- if(offscreen_dicing_scale > 1.0f) {
- float3 p = transform_point(&worldtocamera, P);
-
- /* Distance from the four planes */
- float r = dot(p, frustum_right_normal);
- float t = dot(p, frustum_top_normal);
- p = make_float3(-p.x, -p.y, p.z);
- float l = dot(p, frustum_right_normal);
- float b = dot(p, frustum_top_normal);
- p = make_float3(-p.x, -p.y, p.z);
-
- if(r <= 0.0f && l <= 0.0f && t <= 0.0f && b <= 0.0f) {
- /* Point is inside frustum */
- f_dist = 0.0f;
- }
- else if(r > 0.0f && l > 0.0f && t > 0.0f && b > 0.0f) {
- /* Point is behind frustum */
- f_dist = len(p);
- }
- else {
- /* Point may be behind or off to the side, need to check */
- float3 along_right = make_float3(-frustum_right_normal.z, 0.0f, frustum_right_normal.x);
- float3 along_left = make_float3(frustum_right_normal.z, 0.0f, frustum_right_normal.x);
- float3 along_top = make_float3(0.0f, -frustum_top_normal.z, frustum_top_normal.y);
- float3 along_bottom = make_float3(0.0f, frustum_top_normal.z, frustum_top_normal.y);
-
- float dist[] = {r, l, t, b};
- float3 along[] = {along_right, along_left, along_top, along_bottom};
-
- bool test_o = false;
-
- float *d = dist;
- float3 *a = along;
- for(int i = 0; i < 4; i++, d++, a++) {
- /* Test if we should check this side at all */
- if(*d > 0.0f) {
- if(dot(p, *a) >= 0.0f) {
- /* We are in front of the back edge of this side of the frustum */
- f_dist = max(f_dist, *d);
- }
- else {
- /* Possibly far enough behind the frustum to use distance to origin instead of edge */
- test_o = true;
- }
- }
- }
-
- if(test_o) {
- f_dist = (f_dist > 0) ? min(f_dist, len(p)) : len(p);
- }
- }
-
- if(f_dist > 0.0f) {
- res += len(dDdx - dot(dDdx, D)*D) * f_dist * (offscreen_dicing_scale - 1.0f);
- }
- }
- }
- else if(type == CAMERA_PANORAMA) {
- float3 D = transform_point(&worldtocamera, P);
- float dist = len(D);
-
- Ray ray = {{0}};
-
- /* Distortion can become so great that the results become meaningless, there
- * may be a better way to do this, but calculating differentials from the
- * point directly ahead seems to produce good enough results. */
+ float res = 1.0f;
+
+ if (type == CAMERA_ORTHOGRAPHIC) {
+ res = min(len(full_dx), len(full_dy));
+
+ if (offscreen_dicing_scale > 1.0f) {
+ float3 p = transform_point(&worldtocamera, P);
+ float3 v = transform_perspective(&full_rastertocamera,
+ make_float3(full_width, full_height, 0.0f));
+
+ /* Create point clamped to frustum */
+ float3 c;
+ c.x = max(-v.x, min(v.x, p.x));
+ c.y = max(-v.y, min(v.y, p.y));
+ c.z = max(0.0f, p.z);
+
+ float f_dist = len(p - c) / sqrtf((v.x * v.x + v.y * v.y) * 0.5f);
+
+ if (f_dist > 0.0f) {
+ res += res * f_dist * (offscreen_dicing_scale - 1.0f);
+ }
+ }
+ }
+ else if (type == CAMERA_PERSPECTIVE) {
+ /* Calculate as if point is directly ahead of the camera. */
+ float3 raster = make_float3(0.5f * full_width, 0.5f * full_height, 0.0f);
+ float3 Pcamera = transform_perspective(&full_rastertocamera, raster);
+
+ /* dDdx */
+ float3 Ddiff = transform_direction(&cameratoworld, Pcamera);
+ float3 dx = len_squared(full_dx) < len_squared(full_dy) ? full_dx : full_dy;
+ float3 dDdx = normalize(Ddiff + dx) - normalize(Ddiff);
+
+ /* dPdx */
+ float dist = len(transform_point(&worldtocamera, P));
+ float3 D = normalize(Ddiff);
+ res = len(dist * dDdx - dot(dist * dDdx, D) * D);
+
+ /* Decent approx distance to frustum (doesn't handle corners correctly, but not that big of a deal) */
+ float f_dist = 0.0f;
+
+ if (offscreen_dicing_scale > 1.0f) {
+ float3 p = transform_point(&worldtocamera, P);
+
+ /* Distance from the four planes */
+ float r = dot(p, frustum_right_normal);
+ float t = dot(p, frustum_top_normal);
+ p = make_float3(-p.x, -p.y, p.z);
+ float l = dot(p, frustum_right_normal);
+ float b = dot(p, frustum_top_normal);
+ p = make_float3(-p.x, -p.y, p.z);
+
+ if (r <= 0.0f && l <= 0.0f && t <= 0.0f && b <= 0.0f) {
+ /* Point is inside frustum */
+ f_dist = 0.0f;
+ }
+ else if (r > 0.0f && l > 0.0f && t > 0.0f && b > 0.0f) {
+ /* Point is behind frustum */
+ f_dist = len(p);
+ }
+ else {
+ /* Point may be behind or off to the side, need to check */
+ float3 along_right = make_float3(-frustum_right_normal.z, 0.0f, frustum_right_normal.x);
+ float3 along_left = make_float3(frustum_right_normal.z, 0.0f, frustum_right_normal.x);
+ float3 along_top = make_float3(0.0f, -frustum_top_normal.z, frustum_top_normal.y);
+ float3 along_bottom = make_float3(0.0f, frustum_top_normal.z, frustum_top_normal.y);
+
+ float dist[] = {r, l, t, b};
+ float3 along[] = {along_right, along_left, along_top, along_bottom};
+
+ bool test_o = false;
+
+ float *d = dist;
+ float3 *a = along;
+ for (int i = 0; i < 4; i++, d++, a++) {
+ /* Test if we should check this side at all */
+ if (*d > 0.0f) {
+ if (dot(p, *a) >= 0.0f) {
+ /* We are in front of the back edge of this side of the frustum */
+ f_dist = max(f_dist, *d);
+ }
+ else {
+ /* Possibly far enough behind the frustum to use distance to origin instead of edge */
+ test_o = true;
+ }
+ }
+ }
+
+ if (test_o) {
+ f_dist = (f_dist > 0) ? min(f_dist, len(p)) : len(p);
+ }
+ }
+
+ if (f_dist > 0.0f) {
+ res += len(dDdx - dot(dDdx, D) * D) * f_dist * (offscreen_dicing_scale - 1.0f);
+ }
+ }
+ }
+ else if (type == CAMERA_PANORAMA) {
+ float3 D = transform_point(&worldtocamera, P);
+ float dist = len(D);
+
+ Ray ray = {{0}};
+
+ /* Distortion can become so great that the results become meaningless, there
+ * may be a better way to do this, but calculating differentials from the
+ * point directly ahead seems to produce good enough results. */
#if 0
- float2 dir = direction_to_panorama(&kernel_camera, kernel_camera_motion.data(), normalize(D));
- float3 raster = transform_perspective(&full_cameratoraster, make_float3(dir.x, dir.y, 0.0f));
-
- ray.t = 1.0f;
- camera_sample_panorama(&kernel_camera, kernel_camera_motion.data(), raster.x, raster.y, 0.0f, 0.0f, &ray);
- if(ray.t == 0.0f) {
- /* No differentials, just use from directly ahead. */
- camera_sample_panorama(&kernel_camera, kernel_camera_motion.data(), 0.5f*full_width, 0.5f*full_height, 0.0f, 0.0f, &ray);
- }
+ float2 dir = direction_to_panorama(&kernel_camera, kernel_camera_motion.data(), normalize(D));
+ float3 raster = transform_perspective(&full_cameratoraster, make_float3(dir.x, dir.y, 0.0f));
+
+ ray.t = 1.0f;
+ camera_sample_panorama(&kernel_camera, kernel_camera_motion.data(), raster.x, raster.y, 0.0f, 0.0f, &ray);
+ if(ray.t == 0.0f) {
+ /* No differentials, just use from directly ahead. */
+ camera_sample_panorama(&kernel_camera, kernel_camera_motion.data(), 0.5f*full_width, 0.5f*full_height, 0.0f, 0.0f, &ray);
+ }
#else
- camera_sample_panorama(&kernel_camera, kernel_camera_motion.data(), 0.5f*full_width, 0.5f*full_height, 0.0f, 0.0f, &ray);
+ camera_sample_panorama(&kernel_camera,
+ kernel_camera_motion.data(),
+ 0.5f * full_width,
+ 0.5f * full_height,
+ 0.0f,
+ 0.0f,
+ &ray);
#endif
- differential_transfer(&ray.dP, ray.dP, ray.D, ray.dD, ray.D, dist);
+ differential_transfer(&ray.dP, ray.dP, ray.D, ray.dD, ray.D, dist);
- return max(len(ray.dP.dx),len(ray.dP.dy));
- }
+ return max(len(ray.dP.dx), len(ray.dP.dy));
+ }
- return res;
+ return res;
}
bool Camera::use_motion() const
{
- return motion.size() > 1;
+ return motion.size() > 1;
}
float Camera::motion_time(int step) const
{
- return (use_motion()) ? 2.0f * step / (motion.size() - 1) - 1.0f : 0.0f;
+ return (use_motion()) ? 2.0f * step / (motion.size() - 1) - 1.0f : 0.0f;
}
int Camera::motion_step(float time) const
{
- if(use_motion()) {
- for(int step = 0; step < motion.size(); step++) {
- if(time == motion_time(step)) {
- return step;
- }
- }
- }
-
- return -1;
+ if (use_motion()) {
+ for (int step = 0; step < motion.size(); step++) {
+ if (time == motion_time(step)) {
+ return step;
+ }
+ }
+ }
+
+ return -1;
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/render/camera.h b/intern/cycles/render/camera.h
index 961e8f918ea..0e91fa44a5b 100644
--- a/intern/cycles/render/camera.h
+++ b/intern/cycles/render/camera.h
@@ -40,179 +40,179 @@ class Scene;
*/
class Camera : public Node {
-public:
- NODE_DECLARE
-
- /* Specifies an offset for the shutter's time interval. */
- enum MotionPosition {
- /* Shutter opens at the current frame. */
- MOTION_POSITION_START = 0,
- /* Shutter is fully open at the current frame. */
- MOTION_POSITION_CENTER = 1,
- /* Shutter closes at the current frame. */
- MOTION_POSITION_END = 2,
-
- MOTION_NUM_POSITIONS,
- };
-
- /* Specifies rolling shutter effect. */
- enum RollingShutterType {
- /* No rolling shutter effect. */
- ROLLING_SHUTTER_NONE = 0,
- /* Sensor is being scanned vertically from top to bottom. */
- ROLLING_SHUTTER_TOP = 1,
-
- ROLLING_SHUTTER_NUM_TYPES,
- };
-
- /* Stereo Type */
- enum StereoEye {
- STEREO_NONE,
- STEREO_LEFT,
- STEREO_RIGHT,
- };
-
- /* motion blur */
- float shuttertime;
- MotionPosition motion_position;
- array<float> shutter_curve;
- size_t shutter_table_offset;
-
- /* ** Rolling shutter effect. ** */
- /* Defines rolling shutter effect type. */
- RollingShutterType rolling_shutter_type;
- /* Specifies exposure time of scanlines when using
- * rolling shutter effect.
- */
- float rolling_shutter_duration;
-
- /* depth of field */
- float focaldistance;
- float aperturesize;
- uint blades;
- float bladesrotation;
-
- /* type */
- CameraType type;
- float fov;
-
- /* panorama */
- PanoramaType panorama_type;
- float fisheye_fov;
- float fisheye_lens;
- float latitude_min;
- float latitude_max;
- float longitude_min;
- float longitude_max;
-
- /* panorama stereo */
- StereoEye stereo_eye;
- bool use_spherical_stereo;
- float interocular_distance;
- float convergence_distance;
- bool use_pole_merge;
- float pole_merge_angle_from;
- float pole_merge_angle_to;
-
- /* anamorphic lens bokeh */
- float aperture_ratio;
-
- /* sensor */
- float sensorwidth;
- float sensorheight;
-
- /* clipping */
- float nearclip;
- float farclip;
-
- /* screen */
- int width, height;
- int resolution;
- BoundBox2D viewplane;
- /* width and height change during preview, so we need these for calculating dice rates. */
- int full_width, full_height;
- /* controls how fast the dicing rate falls off for geometry out side of view */
- float offscreen_dicing_scale;
-
- /* border */
- BoundBox2D border;
- BoundBox2D viewport_camera_border;
-
- /* transformation */
- Transform matrix;
-
- /* motion */
- array<Transform> motion;
- bool use_perspective_motion;
- float fov_pre, fov_post;
-
- /* computed camera parameters */
- ProjectionTransform screentoworld;
- ProjectionTransform rastertoworld;
- ProjectionTransform ndctoworld;
- Transform cameratoworld;
-
- ProjectionTransform worldtoraster;
- ProjectionTransform worldtoscreen;
- ProjectionTransform worldtondc;
- Transform worldtocamera;
-
- ProjectionTransform rastertocamera;
- ProjectionTransform cameratoraster;
-
- ProjectionTransform full_rastertocamera;
-
- float3 dx;
- float3 dy;
-
- float3 full_dx;
- float3 full_dy;
-
- float3 frustum_right_normal;
- float3 frustum_top_normal;
-
- /* update */
- bool need_update;
- bool need_device_update;
- bool need_flags_update;
- int previous_need_motion;
-
- /* Kernel camera data, copied here for dicing. */
- KernelCamera kernel_camera;
- array<DecomposedTransform> kernel_camera_motion;
-
- /* functions */
- Camera();
- ~Camera();
-
- void compute_auto_viewplane();
-
- void update(Scene *scene);
-
- void device_update(Device *device, DeviceScene *dscene, Scene *scene);
- void device_update_volume(Device *device, DeviceScene *dscene, Scene *scene);
- void device_free(Device *device, DeviceScene *dscene, Scene *scene);
-
- bool modified(const Camera& cam);
- bool motion_modified(const Camera& cam);
- void tag_update();
-
- /* Public utility functions. */
- BoundBox viewplane_bounds_get();
-
- /* Calculates the width of a pixel at point in world space. */
- float world_to_raster_size(float3 P);
-
- /* Motion blur. */
- float motion_time(int step) const;
- int motion_step(float time) const;
- bool use_motion() const;
-
-private:
- /* Private utility functions. */
- float3 transform_raster_to_world(float raster_x, float raster_y);
+ public:
+ NODE_DECLARE
+
+ /* Specifies an offset for the shutter's time interval. */
+ enum MotionPosition {
+ /* Shutter opens at the current frame. */
+ MOTION_POSITION_START = 0,
+ /* Shutter is fully open at the current frame. */
+ MOTION_POSITION_CENTER = 1,
+ /* Shutter closes at the current frame. */
+ MOTION_POSITION_END = 2,
+
+ MOTION_NUM_POSITIONS,
+ };
+
+ /* Specifies rolling shutter effect. */
+ enum RollingShutterType {
+ /* No rolling shutter effect. */
+ ROLLING_SHUTTER_NONE = 0,
+ /* Sensor is being scanned vertically from top to bottom. */
+ ROLLING_SHUTTER_TOP = 1,
+
+ ROLLING_SHUTTER_NUM_TYPES,
+ };
+
+ /* Stereo Type */
+ enum StereoEye {
+ STEREO_NONE,
+ STEREO_LEFT,
+ STEREO_RIGHT,
+ };
+
+ /* motion blur */
+ float shuttertime;
+ MotionPosition motion_position;
+ array<float> shutter_curve;
+ size_t shutter_table_offset;
+
+ /* ** Rolling shutter effect. ** */
+ /* Defines rolling shutter effect type. */
+ RollingShutterType rolling_shutter_type;
+ /* Specifies exposure time of scanlines when using
+ * rolling shutter effect.
+ */
+ float rolling_shutter_duration;
+
+ /* depth of field */
+ float focaldistance;
+ float aperturesize;
+ uint blades;
+ float bladesrotation;
+
+ /* type */
+ CameraType type;
+ float fov;
+
+ /* panorama */
+ PanoramaType panorama_type;
+ float fisheye_fov;
+ float fisheye_lens;
+ float latitude_min;
+ float latitude_max;
+ float longitude_min;
+ float longitude_max;
+
+ /* panorama stereo */
+ StereoEye stereo_eye;
+ bool use_spherical_stereo;
+ float interocular_distance;
+ float convergence_distance;
+ bool use_pole_merge;
+ float pole_merge_angle_from;
+ float pole_merge_angle_to;
+
+ /* anamorphic lens bokeh */
+ float aperture_ratio;
+
+ /* sensor */
+ float sensorwidth;
+ float sensorheight;
+
+ /* clipping */
+ float nearclip;
+ float farclip;
+
+ /* screen */
+ int width, height;
+ int resolution;
+ BoundBox2D viewplane;
+ /* width and height change during preview, so we need these for calculating dice rates. */
+ int full_width, full_height;
+ /* controls how fast the dicing rate falls off for geometry out side of view */
+ float offscreen_dicing_scale;
+
+ /* border */
+ BoundBox2D border;
+ BoundBox2D viewport_camera_border;
+
+ /* transformation */
+ Transform matrix;
+
+ /* motion */
+ array<Transform> motion;
+ bool use_perspective_motion;
+ float fov_pre, fov_post;
+
+ /* computed camera parameters */
+ ProjectionTransform screentoworld;
+ ProjectionTransform rastertoworld;
+ ProjectionTransform ndctoworld;
+ Transform cameratoworld;
+
+ ProjectionTransform worldtoraster;
+ ProjectionTransform worldtoscreen;
+ ProjectionTransform worldtondc;
+ Transform worldtocamera;
+
+ ProjectionTransform rastertocamera;
+ ProjectionTransform cameratoraster;
+
+ ProjectionTransform full_rastertocamera;
+
+ float3 dx;
+ float3 dy;
+
+ float3 full_dx;
+ float3 full_dy;
+
+ float3 frustum_right_normal;
+ float3 frustum_top_normal;
+
+ /* update */
+ bool need_update;
+ bool need_device_update;
+ bool need_flags_update;
+ int previous_need_motion;
+
+ /* Kernel camera data, copied here for dicing. */
+ KernelCamera kernel_camera;
+ array<DecomposedTransform> kernel_camera_motion;
+
+ /* functions */
+ Camera();
+ ~Camera();
+
+ void compute_auto_viewplane();
+
+ void update(Scene *scene);
+
+ void device_update(Device *device, DeviceScene *dscene, Scene *scene);
+ void device_update_volume(Device *device, DeviceScene *dscene, Scene *scene);
+ void device_free(Device *device, DeviceScene *dscene, Scene *scene);
+
+ bool modified(const Camera &cam);
+ bool motion_modified(const Camera &cam);
+ void tag_update();
+
+ /* Public utility functions. */
+ BoundBox viewplane_bounds_get();
+
+ /* Calculates the width of a pixel at point in world space. */
+ float world_to_raster_size(float3 P);
+
+ /* Motion blur. */
+ float motion_time(int step) const;
+ int motion_step(float time) const;
+ bool use_motion() const;
+
+ private:
+ /* Private utility functions. */
+ float3 transform_raster_to_world(float raster_x, float raster_y);
};
CCL_NAMESPACE_END
-#endif /* __CAMERA_H__ */
+#endif /* __CAMERA_H__ */
diff --git a/intern/cycles/render/constant_fold.cpp b/intern/cycles/render/constant_fold.cpp
index 98c3e99996c..e475ff60eef 100644
--- a/intern/cycles/render/constant_fold.cpp
+++ b/intern/cycles/render/constant_fold.cpp
@@ -22,371 +22,374 @@
CCL_NAMESPACE_BEGIN
-ConstantFolder::ConstantFolder(ShaderGraph *graph, ShaderNode *node, ShaderOutput *output, Scene *scene)
-: graph(graph), node(node), output(output), scene(scene)
+ConstantFolder::ConstantFolder(ShaderGraph *graph,
+ ShaderNode *node,
+ ShaderOutput *output,
+ Scene *scene)
+ : graph(graph), node(node), output(output), scene(scene)
{
}
bool ConstantFolder::all_inputs_constant() const
{
- foreach(ShaderInput *input, node->inputs) {
- if(input->link) {
- return false;
- }
- }
+ foreach (ShaderInput *input, node->inputs) {
+ if (input->link) {
+ return false;
+ }
+ }
- return true;
+ return true;
}
void ConstantFolder::make_constant(float value) const
{
- VLOG(1) << "Folding " << node->name << "::" << output->name() << " to constant (" << value << ").";
+ VLOG(1) << "Folding " << node->name << "::" << output->name() << " to constant (" << value
+ << ").";
- foreach(ShaderInput *sock, output->links) {
- sock->set(value);
- }
+ foreach (ShaderInput *sock, output->links) {
+ sock->set(value);
+ }
- graph->disconnect(output);
+ graph->disconnect(output);
}
void ConstantFolder::make_constant(float3 value) const
{
- VLOG(1) << "Folding " << node->name << "::" << output->name() << " to constant " << value << ".";
+ VLOG(1) << "Folding " << node->name << "::" << output->name() << " to constant " << value << ".";
- foreach(ShaderInput *sock, output->links) {
- sock->set(value);
- }
+ foreach (ShaderInput *sock, output->links) {
+ sock->set(value);
+ }
- graph->disconnect(output);
+ graph->disconnect(output);
}
void ConstantFolder::make_constant_clamp(float value, bool clamp) const
{
- make_constant(clamp ? saturate(value) : value);
+ make_constant(clamp ? saturate(value) : value);
}
void ConstantFolder::make_constant_clamp(float3 value, bool clamp) const
{
- if(clamp) {
- value.x = saturate(value.x);
- value.y = saturate(value.y);
- value.z = saturate(value.z);
- }
+ if (clamp) {
+ value.x = saturate(value.x);
+ value.y = saturate(value.y);
+ value.z = saturate(value.z);
+ }
- make_constant(value);
+ make_constant(value);
}
void ConstantFolder::make_zero() const
{
- if(output->type() == SocketType::FLOAT) {
- make_constant(0.0f);
- }
- else if(SocketType::is_float3(output->type())) {
- make_constant(make_float3(0.0f, 0.0f, 0.0f));
- }
- else {
- assert(0);
- }
+ if (output->type() == SocketType::FLOAT) {
+ make_constant(0.0f);
+ }
+ else if (SocketType::is_float3(output->type())) {
+ make_constant(make_float3(0.0f, 0.0f, 0.0f));
+ }
+ else {
+ assert(0);
+ }
}
void ConstantFolder::make_one() const
{
- if(output->type() == SocketType::FLOAT) {
- make_constant(1.0f);
- }
- else if(SocketType::is_float3(output->type())) {
- make_constant(make_float3(1.0f, 1.0f, 1.0f));
- }
- else {
- assert(0);
- }
+ if (output->type() == SocketType::FLOAT) {
+ make_constant(1.0f);
+ }
+ else if (SocketType::is_float3(output->type())) {
+ make_constant(make_float3(1.0f, 1.0f, 1.0f));
+ }
+ else {
+ assert(0);
+ }
}
void ConstantFolder::bypass(ShaderOutput *new_output) const
{
- assert(new_output);
+ assert(new_output);
- VLOG(1) << "Folding " << node->name << "::" << output->name() << " to socket " << new_output->parent->name << "::" << new_output->name() << ".";
+ VLOG(1) << "Folding " << node->name << "::" << output->name() << " to socket "
+ << new_output->parent->name << "::" << new_output->name() << ".";
- /* Remove all outgoing links from socket and connect them to new_output instead.
- * The graph->relink method affects node inputs, so it's not safe to use in constant
- * folding if the node has multiple outputs and will thus be folded multiple times. */
- vector<ShaderInput*> outputs = output->links;
+ /* Remove all outgoing links from socket and connect them to new_output instead.
+ * The graph->relink method affects node inputs, so it's not safe to use in constant
+ * folding if the node has multiple outputs and will thus be folded multiple times. */
+ vector<ShaderInput *> outputs = output->links;
- graph->disconnect(output);
+ graph->disconnect(output);
- foreach(ShaderInput *sock, outputs) {
- graph->connect(new_output, sock);
- }
+ foreach (ShaderInput *sock, outputs) {
+ graph->connect(new_output, sock);
+ }
}
void ConstantFolder::discard() const
{
- assert(output->type() == SocketType::CLOSURE);
+ assert(output->type() == SocketType::CLOSURE);
- VLOG(1) << "Discarding closure " << node->name << ".";
+ VLOG(1) << "Discarding closure " << node->name << ".";
- graph->disconnect(output);
+ graph->disconnect(output);
}
void ConstantFolder::bypass_or_discard(ShaderInput *input) const
{
- assert(input->type() == SocketType::CLOSURE);
-
- if(input->link) {
- bypass(input->link);
- }
- else {
- discard();
- }
+ assert(input->type() == SocketType::CLOSURE);
+
+ if (input->link) {
+ bypass(input->link);
+ }
+ else {
+ discard();
+ }
}
bool ConstantFolder::try_bypass_or_make_constant(ShaderInput *input, bool clamp) const
{
- if(input->type() != output->type()) {
- return false;
- }
- else if(!input->link) {
- if(input->type() == SocketType::FLOAT) {
- make_constant_clamp(node->get_float(input->socket_type), clamp);
- return true;
- }
- else if(SocketType::is_float3(input->type())) {
- make_constant_clamp(node->get_float3(input->socket_type), clamp);
- return true;
- }
- }
- else if(!clamp) {
- bypass(input->link);
- return true;
- }
- else {
- /* disconnect other inputs if we can't fully bypass due to clamp */
- foreach(ShaderInput *other, node->inputs) {
- if(other != input && other->link) {
- graph->disconnect(other);
- }
- }
- }
-
- return false;
+ if (input->type() != output->type()) {
+ return false;
+ }
+ else if (!input->link) {
+ if (input->type() == SocketType::FLOAT) {
+ make_constant_clamp(node->get_float(input->socket_type), clamp);
+ return true;
+ }
+ else if (SocketType::is_float3(input->type())) {
+ make_constant_clamp(node->get_float3(input->socket_type), clamp);
+ return true;
+ }
+ }
+ else if (!clamp) {
+ bypass(input->link);
+ return true;
+ }
+ else {
+ /* disconnect other inputs if we can't fully bypass due to clamp */
+ foreach (ShaderInput *other, node->inputs) {
+ if (other != input && other->link) {
+ graph->disconnect(other);
+ }
+ }
+ }
+
+ return false;
}
bool ConstantFolder::is_zero(ShaderInput *input) const
{
- if(!input->link) {
- if(input->type() == SocketType::FLOAT) {
- return node->get_float(input->socket_type) == 0.0f;
- }
- else if(SocketType::is_float3(input->type())) {
- return node->get_float3(input->socket_type) ==
- make_float3(0.0f, 0.0f, 0.0f);
- }
- }
-
- return false;
+ if (!input->link) {
+ if (input->type() == SocketType::FLOAT) {
+ return node->get_float(input->socket_type) == 0.0f;
+ }
+ else if (SocketType::is_float3(input->type())) {
+ return node->get_float3(input->socket_type) == make_float3(0.0f, 0.0f, 0.0f);
+ }
+ }
+
+ return false;
}
bool ConstantFolder::is_one(ShaderInput *input) const
{
- if(!input->link) {
- if(input->type() == SocketType::FLOAT) {
- return node->get_float(input->socket_type) == 1.0f;
- }
- else if(SocketType::is_float3(input->type())) {
- return node->get_float3(input->socket_type) ==
- make_float3(1.0f, 1.0f, 1.0f);
- }
- }
-
- return false;
+ if (!input->link) {
+ if (input->type() == SocketType::FLOAT) {
+ return node->get_float(input->socket_type) == 1.0f;
+ }
+ else if (SocketType::is_float3(input->type())) {
+ return node->get_float3(input->socket_type) == make_float3(1.0f, 1.0f, 1.0f);
+ }
+ }
+
+ return false;
}
/* Specific nodes */
void ConstantFolder::fold_mix(NodeMix type, bool clamp) const
{
- ShaderInput *fac_in = node->input("Fac");
- ShaderInput *color1_in = node->input("Color1");
- ShaderInput *color2_in = node->input("Color2");
-
- float fac = saturate(node->get_float(fac_in->socket_type));
- bool fac_is_zero = !fac_in->link && fac == 0.0f;
- bool fac_is_one = !fac_in->link && fac == 1.0f;
-
- /* remove no-op node when factor is 0.0 */
- if(fac_is_zero) {
- /* note that some of the modes will clamp out of bounds values even without use_clamp */
- if(!(type == NODE_MIX_LIGHT || type == NODE_MIX_DODGE || type == NODE_MIX_BURN)) {
- if(try_bypass_or_make_constant(color1_in, clamp)) {
- return;
- }
- }
- }
-
- switch(type) {
- case NODE_MIX_BLEND:
- /* remove useless mix colors nodes */
- if(color1_in->link && color2_in->link) {
- if(color1_in->link == color2_in->link) {
- try_bypass_or_make_constant(color1_in, clamp);
- break;
- }
- }
- else if(!color1_in->link && !color2_in->link) {
- float3 color1 = node->get_float3(color1_in->socket_type);
- float3 color2 = node->get_float3(color2_in->socket_type);
- if(color1 == color2) {
- try_bypass_or_make_constant(color1_in, clamp);
- break;
- }
- }
- /* remove no-op mix color node when factor is 1.0 */
- if(fac_is_one) {
- try_bypass_or_make_constant(color2_in, clamp);
- break;
- }
- break;
- case NODE_MIX_ADD:
- /* 0 + X (fac 1) == X */
- if(is_zero(color1_in) && fac_is_one) {
- try_bypass_or_make_constant(color2_in, clamp);
- }
- /* X + 0 (fac ?) == X */
- else if(is_zero(color2_in)) {
- try_bypass_or_make_constant(color1_in, clamp);
- }
- break;
- case NODE_MIX_SUB:
- /* X - 0 (fac ?) == X */
- if(is_zero(color2_in)) {
- try_bypass_or_make_constant(color1_in, clamp);
- }
- /* X - X (fac 1) == 0 */
- else if(color1_in->link && color1_in->link == color2_in->link && fac_is_one) {
- make_zero();
- }
- break;
- case NODE_MIX_MUL:
- /* X * 1 (fac ?) == X, 1 * X (fac 1) == X */
- if(is_one(color1_in) && fac_is_one) {
- try_bypass_or_make_constant(color2_in, clamp);
- }
- else if(is_one(color2_in)) {
- try_bypass_or_make_constant(color1_in, clamp);
- }
- /* 0 * ? (fac ?) == 0, ? * 0 (fac 1) == 0 */
- else if(is_zero(color1_in)) {
- make_zero();
- }
- else if(is_zero(color2_in) && fac_is_one) {
- make_zero();
- }
- break;
- case NODE_MIX_DIV:
- /* X / 1 (fac ?) == X */
- if(is_one(color2_in)) {
- try_bypass_or_make_constant(color1_in, clamp);
- }
- /* 0 / ? (fac ?) == 0 */
- else if(is_zero(color1_in)) {
- make_zero();
- }
- break;
- default:
- break;
- }
+ ShaderInput *fac_in = node->input("Fac");
+ ShaderInput *color1_in = node->input("Color1");
+ ShaderInput *color2_in = node->input("Color2");
+
+ float fac = saturate(node->get_float(fac_in->socket_type));
+ bool fac_is_zero = !fac_in->link && fac == 0.0f;
+ bool fac_is_one = !fac_in->link && fac == 1.0f;
+
+ /* remove no-op node when factor is 0.0 */
+ if (fac_is_zero) {
+ /* note that some of the modes will clamp out of bounds values even without use_clamp */
+ if (!(type == NODE_MIX_LIGHT || type == NODE_MIX_DODGE || type == NODE_MIX_BURN)) {
+ if (try_bypass_or_make_constant(color1_in, clamp)) {
+ return;
+ }
+ }
+ }
+
+ switch (type) {
+ case NODE_MIX_BLEND:
+ /* remove useless mix colors nodes */
+ if (color1_in->link && color2_in->link) {
+ if (color1_in->link == color2_in->link) {
+ try_bypass_or_make_constant(color1_in, clamp);
+ break;
+ }
+ }
+ else if (!color1_in->link && !color2_in->link) {
+ float3 color1 = node->get_float3(color1_in->socket_type);
+ float3 color2 = node->get_float3(color2_in->socket_type);
+ if (color1 == color2) {
+ try_bypass_or_make_constant(color1_in, clamp);
+ break;
+ }
+ }
+ /* remove no-op mix color node when factor is 1.0 */
+ if (fac_is_one) {
+ try_bypass_or_make_constant(color2_in, clamp);
+ break;
+ }
+ break;
+ case NODE_MIX_ADD:
+ /* 0 + X (fac 1) == X */
+ if (is_zero(color1_in) && fac_is_one) {
+ try_bypass_or_make_constant(color2_in, clamp);
+ }
+ /* X + 0 (fac ?) == X */
+ else if (is_zero(color2_in)) {
+ try_bypass_or_make_constant(color1_in, clamp);
+ }
+ break;
+ case NODE_MIX_SUB:
+ /* X - 0 (fac ?) == X */
+ if (is_zero(color2_in)) {
+ try_bypass_or_make_constant(color1_in, clamp);
+ }
+ /* X - X (fac 1) == 0 */
+ else if (color1_in->link && color1_in->link == color2_in->link && fac_is_one) {
+ make_zero();
+ }
+ break;
+ case NODE_MIX_MUL:
+ /* X * 1 (fac ?) == X, 1 * X (fac 1) == X */
+ if (is_one(color1_in) && fac_is_one) {
+ try_bypass_or_make_constant(color2_in, clamp);
+ }
+ else if (is_one(color2_in)) {
+ try_bypass_or_make_constant(color1_in, clamp);
+ }
+ /* 0 * ? (fac ?) == 0, ? * 0 (fac 1) == 0 */
+ else if (is_zero(color1_in)) {
+ make_zero();
+ }
+ else if (is_zero(color2_in) && fac_is_one) {
+ make_zero();
+ }
+ break;
+ case NODE_MIX_DIV:
+ /* X / 1 (fac ?) == X */
+ if (is_one(color2_in)) {
+ try_bypass_or_make_constant(color1_in, clamp);
+ }
+ /* 0 / ? (fac ?) == 0 */
+ else if (is_zero(color1_in)) {
+ make_zero();
+ }
+ break;
+ default:
+ break;
+ }
}
void ConstantFolder::fold_math(NodeMath type, bool clamp) const
{
- ShaderInput *value1_in = node->input("Value1");
- ShaderInput *value2_in = node->input("Value2");
-
- switch(type) {
- case NODE_MATH_ADD:
- /* X + 0 == 0 + X == X */
- if(is_zero(value1_in)) {
- try_bypass_or_make_constant(value2_in, clamp);
- }
- else if(is_zero(value2_in)) {
- try_bypass_or_make_constant(value1_in, clamp);
- }
- break;
- case NODE_MATH_SUBTRACT:
- /* X - 0 == X */
- if(is_zero(value2_in)) {
- try_bypass_or_make_constant(value1_in, clamp);
- }
- break;
- case NODE_MATH_MULTIPLY:
- /* X * 1 == 1 * X == X */
- if(is_one(value1_in)) {
- try_bypass_or_make_constant(value2_in, clamp);
- }
- else if(is_one(value2_in)) {
- try_bypass_or_make_constant(value1_in, clamp);
- }
- /* X * 0 == 0 * X == 0 */
- else if(is_zero(value1_in) || is_zero(value2_in)) {
- make_zero();
- }
- break;
- case NODE_MATH_DIVIDE:
- /* X / 1 == X */
- if(is_one(value2_in)) {
- try_bypass_or_make_constant(value1_in, clamp);
- }
- /* 0 / X == 0 */
- else if(is_zero(value1_in)) {
- make_zero();
- }
- break;
- case NODE_MATH_POWER:
- /* 1 ^ X == X ^ 0 == 1 */
- if(is_one(value1_in) || is_zero(value2_in)) {
- make_one();
- }
- /* X ^ 1 == X */
- else if(is_one(value2_in)) {
- try_bypass_or_make_constant(value1_in, clamp);
- }
- default:
- break;
- }
+ ShaderInput *value1_in = node->input("Value1");
+ ShaderInput *value2_in = node->input("Value2");
+
+ switch (type) {
+ case NODE_MATH_ADD:
+ /* X + 0 == 0 + X == X */
+ if (is_zero(value1_in)) {
+ try_bypass_or_make_constant(value2_in, clamp);
+ }
+ else if (is_zero(value2_in)) {
+ try_bypass_or_make_constant(value1_in, clamp);
+ }
+ break;
+ case NODE_MATH_SUBTRACT:
+ /* X - 0 == X */
+ if (is_zero(value2_in)) {
+ try_bypass_or_make_constant(value1_in, clamp);
+ }
+ break;
+ case NODE_MATH_MULTIPLY:
+ /* X * 1 == 1 * X == X */
+ if (is_one(value1_in)) {
+ try_bypass_or_make_constant(value2_in, clamp);
+ }
+ else if (is_one(value2_in)) {
+ try_bypass_or_make_constant(value1_in, clamp);
+ }
+ /* X * 0 == 0 * X == 0 */
+ else if (is_zero(value1_in) || is_zero(value2_in)) {
+ make_zero();
+ }
+ break;
+ case NODE_MATH_DIVIDE:
+ /* X / 1 == X */
+ if (is_one(value2_in)) {
+ try_bypass_or_make_constant(value1_in, clamp);
+ }
+ /* 0 / X == 0 */
+ else if (is_zero(value1_in)) {
+ make_zero();
+ }
+ break;
+ case NODE_MATH_POWER:
+ /* 1 ^ X == X ^ 0 == 1 */
+ if (is_one(value1_in) || is_zero(value2_in)) {
+ make_one();
+ }
+ /* X ^ 1 == X */
+ else if (is_one(value2_in)) {
+ try_bypass_or_make_constant(value1_in, clamp);
+ }
+ default:
+ break;
+ }
}
void ConstantFolder::fold_vector_math(NodeVectorMath type) const
{
- ShaderInput *vector1_in = node->input("Vector1");
- ShaderInput *vector2_in = node->input("Vector2");
-
- switch(type) {
- case NODE_VECTOR_MATH_ADD:
- /* X + 0 == 0 + X == X */
- if(is_zero(vector1_in)) {
- try_bypass_or_make_constant(vector2_in);
- }
- else if(is_zero(vector2_in)) {
- try_bypass_or_make_constant(vector1_in);
- }
- break;
- case NODE_VECTOR_MATH_SUBTRACT:
- /* X - 0 == X */
- if(is_zero(vector2_in)) {
- try_bypass_or_make_constant(vector1_in);
- }
- break;
- case NODE_VECTOR_MATH_DOT_PRODUCT:
- case NODE_VECTOR_MATH_CROSS_PRODUCT:
- /* X * 0 == 0 * X == 0 */
- if(is_zero(vector1_in) || is_zero(vector2_in)) {
- make_zero();
- }
- break;
- default:
- break;
- }
+ ShaderInput *vector1_in = node->input("Vector1");
+ ShaderInput *vector2_in = node->input("Vector2");
+
+ switch (type) {
+ case NODE_VECTOR_MATH_ADD:
+ /* X + 0 == 0 + X == X */
+ if (is_zero(vector1_in)) {
+ try_bypass_or_make_constant(vector2_in);
+ }
+ else if (is_zero(vector2_in)) {
+ try_bypass_or_make_constant(vector1_in);
+ }
+ break;
+ case NODE_VECTOR_MATH_SUBTRACT:
+ /* X - 0 == X */
+ if (is_zero(vector2_in)) {
+ try_bypass_or_make_constant(vector1_in);
+ }
+ break;
+ case NODE_VECTOR_MATH_DOT_PRODUCT:
+ case NODE_VECTOR_MATH_CROSS_PRODUCT:
+ /* X * 0 == 0 * X == 0 */
+ if (is_zero(vector1_in) || is_zero(vector2_in)) {
+ make_zero();
+ }
+ break;
+ default:
+ break;
+ }
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/render/constant_fold.h b/intern/cycles/render/constant_fold.h
index 6ec94b055e3..c14b94868dc 100644
--- a/intern/cycles/render/constant_fold.h
+++ b/intern/cycles/render/constant_fold.h
@@ -29,45 +29,45 @@ class ShaderNode;
class ShaderOutput;
class ConstantFolder {
-public:
- ShaderGraph *const graph;
- ShaderNode *const node;
- ShaderOutput *const output;
+ public:
+ ShaderGraph *const graph;
+ ShaderNode *const node;
+ ShaderOutput *const output;
- Scene *scene;
+ Scene *scene;
- ConstantFolder(ShaderGraph *graph, ShaderNode *node, ShaderOutput *output, Scene *scene);
+ ConstantFolder(ShaderGraph *graph, ShaderNode *node, ShaderOutput *output, Scene *scene);
- bool all_inputs_constant() const;
+ bool all_inputs_constant() const;
- /* Constant folding helpers */
- void make_constant(float value) const;
- void make_constant(float3 value) const;
- void make_constant_clamp(float value, bool clamp) const;
- void make_constant_clamp(float3 value, bool clamp) const;
- void make_zero() const;
- void make_one() const;
+ /* Constant folding helpers */
+ void make_constant(float value) const;
+ void make_constant(float3 value) const;
+ void make_constant_clamp(float value, bool clamp) const;
+ void make_constant_clamp(float3 value, bool clamp) const;
+ void make_zero() const;
+ void make_one() const;
- /* Bypass node, relinking to another output socket. */
- void bypass(ShaderOutput *output) const;
+ /* Bypass node, relinking to another output socket. */
+ void bypass(ShaderOutput *output) const;
- /* For closure nodes, discard node entirely or bypass to one of its inputs. */
- void discard() const;
- void bypass_or_discard(ShaderInput *input) const;
+ /* For closure nodes, discard node entirely or bypass to one of its inputs. */
+ void discard() const;
+ void bypass_or_discard(ShaderInput *input) const;
- /* Bypass or make constant, unless we can't due to clamp being true. */
- bool try_bypass_or_make_constant(ShaderInput *input, bool clamp = false) const;
+ /* Bypass or make constant, unless we can't due to clamp being true. */
+ bool try_bypass_or_make_constant(ShaderInput *input, bool clamp = false) const;
- /* Test if shader inputs of the current nodes have fixed values. */
- bool is_zero(ShaderInput *input) const;
- bool is_one(ShaderInput *input) const;
+ /* Test if shader inputs of the current nodes have fixed values. */
+ bool is_zero(ShaderInput *input) const;
+ bool is_one(ShaderInput *input) const;
- /* Specific nodes. */
- void fold_mix(NodeMix type, bool clamp) const;
- void fold_math(NodeMath type, bool clamp) const;
- void fold_vector_math(NodeVectorMath type) const;
+ /* Specific nodes. */
+ void fold_mix(NodeMix type, bool clamp) const;
+ void fold_math(NodeMath type, bool clamp) const;
+ void fold_vector_math(NodeVectorMath type) const;
};
CCL_NAMESPACE_END
-#endif /* __CONSTANT_FOLD_H__ */
+#endif /* __CONSTANT_FOLD_H__ */
diff --git a/intern/cycles/render/coverage.cpp b/intern/cycles/render/coverage.cpp
index 72ef4cda3ff..0a29903728a 100644
--- a/intern/cycles/render/coverage.cpp
+++ b/intern/cycles/render/coverage.cpp
@@ -25,119 +25,128 @@
CCL_NAMESPACE_BEGIN
-static bool crypomatte_comp(const pair<float, float>& i, const pair<float, float> j) { return i.first > j.first; }
+static bool crypomatte_comp(const pair<float, float> &i, const pair<float, float> j)
+{
+ return i.first > j.first;
+}
void Coverage::finalize()
{
- int pass_offset = 0;
- if(kernel_data.film.cryptomatte_passes & CRYPT_OBJECT) {
- finalize_buffer(coverage_object, pass_offset);
- pass_offset += kernel_data.film.cryptomatte_depth * 4;
- }
- if(kernel_data.film.cryptomatte_passes & CRYPT_MATERIAL) {
- finalize_buffer(coverage_material, pass_offset);
- pass_offset += kernel_data.film.cryptomatte_depth * 4;
- }
- if(kernel_data.film.cryptomatte_passes & CRYPT_ASSET) {
- finalize_buffer(coverage_asset, pass_offset);
- }
+ int pass_offset = 0;
+ if (kernel_data.film.cryptomatte_passes & CRYPT_OBJECT) {
+ finalize_buffer(coverage_object, pass_offset);
+ pass_offset += kernel_data.film.cryptomatte_depth * 4;
+ }
+ if (kernel_data.film.cryptomatte_passes & CRYPT_MATERIAL) {
+ finalize_buffer(coverage_material, pass_offset);
+ pass_offset += kernel_data.film.cryptomatte_depth * 4;
+ }
+ if (kernel_data.film.cryptomatte_passes & CRYPT_ASSET) {
+ finalize_buffer(coverage_asset, pass_offset);
+ }
}
void Coverage::init_path_trace()
{
- kg->coverage_object = kg->coverage_material = kg->coverage_asset = NULL;
+ kg->coverage_object = kg->coverage_material = kg->coverage_asset = NULL;
- if(kernel_data.film.cryptomatte_passes & CRYPT_ACCURATE) {
- if(kernel_data.film.cryptomatte_passes & CRYPT_OBJECT) {
- coverage_object.clear();
- coverage_object.resize(tile.w * tile.h);
- }
- if(kernel_data.film.cryptomatte_passes & CRYPT_MATERIAL) {
- coverage_material.clear();
- coverage_material.resize(tile.w * tile.h);
- }
- if(kernel_data.film.cryptomatte_passes & CRYPT_ASSET) {
- coverage_asset.clear();
- coverage_asset.resize(tile.w * tile.h);
- }
- }
+ if (kernel_data.film.cryptomatte_passes & CRYPT_ACCURATE) {
+ if (kernel_data.film.cryptomatte_passes & CRYPT_OBJECT) {
+ coverage_object.clear();
+ coverage_object.resize(tile.w * tile.h);
+ }
+ if (kernel_data.film.cryptomatte_passes & CRYPT_MATERIAL) {
+ coverage_material.clear();
+ coverage_material.resize(tile.w * tile.h);
+ }
+ if (kernel_data.film.cryptomatte_passes & CRYPT_ASSET) {
+ coverage_asset.clear();
+ coverage_asset.resize(tile.w * tile.h);
+ }
+ }
}
void Coverage::init_pixel(int x, int y)
{
- if(kernel_data.film.cryptomatte_passes & CRYPT_ACCURATE) {
- const int pixel_index = tile.w * (y - tile.y) + x - tile.x;
- if(kernel_data.film.cryptomatte_passes & CRYPT_OBJECT) {
- kg->coverage_object = &coverage_object[pixel_index];
- }
- if(kernel_data.film.cryptomatte_passes & CRYPT_MATERIAL) {
- kg->coverage_material = &coverage_material[pixel_index];
- }
- if(kernel_data.film.cryptomatte_passes & CRYPT_ASSET) {
- kg->coverage_asset = &coverage_asset[pixel_index];
- }
- }
+ if (kernel_data.film.cryptomatte_passes & CRYPT_ACCURATE) {
+ const int pixel_index = tile.w * (y - tile.y) + x - tile.x;
+ if (kernel_data.film.cryptomatte_passes & CRYPT_OBJECT) {
+ kg->coverage_object = &coverage_object[pixel_index];
+ }
+ if (kernel_data.film.cryptomatte_passes & CRYPT_MATERIAL) {
+ kg->coverage_material = &coverage_material[pixel_index];
+ }
+ if (kernel_data.film.cryptomatte_passes & CRYPT_ASSET) {
+ kg->coverage_asset = &coverage_asset[pixel_index];
+ }
+ }
}
-void Coverage::finalize_buffer(vector<CoverageMap> & coverage, const int pass_offset)
+void Coverage::finalize_buffer(vector<CoverageMap> &coverage, const int pass_offset)
{
- if(kernel_data.film.cryptomatte_passes & CRYPT_ACCURATE) {
- flatten_buffer(coverage, pass_offset);
- }
- else {
- sort_buffer(pass_offset);
- }
+ if (kernel_data.film.cryptomatte_passes & CRYPT_ACCURATE) {
+ flatten_buffer(coverage, pass_offset);
+ }
+ else {
+ sort_buffer(pass_offset);
+ }
}
void Coverage::flatten_buffer(vector<CoverageMap> &coverage, const int pass_offset)
{
- /* Sort the coverage map and write it to the output */
- int pixel_index = 0;
- int pass_stride = tile.buffers->params.get_passes_size();
- for(int y = 0; y < tile.h; ++y) {
- for(int x = 0; x < tile.w; ++x) {
- const CoverageMap& pixel = coverage[pixel_index];
- if(!pixel.empty()) {
- /* buffer offset */
- int index = x + y * tile.stride;
- float *buffer = (float*)tile.buffer + index*pass_stride;
+ /* Sort the coverage map and write it to the output */
+ int pixel_index = 0;
+ int pass_stride = tile.buffers->params.get_passes_size();
+ for (int y = 0; y < tile.h; ++y) {
+ for (int x = 0; x < tile.w; ++x) {
+ const CoverageMap &pixel = coverage[pixel_index];
+ if (!pixel.empty()) {
+ /* buffer offset */
+ int index = x + y * tile.stride;
+ float *buffer = (float *)tile.buffer + index * pass_stride;
- /* sort the cryptomatte pixel */
- vector<pair<float, float> > sorted_pixel;
- for(CoverageMap::const_iterator it = pixel.begin(); it != pixel.end(); ++it) {
- sorted_pixel.push_back(std::make_pair(it->second, it->first));
- }
- sort(sorted_pixel.begin(), sorted_pixel.end(), crypomatte_comp);
- int num_slots = 2 * (kernel_data.film.cryptomatte_depth);
- if(sorted_pixel.size() > num_slots) {
- float leftover = 0.0f;
- for(vector<pair<float, float> >::iterator it = sorted_pixel.begin()+num_slots; it != sorted_pixel.end(); ++it) {
- leftover += it->first;
- }
- sorted_pixel[num_slots-1].first += leftover;
- }
- int limit = min(num_slots, sorted_pixel.size());
- for(int i = 0; i < limit; ++i) {
- kernel_write_id_slots(buffer + kernel_data.film.pass_cryptomatte + pass_offset, 2 * (kernel_data.film.cryptomatte_depth), sorted_pixel[i].second, sorted_pixel[i].first);
- }
- }
- ++pixel_index;
- }
- }
+ /* sort the cryptomatte pixel */
+ vector<pair<float, float>> sorted_pixel;
+ for (CoverageMap::const_iterator it = pixel.begin(); it != pixel.end(); ++it) {
+ sorted_pixel.push_back(std::make_pair(it->second, it->first));
+ }
+ sort(sorted_pixel.begin(), sorted_pixel.end(), crypomatte_comp);
+ int num_slots = 2 * (kernel_data.film.cryptomatte_depth);
+ if (sorted_pixel.size() > num_slots) {
+ float leftover = 0.0f;
+ for (vector<pair<float, float>>::iterator it = sorted_pixel.begin() + num_slots;
+ it != sorted_pixel.end();
+ ++it) {
+ leftover += it->first;
+ }
+ sorted_pixel[num_slots - 1].first += leftover;
+ }
+ int limit = min(num_slots, sorted_pixel.size());
+ for (int i = 0; i < limit; ++i) {
+ kernel_write_id_slots(buffer + kernel_data.film.pass_cryptomatte + pass_offset,
+ 2 * (kernel_data.film.cryptomatte_depth),
+ sorted_pixel[i].second,
+ sorted_pixel[i].first);
+ }
+ }
+ ++pixel_index;
+ }
+ }
}
void Coverage::sort_buffer(const int pass_offset)
{
- /* Sort the coverage map and write it to the output */
- int pass_stride = tile.buffers->params.get_passes_size();
- for(int y = 0; y < tile.h; ++y) {
- for(int x = 0; x < tile.w; ++x) {
- /* buffer offset */
- int index = x + y*tile.stride;
- float *buffer = (float*)tile.buffer + index*pass_stride;
- kernel_sort_id_slots(buffer + kernel_data.film.pass_cryptomatte + pass_offset, 2 * (kernel_data.film.cryptomatte_depth));
- }
- }
+ /* Sort the coverage map and write it to the output */
+ int pass_stride = tile.buffers->params.get_passes_size();
+ for (int y = 0; y < tile.h; ++y) {
+ for (int x = 0; x < tile.w; ++x) {
+ /* buffer offset */
+ int index = x + y * tile.stride;
+ float *buffer = (float *)tile.buffer + index * pass_stride;
+ kernel_sort_id_slots(buffer + kernel_data.film.pass_cryptomatte + pass_offset,
+ 2 * (kernel_data.film.cryptomatte_depth));
+ }
+ }
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/render/coverage.h b/intern/cycles/render/coverage.h
index 9ee0bce7517..3d1f6a2b040 100644
--- a/intern/cycles/render/coverage.h
+++ b/intern/cycles/render/coverage.h
@@ -22,28 +22,30 @@
#include "util/util_vector.h"
#ifndef __COVERAGE_H__
-#define __COVERAGE_H__
+# define __COVERAGE_H__
CCL_NAMESPACE_BEGIN
class Coverage {
-public:
- Coverage(KernelGlobals *kg_, RenderTile &tile_) : kg(kg_), tile(tile_) { }
- void init_path_trace();
- void init_pixel(int x, int y);
- void finalize();
-private:
- vector<CoverageMap>coverage_object;
- vector<CoverageMap>coverage_material;
- vector<CoverageMap>coverage_asset;
- KernelGlobals *kg;
- RenderTile &tile;
- void finalize_buffer(vector<CoverageMap>&coverage, const int pass_offset);
- void flatten_buffer(vector<CoverageMap>&coverage, const int pass_offset);
- void sort_buffer(const int pass_offset);
-};
+ public:
+ Coverage(KernelGlobals *kg_, RenderTile &tile_) : kg(kg_), tile(tile_)
+ {
+ }
+ void init_path_trace();
+ void init_pixel(int x, int y);
+ void finalize();
+ private:
+ vector<CoverageMap> coverage_object;
+ vector<CoverageMap> coverage_material;
+ vector<CoverageMap> coverage_asset;
+ KernelGlobals *kg;
+ RenderTile &tile;
+ void finalize_buffer(vector<CoverageMap> &coverage, const int pass_offset);
+ void flatten_buffer(vector<CoverageMap> &coverage, const int pass_offset);
+ void sort_buffer(const int pass_offset);
+};
CCL_NAMESPACE_END
-#endif /* __COVERAGE_H__ */
+#endif /* __COVERAGE_H__ */
diff --git a/intern/cycles/render/curves.cpp b/intern/cycles/render/curves.cpp
index 58b71d3e122..49ab70541c2 100644
--- a/intern/cycles/render/curves.cpp
+++ b/intern/cycles/render/curves.cpp
@@ -31,72 +31,73 @@ CCL_NAMESPACE_BEGIN
void curvebounds(float *lower, float *upper, float3 *p, int dim)
{
- float *p0 = &p[0].x;
- float *p1 = &p[1].x;
- float *p2 = &p[2].x;
- float *p3 = &p[3].x;
-
- float fc = 0.71f;
- float curve_coef[4];
- curve_coef[0] = p1[dim];
- curve_coef[1] = -fc*p0[dim] + fc*p2[dim];
- curve_coef[2] = 2.0f * fc * p0[dim] + (fc - 3.0f) * p1[dim] + (3.0f - 2.0f * fc) * p2[dim] - fc * p3[dim];
- curve_coef[3] = -fc * p0[dim] + (2.0f - fc) * p1[dim] + (fc - 2.0f) * p2[dim] + fc * p3[dim];
-
- float discroot = curve_coef[2] * curve_coef[2] - 3 * curve_coef[3] * curve_coef[1];
- float ta = -1.0f;
- float tb = -1.0f;
-
- if(discroot >= 0) {
- discroot = sqrtf(discroot);
- ta = (-curve_coef[2] - discroot) / (3 * curve_coef[3]);
- tb = (-curve_coef[2] + discroot) / (3 * curve_coef[3]);
- ta = (ta > 1.0f || ta < 0.0f) ? -1.0f : ta;
- tb = (tb > 1.0f || tb < 0.0f) ? -1.0f : tb;
- }
-
- *upper = max(p1[dim],p2[dim]);
- *lower = min(p1[dim],p2[dim]);
-
- float exa = p1[dim];
- float exb = p2[dim];
-
- if(ta >= 0.0f) {
- float t2 = ta * ta;
- float t3 = t2 * ta;
- exa = curve_coef[3] * t3 + curve_coef[2] * t2 + curve_coef[1] * ta + curve_coef[0];
- }
- if(tb >= 0.0f) {
- float t2 = tb * tb;
- float t3 = t2 * tb;
- exb = curve_coef[3] * t3 + curve_coef[2] * t2 + curve_coef[1] * tb + curve_coef[0];
- }
-
- *upper = max(*upper, max(exa,exb));
- *lower = min(*lower, min(exa,exb));
+ float *p0 = &p[0].x;
+ float *p1 = &p[1].x;
+ float *p2 = &p[2].x;
+ float *p3 = &p[3].x;
+
+ float fc = 0.71f;
+ float curve_coef[4];
+ curve_coef[0] = p1[dim];
+ curve_coef[1] = -fc * p0[dim] + fc * p2[dim];
+ curve_coef[2] = 2.0f * fc * p0[dim] + (fc - 3.0f) * p1[dim] + (3.0f - 2.0f * fc) * p2[dim] -
+ fc * p3[dim];
+ curve_coef[3] = -fc * p0[dim] + (2.0f - fc) * p1[dim] + (fc - 2.0f) * p2[dim] + fc * p3[dim];
+
+ float discroot = curve_coef[2] * curve_coef[2] - 3 * curve_coef[3] * curve_coef[1];
+ float ta = -1.0f;
+ float tb = -1.0f;
+
+ if (discroot >= 0) {
+ discroot = sqrtf(discroot);
+ ta = (-curve_coef[2] - discroot) / (3 * curve_coef[3]);
+ tb = (-curve_coef[2] + discroot) / (3 * curve_coef[3]);
+ ta = (ta > 1.0f || ta < 0.0f) ? -1.0f : ta;
+ tb = (tb > 1.0f || tb < 0.0f) ? -1.0f : tb;
+ }
+
+ *upper = max(p1[dim], p2[dim]);
+ *lower = min(p1[dim], p2[dim]);
+
+ float exa = p1[dim];
+ float exb = p2[dim];
+
+ if (ta >= 0.0f) {
+ float t2 = ta * ta;
+ float t3 = t2 * ta;
+ exa = curve_coef[3] * t3 + curve_coef[2] * t2 + curve_coef[1] * ta + curve_coef[0];
+ }
+ if (tb >= 0.0f) {
+ float t2 = tb * tb;
+ float t3 = t2 * tb;
+ exb = curve_coef[3] * t3 + curve_coef[2] * t2 + curve_coef[1] * tb + curve_coef[0];
+ }
+
+ *upper = max(*upper, max(exa, exb));
+ *lower = min(*lower, min(exa, exb));
}
/* Hair System Manager */
CurveSystemManager::CurveSystemManager()
{
- primitive = CURVE_LINE_SEGMENTS;
- curve_shape = CURVE_THICK;
- line_method = CURVE_CORRECTED;
- triangle_method = CURVE_CAMERA_TRIANGLES;
- resolution = 3;
- subdivisions = 3;
-
- minimum_width = 0.0f;
- maximum_width = 0.0f;
-
- use_curves = true;
- use_encasing = true;
- use_backfacing = false;
- use_tangent_normal_geometry = false;
-
- need_update = true;
- need_mesh_update = false;
+ primitive = CURVE_LINE_SEGMENTS;
+ curve_shape = CURVE_THICK;
+ line_method = CURVE_CORRECTED;
+ triangle_method = CURVE_CAMERA_TRIANGLES;
+ resolution = 3;
+ subdivisions = 3;
+
+ minimum_width = 0.0f;
+ maximum_width = 0.0f;
+
+ use_curves = true;
+ use_encasing = true;
+ use_backfacing = false;
+ use_tangent_normal_geometry = false;
+
+ need_update = true;
+ need_mesh_update = false;
}
CurveSystemManager::~CurveSystemManager()
@@ -106,85 +107,82 @@ CurveSystemManager::~CurveSystemManager()
void CurveSystemManager::device_update(Device *device,
DeviceScene *dscene,
Scene * /*scene*/,
- Progress& progress)
+ Progress &progress)
{
- if(!need_update)
- return;
+ if (!need_update)
+ return;
- device_free(device, dscene);
+ device_free(device, dscene);
- progress.set_status("Updating Hair settings", "Copying Hair settings to device");
+ progress.set_status("Updating Hair settings", "Copying Hair settings to device");
- KernelCurves *kcurve = &dscene->data.curve;
+ KernelCurves *kcurve = &dscene->data.curve;
- kcurve->curveflags = 0;
+ kcurve->curveflags = 0;
- if(use_curves) {
- if(primitive == CURVE_SEGMENTS || primitive == CURVE_RIBBONS)
- kcurve->curveflags |= CURVE_KN_INTERPOLATE;
- if(primitive == CURVE_RIBBONS)
- kcurve->curveflags |= CURVE_KN_RIBBONS;
+ if (use_curves) {
+ if (primitive == CURVE_SEGMENTS || primitive == CURVE_RIBBONS)
+ kcurve->curveflags |= CURVE_KN_INTERPOLATE;
+ if (primitive == CURVE_RIBBONS)
+ kcurve->curveflags |= CURVE_KN_RIBBONS;
- if(line_method == CURVE_ACCURATE)
- kcurve->curveflags |= CURVE_KN_ACCURATE;
- else if(line_method == CURVE_CORRECTED)
- kcurve->curveflags |= CURVE_KN_INTERSECTCORRECTION;
+ if (line_method == CURVE_ACCURATE)
+ kcurve->curveflags |= CURVE_KN_ACCURATE;
+ else if (line_method == CURVE_CORRECTED)
+ kcurve->curveflags |= CURVE_KN_INTERSECTCORRECTION;
- if(use_tangent_normal_geometry)
- kcurve->curveflags |= CURVE_KN_TRUETANGENTGNORMAL;
- if(use_backfacing)
- kcurve->curveflags |= CURVE_KN_BACKFACING;
- if(use_encasing)
- kcurve->curveflags |= CURVE_KN_ENCLOSEFILTER;
+ if (use_tangent_normal_geometry)
+ kcurve->curveflags |= CURVE_KN_TRUETANGENTGNORMAL;
+ if (use_backfacing)
+ kcurve->curveflags |= CURVE_KN_BACKFACING;
+ if (use_encasing)
+ kcurve->curveflags |= CURVE_KN_ENCLOSEFILTER;
- kcurve->minimum_width = minimum_width;
- kcurve->maximum_width = maximum_width;
- kcurve->subdivisions = subdivisions;
- }
+ kcurve->minimum_width = minimum_width;
+ kcurve->maximum_width = maximum_width;
+ kcurve->subdivisions = subdivisions;
+ }
- if(progress.get_cancel()) return;
+ if (progress.get_cancel())
+ return;
- need_update = false;
+ need_update = false;
}
-void CurveSystemManager::device_free(Device * /*device*/,
- DeviceScene * /*dscene*/)
+void CurveSystemManager::device_free(Device * /*device*/, DeviceScene * /*dscene*/)
{
-
}
-bool CurveSystemManager::modified(const CurveSystemManager& CurveSystemManager)
+bool CurveSystemManager::modified(const CurveSystemManager &CurveSystemManager)
{
- return !(curve_shape == CurveSystemManager.curve_shape &&
- line_method == CurveSystemManager.line_method &&
- primitive == CurveSystemManager.primitive &&
- use_encasing == CurveSystemManager.use_encasing &&
- use_tangent_normal_geometry == CurveSystemManager.use_tangent_normal_geometry &&
- minimum_width == CurveSystemManager.minimum_width &&
- maximum_width == CurveSystemManager.maximum_width &&
- use_backfacing == CurveSystemManager.use_backfacing &&
- triangle_method == CurveSystemManager.triangle_method &&
- resolution == CurveSystemManager.resolution &&
- use_curves == CurveSystemManager.use_curves &&
- subdivisions == CurveSystemManager.subdivisions);
+ return !(
+ curve_shape == CurveSystemManager.curve_shape &&
+ line_method == CurveSystemManager.line_method && primitive == CurveSystemManager.primitive &&
+ use_encasing == CurveSystemManager.use_encasing &&
+ use_tangent_normal_geometry == CurveSystemManager.use_tangent_normal_geometry &&
+ minimum_width == CurveSystemManager.minimum_width &&
+ maximum_width == CurveSystemManager.maximum_width &&
+ use_backfacing == CurveSystemManager.use_backfacing &&
+ triangle_method == CurveSystemManager.triangle_method &&
+ resolution == CurveSystemManager.resolution && use_curves == CurveSystemManager.use_curves &&
+ subdivisions == CurveSystemManager.subdivisions);
}
-bool CurveSystemManager::modified_mesh(const CurveSystemManager& CurveSystemManager)
+bool CurveSystemManager::modified_mesh(const CurveSystemManager &CurveSystemManager)
{
- return !(primitive == CurveSystemManager.primitive &&
- curve_shape == CurveSystemManager.curve_shape &&
- triangle_method == CurveSystemManager.triangle_method &&
- resolution == CurveSystemManager.resolution &&
- use_curves == CurveSystemManager.use_curves);
+ return !(
+ primitive == CurveSystemManager.primitive && curve_shape == CurveSystemManager.curve_shape &&
+ triangle_method == CurveSystemManager.triangle_method &&
+ resolution == CurveSystemManager.resolution && use_curves == CurveSystemManager.use_curves);
}
void CurveSystemManager::tag_update(Scene * /*scene*/)
{
- need_update = true;
+ need_update = true;
}
void CurveSystemManager::tag_update_mesh()
{
- need_mesh_update = true;
+ need_mesh_update = true;
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/render/curves.h b/intern/cycles/render/curves.h
index 9db411bc04b..81e7b4ac88d 100644
--- a/intern/cycles/render/curves.h
+++ b/intern/cycles/render/curves.h
@@ -30,93 +30,91 @@ class Scene;
void curvebounds(float *lower, float *upper, float3 *p, int dim);
typedef enum CurvePrimitiveType {
- CURVE_TRIANGLES = 0,
- CURVE_LINE_SEGMENTS = 1,
- CURVE_SEGMENTS = 2,
- CURVE_RIBBONS = 3,
+ CURVE_TRIANGLES = 0,
+ CURVE_LINE_SEGMENTS = 1,
+ CURVE_SEGMENTS = 2,
+ CURVE_RIBBONS = 3,
- CURVE_NUM_PRIMITIVE_TYPES,
+ CURVE_NUM_PRIMITIVE_TYPES,
} CurvePrimitiveType;
typedef enum CurveShapeType {
- CURVE_RIBBON = 0,
- CURVE_THICK = 1,
+ CURVE_RIBBON = 0,
+ CURVE_THICK = 1,
- CURVE_NUM_SHAPE_TYPES,
+ CURVE_NUM_SHAPE_TYPES,
} CurveShapeType;
typedef enum CurveTriangleMethod {
- CURVE_CAMERA_TRIANGLES,
- CURVE_TESSELATED_TRIANGLES
+ CURVE_CAMERA_TRIANGLES,
+ CURVE_TESSELATED_TRIANGLES
} CurveTriangleMethod;
typedef enum CurveLineMethod {
- CURVE_ACCURATE,
- CURVE_CORRECTED,
- CURVE_UNCORRECTED
+ CURVE_ACCURATE,
+ CURVE_CORRECTED,
+ CURVE_UNCORRECTED
} CurveLineMethod;
class ParticleCurveData {
-public:
+ public:
+ ParticleCurveData();
+ ~ParticleCurveData();
- ParticleCurveData();
- ~ParticleCurveData();
+ array<int> psys_firstcurve;
+ array<int> psys_curvenum;
+ array<int> psys_shader;
- array<int> psys_firstcurve;
- array<int> psys_curvenum;
- array<int> psys_shader;
+ array<float> psys_rootradius;
+ array<float> psys_tipradius;
+ array<float> psys_shape;
+ array<bool> psys_closetip;
- array<float> psys_rootradius;
- array<float> psys_tipradius;
- array<float> psys_shape;
- array<bool> psys_closetip;
+ array<int> curve_firstkey;
+ array<int> curve_keynum;
+ array<float> curve_length;
+ array<float2> curve_uv;
+ array<float3> curve_vcol;
- array<int> curve_firstkey;
- array<int> curve_keynum;
- array<float> curve_length;
- array<float2> curve_uv;
- array<float3> curve_vcol;
-
- array<float3> curvekey_co;
- array<float> curvekey_time;
+ array<float3> curvekey_co;
+ array<float> curvekey_time;
};
/* HairSystem Manager */
class CurveSystemManager {
-public:
-
- CurvePrimitiveType primitive;
- CurveShapeType curve_shape;
- CurveLineMethod line_method;
- CurveTriangleMethod triangle_method;
- int resolution;
- int subdivisions;
-
- float minimum_width;
- float maximum_width;
-
- bool use_curves;
- bool use_encasing;
- bool use_backfacing;
- bool use_tangent_normal_geometry;
-
- bool need_update;
- bool need_mesh_update;
-
- CurveSystemManager();
- ~CurveSystemManager();
-
- void device_update(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress);
- void device_free(Device *device, DeviceScene *dscene);
- bool modified(const CurveSystemManager& CurveSystemManager);
- bool modified_mesh(const CurveSystemManager& CurveSystemManager);
-
- void tag_update(Scene *scene);
- void tag_update_mesh();
+ public:
+ CurvePrimitiveType primitive;
+ CurveShapeType curve_shape;
+ CurveLineMethod line_method;
+ CurveTriangleMethod triangle_method;
+ int resolution;
+ int subdivisions;
+
+ float minimum_width;
+ float maximum_width;
+
+ bool use_curves;
+ bool use_encasing;
+ bool use_backfacing;
+ bool use_tangent_normal_geometry;
+
+ bool need_update;
+ bool need_mesh_update;
+
+ CurveSystemManager();
+ ~CurveSystemManager();
+
+ void device_update(Device *device, DeviceScene *dscene, Scene *scene, Progress &progress);
+ void device_free(Device *device, DeviceScene *dscene);
+ bool modified(const CurveSystemManager &CurveSystemManager);
+ bool modified_mesh(const CurveSystemManager &CurveSystemManager);
+
+ void tag_update(Scene *scene);
+ void tag_update_mesh();
};
CCL_NAMESPACE_END
-#endif /* __CURVES_H__ */
+#endif /* __CURVES_H__ */
diff --git a/intern/cycles/render/denoising.cpp b/intern/cycles/render/denoising.cpp
index ab74fd8fd38..c4f21d9c771 100644
--- a/intern/cycles/render/denoising.cpp
+++ b/intern/cycles/render/denoising.cpp
@@ -31,55 +31,55 @@ CCL_NAMESPACE_BEGIN
static void print_progress(int num, int total, int frame, int num_frames)
{
- const char *label = "Denoise Frame ";
- int cols = system_console_width();
-
- cols -= strlen(label);
-
- int len = 1;
- for(int x = total; x > 9; x /= 10) {
- len++;
- }
-
- int bars = cols - 2*len - 6;
-
- printf("\r%s", label);
-
- if(num_frames > 1) {
- int frame_len = 1;
- for(int x = num_frames - 1; x > 9; x /= 10) {
- frame_len++;
- }
- bars -= frame_len + 2;
- printf("%*d ", frame_len, frame);
- }
-
- int v = int(float(num)*bars/total);
- printf("[");
- for(int i = 0; i < v; i++) {
- printf("=");
- }
- if(v < bars) {
- printf(">");
- }
- for(int i = v+1; i < bars; i++) {
- printf(" ");
- }
- printf(string_printf("] %%%dd / %d", len, total).c_str(), num);
- fflush(stdout);
+ const char *label = "Denoise Frame ";
+ int cols = system_console_width();
+
+ cols -= strlen(label);
+
+ int len = 1;
+ for (int x = total; x > 9; x /= 10) {
+ len++;
+ }
+
+ int bars = cols - 2 * len - 6;
+
+ printf("\r%s", label);
+
+ if (num_frames > 1) {
+ int frame_len = 1;
+ for (int x = num_frames - 1; x > 9; x /= 10) {
+ frame_len++;
+ }
+ bars -= frame_len + 2;
+ printf("%*d ", frame_len, frame);
+ }
+
+ int v = int(float(num) * bars / total);
+ printf("[");
+ for (int i = 0; i < v; i++) {
+ printf("=");
+ }
+ if (v < bars) {
+ printf(">");
+ }
+ for (int i = v + 1; i < bars; i++) {
+ printf(" ");
+ }
+ printf(string_printf("] %%%dd / %d", len, total).c_str(), num);
+ fflush(stdout);
}
/* Splits in at its last dot, setting suffix to the part after the dot and in to the part before it.
* Returns whether a dot was found. */
static bool split_last_dot(string &in, string &suffix)
{
- size_t pos = in.rfind(".");
- if(pos == string::npos) {
- return false;
- }
- suffix = in.substr(pos+1);
- in = in.substr(0, pos);
- return true;
+ size_t pos = in.rfind(".");
+ if (pos == string::npos) {
+ return false;
+ }
+ suffix = in.substr(pos + 1);
+ in = in.substr(0, pos);
+ return true;
}
/* Separate channel names as generated by Blender.
@@ -87,39 +87,40 @@ static bool split_last_dot(string &in, string &suffix)
* Inputs are expected in the form RenderLayer.Pass.View.Channel, sets renderlayer to "RenderLayer.View"
* Otherwise:
* Inputs are expected in the form RenderLayer.Pass.Channel */
-static bool parse_channel_name(string name, string &renderlayer, string &pass, string &channel, bool multiview_channels)
+static bool parse_channel_name(
+ string name, string &renderlayer, string &pass, string &channel, bool multiview_channels)
{
- if(!split_last_dot(name, channel)) {
- return false;
- }
- string view;
- if(multiview_channels && !split_last_dot(name, view)) {
- return false;
- }
- if(!split_last_dot(name, pass)) {
- return false;
- }
- renderlayer = name;
+ if (!split_last_dot(name, channel)) {
+ return false;
+ }
+ string view;
+ if (multiview_channels && !split_last_dot(name, view)) {
+ return false;
+ }
+ if (!split_last_dot(name, pass)) {
+ return false;
+ }
+ renderlayer = name;
- if(multiview_channels) {
- renderlayer += "." + view;
- }
+ if (multiview_channels) {
+ renderlayer += "." + view;
+ }
- return true;
+ return true;
}
/* Channel Mapping */
struct ChannelMapping {
- int channel;
- string name;
+ int channel;
+ string name;
};
static void fill_mapping(vector<ChannelMapping> &map, int pos, string name, string channels)
{
- for(const char *chan = channels.c_str(); *chan; chan++) {
- map.push_back({pos++, name + "." + *chan});
- }
+ for (const char *chan = channels.c_str(); *chan; chan++) {
+ map.push_back({pos++, name + "." + *chan});
+ }
}
static const int INPUT_NUM_CHANNELS = 15;
@@ -132,131 +133,135 @@ static const int INPUT_DENOISING_VARIANCE = 11;
static const int INPUT_DENOISING_INTENSITY = 14;
static vector<ChannelMapping> input_channels()
{
- vector<ChannelMapping> map;
- fill_mapping(map, INPUT_DENOISING_DEPTH, "Denoising Depth", "Z");
- fill_mapping(map, INPUT_DENOISING_NORMAL, "Denoising Normal", "XYZ");
- fill_mapping(map, INPUT_DENOISING_SHADOWING, "Denoising Shadowing", "X");
- fill_mapping(map, INPUT_DENOISING_ALBEDO, "Denoising Albedo", "RGB");
- fill_mapping(map, INPUT_NOISY_IMAGE, "Noisy Image", "RGB");
- fill_mapping(map, INPUT_DENOISING_VARIANCE, "Denoising Variance", "RGB");
- fill_mapping(map, INPUT_DENOISING_INTENSITY, "Denoising Intensity", "X");
- return map;
+ vector<ChannelMapping> map;
+ fill_mapping(map, INPUT_DENOISING_DEPTH, "Denoising Depth", "Z");
+ fill_mapping(map, INPUT_DENOISING_NORMAL, "Denoising Normal", "XYZ");
+ fill_mapping(map, INPUT_DENOISING_SHADOWING, "Denoising Shadowing", "X");
+ fill_mapping(map, INPUT_DENOISING_ALBEDO, "Denoising Albedo", "RGB");
+ fill_mapping(map, INPUT_NOISY_IMAGE, "Noisy Image", "RGB");
+ fill_mapping(map, INPUT_DENOISING_VARIANCE, "Denoising Variance", "RGB");
+ fill_mapping(map, INPUT_DENOISING_INTENSITY, "Denoising Intensity", "X");
+ return map;
}
static const int OUTPUT_NUM_CHANNELS = 3;
static vector<ChannelMapping> output_channels()
{
- vector<ChannelMapping> map;
- fill_mapping(map, 0, "Combined", "RGB");
- return map;
+ vector<ChannelMapping> map;
+ fill_mapping(map, 0, "Combined", "RGB");
+ return map;
}
/* Renderlayer Handling */
bool DenoiseImageLayer::detect_denoising_channels()
{
- /* Map device input to image channels. */
- input_to_image_channel.clear();
- input_to_image_channel.resize(INPUT_NUM_CHANNELS, -1);
+ /* Map device input to image channels. */
+ input_to_image_channel.clear();
+ input_to_image_channel.resize(INPUT_NUM_CHANNELS, -1);
- foreach(const ChannelMapping& mapping, input_channels()) {
- vector<string>::iterator i = find(channels.begin(), channels.end(), mapping.name);
- if(i == channels.end()) {
- return false;
- }
+ foreach (const ChannelMapping &mapping, input_channels()) {
+ vector<string>::iterator i = find(channels.begin(), channels.end(), mapping.name);
+ if (i == channels.end()) {
+ return false;
+ }
- size_t input_channel = mapping.channel;
- size_t layer_channel = i - channels.begin();
- input_to_image_channel[input_channel] = layer_to_image_channel[layer_channel];
- }
+ size_t input_channel = mapping.channel;
+ size_t layer_channel = i - channels.begin();
+ input_to_image_channel[input_channel] = layer_to_image_channel[layer_channel];
+ }
- /* Map device output to image channels. */
- output_to_image_channel.clear();
- output_to_image_channel.resize(OUTPUT_NUM_CHANNELS, -1);
+ /* Map device output to image channels. */
+ output_to_image_channel.clear();
+ output_to_image_channel.resize(OUTPUT_NUM_CHANNELS, -1);
- foreach(const ChannelMapping& mapping, output_channels()) {
- vector<string>::iterator i = find(channels.begin(), channels.end(), mapping.name);
- if(i == channels.end()) {
- return false;
- }
+ foreach (const ChannelMapping &mapping, output_channels()) {
+ vector<string>::iterator i = find(channels.begin(), channels.end(), mapping.name);
+ if (i == channels.end()) {
+ return false;
+ }
- size_t output_channel = mapping.channel;
- size_t layer_channel = i - channels.begin();
- output_to_image_channel[output_channel] = layer_to_image_channel[layer_channel];
- }
+ size_t output_channel = mapping.channel;
+ size_t layer_channel = i - channels.begin();
+ output_to_image_channel[output_channel] = layer_to_image_channel[layer_channel];
+ }
- /* Check that all buffer channels are correctly set. */
- for(int i = 0; i < INPUT_NUM_CHANNELS; i++) {
- assert(input_to_image_channel[i] >= 0);
- }
- for(int i = 0; i < OUTPUT_NUM_CHANNELS; i++) {
- assert(output_to_image_channel[i] >= 0);
- }
+ /* Check that all buffer channels are correctly set. */
+ for (int i = 0; i < INPUT_NUM_CHANNELS; i++) {
+ assert(input_to_image_channel[i] >= 0);
+ }
+ for (int i = 0; i < OUTPUT_NUM_CHANNELS; i++) {
+ assert(output_to_image_channel[i] >= 0);
+ }
- return true;
+ return true;
}
bool DenoiseImageLayer::match_channels(int neighbor,
const std::vector<string> &channelnames,
const std::vector<string> &neighbor_channelnames)
{
- neighbor_input_to_image_channel.resize(neighbor + 1);
- vector<int>& mapping = neighbor_input_to_image_channel[neighbor];
+ neighbor_input_to_image_channel.resize(neighbor + 1);
+ vector<int> &mapping = neighbor_input_to_image_channel[neighbor];
- assert(mapping.size() == 0);
- mapping.resize(input_to_image_channel.size(), -1);
+ assert(mapping.size() == 0);
+ mapping.resize(input_to_image_channel.size(), -1);
- for(int i = 0; i < input_to_image_channel.size(); i++) {
- const string& channel = channelnames[input_to_image_channel[i]];
- std::vector<string>::const_iterator frame_channel = find(neighbor_channelnames.begin(), neighbor_channelnames.end(), channel);
+ for (int i = 0; i < input_to_image_channel.size(); i++) {
+ const string &channel = channelnames[input_to_image_channel[i]];
+ std::vector<string>::const_iterator frame_channel = find(
+ neighbor_channelnames.begin(), neighbor_channelnames.end(), channel);
- if(frame_channel == neighbor_channelnames.end()) {
- return false;
- }
+ if (frame_channel == neighbor_channelnames.end()) {
+ return false;
+ }
- mapping[i] = frame_channel - neighbor_channelnames.begin();
- }
+ mapping[i] = frame_channel - neighbor_channelnames.begin();
+ }
- return true;
+ return true;
}
/* Denoise Task */
-DenoiseTask::DenoiseTask(Device *device, Denoiser *denoiser, int frame, const vector<int>& neighbor_frames)
-: denoiser(denoiser),
- device(device),
- frame(frame),
- neighbor_frames(neighbor_frames),
- current_layer(0),
- input_pixels(device, "filter input buffer", MEM_READ_ONLY),
- num_tiles(0)
+DenoiseTask::DenoiseTask(Device *device,
+ Denoiser *denoiser,
+ int frame,
+ const vector<int> &neighbor_frames)
+ : denoiser(denoiser),
+ device(device),
+ frame(frame),
+ neighbor_frames(neighbor_frames),
+ current_layer(0),
+ input_pixels(device, "filter input buffer", MEM_READ_ONLY),
+ num_tiles(0)
{
- image.samples = denoiser->samples_override;
+ image.samples = denoiser->samples_override;
}
DenoiseTask::~DenoiseTask()
{
- free();
+ free();
}
/* Device callbacks */
bool DenoiseTask::acquire_tile(Device *device, Device *tile_device, RenderTile &tile)
{
- thread_scoped_lock tile_lock(tiles_mutex);
+ thread_scoped_lock tile_lock(tiles_mutex);
- if(tiles.empty()) {
- return false;
- }
+ if (tiles.empty()) {
+ return false;
+ }
- tile = tiles.front();
- tiles.pop_front();
+ tile = tiles.front();
+ tiles.pop_front();
- device->map_tile(tile_device, tile);
+ device->map_tile(tile_device, tile);
- print_progress(num_tiles - tiles.size(), num_tiles, frame, denoiser->num_frames);
+ print_progress(num_tiles - tiles.size(), num_tiles, frame, denoiser->num_frames);
- return true;
+ return true;
}
/* Mapping tiles is required for regular rendering since each tile has its separate memory
@@ -268,87 +273,89 @@ bool DenoiseTask::acquire_tile(Device *device, Device *tile_device, RenderTile &
* a different buffer to avoid having to copy an entire horizontal slice of the image. */
void DenoiseTask::map_neighboring_tiles(RenderTile *tiles, Device *tile_device)
{
- /* Fill tile information. */
- for(int i = 0; i < 9; i++) {
- if(i == 4) {
- continue;
- }
-
- int dx = (i%3)-1;
- int dy = (i/3)-1;
- tiles[i].x = clamp(tiles[4].x + dx *denoiser->tile_size.x, 0, image.width);
- tiles[i].w = clamp(tiles[4].x + (dx+1)*denoiser->tile_size.x, 0, image.width) - tiles[i].x;
- tiles[i].y = clamp(tiles[4].y + dy *denoiser->tile_size.y, 0, image.height);
- tiles[i].h = clamp(tiles[4].y + (dy+1)*denoiser->tile_size.y, 0, image.height) - tiles[i].y;
-
- tiles[i].buffer = tiles[4].buffer;
- tiles[i].offset = tiles[4].offset;
- tiles[i].stride = image.width;
- }
-
- /* Allocate output buffer. */
- device_vector<float> *output_mem = new device_vector<float>(tile_device, "denoising_output", MEM_READ_WRITE);
- output_mem->alloc(OUTPUT_NUM_CHANNELS*tiles[4].w*tiles[4].h);
-
- /* Fill output buffer with noisy image, assumed by kernel_filter_finalize
- * when skipping denoising of some pixels. */
- float *result = output_mem->data();
- float *in = &image.pixels[image.num_channels*(tiles[4].y*image.width + tiles[4].x)];
-
- const DenoiseImageLayer& layer = image.layers[current_layer];
- const int *input_to_image_channel = layer.input_to_image_channel.data();
-
- for(int y = 0; y < tiles[4].h; y++) {
- for(int x = 0; x < tiles[4].w; x++, result += OUTPUT_NUM_CHANNELS) {
- for(int i = 0; i < OUTPUT_NUM_CHANNELS; i++) {
- result[i] = in[image.num_channels*x + input_to_image_channel[INPUT_NOISY_IMAGE + i]];
- }
- }
- in += image.num_channels * image.width;
- }
-
- output_mem->copy_to_device();
-
- /* Fill output tile info. */
- tiles[9] = tiles[4];
- tiles[9].buffer = output_mem->device_pointer;
- tiles[9].stride = tiles[9].w;
- tiles[9].offset -= tiles[9].x + tiles[9].y*tiles[9].stride;
-
- thread_scoped_lock output_lock(output_mutex);
- assert(output_pixels.count(tiles[4].tile_index) == 0);
- output_pixels[tiles[9].tile_index] = output_mem;
+ /* Fill tile information. */
+ for (int i = 0; i < 9; i++) {
+ if (i == 4) {
+ continue;
+ }
+
+ int dx = (i % 3) - 1;
+ int dy = (i / 3) - 1;
+ tiles[i].x = clamp(tiles[4].x + dx * denoiser->tile_size.x, 0, image.width);
+ tiles[i].w = clamp(tiles[4].x + (dx + 1) * denoiser->tile_size.x, 0, image.width) - tiles[i].x;
+ tiles[i].y = clamp(tiles[4].y + dy * denoiser->tile_size.y, 0, image.height);
+ tiles[i].h = clamp(tiles[4].y + (dy + 1) * denoiser->tile_size.y, 0, image.height) -
+ tiles[i].y;
+
+ tiles[i].buffer = tiles[4].buffer;
+ tiles[i].offset = tiles[4].offset;
+ tiles[i].stride = image.width;
+ }
+
+ /* Allocate output buffer. */
+ device_vector<float> *output_mem = new device_vector<float>(
+ tile_device, "denoising_output", MEM_READ_WRITE);
+ output_mem->alloc(OUTPUT_NUM_CHANNELS * tiles[4].w * tiles[4].h);
+
+ /* Fill output buffer with noisy image, assumed by kernel_filter_finalize
+ * when skipping denoising of some pixels. */
+ float *result = output_mem->data();
+ float *in = &image.pixels[image.num_channels * (tiles[4].y * image.width + tiles[4].x)];
+
+ const DenoiseImageLayer &layer = image.layers[current_layer];
+ const int *input_to_image_channel = layer.input_to_image_channel.data();
+
+ for (int y = 0; y < tiles[4].h; y++) {
+ for (int x = 0; x < tiles[4].w; x++, result += OUTPUT_NUM_CHANNELS) {
+ for (int i = 0; i < OUTPUT_NUM_CHANNELS; i++) {
+ result[i] = in[image.num_channels * x + input_to_image_channel[INPUT_NOISY_IMAGE + i]];
+ }
+ }
+ in += image.num_channels * image.width;
+ }
+
+ output_mem->copy_to_device();
+
+ /* Fill output tile info. */
+ tiles[9] = tiles[4];
+ tiles[9].buffer = output_mem->device_pointer;
+ tiles[9].stride = tiles[9].w;
+ tiles[9].offset -= tiles[9].x + tiles[9].y * tiles[9].stride;
+
+ thread_scoped_lock output_lock(output_mutex);
+ assert(output_pixels.count(tiles[4].tile_index) == 0);
+ output_pixels[tiles[9].tile_index] = output_mem;
}
void DenoiseTask::unmap_neighboring_tiles(RenderTile *tiles)
{
- thread_scoped_lock output_lock(output_mutex);
- assert(output_pixels.count(tiles[4].tile_index) == 1);
- device_vector<float> *output_mem = output_pixels[tiles[9].tile_index];
- output_pixels.erase(tiles[4].tile_index);
- output_lock.unlock();
+ thread_scoped_lock output_lock(output_mutex);
+ assert(output_pixels.count(tiles[4].tile_index) == 1);
+ device_vector<float> *output_mem = output_pixels[tiles[9].tile_index];
+ output_pixels.erase(tiles[4].tile_index);
+ output_lock.unlock();
- /* Copy denoised pixels from device. */
- output_mem->copy_from_device(0, OUTPUT_NUM_CHANNELS*tiles[9].w, tiles[9].h);
+ /* Copy denoised pixels from device. */
+ output_mem->copy_from_device(0, OUTPUT_NUM_CHANNELS * tiles[9].w, tiles[9].h);
- float *result = output_mem->data();
- float *out = &image.pixels[image.num_channels*(tiles[9].y*image.width + tiles[9].x)];
+ float *result = output_mem->data();
+ float *out = &image.pixels[image.num_channels * (tiles[9].y * image.width + tiles[9].x)];
- const DenoiseImageLayer& layer = image.layers[current_layer];
- const int *output_to_image_channel = layer.output_to_image_channel.data();
+ const DenoiseImageLayer &layer = image.layers[current_layer];
+ const int *output_to_image_channel = layer.output_to_image_channel.data();
- for(int y = 0; y < tiles[9].h; y++) {
- for(int x = 0; x < tiles[9].w; x++, result += OUTPUT_NUM_CHANNELS) {
- for(int i = 0; i < OUTPUT_NUM_CHANNELS; i++) {
- out[image.num_channels*x + output_to_image_channel[i]] = result[i];
- }
- }
- out += image.num_channels * image.width;
- }
+ for (int y = 0; y < tiles[9].h; y++) {
+ for (int x = 0; x < tiles[9].w; x++, result += OUTPUT_NUM_CHANNELS) {
+ for (int i = 0; i < OUTPUT_NUM_CHANNELS; i++) {
+ out[image.num_channels * x + output_to_image_channel[i]] = result[i];
+ }
+ }
+ out += image.num_channels * image.width;
+ }
- /* Free device buffer. */
- output_mem->free();
- delete output_mem;
+ /* Free device buffer. */
+ output_mem->free();
+ delete output_mem;
}
void DenoiseTask::release_tile()
@@ -357,542 +364,547 @@ void DenoiseTask::release_tile()
bool DenoiseTask::get_cancel()
{
- return false;
-}
-
-void DenoiseTask::create_task(DeviceTask& task)
-{
- /* Callback functions. */
- task.acquire_tile = function_bind(&DenoiseTask::acquire_tile, this, device, _1, _2);
- task.map_neighbor_tiles = function_bind(&DenoiseTask::map_neighboring_tiles, this, _1, _2);
- task.unmap_neighbor_tiles = function_bind(&DenoiseTask::unmap_neighboring_tiles, this, _1);
- task.release_tile = function_bind(&DenoiseTask::release_tile, this);
- task.get_cancel = function_bind(&DenoiseTask::get_cancel, this);
-
- /* Denoising parameters. */
- task.denoising = denoiser->params;
- task.denoising_do_filter = true;
- task.denoising_write_passes = false;
- task.denoising_from_render = false;
-
- task.denoising_frames.resize(neighbor_frames.size());
- for(int i = 0; i < neighbor_frames.size(); i++) {
- task.denoising_frames[i] = neighbor_frames[i] - frame;
- }
-
- /* Buffer parameters. */
- task.pass_stride = INPUT_NUM_CHANNELS;
- task.target_pass_stride = OUTPUT_NUM_CHANNELS;
- task.pass_denoising_data = 0;
- task.pass_denoising_clean = -1;
- task.frame_stride = image.width * image.height * INPUT_NUM_CHANNELS;
-
- /* Create tiles. */
- thread_scoped_lock tile_lock(tiles_mutex);
- thread_scoped_lock output_lock(output_mutex);
-
- tiles.clear();
- assert(output_pixels.empty());
- output_pixels.clear();
-
- int tiles_x = divide_up(image.width, denoiser->tile_size.x);
- int tiles_y = divide_up(image.height, denoiser->tile_size.y);
-
- for(int ty = 0; ty < tiles_y; ty++) {
- for(int tx = 0; tx < tiles_x; tx++) {
- RenderTile tile;
- tile.x = tx * denoiser->tile_size.x;
- tile.y = ty * denoiser->tile_size.y;
- tile.w = min(image.width - tile.x, denoiser->tile_size.x);
- tile.h = min(image.height - tile.y, denoiser->tile_size.y);
- tile.start_sample = 0;
- tile.num_samples = image.layers[current_layer].samples;
- tile.sample = 0;
- tile.offset = 0;
- tile.stride = image.width;
- tile.tile_index = ty*tiles_x + tx;
- tile.task = RenderTile::DENOISE;
- tile.buffers = NULL;
- tile.buffer = input_pixels.device_pointer;
- tiles.push_back(tile);
- }
- }
-
- num_tiles = tiles.size();
+ return false;
+}
+
+void DenoiseTask::create_task(DeviceTask &task)
+{
+ /* Callback functions. */
+ task.acquire_tile = function_bind(&DenoiseTask::acquire_tile, this, device, _1, _2);
+ task.map_neighbor_tiles = function_bind(&DenoiseTask::map_neighboring_tiles, this, _1, _2);
+ task.unmap_neighbor_tiles = function_bind(&DenoiseTask::unmap_neighboring_tiles, this, _1);
+ task.release_tile = function_bind(&DenoiseTask::release_tile, this);
+ task.get_cancel = function_bind(&DenoiseTask::get_cancel, this);
+
+ /* Denoising parameters. */
+ task.denoising = denoiser->params;
+ task.denoising_do_filter = true;
+ task.denoising_write_passes = false;
+ task.denoising_from_render = false;
+
+ task.denoising_frames.resize(neighbor_frames.size());
+ for (int i = 0; i < neighbor_frames.size(); i++) {
+ task.denoising_frames[i] = neighbor_frames[i] - frame;
+ }
+
+ /* Buffer parameters. */
+ task.pass_stride = INPUT_NUM_CHANNELS;
+ task.target_pass_stride = OUTPUT_NUM_CHANNELS;
+ task.pass_denoising_data = 0;
+ task.pass_denoising_clean = -1;
+ task.frame_stride = image.width * image.height * INPUT_NUM_CHANNELS;
+
+ /* Create tiles. */
+ thread_scoped_lock tile_lock(tiles_mutex);
+ thread_scoped_lock output_lock(output_mutex);
+
+ tiles.clear();
+ assert(output_pixels.empty());
+ output_pixels.clear();
+
+ int tiles_x = divide_up(image.width, denoiser->tile_size.x);
+ int tiles_y = divide_up(image.height, denoiser->tile_size.y);
+
+ for (int ty = 0; ty < tiles_y; ty++) {
+ for (int tx = 0; tx < tiles_x; tx++) {
+ RenderTile tile;
+ tile.x = tx * denoiser->tile_size.x;
+ tile.y = ty * denoiser->tile_size.y;
+ tile.w = min(image.width - tile.x, denoiser->tile_size.x);
+ tile.h = min(image.height - tile.y, denoiser->tile_size.y);
+ tile.start_sample = 0;
+ tile.num_samples = image.layers[current_layer].samples;
+ tile.sample = 0;
+ tile.offset = 0;
+ tile.stride = image.width;
+ tile.tile_index = ty * tiles_x + tx;
+ tile.task = RenderTile::DENOISE;
+ tile.buffers = NULL;
+ tile.buffer = input_pixels.device_pointer;
+ tiles.push_back(tile);
+ }
+ }
+
+ num_tiles = tiles.size();
}
/* Denoiser Operations */
bool DenoiseTask::load_input_pixels(int layer)
{
- int w = image.width;
- int h = image.height;
- int num_pixels = image.width * image.height;
- int frame_stride = num_pixels * INPUT_NUM_CHANNELS;
-
- /* Load center image */
- DenoiseImageLayer& image_layer = image.layers[layer];
-
- float *buffer_data = input_pixels.data();
- image.read_pixels(image_layer, buffer_data);
- buffer_data += frame_stride;
-
- /* Load neighbor images */
- for(int i = 0; i < image.in_neighbors.size(); i++) {
- if(!image.read_neighbor_pixels(i, image_layer, buffer_data)) {
- error = "Failed to read neighbor frame pixels";
- return false;
- }
- buffer_data += frame_stride;
- }
-
- /* Preprocess */
- buffer_data = input_pixels.data();
- for(int neighbor = 0; neighbor < image.in_neighbors.size() + 1; neighbor++) {
- /* Clamp */
- if(denoiser->params.clamp_input) {
- for(int i = 0; i < num_pixels*INPUT_NUM_CHANNELS; i++) {
- buffer_data[i] = clamp(buffer_data[i], -1e8f, 1e8f);
- }
- }
-
- /* Box blur */
- int r = 5 * denoiser->params.radius;
- float *data = buffer_data + 14;
- array<float> temp(num_pixels);
-
- for(int y = 0; y < h; y++) {
- for(int x = 0; x < w; x++) {
- int n = 0;
- float sum = 0.0f;
- for(int dx = max(x - r, 0); dx < min(x + r + 1, w); dx++, n++) {
- sum += data[INPUT_NUM_CHANNELS * (y * w + dx)];
- }
- temp[y * w + x] = sum/n;
- }
- }
-
- for(int y = 0; y < h; y++) {
- for(int x = 0; x < w; x++) {
- int n = 0;
- float sum = 0.0f;
-
- for(int dy = max(y - r, 0); dy < min(y + r + 1, h); dy++, n++) {
- sum += temp[dy * w + x];
- }
-
- data[INPUT_NUM_CHANNELS * (y * w + x)] = sum/n;
- }
- }
-
- buffer_data += frame_stride;
- }
-
- /* Copy to device */
- input_pixels.copy_to_device();
-
- return true;
+ int w = image.width;
+ int h = image.height;
+ int num_pixels = image.width * image.height;
+ int frame_stride = num_pixels * INPUT_NUM_CHANNELS;
+
+ /* Load center image */
+ DenoiseImageLayer &image_layer = image.layers[layer];
+
+ float *buffer_data = input_pixels.data();
+ image.read_pixels(image_layer, buffer_data);
+ buffer_data += frame_stride;
+
+ /* Load neighbor images */
+ for (int i = 0; i < image.in_neighbors.size(); i++) {
+ if (!image.read_neighbor_pixels(i, image_layer, buffer_data)) {
+ error = "Failed to read neighbor frame pixels";
+ return false;
+ }
+ buffer_data += frame_stride;
+ }
+
+ /* Preprocess */
+ buffer_data = input_pixels.data();
+ for (int neighbor = 0; neighbor < image.in_neighbors.size() + 1; neighbor++) {
+ /* Clamp */
+ if (denoiser->params.clamp_input) {
+ for (int i = 0; i < num_pixels * INPUT_NUM_CHANNELS; i++) {
+ buffer_data[i] = clamp(buffer_data[i], -1e8f, 1e8f);
+ }
+ }
+
+ /* Box blur */
+ int r = 5 * denoiser->params.radius;
+ float *data = buffer_data + 14;
+ array<float> temp(num_pixels);
+
+ for (int y = 0; y < h; y++) {
+ for (int x = 0; x < w; x++) {
+ int n = 0;
+ float sum = 0.0f;
+ for (int dx = max(x - r, 0); dx < min(x + r + 1, w); dx++, n++) {
+ sum += data[INPUT_NUM_CHANNELS * (y * w + dx)];
+ }
+ temp[y * w + x] = sum / n;
+ }
+ }
+
+ for (int y = 0; y < h; y++) {
+ for (int x = 0; x < w; x++) {
+ int n = 0;
+ float sum = 0.0f;
+
+ for (int dy = max(y - r, 0); dy < min(y + r + 1, h); dy++, n++) {
+ sum += temp[dy * w + x];
+ }
+
+ data[INPUT_NUM_CHANNELS * (y * w + x)] = sum / n;
+ }
+ }
+
+ buffer_data += frame_stride;
+ }
+
+ /* Copy to device */
+ input_pixels.copy_to_device();
+
+ return true;
}
/* Task stages */
bool DenoiseTask::load()
{
- string center_filepath = denoiser->input[frame];
- if(!image.load(center_filepath, error)) {
- return false;
- }
+ string center_filepath = denoiser->input[frame];
+ if (!image.load(center_filepath, error)) {
+ return false;
+ }
- if(!image.load_neighbors(denoiser->input, neighbor_frames, error)) {
- return false;
- }
+ if (!image.load_neighbors(denoiser->input, neighbor_frames, error)) {
+ return false;
+ }
- if(image.layers.empty()) {
- error = "No image layers found to denoise in " + center_filepath;
- return false;
- }
+ if (image.layers.empty()) {
+ error = "No image layers found to denoise in " + center_filepath;
+ return false;
+ }
- /* Allocate device buffer. */
- int num_frames = image.in_neighbors.size() + 1;
- input_pixels.alloc(image.width * INPUT_NUM_CHANNELS, image.height * num_frames);
- input_pixels.zero_to_device();
+ /* Allocate device buffer. */
+ int num_frames = image.in_neighbors.size() + 1;
+ input_pixels.alloc(image.width * INPUT_NUM_CHANNELS, image.height * num_frames);
+ input_pixels.zero_to_device();
- /* Read pixels for first layer. */
- current_layer = 0;
- if(!load_input_pixels(current_layer)) {
- return false;
- }
+ /* Read pixels for first layer. */
+ current_layer = 0;
+ if (!load_input_pixels(current_layer)) {
+ return false;
+ }
- return true;
+ return true;
}
bool DenoiseTask::exec()
{
- for(current_layer = 0; current_layer < image.layers.size(); current_layer++) {
- /* Read pixels for secondary layers, first was already loaded. */
- if(current_layer > 0) {
- if(!load_input_pixels(current_layer)) {
- return false;
- }
- }
+ for (current_layer = 0; current_layer < image.layers.size(); current_layer++) {
+ /* Read pixels for secondary layers, first was already loaded. */
+ if (current_layer > 0) {
+ if (!load_input_pixels(current_layer)) {
+ return false;
+ }
+ }
- /* Run task on device. */
- DeviceTask task(DeviceTask::RENDER);
- create_task(task);
- device->task_add(task);
- device->task_wait();
+ /* Run task on device. */
+ DeviceTask task(DeviceTask::RENDER);
+ create_task(task);
+ device->task_add(task);
+ device->task_wait();
- printf("\n");
- }
+ printf("\n");
+ }
- return true;
+ return true;
}
bool DenoiseTask::save()
{
- bool ok = image.save_output(denoiser->output[frame], error);
- free();
- return ok;
+ bool ok = image.save_output(denoiser->output[frame], error);
+ free();
+ return ok;
}
void DenoiseTask::free()
{
- image.free();
- input_pixels.free();
- assert(output_pixels.empty());
+ image.free();
+ input_pixels.free();
+ assert(output_pixels.empty());
}
/* Denoise Image Storage */
DenoiseImage::DenoiseImage()
{
- width = 0;
- height = 0;
- num_channels = 0;
- samples = 0;
+ width = 0;
+ height = 0;
+ num_channels = 0;
+ samples = 0;
}
DenoiseImage::~DenoiseImage()
{
- free();
+ free();
}
void DenoiseImage::close_input()
{
- in_neighbors.clear();
+ in_neighbors.clear();
}
void DenoiseImage::free()
{
- close_input();
- pixels.clear();
-}
-
-bool DenoiseImage::parse_channels(const ImageSpec &in_spec, string& error)
+ close_input();
+ pixels.clear();
+}
+
+bool DenoiseImage::parse_channels(const ImageSpec &in_spec, string &error)
{
- const std::vector<string> &channels = in_spec.channelnames;
- const ParamValue *multiview = in_spec.find_attribute("multiView");
- const bool multiview_channels = (multiview &&
- multiview->type().basetype == TypeDesc::STRING &&
- multiview->type().arraylen >= 2);
-
- layers.clear();
-
- /* Loop over all the channels in the file, parse their name and sort them
- * by RenderLayer.
- * Channels that can't be parsed are directly passed through to the output. */
- map<string, DenoiseImageLayer> file_layers;
- for(int i = 0; i < channels.size(); i++) {
- string layer, pass, channel;
- if(parse_channel_name(channels[i], layer, pass, channel, multiview_channels)) {
- file_layers[layer].channels.push_back(pass + "." + channel);
- file_layers[layer].layer_to_image_channel.push_back(i);
- }
- }
-
- /* Loop over all detected RenderLayers, check whether they contain a full set of input channels.
- * Any channels that won't be processed internally are also passed through. */
- for(map<string, DenoiseImageLayer>::iterator i = file_layers.begin(); i != file_layers.end(); ++i) {
- const string& name = i->first;
- DenoiseImageLayer& layer = i->second;
-
- /* Check for full pass set. */
- if(!layer.detect_denoising_channels()) {
- continue;
- }
-
- layer.name = name;
- layer.samples = samples;
-
- /* If the sample value isn't set yet, check if there is a layer-specific one in the input file. */
- if(layer.samples < 1) {
- string sample_string = in_spec.get_string_attribute("cycles." + name + ".samples", "");
- if(sample_string != "") {
- if(!sscanf(sample_string.c_str(), "%d", &layer.samples)) {
- error = "Failed to parse samples metadata: " + sample_string;
- return false;
- }
- }
- }
-
- if(layer.samples < 1) {
- error = string_printf("No sample number specified in the file for layer %s or on the command line", name.c_str());
- return false;
- }
-
- layers.push_back(layer);
- }
-
- return true;
-}
-
-void DenoiseImage::read_pixels(const DenoiseImageLayer& layer, float *input_pixels)
-{
- /* Pixels from center file have already been loaded into pixels.
- * We copy a subset into the device input buffer with channels reshuffled. */
- const int *input_to_image_channel = layer.input_to_image_channel.data();
-
- for(int i = 0; i < width * height; i++) {
- for(int j = 0; j < INPUT_NUM_CHANNELS; j++) {
- int image_channel = input_to_image_channel[j];
- input_pixels[i*INPUT_NUM_CHANNELS + j] = pixels[((size_t)i)*num_channels + image_channel];
- }
- }
-}
-
-bool DenoiseImage::read_neighbor_pixels(int neighbor, const DenoiseImageLayer& layer, float *input_pixels)
-{
- /* Load pixels from neighboring frames, and copy them into device buffer
- * with channels reshuffled. */
- size_t num_pixels = (size_t)width * (size_t)height;
- array<float> neighbor_pixels(num_pixels * num_channels);
- if(!in_neighbors[neighbor]->read_image(TypeDesc::FLOAT, neighbor_pixels.data())) {
- return false;
- }
-
- const int *input_to_image_channel = layer.neighbor_input_to_image_channel[neighbor].data();
-
- for(int i = 0; i < width * height; i++) {
- for(int j = 0; j < INPUT_NUM_CHANNELS; j++) {
- int image_channel = input_to_image_channel[j];
- input_pixels[i*INPUT_NUM_CHANNELS + j] = neighbor_pixels[((size_t)i)*num_channels + image_channel];
- }
- }
-
- return true;
-}
-
-bool DenoiseImage::load(const string& in_filepath, string& error)
-{
- if(!Filesystem::is_regular(in_filepath)) {
- error = "Couldn't find file: " + in_filepath;
- return false;
- }
-
- unique_ptr<ImageInput> in(ImageInput::open(in_filepath));
- if(!in) {
- error = "Couldn't open file: " + in_filepath;
- return false;
- }
-
- in_spec = in->spec();
- width = in_spec.width;
- height = in_spec.height;
- num_channels = in_spec.nchannels;
-
- if(!parse_channels(in_spec, error)) {
- return false;
- }
-
- if(layers.size() == 0) {
- error = "Could not find a render layer containing denoising info";
- return false;
- }
-
- size_t num_pixels = (size_t)width * (size_t)height;
- pixels.resize(num_pixels * num_channels);
-
- /* Read all channels into buffer. Reading all channels at once is faster
- * than individually due to interleaved EXR channel storage. */
- if(!in->read_image(TypeDesc::FLOAT, pixels.data())) {
- error = "Failed to read image: " + in_filepath;
- return false;
- }
-
- return true;
-}
-
-bool DenoiseImage::load_neighbors(const vector<string>& filepaths, const vector<int>& frames, string& error)
-{
- if(frames.size() > DENOISE_MAX_FRAMES - 1) {
- error = string_printf("Maximum number of neighbors (%d) exceeded\n", DENOISE_MAX_FRAMES - 1);
- return false;
- }
-
- for(int neighbor = 0; neighbor < frames.size(); neighbor++) {
- int frame = frames[neighbor];
- const string& filepath = filepaths[frame];
-
- if(!Filesystem::is_regular(filepath)) {
- error = "Couldn't find neighbor frame: " + filepath;
- return false;
- }
-
- unique_ptr<ImageInput> in_neighbor(ImageInput::open(filepath));
- if(!in_neighbor) {
- error = "Couldn't open neighbor frame: " + filepath;
- return false;
- }
+ const std::vector<string> &channels = in_spec.channelnames;
+ const ParamValue *multiview = in_spec.find_attribute("multiView");
+ const bool multiview_channels = (multiview && multiview->type().basetype == TypeDesc::STRING &&
+ multiview->type().arraylen >= 2);
+
+ layers.clear();
+
+ /* Loop over all the channels in the file, parse their name and sort them
+ * by RenderLayer.
+ * Channels that can't be parsed are directly passed through to the output. */
+ map<string, DenoiseImageLayer> file_layers;
+ for (int i = 0; i < channels.size(); i++) {
+ string layer, pass, channel;
+ if (parse_channel_name(channels[i], layer, pass, channel, multiview_channels)) {
+ file_layers[layer].channels.push_back(pass + "." + channel);
+ file_layers[layer].layer_to_image_channel.push_back(i);
+ }
+ }
+
+ /* Loop over all detected RenderLayers, check whether they contain a full set of input channels.
+ * Any channels that won't be processed internally are also passed through. */
+ for (map<string, DenoiseImageLayer>::iterator i = file_layers.begin(); i != file_layers.end();
+ ++i) {
+ const string &name = i->first;
+ DenoiseImageLayer &layer = i->second;
+
+ /* Check for full pass set. */
+ if (!layer.detect_denoising_channels()) {
+ continue;
+ }
+
+ layer.name = name;
+ layer.samples = samples;
+
+ /* If the sample value isn't set yet, check if there is a layer-specific one in the input file. */
+ if (layer.samples < 1) {
+ string sample_string = in_spec.get_string_attribute("cycles." + name + ".samples", "");
+ if (sample_string != "") {
+ if (!sscanf(sample_string.c_str(), "%d", &layer.samples)) {
+ error = "Failed to parse samples metadata: " + sample_string;
+ return false;
+ }
+ }
+ }
+
+ if (layer.samples < 1) {
+ error = string_printf(
+ "No sample number specified in the file for layer %s or on the command line",
+ name.c_str());
+ return false;
+ }
+
+ layers.push_back(layer);
+ }
+
+ return true;
+}
+
+void DenoiseImage::read_pixels(const DenoiseImageLayer &layer, float *input_pixels)
+{
+ /* Pixels from center file have already been loaded into pixels.
+ * We copy a subset into the device input buffer with channels reshuffled. */
+ const int *input_to_image_channel = layer.input_to_image_channel.data();
+
+ for (int i = 0; i < width * height; i++) {
+ for (int j = 0; j < INPUT_NUM_CHANNELS; j++) {
+ int image_channel = input_to_image_channel[j];
+ input_pixels[i * INPUT_NUM_CHANNELS + j] =
+ pixels[((size_t)i) * num_channels + image_channel];
+ }
+ }
+}
+
+bool DenoiseImage::read_neighbor_pixels(int neighbor,
+ const DenoiseImageLayer &layer,
+ float *input_pixels)
+{
+ /* Load pixels from neighboring frames, and copy them into device buffer
+ * with channels reshuffled. */
+ size_t num_pixels = (size_t)width * (size_t)height;
+ array<float> neighbor_pixels(num_pixels * num_channels);
+ if (!in_neighbors[neighbor]->read_image(TypeDesc::FLOAT, neighbor_pixels.data())) {
+ return false;
+ }
+
+ const int *input_to_image_channel = layer.neighbor_input_to_image_channel[neighbor].data();
+
+ for (int i = 0; i < width * height; i++) {
+ for (int j = 0; j < INPUT_NUM_CHANNELS; j++) {
+ int image_channel = input_to_image_channel[j];
+ input_pixels[i * INPUT_NUM_CHANNELS + j] =
+ neighbor_pixels[((size_t)i) * num_channels + image_channel];
+ }
+ }
+
+ return true;
+}
+
+bool DenoiseImage::load(const string &in_filepath, string &error)
+{
+ if (!Filesystem::is_regular(in_filepath)) {
+ error = "Couldn't find file: " + in_filepath;
+ return false;
+ }
+
+ unique_ptr<ImageInput> in(ImageInput::open(in_filepath));
+ if (!in) {
+ error = "Couldn't open file: " + in_filepath;
+ return false;
+ }
+
+ in_spec = in->spec();
+ width = in_spec.width;
+ height = in_spec.height;
+ num_channels = in_spec.nchannels;
+
+ if (!parse_channels(in_spec, error)) {
+ return false;
+ }
+
+ if (layers.size() == 0) {
+ error = "Could not find a render layer containing denoising info";
+ return false;
+ }
+
+ size_t num_pixels = (size_t)width * (size_t)height;
+ pixels.resize(num_pixels * num_channels);
+
+ /* Read all channels into buffer. Reading all channels at once is faster
+ * than individually due to interleaved EXR channel storage. */
+ if (!in->read_image(TypeDesc::FLOAT, pixels.data())) {
+ error = "Failed to read image: " + in_filepath;
+ return false;
+ }
+
+ return true;
+}
+
+bool DenoiseImage::load_neighbors(const vector<string> &filepaths,
+ const vector<int> &frames,
+ string &error)
+{
+ if (frames.size() > DENOISE_MAX_FRAMES - 1) {
+ error = string_printf("Maximum number of neighbors (%d) exceeded\n", DENOISE_MAX_FRAMES - 1);
+ return false;
+ }
+
+ for (int neighbor = 0; neighbor < frames.size(); neighbor++) {
+ int frame = frames[neighbor];
+ const string &filepath = filepaths[frame];
- const ImageSpec &neighbor_spec = in_neighbor->spec();
- if(neighbor_spec.width != width || neighbor_spec.height != height) {
- error = "Neighbor frame has different dimensions: " + filepath;
- return false;
- }
-
- foreach(DenoiseImageLayer& layer, layers) {
- if(!layer.match_channels(neighbor,
- in_spec.channelnames,
- neighbor_spec.channelnames))
- {
- error = "Neighbor frame misses denoising data passes: " + filepath;
- return false;
- }
- }
-
- in_neighbors.push_back(std::move(in_neighbor));
- }
-
- return true;
-}
-
-bool DenoiseImage::save_output(const string& out_filepath, string& error)
-{
- /* Save image with identical dimensions, channels and metadata. */
- ImageSpec out_spec = in_spec;
-
- /* Ensure that the output frame contains sample information even if the input didn't. */
- for(int i = 0; i < layers.size(); i++) {
- string name = "cycles." + layers[i].name + ".samples";
- if(!out_spec.find_attribute(name, TypeDesc::STRING)) {
- out_spec.attribute(name, TypeDesc::STRING, string_printf("%d", layers[i].samples));
- }
- }
+ if (!Filesystem::is_regular(filepath)) {
+ error = "Couldn't find neighbor frame: " + filepath;
+ return false;
+ }
+
+ unique_ptr<ImageInput> in_neighbor(ImageInput::open(filepath));
+ if (!in_neighbor) {
+ error = "Couldn't open neighbor frame: " + filepath;
+ return false;
+ }
+
+ const ImageSpec &neighbor_spec = in_neighbor->spec();
+ if (neighbor_spec.width != width || neighbor_spec.height != height) {
+ error = "Neighbor frame has different dimensions: " + filepath;
+ return false;
+ }
+
+ foreach (DenoiseImageLayer &layer, layers) {
+ if (!layer.match_channels(neighbor, in_spec.channelnames, neighbor_spec.channelnames)) {
+ error = "Neighbor frame misses denoising data passes: " + filepath;
+ return false;
+ }
+ }
+
+ in_neighbors.push_back(std::move(in_neighbor));
+ }
+
+ return true;
+}
+
+bool DenoiseImage::save_output(const string &out_filepath, string &error)
+{
+ /* Save image with identical dimensions, channels and metadata. */
+ ImageSpec out_spec = in_spec;
+
+ /* Ensure that the output frame contains sample information even if the input didn't. */
+ for (int i = 0; i < layers.size(); i++) {
+ string name = "cycles." + layers[i].name + ".samples";
+ if (!out_spec.find_attribute(name, TypeDesc::STRING)) {
+ out_spec.attribute(name, TypeDesc::STRING, string_printf("%d", layers[i].samples));
+ }
+ }
- /* We don't need input anymore at this point, and will possibly
- * overwrite the same file. */
- close_input();
-
- /* Write to temporary file path, so we denoise images in place and don't
- * risk destroying files when something goes wrong in file saving. */
- string extension = OIIO::Filesystem::extension(out_filepath);
- string unique_name = ".denoise-tmp-" + OIIO::Filesystem::unique_path();
- string tmp_filepath = out_filepath + unique_name + extension;
- unique_ptr<ImageOutput> out(ImageOutput::create(tmp_filepath));
-
- if(!out) {
- error = "Failed to open temporary file " + tmp_filepath + " for writing";
- return false;
- }
-
- /* Open temporary file and write image buffers. */
- if(!out->open(tmp_filepath, out_spec)) {
- error = "Failed to open file " + tmp_filepath + " for writing: " + out->geterror();
- return false;
- }
-
- bool ok = true;
- if(!out->write_image(TypeDesc::FLOAT, pixels.data())) {
- error = "Failed to write to file " + tmp_filepath + ": " + out->geterror();
- ok = false;
- }
-
- if(!out->close()) {
- error = "Failed to save to file " + tmp_filepath + ": " + out->geterror();
- ok = false;
- }
-
- out.reset();
-
- /* Copy temporary file to outputput filepath. */
- string rename_error;
- if(ok && !OIIO::Filesystem::rename(tmp_filepath, out_filepath, rename_error)) {
- error = "Failed to move denoised image to " + out_filepath + ": " + rename_error;
- ok = false;
- }
-
- if(!ok) {
- OIIO::Filesystem::remove(tmp_filepath);
- }
-
- return ok;
+ /* We don't need input anymore at this point, and will possibly
+ * overwrite the same file. */
+ close_input();
+
+ /* Write to temporary file path, so we denoise images in place and don't
+ * risk destroying files when something goes wrong in file saving. */
+ string extension = OIIO::Filesystem::extension(out_filepath);
+ string unique_name = ".denoise-tmp-" + OIIO::Filesystem::unique_path();
+ string tmp_filepath = out_filepath + unique_name + extension;
+ unique_ptr<ImageOutput> out(ImageOutput::create(tmp_filepath));
+
+ if (!out) {
+ error = "Failed to open temporary file " + tmp_filepath + " for writing";
+ return false;
+ }
+
+ /* Open temporary file and write image buffers. */
+ if (!out->open(tmp_filepath, out_spec)) {
+ error = "Failed to open file " + tmp_filepath + " for writing: " + out->geterror();
+ return false;
+ }
+
+ bool ok = true;
+ if (!out->write_image(TypeDesc::FLOAT, pixels.data())) {
+ error = "Failed to write to file " + tmp_filepath + ": " + out->geterror();
+ ok = false;
+ }
+
+ if (!out->close()) {
+ error = "Failed to save to file " + tmp_filepath + ": " + out->geterror();
+ ok = false;
+ }
+
+ out.reset();
+
+ /* Copy temporary file to outputput filepath. */
+ string rename_error;
+ if (ok && !OIIO::Filesystem::rename(tmp_filepath, out_filepath, rename_error)) {
+ error = "Failed to move denoised image to " + out_filepath + ": " + rename_error;
+ ok = false;
+ }
+
+ if (!ok) {
+ OIIO::Filesystem::remove(tmp_filepath);
+ }
+
+ return ok;
}
/* File pattern handling and outer loop over frames */
-Denoiser::Denoiser(DeviceInfo& device_info)
+Denoiser::Denoiser(DeviceInfo &device_info)
{
- samples_override = 0;
- tile_size = make_int2(64, 64);
+ samples_override = 0;
+ tile_size = make_int2(64, 64);
- num_frames = 0;
+ num_frames = 0;
- /* Initialize task scheduler. */
- TaskScheduler::init();
+ /* Initialize task scheduler. */
+ TaskScheduler::init();
- /* Initialize device. */
- DeviceRequestedFeatures req;
- device = Device::create(device_info, stats, profiler, true);
- device->load_kernels(req);
+ /* Initialize device. */
+ DeviceRequestedFeatures req;
+ device = Device::create(device_info, stats, profiler, true);
+ device->load_kernels(req);
}
Denoiser::~Denoiser()
{
- delete device;
- TaskScheduler::exit();
+ delete device;
+ TaskScheduler::exit();
}
bool Denoiser::run()
{
- assert(input.size() == output.size());
-
- num_frames = output.size();
-
- for(int frame = 0; frame < num_frames; frame++) {
- /* Skip empty output paths. */
- if(output[frame].empty()) {
- continue;
- }
-
- /* Determine neighbor frame numbers that should be used for filtering. */
- vector<int> neighbor_frames;
- for(int f = frame - params.neighbor_frames; f <= frame + params.neighbor_frames; f++) {
- if (f >= 0 && f < num_frames && f != frame) {
- neighbor_frames.push_back(f);
- }
- }
-
- /* Execute task. */
- DenoiseTask task(device, this, frame, neighbor_frames);
- if(!task.load()) {
- error = task.error;
- return false;
- }
-
- if(!task.exec()) {
- error = task.error;
- return false;
- }
-
- if(!task.save()) {
- error = task.error;
- return false;
- }
-
- task.free();
- }
-
- return true;
+ assert(input.size() == output.size());
+
+ num_frames = output.size();
+
+ for (int frame = 0; frame < num_frames; frame++) {
+ /* Skip empty output paths. */
+ if (output[frame].empty()) {
+ continue;
+ }
+
+ /* Determine neighbor frame numbers that should be used for filtering. */
+ vector<int> neighbor_frames;
+ for (int f = frame - params.neighbor_frames; f <= frame + params.neighbor_frames; f++) {
+ if (f >= 0 && f < num_frames && f != frame) {
+ neighbor_frames.push_back(f);
+ }
+ }
+
+ /* Execute task. */
+ DenoiseTask task(device, this, frame, neighbor_frames);
+ if (!task.load()) {
+ error = task.error;
+ return false;
+ }
+
+ if (!task.exec()) {
+ error = task.error;
+ return false;
+ }
+
+ if (!task.save()) {
+ error = task.error;
+ return false;
+ }
+
+ task.free();
+ }
+
+ return true;
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/render/denoising.h b/intern/cycles/render/denoising.h
index 5bf1a8dd0fa..dcb842a4603 100644
--- a/intern/cycles/render/denoising.h
+++ b/intern/cycles/render/denoising.h
@@ -35,166 +35,166 @@ CCL_NAMESPACE_BEGIN
/* Denoiser */
class Denoiser {
-public:
- Denoiser(DeviceInfo& device_info);
- ~Denoiser();
+ public:
+ Denoiser(DeviceInfo &device_info);
+ ~Denoiser();
- bool run();
+ bool run();
- /* Error message after running, in case of failure. */
- string error;
+ /* Error message after running, in case of failure. */
+ string error;
- /* Sequential list of frame filepaths to denoise. */
- vector<string> input;
- /* Sequential list of frame filepaths to write result to. Empty entries
- * are skipped, so only a subset of the sequence can be denoised while
- * taking into account all input frames. */
- vector<string> output;
+ /* Sequential list of frame filepaths to denoise. */
+ vector<string> input;
+ /* Sequential list of frame filepaths to write result to. Empty entries
+ * are skipped, so only a subset of the sequence can be denoised while
+ * taking into account all input frames. */
+ vector<string> output;
- /* Sample number override, takes precedence over values from input frames. */
- int samples_override;
- /* Tile size for processing on device. */
- int2 tile_size;
+ /* Sample number override, takes precedence over values from input frames. */
+ int samples_override;
+ /* Tile size for processing on device. */
+ int2 tile_size;
- /* Equivalent to the settings in the regular denoiser. */
- DenoiseParams params;
+ /* Equivalent to the settings in the regular denoiser. */
+ DenoiseParams params;
-protected:
- friend class DenoiseTask;
+ protected:
+ friend class DenoiseTask;
- Stats stats;
- Profiler profiler;
- Device *device;
+ Stats stats;
+ Profiler profiler;
+ Device *device;
- int num_frames;
+ int num_frames;
};
/* Denoise Image Layer */
struct DenoiseImageLayer {
- string name;
- /* All channels belonging to this DenoiseImageLayer. */
- vector<string> channels;
- /* Layer to image channel mapping. */
- vector<int> layer_to_image_channel;
+ string name;
+ /* All channels belonging to this DenoiseImageLayer. */
+ vector<string> channels;
+ /* Layer to image channel mapping. */
+ vector<int> layer_to_image_channel;
- /* Sample amount that was used for rendering this layer. */
- int samples;
+ /* Sample amount that was used for rendering this layer. */
+ int samples;
- /* Device input channel will be copied from image channel input_to_image_channel[i]. */
- vector<int> input_to_image_channel;
+ /* Device input channel will be copied from image channel input_to_image_channel[i]. */
+ vector<int> input_to_image_channel;
- /* input_to_image_channel of the secondary frames, if any are used. */
- vector<vector<int>> neighbor_input_to_image_channel;
+ /* input_to_image_channel of the secondary frames, if any are used. */
+ vector<vector<int>> neighbor_input_to_image_channel;
- /* Write i-th channel of the processing output to output_to_image_channel[i]-th channel of the file. */
- vector<int> output_to_image_channel;
+ /* Write i-th channel of the processing output to output_to_image_channel[i]-th channel of the file. */
+ vector<int> output_to_image_channel;
- /* Detect whether this layer contains a full set of channels and set up the offsets accordingly. */
- bool detect_denoising_channels();
+ /* Detect whether this layer contains a full set of channels and set up the offsets accordingly. */
+ bool detect_denoising_channels();
- /* Map the channels of a secondary frame to the channels that are required for processing,
- * fill neighbor_input_to_image_channel if all are present or return false if a channel are missing. */
- bool match_channels(int neighbor,
- const std::vector<string> &channelnames,
- const std::vector<string> &neighbor_channelnames);
+ /* Map the channels of a secondary frame to the channels that are required for processing,
+ * fill neighbor_input_to_image_channel if all are present or return false if a channel are missing. */
+ bool match_channels(int neighbor,
+ const std::vector<string> &channelnames,
+ const std::vector<string> &neighbor_channelnames);
};
/* Denoise Image Data */
class DenoiseImage {
-public:
- DenoiseImage();
- ~DenoiseImage();
+ public:
+ DenoiseImage();
+ ~DenoiseImage();
- /* Dimensions */
- int width, height, num_channels;
+ /* Dimensions */
+ int width, height, num_channels;
- /* Samples */
- int samples;
+ /* Samples */
+ int samples;
- /* Pixel buffer with interleaved channels. */
- array<float> pixels;
+ /* Pixel buffer with interleaved channels. */
+ array<float> pixels;
- /* Image file handles */
- ImageSpec in_spec;
- vector<unique_ptr<ImageInput>> in_neighbors;
+ /* Image file handles */
+ ImageSpec in_spec;
+ vector<unique_ptr<ImageInput>> in_neighbors;
- /* Render layers */
- vector<DenoiseImageLayer> layers;
+ /* Render layers */
+ vector<DenoiseImageLayer> layers;
- void free();
+ void free();
- /* Open the input image, parse its channels, open the output image and allocate the output buffer. */
- bool load(const string& in_filepath, string& error);
+ /* Open the input image, parse its channels, open the output image and allocate the output buffer. */
+ bool load(const string &in_filepath, string &error);
- /* Load neighboring frames. */
- bool load_neighbors(const vector<string>& filepaths, const vector<int>& frames, string& error);
+ /* Load neighboring frames. */
+ bool load_neighbors(const vector<string> &filepaths, const vector<int> &frames, string &error);
- /* Load subset of pixels from file buffer into input buffer, as needed for denoising
- * on the device. Channels are reshuffled following the provided mapping. */
- void read_pixels(const DenoiseImageLayer& layer, float *input_pixels);
- bool read_neighbor_pixels(int neighbor, const DenoiseImageLayer& layer, float *input_pixels);
+ /* Load subset of pixels from file buffer into input buffer, as needed for denoising
+ * on the device. Channels are reshuffled following the provided mapping. */
+ void read_pixels(const DenoiseImageLayer &layer, float *input_pixels);
+ bool read_neighbor_pixels(int neighbor, const DenoiseImageLayer &layer, float *input_pixels);
- bool save_output(const string& out_filepath, string& error);
+ bool save_output(const string &out_filepath, string &error);
-protected:
- /* Parse input file channels, separate them into DenoiseImageLayers, detect DenoiseImageLayers with full channel sets,
- * fill layers and set up the output channels and passthrough map. */
- bool parse_channels(const ImageSpec &in_spec, string& error);
+ protected:
+ /* Parse input file channels, separate them into DenoiseImageLayers, detect DenoiseImageLayers with full channel sets,
+ * fill layers and set up the output channels and passthrough map. */
+ bool parse_channels(const ImageSpec &in_spec, string &error);
- void close_input();
+ void close_input();
};
/* Denoise Task */
class DenoiseTask {
-public:
- DenoiseTask(Device *device, Denoiser *denoiser, int frame, const vector<int>& neighbor_frames);
- ~DenoiseTask();
-
- /* Task stages */
- bool load();
- bool exec();
- bool save();
- void free();
-
- string error;
-
-protected:
- /* Denoiser parameters and device */
- Denoiser *denoiser;
- Device *device;
-
- /* Frame number to be denoised */
- int frame;
- vector<int> neighbor_frames;
-
- /* Image file data */
- DenoiseImage image;
- int current_layer;
-
- /* Device input buffer */
- device_vector<float> input_pixels;
-
- /* Tiles */
- thread_mutex tiles_mutex;
- list<RenderTile> tiles;
- int num_tiles;
-
- thread_mutex output_mutex;
- map<int, device_vector<float>*> output_pixels;
-
- /* Task handling */
- bool load_input_pixels(int layer);
- void create_task(DeviceTask& task);
-
- /* Device task callbacks */
- bool acquire_tile(Device *device, Device *tile_device, RenderTile &tile);
- void map_neighboring_tiles(RenderTile *tiles, Device *tile_device);
- void unmap_neighboring_tiles(RenderTile *tiles);
- void release_tile();
- bool get_cancel();
+ public:
+ DenoiseTask(Device *device, Denoiser *denoiser, int frame, const vector<int> &neighbor_frames);
+ ~DenoiseTask();
+
+ /* Task stages */
+ bool load();
+ bool exec();
+ bool save();
+ void free();
+
+ string error;
+
+ protected:
+ /* Denoiser parameters and device */
+ Denoiser *denoiser;
+ Device *device;
+
+ /* Frame number to be denoised */
+ int frame;
+ vector<int> neighbor_frames;
+
+ /* Image file data */
+ DenoiseImage image;
+ int current_layer;
+
+ /* Device input buffer */
+ device_vector<float> input_pixels;
+
+ /* Tiles */
+ thread_mutex tiles_mutex;
+ list<RenderTile> tiles;
+ int num_tiles;
+
+ thread_mutex output_mutex;
+ map<int, device_vector<float> *> output_pixels;
+
+ /* Task handling */
+ bool load_input_pixels(int layer);
+ void create_task(DeviceTask &task);
+
+ /* Device task callbacks */
+ bool acquire_tile(Device *device, Device *tile_device, RenderTile &tile);
+ void map_neighboring_tiles(RenderTile *tiles, Device *tile_device);
+ void unmap_neighboring_tiles(RenderTile *tiles);
+ void release_tile();
+ bool get_cancel();
};
CCL_NAMESPACE_END
diff --git a/intern/cycles/render/film.cpp b/intern/cycles/render/film.cpp
index 1d1668a20d1..d6c44b66117 100644
--- a/intern/cycles/render/film.cpp
+++ b/intern/cycles/render/film.cpp
@@ -31,277 +31,275 @@ CCL_NAMESPACE_BEGIN
/* Pass */
-static bool compare_pass_order(const Pass& a, const Pass& b)
+static bool compare_pass_order(const Pass &a, const Pass &b)
{
- if(a.components == b.components)
- return (a.type < b.type);
- return (a.components > b.components);
+ if (a.components == b.components)
+ return (a.type < b.type);
+ return (a.components > b.components);
}
-void Pass::add(PassType type, vector<Pass>& passes, const char *name)
+void Pass::add(PassType type, vector<Pass> &passes, const char *name)
{
- for(size_t i = 0; i < passes.size(); i++) {
- if(passes[i].type == type &&
- (name ? (passes[i].name == name) : passes[i].name.empty())) {
- return;
- }
- }
-
- Pass pass;
-
- pass.type = type;
- pass.filter = true;
- pass.exposure = false;
- pass.divide_type = PASS_NONE;
- if(name) {
- pass.name = name;
- }
-
- switch(type) {
- case PASS_NONE:
- pass.components = 0;
- break;
- case PASS_COMBINED:
- pass.components = 4;
- pass.exposure = true;
- break;
- case PASS_DEPTH:
- pass.components = 1;
- pass.filter = false;
- break;
- case PASS_MIST:
- pass.components = 1;
- break;
- case PASS_NORMAL:
- pass.components = 4;
- break;
- case PASS_UV:
- pass.components = 4;
- break;
- case PASS_MOTION:
- pass.components = 4;
- pass.divide_type = PASS_MOTION_WEIGHT;
- break;
- case PASS_MOTION_WEIGHT:
- pass.components = 1;
- break;
- case PASS_OBJECT_ID:
- case PASS_MATERIAL_ID:
- pass.components = 1;
- pass.filter = false;
- break;
-
- case PASS_EMISSION:
- case PASS_BACKGROUND:
- pass.components = 4;
- pass.exposure = true;
- break;
- case PASS_AO:
- pass.components = 4;
- break;
- case PASS_SHADOW:
- pass.components = 4;
- pass.exposure = false;
- break;
- case PASS_LIGHT:
- /* This isn't a real pass, used by baking to see whether
- * light data is needed or not.
- *
- * Set components to 0 so pass sort below happens in a
- * determined way.
- */
- pass.components = 0;
- break;
+ for (size_t i = 0; i < passes.size(); i++) {
+ if (passes[i].type == type && (name ? (passes[i].name == name) : passes[i].name.empty())) {
+ return;
+ }
+ }
+
+ Pass pass;
+
+ pass.type = type;
+ pass.filter = true;
+ pass.exposure = false;
+ pass.divide_type = PASS_NONE;
+ if (name) {
+ pass.name = name;
+ }
+
+ switch (type) {
+ case PASS_NONE:
+ pass.components = 0;
+ break;
+ case PASS_COMBINED:
+ pass.components = 4;
+ pass.exposure = true;
+ break;
+ case PASS_DEPTH:
+ pass.components = 1;
+ pass.filter = false;
+ break;
+ case PASS_MIST:
+ pass.components = 1;
+ break;
+ case PASS_NORMAL:
+ pass.components = 4;
+ break;
+ case PASS_UV:
+ pass.components = 4;
+ break;
+ case PASS_MOTION:
+ pass.components = 4;
+ pass.divide_type = PASS_MOTION_WEIGHT;
+ break;
+ case PASS_MOTION_WEIGHT:
+ pass.components = 1;
+ break;
+ case PASS_OBJECT_ID:
+ case PASS_MATERIAL_ID:
+ pass.components = 1;
+ pass.filter = false;
+ break;
+
+ case PASS_EMISSION:
+ case PASS_BACKGROUND:
+ pass.components = 4;
+ pass.exposure = true;
+ break;
+ case PASS_AO:
+ pass.components = 4;
+ break;
+ case PASS_SHADOW:
+ pass.components = 4;
+ pass.exposure = false;
+ break;
+ case PASS_LIGHT:
+ /* This isn't a real pass, used by baking to see whether
+ * light data is needed or not.
+ *
+ * Set components to 0 so pass sort below happens in a
+ * determined way.
+ */
+ pass.components = 0;
+ break;
#ifdef WITH_CYCLES_DEBUG
- case PASS_BVH_TRAVERSED_NODES:
- case PASS_BVH_TRAVERSED_INSTANCES:
- case PASS_BVH_INTERSECTIONS:
- case PASS_RAY_BOUNCES:
- pass.components = 1;
- pass.exposure = false;
- break;
+ case PASS_BVH_TRAVERSED_NODES:
+ case PASS_BVH_TRAVERSED_INSTANCES:
+ case PASS_BVH_INTERSECTIONS:
+ case PASS_RAY_BOUNCES:
+ pass.components = 1;
+ pass.exposure = false;
+ break;
#endif
- case PASS_RENDER_TIME:
- /* This pass is handled entirely on the host side. */
- pass.components = 0;
- break;
-
- case PASS_DIFFUSE_COLOR:
- case PASS_GLOSSY_COLOR:
- case PASS_TRANSMISSION_COLOR:
- case PASS_SUBSURFACE_COLOR:
- pass.components = 4;
- break;
- case PASS_DIFFUSE_DIRECT:
- case PASS_DIFFUSE_INDIRECT:
- pass.components = 4;
- pass.exposure = true;
- pass.divide_type = PASS_DIFFUSE_COLOR;
- break;
- case PASS_GLOSSY_DIRECT:
- case PASS_GLOSSY_INDIRECT:
- pass.components = 4;
- pass.exposure = true;
- pass.divide_type = PASS_GLOSSY_COLOR;
- break;
- case PASS_TRANSMISSION_DIRECT:
- case PASS_TRANSMISSION_INDIRECT:
- pass.components = 4;
- pass.exposure = true;
- pass.divide_type = PASS_TRANSMISSION_COLOR;
- break;
- case PASS_SUBSURFACE_DIRECT:
- case PASS_SUBSURFACE_INDIRECT:
- pass.components = 4;
- pass.exposure = true;
- pass.divide_type = PASS_SUBSURFACE_COLOR;
- break;
- case PASS_VOLUME_DIRECT:
- case PASS_VOLUME_INDIRECT:
- pass.components = 4;
- pass.exposure = true;
- break;
- case PASS_CRYPTOMATTE:
- pass.components = 4;
- break;
- default:
- assert(false);
- break;
- }
-
- passes.push_back(pass);
-
- /* order from by components, to ensure alignment so passes with size 4
- * come first and then passes with size 1 */
- sort(&passes[0], &passes[0] + passes.size(), compare_pass_order);
-
- if(pass.divide_type != PASS_NONE)
- Pass::add(pass.divide_type, passes);
+ case PASS_RENDER_TIME:
+ /* This pass is handled entirely on the host side. */
+ pass.components = 0;
+ break;
+
+ case PASS_DIFFUSE_COLOR:
+ case PASS_GLOSSY_COLOR:
+ case PASS_TRANSMISSION_COLOR:
+ case PASS_SUBSURFACE_COLOR:
+ pass.components = 4;
+ break;
+ case PASS_DIFFUSE_DIRECT:
+ case PASS_DIFFUSE_INDIRECT:
+ pass.components = 4;
+ pass.exposure = true;
+ pass.divide_type = PASS_DIFFUSE_COLOR;
+ break;
+ case PASS_GLOSSY_DIRECT:
+ case PASS_GLOSSY_INDIRECT:
+ pass.components = 4;
+ pass.exposure = true;
+ pass.divide_type = PASS_GLOSSY_COLOR;
+ break;
+ case PASS_TRANSMISSION_DIRECT:
+ case PASS_TRANSMISSION_INDIRECT:
+ pass.components = 4;
+ pass.exposure = true;
+ pass.divide_type = PASS_TRANSMISSION_COLOR;
+ break;
+ case PASS_SUBSURFACE_DIRECT:
+ case PASS_SUBSURFACE_INDIRECT:
+ pass.components = 4;
+ pass.exposure = true;
+ pass.divide_type = PASS_SUBSURFACE_COLOR;
+ break;
+ case PASS_VOLUME_DIRECT:
+ case PASS_VOLUME_INDIRECT:
+ pass.components = 4;
+ pass.exposure = true;
+ break;
+ case PASS_CRYPTOMATTE:
+ pass.components = 4;
+ break;
+ default:
+ assert(false);
+ break;
+ }
+
+ passes.push_back(pass);
+
+ /* order from by components, to ensure alignment so passes with size 4
+ * come first and then passes with size 1 */
+ sort(&passes[0], &passes[0] + passes.size(), compare_pass_order);
+
+ if (pass.divide_type != PASS_NONE)
+ Pass::add(pass.divide_type, passes);
}
-bool Pass::equals(const vector<Pass>& A, const vector<Pass>& B)
+bool Pass::equals(const vector<Pass> &A, const vector<Pass> &B)
{
- if(A.size() != B.size())
- return false;
+ if (A.size() != B.size())
+ return false;
- for(int i = 0; i < A.size(); i++)
- if(A[i].type != B[i].type || A[i].name != B[i].name)
- return false;
+ for (int i = 0; i < A.size(); i++)
+ if (A[i].type != B[i].type || A[i].name != B[i].name)
+ return false;
- return true;
+ return true;
}
-bool Pass::contains(const vector<Pass>& passes, PassType type)
+bool Pass::contains(const vector<Pass> &passes, PassType type)
{
- for(size_t i = 0; i < passes.size(); i++)
- if(passes[i].type == type)
- return true;
+ for (size_t i = 0; i < passes.size(); i++)
+ if (passes[i].type == type)
+ return true;
- return false;
+ return false;
}
/* Pixel Filter */
static float filter_func_box(float /*v*/, float /*width*/)
{
- return 1.0f;
+ return 1.0f;
}
static float filter_func_gaussian(float v, float width)
{
- v *= 6.0f/width;
- return expf(-2.0f*v*v);
+ v *= 6.0f / width;
+ return expf(-2.0f * v * v);
}
static float filter_func_blackman_harris(float v, float width)
{
- v = M_2PI_F * (v / width + 0.5f);
- return 0.35875f - 0.48829f*cosf(v) + 0.14128f*cosf(2.0f*v) - 0.01168f*cosf(3.0f*v);
+ v = M_2PI_F * (v / width + 0.5f);
+ return 0.35875f - 0.48829f * cosf(v) + 0.14128f * cosf(2.0f * v) - 0.01168f * cosf(3.0f * v);
}
static vector<float> filter_table(FilterType type, float width)
{
- vector<float> filter_table(FILTER_TABLE_SIZE);
- float (*filter_func)(float, float) = NULL;
-
- switch(type) {
- case FILTER_BOX:
- filter_func = filter_func_box;
- break;
- case FILTER_GAUSSIAN:
- filter_func = filter_func_gaussian;
- width *= 3.0f;
- break;
- case FILTER_BLACKMAN_HARRIS:
- filter_func = filter_func_blackman_harris;
- width *= 2.0f;
- break;
- default:
- assert(0);
- }
-
- /* Create importance sampling table. */
-
- /* TODO(sergey): With the even filter table size resolution we can not
- * really make it nice symmetric importance map without sampling full range
- * (meaning, we would need to sample full filter range and not use the
- * make_symmetric argument).
- *
- * Current code matches exactly initial filter table code, but we should
- * consider either making FILTER_TABLE_SIZE odd value or sample full filter.
- */
-
- util_cdf_inverted(FILTER_TABLE_SIZE,
- 0.0f,
- width * 0.5f,
- function_bind(filter_func, _1, width),
- true,
- filter_table);
-
- return filter_table;
+ vector<float> filter_table(FILTER_TABLE_SIZE);
+ float (*filter_func)(float, float) = NULL;
+
+ switch (type) {
+ case FILTER_BOX:
+ filter_func = filter_func_box;
+ break;
+ case FILTER_GAUSSIAN:
+ filter_func = filter_func_gaussian;
+ width *= 3.0f;
+ break;
+ case FILTER_BLACKMAN_HARRIS:
+ filter_func = filter_func_blackman_harris;
+ width *= 2.0f;
+ break;
+ default:
+ assert(0);
+ }
+
+ /* Create importance sampling table. */
+
+ /* TODO(sergey): With the even filter table size resolution we can not
+ * really make it nice symmetric importance map without sampling full range
+ * (meaning, we would need to sample full filter range and not use the
+ * make_symmetric argument).
+ *
+ * Current code matches exactly initial filter table code, but we should
+ * consider either making FILTER_TABLE_SIZE odd value or sample full filter.
+ */
+
+ util_cdf_inverted(FILTER_TABLE_SIZE,
+ 0.0f,
+ width * 0.5f,
+ function_bind(filter_func, _1, width),
+ true,
+ filter_table);
+
+ return filter_table;
}
/* Film */
NODE_DEFINE(Film)
{
- NodeType* type = NodeType::add("film", create);
+ NodeType *type = NodeType::add("film", create);
- SOCKET_FLOAT(exposure, "Exposure", 0.8f);
- SOCKET_FLOAT(pass_alpha_threshold, "Pass Alpha Threshold", 0.5f);
+ SOCKET_FLOAT(exposure, "Exposure", 0.8f);
+ SOCKET_FLOAT(pass_alpha_threshold, "Pass Alpha Threshold", 0.5f);
- static NodeEnum filter_enum;
- filter_enum.insert("box", FILTER_BOX);
- filter_enum.insert("gaussian", FILTER_GAUSSIAN);
- filter_enum.insert("blackman_harris", FILTER_BLACKMAN_HARRIS);
+ static NodeEnum filter_enum;
+ filter_enum.insert("box", FILTER_BOX);
+ filter_enum.insert("gaussian", FILTER_GAUSSIAN);
+ filter_enum.insert("blackman_harris", FILTER_BLACKMAN_HARRIS);
- SOCKET_ENUM(filter_type, "Filter Type", filter_enum, FILTER_BOX);
- SOCKET_FLOAT(filter_width, "Filter Width", 1.0f);
+ SOCKET_ENUM(filter_type, "Filter Type", filter_enum, FILTER_BOX);
+ SOCKET_FLOAT(filter_width, "Filter Width", 1.0f);
- SOCKET_FLOAT(mist_start, "Mist Start", 0.0f);
- SOCKET_FLOAT(mist_depth, "Mist Depth", 100.0f);
- SOCKET_FLOAT(mist_falloff, "Mist Falloff", 1.0f);
+ SOCKET_FLOAT(mist_start, "Mist Start", 0.0f);
+ SOCKET_FLOAT(mist_depth, "Mist Depth", 100.0f);
+ SOCKET_FLOAT(mist_falloff, "Mist Falloff", 1.0f);
- SOCKET_BOOLEAN(use_sample_clamp, "Use Sample Clamp", false);
+ SOCKET_BOOLEAN(use_sample_clamp, "Use Sample Clamp", false);
- SOCKET_BOOLEAN(denoising_data_pass, "Generate Denoising Data Pass", false);
- SOCKET_BOOLEAN(denoising_clean_pass, "Generate Denoising Clean Pass", false);
- SOCKET_BOOLEAN(denoising_prefiltered_pass, "Generate Denoising Prefiltered Pass", false);
- SOCKET_INT(denoising_flags, "Denoising Flags", 0);
+ SOCKET_BOOLEAN(denoising_data_pass, "Generate Denoising Data Pass", false);
+ SOCKET_BOOLEAN(denoising_clean_pass, "Generate Denoising Clean Pass", false);
+ SOCKET_BOOLEAN(denoising_prefiltered_pass, "Generate Denoising Prefiltered Pass", false);
+ SOCKET_INT(denoising_flags, "Denoising Flags", 0);
- return type;
+ return type;
}
-Film::Film()
-: Node(node_type)
+Film::Film() : Node(node_type)
{
- Pass::add(PASS_COMBINED, passes);
+ Pass::add(PASS_COMBINED, passes);
- use_light_visibility = false;
- filter_table_offset = TABLE_OFFSET_INVALID;
- cryptomatte_passes = CRYPT_NONE;
+ use_light_visibility = false;
+ filter_table_offset = TABLE_OFFSET_INVALID;
+ cryptomatte_passes = CRYPT_NONE;
- need_update = true;
+ need_update = true;
}
Film::~Film()
@@ -310,233 +308,233 @@ Film::~Film()
void Film::device_update(Device *device, DeviceScene *dscene, Scene *scene)
{
- if(!need_update)
- return;
-
- device_free(device, dscene, scene);
-
- KernelFilm *kfilm = &dscene->data.film;
-
- /* update __data */
- kfilm->exposure = exposure;
- kfilm->pass_flag = 0;
- kfilm->light_pass_flag = 0;
- kfilm->pass_stride = 0;
- kfilm->use_light_pass = use_light_visibility || use_sample_clamp;
-
- bool have_cryptomatte = false;
-
- for(size_t i = 0; i < passes.size(); i++) {
- Pass& pass = passes[i];
-
- if(pass.type == PASS_NONE) {
- continue;
- }
-
- /* Can't do motion pass if no motion vectors are available. */
- if (pass.type == PASS_MOTION || pass.type == PASS_MOTION_WEIGHT) {
- if (scene->need_motion() != Scene::MOTION_PASS) {
- kfilm->pass_stride += pass.components;
- continue;
- }
- }
-
- int pass_flag = (1 << (pass.type % 32));
- if(pass.type <= PASS_CATEGORY_MAIN_END) {
- kfilm->pass_flag |= pass_flag;
- }
- else {
- assert(pass.type <= PASS_CATEGORY_LIGHT_END);
- kfilm->use_light_pass = 1;
- kfilm->light_pass_flag |= pass_flag;
- }
-
- switch(pass.type) {
- case PASS_COMBINED:
- kfilm->pass_combined = kfilm->pass_stride;
- break;
- case PASS_DEPTH:
- kfilm->pass_depth = kfilm->pass_stride;
- break;
- case PASS_NORMAL:
- kfilm->pass_normal = kfilm->pass_stride;
- break;
- case PASS_UV:
- kfilm->pass_uv = kfilm->pass_stride;
- break;
- case PASS_MOTION:
- kfilm->pass_motion = kfilm->pass_stride;
- break;
- case PASS_MOTION_WEIGHT:
- kfilm->pass_motion_weight = kfilm->pass_stride;
- break;
- case PASS_OBJECT_ID:
- kfilm->pass_object_id = kfilm->pass_stride;
- break;
- case PASS_MATERIAL_ID:
- kfilm->pass_material_id = kfilm->pass_stride;
- break;
-
- case PASS_MIST:
- kfilm->pass_mist = kfilm->pass_stride;
- break;
- case PASS_EMISSION:
- kfilm->pass_emission = kfilm->pass_stride;
- break;
- case PASS_BACKGROUND:
- kfilm->pass_background = kfilm->pass_stride;
- break;
- case PASS_AO:
- kfilm->pass_ao = kfilm->pass_stride;
- break;
- case PASS_SHADOW:
- kfilm->pass_shadow = kfilm->pass_stride;
- break;
-
- case PASS_LIGHT:
- break;
-
- case PASS_DIFFUSE_COLOR:
- kfilm->pass_diffuse_color = kfilm->pass_stride;
- break;
- case PASS_GLOSSY_COLOR:
- kfilm->pass_glossy_color = kfilm->pass_stride;
- break;
- case PASS_TRANSMISSION_COLOR:
- kfilm->pass_transmission_color = kfilm->pass_stride;
- break;
- case PASS_SUBSURFACE_COLOR:
- kfilm->pass_subsurface_color = kfilm->pass_stride;
- break;
- case PASS_DIFFUSE_INDIRECT:
- kfilm->pass_diffuse_indirect = kfilm->pass_stride;
- break;
- case PASS_GLOSSY_INDIRECT:
- kfilm->pass_glossy_indirect = kfilm->pass_stride;
- break;
- case PASS_TRANSMISSION_INDIRECT:
- kfilm->pass_transmission_indirect = kfilm->pass_stride;
- break;
- case PASS_SUBSURFACE_INDIRECT:
- kfilm->pass_subsurface_indirect = kfilm->pass_stride;
- break;
- case PASS_VOLUME_INDIRECT:
- kfilm->pass_volume_indirect = kfilm->pass_stride;
- break;
- case PASS_DIFFUSE_DIRECT:
- kfilm->pass_diffuse_direct = kfilm->pass_stride;
- break;
- case PASS_GLOSSY_DIRECT:
- kfilm->pass_glossy_direct = kfilm->pass_stride;
- break;
- case PASS_TRANSMISSION_DIRECT:
- kfilm->pass_transmission_direct = kfilm->pass_stride;
- break;
- case PASS_SUBSURFACE_DIRECT:
- kfilm->pass_subsurface_direct = kfilm->pass_stride;
- break;
- case PASS_VOLUME_DIRECT:
- kfilm->pass_volume_direct = kfilm->pass_stride;
- break;
+ if (!need_update)
+ return;
+
+ device_free(device, dscene, scene);
+
+ KernelFilm *kfilm = &dscene->data.film;
+
+ /* update __data */
+ kfilm->exposure = exposure;
+ kfilm->pass_flag = 0;
+ kfilm->light_pass_flag = 0;
+ kfilm->pass_stride = 0;
+ kfilm->use_light_pass = use_light_visibility || use_sample_clamp;
+
+ bool have_cryptomatte = false;
+
+ for (size_t i = 0; i < passes.size(); i++) {
+ Pass &pass = passes[i];
+
+ if (pass.type == PASS_NONE) {
+ continue;
+ }
+
+ /* Can't do motion pass if no motion vectors are available. */
+ if (pass.type == PASS_MOTION || pass.type == PASS_MOTION_WEIGHT) {
+ if (scene->need_motion() != Scene::MOTION_PASS) {
+ kfilm->pass_stride += pass.components;
+ continue;
+ }
+ }
+
+ int pass_flag = (1 << (pass.type % 32));
+ if (pass.type <= PASS_CATEGORY_MAIN_END) {
+ kfilm->pass_flag |= pass_flag;
+ }
+ else {
+ assert(pass.type <= PASS_CATEGORY_LIGHT_END);
+ kfilm->use_light_pass = 1;
+ kfilm->light_pass_flag |= pass_flag;
+ }
+
+ switch (pass.type) {
+ case PASS_COMBINED:
+ kfilm->pass_combined = kfilm->pass_stride;
+ break;
+ case PASS_DEPTH:
+ kfilm->pass_depth = kfilm->pass_stride;
+ break;
+ case PASS_NORMAL:
+ kfilm->pass_normal = kfilm->pass_stride;
+ break;
+ case PASS_UV:
+ kfilm->pass_uv = kfilm->pass_stride;
+ break;
+ case PASS_MOTION:
+ kfilm->pass_motion = kfilm->pass_stride;
+ break;
+ case PASS_MOTION_WEIGHT:
+ kfilm->pass_motion_weight = kfilm->pass_stride;
+ break;
+ case PASS_OBJECT_ID:
+ kfilm->pass_object_id = kfilm->pass_stride;
+ break;
+ case PASS_MATERIAL_ID:
+ kfilm->pass_material_id = kfilm->pass_stride;
+ break;
+
+ case PASS_MIST:
+ kfilm->pass_mist = kfilm->pass_stride;
+ break;
+ case PASS_EMISSION:
+ kfilm->pass_emission = kfilm->pass_stride;
+ break;
+ case PASS_BACKGROUND:
+ kfilm->pass_background = kfilm->pass_stride;
+ break;
+ case PASS_AO:
+ kfilm->pass_ao = kfilm->pass_stride;
+ break;
+ case PASS_SHADOW:
+ kfilm->pass_shadow = kfilm->pass_stride;
+ break;
+
+ case PASS_LIGHT:
+ break;
+
+ case PASS_DIFFUSE_COLOR:
+ kfilm->pass_diffuse_color = kfilm->pass_stride;
+ break;
+ case PASS_GLOSSY_COLOR:
+ kfilm->pass_glossy_color = kfilm->pass_stride;
+ break;
+ case PASS_TRANSMISSION_COLOR:
+ kfilm->pass_transmission_color = kfilm->pass_stride;
+ break;
+ case PASS_SUBSURFACE_COLOR:
+ kfilm->pass_subsurface_color = kfilm->pass_stride;
+ break;
+ case PASS_DIFFUSE_INDIRECT:
+ kfilm->pass_diffuse_indirect = kfilm->pass_stride;
+ break;
+ case PASS_GLOSSY_INDIRECT:
+ kfilm->pass_glossy_indirect = kfilm->pass_stride;
+ break;
+ case PASS_TRANSMISSION_INDIRECT:
+ kfilm->pass_transmission_indirect = kfilm->pass_stride;
+ break;
+ case PASS_SUBSURFACE_INDIRECT:
+ kfilm->pass_subsurface_indirect = kfilm->pass_stride;
+ break;
+ case PASS_VOLUME_INDIRECT:
+ kfilm->pass_volume_indirect = kfilm->pass_stride;
+ break;
+ case PASS_DIFFUSE_DIRECT:
+ kfilm->pass_diffuse_direct = kfilm->pass_stride;
+ break;
+ case PASS_GLOSSY_DIRECT:
+ kfilm->pass_glossy_direct = kfilm->pass_stride;
+ break;
+ case PASS_TRANSMISSION_DIRECT:
+ kfilm->pass_transmission_direct = kfilm->pass_stride;
+ break;
+ case PASS_SUBSURFACE_DIRECT:
+ kfilm->pass_subsurface_direct = kfilm->pass_stride;
+ break;
+ case PASS_VOLUME_DIRECT:
+ kfilm->pass_volume_direct = kfilm->pass_stride;
+ break;
#ifdef WITH_CYCLES_DEBUG
- case PASS_BVH_TRAVERSED_NODES:
- kfilm->pass_bvh_traversed_nodes = kfilm->pass_stride;
- break;
- case PASS_BVH_TRAVERSED_INSTANCES:
- kfilm->pass_bvh_traversed_instances = kfilm->pass_stride;
- break;
- case PASS_BVH_INTERSECTIONS:
- kfilm->pass_bvh_intersections = kfilm->pass_stride;
- break;
- case PASS_RAY_BOUNCES:
- kfilm->pass_ray_bounces = kfilm->pass_stride;
- break;
+ case PASS_BVH_TRAVERSED_NODES:
+ kfilm->pass_bvh_traversed_nodes = kfilm->pass_stride;
+ break;
+ case PASS_BVH_TRAVERSED_INSTANCES:
+ kfilm->pass_bvh_traversed_instances = kfilm->pass_stride;
+ break;
+ case PASS_BVH_INTERSECTIONS:
+ kfilm->pass_bvh_intersections = kfilm->pass_stride;
+ break;
+ case PASS_RAY_BOUNCES:
+ kfilm->pass_ray_bounces = kfilm->pass_stride;
+ break;
#endif
- case PASS_RENDER_TIME:
- break;
- case PASS_CRYPTOMATTE:
- kfilm->pass_cryptomatte = have_cryptomatte ? min(kfilm->pass_cryptomatte, kfilm->pass_stride) : kfilm->pass_stride;
- have_cryptomatte = true;
- break;
- default:
- assert(false);
- break;
- }
-
- kfilm->pass_stride += pass.components;
- }
-
- kfilm->pass_denoising_data = 0;
- kfilm->pass_denoising_clean = 0;
- kfilm->denoising_flags = 0;
- if(denoising_data_pass) {
- kfilm->pass_denoising_data = kfilm->pass_stride;
- kfilm->pass_stride += DENOISING_PASS_SIZE_BASE;
- kfilm->denoising_flags = denoising_flags;
- if(denoising_clean_pass) {
- kfilm->pass_denoising_clean = kfilm->pass_stride;
- kfilm->pass_stride += DENOISING_PASS_SIZE_CLEAN;
- kfilm->use_light_pass = 1;
- }
- if(denoising_prefiltered_pass) {
- kfilm->pass_stride += DENOISING_PASS_SIZE_PREFILTERED;
- }
- }
-
- kfilm->pass_stride = align_up(kfilm->pass_stride, 4);
- kfilm->pass_alpha_threshold = pass_alpha_threshold;
-
- /* update filter table */
- vector<float> table = filter_table(filter_type, filter_width);
- scene->lookup_tables->remove_table(&filter_table_offset);
- filter_table_offset = scene->lookup_tables->add_table(dscene, table);
- kfilm->filter_table_offset = (int)filter_table_offset;
-
- /* mist pass parameters */
- kfilm->mist_start = mist_start;
- kfilm->mist_inv_depth = (mist_depth > 0.0f)? 1.0f/mist_depth: 0.0f;
- kfilm->mist_falloff = mist_falloff;
-
- kfilm->cryptomatte_passes = cryptomatte_passes;
- kfilm->cryptomatte_depth = cryptomatte_depth;
-
- pass_stride = kfilm->pass_stride;
- denoising_data_offset = kfilm->pass_denoising_data;
- denoising_clean_offset = kfilm->pass_denoising_clean;
-
- need_update = false;
+ case PASS_RENDER_TIME:
+ break;
+ case PASS_CRYPTOMATTE:
+ kfilm->pass_cryptomatte = have_cryptomatte ?
+ min(kfilm->pass_cryptomatte, kfilm->pass_stride) :
+ kfilm->pass_stride;
+ have_cryptomatte = true;
+ break;
+ default:
+ assert(false);
+ break;
+ }
+
+ kfilm->pass_stride += pass.components;
+ }
+
+ kfilm->pass_denoising_data = 0;
+ kfilm->pass_denoising_clean = 0;
+ kfilm->denoising_flags = 0;
+ if (denoising_data_pass) {
+ kfilm->pass_denoising_data = kfilm->pass_stride;
+ kfilm->pass_stride += DENOISING_PASS_SIZE_BASE;
+ kfilm->denoising_flags = denoising_flags;
+ if (denoising_clean_pass) {
+ kfilm->pass_denoising_clean = kfilm->pass_stride;
+ kfilm->pass_stride += DENOISING_PASS_SIZE_CLEAN;
+ kfilm->use_light_pass = 1;
+ }
+ if (denoising_prefiltered_pass) {
+ kfilm->pass_stride += DENOISING_PASS_SIZE_PREFILTERED;
+ }
+ }
+
+ kfilm->pass_stride = align_up(kfilm->pass_stride, 4);
+ kfilm->pass_alpha_threshold = pass_alpha_threshold;
+
+ /* update filter table */
+ vector<float> table = filter_table(filter_type, filter_width);
+ scene->lookup_tables->remove_table(&filter_table_offset);
+ filter_table_offset = scene->lookup_tables->add_table(dscene, table);
+ kfilm->filter_table_offset = (int)filter_table_offset;
+
+ /* mist pass parameters */
+ kfilm->mist_start = mist_start;
+ kfilm->mist_inv_depth = (mist_depth > 0.0f) ? 1.0f / mist_depth : 0.0f;
+ kfilm->mist_falloff = mist_falloff;
+
+ kfilm->cryptomatte_passes = cryptomatte_passes;
+ kfilm->cryptomatte_depth = cryptomatte_depth;
+
+ pass_stride = kfilm->pass_stride;
+ denoising_data_offset = kfilm->pass_denoising_data;
+ denoising_clean_offset = kfilm->pass_denoising_clean;
+
+ need_update = false;
}
-void Film::device_free(Device * /*device*/,
- DeviceScene * /*dscene*/,
- Scene *scene)
+void Film::device_free(Device * /*device*/, DeviceScene * /*dscene*/, Scene *scene)
{
- scene->lookup_tables->remove_table(&filter_table_offset);
+ scene->lookup_tables->remove_table(&filter_table_offset);
}
-bool Film::modified(const Film& film)
+bool Film::modified(const Film &film)
{
- return !Node::equals(film) || !Pass::equals(passes, film.passes);
+ return !Node::equals(film) || !Pass::equals(passes, film.passes);
}
-void Film::tag_passes_update(Scene *scene, const vector<Pass>& passes_)
+void Film::tag_passes_update(Scene *scene, const vector<Pass> &passes_)
{
- if(Pass::contains(passes, PASS_UV) != Pass::contains(passes_, PASS_UV)) {
- scene->mesh_manager->tag_update(scene);
+ if (Pass::contains(passes, PASS_UV) != Pass::contains(passes_, PASS_UV)) {
+ scene->mesh_manager->tag_update(scene);
- foreach(Shader *shader, scene->shaders)
- shader->need_update_mesh = true;
- }
- else if(Pass::contains(passes, PASS_MOTION) != Pass::contains(passes_, PASS_MOTION))
- scene->mesh_manager->tag_update(scene);
+ foreach (Shader *shader, scene->shaders)
+ shader->need_update_mesh = true;
+ }
+ else if (Pass::contains(passes, PASS_MOTION) != Pass::contains(passes_, PASS_MOTION))
+ scene->mesh_manager->tag_update(scene);
- passes = passes_;
+ passes = passes_;
}
void Film::tag_update(Scene * /*scene*/)
{
- need_update = true;
+ need_update = true;
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/render/film.h b/intern/cycles/render/film.h
index 8330a4cf413..1cfa7c3b77d 100644
--- a/intern/cycles/render/film.h
+++ b/intern/cycles/render/film.h
@@ -31,69 +31,69 @@ class DeviceScene;
class Scene;
typedef enum FilterType {
- FILTER_BOX,
- FILTER_GAUSSIAN,
- FILTER_BLACKMAN_HARRIS,
+ FILTER_BOX,
+ FILTER_GAUSSIAN,
+ FILTER_BLACKMAN_HARRIS,
- FILTER_NUM_TYPES,
+ FILTER_NUM_TYPES,
} FilterType;
class Pass {
-public:
- PassType type;
- int components;
- bool filter;
- bool exposure;
- PassType divide_type;
- string name;
-
- static void add(PassType type, vector<Pass>& passes, const char* name = NULL);
- static bool equals(const vector<Pass>& A, const vector<Pass>& B);
- static bool contains(const vector<Pass>& passes, PassType);
+ public:
+ PassType type;
+ int components;
+ bool filter;
+ bool exposure;
+ PassType divide_type;
+ string name;
+
+ static void add(PassType type, vector<Pass> &passes, const char *name = NULL);
+ static bool equals(const vector<Pass> &A, const vector<Pass> &B);
+ static bool contains(const vector<Pass> &passes, PassType);
};
class Film : public Node {
-public:
- NODE_DECLARE
+ public:
+ NODE_DECLARE
- float exposure;
- vector<Pass> passes;
- bool denoising_data_pass;
- bool denoising_clean_pass;
- bool denoising_prefiltered_pass;
- int denoising_flags;
- float pass_alpha_threshold;
+ float exposure;
+ vector<Pass> passes;
+ bool denoising_data_pass;
+ bool denoising_clean_pass;
+ bool denoising_prefiltered_pass;
+ int denoising_flags;
+ float pass_alpha_threshold;
- int pass_stride;
- int denoising_data_offset;
- int denoising_clean_offset;
+ int pass_stride;
+ int denoising_data_offset;
+ int denoising_clean_offset;
- FilterType filter_type;
- float filter_width;
- size_t filter_table_offset;
+ FilterType filter_type;
+ float filter_width;
+ size_t filter_table_offset;
- float mist_start;
- float mist_depth;
- float mist_falloff;
+ float mist_start;
+ float mist_depth;
+ float mist_falloff;
- bool use_light_visibility;
- bool use_sample_clamp;
- CryptomatteType cryptomatte_passes;
- int cryptomatte_depth;
+ bool use_light_visibility;
+ bool use_sample_clamp;
+ CryptomatteType cryptomatte_passes;
+ int cryptomatte_depth;
- bool need_update;
+ bool need_update;
- Film();
- ~Film();
+ Film();
+ ~Film();
- void device_update(Device *device, DeviceScene *dscene, Scene *scene);
- void device_free(Device *device, DeviceScene *dscene, Scene *scene);
+ void device_update(Device *device, DeviceScene *dscene, Scene *scene);
+ void device_free(Device *device, DeviceScene *dscene, Scene *scene);
- bool modified(const Film& film);
- void tag_passes_update(Scene *scene, const vector<Pass>& passes_);
- void tag_update(Scene *scene);
+ bool modified(const Film &film);
+ void tag_passes_update(Scene *scene, const vector<Pass> &passes_);
+ void tag_update(Scene *scene);
};
CCL_NAMESPACE_END
-#endif /* __FILM_H__ */
+#endif /* __FILM_H__ */
diff --git a/intern/cycles/render/graph.cpp b/intern/cycles/render/graph.cpp
index eea1bed58dc..c284c64b5bf 100644
--- a/intern/cycles/render/graph.cpp
+++ b/intern/cycles/render/graph.cpp
@@ -33,388 +33,385 @@ namespace {
bool check_node_inputs_has_links(const ShaderNode *node)
{
- foreach(const ShaderInput *in, node->inputs) {
- if(in->link) {
- return true;
- }
- }
- return false;
+ foreach (const ShaderInput *in, node->inputs) {
+ if (in->link) {
+ return true;
+ }
+ }
+ return false;
}
-bool check_node_inputs_traversed(const ShaderNode *node,
- const ShaderNodeSet& done)
+bool check_node_inputs_traversed(const ShaderNode *node, const ShaderNodeSet &done)
{
- foreach(const ShaderInput *in, node->inputs) {
- if(in->link) {
- if(done.find(in->link->parent) == done.end()) {
- return false;
- }
- }
- }
- return true;
+ foreach (const ShaderInput *in, node->inputs) {
+ if (in->link) {
+ if (done.find(in->link->parent) == done.end()) {
+ return false;
+ }
+ }
+ }
+ return true;
}
-} /* namespace */
+} /* namespace */
/* Node */
-ShaderNode::ShaderNode(const NodeType *type)
-: Node(type)
+ShaderNode::ShaderNode(const NodeType *type) : Node(type)
{
- name = type->name;
- id = -1;
- bump = SHADER_BUMP_NONE;
- special_type = SHADER_SPECIAL_TYPE_NONE;
+ name = type->name;
+ id = -1;
+ bump = SHADER_BUMP_NONE;
+ special_type = SHADER_SPECIAL_TYPE_NONE;
- create_inputs_outputs(type);
+ create_inputs_outputs(type);
}
ShaderNode::~ShaderNode()
{
- foreach(ShaderInput *socket, inputs)
- delete socket;
+ foreach (ShaderInput *socket, inputs)
+ delete socket;
- foreach(ShaderOutput *socket, outputs)
- delete socket;
+ foreach (ShaderOutput *socket, outputs)
+ delete socket;
}
void ShaderNode::create_inputs_outputs(const NodeType *type)
{
- foreach(const SocketType& socket, type->inputs) {
- if(socket.flags & SocketType::LINKABLE) {
- inputs.push_back(new ShaderInput(socket, this));
- }
- }
-
- foreach(const SocketType& socket, type->outputs) {
- outputs.push_back(new ShaderOutput(socket, this));
- }
+ foreach (const SocketType &socket, type->inputs) {
+ if (socket.flags & SocketType::LINKABLE) {
+ inputs.push_back(new ShaderInput(socket, this));
+ }
+ }
+
+ foreach (const SocketType &socket, type->outputs) {
+ outputs.push_back(new ShaderOutput(socket, this));
+ }
}
ShaderInput *ShaderNode::input(const char *name)
{
- foreach(ShaderInput *socket, inputs) {
- if(socket->name() == name)
- return socket;
- }
+ foreach (ShaderInput *socket, inputs) {
+ if (socket->name() == name)
+ return socket;
+ }
- return NULL;
+ return NULL;
}
ShaderOutput *ShaderNode::output(const char *name)
{
- foreach(ShaderOutput *socket, outputs)
- if(socket->name() == name)
- return socket;
+ foreach (ShaderOutput *socket, outputs)
+ if (socket->name() == name)
+ return socket;
- return NULL;
+ return NULL;
}
ShaderInput *ShaderNode::input(ustring name)
{
- foreach(ShaderInput *socket, inputs) {
- if(socket->name() == name)
- return socket;
- }
+ foreach (ShaderInput *socket, inputs) {
+ if (socket->name() == name)
+ return socket;
+ }
- return NULL;
+ return NULL;
}
ShaderOutput *ShaderNode::output(ustring name)
{
- foreach(ShaderOutput *socket, outputs)
- if(socket->name() == name)
- return socket;
+ foreach (ShaderOutput *socket, outputs)
+ if (socket->name() == name)
+ return socket;
- return NULL;
+ return NULL;
}
void ShaderNode::attributes(Shader *shader, AttributeRequestSet *attributes)
{
- foreach(ShaderInput *input, inputs) {
- if(!input->link) {
- if(input->flags() & SocketType::LINK_TEXTURE_GENERATED) {
- if(shader->has_surface)
- attributes->add(ATTR_STD_GENERATED);
- if(shader->has_volume)
- attributes->add(ATTR_STD_GENERATED_TRANSFORM);
- }
- else if(input->flags() & SocketType::LINK_TEXTURE_UV) {
- if(shader->has_surface)
- attributes->add(ATTR_STD_UV);
- }
- }
- }
+ foreach (ShaderInput *input, inputs) {
+ if (!input->link) {
+ if (input->flags() & SocketType::LINK_TEXTURE_GENERATED) {
+ if (shader->has_surface)
+ attributes->add(ATTR_STD_GENERATED);
+ if (shader->has_volume)
+ attributes->add(ATTR_STD_GENERATED_TRANSFORM);
+ }
+ else if (input->flags() & SocketType::LINK_TEXTURE_UV) {
+ if (shader->has_surface)
+ attributes->add(ATTR_STD_UV);
+ }
+ }
+ }
}
-bool ShaderNode::equals(const ShaderNode& other)
+bool ShaderNode::equals(const ShaderNode &other)
{
- if(type != other.type || bump != other.bump) {
- return false;
- }
-
- assert(inputs.size() == other.inputs.size());
-
- /* Compare unlinkable sockets */
- foreach(const SocketType& socket, type->inputs) {
- if(!(socket.flags & SocketType::LINKABLE)) {
- if(!Node::equals_value(other, socket)) {
- return false;
- }
- }
- }
-
- /* Compare linkable input sockets */
- for(int i = 0; i < inputs.size(); ++i) {
- ShaderInput *input_a = inputs[i],
- *input_b = other.inputs[i];
- if(input_a->link == NULL && input_b->link == NULL) {
- /* Unconnected inputs are expected to have the same value. */
- if(!Node::equals_value(other, input_a->socket_type)) {
- return false;
- }
- }
- else if(input_a->link != NULL && input_b->link != NULL) {
- /* Expect links are to come from the same exact socket. */
- if(input_a->link != input_b->link) {
- return false;
- }
- }
- else {
- /* One socket has a link and another has not, inputs can't be
- * considered equal.
- */
- return false;
- }
- }
-
- return true;
+ if (type != other.type || bump != other.bump) {
+ return false;
+ }
+
+ assert(inputs.size() == other.inputs.size());
+
+ /* Compare unlinkable sockets */
+ foreach (const SocketType &socket, type->inputs) {
+ if (!(socket.flags & SocketType::LINKABLE)) {
+ if (!Node::equals_value(other, socket)) {
+ return false;
+ }
+ }
+ }
+
+ /* Compare linkable input sockets */
+ for (int i = 0; i < inputs.size(); ++i) {
+ ShaderInput *input_a = inputs[i], *input_b = other.inputs[i];
+ if (input_a->link == NULL && input_b->link == NULL) {
+ /* Unconnected inputs are expected to have the same value. */
+ if (!Node::equals_value(other, input_a->socket_type)) {
+ return false;
+ }
+ }
+ else if (input_a->link != NULL && input_b->link != NULL) {
+ /* Expect links are to come from the same exact socket. */
+ if (input_a->link != input_b->link) {
+ return false;
+ }
+ }
+ else {
+ /* One socket has a link and another has not, inputs can't be
+ * considered equal.
+ */
+ return false;
+ }
+ }
+
+ return true;
}
/* Graph */
ShaderGraph::ShaderGraph()
{
- finalized = false;
- simplified = false;
- num_node_ids = 0;
- add(new OutputNode());
+ finalized = false;
+ simplified = false;
+ num_node_ids = 0;
+ add(new OutputNode());
}
ShaderGraph::~ShaderGraph()
{
- clear_nodes();
+ clear_nodes();
}
ShaderNode *ShaderGraph::add(ShaderNode *node)
{
- assert(!finalized);
- simplified = false;
+ assert(!finalized);
+ simplified = false;
- node->id = num_node_ids++;
- nodes.push_back(node);
- return node;
+ node->id = num_node_ids++;
+ nodes.push_back(node);
+ return node;
}
OutputNode *ShaderGraph::output()
{
- return (OutputNode*)nodes.front();
+ return (OutputNode *)nodes.front();
}
void ShaderGraph::connect(ShaderOutput *from, ShaderInput *to)
{
- assert(!finalized);
- assert(from && to);
-
- if(to->link) {
- fprintf(stderr, "Cycles shader graph connect: input already connected.\n");
- return;
- }
-
- if(from->type() != to->type()) {
- /* can't do automatic conversion from closure */
- if(from->type() == SocketType::CLOSURE) {
- fprintf(stderr, "Cycles shader graph connect: can only connect closure to closure "
- "(%s.%s to %s.%s).\n",
- from->parent->name.c_str(), from->name().c_str(),
- to->parent->name.c_str(), to->name().c_str());
- return;
- }
-
- /* add automatic conversion node in case of type mismatch */
- ShaderNode *convert;
- ShaderInput *convert_in;
-
- if(to->type() == SocketType::CLOSURE) {
- EmissionNode *emission = new EmissionNode();
- emission->color = make_float3(1.0f, 1.0f, 1.0f);
- emission->strength = 1.0f;
- convert = add(emission);
- /* Connect float inputs to Strength to save an additional Falue->Color conversion. */
- if(from->type() == SocketType::FLOAT) {
- convert_in = convert->input("Strength");
- }
- else {
- convert_in = convert->input("Color");
- }
- }
- else {
- convert = add(new ConvertNode(from->type(), to->type(), true));
- convert_in = convert->inputs[0];
- }
-
- connect(from, convert_in);
- connect(convert->outputs[0], to);
- }
- else {
- /* types match, just connect */
- to->link = from;
- from->links.push_back(to);
- }
+ assert(!finalized);
+ assert(from && to);
+
+ if (to->link) {
+ fprintf(stderr, "Cycles shader graph connect: input already connected.\n");
+ return;
+ }
+
+ if (from->type() != to->type()) {
+ /* can't do automatic conversion from closure */
+ if (from->type() == SocketType::CLOSURE) {
+ fprintf(stderr,
+ "Cycles shader graph connect: can only connect closure to closure "
+ "(%s.%s to %s.%s).\n",
+ from->parent->name.c_str(),
+ from->name().c_str(),
+ to->parent->name.c_str(),
+ to->name().c_str());
+ return;
+ }
+
+ /* add automatic conversion node in case of type mismatch */
+ ShaderNode *convert;
+ ShaderInput *convert_in;
+
+ if (to->type() == SocketType::CLOSURE) {
+ EmissionNode *emission = new EmissionNode();
+ emission->color = make_float3(1.0f, 1.0f, 1.0f);
+ emission->strength = 1.0f;
+ convert = add(emission);
+ /* Connect float inputs to Strength to save an additional Falue->Color conversion. */
+ if (from->type() == SocketType::FLOAT) {
+ convert_in = convert->input("Strength");
+ }
+ else {
+ convert_in = convert->input("Color");
+ }
+ }
+ else {
+ convert = add(new ConvertNode(from->type(), to->type(), true));
+ convert_in = convert->inputs[0];
+ }
+
+ connect(from, convert_in);
+ connect(convert->outputs[0], to);
+ }
+ else {
+ /* types match, just connect */
+ to->link = from;
+ from->links.push_back(to);
+ }
}
void ShaderGraph::disconnect(ShaderOutput *from)
{
- assert(!finalized);
- simplified = false;
+ assert(!finalized);
+ simplified = false;
- foreach(ShaderInput *sock, from->links) {
- sock->link = NULL;
- }
+ foreach (ShaderInput *sock, from->links) {
+ sock->link = NULL;
+ }
- from->links.clear();
+ from->links.clear();
}
void ShaderGraph::disconnect(ShaderInput *to)
{
- assert(!finalized);
- assert(to->link);
- simplified = false;
+ assert(!finalized);
+ assert(to->link);
+ simplified = false;
- ShaderOutput *from = to->link;
+ ShaderOutput *from = to->link;
- to->link = NULL;
- from->links.erase(remove(from->links.begin(), from->links.end(), to), from->links.end());
+ to->link = NULL;
+ from->links.erase(remove(from->links.begin(), from->links.end(), to), from->links.end());
}
void ShaderGraph::relink(ShaderNode *node, ShaderOutput *from, ShaderOutput *to)
{
- simplified = false;
-
- /* Copy because disconnect modifies this list */
- vector<ShaderInput*> outputs = from->links;
-
- /* Bypass node by moving all links from "from" to "to" */
- foreach(ShaderInput *sock, node->inputs) {
- if(sock->link)
- disconnect(sock);
- }
-
- foreach(ShaderInput *sock, outputs) {
- disconnect(sock);
- if(to)
- connect(to, sock);
- }
+ simplified = false;
+
+ /* Copy because disconnect modifies this list */
+ vector<ShaderInput *> outputs = from->links;
+
+ /* Bypass node by moving all links from "from" to "to" */
+ foreach (ShaderInput *sock, node->inputs) {
+ if (sock->link)
+ disconnect(sock);
+ }
+
+ foreach (ShaderInput *sock, outputs) {
+ disconnect(sock);
+ if (to)
+ connect(to, sock);
+ }
}
void ShaderGraph::simplify(Scene *scene)
{
- if(!simplified) {
- default_inputs(scene->shader_manager->use_osl());
- clean(scene);
- refine_bump_nodes();
+ if (!simplified) {
+ default_inputs(scene->shader_manager->use_osl());
+ clean(scene);
+ refine_bump_nodes();
- simplified = true;
- }
+ simplified = true;
+ }
}
-void ShaderGraph::finalize(Scene *scene,
- bool do_bump,
- bool do_simplify,
- bool bump_in_object_space)
+void ShaderGraph::finalize(Scene *scene, bool do_bump, bool do_simplify, bool bump_in_object_space)
{
- /* before compiling, the shader graph may undergo a number of modifications.
- * currently we set default geometry shader inputs, and create automatic bump
- * from displacement. a graph can be finalized only once, and should not be
- * modified afterwards. */
+ /* before compiling, the shader graph may undergo a number of modifications.
+ * currently we set default geometry shader inputs, and create automatic bump
+ * from displacement. a graph can be finalized only once, and should not be
+ * modified afterwards. */
- if(!finalized) {
- simplify(scene);
+ if (!finalized) {
+ simplify(scene);
- if(do_bump)
- bump_from_displacement(bump_in_object_space);
+ if (do_bump)
+ bump_from_displacement(bump_in_object_space);
- ShaderInput *surface_in = output()->input("Surface");
- ShaderInput *volume_in = output()->input("Volume");
+ ShaderInput *surface_in = output()->input("Surface");
+ ShaderInput *volume_in = output()->input("Volume");
- /* todo: make this work when surface and volume closures are tangled up */
+ /* todo: make this work when surface and volume closures are tangled up */
- if(surface_in->link)
- transform_multi_closure(surface_in->link->parent, NULL, false);
- if(volume_in->link)
- transform_multi_closure(volume_in->link->parent, NULL, true);
+ if (surface_in->link)
+ transform_multi_closure(surface_in->link->parent, NULL, false);
+ if (volume_in->link)
+ transform_multi_closure(volume_in->link->parent, NULL, true);
- finalized = true;
- }
- else if(do_simplify) {
- simplify_settings(scene);
- }
+ finalized = true;
+ }
+ else if (do_simplify) {
+ simplify_settings(scene);
+ }
}
-void ShaderGraph::find_dependencies(ShaderNodeSet& dependencies, ShaderInput *input)
+void ShaderGraph::find_dependencies(ShaderNodeSet &dependencies, ShaderInput *input)
{
- /* find all nodes that this input depends on directly and indirectly */
- ShaderNode *node = (input->link)? input->link->parent: NULL;
+ /* find all nodes that this input depends on directly and indirectly */
+ ShaderNode *node = (input->link) ? input->link->parent : NULL;
- if(node != NULL && dependencies.find(node) == dependencies.end()) {
- foreach(ShaderInput *in, node->inputs)
- find_dependencies(dependencies, in);
+ if (node != NULL && dependencies.find(node) == dependencies.end()) {
+ foreach (ShaderInput *in, node->inputs)
+ find_dependencies(dependencies, in);
- dependencies.insert(node);
- }
+ dependencies.insert(node);
+ }
}
void ShaderGraph::clear_nodes()
{
- foreach(ShaderNode *node, nodes) {
- delete node;
- }
- nodes.clear();
+ foreach (ShaderNode *node, nodes) {
+ delete node;
+ }
+ nodes.clear();
}
-void ShaderGraph::copy_nodes(ShaderNodeSet& nodes, ShaderNodeMap& nnodemap)
+void ShaderGraph::copy_nodes(ShaderNodeSet &nodes, ShaderNodeMap &nnodemap)
{
- /* copy a set of nodes, and the links between them. the assumption is
- * made that all nodes that inputs are linked to are in the set too. */
-
- /* copy nodes */
- foreach(ShaderNode *node, nodes) {
- ShaderNode *nnode = node->clone();
- nnodemap[node] = nnode;
-
- /* create new inputs and outputs to recreate links and ensure
- * that we still point to valid SocketType if the NodeType
- * changed in cloning, as it does for OSL nodes */
- nnode->inputs.clear();
- nnode->outputs.clear();
- nnode->create_inputs_outputs(nnode->type);
- }
-
- /* recreate links */
- foreach(ShaderNode *node, nodes) {
- foreach(ShaderInput *input, node->inputs) {
- if(input->link) {
- /* find new input and output */
- ShaderNode *nfrom = nnodemap[input->link->parent];
- ShaderNode *nto = nnodemap[input->parent];
- ShaderOutput *noutput = nfrom->output(input->link->name());
- ShaderInput *ninput = nto->input(input->name());
-
- /* connect */
- connect(noutput, ninput);
- }
- }
- }
+ /* copy a set of nodes, and the links between them. the assumption is
+ * made that all nodes that inputs are linked to are in the set too. */
+
+ /* copy nodes */
+ foreach (ShaderNode *node, nodes) {
+ ShaderNode *nnode = node->clone();
+ nnodemap[node] = nnode;
+
+ /* create new inputs and outputs to recreate links and ensure
+ * that we still point to valid SocketType if the NodeType
+ * changed in cloning, as it does for OSL nodes */
+ nnode->inputs.clear();
+ nnode->outputs.clear();
+ nnode->create_inputs_outputs(nnode->type);
+ }
+
+ /* recreate links */
+ foreach (ShaderNode *node, nodes) {
+ foreach (ShaderInput *input, node->inputs) {
+ if (input->link) {
+ /* find new input and output */
+ ShaderNode *nfrom = nnodemap[input->link->parent];
+ ShaderNode *nto = nnodemap[input->parent];
+ ShaderOutput *noutput = nfrom->output(input->link->name());
+ ShaderInput *ninput = nto->input(input->name());
+
+ /* connect */
+ connect(noutput, ninput);
+ }
+ }
+ }
}
/* Graph simplification */
@@ -427,68 +424,68 @@ void ShaderGraph::copy_nodes(ShaderNodeSet& nodes, ShaderNodeMap& nnodemap)
*/
void ShaderGraph::remove_proxy_nodes()
{
- vector<bool> removed(num_node_ids, false);
- bool any_node_removed = false;
-
- foreach(ShaderNode *node, nodes) {
- if(node->special_type == SHADER_SPECIAL_TYPE_PROXY) {
- ConvertNode *proxy = static_cast<ConvertNode*>(node);
- ShaderInput *input = proxy->inputs[0];
- ShaderOutput *output = proxy->outputs[0];
-
- /* bypass the proxy node */
- if(input->link) {
- relink(proxy, output, input->link);
- }
- else {
- /* Copy because disconnect modifies this list */
- vector<ShaderInput*> links(output->links);
-
- foreach(ShaderInput *to, links) {
- /* remove any autoconvert nodes too if they lead to
- * sockets with an automatically set default value */
- ShaderNode *tonode = to->parent;
-
- if(tonode->special_type == SHADER_SPECIAL_TYPE_AUTOCONVERT) {
- bool all_links_removed = true;
- vector<ShaderInput*> links = tonode->outputs[0]->links;
-
- foreach(ShaderInput *autoin, links) {
- if(autoin->flags() & SocketType::DEFAULT_LINK_MASK)
- disconnect(autoin);
- else
- all_links_removed = false;
- }
-
- if(all_links_removed)
- removed[tonode->id] = true;
- }
-
- disconnect(to);
-
- /* transfer the default input value to the target socket */
- tonode->copy_value(to->socket_type, *proxy, input->socket_type);
- }
- }
-
- removed[proxy->id] = true;
- any_node_removed = true;
- }
- }
-
- /* remove nodes */
- if(any_node_removed) {
- list<ShaderNode*> newnodes;
-
- foreach(ShaderNode *node, nodes) {
- if(!removed[node->id])
- newnodes.push_back(node);
- else
- delete node;
- }
-
- nodes = newnodes;
- }
+ vector<bool> removed(num_node_ids, false);
+ bool any_node_removed = false;
+
+ foreach (ShaderNode *node, nodes) {
+ if (node->special_type == SHADER_SPECIAL_TYPE_PROXY) {
+ ConvertNode *proxy = static_cast<ConvertNode *>(node);
+ ShaderInput *input = proxy->inputs[0];
+ ShaderOutput *output = proxy->outputs[0];
+
+ /* bypass the proxy node */
+ if (input->link) {
+ relink(proxy, output, input->link);
+ }
+ else {
+ /* Copy because disconnect modifies this list */
+ vector<ShaderInput *> links(output->links);
+
+ foreach (ShaderInput *to, links) {
+ /* remove any autoconvert nodes too if they lead to
+ * sockets with an automatically set default value */
+ ShaderNode *tonode = to->parent;
+
+ if (tonode->special_type == SHADER_SPECIAL_TYPE_AUTOCONVERT) {
+ bool all_links_removed = true;
+ vector<ShaderInput *> links = tonode->outputs[0]->links;
+
+ foreach (ShaderInput *autoin, links) {
+ if (autoin->flags() & SocketType::DEFAULT_LINK_MASK)
+ disconnect(autoin);
+ else
+ all_links_removed = false;
+ }
+
+ if (all_links_removed)
+ removed[tonode->id] = true;
+ }
+
+ disconnect(to);
+
+ /* transfer the default input value to the target socket */
+ tonode->copy_value(to->socket_type, *proxy, input->socket_type);
+ }
+ }
+
+ removed[proxy->id] = true;
+ any_node_removed = true;
+ }
+ }
+
+ /* remove nodes */
+ if (any_node_removed) {
+ list<ShaderNode *> newnodes;
+
+ foreach (ShaderNode *node, nodes) {
+ if (!removed[node->id])
+ newnodes.push_back(node);
+ else
+ delete node;
+ }
+
+ nodes = newnodes;
+ }
}
/* Constant folding.
@@ -498,143 +495,143 @@ void ShaderGraph::remove_proxy_nodes()
*/
void ShaderGraph::constant_fold(Scene *scene)
{
- ShaderNodeSet done, scheduled;
- queue<ShaderNode*> traverse_queue;
-
- bool has_displacement = (output()->input("Displacement")->link != NULL);
-
- /* Schedule nodes which doesn't have any dependencies. */
- foreach(ShaderNode *node, nodes) {
- if(!check_node_inputs_has_links(node)) {
- traverse_queue.push(node);
- scheduled.insert(node);
- }
- }
-
- while(!traverse_queue.empty()) {
- ShaderNode *node = traverse_queue.front();
- traverse_queue.pop();
- done.insert(node);
- foreach(ShaderOutput *output, node->outputs) {
- if(output->links.size() == 0) {
- continue;
- }
- /* Schedule node which was depending on the value,
- * when possible. Do it before disconnect.
- */
- foreach(ShaderInput *input, output->links) {
- if(scheduled.find(input->parent) != scheduled.end()) {
- /* Node might not be optimized yet but scheduled already
- * by other dependencies. No need to re-schedule it.
- */
- continue;
- }
- /* Schedule node if its inputs are fully done. */
- if(check_node_inputs_traversed(input->parent, done)) {
- traverse_queue.push(input->parent);
- scheduled.insert(input->parent);
- }
- }
- /* Optimize current node. */
- ConstantFolder folder(this, node, output, scene);
- node->constant_fold(folder);
- }
- }
-
- /* Folding might have removed all nodes connected to the displacement output
- * even tho there is displacement to be applied, so add in a value node if
- * that happens to ensure there is still a valid graph for displacement.
- */
- if(has_displacement && !output()->input("Displacement")->link) {
- ColorNode *value = (ColorNode*)add(new ColorNode());
- value->value = output()->displacement;
-
- connect(value->output("Color"), output()->input("Displacement"));
- }
+ ShaderNodeSet done, scheduled;
+ queue<ShaderNode *> traverse_queue;
+
+ bool has_displacement = (output()->input("Displacement")->link != NULL);
+
+ /* Schedule nodes which doesn't have any dependencies. */
+ foreach (ShaderNode *node, nodes) {
+ if (!check_node_inputs_has_links(node)) {
+ traverse_queue.push(node);
+ scheduled.insert(node);
+ }
+ }
+
+ while (!traverse_queue.empty()) {
+ ShaderNode *node = traverse_queue.front();
+ traverse_queue.pop();
+ done.insert(node);
+ foreach (ShaderOutput *output, node->outputs) {
+ if (output->links.size() == 0) {
+ continue;
+ }
+ /* Schedule node which was depending on the value,
+ * when possible. Do it before disconnect.
+ */
+ foreach (ShaderInput *input, output->links) {
+ if (scheduled.find(input->parent) != scheduled.end()) {
+ /* Node might not be optimized yet but scheduled already
+ * by other dependencies. No need to re-schedule it.
+ */
+ continue;
+ }
+ /* Schedule node if its inputs are fully done. */
+ if (check_node_inputs_traversed(input->parent, done)) {
+ traverse_queue.push(input->parent);
+ scheduled.insert(input->parent);
+ }
+ }
+ /* Optimize current node. */
+ ConstantFolder folder(this, node, output, scene);
+ node->constant_fold(folder);
+ }
+ }
+
+ /* Folding might have removed all nodes connected to the displacement output
+ * even tho there is displacement to be applied, so add in a value node if
+ * that happens to ensure there is still a valid graph for displacement.
+ */
+ if (has_displacement && !output()->input("Displacement")->link) {
+ ColorNode *value = (ColorNode *)add(new ColorNode());
+ value->value = output()->displacement;
+
+ connect(value->output("Color"), output()->input("Displacement"));
+ }
}
/* Simplification. */
void ShaderGraph::simplify_settings(Scene *scene)
{
- foreach(ShaderNode *node, nodes) {
- node->simplify_settings(scene);
- }
+ foreach (ShaderNode *node, nodes) {
+ node->simplify_settings(scene);
+ }
}
/* Deduplicate nodes with same settings. */
void ShaderGraph::deduplicate_nodes()
{
- /* NOTES:
- * - Deduplication happens for nodes which has same exact settings and same
- * exact input links configuration (either connected to same output or has
- * the same exact default value).
- * - Deduplication happens in the bottom-top manner, so we know for fact that
- * all traversed nodes are either can not be deduplicated at all or were
- * already deduplicated.
- */
-
- ShaderNodeSet scheduled, done;
- map<ustring, ShaderNodeSet> candidates;
- queue<ShaderNode*> traverse_queue;
- int num_deduplicated = 0;
-
- /* Schedule nodes which doesn't have any dependencies. */
- foreach(ShaderNode *node, nodes) {
- if(!check_node_inputs_has_links(node)) {
- traverse_queue.push(node);
- scheduled.insert(node);
- }
- }
-
- while(!traverse_queue.empty()) {
- ShaderNode *node = traverse_queue.front();
- traverse_queue.pop();
- done.insert(node);
- /* Schedule the nodes which were depending on the current node. */
- bool has_output_links = false;
- foreach(ShaderOutput *output, node->outputs) {
- foreach(ShaderInput *input, output->links) {
- has_output_links = true;
- if(scheduled.find(input->parent) != scheduled.end()) {
- /* Node might not be optimized yet but scheduled already
- * by other dependencies. No need to re-schedule it.
- */
- continue;
- }
- /* Schedule node if its inputs are fully done. */
- if(check_node_inputs_traversed(input->parent, done)) {
- traverse_queue.push(input->parent);
- scheduled.insert(input->parent);
- }
- }
- }
- /* Only need to care about nodes that are actually used */
- if(!has_output_links) {
- continue;
- }
- /* Try to merge this node with another one. */
- ShaderNode *merge_with = NULL;
- foreach(ShaderNode *other_node, candidates[node->type->name]) {
- if(node != other_node && node->equals(*other_node)) {
- merge_with = other_node;
- break;
- }
- }
- /* If found an equivalent, merge; otherwise keep node for later merges */
- if(merge_with != NULL) {
- for(int i = 0; i < node->outputs.size(); ++i) {
- relink(node, node->outputs[i], merge_with->outputs[i]);
- }
- num_deduplicated++;
- }
- else {
- candidates[node->type->name].insert(node);
- }
- }
-
- if(num_deduplicated > 0) {
- VLOG(1) << "Deduplicated " << num_deduplicated << " nodes.";
- }
+ /* NOTES:
+ * - Deduplication happens for nodes which has same exact settings and same
+ * exact input links configuration (either connected to same output or has
+ * the same exact default value).
+ * - Deduplication happens in the bottom-top manner, so we know for fact that
+ * all traversed nodes are either can not be deduplicated at all or were
+ * already deduplicated.
+ */
+
+ ShaderNodeSet scheduled, done;
+ map<ustring, ShaderNodeSet> candidates;
+ queue<ShaderNode *> traverse_queue;
+ int num_deduplicated = 0;
+
+ /* Schedule nodes which doesn't have any dependencies. */
+ foreach (ShaderNode *node, nodes) {
+ if (!check_node_inputs_has_links(node)) {
+ traverse_queue.push(node);
+ scheduled.insert(node);
+ }
+ }
+
+ while (!traverse_queue.empty()) {
+ ShaderNode *node = traverse_queue.front();
+ traverse_queue.pop();
+ done.insert(node);
+ /* Schedule the nodes which were depending on the current node. */
+ bool has_output_links = false;
+ foreach (ShaderOutput *output, node->outputs) {
+ foreach (ShaderInput *input, output->links) {
+ has_output_links = true;
+ if (scheduled.find(input->parent) != scheduled.end()) {
+ /* Node might not be optimized yet but scheduled already
+ * by other dependencies. No need to re-schedule it.
+ */
+ continue;
+ }
+ /* Schedule node if its inputs are fully done. */
+ if (check_node_inputs_traversed(input->parent, done)) {
+ traverse_queue.push(input->parent);
+ scheduled.insert(input->parent);
+ }
+ }
+ }
+ /* Only need to care about nodes that are actually used */
+ if (!has_output_links) {
+ continue;
+ }
+ /* Try to merge this node with another one. */
+ ShaderNode *merge_with = NULL;
+ foreach (ShaderNode *other_node, candidates[node->type->name]) {
+ if (node != other_node && node->equals(*other_node)) {
+ merge_with = other_node;
+ break;
+ }
+ }
+ /* If found an equivalent, merge; otherwise keep node for later merges */
+ if (merge_with != NULL) {
+ for (int i = 0; i < node->outputs.size(); ++i) {
+ relink(node, node->outputs[i], merge_with->outputs[i]);
+ }
+ num_deduplicated++;
+ }
+ else {
+ candidates[node->type->name].insert(node);
+ }
+ }
+
+ if (num_deduplicated > 0) {
+ VLOG(1) << "Deduplicated " << num_deduplicated << " nodes.";
+ }
}
/* Check whether volume output has meaningful nodes, otherwise
@@ -642,535 +639,536 @@ void ShaderGraph::deduplicate_nodes()
*/
void ShaderGraph::verify_volume_output()
{
- /* Check whether we can optimize the whole volume graph out. */
- ShaderInput *volume_in = output()->input("Volume");
- if(volume_in->link == NULL) {
- return;
- }
- bool has_valid_volume = false;
- ShaderNodeSet scheduled;
- queue<ShaderNode*> traverse_queue;
- /* Schedule volume output. */
- traverse_queue.push(volume_in->link->parent);
- scheduled.insert(volume_in->link->parent);
- /* Traverse down the tree. */
- while(!traverse_queue.empty()) {
- ShaderNode *node = traverse_queue.front();
- traverse_queue.pop();
- /* Node is fully valid for volume, can't optimize anything out. */
- if(node->has_volume_support()) {
- has_valid_volume = true;
- break;
- }
- foreach(ShaderInput *input, node->inputs) {
- if(input->link == NULL) {
- continue;
- }
- if(scheduled.find(input->link->parent) != scheduled.end()) {
- continue;
- }
- traverse_queue.push(input->link->parent);
- scheduled.insert(input->link->parent);
- }
- }
- if(!has_valid_volume) {
- VLOG(1) << "Disconnect meaningless volume output.";
- disconnect(volume_in->link);
- }
+ /* Check whether we can optimize the whole volume graph out. */
+ ShaderInput *volume_in = output()->input("Volume");
+ if (volume_in->link == NULL) {
+ return;
+ }
+ bool has_valid_volume = false;
+ ShaderNodeSet scheduled;
+ queue<ShaderNode *> traverse_queue;
+ /* Schedule volume output. */
+ traverse_queue.push(volume_in->link->parent);
+ scheduled.insert(volume_in->link->parent);
+ /* Traverse down the tree. */
+ while (!traverse_queue.empty()) {
+ ShaderNode *node = traverse_queue.front();
+ traverse_queue.pop();
+ /* Node is fully valid for volume, can't optimize anything out. */
+ if (node->has_volume_support()) {
+ has_valid_volume = true;
+ break;
+ }
+ foreach (ShaderInput *input, node->inputs) {
+ if (input->link == NULL) {
+ continue;
+ }
+ if (scheduled.find(input->link->parent) != scheduled.end()) {
+ continue;
+ }
+ traverse_queue.push(input->link->parent);
+ scheduled.insert(input->link->parent);
+ }
+ }
+ if (!has_valid_volume) {
+ VLOG(1) << "Disconnect meaningless volume output.";
+ disconnect(volume_in->link);
+ }
}
-void ShaderGraph::break_cycles(ShaderNode *node, vector<bool>& visited, vector<bool>& on_stack)
+void ShaderGraph::break_cycles(ShaderNode *node, vector<bool> &visited, vector<bool> &on_stack)
{
- visited[node->id] = true;
- on_stack[node->id] = true;
-
- foreach(ShaderInput *input, node->inputs) {
- if(input->link) {
- ShaderNode *depnode = input->link->parent;
-
- if(on_stack[depnode->id]) {
- /* break cycle */
- disconnect(input);
- fprintf(stderr, "Cycles shader graph: detected cycle in graph, connection removed.\n");
- }
- else if(!visited[depnode->id]) {
- /* visit dependencies */
- break_cycles(depnode, visited, on_stack);
- }
- }
- }
-
- on_stack[node->id] = false;
+ visited[node->id] = true;
+ on_stack[node->id] = true;
+
+ foreach (ShaderInput *input, node->inputs) {
+ if (input->link) {
+ ShaderNode *depnode = input->link->parent;
+
+ if (on_stack[depnode->id]) {
+ /* break cycle */
+ disconnect(input);
+ fprintf(stderr, "Cycles shader graph: detected cycle in graph, connection removed.\n");
+ }
+ else if (!visited[depnode->id]) {
+ /* visit dependencies */
+ break_cycles(depnode, visited, on_stack);
+ }
+ }
+ }
+
+ on_stack[node->id] = false;
}
void ShaderGraph::compute_displacement_hash()
{
- /* Compute hash of all nodes linked to displacement, to detect if we need
- * to recompute displacement when shader nodes change. */
- ShaderInput *displacement_in = output()->input("Displacement");
-
- if(!displacement_in->link) {
- displacement_hash = "";
- return;
- }
-
- ShaderNodeSet nodes_displace;
- find_dependencies(nodes_displace, displacement_in);
-
- MD5Hash md5;
- foreach(ShaderNode *node, nodes_displace) {
- node->hash(md5);
- foreach(ShaderInput *input, node->inputs) {
- int link_id = (input->link) ? input->link->parent->id : 0;
- md5.append((uint8_t*)&link_id, sizeof(link_id));
- }
- }
-
- displacement_hash = md5.get_hex();
+ /* Compute hash of all nodes linked to displacement, to detect if we need
+ * to recompute displacement when shader nodes change. */
+ ShaderInput *displacement_in = output()->input("Displacement");
+
+ if (!displacement_in->link) {
+ displacement_hash = "";
+ return;
+ }
+
+ ShaderNodeSet nodes_displace;
+ find_dependencies(nodes_displace, displacement_in);
+
+ MD5Hash md5;
+ foreach (ShaderNode *node, nodes_displace) {
+ node->hash(md5);
+ foreach (ShaderInput *input, node->inputs) {
+ int link_id = (input->link) ? input->link->parent->id : 0;
+ md5.append((uint8_t *)&link_id, sizeof(link_id));
+ }
+ }
+
+ displacement_hash = md5.get_hex();
}
void ShaderGraph::clean(Scene *scene)
{
- /* Graph simplification */
-
- /* NOTE: Remove proxy nodes was already done. */
- constant_fold(scene);
- simplify_settings(scene);
- deduplicate_nodes();
- verify_volume_output();
-
- /* we do two things here: find cycles and break them, and remove unused
- * nodes that don't feed into the output. how cycles are broken is
- * undefined, they are invalid input, the important thing is to not crash */
-
- vector<bool> visited(num_node_ids, false);
- vector<bool> on_stack(num_node_ids, false);
-
- /* break cycles */
- break_cycles(output(), visited, on_stack);
-
- /* disconnect unused nodes */
- foreach(ShaderNode *node, nodes) {
- if(!visited[node->id]) {
- foreach(ShaderInput *to, node->inputs) {
- ShaderOutput *from = to->link;
-
- if(from) {
- to->link = NULL;
- from->links.erase(remove(from->links.begin(), from->links.end(), to), from->links.end());
- }
- }
- }
- }
-
- /* remove unused nodes */
- list<ShaderNode*> newnodes;
-
- foreach(ShaderNode *node, nodes) {
- if(visited[node->id])
- newnodes.push_back(node);
- else
- delete node;
- }
-
- nodes = newnodes;
+ /* Graph simplification */
+
+ /* NOTE: Remove proxy nodes was already done. */
+ constant_fold(scene);
+ simplify_settings(scene);
+ deduplicate_nodes();
+ verify_volume_output();
+
+ /* we do two things here: find cycles and break them, and remove unused
+ * nodes that don't feed into the output. how cycles are broken is
+ * undefined, they are invalid input, the important thing is to not crash */
+
+ vector<bool> visited(num_node_ids, false);
+ vector<bool> on_stack(num_node_ids, false);
+
+ /* break cycles */
+ break_cycles(output(), visited, on_stack);
+
+ /* disconnect unused nodes */
+ foreach (ShaderNode *node, nodes) {
+ if (!visited[node->id]) {
+ foreach (ShaderInput *to, node->inputs) {
+ ShaderOutput *from = to->link;
+
+ if (from) {
+ to->link = NULL;
+ from->links.erase(remove(from->links.begin(), from->links.end(), to), from->links.end());
+ }
+ }
+ }
+ }
+
+ /* remove unused nodes */
+ list<ShaderNode *> newnodes;
+
+ foreach (ShaderNode *node, nodes) {
+ if (visited[node->id])
+ newnodes.push_back(node);
+ else
+ delete node;
+ }
+
+ nodes = newnodes;
}
void ShaderGraph::default_inputs(bool do_osl)
{
- /* nodes can specify default texture coordinates, for now we give
- * everything the position by default, except for the sky texture */
-
- ShaderNode *geom = NULL;
- ShaderNode *texco = NULL;
-
- foreach(ShaderNode *node, nodes) {
- foreach(ShaderInput *input, node->inputs) {
- if(!input->link && (!(input->flags() & SocketType::OSL_INTERNAL) || do_osl)) {
- if(input->flags() & SocketType::LINK_TEXTURE_GENERATED) {
- if(!texco)
- texco = new TextureCoordinateNode();
-
- connect(texco->output("Generated"), input);
- }
- if(input->flags() & SocketType::LINK_TEXTURE_NORMAL) {
- if(!texco)
- texco = new TextureCoordinateNode();
-
- connect(texco->output("Normal"), input);
- }
- else if(input->flags() & SocketType::LINK_TEXTURE_UV) {
- if(!texco)
- texco = new TextureCoordinateNode();
-
- connect(texco->output("UV"), input);
- }
- else if(input->flags() & SocketType::LINK_INCOMING) {
- if(!geom)
- geom = new GeometryNode();
-
- connect(geom->output("Incoming"), input);
- }
- else if(input->flags() & SocketType::LINK_NORMAL) {
- if(!geom)
- geom = new GeometryNode();
-
- connect(geom->output("Normal"), input);
- }
- else if(input->flags() & SocketType::LINK_POSITION) {
- if(!geom)
- geom = new GeometryNode();
-
- connect(geom->output("Position"), input);
- }
- else if(input->flags() & SocketType::LINK_TANGENT) {
- if(!geom)
- geom = new GeometryNode();
-
- connect(geom->output("Tangent"), input);
- }
- }
- }
- }
-
- if(geom)
- add(geom);
- if(texco)
- add(texco);
+ /* nodes can specify default texture coordinates, for now we give
+ * everything the position by default, except for the sky texture */
+
+ ShaderNode *geom = NULL;
+ ShaderNode *texco = NULL;
+
+ foreach (ShaderNode *node, nodes) {
+ foreach (ShaderInput *input, node->inputs) {
+ if (!input->link && (!(input->flags() & SocketType::OSL_INTERNAL) || do_osl)) {
+ if (input->flags() & SocketType::LINK_TEXTURE_GENERATED) {
+ if (!texco)
+ texco = new TextureCoordinateNode();
+
+ connect(texco->output("Generated"), input);
+ }
+ if (input->flags() & SocketType::LINK_TEXTURE_NORMAL) {
+ if (!texco)
+ texco = new TextureCoordinateNode();
+
+ connect(texco->output("Normal"), input);
+ }
+ else if (input->flags() & SocketType::LINK_TEXTURE_UV) {
+ if (!texco)
+ texco = new TextureCoordinateNode();
+
+ connect(texco->output("UV"), input);
+ }
+ else if (input->flags() & SocketType::LINK_INCOMING) {
+ if (!geom)
+ geom = new GeometryNode();
+
+ connect(geom->output("Incoming"), input);
+ }
+ else if (input->flags() & SocketType::LINK_NORMAL) {
+ if (!geom)
+ geom = new GeometryNode();
+
+ connect(geom->output("Normal"), input);
+ }
+ else if (input->flags() & SocketType::LINK_POSITION) {
+ if (!geom)
+ geom = new GeometryNode();
+
+ connect(geom->output("Position"), input);
+ }
+ else if (input->flags() & SocketType::LINK_TANGENT) {
+ if (!geom)
+ geom = new GeometryNode();
+
+ connect(geom->output("Tangent"), input);
+ }
+ }
+ }
+ }
+
+ if (geom)
+ add(geom);
+ if (texco)
+ add(texco);
}
void ShaderGraph::refine_bump_nodes()
{
- /* we transverse the node graph looking for bump nodes, when we find them,
- * like in bump_from_displacement(), we copy the sub-graph defined from "bump"
- * input to the inputs "center","dx" and "dy" What is in "bump" input is moved
- * to "center" input. */
-
- foreach(ShaderNode *node, nodes) {
- if(node->special_type == SHADER_SPECIAL_TYPE_BUMP && node->input("Height")->link) {
- ShaderInput *bump_input = node->input("Height");
- ShaderNodeSet nodes_bump;
-
- /* make 2 extra copies of the subgraph defined in Bump input */
- ShaderNodeMap nodes_dx;
- ShaderNodeMap nodes_dy;
-
- /* find dependencies for the given input */
- find_dependencies(nodes_bump, bump_input);
-
- copy_nodes(nodes_bump, nodes_dx);
- copy_nodes(nodes_bump, nodes_dy);
-
- /* mark nodes to indicate they are use for bump computation, so
- that any texture coordinates are shifted by dx/dy when sampling */
- foreach(ShaderNode *node, nodes_bump)
- node->bump = SHADER_BUMP_CENTER;
- foreach(NodePair& pair, nodes_dx)
- pair.second->bump = SHADER_BUMP_DX;
- foreach(NodePair& pair, nodes_dy)
- pair.second->bump = SHADER_BUMP_DY;
-
- ShaderOutput *out = bump_input->link;
- ShaderOutput *out_dx = nodes_dx[out->parent]->output(out->name());
- ShaderOutput *out_dy = nodes_dy[out->parent]->output(out->name());
-
- connect(out_dx, node->input("SampleX"));
- connect(out_dy, node->input("SampleY"));
-
- /* add generated nodes */
- foreach(NodePair& pair, nodes_dx)
- add(pair.second);
- foreach(NodePair& pair, nodes_dy)
- add(pair.second);
-
- /* connect what is connected is bump to samplecenter input*/
- connect(out , node->input("SampleCenter"));
-
- /* bump input is just for connectivity purpose for the graph input,
- * we re-connected this input to samplecenter, so lets disconnect it
- * from bump input */
- disconnect(bump_input);
- }
- }
+ /* we transverse the node graph looking for bump nodes, when we find them,
+ * like in bump_from_displacement(), we copy the sub-graph defined from "bump"
+ * input to the inputs "center","dx" and "dy" What is in "bump" input is moved
+ * to "center" input. */
+
+ foreach (ShaderNode *node, nodes) {
+ if (node->special_type == SHADER_SPECIAL_TYPE_BUMP && node->input("Height")->link) {
+ ShaderInput *bump_input = node->input("Height");
+ ShaderNodeSet nodes_bump;
+
+ /* make 2 extra copies of the subgraph defined in Bump input */
+ ShaderNodeMap nodes_dx;
+ ShaderNodeMap nodes_dy;
+
+ /* find dependencies for the given input */
+ find_dependencies(nodes_bump, bump_input);
+
+ copy_nodes(nodes_bump, nodes_dx);
+ copy_nodes(nodes_bump, nodes_dy);
+
+ /* mark nodes to indicate they are use for bump computation, so
+ that any texture coordinates are shifted by dx/dy when sampling */
+ foreach (ShaderNode *node, nodes_bump)
+ node->bump = SHADER_BUMP_CENTER;
+ foreach (NodePair &pair, nodes_dx)
+ pair.second->bump = SHADER_BUMP_DX;
+ foreach (NodePair &pair, nodes_dy)
+ pair.second->bump = SHADER_BUMP_DY;
+
+ ShaderOutput *out = bump_input->link;
+ ShaderOutput *out_dx = nodes_dx[out->parent]->output(out->name());
+ ShaderOutput *out_dy = nodes_dy[out->parent]->output(out->name());
+
+ connect(out_dx, node->input("SampleX"));
+ connect(out_dy, node->input("SampleY"));
+
+ /* add generated nodes */
+ foreach (NodePair &pair, nodes_dx)
+ add(pair.second);
+ foreach (NodePair &pair, nodes_dy)
+ add(pair.second);
+
+ /* connect what is connected is bump to samplecenter input*/
+ connect(out, node->input("SampleCenter"));
+
+ /* bump input is just for connectivity purpose for the graph input,
+ * we re-connected this input to samplecenter, so lets disconnect it
+ * from bump input */
+ disconnect(bump_input);
+ }
+ }
}
void ShaderGraph::bump_from_displacement(bool use_object_space)
{
- /* generate bump mapping automatically from displacement. bump mapping is
- * done using a 3-tap filter, computing the displacement at the center,
- * and two other positions shifted by ray differentials.
- *
- * since the input to displacement is a node graph, we need to ensure that
- * all texture coordinates use are shift by the ray differentials. for this
- * reason we make 3 copies of the node subgraph defining the displacement,
- * with each different geometry and texture coordinate nodes that generate
- * different shifted coordinates.
- *
- * these 3 displacement values are then fed into the bump node, which will
- * output the perturbed normal. */
-
- ShaderInput *displacement_in = output()->input("Displacement");
-
- if(!displacement_in->link)
- return;
-
- /* find dependencies for the given input */
- ShaderNodeSet nodes_displace;
- find_dependencies(nodes_displace, displacement_in);
-
- /* copy nodes for 3 bump samples */
- ShaderNodeMap nodes_center;
- ShaderNodeMap nodes_dx;
- ShaderNodeMap nodes_dy;
-
- copy_nodes(nodes_displace, nodes_center);
- copy_nodes(nodes_displace, nodes_dx);
- copy_nodes(nodes_displace, nodes_dy);
-
- /* mark nodes to indicate they are use for bump computation, so
- * that any texture coordinates are shifted by dx/dy when sampling */
- foreach(NodePair& pair, nodes_center)
- pair.second->bump = SHADER_BUMP_CENTER;
- foreach(NodePair& pair, nodes_dx)
- pair.second->bump = SHADER_BUMP_DX;
- foreach(NodePair& pair, nodes_dy)
- pair.second->bump = SHADER_BUMP_DY;
-
- /* add set normal node and connect the bump normal ouput to the set normal
- * output, so it can finally set the shader normal, note we are only doing
- * this for bump from displacement, this will be the only bump allowed to
- * overwrite the shader normal */
- ShaderNode *set_normal = add(new SetNormalNode());
-
- /* add bump node and connect copied graphs to it */
- BumpNode *bump = (BumpNode*)add(new BumpNode());
- bump->use_object_space = use_object_space;
- bump->distance = 1.0f;
-
- ShaderOutput *out = displacement_in->link;
- ShaderOutput *out_center = nodes_center[out->parent]->output(out->name());
- ShaderOutput *out_dx = nodes_dx[out->parent]->output(out->name());
- ShaderOutput *out_dy = nodes_dy[out->parent]->output(out->name());
-
- /* convert displacement vector to height */
- VectorMathNode *dot_center = (VectorMathNode*)add(new VectorMathNode());
- VectorMathNode *dot_dx = (VectorMathNode*)add(new VectorMathNode());
- VectorMathNode *dot_dy = (VectorMathNode*)add(new VectorMathNode());
-
- dot_center->type = NODE_VECTOR_MATH_DOT_PRODUCT;
- dot_dx->type = NODE_VECTOR_MATH_DOT_PRODUCT;
- dot_dy->type = NODE_VECTOR_MATH_DOT_PRODUCT;
-
- GeometryNode *geom = (GeometryNode*)add(new GeometryNode());
- connect(geom->output("Normal"), dot_center->input("Vector2"));
- connect(geom->output("Normal"), dot_dx->input("Vector2"));
- connect(geom->output("Normal"), dot_dy->input("Vector2"));
-
- connect(out_center, dot_center->input("Vector1"));
- connect(out_dx, dot_dx->input("Vector1"));
- connect(out_dy, dot_dy->input("Vector1"));
-
- connect(dot_center->output("Value"), bump->input("SampleCenter"));
- connect(dot_dx->output("Value"), bump->input("SampleX"));
- connect(dot_dy->output("Value"), bump->input("SampleY"));
-
- /* connect the bump out to the set normal in: */
- connect(bump->output("Normal"), set_normal->input("Direction"));
-
- /* connect to output node */
- connect(set_normal->output("Normal"), output()->input("Normal"));
-
- /* finally, add the copied nodes to the graph. we can't do this earlier
- * because we would create dependency cycles in the above loop */
- foreach(NodePair& pair, nodes_center)
- add(pair.second);
- foreach(NodePair& pair, nodes_dx)
- add(pair.second);
- foreach(NodePair& pair, nodes_dy)
- add(pair.second);
+ /* generate bump mapping automatically from displacement. bump mapping is
+ * done using a 3-tap filter, computing the displacement at the center,
+ * and two other positions shifted by ray differentials.
+ *
+ * since the input to displacement is a node graph, we need to ensure that
+ * all texture coordinates use are shift by the ray differentials. for this
+ * reason we make 3 copies of the node subgraph defining the displacement,
+ * with each different geometry and texture coordinate nodes that generate
+ * different shifted coordinates.
+ *
+ * these 3 displacement values are then fed into the bump node, which will
+ * output the perturbed normal. */
+
+ ShaderInput *displacement_in = output()->input("Displacement");
+
+ if (!displacement_in->link)
+ return;
+
+ /* find dependencies for the given input */
+ ShaderNodeSet nodes_displace;
+ find_dependencies(nodes_displace, displacement_in);
+
+ /* copy nodes for 3 bump samples */
+ ShaderNodeMap nodes_center;
+ ShaderNodeMap nodes_dx;
+ ShaderNodeMap nodes_dy;
+
+ copy_nodes(nodes_displace, nodes_center);
+ copy_nodes(nodes_displace, nodes_dx);
+ copy_nodes(nodes_displace, nodes_dy);
+
+ /* mark nodes to indicate they are use for bump computation, so
+ * that any texture coordinates are shifted by dx/dy when sampling */
+ foreach (NodePair &pair, nodes_center)
+ pair.second->bump = SHADER_BUMP_CENTER;
+ foreach (NodePair &pair, nodes_dx)
+ pair.second->bump = SHADER_BUMP_DX;
+ foreach (NodePair &pair, nodes_dy)
+ pair.second->bump = SHADER_BUMP_DY;
+
+ /* add set normal node and connect the bump normal ouput to the set normal
+ * output, so it can finally set the shader normal, note we are only doing
+ * this for bump from displacement, this will be the only bump allowed to
+ * overwrite the shader normal */
+ ShaderNode *set_normal = add(new SetNormalNode());
+
+ /* add bump node and connect copied graphs to it */
+ BumpNode *bump = (BumpNode *)add(new BumpNode());
+ bump->use_object_space = use_object_space;
+ bump->distance = 1.0f;
+
+ ShaderOutput *out = displacement_in->link;
+ ShaderOutput *out_center = nodes_center[out->parent]->output(out->name());
+ ShaderOutput *out_dx = nodes_dx[out->parent]->output(out->name());
+ ShaderOutput *out_dy = nodes_dy[out->parent]->output(out->name());
+
+ /* convert displacement vector to height */
+ VectorMathNode *dot_center = (VectorMathNode *)add(new VectorMathNode());
+ VectorMathNode *dot_dx = (VectorMathNode *)add(new VectorMathNode());
+ VectorMathNode *dot_dy = (VectorMathNode *)add(new VectorMathNode());
+
+ dot_center->type = NODE_VECTOR_MATH_DOT_PRODUCT;
+ dot_dx->type = NODE_VECTOR_MATH_DOT_PRODUCT;
+ dot_dy->type = NODE_VECTOR_MATH_DOT_PRODUCT;
+
+ GeometryNode *geom = (GeometryNode *)add(new GeometryNode());
+ connect(geom->output("Normal"), dot_center->input("Vector2"));
+ connect(geom->output("Normal"), dot_dx->input("Vector2"));
+ connect(geom->output("Normal"), dot_dy->input("Vector2"));
+
+ connect(out_center, dot_center->input("Vector1"));
+ connect(out_dx, dot_dx->input("Vector1"));
+ connect(out_dy, dot_dy->input("Vector1"));
+
+ connect(dot_center->output("Value"), bump->input("SampleCenter"));
+ connect(dot_dx->output("Value"), bump->input("SampleX"));
+ connect(dot_dy->output("Value"), bump->input("SampleY"));
+
+ /* connect the bump out to the set normal in: */
+ connect(bump->output("Normal"), set_normal->input("Direction"));
+
+ /* connect to output node */
+ connect(set_normal->output("Normal"), output()->input("Normal"));
+
+ /* finally, add the copied nodes to the graph. we can't do this earlier
+ * because we would create dependency cycles in the above loop */
+ foreach (NodePair &pair, nodes_center)
+ add(pair.second);
+ foreach (NodePair &pair, nodes_dx)
+ add(pair.second);
+ foreach (NodePair &pair, nodes_dy)
+ add(pair.second);
}
void ShaderGraph::transform_multi_closure(ShaderNode *node, ShaderOutput *weight_out, bool volume)
{
- /* for SVM in multi closure mode, this transforms the shader mix/add part of
- * the graph into nodes that feed weights into closure nodes. this is too
- * avoid building a closure tree and then flattening it, and instead write it
- * directly to an array */
-
- if(node->special_type == SHADER_SPECIAL_TYPE_COMBINE_CLOSURE) {
- ShaderInput *fin = node->input("Fac");
- ShaderInput *cl1in = node->input("Closure1");
- ShaderInput *cl2in = node->input("Closure2");
- ShaderOutput *weight1_out, *weight2_out;
-
- if(fin) {
- /* mix closure: add node to mix closure weights */
- MixClosureWeightNode *mix_node = new MixClosureWeightNode();
- add(mix_node);
- ShaderInput *fac_in = mix_node->input("Fac");
- ShaderInput *weight_in = mix_node->input("Weight");
-
- if(fin->link)
- connect(fin->link, fac_in);
- else
- mix_node->fac = node->get_float(fin->socket_type);
-
- if(weight_out)
- connect(weight_out, weight_in);
-
- weight1_out = mix_node->output("Weight1");
- weight2_out = mix_node->output("Weight2");
- }
- else {
- /* add closure: just pass on any weights */
- weight1_out = weight_out;
- weight2_out = weight_out;
- }
-
- if(cl1in->link)
- transform_multi_closure(cl1in->link->parent, weight1_out, volume);
- if(cl2in->link)
- transform_multi_closure(cl2in->link->parent, weight2_out, volume);
- }
- else {
- ShaderInput *weight_in = node->input((volume)? "VolumeMixWeight": "SurfaceMixWeight");
-
- /* not a closure node? */
- if(!weight_in)
- return;
-
- /* already has a weight connected to it? add weights */
- float weight_value = node->get_float(weight_in->socket_type);
- if(weight_in->link || weight_value != 0.0f) {
- MathNode *math_node = new MathNode();
- add(math_node);
-
- if(weight_in->link)
- connect(weight_in->link, math_node->input("Value1"));
- else
- math_node->value1 = weight_value;
-
- if(weight_out)
- connect(weight_out, math_node->input("Value2"));
- else
- math_node->value2 = 1.0f;
-
- weight_out = math_node->output("Value");
- if(weight_in->link)
- disconnect(weight_in);
- }
-
- /* connected to closure mix weight */
- if(weight_out)
- connect(weight_out, weight_in);
- else
- node->set(weight_in->socket_type, weight_value + 1.0f);
- }
+ /* for SVM in multi closure mode, this transforms the shader mix/add part of
+ * the graph into nodes that feed weights into closure nodes. this is too
+ * avoid building a closure tree and then flattening it, and instead write it
+ * directly to an array */
+
+ if (node->special_type == SHADER_SPECIAL_TYPE_COMBINE_CLOSURE) {
+ ShaderInput *fin = node->input("Fac");
+ ShaderInput *cl1in = node->input("Closure1");
+ ShaderInput *cl2in = node->input("Closure2");
+ ShaderOutput *weight1_out, *weight2_out;
+
+ if (fin) {
+ /* mix closure: add node to mix closure weights */
+ MixClosureWeightNode *mix_node = new MixClosureWeightNode();
+ add(mix_node);
+ ShaderInput *fac_in = mix_node->input("Fac");
+ ShaderInput *weight_in = mix_node->input("Weight");
+
+ if (fin->link)
+ connect(fin->link, fac_in);
+ else
+ mix_node->fac = node->get_float(fin->socket_type);
+
+ if (weight_out)
+ connect(weight_out, weight_in);
+
+ weight1_out = mix_node->output("Weight1");
+ weight2_out = mix_node->output("Weight2");
+ }
+ else {
+ /* add closure: just pass on any weights */
+ weight1_out = weight_out;
+ weight2_out = weight_out;
+ }
+
+ if (cl1in->link)
+ transform_multi_closure(cl1in->link->parent, weight1_out, volume);
+ if (cl2in->link)
+ transform_multi_closure(cl2in->link->parent, weight2_out, volume);
+ }
+ else {
+ ShaderInput *weight_in = node->input((volume) ? "VolumeMixWeight" : "SurfaceMixWeight");
+
+ /* not a closure node? */
+ if (!weight_in)
+ return;
+
+ /* already has a weight connected to it? add weights */
+ float weight_value = node->get_float(weight_in->socket_type);
+ if (weight_in->link || weight_value != 0.0f) {
+ MathNode *math_node = new MathNode();
+ add(math_node);
+
+ if (weight_in->link)
+ connect(weight_in->link, math_node->input("Value1"));
+ else
+ math_node->value1 = weight_value;
+
+ if (weight_out)
+ connect(weight_out, math_node->input("Value2"));
+ else
+ math_node->value2 = 1.0f;
+
+ weight_out = math_node->output("Value");
+ if (weight_in->link)
+ disconnect(weight_in);
+ }
+
+ /* connected to closure mix weight */
+ if (weight_out)
+ connect(weight_out, weight_in);
+ else
+ node->set(weight_in->socket_type, weight_value + 1.0f);
+ }
}
int ShaderGraph::get_num_closures()
{
- int num_closures = 0;
- foreach(ShaderNode *node, nodes) {
- ClosureType closure_type = node->get_closure_type();
- if(closure_type == CLOSURE_NONE_ID) {
- continue;
- }
- else if(CLOSURE_IS_BSSRDF(closure_type)) {
- num_closures += 3;
- }
- else if(CLOSURE_IS_GLASS(closure_type)) {
- num_closures += 2;
- }
- else if(CLOSURE_IS_BSDF_MULTISCATTER(closure_type)) {
- num_closures += 2;
- }
- else if(CLOSURE_IS_PRINCIPLED(closure_type)) {
- num_closures += 8;
- }
- else if(CLOSURE_IS_VOLUME(closure_type)) {
- num_closures += VOLUME_STACK_SIZE;
- }
- else if(closure_type == CLOSURE_BSDF_HAIR_PRINCIPLED_ID) {
- num_closures += 4;
- }
- else {
- ++num_closures;
- }
- }
- return num_closures;
+ int num_closures = 0;
+ foreach (ShaderNode *node, nodes) {
+ ClosureType closure_type = node->get_closure_type();
+ if (closure_type == CLOSURE_NONE_ID) {
+ continue;
+ }
+ else if (CLOSURE_IS_BSSRDF(closure_type)) {
+ num_closures += 3;
+ }
+ else if (CLOSURE_IS_GLASS(closure_type)) {
+ num_closures += 2;
+ }
+ else if (CLOSURE_IS_BSDF_MULTISCATTER(closure_type)) {
+ num_closures += 2;
+ }
+ else if (CLOSURE_IS_PRINCIPLED(closure_type)) {
+ num_closures += 8;
+ }
+ else if (CLOSURE_IS_VOLUME(closure_type)) {
+ num_closures += VOLUME_STACK_SIZE;
+ }
+ else if (closure_type == CLOSURE_BSDF_HAIR_PRINCIPLED_ID) {
+ num_closures += 4;
+ }
+ else {
+ ++num_closures;
+ }
+ }
+ return num_closures;
}
void ShaderGraph::dump_graph(const char *filename)
{
- FILE *fd = fopen(filename, "w");
-
- if(fd == NULL) {
- printf("Error opening file for dumping the graph: %s\n", filename);
- return;
- }
-
- fprintf(fd, "digraph shader_graph {\n");
- fprintf(fd, "ranksep=1.5\n");
- fprintf(fd, "rankdir=LR\n");
- fprintf(fd, "splines=false\n");
-
- foreach(ShaderNode *node, nodes) {
- fprintf(fd, "// NODE: %p\n", node);
- fprintf(fd, "\"%p\" [shape=record,label=\"{", node);
- if(node->inputs.size()) {
- fprintf(fd, "{");
- foreach(ShaderInput *socket, node->inputs) {
- if(socket != node->inputs[0]) {
- fprintf(fd, "|");
- }
- fprintf(fd, "<IN_%p>%s", socket, socket->name().c_str());
- }
- fprintf(fd, "}|");
- }
- fprintf(fd, "%s", node->name.c_str());
- if(node->bump == SHADER_BUMP_CENTER) {
- fprintf(fd, " (bump:center)");
- }
- else if(node->bump == SHADER_BUMP_DX) {
- fprintf(fd, " (bump:dx)");
- }
- else if(node->bump == SHADER_BUMP_DY) {
- fprintf(fd, " (bump:dy)");
- }
- if(node->outputs.size()) {
- fprintf(fd, "|{");
- foreach(ShaderOutput *socket, node->outputs) {
- if(socket != node->outputs[0]) {
- fprintf(fd, "|");
- }
- fprintf(fd, "<OUT_%p>%s", socket, socket->name().c_str());
- }
- fprintf(fd, "}");
- }
- fprintf(fd, "}\"]");
- }
-
- foreach(ShaderNode *node, nodes) {
- foreach(ShaderOutput *output, node->outputs) {
- foreach(ShaderInput *input, output->links) {
- fprintf(fd,
- "// CONNECTION: OUT_%p->IN_%p (%s:%s)\n",
- output,
- input,
- output->name().c_str(), input->name().c_str());
- fprintf(fd,
- "\"%p\":\"OUT_%p\":e -> \"%p\":\"IN_%p\":w [label=\"\"]\n",
- output->parent,
- output,
- input->parent,
- input);
- }
- }
- }
-
- fprintf(fd, "}\n");
- fclose(fd);
+ FILE *fd = fopen(filename, "w");
+
+ if (fd == NULL) {
+ printf("Error opening file for dumping the graph: %s\n", filename);
+ return;
+ }
+
+ fprintf(fd, "digraph shader_graph {\n");
+ fprintf(fd, "ranksep=1.5\n");
+ fprintf(fd, "rankdir=LR\n");
+ fprintf(fd, "splines=false\n");
+
+ foreach (ShaderNode *node, nodes) {
+ fprintf(fd, "// NODE: %p\n", node);
+ fprintf(fd, "\"%p\" [shape=record,label=\"{", node);
+ if (node->inputs.size()) {
+ fprintf(fd, "{");
+ foreach (ShaderInput *socket, node->inputs) {
+ if (socket != node->inputs[0]) {
+ fprintf(fd, "|");
+ }
+ fprintf(fd, "<IN_%p>%s", socket, socket->name().c_str());
+ }
+ fprintf(fd, "}|");
+ }
+ fprintf(fd, "%s", node->name.c_str());
+ if (node->bump == SHADER_BUMP_CENTER) {
+ fprintf(fd, " (bump:center)");
+ }
+ else if (node->bump == SHADER_BUMP_DX) {
+ fprintf(fd, " (bump:dx)");
+ }
+ else if (node->bump == SHADER_BUMP_DY) {
+ fprintf(fd, " (bump:dy)");
+ }
+ if (node->outputs.size()) {
+ fprintf(fd, "|{");
+ foreach (ShaderOutput *socket, node->outputs) {
+ if (socket != node->outputs[0]) {
+ fprintf(fd, "|");
+ }
+ fprintf(fd, "<OUT_%p>%s", socket, socket->name().c_str());
+ }
+ fprintf(fd, "}");
+ }
+ fprintf(fd, "}\"]");
+ }
+
+ foreach (ShaderNode *node, nodes) {
+ foreach (ShaderOutput *output, node->outputs) {
+ foreach (ShaderInput *input, output->links) {
+ fprintf(fd,
+ "// CONNECTION: OUT_%p->IN_%p (%s:%s)\n",
+ output,
+ input,
+ output->name().c_str(),
+ input->name().c_str());
+ fprintf(fd,
+ "\"%p\":\"OUT_%p\":e -> \"%p\":\"IN_%p\":w [label=\"\"]\n",
+ output->parent,
+ output,
+ input->parent,
+ input);
+ }
+ }
+ }
+
+ fprintf(fd, "}\n");
+ fclose(fd);
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/render/graph.h b/intern/cycles/render/graph.h
index d14a59b4900..a2c030fd226 100644
--- a/intern/cycles/render/graph.h
+++ b/intern/cycles/render/graph.h
@@ -49,12 +49,7 @@ class MD5Hash;
* For bump mapping, a node may be evaluated multiple times, using different
* samples to reconstruct the normal, this indicates the sample position */
-enum ShaderBump {
- SHADER_BUMP_NONE,
- SHADER_BUMP_CENTER,
- SHADER_BUMP_DX,
- SHADER_BUMP_DY
-};
+enum ShaderBump { SHADER_BUMP_NONE, SHADER_BUMP_CENTER, SHADER_BUMP_DX, SHADER_BUMP_DY };
/* Identifiers for some special node types.
*
@@ -62,16 +57,16 @@ enum ShaderBump {
* Cannot use dynamic_cast, as this is disabled for OSL. */
enum ShaderNodeSpecialType {
- SHADER_SPECIAL_TYPE_NONE,
- SHADER_SPECIAL_TYPE_PROXY,
- SHADER_SPECIAL_TYPE_AUTOCONVERT,
- SHADER_SPECIAL_TYPE_GEOMETRY,
- SHADER_SPECIAL_TYPE_SCRIPT,
- SHADER_SPECIAL_TYPE_IMAGE_SLOT,
- SHADER_SPECIAL_TYPE_CLOSURE,
- SHADER_SPECIAL_TYPE_COMBINE_CLOSURE,
- SHADER_SPECIAL_TYPE_OUTPUT,
- SHADER_SPECIAL_TYPE_BUMP,
+ SHADER_SPECIAL_TYPE_NONE,
+ SHADER_SPECIAL_TYPE_PROXY,
+ SHADER_SPECIAL_TYPE_AUTOCONVERT,
+ SHADER_SPECIAL_TYPE_GEOMETRY,
+ SHADER_SPECIAL_TYPE_SCRIPT,
+ SHADER_SPECIAL_TYPE_IMAGE_SLOT,
+ SHADER_SPECIAL_TYPE_CLOSURE,
+ SHADER_SPECIAL_TYPE_COMBINE_CLOSURE,
+ SHADER_SPECIAL_TYPE_OUTPUT,
+ SHADER_SPECIAL_TYPE_BUMP,
};
/* Input
@@ -81,22 +76,38 @@ enum ShaderNodeSpecialType {
* coordinate. */
class ShaderInput {
-public:
- ShaderInput(const SocketType& socket_type_, ShaderNode* parent_)
- : socket_type(socket_type_), parent(parent_), link(NULL), stack_offset(SVM_STACK_INVALID)
- {}
-
- ustring name() { return socket_type.ui_name; }
- int flags() { return socket_type.flags; }
- SocketType::Type type() { return socket_type.type; }
-
- void set(float f) { ((Node*)parent)->set(socket_type, f); }
- void set(float3 f) { ((Node*)parent)->set(socket_type, f); }
-
- const SocketType& socket_type;
- ShaderNode *parent;
- ShaderOutput *link;
- int stack_offset; /* for SVM compiler */
+ public:
+ ShaderInput(const SocketType &socket_type_, ShaderNode *parent_)
+ : socket_type(socket_type_), parent(parent_), link(NULL), stack_offset(SVM_STACK_INVALID)
+ {
+ }
+
+ ustring name()
+ {
+ return socket_type.ui_name;
+ }
+ int flags()
+ {
+ return socket_type.flags;
+ }
+ SocketType::Type type()
+ {
+ return socket_type.type;
+ }
+
+ void set(float f)
+ {
+ ((Node *)parent)->set(socket_type, f);
+ }
+ void set(float3 f)
+ {
+ ((Node *)parent)->set(socket_type, f);
+ }
+
+ const SocketType &socket_type;
+ ShaderNode *parent;
+ ShaderOutput *link;
+ int stack_offset; /* for SVM compiler */
};
/* Output
@@ -104,18 +115,25 @@ public:
* Output socket for a shader node. */
class ShaderOutput {
-public:
- ShaderOutput(const SocketType& socket_type_, ShaderNode* parent_)
- : socket_type(socket_type_), parent(parent_), stack_offset(SVM_STACK_INVALID)
- {}
-
- ustring name() { return socket_type.ui_name; }
- SocketType::Type type() { return socket_type.type; }
-
- const SocketType& socket_type;
- ShaderNode *parent;
- vector<ShaderInput*> links;
- int stack_offset; /* for SVM compiler */
+ public:
+ ShaderOutput(const SocketType &socket_type_, ShaderNode *parent_)
+ : socket_type(socket_type_), parent(parent_), stack_offset(SVM_STACK_INVALID)
+ {
+ }
+
+ ustring name()
+ {
+ return socket_type.ui_name;
+ }
+ SocketType::Type type()
+ {
+ return socket_type.type;
+ }
+
+ const SocketType &socket_type;
+ ShaderNode *parent;
+ vector<ShaderInput *> links;
+ int stack_offset; /* for SVM compiler */
};
/* Node
@@ -124,115 +142,163 @@ public:
* base class for all node types. */
class ShaderNode : public Node {
-public:
- explicit ShaderNode(const NodeType *type);
- virtual ~ShaderNode();
-
- void create_inputs_outputs(const NodeType *type);
-
- ShaderInput *input(const char *name);
- ShaderOutput *output(const char *name);
- ShaderInput *input(ustring name);
- ShaderOutput *output(ustring name);
-
- virtual ShaderNode *clone() const = 0;
- virtual void attributes(Shader *shader, AttributeRequestSet *attributes);
- virtual void compile(SVMCompiler& compiler) = 0;
- virtual void compile(OSLCompiler& compiler) = 0;
-
- /* ** Node optimization ** */
- /* Check whether the node can be replaced with single constant. */
- virtual void constant_fold(const ConstantFolder& /*folder*/) {}
-
- /* Simplify settings used by artists to the ones which are simpler to
- * evaluate in the kernel but keep the final result unchanged.
- */
- virtual void simplify_settings(Scene * /*scene*/) {};
-
- virtual bool has_surface_emission() { return false; }
- virtual bool has_surface_transparent() { return false; }
- virtual bool has_surface_bssrdf() { return false; }
- virtual bool has_bump() { return false; }
- virtual bool has_bssrdf_bump() { return false; }
- virtual bool has_spatial_varying() { return false; }
- virtual bool has_object_dependency() { return false; }
- virtual bool has_attribute_dependency() { return false; }
- virtual bool has_integrator_dependency() { return false; }
- virtual bool has_volume_support() { return false; }
- virtual bool has_raytrace() { return false; }
- vector<ShaderInput*> inputs;
- vector<ShaderOutput*> outputs;
-
- int id; /* index in graph node array */
- ShaderBump bump; /* for bump mapping utility */
-
- ShaderNodeSpecialType special_type; /* special node type */
-
- /* ** Selective nodes compilation ** */
-
- /* TODO(sergey): More explicitly mention in the function names
- * that those functions are for selective compilation only?
- */
-
- /* Nodes are split into several groups, group of level 0 contains
- * nodes which are most commonly used, further levels are extension
- * of previous one and includes less commonly used nodes.
- */
- virtual int get_group() { return NODE_GROUP_LEVEL_0; }
-
- /* Node feature are used to disable huge nodes inside the group,
- * so it's possible to disable huge nodes inside of the required
- * nodes group.
- */
- virtual int get_feature() { return bump == SHADER_BUMP_NONE ? 0 : NODE_FEATURE_BUMP; }
-
- /* Get closure ID to which the node compiles into. */
- virtual ClosureType get_closure_type() { return CLOSURE_NONE_ID; }
-
- /* Check whether settings of the node equals to another one.
- *
- * This is mainly used to check whether two nodes can be merged
- * together. Meaning, runtime stuff like node id and unbound slots
- * will be ignored for comparison.
- *
- * NOTE: If some node can't be de-duplicated for whatever reason it
- * is to be handled in the subclass.
- */
- virtual bool equals(const ShaderNode& other);
+ public:
+ explicit ShaderNode(const NodeType *type);
+ virtual ~ShaderNode();
+
+ void create_inputs_outputs(const NodeType *type);
+
+ ShaderInput *input(const char *name);
+ ShaderOutput *output(const char *name);
+ ShaderInput *input(ustring name);
+ ShaderOutput *output(ustring name);
+
+ virtual ShaderNode *clone() const = 0;
+ virtual void attributes(Shader *shader, AttributeRequestSet *attributes);
+ virtual void compile(SVMCompiler &compiler) = 0;
+ virtual void compile(OSLCompiler &compiler) = 0;
+
+ /* ** Node optimization ** */
+ /* Check whether the node can be replaced with single constant. */
+ virtual void constant_fold(const ConstantFolder & /*folder*/)
+ {
+ }
+
+ /* Simplify settings used by artists to the ones which are simpler to
+ * evaluate in the kernel but keep the final result unchanged.
+ */
+ virtual void simplify_settings(Scene * /*scene*/){};
+
+ virtual bool has_surface_emission()
+ {
+ return false;
+ }
+ virtual bool has_surface_transparent()
+ {
+ return false;
+ }
+ virtual bool has_surface_bssrdf()
+ {
+ return false;
+ }
+ virtual bool has_bump()
+ {
+ return false;
+ }
+ virtual bool has_bssrdf_bump()
+ {
+ return false;
+ }
+ virtual bool has_spatial_varying()
+ {
+ return false;
+ }
+ virtual bool has_object_dependency()
+ {
+ return false;
+ }
+ virtual bool has_attribute_dependency()
+ {
+ return false;
+ }
+ virtual bool has_integrator_dependency()
+ {
+ return false;
+ }
+ virtual bool has_volume_support()
+ {
+ return false;
+ }
+ virtual bool has_raytrace()
+ {
+ return false;
+ }
+ vector<ShaderInput *> inputs;
+ vector<ShaderOutput *> outputs;
+
+ int id; /* index in graph node array */
+ ShaderBump bump; /* for bump mapping utility */
+
+ ShaderNodeSpecialType special_type; /* special node type */
+
+ /* ** Selective nodes compilation ** */
+
+ /* TODO(sergey): More explicitly mention in the function names
+ * that those functions are for selective compilation only?
+ */
+
+ /* Nodes are split into several groups, group of level 0 contains
+ * nodes which are most commonly used, further levels are extension
+ * of previous one and includes less commonly used nodes.
+ */
+ virtual int get_group()
+ {
+ return NODE_GROUP_LEVEL_0;
+ }
+
+ /* Node feature are used to disable huge nodes inside the group,
+ * so it's possible to disable huge nodes inside of the required
+ * nodes group.
+ */
+ virtual int get_feature()
+ {
+ return bump == SHADER_BUMP_NONE ? 0 : NODE_FEATURE_BUMP;
+ }
+
+ /* Get closure ID to which the node compiles into. */
+ virtual ClosureType get_closure_type()
+ {
+ return CLOSURE_NONE_ID;
+ }
+
+ /* Check whether settings of the node equals to another one.
+ *
+ * This is mainly used to check whether two nodes can be merged
+ * together. Meaning, runtime stuff like node id and unbound slots
+ * will be ignored for comparison.
+ *
+ * NOTE: If some node can't be de-duplicated for whatever reason it
+ * is to be handled in the subclass.
+ */
+ virtual bool equals(const ShaderNode &other);
};
-
/* Node definition utility macros */
#define SHADER_NODE_CLASS(type) \
- NODE_DECLARE \
- type(); \
- virtual ShaderNode *clone() const { return new type(*this); } \
- virtual void compile(SVMCompiler& compiler); \
- virtual void compile(OSLCompiler& compiler); \
+ NODE_DECLARE \
+ type(); \
+ virtual ShaderNode *clone() const \
+ { \
+ return new type(*this); \
+ } \
+ virtual void compile(SVMCompiler &compiler); \
+ virtual void compile(OSLCompiler &compiler);
#define SHADER_NODE_NO_CLONE_CLASS(type) \
- NODE_DECLARE \
- type(); \
- virtual void compile(SVMCompiler& compiler); \
- virtual void compile(OSLCompiler& compiler); \
+ NODE_DECLARE \
+ type(); \
+ virtual void compile(SVMCompiler &compiler); \
+ virtual void compile(OSLCompiler &compiler);
#define SHADER_NODE_BASE_CLASS(type) \
- virtual ShaderNode *clone() const { return new type(*this); } \
- virtual void compile(SVMCompiler& compiler); \
- virtual void compile(OSLCompiler& compiler); \
-
-class ShaderNodeIDComparator
-{
-public:
- bool operator()(const ShaderNode *n1, const ShaderNode *n2) const
- {
- return n1->id < n2->id;
- }
+ virtual ShaderNode *clone() const \
+ { \
+ return new type(*this); \
+ } \
+ virtual void compile(SVMCompiler &compiler); \
+ virtual void compile(OSLCompiler &compiler);
+
+class ShaderNodeIDComparator {
+ public:
+ bool operator()(const ShaderNode *n1, const ShaderNode *n2) const
+ {
+ return n1->id < n2->id;
+ }
};
-typedef set<ShaderNode*, ShaderNodeIDComparator> ShaderNodeSet;
-typedef map<ShaderNode*, ShaderNode*, ShaderNodeIDComparator> ShaderNodeMap;
+typedef set<ShaderNode *, ShaderNodeIDComparator> ShaderNodeSet;
+typedef map<ShaderNode *, ShaderNode *, ShaderNodeIDComparator> ShaderNodeMap;
/* Graph
*
@@ -240,57 +306,57 @@ typedef map<ShaderNode*, ShaderNode*, ShaderNodeIDComparator> ShaderNodeMap;
* bump mapping from displacement, and possibly other things in the future. */
class ShaderGraph {
-public:
- list<ShaderNode*> nodes;
- size_t num_node_ids;
- bool finalized;
- bool simplified;
- string displacement_hash;
-
- ShaderGraph();
- ~ShaderGraph();
-
- ShaderNode *add(ShaderNode *node);
- OutputNode *output();
-
- void connect(ShaderOutput *from, ShaderInput *to);
- void disconnect(ShaderOutput *from);
- void disconnect(ShaderInput *to);
- void relink(ShaderNode *node, ShaderOutput *from, ShaderOutput *to);
-
- void remove_proxy_nodes();
- void compute_displacement_hash();
- void simplify(Scene *scene);
- void finalize(Scene *scene,
- bool do_bump = false,
- bool do_simplify = false,
- bool bump_in_object_space = false);
-
- int get_num_closures();
-
- void dump_graph(const char *filename);
-
-protected:
- typedef pair<ShaderNode* const, ShaderNode*> NodePair;
-
- void find_dependencies(ShaderNodeSet& dependencies, ShaderInput *input);
- void clear_nodes();
- void copy_nodes(ShaderNodeSet& nodes, ShaderNodeMap& nnodemap);
-
- void break_cycles(ShaderNode *node, vector<bool>& visited, vector<bool>& on_stack);
- void bump_from_displacement(bool use_object_space);
- void refine_bump_nodes();
- void default_inputs(bool do_osl);
- void transform_multi_closure(ShaderNode *node, ShaderOutput *weight_out, bool volume);
-
- /* Graph simplification routines. */
- void clean(Scene *scene);
- void constant_fold(Scene *scene);
- void simplify_settings(Scene *scene);
- void deduplicate_nodes();
- void verify_volume_output();
+ public:
+ list<ShaderNode *> nodes;
+ size_t num_node_ids;
+ bool finalized;
+ bool simplified;
+ string displacement_hash;
+
+ ShaderGraph();
+ ~ShaderGraph();
+
+ ShaderNode *add(ShaderNode *node);
+ OutputNode *output();
+
+ void connect(ShaderOutput *from, ShaderInput *to);
+ void disconnect(ShaderOutput *from);
+ void disconnect(ShaderInput *to);
+ void relink(ShaderNode *node, ShaderOutput *from, ShaderOutput *to);
+
+ void remove_proxy_nodes();
+ void compute_displacement_hash();
+ void simplify(Scene *scene);
+ void finalize(Scene *scene,
+ bool do_bump = false,
+ bool do_simplify = false,
+ bool bump_in_object_space = false);
+
+ int get_num_closures();
+
+ void dump_graph(const char *filename);
+
+ protected:
+ typedef pair<ShaderNode *const, ShaderNode *> NodePair;
+
+ void find_dependencies(ShaderNodeSet &dependencies, ShaderInput *input);
+ void clear_nodes();
+ void copy_nodes(ShaderNodeSet &nodes, ShaderNodeMap &nnodemap);
+
+ void break_cycles(ShaderNode *node, vector<bool> &visited, vector<bool> &on_stack);
+ void bump_from_displacement(bool use_object_space);
+ void refine_bump_nodes();
+ void default_inputs(bool do_osl);
+ void transform_multi_closure(ShaderNode *node, ShaderOutput *weight_out, bool volume);
+
+ /* Graph simplification routines. */
+ void clean(Scene *scene);
+ void constant_fold(Scene *scene);
+ void simplify_settings(Scene *scene);
+ void deduplicate_nodes();
+ void verify_volume_output();
};
CCL_NAMESPACE_END
-#endif /* __GRAPH_H__ */
+#endif /* __GRAPH_H__ */
diff --git a/intern/cycles/render/image.cpp b/intern/cycles/render/image.cpp
index 1edd5865836..ae219e912e0 100644
--- a/intern/cycles/render/image.cpp
+++ b/intern/cycles/render/image.cpp
@@ -27,7 +27,7 @@
#include "util/util_unique_ptr.h"
#ifdef WITH_OSL
-#include <OSL/oslexec.h>
+# include <OSL/oslexec.h>
#endif
CCL_NAMESPACE_BEGIN
@@ -37,15 +37,15 @@ namespace {
/* Some helpers to silence warning in templated function. */
bool isfinite(uchar /*value*/)
{
- return true;
+ return true;
}
bool isfinite(half /*value*/)
{
- return true;
+ return true;
}
-bool isfinite(uint16_t /*value*/)
+bool isfinite(uint16_t /*value*/)
{
- return true;
+ return true;
}
/* The lower three bits of a device texture slot number indicate its type.
@@ -54,946 +54,888 @@ bool isfinite(uint16_t /*value*/)
*/
int type_index_to_flattened_slot(int slot, ImageDataType type)
{
- return (slot << IMAGE_DATA_TYPE_SHIFT) | (type);
+ return (slot << IMAGE_DATA_TYPE_SHIFT) | (type);
}
int flattened_slot_to_type_index(int flat_slot, ImageDataType *type)
{
- *type = (ImageDataType)(flat_slot & IMAGE_DATA_TYPE_MASK);
- return flat_slot >> IMAGE_DATA_TYPE_SHIFT;
+ *type = (ImageDataType)(flat_slot & IMAGE_DATA_TYPE_MASK);
+ return flat_slot >> IMAGE_DATA_TYPE_SHIFT;
}
-const char* name_from_type(ImageDataType type)
+const char *name_from_type(ImageDataType type)
{
- switch(type) {
- case IMAGE_DATA_TYPE_FLOAT4: return "float4";
- case IMAGE_DATA_TYPE_BYTE4: return "byte4";
- case IMAGE_DATA_TYPE_HALF4: return "half4";
- case IMAGE_DATA_TYPE_FLOAT: return "float";
- case IMAGE_DATA_TYPE_BYTE: return "byte";
- case IMAGE_DATA_TYPE_HALF: return "half";
- case IMAGE_DATA_TYPE_USHORT4: return "ushort4";
- case IMAGE_DATA_TYPE_USHORT: return "ushort";
- case IMAGE_DATA_NUM_TYPES:
- assert(!"System enumerator type, should never be used");
- return "";
- }
- assert(!"Unhandled image data type");
- return "";
+ switch (type) {
+ case IMAGE_DATA_TYPE_FLOAT4:
+ return "float4";
+ case IMAGE_DATA_TYPE_BYTE4:
+ return "byte4";
+ case IMAGE_DATA_TYPE_HALF4:
+ return "half4";
+ case IMAGE_DATA_TYPE_FLOAT:
+ return "float";
+ case IMAGE_DATA_TYPE_BYTE:
+ return "byte";
+ case IMAGE_DATA_TYPE_HALF:
+ return "half";
+ case IMAGE_DATA_TYPE_USHORT4:
+ return "ushort4";
+ case IMAGE_DATA_TYPE_USHORT:
+ return "ushort";
+ case IMAGE_DATA_NUM_TYPES:
+ assert(!"System enumerator type, should never be used");
+ return "";
+ }
+ assert(!"Unhandled image data type");
+ return "";
}
} // namespace
-ImageManager::ImageManager(const DeviceInfo& info)
+ImageManager::ImageManager(const DeviceInfo &info)
{
- need_update = true;
- osl_texture_system = NULL;
- animation_frame = 0;
+ need_update = true;
+ osl_texture_system = NULL;
+ animation_frame = 0;
- /* Set image limits */
- max_num_images = TEX_NUM_MAX;
- has_half_images = info.has_half_images;
+ /* Set image limits */
+ max_num_images = TEX_NUM_MAX;
+ has_half_images = info.has_half_images;
- for(size_t type = 0; type < IMAGE_DATA_NUM_TYPES; type++) {
- tex_num_images[type] = 0;
- }
+ for (size_t type = 0; type < IMAGE_DATA_NUM_TYPES; type++) {
+ tex_num_images[type] = 0;
+ }
}
ImageManager::~ImageManager()
{
- for(size_t type = 0; type < IMAGE_DATA_NUM_TYPES; type++) {
- for(size_t slot = 0; slot < images[type].size(); slot++)
- assert(!images[type][slot]);
- }
+ for (size_t type = 0; type < IMAGE_DATA_NUM_TYPES; type++) {
+ for (size_t slot = 0; slot < images[type].size(); slot++)
+ assert(!images[type][slot]);
+ }
}
void ImageManager::set_osl_texture_system(void *texture_system)
{
- osl_texture_system = texture_system;
+ osl_texture_system = texture_system;
}
bool ImageManager::set_animation_frame_update(int frame)
{
- if(frame != animation_frame) {
- animation_frame = frame;
-
- for(size_t type = 0; type < IMAGE_DATA_NUM_TYPES; type++) {
- for(size_t slot = 0; slot < images[type].size(); slot++) {
- if(images[type][slot] && images[type][slot]->animated)
- return true;
- }
- }
- }
-
- return false;
+ if (frame != animation_frame) {
+ animation_frame = frame;
+
+ for (size_t type = 0; type < IMAGE_DATA_NUM_TYPES; type++) {
+ for (size_t slot = 0; slot < images[type].size(); slot++) {
+ if (images[type][slot] && images[type][slot]->animated)
+ return true;
+ }
+ }
+ }
+
+ return false;
}
device_memory *ImageManager::image_memory(int flat_slot)
{
- ImageDataType type;
- int slot = flattened_slot_to_type_index(flat_slot, &type);
+ ImageDataType type;
+ int slot = flattened_slot_to_type_index(flat_slot, &type);
- Image *img = images[type][slot];
+ Image *img = images[type][slot];
- return img->mem;
+ return img->mem;
}
-bool ImageManager::get_image_metadata(int flat_slot,
- ImageMetaData& metadata)
+bool ImageManager::get_image_metadata(int flat_slot, ImageMetaData &metadata)
{
- if(flat_slot == -1) {
- return false;
- }
+ if (flat_slot == -1) {
+ return false;
+ }
- ImageDataType type;
- int slot = flattened_slot_to_type_index(flat_slot, &type);
+ ImageDataType type;
+ int slot = flattened_slot_to_type_index(flat_slot, &type);
- Image *img = images[type][slot];
- if(img) {
- metadata = img->metadata;
- return true;
- }
+ Image *img = images[type][slot];
+ if (img) {
+ metadata = img->metadata;
+ return true;
+ }
- return false;
+ return false;
}
-bool ImageManager::get_image_metadata(const string& filename,
+bool ImageManager::get_image_metadata(const string &filename,
void *builtin_data,
- ImageMetaData& metadata)
+ ImageMetaData &metadata)
{
- memset(&metadata, 0, sizeof(metadata));
-
- if(builtin_data) {
- if(builtin_image_info_cb) {
- builtin_image_info_cb(filename, builtin_data, metadata);
- }
- else {
- return false;
- }
-
- if(metadata.is_float) {
- metadata.is_linear = true;
- metadata.type = (metadata.channels > 1) ? IMAGE_DATA_TYPE_FLOAT4
- : IMAGE_DATA_TYPE_FLOAT;
- }
- else {
- metadata.type = (metadata.channels > 1) ? IMAGE_DATA_TYPE_BYTE4
- : IMAGE_DATA_TYPE_BYTE;
- }
-
- return true;
- }
-
- /* Perform preliminary checks, with meaningful logging. */
- if(!path_exists(filename)) {
- VLOG(1) << "File '" << filename << "' does not exist.";
- return false;
- }
- if(path_is_directory(filename)) {
- VLOG(1) << "File '" << filename
- << "' is a directory, can't use as image.";
- return false;
- }
-
- unique_ptr<ImageInput> in(ImageInput::create(filename));
-
- if(!in) {
- return false;
- }
-
- ImageSpec spec;
- if(!in->open(filename, spec)) {
- return false;
- }
-
- metadata.width = spec.width;
- metadata.height = spec.height;
- metadata.depth = spec.depth;
-
-
- /* Check the main format, and channel formats. */
- size_t channel_size = spec.format.basesize();
-
- if(spec.format.is_floating_point()) {
- metadata.is_float = true;
- metadata.is_linear = true;
- }
-
- for(size_t channel = 0; channel < spec.channelformats.size(); channel++) {
- channel_size = max(channel_size, spec.channelformats[channel].basesize());
- if(spec.channelformats[channel].is_floating_point()) {
- metadata.is_float = true;
- metadata.is_linear = true;
- }
- }
-
- /* check if it's half float */
- if(spec.format == TypeDesc::HALF) {
- metadata.is_half = true;
- }
-
- /* basic color space detection, not great but better than nothing
- * before we do OpenColorIO integration */
- if(metadata.is_float) {
- string colorspace = spec.get_string_attribute("oiio:ColorSpace");
-
- metadata.is_linear = !(colorspace == "sRGB" ||
- colorspace == "GammaCorrected" ||
- (colorspace == "" &&
- (strcmp(in->format_name(), "png") == 0 ||
- strcmp(in->format_name(), "tiff") == 0 ||
- strcmp(in->format_name(), "dpx") == 0 ||
- strcmp(in->format_name(), "jpeg2000") == 0)));
- }
- else {
- metadata.is_linear = false;
- }
-
- /* set type and channels */
- metadata.channels = spec.nchannels;
-
- if(metadata.is_half) {
- metadata.type = (metadata.channels > 1) ? IMAGE_DATA_TYPE_HALF4
- : IMAGE_DATA_TYPE_HALF;
- }
- else if(metadata.is_float) {
- metadata.type = (metadata.channels > 1) ? IMAGE_DATA_TYPE_FLOAT4
- : IMAGE_DATA_TYPE_FLOAT;
- }
- else if(spec.format == TypeDesc::USHORT) {
- metadata.type = (metadata.channels > 1) ? IMAGE_DATA_TYPE_USHORT4
- : IMAGE_DATA_TYPE_USHORT;
- }
- else {
- metadata.type = (metadata.channels > 1) ? IMAGE_DATA_TYPE_BYTE4
- : IMAGE_DATA_TYPE_BYTE;
- }
-
- in->close();
-
- return true;
+ memset(&metadata, 0, sizeof(metadata));
+
+ if (builtin_data) {
+ if (builtin_image_info_cb) {
+ builtin_image_info_cb(filename, builtin_data, metadata);
+ }
+ else {
+ return false;
+ }
+
+ if (metadata.is_float) {
+ metadata.is_linear = true;
+ metadata.type = (metadata.channels > 1) ? IMAGE_DATA_TYPE_FLOAT4 : IMAGE_DATA_TYPE_FLOAT;
+ }
+ else {
+ metadata.type = (metadata.channels > 1) ? IMAGE_DATA_TYPE_BYTE4 : IMAGE_DATA_TYPE_BYTE;
+ }
+
+ return true;
+ }
+
+ /* Perform preliminary checks, with meaningful logging. */
+ if (!path_exists(filename)) {
+ VLOG(1) << "File '" << filename << "' does not exist.";
+ return false;
+ }
+ if (path_is_directory(filename)) {
+ VLOG(1) << "File '" << filename << "' is a directory, can't use as image.";
+ return false;
+ }
+
+ unique_ptr<ImageInput> in(ImageInput::create(filename));
+
+ if (!in) {
+ return false;
+ }
+
+ ImageSpec spec;
+ if (!in->open(filename, spec)) {
+ return false;
+ }
+
+ metadata.width = spec.width;
+ metadata.height = spec.height;
+ metadata.depth = spec.depth;
+
+ /* Check the main format, and channel formats. */
+ size_t channel_size = spec.format.basesize();
+
+ if (spec.format.is_floating_point()) {
+ metadata.is_float = true;
+ metadata.is_linear = true;
+ }
+
+ for (size_t channel = 0; channel < spec.channelformats.size(); channel++) {
+ channel_size = max(channel_size, spec.channelformats[channel].basesize());
+ if (spec.channelformats[channel].is_floating_point()) {
+ metadata.is_float = true;
+ metadata.is_linear = true;
+ }
+ }
+
+ /* check if it's half float */
+ if (spec.format == TypeDesc::HALF) {
+ metadata.is_half = true;
+ }
+
+ /* basic color space detection, not great but better than nothing
+ * before we do OpenColorIO integration */
+ if (metadata.is_float) {
+ string colorspace = spec.get_string_attribute("oiio:ColorSpace");
+
+ metadata.is_linear = !(
+ colorspace == "sRGB" || colorspace == "GammaCorrected" ||
+ (colorspace == "" &&
+ (strcmp(in->format_name(), "png") == 0 || strcmp(in->format_name(), "tiff") == 0 ||
+ strcmp(in->format_name(), "dpx") == 0 || strcmp(in->format_name(), "jpeg2000") == 0)));
+ }
+ else {
+ metadata.is_linear = false;
+ }
+
+ /* set type and channels */
+ metadata.channels = spec.nchannels;
+
+ if (metadata.is_half) {
+ metadata.type = (metadata.channels > 1) ? IMAGE_DATA_TYPE_HALF4 : IMAGE_DATA_TYPE_HALF;
+ }
+ else if (metadata.is_float) {
+ metadata.type = (metadata.channels > 1) ? IMAGE_DATA_TYPE_FLOAT4 : IMAGE_DATA_TYPE_FLOAT;
+ }
+ else if (spec.format == TypeDesc::USHORT) {
+ metadata.type = (metadata.channels > 1) ? IMAGE_DATA_TYPE_USHORT4 : IMAGE_DATA_TYPE_USHORT;
+ }
+ else {
+ metadata.type = (metadata.channels > 1) ? IMAGE_DATA_TYPE_BYTE4 : IMAGE_DATA_TYPE_BYTE;
+ }
+
+ in->close();
+
+ return true;
}
static bool image_equals(ImageManager::Image *image,
- const string& filename,
+ const string &filename,
void *builtin_data,
InterpolationType interpolation,
ExtensionType extension,
bool use_alpha)
{
- return image->filename == filename &&
- image->builtin_data == builtin_data &&
- image->interpolation == interpolation &&
- image->extension == extension &&
- image->use_alpha == use_alpha;
+ return image->filename == filename && image->builtin_data == builtin_data &&
+ image->interpolation == interpolation && image->extension == extension &&
+ image->use_alpha == use_alpha;
}
-int ImageManager::add_image(const string& filename,
+int ImageManager::add_image(const string &filename,
void *builtin_data,
bool animated,
float frame,
InterpolationType interpolation,
ExtensionType extension,
bool use_alpha,
- ImageMetaData& metadata)
+ ImageMetaData &metadata)
{
- Image *img;
- size_t slot;
-
- get_image_metadata(filename, builtin_data, metadata);
- ImageDataType type = metadata.type;
-
- thread_scoped_lock device_lock(device_mutex);
-
- /* No half textures on OpenCL, use full float instead. */
- if(!has_half_images) {
- if(type == IMAGE_DATA_TYPE_HALF4) {
- type = IMAGE_DATA_TYPE_FLOAT4;
- }
- else if(type == IMAGE_DATA_TYPE_HALF) {
- type = IMAGE_DATA_TYPE_FLOAT;
- }
- }
-
- /* Fnd existing image. */
- for(slot = 0; slot < images[type].size(); slot++) {
- img = images[type][slot];
- if(img && image_equals(img,
- filename,
- builtin_data,
- interpolation,
- extension,
- use_alpha))
- {
- if(img->frame != frame) {
- img->frame = frame;
- img->need_load = true;
- }
- if(img->use_alpha != use_alpha) {
- img->use_alpha = use_alpha;
- img->need_load = true;
- }
- if(!(img->metadata == metadata)) {
- img->metadata = metadata;
- img->need_load = true;
- }
- img->users++;
- return type_index_to_flattened_slot(slot, type);
- }
- }
-
- /* Find free slot. */
- for(slot = 0; slot < images[type].size(); slot++) {
- if(!images[type][slot])
- break;
- }
-
- /* Count if we're over the limit.
- * Very unlikely, since max_num_images is insanely big. But better safe
- * than sorry.
- */
- int tex_count = 0;
- for(int type = 0; type < IMAGE_DATA_NUM_TYPES; type++) {
- tex_count += tex_num_images[type];
- }
- if(tex_count > max_num_images) {
- printf("ImageManager::add_image: Reached image limit (%d), "
- "skipping '%s'\n", max_num_images, filename.c_str());
- return -1;
- }
-
- if(slot == images[type].size()) {
- images[type].resize(images[type].size() + 1);
- }
-
- /* Add new image. */
- img = new Image();
- img->filename = filename;
- img->builtin_data = builtin_data;
- img->metadata = metadata;
- img->need_load = true;
- img->animated = animated;
- img->frame = frame;
- img->interpolation = interpolation;
- img->extension = extension;
- img->users = 1;
- img->use_alpha = use_alpha;
- img->mem = NULL;
-
- images[type][slot] = img;
-
- ++tex_num_images[type];
-
- need_update = true;
-
- return type_index_to_flattened_slot(slot, type);
+ Image *img;
+ size_t slot;
+
+ get_image_metadata(filename, builtin_data, metadata);
+ ImageDataType type = metadata.type;
+
+ thread_scoped_lock device_lock(device_mutex);
+
+ /* No half textures on OpenCL, use full float instead. */
+ if (!has_half_images) {
+ if (type == IMAGE_DATA_TYPE_HALF4) {
+ type = IMAGE_DATA_TYPE_FLOAT4;
+ }
+ else if (type == IMAGE_DATA_TYPE_HALF) {
+ type = IMAGE_DATA_TYPE_FLOAT;
+ }
+ }
+
+ /* Fnd existing image. */
+ for (slot = 0; slot < images[type].size(); slot++) {
+ img = images[type][slot];
+ if (img && image_equals(img, filename, builtin_data, interpolation, extension, use_alpha)) {
+ if (img->frame != frame) {
+ img->frame = frame;
+ img->need_load = true;
+ }
+ if (img->use_alpha != use_alpha) {
+ img->use_alpha = use_alpha;
+ img->need_load = true;
+ }
+ if (!(img->metadata == metadata)) {
+ img->metadata = metadata;
+ img->need_load = true;
+ }
+ img->users++;
+ return type_index_to_flattened_slot(slot, type);
+ }
+ }
+
+ /* Find free slot. */
+ for (slot = 0; slot < images[type].size(); slot++) {
+ if (!images[type][slot])
+ break;
+ }
+
+ /* Count if we're over the limit.
+ * Very unlikely, since max_num_images is insanely big. But better safe
+ * than sorry.
+ */
+ int tex_count = 0;
+ for (int type = 0; type < IMAGE_DATA_NUM_TYPES; type++) {
+ tex_count += tex_num_images[type];
+ }
+ if (tex_count > max_num_images) {
+ printf(
+ "ImageManager::add_image: Reached image limit (%d), "
+ "skipping '%s'\n",
+ max_num_images,
+ filename.c_str());
+ return -1;
+ }
+
+ if (slot == images[type].size()) {
+ images[type].resize(images[type].size() + 1);
+ }
+
+ /* Add new image. */
+ img = new Image();
+ img->filename = filename;
+ img->builtin_data = builtin_data;
+ img->metadata = metadata;
+ img->need_load = true;
+ img->animated = animated;
+ img->frame = frame;
+ img->interpolation = interpolation;
+ img->extension = extension;
+ img->users = 1;
+ img->use_alpha = use_alpha;
+ img->mem = NULL;
+
+ images[type][slot] = img;
+
+ ++tex_num_images[type];
+
+ need_update = true;
+
+ return type_index_to_flattened_slot(slot, type);
}
void ImageManager::remove_image(int flat_slot)
{
- ImageDataType type;
- int slot = flattened_slot_to_type_index(flat_slot, &type);
+ ImageDataType type;
+ int slot = flattened_slot_to_type_index(flat_slot, &type);
- Image *image = images[type][slot];
- assert(image && image->users >= 1);
+ Image *image = images[type][slot];
+ assert(image && image->users >= 1);
- /* decrement user count */
- image->users--;
+ /* decrement user count */
+ image->users--;
- /* don't remove immediately, rather do it all together later on. one of
- * the reasons for this is that on shader changes we add and remove nodes
- * that use them, but we do not want to reload the image all the time. */
- if(image->users == 0)
- need_update = true;
+ /* don't remove immediately, rather do it all together later on. one of
+ * the reasons for this is that on shader changes we add and remove nodes
+ * that use them, but we do not want to reload the image all the time. */
+ if (image->users == 0)
+ need_update = true;
}
-void ImageManager::remove_image(const string& filename,
+void ImageManager::remove_image(const string &filename,
void *builtin_data,
InterpolationType interpolation,
ExtensionType extension,
bool use_alpha)
{
- size_t slot;
-
- for(int type = 0; type < IMAGE_DATA_NUM_TYPES; type++) {
- for(slot = 0; slot < images[type].size(); slot++) {
- if(images[type][slot] && image_equals(images[type][slot],
- filename,
- builtin_data,
- interpolation,
- extension,
- use_alpha))
- {
- remove_image(type_index_to_flattened_slot(slot, (ImageDataType)type));
- return;
- }
- }
- }
+ size_t slot;
+
+ for (int type = 0; type < IMAGE_DATA_NUM_TYPES; type++) {
+ for (slot = 0; slot < images[type].size(); slot++) {
+ if (images[type][slot] &&
+ image_equals(
+ images[type][slot], filename, builtin_data, interpolation, extension, use_alpha)) {
+ remove_image(type_index_to_flattened_slot(slot, (ImageDataType)type));
+ return;
+ }
+ }
+ }
}
/* TODO(sergey): Deduplicate with the iteration above, but make it pretty,
* without bunch of arguments passing around making code readability even
* more cluttered.
*/
-void ImageManager::tag_reload_image(const string& filename,
+void ImageManager::tag_reload_image(const string &filename,
void *builtin_data,
InterpolationType interpolation,
ExtensionType extension,
bool use_alpha)
{
- for(size_t type = 0; type < IMAGE_DATA_NUM_TYPES; type++) {
- for(size_t slot = 0; slot < images[type].size(); slot++) {
- if(images[type][slot] && image_equals(images[type][slot],
- filename,
- builtin_data,
- interpolation,
- extension,
- use_alpha))
- {
- images[type][slot]->need_load = true;
- break;
- }
- }
- }
+ for (size_t type = 0; type < IMAGE_DATA_NUM_TYPES; type++) {
+ for (size_t slot = 0; slot < images[type].size(); slot++) {
+ if (images[type][slot] &&
+ image_equals(
+ images[type][slot], filename, builtin_data, interpolation, extension, use_alpha)) {
+ images[type][slot]->need_load = true;
+ break;
+ }
+ }
+ }
}
-bool ImageManager::file_load_image_generic(Image *img,
- unique_ptr<ImageInput> *in)
+bool ImageManager::file_load_image_generic(Image *img, unique_ptr<ImageInput> *in)
{
- if(img->filename == "")
- return false;
-
- if(!img->builtin_data) {
- /* NOTE: Error logging is done in meta data acquisition. */
- if(!path_exists(img->filename) || path_is_directory(img->filename)) {
- return false;
- }
-
- /* load image from file through OIIO */
- *in = unique_ptr<ImageInput>(ImageInput::create(img->filename));
-
- if(!*in)
- return false;
-
- ImageSpec spec = ImageSpec();
- ImageSpec config = ImageSpec();
-
- if(img->use_alpha == false)
- config.attribute("oiio:UnassociatedAlpha", 1);
-
- if(!(*in)->open(img->filename, spec, config)) {
- return false;
- }
- }
- else {
- /* load image using builtin images callbacks */
- if(!builtin_image_info_cb || !builtin_image_pixels_cb)
- return false;
- }
-
- /* we only handle certain number of components */
- if(!(img->metadata.channels >= 1 && img->metadata.channels <= 4)) {
- if(*in) {
- (*in)->close();
- }
- return false;
- }
-
- return true;
+ if (img->filename == "")
+ return false;
+
+ if (!img->builtin_data) {
+ /* NOTE: Error logging is done in meta data acquisition. */
+ if (!path_exists(img->filename) || path_is_directory(img->filename)) {
+ return false;
+ }
+
+ /* load image from file through OIIO */
+ *in = unique_ptr<ImageInput>(ImageInput::create(img->filename));
+
+ if (!*in)
+ return false;
+
+ ImageSpec spec = ImageSpec();
+ ImageSpec config = ImageSpec();
+
+ if (img->use_alpha == false)
+ config.attribute("oiio:UnassociatedAlpha", 1);
+
+ if (!(*in)->open(img->filename, spec, config)) {
+ return false;
+ }
+ }
+ else {
+ /* load image using builtin images callbacks */
+ if (!builtin_image_info_cb || !builtin_image_pixels_cb)
+ return false;
+ }
+
+ /* we only handle certain number of components */
+ if (!(img->metadata.channels >= 1 && img->metadata.channels <= 4)) {
+ if (*in) {
+ (*in)->close();
+ }
+ return false;
+ }
+
+ return true;
}
-template<TypeDesc::BASETYPE FileFormat,
- typename StorageType,
- typename DeviceType>
+template<TypeDesc::BASETYPE FileFormat, typename StorageType, typename DeviceType>
bool ImageManager::file_load_image(Image *img,
ImageDataType type,
int texture_limit,
- device_vector<DeviceType>& tex_img)
+ device_vector<DeviceType> &tex_img)
{
- unique_ptr<ImageInput> in = NULL;
- if(!file_load_image_generic(img, &in)) {
- return false;
- }
-
- /* Get metadata. */
- int width = img->metadata.width;
- int height = img->metadata.height;
- int depth = img->metadata.depth;
- int components = img->metadata.channels;
-
- /* Read RGBA pixels. */
- vector<StorageType> pixels_storage;
- StorageType *pixels;
- const size_t max_size = max(max(width, height), depth);
- if(max_size == 0) {
- /* Don't bother with invalid images. */
- return false;
- }
- if(texture_limit > 0 && max_size > texture_limit) {
- pixels_storage.resize(((size_t)width)*height*depth*4);
- pixels = &pixels_storage[0];
- }
- else {
- thread_scoped_lock device_lock(device_mutex);
- pixels = (StorageType*)tex_img.alloc(width, height, depth);
- }
- if(pixels == NULL) {
- /* Could be that we've run out of memory. */
- return false;
- }
- bool cmyk = false;
- const size_t num_pixels = ((size_t)width) * height * depth;
- if(in) {
- StorageType *readpixels = pixels;
- vector<StorageType> tmppixels;
- if(components > 4) {
- tmppixels.resize(((size_t)width)*height*components);
- readpixels = &tmppixels[0];
- }
- if(depth <= 1) {
- size_t scanlinesize = ((size_t)width)*components*sizeof(StorageType);
- in->read_image(FileFormat,
- (uchar*)readpixels + (height-1)*scanlinesize,
- AutoStride,
- -scanlinesize,
- AutoStride);
- }
- else {
- in->read_image(FileFormat, (uchar*)readpixels);
- }
- if(components > 4) {
- size_t dimensions = ((size_t)width)*height;
- for(size_t i = dimensions-1, pixel = 0; pixel < dimensions; pixel++, i--) {
- pixels[i*4+3] = tmppixels[i*components+3];
- pixels[i*4+2] = tmppixels[i*components+2];
- pixels[i*4+1] = tmppixels[i*components+1];
- pixels[i*4+0] = tmppixels[i*components+0];
- }
- tmppixels.clear();
- }
- cmyk = strcmp(in->format_name(), "jpeg") == 0 && components == 4;
- in->close();
- }
- else {
- if(FileFormat == TypeDesc::FLOAT) {
- builtin_image_float_pixels_cb(img->filename,
- img->builtin_data,
- (float*)&pixels[0],
- num_pixels * components,
- img->metadata.builtin_free_cache);
- }
- else if(FileFormat == TypeDesc::UINT8) {
- builtin_image_pixels_cb(img->filename,
- img->builtin_data,
- (uchar*)&pixels[0],
- num_pixels * components,
- img->metadata.builtin_free_cache);
- }
- else {
- /* TODO(dingto): Support half for ImBuf. */
- }
- }
- /* Check if we actually have a float4 slot, in case components == 1,
- * but device doesn't support single channel textures.
- */
- bool is_rgba = (type == IMAGE_DATA_TYPE_FLOAT4 ||
- type == IMAGE_DATA_TYPE_HALF4 ||
- type == IMAGE_DATA_TYPE_BYTE4 ||
- type == IMAGE_DATA_TYPE_USHORT4);
- if(is_rgba) {
- const StorageType one = util_image_cast_from_float<StorageType>(1.0f);
-
- if(cmyk) {
- /* CMYK */
- for(size_t i = num_pixels-1, pixel = 0; pixel < num_pixels; pixel++, i--) {
- float c = util_image_cast_to_float(pixels[i*4+0]);
- float m = util_image_cast_to_float(pixels[i*4+1]);
- float y = util_image_cast_to_float(pixels[i*4+2]);
- float k = util_image_cast_to_float(pixels[i*4+3]);
- pixels[i*4+0] = util_image_cast_from_float<StorageType>((1.0f - c) * (1.0f - k));
- pixels[i*4+1] = util_image_cast_from_float<StorageType>((1.0f - m) * (1.0f - k));
- pixels[i*4+2] = util_image_cast_from_float<StorageType>((1.0f - y) * (1.0f - k));
- pixels[i*4+3] = one;
- }
- }
- else if(components == 2) {
- /* grayscale + alpha */
- for(size_t i = num_pixels-1, pixel = 0; pixel < num_pixels; pixel++, i--) {
- pixels[i*4+3] = pixels[i*2+1];
- pixels[i*4+2] = pixels[i*2+0];
- pixels[i*4+1] = pixels[i*2+0];
- pixels[i*4+0] = pixels[i*2+0];
- }
- }
- else if(components == 3) {
- /* RGB */
- for(size_t i = num_pixels-1, pixel = 0; pixel < num_pixels; pixel++, i--) {
- pixels[i*4+3] = one;
- pixels[i*4+2] = pixels[i*3+2];
- pixels[i*4+1] = pixels[i*3+1];
- pixels[i*4+0] = pixels[i*3+0];
- }
- }
- else if(components == 1) {
- /* grayscale */
- for(size_t i = num_pixels-1, pixel = 0; pixel < num_pixels; pixel++, i--) {
- pixels[i*4+3] = one;
- pixels[i*4+2] = pixels[i];
- pixels[i*4+1] = pixels[i];
- pixels[i*4+0] = pixels[i];
- }
- }
- if(img->use_alpha == false) {
- for(size_t i = num_pixels-1, pixel = 0; pixel < num_pixels; pixel++, i--) {
- pixels[i*4+3] = one;
- }
- }
- }
- /* Make sure we don't have buggy values. */
- if(FileFormat == TypeDesc::FLOAT) {
- /* For RGBA buffers we put all channels to 0 if either of them is not
- * finite. This way we avoid possible artifacts caused by fully changed
- * hue.
- */
- if(is_rgba) {
- for(size_t i = 0; i < num_pixels; i += 4) {
- StorageType *pixel = &pixels[i*4];
- if(!isfinite(pixel[0]) ||
- !isfinite(pixel[1]) ||
- !isfinite(pixel[2]) ||
- !isfinite(pixel[3]))
- {
- pixel[0] = 0;
- pixel[1] = 0;
- pixel[2] = 0;
- pixel[3] = 0;
- }
- }
- }
- else {
- for(size_t i = 0; i < num_pixels; ++i) {
- StorageType *pixel = &pixels[i];
- if(!isfinite(pixel[0])) {
- pixel[0] = 0;
- }
- }
- }
- }
- /* Scale image down if needed. */
- if(pixels_storage.size() > 0) {
- float scale_factor = 1.0f;
- while(max_size * scale_factor > texture_limit) {
- scale_factor *= 0.5f;
- }
- VLOG(1) << "Scaling image " << img->filename
- << " by a factor of " << scale_factor << ".";
- vector<StorageType> scaled_pixels;
- size_t scaled_width, scaled_height, scaled_depth;
- util_image_resize_pixels(pixels_storage,
- width, height, depth,
- is_rgba ? 4 : 1,
- scale_factor,
- &scaled_pixels,
- &scaled_width, &scaled_height, &scaled_depth);
-
- StorageType *texture_pixels;
-
- {
- thread_scoped_lock device_lock(device_mutex);
- texture_pixels = (StorageType*)tex_img.alloc(scaled_width,
- scaled_height,
- scaled_depth);
- }
-
- memcpy(texture_pixels,
- &scaled_pixels[0],
- scaled_pixels.size() * sizeof(StorageType));
- }
- return true;
+ unique_ptr<ImageInput> in = NULL;
+ if (!file_load_image_generic(img, &in)) {
+ return false;
+ }
+
+ /* Get metadata. */
+ int width = img->metadata.width;
+ int height = img->metadata.height;
+ int depth = img->metadata.depth;
+ int components = img->metadata.channels;
+
+ /* Read RGBA pixels. */
+ vector<StorageType> pixels_storage;
+ StorageType *pixels;
+ const size_t max_size = max(max(width, height), depth);
+ if (max_size == 0) {
+ /* Don't bother with invalid images. */
+ return false;
+ }
+ if (texture_limit > 0 && max_size > texture_limit) {
+ pixels_storage.resize(((size_t)width) * height * depth * 4);
+ pixels = &pixels_storage[0];
+ }
+ else {
+ thread_scoped_lock device_lock(device_mutex);
+ pixels = (StorageType *)tex_img.alloc(width, height, depth);
+ }
+ if (pixels == NULL) {
+ /* Could be that we've run out of memory. */
+ return false;
+ }
+ bool cmyk = false;
+ const size_t num_pixels = ((size_t)width) * height * depth;
+ if (in) {
+ StorageType *readpixels = pixels;
+ vector<StorageType> tmppixels;
+ if (components > 4) {
+ tmppixels.resize(((size_t)width) * height * components);
+ readpixels = &tmppixels[0];
+ }
+ if (depth <= 1) {
+ size_t scanlinesize = ((size_t)width) * components * sizeof(StorageType);
+ in->read_image(FileFormat,
+ (uchar *)readpixels + (height - 1) * scanlinesize,
+ AutoStride,
+ -scanlinesize,
+ AutoStride);
+ }
+ else {
+ in->read_image(FileFormat, (uchar *)readpixels);
+ }
+ if (components > 4) {
+ size_t dimensions = ((size_t)width) * height;
+ for (size_t i = dimensions - 1, pixel = 0; pixel < dimensions; pixel++, i--) {
+ pixels[i * 4 + 3] = tmppixels[i * components + 3];
+ pixels[i * 4 + 2] = tmppixels[i * components + 2];
+ pixels[i * 4 + 1] = tmppixels[i * components + 1];
+ pixels[i * 4 + 0] = tmppixels[i * components + 0];
+ }
+ tmppixels.clear();
+ }
+ cmyk = strcmp(in->format_name(), "jpeg") == 0 && components == 4;
+ in->close();
+ }
+ else {
+ if (FileFormat == TypeDesc::FLOAT) {
+ builtin_image_float_pixels_cb(img->filename,
+ img->builtin_data,
+ (float *)&pixels[0],
+ num_pixels * components,
+ img->metadata.builtin_free_cache);
+ }
+ else if (FileFormat == TypeDesc::UINT8) {
+ builtin_image_pixels_cb(img->filename,
+ img->builtin_data,
+ (uchar *)&pixels[0],
+ num_pixels * components,
+ img->metadata.builtin_free_cache);
+ }
+ else {
+ /* TODO(dingto): Support half for ImBuf. */
+ }
+ }
+ /* Check if we actually have a float4 slot, in case components == 1,
+ * but device doesn't support single channel textures.
+ */
+ bool is_rgba = (type == IMAGE_DATA_TYPE_FLOAT4 || type == IMAGE_DATA_TYPE_HALF4 ||
+ type == IMAGE_DATA_TYPE_BYTE4 || type == IMAGE_DATA_TYPE_USHORT4);
+ if (is_rgba) {
+ const StorageType one = util_image_cast_from_float<StorageType>(1.0f);
+
+ if (cmyk) {
+ /* CMYK */
+ for (size_t i = num_pixels - 1, pixel = 0; pixel < num_pixels; pixel++, i--) {
+ float c = util_image_cast_to_float(pixels[i * 4 + 0]);
+ float m = util_image_cast_to_float(pixels[i * 4 + 1]);
+ float y = util_image_cast_to_float(pixels[i * 4 + 2]);
+ float k = util_image_cast_to_float(pixels[i * 4 + 3]);
+ pixels[i * 4 + 0] = util_image_cast_from_float<StorageType>((1.0f - c) * (1.0f - k));
+ pixels[i * 4 + 1] = util_image_cast_from_float<StorageType>((1.0f - m) * (1.0f - k));
+ pixels[i * 4 + 2] = util_image_cast_from_float<StorageType>((1.0f - y) * (1.0f - k));
+ pixels[i * 4 + 3] = one;
+ }
+ }
+ else if (components == 2) {
+ /* grayscale + alpha */
+ for (size_t i = num_pixels - 1, pixel = 0; pixel < num_pixels; pixel++, i--) {
+ pixels[i * 4 + 3] = pixels[i * 2 + 1];
+ pixels[i * 4 + 2] = pixels[i * 2 + 0];
+ pixels[i * 4 + 1] = pixels[i * 2 + 0];
+ pixels[i * 4 + 0] = pixels[i * 2 + 0];
+ }
+ }
+ else if (components == 3) {
+ /* RGB */
+ for (size_t i = num_pixels - 1, pixel = 0; pixel < num_pixels; pixel++, i--) {
+ pixels[i * 4 + 3] = one;
+ pixels[i * 4 + 2] = pixels[i * 3 + 2];
+ pixels[i * 4 + 1] = pixels[i * 3 + 1];
+ pixels[i * 4 + 0] = pixels[i * 3 + 0];
+ }
+ }
+ else if (components == 1) {
+ /* grayscale */
+ for (size_t i = num_pixels - 1, pixel = 0; pixel < num_pixels; pixel++, i--) {
+ pixels[i * 4 + 3] = one;
+ pixels[i * 4 + 2] = pixels[i];
+ pixels[i * 4 + 1] = pixels[i];
+ pixels[i * 4 + 0] = pixels[i];
+ }
+ }
+ if (img->use_alpha == false) {
+ for (size_t i = num_pixels - 1, pixel = 0; pixel < num_pixels; pixel++, i--) {
+ pixels[i * 4 + 3] = one;
+ }
+ }
+ }
+ /* Make sure we don't have buggy values. */
+ if (FileFormat == TypeDesc::FLOAT) {
+ /* For RGBA buffers we put all channels to 0 if either of them is not
+ * finite. This way we avoid possible artifacts caused by fully changed
+ * hue.
+ */
+ if (is_rgba) {
+ for (size_t i = 0; i < num_pixels; i += 4) {
+ StorageType *pixel = &pixels[i * 4];
+ if (!isfinite(pixel[0]) || !isfinite(pixel[1]) || !isfinite(pixel[2]) ||
+ !isfinite(pixel[3])) {
+ pixel[0] = 0;
+ pixel[1] = 0;
+ pixel[2] = 0;
+ pixel[3] = 0;
+ }
+ }
+ }
+ else {
+ for (size_t i = 0; i < num_pixels; ++i) {
+ StorageType *pixel = &pixels[i];
+ if (!isfinite(pixel[0])) {
+ pixel[0] = 0;
+ }
+ }
+ }
+ }
+ /* Scale image down if needed. */
+ if (pixels_storage.size() > 0) {
+ float scale_factor = 1.0f;
+ while (max_size * scale_factor > texture_limit) {
+ scale_factor *= 0.5f;
+ }
+ VLOG(1) << "Scaling image " << img->filename << " by a factor of " << scale_factor << ".";
+ vector<StorageType> scaled_pixels;
+ size_t scaled_width, scaled_height, scaled_depth;
+ util_image_resize_pixels(pixels_storage,
+ width,
+ height,
+ depth,
+ is_rgba ? 4 : 1,
+ scale_factor,
+ &scaled_pixels,
+ &scaled_width,
+ &scaled_height,
+ &scaled_depth);
+
+ StorageType *texture_pixels;
+
+ {
+ thread_scoped_lock device_lock(device_mutex);
+ texture_pixels = (StorageType *)tex_img.alloc(scaled_width, scaled_height, scaled_depth);
+ }
+
+ memcpy(texture_pixels, &scaled_pixels[0], scaled_pixels.size() * sizeof(StorageType));
+ }
+ return true;
}
-void ImageManager::device_load_image(Device *device,
- Scene *scene,
- ImageDataType type,
- int slot,
- Progress *progress)
+void ImageManager::device_load_image(
+ Device *device, Scene *scene, ImageDataType type, int slot, Progress *progress)
{
- if(progress->get_cancel())
- return;
-
- Image *img = images[type][slot];
-
- if(osl_texture_system && !img->builtin_data)
- return;
-
- string filename = path_filename(images[type][slot]->filename);
- progress->set_status("Updating Images", "Loading " + filename);
-
- const int texture_limit = scene->params.texture_limit;
-
- /* Slot assignment */
- int flat_slot = type_index_to_flattened_slot(slot, type);
- img->mem_name = string_printf("__tex_image_%s_%03d",
- name_from_type(type), flat_slot);
-
- /* Free previous texture in slot. */
- if(img->mem) {
- thread_scoped_lock device_lock(device_mutex);
- delete img->mem;
- img->mem = NULL;
- }
-
- /* Create new texture. */
- if(type == IMAGE_DATA_TYPE_FLOAT4) {
- device_vector<float4> *tex_img
- = new device_vector<float4>(device, img->mem_name.c_str(), MEM_TEXTURE);
-
- if(!file_load_image<TypeDesc::FLOAT, float>(img,
- type,
- texture_limit,
- *tex_img))
- {
- /* on failure to load, we set a 1x1 pixels pink image */
- thread_scoped_lock device_lock(device_mutex);
- float *pixels = (float*)tex_img->alloc(1, 1);
-
- pixels[0] = TEX_IMAGE_MISSING_R;
- pixels[1] = TEX_IMAGE_MISSING_G;
- pixels[2] = TEX_IMAGE_MISSING_B;
- pixels[3] = TEX_IMAGE_MISSING_A;
- }
-
- img->mem = tex_img;
- img->mem->interpolation = img->interpolation;
- img->mem->extension = img->extension;
-
- thread_scoped_lock device_lock(device_mutex);
- tex_img->copy_to_device();
- }
- else if(type == IMAGE_DATA_TYPE_FLOAT) {
- device_vector<float> *tex_img
- = new device_vector<float>(device, img->mem_name.c_str(), MEM_TEXTURE);
-
- if(!file_load_image<TypeDesc::FLOAT, float>(img,
- type,
- texture_limit,
- *tex_img))
- {
- /* on failure to load, we set a 1x1 pixels pink image */
- thread_scoped_lock device_lock(device_mutex);
- float *pixels = (float*)tex_img->alloc(1, 1);
-
- pixels[0] = TEX_IMAGE_MISSING_R;
- }
-
- img->mem = tex_img;
- img->mem->interpolation = img->interpolation;
- img->mem->extension = img->extension;
-
- thread_scoped_lock device_lock(device_mutex);
- tex_img->copy_to_device();
- }
- else if(type == IMAGE_DATA_TYPE_BYTE4) {
- device_vector<uchar4> *tex_img
- = new device_vector<uchar4>(device, img->mem_name.c_str(), MEM_TEXTURE);
-
- if(!file_load_image<TypeDesc::UINT8, uchar>(img,
- type,
- texture_limit,
- *tex_img))
- {
- /* on failure to load, we set a 1x1 pixels pink image */
- thread_scoped_lock device_lock(device_mutex);
- uchar *pixels = (uchar*)tex_img->alloc(1, 1);
-
- pixels[0] = (TEX_IMAGE_MISSING_R * 255);
- pixels[1] = (TEX_IMAGE_MISSING_G * 255);
- pixels[2] = (TEX_IMAGE_MISSING_B * 255);
- pixels[3] = (TEX_IMAGE_MISSING_A * 255);
- }
-
- img->mem = tex_img;
- img->mem->interpolation = img->interpolation;
- img->mem->extension = img->extension;
-
- thread_scoped_lock device_lock(device_mutex);
- tex_img->copy_to_device();
- }
- else if(type == IMAGE_DATA_TYPE_BYTE) {
- device_vector<uchar> *tex_img
- = new device_vector<uchar>(device, img->mem_name.c_str(), MEM_TEXTURE);
-
- if(!file_load_image<TypeDesc::UINT8, uchar>(img,
- type,
- texture_limit,
- *tex_img)) {
- /* on failure to load, we set a 1x1 pixels pink image */
- thread_scoped_lock device_lock(device_mutex);
- uchar *pixels = (uchar*)tex_img->alloc(1, 1);
-
- pixels[0] = (TEX_IMAGE_MISSING_R * 255);
- }
-
- img->mem = tex_img;
- img->mem->interpolation = img->interpolation;
- img->mem->extension = img->extension;
-
- thread_scoped_lock device_lock(device_mutex);
- tex_img->copy_to_device();
- }
- else if(type == IMAGE_DATA_TYPE_HALF4) {
- device_vector<half4> *tex_img
- = new device_vector<half4>(device, img->mem_name.c_str(), MEM_TEXTURE);
-
- if(!file_load_image<TypeDesc::HALF, half>(img,
- type,
- texture_limit,
- *tex_img)) {
- /* on failure to load, we set a 1x1 pixels pink image */
- thread_scoped_lock device_lock(device_mutex);
- half *pixels = (half*)tex_img->alloc(1, 1);
-
- pixels[0] = TEX_IMAGE_MISSING_R;
- pixels[1] = TEX_IMAGE_MISSING_G;
- pixels[2] = TEX_IMAGE_MISSING_B;
- pixels[3] = TEX_IMAGE_MISSING_A;
- }
-
- img->mem = tex_img;
- img->mem->interpolation = img->interpolation;
- img->mem->extension = img->extension;
-
- thread_scoped_lock device_lock(device_mutex);
- tex_img->copy_to_device();
- }
- else if(type == IMAGE_DATA_TYPE_USHORT) {
- device_vector<uint16_t> *tex_img
- = new device_vector<uint16_t>(device, img->mem_name.c_str(), MEM_TEXTURE);
-
- if(!file_load_image<TypeDesc::USHORT, uint16_t>(img,
- type,
- texture_limit,
- *tex_img)) {
- /* on failure to load, we set a 1x1 pixels pink image */
- thread_scoped_lock device_lock(device_mutex);
- uint16_t *pixels = (uint16_t*)tex_img->alloc(1, 1);
-
- pixels[0] = (TEX_IMAGE_MISSING_R * 65535);
- }
-
- img->mem = tex_img;
- img->mem->interpolation = img->interpolation;
- img->mem->extension = img->extension;
-
- thread_scoped_lock device_lock(device_mutex);
- tex_img->copy_to_device();
- }
- else if(type == IMAGE_DATA_TYPE_USHORT4) {
- device_vector<ushort4> *tex_img
- = new device_vector<ushort4>(device, img->mem_name.c_str(), MEM_TEXTURE);
-
- if(!file_load_image<TypeDesc::USHORT, uint16_t>(img,
- type,
- texture_limit,
- *tex_img)) {
- /* on failure to load, we set a 1x1 pixels pink image */
- thread_scoped_lock device_lock(device_mutex);
- uint16_t *pixels = (uint16_t*)tex_img->alloc(1, 1);
-
- pixels[0] = (TEX_IMAGE_MISSING_R * 65535);
- pixels[1] = (TEX_IMAGE_MISSING_G * 65535);
- pixels[2] = (TEX_IMAGE_MISSING_B * 65535);
- pixels[3] = (TEX_IMAGE_MISSING_A * 65535);
- }
-
- img->mem = tex_img;
- img->mem->interpolation = img->interpolation;
- img->mem->extension = img->extension;
-
- thread_scoped_lock device_lock(device_mutex);
- tex_img->copy_to_device();
- }
- else if(type == IMAGE_DATA_TYPE_HALF) {
- device_vector<half> *tex_img
- = new device_vector<half>(device, img->mem_name.c_str(), MEM_TEXTURE);
-
- if(!file_load_image<TypeDesc::HALF, half>(img,
- type,
- texture_limit,
- *tex_img)) {
- /* on failure to load, we set a 1x1 pixels pink image */
- thread_scoped_lock device_lock(device_mutex);
- half *pixels = (half*)tex_img->alloc(1, 1);
-
- pixels[0] = TEX_IMAGE_MISSING_R;
- }
-
- img->mem = tex_img;
- img->mem->interpolation = img->interpolation;
- img->mem->extension = img->extension;
-
- thread_scoped_lock device_lock(device_mutex);
- tex_img->copy_to_device();
- }
- img->need_load = false;
+ if (progress->get_cancel())
+ return;
+
+ Image *img = images[type][slot];
+
+ if (osl_texture_system && !img->builtin_data)
+ return;
+
+ string filename = path_filename(images[type][slot]->filename);
+ progress->set_status("Updating Images", "Loading " + filename);
+
+ const int texture_limit = scene->params.texture_limit;
+
+ /* Slot assignment */
+ int flat_slot = type_index_to_flattened_slot(slot, type);
+ img->mem_name = string_printf("__tex_image_%s_%03d", name_from_type(type), flat_slot);
+
+ /* Free previous texture in slot. */
+ if (img->mem) {
+ thread_scoped_lock device_lock(device_mutex);
+ delete img->mem;
+ img->mem = NULL;
+ }
+
+ /* Create new texture. */
+ if (type == IMAGE_DATA_TYPE_FLOAT4) {
+ device_vector<float4> *tex_img = new device_vector<float4>(
+ device, img->mem_name.c_str(), MEM_TEXTURE);
+
+ if (!file_load_image<TypeDesc::FLOAT, float>(img, type, texture_limit, *tex_img)) {
+ /* on failure to load, we set a 1x1 pixels pink image */
+ thread_scoped_lock device_lock(device_mutex);
+ float *pixels = (float *)tex_img->alloc(1, 1);
+
+ pixels[0] = TEX_IMAGE_MISSING_R;
+ pixels[1] = TEX_IMAGE_MISSING_G;
+ pixels[2] = TEX_IMAGE_MISSING_B;
+ pixels[3] = TEX_IMAGE_MISSING_A;
+ }
+
+ img->mem = tex_img;
+ img->mem->interpolation = img->interpolation;
+ img->mem->extension = img->extension;
+
+ thread_scoped_lock device_lock(device_mutex);
+ tex_img->copy_to_device();
+ }
+ else if (type == IMAGE_DATA_TYPE_FLOAT) {
+ device_vector<float> *tex_img = new device_vector<float>(
+ device, img->mem_name.c_str(), MEM_TEXTURE);
+
+ if (!file_load_image<TypeDesc::FLOAT, float>(img, type, texture_limit, *tex_img)) {
+ /* on failure to load, we set a 1x1 pixels pink image */
+ thread_scoped_lock device_lock(device_mutex);
+ float *pixels = (float *)tex_img->alloc(1, 1);
+
+ pixels[0] = TEX_IMAGE_MISSING_R;
+ }
+
+ img->mem = tex_img;
+ img->mem->interpolation = img->interpolation;
+ img->mem->extension = img->extension;
+
+ thread_scoped_lock device_lock(device_mutex);
+ tex_img->copy_to_device();
+ }
+ else if (type == IMAGE_DATA_TYPE_BYTE4) {
+ device_vector<uchar4> *tex_img = new device_vector<uchar4>(
+ device, img->mem_name.c_str(), MEM_TEXTURE);
+
+ if (!file_load_image<TypeDesc::UINT8, uchar>(img, type, texture_limit, *tex_img)) {
+ /* on failure to load, we set a 1x1 pixels pink image */
+ thread_scoped_lock device_lock(device_mutex);
+ uchar *pixels = (uchar *)tex_img->alloc(1, 1);
+
+ pixels[0] = (TEX_IMAGE_MISSING_R * 255);
+ pixels[1] = (TEX_IMAGE_MISSING_G * 255);
+ pixels[2] = (TEX_IMAGE_MISSING_B * 255);
+ pixels[3] = (TEX_IMAGE_MISSING_A * 255);
+ }
+
+ img->mem = tex_img;
+ img->mem->interpolation = img->interpolation;
+ img->mem->extension = img->extension;
+
+ thread_scoped_lock device_lock(device_mutex);
+ tex_img->copy_to_device();
+ }
+ else if (type == IMAGE_DATA_TYPE_BYTE) {
+ device_vector<uchar> *tex_img = new device_vector<uchar>(
+ device, img->mem_name.c_str(), MEM_TEXTURE);
+
+ if (!file_load_image<TypeDesc::UINT8, uchar>(img, type, texture_limit, *tex_img)) {
+ /* on failure to load, we set a 1x1 pixels pink image */
+ thread_scoped_lock device_lock(device_mutex);
+ uchar *pixels = (uchar *)tex_img->alloc(1, 1);
+
+ pixels[0] = (TEX_IMAGE_MISSING_R * 255);
+ }
+
+ img->mem = tex_img;
+ img->mem->interpolation = img->interpolation;
+ img->mem->extension = img->extension;
+
+ thread_scoped_lock device_lock(device_mutex);
+ tex_img->copy_to_device();
+ }
+ else if (type == IMAGE_DATA_TYPE_HALF4) {
+ device_vector<half4> *tex_img = new device_vector<half4>(
+ device, img->mem_name.c_str(), MEM_TEXTURE);
+
+ if (!file_load_image<TypeDesc::HALF, half>(img, type, texture_limit, *tex_img)) {
+ /* on failure to load, we set a 1x1 pixels pink image */
+ thread_scoped_lock device_lock(device_mutex);
+ half *pixels = (half *)tex_img->alloc(1, 1);
+
+ pixels[0] = TEX_IMAGE_MISSING_R;
+ pixels[1] = TEX_IMAGE_MISSING_G;
+ pixels[2] = TEX_IMAGE_MISSING_B;
+ pixels[3] = TEX_IMAGE_MISSING_A;
+ }
+
+ img->mem = tex_img;
+ img->mem->interpolation = img->interpolation;
+ img->mem->extension = img->extension;
+
+ thread_scoped_lock device_lock(device_mutex);
+ tex_img->copy_to_device();
+ }
+ else if (type == IMAGE_DATA_TYPE_USHORT) {
+ device_vector<uint16_t> *tex_img = new device_vector<uint16_t>(
+ device, img->mem_name.c_str(), MEM_TEXTURE);
+
+ if (!file_load_image<TypeDesc::USHORT, uint16_t>(img, type, texture_limit, *tex_img)) {
+ /* on failure to load, we set a 1x1 pixels pink image */
+ thread_scoped_lock device_lock(device_mutex);
+ uint16_t *pixels = (uint16_t *)tex_img->alloc(1, 1);
+
+ pixels[0] = (TEX_IMAGE_MISSING_R * 65535);
+ }
+
+ img->mem = tex_img;
+ img->mem->interpolation = img->interpolation;
+ img->mem->extension = img->extension;
+
+ thread_scoped_lock device_lock(device_mutex);
+ tex_img->copy_to_device();
+ }
+ else if (type == IMAGE_DATA_TYPE_USHORT4) {
+ device_vector<ushort4> *tex_img = new device_vector<ushort4>(
+ device, img->mem_name.c_str(), MEM_TEXTURE);
+
+ if (!file_load_image<TypeDesc::USHORT, uint16_t>(img, type, texture_limit, *tex_img)) {
+ /* on failure to load, we set a 1x1 pixels pink image */
+ thread_scoped_lock device_lock(device_mutex);
+ uint16_t *pixels = (uint16_t *)tex_img->alloc(1, 1);
+
+ pixels[0] = (TEX_IMAGE_MISSING_R * 65535);
+ pixels[1] = (TEX_IMAGE_MISSING_G * 65535);
+ pixels[2] = (TEX_IMAGE_MISSING_B * 65535);
+ pixels[3] = (TEX_IMAGE_MISSING_A * 65535);
+ }
+
+ img->mem = tex_img;
+ img->mem->interpolation = img->interpolation;
+ img->mem->extension = img->extension;
+
+ thread_scoped_lock device_lock(device_mutex);
+ tex_img->copy_to_device();
+ }
+ else if (type == IMAGE_DATA_TYPE_HALF) {
+ device_vector<half> *tex_img = new device_vector<half>(
+ device, img->mem_name.c_str(), MEM_TEXTURE);
+
+ if (!file_load_image<TypeDesc::HALF, half>(img, type, texture_limit, *tex_img)) {
+ /* on failure to load, we set a 1x1 pixels pink image */
+ thread_scoped_lock device_lock(device_mutex);
+ half *pixels = (half *)tex_img->alloc(1, 1);
+
+ pixels[0] = TEX_IMAGE_MISSING_R;
+ }
+
+ img->mem = tex_img;
+ img->mem->interpolation = img->interpolation;
+ img->mem->extension = img->extension;
+
+ thread_scoped_lock device_lock(device_mutex);
+ tex_img->copy_to_device();
+ }
+ img->need_load = false;
}
void ImageManager::device_free_image(Device *, ImageDataType type, int slot)
{
- Image *img = images[type][slot];
+ Image *img = images[type][slot];
- if(img) {
- if(osl_texture_system && !img->builtin_data) {
+ if (img) {
+ if (osl_texture_system && !img->builtin_data) {
#ifdef WITH_OSL
- ustring filename(images[type][slot]->filename);
- ((OSL::TextureSystem*)osl_texture_system)->invalidate(filename);
+ ustring filename(images[type][slot]->filename);
+ ((OSL::TextureSystem *)osl_texture_system)->invalidate(filename);
#endif
- }
+ }
- if(img->mem) {
- thread_scoped_lock device_lock(device_mutex);
- delete img->mem;
- }
+ if (img->mem) {
+ thread_scoped_lock device_lock(device_mutex);
+ delete img->mem;
+ }
- delete img;
- images[type][slot] = NULL;
- --tex_num_images[type];
- }
+ delete img;
+ images[type][slot] = NULL;
+ --tex_num_images[type];
+ }
}
-void ImageManager::device_update(Device *device,
- Scene *scene,
- Progress& progress)
+void ImageManager::device_update(Device *device, Scene *scene, Progress &progress)
{
- if(!need_update) {
- return;
- }
-
- TaskPool pool;
- for(int type = 0; type < IMAGE_DATA_NUM_TYPES; type++) {
- for(size_t slot = 0; slot < images[type].size(); slot++) {
- if(!images[type][slot])
- continue;
-
- if(images[type][slot]->users == 0) {
- device_free_image(device, (ImageDataType)type, slot);
- }
- else if(images[type][slot]->need_load) {
- if(!osl_texture_system || images[type][slot]->builtin_data)
- pool.push(function_bind(&ImageManager::device_load_image,
- this,
- device,
- scene,
- (ImageDataType)type,
- slot,
- &progress));
- }
- }
- }
-
- pool.wait_work();
-
- need_update = false;
+ if (!need_update) {
+ return;
+ }
+
+ TaskPool pool;
+ for (int type = 0; type < IMAGE_DATA_NUM_TYPES; type++) {
+ for (size_t slot = 0; slot < images[type].size(); slot++) {
+ if (!images[type][slot])
+ continue;
+
+ if (images[type][slot]->users == 0) {
+ device_free_image(device, (ImageDataType)type, slot);
+ }
+ else if (images[type][slot]->need_load) {
+ if (!osl_texture_system || images[type][slot]->builtin_data)
+ pool.push(function_bind(&ImageManager::device_load_image,
+ this,
+ device,
+ scene,
+ (ImageDataType)type,
+ slot,
+ &progress));
+ }
+ }
+ }
+
+ pool.wait_work();
+
+ need_update = false;
}
void ImageManager::device_update_slot(Device *device,
@@ -1001,87 +943,80 @@ void ImageManager::device_update_slot(Device *device,
int flat_slot,
Progress *progress)
{
- ImageDataType type;
- int slot = flattened_slot_to_type_index(flat_slot, &type);
-
- Image *image = images[type][slot];
- assert(image != NULL);
-
- if(image->users == 0) {
- device_free_image(device, type, slot);
- }
- else if(image->need_load) {
- if(!osl_texture_system || image->builtin_data)
- device_load_image(device,
- scene,
- type,
- slot,
- progress);
- }
+ ImageDataType type;
+ int slot = flattened_slot_to_type_index(flat_slot, &type);
+
+ Image *image = images[type][slot];
+ assert(image != NULL);
+
+ if (image->users == 0) {
+ device_free_image(device, type, slot);
+ }
+ else if (image->need_load) {
+ if (!osl_texture_system || image->builtin_data)
+ device_load_image(device, scene, type, slot, progress);
+ }
}
-void ImageManager::device_load_builtin(Device *device,
- Scene *scene,
- Progress& progress)
+void ImageManager::device_load_builtin(Device *device, Scene *scene, Progress &progress)
{
- /* Load only builtin images, Blender needs this to load evaluated
- * scene data from depsgraph before it is freed. */
- if(!need_update) {
- return;
- }
-
- TaskPool pool;
- for(int type = 0; type < IMAGE_DATA_NUM_TYPES; type++) {
- for(size_t slot = 0; slot < images[type].size(); slot++) {
- if(!images[type][slot])
- continue;
-
- if(images[type][slot]->need_load) {
- if(images[type][slot]->builtin_data) {
- pool.push(function_bind(&ImageManager::device_load_image,
- this,
- device,
- scene,
- (ImageDataType)type,
- slot,
- &progress));
- }
- }
- }
- }
-
- pool.wait_work();
+ /* Load only builtin images, Blender needs this to load evaluated
+ * scene data from depsgraph before it is freed. */
+ if (!need_update) {
+ return;
+ }
+
+ TaskPool pool;
+ for (int type = 0; type < IMAGE_DATA_NUM_TYPES; type++) {
+ for (size_t slot = 0; slot < images[type].size(); slot++) {
+ if (!images[type][slot])
+ continue;
+
+ if (images[type][slot]->need_load) {
+ if (images[type][slot]->builtin_data) {
+ pool.push(function_bind(&ImageManager::device_load_image,
+ this,
+ device,
+ scene,
+ (ImageDataType)type,
+ slot,
+ &progress));
+ }
+ }
+ }
+ }
+
+ pool.wait_work();
}
void ImageManager::device_free_builtin(Device *device)
{
- for(int type = 0; type < IMAGE_DATA_NUM_TYPES; type++) {
- for(size_t slot = 0; slot < images[type].size(); slot++) {
- if(images[type][slot] && images[type][slot]->builtin_data)
- device_free_image(device, (ImageDataType)type, slot);
- }
- }
+ for (int type = 0; type < IMAGE_DATA_NUM_TYPES; type++) {
+ for (size_t slot = 0; slot < images[type].size(); slot++) {
+ if (images[type][slot] && images[type][slot]->builtin_data)
+ device_free_image(device, (ImageDataType)type, slot);
+ }
+ }
}
void ImageManager::device_free(Device *device)
{
- for(int type = 0; type < IMAGE_DATA_NUM_TYPES; type++) {
- for(size_t slot = 0; slot < images[type].size(); slot++) {
- device_free_image(device, (ImageDataType)type, slot);
- }
- images[type].clear();
- }
+ for (int type = 0; type < IMAGE_DATA_NUM_TYPES; type++) {
+ for (size_t slot = 0; slot < images[type].size(); slot++) {
+ device_free_image(device, (ImageDataType)type, slot);
+ }
+ images[type].clear();
+ }
}
void ImageManager::collect_statistics(RenderStats *stats)
{
- for(int type = 0; type < IMAGE_DATA_NUM_TYPES; type++) {
- foreach(const Image *image, images[type]) {
- stats->image.textures.add_entry(
- NamedSizeEntry(path_filename(image->filename),
- image->mem->memory_size()));
- }
- }
+ for (int type = 0; type < IMAGE_DATA_NUM_TYPES; type++) {
+ foreach (const Image *image, images[type]) {
+ stats->image.textures.add_entry(
+ NamedSizeEntry(path_filename(image->filename), image->mem->memory_size()));
+ }
+ }
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/render/image.h b/intern/cycles/render/image.h
index 1403b9050fd..34f046692f6 100644
--- a/intern/cycles/render/image.h
+++ b/intern/cycles/render/image.h
@@ -34,150 +34,129 @@ class RenderStats;
class Scene;
class ImageMetaData {
-public:
- /* Must be set by image file or builtin callback. */
- bool is_float, is_half;
- int channels;
- size_t width, height, depth;
- bool builtin_free_cache;
-
- /* Automatically set. */
- ImageDataType type;
- bool is_linear;
-
- bool operator==(const ImageMetaData& other) const
- {
- return is_float == other.is_float &&
- is_half == other.is_half &&
- channels == other.channels &&
- width == other.width &&
- height == other.height &&
- depth == other.depth &&
- type == other.type &&
- is_linear == other.is_linear;
- }
+ public:
+ /* Must be set by image file or builtin callback. */
+ bool is_float, is_half;
+ int channels;
+ size_t width, height, depth;
+ bool builtin_free_cache;
+
+ /* Automatically set. */
+ ImageDataType type;
+ bool is_linear;
+
+ bool operator==(const ImageMetaData &other) const
+ {
+ return is_float == other.is_float && is_half == other.is_half && channels == other.channels &&
+ width == other.width && height == other.height && depth == other.depth &&
+ type == other.type && is_linear == other.is_linear;
+ }
};
class ImageManager {
-public:
- explicit ImageManager(const DeviceInfo& info);
- ~ImageManager();
-
- int add_image(const string& filename,
- void *builtin_data,
- bool animated,
- float frame,
- InterpolationType interpolation,
- ExtensionType extension,
- bool use_alpha,
- ImageMetaData& metadata);
- void remove_image(int flat_slot);
- void remove_image(const string& filename,
- void *builtin_data,
- InterpolationType interpolation,
- ExtensionType extension,
- bool use_alpha);
- void tag_reload_image(const string& filename,
- void *builtin_data,
- InterpolationType interpolation,
- ExtensionType extension,
- bool use_alpha);
- bool get_image_metadata(const string& filename,
- void *builtin_data,
- ImageMetaData& metadata);
- bool get_image_metadata(int flat_slot,
- ImageMetaData& metadata);
-
- void device_update(Device *device,
- Scene *scene,
- Progress& progress);
- void device_update_slot(Device *device,
- Scene *scene,
- int flat_slot,
- Progress *progress);
- void device_free(Device *device);
-
- void device_load_builtin(Device *device,
- Scene *scene,
- Progress& progress);
- void device_free_builtin(Device *device);
-
- void set_osl_texture_system(void *texture_system);
- bool set_animation_frame_update(int frame);
-
- device_memory *image_memory(int flat_slot);
-
- void collect_statistics(RenderStats *stats);
-
- bool need_update;
-
- /* NOTE: Here pixels_size is a size of storage, which equals to
- * width * height * depth.
- * Use this to avoid some nasty memory corruptions.
- */
- function<void(const string &filename,
- void *data,
- ImageMetaData& metadata)> builtin_image_info_cb;
- function<bool(const string &filename,
- void *data,
- unsigned char *pixels,
- const size_t pixels_size,
- const bool free_cache)> builtin_image_pixels_cb;
- function<bool(const string &filename,
- void *data,
- float *pixels,
- const size_t pixels_size,
- const bool free_cache)> builtin_image_float_pixels_cb;
-
- struct Image {
- string filename;
- void *builtin_data;
- ImageMetaData metadata;
-
- bool use_alpha;
- bool need_load;
- bool animated;
- float frame;
- InterpolationType interpolation;
- ExtensionType extension;
-
- string mem_name;
- device_memory *mem;
-
- int users;
- };
-
-private:
- int tex_num_images[IMAGE_DATA_NUM_TYPES];
- int max_num_images;
- bool has_half_images;
-
- thread_mutex device_mutex;
- int animation_frame;
-
- vector<Image*> images[IMAGE_DATA_NUM_TYPES];
- void *osl_texture_system;
-
- bool file_load_image_generic(Image *img, unique_ptr<ImageInput> *in);
-
- template<TypeDesc::BASETYPE FileFormat,
- typename StorageType,
- typename DeviceType>
- bool file_load_image(Image *img,
- ImageDataType type,
- int texture_limit,
- device_vector<DeviceType>& tex_img);
-
- void device_load_image(Device *device,
- Scene *scene,
- ImageDataType type,
- int slot,
- Progress *progress);
- void device_free_image(Device *device,
- ImageDataType type,
- int slot);
+ public:
+ explicit ImageManager(const DeviceInfo &info);
+ ~ImageManager();
+
+ int add_image(const string &filename,
+ void *builtin_data,
+ bool animated,
+ float frame,
+ InterpolationType interpolation,
+ ExtensionType extension,
+ bool use_alpha,
+ ImageMetaData &metadata);
+ void remove_image(int flat_slot);
+ void remove_image(const string &filename,
+ void *builtin_data,
+ InterpolationType interpolation,
+ ExtensionType extension,
+ bool use_alpha);
+ void tag_reload_image(const string &filename,
+ void *builtin_data,
+ InterpolationType interpolation,
+ ExtensionType extension,
+ bool use_alpha);
+ bool get_image_metadata(const string &filename, void *builtin_data, ImageMetaData &metadata);
+ bool get_image_metadata(int flat_slot, ImageMetaData &metadata);
+
+ void device_update(Device *device, Scene *scene, Progress &progress);
+ void device_update_slot(Device *device, Scene *scene, int flat_slot, Progress *progress);
+ void device_free(Device *device);
+
+ void device_load_builtin(Device *device, Scene *scene, Progress &progress);
+ void device_free_builtin(Device *device);
+
+ void set_osl_texture_system(void *texture_system);
+ bool set_animation_frame_update(int frame);
+
+ device_memory *image_memory(int flat_slot);
+
+ void collect_statistics(RenderStats *stats);
+
+ bool need_update;
+
+ /* NOTE: Here pixels_size is a size of storage, which equals to
+ * width * height * depth.
+ * Use this to avoid some nasty memory corruptions.
+ */
+ function<void(const string &filename, void *data, ImageMetaData &metadata)>
+ builtin_image_info_cb;
+ function<bool(const string &filename,
+ void *data,
+ unsigned char *pixels,
+ const size_t pixels_size,
+ const bool free_cache)>
+ builtin_image_pixels_cb;
+ function<bool(const string &filename,
+ void *data,
+ float *pixels,
+ const size_t pixels_size,
+ const bool free_cache)>
+ builtin_image_float_pixels_cb;
+
+ struct Image {
+ string filename;
+ void *builtin_data;
+ ImageMetaData metadata;
+
+ bool use_alpha;
+ bool need_load;
+ bool animated;
+ float frame;
+ InterpolationType interpolation;
+ ExtensionType extension;
+
+ string mem_name;
+ device_memory *mem;
+
+ int users;
+ };
+
+ private:
+ int tex_num_images[IMAGE_DATA_NUM_TYPES];
+ int max_num_images;
+ bool has_half_images;
+
+ thread_mutex device_mutex;
+ int animation_frame;
+
+ vector<Image *> images[IMAGE_DATA_NUM_TYPES];
+ void *osl_texture_system;
+
+ bool file_load_image_generic(Image *img, unique_ptr<ImageInput> *in);
+
+ template<TypeDesc::BASETYPE FileFormat, typename StorageType, typename DeviceType>
+ bool file_load_image(Image *img,
+ ImageDataType type,
+ int texture_limit,
+ device_vector<DeviceType> &tex_img);
+
+ void device_load_image(
+ Device *device, Scene *scene, ImageDataType type, int slot, Progress *progress);
+ void device_free_image(Device *device, ImageDataType type, int slot);
};
CCL_NAMESPACE_END
-#endif /* __IMAGE_H__ */
+#endif /* __IMAGE_H__ */
diff --git a/intern/cycles/render/integrator.cpp b/intern/cycles/render/integrator.cpp
index d86eb8fc5d3..d3873dcfe46 100644
--- a/intern/cycles/render/integrator.cpp
+++ b/intern/cycles/render/integrator.cpp
@@ -30,61 +30,60 @@ CCL_NAMESPACE_BEGIN
NODE_DEFINE(Integrator)
{
- NodeType *type = NodeType::add("integrator", create);
-
- SOCKET_INT(max_bounce, "Max Bounce", 7);
-
- SOCKET_INT(max_diffuse_bounce, "Max Diffuse Bounce", 7);
- SOCKET_INT(max_glossy_bounce, "Max Glossy Bounce", 7);
- SOCKET_INT(max_transmission_bounce, "Max Transmission Bounce", 7);
- SOCKET_INT(max_volume_bounce, "Max Volume Bounce", 7);
-
- SOCKET_INT(transparent_max_bounce, "Transparent Max Bounce", 7);
-
- SOCKET_INT(ao_bounces, "AO Bounces", 0);
-
- SOCKET_INT(volume_max_steps, "Volume Max Steps", 1024);
- SOCKET_FLOAT(volume_step_size, "Volume Step Size", 0.1f);
-
- SOCKET_BOOLEAN(caustics_reflective, "Reflective Caustics", true);
- SOCKET_BOOLEAN(caustics_refractive, "Refractive Caustics", true);
- SOCKET_FLOAT(filter_glossy, "Filter Glossy", 0.0f);
- SOCKET_INT(seed, "Seed", 0);
- SOCKET_FLOAT(sample_clamp_direct, "Sample Clamp Direct", 0.0f);
- SOCKET_FLOAT(sample_clamp_indirect, "Sample Clamp Indirect", 0.0f);
- SOCKET_BOOLEAN(motion_blur, "Motion Blur", false);
-
- SOCKET_INT(aa_samples, "AA Samples", 0);
- SOCKET_INT(diffuse_samples, "Diffuse Samples", 1);
- SOCKET_INT(glossy_samples, "Glossy Samples", 1);
- SOCKET_INT(transmission_samples, "Transmission Samples", 1);
- SOCKET_INT(ao_samples, "AO Samples", 1);
- SOCKET_INT(mesh_light_samples, "Mesh Light Samples", 1);
- SOCKET_INT(subsurface_samples, "Subsurface Samples", 1);
- SOCKET_INT(volume_samples, "Volume Samples", 1);
- SOCKET_INT(start_sample, "Start Sample", 0);
-
- SOCKET_BOOLEAN(sample_all_lights_direct, "Sample All Lights Direct", true);
- SOCKET_BOOLEAN(sample_all_lights_indirect, "Sample All Lights Indirect", true);
- SOCKET_FLOAT(light_sampling_threshold, "Light Sampling Threshold", 0.05f);
-
- static NodeEnum method_enum;
- method_enum.insert("path", PATH);
- method_enum.insert("branched_path", BRANCHED_PATH);
- SOCKET_ENUM(method, "Method", method_enum, PATH);
-
- static NodeEnum sampling_pattern_enum;
- sampling_pattern_enum.insert("sobol", SAMPLING_PATTERN_SOBOL);
- sampling_pattern_enum.insert("cmj", SAMPLING_PATTERN_CMJ);
- SOCKET_ENUM(sampling_pattern, "Sampling Pattern", sampling_pattern_enum, SAMPLING_PATTERN_SOBOL);
-
- return type;
+ NodeType *type = NodeType::add("integrator", create);
+
+ SOCKET_INT(max_bounce, "Max Bounce", 7);
+
+ SOCKET_INT(max_diffuse_bounce, "Max Diffuse Bounce", 7);
+ SOCKET_INT(max_glossy_bounce, "Max Glossy Bounce", 7);
+ SOCKET_INT(max_transmission_bounce, "Max Transmission Bounce", 7);
+ SOCKET_INT(max_volume_bounce, "Max Volume Bounce", 7);
+
+ SOCKET_INT(transparent_max_bounce, "Transparent Max Bounce", 7);
+
+ SOCKET_INT(ao_bounces, "AO Bounces", 0);
+
+ SOCKET_INT(volume_max_steps, "Volume Max Steps", 1024);
+ SOCKET_FLOAT(volume_step_size, "Volume Step Size", 0.1f);
+
+ SOCKET_BOOLEAN(caustics_reflective, "Reflective Caustics", true);
+ SOCKET_BOOLEAN(caustics_refractive, "Refractive Caustics", true);
+ SOCKET_FLOAT(filter_glossy, "Filter Glossy", 0.0f);
+ SOCKET_INT(seed, "Seed", 0);
+ SOCKET_FLOAT(sample_clamp_direct, "Sample Clamp Direct", 0.0f);
+ SOCKET_FLOAT(sample_clamp_indirect, "Sample Clamp Indirect", 0.0f);
+ SOCKET_BOOLEAN(motion_blur, "Motion Blur", false);
+
+ SOCKET_INT(aa_samples, "AA Samples", 0);
+ SOCKET_INT(diffuse_samples, "Diffuse Samples", 1);
+ SOCKET_INT(glossy_samples, "Glossy Samples", 1);
+ SOCKET_INT(transmission_samples, "Transmission Samples", 1);
+ SOCKET_INT(ao_samples, "AO Samples", 1);
+ SOCKET_INT(mesh_light_samples, "Mesh Light Samples", 1);
+ SOCKET_INT(subsurface_samples, "Subsurface Samples", 1);
+ SOCKET_INT(volume_samples, "Volume Samples", 1);
+ SOCKET_INT(start_sample, "Start Sample", 0);
+
+ SOCKET_BOOLEAN(sample_all_lights_direct, "Sample All Lights Direct", true);
+ SOCKET_BOOLEAN(sample_all_lights_indirect, "Sample All Lights Indirect", true);
+ SOCKET_FLOAT(light_sampling_threshold, "Light Sampling Threshold", 0.05f);
+
+ static NodeEnum method_enum;
+ method_enum.insert("path", PATH);
+ method_enum.insert("branched_path", BRANCHED_PATH);
+ SOCKET_ENUM(method, "Method", method_enum, PATH);
+
+ static NodeEnum sampling_pattern_enum;
+ sampling_pattern_enum.insert("sobol", SAMPLING_PATTERN_SOBOL);
+ sampling_pattern_enum.insert("cmj", SAMPLING_PATTERN_CMJ);
+ SOCKET_ENUM(sampling_pattern, "Sampling Pattern", sampling_pattern_enum, SAMPLING_PATTERN_SOBOL);
+
+ return type;
}
-Integrator::Integrator()
-: Node(node_type)
+Integrator::Integrator() : Node(node_type)
{
- need_update = true;
+ need_update = true;
}
Integrator::~Integrator()
@@ -93,146 +92,148 @@ Integrator::~Integrator()
void Integrator::device_update(Device *device, DeviceScene *dscene, Scene *scene)
{
- if(!need_update)
- return;
-
- device_free(device, dscene);
-
- KernelIntegrator *kintegrator = &dscene->data.integrator;
-
- /* integrator parameters */
- kintegrator->max_bounce = max_bounce + 1;
-
- kintegrator->max_diffuse_bounce = max_diffuse_bounce + 1;
- kintegrator->max_glossy_bounce = max_glossy_bounce + 1;
- kintegrator->max_transmission_bounce = max_transmission_bounce + 1;
- kintegrator->max_volume_bounce = max_volume_bounce + 1;
-
- kintegrator->transparent_max_bounce = transparent_max_bounce + 1;
-
- if(ao_bounces == 0) {
- kintegrator->ao_bounces = INT_MAX;
- }
- else {
- kintegrator->ao_bounces = ao_bounces - 1;
- }
-
- /* Transparent Shadows
- * We only need to enable transparent shadows, if we actually have
- * transparent shaders in the scene. Otherwise we can disable it
- * to improve performance a bit. */
- kintegrator->transparent_shadows = false;
- foreach(Shader *shader, scene->shaders) {
- /* keep this in sync with SD_HAS_TRANSPARENT_SHADOW in shader.cpp */
- if((shader->has_surface_transparent && shader->use_transparent_shadow) || shader->has_volume) {
- kintegrator->transparent_shadows = true;
- break;
- }
- }
-
- kintegrator->volume_max_steps = volume_max_steps;
- kintegrator->volume_step_size = volume_step_size;
-
- kintegrator->caustics_reflective = caustics_reflective;
- kintegrator->caustics_refractive = caustics_refractive;
- kintegrator->filter_glossy = (filter_glossy == 0.0f)? FLT_MAX: 1.0f/filter_glossy;
-
- kintegrator->seed = hash_int(seed);
-
- kintegrator->use_ambient_occlusion =
- ((Pass::contains(scene->film->passes, PASS_AO)) || dscene->data.background.ao_factor != 0.0f);
-
- kintegrator->sample_clamp_direct = (sample_clamp_direct == 0.0f)? FLT_MAX: sample_clamp_direct*3.0f;
- kintegrator->sample_clamp_indirect = (sample_clamp_indirect == 0.0f)? FLT_MAX: sample_clamp_indirect*3.0f;
-
- kintegrator->branched = (method == BRANCHED_PATH);
- kintegrator->volume_decoupled = device->info.has_volume_decoupled;
- kintegrator->diffuse_samples = diffuse_samples;
- kintegrator->glossy_samples = glossy_samples;
- kintegrator->transmission_samples = transmission_samples;
- kintegrator->ao_samples = ao_samples;
- kintegrator->mesh_light_samples = mesh_light_samples;
- kintegrator->subsurface_samples = subsurface_samples;
- kintegrator->volume_samples = volume_samples;
- kintegrator->start_sample = start_sample;
-
- if(method == BRANCHED_PATH) {
- kintegrator->sample_all_lights_direct = sample_all_lights_direct;
- kintegrator->sample_all_lights_indirect = sample_all_lights_indirect;
- }
- else {
- kintegrator->sample_all_lights_direct = false;
- kintegrator->sample_all_lights_indirect = false;
- }
-
- kintegrator->sampling_pattern = sampling_pattern;
- kintegrator->aa_samples = aa_samples;
-
- if(light_sampling_threshold > 0.0f) {
- kintegrator->light_inv_rr_threshold = 1.0f / light_sampling_threshold;
- }
- else {
- kintegrator->light_inv_rr_threshold = 0.0f;
- }
-
- /* sobol directions table */
- int max_samples = 1;
-
- if(method == BRANCHED_PATH) {
- foreach(Light *light, scene->lights)
- max_samples = max(max_samples, light->samples);
-
- max_samples = max(max_samples, max(diffuse_samples, max(glossy_samples, transmission_samples)));
- max_samples = max(max_samples, max(ao_samples, max(mesh_light_samples, subsurface_samples)));
- max_samples = max(max_samples, volume_samples);
- }
-
- uint total_bounces = max_bounce +
- transparent_max_bounce + 3 +
- VOLUME_BOUNDS_MAX +
- max(BSSRDF_MAX_HITS, BSSRDF_MAX_BOUNCES);
-
- max_samples *= total_bounces;
-
- int dimensions = PRNG_BASE_NUM + max_samples*PRNG_BOUNCE_NUM;
- dimensions = min(dimensions, SOBOL_MAX_DIMENSIONS);
-
- uint *directions = dscene->sobol_directions.alloc(SOBOL_BITS*dimensions);
-
- sobol_generate_direction_vectors((uint(*)[SOBOL_BITS])directions, dimensions);
-
- dscene->sobol_directions.copy_to_device();
-
- /* Clamping. */
- bool use_sample_clamp = (sample_clamp_direct != 0.0f ||
- sample_clamp_indirect != 0.0f);
- if(use_sample_clamp != scene->film->use_sample_clamp) {
- scene->film->use_sample_clamp = use_sample_clamp;
- scene->film->tag_update(scene);
- }
-
- need_update = false;
+ if (!need_update)
+ return;
+
+ device_free(device, dscene);
+
+ KernelIntegrator *kintegrator = &dscene->data.integrator;
+
+ /* integrator parameters */
+ kintegrator->max_bounce = max_bounce + 1;
+
+ kintegrator->max_diffuse_bounce = max_diffuse_bounce + 1;
+ kintegrator->max_glossy_bounce = max_glossy_bounce + 1;
+ kintegrator->max_transmission_bounce = max_transmission_bounce + 1;
+ kintegrator->max_volume_bounce = max_volume_bounce + 1;
+
+ kintegrator->transparent_max_bounce = transparent_max_bounce + 1;
+
+ if (ao_bounces == 0) {
+ kintegrator->ao_bounces = INT_MAX;
+ }
+ else {
+ kintegrator->ao_bounces = ao_bounces - 1;
+ }
+
+ /* Transparent Shadows
+ * We only need to enable transparent shadows, if we actually have
+ * transparent shaders in the scene. Otherwise we can disable it
+ * to improve performance a bit. */
+ kintegrator->transparent_shadows = false;
+ foreach (Shader *shader, scene->shaders) {
+ /* keep this in sync with SD_HAS_TRANSPARENT_SHADOW in shader.cpp */
+ if ((shader->has_surface_transparent && shader->use_transparent_shadow) ||
+ shader->has_volume) {
+ kintegrator->transparent_shadows = true;
+ break;
+ }
+ }
+
+ kintegrator->volume_max_steps = volume_max_steps;
+ kintegrator->volume_step_size = volume_step_size;
+
+ kintegrator->caustics_reflective = caustics_reflective;
+ kintegrator->caustics_refractive = caustics_refractive;
+ kintegrator->filter_glossy = (filter_glossy == 0.0f) ? FLT_MAX : 1.0f / filter_glossy;
+
+ kintegrator->seed = hash_int(seed);
+
+ kintegrator->use_ambient_occlusion = ((Pass::contains(scene->film->passes, PASS_AO)) ||
+ dscene->data.background.ao_factor != 0.0f);
+
+ kintegrator->sample_clamp_direct = (sample_clamp_direct == 0.0f) ? FLT_MAX :
+ sample_clamp_direct * 3.0f;
+ kintegrator->sample_clamp_indirect = (sample_clamp_indirect == 0.0f) ?
+ FLT_MAX :
+ sample_clamp_indirect * 3.0f;
+
+ kintegrator->branched = (method == BRANCHED_PATH);
+ kintegrator->volume_decoupled = device->info.has_volume_decoupled;
+ kintegrator->diffuse_samples = diffuse_samples;
+ kintegrator->glossy_samples = glossy_samples;
+ kintegrator->transmission_samples = transmission_samples;
+ kintegrator->ao_samples = ao_samples;
+ kintegrator->mesh_light_samples = mesh_light_samples;
+ kintegrator->subsurface_samples = subsurface_samples;
+ kintegrator->volume_samples = volume_samples;
+ kintegrator->start_sample = start_sample;
+
+ if (method == BRANCHED_PATH) {
+ kintegrator->sample_all_lights_direct = sample_all_lights_direct;
+ kintegrator->sample_all_lights_indirect = sample_all_lights_indirect;
+ }
+ else {
+ kintegrator->sample_all_lights_direct = false;
+ kintegrator->sample_all_lights_indirect = false;
+ }
+
+ kintegrator->sampling_pattern = sampling_pattern;
+ kintegrator->aa_samples = aa_samples;
+
+ if (light_sampling_threshold > 0.0f) {
+ kintegrator->light_inv_rr_threshold = 1.0f / light_sampling_threshold;
+ }
+ else {
+ kintegrator->light_inv_rr_threshold = 0.0f;
+ }
+
+ /* sobol directions table */
+ int max_samples = 1;
+
+ if (method == BRANCHED_PATH) {
+ foreach (Light *light, scene->lights)
+ max_samples = max(max_samples, light->samples);
+
+ max_samples = max(max_samples,
+ max(diffuse_samples, max(glossy_samples, transmission_samples)));
+ max_samples = max(max_samples, max(ao_samples, max(mesh_light_samples, subsurface_samples)));
+ max_samples = max(max_samples, volume_samples);
+ }
+
+ uint total_bounces = max_bounce + transparent_max_bounce + 3 + VOLUME_BOUNDS_MAX +
+ max(BSSRDF_MAX_HITS, BSSRDF_MAX_BOUNCES);
+
+ max_samples *= total_bounces;
+
+ int dimensions = PRNG_BASE_NUM + max_samples * PRNG_BOUNCE_NUM;
+ dimensions = min(dimensions, SOBOL_MAX_DIMENSIONS);
+
+ uint *directions = dscene->sobol_directions.alloc(SOBOL_BITS * dimensions);
+
+ sobol_generate_direction_vectors((uint(*)[SOBOL_BITS])directions, dimensions);
+
+ dscene->sobol_directions.copy_to_device();
+
+ /* Clamping. */
+ bool use_sample_clamp = (sample_clamp_direct != 0.0f || sample_clamp_indirect != 0.0f);
+ if (use_sample_clamp != scene->film->use_sample_clamp) {
+ scene->film->use_sample_clamp = use_sample_clamp;
+ scene->film->tag_update(scene);
+ }
+
+ need_update = false;
}
void Integrator::device_free(Device *, DeviceScene *dscene)
{
- dscene->sobol_directions.free();
+ dscene->sobol_directions.free();
}
-bool Integrator::modified(const Integrator& integrator)
+bool Integrator::modified(const Integrator &integrator)
{
- return !Node::equals(integrator);
+ return !Node::equals(integrator);
}
void Integrator::tag_update(Scene *scene)
{
- foreach(Shader *shader, scene->shaders) {
- if(shader->has_integrator_dependency) {
- scene->shader_manager->need_update = true;
- break;
- }
- }
- need_update = true;
+ foreach (Shader *shader, scene->shaders) {
+ if (shader->has_integrator_dependency) {
+ scene->shader_manager->need_update = true;
+ break;
+ }
+ }
+ need_update = true;
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/render/integrator.h b/intern/cycles/render/integrator.h
index da4e61d8153..6acc68a7402 100644
--- a/intern/cycles/render/integrator.h
+++ b/intern/cycles/render/integrator.h
@@ -28,74 +28,74 @@ class DeviceScene;
class Scene;
class Integrator : public Node {
-public:
- NODE_DECLARE
+ public:
+ NODE_DECLARE
- int max_bounce;
+ int max_bounce;
- int max_diffuse_bounce;
- int max_glossy_bounce;
- int max_transmission_bounce;
- int max_volume_bounce;
+ int max_diffuse_bounce;
+ int max_glossy_bounce;
+ int max_transmission_bounce;
+ int max_volume_bounce;
- int transparent_max_bounce;
+ int transparent_max_bounce;
- int ao_bounces;
+ int ao_bounces;
- int volume_max_steps;
- float volume_step_size;
+ int volume_max_steps;
+ float volume_step_size;
- bool caustics_reflective;
- bool caustics_refractive;
- float filter_glossy;
+ bool caustics_reflective;
+ bool caustics_refractive;
+ float filter_glossy;
- int seed;
+ int seed;
- float sample_clamp_direct;
- float sample_clamp_indirect;
- bool motion_blur;
+ float sample_clamp_direct;
+ float sample_clamp_indirect;
+ bool motion_blur;
- /* Maximum number of samples, beyond which we are likely to run into
- * precision issues for sampling patterns. */
- static const int MAX_SAMPLES = (1 << 24);
+ /* Maximum number of samples, beyond which we are likely to run into
+ * precision issues for sampling patterns. */
+ static const int MAX_SAMPLES = (1 << 24);
- int aa_samples;
- int diffuse_samples;
- int glossy_samples;
- int transmission_samples;
- int ao_samples;
- int mesh_light_samples;
- int subsurface_samples;
- int volume_samples;
- int start_sample;
+ int aa_samples;
+ int diffuse_samples;
+ int glossy_samples;
+ int transmission_samples;
+ int ao_samples;
+ int mesh_light_samples;
+ int subsurface_samples;
+ int volume_samples;
+ int start_sample;
- bool sample_all_lights_direct;
- bool sample_all_lights_indirect;
- float light_sampling_threshold;
+ bool sample_all_lights_direct;
+ bool sample_all_lights_indirect;
+ float light_sampling_threshold;
- enum Method {
- BRANCHED_PATH = 0,
- PATH = 1,
+ enum Method {
+ BRANCHED_PATH = 0,
+ PATH = 1,
- NUM_METHODS,
- };
+ NUM_METHODS,
+ };
- Method method;
+ Method method;
- SamplingPattern sampling_pattern;
+ SamplingPattern sampling_pattern;
- bool need_update;
+ bool need_update;
- Integrator();
- ~Integrator();
+ Integrator();
+ ~Integrator();
- void device_update(Device *device, DeviceScene *dscene, Scene *scene);
- void device_free(Device *device, DeviceScene *dscene);
+ void device_update(Device *device, DeviceScene *dscene, Scene *scene);
+ void device_free(Device *device, DeviceScene *dscene);
- bool modified(const Integrator& integrator);
- void tag_update(Scene *scene);
+ bool modified(const Integrator &integrator);
+ void tag_update(Scene *scene);
};
CCL_NAMESPACE_END
-#endif /* __INTEGRATOR_H__ */
+#endif /* __INTEGRATOR_H__ */
diff --git a/intern/cycles/render/light.cpp b/intern/cycles/render/light.cpp
index 56d60adf71d..d4c233e3bb3 100644
--- a/intern/cycles/render/light.cpp
+++ b/intern/cycles/render/light.cpp
@@ -34,1002 +34,1016 @@
CCL_NAMESPACE_BEGIN
-static void shade_background_pixels(Device *device, DeviceScene *dscene, int width, int height, vector<float3>& pixels, Progress& progress)
+static void shade_background_pixels(Device *device,
+ DeviceScene *dscene,
+ int width,
+ int height,
+ vector<float3> &pixels,
+ Progress &progress)
{
- /* create input */
- device_vector<uint4> d_input(device, "background_input", MEM_READ_ONLY);
- device_vector<float4> d_output(device, "background_output", MEM_READ_WRITE);
-
- uint4 *d_input_data = d_input.alloc(width*height);
-
- for(int y = 0; y < height; y++) {
- for(int x = 0; x < width; x++) {
- float u = (x + 0.5f)/width;
- float v = (y + 0.5f)/height;
-
- uint4 in = make_uint4(__float_as_int(u), __float_as_int(v), 0, 0);
- d_input_data[x + y*width] = in;
- }
- }
-
- /* compute on device */
- d_output.alloc(width*height);
- d_output.zero_to_device();
- d_input.copy_to_device();
-
- device->const_copy_to("__data", &dscene->data, sizeof(dscene->data));
-
- DeviceTask main_task(DeviceTask::SHADER);
- main_task.shader_input = d_input.device_pointer;
- main_task.shader_output = d_output.device_pointer;
- main_task.shader_eval_type = SHADER_EVAL_BACKGROUND;
- main_task.shader_x = 0;
- main_task.shader_w = width*height;
- main_task.num_samples = 1;
- main_task.get_cancel = function_bind(&Progress::get_cancel, &progress);
-
- /* disabled splitting for now, there's an issue with multi-GPU mem_copy_from */
- list<DeviceTask> split_tasks;
- main_task.split(split_tasks, 1, 128*128);
-
- foreach(DeviceTask& task, split_tasks) {
- device->task_add(task);
- device->task_wait();
- d_output.copy_from_device(task.shader_x, 1, task.shader_w);
- }
-
- d_input.free();
-
- float4 *d_output_data = d_output.data();
-
- pixels.resize(width*height);
-
- for(int y = 0; y < height; y++) {
- for(int x = 0; x < width; x++) {
- pixels[y*width + x].x = d_output_data[y*width + x].x;
- pixels[y*width + x].y = d_output_data[y*width + x].y;
- pixels[y*width + x].z = d_output_data[y*width + x].z;
- }
- }
-
- d_output.free();
+ /* create input */
+ device_vector<uint4> d_input(device, "background_input", MEM_READ_ONLY);
+ device_vector<float4> d_output(device, "background_output", MEM_READ_WRITE);
+
+ uint4 *d_input_data = d_input.alloc(width * height);
+
+ for (int y = 0; y < height; y++) {
+ for (int x = 0; x < width; x++) {
+ float u = (x + 0.5f) / width;
+ float v = (y + 0.5f) / height;
+
+ uint4 in = make_uint4(__float_as_int(u), __float_as_int(v), 0, 0);
+ d_input_data[x + y * width] = in;
+ }
+ }
+
+ /* compute on device */
+ d_output.alloc(width * height);
+ d_output.zero_to_device();
+ d_input.copy_to_device();
+
+ device->const_copy_to("__data", &dscene->data, sizeof(dscene->data));
+
+ DeviceTask main_task(DeviceTask::SHADER);
+ main_task.shader_input = d_input.device_pointer;
+ main_task.shader_output = d_output.device_pointer;
+ main_task.shader_eval_type = SHADER_EVAL_BACKGROUND;
+ main_task.shader_x = 0;
+ main_task.shader_w = width * height;
+ main_task.num_samples = 1;
+ main_task.get_cancel = function_bind(&Progress::get_cancel, &progress);
+
+ /* disabled splitting for now, there's an issue with multi-GPU mem_copy_from */
+ list<DeviceTask> split_tasks;
+ main_task.split(split_tasks, 1, 128 * 128);
+
+ foreach (DeviceTask &task, split_tasks) {
+ device->task_add(task);
+ device->task_wait();
+ d_output.copy_from_device(task.shader_x, 1, task.shader_w);
+ }
+
+ d_input.free();
+
+ float4 *d_output_data = d_output.data();
+
+ pixels.resize(width * height);
+
+ for (int y = 0; y < height; y++) {
+ for (int x = 0; x < width; x++) {
+ pixels[y * width + x].x = d_output_data[y * width + x].x;
+ pixels[y * width + x].y = d_output_data[y * width + x].y;
+ pixels[y * width + x].z = d_output_data[y * width + x].z;
+ }
+ }
+
+ d_output.free();
}
/* Light */
NODE_DEFINE(Light)
{
- NodeType* type = NodeType::add("light", create);
+ NodeType *type = NodeType::add("light", create);
- static NodeEnum type_enum;
- type_enum.insert("point", LIGHT_POINT);
- type_enum.insert("distant", LIGHT_DISTANT);
- type_enum.insert("background", LIGHT_BACKGROUND);
- type_enum.insert("area", LIGHT_AREA);
- type_enum.insert("spot", LIGHT_SPOT);
- SOCKET_ENUM(type, "Type", type_enum, LIGHT_POINT);
+ static NodeEnum type_enum;
+ type_enum.insert("point", LIGHT_POINT);
+ type_enum.insert("distant", LIGHT_DISTANT);
+ type_enum.insert("background", LIGHT_BACKGROUND);
+ type_enum.insert("area", LIGHT_AREA);
+ type_enum.insert("spot", LIGHT_SPOT);
+ SOCKET_ENUM(type, "Type", type_enum, LIGHT_POINT);
- SOCKET_POINT(co, "Co", make_float3(0.0f, 0.0f, 0.0f));
+ SOCKET_POINT(co, "Co", make_float3(0.0f, 0.0f, 0.0f));
- SOCKET_VECTOR(dir, "Dir", make_float3(0.0f, 0.0f, 0.0f));
- SOCKET_FLOAT(size, "Size", 0.0f);
+ SOCKET_VECTOR(dir, "Dir", make_float3(0.0f, 0.0f, 0.0f));
+ SOCKET_FLOAT(size, "Size", 0.0f);
- SOCKET_VECTOR(axisu, "Axis U", make_float3(0.0f, 0.0f, 0.0f));
- SOCKET_FLOAT(sizeu, "Size U", 1.0f);
- SOCKET_VECTOR(axisv, "Axis V", make_float3(0.0f, 0.0f, 0.0f));
- SOCKET_FLOAT(sizev, "Size V", 1.0f);
- SOCKET_BOOLEAN(round, "Round", false);
+ SOCKET_VECTOR(axisu, "Axis U", make_float3(0.0f, 0.0f, 0.0f));
+ SOCKET_FLOAT(sizeu, "Size U", 1.0f);
+ SOCKET_VECTOR(axisv, "Axis V", make_float3(0.0f, 0.0f, 0.0f));
+ SOCKET_FLOAT(sizev, "Size V", 1.0f);
+ SOCKET_BOOLEAN(round, "Round", false);
- SOCKET_INT(map_resolution, "Map Resolution", 0);
+ SOCKET_INT(map_resolution, "Map Resolution", 0);
- SOCKET_FLOAT(spot_angle, "Spot Angle", M_PI_4_F);
- SOCKET_FLOAT(spot_smooth, "Spot Smooth", 0.0f);
+ SOCKET_FLOAT(spot_angle, "Spot Angle", M_PI_4_F);
+ SOCKET_FLOAT(spot_smooth, "Spot Smooth", 0.0f);
- SOCKET_TRANSFORM(tfm, "Transform", transform_identity());
+ SOCKET_TRANSFORM(tfm, "Transform", transform_identity());
- SOCKET_BOOLEAN(cast_shadow, "Cast Shadow", true);
- SOCKET_BOOLEAN(use_mis, "Use Mis", false);
- SOCKET_BOOLEAN(use_diffuse, "Use Diffuse", true);
- SOCKET_BOOLEAN(use_glossy, "Use Glossy", true);
- SOCKET_BOOLEAN(use_transmission, "Use Transmission", true);
- SOCKET_BOOLEAN(use_scatter, "Use Scatter", true);
+ SOCKET_BOOLEAN(cast_shadow, "Cast Shadow", true);
+ SOCKET_BOOLEAN(use_mis, "Use Mis", false);
+ SOCKET_BOOLEAN(use_diffuse, "Use Diffuse", true);
+ SOCKET_BOOLEAN(use_glossy, "Use Glossy", true);
+ SOCKET_BOOLEAN(use_transmission, "Use Transmission", true);
+ SOCKET_BOOLEAN(use_scatter, "Use Scatter", true);
- SOCKET_INT(samples, "Samples", 1);
- SOCKET_INT(max_bounces, "Max Bounces", 1024);
- SOCKET_UINT(random_id, "Random ID", 0);
+ SOCKET_INT(samples, "Samples", 1);
+ SOCKET_INT(max_bounces, "Max Bounces", 1024);
+ SOCKET_UINT(random_id, "Random ID", 0);
- SOCKET_BOOLEAN(is_portal, "Is Portal", false);
- SOCKET_BOOLEAN(is_enabled, "Is Enabled", true);
+ SOCKET_BOOLEAN(is_portal, "Is Portal", false);
+ SOCKET_BOOLEAN(is_enabled, "Is Enabled", true);
- SOCKET_NODE(shader, "Shader", &Shader::node_type);
+ SOCKET_NODE(shader, "Shader", &Shader::node_type);
- return type;
+ return type;
}
-Light::Light()
-: Node(node_type)
+Light::Light() : Node(node_type)
{
}
void Light::tag_update(Scene *scene)
{
- scene->light_manager->need_update = true;
+ scene->light_manager->need_update = true;
}
bool Light::has_contribution(Scene *scene)
{
- if(is_portal) {
- return false;
- }
- if(type == LIGHT_BACKGROUND) {
- return true;
- }
- return (shader) ? shader->has_surface_emission : scene->default_light->has_surface_emission;
+ if (is_portal) {
+ return false;
+ }
+ if (type == LIGHT_BACKGROUND) {
+ return true;
+ }
+ return (shader) ? shader->has_surface_emission : scene->default_light->has_surface_emission;
}
/* Light Manager */
LightManager::LightManager()
{
- need_update = true;
- use_light_visibility = false;
+ need_update = true;
+ use_light_visibility = false;
}
LightManager::~LightManager()
{
- foreach(IESSlot *slot, ies_slots) {
- delete slot;
- }
+ foreach (IESSlot *slot, ies_slots) {
+ delete slot;
+ }
}
bool LightManager::has_background_light(Scene *scene)
{
- foreach(Light *light, scene->lights) {
- if(light->type == LIGHT_BACKGROUND && light->is_enabled) {
- return true;
- }
- }
- return false;
+ foreach (Light *light, scene->lights) {
+ if (light->type == LIGHT_BACKGROUND && light->is_enabled) {
+ return true;
+ }
+ }
+ return false;
}
void LightManager::disable_ineffective_light(Scene *scene)
{
- /* Make all lights enabled by default, and perform some preliminary checks
- * needed for finer-tuning of settings (for example, check whether we've
- * got portals or not).
- */
- bool has_portal = false, has_background = false;
- foreach(Light *light, scene->lights) {
- light->is_enabled = light->has_contribution(scene);
- has_portal |= light->is_portal;
- has_background |= light->type == LIGHT_BACKGROUND;
- }
-
- if(has_background) {
- /* Ignore background light if:
- * - If unsupported on a device
- * - If we don't need it (no HDRs etc.)
- */
- Shader *shader = (scene->background->shader) ? scene->background->shader : scene->default_background;
- bool disable_mis = !(has_portal || shader->has_surface_spatial_varying);
- if(disable_mis) {
- VLOG(1) << "Background MIS has been disabled.\n";
- foreach(Light *light, scene->lights) {
- if(light->type == LIGHT_BACKGROUND) {
- light->is_enabled = false;
- }
- }
- }
- }
+ /* Make all lights enabled by default, and perform some preliminary checks
+ * needed for finer-tuning of settings (for example, check whether we've
+ * got portals or not).
+ */
+ bool has_portal = false, has_background = false;
+ foreach (Light *light, scene->lights) {
+ light->is_enabled = light->has_contribution(scene);
+ has_portal |= light->is_portal;
+ has_background |= light->type == LIGHT_BACKGROUND;
+ }
+
+ if (has_background) {
+ /* Ignore background light if:
+ * - If unsupported on a device
+ * - If we don't need it (no HDRs etc.)
+ */
+ Shader *shader = (scene->background->shader) ? scene->background->shader :
+ scene->default_background;
+ bool disable_mis = !(has_portal || shader->has_surface_spatial_varying);
+ if (disable_mis) {
+ VLOG(1) << "Background MIS has been disabled.\n";
+ foreach (Light *light, scene->lights) {
+ if (light->type == LIGHT_BACKGROUND) {
+ light->is_enabled = false;
+ }
+ }
+ }
+ }
}
-bool LightManager::object_usable_as_light(Object *object) {
- Mesh *mesh = object->mesh;
- /* Skip objects with NaNs */
- if(!object->bounds.valid()) {
- return false;
- }
- /* Skip if we are not visible for BSDFs. */
- if(!(object->visibility & (PATH_RAY_DIFFUSE|PATH_RAY_GLOSSY|PATH_RAY_TRANSMIT))) {
- return false;
- }
- /* Skip if we have no emission shaders. */
- /* TODO(sergey): Ideally we want to avoid such duplicated loop, since it'll
- * iterate all mesh shaders twice (when counting and when calculating
- * triangle area.
- */
- foreach(const Shader *shader, mesh->used_shaders) {
- if(shader->use_mis && shader->has_surface_emission) {
- return true;
- }
- }
- return false;
+bool LightManager::object_usable_as_light(Object *object)
+{
+ Mesh *mesh = object->mesh;
+ /* Skip objects with NaNs */
+ if (!object->bounds.valid()) {
+ return false;
+ }
+ /* Skip if we are not visible for BSDFs. */
+ if (!(object->visibility & (PATH_RAY_DIFFUSE | PATH_RAY_GLOSSY | PATH_RAY_TRANSMIT))) {
+ return false;
+ }
+ /* Skip if we have no emission shaders. */
+ /* TODO(sergey): Ideally we want to avoid such duplicated loop, since it'll
+ * iterate all mesh shaders twice (when counting and when calculating
+ * triangle area.
+ */
+ foreach (const Shader *shader, mesh->used_shaders) {
+ if (shader->use_mis && shader->has_surface_emission) {
+ return true;
+ }
+ }
+ return false;
}
-void LightManager::device_update_distribution(Device *, DeviceScene *dscene, Scene *scene, Progress& progress)
+void LightManager::device_update_distribution(Device *,
+ DeviceScene *dscene,
+ Scene *scene,
+ Progress &progress)
{
- progress.set_status("Updating Lights", "Computing distribution");
-
- /* count */
- size_t num_lights = 0;
- size_t num_portals = 0;
- size_t num_background_lights = 0;
- size_t num_triangles = 0;
-
- bool background_mis = false;
-
- foreach(Light *light, scene->lights) {
- if(light->is_enabled) {
- num_lights++;
- }
- if(light->is_portal) {
- num_portals++;
- }
- }
-
- foreach(Object *object, scene->objects) {
- if(progress.get_cancel()) return;
-
- if(!object_usable_as_light(object)) {
- continue;
- }
- /* Count triangles. */
- Mesh *mesh = object->mesh;
- size_t mesh_num_triangles = mesh->num_triangles();
- for(size_t i = 0; i < mesh_num_triangles; i++) {
- int shader_index = mesh->shader[i];
- Shader *shader = (shader_index < mesh->used_shaders.size())
- ? mesh->used_shaders[shader_index]
- : scene->default_surface;
-
- if(shader->use_mis && shader->has_surface_emission) {
- num_triangles++;
- }
- }
- }
-
- size_t num_distribution = num_triangles + num_lights;
- VLOG(1) << "Total " << num_distribution << " of light distribution primitives.";
-
- /* emission area */
- KernelLightDistribution *distribution = dscene->light_distribution.alloc(num_distribution + 1);
- float totarea = 0.0f;
-
- /* triangles */
- size_t offset = 0;
- int j = 0;
-
- foreach(Object *object, scene->objects) {
- if(progress.get_cancel()) return;
-
- if(!object_usable_as_light(object)) {
- j++;
- continue;
- }
- /* Sum area. */
- Mesh *mesh = object->mesh;
- bool transform_applied = mesh->transform_applied;
- Transform tfm = object->tfm;
- int object_id = j;
- int shader_flag = 0;
-
- if(!(object->visibility & PATH_RAY_DIFFUSE)) {
- shader_flag |= SHADER_EXCLUDE_DIFFUSE;
- use_light_visibility = true;
- }
- if(!(object->visibility & PATH_RAY_GLOSSY)) {
- shader_flag |= SHADER_EXCLUDE_GLOSSY;
- use_light_visibility = true;
- }
- if(!(object->visibility & PATH_RAY_TRANSMIT)) {
- shader_flag |= SHADER_EXCLUDE_TRANSMIT;
- use_light_visibility = true;
- }
- if(!(object->visibility & PATH_RAY_VOLUME_SCATTER)) {
- shader_flag |= SHADER_EXCLUDE_SCATTER;
- use_light_visibility = true;
- }
-
- size_t mesh_num_triangles = mesh->num_triangles();
- for(size_t i = 0; i < mesh_num_triangles; i++) {
- int shader_index = mesh->shader[i];
- Shader *shader = (shader_index < mesh->used_shaders.size())
- ? mesh->used_shaders[shader_index]
- : scene->default_surface;
-
- if(shader->use_mis && shader->has_surface_emission) {
- distribution[offset].totarea = totarea;
- distribution[offset].prim = i + mesh->tri_offset;
- distribution[offset].mesh_light.shader_flag = shader_flag;
- distribution[offset].mesh_light.object_id = object_id;
- offset++;
-
- Mesh::Triangle t = mesh->get_triangle(i);
- if(!t.valid(&mesh->verts[0])) {
- continue;
- }
- float3 p1 = mesh->verts[t.v[0]];
- float3 p2 = mesh->verts[t.v[1]];
- float3 p3 = mesh->verts[t.v[2]];
-
- if(!transform_applied) {
- p1 = transform_point(&tfm, p1);
- p2 = transform_point(&tfm, p2);
- p3 = transform_point(&tfm, p3);
- }
-
- totarea += triangle_area(p1, p2, p3);
- }
- }
-
- j++;
- }
-
- float trianglearea = totarea;
-
- /* point lights */
- float lightarea = (totarea > 0.0f) ? totarea / num_lights : 1.0f;
- bool use_lamp_mis = false;
-
- int light_index = 0;
- foreach(Light *light, scene->lights) {
- if(!light->is_enabled)
- continue;
-
- distribution[offset].totarea = totarea;
- distribution[offset].prim = ~light_index;
- distribution[offset].lamp.pad = 1.0f;
- distribution[offset].lamp.size = light->size;
- totarea += lightarea;
-
- if(light->size > 0.0f && light->use_mis)
- use_lamp_mis = true;
- if(light->type == LIGHT_BACKGROUND) {
- num_background_lights++;
- background_mis = light->use_mis;
- }
-
- light_index++;
- offset++;
- }
-
- /* normalize cumulative distribution functions */
- distribution[num_distribution].totarea = totarea;
- distribution[num_distribution].prim = 0.0f;
- distribution[num_distribution].lamp.pad = 0.0f;
- distribution[num_distribution].lamp.size = 0.0f;
-
- if(totarea > 0.0f) {
- for(size_t i = 0; i < num_distribution; i++)
- distribution[i].totarea /= totarea;
- distribution[num_distribution].totarea = 1.0f;
- }
-
- if(progress.get_cancel()) return;
-
- /* update device */
- KernelIntegrator *kintegrator = &dscene->data.integrator;
- KernelFilm *kfilm = &dscene->data.film;
- kintegrator->use_direct_light = (totarea > 0.0f);
-
- if(kintegrator->use_direct_light) {
- /* number of emissives */
- kintegrator->num_distribution = num_distribution;
-
- /* precompute pdfs */
- kintegrator->pdf_triangles = 0.0f;
- kintegrator->pdf_lights = 0.0f;
-
- /* sample one, with 0.5 probability of light or triangle */
- kintegrator->num_all_lights = num_lights;
-
- if(trianglearea > 0.0f) {
- kintegrator->pdf_triangles = 1.0f/trianglearea;
- if(num_lights)
- kintegrator->pdf_triangles *= 0.5f;
- }
-
- if(num_lights) {
- kintegrator->pdf_lights = 1.0f/num_lights;
- if(trianglearea > 0.0f)
- kintegrator->pdf_lights *= 0.5f;
- }
-
- kintegrator->use_lamp_mis = use_lamp_mis;
-
- /* bit of an ugly hack to compensate for emitting triangles influencing
- * amount of samples we get for this pass */
- kfilm->pass_shadow_scale = 1.0f;
-
- if(kintegrator->pdf_triangles != 0.0f)
- kfilm->pass_shadow_scale *= 0.5f;
-
- if(num_background_lights < num_lights)
- kfilm->pass_shadow_scale *= (float)(num_lights - num_background_lights)/(float)num_lights;
-
- /* CDF */
- dscene->light_distribution.copy_to_device();
-
- /* Portals */
- if(num_portals > 0) {
- kintegrator->portal_offset = light_index;
- kintegrator->num_portals = num_portals;
- kintegrator->portal_pdf = background_mis? 0.5f: 1.0f;
- }
- else {
- kintegrator->num_portals = 0;
- kintegrator->portal_offset = 0;
- kintegrator->portal_pdf = 0.0f;
- }
- }
- else {
- dscene->light_distribution.free();
-
- kintegrator->num_distribution = 0;
- kintegrator->num_all_lights = 0;
- kintegrator->pdf_triangles = 0.0f;
- kintegrator->pdf_lights = 0.0f;
- kintegrator->use_lamp_mis = false;
- kintegrator->num_portals = 0;
- kintegrator->portal_offset = 0;
- kintegrator->portal_pdf = 0.0f;
-
- kfilm->pass_shadow_scale = 1.0f;
- }
+ progress.set_status("Updating Lights", "Computing distribution");
+
+ /* count */
+ size_t num_lights = 0;
+ size_t num_portals = 0;
+ size_t num_background_lights = 0;
+ size_t num_triangles = 0;
+
+ bool background_mis = false;
+
+ foreach (Light *light, scene->lights) {
+ if (light->is_enabled) {
+ num_lights++;
+ }
+ if (light->is_portal) {
+ num_portals++;
+ }
+ }
+
+ foreach (Object *object, scene->objects) {
+ if (progress.get_cancel())
+ return;
+
+ if (!object_usable_as_light(object)) {
+ continue;
+ }
+ /* Count triangles. */
+ Mesh *mesh = object->mesh;
+ size_t mesh_num_triangles = mesh->num_triangles();
+ for (size_t i = 0; i < mesh_num_triangles; i++) {
+ int shader_index = mesh->shader[i];
+ Shader *shader = (shader_index < mesh->used_shaders.size()) ?
+ mesh->used_shaders[shader_index] :
+ scene->default_surface;
+
+ if (shader->use_mis && shader->has_surface_emission) {
+ num_triangles++;
+ }
+ }
+ }
+
+ size_t num_distribution = num_triangles + num_lights;
+ VLOG(1) << "Total " << num_distribution << " of light distribution primitives.";
+
+ /* emission area */
+ KernelLightDistribution *distribution = dscene->light_distribution.alloc(num_distribution + 1);
+ float totarea = 0.0f;
+
+ /* triangles */
+ size_t offset = 0;
+ int j = 0;
+
+ foreach (Object *object, scene->objects) {
+ if (progress.get_cancel())
+ return;
+
+ if (!object_usable_as_light(object)) {
+ j++;
+ continue;
+ }
+ /* Sum area. */
+ Mesh *mesh = object->mesh;
+ bool transform_applied = mesh->transform_applied;
+ Transform tfm = object->tfm;
+ int object_id = j;
+ int shader_flag = 0;
+
+ if (!(object->visibility & PATH_RAY_DIFFUSE)) {
+ shader_flag |= SHADER_EXCLUDE_DIFFUSE;
+ use_light_visibility = true;
+ }
+ if (!(object->visibility & PATH_RAY_GLOSSY)) {
+ shader_flag |= SHADER_EXCLUDE_GLOSSY;
+ use_light_visibility = true;
+ }
+ if (!(object->visibility & PATH_RAY_TRANSMIT)) {
+ shader_flag |= SHADER_EXCLUDE_TRANSMIT;
+ use_light_visibility = true;
+ }
+ if (!(object->visibility & PATH_RAY_VOLUME_SCATTER)) {
+ shader_flag |= SHADER_EXCLUDE_SCATTER;
+ use_light_visibility = true;
+ }
+
+ size_t mesh_num_triangles = mesh->num_triangles();
+ for (size_t i = 0; i < mesh_num_triangles; i++) {
+ int shader_index = mesh->shader[i];
+ Shader *shader = (shader_index < mesh->used_shaders.size()) ?
+ mesh->used_shaders[shader_index] :
+ scene->default_surface;
+
+ if (shader->use_mis && shader->has_surface_emission) {
+ distribution[offset].totarea = totarea;
+ distribution[offset].prim = i + mesh->tri_offset;
+ distribution[offset].mesh_light.shader_flag = shader_flag;
+ distribution[offset].mesh_light.object_id = object_id;
+ offset++;
+
+ Mesh::Triangle t = mesh->get_triangle(i);
+ if (!t.valid(&mesh->verts[0])) {
+ continue;
+ }
+ float3 p1 = mesh->verts[t.v[0]];
+ float3 p2 = mesh->verts[t.v[1]];
+ float3 p3 = mesh->verts[t.v[2]];
+
+ if (!transform_applied) {
+ p1 = transform_point(&tfm, p1);
+ p2 = transform_point(&tfm, p2);
+ p3 = transform_point(&tfm, p3);
+ }
+
+ totarea += triangle_area(p1, p2, p3);
+ }
+ }
+
+ j++;
+ }
+
+ float trianglearea = totarea;
+
+ /* point lights */
+ float lightarea = (totarea > 0.0f) ? totarea / num_lights : 1.0f;
+ bool use_lamp_mis = false;
+
+ int light_index = 0;
+ foreach (Light *light, scene->lights) {
+ if (!light->is_enabled)
+ continue;
+
+ distribution[offset].totarea = totarea;
+ distribution[offset].prim = ~light_index;
+ distribution[offset].lamp.pad = 1.0f;
+ distribution[offset].lamp.size = light->size;
+ totarea += lightarea;
+
+ if (light->size > 0.0f && light->use_mis)
+ use_lamp_mis = true;
+ if (light->type == LIGHT_BACKGROUND) {
+ num_background_lights++;
+ background_mis = light->use_mis;
+ }
+
+ light_index++;
+ offset++;
+ }
+
+ /* normalize cumulative distribution functions */
+ distribution[num_distribution].totarea = totarea;
+ distribution[num_distribution].prim = 0.0f;
+ distribution[num_distribution].lamp.pad = 0.0f;
+ distribution[num_distribution].lamp.size = 0.0f;
+
+ if (totarea > 0.0f) {
+ for (size_t i = 0; i < num_distribution; i++)
+ distribution[i].totarea /= totarea;
+ distribution[num_distribution].totarea = 1.0f;
+ }
+
+ if (progress.get_cancel())
+ return;
+
+ /* update device */
+ KernelIntegrator *kintegrator = &dscene->data.integrator;
+ KernelFilm *kfilm = &dscene->data.film;
+ kintegrator->use_direct_light = (totarea > 0.0f);
+
+ if (kintegrator->use_direct_light) {
+ /* number of emissives */
+ kintegrator->num_distribution = num_distribution;
+
+ /* precompute pdfs */
+ kintegrator->pdf_triangles = 0.0f;
+ kintegrator->pdf_lights = 0.0f;
+
+ /* sample one, with 0.5 probability of light or triangle */
+ kintegrator->num_all_lights = num_lights;
+
+ if (trianglearea > 0.0f) {
+ kintegrator->pdf_triangles = 1.0f / trianglearea;
+ if (num_lights)
+ kintegrator->pdf_triangles *= 0.5f;
+ }
+
+ if (num_lights) {
+ kintegrator->pdf_lights = 1.0f / num_lights;
+ if (trianglearea > 0.0f)
+ kintegrator->pdf_lights *= 0.5f;
+ }
+
+ kintegrator->use_lamp_mis = use_lamp_mis;
+
+ /* bit of an ugly hack to compensate for emitting triangles influencing
+ * amount of samples we get for this pass */
+ kfilm->pass_shadow_scale = 1.0f;
+
+ if (kintegrator->pdf_triangles != 0.0f)
+ kfilm->pass_shadow_scale *= 0.5f;
+
+ if (num_background_lights < num_lights)
+ kfilm->pass_shadow_scale *= (float)(num_lights - num_background_lights) / (float)num_lights;
+
+ /* CDF */
+ dscene->light_distribution.copy_to_device();
+
+ /* Portals */
+ if (num_portals > 0) {
+ kintegrator->portal_offset = light_index;
+ kintegrator->num_portals = num_portals;
+ kintegrator->portal_pdf = background_mis ? 0.5f : 1.0f;
+ }
+ else {
+ kintegrator->num_portals = 0;
+ kintegrator->portal_offset = 0;
+ kintegrator->portal_pdf = 0.0f;
+ }
+ }
+ else {
+ dscene->light_distribution.free();
+
+ kintegrator->num_distribution = 0;
+ kintegrator->num_all_lights = 0;
+ kintegrator->pdf_triangles = 0.0f;
+ kintegrator->pdf_lights = 0.0f;
+ kintegrator->use_lamp_mis = false;
+ kintegrator->num_portals = 0;
+ kintegrator->portal_offset = 0;
+ kintegrator->portal_pdf = 0.0f;
+
+ kfilm->pass_shadow_scale = 1.0f;
+ }
}
-static void background_cdf(int start,
- int end,
- int res_x,
- int res_y,
- const vector<float3> *pixels,
- float2 *cond_cdf)
+static void background_cdf(
+ int start, int end, int res_x, int res_y, const vector<float3> *pixels, float2 *cond_cdf)
{
- int cdf_width = res_x+1;
- /* Conditional CDFs (rows, U direction). */
- for(int i = start; i < end; i++) {
- float sin_theta = sinf(M_PI_F * (i + 0.5f) / res_y);
- float3 env_color = (*pixels)[i * res_x];
- float ave_luminance = average(env_color);
-
- cond_cdf[i * cdf_width].x = ave_luminance * sin_theta;
- cond_cdf[i * cdf_width].y = 0.0f;
-
- for(int j = 1; j < res_x; j++) {
- env_color = (*pixels)[i * res_x + j];
- ave_luminance = average(env_color);
-
- cond_cdf[i * cdf_width + j].x = ave_luminance * sin_theta;
- cond_cdf[i * cdf_width + j].y = cond_cdf[i * cdf_width + j - 1].y + cond_cdf[i * cdf_width + j - 1].x / res_x;
- }
-
- float cdf_total = cond_cdf[i * cdf_width + res_x - 1].y + cond_cdf[i * cdf_width + res_x - 1].x / res_x;
- float cdf_total_inv = 1.0f / cdf_total;
-
- /* stuff the total into the brightness value for the last entry, because
- * we are going to normalize the CDFs to 0.0 to 1.0 afterwards */
- cond_cdf[i * cdf_width + res_x].x = cdf_total;
-
- if(cdf_total > 0.0f)
- for(int j = 1; j < res_x; j++)
- cond_cdf[i * cdf_width + j].y *= cdf_total_inv;
-
- cond_cdf[i * cdf_width + res_x].y = 1.0f;
- }
+ int cdf_width = res_x + 1;
+ /* Conditional CDFs (rows, U direction). */
+ for (int i = start; i < end; i++) {
+ float sin_theta = sinf(M_PI_F * (i + 0.5f) / res_y);
+ float3 env_color = (*pixels)[i * res_x];
+ float ave_luminance = average(env_color);
+
+ cond_cdf[i * cdf_width].x = ave_luminance * sin_theta;
+ cond_cdf[i * cdf_width].y = 0.0f;
+
+ for (int j = 1; j < res_x; j++) {
+ env_color = (*pixels)[i * res_x + j];
+ ave_luminance = average(env_color);
+
+ cond_cdf[i * cdf_width + j].x = ave_luminance * sin_theta;
+ cond_cdf[i * cdf_width + j].y = cond_cdf[i * cdf_width + j - 1].y +
+ cond_cdf[i * cdf_width + j - 1].x / res_x;
+ }
+
+ float cdf_total = cond_cdf[i * cdf_width + res_x - 1].y +
+ cond_cdf[i * cdf_width + res_x - 1].x / res_x;
+ float cdf_total_inv = 1.0f / cdf_total;
+
+ /* stuff the total into the brightness value for the last entry, because
+ * we are going to normalize the CDFs to 0.0 to 1.0 afterwards */
+ cond_cdf[i * cdf_width + res_x].x = cdf_total;
+
+ if (cdf_total > 0.0f)
+ for (int j = 1; j < res_x; j++)
+ cond_cdf[i * cdf_width + j].y *= cdf_total_inv;
+
+ cond_cdf[i * cdf_width + res_x].y = 1.0f;
+ }
}
void LightManager::device_update_background(Device *device,
DeviceScene *dscene,
Scene *scene,
- Progress& progress)
+ Progress &progress)
{
- KernelIntegrator *kintegrator = &dscene->data.integrator;
- Light *background_light = NULL;
-
- /* find background light */
- foreach(Light *light, scene->lights) {
- if(light->type == LIGHT_BACKGROUND) {
- background_light = light;
- break;
- }
- }
-
- /* no background light found, signal renderer to skip sampling */
- if(!background_light || !background_light->is_enabled) {
- kintegrator->pdf_background_res_x = 0;
- kintegrator->pdf_background_res_y = 0;
- return;
- }
-
- progress.set_status("Updating Lights", "Importance map");
-
- assert(kintegrator->use_direct_light);
-
- /* get the resolution from the light's size (we stuff it in there) */
- int2 res = make_int2(background_light->map_resolution, background_light->map_resolution/2);
- /* If the resolution isn't set manually, try to find an environment texture. */
- if(res.x == 0) {
- Shader *shader = (scene->background->shader) ? scene->background->shader : scene->default_background;
- foreach(ShaderNode *node, shader->graph->nodes) {
- if(node->type == EnvironmentTextureNode::node_type) {
- EnvironmentTextureNode *env = (EnvironmentTextureNode*) node;
- ImageMetaData metadata;
- if(env->image_manager && env->image_manager->get_image_metadata(env->slot, metadata)) {
- res.x = max(res.x, metadata.width);
- res.y = max(res.y, metadata.height);
- }
- }
- }
- if(res.x > 0 && res.y > 0) {
- VLOG(2) << "Automatically set World MIS resolution to " << res.x << " by " << res.y << "\n";
- }
- }
- /* If it's still unknown, just use the default. */
- if(res.x == 0 || res.y == 0) {
- res = make_int2(1024, 512);
- VLOG(2) << "Setting World MIS resolution to default\n";
- }
- kintegrator->pdf_background_res_x = res.x;
- kintegrator->pdf_background_res_y = res.y;
-
- vector<float3> pixels;
- shade_background_pixels(device, dscene, res.x, res.y, pixels, progress);
-
- if(progress.get_cancel())
- return;
-
- /* build row distributions and column distribution for the infinite area environment light */
- int cdf_width = res.x+1;
- float2 *marg_cdf = dscene->light_background_marginal_cdf.alloc(res.y + 1);
- float2 *cond_cdf = dscene->light_background_conditional_cdf.alloc(cdf_width * res.y);
-
- double time_start = time_dt();
- if(max(res.x, res.y) < 512) {
- /* Small enough resolution, faster to do single-threaded. */
- background_cdf(0, res.y, res.x, res.y, &pixels, cond_cdf);
- }
- else {
- /* Threaded evaluation for large resolution. */
- const int num_blocks = TaskScheduler::num_threads();
- const int chunk_size = res.y / num_blocks;
- int start_row = 0;
- TaskPool pool;
- for(int i = 0; i < num_blocks; ++i) {
- const int current_chunk_size =
- (i != num_blocks - 1) ? chunk_size
- : (res.y - i * chunk_size);
- pool.push(function_bind(&background_cdf,
- start_row, start_row + current_chunk_size,
- res.x,
- res.y,
- &pixels,
- cond_cdf));
- start_row += current_chunk_size;
- }
- pool.wait_work();
- }
-
- /* marginal CDFs (column, V direction, sum of rows) */
- marg_cdf[0].x = cond_cdf[res.x].x;
- marg_cdf[0].y = 0.0f;
-
- for(int i = 1; i < res.y; i++) {
- marg_cdf[i].x = cond_cdf[i * cdf_width + res.x].x;
- marg_cdf[i].y = marg_cdf[i - 1].y + marg_cdf[i - 1].x / res.y;
- }
-
- float cdf_total = marg_cdf[res.y - 1].y + marg_cdf[res.y - 1].x / res.y;
- marg_cdf[res.y].x = cdf_total;
-
- if(cdf_total > 0.0f)
- for(int i = 1; i < res.y; i++)
- marg_cdf[i].y /= cdf_total;
-
- marg_cdf[res.y].y = 1.0f;
-
- VLOG(2) << "Background MIS build time " << time_dt() - time_start << "\n";
-
- /* update device */
- dscene->light_background_marginal_cdf.copy_to_device();
- dscene->light_background_conditional_cdf.copy_to_device();
+ KernelIntegrator *kintegrator = &dscene->data.integrator;
+ Light *background_light = NULL;
+
+ /* find background light */
+ foreach (Light *light, scene->lights) {
+ if (light->type == LIGHT_BACKGROUND) {
+ background_light = light;
+ break;
+ }
+ }
+
+ /* no background light found, signal renderer to skip sampling */
+ if (!background_light || !background_light->is_enabled) {
+ kintegrator->pdf_background_res_x = 0;
+ kintegrator->pdf_background_res_y = 0;
+ return;
+ }
+
+ progress.set_status("Updating Lights", "Importance map");
+
+ assert(kintegrator->use_direct_light);
+
+ /* get the resolution from the light's size (we stuff it in there) */
+ int2 res = make_int2(background_light->map_resolution, background_light->map_resolution / 2);
+ /* If the resolution isn't set manually, try to find an environment texture. */
+ if (res.x == 0) {
+ Shader *shader = (scene->background->shader) ? scene->background->shader :
+ scene->default_background;
+ foreach (ShaderNode *node, shader->graph->nodes) {
+ if (node->type == EnvironmentTextureNode::node_type) {
+ EnvironmentTextureNode *env = (EnvironmentTextureNode *)node;
+ ImageMetaData metadata;
+ if (env->image_manager && env->image_manager->get_image_metadata(env->slot, metadata)) {
+ res.x = max(res.x, metadata.width);
+ res.y = max(res.y, metadata.height);
+ }
+ }
+ }
+ if (res.x > 0 && res.y > 0) {
+ VLOG(2) << "Automatically set World MIS resolution to " << res.x << " by " << res.y << "\n";
+ }
+ }
+ /* If it's still unknown, just use the default. */
+ if (res.x == 0 || res.y == 0) {
+ res = make_int2(1024, 512);
+ VLOG(2) << "Setting World MIS resolution to default\n";
+ }
+ kintegrator->pdf_background_res_x = res.x;
+ kintegrator->pdf_background_res_y = res.y;
+
+ vector<float3> pixels;
+ shade_background_pixels(device, dscene, res.x, res.y, pixels, progress);
+
+ if (progress.get_cancel())
+ return;
+
+ /* build row distributions and column distribution for the infinite area environment light */
+ int cdf_width = res.x + 1;
+ float2 *marg_cdf = dscene->light_background_marginal_cdf.alloc(res.y + 1);
+ float2 *cond_cdf = dscene->light_background_conditional_cdf.alloc(cdf_width * res.y);
+
+ double time_start = time_dt();
+ if (max(res.x, res.y) < 512) {
+ /* Small enough resolution, faster to do single-threaded. */
+ background_cdf(0, res.y, res.x, res.y, &pixels, cond_cdf);
+ }
+ else {
+ /* Threaded evaluation for large resolution. */
+ const int num_blocks = TaskScheduler::num_threads();
+ const int chunk_size = res.y / num_blocks;
+ int start_row = 0;
+ TaskPool pool;
+ for (int i = 0; i < num_blocks; ++i) {
+ const int current_chunk_size = (i != num_blocks - 1) ? chunk_size : (res.y - i * chunk_size);
+ pool.push(function_bind(&background_cdf,
+ start_row,
+ start_row + current_chunk_size,
+ res.x,
+ res.y,
+ &pixels,
+ cond_cdf));
+ start_row += current_chunk_size;
+ }
+ pool.wait_work();
+ }
+
+ /* marginal CDFs (column, V direction, sum of rows) */
+ marg_cdf[0].x = cond_cdf[res.x].x;
+ marg_cdf[0].y = 0.0f;
+
+ for (int i = 1; i < res.y; i++) {
+ marg_cdf[i].x = cond_cdf[i * cdf_width + res.x].x;
+ marg_cdf[i].y = marg_cdf[i - 1].y + marg_cdf[i - 1].x / res.y;
+ }
+
+ float cdf_total = marg_cdf[res.y - 1].y + marg_cdf[res.y - 1].x / res.y;
+ marg_cdf[res.y].x = cdf_total;
+
+ if (cdf_total > 0.0f)
+ for (int i = 1; i < res.y; i++)
+ marg_cdf[i].y /= cdf_total;
+
+ marg_cdf[res.y].y = 1.0f;
+
+ VLOG(2) << "Background MIS build time " << time_dt() - time_start << "\n";
+
+ /* update device */
+ dscene->light_background_marginal_cdf.copy_to_device();
+ dscene->light_background_conditional_cdf.copy_to_device();
}
-void LightManager::device_update_points(Device *,
- DeviceScene *dscene,
- Scene *scene)
+void LightManager::device_update_points(Device *, DeviceScene *dscene, Scene *scene)
{
- int num_scene_lights = scene->lights.size();
-
- int num_lights = 0;
- foreach(Light *light, scene->lights) {
- if(light->is_enabled || light->is_portal) {
- num_lights++;
- }
- }
-
- KernelLight *klights = dscene->lights.alloc(num_lights);
-
- if(num_lights == 0) {
- VLOG(1) << "No effective light, ignoring points update.";
- return;
- }
-
- int light_index = 0;
-
- foreach(Light *light, scene->lights) {
- if(!light->is_enabled) {
- continue;
- }
-
- float3 co = light->co;
- Shader *shader = (light->shader) ? light->shader : scene->default_light;
- int shader_id = scene->shader_manager->get_shader_id(shader);
- int samples = light->samples;
- int max_bounces = light->max_bounces;
- float random = (float)light->random_id * (1.0f/(float)0xFFFFFFFF);
-
- if(!light->cast_shadow)
- shader_id &= ~SHADER_CAST_SHADOW;
-
- if(!light->use_diffuse) {
- shader_id |= SHADER_EXCLUDE_DIFFUSE;
- use_light_visibility = true;
- }
- if(!light->use_glossy) {
- shader_id |= SHADER_EXCLUDE_GLOSSY;
- use_light_visibility = true;
- }
- if(!light->use_transmission) {
- shader_id |= SHADER_EXCLUDE_TRANSMIT;
- use_light_visibility = true;
- }
- if(!light->use_scatter) {
- shader_id |= SHADER_EXCLUDE_SCATTER;
- use_light_visibility = true;
- }
-
- klights[light_index].type = light->type;
- klights[light_index].samples = samples;
-
- if(light->type == LIGHT_POINT) {
- shader_id &= ~SHADER_AREA_LIGHT;
-
- float radius = light->size;
- float invarea = (radius > 0.0f)? 1.0f/(M_PI_F*radius*radius): 1.0f;
-
- if(light->use_mis && radius > 0.0f)
- shader_id |= SHADER_USE_MIS;
-
- klights[light_index].co[0] = co.x;
- klights[light_index].co[1] = co.y;
- klights[light_index].co[2] = co.z;
-
- klights[light_index].spot.radius = radius;
- klights[light_index].spot.invarea = invarea;
- }
- else if(light->type == LIGHT_DISTANT) {
- shader_id &= ~SHADER_AREA_LIGHT;
-
- float radius = light->size;
- float angle = atanf(radius);
- float cosangle = cosf(angle);
- float area = M_PI_F*radius*radius;
- float invarea = (area > 0.0f)? 1.0f/area: 1.0f;
- float3 dir = light->dir;
-
- dir = safe_normalize(dir);
-
- if(light->use_mis && area > 0.0f)
- shader_id |= SHADER_USE_MIS;
-
- klights[light_index].co[0] = dir.x;
- klights[light_index].co[1] = dir.y;
- klights[light_index].co[2] = dir.z;
-
- klights[light_index].distant.invarea = invarea;
- klights[light_index].distant.radius = radius;
- klights[light_index].distant.cosangle = cosangle;
- }
- else if(light->type == LIGHT_BACKGROUND) {
- uint visibility = scene->background->visibility;
-
- shader_id &= ~SHADER_AREA_LIGHT;
- shader_id |= SHADER_USE_MIS;
-
- if(!(visibility & PATH_RAY_DIFFUSE)) {
- shader_id |= SHADER_EXCLUDE_DIFFUSE;
- use_light_visibility = true;
- }
- if(!(visibility & PATH_RAY_GLOSSY)) {
- shader_id |= SHADER_EXCLUDE_GLOSSY;
- use_light_visibility = true;
- }
- if(!(visibility & PATH_RAY_TRANSMIT)) {
- shader_id |= SHADER_EXCLUDE_TRANSMIT;
- use_light_visibility = true;
- }
- if(!(visibility & PATH_RAY_VOLUME_SCATTER)) {
- shader_id |= SHADER_EXCLUDE_SCATTER;
- use_light_visibility = true;
- }
- }
- else if(light->type == LIGHT_AREA) {
- float3 axisu = light->axisu*(light->sizeu*light->size);
- float3 axisv = light->axisv*(light->sizev*light->size);
- float area = len(axisu)*len(axisv);
- if(light->round) {
- area *= -M_PI_4_F;
- }
- float invarea = (area != 0.0f)? 1.0f/area: 1.0f;
- float3 dir = light->dir;
-
- dir = safe_normalize(dir);
-
- if(light->use_mis && area != 0.0f)
- shader_id |= SHADER_USE_MIS;
-
- klights[light_index].co[0] = co.x;
- klights[light_index].co[1] = co.y;
- klights[light_index].co[2] = co.z;
-
- klights[light_index].area.axisu[0] = axisu.x;
- klights[light_index].area.axisu[1] = axisu.y;
- klights[light_index].area.axisu[2] = axisu.z;
- klights[light_index].area.axisv[0] = axisv.x;
- klights[light_index].area.axisv[1] = axisv.y;
- klights[light_index].area.axisv[2] = axisv.z;
- klights[light_index].area.invarea = invarea;
- klights[light_index].area.dir[0] = dir.x;
- klights[light_index].area.dir[1] = dir.y;
- klights[light_index].area.dir[2] = dir.z;
- }
- else if(light->type == LIGHT_SPOT) {
- shader_id &= ~SHADER_AREA_LIGHT;
-
- float radius = light->size;
- float invarea = (radius > 0.0f)? 1.0f/(M_PI_F*radius*radius): 1.0f;
- float spot_angle = cosf(light->spot_angle*0.5f);
- float spot_smooth = (1.0f - spot_angle)*light->spot_smooth;
- float3 dir = light->dir;
-
- dir = safe_normalize(dir);
-
- if(light->use_mis && radius > 0.0f)
- shader_id |= SHADER_USE_MIS;
-
- klights[light_index].co[0] = co.x;
- klights[light_index].co[1] = co.y;
- klights[light_index].co[2] = co.z;
-
- klights[light_index].spot.radius = radius;
- klights[light_index].spot.invarea = invarea;
- klights[light_index].spot.spot_angle = spot_angle;
- klights[light_index].spot.spot_smooth = spot_smooth;
- klights[light_index].spot.dir[0] = dir.x;
- klights[light_index].spot.dir[1] = dir.y;
- klights[light_index].spot.dir[2] = dir.z;
- }
-
- klights[light_index].shader_id = shader_id;
-
- klights[light_index].max_bounces = max_bounces;
- klights[light_index].random = random;
-
- klights[light_index].tfm = light->tfm;
- klights[light_index].itfm = transform_inverse(light->tfm);
-
- light_index++;
- }
-
- /* TODO(sergey): Consider moving portals update to their own function
- * keeping this one more manageable.
- */
- foreach(Light *light, scene->lights) {
- if(!light->is_portal)
- continue;
- assert(light->type == LIGHT_AREA);
-
- float3 co = light->co;
- float3 axisu = light->axisu*(light->sizeu*light->size);
- float3 axisv = light->axisv*(light->sizev*light->size);
- float area = len(axisu)*len(axisv);
- if(light->round) {
- area *= -M_PI_4_F;
- }
- float invarea = (area != 0.0f)? 1.0f/area: 1.0f;
- float3 dir = light->dir;
-
- dir = safe_normalize(dir);
-
- klights[light_index].co[0] = co.x;
- klights[light_index].co[1] = co.y;
- klights[light_index].co[2] = co.z;
-
- klights[light_index].area.axisu[0] = axisu.x;
- klights[light_index].area.axisu[1] = axisu.y;
- klights[light_index].area.axisu[2] = axisu.z;
- klights[light_index].area.axisv[0] = axisv.x;
- klights[light_index].area.axisv[1] = axisv.y;
- klights[light_index].area.axisv[2] = axisv.z;
- klights[light_index].area.invarea = invarea;
- klights[light_index].area.dir[0] = dir.x;
- klights[light_index].area.dir[1] = dir.y;
- klights[light_index].area.dir[2] = dir.z;
- klights[light_index].tfm = light->tfm;
- klights[light_index].itfm = transform_inverse(light->tfm);
-
- light_index++;
- }
-
- VLOG(1) << "Number of lights sent to the device: " << light_index;
-
- VLOG(1) << "Number of lights without contribution: "
- << num_scene_lights - light_index;
-
- dscene->lights.copy_to_device();
+ int num_scene_lights = scene->lights.size();
+
+ int num_lights = 0;
+ foreach (Light *light, scene->lights) {
+ if (light->is_enabled || light->is_portal) {
+ num_lights++;
+ }
+ }
+
+ KernelLight *klights = dscene->lights.alloc(num_lights);
+
+ if (num_lights == 0) {
+ VLOG(1) << "No effective light, ignoring points update.";
+ return;
+ }
+
+ int light_index = 0;
+
+ foreach (Light *light, scene->lights) {
+ if (!light->is_enabled) {
+ continue;
+ }
+
+ float3 co = light->co;
+ Shader *shader = (light->shader) ? light->shader : scene->default_light;
+ int shader_id = scene->shader_manager->get_shader_id(shader);
+ int samples = light->samples;
+ int max_bounces = light->max_bounces;
+ float random = (float)light->random_id * (1.0f / (float)0xFFFFFFFF);
+
+ if (!light->cast_shadow)
+ shader_id &= ~SHADER_CAST_SHADOW;
+
+ if (!light->use_diffuse) {
+ shader_id |= SHADER_EXCLUDE_DIFFUSE;
+ use_light_visibility = true;
+ }
+ if (!light->use_glossy) {
+ shader_id |= SHADER_EXCLUDE_GLOSSY;
+ use_light_visibility = true;
+ }
+ if (!light->use_transmission) {
+ shader_id |= SHADER_EXCLUDE_TRANSMIT;
+ use_light_visibility = true;
+ }
+ if (!light->use_scatter) {
+ shader_id |= SHADER_EXCLUDE_SCATTER;
+ use_light_visibility = true;
+ }
+
+ klights[light_index].type = light->type;
+ klights[light_index].samples = samples;
+
+ if (light->type == LIGHT_POINT) {
+ shader_id &= ~SHADER_AREA_LIGHT;
+
+ float radius = light->size;
+ float invarea = (radius > 0.0f) ? 1.0f / (M_PI_F * radius * radius) : 1.0f;
+
+ if (light->use_mis && radius > 0.0f)
+ shader_id |= SHADER_USE_MIS;
+
+ klights[light_index].co[0] = co.x;
+ klights[light_index].co[1] = co.y;
+ klights[light_index].co[2] = co.z;
+
+ klights[light_index].spot.radius = radius;
+ klights[light_index].spot.invarea = invarea;
+ }
+ else if (light->type == LIGHT_DISTANT) {
+ shader_id &= ~SHADER_AREA_LIGHT;
+
+ float radius = light->size;
+ float angle = atanf(radius);
+ float cosangle = cosf(angle);
+ float area = M_PI_F * radius * radius;
+ float invarea = (area > 0.0f) ? 1.0f / area : 1.0f;
+ float3 dir = light->dir;
+
+ dir = safe_normalize(dir);
+
+ if (light->use_mis && area > 0.0f)
+ shader_id |= SHADER_USE_MIS;
+
+ klights[light_index].co[0] = dir.x;
+ klights[light_index].co[1] = dir.y;
+ klights[light_index].co[2] = dir.z;
+
+ klights[light_index].distant.invarea = invarea;
+ klights[light_index].distant.radius = radius;
+ klights[light_index].distant.cosangle = cosangle;
+ }
+ else if (light->type == LIGHT_BACKGROUND) {
+ uint visibility = scene->background->visibility;
+
+ shader_id &= ~SHADER_AREA_LIGHT;
+ shader_id |= SHADER_USE_MIS;
+
+ if (!(visibility & PATH_RAY_DIFFUSE)) {
+ shader_id |= SHADER_EXCLUDE_DIFFUSE;
+ use_light_visibility = true;
+ }
+ if (!(visibility & PATH_RAY_GLOSSY)) {
+ shader_id |= SHADER_EXCLUDE_GLOSSY;
+ use_light_visibility = true;
+ }
+ if (!(visibility & PATH_RAY_TRANSMIT)) {
+ shader_id |= SHADER_EXCLUDE_TRANSMIT;
+ use_light_visibility = true;
+ }
+ if (!(visibility & PATH_RAY_VOLUME_SCATTER)) {
+ shader_id |= SHADER_EXCLUDE_SCATTER;
+ use_light_visibility = true;
+ }
+ }
+ else if (light->type == LIGHT_AREA) {
+ float3 axisu = light->axisu * (light->sizeu * light->size);
+ float3 axisv = light->axisv * (light->sizev * light->size);
+ float area = len(axisu) * len(axisv);
+ if (light->round) {
+ area *= -M_PI_4_F;
+ }
+ float invarea = (area != 0.0f) ? 1.0f / area : 1.0f;
+ float3 dir = light->dir;
+
+ dir = safe_normalize(dir);
+
+ if (light->use_mis && area != 0.0f)
+ shader_id |= SHADER_USE_MIS;
+
+ klights[light_index].co[0] = co.x;
+ klights[light_index].co[1] = co.y;
+ klights[light_index].co[2] = co.z;
+
+ klights[light_index].area.axisu[0] = axisu.x;
+ klights[light_index].area.axisu[1] = axisu.y;
+ klights[light_index].area.axisu[2] = axisu.z;
+ klights[light_index].area.axisv[0] = axisv.x;
+ klights[light_index].area.axisv[1] = axisv.y;
+ klights[light_index].area.axisv[2] = axisv.z;
+ klights[light_index].area.invarea = invarea;
+ klights[light_index].area.dir[0] = dir.x;
+ klights[light_index].area.dir[1] = dir.y;
+ klights[light_index].area.dir[2] = dir.z;
+ }
+ else if (light->type == LIGHT_SPOT) {
+ shader_id &= ~SHADER_AREA_LIGHT;
+
+ float radius = light->size;
+ float invarea = (radius > 0.0f) ? 1.0f / (M_PI_F * radius * radius) : 1.0f;
+ float spot_angle = cosf(light->spot_angle * 0.5f);
+ float spot_smooth = (1.0f - spot_angle) * light->spot_smooth;
+ float3 dir = light->dir;
+
+ dir = safe_normalize(dir);
+
+ if (light->use_mis && radius > 0.0f)
+ shader_id |= SHADER_USE_MIS;
+
+ klights[light_index].co[0] = co.x;
+ klights[light_index].co[1] = co.y;
+ klights[light_index].co[2] = co.z;
+
+ klights[light_index].spot.radius = radius;
+ klights[light_index].spot.invarea = invarea;
+ klights[light_index].spot.spot_angle = spot_angle;
+ klights[light_index].spot.spot_smooth = spot_smooth;
+ klights[light_index].spot.dir[0] = dir.x;
+ klights[light_index].spot.dir[1] = dir.y;
+ klights[light_index].spot.dir[2] = dir.z;
+ }
+
+ klights[light_index].shader_id = shader_id;
+
+ klights[light_index].max_bounces = max_bounces;
+ klights[light_index].random = random;
+
+ klights[light_index].tfm = light->tfm;
+ klights[light_index].itfm = transform_inverse(light->tfm);
+
+ light_index++;
+ }
+
+ /* TODO(sergey): Consider moving portals update to their own function
+ * keeping this one more manageable.
+ */
+ foreach (Light *light, scene->lights) {
+ if (!light->is_portal)
+ continue;
+ assert(light->type == LIGHT_AREA);
+
+ float3 co = light->co;
+ float3 axisu = light->axisu * (light->sizeu * light->size);
+ float3 axisv = light->axisv * (light->sizev * light->size);
+ float area = len(axisu) * len(axisv);
+ if (light->round) {
+ area *= -M_PI_4_F;
+ }
+ float invarea = (area != 0.0f) ? 1.0f / area : 1.0f;
+ float3 dir = light->dir;
+
+ dir = safe_normalize(dir);
+
+ klights[light_index].co[0] = co.x;
+ klights[light_index].co[1] = co.y;
+ klights[light_index].co[2] = co.z;
+
+ klights[light_index].area.axisu[0] = axisu.x;
+ klights[light_index].area.axisu[1] = axisu.y;
+ klights[light_index].area.axisu[2] = axisu.z;
+ klights[light_index].area.axisv[0] = axisv.x;
+ klights[light_index].area.axisv[1] = axisv.y;
+ klights[light_index].area.axisv[2] = axisv.z;
+ klights[light_index].area.invarea = invarea;
+ klights[light_index].area.dir[0] = dir.x;
+ klights[light_index].area.dir[1] = dir.y;
+ klights[light_index].area.dir[2] = dir.z;
+ klights[light_index].tfm = light->tfm;
+ klights[light_index].itfm = transform_inverse(light->tfm);
+
+ light_index++;
+ }
+
+ VLOG(1) << "Number of lights sent to the device: " << light_index;
+
+ VLOG(1) << "Number of lights without contribution: " << num_scene_lights - light_index;
+
+ dscene->lights.copy_to_device();
}
-void LightManager::device_update(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress)
+void LightManager::device_update(Device *device,
+ DeviceScene *dscene,
+ Scene *scene,
+ Progress &progress)
{
- if(!need_update)
- return;
+ if (!need_update)
+ return;
- VLOG(1) << "Total " << scene->lights.size() << " lights.";
+ VLOG(1) << "Total " << scene->lights.size() << " lights.";
- device_free(device, dscene);
+ device_free(device, dscene);
- use_light_visibility = false;
+ use_light_visibility = false;
- disable_ineffective_light(scene);
+ disable_ineffective_light(scene);
- device_update_points(device, dscene, scene);
- if(progress.get_cancel()) return;
+ device_update_points(device, dscene, scene);
+ if (progress.get_cancel())
+ return;
- device_update_distribution(device, dscene, scene, progress);
- if(progress.get_cancel()) return;
+ device_update_distribution(device, dscene, scene, progress);
+ if (progress.get_cancel())
+ return;
- device_update_background(device, dscene, scene, progress);
- if(progress.get_cancel()) return;
+ device_update_background(device, dscene, scene, progress);
+ if (progress.get_cancel())
+ return;
- device_update_ies(dscene);
- if(progress.get_cancel()) return;
+ device_update_ies(dscene);
+ if (progress.get_cancel())
+ return;
- if(use_light_visibility != scene->film->use_light_visibility) {
- scene->film->use_light_visibility = use_light_visibility;
- scene->film->tag_update(scene);
- }
+ if (use_light_visibility != scene->film->use_light_visibility) {
+ scene->film->use_light_visibility = use_light_visibility;
+ scene->film->tag_update(scene);
+ }
- need_update = false;
+ need_update = false;
}
void LightManager::device_free(Device *, DeviceScene *dscene)
{
- dscene->light_distribution.free();
- dscene->lights.free();
- dscene->light_background_marginal_cdf.free();
- dscene->light_background_conditional_cdf.free();
- dscene->ies_lights.free();
+ dscene->light_distribution.free();
+ dscene->lights.free();
+ dscene->light_background_marginal_cdf.free();
+ dscene->light_background_conditional_cdf.free();
+ dscene->ies_lights.free();
}
void LightManager::tag_update(Scene * /*scene*/)
{
- need_update = true;
+ need_update = true;
}
int LightManager::add_ies_from_file(ustring filename)
{
- string content;
+ string content;
- /* If the file can't be opened, call with an empty line */
- if(filename.empty() || !path_read_text(filename.c_str(), content)) {
- content = "\n";
- }
+ /* If the file can't be opened, call with an empty line */
+ if (filename.empty() || !path_read_text(filename.c_str(), content)) {
+ content = "\n";
+ }
- return add_ies(ustring(content));
+ return add_ies(ustring(content));
}
int LightManager::add_ies(ustring content)
{
- uint hash = hash_string(content.c_str());
-
- thread_scoped_lock ies_lock(ies_mutex);
-
- /* Check whether this IES already has a slot. */
- size_t slot;
- for(slot = 0; slot < ies_slots.size(); slot++) {
- if(ies_slots[slot]->hash == hash) {
- ies_slots[slot]->users++;
- return slot;
- }
- }
-
- /* Try to find an empty slot for the new IES. */
- for(slot = 0; slot < ies_slots.size(); slot++) {
- if(ies_slots[slot]->users == 0 && ies_slots[slot]->hash == 0) {
- break;
- }
- }
-
- /* If there's no free slot, add one. */
- if(slot == ies_slots.size()) {
- ies_slots.push_back(new IESSlot());
- }
-
- ies_slots[slot]->ies.load(content);
- ies_slots[slot]->users = 1;
- ies_slots[slot]->hash = hash;
-
- need_update = true;
-
- return slot;
+ uint hash = hash_string(content.c_str());
+
+ thread_scoped_lock ies_lock(ies_mutex);
+
+ /* Check whether this IES already has a slot. */
+ size_t slot;
+ for (slot = 0; slot < ies_slots.size(); slot++) {
+ if (ies_slots[slot]->hash == hash) {
+ ies_slots[slot]->users++;
+ return slot;
+ }
+ }
+
+ /* Try to find an empty slot for the new IES. */
+ for (slot = 0; slot < ies_slots.size(); slot++) {
+ if (ies_slots[slot]->users == 0 && ies_slots[slot]->hash == 0) {
+ break;
+ }
+ }
+
+ /* If there's no free slot, add one. */
+ if (slot == ies_slots.size()) {
+ ies_slots.push_back(new IESSlot());
+ }
+
+ ies_slots[slot]->ies.load(content);
+ ies_slots[slot]->users = 1;
+ ies_slots[slot]->hash = hash;
+
+ need_update = true;
+
+ return slot;
}
void LightManager::remove_ies(int slot)
{
- thread_scoped_lock ies_lock(ies_mutex);
+ thread_scoped_lock ies_lock(ies_mutex);
- if(slot < 0 || slot >= ies_slots.size()) {
- assert(false);
- return;
- }
+ if (slot < 0 || slot >= ies_slots.size()) {
+ assert(false);
+ return;
+ }
- assert(ies_slots[slot]->users > 0);
- ies_slots[slot]->users--;
+ assert(ies_slots[slot]->users > 0);
+ ies_slots[slot]->users--;
- /* If the slot has no more users, update the device to remove it. */
- need_update |= (ies_slots[slot]->users == 0);
+ /* If the slot has no more users, update the device to remove it. */
+ need_update |= (ies_slots[slot]->users == 0);
}
void LightManager::device_update_ies(DeviceScene *dscene)
{
- /* Clear empty slots. */
- foreach(IESSlot *slot, ies_slots) {
- if(slot->users == 0) {
- slot->hash = 0;
- slot->ies.clear();
- }
- }
-
- /* Shrink the slot table by removing empty slots at the end. */
- int slot_end;
- for(slot_end = ies_slots.size(); slot_end; slot_end--) {
- if(ies_slots[slot_end-1]->users > 0) {
- /* If the preceding slot has users, we found the new end of the table. */
- break;
- }
- else {
- /* The slot will be past the new end of the table, so free it. */
- delete ies_slots[slot_end-1];
- }
- }
- ies_slots.resize(slot_end);
-
- if(ies_slots.size() > 0) {
- int packed_size = 0;
- foreach(IESSlot *slot, ies_slots) {
- packed_size += slot->ies.packed_size();
- }
-
- /* ies_lights starts with an offset table that contains the offset of every slot,
- * or -1 if the slot is invalid.
- * Following that table, the packed valid IES lights are stored. */
- float *data = dscene->ies_lights.alloc(ies_slots.size() + packed_size);
-
- int offset = ies_slots.size();
- for(int i = 0; i < ies_slots.size(); i++) {
- int size = ies_slots[i]->ies.packed_size();
- if(size > 0) {
- data[i] = __int_as_float(offset);
- ies_slots[i]->ies.pack(data + offset);
- offset += size;
- }
- else {
- data[i] = __int_as_float(-1);
- }
- }
-
- dscene->ies_lights.copy_to_device();
- }
+ /* Clear empty slots. */
+ foreach (IESSlot *slot, ies_slots) {
+ if (slot->users == 0) {
+ slot->hash = 0;
+ slot->ies.clear();
+ }
+ }
+
+ /* Shrink the slot table by removing empty slots at the end. */
+ int slot_end;
+ for (slot_end = ies_slots.size(); slot_end; slot_end--) {
+ if (ies_slots[slot_end - 1]->users > 0) {
+ /* If the preceding slot has users, we found the new end of the table. */
+ break;
+ }
+ else {
+ /* The slot will be past the new end of the table, so free it. */
+ delete ies_slots[slot_end - 1];
+ }
+ }
+ ies_slots.resize(slot_end);
+
+ if (ies_slots.size() > 0) {
+ int packed_size = 0;
+ foreach (IESSlot *slot, ies_slots) {
+ packed_size += slot->ies.packed_size();
+ }
+
+ /* ies_lights starts with an offset table that contains the offset of every slot,
+ * or -1 if the slot is invalid.
+ * Following that table, the packed valid IES lights are stored. */
+ float *data = dscene->ies_lights.alloc(ies_slots.size() + packed_size);
+
+ int offset = ies_slots.size();
+ for (int i = 0; i < ies_slots.size(); i++) {
+ int size = ies_slots[i]->ies.packed_size();
+ if (size > 0) {
+ data[i] = __int_as_float(offset);
+ ies_slots[i]->ies.pack(data + offset);
+ offset += size;
+ }
+ else {
+ data[i] = __int_as_float(-1);
+ }
+ }
+
+ dscene->ies_lights.copy_to_device();
+ }
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/render/light.h b/intern/cycles/render/light.h
index a627ec9bdc3..66732000f3b 100644
--- a/intern/cycles/render/light.h
+++ b/intern/cycles/render/light.h
@@ -36,108 +36,103 @@ class Scene;
class Shader;
class Light : public Node {
-public:
- NODE_DECLARE;
+ public:
+ NODE_DECLARE;
- Light();
+ Light();
- LightType type;
- float3 co;
+ LightType type;
+ float3 co;
- float3 dir;
- float size;
+ float3 dir;
+ float size;
- float3 axisu;
- float sizeu;
- float3 axisv;
- float sizev;
- bool round;
+ float3 axisu;
+ float sizeu;
+ float3 axisv;
+ float sizev;
+ bool round;
- Transform tfm;
+ Transform tfm;
- int map_resolution;
+ int map_resolution;
- float spot_angle;
- float spot_smooth;
+ float spot_angle;
+ float spot_smooth;
- bool cast_shadow;
- bool use_mis;
- bool use_diffuse;
- bool use_glossy;
- bool use_transmission;
- bool use_scatter;
+ bool cast_shadow;
+ bool use_mis;
+ bool use_diffuse;
+ bool use_glossy;
+ bool use_transmission;
+ bool use_scatter;
- bool is_portal;
- bool is_enabled;
+ bool is_portal;
+ bool is_enabled;
- Shader *shader;
- int samples;
- int max_bounces;
- uint random_id;
+ Shader *shader;
+ int samples;
+ int max_bounces;
+ uint random_id;
- void tag_update(Scene *scene);
+ void tag_update(Scene *scene);
- /* Check whether the light has contribution the the scene. */
- bool has_contribution(Scene *scene);
+ /* Check whether the light has contribution the the scene. */
+ bool has_contribution(Scene *scene);
};
class LightManager {
-public:
- bool use_light_visibility;
- bool need_update;
-
- LightManager();
- ~LightManager();
-
- /* IES texture management */
- int add_ies(ustring ies);
- int add_ies_from_file(ustring filename);
- void remove_ies(int slot);
-
- void device_update(Device *device,
- DeviceScene *dscene,
- Scene *scene,
- Progress& progress);
- void device_free(Device *device, DeviceScene *dscene);
-
- void tag_update(Scene *scene);
-
- /* Check whether there is a background light. */
- bool has_background_light(Scene *scene);
-
-protected:
- /* Optimization: disable light which is either unsupported or
- * which doesn't contribute to the scene or which is only used for MIS
- * and scene doesn't need MIS.
- */
- void disable_ineffective_light(Scene *scene);
-
- void device_update_points(Device *device,
- DeviceScene *dscene,
- Scene *scene);
- void device_update_distribution(Device *device,
- DeviceScene *dscene,
- Scene *scene,
- Progress& progress);
- void device_update_background(Device *device,
- DeviceScene *dscene,
- Scene *scene,
- Progress& progress);
- void device_update_ies(DeviceScene *dscene);
-
- /* Check whether light manager can use the object as a light-emissive. */
- bool object_usable_as_light(Object *object);
-
- struct IESSlot {
- IESFile ies;
- uint hash;
- int users;
- };
-
- vector<IESSlot*> ies_slots;
- thread_mutex ies_mutex;
+ public:
+ bool use_light_visibility;
+ bool need_update;
+
+ LightManager();
+ ~LightManager();
+
+ /* IES texture management */
+ int add_ies(ustring ies);
+ int add_ies_from_file(ustring filename);
+ void remove_ies(int slot);
+
+ void device_update(Device *device, DeviceScene *dscene, Scene *scene, Progress &progress);
+ void device_free(Device *device, DeviceScene *dscene);
+
+ void tag_update(Scene *scene);
+
+ /* Check whether there is a background light. */
+ bool has_background_light(Scene *scene);
+
+ protected:
+ /* Optimization: disable light which is either unsupported or
+ * which doesn't contribute to the scene or which is only used for MIS
+ * and scene doesn't need MIS.
+ */
+ void disable_ineffective_light(Scene *scene);
+
+ void device_update_points(Device *device, DeviceScene *dscene, Scene *scene);
+ void device_update_distribution(Device *device,
+ DeviceScene *dscene,
+ Scene *scene,
+ Progress &progress);
+ void device_update_background(Device *device,
+ DeviceScene *dscene,
+ Scene *scene,
+ Progress &progress);
+ void device_update_ies(DeviceScene *dscene);
+
+ /* Check whether light manager can use the object as a light-emissive. */
+ bool object_usable_as_light(Object *object);
+
+ struct IESSlot {
+ IESFile ies;
+ uint hash;
+ int users;
+ };
+
+ vector<IESSlot *> ies_slots;
+ thread_mutex ies_mutex;
};
CCL_NAMESPACE_END
-#endif /* __LIGHT_H__ */
+#endif /* __LIGHT_H__ */
diff --git a/intern/cycles/render/merge.cpp b/intern/cycles/render/merge.cpp
index 289bb023d72..cac07e59fe3 100644
--- a/intern/cycles/render/merge.cpp
+++ b/intern/cycles/render/merge.cpp
@@ -32,453 +32,443 @@ CCL_NAMESPACE_BEGIN
/* Merge Image Layer */
enum MergeChannelOp {
- MERGE_CHANNEL_NOP,
- MERGE_CHANNEL_COPY,
- MERGE_CHANNEL_SUM,
- MERGE_CHANNEL_AVERAGE
+ MERGE_CHANNEL_NOP,
+ MERGE_CHANNEL_COPY,
+ MERGE_CHANNEL_SUM,
+ MERGE_CHANNEL_AVERAGE
};
struct MergeImagePass {
- /* Full channel name. */
- string channel_name;
- /* Channel format in the file. */
- TypeDesc format;
- /* Type of operation to perform when merging. */
- MergeChannelOp op;
- /* Offset of layer channels in input image. */
- int offset;
- /* Offset of layer channels in merged image. */
- int merge_offset;
+ /* Full channel name. */
+ string channel_name;
+ /* Channel format in the file. */
+ TypeDesc format;
+ /* Type of operation to perform when merging. */
+ MergeChannelOp op;
+ /* Offset of layer channels in input image. */
+ int offset;
+ /* Offset of layer channels in merged image. */
+ int merge_offset;
};
struct MergeImageLayer {
- /* Layer name. */
- string name;
- /* Passes. */
- vector<MergeImagePass> passes;
- /* Sample amount that was used for rendering this layer. */
- int samples;
+ /* Layer name. */
+ string name;
+ /* Passes. */
+ vector<MergeImagePass> passes;
+ /* Sample amount that was used for rendering this layer. */
+ int samples;
};
/* Merge Image */
struct MergeImage {
- /* OIIO file handle. */
- unique_ptr<ImageInput> in;
- /* Image file path. */
- string filepath;
- /* Render layers. */
- vector<MergeImageLayer> layers;
+ /* OIIO file handle. */
+ unique_ptr<ImageInput> in;
+ /* Image file path. */
+ string filepath;
+ /* Render layers. */
+ vector<MergeImageLayer> layers;
};
/* Channel Parsing */
-static MergeChannelOp parse_channel_operation(const string& pass_name)
+static MergeChannelOp parse_channel_operation(const string &pass_name)
{
- if(pass_name == "Depth" ||
- pass_name == "IndexMA" ||
- pass_name == "IndexOB" ||
- string_startswith(pass_name, "Crypto"))
- {
- return MERGE_CHANNEL_COPY;
- }
- else if(string_startswith(pass_name, "Debug BVH") ||
- string_startswith(pass_name, "Debug Ray") ||
- string_startswith(pass_name, "Debug Render Time"))
- {
- return MERGE_CHANNEL_SUM;
- }
- else {
- return MERGE_CHANNEL_AVERAGE;
- }
+ if (pass_name == "Depth" || pass_name == "IndexMA" || pass_name == "IndexOB" ||
+ string_startswith(pass_name, "Crypto")) {
+ return MERGE_CHANNEL_COPY;
+ }
+ else if (string_startswith(pass_name, "Debug BVH") ||
+ string_startswith(pass_name, "Debug Ray") ||
+ string_startswith(pass_name, "Debug Render Time")) {
+ return MERGE_CHANNEL_SUM;
+ }
+ else {
+ return MERGE_CHANNEL_AVERAGE;
+ }
}
/* Splits in at its last dot, setting suffix to the part after the dot and
* into the part before it. Returns whether a dot was found. */
static bool split_last_dot(string &in, string &suffix)
{
- size_t pos = in.rfind(".");
- if(pos == string::npos) {
- return false;
- }
- suffix = in.substr(pos+1);
- in = in.substr(0, pos);
- return true;
+ size_t pos = in.rfind(".");
+ if (pos == string::npos) {
+ return false;
+ }
+ suffix = in.substr(pos + 1);
+ in = in.substr(0, pos);
+ return true;
}
/* Separate channel names as generated by Blender.
* Multiview format: RenderLayer.Pass.View.Channel
* Otherwise: RenderLayer.Pass.Channel */
-static bool parse_channel_name(string name,
- string &renderlayer,
- string &pass,
- string &channel,
- bool multiview_channels)
+static bool parse_channel_name(
+ string name, string &renderlayer, string &pass, string &channel, bool multiview_channels)
{
- if(!split_last_dot(name, channel)) {
- return false;
- }
- string view;
- if(multiview_channels && !split_last_dot(name, view)) {
- return false;
- }
- if(!split_last_dot(name, pass)) {
- return false;
- }
- renderlayer = name;
-
- if(multiview_channels) {
- renderlayer += "." + view;
- }
-
- return true;
+ if (!split_last_dot(name, channel)) {
+ return false;
+ }
+ string view;
+ if (multiview_channels && !split_last_dot(name, view)) {
+ return false;
+ }
+ if (!split_last_dot(name, pass)) {
+ return false;
+ }
+ renderlayer = name;
+
+ if (multiview_channels) {
+ renderlayer += "." + view;
+ }
+
+ return true;
}
static bool parse_channels(const ImageSpec &in_spec,
- vector<MergeImageLayer>& layers,
- string& error)
+ vector<MergeImageLayer> &layers,
+ string &error)
{
- const ParamValue *multiview = in_spec.find_attribute("multiView");
- const bool multiview_channels = (multiview &&
- multiview->type().basetype == TypeDesc::STRING &&
- multiview->type().arraylen >= 2);
-
- layers.clear();
-
- /* Loop over all the channels in the file, parse their name and sort them
- * by RenderLayer.
- * Channels that can't be parsed are directly passed through to the output. */
- map<string, MergeImageLayer> file_layers;
- for(int i = 0; i < in_spec.nchannels; i++) {
- MergeImagePass pass;
- pass.channel_name = in_spec.channelnames[i];
- pass.format = (in_spec.channelformats.size() > 0) ? in_spec.channelformats[i] : in_spec.format;
- pass.offset = i;
- pass.merge_offset = i;
-
- string layername, passname, channelname;
- if(parse_channel_name(pass.channel_name, layername, passname, channelname, multiview_channels)) {
- /* Channer part of a render layer. */
- pass.op = parse_channel_operation(passname);
- }
- else {
- /* Other channels are added in unnamed layer. */
- layername = "";
- pass.op = parse_channel_operation(pass.channel_name);
- }
-
- file_layers[layername].passes.push_back(pass);
- }
-
- /* Loop over all detected RenderLayers, check whether they contain a full set of input channels.
- * Any channels that won't be processed internally are also passed through. */
- for(auto& i: file_layers) {
- const string& name = i.first;
- MergeImageLayer& layer = i.second;
-
- layer.name = name;
- layer.samples = 0;
-
- /* Determine number of samples from metadata. */
- if(layer.name == "") {
- layer.samples = 1;
- }
- else if(layer.samples < 1) {
- string sample_string = in_spec.get_string_attribute("cycles." + name + ".samples", "");
- if(sample_string != "") {
- if(!sscanf(sample_string.c_str(), "%d", &layer.samples)) {
- error = "Failed to parse samples metadata: " + sample_string;
- return false;
- }
- }
- }
-
- if(layer.samples < 1) {
- error = string_printf("No sample number specified in the file for layer %s or on the command line", name.c_str());
- return false;
- }
-
- layers.push_back(layer);
- }
-
- return true;
+ const ParamValue *multiview = in_spec.find_attribute("multiView");
+ const bool multiview_channels = (multiview && multiview->type().basetype == TypeDesc::STRING &&
+ multiview->type().arraylen >= 2);
+
+ layers.clear();
+
+ /* Loop over all the channels in the file, parse their name and sort them
+ * by RenderLayer.
+ * Channels that can't be parsed are directly passed through to the output. */
+ map<string, MergeImageLayer> file_layers;
+ for (int i = 0; i < in_spec.nchannels; i++) {
+ MergeImagePass pass;
+ pass.channel_name = in_spec.channelnames[i];
+ pass.format = (in_spec.channelformats.size() > 0) ? in_spec.channelformats[i] : in_spec.format;
+ pass.offset = i;
+ pass.merge_offset = i;
+
+ string layername, passname, channelname;
+ if (parse_channel_name(
+ pass.channel_name, layername, passname, channelname, multiview_channels)) {
+ /* Channer part of a render layer. */
+ pass.op = parse_channel_operation(passname);
+ }
+ else {
+ /* Other channels are added in unnamed layer. */
+ layername = "";
+ pass.op = parse_channel_operation(pass.channel_name);
+ }
+
+ file_layers[layername].passes.push_back(pass);
+ }
+
+ /* Loop over all detected RenderLayers, check whether they contain a full set of input channels.
+ * Any channels that won't be processed internally are also passed through. */
+ for (auto &i : file_layers) {
+ const string &name = i.first;
+ MergeImageLayer &layer = i.second;
+
+ layer.name = name;
+ layer.samples = 0;
+
+ /* Determine number of samples from metadata. */
+ if (layer.name == "") {
+ layer.samples = 1;
+ }
+ else if (layer.samples < 1) {
+ string sample_string = in_spec.get_string_attribute("cycles." + name + ".samples", "");
+ if (sample_string != "") {
+ if (!sscanf(sample_string.c_str(), "%d", &layer.samples)) {
+ error = "Failed to parse samples metadata: " + sample_string;
+ return false;
+ }
+ }
+ }
+
+ if (layer.samples < 1) {
+ error = string_printf(
+ "No sample number specified in the file for layer %s or on the command line",
+ name.c_str());
+ return false;
+ }
+
+ layers.push_back(layer);
+ }
+
+ return true;
}
-static bool open_images(const vector<string>& filepaths,
- vector<MergeImage>& images,
- string& error)
+static bool open_images(const vector<string> &filepaths, vector<MergeImage> &images, string &error)
{
- for(const string& filepath: filepaths) {
- unique_ptr<ImageInput> in(ImageInput::open(filepath));
- if(!in) {
- error = "Couldn't open file: " + filepath;
- return false;
- }
-
- MergeImage image;
- image.in = std::move(in);
- image.filepath = filepath;
- if(!parse_channels(image.in->spec(), image.layers, error)) {
- return false;
- }
-
- if(image.layers.size() == 0) {
- error = "Could not find a render layer for merging";
- return false;
- }
-
- if(image.in->spec().deep) {
- error = "Merging deep images not supported.";
- return false;
- }
-
- if(images.size() > 0) {
- const ImageSpec& base_spec = images[0].in->spec();
- const ImageSpec& spec = image.in->spec();
-
- if(base_spec.width != spec.width ||
- base_spec.height != spec.height ||
- base_spec.depth != spec.depth ||
- base_spec.format != spec.format ||
- base_spec.deep != spec.deep)
- {
- error = "Images do not have matching size and data layout.";
- return false;
- }
- }
-
- images.push_back(std::move(image));
- }
-
- return true;
+ for (const string &filepath : filepaths) {
+ unique_ptr<ImageInput> in(ImageInput::open(filepath));
+ if (!in) {
+ error = "Couldn't open file: " + filepath;
+ return false;
+ }
+
+ MergeImage image;
+ image.in = std::move(in);
+ image.filepath = filepath;
+ if (!parse_channels(image.in->spec(), image.layers, error)) {
+ return false;
+ }
+
+ if (image.layers.size() == 0) {
+ error = "Could not find a render layer for merging";
+ return false;
+ }
+
+ if (image.in->spec().deep) {
+ error = "Merging deep images not supported.";
+ return false;
+ }
+
+ if (images.size() > 0) {
+ const ImageSpec &base_spec = images[0].in->spec();
+ const ImageSpec &spec = image.in->spec();
+
+ if (base_spec.width != spec.width || base_spec.height != spec.height ||
+ base_spec.depth != spec.depth || base_spec.format != spec.format ||
+ base_spec.deep != spec.deep) {
+ error = "Images do not have matching size and data layout.";
+ return false;
+ }
+ }
+
+ images.push_back(std::move(image));
+ }
+
+ return true;
}
-static void merge_render_time(ImageSpec& spec,
- const vector<MergeImage>& images,
- const string& name,
+static void merge_render_time(ImageSpec &spec,
+ const vector<MergeImage> &images,
+ const string &name,
const bool average)
{
- double time = 0.0;
+ double time = 0.0;
- for(const MergeImage& image: images) {
- string time_str = image.in->spec().get_string_attribute(name, "");
- time += time_human_readable_to_seconds(time_str);
- }
+ for (const MergeImage &image : images) {
+ string time_str = image.in->spec().get_string_attribute(name, "");
+ time += time_human_readable_to_seconds(time_str);
+ }
- if(average) {
- time /= images.size();
- }
+ if (average) {
+ time /= images.size();
+ }
- spec.attribute(name, TypeDesc::STRING, time_human_readable_from_seconds(time));
+ spec.attribute(name, TypeDesc::STRING, time_human_readable_from_seconds(time));
}
-static void merge_layer_render_time(ImageSpec& spec,
- const vector<MergeImage>& images,
- const string& layer_name,
- const string& time_name,
+static void merge_layer_render_time(ImageSpec &spec,
+ const vector<MergeImage> &images,
+ const string &layer_name,
+ const string &time_name,
const bool average)
{
- string name = "cycles." + layer_name + "." + time_name;
- double time = 0.0;
+ string name = "cycles." + layer_name + "." + time_name;
+ double time = 0.0;
- for(const MergeImage& image: images) {
- string time_str = image.in->spec().get_string_attribute(name, "");
- time += time_human_readable_to_seconds(time_str);
- }
+ for (const MergeImage &image : images) {
+ string time_str = image.in->spec().get_string_attribute(name, "");
+ time += time_human_readable_to_seconds(time_str);
+ }
- if(average) {
- time /= images.size();
- }
+ if (average) {
+ time /= images.size();
+ }
- spec.attribute(name, TypeDesc::STRING, time_human_readable_from_seconds(time));
+ spec.attribute(name, TypeDesc::STRING, time_human_readable_from_seconds(time));
}
-static void merge_channels_metadata(vector<MergeImage>& images,
- ImageSpec& out_spec,
- vector<int>& channel_total_samples)
+static void merge_channels_metadata(vector<MergeImage> &images,
+ ImageSpec &out_spec,
+ vector<int> &channel_total_samples)
{
- /* Based on first image. */
- out_spec = images[0].in->spec();
-
- /* Merge channels and compute offsets. */
- out_spec.nchannels = 0;
- out_spec.channelformats.clear();
- out_spec.channelnames.clear();
-
- for(MergeImage& image: images) {
- for(MergeImageLayer& layer: image.layers) {
- for(MergeImagePass& pass: layer.passes) {
- /* Test if matching channel already exists in merged image. */
- bool found = false;
-
- for(size_t i = 0; i < out_spec.nchannels; i++) {
- if(pass.channel_name == out_spec.channelnames[i]) {
- pass.merge_offset = i;
- channel_total_samples[i] += layer.samples;
- /* First image wins for channels that can't be averaged or summed. */
- if (pass.op == MERGE_CHANNEL_COPY) {
- pass.op = MERGE_CHANNEL_NOP;
- }
- found = true;
- break;
- }
- }
-
- if(!found) {
- /* Add new channel. */
- pass.merge_offset = out_spec.nchannels;
- channel_total_samples.push_back(layer.samples);
-
- out_spec.channelnames.push_back(pass.channel_name);
- out_spec.channelformats.push_back(pass.format);
- out_spec.nchannels++;
- }
- }
- }
- }
-
- /* Merge metadata. */
- merge_render_time(out_spec, images, "RenderTime", false);
-
- map<string, int> layer_num_samples;
- for(MergeImage& image: images) {
- for(MergeImageLayer& layer: image.layers) {
- if(layer.name != "") {
- layer_num_samples[layer.name] += layer.samples;
- }
- }
- }
-
- for(const auto& i: layer_num_samples) {
- string name = "cycles." + i.first + ".samples";
- out_spec.attribute(name, TypeDesc::STRING, string_printf("%d", i.second));
-
- merge_layer_render_time(out_spec, images, i.first, "total_time", false);
- merge_layer_render_time(out_spec, images, i.first, "render_time", false);
- merge_layer_render_time(out_spec, images, i.first, "synchronization_time", true);
- }
+ /* Based on first image. */
+ out_spec = images[0].in->spec();
+
+ /* Merge channels and compute offsets. */
+ out_spec.nchannels = 0;
+ out_spec.channelformats.clear();
+ out_spec.channelnames.clear();
+
+ for (MergeImage &image : images) {
+ for (MergeImageLayer &layer : image.layers) {
+ for (MergeImagePass &pass : layer.passes) {
+ /* Test if matching channel already exists in merged image. */
+ bool found = false;
+
+ for (size_t i = 0; i < out_spec.nchannels; i++) {
+ if (pass.channel_name == out_spec.channelnames[i]) {
+ pass.merge_offset = i;
+ channel_total_samples[i] += layer.samples;
+ /* First image wins for channels that can't be averaged or summed. */
+ if (pass.op == MERGE_CHANNEL_COPY) {
+ pass.op = MERGE_CHANNEL_NOP;
+ }
+ found = true;
+ break;
+ }
+ }
+
+ if (!found) {
+ /* Add new channel. */
+ pass.merge_offset = out_spec.nchannels;
+ channel_total_samples.push_back(layer.samples);
+
+ out_spec.channelnames.push_back(pass.channel_name);
+ out_spec.channelformats.push_back(pass.format);
+ out_spec.nchannels++;
+ }
+ }
+ }
+ }
+
+ /* Merge metadata. */
+ merge_render_time(out_spec, images, "RenderTime", false);
+
+ map<string, int> layer_num_samples;
+ for (MergeImage &image : images) {
+ for (MergeImageLayer &layer : image.layers) {
+ if (layer.name != "") {
+ layer_num_samples[layer.name] += layer.samples;
+ }
+ }
+ }
+
+ for (const auto &i : layer_num_samples) {
+ string name = "cycles." + i.first + ".samples";
+ out_spec.attribute(name, TypeDesc::STRING, string_printf("%d", i.second));
+
+ merge_layer_render_time(out_spec, images, i.first, "total_time", false);
+ merge_layer_render_time(out_spec, images, i.first, "render_time", false);
+ merge_layer_render_time(out_spec, images, i.first, "synchronization_time", true);
+ }
}
-static void alloc_pixels(const ImageSpec& spec, array<float>& pixels)
+static void alloc_pixels(const ImageSpec &spec, array<float> &pixels)
{
- const size_t width = spec.width;
- const size_t height = spec.height;
- const size_t num_channels = spec.nchannels;
+ const size_t width = spec.width;
+ const size_t height = spec.height;
+ const size_t num_channels = spec.nchannels;
- const size_t num_pixels = (size_t)width * (size_t)height;
- pixels.resize(num_pixels * num_channels);
+ const size_t num_pixels = (size_t)width * (size_t)height;
+ pixels.resize(num_pixels * num_channels);
}
-static bool merge_pixels(const vector<MergeImage>& images,
- const ImageSpec& out_spec,
- const vector<int>& channel_total_samples,
- array<float>& out_pixels,
- string& error)
+static bool merge_pixels(const vector<MergeImage> &images,
+ const ImageSpec &out_spec,
+ const vector<int> &channel_total_samples,
+ array<float> &out_pixels,
+ string &error)
{
- alloc_pixels(out_spec, out_pixels);
- memset(out_pixels.data(), 0, out_pixels.size() * sizeof(float));
-
- for(const MergeImage& image: images) {
- /* Read all channels into buffer. Reading all channels at once is
- * faster than individually due to interleaved EXR channel storage. */
- array<float> pixels;
- alloc_pixels(image.in->spec(), pixels);
-
- if(!image.in->read_image(TypeDesc::FLOAT, pixels.data())) {
- error = "Failed to read image: " + image.filepath;
- return false;
- }
-
- for(size_t li = 0; li < image.layers.size(); li++) {
- const MergeImageLayer& layer = image.layers[li];
-
- const size_t stride = image.in->spec().nchannels;
- const size_t out_stride = out_spec.nchannels;
- const size_t num_pixels = pixels.size();
-
- for(const MergeImagePass& pass: layer.passes) {
- size_t offset = pass.offset;
- size_t out_offset = pass.merge_offset;
-
- switch(pass.op) {
- case MERGE_CHANNEL_NOP:
- break;
- case MERGE_CHANNEL_COPY:
- for(; offset < num_pixels; offset += stride, out_offset += out_stride) {
- out_pixels[out_offset] = pixels[offset];
- }
- break;
- case MERGE_CHANNEL_SUM:
- for(; offset < num_pixels; offset += stride, out_offset += out_stride) {
- out_pixels[out_offset] += pixels[offset];
- }
- break;
- case MERGE_CHANNEL_AVERAGE:
- /* Weights based on sample metadata. Per channel since not
- * all files are guaranteed to have the same channels. */
- const int total_samples = channel_total_samples[out_offset];
- const float t = (float)layer.samples / (float)total_samples;
-
- for(; offset < num_pixels; offset += stride, out_offset += out_stride) {
- out_pixels[out_offset] += t * pixels[offset];
- }
- break;
- }
- }
- }
- }
-
- return true;
+ alloc_pixels(out_spec, out_pixels);
+ memset(out_pixels.data(), 0, out_pixels.size() * sizeof(float));
+
+ for (const MergeImage &image : images) {
+ /* Read all channels into buffer. Reading all channels at once is
+ * faster than individually due to interleaved EXR channel storage. */
+ array<float> pixels;
+ alloc_pixels(image.in->spec(), pixels);
+
+ if (!image.in->read_image(TypeDesc::FLOAT, pixels.data())) {
+ error = "Failed to read image: " + image.filepath;
+ return false;
+ }
+
+ for (size_t li = 0; li < image.layers.size(); li++) {
+ const MergeImageLayer &layer = image.layers[li];
+
+ const size_t stride = image.in->spec().nchannels;
+ const size_t out_stride = out_spec.nchannels;
+ const size_t num_pixels = pixels.size();
+
+ for (const MergeImagePass &pass : layer.passes) {
+ size_t offset = pass.offset;
+ size_t out_offset = pass.merge_offset;
+
+ switch (pass.op) {
+ case MERGE_CHANNEL_NOP:
+ break;
+ case MERGE_CHANNEL_COPY:
+ for (; offset < num_pixels; offset += stride, out_offset += out_stride) {
+ out_pixels[out_offset] = pixels[offset];
+ }
+ break;
+ case MERGE_CHANNEL_SUM:
+ for (; offset < num_pixels; offset += stride, out_offset += out_stride) {
+ out_pixels[out_offset] += pixels[offset];
+ }
+ break;
+ case MERGE_CHANNEL_AVERAGE:
+ /* Weights based on sample metadata. Per channel since not
+ * all files are guaranteed to have the same channels. */
+ const int total_samples = channel_total_samples[out_offset];
+ const float t = (float)layer.samples / (float)total_samples;
+
+ for (; offset < num_pixels; offset += stride, out_offset += out_stride) {
+ out_pixels[out_offset] += t * pixels[offset];
+ }
+ break;
+ }
+ }
+ }
+ }
+
+ return true;
}
-static bool save_output(const string& filepath,
- const ImageSpec& spec,
- const array<float>& pixels,
- string& error)
+static bool save_output(const string &filepath,
+ const ImageSpec &spec,
+ const array<float> &pixels,
+ string &error)
{
- /* Write to temporary file path, so we merge images in place and don't
- * risk destroying files when something goes wrong in file saving. */
- string extension = OIIO::Filesystem::extension(filepath);
- string unique_name = ".merge-tmp-" + OIIO::Filesystem::unique_path();
- string tmp_filepath = filepath + unique_name + extension;
- unique_ptr<ImageOutput> out(ImageOutput::create(tmp_filepath));
-
- if(!out) {
- error = "Failed to open temporary file " + tmp_filepath + " for writing";
- return false;
- }
-
- /* Open temporary file and write image buffers. */
- if(!out->open(tmp_filepath, spec)) {
- error = "Failed to open file " + tmp_filepath + " for writing: " + out->geterror();
- return false;
- }
-
- bool ok = true;
- if(!out->write_image(TypeDesc::FLOAT, pixels.data())) {
- error = "Failed to write to file " + tmp_filepath + ": " + out->geterror();
- ok = false;
- }
-
- if(!out->close()) {
- error = "Failed to save to file " + tmp_filepath + ": " + out->geterror();
- ok = false;
- }
-
- out.reset();
-
- /* Copy temporary file to outputput filepath. */
- string rename_error;
- if(ok && !OIIO::Filesystem::rename(tmp_filepath, filepath, rename_error)) {
- error = "Failed to move merged image to " + filepath + ": " + rename_error;
- ok = false;
- }
-
- if(!ok) {
- OIIO::Filesystem::remove(tmp_filepath);
- }
-
- return ok;
+ /* Write to temporary file path, so we merge images in place and don't
+ * risk destroying files when something goes wrong in file saving. */
+ string extension = OIIO::Filesystem::extension(filepath);
+ string unique_name = ".merge-tmp-" + OIIO::Filesystem::unique_path();
+ string tmp_filepath = filepath + unique_name + extension;
+ unique_ptr<ImageOutput> out(ImageOutput::create(tmp_filepath));
+
+ if (!out) {
+ error = "Failed to open temporary file " + tmp_filepath + " for writing";
+ return false;
+ }
+
+ /* Open temporary file and write image buffers. */
+ if (!out->open(tmp_filepath, spec)) {
+ error = "Failed to open file " + tmp_filepath + " for writing: " + out->geterror();
+ return false;
+ }
+
+ bool ok = true;
+ if (!out->write_image(TypeDesc::FLOAT, pixels.data())) {
+ error = "Failed to write to file " + tmp_filepath + ": " + out->geterror();
+ ok = false;
+ }
+
+ if (!out->close()) {
+ error = "Failed to save to file " + tmp_filepath + ": " + out->geterror();
+ ok = false;
+ }
+
+ out.reset();
+
+ /* Copy temporary file to outputput filepath. */
+ string rename_error;
+ if (ok && !OIIO::Filesystem::rename(tmp_filepath, filepath, rename_error)) {
+ error = "Failed to move merged image to " + filepath + ": " + rename_error;
+ ok = false;
+ }
+
+ if (!ok) {
+ OIIO::Filesystem::remove(tmp_filepath);
+ }
+
+ return ok;
}
/* Image Merger */
@@ -489,38 +479,38 @@ ImageMerger::ImageMerger()
bool ImageMerger::run()
{
- if(input.empty()) {
- error = "No input file paths specified.";
- return false;
- }
- if(output.empty()) {
- error = "No output file path specified.";
- return false;
- }
-
- /* Open images and verify they have matching layout. */
- vector<MergeImage> images;
- if(!open_images(input, images, error)) {
- return false;
- }
-
- /* Merge metadata and setup channels and offsets. */
- ImageSpec out_spec;
- vector<int> channel_total_samples;
- merge_channels_metadata(images, out_spec, channel_total_samples);
-
- /* Merge pixels. */
- array<float> out_pixels;
- if(!merge_pixels(images, out_spec, channel_total_samples, out_pixels, error)) {
- return false;
- }
-
- /* We don't need input anymore at this point, and will possibly
- * overwrite the same file. */
- images.clear();
-
- /* Save output file. */
- return save_output(output, out_spec, out_pixels, error);
+ if (input.empty()) {
+ error = "No input file paths specified.";
+ return false;
+ }
+ if (output.empty()) {
+ error = "No output file path specified.";
+ return false;
+ }
+
+ /* Open images and verify they have matching layout. */
+ vector<MergeImage> images;
+ if (!open_images(input, images, error)) {
+ return false;
+ }
+
+ /* Merge metadata and setup channels and offsets. */
+ ImageSpec out_spec;
+ vector<int> channel_total_samples;
+ merge_channels_metadata(images, out_spec, channel_total_samples);
+
+ /* Merge pixels. */
+ array<float> out_pixels;
+ if (!merge_pixels(images, out_spec, channel_total_samples, out_pixels, error)) {
+ return false;
+ }
+
+ /* We don't need input anymore at this point, and will possibly
+ * overwrite the same file. */
+ images.clear();
+
+ /* Save output file. */
+ return save_output(output, out_spec, out_pixels, error);
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/render/merge.h b/intern/cycles/render/merge.h
index 48900a13c27..87e5d2d4723 100644
--- a/intern/cycles/render/merge.h
+++ b/intern/cycles/render/merge.h
@@ -25,17 +25,17 @@ CCL_NAMESPACE_BEGIN
/* Merge OpenEXR multilayer renders. */
class ImageMerger {
-public:
- ImageMerger();
- bool run();
+ public:
+ ImageMerger();
+ bool run();
- /* Error message after running, in case of failure. */
- string error;
+ /* Error message after running, in case of failure. */
+ string error;
- /* List of image filepaths to merge. */
- vector<string> input;
- /* Output filepath. */
- string output;
+ /* List of image filepaths to merge. */
+ vector<string> input;
+ /* Output filepath. */
+ string output;
};
CCL_NAMESPACE_END
diff --git a/intern/cycles/render/mesh.cpp b/intern/cycles/render/mesh.cpp
index eadbe3eda89..54dacf5d1f4 100644
--- a/intern/cycles/render/mesh.cpp
+++ b/intern/cycles/render/mesh.cpp
@@ -47,11 +47,11 @@ CCL_NAMESPACE_BEGIN
/* Triangle */
-void Mesh::Triangle::bounds_grow(const float3 *verts, BoundBox& bounds) const
+void Mesh::Triangle::bounds_grow(const float3 *verts, BoundBox &bounds) const
{
- bounds.grow(verts[v[0]]);
- bounds.grow(verts[v[1]]);
- bounds.grow(verts[v[2]]);
+ bounds.grow(verts[v[0]]);
+ bounds.grow(verts[v[1]]);
+ bounds.grow(verts[v[2]]);
}
void Mesh::Triangle::motion_verts(const float3 *verts,
@@ -61,29 +61,19 @@ void Mesh::Triangle::motion_verts(const float3 *verts,
float time,
float3 r_verts[3]) const
{
- /* Figure out which steps we need to fetch and their interpolation factor. */
- const size_t max_step = num_steps - 1;
- const size_t step = min((int)(time * max_step), max_step - 1);
- const float t = time*max_step - step;
- /* Fetch vertex coordinates. */
- float3 curr_verts[3];
- float3 next_verts[3];
- verts_for_step(verts,
- vert_steps,
- num_verts,
- num_steps,
- step,
- curr_verts);
- verts_for_step(verts,
- vert_steps,
- num_verts,
- num_steps,
- step + 1,
- next_verts);
- /* Interpolate between steps. */
- r_verts[0] = (1.0f - t)*curr_verts[0] + t*next_verts[0];
- r_verts[1] = (1.0f - t)*curr_verts[1] + t*next_verts[1];
- r_verts[2] = (1.0f - t)*curr_verts[2] + t*next_verts[2];
+ /* Figure out which steps we need to fetch and their interpolation factor. */
+ const size_t max_step = num_steps - 1;
+ const size_t step = min((int)(time * max_step), max_step - 1);
+ const float t = time * max_step - step;
+ /* Fetch vertex coordinates. */
+ float3 curr_verts[3];
+ float3 next_verts[3];
+ verts_for_step(verts, vert_steps, num_verts, num_steps, step, curr_verts);
+ verts_for_step(verts, vert_steps, num_verts, num_steps, step + 1, next_verts);
+ /* Interpolate between steps. */
+ r_verts[0] = (1.0f - t) * curr_verts[0] + t * next_verts[0];
+ r_verts[1] = (1.0f - t) * curr_verts[1] + t * next_verts[1];
+ r_verts[2] = (1.0f - t) * curr_verts[2] + t * next_verts[2];
}
void Mesh::Triangle::verts_for_step(const float3 *verts,
@@ -93,120 +83,121 @@ void Mesh::Triangle::verts_for_step(const float3 *verts,
size_t step,
float3 r_verts[3]) const
{
- const size_t center_step = ((num_steps - 1) / 2);
- if(step == center_step) {
- /* Center step: regular vertex location. */
- r_verts[0] = verts[v[0]];
- r_verts[1] = verts[v[1]];
- r_verts[2] = verts[v[2]];
- }
- else {
- /* Center step not stored in the attribute array array. */
- if(step > center_step) {
- step--;
- }
- size_t offset = step * num_verts;
- r_verts[0] = vert_steps[offset + v[0]];
- r_verts[1] = vert_steps[offset + v[1]];
- r_verts[2] = vert_steps[offset + v[2]];
- }
+ const size_t center_step = ((num_steps - 1) / 2);
+ if (step == center_step) {
+ /* Center step: regular vertex location. */
+ r_verts[0] = verts[v[0]];
+ r_verts[1] = verts[v[1]];
+ r_verts[2] = verts[v[2]];
+ }
+ else {
+ /* Center step not stored in the attribute array array. */
+ if (step > center_step) {
+ step--;
+ }
+ size_t offset = step * num_verts;
+ r_verts[0] = vert_steps[offset + v[0]];
+ r_verts[1] = vert_steps[offset + v[1]];
+ r_verts[2] = vert_steps[offset + v[2]];
+ }
}
float3 Mesh::Triangle::compute_normal(const float3 *verts) const
{
- const float3& v0 = verts[v[0]];
- const float3& v1 = verts[v[1]];
- const float3& v2 = verts[v[2]];
- const float3 norm = cross(v1 - v0, v2 - v0);
- const float normlen = len(norm);
- if(normlen == 0.0f) {
- return make_float3(1.0f, 0.0f, 0.0f);
- }
- return norm / normlen;
+ const float3 &v0 = verts[v[0]];
+ const float3 &v1 = verts[v[1]];
+ const float3 &v2 = verts[v[2]];
+ const float3 norm = cross(v1 - v0, v2 - v0);
+ const float normlen = len(norm);
+ if (normlen == 0.0f) {
+ return make_float3(1.0f, 0.0f, 0.0f);
+ }
+ return norm / normlen;
}
bool Mesh::Triangle::valid(const float3 *verts) const
{
- return isfinite3_safe(verts[v[0]]) &&
- isfinite3_safe(verts[v[1]]) &&
- isfinite3_safe(verts[v[2]]);
+ return isfinite3_safe(verts[v[0]]) && isfinite3_safe(verts[v[1]]) && isfinite3_safe(verts[v[2]]);
}
/* Curve */
-void Mesh::Curve::bounds_grow(const int k, const float3 *curve_keys, const float *curve_radius, BoundBox& bounds) const
+void Mesh::Curve::bounds_grow(const int k,
+ const float3 *curve_keys,
+ const float *curve_radius,
+ BoundBox &bounds) const
{
- float3 P[4];
+ float3 P[4];
- P[0] = curve_keys[max(first_key + k - 1,first_key)];
- P[1] = curve_keys[first_key + k];
- P[2] = curve_keys[first_key + k + 1];
- P[3] = curve_keys[min(first_key + k + 2, first_key + num_keys - 1)];
+ P[0] = curve_keys[max(first_key + k - 1, first_key)];
+ P[1] = curve_keys[first_key + k];
+ P[2] = curve_keys[first_key + k + 1];
+ P[3] = curve_keys[min(first_key + k + 2, first_key + num_keys - 1)];
- float3 lower;
- float3 upper;
+ float3 lower;
+ float3 upper;
- curvebounds(&lower.x, &upper.x, P, 0);
- curvebounds(&lower.y, &upper.y, P, 1);
- curvebounds(&lower.z, &upper.z, P, 2);
+ curvebounds(&lower.x, &upper.x, P, 0);
+ curvebounds(&lower.y, &upper.y, P, 1);
+ curvebounds(&lower.z, &upper.z, P, 2);
- float mr = max(curve_radius[first_key + k], curve_radius[first_key + k + 1]);
+ float mr = max(curve_radius[first_key + k], curve_radius[first_key + k + 1]);
- bounds.grow(lower, mr);
- bounds.grow(upper, mr);
+ bounds.grow(lower, mr);
+ bounds.grow(upper, mr);
}
void Mesh::Curve::bounds_grow(const int k,
const float3 *curve_keys,
const float *curve_radius,
- const Transform& aligned_space,
- BoundBox& bounds) const
+ const Transform &aligned_space,
+ BoundBox &bounds) const
{
- float3 P[4];
+ float3 P[4];
- P[0] = curve_keys[max(first_key + k - 1,first_key)];
- P[1] = curve_keys[first_key + k];
- P[2] = curve_keys[first_key + k + 1];
- P[3] = curve_keys[min(first_key + k + 2, first_key + num_keys - 1)];
+ P[0] = curve_keys[max(first_key + k - 1, first_key)];
+ P[1] = curve_keys[first_key + k];
+ P[2] = curve_keys[first_key + k + 1];
+ P[3] = curve_keys[min(first_key + k + 2, first_key + num_keys - 1)];
- P[0] = transform_point(&aligned_space, P[0]);
- P[1] = transform_point(&aligned_space, P[1]);
- P[2] = transform_point(&aligned_space, P[2]);
- P[3] = transform_point(&aligned_space, P[3]);
+ P[0] = transform_point(&aligned_space, P[0]);
+ P[1] = transform_point(&aligned_space, P[1]);
+ P[2] = transform_point(&aligned_space, P[2]);
+ P[3] = transform_point(&aligned_space, P[3]);
- float3 lower;
- float3 upper;
+ float3 lower;
+ float3 upper;
- curvebounds(&lower.x, &upper.x, P, 0);
- curvebounds(&lower.y, &upper.y, P, 1);
- curvebounds(&lower.z, &upper.z, P, 2);
+ curvebounds(&lower.x, &upper.x, P, 0);
+ curvebounds(&lower.y, &upper.y, P, 1);
+ curvebounds(&lower.z, &upper.z, P, 2);
- float mr = max(curve_radius[first_key + k], curve_radius[first_key + k + 1]);
+ float mr = max(curve_radius[first_key + k], curve_radius[first_key + k + 1]);
- bounds.grow(lower, mr);
- bounds.grow(upper, mr);
+ bounds.grow(lower, mr);
+ bounds.grow(upper, mr);
}
-void Mesh::Curve::bounds_grow(float4 keys[4], BoundBox& bounds) const
+void Mesh::Curve::bounds_grow(float4 keys[4], BoundBox &bounds) const
{
- float3 P[4] = {
- float4_to_float3(keys[0]),
- float4_to_float3(keys[1]),
- float4_to_float3(keys[2]),
- float4_to_float3(keys[3]),
- };
+ float3 P[4] = {
+ float4_to_float3(keys[0]),
+ float4_to_float3(keys[1]),
+ float4_to_float3(keys[2]),
+ float4_to_float3(keys[3]),
+ };
- float3 lower;
- float3 upper;
+ float3 lower;
+ float3 upper;
- curvebounds(&lower.x, &upper.x, P, 0);
- curvebounds(&lower.y, &upper.y, P, 1);
- curvebounds(&lower.z, &upper.z, P, 2);
+ curvebounds(&lower.x, &upper.x, P, 0);
+ curvebounds(&lower.y, &upper.y, P, 1);
+ curvebounds(&lower.z, &upper.z, P, 2);
- float mr = max(keys[1].w, keys[2].w);
+ float mr = max(keys[1].w, keys[2].w);
- bounds.grow(lower, mr);
- bounds.grow(upper, mr);
+ bounds.grow(lower, mr);
+ bounds.grow(upper, mr);
}
void Mesh::Curve::motion_keys(const float3 *curve_keys,
@@ -215,35 +206,24 @@ void Mesh::Curve::motion_keys(const float3 *curve_keys,
size_t num_curve_keys,
size_t num_steps,
float time,
- size_t k0, size_t k1,
+ size_t k0,
+ size_t k1,
float4 r_keys[2]) const
{
- /* Figure out which steps we need to fetch and their interpolation factor. */
- const size_t max_step = num_steps - 1;
- const size_t step = min((int)(time * max_step), max_step - 1);
- const float t = time*max_step - step;
- /* Fetch vertex coordinates. */
- float4 curr_keys[2];
- float4 next_keys[2];
- keys_for_step(curve_keys,
- curve_radius,
- key_steps,
- num_curve_keys,
- num_steps,
- step,
- k0, k1,
- curr_keys);
- keys_for_step(curve_keys,
- curve_radius,
- key_steps,
- num_curve_keys,
- num_steps,
- step + 1,
- k0, k1,
- next_keys);
- /* Interpolate between steps. */
- r_keys[0] = (1.0f - t)*curr_keys[0] + t*next_keys[0];
- r_keys[1] = (1.0f - t)*curr_keys[1] + t*next_keys[1];
+ /* Figure out which steps we need to fetch and their interpolation factor. */
+ const size_t max_step = num_steps - 1;
+ const size_t step = min((int)(time * max_step), max_step - 1);
+ const float t = time * max_step - step;
+ /* Fetch vertex coordinates. */
+ float4 curr_keys[2];
+ float4 next_keys[2];
+ keys_for_step(
+ curve_keys, curve_radius, key_steps, num_curve_keys, num_steps, step, k0, k1, curr_keys);
+ keys_for_step(
+ curve_keys, curve_radius, key_steps, num_curve_keys, num_steps, step + 1, k0, k1, next_keys);
+ /* Interpolate between steps. */
+ r_keys[0] = (1.0f - t) * curr_keys[0] + t * next_keys[0];
+ r_keys[1] = (1.0f - t) * curr_keys[1] + t * next_keys[1];
}
void Mesh::Curve::cardinal_motion_keys(const float3 *curve_keys,
@@ -252,38 +232,46 @@ void Mesh::Curve::cardinal_motion_keys(const float3 *curve_keys,
size_t num_curve_keys,
size_t num_steps,
float time,
- size_t k0, size_t k1,
- size_t k2, size_t k3,
+ size_t k0,
+ size_t k1,
+ size_t k2,
+ size_t k3,
float4 r_keys[4]) const
{
- /* Figure out which steps we need to fetch and their interpolation factor. */
- const size_t max_step = num_steps - 1;
- const size_t step = min((int)(time * max_step), max_step - 1);
- const float t = time*max_step - step;
- /* Fetch vertex coordinates. */
- float4 curr_keys[4];
- float4 next_keys[4];
- cardinal_keys_for_step(curve_keys,
- curve_radius,
- key_steps,
- num_curve_keys,
- num_steps,
- step,
- k0, k1, k2, k3,
- curr_keys);
- cardinal_keys_for_step(curve_keys,
- curve_radius,
- key_steps,
- num_curve_keys,
- num_steps,
- step + 1,
- k0, k1, k2, k3,
- next_keys);
- /* Interpolate between steps. */
- r_keys[0] = (1.0f - t)*curr_keys[0] + t*next_keys[0];
- r_keys[1] = (1.0f - t)*curr_keys[1] + t*next_keys[1];
- r_keys[2] = (1.0f - t)*curr_keys[2] + t*next_keys[2];
- r_keys[3] = (1.0f - t)*curr_keys[3] + t*next_keys[3];
+ /* Figure out which steps we need to fetch and their interpolation factor. */
+ const size_t max_step = num_steps - 1;
+ const size_t step = min((int)(time * max_step), max_step - 1);
+ const float t = time * max_step - step;
+ /* Fetch vertex coordinates. */
+ float4 curr_keys[4];
+ float4 next_keys[4];
+ cardinal_keys_for_step(curve_keys,
+ curve_radius,
+ key_steps,
+ num_curve_keys,
+ num_steps,
+ step,
+ k0,
+ k1,
+ k2,
+ k3,
+ curr_keys);
+ cardinal_keys_for_step(curve_keys,
+ curve_radius,
+ key_steps,
+ num_curve_keys,
+ num_steps,
+ step + 1,
+ k0,
+ k1,
+ k2,
+ k3,
+ next_keys);
+ /* Interpolate between steps. */
+ r_keys[0] = (1.0f - t) * curr_keys[0] + t * next_keys[0];
+ r_keys[1] = (1.0f - t) * curr_keys[1] + t * next_keys[1];
+ r_keys[2] = (1.0f - t) * curr_keys[2] + t * next_keys[2];
+ r_keys[3] = (1.0f - t) * curr_keys[3] + t * next_keys[3];
}
void Mesh::Curve::keys_for_step(const float3 *curve_keys,
@@ -292,41 +280,42 @@ void Mesh::Curve::keys_for_step(const float3 *curve_keys,
size_t num_curve_keys,
size_t num_steps,
size_t step,
- size_t k0, size_t k1,
+ size_t k0,
+ size_t k1,
float4 r_keys[2]) const
{
- k0 = max(k0, 0);
- k1 = min(k1, num_keys - 1);
- const size_t center_step = ((num_steps - 1) / 2);
- if(step == center_step) {
- /* Center step: regular key location. */
- /* TODO(sergey): Consider adding make_float4(float3, float)
- * function.
- */
- r_keys[0] = make_float4(curve_keys[first_key + k0].x,
- curve_keys[first_key + k0].y,
- curve_keys[first_key + k0].z,
- curve_radius[first_key + k0]);
- r_keys[1] = make_float4(curve_keys[first_key + k1].x,
- curve_keys[first_key + k1].y,
- curve_keys[first_key + k1].z,
- curve_radius[first_key + k1]);
- }
- else {
- /* Center step is not stored in this array. */
- if(step > center_step) {
- step--;
- }
- const size_t offset = first_key + step * num_curve_keys;
- r_keys[0] = make_float4(key_steps[offset + k0].x,
- key_steps[offset + k0].y,
- key_steps[offset + k0].z,
- curve_radius[first_key + k0]);
- r_keys[1] = make_float4(key_steps[offset + k1].x,
- key_steps[offset + k1].y,
- key_steps[offset + k1].z,
- curve_radius[first_key + k1]);
- }
+ k0 = max(k0, 0);
+ k1 = min(k1, num_keys - 1);
+ const size_t center_step = ((num_steps - 1) / 2);
+ if (step == center_step) {
+ /* Center step: regular key location. */
+ /* TODO(sergey): Consider adding make_float4(float3, float)
+ * function.
+ */
+ r_keys[0] = make_float4(curve_keys[first_key + k0].x,
+ curve_keys[first_key + k0].y,
+ curve_keys[first_key + k0].z,
+ curve_radius[first_key + k0]);
+ r_keys[1] = make_float4(curve_keys[first_key + k1].x,
+ curve_keys[first_key + k1].y,
+ curve_keys[first_key + k1].z,
+ curve_radius[first_key + k1]);
+ }
+ else {
+ /* Center step is not stored in this array. */
+ if (step > center_step) {
+ step--;
+ }
+ const size_t offset = first_key + step * num_curve_keys;
+ r_keys[0] = make_float4(key_steps[offset + k0].x,
+ key_steps[offset + k0].y,
+ key_steps[offset + k0].z,
+ curve_radius[first_key + k0]);
+ r_keys[1] = make_float4(key_steps[offset + k1].x,
+ key_steps[offset + k1].y,
+ key_steps[offset + k1].z,
+ curve_radius[first_key + k1]);
+ }
}
void Mesh::Curve::cardinal_keys_for_step(const float3 *curve_keys,
@@ -335,2033 +324,2044 @@ void Mesh::Curve::cardinal_keys_for_step(const float3 *curve_keys,
size_t num_curve_keys,
size_t num_steps,
size_t step,
- size_t k0, size_t k1,
- size_t k2, size_t k3,
+ size_t k0,
+ size_t k1,
+ size_t k2,
+ size_t k3,
float4 r_keys[4]) const
{
- k0 = max(k0, 0);
- k3 = min(k3, num_keys - 1);
- const size_t center_step = ((num_steps - 1) / 2);
- if(step == center_step) {
- /* Center step: regular key location. */
- r_keys[0] = make_float4(curve_keys[first_key + k0].x,
- curve_keys[first_key + k0].y,
- curve_keys[first_key + k0].z,
- curve_radius[first_key + k0]);
- r_keys[1] = make_float4(curve_keys[first_key + k1].x,
- curve_keys[first_key + k1].y,
- curve_keys[first_key + k1].z,
- curve_radius[first_key + k1]);
- r_keys[2] = make_float4(curve_keys[first_key + k2].x,
- curve_keys[first_key + k2].y,
- curve_keys[first_key + k2].z,
- curve_radius[first_key + k2]);
- r_keys[3] = make_float4(curve_keys[first_key + k3].x,
- curve_keys[first_key + k3].y,
- curve_keys[first_key + k3].z,
- curve_radius[first_key + k3]);
- }
- else {
- /* Center step is not stored in this array. */
- if(step > center_step) {
- step--;
- }
- const size_t offset = first_key + step * num_curve_keys;
- r_keys[0] = make_float4(key_steps[offset + k0].x,
- key_steps[offset + k0].y,
- key_steps[offset + k0].z,
- curve_radius[first_key + k0]);
- r_keys[1] = make_float4(key_steps[offset + k1].x,
- key_steps[offset + k1].y,
- key_steps[offset + k1].z,
- curve_radius[first_key + k1]);
- r_keys[2] = make_float4(key_steps[offset + k2].x,
- key_steps[offset + k2].y,
- key_steps[offset + k2].z,
- curve_radius[first_key + k2]);
- r_keys[3] = make_float4(key_steps[offset + k3].x,
- key_steps[offset + k3].y,
- key_steps[offset + k3].z,
- curve_radius[first_key + k3]);
- }
+ k0 = max(k0, 0);
+ k3 = min(k3, num_keys - 1);
+ const size_t center_step = ((num_steps - 1) / 2);
+ if (step == center_step) {
+ /* Center step: regular key location. */
+ r_keys[0] = make_float4(curve_keys[first_key + k0].x,
+ curve_keys[first_key + k0].y,
+ curve_keys[first_key + k0].z,
+ curve_radius[first_key + k0]);
+ r_keys[1] = make_float4(curve_keys[first_key + k1].x,
+ curve_keys[first_key + k1].y,
+ curve_keys[first_key + k1].z,
+ curve_radius[first_key + k1]);
+ r_keys[2] = make_float4(curve_keys[first_key + k2].x,
+ curve_keys[first_key + k2].y,
+ curve_keys[first_key + k2].z,
+ curve_radius[first_key + k2]);
+ r_keys[3] = make_float4(curve_keys[first_key + k3].x,
+ curve_keys[first_key + k3].y,
+ curve_keys[first_key + k3].z,
+ curve_radius[first_key + k3]);
+ }
+ else {
+ /* Center step is not stored in this array. */
+ if (step > center_step) {
+ step--;
+ }
+ const size_t offset = first_key + step * num_curve_keys;
+ r_keys[0] = make_float4(key_steps[offset + k0].x,
+ key_steps[offset + k0].y,
+ key_steps[offset + k0].z,
+ curve_radius[first_key + k0]);
+ r_keys[1] = make_float4(key_steps[offset + k1].x,
+ key_steps[offset + k1].y,
+ key_steps[offset + k1].z,
+ curve_radius[first_key + k1]);
+ r_keys[2] = make_float4(key_steps[offset + k2].x,
+ key_steps[offset + k2].y,
+ key_steps[offset + k2].z,
+ curve_radius[first_key + k2]);
+ r_keys[3] = make_float4(key_steps[offset + k3].x,
+ key_steps[offset + k3].y,
+ key_steps[offset + k3].z,
+ curve_radius[first_key + k3]);
+ }
}
/* SubdFace */
float3 Mesh::SubdFace::normal(const Mesh *mesh) const
{
- float3 v0 = mesh->verts[mesh->subd_face_corners[start_corner+0]];
- float3 v1 = mesh->verts[mesh->subd_face_corners[start_corner+1]];
- float3 v2 = mesh->verts[mesh->subd_face_corners[start_corner+2]];
+ float3 v0 = mesh->verts[mesh->subd_face_corners[start_corner + 0]];
+ float3 v1 = mesh->verts[mesh->subd_face_corners[start_corner + 1]];
+ float3 v2 = mesh->verts[mesh->subd_face_corners[start_corner + 2]];
- return safe_normalize(cross(v1 - v0, v2 - v0));
+ return safe_normalize(cross(v1 - v0, v2 - v0));
}
/* Mesh */
NODE_DEFINE(Mesh)
{
- NodeType* type = NodeType::add("mesh", create);
+ NodeType *type = NodeType::add("mesh", create);
- SOCKET_UINT(motion_steps, "Motion Steps", 3);
- SOCKET_BOOLEAN(use_motion_blur, "Use Motion Blur", false);
+ SOCKET_UINT(motion_steps, "Motion Steps", 3);
+ SOCKET_BOOLEAN(use_motion_blur, "Use Motion Blur", false);
- SOCKET_INT_ARRAY(triangles, "Triangles", array<int>());
- SOCKET_POINT_ARRAY(verts, "Vertices", array<float3>());
- SOCKET_INT_ARRAY(shader, "Shader", array<int>());
- SOCKET_BOOLEAN_ARRAY(smooth, "Smooth", array<bool>());
+ SOCKET_INT_ARRAY(triangles, "Triangles", array<int>());
+ SOCKET_POINT_ARRAY(verts, "Vertices", array<float3>());
+ SOCKET_INT_ARRAY(shader, "Shader", array<int>());
+ SOCKET_BOOLEAN_ARRAY(smooth, "Smooth", array<bool>());
- SOCKET_POINT_ARRAY(curve_keys, "Curve Keys", array<float3>());
- SOCKET_FLOAT_ARRAY(curve_radius, "Curve Radius", array<float>());
- SOCKET_INT_ARRAY(curve_first_key, "Curve First Key", array<int>());
- SOCKET_INT_ARRAY(curve_shader, "Curve Shader", array<int>());
+ SOCKET_POINT_ARRAY(curve_keys, "Curve Keys", array<float3>());
+ SOCKET_FLOAT_ARRAY(curve_radius, "Curve Radius", array<float>());
+ SOCKET_INT_ARRAY(curve_first_key, "Curve First Key", array<int>());
+ SOCKET_INT_ARRAY(curve_shader, "Curve Shader", array<int>());
- return type;
+ return type;
}
-Mesh::Mesh()
-: Node(node_type)
+Mesh::Mesh() : Node(node_type)
{
- need_update = true;
- need_update_rebuild = false;
- transform_applied = false;
- transform_negative_scaled = false;
- transform_normal = transform_identity();
- bounds = BoundBox::empty;
+ need_update = true;
+ need_update_rebuild = false;
+ transform_applied = false;
+ transform_negative_scaled = false;
+ transform_normal = transform_identity();
+ bounds = BoundBox::empty;
- bvh = NULL;
+ bvh = NULL;
- tri_offset = 0;
- vert_offset = 0;
+ tri_offset = 0;
+ vert_offset = 0;
- curve_offset = 0;
- curvekey_offset = 0;
+ curve_offset = 0;
+ curvekey_offset = 0;
- patch_offset = 0;
- face_offset = 0;
- corner_offset = 0;
+ patch_offset = 0;
+ face_offset = 0;
+ corner_offset = 0;
- attr_map_offset = 0;
+ attr_map_offset = 0;
- num_subd_verts = 0;
+ num_subd_verts = 0;
- attributes.triangle_mesh = this;
- curve_attributes.curve_mesh = this;
- subd_attributes.subd_mesh = this;
+ attributes.triangle_mesh = this;
+ curve_attributes.curve_mesh = this;
+ subd_attributes.subd_mesh = this;
- geometry_flags = GEOMETRY_NONE;
+ geometry_flags = GEOMETRY_NONE;
- volume_isovalue = 0.001f;
- has_volume = false;
- has_surface_bssrdf = false;
+ volume_isovalue = 0.001f;
+ has_volume = false;
+ has_surface_bssrdf = false;
- num_ngons = 0;
+ num_ngons = 0;
- subdivision_type = SUBDIVISION_NONE;
- subd_params = NULL;
+ subdivision_type = SUBDIVISION_NONE;
+ subd_params = NULL;
- patch_table = NULL;
+ patch_table = NULL;
}
Mesh::~Mesh()
{
- delete bvh;
- delete patch_table;
- delete subd_params;
+ delete bvh;
+ delete patch_table;
+ delete subd_params;
}
void Mesh::resize_mesh(int numverts, int numtris)
{
- verts.resize(numverts);
- triangles.resize(numtris * 3);
- shader.resize(numtris);
- smooth.resize(numtris);
+ verts.resize(numverts);
+ triangles.resize(numtris * 3);
+ shader.resize(numtris);
+ smooth.resize(numtris);
- if(subd_faces.size()) {
- triangle_patch.resize(numtris);
- vert_patch_uv.resize(numverts);
- }
+ if (subd_faces.size()) {
+ triangle_patch.resize(numtris);
+ vert_patch_uv.resize(numverts);
+ }
- attributes.resize();
+ attributes.resize();
}
void Mesh::reserve_mesh(int numverts, int numtris)
{
- /* reserve space to add verts and triangles later */
- verts.reserve(numverts);
- triangles.reserve(numtris * 3);
- shader.reserve(numtris);
- smooth.reserve(numtris);
+ /* reserve space to add verts and triangles later */
+ verts.reserve(numverts);
+ triangles.reserve(numtris * 3);
+ shader.reserve(numtris);
+ smooth.reserve(numtris);
- if(subd_faces.size()) {
- triangle_patch.reserve(numtris);
- vert_patch_uv.reserve(numverts);
- }
+ if (subd_faces.size()) {
+ triangle_patch.reserve(numtris);
+ vert_patch_uv.reserve(numverts);
+ }
- attributes.resize(true);
+ attributes.resize(true);
}
void Mesh::resize_curves(int numcurves, int numkeys)
{
- curve_keys.resize(numkeys);
- curve_radius.resize(numkeys);
- curve_first_key.resize(numcurves);
- curve_shader.resize(numcurves);
+ curve_keys.resize(numkeys);
+ curve_radius.resize(numkeys);
+ curve_first_key.resize(numcurves);
+ curve_shader.resize(numcurves);
- curve_attributes.resize();
+ curve_attributes.resize();
}
void Mesh::reserve_curves(int numcurves, int numkeys)
{
- curve_keys.reserve(numkeys);
- curve_radius.reserve(numkeys);
- curve_first_key.reserve(numcurves);
- curve_shader.reserve(numcurves);
+ curve_keys.reserve(numkeys);
+ curve_radius.reserve(numkeys);
+ curve_first_key.reserve(numcurves);
+ curve_shader.reserve(numcurves);
- curve_attributes.resize(true);
+ curve_attributes.resize(true);
}
void Mesh::resize_subd_faces(int numfaces, int num_ngons_, int numcorners)
{
- subd_faces.resize(numfaces);
- subd_face_corners.resize(numcorners);
- num_ngons = num_ngons_;
+ subd_faces.resize(numfaces);
+ subd_face_corners.resize(numcorners);
+ num_ngons = num_ngons_;
- subd_attributes.resize();
+ subd_attributes.resize();
}
void Mesh::reserve_subd_faces(int numfaces, int num_ngons_, int numcorners)
{
- subd_faces.reserve(numfaces);
- subd_face_corners.reserve(numcorners);
- num_ngons = num_ngons_;
+ subd_faces.reserve(numfaces);
+ subd_face_corners.reserve(numcorners);
+ num_ngons = num_ngons_;
- subd_attributes.resize(true);
+ subd_attributes.resize(true);
}
void Mesh::clear(bool preserve_voxel_data)
{
- /* clear all verts and triangles */
- verts.clear();
- triangles.clear();
- shader.clear();
- smooth.clear();
+ /* clear all verts and triangles */
+ verts.clear();
+ triangles.clear();
+ shader.clear();
+ smooth.clear();
- triangle_patch.clear();
- vert_patch_uv.clear();
+ triangle_patch.clear();
+ vert_patch_uv.clear();
- curve_keys.clear();
- curve_radius.clear();
- curve_first_key.clear();
- curve_shader.clear();
+ curve_keys.clear();
+ curve_radius.clear();
+ curve_first_key.clear();
+ curve_shader.clear();
- subd_faces.clear();
- subd_face_corners.clear();
+ subd_faces.clear();
+ subd_face_corners.clear();
- num_subd_verts = 0;
+ num_subd_verts = 0;
- subd_creases.clear();
+ subd_creases.clear();
- curve_attributes.clear();
- subd_attributes.clear();
- attributes.clear(preserve_voxel_data);
+ curve_attributes.clear();
+ subd_attributes.clear();
+ attributes.clear(preserve_voxel_data);
- used_shaders.clear();
+ used_shaders.clear();
- if(!preserve_voxel_data) {
- geometry_flags = GEOMETRY_NONE;
- }
+ if (!preserve_voxel_data) {
+ geometry_flags = GEOMETRY_NONE;
+ }
- transform_applied = false;
- transform_negative_scaled = false;
- transform_normal = transform_identity();
+ transform_applied = false;
+ transform_negative_scaled = false;
+ transform_normal = transform_identity();
- delete patch_table;
- patch_table = NULL;
+ delete patch_table;
+ patch_table = NULL;
}
void Mesh::add_vertex(float3 P)
{
- verts.push_back_reserved(P);
+ verts.push_back_reserved(P);
- if(subd_faces.size()) {
- vert_patch_uv.push_back_reserved(make_float2(0.0f, 0.0f));
- }
+ if (subd_faces.size()) {
+ vert_patch_uv.push_back_reserved(make_float2(0.0f, 0.0f));
+ }
}
void Mesh::add_vertex_slow(float3 P)
{
- verts.push_back_slow(P);
+ verts.push_back_slow(P);
- if(subd_faces.size()) {
- vert_patch_uv.push_back_slow(make_float2(0.0f, 0.0f));
- }
+ if (subd_faces.size()) {
+ vert_patch_uv.push_back_slow(make_float2(0.0f, 0.0f));
+ }
}
void Mesh::add_triangle(int v0, int v1, int v2, int shader_, bool smooth_)
{
- triangles.push_back_reserved(v0);
- triangles.push_back_reserved(v1);
- triangles.push_back_reserved(v2);
- shader.push_back_reserved(shader_);
- smooth.push_back_reserved(smooth_);
+ triangles.push_back_reserved(v0);
+ triangles.push_back_reserved(v1);
+ triangles.push_back_reserved(v2);
+ shader.push_back_reserved(shader_);
+ smooth.push_back_reserved(smooth_);
- if(subd_faces.size()) {
- triangle_patch.push_back_reserved(-1);
- }
+ if (subd_faces.size()) {
+ triangle_patch.push_back_reserved(-1);
+ }
}
void Mesh::add_curve_key(float3 co, float radius)
{
- curve_keys.push_back_reserved(co);
- curve_radius.push_back_reserved(radius);
+ curve_keys.push_back_reserved(co);
+ curve_radius.push_back_reserved(radius);
}
void Mesh::add_curve(int first_key, int shader)
{
- curve_first_key.push_back_reserved(first_key);
- curve_shader.push_back_reserved(shader);
+ curve_first_key.push_back_reserved(first_key);
+ curve_shader.push_back_reserved(shader);
}
-void Mesh::add_subd_face(int* corners, int num_corners, int shader_, bool smooth_)
+void Mesh::add_subd_face(int *corners, int num_corners, int shader_, bool smooth_)
{
- int start_corner = subd_face_corners.size();
+ int start_corner = subd_face_corners.size();
- for(int i = 0; i < num_corners; i++) {
- subd_face_corners.push_back_reserved(corners[i]);
- }
+ for (int i = 0; i < num_corners; i++) {
+ subd_face_corners.push_back_reserved(corners[i]);
+ }
- int ptex_offset = 0;
+ int ptex_offset = 0;
- if(subd_faces.size()) {
- SubdFace& s = subd_faces[subd_faces.size()-1];
- ptex_offset = s.ptex_offset + s.num_ptex_faces();
- }
+ if (subd_faces.size()) {
+ SubdFace &s = subd_faces[subd_faces.size() - 1];
+ ptex_offset = s.ptex_offset + s.num_ptex_faces();
+ }
- SubdFace face = {start_corner, num_corners, shader_, smooth_, ptex_offset};
- subd_faces.push_back_reserved(face);
+ SubdFace face = {start_corner, num_corners, shader_, smooth_, ptex_offset};
+ subd_faces.push_back_reserved(face);
}
void Mesh::compute_bounds()
{
- BoundBox bnds = BoundBox::empty;
- size_t verts_size = verts.size();
- size_t curve_keys_size = curve_keys.size();
+ BoundBox bnds = BoundBox::empty;
+ size_t verts_size = verts.size();
+ size_t curve_keys_size = curve_keys.size();
- if(verts_size + curve_keys_size > 0) {
- for(size_t i = 0; i < verts_size; i++)
- bnds.grow(verts[i]);
+ if (verts_size + curve_keys_size > 0) {
+ for (size_t i = 0; i < verts_size; i++)
+ bnds.grow(verts[i]);
- for(size_t i = 0; i < curve_keys_size; i++)
- bnds.grow(curve_keys[i], curve_radius[i]);
+ for (size_t i = 0; i < curve_keys_size; i++)
+ bnds.grow(curve_keys[i], curve_radius[i]);
- Attribute *attr = attributes.find(ATTR_STD_MOTION_VERTEX_POSITION);
- if(use_motion_blur && attr) {
- size_t steps_size = verts.size() * (motion_steps - 1);
- float3 *vert_steps = attr->data_float3();
+ Attribute *attr = attributes.find(ATTR_STD_MOTION_VERTEX_POSITION);
+ if (use_motion_blur && attr) {
+ size_t steps_size = verts.size() * (motion_steps - 1);
+ float3 *vert_steps = attr->data_float3();
- for(size_t i = 0; i < steps_size; i++)
- bnds.grow(vert_steps[i]);
- }
+ for (size_t i = 0; i < steps_size; i++)
+ bnds.grow(vert_steps[i]);
+ }
- Attribute *curve_attr = curve_attributes.find(ATTR_STD_MOTION_VERTEX_POSITION);
- if(use_motion_blur && curve_attr) {
- size_t steps_size = curve_keys.size() * (motion_steps - 1);
- float3 *key_steps = curve_attr->data_float3();
+ Attribute *curve_attr = curve_attributes.find(ATTR_STD_MOTION_VERTEX_POSITION);
+ if (use_motion_blur && curve_attr) {
+ size_t steps_size = curve_keys.size() * (motion_steps - 1);
+ float3 *key_steps = curve_attr->data_float3();
- for(size_t i = 0; i < steps_size; i++)
- bnds.grow(key_steps[i]);
- }
+ for (size_t i = 0; i < steps_size; i++)
+ bnds.grow(key_steps[i]);
+ }
- if(!bnds.valid()) {
- bnds = BoundBox::empty;
+ if (!bnds.valid()) {
+ bnds = BoundBox::empty;
- /* skip nan or inf coordinates */
- for(size_t i = 0; i < verts_size; i++)
- bnds.grow_safe(verts[i]);
+ /* skip nan or inf coordinates */
+ for (size_t i = 0; i < verts_size; i++)
+ bnds.grow_safe(verts[i]);
- for(size_t i = 0; i < curve_keys_size; i++)
- bnds.grow_safe(curve_keys[i], curve_radius[i]);
+ for (size_t i = 0; i < curve_keys_size; i++)
+ bnds.grow_safe(curve_keys[i], curve_radius[i]);
- if(use_motion_blur && attr) {
- size_t steps_size = verts.size() * (motion_steps - 1);
- float3 *vert_steps = attr->data_float3();
+ if (use_motion_blur && attr) {
+ size_t steps_size = verts.size() * (motion_steps - 1);
+ float3 *vert_steps = attr->data_float3();
- for(size_t i = 0; i < steps_size; i++)
- bnds.grow_safe(vert_steps[i]);
- }
+ for (size_t i = 0; i < steps_size; i++)
+ bnds.grow_safe(vert_steps[i]);
+ }
- if(use_motion_blur && curve_attr) {
- size_t steps_size = curve_keys.size() * (motion_steps - 1);
- float3 *key_steps = curve_attr->data_float3();
+ if (use_motion_blur && curve_attr) {
+ size_t steps_size = curve_keys.size() * (motion_steps - 1);
+ float3 *key_steps = curve_attr->data_float3();
- for(size_t i = 0; i < steps_size; i++)
- bnds.grow_safe(key_steps[i]);
- }
- }
- }
+ for (size_t i = 0; i < steps_size; i++)
+ bnds.grow_safe(key_steps[i]);
+ }
+ }
+ }
- if(!bnds.valid()) {
- /* empty mesh */
- bnds.grow(make_float3(0.0f, 0.0f, 0.0f));
- }
+ if (!bnds.valid()) {
+ /* empty mesh */
+ bnds.grow(make_float3(0.0f, 0.0f, 0.0f));
+ }
- bounds = bnds;
+ bounds = bnds;
}
void Mesh::add_face_normals()
{
- /* don't compute if already there */
- if(attributes.find(ATTR_STD_FACE_NORMAL))
- return;
+ /* don't compute if already there */
+ if (attributes.find(ATTR_STD_FACE_NORMAL))
+ return;
- /* get attributes */
- Attribute *attr_fN = attributes.add(ATTR_STD_FACE_NORMAL);
- float3 *fN = attr_fN->data_float3();
+ /* get attributes */
+ Attribute *attr_fN = attributes.add(ATTR_STD_FACE_NORMAL);
+ float3 *fN = attr_fN->data_float3();
- /* compute face normals */
- size_t triangles_size = num_triangles();
+ /* compute face normals */
+ size_t triangles_size = num_triangles();
- if(triangles_size) {
- float3 *verts_ptr = verts.data();
+ if (triangles_size) {
+ float3 *verts_ptr = verts.data();
- for(size_t i = 0; i < triangles_size; i++) {
- fN[i] = get_triangle(i).compute_normal(verts_ptr);
- }
- }
+ for (size_t i = 0; i < triangles_size; i++) {
+ fN[i] = get_triangle(i).compute_normal(verts_ptr);
+ }
+ }
- /* expected to be in local space */
- if(transform_applied) {
- Transform ntfm = transform_inverse(transform_normal);
+ /* expected to be in local space */
+ if (transform_applied) {
+ Transform ntfm = transform_inverse(transform_normal);
- for(size_t i = 0; i < triangles_size; i++)
- fN[i] = normalize(transform_direction(&ntfm, fN[i]));
- }
+ for (size_t i = 0; i < triangles_size; i++)
+ fN[i] = normalize(transform_direction(&ntfm, fN[i]));
+ }
}
void Mesh::add_vertex_normals()
{
- bool flip = transform_negative_scaled;
- size_t verts_size = verts.size();
- size_t triangles_size = num_triangles();
-
- /* static vertex normals */
- if(!attributes.find(ATTR_STD_VERTEX_NORMAL) && triangles_size) {
- /* get attributes */
- Attribute *attr_fN = attributes.find(ATTR_STD_FACE_NORMAL);
- Attribute *attr_vN = attributes.add(ATTR_STD_VERTEX_NORMAL);
-
- float3 *fN = attr_fN->data_float3();
- float3 *vN = attr_vN->data_float3();
-
- /* compute vertex normals */
- memset(vN, 0, verts.size()*sizeof(float3));
-
- for(size_t i = 0; i < triangles_size; i++) {
- for(size_t j = 0; j < 3; j++) {
- vN[get_triangle(i).v[j]] += fN[i];
- }
- }
-
- for(size_t i = 0; i < verts_size; i++) {
- vN[i] = normalize(vN[i]);
- if(flip) {
- vN[i] = -vN[i];
- }
- }
- }
-
- /* motion vertex normals */
- Attribute *attr_mP = attributes.find(ATTR_STD_MOTION_VERTEX_POSITION);
- Attribute *attr_mN = attributes.find(ATTR_STD_MOTION_VERTEX_NORMAL);
-
- if(has_motion_blur() && attr_mP && !attr_mN && triangles_size) {
- /* create attribute */
- attr_mN = attributes.add(ATTR_STD_MOTION_VERTEX_NORMAL);
-
- for(int step = 0; step < motion_steps - 1; step++) {
- float3 *mP = attr_mP->data_float3() + step*verts.size();
- float3 *mN = attr_mN->data_float3() + step*verts.size();
-
- /* compute */
- memset(mN, 0, verts.size()*sizeof(float3));
-
- for(size_t i = 0; i < triangles_size; i++) {
- for(size_t j = 0; j < 3; j++) {
- float3 fN = get_triangle(i).compute_normal(mP);
- mN[get_triangle(i).v[j]] += fN;
- }
- }
-
- for(size_t i = 0; i < verts_size; i++) {
- mN[i] = normalize(mN[i]);
- if(flip) {
- mN[i] = -mN[i];
- }
- }
- }
- }
-
- /* subd vertex normals */
- if(!subd_attributes.find(ATTR_STD_VERTEX_NORMAL) && subd_faces.size()) {
- /* get attributes */
- Attribute *attr_vN = subd_attributes.add(ATTR_STD_VERTEX_NORMAL);
- float3 *vN = attr_vN->data_float3();
-
- /* compute vertex normals */
- memset(vN, 0, verts.size()*sizeof(float3));
-
- for(size_t i = 0; i < subd_faces.size(); i++) {
- SubdFace& face = subd_faces[i];
- float3 fN = face.normal(this);
-
- for(size_t j = 0; j < face.num_corners; j++) {
- size_t corner = subd_face_corners[face.start_corner+j];
- vN[corner] += fN;
- }
- }
-
- for(size_t i = 0; i < verts_size; i++) {
- vN[i] = normalize(vN[i]);
- if(flip) {
- vN[i] = -vN[i];
- }
- }
- }
+ bool flip = transform_negative_scaled;
+ size_t verts_size = verts.size();
+ size_t triangles_size = num_triangles();
+
+ /* static vertex normals */
+ if (!attributes.find(ATTR_STD_VERTEX_NORMAL) && triangles_size) {
+ /* get attributes */
+ Attribute *attr_fN = attributes.find(ATTR_STD_FACE_NORMAL);
+ Attribute *attr_vN = attributes.add(ATTR_STD_VERTEX_NORMAL);
+
+ float3 *fN = attr_fN->data_float3();
+ float3 *vN = attr_vN->data_float3();
+
+ /* compute vertex normals */
+ memset(vN, 0, verts.size() * sizeof(float3));
+
+ for (size_t i = 0; i < triangles_size; i++) {
+ for (size_t j = 0; j < 3; j++) {
+ vN[get_triangle(i).v[j]] += fN[i];
+ }
+ }
+
+ for (size_t i = 0; i < verts_size; i++) {
+ vN[i] = normalize(vN[i]);
+ if (flip) {
+ vN[i] = -vN[i];
+ }
+ }
+ }
+
+ /* motion vertex normals */
+ Attribute *attr_mP = attributes.find(ATTR_STD_MOTION_VERTEX_POSITION);
+ Attribute *attr_mN = attributes.find(ATTR_STD_MOTION_VERTEX_NORMAL);
+
+ if (has_motion_blur() && attr_mP && !attr_mN && triangles_size) {
+ /* create attribute */
+ attr_mN = attributes.add(ATTR_STD_MOTION_VERTEX_NORMAL);
+
+ for (int step = 0; step < motion_steps - 1; step++) {
+ float3 *mP = attr_mP->data_float3() + step * verts.size();
+ float3 *mN = attr_mN->data_float3() + step * verts.size();
+
+ /* compute */
+ memset(mN, 0, verts.size() * sizeof(float3));
+
+ for (size_t i = 0; i < triangles_size; i++) {
+ for (size_t j = 0; j < 3; j++) {
+ float3 fN = get_triangle(i).compute_normal(mP);
+ mN[get_triangle(i).v[j]] += fN;
+ }
+ }
+
+ for (size_t i = 0; i < verts_size; i++) {
+ mN[i] = normalize(mN[i]);
+ if (flip) {
+ mN[i] = -mN[i];
+ }
+ }
+ }
+ }
+
+ /* subd vertex normals */
+ if (!subd_attributes.find(ATTR_STD_VERTEX_NORMAL) && subd_faces.size()) {
+ /* get attributes */
+ Attribute *attr_vN = subd_attributes.add(ATTR_STD_VERTEX_NORMAL);
+ float3 *vN = attr_vN->data_float3();
+
+ /* compute vertex normals */
+ memset(vN, 0, verts.size() * sizeof(float3));
+
+ for (size_t i = 0; i < subd_faces.size(); i++) {
+ SubdFace &face = subd_faces[i];
+ float3 fN = face.normal(this);
+
+ for (size_t j = 0; j < face.num_corners; j++) {
+ size_t corner = subd_face_corners[face.start_corner + j];
+ vN[corner] += fN;
+ }
+ }
+
+ for (size_t i = 0; i < verts_size; i++) {
+ vN[i] = normalize(vN[i]);
+ if (flip) {
+ vN[i] = -vN[i];
+ }
+ }
+ }
}
void Mesh::add_undisplaced()
{
- AttributeSet& attrs = (subdivision_type == SUBDIVISION_NONE) ? attributes : subd_attributes;
+ AttributeSet &attrs = (subdivision_type == SUBDIVISION_NONE) ? attributes : subd_attributes;
- /* don't compute if already there */
- if(attrs.find(ATTR_STD_POSITION_UNDISPLACED)) {
- return;
- }
+ /* don't compute if already there */
+ if (attrs.find(ATTR_STD_POSITION_UNDISPLACED)) {
+ return;
+ }
- /* get attribute */
- Attribute *attr = attrs.add(ATTR_STD_POSITION_UNDISPLACED);
- attr->flags |= ATTR_SUBDIVIDED;
+ /* get attribute */
+ Attribute *attr = attrs.add(ATTR_STD_POSITION_UNDISPLACED);
+ attr->flags |= ATTR_SUBDIVIDED;
- float3 *data = attr->data_float3();
+ float3 *data = attr->data_float3();
- /* copy verts */
- size_t size = attr->buffer_size(this, (subdivision_type == SUBDIVISION_NONE) ? ATTR_PRIM_TRIANGLE : ATTR_PRIM_SUBD);
+ /* copy verts */
+ size_t size = attr->buffer_size(
+ this, (subdivision_type == SUBDIVISION_NONE) ? ATTR_PRIM_TRIANGLE : ATTR_PRIM_SUBD);
- /* Center points for ngons aren't stored in Mesh::verts but are included in size since they will be
- * calculated later, we subtract them from size here so we don't have an overflow while copying.
- */
- size -= num_ngons * attr->data_sizeof();
+ /* Center points for ngons aren't stored in Mesh::verts but are included in size since they will be
+ * calculated later, we subtract them from size here so we don't have an overflow while copying.
+ */
+ size -= num_ngons * attr->data_sizeof();
- if(size) {
- memcpy(data, verts.data(), size);
- }
+ if (size) {
+ memcpy(data, verts.data(), size);
+ }
}
void Mesh::pack_shaders(Scene *scene, uint *tri_shader)
{
- uint shader_id = 0;
- uint last_shader = -1;
- bool last_smooth = false;
+ uint shader_id = 0;
+ uint last_shader = -1;
+ bool last_smooth = false;
- size_t triangles_size = num_triangles();
- int *shader_ptr = shader.data();
+ size_t triangles_size = num_triangles();
+ int *shader_ptr = shader.data();
- for(size_t i = 0; i < triangles_size; i++) {
- if(shader_ptr[i] != last_shader || last_smooth != smooth[i]) {
- last_shader = shader_ptr[i];
- last_smooth = smooth[i];
- Shader *shader = (last_shader < used_shaders.size()) ?
- used_shaders[last_shader] : scene->default_surface;
- shader_id = scene->shader_manager->get_shader_id(shader, last_smooth);
- }
+ for (size_t i = 0; i < triangles_size; i++) {
+ if (shader_ptr[i] != last_shader || last_smooth != smooth[i]) {
+ last_shader = shader_ptr[i];
+ last_smooth = smooth[i];
+ Shader *shader = (last_shader < used_shaders.size()) ? used_shaders[last_shader] :
+ scene->default_surface;
+ shader_id = scene->shader_manager->get_shader_id(shader, last_smooth);
+ }
- tri_shader[i] = shader_id;
- }
+ tri_shader[i] = shader_id;
+ }
}
void Mesh::pack_normals(float4 *vnormal)
{
- Attribute *attr_vN = attributes.find(ATTR_STD_VERTEX_NORMAL);
- if(attr_vN == NULL) {
- /* Happens on objects with just hair. */
- return;
- }
+ Attribute *attr_vN = attributes.find(ATTR_STD_VERTEX_NORMAL);
+ if (attr_vN == NULL) {
+ /* Happens on objects with just hair. */
+ return;
+ }
- bool do_transform = transform_applied;
- Transform ntfm = transform_normal;
+ bool do_transform = transform_applied;
+ Transform ntfm = transform_normal;
- float3 *vN = attr_vN->data_float3();
- size_t verts_size = verts.size();
+ float3 *vN = attr_vN->data_float3();
+ size_t verts_size = verts.size();
- for(size_t i = 0; i < verts_size; i++) {
- float3 vNi = vN[i];
+ for (size_t i = 0; i < verts_size; i++) {
+ float3 vNi = vN[i];
- if(do_transform)
- vNi = safe_normalize(transform_direction(&ntfm, vNi));
+ if (do_transform)
+ vNi = safe_normalize(transform_direction(&ntfm, vNi));
- vnormal[i] = make_float4(vNi.x, vNi.y, vNi.z, 0.0f);
- }
+ vnormal[i] = make_float4(vNi.x, vNi.y, vNi.z, 0.0f);
+ }
}
-void Mesh::pack_verts(const vector<uint>& tri_prim_index,
+void Mesh::pack_verts(const vector<uint> &tri_prim_index,
uint4 *tri_vindex,
uint *tri_patch,
float2 *tri_patch_uv,
size_t vert_offset,
size_t tri_offset)
{
- size_t verts_size = verts.size();
+ size_t verts_size = verts.size();
- if(verts_size && subd_faces.size()) {
- float2 *vert_patch_uv_ptr = vert_patch_uv.data();
+ if (verts_size && subd_faces.size()) {
+ float2 *vert_patch_uv_ptr = vert_patch_uv.data();
- for(size_t i = 0; i < verts_size; i++) {
- tri_patch_uv[i] = vert_patch_uv_ptr[i];
- }
- }
+ for (size_t i = 0; i < verts_size; i++) {
+ tri_patch_uv[i] = vert_patch_uv_ptr[i];
+ }
+ }
- size_t triangles_size = num_triangles();
+ size_t triangles_size = num_triangles();
- for(size_t i = 0; i < triangles_size; i++) {
- Triangle t = get_triangle(i);
- tri_vindex[i] = make_uint4(t.v[0] + vert_offset,
- t.v[1] + vert_offset,
- t.v[2] + vert_offset,
- tri_prim_index[i + tri_offset]);
+ for (size_t i = 0; i < triangles_size; i++) {
+ Triangle t = get_triangle(i);
+ tri_vindex[i] = make_uint4(t.v[0] + vert_offset,
+ t.v[1] + vert_offset,
+ t.v[2] + vert_offset,
+ tri_prim_index[i + tri_offset]);
- tri_patch[i] = (!subd_faces.size()) ? -1 : (triangle_patch[i]*8 + patch_offset);
- }
+ tri_patch[i] = (!subd_faces.size()) ? -1 : (triangle_patch[i] * 8 + patch_offset);
+ }
}
-void Mesh::pack_curves(Scene *scene, float4 *curve_key_co, float4 *curve_data, size_t curvekey_offset)
+void Mesh::pack_curves(Scene *scene,
+ float4 *curve_key_co,
+ float4 *curve_data,
+ size_t curvekey_offset)
{
- size_t curve_keys_size = curve_keys.size();
+ size_t curve_keys_size = curve_keys.size();
- /* pack curve keys */
- if(curve_keys_size) {
- float3 *keys_ptr = curve_keys.data();
- float *radius_ptr = curve_radius.data();
+ /* pack curve keys */
+ if (curve_keys_size) {
+ float3 *keys_ptr = curve_keys.data();
+ float *radius_ptr = curve_radius.data();
- for(size_t i = 0; i < curve_keys_size; i++)
- curve_key_co[i] = make_float4(keys_ptr[i].x, keys_ptr[i].y, keys_ptr[i].z, radius_ptr[i]);
- }
+ for (size_t i = 0; i < curve_keys_size; i++)
+ curve_key_co[i] = make_float4(keys_ptr[i].x, keys_ptr[i].y, keys_ptr[i].z, radius_ptr[i]);
+ }
- /* pack curve segments */
- size_t curve_num = num_curves();
+ /* pack curve segments */
+ size_t curve_num = num_curves();
- for(size_t i = 0; i < curve_num; i++) {
- Curve curve = get_curve(i);
- int shader_id = curve_shader[i];
- Shader *shader = (shader_id < used_shaders.size()) ?
- used_shaders[shader_id] : scene->default_surface;
- shader_id = scene->shader_manager->get_shader_id(shader, false);
+ for (size_t i = 0; i < curve_num; i++) {
+ Curve curve = get_curve(i);
+ int shader_id = curve_shader[i];
+ Shader *shader = (shader_id < used_shaders.size()) ? used_shaders[shader_id] :
+ scene->default_surface;
+ shader_id = scene->shader_manager->get_shader_id(shader, false);
- curve_data[i] = make_float4(
- __int_as_float(curve.first_key + curvekey_offset),
- __int_as_float(curve.num_keys),
- __int_as_float(shader_id),
- 0.0f);
- }
+ curve_data[i] = make_float4(__int_as_float(curve.first_key + curvekey_offset),
+ __int_as_float(curve.num_keys),
+ __int_as_float(shader_id),
+ 0.0f);
+ }
}
void Mesh::pack_patches(uint *patch_data, uint vert_offset, uint face_offset, uint corner_offset)
{
- size_t num_faces = subd_faces.size();
- int ngons = 0;
-
- for(size_t f = 0; f < num_faces; f++) {
- SubdFace face = subd_faces[f];
-
- if(face.is_quad()) {
- int c[4];
- memcpy(c, &subd_face_corners[face.start_corner], sizeof(int)*4);
-
- *(patch_data++) = c[0] + vert_offset;
- *(patch_data++) = c[1] + vert_offset;
- *(patch_data++) = c[2] + vert_offset;
- *(patch_data++) = c[3] + vert_offset;
-
- *(patch_data++) = f+face_offset;
- *(patch_data++) = face.num_corners;
- *(patch_data++) = face.start_corner + corner_offset;
- *(patch_data++) = 0;
- }
- else {
- for(int i = 0; i < face.num_corners; i++) {
- int c[4];
- c[0] = subd_face_corners[face.start_corner + mod(i + 0, face.num_corners)];
- c[1] = subd_face_corners[face.start_corner + mod(i + 1, face.num_corners)];
- c[2] = verts.size() - num_subd_verts + ngons;
- c[3] = subd_face_corners[face.start_corner + mod(i - 1, face.num_corners)];
-
- *(patch_data++) = c[0] + vert_offset;
- *(patch_data++) = c[1] + vert_offset;
- *(patch_data++) = c[2] + vert_offset;
- *(patch_data++) = c[3] + vert_offset;
-
- *(patch_data++) = f+face_offset;
- *(patch_data++) = face.num_corners | (i << 16);
- *(patch_data++) = face.start_corner + corner_offset;
- *(patch_data++) = subd_face_corners.size() + ngons + corner_offset;
- }
-
- ngons++;
- }
- }
-}
-
-void Mesh::compute_bvh(Device *device,
- DeviceScene *dscene,
- SceneParams *params,
- Progress *progress,
- int n,
- int total)
-{
- if(progress->get_cancel())
- return;
-
- compute_bounds();
-
- if(need_build_bvh()) {
- string msg = "Updating Mesh BVH ";
- if(name == "")
- msg += string_printf("%u/%u", (uint)(n+1), (uint)total);
- else
- msg += string_printf("%s %u/%u", name.c_str(), (uint)(n+1), (uint)total);
-
- Object object;
- object.mesh = this;
-
- vector<Object*> objects;
- objects.push_back(&object);
-
- if(bvh && !need_update_rebuild) {
- progress->set_status(msg, "Refitting BVH");
- bvh->objects = objects;
- bvh->refit(*progress);
- }
- else {
- progress->set_status(msg, "Building BVH");
-
- BVHParams bparams;
- bparams.use_spatial_split = params->use_bvh_spatial_split;
- bparams.bvh_layout = BVHParams::best_bvh_layout(
- params->bvh_layout,
- device->get_bvh_layout_mask());
- bparams.use_unaligned_nodes = dscene->data.bvh.have_curves &&
- params->use_bvh_unaligned_nodes;
- bparams.num_motion_triangle_steps = params->num_bvh_time_steps;
- bparams.num_motion_curve_steps = params->num_bvh_time_steps;
- bparams.bvh_type = params->bvh_type;
- bparams.curve_flags = dscene->data.curve.curveflags;
- bparams.curve_subdivisions = dscene->data.curve.subdivisions;
-
- delete bvh;
- bvh = BVH::create(bparams, objects);
- MEM_GUARDED_CALL(progress, bvh->build, *progress);
- }
- }
-
- need_update = false;
- need_update_rebuild = false;
+ size_t num_faces = subd_faces.size();
+ int ngons = 0;
+
+ for (size_t f = 0; f < num_faces; f++) {
+ SubdFace face = subd_faces[f];
+
+ if (face.is_quad()) {
+ int c[4];
+ memcpy(c, &subd_face_corners[face.start_corner], sizeof(int) * 4);
+
+ *(patch_data++) = c[0] + vert_offset;
+ *(patch_data++) = c[1] + vert_offset;
+ *(patch_data++) = c[2] + vert_offset;
+ *(patch_data++) = c[3] + vert_offset;
+
+ *(patch_data++) = f + face_offset;
+ *(patch_data++) = face.num_corners;
+ *(patch_data++) = face.start_corner + corner_offset;
+ *(patch_data++) = 0;
+ }
+ else {
+ for (int i = 0; i < face.num_corners; i++) {
+ int c[4];
+ c[0] = subd_face_corners[face.start_corner + mod(i + 0, face.num_corners)];
+ c[1] = subd_face_corners[face.start_corner + mod(i + 1, face.num_corners)];
+ c[2] = verts.size() - num_subd_verts + ngons;
+ c[3] = subd_face_corners[face.start_corner + mod(i - 1, face.num_corners)];
+
+ *(patch_data++) = c[0] + vert_offset;
+ *(patch_data++) = c[1] + vert_offset;
+ *(patch_data++) = c[2] + vert_offset;
+ *(patch_data++) = c[3] + vert_offset;
+
+ *(patch_data++) = f + face_offset;
+ *(patch_data++) = face.num_corners | (i << 16);
+ *(patch_data++) = face.start_corner + corner_offset;
+ *(patch_data++) = subd_face_corners.size() + ngons + corner_offset;
+ }
+
+ ngons++;
+ }
+ }
+}
+
+void Mesh::compute_bvh(
+ Device *device, DeviceScene *dscene, SceneParams *params, Progress *progress, int n, int total)
+{
+ if (progress->get_cancel())
+ return;
+
+ compute_bounds();
+
+ if (need_build_bvh()) {
+ string msg = "Updating Mesh BVH ";
+ if (name == "")
+ msg += string_printf("%u/%u", (uint)(n + 1), (uint)total);
+ else
+ msg += string_printf("%s %u/%u", name.c_str(), (uint)(n + 1), (uint)total);
+
+ Object object;
+ object.mesh = this;
+
+ vector<Object *> objects;
+ objects.push_back(&object);
+
+ if (bvh && !need_update_rebuild) {
+ progress->set_status(msg, "Refitting BVH");
+ bvh->objects = objects;
+ bvh->refit(*progress);
+ }
+ else {
+ progress->set_status(msg, "Building BVH");
+
+ BVHParams bparams;
+ bparams.use_spatial_split = params->use_bvh_spatial_split;
+ bparams.bvh_layout = BVHParams::best_bvh_layout(params->bvh_layout,
+ device->get_bvh_layout_mask());
+ bparams.use_unaligned_nodes = dscene->data.bvh.have_curves &&
+ params->use_bvh_unaligned_nodes;
+ bparams.num_motion_triangle_steps = params->num_bvh_time_steps;
+ bparams.num_motion_curve_steps = params->num_bvh_time_steps;
+ bparams.bvh_type = params->bvh_type;
+ bparams.curve_flags = dscene->data.curve.curveflags;
+ bparams.curve_subdivisions = dscene->data.curve.subdivisions;
+
+ delete bvh;
+ bvh = BVH::create(bparams, objects);
+ MEM_GUARDED_CALL(progress, bvh->build, *progress);
+ }
+ }
+
+ need_update = false;
+ need_update_rebuild = false;
}
void Mesh::tag_update(Scene *scene, bool rebuild)
{
- need_update = true;
+ need_update = true;
- if(rebuild) {
- need_update_rebuild = true;
- scene->light_manager->need_update = true;
- }
- else {
- foreach(Shader *shader, used_shaders)
- if(shader->has_surface_emission)
- scene->light_manager->need_update = true;
- }
+ if (rebuild) {
+ need_update_rebuild = true;
+ scene->light_manager->need_update = true;
+ }
+ else {
+ foreach (Shader *shader, used_shaders)
+ if (shader->has_surface_emission)
+ scene->light_manager->need_update = true;
+ }
- scene->mesh_manager->need_update = true;
- scene->object_manager->need_update = true;
+ scene->mesh_manager->need_update = true;
+ scene->object_manager->need_update = true;
}
bool Mesh::has_motion_blur() const
{
- return (use_motion_blur &&
- (attributes.find(ATTR_STD_MOTION_VERTEX_POSITION) ||
- curve_attributes.find(ATTR_STD_MOTION_VERTEX_POSITION)));
+ return (use_motion_blur && (attributes.find(ATTR_STD_MOTION_VERTEX_POSITION) ||
+ curve_attributes.find(ATTR_STD_MOTION_VERTEX_POSITION)));
}
bool Mesh::has_true_displacement() const
{
- foreach(Shader *shader, used_shaders) {
- if(shader->has_displacement && shader->displacement_method != DISPLACE_BUMP) {
- return true;
- }
- }
+ foreach (Shader *shader, used_shaders) {
+ if (shader->has_displacement && shader->displacement_method != DISPLACE_BUMP) {
+ return true;
+ }
+ }
- return false;
+ return false;
}
float Mesh::motion_time(int step) const
{
- return (motion_steps > 1) ? 2.0f * step / (motion_steps - 1) - 1.0f : 0.0f;
+ return (motion_steps > 1) ? 2.0f * step / (motion_steps - 1) - 1.0f : 0.0f;
}
int Mesh::motion_step(float time) const
{
- if(motion_steps > 1) {
- int attr_step = 0;
+ if (motion_steps > 1) {
+ int attr_step = 0;
- for(int step = 0; step < motion_steps; step++) {
- float step_time = motion_time(step);
- if(step_time == time) {
- return attr_step;
- }
+ for (int step = 0; step < motion_steps; step++) {
+ float step_time = motion_time(step);
+ if (step_time == time) {
+ return attr_step;
+ }
- /* Center step is stored in a separate attribute. */
- if(step != motion_steps / 2) {
- attr_step++;
- }
- }
- }
+ /* Center step is stored in a separate attribute. */
+ if (step != motion_steps / 2) {
+ attr_step++;
+ }
+ }
+ }
- return -1;
+ return -1;
}
bool Mesh::need_build_bvh() const
{
- return !transform_applied || has_surface_bssrdf;
+ return !transform_applied || has_surface_bssrdf;
}
bool Mesh::is_instanced() const
{
- /* Currently we treat subsurface objects as instanced.
- *
- * While it might be not very optimal for ray traversal, it avoids having
- * duplicated BVH in the memory, saving quite some space.
- */
- return !transform_applied || has_surface_bssrdf;
+ /* Currently we treat subsurface objects as instanced.
+ *
+ * While it might be not very optimal for ray traversal, it avoids having
+ * duplicated BVH in the memory, saving quite some space.
+ */
+ return !transform_applied || has_surface_bssrdf;
}
/* Mesh Manager */
MeshManager::MeshManager()
{
- need_update = true;
- need_flags_update = true;
+ need_update = true;
+ need_flags_update = true;
}
MeshManager::~MeshManager()
{
}
-void MeshManager::update_osl_attributes(Device *device, Scene *scene, vector<AttributeRequestSet>& mesh_attributes)
+void MeshManager::update_osl_attributes(Device *device,
+ Scene *scene,
+ vector<AttributeRequestSet> &mesh_attributes)
{
#ifdef WITH_OSL
- /* for OSL, a hash map is used to lookup the attribute by name. */
- OSLGlobals *og = (OSLGlobals*)device->osl_memory();
-
- og->object_name_map.clear();
- og->attribute_map.clear();
- og->object_names.clear();
-
- og->attribute_map.resize(scene->objects.size()*ATTR_PRIM_TYPES);
-
- for(size_t i = 0; i < scene->objects.size(); i++) {
- /* set object name to object index map */
- Object *object = scene->objects[i];
- og->object_name_map[object->name] = i;
- og->object_names.push_back(object->name);
-
- /* set object attributes */
- foreach(ParamValue& attr, object->attributes) {
- OSLGlobals::Attribute osl_attr;
-
- osl_attr.type = attr.type();
- osl_attr.desc.element = ATTR_ELEMENT_OBJECT;
- osl_attr.value = attr;
- osl_attr.desc.offset = 0;
- osl_attr.desc.flags = 0;
-
- og->attribute_map[i*ATTR_PRIM_TYPES + ATTR_PRIM_TRIANGLE][attr.name()] = osl_attr;
- og->attribute_map[i*ATTR_PRIM_TYPES + ATTR_PRIM_CURVE][attr.name()] = osl_attr;
- og->attribute_map[i*ATTR_PRIM_TYPES + ATTR_PRIM_SUBD][attr.name()] = osl_attr;
- }
-
- /* find mesh attributes */
- size_t j;
-
- for(j = 0; j < scene->meshes.size(); j++)
- if(scene->meshes[j] == object->mesh)
- break;
-
- AttributeRequestSet& attributes = mesh_attributes[j];
-
- /* set object attributes */
- foreach(AttributeRequest& req, attributes.requests) {
- OSLGlobals::Attribute osl_attr;
-
- if(req.triangle_desc.element != ATTR_ELEMENT_NONE) {
- osl_attr.desc = req.triangle_desc;
-
- if(req.triangle_type == TypeDesc::TypeFloat)
- osl_attr.type = TypeDesc::TypeFloat;
- else if(req.triangle_type == TypeDesc::TypeMatrix)
- osl_attr.type = TypeDesc::TypeMatrix;
- else if(req.triangle_type == TypeFloat2)
- osl_attr.type = TypeFloat2;
- else
- osl_attr.type = TypeDesc::TypeColor;
-
- if(req.std != ATTR_STD_NONE) {
- /* if standard attribute, add lookup by geom: name convention */
- ustring stdname(string("geom:") + string(Attribute::standard_name(req.std)));
- og->attribute_map[i*ATTR_PRIM_TYPES + ATTR_PRIM_TRIANGLE][stdname] = osl_attr;
- }
- else if(req.name != ustring()) {
- /* add lookup by mesh attribute name */
- og->attribute_map[i*ATTR_PRIM_TYPES + ATTR_PRIM_TRIANGLE][req.name] = osl_attr;
- }
- }
-
- if(req.curve_desc.element != ATTR_ELEMENT_NONE) {
- osl_attr.desc = req.curve_desc;
-
- if(req.curve_type == TypeDesc::TypeFloat)
- osl_attr.type = TypeDesc::TypeFloat;
- else if(req.curve_type == TypeDesc::TypeMatrix)
- osl_attr.type = TypeDesc::TypeMatrix;
- else
- osl_attr.type = TypeDesc::TypeColor;
-
- if(req.std != ATTR_STD_NONE) {
- /* if standard attribute, add lookup by geom: name convention */
- ustring stdname(string("geom:") + string(Attribute::standard_name(req.std)));
- og->attribute_map[i*ATTR_PRIM_TYPES + ATTR_PRIM_CURVE][stdname] = osl_attr;
- }
- else if(req.name != ustring()) {
- /* add lookup by mesh attribute name */
- og->attribute_map[i*ATTR_PRIM_TYPES + ATTR_PRIM_CURVE][req.name] = osl_attr;
- }
- }
-
- if(req.subd_desc.element != ATTR_ELEMENT_NONE) {
- osl_attr.desc = req.subd_desc;
-
- if(req.subd_type == TypeDesc::TypeFloat)
- osl_attr.type = TypeDesc::TypeFloat;
- else if(req.subd_type == TypeDesc::TypeMatrix)
- osl_attr.type = TypeDesc::TypeMatrix;
- else
- osl_attr.type = TypeDesc::TypeColor;
-
- if(req.std != ATTR_STD_NONE) {
- /* if standard attribute, add lookup by geom: name convention */
- ustring stdname(string("geom:") + string(Attribute::standard_name(req.std)));
- og->attribute_map[i*ATTR_PRIM_TYPES + ATTR_PRIM_SUBD][stdname] = osl_attr;
- }
- else if(req.name != ustring()) {
- /* add lookup by mesh attribute name */
- og->attribute_map[i*ATTR_PRIM_TYPES + ATTR_PRIM_SUBD][req.name] = osl_attr;
- }
- }
- }
- }
+ /* for OSL, a hash map is used to lookup the attribute by name. */
+ OSLGlobals *og = (OSLGlobals *)device->osl_memory();
+
+ og->object_name_map.clear();
+ og->attribute_map.clear();
+ og->object_names.clear();
+
+ og->attribute_map.resize(scene->objects.size() * ATTR_PRIM_TYPES);
+
+ for (size_t i = 0; i < scene->objects.size(); i++) {
+ /* set object name to object index map */
+ Object *object = scene->objects[i];
+ og->object_name_map[object->name] = i;
+ og->object_names.push_back(object->name);
+
+ /* set object attributes */
+ foreach (ParamValue &attr, object->attributes) {
+ OSLGlobals::Attribute osl_attr;
+
+ osl_attr.type = attr.type();
+ osl_attr.desc.element = ATTR_ELEMENT_OBJECT;
+ osl_attr.value = attr;
+ osl_attr.desc.offset = 0;
+ osl_attr.desc.flags = 0;
+
+ og->attribute_map[i * ATTR_PRIM_TYPES + ATTR_PRIM_TRIANGLE][attr.name()] = osl_attr;
+ og->attribute_map[i * ATTR_PRIM_TYPES + ATTR_PRIM_CURVE][attr.name()] = osl_attr;
+ og->attribute_map[i * ATTR_PRIM_TYPES + ATTR_PRIM_SUBD][attr.name()] = osl_attr;
+ }
+
+ /* find mesh attributes */
+ size_t j;
+
+ for (j = 0; j < scene->meshes.size(); j++)
+ if (scene->meshes[j] == object->mesh)
+ break;
+
+ AttributeRequestSet &attributes = mesh_attributes[j];
+
+ /* set object attributes */
+ foreach (AttributeRequest &req, attributes.requests) {
+ OSLGlobals::Attribute osl_attr;
+
+ if (req.triangle_desc.element != ATTR_ELEMENT_NONE) {
+ osl_attr.desc = req.triangle_desc;
+
+ if (req.triangle_type == TypeDesc::TypeFloat)
+ osl_attr.type = TypeDesc::TypeFloat;
+ else if (req.triangle_type == TypeDesc::TypeMatrix)
+ osl_attr.type = TypeDesc::TypeMatrix;
+ else if (req.triangle_type == TypeFloat2)
+ osl_attr.type = TypeFloat2;
+ else
+ osl_attr.type = TypeDesc::TypeColor;
+
+ if (req.std != ATTR_STD_NONE) {
+ /* if standard attribute, add lookup by geom: name convention */
+ ustring stdname(string("geom:") + string(Attribute::standard_name(req.std)));
+ og->attribute_map[i * ATTR_PRIM_TYPES + ATTR_PRIM_TRIANGLE][stdname] = osl_attr;
+ }
+ else if (req.name != ustring()) {
+ /* add lookup by mesh attribute name */
+ og->attribute_map[i * ATTR_PRIM_TYPES + ATTR_PRIM_TRIANGLE][req.name] = osl_attr;
+ }
+ }
+
+ if (req.curve_desc.element != ATTR_ELEMENT_NONE) {
+ osl_attr.desc = req.curve_desc;
+
+ if (req.curve_type == TypeDesc::TypeFloat)
+ osl_attr.type = TypeDesc::TypeFloat;
+ else if (req.curve_type == TypeDesc::TypeMatrix)
+ osl_attr.type = TypeDesc::TypeMatrix;
+ else
+ osl_attr.type = TypeDesc::TypeColor;
+
+ if (req.std != ATTR_STD_NONE) {
+ /* if standard attribute, add lookup by geom: name convention */
+ ustring stdname(string("geom:") + string(Attribute::standard_name(req.std)));
+ og->attribute_map[i * ATTR_PRIM_TYPES + ATTR_PRIM_CURVE][stdname] = osl_attr;
+ }
+ else if (req.name != ustring()) {
+ /* add lookup by mesh attribute name */
+ og->attribute_map[i * ATTR_PRIM_TYPES + ATTR_PRIM_CURVE][req.name] = osl_attr;
+ }
+ }
+
+ if (req.subd_desc.element != ATTR_ELEMENT_NONE) {
+ osl_attr.desc = req.subd_desc;
+
+ if (req.subd_type == TypeDesc::TypeFloat)
+ osl_attr.type = TypeDesc::TypeFloat;
+ else if (req.subd_type == TypeDesc::TypeMatrix)
+ osl_attr.type = TypeDesc::TypeMatrix;
+ else
+ osl_attr.type = TypeDesc::TypeColor;
+
+ if (req.std != ATTR_STD_NONE) {
+ /* if standard attribute, add lookup by geom: name convention */
+ ustring stdname(string("geom:") + string(Attribute::standard_name(req.std)));
+ og->attribute_map[i * ATTR_PRIM_TYPES + ATTR_PRIM_SUBD][stdname] = osl_attr;
+ }
+ else if (req.name != ustring()) {
+ /* add lookup by mesh attribute name */
+ og->attribute_map[i * ATTR_PRIM_TYPES + ATTR_PRIM_SUBD][req.name] = osl_attr;
+ }
+ }
+ }
+ }
#else
- (void) device;
- (void) scene;
- (void) mesh_attributes;
+ (void)device;
+ (void)scene;
+ (void)mesh_attributes;
#endif
}
-void MeshManager::update_svm_attributes(Device *, DeviceScene *dscene, Scene *scene, vector<AttributeRequestSet>& mesh_attributes)
-{
- /* for SVM, the attributes_map table is used to lookup the offset of an
- * attribute, based on a unique shader attribute id. */
-
- /* compute array stride */
- int attr_map_size = 0;
+void MeshManager::update_svm_attributes(Device *,
+ DeviceScene *dscene,
+ Scene *scene,
+ vector<AttributeRequestSet> &mesh_attributes)
+{
+ /* for SVM, the attributes_map table is used to lookup the offset of an
+ * attribute, based on a unique shader attribute id. */
+
+ /* compute array stride */
+ int attr_map_size = 0;
+
+ for (size_t i = 0; i < scene->meshes.size(); i++) {
+ Mesh *mesh = scene->meshes[i];
+ mesh->attr_map_offset = attr_map_size;
+ attr_map_size += (mesh_attributes[i].size() + 1) * ATTR_PRIM_TYPES;
+ }
- for(size_t i = 0; i < scene->meshes.size(); i++) {
- Mesh *mesh = scene->meshes[i];
- mesh->attr_map_offset = attr_map_size;
- attr_map_size += (mesh_attributes[i].size() + 1)*ATTR_PRIM_TYPES;
- }
+ if (attr_map_size == 0)
+ return;
- if(attr_map_size == 0)
- return;
+ /* create attribute map */
+ uint4 *attr_map = dscene->attributes_map.alloc(attr_map_size);
+ memset(attr_map, 0, dscene->attributes_map.size() * sizeof(uint));
- /* create attribute map */
- uint4 *attr_map = dscene->attributes_map.alloc(attr_map_size);
- memset(attr_map, 0, dscene->attributes_map.size()*sizeof(uint));
+ for (size_t i = 0; i < scene->meshes.size(); i++) {
+ Mesh *mesh = scene->meshes[i];
+ AttributeRequestSet &attributes = mesh_attributes[i];
- for(size_t i = 0; i < scene->meshes.size(); i++) {
- Mesh *mesh = scene->meshes[i];
- AttributeRequestSet& attributes = mesh_attributes[i];
+ /* set object attributes */
+ int index = mesh->attr_map_offset;
- /* set object attributes */
- int index = mesh->attr_map_offset;
+ foreach (AttributeRequest &req, attributes.requests) {
+ uint id;
- foreach(AttributeRequest& req, attributes.requests) {
- uint id;
+ if (req.std == ATTR_STD_NONE)
+ id = scene->shader_manager->get_attribute_id(req.name);
+ else
+ id = scene->shader_manager->get_attribute_id(req.std);
- if(req.std == ATTR_STD_NONE)
- id = scene->shader_manager->get_attribute_id(req.name);
- else
- id = scene->shader_manager->get_attribute_id(req.std);
+ if (mesh->num_triangles()) {
+ attr_map[index].x = id;
+ attr_map[index].y = req.triangle_desc.element;
+ attr_map[index].z = as_uint(req.triangle_desc.offset);
- if(mesh->num_triangles()) {
- attr_map[index].x = id;
- attr_map[index].y = req.triangle_desc.element;
- attr_map[index].z = as_uint(req.triangle_desc.offset);
+ if (req.triangle_type == TypeDesc::TypeFloat)
+ attr_map[index].w = NODE_ATTR_FLOAT;
+ else if (req.triangle_type == TypeDesc::TypeMatrix)
+ attr_map[index].w = NODE_ATTR_MATRIX;
+ else if (req.triangle_type == TypeFloat2)
+ attr_map[index].w = NODE_ATTR_FLOAT2;
+ else
+ attr_map[index].w = NODE_ATTR_FLOAT3;
- if(req.triangle_type == TypeDesc::TypeFloat)
- attr_map[index].w = NODE_ATTR_FLOAT;
- else if(req.triangle_type == TypeDesc::TypeMatrix)
- attr_map[index].w = NODE_ATTR_MATRIX;
- else if(req.triangle_type == TypeFloat2)
- attr_map[index].w = NODE_ATTR_FLOAT2;
- else
- attr_map[index].w = NODE_ATTR_FLOAT3;
+ attr_map[index].w |= req.triangle_desc.flags << 8;
+ }
- attr_map[index].w |= req.triangle_desc.flags << 8;
- }
+ index++;
- index++;
+ if (mesh->num_curves()) {
+ attr_map[index].x = id;
+ attr_map[index].y = req.curve_desc.element;
+ attr_map[index].z = as_uint(req.curve_desc.offset);
- if(mesh->num_curves()) {
- attr_map[index].x = id;
- attr_map[index].y = req.curve_desc.element;
- attr_map[index].z = as_uint(req.curve_desc.offset);
+ if (req.curve_type == TypeDesc::TypeFloat)
+ attr_map[index].w = NODE_ATTR_FLOAT;
+ else if (req.curve_type == TypeDesc::TypeMatrix)
+ attr_map[index].w = NODE_ATTR_MATRIX;
+ else if (req.curve_type == TypeFloat2)
+ attr_map[index].w = NODE_ATTR_FLOAT2;
+ else
+ attr_map[index].w = NODE_ATTR_FLOAT3;
- if(req.curve_type == TypeDesc::TypeFloat)
- attr_map[index].w = NODE_ATTR_FLOAT;
- else if(req.curve_type == TypeDesc::TypeMatrix)
- attr_map[index].w = NODE_ATTR_MATRIX;
- else if(req.curve_type == TypeFloat2)
- attr_map[index].w = NODE_ATTR_FLOAT2;
- else
- attr_map[index].w = NODE_ATTR_FLOAT3;
+ attr_map[index].w |= req.curve_desc.flags << 8;
+ }
- attr_map[index].w |= req.curve_desc.flags << 8;
- }
+ index++;
- index++;
+ if (mesh->subd_faces.size()) {
+ attr_map[index].x = id;
+ attr_map[index].y = req.subd_desc.element;
+ attr_map[index].z = as_uint(req.subd_desc.offset);
- if(mesh->subd_faces.size()) {
- attr_map[index].x = id;
- attr_map[index].y = req.subd_desc.element;
- attr_map[index].z = as_uint(req.subd_desc.offset);
+ if (req.subd_type == TypeDesc::TypeFloat)
+ attr_map[index].w = NODE_ATTR_FLOAT;
+ else if (req.subd_type == TypeDesc::TypeMatrix)
+ attr_map[index].w = NODE_ATTR_MATRIX;
+ else if (req.subd_type == TypeFloat2)
+ attr_map[index].w = NODE_ATTR_FLOAT2;
+ else
+ attr_map[index].w = NODE_ATTR_FLOAT3;
- if(req.subd_type == TypeDesc::TypeFloat)
- attr_map[index].w = NODE_ATTR_FLOAT;
- else if(req.subd_type == TypeDesc::TypeMatrix)
- attr_map[index].w = NODE_ATTR_MATRIX;
- else if(req.subd_type == TypeFloat2)
- attr_map[index].w = NODE_ATTR_FLOAT2;
- else
- attr_map[index].w = NODE_ATTR_FLOAT3;
+ attr_map[index].w |= req.subd_desc.flags << 8;
+ }
- attr_map[index].w |= req.subd_desc.flags << 8;
- }
+ index++;
+ }
- index++;
- }
-
- /* terminator */
- for(int j = 0; j < ATTR_PRIM_TYPES; j++) {
- attr_map[index].x = ATTR_STD_NONE;
- attr_map[index].y = 0;
- attr_map[index].z = 0;
- attr_map[index].w = 0;
-
- index++;
- }
- }
-
- /* copy to device */
- dscene->attributes_map.copy_to_device();
+ /* terminator */
+ for (int j = 0; j < ATTR_PRIM_TYPES; j++) {
+ attr_map[index].x = ATTR_STD_NONE;
+ attr_map[index].y = 0;
+ attr_map[index].z = 0;
+ attr_map[index].w = 0;
+
+ index++;
+ }
+ }
+
+ /* copy to device */
+ dscene->attributes_map.copy_to_device();
}
static void update_attribute_element_size(Mesh *mesh,
Attribute *mattr,
AttributePrimitive prim,
size_t *attr_float_size,
- size_t *attr_float2_size,
+ size_t *attr_float2_size,
size_t *attr_float3_size,
size_t *attr_uchar4_size)
{
- if(mattr) {
- size_t size = mattr->element_size(mesh, prim);
-
- if(mattr->element == ATTR_ELEMENT_VOXEL) {
- /* pass */
- }
- else if(mattr->element == ATTR_ELEMENT_CORNER_BYTE) {
- *attr_uchar4_size += size;
- }
- else if(mattr->type == TypeDesc::TypeFloat) {
- *attr_float_size += size;
- }
- else if(mattr->type == TypeFloat2) {
- *attr_float2_size += size;
- }
- else if(mattr->type == TypeDesc::TypeMatrix) {
- *attr_float3_size += size * 4;
- }
- else {
- *attr_float3_size += size;
- }
- }
+ if (mattr) {
+ size_t size = mattr->element_size(mesh, prim);
+
+ if (mattr->element == ATTR_ELEMENT_VOXEL) {
+ /* pass */
+ }
+ else if (mattr->element == ATTR_ELEMENT_CORNER_BYTE) {
+ *attr_uchar4_size += size;
+ }
+ else if (mattr->type == TypeDesc::TypeFloat) {
+ *attr_float_size += size;
+ }
+ else if (mattr->type == TypeFloat2) {
+ *attr_float2_size += size;
+ }
+ else if (mattr->type == TypeDesc::TypeMatrix) {
+ *attr_float3_size += size * 4;
+ }
+ else {
+ *attr_float3_size += size;
+ }
+ }
}
static void update_attribute_element_offset(Mesh *mesh,
- device_vector<float>& attr_float,
- size_t& attr_float_offset,
- device_vector<float2>& attr_float2,
- size_t& attr_float2_offset,
- device_vector<float4>& attr_float3,
- size_t& attr_float3_offset,
- device_vector<uchar4>& attr_uchar4,
- size_t& attr_uchar4_offset,
+ device_vector<float> &attr_float,
+ size_t &attr_float_offset,
+ device_vector<float2> &attr_float2,
+ size_t &attr_float2_offset,
+ device_vector<float4> &attr_float3,
+ size_t &attr_float3_offset,
+ device_vector<uchar4> &attr_uchar4,
+ size_t &attr_uchar4_offset,
Attribute *mattr,
AttributePrimitive prim,
- TypeDesc& type,
- AttributeDescriptor& desc)
-{
- if(mattr) {
- /* store element and type */
- desc.element = mattr->element;
- desc.flags = mattr->flags;
- type = mattr->type;
-
- /* store attribute data in arrays */
- size_t size = mattr->element_size(mesh, prim);
-
- AttributeElement& element = desc.element;
- int& offset = desc.offset;
-
- if(mattr->element == ATTR_ELEMENT_VOXEL) {
- /* store slot in offset value */
- VoxelAttribute *voxel_data = mattr->data_voxel();
- offset = voxel_data->slot;
- }
- else if(mattr->element == ATTR_ELEMENT_CORNER_BYTE) {
- uchar4 *data = mattr->data_uchar4();
- offset = attr_uchar4_offset;
-
- assert(attr_uchar4.size() >= offset + size);
- for(size_t k = 0; k < size; k++) {
- attr_uchar4[offset+k] = data[k];
- }
- attr_uchar4_offset += size;
- }
- else if(mattr->type == TypeDesc::TypeFloat) {
- float *data = mattr->data_float();
- offset = attr_float_offset;
-
- assert(attr_float.size() >= offset + size);
- for(size_t k = 0; k < size; k++) {
- attr_float[offset+k] = data[k];
- }
- attr_float_offset += size;
- }
- else if(mattr->type == TypeFloat2) {
- float2 *data = mattr->data_float2();
- offset = attr_float2_offset;
-
- assert(attr_float2.size() >= offset + size);
- for(size_t k = 0; k < size; k++) {
- attr_float2[offset+k] = data[k];
- }
- attr_float2_offset += size;
- }
- else if(mattr->type == TypeDesc::TypeMatrix) {
- Transform *tfm = mattr->data_transform();
- offset = attr_float3_offset;
-
- assert(attr_float3.size() >= offset + size * 3);
- for(size_t k = 0; k < size*3; k++) {
- attr_float3[offset+k] = (&tfm->x)[k];
- }
- attr_float3_offset += size * 3;
- }
- else {
- float4 *data = mattr->data_float4();
- offset = attr_float3_offset;
-
- assert(attr_float3.size() >= offset + size);
- for(size_t k = 0; k < size; k++) {
- attr_float3[offset+k] = data[k];
- }
- attr_float3_offset += size;
- }
-
- /* mesh vertex/curve index is global, not per object, so we sneak
- * a correction for that in here */
- if(mesh->subdivision_type == Mesh::SUBDIVISION_CATMULL_CLARK && desc.flags & ATTR_SUBDIVIDED) {
- /* indices for subdivided attributes are retrieved
- * from patch table so no need for correction here*/
- }
- else if(element == ATTR_ELEMENT_VERTEX)
- offset -= mesh->vert_offset;
- else if(element == ATTR_ELEMENT_VERTEX_MOTION)
- offset -= mesh->vert_offset;
- else if(element == ATTR_ELEMENT_FACE) {
- if(prim == ATTR_PRIM_TRIANGLE)
- offset -= mesh->tri_offset;
- else
- offset -= mesh->face_offset;
- }
- else if(element == ATTR_ELEMENT_CORNER || element == ATTR_ELEMENT_CORNER_BYTE) {
- if(prim == ATTR_PRIM_TRIANGLE)
- offset -= 3*mesh->tri_offset;
- else
- offset -= mesh->corner_offset;
- }
- else if(element == ATTR_ELEMENT_CURVE)
- offset -= mesh->curve_offset;
- else if(element == ATTR_ELEMENT_CURVE_KEY)
- offset -= mesh->curvekey_offset;
- else if(element == ATTR_ELEMENT_CURVE_KEY_MOTION)
- offset -= mesh->curvekey_offset;
- }
- else {
- /* attribute not found */
- desc.element = ATTR_ELEMENT_NONE;
- desc.offset = 0;
- }
-}
-
-void MeshManager::device_update_attributes(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress)
-{
- progress.set_status("Updating Mesh", "Computing attributes");
-
- /* gather per mesh requested attributes. as meshes may have multiple
- * shaders assigned, this merges the requested attributes that have
- * been set per shader by the shader manager */
- vector<AttributeRequestSet> mesh_attributes(scene->meshes.size());
-
- for(size_t i = 0; i < scene->meshes.size(); i++) {
- Mesh *mesh = scene->meshes[i];
-
- scene->need_global_attributes(mesh_attributes[i]);
-
- foreach(Shader *shader, mesh->used_shaders) {
- mesh_attributes[i].add(shader->attributes);
- }
- }
-
- /* mesh attribute are stored in a single array per data type. here we fill
- * those arrays, and set the offset and element type to create attribute
- * maps next */
-
- /* Pre-allocate attributes to avoid arrays re-allocation which would
- * take 2x of overall attribute memory usage.
- */
- size_t attr_float_size = 0;
- size_t attr_float2_size = 0;
- size_t attr_float3_size = 0;
- size_t attr_uchar4_size = 0;
- for(size_t i = 0; i < scene->meshes.size(); i++) {
- Mesh *mesh = scene->meshes[i];
- AttributeRequestSet& attributes = mesh_attributes[i];
- foreach(AttributeRequest& req, attributes.requests) {
- Attribute *triangle_mattr = mesh->attributes.find(req);
- Attribute *curve_mattr = mesh->curve_attributes.find(req);
- Attribute *subd_mattr = mesh->subd_attributes.find(req);
-
- update_attribute_element_size(mesh,
- triangle_mattr,
- ATTR_PRIM_TRIANGLE,
- &attr_float_size,
- &attr_float2_size,
- &attr_float3_size,
- &attr_uchar4_size);
- update_attribute_element_size(mesh,
- curve_mattr,
- ATTR_PRIM_CURVE,
- &attr_float_size,
- &attr_float2_size,
- &attr_float3_size,
- &attr_uchar4_size);
- update_attribute_element_size(mesh,
- subd_mattr,
- ATTR_PRIM_SUBD,
- &attr_float_size,
- &attr_float2_size,
- &attr_float3_size,
- &attr_uchar4_size);
- }
- }
-
- dscene->attributes_float.alloc(attr_float_size);
- dscene->attributes_float2.alloc(attr_float2_size);
- dscene->attributes_float3.alloc(attr_float3_size);
- dscene->attributes_uchar4.alloc(attr_uchar4_size);
-
- size_t attr_float_offset = 0;
- size_t attr_float2_offset = 0;
- size_t attr_float3_offset = 0;
- size_t attr_uchar4_offset = 0;
-
- /* Fill in attributes. */
- for(size_t i = 0; i < scene->meshes.size(); i++) {
- Mesh *mesh = scene->meshes[i];
- AttributeRequestSet& attributes = mesh_attributes[i];
-
- /* todo: we now store std and name attributes from requests even if
- * they actually refer to the same mesh attributes, optimize */
- foreach(AttributeRequest& req, attributes.requests) {
- Attribute *triangle_mattr = mesh->attributes.find(req);
- Attribute *curve_mattr = mesh->curve_attributes.find(req);
- Attribute *subd_mattr = mesh->subd_attributes.find(req);
-
- update_attribute_element_offset(mesh,
- dscene->attributes_float, attr_float_offset,
- dscene->attributes_float2, attr_float2_offset,
- dscene->attributes_float3, attr_float3_offset,
- dscene->attributes_uchar4, attr_uchar4_offset,
- triangle_mattr,
- ATTR_PRIM_TRIANGLE,
- req.triangle_type,
- req.triangle_desc);
-
- update_attribute_element_offset(mesh,
- dscene->attributes_float, attr_float_offset,
- dscene->attributes_float2, attr_float2_offset,
- dscene->attributes_float3, attr_float3_offset,
- dscene->attributes_uchar4, attr_uchar4_offset,
- curve_mattr,
- ATTR_PRIM_CURVE,
- req.curve_type,
- req.curve_desc);
-
- update_attribute_element_offset(mesh,
- dscene->attributes_float, attr_float_offset,
- dscene->attributes_float2, attr_float2_offset,
- dscene->attributes_float3, attr_float3_offset,
- dscene->attributes_uchar4, attr_uchar4_offset,
- subd_mattr,
- ATTR_PRIM_SUBD,
- req.subd_type,
- req.subd_desc);
-
- if(progress.get_cancel()) return;
- }
- }
-
- /* create attribute lookup maps */
- if(scene->shader_manager->use_osl())
- update_osl_attributes(device, scene, mesh_attributes);
-
- update_svm_attributes(device, dscene, scene, mesh_attributes);
-
- if(progress.get_cancel()) return;
-
- /* copy to device */
- progress.set_status("Updating Mesh", "Copying Attributes to device");
-
- if(dscene->attributes_float.size()) {
- dscene->attributes_float.copy_to_device();
- }
- if(dscene->attributes_float2.size()) {
- dscene->attributes_float2.copy_to_device();
- }
- if(dscene->attributes_float3.size()) {
- dscene->attributes_float3.copy_to_device();
- }
- if(dscene->attributes_uchar4.size()) {
- dscene->attributes_uchar4.copy_to_device();
- }
-
- if(progress.get_cancel()) return;
-
- /* After mesh attributes and patch tables have been copied to device memory,
- * we need to update offsets in the objects. */
- scene->object_manager->device_update_mesh_offsets(device, dscene, scene);
+ TypeDesc &type,
+ AttributeDescriptor &desc)
+{
+ if (mattr) {
+ /* store element and type */
+ desc.element = mattr->element;
+ desc.flags = mattr->flags;
+ type = mattr->type;
+
+ /* store attribute data in arrays */
+ size_t size = mattr->element_size(mesh, prim);
+
+ AttributeElement &element = desc.element;
+ int &offset = desc.offset;
+
+ if (mattr->element == ATTR_ELEMENT_VOXEL) {
+ /* store slot in offset value */
+ VoxelAttribute *voxel_data = mattr->data_voxel();
+ offset = voxel_data->slot;
+ }
+ else if (mattr->element == ATTR_ELEMENT_CORNER_BYTE) {
+ uchar4 *data = mattr->data_uchar4();
+ offset = attr_uchar4_offset;
+
+ assert(attr_uchar4.size() >= offset + size);
+ for (size_t k = 0; k < size; k++) {
+ attr_uchar4[offset + k] = data[k];
+ }
+ attr_uchar4_offset += size;
+ }
+ else if (mattr->type == TypeDesc::TypeFloat) {
+ float *data = mattr->data_float();
+ offset = attr_float_offset;
+
+ assert(attr_float.size() >= offset + size);
+ for (size_t k = 0; k < size; k++) {
+ attr_float[offset + k] = data[k];
+ }
+ attr_float_offset += size;
+ }
+ else if (mattr->type == TypeFloat2) {
+ float2 *data = mattr->data_float2();
+ offset = attr_float2_offset;
+
+ assert(attr_float2.size() >= offset + size);
+ for (size_t k = 0; k < size; k++) {
+ attr_float2[offset + k] = data[k];
+ }
+ attr_float2_offset += size;
+ }
+ else if (mattr->type == TypeDesc::TypeMatrix) {
+ Transform *tfm = mattr->data_transform();
+ offset = attr_float3_offset;
+
+ assert(attr_float3.size() >= offset + size * 3);
+ for (size_t k = 0; k < size * 3; k++) {
+ attr_float3[offset + k] = (&tfm->x)[k];
+ }
+ attr_float3_offset += size * 3;
+ }
+ else {
+ float4 *data = mattr->data_float4();
+ offset = attr_float3_offset;
+
+ assert(attr_float3.size() >= offset + size);
+ for (size_t k = 0; k < size; k++) {
+ attr_float3[offset + k] = data[k];
+ }
+ attr_float3_offset += size;
+ }
+
+ /* mesh vertex/curve index is global, not per object, so we sneak
+ * a correction for that in here */
+ if (mesh->subdivision_type == Mesh::SUBDIVISION_CATMULL_CLARK &&
+ desc.flags & ATTR_SUBDIVIDED) {
+ /* indices for subdivided attributes are retrieved
+ * from patch table so no need for correction here*/
+ }
+ else if (element == ATTR_ELEMENT_VERTEX)
+ offset -= mesh->vert_offset;
+ else if (element == ATTR_ELEMENT_VERTEX_MOTION)
+ offset -= mesh->vert_offset;
+ else if (element == ATTR_ELEMENT_FACE) {
+ if (prim == ATTR_PRIM_TRIANGLE)
+ offset -= mesh->tri_offset;
+ else
+ offset -= mesh->face_offset;
+ }
+ else if (element == ATTR_ELEMENT_CORNER || element == ATTR_ELEMENT_CORNER_BYTE) {
+ if (prim == ATTR_PRIM_TRIANGLE)
+ offset -= 3 * mesh->tri_offset;
+ else
+ offset -= mesh->corner_offset;
+ }
+ else if (element == ATTR_ELEMENT_CURVE)
+ offset -= mesh->curve_offset;
+ else if (element == ATTR_ELEMENT_CURVE_KEY)
+ offset -= mesh->curvekey_offset;
+ else if (element == ATTR_ELEMENT_CURVE_KEY_MOTION)
+ offset -= mesh->curvekey_offset;
+ }
+ else {
+ /* attribute not found */
+ desc.element = ATTR_ELEMENT_NONE;
+ desc.offset = 0;
+ }
+}
+
+void MeshManager::device_update_attributes(Device *device,
+ DeviceScene *dscene,
+ Scene *scene,
+ Progress &progress)
+{
+ progress.set_status("Updating Mesh", "Computing attributes");
+
+ /* gather per mesh requested attributes. as meshes may have multiple
+ * shaders assigned, this merges the requested attributes that have
+ * been set per shader by the shader manager */
+ vector<AttributeRequestSet> mesh_attributes(scene->meshes.size());
+
+ for (size_t i = 0; i < scene->meshes.size(); i++) {
+ Mesh *mesh = scene->meshes[i];
+
+ scene->need_global_attributes(mesh_attributes[i]);
+
+ foreach (Shader *shader, mesh->used_shaders) {
+ mesh_attributes[i].add(shader->attributes);
+ }
+ }
+
+ /* mesh attribute are stored in a single array per data type. here we fill
+ * those arrays, and set the offset and element type to create attribute
+ * maps next */
+
+ /* Pre-allocate attributes to avoid arrays re-allocation which would
+ * take 2x of overall attribute memory usage.
+ */
+ size_t attr_float_size = 0;
+ size_t attr_float2_size = 0;
+ size_t attr_float3_size = 0;
+ size_t attr_uchar4_size = 0;
+ for (size_t i = 0; i < scene->meshes.size(); i++) {
+ Mesh *mesh = scene->meshes[i];
+ AttributeRequestSet &attributes = mesh_attributes[i];
+ foreach (AttributeRequest &req, attributes.requests) {
+ Attribute *triangle_mattr = mesh->attributes.find(req);
+ Attribute *curve_mattr = mesh->curve_attributes.find(req);
+ Attribute *subd_mattr = mesh->subd_attributes.find(req);
+
+ update_attribute_element_size(mesh,
+ triangle_mattr,
+ ATTR_PRIM_TRIANGLE,
+ &attr_float_size,
+ &attr_float2_size,
+ &attr_float3_size,
+ &attr_uchar4_size);
+ update_attribute_element_size(mesh,
+ curve_mattr,
+ ATTR_PRIM_CURVE,
+ &attr_float_size,
+ &attr_float2_size,
+ &attr_float3_size,
+ &attr_uchar4_size);
+ update_attribute_element_size(mesh,
+ subd_mattr,
+ ATTR_PRIM_SUBD,
+ &attr_float_size,
+ &attr_float2_size,
+ &attr_float3_size,
+ &attr_uchar4_size);
+ }
+ }
+
+ dscene->attributes_float.alloc(attr_float_size);
+ dscene->attributes_float2.alloc(attr_float2_size);
+ dscene->attributes_float3.alloc(attr_float3_size);
+ dscene->attributes_uchar4.alloc(attr_uchar4_size);
+
+ size_t attr_float_offset = 0;
+ size_t attr_float2_offset = 0;
+ size_t attr_float3_offset = 0;
+ size_t attr_uchar4_offset = 0;
+
+ /* Fill in attributes. */
+ for (size_t i = 0; i < scene->meshes.size(); i++) {
+ Mesh *mesh = scene->meshes[i];
+ AttributeRequestSet &attributes = mesh_attributes[i];
+
+ /* todo: we now store std and name attributes from requests even if
+ * they actually refer to the same mesh attributes, optimize */
+ foreach (AttributeRequest &req, attributes.requests) {
+ Attribute *triangle_mattr = mesh->attributes.find(req);
+ Attribute *curve_mattr = mesh->curve_attributes.find(req);
+ Attribute *subd_mattr = mesh->subd_attributes.find(req);
+
+ update_attribute_element_offset(mesh,
+ dscene->attributes_float,
+ attr_float_offset,
+ dscene->attributes_float2,
+ attr_float2_offset,
+ dscene->attributes_float3,
+ attr_float3_offset,
+ dscene->attributes_uchar4,
+ attr_uchar4_offset,
+ triangle_mattr,
+ ATTR_PRIM_TRIANGLE,
+ req.triangle_type,
+ req.triangle_desc);
+
+ update_attribute_element_offset(mesh,
+ dscene->attributes_float,
+ attr_float_offset,
+ dscene->attributes_float2,
+ attr_float2_offset,
+ dscene->attributes_float3,
+ attr_float3_offset,
+ dscene->attributes_uchar4,
+ attr_uchar4_offset,
+ curve_mattr,
+ ATTR_PRIM_CURVE,
+ req.curve_type,
+ req.curve_desc);
+
+ update_attribute_element_offset(mesh,
+ dscene->attributes_float,
+ attr_float_offset,
+ dscene->attributes_float2,
+ attr_float2_offset,
+ dscene->attributes_float3,
+ attr_float3_offset,
+ dscene->attributes_uchar4,
+ attr_uchar4_offset,
+ subd_mattr,
+ ATTR_PRIM_SUBD,
+ req.subd_type,
+ req.subd_desc);
+
+ if (progress.get_cancel())
+ return;
+ }
+ }
+
+ /* create attribute lookup maps */
+ if (scene->shader_manager->use_osl())
+ update_osl_attributes(device, scene, mesh_attributes);
+
+ update_svm_attributes(device, dscene, scene, mesh_attributes);
+
+ if (progress.get_cancel())
+ return;
+
+ /* copy to device */
+ progress.set_status("Updating Mesh", "Copying Attributes to device");
+
+ if (dscene->attributes_float.size()) {
+ dscene->attributes_float.copy_to_device();
+ }
+ if (dscene->attributes_float2.size()) {
+ dscene->attributes_float2.copy_to_device();
+ }
+ if (dscene->attributes_float3.size()) {
+ dscene->attributes_float3.copy_to_device();
+ }
+ if (dscene->attributes_uchar4.size()) {
+ dscene->attributes_uchar4.copy_to_device();
+ }
+
+ if (progress.get_cancel())
+ return;
+
+ /* After mesh attributes and patch tables have been copied to device memory,
+ * we need to update offsets in the objects. */
+ scene->object_manager->device_update_mesh_offsets(device, dscene, scene);
}
void MeshManager::mesh_calc_offset(Scene *scene)
{
- size_t vert_size = 0;
- size_t tri_size = 0;
-
- size_t curve_key_size = 0;
- size_t curve_size = 0;
-
- size_t patch_size = 0;
- size_t face_size = 0;
- size_t corner_size = 0;
-
- foreach(Mesh *mesh, scene->meshes) {
- mesh->vert_offset = vert_size;
- mesh->tri_offset = tri_size;
-
- mesh->curvekey_offset = curve_key_size;
- mesh->curve_offset = curve_size;
-
- mesh->patch_offset = patch_size;
- mesh->face_offset = face_size;
- mesh->corner_offset = corner_size;
-
- vert_size += mesh->verts.size();
- tri_size += mesh->num_triangles();
-
- curve_key_size += mesh->curve_keys.size();
- curve_size += mesh->num_curves();
-
- if(mesh->subd_faces.size()) {
- Mesh::SubdFace& last = mesh->subd_faces[mesh->subd_faces.size()-1];
- patch_size += (last.ptex_offset + last.num_ptex_faces()) * 8;
-
- /* patch tables are stored in same array so include them in patch_size */
- if(mesh->patch_table) {
- mesh->patch_table_offset = patch_size;
- patch_size += mesh->patch_table->total_size();
- }
- }
- face_size += mesh->subd_faces.size();
- corner_size += mesh->subd_face_corners.size();
- }
-}
-
-void MeshManager::device_update_mesh(Device *,
- DeviceScene *dscene,
- Scene *scene,
- bool for_displacement,
- Progress& progress)
-{
- /* Count. */
- size_t vert_size = 0;
- size_t tri_size = 0;
-
- size_t curve_key_size = 0;
- size_t curve_size = 0;
-
- size_t patch_size = 0;
-
- foreach(Mesh *mesh, scene->meshes) {
- vert_size += mesh->verts.size();
- tri_size += mesh->num_triangles();
-
- curve_key_size += mesh->curve_keys.size();
- curve_size += mesh->num_curves();
-
- if(mesh->subd_faces.size()) {
- Mesh::SubdFace& last = mesh->subd_faces[mesh->subd_faces.size()-1];
- patch_size += (last.ptex_offset + last.num_ptex_faces()) * 8;
-
- /* patch tables are stored in same array so include them in patch_size */
- if(mesh->patch_table) {
- mesh->patch_table_offset = patch_size;
- patch_size += mesh->patch_table->total_size();
- }
- }
- }
-
- /* Create mapping from triangle to primitive triangle array. */
- vector<uint> tri_prim_index(tri_size);
- if(for_displacement) {
- /* For displacement kernels we do some trickery to make them believe
- * we've got all required data ready. However, that data is different
- * from final render kernels since we don't have BVH yet, so can't
- * really use same semantic of arrays.
- */
- foreach(Mesh *mesh, scene->meshes) {
- for(size_t i = 0; i < mesh->num_triangles(); ++i) {
- tri_prim_index[i + mesh->tri_offset] = 3 * (i + mesh->tri_offset);
- }
- }
- }
- else {
- for(size_t i = 0; i < dscene->prim_index.size(); ++i) {
- if((dscene->prim_type[i] & PRIMITIVE_ALL_TRIANGLE) != 0) {
- tri_prim_index[dscene->prim_index[i]] = dscene->prim_tri_index[i];
- }
- }
- }
-
- /* Fill in all the arrays. */
- if(tri_size != 0) {
- /* normals */
- progress.set_status("Updating Mesh", "Computing normals");
-
- uint *tri_shader = dscene->tri_shader.alloc(tri_size);
- float4 *vnormal = dscene->tri_vnormal.alloc(vert_size);
- uint4 *tri_vindex = dscene->tri_vindex.alloc(tri_size);
- uint *tri_patch = dscene->tri_patch.alloc(tri_size);
- float2 *tri_patch_uv = dscene->tri_patch_uv.alloc(vert_size);
-
- foreach(Mesh *mesh, scene->meshes) {
- mesh->pack_shaders(scene,
- &tri_shader[mesh->tri_offset]);
- mesh->pack_normals(&vnormal[mesh->vert_offset]);
- mesh->pack_verts(tri_prim_index,
- &tri_vindex[mesh->tri_offset],
- &tri_patch[mesh->tri_offset],
- &tri_patch_uv[mesh->vert_offset],
- mesh->vert_offset,
- mesh->tri_offset);
- if(progress.get_cancel()) return;
- }
-
- /* vertex coordinates */
- progress.set_status("Updating Mesh", "Copying Mesh to device");
-
- dscene->tri_shader.copy_to_device();
- dscene->tri_vnormal.copy_to_device();
- dscene->tri_vindex.copy_to_device();
- dscene->tri_patch.copy_to_device();
- dscene->tri_patch_uv.copy_to_device();
- }
-
- if(curve_size != 0) {
- progress.set_status("Updating Mesh", "Copying Strands to device");
-
- float4 *curve_keys = dscene->curve_keys.alloc(curve_key_size);
- float4 *curves = dscene->curves.alloc(curve_size);
-
- foreach(Mesh *mesh, scene->meshes) {
- mesh->pack_curves(scene, &curve_keys[mesh->curvekey_offset], &curves[mesh->curve_offset], mesh->curvekey_offset);
- if(progress.get_cancel()) return;
- }
-
- dscene->curve_keys.copy_to_device();
- dscene->curves.copy_to_device();
- }
-
- if(patch_size != 0) {
- progress.set_status("Updating Mesh", "Copying Patches to device");
-
- uint *patch_data = dscene->patches.alloc(patch_size);
-
- foreach(Mesh *mesh, scene->meshes) {
- mesh->pack_patches(&patch_data[mesh->patch_offset], mesh->vert_offset, mesh->face_offset, mesh->corner_offset);
-
- if(mesh->patch_table) {
- mesh->patch_table->copy_adjusting_offsets(&patch_data[mesh->patch_table_offset], mesh->patch_table_offset);
- }
-
- if(progress.get_cancel()) return;
- }
-
- dscene->patches.copy_to_device();
- }
-
- if(for_displacement) {
- float4 *prim_tri_verts = dscene->prim_tri_verts.alloc(tri_size * 3);
- foreach(Mesh *mesh, scene->meshes) {
- for(size_t i = 0; i < mesh->num_triangles(); ++i) {
- Mesh::Triangle t = mesh->get_triangle(i);
- size_t offset = 3 * (i + mesh->tri_offset);
- prim_tri_verts[offset + 0] = float3_to_float4(mesh->verts[t.v[0]]);
- prim_tri_verts[offset + 1] = float3_to_float4(mesh->verts[t.v[1]]);
- prim_tri_verts[offset + 2] = float3_to_float4(mesh->verts[t.v[2]]);
- }
- }
- dscene->prim_tri_verts.copy_to_device();
- }
-}
-
-void MeshManager::device_update_bvh(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress)
-{
- /* bvh build */
- progress.set_status("Updating Scene BVH", "Building");
-
- BVHParams bparams;
- bparams.top_level = true;
- bparams.bvh_layout = BVHParams::best_bvh_layout(
- scene->params.bvh_layout,
- device->get_bvh_layout_mask());
- bparams.use_spatial_split = scene->params.use_bvh_spatial_split;
- bparams.use_unaligned_nodes = dscene->data.bvh.have_curves &&
- scene->params.use_bvh_unaligned_nodes;
- bparams.num_motion_triangle_steps = scene->params.num_bvh_time_steps;
- bparams.num_motion_curve_steps = scene->params.num_bvh_time_steps;
- bparams.bvh_type = scene->params.bvh_type;
- bparams.curve_flags = dscene->data.curve.curveflags;
- bparams.curve_subdivisions = dscene->data.curve.subdivisions;
-
- VLOG(1) << "Using " << bvh_layout_name(bparams.bvh_layout)
- << " layout.";
+ size_t vert_size = 0;
+ size_t tri_size = 0;
+
+ size_t curve_key_size = 0;
+ size_t curve_size = 0;
+
+ size_t patch_size = 0;
+ size_t face_size = 0;
+ size_t corner_size = 0;
+
+ foreach (Mesh *mesh, scene->meshes) {
+ mesh->vert_offset = vert_size;
+ mesh->tri_offset = tri_size;
+
+ mesh->curvekey_offset = curve_key_size;
+ mesh->curve_offset = curve_size;
+
+ mesh->patch_offset = patch_size;
+ mesh->face_offset = face_size;
+ mesh->corner_offset = corner_size;
+
+ vert_size += mesh->verts.size();
+ tri_size += mesh->num_triangles();
+
+ curve_key_size += mesh->curve_keys.size();
+ curve_size += mesh->num_curves();
+
+ if (mesh->subd_faces.size()) {
+ Mesh::SubdFace &last = mesh->subd_faces[mesh->subd_faces.size() - 1];
+ patch_size += (last.ptex_offset + last.num_ptex_faces()) * 8;
+
+ /* patch tables are stored in same array so include them in patch_size */
+ if (mesh->patch_table) {
+ mesh->patch_table_offset = patch_size;
+ patch_size += mesh->patch_table->total_size();
+ }
+ }
+ face_size += mesh->subd_faces.size();
+ corner_size += mesh->subd_face_corners.size();
+ }
+}
+
+void MeshManager::device_update_mesh(
+ Device *, DeviceScene *dscene, Scene *scene, bool for_displacement, Progress &progress)
+{
+ /* Count. */
+ size_t vert_size = 0;
+ size_t tri_size = 0;
+
+ size_t curve_key_size = 0;
+ size_t curve_size = 0;
+
+ size_t patch_size = 0;
+
+ foreach (Mesh *mesh, scene->meshes) {
+ vert_size += mesh->verts.size();
+ tri_size += mesh->num_triangles();
+
+ curve_key_size += mesh->curve_keys.size();
+ curve_size += mesh->num_curves();
+
+ if (mesh->subd_faces.size()) {
+ Mesh::SubdFace &last = mesh->subd_faces[mesh->subd_faces.size() - 1];
+ patch_size += (last.ptex_offset + last.num_ptex_faces()) * 8;
+
+ /* patch tables are stored in same array so include them in patch_size */
+ if (mesh->patch_table) {
+ mesh->patch_table_offset = patch_size;
+ patch_size += mesh->patch_table->total_size();
+ }
+ }
+ }
+
+ /* Create mapping from triangle to primitive triangle array. */
+ vector<uint> tri_prim_index(tri_size);
+ if (for_displacement) {
+ /* For displacement kernels we do some trickery to make them believe
+ * we've got all required data ready. However, that data is different
+ * from final render kernels since we don't have BVH yet, so can't
+ * really use same semantic of arrays.
+ */
+ foreach (Mesh *mesh, scene->meshes) {
+ for (size_t i = 0; i < mesh->num_triangles(); ++i) {
+ tri_prim_index[i + mesh->tri_offset] = 3 * (i + mesh->tri_offset);
+ }
+ }
+ }
+ else {
+ for (size_t i = 0; i < dscene->prim_index.size(); ++i) {
+ if ((dscene->prim_type[i] & PRIMITIVE_ALL_TRIANGLE) != 0) {
+ tri_prim_index[dscene->prim_index[i]] = dscene->prim_tri_index[i];
+ }
+ }
+ }
+
+ /* Fill in all the arrays. */
+ if (tri_size != 0) {
+ /* normals */
+ progress.set_status("Updating Mesh", "Computing normals");
+
+ uint *tri_shader = dscene->tri_shader.alloc(tri_size);
+ float4 *vnormal = dscene->tri_vnormal.alloc(vert_size);
+ uint4 *tri_vindex = dscene->tri_vindex.alloc(tri_size);
+ uint *tri_patch = dscene->tri_patch.alloc(tri_size);
+ float2 *tri_patch_uv = dscene->tri_patch_uv.alloc(vert_size);
+
+ foreach (Mesh *mesh, scene->meshes) {
+ mesh->pack_shaders(scene, &tri_shader[mesh->tri_offset]);
+ mesh->pack_normals(&vnormal[mesh->vert_offset]);
+ mesh->pack_verts(tri_prim_index,
+ &tri_vindex[mesh->tri_offset],
+ &tri_patch[mesh->tri_offset],
+ &tri_patch_uv[mesh->vert_offset],
+ mesh->vert_offset,
+ mesh->tri_offset);
+ if (progress.get_cancel())
+ return;
+ }
+
+ /* vertex coordinates */
+ progress.set_status("Updating Mesh", "Copying Mesh to device");
+
+ dscene->tri_shader.copy_to_device();
+ dscene->tri_vnormal.copy_to_device();
+ dscene->tri_vindex.copy_to_device();
+ dscene->tri_patch.copy_to_device();
+ dscene->tri_patch_uv.copy_to_device();
+ }
+
+ if (curve_size != 0) {
+ progress.set_status("Updating Mesh", "Copying Strands to device");
+
+ float4 *curve_keys = dscene->curve_keys.alloc(curve_key_size);
+ float4 *curves = dscene->curves.alloc(curve_size);
+
+ foreach (Mesh *mesh, scene->meshes) {
+ mesh->pack_curves(scene,
+ &curve_keys[mesh->curvekey_offset],
+ &curves[mesh->curve_offset],
+ mesh->curvekey_offset);
+ if (progress.get_cancel())
+ return;
+ }
+
+ dscene->curve_keys.copy_to_device();
+ dscene->curves.copy_to_device();
+ }
+
+ if (patch_size != 0) {
+ progress.set_status("Updating Mesh", "Copying Patches to device");
+
+ uint *patch_data = dscene->patches.alloc(patch_size);
+
+ foreach (Mesh *mesh, scene->meshes) {
+ mesh->pack_patches(&patch_data[mesh->patch_offset],
+ mesh->vert_offset,
+ mesh->face_offset,
+ mesh->corner_offset);
+
+ if (mesh->patch_table) {
+ mesh->patch_table->copy_adjusting_offsets(&patch_data[mesh->patch_table_offset],
+ mesh->patch_table_offset);
+ }
+
+ if (progress.get_cancel())
+ return;
+ }
+
+ dscene->patches.copy_to_device();
+ }
+
+ if (for_displacement) {
+ float4 *prim_tri_verts = dscene->prim_tri_verts.alloc(tri_size * 3);
+ foreach (Mesh *mesh, scene->meshes) {
+ for (size_t i = 0; i < mesh->num_triangles(); ++i) {
+ Mesh::Triangle t = mesh->get_triangle(i);
+ size_t offset = 3 * (i + mesh->tri_offset);
+ prim_tri_verts[offset + 0] = float3_to_float4(mesh->verts[t.v[0]]);
+ prim_tri_verts[offset + 1] = float3_to_float4(mesh->verts[t.v[1]]);
+ prim_tri_verts[offset + 2] = float3_to_float4(mesh->verts[t.v[2]]);
+ }
+ }
+ dscene->prim_tri_verts.copy_to_device();
+ }
+}
+
+void MeshManager::device_update_bvh(Device *device,
+ DeviceScene *dscene,
+ Scene *scene,
+ Progress &progress)
+{
+ /* bvh build */
+ progress.set_status("Updating Scene BVH", "Building");
+
+ BVHParams bparams;
+ bparams.top_level = true;
+ bparams.bvh_layout = BVHParams::best_bvh_layout(scene->params.bvh_layout,
+ device->get_bvh_layout_mask());
+ bparams.use_spatial_split = scene->params.use_bvh_spatial_split;
+ bparams.use_unaligned_nodes = dscene->data.bvh.have_curves &&
+ scene->params.use_bvh_unaligned_nodes;
+ bparams.num_motion_triangle_steps = scene->params.num_bvh_time_steps;
+ bparams.num_motion_curve_steps = scene->params.num_bvh_time_steps;
+ bparams.bvh_type = scene->params.bvh_type;
+ bparams.curve_flags = dscene->data.curve.curveflags;
+ bparams.curve_subdivisions = dscene->data.curve.subdivisions;
+
+ VLOG(1) << "Using " << bvh_layout_name(bparams.bvh_layout) << " layout.";
#ifdef WITH_EMBREE
- if(bparams.bvh_layout == BVH_LAYOUT_EMBREE) {
- if(dscene->data.bvh.scene) {
- BVHEmbree::destroy(dscene->data.bvh.scene);
- }
- }
+ if (bparams.bvh_layout == BVH_LAYOUT_EMBREE) {
+ if (dscene->data.bvh.scene) {
+ BVHEmbree::destroy(dscene->data.bvh.scene);
+ }
+ }
#endif
- BVH *bvh = BVH::create(bparams, scene->objects);
- bvh->build(progress, &device->stats);
+ BVH *bvh = BVH::create(bparams, scene->objects);
+ bvh->build(progress, &device->stats);
- if(progress.get_cancel()) {
+ if (progress.get_cancel()) {
#ifdef WITH_EMBREE
- if(bparams.bvh_layout == BVH_LAYOUT_EMBREE) {
- if(dscene->data.bvh.scene) {
- BVHEmbree::destroy(dscene->data.bvh.scene);
- }
- }
+ if (bparams.bvh_layout == BVH_LAYOUT_EMBREE) {
+ if (dscene->data.bvh.scene) {
+ BVHEmbree::destroy(dscene->data.bvh.scene);
+ }
+ }
#endif
- delete bvh;
- return;
- }
-
- /* copy to device */
- progress.set_status("Updating Scene BVH", "Copying BVH to device");
-
- PackedBVH& pack = bvh->pack;
-
- if(pack.nodes.size()) {
- dscene->bvh_nodes.steal_data(pack.nodes);
- dscene->bvh_nodes.copy_to_device();
- }
- if(pack.leaf_nodes.size()) {
- dscene->bvh_leaf_nodes.steal_data(pack.leaf_nodes);
- dscene->bvh_leaf_nodes.copy_to_device();
- }
- if(pack.object_node.size()) {
- dscene->object_node.steal_data(pack.object_node);
- dscene->object_node.copy_to_device();
- }
- if(pack.prim_tri_index.size()) {
- dscene->prim_tri_index.steal_data(pack.prim_tri_index);
- dscene->prim_tri_index.copy_to_device();
- }
- if(pack.prim_tri_verts.size()) {
- dscene->prim_tri_verts.steal_data(pack.prim_tri_verts);
- dscene->prim_tri_verts.copy_to_device();
- }
- if(pack.prim_type.size()) {
- dscene->prim_type.steal_data(pack.prim_type);
- dscene->prim_type.copy_to_device();
- }
- if(pack.prim_visibility.size()) {
- dscene->prim_visibility.steal_data(pack.prim_visibility);
- dscene->prim_visibility.copy_to_device();
- }
- if(pack.prim_index.size()) {
- dscene->prim_index.steal_data(pack.prim_index);
- dscene->prim_index.copy_to_device();
- }
- if(pack.prim_object.size()) {
- dscene->prim_object.steal_data(pack.prim_object);
- dscene->prim_object.copy_to_device();
- }
- if(pack.prim_time.size()) {
- dscene->prim_time.steal_data(pack.prim_time);
- dscene->prim_time.copy_to_device();
- }
-
- dscene->data.bvh.root = pack.root_index;
- dscene->data.bvh.bvh_layout = bparams.bvh_layout;
- dscene->data.bvh.use_bvh_steps = (scene->params.num_bvh_time_steps != 0);
-
+ delete bvh;
+ return;
+ }
+
+ /* copy to device */
+ progress.set_status("Updating Scene BVH", "Copying BVH to device");
+
+ PackedBVH &pack = bvh->pack;
+
+ if (pack.nodes.size()) {
+ dscene->bvh_nodes.steal_data(pack.nodes);
+ dscene->bvh_nodes.copy_to_device();
+ }
+ if (pack.leaf_nodes.size()) {
+ dscene->bvh_leaf_nodes.steal_data(pack.leaf_nodes);
+ dscene->bvh_leaf_nodes.copy_to_device();
+ }
+ if (pack.object_node.size()) {
+ dscene->object_node.steal_data(pack.object_node);
+ dscene->object_node.copy_to_device();
+ }
+ if (pack.prim_tri_index.size()) {
+ dscene->prim_tri_index.steal_data(pack.prim_tri_index);
+ dscene->prim_tri_index.copy_to_device();
+ }
+ if (pack.prim_tri_verts.size()) {
+ dscene->prim_tri_verts.steal_data(pack.prim_tri_verts);
+ dscene->prim_tri_verts.copy_to_device();
+ }
+ if (pack.prim_type.size()) {
+ dscene->prim_type.steal_data(pack.prim_type);
+ dscene->prim_type.copy_to_device();
+ }
+ if (pack.prim_visibility.size()) {
+ dscene->prim_visibility.steal_data(pack.prim_visibility);
+ dscene->prim_visibility.copy_to_device();
+ }
+ if (pack.prim_index.size()) {
+ dscene->prim_index.steal_data(pack.prim_index);
+ dscene->prim_index.copy_to_device();
+ }
+ if (pack.prim_object.size()) {
+ dscene->prim_object.steal_data(pack.prim_object);
+ dscene->prim_object.copy_to_device();
+ }
+ if (pack.prim_time.size()) {
+ dscene->prim_time.steal_data(pack.prim_time);
+ dscene->prim_time.copy_to_device();
+ }
+
+ dscene->data.bvh.root = pack.root_index;
+ dscene->data.bvh.bvh_layout = bparams.bvh_layout;
+ dscene->data.bvh.use_bvh_steps = (scene->params.num_bvh_time_steps != 0);
#ifdef WITH_EMBREE
- if(bparams.bvh_layout == BVH_LAYOUT_EMBREE) {
- dscene->data.bvh.scene = ((BVHEmbree*)bvh)->scene;
- }
- else {
- dscene->data.bvh.scene = NULL;
- }
+ if (bparams.bvh_layout == BVH_LAYOUT_EMBREE) {
+ dscene->data.bvh.scene = ((BVHEmbree *)bvh)->scene;
+ }
+ else {
+ dscene->data.bvh.scene = NULL;
+ }
#endif
- delete bvh;
+ delete bvh;
}
-void MeshManager::device_update_preprocess(Device *device,
- Scene *scene,
- Progress& progress)
+void MeshManager::device_update_preprocess(Device *device, Scene *scene, Progress &progress)
{
- if(!need_update && !need_flags_update) {
- return;
- }
+ if (!need_update && !need_flags_update) {
+ return;
+ }
- progress.set_status("Updating Meshes Flags");
+ progress.set_status("Updating Meshes Flags");
- /* Update flags. */
- bool volume_images_updated = false;
+ /* Update flags. */
+ bool volume_images_updated = false;
- foreach(Mesh *mesh, scene->meshes) {
- mesh->has_volume = false;
+ foreach (Mesh *mesh, scene->meshes) {
+ mesh->has_volume = false;
- foreach(const Shader *shader, mesh->used_shaders) {
- if(shader->has_volume) {
- mesh->has_volume = true;
- }
- if(shader->has_surface_bssrdf) {
- mesh->has_surface_bssrdf = true;
- }
- }
+ foreach (const Shader *shader, mesh->used_shaders) {
+ if (shader->has_volume) {
+ mesh->has_volume = true;
+ }
+ if (shader->has_surface_bssrdf) {
+ mesh->has_surface_bssrdf = true;
+ }
+ }
- if(need_update && mesh->has_volume) {
- /* Create volume meshes if there is voxel data. */
- bool has_voxel_attributes = false;
+ if (need_update && mesh->has_volume) {
+ /* Create volume meshes if there is voxel data. */
+ bool has_voxel_attributes = false;
- foreach(Attribute& attr, mesh->attributes.attributes) {
- if(attr.element == ATTR_ELEMENT_VOXEL) {
- has_voxel_attributes = true;
- }
- }
+ foreach (Attribute &attr, mesh->attributes.attributes) {
+ if (attr.element == ATTR_ELEMENT_VOXEL) {
+ has_voxel_attributes = true;
+ }
+ }
- if(has_voxel_attributes) {
- if(!volume_images_updated) {
- progress.set_status("Updating Meshes Volume Bounds");
- device_update_volume_images(device, scene, progress);
- volume_images_updated = true;
- }
+ if (has_voxel_attributes) {
+ if (!volume_images_updated) {
+ progress.set_status("Updating Meshes Volume Bounds");
+ device_update_volume_images(device, scene, progress);
+ volume_images_updated = true;
+ }
- create_volume_mesh(scene, mesh, progress);
- }
- }
- }
+ create_volume_mesh(scene, mesh, progress);
+ }
+ }
+ }
- need_flags_update = false;
+ need_flags_update = false;
}
void MeshManager::device_update_displacement_images(Device *device,
Scene *scene,
- Progress& progress)
-{
- progress.set_status("Updating Displacement Images");
- TaskPool pool;
- ImageManager *image_manager = scene->image_manager;
- set<int> bump_images;
- foreach(Mesh *mesh, scene->meshes) {
- if(mesh->need_update) {
- foreach(Shader *shader, mesh->used_shaders) {
- if(!shader->has_displacement || shader->displacement_method == DISPLACE_BUMP) {
- continue;
- }
- foreach(ShaderNode* node, shader->graph->nodes) {
- if(node->special_type != SHADER_SPECIAL_TYPE_IMAGE_SLOT) {
- continue;
- }
-
- ImageSlotTextureNode *image_node = static_cast<ImageSlotTextureNode*>(node);
- int slot = image_node->slot;
- if(slot != -1) {
- bump_images.insert(slot);
- }
- }
- }
- }
- }
- foreach(int slot, bump_images) {
- pool.push(function_bind(&ImageManager::device_update_slot,
- image_manager,
- device,
- scene,
- slot,
- &progress));
- }
- pool.wait_work();
-}
-
-void MeshManager::device_update_volume_images(Device *device,
- Scene *scene,
- Progress& progress)
-{
- progress.set_status("Updating Volume Images");
- TaskPool pool;
- ImageManager *image_manager = scene->image_manager;
- set<int> volume_images;
-
- foreach(Mesh *mesh, scene->meshes) {
- if(!mesh->need_update) {
- continue;
- }
-
- foreach(Attribute& attr, mesh->attributes.attributes) {
- if(attr.element != ATTR_ELEMENT_VOXEL) {
- continue;
- }
-
- VoxelAttribute *voxel = attr.data_voxel();
-
- if(voxel->slot != -1) {
- volume_images.insert(voxel->slot);
- }
- }
- }
-
- foreach(int slot, volume_images) {
- pool.push(function_bind(&ImageManager::device_update_slot,
- image_manager,
- device,
- scene,
- slot,
- &progress));
- }
- pool.wait_work();
-}
-
-void MeshManager::device_update(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress)
-{
- if(!need_update)
- return;
-
- VLOG(1) << "Total " << scene->meshes.size() << " meshes.";
-
- bool true_displacement_used = false;
- size_t total_tess_needed = 0;
-
- foreach(Mesh *mesh, scene->meshes) {
- foreach(Shader *shader, mesh->used_shaders) {
- if(shader->need_update_mesh)
- mesh->need_update = true;
- }
-
- if(mesh->need_update) {
- /* Update normals. */
- mesh->add_face_normals();
- mesh->add_vertex_normals();
-
- if(mesh->need_attribute(scene, ATTR_STD_POSITION_UNDISPLACED)) {
- mesh->add_undisplaced();
- }
-
- /* Test if we need tessellation. */
- if(mesh->subdivision_type != Mesh::SUBDIVISION_NONE &&
- mesh->num_subd_verts == 0 &&
- mesh->subd_params)
- {
- total_tess_needed++;
- }
-
- /* Test if we need displacement. */
- if(mesh->has_true_displacement()) {
- true_displacement_used = true;
- }
-
- if(progress.get_cancel()) return;
- }
- }
-
- /* Tessellate meshes that are using subdivision */
- if(total_tess_needed) {
- Camera *dicing_camera = scene->dicing_camera;
- dicing_camera->update(scene);
-
- size_t i = 0;
- foreach(Mesh *mesh, scene->meshes) {
- if(mesh->need_update &&
- mesh->subdivision_type != Mesh::SUBDIVISION_NONE &&
- mesh->num_subd_verts == 0 &&
- mesh->subd_params)
- {
- string msg = "Tessellating ";
- if(mesh->name == "")
- msg += string_printf("%u/%u", (uint)(i+1), (uint)total_tess_needed);
- else
- msg += string_printf("%s %u/%u", mesh->name.c_str(), (uint)(i+1), (uint)total_tess_needed);
-
- progress.set_status("Updating Mesh", msg);
-
- mesh->subd_params->camera = dicing_camera;
- DiagSplit dsplit(*mesh->subd_params);
- mesh->tessellate(&dsplit);
-
- i++;
-
- if(progress.get_cancel()) return;
- }
-
- }
- }
-
- /* Update images needed for true displacement. */
- bool old_need_object_flags_update = false;
- if(true_displacement_used) {
- VLOG(1) << "Updating images used for true displacement.";
- device_update_displacement_images(device, scene, progress);
- old_need_object_flags_update = scene->object_manager->need_flags_update;
- scene->object_manager->device_update_flags(device,
- dscene,
- scene,
- progress,
- false);
- }
-
- /* Device update. */
- device_free(device, dscene);
-
- mesh_calc_offset(scene);
- if(true_displacement_used) {
- device_update_mesh(device, dscene, scene, true, progress);
- }
- if(progress.get_cancel()) return;
-
- device_update_attributes(device, dscene, scene, progress);
- if(progress.get_cancel()) return;
-
- /* Update displacement. */
- bool displacement_done = false;
- size_t num_bvh = 0;
-
- foreach(Mesh *mesh, scene->meshes) {
- if(mesh->need_update) {
- if(displace(device, dscene, scene, mesh, progress)) {
- displacement_done = true;
- }
-
- if(mesh->need_build_bvh()) {
- num_bvh++;
- }
- }
-
- if(progress.get_cancel()) return;
- }
-
- /* Device re-update after displacement. */
- if(displacement_done) {
- device_free(device, dscene);
-
- device_update_attributes(device, dscene, scene, progress);
- if(progress.get_cancel()) return;
- }
-
- TaskPool pool;
-
- size_t i = 0;
- foreach(Mesh *mesh, scene->meshes) {
- if(mesh->need_update) {
- pool.push(function_bind(&Mesh::compute_bvh,
- mesh,
- device,
- dscene,
- &scene->params,
- &progress,
- i,
- num_bvh));
- if(mesh->need_build_bvh()) {
- i++;
- }
- }
- }
-
- TaskPool::Summary summary;
- pool.wait_work(&summary);
- VLOG(2) << "Objects BVH build pool statistics:\n"
- << summary.full_report();
-
- foreach(Shader *shader, scene->shaders) {
- shader->need_update_mesh = false;
- }
-
- Scene::MotionType need_motion = scene->need_motion();
- bool motion_blur = need_motion == Scene::MOTION_BLUR;
-
- /* Update objects. */
- vector<Object *> volume_objects;
- foreach(Object *object, scene->objects) {
- object->compute_bounds(motion_blur);
- }
-
- if(progress.get_cancel()) return;
-
- device_update_bvh(device, dscene, scene, progress);
- if(progress.get_cancel()) return;
-
- device_update_mesh(device, dscene, scene, false, progress);
- if(progress.get_cancel()) return;
-
- need_update = false;
-
- if(true_displacement_used) {
- /* Re-tag flags for update, so they're re-evaluated
- * for meshes with correct bounding boxes.
- *
- * This wouldn't cause wrong results, just true
- * displacement might be less optimal ot calculate.
- */
- scene->object_manager->need_flags_update = old_need_object_flags_update;
- }
+ Progress &progress)
+{
+ progress.set_status("Updating Displacement Images");
+ TaskPool pool;
+ ImageManager *image_manager = scene->image_manager;
+ set<int> bump_images;
+ foreach (Mesh *mesh, scene->meshes) {
+ if (mesh->need_update) {
+ foreach (Shader *shader, mesh->used_shaders) {
+ if (!shader->has_displacement || shader->displacement_method == DISPLACE_BUMP) {
+ continue;
+ }
+ foreach (ShaderNode *node, shader->graph->nodes) {
+ if (node->special_type != SHADER_SPECIAL_TYPE_IMAGE_SLOT) {
+ continue;
+ }
+
+ ImageSlotTextureNode *image_node = static_cast<ImageSlotTextureNode *>(node);
+ int slot = image_node->slot;
+ if (slot != -1) {
+ bump_images.insert(slot);
+ }
+ }
+ }
+ }
+ }
+ foreach (int slot, bump_images) {
+ pool.push(function_bind(
+ &ImageManager::device_update_slot, image_manager, device, scene, slot, &progress));
+ }
+ pool.wait_work();
+}
+
+void MeshManager::device_update_volume_images(Device *device, Scene *scene, Progress &progress)
+{
+ progress.set_status("Updating Volume Images");
+ TaskPool pool;
+ ImageManager *image_manager = scene->image_manager;
+ set<int> volume_images;
+
+ foreach (Mesh *mesh, scene->meshes) {
+ if (!mesh->need_update) {
+ continue;
+ }
+
+ foreach (Attribute &attr, mesh->attributes.attributes) {
+ if (attr.element != ATTR_ELEMENT_VOXEL) {
+ continue;
+ }
+
+ VoxelAttribute *voxel = attr.data_voxel();
+
+ if (voxel->slot != -1) {
+ volume_images.insert(voxel->slot);
+ }
+ }
+ }
+
+ foreach (int slot, volume_images) {
+ pool.push(function_bind(
+ &ImageManager::device_update_slot, image_manager, device, scene, slot, &progress));
+ }
+ pool.wait_work();
+}
+
+void MeshManager::device_update(Device *device,
+ DeviceScene *dscene,
+ Scene *scene,
+ Progress &progress)
+{
+ if (!need_update)
+ return;
+
+ VLOG(1) << "Total " << scene->meshes.size() << " meshes.";
+
+ bool true_displacement_used = false;
+ size_t total_tess_needed = 0;
+
+ foreach (Mesh *mesh, scene->meshes) {
+ foreach (Shader *shader, mesh->used_shaders) {
+ if (shader->need_update_mesh)
+ mesh->need_update = true;
+ }
+
+ if (mesh->need_update) {
+ /* Update normals. */
+ mesh->add_face_normals();
+ mesh->add_vertex_normals();
+
+ if (mesh->need_attribute(scene, ATTR_STD_POSITION_UNDISPLACED)) {
+ mesh->add_undisplaced();
+ }
+
+ /* Test if we need tessellation. */
+ if (mesh->subdivision_type != Mesh::SUBDIVISION_NONE && mesh->num_subd_verts == 0 &&
+ mesh->subd_params) {
+ total_tess_needed++;
+ }
+
+ /* Test if we need displacement. */
+ if (mesh->has_true_displacement()) {
+ true_displacement_used = true;
+ }
+
+ if (progress.get_cancel())
+ return;
+ }
+ }
+
+ /* Tessellate meshes that are using subdivision */
+ if (total_tess_needed) {
+ Camera *dicing_camera = scene->dicing_camera;
+ dicing_camera->update(scene);
+
+ size_t i = 0;
+ foreach (Mesh *mesh, scene->meshes) {
+ if (mesh->need_update && mesh->subdivision_type != Mesh::SUBDIVISION_NONE &&
+ mesh->num_subd_verts == 0 && mesh->subd_params) {
+ string msg = "Tessellating ";
+ if (mesh->name == "")
+ msg += string_printf("%u/%u", (uint)(i + 1), (uint)total_tess_needed);
+ else
+ msg += string_printf(
+ "%s %u/%u", mesh->name.c_str(), (uint)(i + 1), (uint)total_tess_needed);
+
+ progress.set_status("Updating Mesh", msg);
+
+ mesh->subd_params->camera = dicing_camera;
+ DiagSplit dsplit(*mesh->subd_params);
+ mesh->tessellate(&dsplit);
+
+ i++;
+
+ if (progress.get_cancel())
+ return;
+ }
+ }
+ }
+
+ /* Update images needed for true displacement. */
+ bool old_need_object_flags_update = false;
+ if (true_displacement_used) {
+ VLOG(1) << "Updating images used for true displacement.";
+ device_update_displacement_images(device, scene, progress);
+ old_need_object_flags_update = scene->object_manager->need_flags_update;
+ scene->object_manager->device_update_flags(device, dscene, scene, progress, false);
+ }
+
+ /* Device update. */
+ device_free(device, dscene);
+
+ mesh_calc_offset(scene);
+ if (true_displacement_used) {
+ device_update_mesh(device, dscene, scene, true, progress);
+ }
+ if (progress.get_cancel())
+ return;
+
+ device_update_attributes(device, dscene, scene, progress);
+ if (progress.get_cancel())
+ return;
+
+ /* Update displacement. */
+ bool displacement_done = false;
+ size_t num_bvh = 0;
+
+ foreach (Mesh *mesh, scene->meshes) {
+ if (mesh->need_update) {
+ if (displace(device, dscene, scene, mesh, progress)) {
+ displacement_done = true;
+ }
+
+ if (mesh->need_build_bvh()) {
+ num_bvh++;
+ }
+ }
+
+ if (progress.get_cancel())
+ return;
+ }
+
+ /* Device re-update after displacement. */
+ if (displacement_done) {
+ device_free(device, dscene);
+
+ device_update_attributes(device, dscene, scene, progress);
+ if (progress.get_cancel())
+ return;
+ }
+
+ TaskPool pool;
+
+ size_t i = 0;
+ foreach (Mesh *mesh, scene->meshes) {
+ if (mesh->need_update) {
+ pool.push(function_bind(
+ &Mesh::compute_bvh, mesh, device, dscene, &scene->params, &progress, i, num_bvh));
+ if (mesh->need_build_bvh()) {
+ i++;
+ }
+ }
+ }
+
+ TaskPool::Summary summary;
+ pool.wait_work(&summary);
+ VLOG(2) << "Objects BVH build pool statistics:\n" << summary.full_report();
+
+ foreach (Shader *shader, scene->shaders) {
+ shader->need_update_mesh = false;
+ }
+
+ Scene::MotionType need_motion = scene->need_motion();
+ bool motion_blur = need_motion == Scene::MOTION_BLUR;
+
+ /* Update objects. */
+ vector<Object *> volume_objects;
+ foreach (Object *object, scene->objects) {
+ object->compute_bounds(motion_blur);
+ }
+
+ if (progress.get_cancel())
+ return;
+
+ device_update_bvh(device, dscene, scene, progress);
+ if (progress.get_cancel())
+ return;
+
+ device_update_mesh(device, dscene, scene, false, progress);
+ if (progress.get_cancel())
+ return;
+
+ need_update = false;
+
+ if (true_displacement_used) {
+ /* Re-tag flags for update, so they're re-evaluated
+ * for meshes with correct bounding boxes.
+ *
+ * This wouldn't cause wrong results, just true
+ * displacement might be less optimal ot calculate.
+ */
+ scene->object_manager->need_flags_update = old_need_object_flags_update;
+ }
}
void MeshManager::device_free(Device *device, DeviceScene *dscene)
{
- dscene->bvh_nodes.free();
- dscene->bvh_leaf_nodes.free();
- dscene->object_node.free();
- dscene->prim_tri_verts.free();
- dscene->prim_tri_index.free();
- dscene->prim_type.free();
- dscene->prim_visibility.free();
- dscene->prim_index.free();
- dscene->prim_object.free();
- dscene->prim_time.free();
- dscene->tri_shader.free();
- dscene->tri_vnormal.free();
- dscene->tri_vindex.free();
- dscene->tri_patch.free();
- dscene->tri_patch_uv.free();
- dscene->curves.free();
- dscene->curve_keys.free();
- dscene->patches.free();
- dscene->attributes_map.free();
- dscene->attributes_float.free();
- dscene->attributes_float2.free();
- dscene->attributes_float3.free();
- dscene->attributes_uchar4.free();
+ dscene->bvh_nodes.free();
+ dscene->bvh_leaf_nodes.free();
+ dscene->object_node.free();
+ dscene->prim_tri_verts.free();
+ dscene->prim_tri_index.free();
+ dscene->prim_type.free();
+ dscene->prim_visibility.free();
+ dscene->prim_index.free();
+ dscene->prim_object.free();
+ dscene->prim_time.free();
+ dscene->tri_shader.free();
+ dscene->tri_vnormal.free();
+ dscene->tri_vindex.free();
+ dscene->tri_patch.free();
+ dscene->tri_patch_uv.free();
+ dscene->curves.free();
+ dscene->curve_keys.free();
+ dscene->patches.free();
+ dscene->attributes_map.free();
+ dscene->attributes_float.free();
+ dscene->attributes_float2.free();
+ dscene->attributes_float3.free();
+ dscene->attributes_uchar4.free();
#ifdef WITH_OSL
- OSLGlobals *og = (OSLGlobals*)device->osl_memory();
+ OSLGlobals *og = (OSLGlobals *)device->osl_memory();
- if(og) {
- og->object_name_map.clear();
- og->attribute_map.clear();
- og->object_names.clear();
- }
+ if (og) {
+ og->object_name_map.clear();
+ og->attribute_map.clear();
+ og->object_names.clear();
+ }
#else
- (void) device;
+ (void)device;
#endif
}
void MeshManager::tag_update(Scene *scene)
{
- need_update = true;
- scene->object_manager->need_update = true;
+ need_update = true;
+ scene->object_manager->need_update = true;
}
void MeshManager::collect_statistics(const Scene *scene, RenderStats *stats)
{
- foreach(Mesh *mesh, scene->meshes) {
- stats->mesh.geometry.add_entry(
- NamedSizeEntry(string(mesh->name.c_str()),
- mesh->get_total_size_in_bytes()));
- }
+ foreach (Mesh *mesh, scene->meshes) {
+ stats->mesh.geometry.add_entry(
+ NamedSizeEntry(string(mesh->name.c_str()), mesh->get_total_size_in_bytes()));
+ }
}
bool Mesh::need_attribute(Scene *scene, AttributeStandard std)
{
- if(std == ATTR_STD_NONE)
- return false;
+ if (std == ATTR_STD_NONE)
+ return false;
- if(scene->need_global_attribute(std))
- return true;
+ if (scene->need_global_attribute(std))
+ return true;
- foreach(Shader *shader, used_shaders)
- if(shader->attributes.find(std))
- return true;
+ foreach (Shader *shader, used_shaders)
+ if (shader->attributes.find(std))
+ return true;
- return false;
+ return false;
}
bool Mesh::need_attribute(Scene * /*scene*/, ustring name)
{
- if(name == ustring())
- return false;
+ if (name == ustring())
+ return false;
- foreach(Shader *shader, used_shaders)
- if(shader->attributes.find(name))
- return true;
+ foreach (Shader *shader, used_shaders)
+ if (shader->attributes.find(name))
+ return true;
- return false;
+ return false;
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/render/mesh.h b/intern/cycles/render/mesh.h
index 789d1cc2b54..05c67ccb3b7 100644
--- a/intern/cycles/render/mesh.h
+++ b/intern/cycles/render/mesh.h
@@ -50,344 +50,352 @@ struct PackedPatchTable;
/* Mesh */
class Mesh : public Node {
-public:
- NODE_DECLARE
-
- /* Mesh Triangle */
- struct Triangle {
- int v[3];
-
- void bounds_grow(const float3 *verts, BoundBox& bounds) const;
-
- void motion_verts(const float3 *verts,
- const float3 *vert_steps,
- size_t num_verts,
- size_t num_steps,
- float time,
- float3 r_verts[3]) const;
-
- void verts_for_step(const float3 *verts,
- const float3 *vert_steps,
- size_t num_verts,
- size_t num_steps,
- size_t step,
- float3 r_verts[3]) const;
-
- float3 compute_normal(const float3 *verts) const;
-
- bool valid(const float3 *verts) const;
- };
-
- Triangle get_triangle(size_t i) const
- {
- Triangle tri = {{triangles[i*3 + 0],
- triangles[i*3 + 1],
- triangles[i*3 + 2]}};
- return tri;
- }
-
- size_t num_triangles() const
- {
- return triangles.size() / 3;
- }
-
- /* Mesh Curve */
- struct Curve {
- int first_key;
- int num_keys;
-
- int num_segments() { return num_keys - 1; }
-
- void bounds_grow(const int k,
- const float3 *curve_keys,
- const float *curve_radius,
- BoundBox& bounds) const;
- void bounds_grow(float4 keys[4], BoundBox& bounds) const;
- void bounds_grow(const int k,
- const float3 *curve_keys,
- const float *curve_radius,
- const Transform& aligned_space,
- BoundBox& bounds) const;
-
- void motion_keys(const float3 *curve_keys,
- const float *curve_radius,
- const float3 *key_steps,
- size_t num_curve_keys,
- size_t num_steps,
- float time,
- size_t k0, size_t k1,
- float4 r_keys[2]) const;
- void cardinal_motion_keys(const float3 *curve_keys,
- const float *curve_radius,
- const float3 *key_steps,
- size_t num_curve_keys,
- size_t num_steps,
- float time,
- size_t k0, size_t k1,
- size_t k2, size_t k3,
- float4 r_keys[4]) const;
-
- void keys_for_step(const float3 *curve_keys,
- const float *curve_radius,
- const float3 *key_steps,
- size_t num_curve_keys,
- size_t num_steps,
- size_t step,
- size_t k0, size_t k1,
- float4 r_keys[2]) const;
- void cardinal_keys_for_step(const float3 *curve_keys,
- const float *curve_radius,
- const float3 *key_steps,
- size_t num_curve_keys,
- size_t num_steps,
- size_t step,
- size_t k0, size_t k1,
- size_t k2, size_t k3,
- float4 r_keys[4]) const;
- };
-
- Curve get_curve(size_t i) const
- {
- int first = curve_first_key[i];
- int next_first = (i+1 < curve_first_key.size()) ? curve_first_key[i+1] : curve_keys.size();
-
- Curve curve = {first, next_first - first};
- return curve;
- }
-
- size_t num_curves() const
- {
- return curve_first_key.size();
- }
-
- /* Mesh SubdFace */
- struct SubdFace {
- int start_corner;
- int num_corners;
- int shader;
- bool smooth;
- int ptex_offset;
-
- bool is_quad() { return num_corners == 4; }
- float3 normal(const Mesh *mesh) const;
- int num_ptex_faces() const { return num_corners == 4 ? 1 : num_corners; }
- };
-
- struct SubdEdgeCrease {
- int v[2];
- float crease;
- };
-
- enum SubdivisionType {
- SUBDIVISION_NONE,
- SUBDIVISION_LINEAR,
- SUBDIVISION_CATMULL_CLARK,
- };
-
- SubdivisionType subdivision_type;
-
- /* Mesh Data */
- enum GeometryFlags {
- GEOMETRY_NONE = 0,
- GEOMETRY_TRIANGLES = (1 << 0),
- GEOMETRY_CURVES = (1 << 1),
- };
- int geometry_flags; /* used to distinguish meshes with no verts
- and meshed for which geometry is not created */
-
- array<int> triangles;
- array<float3> verts;
- array<int> shader;
- array<bool> smooth;
-
- /* used for storing patch info for subd triangles, only allocated if there are patches */
- array<int> triangle_patch; /* must be < 0 for non subd triangles */
- array<float2> vert_patch_uv;
-
- float volume_isovalue;
- bool has_volume; /* Set in the device_update_flags(). */
- bool has_surface_bssrdf; /* Set in the device_update_flags(). */
-
- array<float3> curve_keys;
- array<float> curve_radius;
- array<int> curve_first_key;
- array<int> curve_shader;
-
- array<SubdFace> subd_faces;
- array<int> subd_face_corners;
- int num_ngons;
-
- array<SubdEdgeCrease> subd_creases;
-
- SubdParams *subd_params;
-
- vector<Shader*> used_shaders;
- AttributeSet attributes;
- AttributeSet curve_attributes;
- AttributeSet subd_attributes;
-
- BoundBox bounds;
- bool transform_applied;
- bool transform_negative_scaled;
- Transform transform_normal;
-
- PackedPatchTable *patch_table;
-
- uint motion_steps;
- bool use_motion_blur;
-
- /* Update Flags */
- bool need_update;
- bool need_update_rebuild;
-
- /* BVH */
- BVH *bvh;
- size_t tri_offset;
- size_t vert_offset;
-
- size_t curve_offset;
- size_t curvekey_offset;
-
- size_t patch_offset;
- size_t patch_table_offset;
- size_t face_offset;
- size_t corner_offset;
-
- size_t attr_map_offset;
-
- size_t num_subd_verts;
-
- /* Functions */
- Mesh();
- ~Mesh();
-
- void resize_mesh(int numverts, int numfaces);
- void reserve_mesh(int numverts, int numfaces);
- void resize_curves(int numcurves, int numkeys);
- void reserve_curves(int numcurves, int numkeys);
- void resize_subd_faces(int numfaces, int num_ngons, int numcorners);
- void reserve_subd_faces(int numfaces, int num_ngons, int numcorners);
- void clear(bool preserve_voxel_data = false);
- void add_vertex(float3 P);
- void add_vertex_slow(float3 P);
- void add_triangle(int v0, int v1, int v2, int shader, bool smooth);
- void add_curve_key(float3 loc, float radius);
- void add_curve(int first_key, int shader);
- void add_subd_face(int* corners, int num_corners, int shader_, bool smooth_);
-
- void compute_bounds();
- void add_face_normals();
- void add_vertex_normals();
- void add_undisplaced();
-
- void pack_shaders(Scene *scene, uint *shader);
- void pack_normals(float4 *vnormal);
- void pack_verts(const vector<uint>& tri_prim_index,
- uint4 *tri_vindex,
- uint *tri_patch,
- float2 *tri_patch_uv,
- size_t vert_offset,
- size_t tri_offset);
- void pack_curves(Scene *scene, float4 *curve_key_co, float4 *curve_data, size_t curvekey_offset);
- void pack_patches(uint *patch_data, uint vert_offset, uint face_offset, uint corner_offset);
-
- void compute_bvh(Device *device,
- DeviceScene *dscene,
- SceneParams *params,
- Progress *progress,
- int n,
- int total);
-
- bool need_attribute(Scene *scene, AttributeStandard std);
- bool need_attribute(Scene *scene, ustring name);
-
- void tag_update(Scene *scene, bool rebuild);
-
- bool has_motion_blur() const;
- bool has_true_displacement() const;
-
- /* Convert between normalized -1..1 motion time and index
- * in the VERTEX_MOTION attribute. */
- float motion_time(int step) const;
- int motion_step(float time) const;
-
- /* Check whether the mesh should have own BVH built separately. Briefly,
- * own BVH is needed for mesh, if:
- *
- * - It is instanced multiple times, so each instance object should share the
- * same BVH tree.
- * - Special ray intersection is needed, for example to limit subsurface rays
- * to only the mesh itself.
- */
- bool need_build_bvh() const;
-
- /* Check if the mesh should be treated as instanced. */
- bool is_instanced() const;
-
- void tessellate(DiagSplit *split);
+ public:
+ NODE_DECLARE
+
+ /* Mesh Triangle */
+ struct Triangle {
+ int v[3];
+
+ void bounds_grow(const float3 *verts, BoundBox &bounds) const;
+
+ void motion_verts(const float3 *verts,
+ const float3 *vert_steps,
+ size_t num_verts,
+ size_t num_steps,
+ float time,
+ float3 r_verts[3]) const;
+
+ void verts_for_step(const float3 *verts,
+ const float3 *vert_steps,
+ size_t num_verts,
+ size_t num_steps,
+ size_t step,
+ float3 r_verts[3]) const;
+
+ float3 compute_normal(const float3 *verts) const;
+
+ bool valid(const float3 *verts) const;
+ };
+
+ Triangle get_triangle(size_t i) const
+ {
+ Triangle tri = {{triangles[i * 3 + 0], triangles[i * 3 + 1], triangles[i * 3 + 2]}};
+ return tri;
+ }
+
+ size_t num_triangles() const
+ {
+ return triangles.size() / 3;
+ }
+
+ /* Mesh Curve */
+ struct Curve {
+ int first_key;
+ int num_keys;
+
+ int num_segments()
+ {
+ return num_keys - 1;
+ }
+
+ void bounds_grow(const int k,
+ const float3 *curve_keys,
+ const float *curve_radius,
+ BoundBox &bounds) const;
+ void bounds_grow(float4 keys[4], BoundBox &bounds) const;
+ void bounds_grow(const int k,
+ const float3 *curve_keys,
+ const float *curve_radius,
+ const Transform &aligned_space,
+ BoundBox &bounds) const;
+
+ void motion_keys(const float3 *curve_keys,
+ const float *curve_radius,
+ const float3 *key_steps,
+ size_t num_curve_keys,
+ size_t num_steps,
+ float time,
+ size_t k0,
+ size_t k1,
+ float4 r_keys[2]) const;
+ void cardinal_motion_keys(const float3 *curve_keys,
+ const float *curve_radius,
+ const float3 *key_steps,
+ size_t num_curve_keys,
+ size_t num_steps,
+ float time,
+ size_t k0,
+ size_t k1,
+ size_t k2,
+ size_t k3,
+ float4 r_keys[4]) const;
+
+ void keys_for_step(const float3 *curve_keys,
+ const float *curve_radius,
+ const float3 *key_steps,
+ size_t num_curve_keys,
+ size_t num_steps,
+ size_t step,
+ size_t k0,
+ size_t k1,
+ float4 r_keys[2]) const;
+ void cardinal_keys_for_step(const float3 *curve_keys,
+ const float *curve_radius,
+ const float3 *key_steps,
+ size_t num_curve_keys,
+ size_t num_steps,
+ size_t step,
+ size_t k0,
+ size_t k1,
+ size_t k2,
+ size_t k3,
+ float4 r_keys[4]) const;
+ };
+
+ Curve get_curve(size_t i) const
+ {
+ int first = curve_first_key[i];
+ int next_first = (i + 1 < curve_first_key.size()) ? curve_first_key[i + 1] : curve_keys.size();
+
+ Curve curve = {first, next_first - first};
+ return curve;
+ }
+
+ size_t num_curves() const
+ {
+ return curve_first_key.size();
+ }
+
+ /* Mesh SubdFace */
+ struct SubdFace {
+ int start_corner;
+ int num_corners;
+ int shader;
+ bool smooth;
+ int ptex_offset;
+
+ bool is_quad()
+ {
+ return num_corners == 4;
+ }
+ float3 normal(const Mesh *mesh) const;
+ int num_ptex_faces() const
+ {
+ return num_corners == 4 ? 1 : num_corners;
+ }
+ };
+
+ struct SubdEdgeCrease {
+ int v[2];
+ float crease;
+ };
+
+ enum SubdivisionType {
+ SUBDIVISION_NONE,
+ SUBDIVISION_LINEAR,
+ SUBDIVISION_CATMULL_CLARK,
+ };
+
+ SubdivisionType subdivision_type;
+
+ /* Mesh Data */
+ enum GeometryFlags {
+ GEOMETRY_NONE = 0,
+ GEOMETRY_TRIANGLES = (1 << 0),
+ GEOMETRY_CURVES = (1 << 1),
+ };
+ int geometry_flags; /* used to distinguish meshes with no verts
+ and meshed for which geometry is not created */
+
+ array<int> triangles;
+ array<float3> verts;
+ array<int> shader;
+ array<bool> smooth;
+
+ /* used for storing patch info for subd triangles, only allocated if there are patches */
+ array<int> triangle_patch; /* must be < 0 for non subd triangles */
+ array<float2> vert_patch_uv;
+
+ float volume_isovalue;
+ bool has_volume; /* Set in the device_update_flags(). */
+ bool has_surface_bssrdf; /* Set in the device_update_flags(). */
+
+ array<float3> curve_keys;
+ array<float> curve_radius;
+ array<int> curve_first_key;
+ array<int> curve_shader;
+
+ array<SubdFace> subd_faces;
+ array<int> subd_face_corners;
+ int num_ngons;
+
+ array<SubdEdgeCrease> subd_creases;
+
+ SubdParams *subd_params;
+
+ vector<Shader *> used_shaders;
+ AttributeSet attributes;
+ AttributeSet curve_attributes;
+ AttributeSet subd_attributes;
+
+ BoundBox bounds;
+ bool transform_applied;
+ bool transform_negative_scaled;
+ Transform transform_normal;
+
+ PackedPatchTable *patch_table;
+
+ uint motion_steps;
+ bool use_motion_blur;
+
+ /* Update Flags */
+ bool need_update;
+ bool need_update_rebuild;
+
+ /* BVH */
+ BVH *bvh;
+ size_t tri_offset;
+ size_t vert_offset;
+
+ size_t curve_offset;
+ size_t curvekey_offset;
+
+ size_t patch_offset;
+ size_t patch_table_offset;
+ size_t face_offset;
+ size_t corner_offset;
+
+ size_t attr_map_offset;
+
+ size_t num_subd_verts;
+
+ /* Functions */
+ Mesh();
+ ~Mesh();
+
+ void resize_mesh(int numverts, int numfaces);
+ void reserve_mesh(int numverts, int numfaces);
+ void resize_curves(int numcurves, int numkeys);
+ void reserve_curves(int numcurves, int numkeys);
+ void resize_subd_faces(int numfaces, int num_ngons, int numcorners);
+ void reserve_subd_faces(int numfaces, int num_ngons, int numcorners);
+ void clear(bool preserve_voxel_data = false);
+ void add_vertex(float3 P);
+ void add_vertex_slow(float3 P);
+ void add_triangle(int v0, int v1, int v2, int shader, bool smooth);
+ void add_curve_key(float3 loc, float radius);
+ void add_curve(int first_key, int shader);
+ void add_subd_face(int *corners, int num_corners, int shader_, bool smooth_);
+
+ void compute_bounds();
+ void add_face_normals();
+ void add_vertex_normals();
+ void add_undisplaced();
+
+ void pack_shaders(Scene *scene, uint *shader);
+ void pack_normals(float4 *vnormal);
+ void pack_verts(const vector<uint> &tri_prim_index,
+ uint4 *tri_vindex,
+ uint *tri_patch,
+ float2 *tri_patch_uv,
+ size_t vert_offset,
+ size_t tri_offset);
+ void pack_curves(Scene *scene, float4 *curve_key_co, float4 *curve_data, size_t curvekey_offset);
+ void pack_patches(uint *patch_data, uint vert_offset, uint face_offset, uint corner_offset);
+
+ void compute_bvh(Device *device,
+ DeviceScene *dscene,
+ SceneParams *params,
+ Progress *progress,
+ int n,
+ int total);
+
+ bool need_attribute(Scene *scene, AttributeStandard std);
+ bool need_attribute(Scene *scene, ustring name);
+
+ void tag_update(Scene *scene, bool rebuild);
+
+ bool has_motion_blur() const;
+ bool has_true_displacement() const;
+
+ /* Convert between normalized -1..1 motion time and index
+ * in the VERTEX_MOTION attribute. */
+ float motion_time(int step) const;
+ int motion_step(float time) const;
+
+ /* Check whether the mesh should have own BVH built separately. Briefly,
+ * own BVH is needed for mesh, if:
+ *
+ * - It is instanced multiple times, so each instance object should share the
+ * same BVH tree.
+ * - Special ray intersection is needed, for example to limit subsurface rays
+ * to only the mesh itself.
+ */
+ bool need_build_bvh() const;
+
+ /* Check if the mesh should be treated as instanced. */
+ bool is_instanced() const;
+
+ void tessellate(DiagSplit *split);
};
/* Mesh Manager */
class MeshManager {
-public:
- bool need_update;
- bool need_flags_update;
+ public:
+ bool need_update;
+ bool need_flags_update;
- MeshManager();
- ~MeshManager();
+ MeshManager();
+ ~MeshManager();
- bool displace(Device *device, DeviceScene *dscene, Scene *scene, Mesh *mesh, Progress& progress);
+ bool displace(Device *device, DeviceScene *dscene, Scene *scene, Mesh *mesh, Progress &progress);
- /* attributes */
- void update_osl_attributes(Device *device, Scene *scene, vector<AttributeRequestSet>& mesh_attributes);
- void update_svm_attributes(Device *device, DeviceScene *dscene, Scene *scene, vector<AttributeRequestSet>& mesh_attributes);
+ /* attributes */
+ void update_osl_attributes(Device *device,
+ Scene *scene,
+ vector<AttributeRequestSet> &mesh_attributes);
+ void update_svm_attributes(Device *device,
+ DeviceScene *dscene,
+ Scene *scene,
+ vector<AttributeRequestSet> &mesh_attributes);
- void device_update_preprocess(Device *device, Scene *scene, Progress& progress);
- void device_update(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress);
+ void device_update_preprocess(Device *device, Scene *scene, Progress &progress);
+ void device_update(Device *device, DeviceScene *dscene, Scene *scene, Progress &progress);
- void device_free(Device *device, DeviceScene *dscene);
+ void device_free(Device *device, DeviceScene *dscene);
- void tag_update(Scene *scene);
+ void tag_update(Scene *scene);
- void create_volume_mesh(Scene *scene, Mesh *mesh, Progress &progress);
+ void create_volume_mesh(Scene *scene, Mesh *mesh, Progress &progress);
- void collect_statistics(const Scene *scene, RenderStats *stats);
+ void collect_statistics(const Scene *scene, RenderStats *stats);
-protected:
- /* Calculate verts/triangles/curves offsets in global arrays. */
- void mesh_calc_offset(Scene *scene);
+ protected:
+ /* Calculate verts/triangles/curves offsets in global arrays. */
+ void mesh_calc_offset(Scene *scene);
- void device_update_object(Device *device,
- DeviceScene *dscene,
- Scene *scene,
- Progress& progress);
+ void device_update_object(Device *device, DeviceScene *dscene, Scene *scene, Progress &progress);
- void device_update_mesh(Device *device,
- DeviceScene *dscene,
- Scene *scene,
- bool for_displacement,
- Progress& progress);
+ void device_update_mesh(Device *device,
+ DeviceScene *dscene,
+ Scene *scene,
+ bool for_displacement,
+ Progress &progress);
- void device_update_attributes(Device *device,
- DeviceScene *dscene,
- Scene *scene,
- Progress& progress);
+ void device_update_attributes(Device *device,
+ DeviceScene *dscene,
+ Scene *scene,
+ Progress &progress);
- void device_update_bvh(Device *device,
- DeviceScene *dscene,
- Scene *scene,
- Progress& progress);
+ void device_update_bvh(Device *device, DeviceScene *dscene, Scene *scene, Progress &progress);
- void device_update_displacement_images(Device *device,
- Scene *scene,
- Progress& progress);
+ void device_update_displacement_images(Device *device, Scene *scene, Progress &progress);
- void device_update_volume_images(Device *device,
- Scene *scene,
- Progress& progress);
+ void device_update_volume_images(Device *device, Scene *scene, Progress &progress);
};
CCL_NAMESPACE_END
-#endif /* __MESH_H__ */
+#endif /* __MESH_H__ */
diff --git a/intern/cycles/render/mesh_displace.cpp b/intern/cycles/render/mesh_displace.cpp
index 53b9bfa3451..5ae9348d83e 100644
--- a/intern/cycles/render/mesh_displace.cpp
+++ b/intern/cycles/render/mesh_displace.cpp
@@ -26,296 +26,301 @@
CCL_NAMESPACE_BEGIN
-static float3 compute_face_normal(const Mesh::Triangle& t, float3 *verts)
+static float3 compute_face_normal(const Mesh::Triangle &t, float3 *verts)
{
- float3 v0 = verts[t.v[0]];
- float3 v1 = verts[t.v[1]];
- float3 v2 = verts[t.v[2]];
+ float3 v0 = verts[t.v[0]];
+ float3 v1 = verts[t.v[1]];
+ float3 v2 = verts[t.v[2]];
- float3 norm = cross(v1 - v0, v2 - v0);
- float normlen = len(norm);
+ float3 norm = cross(v1 - v0, v2 - v0);
+ float normlen = len(norm);
- if(normlen == 0.0f)
- return make_float3(1.0f, 0.0f, 0.0f);
+ if (normlen == 0.0f)
+ return make_float3(1.0f, 0.0f, 0.0f);
- return norm / normlen;
+ return norm / normlen;
}
-bool MeshManager::displace(Device *device, DeviceScene *dscene, Scene *scene, Mesh *mesh, Progress& progress)
+bool MeshManager::displace(
+ Device *device, DeviceScene *dscene, Scene *scene, Mesh *mesh, Progress &progress)
{
- /* verify if we have a displacement shader */
- if(!mesh->has_true_displacement()) {
- return false;
- }
-
- string msg = string_printf("Computing Displacement %s", mesh->name.c_str());
- progress.set_status("Updating Mesh", msg);
-
- /* find object index. todo: is arbitrary */
- size_t object_index = OBJECT_NONE;
-
- for(size_t i = 0; i < scene->objects.size(); i++) {
- if(scene->objects[i]->mesh == mesh) {
- object_index = i;
- break;
- }
- }
-
- /* setup input for device task */
- const size_t num_verts = mesh->verts.size();
- vector<bool> done(num_verts, false);
- device_vector<uint4> d_input(device, "displace_input", MEM_READ_ONLY);
- uint4 *d_input_data = d_input.alloc(num_verts);
- size_t d_input_size = 0;
-
- size_t num_triangles = mesh->num_triangles();
- for(size_t i = 0; i < num_triangles; i++) {
- Mesh::Triangle t = mesh->get_triangle(i);
- int shader_index = mesh->shader[i];
- Shader *shader = (shader_index < mesh->used_shaders.size()) ?
- mesh->used_shaders[shader_index] : scene->default_surface;
-
- if(!shader->has_displacement || shader->displacement_method == DISPLACE_BUMP) {
- continue;
- }
-
- for(int j = 0; j < 3; j++) {
- if(done[t.v[j]])
- continue;
-
- done[t.v[j]] = true;
-
- /* set up object, primitive and barycentric coordinates */
- int object = object_index;
- int prim = mesh->tri_offset + i;
- float u, v;
-
- switch(j) {
- case 0:
- u = 1.0f;
- v = 0.0f;
- break;
- case 1:
- u = 0.0f;
- v = 1.0f;
- break;
- default:
- u = 0.0f;
- v = 0.0f;
- break;
- }
-
- /* back */
- uint4 in = make_uint4(object, prim, __float_as_int(u), __float_as_int(v));
- d_input_data[d_input_size++] = in;
- }
- }
-
- if(d_input_size == 0)
- return false;
-
- /* run device task */
- device_vector<float4> d_output(device, "displace_output", MEM_READ_WRITE);
- d_output.alloc(d_input_size);
- d_output.zero_to_device();
- d_input.copy_to_device();
-
- /* needs to be up to data for attribute access */
- device->const_copy_to("__data", &dscene->data, sizeof(dscene->data));
-
- DeviceTask task(DeviceTask::SHADER);
- task.shader_input = d_input.device_pointer;
- task.shader_output = d_output.device_pointer;
- task.shader_eval_type = SHADER_EVAL_DISPLACE;
- task.shader_x = 0;
- task.shader_w = d_output.size();
- task.num_samples = 1;
- task.get_cancel = function_bind(&Progress::get_cancel, &progress);
-
- device->task_add(task);
- device->task_wait();
-
- if(progress.get_cancel()) {
- d_input.free();
- d_output.free();
- return false;
- }
-
- d_output.copy_from_device(0, 1, d_output.size());
- d_input.free();
-
- /* read result */
- done.clear();
- done.resize(num_verts, false);
- int k = 0;
-
- float4 *offset = d_output.data();
-
- Attribute *attr_mP = mesh->attributes.find(ATTR_STD_MOTION_VERTEX_POSITION);
- for(size_t i = 0; i < num_triangles; i++) {
- Mesh::Triangle t = mesh->get_triangle(i);
- int shader_index = mesh->shader[i];
- Shader *shader = (shader_index < mesh->used_shaders.size()) ?
- mesh->used_shaders[shader_index] : scene->default_surface;
-
- if(!shader->has_displacement || shader->displacement_method == DISPLACE_BUMP) {
- continue;
- }
-
- for(int j = 0; j < 3; j++) {
- if(!done[t.v[j]]) {
- done[t.v[j]] = true;
- float3 off = float4_to_float3(offset[k++]);
- /* Avoid illegal vertex coordinates. */
- off = ensure_finite3(off);
- mesh->verts[t.v[j]] += off;
- if(attr_mP != NULL) {
- for(int step = 0; step < mesh->motion_steps - 1; step++) {
- float3 *mP = attr_mP->data_float3() + step*num_verts;
- mP[t.v[j]] += off;
- }
- }
- }
- }
- }
-
- d_output.free();
-
- /* for displacement method both, we only need to recompute the face
- * normals, as bump mapping in the shader will already alter the
- * vertex normal, so we start from the non-displaced vertex normals
- * to avoid applying the perturbation twice. */
- mesh->attributes.remove(ATTR_STD_FACE_NORMAL);
- mesh->add_face_normals();
-
- bool need_recompute_vertex_normals = false;
-
- foreach(Shader *shader, mesh->used_shaders) {
- if(shader->has_displacement && shader->displacement_method == DISPLACE_TRUE) {
- need_recompute_vertex_normals = true;
- break;
- }
- }
-
- if(need_recompute_vertex_normals) {
- bool flip = mesh->transform_negative_scaled;
- vector<bool> tri_has_true_disp(num_triangles, false);
-
- for(size_t i = 0; i < num_triangles; i++) {
- int shader_index = mesh->shader[i];
- Shader *shader = (shader_index < mesh->used_shaders.size()) ?
- mesh->used_shaders[shader_index] : scene->default_surface;
-
- tri_has_true_disp[i] = shader->has_displacement && shader->displacement_method == DISPLACE_TRUE;
- }
-
- /* static vertex normals */
-
- /* get attributes */
- Attribute *attr_fN = mesh->attributes.find(ATTR_STD_FACE_NORMAL);
- Attribute *attr_vN = mesh->attributes.find(ATTR_STD_VERTEX_NORMAL);
-
- float3 *fN = attr_fN->data_float3();
- float3 *vN = attr_vN->data_float3();
-
- /* compute vertex normals */
-
- /* zero vertex normals on triangles with true displacement */
- for(size_t i = 0; i < num_triangles; i++) {
- if(tri_has_true_disp[i]) {
- for(size_t j = 0; j < 3; j++) {
- vN[mesh->get_triangle(i).v[j]] = make_float3(0.0f, 0.0f, 0.0f);
- }
- }
- }
-
- /* add face normals to vertex normals */
- for(size_t i = 0; i < num_triangles; i++) {
- if(tri_has_true_disp[i]) {
- for(size_t j = 0; j < 3; j++) {
- vN[mesh->get_triangle(i).v[j]] += fN[i];
- }
- }
- }
-
- /* normalize vertex normals */
- done.clear();
- done.resize(num_verts, false);
-
- for(size_t i = 0; i < num_triangles; i++) {
- if(tri_has_true_disp[i]) {
- for(size_t j = 0; j < 3; j++) {
- int vert = mesh->get_triangle(i).v[j];
-
- if(done[vert]) {
- continue;
- }
-
- vN[vert] = normalize(vN[vert]);
- if(flip)
- vN[vert] = -vN[vert];
-
- done[vert] = true;
- }
- }
- }
-
- /* motion vertex normals */
- Attribute *attr_mP = mesh->attributes.find(ATTR_STD_MOTION_VERTEX_POSITION);
- Attribute *attr_mN = mesh->attributes.find(ATTR_STD_MOTION_VERTEX_NORMAL);
-
- if(mesh->has_motion_blur() && attr_mP && attr_mN) {
- for(int step = 0; step < mesh->motion_steps - 1; step++) {
- float3 *mP = attr_mP->data_float3() + step*mesh->verts.size();
- float3 *mN = attr_mN->data_float3() + step*mesh->verts.size();
-
- /* compute */
-
- /* zero vertex normals on triangles with true displacement */
- for(size_t i = 0; i < num_triangles; i++) {
- if(tri_has_true_disp[i]) {
- for(size_t j = 0; j < 3; j++) {
- mN[mesh->get_triangle(i).v[j]] = make_float3(0.0f, 0.0f, 0.0f);
- }
- }
- }
-
- /* add face normals to vertex normals */
- for(size_t i = 0; i < num_triangles; i++) {
- if(tri_has_true_disp[i]) {
- for(size_t j = 0; j < 3; j++) {
- float3 fN = compute_face_normal(mesh->get_triangle(i), mP);
- mN[mesh->get_triangle(i).v[j]] += fN;
- }
- }
- }
-
- /* normalize vertex normals */
- done.clear();
- done.resize(num_verts, false);
-
- for(size_t i = 0; i < num_triangles; i++) {
- if(tri_has_true_disp[i]) {
- for(size_t j = 0; j < 3; j++) {
- int vert = mesh->get_triangle(i).v[j];
-
- if(done[vert]) {
- continue;
- }
-
- mN[vert] = normalize(mN[vert]);
- if(flip)
- mN[vert] = -mN[vert];
-
- done[vert] = true;
- }
- }
- }
- }
- }
- }
-
- return true;
+ /* verify if we have a displacement shader */
+ if (!mesh->has_true_displacement()) {
+ return false;
+ }
+
+ string msg = string_printf("Computing Displacement %s", mesh->name.c_str());
+ progress.set_status("Updating Mesh", msg);
+
+ /* find object index. todo: is arbitrary */
+ size_t object_index = OBJECT_NONE;
+
+ for (size_t i = 0; i < scene->objects.size(); i++) {
+ if (scene->objects[i]->mesh == mesh) {
+ object_index = i;
+ break;
+ }
+ }
+
+ /* setup input for device task */
+ const size_t num_verts = mesh->verts.size();
+ vector<bool> done(num_verts, false);
+ device_vector<uint4> d_input(device, "displace_input", MEM_READ_ONLY);
+ uint4 *d_input_data = d_input.alloc(num_verts);
+ size_t d_input_size = 0;
+
+ size_t num_triangles = mesh->num_triangles();
+ for (size_t i = 0; i < num_triangles; i++) {
+ Mesh::Triangle t = mesh->get_triangle(i);
+ int shader_index = mesh->shader[i];
+ Shader *shader = (shader_index < mesh->used_shaders.size()) ?
+ mesh->used_shaders[shader_index] :
+ scene->default_surface;
+
+ if (!shader->has_displacement || shader->displacement_method == DISPLACE_BUMP) {
+ continue;
+ }
+
+ for (int j = 0; j < 3; j++) {
+ if (done[t.v[j]])
+ continue;
+
+ done[t.v[j]] = true;
+
+ /* set up object, primitive and barycentric coordinates */
+ int object = object_index;
+ int prim = mesh->tri_offset + i;
+ float u, v;
+
+ switch (j) {
+ case 0:
+ u = 1.0f;
+ v = 0.0f;
+ break;
+ case 1:
+ u = 0.0f;
+ v = 1.0f;
+ break;
+ default:
+ u = 0.0f;
+ v = 0.0f;
+ break;
+ }
+
+ /* back */
+ uint4 in = make_uint4(object, prim, __float_as_int(u), __float_as_int(v));
+ d_input_data[d_input_size++] = in;
+ }
+ }
+
+ if (d_input_size == 0)
+ return false;
+
+ /* run device task */
+ device_vector<float4> d_output(device, "displace_output", MEM_READ_WRITE);
+ d_output.alloc(d_input_size);
+ d_output.zero_to_device();
+ d_input.copy_to_device();
+
+ /* needs to be up to data for attribute access */
+ device->const_copy_to("__data", &dscene->data, sizeof(dscene->data));
+
+ DeviceTask task(DeviceTask::SHADER);
+ task.shader_input = d_input.device_pointer;
+ task.shader_output = d_output.device_pointer;
+ task.shader_eval_type = SHADER_EVAL_DISPLACE;
+ task.shader_x = 0;
+ task.shader_w = d_output.size();
+ task.num_samples = 1;
+ task.get_cancel = function_bind(&Progress::get_cancel, &progress);
+
+ device->task_add(task);
+ device->task_wait();
+
+ if (progress.get_cancel()) {
+ d_input.free();
+ d_output.free();
+ return false;
+ }
+
+ d_output.copy_from_device(0, 1, d_output.size());
+ d_input.free();
+
+ /* read result */
+ done.clear();
+ done.resize(num_verts, false);
+ int k = 0;
+
+ float4 *offset = d_output.data();
+
+ Attribute *attr_mP = mesh->attributes.find(ATTR_STD_MOTION_VERTEX_POSITION);
+ for (size_t i = 0; i < num_triangles; i++) {
+ Mesh::Triangle t = mesh->get_triangle(i);
+ int shader_index = mesh->shader[i];
+ Shader *shader = (shader_index < mesh->used_shaders.size()) ?
+ mesh->used_shaders[shader_index] :
+ scene->default_surface;
+
+ if (!shader->has_displacement || shader->displacement_method == DISPLACE_BUMP) {
+ continue;
+ }
+
+ for (int j = 0; j < 3; j++) {
+ if (!done[t.v[j]]) {
+ done[t.v[j]] = true;
+ float3 off = float4_to_float3(offset[k++]);
+ /* Avoid illegal vertex coordinates. */
+ off = ensure_finite3(off);
+ mesh->verts[t.v[j]] += off;
+ if (attr_mP != NULL) {
+ for (int step = 0; step < mesh->motion_steps - 1; step++) {
+ float3 *mP = attr_mP->data_float3() + step * num_verts;
+ mP[t.v[j]] += off;
+ }
+ }
+ }
+ }
+ }
+
+ d_output.free();
+
+ /* for displacement method both, we only need to recompute the face
+ * normals, as bump mapping in the shader will already alter the
+ * vertex normal, so we start from the non-displaced vertex normals
+ * to avoid applying the perturbation twice. */
+ mesh->attributes.remove(ATTR_STD_FACE_NORMAL);
+ mesh->add_face_normals();
+
+ bool need_recompute_vertex_normals = false;
+
+ foreach (Shader *shader, mesh->used_shaders) {
+ if (shader->has_displacement && shader->displacement_method == DISPLACE_TRUE) {
+ need_recompute_vertex_normals = true;
+ break;
+ }
+ }
+
+ if (need_recompute_vertex_normals) {
+ bool flip = mesh->transform_negative_scaled;
+ vector<bool> tri_has_true_disp(num_triangles, false);
+
+ for (size_t i = 0; i < num_triangles; i++) {
+ int shader_index = mesh->shader[i];
+ Shader *shader = (shader_index < mesh->used_shaders.size()) ?
+ mesh->used_shaders[shader_index] :
+ scene->default_surface;
+
+ tri_has_true_disp[i] = shader->has_displacement &&
+ shader->displacement_method == DISPLACE_TRUE;
+ }
+
+ /* static vertex normals */
+
+ /* get attributes */
+ Attribute *attr_fN = mesh->attributes.find(ATTR_STD_FACE_NORMAL);
+ Attribute *attr_vN = mesh->attributes.find(ATTR_STD_VERTEX_NORMAL);
+
+ float3 *fN = attr_fN->data_float3();
+ float3 *vN = attr_vN->data_float3();
+
+ /* compute vertex normals */
+
+ /* zero vertex normals on triangles with true displacement */
+ for (size_t i = 0; i < num_triangles; i++) {
+ if (tri_has_true_disp[i]) {
+ for (size_t j = 0; j < 3; j++) {
+ vN[mesh->get_triangle(i).v[j]] = make_float3(0.0f, 0.0f, 0.0f);
+ }
+ }
+ }
+
+ /* add face normals to vertex normals */
+ for (size_t i = 0; i < num_triangles; i++) {
+ if (tri_has_true_disp[i]) {
+ for (size_t j = 0; j < 3; j++) {
+ vN[mesh->get_triangle(i).v[j]] += fN[i];
+ }
+ }
+ }
+
+ /* normalize vertex normals */
+ done.clear();
+ done.resize(num_verts, false);
+
+ for (size_t i = 0; i < num_triangles; i++) {
+ if (tri_has_true_disp[i]) {
+ for (size_t j = 0; j < 3; j++) {
+ int vert = mesh->get_triangle(i).v[j];
+
+ if (done[vert]) {
+ continue;
+ }
+
+ vN[vert] = normalize(vN[vert]);
+ if (flip)
+ vN[vert] = -vN[vert];
+
+ done[vert] = true;
+ }
+ }
+ }
+
+ /* motion vertex normals */
+ Attribute *attr_mP = mesh->attributes.find(ATTR_STD_MOTION_VERTEX_POSITION);
+ Attribute *attr_mN = mesh->attributes.find(ATTR_STD_MOTION_VERTEX_NORMAL);
+
+ if (mesh->has_motion_blur() && attr_mP && attr_mN) {
+ for (int step = 0; step < mesh->motion_steps - 1; step++) {
+ float3 *mP = attr_mP->data_float3() + step * mesh->verts.size();
+ float3 *mN = attr_mN->data_float3() + step * mesh->verts.size();
+
+ /* compute */
+
+ /* zero vertex normals on triangles with true displacement */
+ for (size_t i = 0; i < num_triangles; i++) {
+ if (tri_has_true_disp[i]) {
+ for (size_t j = 0; j < 3; j++) {
+ mN[mesh->get_triangle(i).v[j]] = make_float3(0.0f, 0.0f, 0.0f);
+ }
+ }
+ }
+
+ /* add face normals to vertex normals */
+ for (size_t i = 0; i < num_triangles; i++) {
+ if (tri_has_true_disp[i]) {
+ for (size_t j = 0; j < 3; j++) {
+ float3 fN = compute_face_normal(mesh->get_triangle(i), mP);
+ mN[mesh->get_triangle(i).v[j]] += fN;
+ }
+ }
+ }
+
+ /* normalize vertex normals */
+ done.clear();
+ done.resize(num_verts, false);
+
+ for (size_t i = 0; i < num_triangles; i++) {
+ if (tri_has_true_disp[i]) {
+ for (size_t j = 0; j < 3; j++) {
+ int vert = mesh->get_triangle(i).v[j];
+
+ if (done[vert]) {
+ continue;
+ }
+
+ mN[vert] = normalize(mN[vert]);
+ if (flip)
+ mN[vert] = -mN[vert];
+
+ done[vert] = true;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ return true;
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/render/mesh_subdivision.cpp b/intern/cycles/render/mesh_subdivision.cpp
index 95cc6f1fca1..46c8240fb71 100644
--- a/intern/cycles/render/mesh_subdivision.cpp
+++ b/intern/cycles/render/mesh_subdivision.cpp
@@ -31,87 +31,92 @@ CCL_NAMESPACE_BEGIN
CCL_NAMESPACE_END
-#include <opensubdiv/far/topologyRefinerFactory.h>
-#include <opensubdiv/far/primvarRefiner.h>
-#include <opensubdiv/far/patchTableFactory.h>
-#include <opensubdiv/far/patchMap.h>
+# include <opensubdiv/far/topologyRefinerFactory.h>
+# include <opensubdiv/far/primvarRefiner.h>
+# include <opensubdiv/far/patchTableFactory.h>
+# include <opensubdiv/far/patchMap.h>
/* specializations of TopologyRefinerFactory for ccl::Mesh */
namespace OpenSubdiv {
namespace OPENSUBDIV_VERSION {
namespace Far {
- template<>
- bool TopologyRefinerFactory<ccl::Mesh>::resizeComponentTopology(TopologyRefiner& refiner, ccl::Mesh const& mesh)
- {
- setNumBaseVertices(refiner, mesh.verts.size());
- setNumBaseFaces(refiner, mesh.subd_faces.size());
+template<>
+bool TopologyRefinerFactory<ccl::Mesh>::resizeComponentTopology(TopologyRefiner &refiner,
+ ccl::Mesh const &mesh)
+{
+ setNumBaseVertices(refiner, mesh.verts.size());
+ setNumBaseFaces(refiner, mesh.subd_faces.size());
- const ccl::Mesh::SubdFace* face = mesh.subd_faces.data();
+ const ccl::Mesh::SubdFace *face = mesh.subd_faces.data();
- for(int i = 0; i < mesh.subd_faces.size(); i++, face++) {
- setNumBaseFaceVertices(refiner, i, face->num_corners);
- }
+ for (int i = 0; i < mesh.subd_faces.size(); i++, face++) {
+ setNumBaseFaceVertices(refiner, i, face->num_corners);
+ }
- return true;
- }
+ return true;
+}
- template<>
- bool TopologyRefinerFactory<ccl::Mesh>::assignComponentTopology(TopologyRefiner& refiner, ccl::Mesh const& mesh)
- {
- const ccl::Mesh::SubdFace* face = mesh.subd_faces.data();
+template<>
+bool TopologyRefinerFactory<ccl::Mesh>::assignComponentTopology(TopologyRefiner &refiner,
+ ccl::Mesh const &mesh)
+{
+ const ccl::Mesh::SubdFace *face = mesh.subd_faces.data();
- for(int i = 0; i < mesh.subd_faces.size(); i++, face++) {
- IndexArray face_verts = getBaseFaceVertices(refiner, i);
+ for (int i = 0; i < mesh.subd_faces.size(); i++, face++) {
+ IndexArray face_verts = getBaseFaceVertices(refiner, i);
- int* corner = &mesh.subd_face_corners[face->start_corner];
+ int *corner = &mesh.subd_face_corners[face->start_corner];
- for(int j = 0; j < face->num_corners; j++, corner++) {
- face_verts[j] = *corner;
- }
- }
+ for (int j = 0; j < face->num_corners; j++, corner++) {
+ face_verts[j] = *corner;
+ }
+ }
- return true;
- }
+ return true;
+}
- template<>
- bool TopologyRefinerFactory<ccl::Mesh>::assignComponentTags(TopologyRefiner& refiner, ccl::Mesh const& mesh)
- {
- const ccl::Mesh::SubdEdgeCrease* crease = mesh.subd_creases.data();
+template<>
+bool TopologyRefinerFactory<ccl::Mesh>::assignComponentTags(TopologyRefiner &refiner,
+ ccl::Mesh const &mesh)
+{
+ const ccl::Mesh::SubdEdgeCrease *crease = mesh.subd_creases.data();
- for(int i = 0; i < mesh.subd_creases.size(); i++, crease++) {
- Index edge = findBaseEdge(refiner, crease->v[0], crease->v[1]);
+ for (int i = 0; i < mesh.subd_creases.size(); i++, crease++) {
+ Index edge = findBaseEdge(refiner, crease->v[0], crease->v[1]);
- if(edge != INDEX_INVALID) {
- setBaseEdgeSharpness(refiner, edge, crease->crease * 10.0f);
- }
- }
+ if (edge != INDEX_INVALID) {
+ setBaseEdgeSharpness(refiner, edge, crease->crease * 10.0f);
+ }
+ }
- for(int i = 0; i < mesh.verts.size(); i++) {
- ConstIndexArray vert_edges = getBaseVertexEdges(refiner, i);
+ for (int i = 0; i < mesh.verts.size(); i++) {
+ ConstIndexArray vert_edges = getBaseVertexEdges(refiner, i);
- if(vert_edges.size() == 2) {
- float sharpness = refiner.getLevel(0).getEdgeSharpness(vert_edges[0]);
- sharpness = ccl::min(sharpness, refiner.getLevel(0).getEdgeSharpness(vert_edges[1]));
+ if (vert_edges.size() == 2) {
+ float sharpness = refiner.getLevel(0).getEdgeSharpness(vert_edges[0]);
+ sharpness = ccl::min(sharpness, refiner.getLevel(0).getEdgeSharpness(vert_edges[1]));
- setBaseVertexSharpness(refiner, i, sharpness);
- }
- }
+ setBaseVertexSharpness(refiner, i, sharpness);
+ }
+ }
- return true;
- }
+ return true;
+}
- template<>
- bool TopologyRefinerFactory<ccl::Mesh>::assignFaceVaryingTopology(TopologyRefiner& /*refiner*/, ccl::Mesh const& /*mesh*/)
- {
- return true;
- }
+template<>
+bool TopologyRefinerFactory<ccl::Mesh>::assignFaceVaryingTopology(TopologyRefiner & /*refiner*/,
+ ccl::Mesh const & /*mesh*/)
+{
+ return true;
+}
- template<>
- void TopologyRefinerFactory<ccl::Mesh>::reportInvalidTopology(TopologyError /*err_code*/,
- char const * /*msg*/, ccl::Mesh const& /*mesh*/)
- {
- }
+template<>
+void TopologyRefinerFactory<ccl::Mesh>::reportInvalidTopology(TopologyError /*err_code*/,
+ char const * /*msg*/,
+ ccl::Mesh const & /*mesh*/)
+{
+}
} /* namespace Far */
} /* namespace OPENSUBDIV_VERSION */
} /* namespace OpenSubdiv */
@@ -122,226 +127,242 @@ using namespace OpenSubdiv;
/* struct that implements OpenSubdiv's vertex interface */
-template<typename T>
-struct OsdValue {
- T value;
+template<typename T> struct OsdValue {
+ T value;
- OsdValue() {}
+ OsdValue()
+ {
+ }
- void Clear(void* = 0) {
- memset(&value, 0, sizeof(T));
- }
+ void Clear(void * = 0)
+ {
+ memset(&value, 0, sizeof(T));
+ }
- void AddWithWeight(OsdValue<T> const& src, float weight) {
- value += src.value * weight;
- }
+ void AddWithWeight(OsdValue<T> const &src, float weight)
+ {
+ value += src.value * weight;
+ }
};
-template<>
-void OsdValue<uchar4>::AddWithWeight(OsdValue<uchar4> const& src, float weight)
+template<> void OsdValue<uchar4>::AddWithWeight(OsdValue<uchar4> const &src, float weight)
{
- for(int i = 0; i < 4; i++) {
- value[i] += (uchar)(src.value[i] * weight);
- }
+ for (int i = 0; i < 4; i++) {
+ value[i] += (uchar)(src.value[i] * weight);
+ }
}
/* class for holding OpenSubdiv data used during tessellation */
class OsdData {
- Mesh* mesh;
- vector<OsdValue<float3> > verts;
- Far::TopologyRefiner* refiner;
- Far::PatchTable* patch_table;
- Far::PatchMap* patch_map;
-
-public:
- OsdData() : mesh(NULL), refiner(NULL), patch_table(NULL), patch_map(NULL) {}
-
- ~OsdData()
- {
- delete refiner;
- delete patch_table;
- delete patch_map;
- }
-
- void build_from_mesh(Mesh* mesh_)
- {
- mesh = mesh_;
-
- /* type and options */
- Sdc::SchemeType type = Sdc::SCHEME_CATMARK;
-
- Sdc::Options options;
- options.SetVtxBoundaryInterpolation(Sdc::Options::VTX_BOUNDARY_EDGE_ONLY);
-
- /* create refiner */
- refiner = Far::TopologyRefinerFactory<Mesh>::Create(*mesh,
- Far::TopologyRefinerFactory<Mesh>::Options(type, options));
-
- /* adaptive refinement */
- int max_isolation = calculate_max_isolation();
- refiner->RefineAdaptive(Far::TopologyRefiner::AdaptiveOptions(max_isolation));
-
- /* create patch table */
- Far::PatchTableFactory::Options patch_options;
- patch_options.endCapType = Far::PatchTableFactory::Options::ENDCAP_GREGORY_BASIS;
-
- patch_table = Far::PatchTableFactory::Create(*refiner, patch_options);
-
- /* interpolate verts */
- int num_refiner_verts = refiner->GetNumVerticesTotal();
- int num_local_points = patch_table->GetNumLocalPoints();
-
- verts.resize(num_refiner_verts + num_local_points);
- for(int i = 0; i < mesh->verts.size(); i++) {
- verts[i].value = mesh->verts[i];
- }
-
- OsdValue<float3>* src = verts.data();
- for(int i = 0; i < refiner->GetMaxLevel(); i++) {
- OsdValue<float3>* dest = src + refiner->GetLevel(i).GetNumVertices();
- Far::PrimvarRefiner(*refiner).Interpolate(i+1, src, dest);
- src = dest;
- }
-
- if(num_local_points) {
- patch_table->ComputeLocalPointValues(&verts[0], &verts[num_refiner_verts]);
- }
-
- /* create patch map */
- patch_map = new Far::PatchMap(*patch_table);
- }
-
- void subdivide_attribute(Attribute& attr)
- {
- Far::PrimvarRefiner primvar_refiner(*refiner);
-
- if(attr.element == ATTR_ELEMENT_VERTEX) {
- int num_refiner_verts = refiner->GetNumVerticesTotal();
- int num_local_points = patch_table->GetNumLocalPoints();
-
- attr.resize(num_refiner_verts + num_local_points);
- attr.flags |= ATTR_FINAL_SIZE;
-
- char* src = attr.buffer.data();
-
- for(int i = 0; i < refiner->GetMaxLevel(); i++) {
- char* dest = src + refiner->GetLevel(i).GetNumVertices() * attr.data_sizeof();
-
- if(attr.same_storage(attr.type, TypeDesc::TypeFloat)) {
- primvar_refiner.Interpolate(i+1, (OsdValue<float>*)src, (OsdValue<float>*&)dest);
- }
- else if(attr.same_storage(attr.type, TypeFloat2)) {
- primvar_refiner.Interpolate(i+1, (OsdValue<float2>*)src, (OsdValue<float2>*&)dest);
- }
- else {
- primvar_refiner.Interpolate(i+1, (OsdValue<float4>*)src, (OsdValue<float4>*&)dest);
- }
-
- src = dest;
- }
-
- if(num_local_points) {
- if(attr.same_storage(attr.type, TypeDesc::TypeFloat)) {
- patch_table->ComputeLocalPointValues((OsdValue<float>*)&attr.buffer[0],
- (OsdValue<float>*)&attr.buffer[num_refiner_verts * attr.data_sizeof()]);
- }
- else if(attr.same_storage(attr.type, TypeFloat2)) {
- patch_table->ComputeLocalPointValues((OsdValue<float2>*)&attr.buffer[0],
- (OsdValue<float2>*)&attr.buffer[num_refiner_verts * attr.data_sizeof()]);
- }
- else {
- patch_table->ComputeLocalPointValues((OsdValue<float4>*)&attr.buffer[0],
- (OsdValue<float4>*)&attr.buffer[num_refiner_verts * attr.data_sizeof()]);
- }
- }
- }
- else if(attr.element == ATTR_ELEMENT_CORNER || attr.element == ATTR_ELEMENT_CORNER_BYTE) {
- // TODO(mai): fvar interpolation
- }
- }
-
- int calculate_max_isolation()
- {
- /* loop over all edges to find longest in screen space */
- const Far::TopologyLevel& level = refiner->GetLevel(0);
- Transform objecttoworld = mesh->subd_params->objecttoworld;
- Camera* cam = mesh->subd_params->camera;
-
- float longest_edge = 0.0f;
-
- for(size_t i = 0; i < level.GetNumEdges(); i++) {
- Far::ConstIndexArray verts = level.GetEdgeVertices(i);
-
- float3 a = mesh->verts[verts[0]];
- float3 b = mesh->verts[verts[1]];
-
- float edge_len;
-
- if(cam) {
- a = transform_point(&objecttoworld, a);
- b = transform_point(&objecttoworld, b);
-
- edge_len = len(a - b) / cam->world_to_raster_size((a + b) * 0.5f);
- }
- else {
- edge_len = len(a - b);
- }
-
- longest_edge = max(longest_edge, edge_len);
- }
-
- /* calculate isolation level */
- int isolation = (int)(log2f(max(longest_edge / mesh->subd_params->dicing_rate, 1.0f)) + 1.0f);
-
- return min(isolation, 10);
- }
-
- friend struct OsdPatch;
- friend class Mesh;
+ Mesh *mesh;
+ vector<OsdValue<float3>> verts;
+ Far::TopologyRefiner *refiner;
+ Far::PatchTable *patch_table;
+ Far::PatchMap *patch_map;
+
+ public:
+ OsdData() : mesh(NULL), refiner(NULL), patch_table(NULL), patch_map(NULL)
+ {
+ }
+
+ ~OsdData()
+ {
+ delete refiner;
+ delete patch_table;
+ delete patch_map;
+ }
+
+ void build_from_mesh(Mesh *mesh_)
+ {
+ mesh = mesh_;
+
+ /* type and options */
+ Sdc::SchemeType type = Sdc::SCHEME_CATMARK;
+
+ Sdc::Options options;
+ options.SetVtxBoundaryInterpolation(Sdc::Options::VTX_BOUNDARY_EDGE_ONLY);
+
+ /* create refiner */
+ refiner = Far::TopologyRefinerFactory<Mesh>::Create(
+ *mesh, Far::TopologyRefinerFactory<Mesh>::Options(type, options));
+
+ /* adaptive refinement */
+ int max_isolation = calculate_max_isolation();
+ refiner->RefineAdaptive(Far::TopologyRefiner::AdaptiveOptions(max_isolation));
+
+ /* create patch table */
+ Far::PatchTableFactory::Options patch_options;
+ patch_options.endCapType = Far::PatchTableFactory::Options::ENDCAP_GREGORY_BASIS;
+
+ patch_table = Far::PatchTableFactory::Create(*refiner, patch_options);
+
+ /* interpolate verts */
+ int num_refiner_verts = refiner->GetNumVerticesTotal();
+ int num_local_points = patch_table->GetNumLocalPoints();
+
+ verts.resize(num_refiner_verts + num_local_points);
+ for (int i = 0; i < mesh->verts.size(); i++) {
+ verts[i].value = mesh->verts[i];
+ }
+
+ OsdValue<float3> *src = verts.data();
+ for (int i = 0; i < refiner->GetMaxLevel(); i++) {
+ OsdValue<float3> *dest = src + refiner->GetLevel(i).GetNumVertices();
+ Far::PrimvarRefiner(*refiner).Interpolate(i + 1, src, dest);
+ src = dest;
+ }
+
+ if (num_local_points) {
+ patch_table->ComputeLocalPointValues(&verts[0], &verts[num_refiner_verts]);
+ }
+
+ /* create patch map */
+ patch_map = new Far::PatchMap(*patch_table);
+ }
+
+ void subdivide_attribute(Attribute &attr)
+ {
+ Far::PrimvarRefiner primvar_refiner(*refiner);
+
+ if (attr.element == ATTR_ELEMENT_VERTEX) {
+ int num_refiner_verts = refiner->GetNumVerticesTotal();
+ int num_local_points = patch_table->GetNumLocalPoints();
+
+ attr.resize(num_refiner_verts + num_local_points);
+ attr.flags |= ATTR_FINAL_SIZE;
+
+ char *src = attr.buffer.data();
+
+ for (int i = 0; i < refiner->GetMaxLevel(); i++) {
+ char *dest = src + refiner->GetLevel(i).GetNumVertices() * attr.data_sizeof();
+
+ if (attr.same_storage(attr.type, TypeDesc::TypeFloat)) {
+ primvar_refiner.Interpolate(i + 1, (OsdValue<float> *)src, (OsdValue<float> *&)dest);
+ }
+ else if (attr.same_storage(attr.type, TypeFloat2)) {
+ primvar_refiner.Interpolate(i + 1, (OsdValue<float2> *)src, (OsdValue<float2> *&)dest);
+ }
+ else {
+ primvar_refiner.Interpolate(i + 1, (OsdValue<float4> *)src, (OsdValue<float4> *&)dest);
+ }
+
+ src = dest;
+ }
+
+ if (num_local_points) {
+ if (attr.same_storage(attr.type, TypeDesc::TypeFloat)) {
+ patch_table->ComputeLocalPointValues(
+ (OsdValue<float> *)&attr.buffer[0],
+ (OsdValue<float> *)&attr.buffer[num_refiner_verts * attr.data_sizeof()]);
+ }
+ else if (attr.same_storage(attr.type, TypeFloat2)) {
+ patch_table->ComputeLocalPointValues(
+ (OsdValue<float2> *)&attr.buffer[0],
+ (OsdValue<float2> *)&attr.buffer[num_refiner_verts * attr.data_sizeof()]);
+ }
+ else {
+ patch_table->ComputeLocalPointValues(
+ (OsdValue<float4> *)&attr.buffer[0],
+ (OsdValue<float4> *)&attr.buffer[num_refiner_verts * attr.data_sizeof()]);
+ }
+ }
+ }
+ else if (attr.element == ATTR_ELEMENT_CORNER || attr.element == ATTR_ELEMENT_CORNER_BYTE) {
+ // TODO(mai): fvar interpolation
+ }
+ }
+
+ int calculate_max_isolation()
+ {
+ /* loop over all edges to find longest in screen space */
+ const Far::TopologyLevel &level = refiner->GetLevel(0);
+ Transform objecttoworld = mesh->subd_params->objecttoworld;
+ Camera *cam = mesh->subd_params->camera;
+
+ float longest_edge = 0.0f;
+
+ for (size_t i = 0; i < level.GetNumEdges(); i++) {
+ Far::ConstIndexArray verts = level.GetEdgeVertices(i);
+
+ float3 a = mesh->verts[verts[0]];
+ float3 b = mesh->verts[verts[1]];
+
+ float edge_len;
+
+ if (cam) {
+ a = transform_point(&objecttoworld, a);
+ b = transform_point(&objecttoworld, b);
+
+ edge_len = len(a - b) / cam->world_to_raster_size((a + b) * 0.5f);
+ }
+ else {
+ edge_len = len(a - b);
+ }
+
+ longest_edge = max(longest_edge, edge_len);
+ }
+
+ /* calculate isolation level */
+ int isolation = (int)(log2f(max(longest_edge / mesh->subd_params->dicing_rate, 1.0f)) + 1.0f);
+
+ return min(isolation, 10);
+ }
+
+ friend struct OsdPatch;
+ friend class Mesh;
};
/* ccl::Patch implementation that uses OpenSubdiv for eval */
struct OsdPatch : Patch {
- OsdData* osd_data;
-
- OsdPatch(OsdData* data) : osd_data(data) {}
-
- void eval(float3 *P, float3 *dPdu, float3 *dPdv, float3 *N, float u, float v)
- {
- const Far::PatchTable::PatchHandle* handle = osd_data->patch_map->FindPatch(patch_index, u, v);
- assert(handle);
-
- float p_weights[20], du_weights[20], dv_weights[20];
- osd_data->patch_table->EvaluateBasis(*handle, u, v, p_weights, du_weights, dv_weights);
-
- Far::ConstIndexArray cv = osd_data->patch_table->GetPatchVertices(*handle);
-
- float3 du, dv;
- if(P) *P = make_float3(0.0f, 0.0f, 0.0f);
- du = make_float3(0.0f, 0.0f, 0.0f);
- dv = make_float3(0.0f, 0.0f, 0.0f);
-
- for(int i = 0; i < cv.size(); i++) {
- float3 p = osd_data->verts[cv[i]].value;
-
- if(P) *P += p * p_weights[i];
- du += p * du_weights[i];
- dv += p * dv_weights[i];
- }
-
- if(dPdu) *dPdu = du;
- if(dPdv) *dPdv = dv;
- if(N) {
- *N = cross(du, dv);
-
- float t = len(*N);
- *N = (t != 0.0f) ? *N/t : make_float3(0.0f, 0.0f, 1.0f);
- }
- }
-
- BoundBox bound() { return BoundBox::empty; }
+ OsdData *osd_data;
+
+ OsdPatch(OsdData *data) : osd_data(data)
+ {
+ }
+
+ void eval(float3 *P, float3 *dPdu, float3 *dPdv, float3 *N, float u, float v)
+ {
+ const Far::PatchTable::PatchHandle *handle = osd_data->patch_map->FindPatch(patch_index, u, v);
+ assert(handle);
+
+ float p_weights[20], du_weights[20], dv_weights[20];
+ osd_data->patch_table->EvaluateBasis(*handle, u, v, p_weights, du_weights, dv_weights);
+
+ Far::ConstIndexArray cv = osd_data->patch_table->GetPatchVertices(*handle);
+
+ float3 du, dv;
+ if (P)
+ *P = make_float3(0.0f, 0.0f, 0.0f);
+ du = make_float3(0.0f, 0.0f, 0.0f);
+ dv = make_float3(0.0f, 0.0f, 0.0f);
+
+ for (int i = 0; i < cv.size(); i++) {
+ float3 p = osd_data->verts[cv[i]].value;
+
+ if (P)
+ *P += p * p_weights[i];
+ du += p * du_weights[i];
+ dv += p * dv_weights[i];
+ }
+
+ if (dPdu)
+ *dPdu = du;
+ if (dPdv)
+ *dPdv = dv;
+ if (N) {
+ *N = cross(du, dv);
+
+ float t = len(*N);
+ *N = (t != 0.0f) ? *N / t : make_float3(0.0f, 0.0f, 1.0f);
+ }
+ }
+
+ BoundBox bound()
+ {
+ return BoundBox::empty;
+ }
};
#endif
@@ -349,273 +370,280 @@ struct OsdPatch : Patch {
void Mesh::tessellate(DiagSplit *split)
{
#ifdef WITH_OPENSUBDIV
- OsdData osd_data;
- bool need_packed_patch_table = false;
-
- if(subdivision_type == SUBDIVISION_CATMULL_CLARK) {
- if(subd_faces.size()) {
- osd_data.build_from_mesh(this);
- }
- }
- else
+ OsdData osd_data;
+ bool need_packed_patch_table = false;
+
+ if (subdivision_type == SUBDIVISION_CATMULL_CLARK) {
+ if (subd_faces.size()) {
+ osd_data.build_from_mesh(this);
+ }
+ }
+ else
#endif
- {
- /* force linear subdivision if OpenSubdiv is unavailable to avoid
- * falling into catmull-clark code paths by accident
- */
- subdivision_type = SUBDIVISION_LINEAR;
+ {
+ /* force linear subdivision if OpenSubdiv is unavailable to avoid
+ * falling into catmull-clark code paths by accident
+ */
+ subdivision_type = SUBDIVISION_LINEAR;
- /* force disable attribute subdivision for same reason as above */
- foreach(Attribute& attr, subd_attributes.attributes) {
- attr.flags &= ~ATTR_SUBDIVIDED;
- }
- }
+ /* force disable attribute subdivision for same reason as above */
+ foreach (Attribute &attr, subd_attributes.attributes) {
+ attr.flags &= ~ATTR_SUBDIVIDED;
+ }
+ }
- int num_faces = subd_faces.size();
+ int num_faces = subd_faces.size();
- Attribute *attr_vN = subd_attributes.find(ATTR_STD_VERTEX_NORMAL);
- float3* vN = attr_vN->data_float3();
+ Attribute *attr_vN = subd_attributes.find(ATTR_STD_VERTEX_NORMAL);
+ float3 *vN = attr_vN->data_float3();
- for(int f = 0; f < num_faces; f++) {
- SubdFace& face = subd_faces[f];
+ for (int f = 0; f < num_faces; f++) {
+ SubdFace &face = subd_faces[f];
- if(face.is_quad()) {
- /* quad */
- QuadDice::SubPatch subpatch;
+ if (face.is_quad()) {
+ /* quad */
+ QuadDice::SubPatch subpatch;
- LinearQuadPatch quad_patch;
+ LinearQuadPatch quad_patch;
#ifdef WITH_OPENSUBDIV
- OsdPatch osd_patch(&osd_data);
+ OsdPatch osd_patch(&osd_data);
- if(subdivision_type == SUBDIVISION_CATMULL_CLARK) {
- osd_patch.patch_index = face.ptex_offset;
+ if (subdivision_type == SUBDIVISION_CATMULL_CLARK) {
+ osd_patch.patch_index = face.ptex_offset;
- subpatch.patch = &osd_patch;
- }
- else
+ subpatch.patch = &osd_patch;
+ }
+ else
#endif
- {
- float3 *hull = quad_patch.hull;
- float3 *normals = quad_patch.normals;
-
- quad_patch.patch_index = face.ptex_offset;
-
- for(int i = 0; i < 4; i++) {
- hull[i] = verts[subd_face_corners[face.start_corner+i]];
- }
-
- if(face.smooth) {
- for(int i = 0; i < 4; i++) {
- normals[i] = vN[subd_face_corners[face.start_corner+i]];
- }
- }
- else {
- float3 N = face.normal(this);
- for(int i = 0; i < 4; i++) {
- normals[i] = N;
- }
- }
-
- swap(hull[2], hull[3]);
- swap(normals[2], normals[3]);
-
- subpatch.patch = &quad_patch;
- }
-
- subpatch.patch->shader = face.shader;
-
- /* Quad faces need to be split at least once to line up with split ngons, we do this
- * here in this manner because if we do it later edge factors may end up slightly off.
- */
- subpatch.P00 = make_float2(0.0f, 0.0f);
- subpatch.P10 = make_float2(0.5f, 0.0f);
- subpatch.P01 = make_float2(0.0f, 0.5f);
- subpatch.P11 = make_float2(0.5f, 0.5f);
- split->split_quad(subpatch.patch, &subpatch);
-
- subpatch.P00 = make_float2(0.5f, 0.0f);
- subpatch.P10 = make_float2(1.0f, 0.0f);
- subpatch.P01 = make_float2(0.5f, 0.5f);
- subpatch.P11 = make_float2(1.0f, 0.5f);
- split->split_quad(subpatch.patch, &subpatch);
-
- subpatch.P00 = make_float2(0.0f, 0.5f);
- subpatch.P10 = make_float2(0.5f, 0.5f);
- subpatch.P01 = make_float2(0.0f, 1.0f);
- subpatch.P11 = make_float2(0.5f, 1.0f);
- split->split_quad(subpatch.patch, &subpatch);
-
- subpatch.P00 = make_float2(0.5f, 0.5f);
- subpatch.P10 = make_float2(1.0f, 0.5f);
- subpatch.P01 = make_float2(0.5f, 1.0f);
- subpatch.P11 = make_float2(1.0f, 1.0f);
- split->split_quad(subpatch.patch, &subpatch);
- }
- else {
- /* ngon */
+ {
+ float3 *hull = quad_patch.hull;
+ float3 *normals = quad_patch.normals;
+
+ quad_patch.patch_index = face.ptex_offset;
+
+ for (int i = 0; i < 4; i++) {
+ hull[i] = verts[subd_face_corners[face.start_corner + i]];
+ }
+
+ if (face.smooth) {
+ for (int i = 0; i < 4; i++) {
+ normals[i] = vN[subd_face_corners[face.start_corner + i]];
+ }
+ }
+ else {
+ float3 N = face.normal(this);
+ for (int i = 0; i < 4; i++) {
+ normals[i] = N;
+ }
+ }
+
+ swap(hull[2], hull[3]);
+ swap(normals[2], normals[3]);
+
+ subpatch.patch = &quad_patch;
+ }
+
+ subpatch.patch->shader = face.shader;
+
+ /* Quad faces need to be split at least once to line up with split ngons, we do this
+ * here in this manner because if we do it later edge factors may end up slightly off.
+ */
+ subpatch.P00 = make_float2(0.0f, 0.0f);
+ subpatch.P10 = make_float2(0.5f, 0.0f);
+ subpatch.P01 = make_float2(0.0f, 0.5f);
+ subpatch.P11 = make_float2(0.5f, 0.5f);
+ split->split_quad(subpatch.patch, &subpatch);
+
+ subpatch.P00 = make_float2(0.5f, 0.0f);
+ subpatch.P10 = make_float2(1.0f, 0.0f);
+ subpatch.P01 = make_float2(0.5f, 0.5f);
+ subpatch.P11 = make_float2(1.0f, 0.5f);
+ split->split_quad(subpatch.patch, &subpatch);
+
+ subpatch.P00 = make_float2(0.0f, 0.5f);
+ subpatch.P10 = make_float2(0.5f, 0.5f);
+ subpatch.P01 = make_float2(0.0f, 1.0f);
+ subpatch.P11 = make_float2(0.5f, 1.0f);
+ split->split_quad(subpatch.patch, &subpatch);
+
+ subpatch.P00 = make_float2(0.5f, 0.5f);
+ subpatch.P10 = make_float2(1.0f, 0.5f);
+ subpatch.P01 = make_float2(0.5f, 1.0f);
+ subpatch.P11 = make_float2(1.0f, 1.0f);
+ split->split_quad(subpatch.patch, &subpatch);
+ }
+ else {
+ /* ngon */
#ifdef WITH_OPENSUBDIV
- if(subdivision_type == SUBDIVISION_CATMULL_CLARK) {
- OsdPatch patch(&osd_data);
+ if (subdivision_type == SUBDIVISION_CATMULL_CLARK) {
+ OsdPatch patch(&osd_data);
- patch.shader = face.shader;
+ patch.shader = face.shader;
- for(int corner = 0; corner < face.num_corners; corner++) {
- patch.patch_index = face.ptex_offset + corner;
+ for (int corner = 0; corner < face.num_corners; corner++) {
+ patch.patch_index = face.ptex_offset + corner;
- split->split_quad(&patch);
- }
- }
- else
+ split->split_quad(&patch);
+ }
+ }
+ else
#endif
- {
- float3 center_vert = make_float3(0.0f, 0.0f, 0.0f);
- float3 center_normal = make_float3(0.0f, 0.0f, 0.0f);
-
- float inv_num_corners = 1.0f/float(face.num_corners);
- for(int corner = 0; corner < face.num_corners; corner++) {
- center_vert += verts[subd_face_corners[face.start_corner + corner]] * inv_num_corners;
- center_normal += vN[subd_face_corners[face.start_corner + corner]] * inv_num_corners;
- }
-
- for(int corner = 0; corner < face.num_corners; corner++) {
- LinearQuadPatch patch;
- float3 *hull = patch.hull;
- float3 *normals = patch.normals;
-
- patch.patch_index = face.ptex_offset + corner;
-
- patch.shader = face.shader;
-
- hull[0] = verts[subd_face_corners[face.start_corner + mod(corner + 0, face.num_corners)]];
- hull[1] = verts[subd_face_corners[face.start_corner + mod(corner + 1, face.num_corners)]];
- hull[2] = verts[subd_face_corners[face.start_corner + mod(corner - 1, face.num_corners)]];
- hull[3] = center_vert;
-
- hull[1] = (hull[1] + hull[0]) * 0.5;
- hull[2] = (hull[2] + hull[0]) * 0.5;
-
- if(face.smooth) {
- normals[0] = vN[subd_face_corners[face.start_corner + mod(corner + 0, face.num_corners)]];
- normals[1] = vN[subd_face_corners[face.start_corner + mod(corner + 1, face.num_corners)]];
- normals[2] = vN[subd_face_corners[face.start_corner + mod(corner - 1, face.num_corners)]];
- normals[3] = center_normal;
-
- normals[1] = (normals[1] + normals[0]) * 0.5;
- normals[2] = (normals[2] + normals[0]) * 0.5;
- }
- else {
- float3 N = face.normal(this);
- for(int i = 0; i < 4; i++) {
- normals[i] = N;
- }
- }
-
- split->split_quad(&patch);
- }
- }
- }
- }
-
- /* interpolate center points for attributes */
- foreach(Attribute& attr, subd_attributes.attributes) {
+ {
+ float3 center_vert = make_float3(0.0f, 0.0f, 0.0f);
+ float3 center_normal = make_float3(0.0f, 0.0f, 0.0f);
+
+ float inv_num_corners = 1.0f / float(face.num_corners);
+ for (int corner = 0; corner < face.num_corners; corner++) {
+ center_vert += verts[subd_face_corners[face.start_corner + corner]] * inv_num_corners;
+ center_normal += vN[subd_face_corners[face.start_corner + corner]] * inv_num_corners;
+ }
+
+ for (int corner = 0; corner < face.num_corners; corner++) {
+ LinearQuadPatch patch;
+ float3 *hull = patch.hull;
+ float3 *normals = patch.normals;
+
+ patch.patch_index = face.ptex_offset + corner;
+
+ patch.shader = face.shader;
+
+ hull[0] =
+ verts[subd_face_corners[face.start_corner + mod(corner + 0, face.num_corners)]];
+ hull[1] =
+ verts[subd_face_corners[face.start_corner + mod(corner + 1, face.num_corners)]];
+ hull[2] =
+ verts[subd_face_corners[face.start_corner + mod(corner - 1, face.num_corners)]];
+ hull[3] = center_vert;
+
+ hull[1] = (hull[1] + hull[0]) * 0.5;
+ hull[2] = (hull[2] + hull[0]) * 0.5;
+
+ if (face.smooth) {
+ normals[0] =
+ vN[subd_face_corners[face.start_corner + mod(corner + 0, face.num_corners)]];
+ normals[1] =
+ vN[subd_face_corners[face.start_corner + mod(corner + 1, face.num_corners)]];
+ normals[2] =
+ vN[subd_face_corners[face.start_corner + mod(corner - 1, face.num_corners)]];
+ normals[3] = center_normal;
+
+ normals[1] = (normals[1] + normals[0]) * 0.5;
+ normals[2] = (normals[2] + normals[0]) * 0.5;
+ }
+ else {
+ float3 N = face.normal(this);
+ for (int i = 0; i < 4; i++) {
+ normals[i] = N;
+ }
+ }
+
+ split->split_quad(&patch);
+ }
+ }
+ }
+ }
+
+ /* interpolate center points for attributes */
+ foreach (Attribute &attr, subd_attributes.attributes) {
#ifdef WITH_OPENSUBDIV
- if(subdivision_type == SUBDIVISION_CATMULL_CLARK && attr.flags & ATTR_SUBDIVIDED) {
- if(attr.element == ATTR_ELEMENT_CORNER || attr.element == ATTR_ELEMENT_CORNER_BYTE) {
- /* keep subdivision for corner attributes disabled for now */
- attr.flags &= ~ATTR_SUBDIVIDED;
- }
- else if(subd_faces.size()) {
- osd_data.subdivide_attribute(attr);
-
- need_packed_patch_table = true;
- continue;
- }
- }
+ if (subdivision_type == SUBDIVISION_CATMULL_CLARK && attr.flags & ATTR_SUBDIVIDED) {
+ if (attr.element == ATTR_ELEMENT_CORNER || attr.element == ATTR_ELEMENT_CORNER_BYTE) {
+ /* keep subdivision for corner attributes disabled for now */
+ attr.flags &= ~ATTR_SUBDIVIDED;
+ }
+ else if (subd_faces.size()) {
+ osd_data.subdivide_attribute(attr);
+
+ need_packed_patch_table = true;
+ continue;
+ }
+ }
#endif
- char* data = attr.data();
- size_t stride = attr.data_sizeof();
- int ngons = 0;
-
- switch(attr.element) {
- case ATTR_ELEMENT_VERTEX: {
- for(int f = 0; f < num_faces; f++) {
- SubdFace& face = subd_faces[f];
-
- if(!face.is_quad()) {
- char* center = data + (verts.size() - num_subd_verts + ngons) * stride;
- attr.zero_data(center);
-
- float inv_num_corners = 1.0f / float(face.num_corners);
-
- for(int corner = 0; corner < face.num_corners; corner++) {
- attr.add_with_weight(center,
- data + subd_face_corners[face.start_corner + corner] * stride,
- inv_num_corners);
- }
-
- ngons++;
- }
- }
- } break;
- case ATTR_ELEMENT_VERTEX_MOTION: {
- // TODO(mai): implement
- } break;
- case ATTR_ELEMENT_CORNER: {
- for(int f = 0; f < num_faces; f++) {
- SubdFace& face = subd_faces[f];
-
- if(!face.is_quad()) {
- char* center = data + (subd_face_corners.size() + ngons) * stride;
- attr.zero_data(center);
-
- float inv_num_corners = 1.0f / float(face.num_corners);
-
- for(int corner = 0; corner < face.num_corners; corner++) {
- attr.add_with_weight(center,
- data + (face.start_corner + corner) * stride,
- inv_num_corners);
- }
-
- ngons++;
- }
- }
- } break;
- case ATTR_ELEMENT_CORNER_BYTE: {
- for(int f = 0; f < num_faces; f++) {
- SubdFace& face = subd_faces[f];
-
- if(!face.is_quad()) {
- uchar* center = (uchar*)data + (subd_face_corners.size() + ngons) * stride;
-
- float inv_num_corners = 1.0f / float(face.num_corners);
- float4 val = make_float4(0.0f, 0.0f, 0.0f, 0.0f);
-
- for(int corner = 0; corner < face.num_corners; corner++) {
- for(int i = 0; i < 4; i++) {
- val[i] += float(*(data + (face.start_corner + corner) * stride + i)) * inv_num_corners;
- }
- }
-
- for(int i = 0; i < 4; i++) {
- center[i] = uchar(min(max(val[i], 0.0f), 255.0f));
- }
-
- ngons++;
- }
- }
- } break;
- default: break;
- }
- }
+ char *data = attr.data();
+ size_t stride = attr.data_sizeof();
+ int ngons = 0;
+
+ switch (attr.element) {
+ case ATTR_ELEMENT_VERTEX: {
+ for (int f = 0; f < num_faces; f++) {
+ SubdFace &face = subd_faces[f];
+
+ if (!face.is_quad()) {
+ char *center = data + (verts.size() - num_subd_verts + ngons) * stride;
+ attr.zero_data(center);
+
+ float inv_num_corners = 1.0f / float(face.num_corners);
+
+ for (int corner = 0; corner < face.num_corners; corner++) {
+ attr.add_with_weight(center,
+ data + subd_face_corners[face.start_corner + corner] * stride,
+ inv_num_corners);
+ }
+
+ ngons++;
+ }
+ }
+ } break;
+ case ATTR_ELEMENT_VERTEX_MOTION: {
+ // TODO(mai): implement
+ } break;
+ case ATTR_ELEMENT_CORNER: {
+ for (int f = 0; f < num_faces; f++) {
+ SubdFace &face = subd_faces[f];
+
+ if (!face.is_quad()) {
+ char *center = data + (subd_face_corners.size() + ngons) * stride;
+ attr.zero_data(center);
+
+ float inv_num_corners = 1.0f / float(face.num_corners);
+
+ for (int corner = 0; corner < face.num_corners; corner++) {
+ attr.add_with_weight(
+ center, data + (face.start_corner + corner) * stride, inv_num_corners);
+ }
+
+ ngons++;
+ }
+ }
+ } break;
+ case ATTR_ELEMENT_CORNER_BYTE: {
+ for (int f = 0; f < num_faces; f++) {
+ SubdFace &face = subd_faces[f];
+
+ if (!face.is_quad()) {
+ uchar *center = (uchar *)data + (subd_face_corners.size() + ngons) * stride;
+
+ float inv_num_corners = 1.0f / float(face.num_corners);
+ float4 val = make_float4(0.0f, 0.0f, 0.0f, 0.0f);
+
+ for (int corner = 0; corner < face.num_corners; corner++) {
+ for (int i = 0; i < 4; i++) {
+ val[i] += float(*(data + (face.start_corner + corner) * stride + i)) *
+ inv_num_corners;
+ }
+ }
+
+ for (int i = 0; i < 4; i++) {
+ center[i] = uchar(min(max(val[i], 0.0f), 255.0f));
+ }
+
+ ngons++;
+ }
+ }
+ } break;
+ default:
+ break;
+ }
+ }
#ifdef WITH_OPENSUBDIV
- /* pack patch tables */
- if(need_packed_patch_table) {
- delete patch_table;
- patch_table = new PackedPatchTable;
- patch_table->pack(osd_data.patch_table);
- }
+ /* pack patch tables */
+ if (need_packed_patch_table) {
+ delete patch_table;
+ patch_table = new PackedPatchTable;
+ patch_table->pack(osd_data.patch_table);
+ }
#endif
}
diff --git a/intern/cycles/render/mesh_volume.cpp b/intern/cycles/render/mesh_volume.cpp
index 3ee4124ba0f..a1d61fd4db7 100644
--- a/intern/cycles/render/mesh_volume.cpp
+++ b/intern/cycles/render/mesh_volume.cpp
@@ -27,98 +27,106 @@ CCL_NAMESPACE_BEGIN
static size_t compute_voxel_index(const int3 &resolution, size_t x, size_t y, size_t z)
{
- if(x == -1 || x >= resolution.x) {
- return -1;
- }
+ if (x == -1 || x >= resolution.x) {
+ return -1;
+ }
- if(y == -1 || y >= resolution.y) {
- return -1;
- }
+ if (y == -1 || y >= resolution.y) {
+ return -1;
+ }
- if(z == -1 || z >= resolution.z) {
- return -1;
- }
+ if (z == -1 || z >= resolution.z) {
+ return -1;
+ }
- return x + y*resolution.x + z*resolution.x*resolution.y;
+ return x + y * resolution.x + z * resolution.x * resolution.y;
}
struct QuadData {
- int v0, v1, v2, v3;
+ int v0, v1, v2, v3;
- float3 normal;
+ float3 normal;
};
enum {
- QUAD_X_MIN = 0,
- QUAD_X_MAX = 1,
- QUAD_Y_MIN = 2,
- QUAD_Y_MAX = 3,
- QUAD_Z_MIN = 4,
- QUAD_Z_MAX = 5,
+ QUAD_X_MIN = 0,
+ QUAD_X_MAX = 1,
+ QUAD_Y_MIN = 2,
+ QUAD_Y_MAX = 3,
+ QUAD_Z_MIN = 4,
+ QUAD_Z_MAX = 5,
};
const int quads_indices[6][4] = {
- /* QUAD_X_MIN */
- { 4, 0, 3, 7 },
- /* QUAD_X_MAX */
- { 1, 5, 6, 2 },
- /* QUAD_Y_MIN */
- { 4, 5, 1, 0 },
- /* QUAD_Y_MAX */
- { 3, 2, 6, 7 },
- /* QUAD_Z_MIN */
- { 0, 1, 2, 3 },
- /* QUAD_Z_MAX */
- { 5, 4, 7, 6 },
+ /* QUAD_X_MIN */
+ {4, 0, 3, 7},
+ /* QUAD_X_MAX */
+ {1, 5, 6, 2},
+ /* QUAD_Y_MIN */
+ {4, 5, 1, 0},
+ /* QUAD_Y_MAX */
+ {3, 2, 6, 7},
+ /* QUAD_Z_MIN */
+ {0, 1, 2, 3},
+ /* QUAD_Z_MAX */
+ {5, 4, 7, 6},
};
const float3 quads_normals[6] = {
- /* QUAD_X_MIN */
- make_float3(-1.0f, 0.0f, 0.0f),
- /* QUAD_X_MAX */
- make_float3(1.0f, 0.0f, 0.0f),
- /* QUAD_Y_MIN */
- make_float3(0.0f, -1.0f, 0.0f),
- /* QUAD_Y_MAX */
- make_float3(0.0f, 1.0f, 0.0f),
- /* QUAD_Z_MIN */
- make_float3(0.0f, 0.0f, -1.0f),
- /* QUAD_Z_MAX */
- make_float3(0.0f, 0.0f, 1.0f),
+ /* QUAD_X_MIN */
+ make_float3(-1.0f, 0.0f, 0.0f),
+ /* QUAD_X_MAX */
+ make_float3(1.0f, 0.0f, 0.0f),
+ /* QUAD_Y_MIN */
+ make_float3(0.0f, -1.0f, 0.0f),
+ /* QUAD_Y_MAX */
+ make_float3(0.0f, 1.0f, 0.0f),
+ /* QUAD_Z_MIN */
+ make_float3(0.0f, 0.0f, -1.0f),
+ /* QUAD_Z_MAX */
+ make_float3(0.0f, 0.0f, 1.0f),
};
-static int add_vertex(int3 v, vector<int3> &vertices, int3 res, unordered_map<size_t, int> &used_verts)
+static int add_vertex(int3 v,
+ vector<int3> &vertices,
+ int3 res,
+ unordered_map<size_t, int> &used_verts)
{
- size_t vert_key = v.x + v.y * (res.x+1) + v.z * (res.x+1)*(res.y+1);
- unordered_map<size_t, int>::iterator it = used_verts.find(vert_key);
+ size_t vert_key = v.x + v.y * (res.x + 1) + v.z * (res.x + 1) * (res.y + 1);
+ unordered_map<size_t, int>::iterator it = used_verts.find(vert_key);
- if(it != used_verts.end()) {
- return it->second;
- }
+ if (it != used_verts.end()) {
+ return it->second;
+ }
- int vertex_offset = vertices.size();
- used_verts[vert_key] = vertex_offset;
- vertices.push_back(v);
- return vertex_offset;
+ int vertex_offset = vertices.size();
+ used_verts[vert_key] = vertex_offset;
+ vertices.push_back(v);
+ return vertex_offset;
}
-static void create_quad(int3 corners[8], vector<int3> &vertices, vector<QuadData> &quads, int3 res, unordered_map<size_t, int> &used_verts, int face_index)
+static void create_quad(int3 corners[8],
+ vector<int3> &vertices,
+ vector<QuadData> &quads,
+ int3 res,
+ unordered_map<size_t, int> &used_verts,
+ int face_index)
{
- QuadData quad;
- quad.v0 = add_vertex(corners[quads_indices[face_index][0]], vertices, res, used_verts);
- quad.v1 = add_vertex(corners[quads_indices[face_index][1]], vertices, res, used_verts);
- quad.v2 = add_vertex(corners[quads_indices[face_index][2]], vertices, res, used_verts);
- quad.v3 = add_vertex(corners[quads_indices[face_index][3]], vertices, res, used_verts);
- quad.normal = quads_normals[face_index];
-
- quads.push_back(quad);
+ QuadData quad;
+ quad.v0 = add_vertex(corners[quads_indices[face_index][0]], vertices, res, used_verts);
+ quad.v1 = add_vertex(corners[quads_indices[face_index][1]], vertices, res, used_verts);
+ quad.v2 = add_vertex(corners[quads_indices[face_index][2]], vertices, res, used_verts);
+ quad.v3 = add_vertex(corners[quads_indices[face_index][3]], vertices, res, used_verts);
+ quad.normal = quads_normals[face_index];
+
+ quads.push_back(quad);
}
struct VolumeParams {
- int3 resolution;
- float3 cell_size;
- float3 start_point;
- int pad_size;
+ int3 resolution;
+ float3 cell_size;
+ float3 start_point;
+ int pad_size;
};
static const int CUBE_SIZE = 8;
@@ -135,373 +143,365 @@ static const int CUBE_SIZE = 8;
* volume to generate a tight mesh around the volume.
*/
class VolumeMeshBuilder {
- /* Auxilliary volume that is used to check if a node already added. */
- vector<char> grid;
+ /* Auxilliary volume that is used to check if a node already added. */
+ vector<char> grid;
- /* The resolution of the auxilliary volume, set to be equal to 1/CUBE_SIZE
- * of the original volume on each axis. */
- int3 res;
+ /* The resolution of the auxilliary volume, set to be equal to 1/CUBE_SIZE
+ * of the original volume on each axis. */
+ int3 res;
- size_t number_of_nodes;
+ size_t number_of_nodes;
- /* Offset due to padding in the original grid. Padding will transform the
- * coordinates of the original grid from 0...res to -padding...res+padding,
- * so some coordinates are negative, and we need to properly account for
- * them. */
- int3 pad_offset;
+ /* Offset due to padding in the original grid. Padding will transform the
+ * coordinates of the original grid from 0...res to -padding...res+padding,
+ * so some coordinates are negative, and we need to properly account for
+ * them. */
+ int3 pad_offset;
- VolumeParams *params;
+ VolumeParams *params;
-public:
- VolumeMeshBuilder(VolumeParams *volume_params);
+ public:
+ VolumeMeshBuilder(VolumeParams *volume_params);
- void add_node(int x, int y, int z);
+ void add_node(int x, int y, int z);
- void add_node_with_padding(int x, int y, int z);
+ void add_node_with_padding(int x, int y, int z);
- void create_mesh(vector<float3> &vertices,
- vector<int> &indices,
- vector<float3> &face_normals);
+ void create_mesh(vector<float3> &vertices, vector<int> &indices, vector<float3> &face_normals);
-private:
- void generate_vertices_and_quads(vector<int3> &vertices_is,
- vector<QuadData> &quads);
+ private:
+ void generate_vertices_and_quads(vector<int3> &vertices_is, vector<QuadData> &quads);
- void convert_object_space(const vector<int3> &vertices,
- vector<float3> &out_vertices);
+ void convert_object_space(const vector<int3> &vertices, vector<float3> &out_vertices);
- void convert_quads_to_tris(const vector<QuadData> &quads,
- vector<int> &tris,
- vector<float3> &face_normals);
+ void convert_quads_to_tris(const vector<QuadData> &quads,
+ vector<int> &tris,
+ vector<float3> &face_normals);
};
VolumeMeshBuilder::VolumeMeshBuilder(VolumeParams *volume_params)
{
- params = volume_params;
- number_of_nodes = 0;
+ params = volume_params;
+ number_of_nodes = 0;
- const size_t x = divide_up(params->resolution.x, CUBE_SIZE);
- const size_t y = divide_up(params->resolution.y, CUBE_SIZE);
- const size_t z = divide_up(params->resolution.z, CUBE_SIZE);
+ const size_t x = divide_up(params->resolution.x, CUBE_SIZE);
+ const size_t y = divide_up(params->resolution.y, CUBE_SIZE);
+ const size_t z = divide_up(params->resolution.z, CUBE_SIZE);
- /* Adding 2*pad_size since we pad in both positive and negative directions
- * along the axis. */
- const size_t px = divide_up(params->resolution.x + 2*params->pad_size, CUBE_SIZE);
- const size_t py = divide_up(params->resolution.y + 2*params->pad_size, CUBE_SIZE);
- const size_t pz = divide_up(params->resolution.z + 2*params->pad_size, CUBE_SIZE);
+ /* Adding 2*pad_size since we pad in both positive and negative directions
+ * along the axis. */
+ const size_t px = divide_up(params->resolution.x + 2 * params->pad_size, CUBE_SIZE);
+ const size_t py = divide_up(params->resolution.y + 2 * params->pad_size, CUBE_SIZE);
+ const size_t pz = divide_up(params->resolution.z + 2 * params->pad_size, CUBE_SIZE);
- res = make_int3(px, py, pz);
- pad_offset = make_int3(px - x, py - y, pz - z);
+ res = make_int3(px, py, pz);
+ pad_offset = make_int3(px - x, py - y, pz - z);
- grid.resize(px*py*pz, 0);
+ grid.resize(px * py * pz, 0);
}
void VolumeMeshBuilder::add_node(int x, int y, int z)
{
- /* Map coordinates to index space. */
- const int index_x = (x/CUBE_SIZE) + pad_offset.x;
- const int index_y = (y/CUBE_SIZE) + pad_offset.y;
- const int index_z = (z/CUBE_SIZE) + pad_offset.z;
+ /* Map coordinates to index space. */
+ const int index_x = (x / CUBE_SIZE) + pad_offset.x;
+ const int index_y = (y / CUBE_SIZE) + pad_offset.y;
+ const int index_z = (z / CUBE_SIZE) + pad_offset.z;
- assert((index_x >= 0) && (index_y >= 0) && (index_z >= 0));
+ assert((index_x >= 0) && (index_y >= 0) && (index_z >= 0));
- const size_t index = compute_voxel_index(res, index_x, index_y, index_z);
+ const size_t index = compute_voxel_index(res, index_x, index_y, index_z);
- /* We already have a node here. */
- if(grid[index] == 1) {
- return;
- }
+ /* We already have a node here. */
+ if (grid[index] == 1) {
+ return;
+ }
- ++number_of_nodes;
+ ++number_of_nodes;
- grid[index] = 1;
+ grid[index] = 1;
}
void VolumeMeshBuilder::add_node_with_padding(int x, int y, int z)
{
- for(int px = x - params->pad_size; px < x + params->pad_size; ++px) {
- for(int py = y - params->pad_size; py < y + params->pad_size; ++py) {
- for(int pz = z - params->pad_size; pz < z + params->pad_size; ++pz) {
- add_node(px, py, pz);
- }
- }
- }
+ for (int px = x - params->pad_size; px < x + params->pad_size; ++px) {
+ for (int py = y - params->pad_size; py < y + params->pad_size; ++py) {
+ for (int pz = z - params->pad_size; pz < z + params->pad_size; ++pz) {
+ add_node(px, py, pz);
+ }
+ }
+ }
}
void VolumeMeshBuilder::create_mesh(vector<float3> &vertices,
vector<int> &indices,
vector<float3> &face_normals)
{
- /* We create vertices in index space (is), and only convert them to object
- * space when done. */
- vector<int3> vertices_is;
- vector<QuadData> quads;
+ /* We create vertices in index space (is), and only convert them to object
+ * space when done. */
+ vector<int3> vertices_is;
+ vector<QuadData> quads;
- generate_vertices_and_quads(vertices_is, quads);
+ generate_vertices_and_quads(vertices_is, quads);
- convert_object_space(vertices_is, vertices);
+ convert_object_space(vertices_is, vertices);
- convert_quads_to_tris(quads, indices, face_normals);
+ convert_quads_to_tris(quads, indices, face_normals);
}
-void VolumeMeshBuilder::generate_vertices_and_quads(
- vector<ccl::int3> &vertices_is,
- vector<QuadData> &quads)
+void VolumeMeshBuilder::generate_vertices_and_quads(vector<ccl::int3> &vertices_is,
+ vector<QuadData> &quads)
{
- unordered_map<size_t, int> used_verts;
-
- for(int z = 0; z < res.z; ++z) {
- for(int y = 0; y < res.y; ++y) {
- for(int x = 0; x < res.x; ++x) {
- size_t voxel_index = compute_voxel_index(res, x, y, z);
- if(grid[voxel_index] == 0) {
- continue;
- }
-
- /* Compute min and max coords of the node in index space. */
- int3 min = make_int3((x - pad_offset.x)*CUBE_SIZE,
- (y - pad_offset.y)*CUBE_SIZE,
- (z - pad_offset.z)*CUBE_SIZE);
-
- /* Maximum is just CUBE_SIZE voxels away from minimum on each axis. */
- int3 max = make_int3(min.x + CUBE_SIZE, min.y + CUBE_SIZE, min.z + CUBE_SIZE);
-
- int3 corners[8] = {
- make_int3(min[0], min[1], min[2]),
- make_int3(max[0], min[1], min[2]),
- make_int3(max[0], max[1], min[2]),
- make_int3(min[0], max[1], min[2]),
- make_int3(min[0], min[1], max[2]),
- make_int3(max[0], min[1], max[2]),
- make_int3(max[0], max[1], max[2]),
- make_int3(min[0], max[1], max[2]),
- };
-
- /* Only create a quad if on the border between an active and
- * an inactive node.
- */
-
- voxel_index = compute_voxel_index(res, x - 1, y, z);
- if(voxel_index == -1 || grid[voxel_index] == 0) {
- create_quad(corners, vertices_is, quads, res, used_verts, QUAD_X_MIN);
- }
-
- voxel_index = compute_voxel_index(res, x + 1, y, z);
- if(voxel_index == -1 || grid[voxel_index] == 0) {
- create_quad(corners, vertices_is, quads, res, used_verts, QUAD_X_MAX);
- }
-
- voxel_index = compute_voxel_index(res, x, y - 1, z);
- if(voxel_index == -1 || grid[voxel_index] == 0) {
- create_quad(corners, vertices_is, quads, res, used_verts, QUAD_Y_MIN);
- }
-
- voxel_index = compute_voxel_index(res, x, y + 1, z);
- if(voxel_index == -1 || grid[voxel_index] == 0) {
- create_quad(corners, vertices_is, quads, res, used_verts, QUAD_Y_MAX);
- }
-
- voxel_index = compute_voxel_index(res, x, y, z - 1);
- if(voxel_index == -1 || grid[voxel_index] == 0) {
- create_quad(corners, vertices_is, quads, res, used_verts, QUAD_Z_MIN);
- }
-
- voxel_index = compute_voxel_index(res, x, y, z + 1);
- if(voxel_index == -1 || grid[voxel_index] == 0) {
- create_quad(corners, vertices_is, quads, res, used_verts, QUAD_Z_MAX);
- }
- }
- }
- }
+ unordered_map<size_t, int> used_verts;
+
+ for (int z = 0; z < res.z; ++z) {
+ for (int y = 0; y < res.y; ++y) {
+ for (int x = 0; x < res.x; ++x) {
+ size_t voxel_index = compute_voxel_index(res, x, y, z);
+ if (grid[voxel_index] == 0) {
+ continue;
+ }
+
+ /* Compute min and max coords of the node in index space. */
+ int3 min = make_int3((x - pad_offset.x) * CUBE_SIZE,
+ (y - pad_offset.y) * CUBE_SIZE,
+ (z - pad_offset.z) * CUBE_SIZE);
+
+ /* Maximum is just CUBE_SIZE voxels away from minimum on each axis. */
+ int3 max = make_int3(min.x + CUBE_SIZE, min.y + CUBE_SIZE, min.z + CUBE_SIZE);
+
+ int3 corners[8] = {
+ make_int3(min[0], min[1], min[2]),
+ make_int3(max[0], min[1], min[2]),
+ make_int3(max[0], max[1], min[2]),
+ make_int3(min[0], max[1], min[2]),
+ make_int3(min[0], min[1], max[2]),
+ make_int3(max[0], min[1], max[2]),
+ make_int3(max[0], max[1], max[2]),
+ make_int3(min[0], max[1], max[2]),
+ };
+
+ /* Only create a quad if on the border between an active and
+ * an inactive node.
+ */
+
+ voxel_index = compute_voxel_index(res, x - 1, y, z);
+ if (voxel_index == -1 || grid[voxel_index] == 0) {
+ create_quad(corners, vertices_is, quads, res, used_verts, QUAD_X_MIN);
+ }
+
+ voxel_index = compute_voxel_index(res, x + 1, y, z);
+ if (voxel_index == -1 || grid[voxel_index] == 0) {
+ create_quad(corners, vertices_is, quads, res, used_verts, QUAD_X_MAX);
+ }
+
+ voxel_index = compute_voxel_index(res, x, y - 1, z);
+ if (voxel_index == -1 || grid[voxel_index] == 0) {
+ create_quad(corners, vertices_is, quads, res, used_verts, QUAD_Y_MIN);
+ }
+
+ voxel_index = compute_voxel_index(res, x, y + 1, z);
+ if (voxel_index == -1 || grid[voxel_index] == 0) {
+ create_quad(corners, vertices_is, quads, res, used_verts, QUAD_Y_MAX);
+ }
+
+ voxel_index = compute_voxel_index(res, x, y, z - 1);
+ if (voxel_index == -1 || grid[voxel_index] == 0) {
+ create_quad(corners, vertices_is, quads, res, used_verts, QUAD_Z_MIN);
+ }
+
+ voxel_index = compute_voxel_index(res, x, y, z + 1);
+ if (voxel_index == -1 || grid[voxel_index] == 0) {
+ create_quad(corners, vertices_is, quads, res, used_verts, QUAD_Z_MAX);
+ }
+ }
+ }
+ }
}
void VolumeMeshBuilder::convert_object_space(const vector<int3> &vertices,
- vector<float3> &out_vertices)
+ vector<float3> &out_vertices)
{
- out_vertices.reserve(vertices.size());
+ out_vertices.reserve(vertices.size());
- for(size_t i = 0; i < vertices.size(); ++i) {
- float3 vertex = make_float3(vertices[i].x, vertices[i].y, vertices[i].z);
- vertex *= params->cell_size;
- vertex += params->start_point;
+ for (size_t i = 0; i < vertices.size(); ++i) {
+ float3 vertex = make_float3(vertices[i].x, vertices[i].y, vertices[i].z);
+ vertex *= params->cell_size;
+ vertex += params->start_point;
- out_vertices.push_back(vertex);
- }
+ out_vertices.push_back(vertex);
+ }
}
void VolumeMeshBuilder::convert_quads_to_tris(const vector<QuadData> &quads,
vector<int> &tris,
vector<float3> &face_normals)
{
- int index_offset = 0;
- tris.resize(quads.size()*6);
- face_normals.reserve(quads.size()*2);
+ int index_offset = 0;
+ tris.resize(quads.size() * 6);
+ face_normals.reserve(quads.size() * 2);
- for(size_t i = 0; i < quads.size(); ++i) {
- tris[index_offset++] = quads[i].v0;
- tris[index_offset++] = quads[i].v2;
- tris[index_offset++] = quads[i].v1;
+ for (size_t i = 0; i < quads.size(); ++i) {
+ tris[index_offset++] = quads[i].v0;
+ tris[index_offset++] = quads[i].v2;
+ tris[index_offset++] = quads[i].v1;
- face_normals.push_back(quads[i].normal);
+ face_normals.push_back(quads[i].normal);
- tris[index_offset++] = quads[i].v0;
- tris[index_offset++] = quads[i].v3;
- tris[index_offset++] = quads[i].v2;
+ tris[index_offset++] = quads[i].v0;
+ tris[index_offset++] = quads[i].v3;
+ tris[index_offset++] = quads[i].v2;
- face_normals.push_back(quads[i].normal);
- }
+ face_normals.push_back(quads[i].normal);
+ }
}
/* ************************************************************************** */
struct VoxelAttributeGrid {
- float *data;
- int channels;
+ float *data;
+ int channels;
};
-void MeshManager::create_volume_mesh(Scene *scene,
- Mesh *mesh,
- Progress& progress)
+void MeshManager::create_volume_mesh(Scene *scene, Mesh *mesh, Progress &progress)
{
- string msg = string_printf("Computing Volume Mesh %s", mesh->name.c_str());
- progress.set_status("Updating Mesh", msg);
-
- vector<VoxelAttributeGrid> voxel_grids;
-
- /* Compute volume parameters. */
- VolumeParams volume_params;
- volume_params.resolution = make_int3(0, 0, 0);
-
- foreach(Attribute& attr, mesh->attributes.attributes) {
- if(attr.element != ATTR_ELEMENT_VOXEL) {
- continue;
- }
-
- VoxelAttribute *voxel = attr.data_voxel();
- device_memory *image_memory = scene->image_manager->image_memory(voxel->slot);
- int3 resolution = make_int3(image_memory->data_width,
- image_memory->data_height,
- image_memory->data_depth);
-
- if(volume_params.resolution == make_int3(0, 0, 0)) {
- volume_params.resolution = resolution;
- }
- else if(volume_params.resolution != resolution) {
- VLOG(1) << "Can't create volume mesh, all voxel grid resolutions must be equal\n";
- return;
- }
-
- VoxelAttributeGrid voxel_grid;
- voxel_grid.data = static_cast<float*>(image_memory->host_pointer);
- voxel_grid.channels = image_memory->data_elements;
- voxel_grids.push_back(voxel_grid);
- }
-
- if(voxel_grids.empty()) {
- return;
- }
-
- /* Compute padding. */
- Shader *volume_shader = NULL;
- int pad_size = 0;
-
- foreach(Shader *shader, mesh->used_shaders) {
- if(!shader->has_volume) {
- continue;
- }
-
- volume_shader = shader;
-
- if(shader->volume_interpolation_method == VOLUME_INTERPOLATION_LINEAR) {
- pad_size = max(1, pad_size);
- }
- else if(shader->volume_interpolation_method == VOLUME_INTERPOLATION_CUBIC) {
- pad_size = max(2, pad_size);
- }
-
- break;
- }
-
- if(!volume_shader) {
- return;
- }
-
- /* Compute start point and cell size from transform. */
- Attribute *attr = mesh->attributes.find(ATTR_STD_GENERATED_TRANSFORM);
- const int3 resolution = volume_params.resolution;
- float3 start_point = make_float3(0.0f, 0.0f, 0.0f);
- float3 cell_size = make_float3(1.0f/resolution.x,
- 1.0f/resolution.y,
- 1.0f/resolution.z);
-
- if(attr) {
- const Transform *tfm = attr->data_transform();
- const Transform itfm = transform_inverse(*tfm);
- start_point = transform_point(&itfm, start_point);
- cell_size = transform_direction(&itfm, cell_size);
- }
-
- volume_params.start_point = start_point;
- volume_params.cell_size = cell_size;
- volume_params.pad_size = pad_size;
-
- /* Build bounding mesh around non-empty volume cells. */
- VolumeMeshBuilder builder(&volume_params);
- const float isovalue = mesh->volume_isovalue;
-
- for(int z = 0; z < resolution.z; ++z) {
- for(int y = 0; y < resolution.y; ++y) {
- for(int x = 0; x < resolution.x; ++x) {
- size_t voxel_index = compute_voxel_index(resolution, x, y, z);
-
- for(size_t i = 0; i < voxel_grids.size(); ++i) {
- const VoxelAttributeGrid &voxel_grid = voxel_grids[i];
- const int channels = voxel_grid.channels;
-
- for(int c = 0; c < channels; c++) {
- if(voxel_grid.data[voxel_index * channels + c] >= isovalue) {
- builder.add_node_with_padding(x, y, z);
- break;
- }
- }
- }
- }
- }
- }
-
- /* Create mesh. */
- vector<float3> vertices;
- vector<int> indices;
- vector<float3> face_normals;
- builder.create_mesh(vertices, indices, face_normals);
-
- mesh->clear(true);
- mesh->reserve_mesh(vertices.size(), indices.size()/3);
- mesh->used_shaders.push_back(volume_shader);
-
- for(size_t i = 0; i < vertices.size(); ++i) {
- mesh->add_vertex(vertices[i]);
- }
-
- for(size_t i = 0; i < indices.size(); i += 3) {
- mesh->add_triangle(indices[i], indices[i + 1], indices[i + 2], 0, false);
- }
-
- Attribute *attr_fN = mesh->attributes.add(ATTR_STD_FACE_NORMAL);
- float3 *fN = attr_fN->data_float3();
-
- for(size_t i = 0; i < face_normals.size(); ++i) {
- fN[i] = face_normals[i];
- }
-
- /* Print stats. */
- VLOG(1) << "Memory usage volume mesh: "
- << ((vertices.size() + face_normals.size())*sizeof(float3) + indices.size()*sizeof(int))/(1024.0*1024.0)
- << "Mb.";
-
- VLOG(1) << "Memory usage volume grid: "
- << (resolution.x*resolution.y*resolution.z*sizeof(float))/(1024.0*1024.0)
- << "Mb.";
+ string msg = string_printf("Computing Volume Mesh %s", mesh->name.c_str());
+ progress.set_status("Updating Mesh", msg);
+
+ vector<VoxelAttributeGrid> voxel_grids;
+
+ /* Compute volume parameters. */
+ VolumeParams volume_params;
+ volume_params.resolution = make_int3(0, 0, 0);
+
+ foreach (Attribute &attr, mesh->attributes.attributes) {
+ if (attr.element != ATTR_ELEMENT_VOXEL) {
+ continue;
+ }
+
+ VoxelAttribute *voxel = attr.data_voxel();
+ device_memory *image_memory = scene->image_manager->image_memory(voxel->slot);
+ int3 resolution = make_int3(
+ image_memory->data_width, image_memory->data_height, image_memory->data_depth);
+
+ if (volume_params.resolution == make_int3(0, 0, 0)) {
+ volume_params.resolution = resolution;
+ }
+ else if (volume_params.resolution != resolution) {
+ VLOG(1) << "Can't create volume mesh, all voxel grid resolutions must be equal\n";
+ return;
+ }
+
+ VoxelAttributeGrid voxel_grid;
+ voxel_grid.data = static_cast<float *>(image_memory->host_pointer);
+ voxel_grid.channels = image_memory->data_elements;
+ voxel_grids.push_back(voxel_grid);
+ }
+
+ if (voxel_grids.empty()) {
+ return;
+ }
+
+ /* Compute padding. */
+ Shader *volume_shader = NULL;
+ int pad_size = 0;
+
+ foreach (Shader *shader, mesh->used_shaders) {
+ if (!shader->has_volume) {
+ continue;
+ }
+
+ volume_shader = shader;
+
+ if (shader->volume_interpolation_method == VOLUME_INTERPOLATION_LINEAR) {
+ pad_size = max(1, pad_size);
+ }
+ else if (shader->volume_interpolation_method == VOLUME_INTERPOLATION_CUBIC) {
+ pad_size = max(2, pad_size);
+ }
+
+ break;
+ }
+
+ if (!volume_shader) {
+ return;
+ }
+
+ /* Compute start point and cell size from transform. */
+ Attribute *attr = mesh->attributes.find(ATTR_STD_GENERATED_TRANSFORM);
+ const int3 resolution = volume_params.resolution;
+ float3 start_point = make_float3(0.0f, 0.0f, 0.0f);
+ float3 cell_size = make_float3(1.0f / resolution.x, 1.0f / resolution.y, 1.0f / resolution.z);
+
+ if (attr) {
+ const Transform *tfm = attr->data_transform();
+ const Transform itfm = transform_inverse(*tfm);
+ start_point = transform_point(&itfm, start_point);
+ cell_size = transform_direction(&itfm, cell_size);
+ }
+
+ volume_params.start_point = start_point;
+ volume_params.cell_size = cell_size;
+ volume_params.pad_size = pad_size;
+
+ /* Build bounding mesh around non-empty volume cells. */
+ VolumeMeshBuilder builder(&volume_params);
+ const float isovalue = mesh->volume_isovalue;
+
+ for (int z = 0; z < resolution.z; ++z) {
+ for (int y = 0; y < resolution.y; ++y) {
+ for (int x = 0; x < resolution.x; ++x) {
+ size_t voxel_index = compute_voxel_index(resolution, x, y, z);
+
+ for (size_t i = 0; i < voxel_grids.size(); ++i) {
+ const VoxelAttributeGrid &voxel_grid = voxel_grids[i];
+ const int channels = voxel_grid.channels;
+
+ for (int c = 0; c < channels; c++) {
+ if (voxel_grid.data[voxel_index * channels + c] >= isovalue) {
+ builder.add_node_with_padding(x, y, z);
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ /* Create mesh. */
+ vector<float3> vertices;
+ vector<int> indices;
+ vector<float3> face_normals;
+ builder.create_mesh(vertices, indices, face_normals);
+
+ mesh->clear(true);
+ mesh->reserve_mesh(vertices.size(), indices.size() / 3);
+ mesh->used_shaders.push_back(volume_shader);
+
+ for (size_t i = 0; i < vertices.size(); ++i) {
+ mesh->add_vertex(vertices[i]);
+ }
+
+ for (size_t i = 0; i < indices.size(); i += 3) {
+ mesh->add_triangle(indices[i], indices[i + 1], indices[i + 2], 0, false);
+ }
+
+ Attribute *attr_fN = mesh->attributes.add(ATTR_STD_FACE_NORMAL);
+ float3 *fN = attr_fN->data_float3();
+
+ for (size_t i = 0; i < face_normals.size(); ++i) {
+ fN[i] = face_normals[i];
+ }
+
+ /* Print stats. */
+ VLOG(1) << "Memory usage volume mesh: "
+ << ((vertices.size() + face_normals.size()) * sizeof(float3) +
+ indices.size() * sizeof(int)) /
+ (1024.0 * 1024.0)
+ << "Mb.";
+
+ VLOG(1) << "Memory usage volume grid: "
+ << (resolution.x * resolution.y * resolution.z * sizeof(float)) / (1024.0 * 1024.0)
+ << "Mb.";
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/render/nodes.cpp b/intern/cycles/render/nodes.cpp
index cc9dd8f2679..f3572ee1585 100644
--- a/intern/cycles/render/nodes.cpp
+++ b/intern/cycles/render/nodes.cpp
@@ -37,36 +37,36 @@ CCL_NAMESPACE_BEGIN
/* Texture Mapping */
#define TEXTURE_MAPPING_DEFINE(TextureNode) \
- SOCKET_POINT(tex_mapping.translation, "Translation", make_float3(0.0f, 0.0f, 0.0f)); \
- SOCKET_VECTOR(tex_mapping.rotation, "Rotation", make_float3(0.0f, 0.0f, 0.0f)); \
- SOCKET_VECTOR(tex_mapping.scale, "Scale", make_float3(1.0f, 1.0f, 1.0f)); \
- \
- SOCKET_VECTOR(tex_mapping.min, "Min", make_float3(-FLT_MAX, -FLT_MAX, -FLT_MAX)); \
- SOCKET_VECTOR(tex_mapping.max, "Max", make_float3(FLT_MAX, FLT_MAX, FLT_MAX)); \
- SOCKET_BOOLEAN(tex_mapping.use_minmax, "Use Min Max", false); \
- \
- static NodeEnum mapping_axis_enum; \
- mapping_axis_enum.insert("none", TextureMapping::NONE); \
- mapping_axis_enum.insert("x", TextureMapping::X); \
- mapping_axis_enum.insert("y", TextureMapping::Y); \
- mapping_axis_enum.insert("z", TextureMapping::Z); \
- SOCKET_ENUM(tex_mapping.x_mapping, "x_mapping", mapping_axis_enum, TextureMapping::X); \
- SOCKET_ENUM(tex_mapping.y_mapping, "y_mapping", mapping_axis_enum, TextureMapping::Y); \
- SOCKET_ENUM(tex_mapping.z_mapping, "z_mapping", mapping_axis_enum, TextureMapping::Z); \
- \
- static NodeEnum mapping_type_enum; \
- mapping_type_enum.insert("point", TextureMapping::POINT); \
- mapping_type_enum.insert("texture", TextureMapping::TEXTURE); \
- mapping_type_enum.insert("vector", TextureMapping::VECTOR); \
- mapping_type_enum.insert("normal", TextureMapping::NORMAL); \
- SOCKET_ENUM(tex_mapping.type, "Type", mapping_type_enum, TextureMapping::TEXTURE); \
- \
- static NodeEnum mapping_projection_enum; \
- mapping_projection_enum.insert("flat", TextureMapping::FLAT); \
- mapping_projection_enum.insert("cube", TextureMapping::CUBE); \
- mapping_projection_enum.insert("tube", TextureMapping::TUBE); \
- mapping_projection_enum.insert("sphere", TextureMapping::SPHERE); \
- SOCKET_ENUM(tex_mapping.projection, "Projection", mapping_projection_enum, TextureMapping::FLAT);
+ SOCKET_POINT(tex_mapping.translation, "Translation", make_float3(0.0f, 0.0f, 0.0f)); \
+ SOCKET_VECTOR(tex_mapping.rotation, "Rotation", make_float3(0.0f, 0.0f, 0.0f)); \
+ SOCKET_VECTOR(tex_mapping.scale, "Scale", make_float3(1.0f, 1.0f, 1.0f)); \
+\
+ SOCKET_VECTOR(tex_mapping.min, "Min", make_float3(-FLT_MAX, -FLT_MAX, -FLT_MAX)); \
+ SOCKET_VECTOR(tex_mapping.max, "Max", make_float3(FLT_MAX, FLT_MAX, FLT_MAX)); \
+ SOCKET_BOOLEAN(tex_mapping.use_minmax, "Use Min Max", false); \
+\
+ static NodeEnum mapping_axis_enum; \
+ mapping_axis_enum.insert("none", TextureMapping::NONE); \
+ mapping_axis_enum.insert("x", TextureMapping::X); \
+ mapping_axis_enum.insert("y", TextureMapping::Y); \
+ mapping_axis_enum.insert("z", TextureMapping::Z); \
+ SOCKET_ENUM(tex_mapping.x_mapping, "x_mapping", mapping_axis_enum, TextureMapping::X); \
+ SOCKET_ENUM(tex_mapping.y_mapping, "y_mapping", mapping_axis_enum, TextureMapping::Y); \
+ SOCKET_ENUM(tex_mapping.z_mapping, "z_mapping", mapping_axis_enum, TextureMapping::Z); \
+\
+ static NodeEnum mapping_type_enum; \
+ mapping_type_enum.insert("point", TextureMapping::POINT); \
+ mapping_type_enum.insert("texture", TextureMapping::TEXTURE); \
+ mapping_type_enum.insert("vector", TextureMapping::VECTOR); \
+ mapping_type_enum.insert("normal", TextureMapping::NORMAL); \
+ SOCKET_ENUM(tex_mapping.type, "Type", mapping_type_enum, TextureMapping::TEXTURE); \
+\
+ static NodeEnum mapping_projection_enum; \
+ mapping_projection_enum.insert("flat", TextureMapping::FLAT); \
+ mapping_projection_enum.insert("cube", TextureMapping::CUBE); \
+ mapping_projection_enum.insert("tube", TextureMapping::TUBE); \
+ mapping_projection_enum.insert("sphere", TextureMapping::SPHERE); \
+ SOCKET_ENUM(tex_mapping.projection, "Projection", mapping_projection_enum, TextureMapping::FLAT);
TextureMapping::TextureMapping()
{
@@ -74,6146 +74,6096 @@ TextureMapping::TextureMapping()
Transform TextureMapping::compute_transform()
{
- Transform mmat = transform_scale(make_float3(0.0f, 0.0f, 0.0f));
-
- if(x_mapping != NONE)
- mmat[0][x_mapping-1] = 1.0f;
- if(y_mapping != NONE)
- mmat[1][y_mapping-1] = 1.0f;
- if(z_mapping != NONE)
- mmat[2][z_mapping-1] = 1.0f;
-
- float3 scale_clamped = scale;
-
- if(type == TEXTURE || type == NORMAL) {
- /* keep matrix invertible */
- if(fabsf(scale.x) < 1e-5f)
- scale_clamped.x = signf(scale.x)*1e-5f;
- if(fabsf(scale.y) < 1e-5f)
- scale_clamped.y = signf(scale.y)*1e-5f;
- if(fabsf(scale.z) < 1e-5f)
- scale_clamped.z = signf(scale.z)*1e-5f;
- }
-
- Transform smat = transform_scale(scale_clamped);
- Transform rmat = transform_euler(rotation);
- Transform tmat = transform_translate(translation);
-
- Transform mat;
-
- switch(type) {
- case TEXTURE:
- /* inverse transform on texture coordinate gives
- * forward transform on texture */
- mat = tmat*rmat*smat;
- mat = transform_inverse(mat);
- break;
- case POINT:
- /* full transform */
- mat = tmat*rmat*smat;
- break;
- case VECTOR:
- /* no translation for vectors */
- mat = rmat*smat;
- break;
- case NORMAL:
- /* no translation for normals, and inverse transpose */
- mat = rmat*smat;
- mat = transform_transposed_inverse(mat);
- break;
- }
-
- /* projection last */
- mat = mat*mmat;
-
- return mat;
+ Transform mmat = transform_scale(make_float3(0.0f, 0.0f, 0.0f));
+
+ if (x_mapping != NONE)
+ mmat[0][x_mapping - 1] = 1.0f;
+ if (y_mapping != NONE)
+ mmat[1][y_mapping - 1] = 1.0f;
+ if (z_mapping != NONE)
+ mmat[2][z_mapping - 1] = 1.0f;
+
+ float3 scale_clamped = scale;
+
+ if (type == TEXTURE || type == NORMAL) {
+ /* keep matrix invertible */
+ if (fabsf(scale.x) < 1e-5f)
+ scale_clamped.x = signf(scale.x) * 1e-5f;
+ if (fabsf(scale.y) < 1e-5f)
+ scale_clamped.y = signf(scale.y) * 1e-5f;
+ if (fabsf(scale.z) < 1e-5f)
+ scale_clamped.z = signf(scale.z) * 1e-5f;
+ }
+
+ Transform smat = transform_scale(scale_clamped);
+ Transform rmat = transform_euler(rotation);
+ Transform tmat = transform_translate(translation);
+
+ Transform mat;
+
+ switch (type) {
+ case TEXTURE:
+ /* inverse transform on texture coordinate gives
+ * forward transform on texture */
+ mat = tmat * rmat * smat;
+ mat = transform_inverse(mat);
+ break;
+ case POINT:
+ /* full transform */
+ mat = tmat * rmat * smat;
+ break;
+ case VECTOR:
+ /* no translation for vectors */
+ mat = rmat * smat;
+ break;
+ case NORMAL:
+ /* no translation for normals, and inverse transpose */
+ mat = rmat * smat;
+ mat = transform_transposed_inverse(mat);
+ break;
+ }
+
+ /* projection last */
+ mat = mat * mmat;
+
+ return mat;
}
bool TextureMapping::skip()
{
- if(translation != make_float3(0.0f, 0.0f, 0.0f))
- return false;
- if(rotation != make_float3(0.0f, 0.0f, 0.0f))
- return false;
- if(scale != make_float3(1.0f, 1.0f, 1.0f))
- return false;
+ if (translation != make_float3(0.0f, 0.0f, 0.0f))
+ return false;
+ if (rotation != make_float3(0.0f, 0.0f, 0.0f))
+ return false;
+ if (scale != make_float3(1.0f, 1.0f, 1.0f))
+ return false;
- if(x_mapping != X || y_mapping != Y || z_mapping != Z)
- return false;
- if(use_minmax)
- return false;
+ if (x_mapping != X || y_mapping != Y || z_mapping != Z)
+ return false;
+ if (use_minmax)
+ return false;
- return true;
+ return true;
}
-void TextureMapping::compile(SVMCompiler& compiler, int offset_in, int offset_out)
+void TextureMapping::compile(SVMCompiler &compiler, int offset_in, int offset_out)
{
- compiler.add_node(NODE_MAPPING, offset_in, offset_out);
+ compiler.add_node(NODE_MAPPING, offset_in, offset_out);
- Transform tfm = compute_transform();
- compiler.add_node(tfm.x);
- compiler.add_node(tfm.y);
- compiler.add_node(tfm.z);
+ Transform tfm = compute_transform();
+ compiler.add_node(tfm.x);
+ compiler.add_node(tfm.y);
+ compiler.add_node(tfm.z);
- if(use_minmax) {
- compiler.add_node(NODE_MIN_MAX, offset_out, offset_out);
- compiler.add_node(float3_to_float4(min));
- compiler.add_node(float3_to_float4(max));
- }
+ if (use_minmax) {
+ compiler.add_node(NODE_MIN_MAX, offset_out, offset_out);
+ compiler.add_node(float3_to_float4(min));
+ compiler.add_node(float3_to_float4(max));
+ }
- if(type == NORMAL) {
- compiler.add_node(NODE_VECTOR_MATH, NODE_VECTOR_MATH_NORMALIZE, offset_out, offset_out);
- compiler.add_node(NODE_VECTOR_MATH, SVM_STACK_INVALID, offset_out);
- }
+ if (type == NORMAL) {
+ compiler.add_node(NODE_VECTOR_MATH, NODE_VECTOR_MATH_NORMALIZE, offset_out, offset_out);
+ compiler.add_node(NODE_VECTOR_MATH, SVM_STACK_INVALID, offset_out);
+ }
}
/* Convenience function for texture nodes, allocating stack space to output
* a modified vector and returning its offset */
-int TextureMapping::compile_begin(SVMCompiler& compiler, ShaderInput *vector_in)
+int TextureMapping::compile_begin(SVMCompiler &compiler, ShaderInput *vector_in)
{
- if(!skip()) {
- int offset_in = compiler.stack_assign(vector_in);
- int offset_out = compiler.stack_find_offset(SocketType::VECTOR);
+ if (!skip()) {
+ int offset_in = compiler.stack_assign(vector_in);
+ int offset_out = compiler.stack_find_offset(SocketType::VECTOR);
- compile(compiler, offset_in, offset_out);
+ compile(compiler, offset_in, offset_out);
- return offset_out;
- }
+ return offset_out;
+ }
- return compiler.stack_assign(vector_in);
+ return compiler.stack_assign(vector_in);
}
-void TextureMapping::compile_end(SVMCompiler& compiler, ShaderInput *vector_in, int vector_offset)
+void TextureMapping::compile_end(SVMCompiler &compiler, ShaderInput *vector_in, int vector_offset)
{
- if(!skip()) {
- compiler.stack_clear_offset(vector_in->type(), vector_offset);
- }
+ if (!skip()) {
+ compiler.stack_clear_offset(vector_in->type(), vector_offset);
+ }
}
void TextureMapping::compile(OSLCompiler &compiler)
{
- if(!skip()) {
- compiler.parameter("mapping", compute_transform());
- compiler.parameter("use_mapping", 1);
- }
+ if (!skip()) {
+ compiler.parameter("mapping", compute_transform());
+ compiler.parameter("use_mapping", 1);
+ }
}
/* Image Texture */
NODE_DEFINE(ImageTextureNode)
{
- NodeType* type = NodeType::add("image_texture", create, NodeType::SHADER);
+ NodeType *type = NodeType::add("image_texture", create, NodeType::SHADER);
- TEXTURE_MAPPING_DEFINE(ImageTextureNode);
+ TEXTURE_MAPPING_DEFINE(ImageTextureNode);
- SOCKET_STRING(filename, "Filename", ustring());
+ SOCKET_STRING(filename, "Filename", ustring());
- static NodeEnum color_space_enum;
- color_space_enum.insert("none", NODE_COLOR_SPACE_NONE);
- color_space_enum.insert("color", NODE_COLOR_SPACE_COLOR);
- SOCKET_ENUM(color_space, "Color Space", color_space_enum, NODE_COLOR_SPACE_COLOR);
+ static NodeEnum color_space_enum;
+ color_space_enum.insert("none", NODE_COLOR_SPACE_NONE);
+ color_space_enum.insert("color", NODE_COLOR_SPACE_COLOR);
+ SOCKET_ENUM(color_space, "Color Space", color_space_enum, NODE_COLOR_SPACE_COLOR);
- SOCKET_BOOLEAN(use_alpha, "Use Alpha", true);
+ SOCKET_BOOLEAN(use_alpha, "Use Alpha", true);
- static NodeEnum interpolation_enum;
- interpolation_enum.insert("closest", INTERPOLATION_CLOSEST);
- interpolation_enum.insert("linear", INTERPOLATION_LINEAR);
- interpolation_enum.insert("cubic", INTERPOLATION_CUBIC);
- interpolation_enum.insert("smart", INTERPOLATION_SMART);
- SOCKET_ENUM(interpolation, "Interpolation", interpolation_enum, INTERPOLATION_LINEAR);
+ static NodeEnum interpolation_enum;
+ interpolation_enum.insert("closest", INTERPOLATION_CLOSEST);
+ interpolation_enum.insert("linear", INTERPOLATION_LINEAR);
+ interpolation_enum.insert("cubic", INTERPOLATION_CUBIC);
+ interpolation_enum.insert("smart", INTERPOLATION_SMART);
+ SOCKET_ENUM(interpolation, "Interpolation", interpolation_enum, INTERPOLATION_LINEAR);
- static NodeEnum extension_enum;
- extension_enum.insert("periodic", EXTENSION_REPEAT);
- extension_enum.insert("clamp", EXTENSION_EXTEND);
- extension_enum.insert("black", EXTENSION_CLIP);
- SOCKET_ENUM(extension, "Extension", extension_enum, EXTENSION_REPEAT);
+ static NodeEnum extension_enum;
+ extension_enum.insert("periodic", EXTENSION_REPEAT);
+ extension_enum.insert("clamp", EXTENSION_EXTEND);
+ extension_enum.insert("black", EXTENSION_CLIP);
+ SOCKET_ENUM(extension, "Extension", extension_enum, EXTENSION_REPEAT);
- static NodeEnum projection_enum;
- projection_enum.insert("flat", NODE_IMAGE_PROJ_FLAT);
- projection_enum.insert("box", NODE_IMAGE_PROJ_BOX);
- projection_enum.insert("sphere", NODE_IMAGE_PROJ_SPHERE);
- projection_enum.insert("tube", NODE_IMAGE_PROJ_TUBE);
- SOCKET_ENUM(projection, "Projection", projection_enum, NODE_IMAGE_PROJ_FLAT);
+ static NodeEnum projection_enum;
+ projection_enum.insert("flat", NODE_IMAGE_PROJ_FLAT);
+ projection_enum.insert("box", NODE_IMAGE_PROJ_BOX);
+ projection_enum.insert("sphere", NODE_IMAGE_PROJ_SPHERE);
+ projection_enum.insert("tube", NODE_IMAGE_PROJ_TUBE);
+ SOCKET_ENUM(projection, "Projection", projection_enum, NODE_IMAGE_PROJ_FLAT);
- SOCKET_FLOAT(projection_blend, "Projection Blend", 0.0f);
+ SOCKET_FLOAT(projection_blend, "Projection Blend", 0.0f);
- SOCKET_IN_POINT(vector, "Vector", make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_TEXTURE_UV);
+ SOCKET_IN_POINT(vector, "Vector", make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_TEXTURE_UV);
- SOCKET_OUT_COLOR(color, "Color");
- SOCKET_OUT_FLOAT(alpha, "Alpha");
+ SOCKET_OUT_COLOR(color, "Color");
+ SOCKET_OUT_FLOAT(alpha, "Alpha");
- return type;
+ return type;
}
-ImageTextureNode::ImageTextureNode()
-: ImageSlotTextureNode(node_type)
+ImageTextureNode::ImageTextureNode() : ImageSlotTextureNode(node_type)
{
- image_manager = NULL;
- slot = -1;
- is_float = -1;
- is_linear = false;
- builtin_data = NULL;
- animated = false;
+ image_manager = NULL;
+ slot = -1;
+ is_float = -1;
+ is_linear = false;
+ builtin_data = NULL;
+ animated = false;
}
ImageTextureNode::~ImageTextureNode()
{
- if(image_manager) {
- image_manager->remove_image(filename.string(),
- builtin_data,
- interpolation,
- extension,
- use_alpha);
- }
+ if (image_manager) {
+ image_manager->remove_image(
+ filename.string(), builtin_data, interpolation, extension, use_alpha);
+ }
}
ShaderNode *ImageTextureNode::clone() const
{
- ImageTextureNode *node = new ImageTextureNode(*this);
- node->image_manager = NULL;
- node->slot = -1;
- node->is_float = -1;
- node->is_linear = false;
- return node;
+ ImageTextureNode *node = new ImageTextureNode(*this);
+ node->image_manager = NULL;
+ node->slot = -1;
+ node->is_float = -1;
+ node->is_linear = false;
+ return node;
}
void ImageTextureNode::attributes(Shader *shader, AttributeRequestSet *attributes)
{
#ifdef WITH_PTEX
- /* todo: avoid loading other texture coordinates when using ptex,
- * and hide texture coordinate socket in the UI */
- if(shader->has_surface && string_endswith(filename, ".ptx")) {
- /* ptex */
- attributes->add(ATTR_STD_PTEX_FACE_ID);
- attributes->add(ATTR_STD_PTEX_UV);
- }
+ /* todo: avoid loading other texture coordinates when using ptex,
+ * and hide texture coordinate socket in the UI */
+ if (shader->has_surface && string_endswith(filename, ".ptx")) {
+ /* ptex */
+ attributes->add(ATTR_STD_PTEX_FACE_ID);
+ attributes->add(ATTR_STD_PTEX_UV);
+ }
#endif
- ShaderNode::attributes(shader, attributes);
-}
-
-void ImageTextureNode::compile(SVMCompiler& compiler)
-{
- ShaderInput *vector_in = input("Vector");
- ShaderOutput *color_out = output("Color");
- ShaderOutput *alpha_out = output("Alpha");
-
- image_manager = compiler.image_manager;
- if(is_float == -1) {
- ImageMetaData metadata;
- slot = image_manager->add_image(filename.string(),
- builtin_data,
- animated,
- 0,
- interpolation,
- extension,
- use_alpha,
- metadata);
- is_float = metadata.is_float;
- is_linear = metadata.is_linear;
- }
-
- if(slot != -1) {
- int srgb = (is_linear || color_space != NODE_COLOR_SPACE_COLOR)? 0: 1;
- int vector_offset = tex_mapping.compile_begin(compiler, vector_in);
-
- if(projection != NODE_IMAGE_PROJ_BOX) {
- compiler.add_node(NODE_TEX_IMAGE,
- slot,
- compiler.encode_uchar4(
- vector_offset,
- compiler.stack_assign_if_linked(color_out),
- compiler.stack_assign_if_linked(alpha_out),
- srgb),
- projection);
- }
- else {
- compiler.add_node(NODE_TEX_IMAGE_BOX,
- slot,
- compiler.encode_uchar4(
- vector_offset,
- compiler.stack_assign_if_linked(color_out),
- compiler.stack_assign_if_linked(alpha_out),
- srgb),
- __float_as_int(projection_blend));
- }
-
- tex_mapping.compile_end(compiler, vector_in, vector_offset);
- }
- else {
- /* image not found */
- if(!color_out->links.empty()) {
- compiler.add_node(NODE_VALUE_V, compiler.stack_assign(color_out));
- compiler.add_node(NODE_VALUE_V, make_float3(TEX_IMAGE_MISSING_R,
- TEX_IMAGE_MISSING_G,
- TEX_IMAGE_MISSING_B));
- }
- if(!alpha_out->links.empty())
- compiler.add_node(NODE_VALUE_F, __float_as_int(TEX_IMAGE_MISSING_A), compiler.stack_assign(alpha_out));
- }
-}
-
-void ImageTextureNode::compile(OSLCompiler& compiler)
-{
- ShaderOutput *alpha_out = output("Alpha");
-
- tex_mapping.compile(compiler);
-
- image_manager = compiler.image_manager;
- if(is_float == -1) {
- ImageMetaData metadata;
- if(builtin_data == NULL) {
- image_manager->get_image_metadata(filename.string(), NULL, metadata);
- }
- else {
- slot = image_manager->add_image(filename.string(),
- builtin_data,
- animated,
- 0,
- interpolation,
- extension,
- use_alpha,
- metadata);
- }
- is_float = metadata.is_float;
- is_linear = metadata.is_linear;
- }
-
- if(slot == -1) {
- compiler.parameter(this, "filename");
- }
- else {
- /* TODO(sergey): It's not so simple to pass custom attribute
- * to the texture() function in order to make builtin images
- * support more clear. So we use special file name which is
- * "@i<slot_number>" and check whether file name matches this
- * mask in the OSLRenderServices::texture().
- */
- compiler.parameter("filename", string_printf("@i%d", slot).c_str());
- }
- if(is_linear || color_space != NODE_COLOR_SPACE_COLOR)
- compiler.parameter("color_space", "linear");
- else
- compiler.parameter("color_space", "sRGB");
- compiler.parameter(this, "projection");
- compiler.parameter(this, "projection_blend");
- compiler.parameter("is_float", is_float);
- compiler.parameter("use_alpha", !alpha_out->links.empty());
- compiler.parameter(this, "interpolation");
- compiler.parameter(this, "extension");
-
- compiler.add(this, "node_image_texture");
+ ShaderNode::attributes(shader, attributes);
+}
+
+void ImageTextureNode::compile(SVMCompiler &compiler)
+{
+ ShaderInput *vector_in = input("Vector");
+ ShaderOutput *color_out = output("Color");
+ ShaderOutput *alpha_out = output("Alpha");
+
+ image_manager = compiler.image_manager;
+ if (is_float == -1) {
+ ImageMetaData metadata;
+ slot = image_manager->add_image(filename.string(),
+ builtin_data,
+ animated,
+ 0,
+ interpolation,
+ extension,
+ use_alpha,
+ metadata);
+ is_float = metadata.is_float;
+ is_linear = metadata.is_linear;
+ }
+
+ if (slot != -1) {
+ int srgb = (is_linear || color_space != NODE_COLOR_SPACE_COLOR) ? 0 : 1;
+ int vector_offset = tex_mapping.compile_begin(compiler, vector_in);
+
+ if (projection != NODE_IMAGE_PROJ_BOX) {
+ compiler.add_node(NODE_TEX_IMAGE,
+ slot,
+ compiler.encode_uchar4(vector_offset,
+ compiler.stack_assign_if_linked(color_out),
+ compiler.stack_assign_if_linked(alpha_out),
+ srgb),
+ projection);
+ }
+ else {
+ compiler.add_node(NODE_TEX_IMAGE_BOX,
+ slot,
+ compiler.encode_uchar4(vector_offset,
+ compiler.stack_assign_if_linked(color_out),
+ compiler.stack_assign_if_linked(alpha_out),
+ srgb),
+ __float_as_int(projection_blend));
+ }
+
+ tex_mapping.compile_end(compiler, vector_in, vector_offset);
+ }
+ else {
+ /* image not found */
+ if (!color_out->links.empty()) {
+ compiler.add_node(NODE_VALUE_V, compiler.stack_assign(color_out));
+ compiler.add_node(
+ NODE_VALUE_V,
+ make_float3(TEX_IMAGE_MISSING_R, TEX_IMAGE_MISSING_G, TEX_IMAGE_MISSING_B));
+ }
+ if (!alpha_out->links.empty())
+ compiler.add_node(
+ NODE_VALUE_F, __float_as_int(TEX_IMAGE_MISSING_A), compiler.stack_assign(alpha_out));
+ }
+}
+
+void ImageTextureNode::compile(OSLCompiler &compiler)
+{
+ ShaderOutput *alpha_out = output("Alpha");
+
+ tex_mapping.compile(compiler);
+
+ image_manager = compiler.image_manager;
+ if (is_float == -1) {
+ ImageMetaData metadata;
+ if (builtin_data == NULL) {
+ image_manager->get_image_metadata(filename.string(), NULL, metadata);
+ }
+ else {
+ slot = image_manager->add_image(filename.string(),
+ builtin_data,
+ animated,
+ 0,
+ interpolation,
+ extension,
+ use_alpha,
+ metadata);
+ }
+ is_float = metadata.is_float;
+ is_linear = metadata.is_linear;
+ }
+
+ if (slot == -1) {
+ compiler.parameter(this, "filename");
+ }
+ else {
+ /* TODO(sergey): It's not so simple to pass custom attribute
+ * to the texture() function in order to make builtin images
+ * support more clear. So we use special file name which is
+ * "@i<slot_number>" and check whether file name matches this
+ * mask in the OSLRenderServices::texture().
+ */
+ compiler.parameter("filename", string_printf("@i%d", slot).c_str());
+ }
+ if (is_linear || color_space != NODE_COLOR_SPACE_COLOR)
+ compiler.parameter("color_space", "linear");
+ else
+ compiler.parameter("color_space", "sRGB");
+ compiler.parameter(this, "projection");
+ compiler.parameter(this, "projection_blend");
+ compiler.parameter("is_float", is_float);
+ compiler.parameter("use_alpha", !alpha_out->links.empty());
+ compiler.parameter(this, "interpolation");
+ compiler.parameter(this, "extension");
+
+ compiler.add(this, "node_image_texture");
}
/* Environment Texture */
NODE_DEFINE(EnvironmentTextureNode)
{
- NodeType* type = NodeType::add("environment_texture", create, NodeType::SHADER);
+ NodeType *type = NodeType::add("environment_texture", create, NodeType::SHADER);
- TEXTURE_MAPPING_DEFINE(EnvironmentTextureNode);
+ TEXTURE_MAPPING_DEFINE(EnvironmentTextureNode);
- SOCKET_STRING(filename, "Filename", ustring());
+ SOCKET_STRING(filename, "Filename", ustring());
- static NodeEnum color_space_enum;
- color_space_enum.insert("none", NODE_COLOR_SPACE_NONE);
- color_space_enum.insert("color", NODE_COLOR_SPACE_COLOR);
- SOCKET_ENUM(color_space, "Color Space", color_space_enum, NODE_COLOR_SPACE_COLOR);
+ static NodeEnum color_space_enum;
+ color_space_enum.insert("none", NODE_COLOR_SPACE_NONE);
+ color_space_enum.insert("color", NODE_COLOR_SPACE_COLOR);
+ SOCKET_ENUM(color_space, "Color Space", color_space_enum, NODE_COLOR_SPACE_COLOR);
- SOCKET_BOOLEAN(use_alpha, "Use Alpha", true);
+ SOCKET_BOOLEAN(use_alpha, "Use Alpha", true);
- static NodeEnum interpolation_enum;
- interpolation_enum.insert("closest", INTERPOLATION_CLOSEST);
- interpolation_enum.insert("linear", INTERPOLATION_LINEAR);
- interpolation_enum.insert("cubic", INTERPOLATION_CUBIC);
- interpolation_enum.insert("smart", INTERPOLATION_SMART);
- SOCKET_ENUM(interpolation, "Interpolation", interpolation_enum, INTERPOLATION_LINEAR);
+ static NodeEnum interpolation_enum;
+ interpolation_enum.insert("closest", INTERPOLATION_CLOSEST);
+ interpolation_enum.insert("linear", INTERPOLATION_LINEAR);
+ interpolation_enum.insert("cubic", INTERPOLATION_CUBIC);
+ interpolation_enum.insert("smart", INTERPOLATION_SMART);
+ SOCKET_ENUM(interpolation, "Interpolation", interpolation_enum, INTERPOLATION_LINEAR);
- static NodeEnum projection_enum;
- projection_enum.insert("equirectangular", NODE_ENVIRONMENT_EQUIRECTANGULAR);
- projection_enum.insert("mirror_ball", NODE_ENVIRONMENT_MIRROR_BALL);
- SOCKET_ENUM(projection, "Projection", projection_enum, NODE_ENVIRONMENT_EQUIRECTANGULAR);
+ static NodeEnum projection_enum;
+ projection_enum.insert("equirectangular", NODE_ENVIRONMENT_EQUIRECTANGULAR);
+ projection_enum.insert("mirror_ball", NODE_ENVIRONMENT_MIRROR_BALL);
+ SOCKET_ENUM(projection, "Projection", projection_enum, NODE_ENVIRONMENT_EQUIRECTANGULAR);
- SOCKET_IN_POINT(vector, "Vector", make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_POSITION);
+ SOCKET_IN_POINT(vector, "Vector", make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_POSITION);
- SOCKET_OUT_COLOR(color, "Color");
- SOCKET_OUT_FLOAT(alpha, "Alpha");
+ SOCKET_OUT_COLOR(color, "Color");
+ SOCKET_OUT_FLOAT(alpha, "Alpha");
- return type;
+ return type;
}
-EnvironmentTextureNode::EnvironmentTextureNode()
-: ImageSlotTextureNode(node_type)
+EnvironmentTextureNode::EnvironmentTextureNode() : ImageSlotTextureNode(node_type)
{
- image_manager = NULL;
- slot = -1;
- is_float = -1;
- is_linear = false;
- builtin_data = NULL;
- animated = false;
+ image_manager = NULL;
+ slot = -1;
+ is_float = -1;
+ is_linear = false;
+ builtin_data = NULL;
+ animated = false;
}
EnvironmentTextureNode::~EnvironmentTextureNode()
{
- if(image_manager) {
- image_manager->remove_image(filename.string(),
- builtin_data,
- interpolation,
- EXTENSION_REPEAT,
- use_alpha);
- }
+ if (image_manager) {
+ image_manager->remove_image(
+ filename.string(), builtin_data, interpolation, EXTENSION_REPEAT, use_alpha);
+ }
}
ShaderNode *EnvironmentTextureNode::clone() const
{
- EnvironmentTextureNode *node = new EnvironmentTextureNode(*this);
- node->image_manager = NULL;
- node->slot = -1;
- node->is_float = -1;
- node->is_linear = false;
- return node;
+ EnvironmentTextureNode *node = new EnvironmentTextureNode(*this);
+ node->image_manager = NULL;
+ node->slot = -1;
+ node->is_float = -1;
+ node->is_linear = false;
+ return node;
}
void EnvironmentTextureNode::attributes(Shader *shader, AttributeRequestSet *attributes)
{
#ifdef WITH_PTEX
- if(shader->has_surface && string_endswith(filename, ".ptx")) {
- /* ptex */
- attributes->add(ATTR_STD_PTEX_FACE_ID);
- attributes->add(ATTR_STD_PTEX_UV);
- }
+ if (shader->has_surface && string_endswith(filename, ".ptx")) {
+ /* ptex */
+ attributes->add(ATTR_STD_PTEX_FACE_ID);
+ attributes->add(ATTR_STD_PTEX_UV);
+ }
#endif
- ShaderNode::attributes(shader, attributes);
-}
-
-void EnvironmentTextureNode::compile(SVMCompiler& compiler)
-{
- ShaderInput *vector_in = input("Vector");
- ShaderOutput *color_out = output("Color");
- ShaderOutput *alpha_out = output("Alpha");
-
- image_manager = compiler.image_manager;
- if(slot == -1) {
- ImageMetaData metadata;
- slot = image_manager->add_image(filename.string(),
- builtin_data,
- animated,
- 0,
- interpolation,
- EXTENSION_REPEAT,
- use_alpha,
- metadata);
- is_float = metadata.is_float;
- is_linear = metadata.is_linear;
- }
-
- if(slot != -1) {
- int srgb = (is_linear || color_space != NODE_COLOR_SPACE_COLOR)? 0: 1;
- int vector_offset = tex_mapping.compile_begin(compiler, vector_in);
-
- compiler.add_node(NODE_TEX_ENVIRONMENT,
- slot,
- compiler.encode_uchar4(
- vector_offset,
- compiler.stack_assign_if_linked(color_out),
- compiler.stack_assign_if_linked(alpha_out),
- srgb),
- projection);
-
- tex_mapping.compile_end(compiler, vector_in, vector_offset);
- }
- else {
- /* image not found */
- if(!color_out->links.empty()) {
- compiler.add_node(NODE_VALUE_V, compiler.stack_assign(color_out));
- compiler.add_node(NODE_VALUE_V, make_float3(TEX_IMAGE_MISSING_R,
- TEX_IMAGE_MISSING_G,
- TEX_IMAGE_MISSING_B));
- }
- if(!alpha_out->links.empty())
- compiler.add_node(NODE_VALUE_F, __float_as_int(TEX_IMAGE_MISSING_A), compiler.stack_assign(alpha_out));
- }
-}
-
-void EnvironmentTextureNode::compile(OSLCompiler& compiler)
-{
- ShaderOutput *alpha_out = output("Alpha");
-
- tex_mapping.compile(compiler);
-
- /* See comments in ImageTextureNode::compile about support
- * of builtin images.
- */
- image_manager = compiler.image_manager;
- if(is_float == -1) {
- ImageMetaData metadata;
- if(builtin_data == NULL) {
- image_manager->get_image_metadata(filename.string(), NULL, metadata);
- }
- else {
- slot = image_manager->add_image(filename.string(),
- builtin_data,
- animated,
- 0,
- interpolation,
- EXTENSION_REPEAT,
- use_alpha,
- metadata);
- }
- is_float = metadata.is_float;
- is_linear = metadata.is_linear;
- }
-
- if(slot == -1) {
- compiler.parameter(this, "filename");
- }
- else {
- compiler.parameter("filename", string_printf("@i%d", slot).c_str());
- }
- compiler.parameter(this, "projection");
- if(is_linear || color_space != NODE_COLOR_SPACE_COLOR)
- compiler.parameter("color_space", "linear");
- else
- compiler.parameter("color_space", "sRGB");
-
- compiler.parameter(this, "interpolation");
- compiler.parameter("is_float", is_float);
- compiler.parameter("use_alpha", !alpha_out->links.empty());
- compiler.add(this, "node_environment_texture");
+ ShaderNode::attributes(shader, attributes);
+}
+
+void EnvironmentTextureNode::compile(SVMCompiler &compiler)
+{
+ ShaderInput *vector_in = input("Vector");
+ ShaderOutput *color_out = output("Color");
+ ShaderOutput *alpha_out = output("Alpha");
+
+ image_manager = compiler.image_manager;
+ if (slot == -1) {
+ ImageMetaData metadata;
+ slot = image_manager->add_image(filename.string(),
+ builtin_data,
+ animated,
+ 0,
+ interpolation,
+ EXTENSION_REPEAT,
+ use_alpha,
+ metadata);
+ is_float = metadata.is_float;
+ is_linear = metadata.is_linear;
+ }
+
+ if (slot != -1) {
+ int srgb = (is_linear || color_space != NODE_COLOR_SPACE_COLOR) ? 0 : 1;
+ int vector_offset = tex_mapping.compile_begin(compiler, vector_in);
+
+ compiler.add_node(NODE_TEX_ENVIRONMENT,
+ slot,
+ compiler.encode_uchar4(vector_offset,
+ compiler.stack_assign_if_linked(color_out),
+ compiler.stack_assign_if_linked(alpha_out),
+ srgb),
+ projection);
+
+ tex_mapping.compile_end(compiler, vector_in, vector_offset);
+ }
+ else {
+ /* image not found */
+ if (!color_out->links.empty()) {
+ compiler.add_node(NODE_VALUE_V, compiler.stack_assign(color_out));
+ compiler.add_node(
+ NODE_VALUE_V,
+ make_float3(TEX_IMAGE_MISSING_R, TEX_IMAGE_MISSING_G, TEX_IMAGE_MISSING_B));
+ }
+ if (!alpha_out->links.empty())
+ compiler.add_node(
+ NODE_VALUE_F, __float_as_int(TEX_IMAGE_MISSING_A), compiler.stack_assign(alpha_out));
+ }
+}
+
+void EnvironmentTextureNode::compile(OSLCompiler &compiler)
+{
+ ShaderOutput *alpha_out = output("Alpha");
+
+ tex_mapping.compile(compiler);
+
+ /* See comments in ImageTextureNode::compile about support
+ * of builtin images.
+ */
+ image_manager = compiler.image_manager;
+ if (is_float == -1) {
+ ImageMetaData metadata;
+ if (builtin_data == NULL) {
+ image_manager->get_image_metadata(filename.string(), NULL, metadata);
+ }
+ else {
+ slot = image_manager->add_image(filename.string(),
+ builtin_data,
+ animated,
+ 0,
+ interpolation,
+ EXTENSION_REPEAT,
+ use_alpha,
+ metadata);
+ }
+ is_float = metadata.is_float;
+ is_linear = metadata.is_linear;
+ }
+
+ if (slot == -1) {
+ compiler.parameter(this, "filename");
+ }
+ else {
+ compiler.parameter("filename", string_printf("@i%d", slot).c_str());
+ }
+ compiler.parameter(this, "projection");
+ if (is_linear || color_space != NODE_COLOR_SPACE_COLOR)
+ compiler.parameter("color_space", "linear");
+ else
+ compiler.parameter("color_space", "sRGB");
+
+ compiler.parameter(this, "interpolation");
+ compiler.parameter("is_float", is_float);
+ compiler.parameter("use_alpha", !alpha_out->links.empty());
+ compiler.add(this, "node_environment_texture");
}
/* Sky Texture */
static float2 sky_spherical_coordinates(float3 dir)
{
- return make_float2(acosf(dir.z), atan2f(dir.x, dir.y));
+ return make_float2(acosf(dir.z), atan2f(dir.x, dir.y));
}
typedef struct SunSky {
- /* sun direction in spherical and cartesian */
- float theta, phi;
+ /* sun direction in spherical and cartesian */
+ float theta, phi;
- /* Parameter */
- float radiance_x, radiance_y, radiance_z;
- float config_x[9], config_y[9], config_z[9];
+ /* Parameter */
+ float radiance_x, radiance_y, radiance_z;
+ float config_x[9], config_y[9], config_z[9];
} SunSky;
/* Preetham model */
static float sky_perez_function(float lam[6], float theta, float gamma)
{
- return (1.0f + lam[0]*expf(lam[1]/cosf(theta))) * (1.0f + lam[2]*expf(lam[3]*gamma) + lam[4]*cosf(gamma)*cosf(gamma));
+ return (1.0f + lam[0] * expf(lam[1] / cosf(theta))) *
+ (1.0f + lam[2] * expf(lam[3] * gamma) + lam[4] * cosf(gamma) * cosf(gamma));
}
static void sky_texture_precompute_old(SunSky *sunsky, float3 dir, float turbidity)
{
- /*
- * We re-use the SunSky struct of the new model, to avoid extra variables
- * zenith_Y/x/y is now radiance_x/y/z
- * perez_Y/x/y is now config_x/y/z
- */
-
- float2 spherical = sky_spherical_coordinates(dir);
- float theta = spherical.x;
- float phi = spherical.y;
-
- sunsky->theta = theta;
- sunsky->phi = phi;
-
- float theta2 = theta*theta;
- float theta3 = theta2*theta;
- float T = turbidity;
- float T2 = T * T;
-
- float chi = (4.0f / 9.0f - T / 120.0f) * (M_PI_F - 2.0f * theta);
- sunsky->radiance_x = (4.0453f * T - 4.9710f) * tanf(chi) - 0.2155f * T + 2.4192f;
- sunsky->radiance_x *= 0.06f;
-
- sunsky->radiance_y =
- (0.00166f * theta3 - 0.00375f * theta2 + 0.00209f * theta) * T2 +
- (-0.02903f * theta3 + 0.06377f * theta2 - 0.03202f * theta + 0.00394f) * T +
- (0.11693f * theta3 - 0.21196f * theta2 + 0.06052f * theta + 0.25886f);
-
- sunsky->radiance_z =
- (0.00275f * theta3 - 0.00610f * theta2 + 0.00317f * theta) * T2 +
- (-0.04214f * theta3 + 0.08970f * theta2 - 0.04153f * theta + 0.00516f) * T +
- (0.15346f * theta3 - 0.26756f * theta2 + 0.06670f * theta + 0.26688f);
-
- sunsky->config_x[0] = (0.1787f * T - 1.4630f);
- sunsky->config_x[1] = (-0.3554f * T + 0.4275f);
- sunsky->config_x[2] = (-0.0227f * T + 5.3251f);
- sunsky->config_x[3] = (0.1206f * T - 2.5771f);
- sunsky->config_x[4] = (-0.0670f * T + 0.3703f);
-
- sunsky->config_y[0] = (-0.0193f * T - 0.2592f);
- sunsky->config_y[1] = (-0.0665f * T + 0.0008f);
- sunsky->config_y[2] = (-0.0004f * T + 0.2125f);
- sunsky->config_y[3] = (-0.0641f * T - 0.8989f);
- sunsky->config_y[4] = (-0.0033f * T + 0.0452f);
-
- sunsky->config_z[0] = (-0.0167f * T - 0.2608f);
- sunsky->config_z[1] = (-0.0950f * T + 0.0092f);
- sunsky->config_z[2] = (-0.0079f * T + 0.2102f);
- sunsky->config_z[3] = (-0.0441f * T - 1.6537f);
- sunsky->config_z[4] = (-0.0109f * T + 0.0529f);
-
- /* unused for old sky model */
- for(int i = 5; i < 9; i++) {
- sunsky->config_x[i] = 0.0f;
- sunsky->config_y[i] = 0.0f;
- sunsky->config_z[i] = 0.0f;
- }
-
- sunsky->radiance_x /= sky_perez_function(sunsky->config_x, 0, theta);
- sunsky->radiance_y /= sky_perez_function(sunsky->config_y, 0, theta);
- sunsky->radiance_z /= sky_perez_function(sunsky->config_z, 0, theta);
+ /*
+ * We re-use the SunSky struct of the new model, to avoid extra variables
+ * zenith_Y/x/y is now radiance_x/y/z
+ * perez_Y/x/y is now config_x/y/z
+ */
+
+ float2 spherical = sky_spherical_coordinates(dir);
+ float theta = spherical.x;
+ float phi = spherical.y;
+
+ sunsky->theta = theta;
+ sunsky->phi = phi;
+
+ float theta2 = theta * theta;
+ float theta3 = theta2 * theta;
+ float T = turbidity;
+ float T2 = T * T;
+
+ float chi = (4.0f / 9.0f - T / 120.0f) * (M_PI_F - 2.0f * theta);
+ sunsky->radiance_x = (4.0453f * T - 4.9710f) * tanf(chi) - 0.2155f * T + 2.4192f;
+ sunsky->radiance_x *= 0.06f;
+
+ sunsky->radiance_y = (0.00166f * theta3 - 0.00375f * theta2 + 0.00209f * theta) * T2 +
+ (-0.02903f * theta3 + 0.06377f * theta2 - 0.03202f * theta + 0.00394f) * T +
+ (0.11693f * theta3 - 0.21196f * theta2 + 0.06052f * theta + 0.25886f);
+
+ sunsky->radiance_z = (0.00275f * theta3 - 0.00610f * theta2 + 0.00317f * theta) * T2 +
+ (-0.04214f * theta3 + 0.08970f * theta2 - 0.04153f * theta + 0.00516f) * T +
+ (0.15346f * theta3 - 0.26756f * theta2 + 0.06670f * theta + 0.26688f);
+
+ sunsky->config_x[0] = (0.1787f * T - 1.4630f);
+ sunsky->config_x[1] = (-0.3554f * T + 0.4275f);
+ sunsky->config_x[2] = (-0.0227f * T + 5.3251f);
+ sunsky->config_x[3] = (0.1206f * T - 2.5771f);
+ sunsky->config_x[4] = (-0.0670f * T + 0.3703f);
+
+ sunsky->config_y[0] = (-0.0193f * T - 0.2592f);
+ sunsky->config_y[1] = (-0.0665f * T + 0.0008f);
+ sunsky->config_y[2] = (-0.0004f * T + 0.2125f);
+ sunsky->config_y[3] = (-0.0641f * T - 0.8989f);
+ sunsky->config_y[4] = (-0.0033f * T + 0.0452f);
+
+ sunsky->config_z[0] = (-0.0167f * T - 0.2608f);
+ sunsky->config_z[1] = (-0.0950f * T + 0.0092f);
+ sunsky->config_z[2] = (-0.0079f * T + 0.2102f);
+ sunsky->config_z[3] = (-0.0441f * T - 1.6537f);
+ sunsky->config_z[4] = (-0.0109f * T + 0.0529f);
+
+ /* unused for old sky model */
+ for (int i = 5; i < 9; i++) {
+ sunsky->config_x[i] = 0.0f;
+ sunsky->config_y[i] = 0.0f;
+ sunsky->config_z[i] = 0.0f;
+ }
+
+ sunsky->radiance_x /= sky_perez_function(sunsky->config_x, 0, theta);
+ sunsky->radiance_y /= sky_perez_function(sunsky->config_y, 0, theta);
+ sunsky->radiance_z /= sky_perez_function(sunsky->config_z, 0, theta);
}
/* Hosek / Wilkie */
-static void sky_texture_precompute_new(SunSky *sunsky, float3 dir, float turbidity, float ground_albedo)
+static void sky_texture_precompute_new(SunSky *sunsky,
+ float3 dir,
+ float turbidity,
+ float ground_albedo)
{
- /* Calculate Sun Direction and save coordinates */
- float2 spherical = sky_spherical_coordinates(dir);
- float theta = spherical.x;
- float phi = spherical.y;
+ /* Calculate Sun Direction and save coordinates */
+ float2 spherical = sky_spherical_coordinates(dir);
+ float theta = spherical.x;
+ float phi = spherical.y;
- /* Clamp Turbidity */
- turbidity = clamp(turbidity, 0.0f, 10.0f);
+ /* Clamp Turbidity */
+ turbidity = clamp(turbidity, 0.0f, 10.0f);
- /* Clamp to Horizon */
- theta = clamp(theta, 0.0f, M_PI_2_F);
+ /* Clamp to Horizon */
+ theta = clamp(theta, 0.0f, M_PI_2_F);
- sunsky->theta = theta;
- sunsky->phi = phi;
+ sunsky->theta = theta;
+ sunsky->phi = phi;
- float solarElevation = M_PI_2_F - theta;
+ float solarElevation = M_PI_2_F - theta;
- /* Initialize Sky Model */
- ArHosekSkyModelState *sky_state;
- sky_state = arhosek_xyz_skymodelstate_alloc_init((double)turbidity, (double)ground_albedo, (double)solarElevation);
+ /* Initialize Sky Model */
+ ArHosekSkyModelState *sky_state;
+ sky_state = arhosek_xyz_skymodelstate_alloc_init(
+ (double)turbidity, (double)ground_albedo, (double)solarElevation);
- /* Copy values from sky_state to SunSky */
- for(int i = 0; i < 9; ++i) {
- sunsky->config_x[i] = (float)sky_state->configs[0][i];
- sunsky->config_y[i] = (float)sky_state->configs[1][i];
- sunsky->config_z[i] = (float)sky_state->configs[2][i];
- }
- sunsky->radiance_x = (float)sky_state->radiances[0];
- sunsky->radiance_y = (float)sky_state->radiances[1];
- sunsky->radiance_z = (float)sky_state->radiances[2];
+ /* Copy values from sky_state to SunSky */
+ for (int i = 0; i < 9; ++i) {
+ sunsky->config_x[i] = (float)sky_state->configs[0][i];
+ sunsky->config_y[i] = (float)sky_state->configs[1][i];
+ sunsky->config_z[i] = (float)sky_state->configs[2][i];
+ }
+ sunsky->radiance_x = (float)sky_state->radiances[0];
+ sunsky->radiance_y = (float)sky_state->radiances[1];
+ sunsky->radiance_z = (float)sky_state->radiances[2];
- /* Free sky_state */
- arhosekskymodelstate_free(sky_state);
+ /* Free sky_state */
+ arhosekskymodelstate_free(sky_state);
}
NODE_DEFINE(SkyTextureNode)
{
- NodeType* type = NodeType::add("sky_texture", create, NodeType::SHADER);
-
- TEXTURE_MAPPING_DEFINE(SkyTextureNode);
-
- static NodeEnum type_enum;
- type_enum.insert("preetham", NODE_SKY_OLD);
- type_enum.insert("hosek_wilkie", NODE_SKY_NEW);
- SOCKET_ENUM(type, "Type", type_enum, NODE_SKY_NEW);
-
- SOCKET_VECTOR(sun_direction, "Sun Direction", make_float3(0.0f, 0.0f, 1.0f));
- SOCKET_FLOAT(turbidity, "Turbidity", 2.2f);
- SOCKET_FLOAT(ground_albedo, "Ground Albedo", 0.3f);
-
- SOCKET_IN_POINT(vector, "Vector", make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_TEXTURE_GENERATED);
-
- SOCKET_OUT_COLOR(color, "Color");
-
- return type;
-}
-
-SkyTextureNode::SkyTextureNode()
-: TextureNode(node_type)
-{
-}
-
-void SkyTextureNode::compile(SVMCompiler& compiler)
-{
- ShaderInput *vector_in = input("Vector");
- ShaderOutput *color_out = output("Color");
-
- SunSky sunsky;
- if(type == NODE_SKY_OLD)
- sky_texture_precompute_old(&sunsky, sun_direction, turbidity);
- else if(type == NODE_SKY_NEW)
- sky_texture_precompute_new(&sunsky, sun_direction, turbidity, ground_albedo);
- else
- assert(false);
-
- int vector_offset = tex_mapping.compile_begin(compiler, vector_in);
-
- compiler.stack_assign(color_out);
- compiler.add_node(NODE_TEX_SKY, vector_offset, compiler.stack_assign(color_out), type);
- compiler.add_node(__float_as_uint(sunsky.phi), __float_as_uint(sunsky.theta), __float_as_uint(sunsky.radiance_x), __float_as_uint(sunsky.radiance_y));
- compiler.add_node(__float_as_uint(sunsky.radiance_z), __float_as_uint(sunsky.config_x[0]), __float_as_uint(sunsky.config_x[1]), __float_as_uint(sunsky.config_x[2]));
- compiler.add_node(__float_as_uint(sunsky.config_x[3]), __float_as_uint(sunsky.config_x[4]), __float_as_uint(sunsky.config_x[5]), __float_as_uint(sunsky.config_x[6]));
- compiler.add_node(__float_as_uint(sunsky.config_x[7]), __float_as_uint(sunsky.config_x[8]), __float_as_uint(sunsky.config_y[0]), __float_as_uint(sunsky.config_y[1]));
- compiler.add_node(__float_as_uint(sunsky.config_y[2]), __float_as_uint(sunsky.config_y[3]), __float_as_uint(sunsky.config_y[4]), __float_as_uint(sunsky.config_y[5]));
- compiler.add_node(__float_as_uint(sunsky.config_y[6]), __float_as_uint(sunsky.config_y[7]), __float_as_uint(sunsky.config_y[8]), __float_as_uint(sunsky.config_z[0]));
- compiler.add_node(__float_as_uint(sunsky.config_z[1]), __float_as_uint(sunsky.config_z[2]), __float_as_uint(sunsky.config_z[3]), __float_as_uint(sunsky.config_z[4]));
- compiler.add_node(__float_as_uint(sunsky.config_z[5]), __float_as_uint(sunsky.config_z[6]), __float_as_uint(sunsky.config_z[7]), __float_as_uint(sunsky.config_z[8]));
-
- tex_mapping.compile_end(compiler, vector_in, vector_offset);
-}
-
-void SkyTextureNode::compile(OSLCompiler& compiler)
-{
- tex_mapping.compile(compiler);
-
- SunSky sunsky;
- if(type == NODE_SKY_OLD)
- sky_texture_precompute_old(&sunsky, sun_direction, turbidity);
- else if(type == NODE_SKY_NEW)
- sky_texture_precompute_new(&sunsky, sun_direction, turbidity, ground_albedo);
- else
- assert(false);
-
- compiler.parameter(this, "type");
- compiler.parameter("theta", sunsky.theta);
- compiler.parameter("phi", sunsky.phi);
- compiler.parameter_color("radiance", make_float3(sunsky.radiance_x, sunsky.radiance_y, sunsky.radiance_z));
- compiler.parameter_array("config_x", sunsky.config_x, 9);
- compiler.parameter_array("config_y", sunsky.config_y, 9);
- compiler.parameter_array("config_z", sunsky.config_z, 9);
- compiler.add(this, "node_sky_texture");
+ NodeType *type = NodeType::add("sky_texture", create, NodeType::SHADER);
+
+ TEXTURE_MAPPING_DEFINE(SkyTextureNode);
+
+ static NodeEnum type_enum;
+ type_enum.insert("preetham", NODE_SKY_OLD);
+ type_enum.insert("hosek_wilkie", NODE_SKY_NEW);
+ SOCKET_ENUM(type, "Type", type_enum, NODE_SKY_NEW);
+
+ SOCKET_VECTOR(sun_direction, "Sun Direction", make_float3(0.0f, 0.0f, 1.0f));
+ SOCKET_FLOAT(turbidity, "Turbidity", 2.2f);
+ SOCKET_FLOAT(ground_albedo, "Ground Albedo", 0.3f);
+
+ SOCKET_IN_POINT(
+ vector, "Vector", make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_TEXTURE_GENERATED);
+
+ SOCKET_OUT_COLOR(color, "Color");
+
+ return type;
+}
+
+SkyTextureNode::SkyTextureNode() : TextureNode(node_type)
+{
+}
+
+void SkyTextureNode::compile(SVMCompiler &compiler)
+{
+ ShaderInput *vector_in = input("Vector");
+ ShaderOutput *color_out = output("Color");
+
+ SunSky sunsky;
+ if (type == NODE_SKY_OLD)
+ sky_texture_precompute_old(&sunsky, sun_direction, turbidity);
+ else if (type == NODE_SKY_NEW)
+ sky_texture_precompute_new(&sunsky, sun_direction, turbidity, ground_albedo);
+ else
+ assert(false);
+
+ int vector_offset = tex_mapping.compile_begin(compiler, vector_in);
+
+ compiler.stack_assign(color_out);
+ compiler.add_node(NODE_TEX_SKY, vector_offset, compiler.stack_assign(color_out), type);
+ compiler.add_node(__float_as_uint(sunsky.phi),
+ __float_as_uint(sunsky.theta),
+ __float_as_uint(sunsky.radiance_x),
+ __float_as_uint(sunsky.radiance_y));
+ compiler.add_node(__float_as_uint(sunsky.radiance_z),
+ __float_as_uint(sunsky.config_x[0]),
+ __float_as_uint(sunsky.config_x[1]),
+ __float_as_uint(sunsky.config_x[2]));
+ compiler.add_node(__float_as_uint(sunsky.config_x[3]),
+ __float_as_uint(sunsky.config_x[4]),
+ __float_as_uint(sunsky.config_x[5]),
+ __float_as_uint(sunsky.config_x[6]));
+ compiler.add_node(__float_as_uint(sunsky.config_x[7]),
+ __float_as_uint(sunsky.config_x[8]),
+ __float_as_uint(sunsky.config_y[0]),
+ __float_as_uint(sunsky.config_y[1]));
+ compiler.add_node(__float_as_uint(sunsky.config_y[2]),
+ __float_as_uint(sunsky.config_y[3]),
+ __float_as_uint(sunsky.config_y[4]),
+ __float_as_uint(sunsky.config_y[5]));
+ compiler.add_node(__float_as_uint(sunsky.config_y[6]),
+ __float_as_uint(sunsky.config_y[7]),
+ __float_as_uint(sunsky.config_y[8]),
+ __float_as_uint(sunsky.config_z[0]));
+ compiler.add_node(__float_as_uint(sunsky.config_z[1]),
+ __float_as_uint(sunsky.config_z[2]),
+ __float_as_uint(sunsky.config_z[3]),
+ __float_as_uint(sunsky.config_z[4]));
+ compiler.add_node(__float_as_uint(sunsky.config_z[5]),
+ __float_as_uint(sunsky.config_z[6]),
+ __float_as_uint(sunsky.config_z[7]),
+ __float_as_uint(sunsky.config_z[8]));
+
+ tex_mapping.compile_end(compiler, vector_in, vector_offset);
+}
+
+void SkyTextureNode::compile(OSLCompiler &compiler)
+{
+ tex_mapping.compile(compiler);
+
+ SunSky sunsky;
+ if (type == NODE_SKY_OLD)
+ sky_texture_precompute_old(&sunsky, sun_direction, turbidity);
+ else if (type == NODE_SKY_NEW)
+ sky_texture_precompute_new(&sunsky, sun_direction, turbidity, ground_albedo);
+ else
+ assert(false);
+
+ compiler.parameter(this, "type");
+ compiler.parameter("theta", sunsky.theta);
+ compiler.parameter("phi", sunsky.phi);
+ compiler.parameter_color("radiance",
+ make_float3(sunsky.radiance_x, sunsky.radiance_y, sunsky.radiance_z));
+ compiler.parameter_array("config_x", sunsky.config_x, 9);
+ compiler.parameter_array("config_y", sunsky.config_y, 9);
+ compiler.parameter_array("config_z", sunsky.config_z, 9);
+ compiler.add(this, "node_sky_texture");
}
/* Gradient Texture */
NODE_DEFINE(GradientTextureNode)
{
- NodeType* type = NodeType::add("gradient_texture", create, NodeType::SHADER);
+ NodeType *type = NodeType::add("gradient_texture", create, NodeType::SHADER);
- TEXTURE_MAPPING_DEFINE(GradientTextureNode);
+ TEXTURE_MAPPING_DEFINE(GradientTextureNode);
- static NodeEnum type_enum;
- type_enum.insert("linear", NODE_BLEND_LINEAR);
- type_enum.insert("quadratic", NODE_BLEND_QUADRATIC);
- type_enum.insert("easing", NODE_BLEND_EASING);
- type_enum.insert("diagonal", NODE_BLEND_DIAGONAL);
- type_enum.insert("radial", NODE_BLEND_RADIAL);
- type_enum.insert("quadratic_sphere", NODE_BLEND_QUADRATIC_SPHERE);
- type_enum.insert("spherical", NODE_BLEND_SPHERICAL);
- SOCKET_ENUM(type, "Type", type_enum, NODE_BLEND_LINEAR);
+ static NodeEnum type_enum;
+ type_enum.insert("linear", NODE_BLEND_LINEAR);
+ type_enum.insert("quadratic", NODE_BLEND_QUADRATIC);
+ type_enum.insert("easing", NODE_BLEND_EASING);
+ type_enum.insert("diagonal", NODE_BLEND_DIAGONAL);
+ type_enum.insert("radial", NODE_BLEND_RADIAL);
+ type_enum.insert("quadratic_sphere", NODE_BLEND_QUADRATIC_SPHERE);
+ type_enum.insert("spherical", NODE_BLEND_SPHERICAL);
+ SOCKET_ENUM(type, "Type", type_enum, NODE_BLEND_LINEAR);
- SOCKET_IN_POINT(vector, "Vector", make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_TEXTURE_GENERATED);
+ SOCKET_IN_POINT(
+ vector, "Vector", make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_TEXTURE_GENERATED);
- SOCKET_OUT_COLOR(color, "Color");
- SOCKET_OUT_FLOAT(fac, "Fac");
+ SOCKET_OUT_COLOR(color, "Color");
+ SOCKET_OUT_FLOAT(fac, "Fac");
- return type;
+ return type;
}
-GradientTextureNode::GradientTextureNode()
-: TextureNode(node_type)
+GradientTextureNode::GradientTextureNode() : TextureNode(node_type)
{
}
-void GradientTextureNode::compile(SVMCompiler& compiler)
+void GradientTextureNode::compile(SVMCompiler &compiler)
{
- ShaderInput *vector_in = input("Vector");
- ShaderOutput *color_out = output("Color");
- ShaderOutput *fac_out = output("Fac");
+ ShaderInput *vector_in = input("Vector");
+ ShaderOutput *color_out = output("Color");
+ ShaderOutput *fac_out = output("Fac");
- int vector_offset = tex_mapping.compile_begin(compiler, vector_in);
+ int vector_offset = tex_mapping.compile_begin(compiler, vector_in);
- compiler.add_node(NODE_TEX_GRADIENT,
- compiler.encode_uchar4(
- type,
- vector_offset,
- compiler.stack_assign_if_linked(fac_out),
- compiler.stack_assign_if_linked(color_out)));
+ compiler.add_node(NODE_TEX_GRADIENT,
+ compiler.encode_uchar4(type,
+ vector_offset,
+ compiler.stack_assign_if_linked(fac_out),
+ compiler.stack_assign_if_linked(color_out)));
- tex_mapping.compile_end(compiler, vector_in, vector_offset);
+ tex_mapping.compile_end(compiler, vector_in, vector_offset);
}
-void GradientTextureNode::compile(OSLCompiler& compiler)
+void GradientTextureNode::compile(OSLCompiler &compiler)
{
- tex_mapping.compile(compiler);
+ tex_mapping.compile(compiler);
- compiler.parameter(this, "type");
- compiler.add(this, "node_gradient_texture");
+ compiler.parameter(this, "type");
+ compiler.add(this, "node_gradient_texture");
}
/* Noise Texture */
NODE_DEFINE(NoiseTextureNode)
{
- NodeType* type = NodeType::add("noise_texture", create, NodeType::SHADER);
+ NodeType *type = NodeType::add("noise_texture", create, NodeType::SHADER);
- TEXTURE_MAPPING_DEFINE(NoiseTextureNode);
+ TEXTURE_MAPPING_DEFINE(NoiseTextureNode);
- SOCKET_IN_FLOAT(scale, "Scale", 1.0f);
- SOCKET_IN_FLOAT(detail, "Detail", 2.0f);
- SOCKET_IN_FLOAT(distortion, "Distortion", 0.0f);
- SOCKET_IN_POINT(vector, "Vector", make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_TEXTURE_GENERATED);
+ SOCKET_IN_FLOAT(scale, "Scale", 1.0f);
+ SOCKET_IN_FLOAT(detail, "Detail", 2.0f);
+ SOCKET_IN_FLOAT(distortion, "Distortion", 0.0f);
+ SOCKET_IN_POINT(
+ vector, "Vector", make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_TEXTURE_GENERATED);
- SOCKET_OUT_COLOR(color, "Color");
- SOCKET_OUT_FLOAT(fac, "Fac");
+ SOCKET_OUT_COLOR(color, "Color");
+ SOCKET_OUT_FLOAT(fac, "Fac");
- return type;
+ return type;
}
-NoiseTextureNode::NoiseTextureNode()
-: TextureNode(node_type)
+NoiseTextureNode::NoiseTextureNode() : TextureNode(node_type)
{
}
-void NoiseTextureNode::compile(SVMCompiler& compiler)
+void NoiseTextureNode::compile(SVMCompiler &compiler)
{
- ShaderInput *distortion_in = input("Distortion");
- ShaderInput *detail_in = input("Detail");
- ShaderInput *scale_in = input("Scale");
- ShaderInput *vector_in = input("Vector");
- ShaderOutput *color_out = output("Color");
- ShaderOutput *fac_out = output("Fac");
+ ShaderInput *distortion_in = input("Distortion");
+ ShaderInput *detail_in = input("Detail");
+ ShaderInput *scale_in = input("Scale");
+ ShaderInput *vector_in = input("Vector");
+ ShaderOutput *color_out = output("Color");
+ ShaderOutput *fac_out = output("Fac");
- int vector_offset = tex_mapping.compile_begin(compiler, vector_in);
+ int vector_offset = tex_mapping.compile_begin(compiler, vector_in);
- compiler.add_node(NODE_TEX_NOISE,
- compiler.encode_uchar4(
- vector_offset,
- compiler.stack_assign_if_linked(scale_in),
- compiler.stack_assign_if_linked(detail_in),
- compiler.stack_assign_if_linked(distortion_in)),
- compiler.encode_uchar4(
- compiler.stack_assign_if_linked(color_out),
- compiler.stack_assign_if_linked(fac_out)));
- compiler.add_node(
- __float_as_int(scale),
- __float_as_int(detail),
- __float_as_int(distortion));
+ compiler.add_node(NODE_TEX_NOISE,
+ compiler.encode_uchar4(vector_offset,
+ compiler.stack_assign_if_linked(scale_in),
+ compiler.stack_assign_if_linked(detail_in),
+ compiler.stack_assign_if_linked(distortion_in)),
+ compiler.encode_uchar4(compiler.stack_assign_if_linked(color_out),
+ compiler.stack_assign_if_linked(fac_out)));
+ compiler.add_node(__float_as_int(scale), __float_as_int(detail), __float_as_int(distortion));
- tex_mapping.compile_end(compiler, vector_in, vector_offset);
+ tex_mapping.compile_end(compiler, vector_in, vector_offset);
}
-void NoiseTextureNode::compile(OSLCompiler& compiler)
+void NoiseTextureNode::compile(OSLCompiler &compiler)
{
- tex_mapping.compile(compiler);
+ tex_mapping.compile(compiler);
- compiler.add(this, "node_noise_texture");
+ compiler.add(this, "node_noise_texture");
}
/* Voronoi Texture */
NODE_DEFINE(VoronoiTextureNode)
{
- NodeType* type = NodeType::add("voronoi_texture", create, NodeType::SHADER);
+ NodeType *type = NodeType::add("voronoi_texture", create, NodeType::SHADER);
- TEXTURE_MAPPING_DEFINE(VoronoiTextureNode);
+ TEXTURE_MAPPING_DEFINE(VoronoiTextureNode);
- static NodeEnum coloring_enum;
- coloring_enum.insert("intensity", NODE_VORONOI_INTENSITY);
- coloring_enum.insert("cells", NODE_VORONOI_CELLS);
- SOCKET_ENUM(coloring, "Coloring", coloring_enum, NODE_VORONOI_INTENSITY);
+ static NodeEnum coloring_enum;
+ coloring_enum.insert("intensity", NODE_VORONOI_INTENSITY);
+ coloring_enum.insert("cells", NODE_VORONOI_CELLS);
+ SOCKET_ENUM(coloring, "Coloring", coloring_enum, NODE_VORONOI_INTENSITY);
- static NodeEnum metric;
- metric.insert("distance", NODE_VORONOI_DISTANCE);
- metric.insert("manhattan", NODE_VORONOI_MANHATTAN);
- metric.insert("chebychev", NODE_VORONOI_CHEBYCHEV);
- metric.insert("minkowski", NODE_VORONOI_MINKOWSKI);
- SOCKET_ENUM(metric, "Distance Metric", metric, NODE_VORONOI_INTENSITY);
+ static NodeEnum metric;
+ metric.insert("distance", NODE_VORONOI_DISTANCE);
+ metric.insert("manhattan", NODE_VORONOI_MANHATTAN);
+ metric.insert("chebychev", NODE_VORONOI_CHEBYCHEV);
+ metric.insert("minkowski", NODE_VORONOI_MINKOWSKI);
+ SOCKET_ENUM(metric, "Distance Metric", metric, NODE_VORONOI_INTENSITY);
- static NodeEnum feature_enum;
- feature_enum.insert("F1", NODE_VORONOI_F1);
- feature_enum.insert("F2", NODE_VORONOI_F2);
- feature_enum.insert("F3", NODE_VORONOI_F3);
- feature_enum.insert("F4", NODE_VORONOI_F4);
- feature_enum.insert("F2F1", NODE_VORONOI_F2F1);
- SOCKET_ENUM(feature, "Feature", feature_enum, NODE_VORONOI_INTENSITY);
+ static NodeEnum feature_enum;
+ feature_enum.insert("F1", NODE_VORONOI_F1);
+ feature_enum.insert("F2", NODE_VORONOI_F2);
+ feature_enum.insert("F3", NODE_VORONOI_F3);
+ feature_enum.insert("F4", NODE_VORONOI_F4);
+ feature_enum.insert("F2F1", NODE_VORONOI_F2F1);
+ SOCKET_ENUM(feature, "Feature", feature_enum, NODE_VORONOI_INTENSITY);
- SOCKET_IN_FLOAT(scale, "Scale", 1.0f);
- SOCKET_IN_FLOAT(exponent, "Exponent", 0.5f);
- SOCKET_IN_POINT(vector, "Vector", make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_TEXTURE_GENERATED);
+ SOCKET_IN_FLOAT(scale, "Scale", 1.0f);
+ SOCKET_IN_FLOAT(exponent, "Exponent", 0.5f);
+ SOCKET_IN_POINT(
+ vector, "Vector", make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_TEXTURE_GENERATED);
- SOCKET_OUT_COLOR(color, "Color");
- SOCKET_OUT_FLOAT(fac, "Fac");
+ SOCKET_OUT_COLOR(color, "Color");
+ SOCKET_OUT_FLOAT(fac, "Fac");
- return type;
+ return type;
}
-VoronoiTextureNode::VoronoiTextureNode()
-: TextureNode(node_type)
+VoronoiTextureNode::VoronoiTextureNode() : TextureNode(node_type)
{
}
-void VoronoiTextureNode::compile(SVMCompiler& compiler)
+void VoronoiTextureNode::compile(SVMCompiler &compiler)
{
- ShaderInput *scale_in = input("Scale");
- ShaderInput *vector_in = input("Vector");
- ShaderInput *exponent_in = input("Exponent");
- ShaderOutput *color_out = output("Color");
- ShaderOutput *fac_out = output("Fac");
+ ShaderInput *scale_in = input("Scale");
+ ShaderInput *vector_in = input("Vector");
+ ShaderInput *exponent_in = input("Exponent");
+ ShaderOutput *color_out = output("Color");
+ ShaderOutput *fac_out = output("Fac");
- if(vector_in->link) compiler.stack_assign(vector_in);
- if(scale_in->link) compiler.stack_assign(scale_in);
- if(exponent_in->link) compiler.stack_assign(exponent_in);
+ if (vector_in->link)
+ compiler.stack_assign(vector_in);
+ if (scale_in->link)
+ compiler.stack_assign(scale_in);
+ if (exponent_in->link)
+ compiler.stack_assign(exponent_in);
- int vector_offset = tex_mapping.compile_begin(compiler, vector_in);
+ int vector_offset = tex_mapping.compile_begin(compiler, vector_in);
- compiler.add_node(NODE_TEX_VORONOI,
- compiler.encode_uchar4(
- vector_offset,
- coloring,
- metric,
- feature
- ),
- compiler.encode_uchar4(
- compiler.stack_assign_if_linked(scale_in),
- compiler.stack_assign_if_linked(exponent_in),
- compiler.stack_assign(fac_out),
- compiler.stack_assign(color_out)
- ));
- compiler.add_node(
- __float_as_int(scale),
- __float_as_int(exponent));
+ compiler.add_node(NODE_TEX_VORONOI,
+ compiler.encode_uchar4(vector_offset, coloring, metric, feature),
+ compiler.encode_uchar4(compiler.stack_assign_if_linked(scale_in),
+ compiler.stack_assign_if_linked(exponent_in),
+ compiler.stack_assign(fac_out),
+ compiler.stack_assign(color_out)));
+ compiler.add_node(__float_as_int(scale), __float_as_int(exponent));
- tex_mapping.compile_end(compiler, vector_in, vector_offset);
+ tex_mapping.compile_end(compiler, vector_in, vector_offset);
}
-void VoronoiTextureNode::compile(OSLCompiler& compiler)
+void VoronoiTextureNode::compile(OSLCompiler &compiler)
{
- tex_mapping.compile(compiler);
+ tex_mapping.compile(compiler);
- compiler.parameter(this, "coloring");
- compiler.parameter(this, "metric");
- compiler.parameter(this, "feature");
- compiler.add(this, "node_voronoi_texture");
+ compiler.parameter(this, "coloring");
+ compiler.parameter(this, "metric");
+ compiler.parameter(this, "feature");
+ compiler.add(this, "node_voronoi_texture");
}
/* IES Light */
NODE_DEFINE(IESLightNode)
{
- NodeType* type = NodeType::add("ies_light", create, NodeType::SHADER);
+ NodeType *type = NodeType::add("ies_light", create, NodeType::SHADER);
- TEXTURE_MAPPING_DEFINE(IESLightNode);
+ TEXTURE_MAPPING_DEFINE(IESLightNode);
- SOCKET_STRING(ies, "IES", ustring());
- SOCKET_STRING(filename, "File Name", ustring());
+ SOCKET_STRING(ies, "IES", ustring());
+ SOCKET_STRING(filename, "File Name", ustring());
- SOCKET_IN_FLOAT(strength, "Strength", 1.0f);
- SOCKET_IN_POINT(vector, "Vector", make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_TEXTURE_NORMAL);
+ SOCKET_IN_FLOAT(strength, "Strength", 1.0f);
+ SOCKET_IN_POINT(
+ vector, "Vector", make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_TEXTURE_NORMAL);
- SOCKET_OUT_FLOAT(fac, "Fac");
+ SOCKET_OUT_FLOAT(fac, "Fac");
- return type;
+ return type;
}
-IESLightNode::IESLightNode()
-: TextureNode(node_type)
+IESLightNode::IESLightNode() : TextureNode(node_type)
{
- light_manager = NULL;
- slot = -1;
+ light_manager = NULL;
+ slot = -1;
}
ShaderNode *IESLightNode::clone() const
{
- IESLightNode *node = new IESLightNode(*this);
+ IESLightNode *node = new IESLightNode(*this);
- node->light_manager = NULL;
- node->slot = -1;
+ node->light_manager = NULL;
+ node->slot = -1;
- return node;
+ return node;
}
IESLightNode::~IESLightNode()
{
- if(light_manager) {
- light_manager->remove_ies(slot);
- }
+ if (light_manager) {
+ light_manager->remove_ies(slot);
+ }
}
void IESLightNode::get_slot()
{
- assert(light_manager);
+ assert(light_manager);
- if(slot == -1) {
- if(ies.empty()) {
- slot = light_manager->add_ies_from_file(filename);
- }
- else {
- slot = light_manager->add_ies(ies);
- }
- }
+ if (slot == -1) {
+ if (ies.empty()) {
+ slot = light_manager->add_ies_from_file(filename);
+ }
+ else {
+ slot = light_manager->add_ies(ies);
+ }
+ }
}
-void IESLightNode::compile(SVMCompiler& compiler)
+void IESLightNode::compile(SVMCompiler &compiler)
{
- light_manager = compiler.light_manager;
- get_slot();
+ light_manager = compiler.light_manager;
+ get_slot();
- ShaderInput *strength_in = input("Strength");
- ShaderInput *vector_in = input("Vector");
- ShaderOutput *fac_out = output("Fac");
+ ShaderInput *strength_in = input("Strength");
+ ShaderInput *vector_in = input("Vector");
+ ShaderOutput *fac_out = output("Fac");
- int vector_offset = tex_mapping.compile_begin(compiler, vector_in);
+ int vector_offset = tex_mapping.compile_begin(compiler, vector_in);
- compiler.add_node(NODE_IES,
- compiler.encode_uchar4(
- compiler.stack_assign_if_linked(strength_in),
- vector_offset,
- compiler.stack_assign(fac_out),
- 0),
- slot,
- __float_as_int(strength));
+ compiler.add_node(NODE_IES,
+ compiler.encode_uchar4(compiler.stack_assign_if_linked(strength_in),
+ vector_offset,
+ compiler.stack_assign(fac_out),
+ 0),
+ slot,
+ __float_as_int(strength));
- tex_mapping.compile_end(compiler, vector_in, vector_offset);
+ tex_mapping.compile_end(compiler, vector_in, vector_offset);
}
-void IESLightNode::compile(OSLCompiler& compiler)
+void IESLightNode::compile(OSLCompiler &compiler)
{
- light_manager = compiler.light_manager;
- get_slot();
+ light_manager = compiler.light_manager;
+ get_slot();
- tex_mapping.compile(compiler);
+ tex_mapping.compile(compiler);
- compiler.parameter("slot", slot);
- compiler.add(this, "node_ies_light");
+ compiler.parameter("slot", slot);
+ compiler.add(this, "node_ies_light");
}
/* Musgrave Texture */
NODE_DEFINE(MusgraveTextureNode)
{
- NodeType* type = NodeType::add("musgrave_texture", create, NodeType::SHADER);
+ NodeType *type = NodeType::add("musgrave_texture", create, NodeType::SHADER);
- TEXTURE_MAPPING_DEFINE(MusgraveTextureNode);
+ TEXTURE_MAPPING_DEFINE(MusgraveTextureNode);
- static NodeEnum type_enum;
- type_enum.insert("multifractal", NODE_MUSGRAVE_MULTIFRACTAL);
- type_enum.insert("fBM", NODE_MUSGRAVE_FBM);
- type_enum.insert("hybrid_multifractal", NODE_MUSGRAVE_HYBRID_MULTIFRACTAL);
- type_enum.insert("ridged_multifractal", NODE_MUSGRAVE_RIDGED_MULTIFRACTAL);
- type_enum.insert("hetero_terrain", NODE_MUSGRAVE_HETERO_TERRAIN);
- SOCKET_ENUM(type, "Type", type_enum, NODE_MUSGRAVE_FBM);
+ static NodeEnum type_enum;
+ type_enum.insert("multifractal", NODE_MUSGRAVE_MULTIFRACTAL);
+ type_enum.insert("fBM", NODE_MUSGRAVE_FBM);
+ type_enum.insert("hybrid_multifractal", NODE_MUSGRAVE_HYBRID_MULTIFRACTAL);
+ type_enum.insert("ridged_multifractal", NODE_MUSGRAVE_RIDGED_MULTIFRACTAL);
+ type_enum.insert("hetero_terrain", NODE_MUSGRAVE_HETERO_TERRAIN);
+ SOCKET_ENUM(type, "Type", type_enum, NODE_MUSGRAVE_FBM);
- SOCKET_IN_FLOAT(scale, "Scale", 1.0f);
- SOCKET_IN_FLOAT(detail, "Detail", 2.0f);
- SOCKET_IN_FLOAT(dimension, "Dimension", 2.0f);
- SOCKET_IN_FLOAT(lacunarity, "Lacunarity", 1.0f);
- SOCKET_IN_FLOAT(offset, "Offset", 0.0f);
- SOCKET_IN_FLOAT(gain, "Gain", 1.0f);
- SOCKET_IN_POINT(vector, "Vector", make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_TEXTURE_GENERATED);
+ SOCKET_IN_FLOAT(scale, "Scale", 1.0f);
+ SOCKET_IN_FLOAT(detail, "Detail", 2.0f);
+ SOCKET_IN_FLOAT(dimension, "Dimension", 2.0f);
+ SOCKET_IN_FLOAT(lacunarity, "Lacunarity", 1.0f);
+ SOCKET_IN_FLOAT(offset, "Offset", 0.0f);
+ SOCKET_IN_FLOAT(gain, "Gain", 1.0f);
+ SOCKET_IN_POINT(
+ vector, "Vector", make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_TEXTURE_GENERATED);
- SOCKET_OUT_COLOR(color, "Color");
- SOCKET_OUT_FLOAT(fac, "Fac");
+ SOCKET_OUT_COLOR(color, "Color");
+ SOCKET_OUT_FLOAT(fac, "Fac");
- return type;
+ return type;
}
-MusgraveTextureNode::MusgraveTextureNode()
-: TextureNode(node_type)
+MusgraveTextureNode::MusgraveTextureNode() : TextureNode(node_type)
{
}
-void MusgraveTextureNode::compile(SVMCompiler& compiler)
+void MusgraveTextureNode::compile(SVMCompiler &compiler)
{
- ShaderInput *vector_in = input("Vector");
- ShaderInput *scale_in = input("Scale");
- ShaderInput *dimension_in = input("Dimension");
- ShaderInput *lacunarity_in = input("Lacunarity");
- ShaderInput *detail_in = input("Detail");
- ShaderInput *offset_in = input("Offset");
- ShaderInput *gain_in = input("Gain");
- ShaderOutput *fac_out = output("Fac");
- ShaderOutput *color_out = output("Color");
+ ShaderInput *vector_in = input("Vector");
+ ShaderInput *scale_in = input("Scale");
+ ShaderInput *dimension_in = input("Dimension");
+ ShaderInput *lacunarity_in = input("Lacunarity");
+ ShaderInput *detail_in = input("Detail");
+ ShaderInput *offset_in = input("Offset");
+ ShaderInput *gain_in = input("Gain");
+ ShaderOutput *fac_out = output("Fac");
+ ShaderOutput *color_out = output("Color");
- int vector_offset = tex_mapping.compile_begin(compiler, vector_in);
+ int vector_offset = tex_mapping.compile_begin(compiler, vector_in);
- compiler.add_node(NODE_TEX_MUSGRAVE,
- compiler.encode_uchar4(
- type,
- vector_offset,
- compiler.stack_assign_if_linked(color_out),
- compiler.stack_assign_if_linked(fac_out)),
- compiler.encode_uchar4(
- compiler.stack_assign_if_linked(dimension_in),
- compiler.stack_assign_if_linked(lacunarity_in),
- compiler.stack_assign_if_linked(detail_in),
- compiler.stack_assign_if_linked(offset_in)),
- compiler.encode_uchar4(
- compiler.stack_assign_if_linked(gain_in),
- compiler.stack_assign_if_linked(scale_in)));
- compiler.add_node(__float_as_int(dimension),
- __float_as_int(lacunarity),
- __float_as_int(detail),
- __float_as_int(offset));
- compiler.add_node(__float_as_int(gain),
- __float_as_int(scale));
+ compiler.add_node(NODE_TEX_MUSGRAVE,
+ compiler.encode_uchar4(type,
+ vector_offset,
+ compiler.stack_assign_if_linked(color_out),
+ compiler.stack_assign_if_linked(fac_out)),
+ compiler.encode_uchar4(compiler.stack_assign_if_linked(dimension_in),
+ compiler.stack_assign_if_linked(lacunarity_in),
+ compiler.stack_assign_if_linked(detail_in),
+ compiler.stack_assign_if_linked(offset_in)),
+ compiler.encode_uchar4(compiler.stack_assign_if_linked(gain_in),
+ compiler.stack_assign_if_linked(scale_in)));
+ compiler.add_node(__float_as_int(dimension),
+ __float_as_int(lacunarity),
+ __float_as_int(detail),
+ __float_as_int(offset));
+ compiler.add_node(__float_as_int(gain), __float_as_int(scale));
- tex_mapping.compile_end(compiler, vector_in, vector_offset);
+ tex_mapping.compile_end(compiler, vector_in, vector_offset);
}
-void MusgraveTextureNode::compile(OSLCompiler& compiler)
+void MusgraveTextureNode::compile(OSLCompiler &compiler)
{
- tex_mapping.compile(compiler);
+ tex_mapping.compile(compiler);
- compiler.parameter(this, "type");
- compiler.add(this, "node_musgrave_texture");
+ compiler.parameter(this, "type");
+ compiler.add(this, "node_musgrave_texture");
}
/* Wave Texture */
NODE_DEFINE(WaveTextureNode)
{
- NodeType* type = NodeType::add("wave_texture", create, NodeType::SHADER);
+ NodeType *type = NodeType::add("wave_texture", create, NodeType::SHADER);
- TEXTURE_MAPPING_DEFINE(WaveTextureNode);
+ TEXTURE_MAPPING_DEFINE(WaveTextureNode);
- static NodeEnum type_enum;
- type_enum.insert("bands", NODE_WAVE_BANDS);
- type_enum.insert("rings", NODE_WAVE_RINGS);
- SOCKET_ENUM(type, "Type", type_enum, NODE_WAVE_BANDS);
+ static NodeEnum type_enum;
+ type_enum.insert("bands", NODE_WAVE_BANDS);
+ type_enum.insert("rings", NODE_WAVE_RINGS);
+ SOCKET_ENUM(type, "Type", type_enum, NODE_WAVE_BANDS);
- static NodeEnum profile_enum;
- profile_enum.insert("sine", NODE_WAVE_PROFILE_SIN);
- profile_enum.insert("saw", NODE_WAVE_PROFILE_SAW);
- SOCKET_ENUM(profile, "Profile", profile_enum, NODE_WAVE_PROFILE_SIN);
+ static NodeEnum profile_enum;
+ profile_enum.insert("sine", NODE_WAVE_PROFILE_SIN);
+ profile_enum.insert("saw", NODE_WAVE_PROFILE_SAW);
+ SOCKET_ENUM(profile, "Profile", profile_enum, NODE_WAVE_PROFILE_SIN);
- SOCKET_IN_FLOAT(scale, "Scale", 1.0f);
- SOCKET_IN_FLOAT(distortion, "Distortion", 0.0f);
- SOCKET_IN_FLOAT(detail, "Detail", 2.0f);
- SOCKET_IN_FLOAT(detail_scale, "Detail Scale", 0.0f);
- SOCKET_IN_POINT(vector, "Vector", make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_TEXTURE_GENERATED);
+ SOCKET_IN_FLOAT(scale, "Scale", 1.0f);
+ SOCKET_IN_FLOAT(distortion, "Distortion", 0.0f);
+ SOCKET_IN_FLOAT(detail, "Detail", 2.0f);
+ SOCKET_IN_FLOAT(detail_scale, "Detail Scale", 0.0f);
+ SOCKET_IN_POINT(
+ vector, "Vector", make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_TEXTURE_GENERATED);
- SOCKET_OUT_COLOR(color, "Color");
- SOCKET_OUT_FLOAT(fac, "Fac");
+ SOCKET_OUT_COLOR(color, "Color");
+ SOCKET_OUT_FLOAT(fac, "Fac");
- return type;
+ return type;
}
-WaveTextureNode::WaveTextureNode()
-: TextureNode(node_type)
+WaveTextureNode::WaveTextureNode() : TextureNode(node_type)
{
}
-void WaveTextureNode::compile(SVMCompiler& compiler)
+void WaveTextureNode::compile(SVMCompiler &compiler)
{
- ShaderInput *scale_in = input("Scale");
- ShaderInput *distortion_in = input("Distortion");
- ShaderInput *dscale_in = input("Detail Scale");
- ShaderInput *detail_in = input("Detail");
- ShaderInput *vector_in = input("Vector");
- ShaderOutput *fac_out = output("Fac");
- ShaderOutput *color_out = output("Color");
+ ShaderInput *scale_in = input("Scale");
+ ShaderInput *distortion_in = input("Distortion");
+ ShaderInput *dscale_in = input("Detail Scale");
+ ShaderInput *detail_in = input("Detail");
+ ShaderInput *vector_in = input("Vector");
+ ShaderOutput *fac_out = output("Fac");
+ ShaderOutput *color_out = output("Color");
- int vector_offset = tex_mapping.compile_begin(compiler, vector_in);
+ int vector_offset = tex_mapping.compile_begin(compiler, vector_in);
- compiler.add_node(NODE_TEX_WAVE,
- compiler.encode_uchar4(
- type,
- compiler.stack_assign_if_linked(color_out),
- compiler.stack_assign_if_linked(fac_out),
- compiler.stack_assign_if_linked(dscale_in)),
- compiler.encode_uchar4(
- vector_offset,
- compiler.stack_assign_if_linked(scale_in),
- compiler.stack_assign_if_linked(detail_in),
- compiler.stack_assign_if_linked(distortion_in)),
- profile);
+ compiler.add_node(NODE_TEX_WAVE,
+ compiler.encode_uchar4(type,
+ compiler.stack_assign_if_linked(color_out),
+ compiler.stack_assign_if_linked(fac_out),
+ compiler.stack_assign_if_linked(dscale_in)),
+ compiler.encode_uchar4(vector_offset,
+ compiler.stack_assign_if_linked(scale_in),
+ compiler.stack_assign_if_linked(detail_in),
+ compiler.stack_assign_if_linked(distortion_in)),
+ profile);
- compiler.add_node(
- __float_as_int(scale),
- __float_as_int(detail),
- __float_as_int(distortion),
- __float_as_int(detail_scale));
+ compiler.add_node(__float_as_int(scale),
+ __float_as_int(detail),
+ __float_as_int(distortion),
+ __float_as_int(detail_scale));
- tex_mapping.compile_end(compiler, vector_in, vector_offset);
+ tex_mapping.compile_end(compiler, vector_in, vector_offset);
}
-void WaveTextureNode::compile(OSLCompiler& compiler)
+void WaveTextureNode::compile(OSLCompiler &compiler)
{
- tex_mapping.compile(compiler);
+ tex_mapping.compile(compiler);
- compiler.parameter(this, "type");
- compiler.parameter(this, "profile");
+ compiler.parameter(this, "type");
+ compiler.parameter(this, "profile");
- compiler.add(this, "node_wave_texture");
+ compiler.add(this, "node_wave_texture");
}
/* Magic Texture */
NODE_DEFINE(MagicTextureNode)
{
- NodeType* type = NodeType::add("magic_texture", create, NodeType::SHADER);
+ NodeType *type = NodeType::add("magic_texture", create, NodeType::SHADER);
- TEXTURE_MAPPING_DEFINE(MagicTextureNode);
+ TEXTURE_MAPPING_DEFINE(MagicTextureNode);
- SOCKET_INT(depth, "Depth", 2);
+ SOCKET_INT(depth, "Depth", 2);
- SOCKET_IN_POINT(vector, "Vector", make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_TEXTURE_GENERATED);
- SOCKET_IN_FLOAT(scale, "Scale", 5.0f);
- SOCKET_IN_FLOAT(distortion, "Distortion", 1.0f);
+ SOCKET_IN_POINT(
+ vector, "Vector", make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_TEXTURE_GENERATED);
+ SOCKET_IN_FLOAT(scale, "Scale", 5.0f);
+ SOCKET_IN_FLOAT(distortion, "Distortion", 1.0f);
- SOCKET_OUT_COLOR(color, "Color");
- SOCKET_OUT_FLOAT(fac, "Fac");
+ SOCKET_OUT_COLOR(color, "Color");
+ SOCKET_OUT_FLOAT(fac, "Fac");
- return type;
+ return type;
}
-MagicTextureNode::MagicTextureNode()
-: TextureNode(node_type)
+MagicTextureNode::MagicTextureNode() : TextureNode(node_type)
{
}
-void MagicTextureNode::compile(SVMCompiler& compiler)
+void MagicTextureNode::compile(SVMCompiler &compiler)
{
- ShaderInput *vector_in = input("Vector");
- ShaderInput *scale_in = input("Scale");
- ShaderInput *distortion_in = input("Distortion");
- ShaderOutput *color_out = output("Color");
- ShaderOutput *fac_out = output("Fac");
+ ShaderInput *vector_in = input("Vector");
+ ShaderInput *scale_in = input("Scale");
+ ShaderInput *distortion_in = input("Distortion");
+ ShaderOutput *color_out = output("Color");
+ ShaderOutput *fac_out = output("Fac");
- int vector_offset = tex_mapping.compile_begin(compiler, vector_in);
+ int vector_offset = tex_mapping.compile_begin(compiler, vector_in);
- compiler.add_node(NODE_TEX_MAGIC,
- compiler.encode_uchar4(
- depth,
- compiler.stack_assign_if_linked(color_out),
- compiler.stack_assign_if_linked(fac_out)),
- compiler.encode_uchar4(
- vector_offset,
- compiler.stack_assign_if_linked(scale_in),
- compiler.stack_assign_if_linked(distortion_in)));
- compiler.add_node(
- __float_as_int(scale),
- __float_as_int(distortion));
+ compiler.add_node(NODE_TEX_MAGIC,
+ compiler.encode_uchar4(depth,
+ compiler.stack_assign_if_linked(color_out),
+ compiler.stack_assign_if_linked(fac_out)),
+ compiler.encode_uchar4(vector_offset,
+ compiler.stack_assign_if_linked(scale_in),
+ compiler.stack_assign_if_linked(distortion_in)));
+ compiler.add_node(__float_as_int(scale), __float_as_int(distortion));
- tex_mapping.compile_end(compiler, vector_in, vector_offset);
+ tex_mapping.compile_end(compiler, vector_in, vector_offset);
}
-void MagicTextureNode::compile(OSLCompiler& compiler)
+void MagicTextureNode::compile(OSLCompiler &compiler)
{
- tex_mapping.compile(compiler);
+ tex_mapping.compile(compiler);
- compiler.parameter(this, "depth");
- compiler.add(this, "node_magic_texture");
+ compiler.parameter(this, "depth");
+ compiler.add(this, "node_magic_texture");
}
/* Checker Texture */
NODE_DEFINE(CheckerTextureNode)
{
- NodeType* type = NodeType::add("checker_texture", create, NodeType::SHADER);
+ NodeType *type = NodeType::add("checker_texture", create, NodeType::SHADER);
- TEXTURE_MAPPING_DEFINE(CheckerTextureNode);
+ TEXTURE_MAPPING_DEFINE(CheckerTextureNode);
- SOCKET_IN_POINT(vector, "Vector", make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_TEXTURE_GENERATED);
- SOCKET_IN_COLOR(color1, "Color1", make_float3(0.0f, 0.0f, 0.0f));
- SOCKET_IN_COLOR(color2, "Color2", make_float3(0.0f, 0.0f, 0.0f));
- SOCKET_IN_FLOAT(scale, "Scale", 1.0f);
+ SOCKET_IN_POINT(
+ vector, "Vector", make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_TEXTURE_GENERATED);
+ SOCKET_IN_COLOR(color1, "Color1", make_float3(0.0f, 0.0f, 0.0f));
+ SOCKET_IN_COLOR(color2, "Color2", make_float3(0.0f, 0.0f, 0.0f));
+ SOCKET_IN_FLOAT(scale, "Scale", 1.0f);
- SOCKET_OUT_COLOR(color, "Color");
- SOCKET_OUT_FLOAT(fac, "Fac");
+ SOCKET_OUT_COLOR(color, "Color");
+ SOCKET_OUT_FLOAT(fac, "Fac");
- return type;
+ return type;
}
-CheckerTextureNode::CheckerTextureNode()
-: TextureNode(node_type)
+CheckerTextureNode::CheckerTextureNode() : TextureNode(node_type)
{
}
-void CheckerTextureNode::compile(SVMCompiler& compiler)
+void CheckerTextureNode::compile(SVMCompiler &compiler)
{
- ShaderInput *vector_in = input("Vector");
- ShaderInput *color1_in = input("Color1");
- ShaderInput *color2_in = input("Color2");
- ShaderInput *scale_in = input("Scale");
+ ShaderInput *vector_in = input("Vector");
+ ShaderInput *color1_in = input("Color1");
+ ShaderInput *color2_in = input("Color2");
+ ShaderInput *scale_in = input("Scale");
- ShaderOutput *color_out = output("Color");
- ShaderOutput *fac_out = output("Fac");
+ ShaderOutput *color_out = output("Color");
+ ShaderOutput *fac_out = output("Fac");
- int vector_offset = tex_mapping.compile_begin(compiler, vector_in);
+ int vector_offset = tex_mapping.compile_begin(compiler, vector_in);
- compiler.add_node(NODE_TEX_CHECKER,
- compiler.encode_uchar4(
- vector_offset,
- compiler.stack_assign(color1_in),
- compiler.stack_assign(color2_in),
- compiler.stack_assign_if_linked(scale_in)),
- compiler.encode_uchar4(
- compiler.stack_assign_if_linked(color_out),
- compiler.stack_assign_if_linked(fac_out)),
- __float_as_int(scale));
+ compiler.add_node(NODE_TEX_CHECKER,
+ compiler.encode_uchar4(vector_offset,
+ compiler.stack_assign(color1_in),
+ compiler.stack_assign(color2_in),
+ compiler.stack_assign_if_linked(scale_in)),
+ compiler.encode_uchar4(compiler.stack_assign_if_linked(color_out),
+ compiler.stack_assign_if_linked(fac_out)),
+ __float_as_int(scale));
- tex_mapping.compile_end(compiler, vector_in, vector_offset);
+ tex_mapping.compile_end(compiler, vector_in, vector_offset);
}
-void CheckerTextureNode::compile(OSLCompiler& compiler)
+void CheckerTextureNode::compile(OSLCompiler &compiler)
{
- tex_mapping.compile(compiler);
+ tex_mapping.compile(compiler);
- compiler.add(this, "node_checker_texture");
+ compiler.add(this, "node_checker_texture");
}
/* Brick Texture */
NODE_DEFINE(BrickTextureNode)
{
- NodeType* type = NodeType::add("brick_texture", create, NodeType::SHADER);
+ NodeType *type = NodeType::add("brick_texture", create, NodeType::SHADER);
- TEXTURE_MAPPING_DEFINE(BrickTextureNode);
+ TEXTURE_MAPPING_DEFINE(BrickTextureNode);
- SOCKET_FLOAT(offset, "Offset", 0.5f);
- SOCKET_INT(offset_frequency, "Offset Frequency", 2);
- SOCKET_FLOAT(squash, "Squash", 1.0f);
- SOCKET_INT(squash_frequency, "Squash Frequency", 2);
+ SOCKET_FLOAT(offset, "Offset", 0.5f);
+ SOCKET_INT(offset_frequency, "Offset Frequency", 2);
+ SOCKET_FLOAT(squash, "Squash", 1.0f);
+ SOCKET_INT(squash_frequency, "Squash Frequency", 2);
- SOCKET_IN_POINT(vector, "Vector", make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_TEXTURE_GENERATED);
+ SOCKET_IN_POINT(
+ vector, "Vector", make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_TEXTURE_GENERATED);
- SOCKET_IN_COLOR(color1, "Color1", make_float3(0.0f, 0.0f, 0.0f));
- SOCKET_IN_COLOR(color2, "Color2", make_float3(0.0f, 0.0f, 0.0f));
- SOCKET_IN_COLOR(mortar, "Mortar", make_float3(0.0f, 0.0f, 0.0f));
- SOCKET_IN_FLOAT(scale, "Scale", 5.0f);
- SOCKET_IN_FLOAT(mortar_size, "Mortar Size", 0.02f);
- SOCKET_IN_FLOAT(mortar_smooth, "Mortar Smooth", 0.0f);
- SOCKET_IN_FLOAT(bias, "Bias", 0.0f);
- SOCKET_IN_FLOAT(brick_width, "Brick Width", 0.5f);
- SOCKET_IN_FLOAT(row_height, "Row Height", 0.25f);
+ SOCKET_IN_COLOR(color1, "Color1", make_float3(0.0f, 0.0f, 0.0f));
+ SOCKET_IN_COLOR(color2, "Color2", make_float3(0.0f, 0.0f, 0.0f));
+ SOCKET_IN_COLOR(mortar, "Mortar", make_float3(0.0f, 0.0f, 0.0f));
+ SOCKET_IN_FLOAT(scale, "Scale", 5.0f);
+ SOCKET_IN_FLOAT(mortar_size, "Mortar Size", 0.02f);
+ SOCKET_IN_FLOAT(mortar_smooth, "Mortar Smooth", 0.0f);
+ SOCKET_IN_FLOAT(bias, "Bias", 0.0f);
+ SOCKET_IN_FLOAT(brick_width, "Brick Width", 0.5f);
+ SOCKET_IN_FLOAT(row_height, "Row Height", 0.25f);
- SOCKET_OUT_COLOR(color, "Color");
- SOCKET_OUT_FLOAT(fac, "Fac");
+ SOCKET_OUT_COLOR(color, "Color");
+ SOCKET_OUT_FLOAT(fac, "Fac");
- return type;
+ return type;
}
-BrickTextureNode::BrickTextureNode()
-: TextureNode(node_type)
+BrickTextureNode::BrickTextureNode() : TextureNode(node_type)
{
}
-void BrickTextureNode::compile(SVMCompiler& compiler)
+void BrickTextureNode::compile(SVMCompiler &compiler)
{
- ShaderInput *vector_in = input("Vector");
- ShaderInput *color1_in = input("Color1");
- ShaderInput *color2_in = input("Color2");
- ShaderInput *mortar_in = input("Mortar");
- ShaderInput *scale_in = input("Scale");
- ShaderInput *mortar_size_in = input("Mortar Size");
- ShaderInput *mortar_smooth_in = input("Mortar Smooth");
- ShaderInput *bias_in = input("Bias");
- ShaderInput *brick_width_in = input("Brick Width");
- ShaderInput *row_height_in = input("Row Height");
+ ShaderInput *vector_in = input("Vector");
+ ShaderInput *color1_in = input("Color1");
+ ShaderInput *color2_in = input("Color2");
+ ShaderInput *mortar_in = input("Mortar");
+ ShaderInput *scale_in = input("Scale");
+ ShaderInput *mortar_size_in = input("Mortar Size");
+ ShaderInput *mortar_smooth_in = input("Mortar Smooth");
+ ShaderInput *bias_in = input("Bias");
+ ShaderInput *brick_width_in = input("Brick Width");
+ ShaderInput *row_height_in = input("Row Height");
- ShaderOutput *color_out = output("Color");
- ShaderOutput *fac_out = output("Fac");
+ ShaderOutput *color_out = output("Color");
+ ShaderOutput *fac_out = output("Fac");
- int vector_offset = tex_mapping.compile_begin(compiler, vector_in);
+ int vector_offset = tex_mapping.compile_begin(compiler, vector_in);
- compiler.add_node(NODE_TEX_BRICK,
- compiler.encode_uchar4(
- vector_offset,
- compiler.stack_assign(color1_in),
- compiler.stack_assign(color2_in),
- compiler.stack_assign(mortar_in)),
- compiler.encode_uchar4(
- compiler.stack_assign_if_linked(scale_in),
- compiler.stack_assign_if_linked(mortar_size_in),
- compiler.stack_assign_if_linked(bias_in),
- compiler.stack_assign_if_linked(brick_width_in)),
- compiler.encode_uchar4(
- compiler.stack_assign_if_linked(row_height_in),
- compiler.stack_assign_if_linked(color_out),
- compiler.stack_assign_if_linked(fac_out),
- compiler.stack_assign_if_linked(mortar_smooth_in)));
+ compiler.add_node(NODE_TEX_BRICK,
+ compiler.encode_uchar4(vector_offset,
+ compiler.stack_assign(color1_in),
+ compiler.stack_assign(color2_in),
+ compiler.stack_assign(mortar_in)),
+ compiler.encode_uchar4(compiler.stack_assign_if_linked(scale_in),
+ compiler.stack_assign_if_linked(mortar_size_in),
+ compiler.stack_assign_if_linked(bias_in),
+ compiler.stack_assign_if_linked(brick_width_in)),
+ compiler.encode_uchar4(compiler.stack_assign_if_linked(row_height_in),
+ compiler.stack_assign_if_linked(color_out),
+ compiler.stack_assign_if_linked(fac_out),
+ compiler.stack_assign_if_linked(mortar_smooth_in)));
- compiler.add_node(compiler.encode_uchar4(offset_frequency, squash_frequency),
- __float_as_int(scale),
- __float_as_int(mortar_size),
- __float_as_int(bias));
+ compiler.add_node(compiler.encode_uchar4(offset_frequency, squash_frequency),
+ __float_as_int(scale),
+ __float_as_int(mortar_size),
+ __float_as_int(bias));
- compiler.add_node(__float_as_int(brick_width),
- __float_as_int(row_height),
- __float_as_int(offset),
- __float_as_int(squash));
+ compiler.add_node(__float_as_int(brick_width),
+ __float_as_int(row_height),
+ __float_as_int(offset),
+ __float_as_int(squash));
- compiler.add_node(__float_as_int(mortar_smooth),
- SVM_STACK_INVALID,
- SVM_STACK_INVALID,
- SVM_STACK_INVALID);
+ compiler.add_node(
+ __float_as_int(mortar_smooth), SVM_STACK_INVALID, SVM_STACK_INVALID, SVM_STACK_INVALID);
- tex_mapping.compile_end(compiler, vector_in, vector_offset);
+ tex_mapping.compile_end(compiler, vector_in, vector_offset);
}
-void BrickTextureNode::compile(OSLCompiler& compiler)
+void BrickTextureNode::compile(OSLCompiler &compiler)
{
- tex_mapping.compile(compiler);
+ tex_mapping.compile(compiler);
- compiler.parameter(this, "offset");
- compiler.parameter(this, "offset_frequency");
- compiler.parameter(this, "squash");
- compiler.parameter(this, "squash_frequency");
- compiler.add(this, "node_brick_texture");
+ compiler.parameter(this, "offset");
+ compiler.parameter(this, "offset_frequency");
+ compiler.parameter(this, "squash");
+ compiler.parameter(this, "squash_frequency");
+ compiler.add(this, "node_brick_texture");
}
/* Point Density Texture */
NODE_DEFINE(PointDensityTextureNode)
{
- NodeType* type = NodeType::add("point_density_texture", create, NodeType::SHADER);
+ NodeType *type = NodeType::add("point_density_texture", create, NodeType::SHADER);
- SOCKET_STRING(filename, "Filename", ustring());
+ SOCKET_STRING(filename, "Filename", ustring());
- static NodeEnum space_enum;
- space_enum.insert("object", NODE_TEX_VOXEL_SPACE_OBJECT);
- space_enum.insert("world", NODE_TEX_VOXEL_SPACE_WORLD);
- SOCKET_ENUM(space, "Space", space_enum, NODE_TEX_VOXEL_SPACE_OBJECT);
+ static NodeEnum space_enum;
+ space_enum.insert("object", NODE_TEX_VOXEL_SPACE_OBJECT);
+ space_enum.insert("world", NODE_TEX_VOXEL_SPACE_WORLD);
+ SOCKET_ENUM(space, "Space", space_enum, NODE_TEX_VOXEL_SPACE_OBJECT);
- static NodeEnum interpolation_enum;
- interpolation_enum.insert("closest", INTERPOLATION_CLOSEST);
- interpolation_enum.insert("linear", INTERPOLATION_LINEAR);
- interpolation_enum.insert("cubic", INTERPOLATION_CUBIC);
- interpolation_enum.insert("smart", INTERPOLATION_SMART);
- SOCKET_ENUM(interpolation, "Interpolation", interpolation_enum, INTERPOLATION_LINEAR);
+ static NodeEnum interpolation_enum;
+ interpolation_enum.insert("closest", INTERPOLATION_CLOSEST);
+ interpolation_enum.insert("linear", INTERPOLATION_LINEAR);
+ interpolation_enum.insert("cubic", INTERPOLATION_CUBIC);
+ interpolation_enum.insert("smart", INTERPOLATION_SMART);
+ SOCKET_ENUM(interpolation, "Interpolation", interpolation_enum, INTERPOLATION_LINEAR);
- SOCKET_TRANSFORM(tfm, "Transform", transform_identity());
+ SOCKET_TRANSFORM(tfm, "Transform", transform_identity());
- SOCKET_IN_POINT(vector, "Vector", make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_POSITION);
+ SOCKET_IN_POINT(vector, "Vector", make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_POSITION);
- SOCKET_OUT_FLOAT(density, "Density");
- SOCKET_OUT_COLOR(color, "Color");
+ SOCKET_OUT_FLOAT(density, "Density");
+ SOCKET_OUT_COLOR(color, "Color");
- return type;
+ return type;
}
-PointDensityTextureNode::PointDensityTextureNode()
-: ShaderNode(node_type)
+PointDensityTextureNode::PointDensityTextureNode() : ShaderNode(node_type)
{
- image_manager = NULL;
- slot = -1;
- builtin_data = NULL;
+ image_manager = NULL;
+ slot = -1;
+ builtin_data = NULL;
}
PointDensityTextureNode::~PointDensityTextureNode()
{
- if(image_manager) {
- image_manager->remove_image(filename.string(),
- builtin_data,
- interpolation,
- EXTENSION_CLIP,
- true);
- }
+ if (image_manager) {
+ image_manager->remove_image(
+ filename.string(), builtin_data, interpolation, EXTENSION_CLIP, true);
+ }
}
ShaderNode *PointDensityTextureNode::clone() const
{
- PointDensityTextureNode *node = new PointDensityTextureNode(*this);
- node->image_manager = NULL;
- node->slot = -1;
- return node;
+ PointDensityTextureNode *node = new PointDensityTextureNode(*this);
+ node->image_manager = NULL;
+ node->slot = -1;
+ return node;
}
-void PointDensityTextureNode::attributes(Shader *shader,
- AttributeRequestSet *attributes)
+void PointDensityTextureNode::attributes(Shader *shader, AttributeRequestSet *attributes)
{
- if(shader->has_volume)
- attributes->add(ATTR_STD_GENERATED_TRANSFORM);
+ if (shader->has_volume)
+ attributes->add(ATTR_STD_GENERATED_TRANSFORM);
- ShaderNode::attributes(shader, attributes);
+ ShaderNode::attributes(shader, attributes);
}
void PointDensityTextureNode::add_image()
{
- if(slot == -1) {
- ImageMetaData metadata;
- slot = image_manager->add_image(filename.string(), builtin_data,
- false, 0,
- interpolation,
- EXTENSION_CLIP,
- true,
- metadata);
- }
-}
-
-void PointDensityTextureNode::compile(SVMCompiler& compiler)
-{
- ShaderInput *vector_in = input("Vector");
- ShaderOutput *density_out = output("Density");
- ShaderOutput *color_out = output("Color");
-
- const bool use_density = !density_out->links.empty();
- const bool use_color = !color_out->links.empty();
-
- image_manager = compiler.image_manager;
-
- if(use_density || use_color) {
- add_image();
-
- if(slot != -1) {
- compiler.stack_assign(vector_in);
- compiler.add_node(NODE_TEX_VOXEL,
- slot,
- compiler.encode_uchar4(compiler.stack_assign(vector_in),
- compiler.stack_assign_if_linked(density_out),
- compiler.stack_assign_if_linked(color_out),
- space));
- if(space == NODE_TEX_VOXEL_SPACE_WORLD) {
- compiler.add_node(tfm.x);
- compiler.add_node(tfm.y);
- compiler.add_node(tfm.z);
- }
- }
- else {
- if(use_density) {
- compiler.add_node(NODE_VALUE_F,
- __float_as_int(0.0f),
- compiler.stack_assign(density_out));
- }
- if(use_color) {
- compiler.add_node(NODE_VALUE_V, compiler.stack_assign(color_out));
- compiler.add_node(NODE_VALUE_V, make_float3(TEX_IMAGE_MISSING_R,
- TEX_IMAGE_MISSING_G,
- TEX_IMAGE_MISSING_B));
- }
- }
- }
-}
-
-void PointDensityTextureNode::compile(OSLCompiler& compiler)
-{
- ShaderOutput *density_out = output("Density");
- ShaderOutput *color_out = output("Color");
-
- const bool use_density = !density_out->links.empty();
- const bool use_color = !color_out->links.empty();
-
- image_manager = compiler.image_manager;
-
- if(use_density || use_color) {
- add_image();
-
- if(slot != -1) {
- compiler.parameter("filename", string_printf("@i%d", slot).c_str());
- }
- if(space == NODE_TEX_VOXEL_SPACE_WORLD) {
- compiler.parameter("mapping", tfm);
- compiler.parameter("use_mapping", 1);
- }
- compiler.parameter(this, "interpolation");
- compiler.add(this, "node_voxel_texture");
- }
+ if (slot == -1) {
+ ImageMetaData metadata;
+ slot = image_manager->add_image(
+ filename.string(), builtin_data, false, 0, interpolation, EXTENSION_CLIP, true, metadata);
+ }
+}
+
+void PointDensityTextureNode::compile(SVMCompiler &compiler)
+{
+ ShaderInput *vector_in = input("Vector");
+ ShaderOutput *density_out = output("Density");
+ ShaderOutput *color_out = output("Color");
+
+ const bool use_density = !density_out->links.empty();
+ const bool use_color = !color_out->links.empty();
+
+ image_manager = compiler.image_manager;
+
+ if (use_density || use_color) {
+ add_image();
+
+ if (slot != -1) {
+ compiler.stack_assign(vector_in);
+ compiler.add_node(NODE_TEX_VOXEL,
+ slot,
+ compiler.encode_uchar4(compiler.stack_assign(vector_in),
+ compiler.stack_assign_if_linked(density_out),
+ compiler.stack_assign_if_linked(color_out),
+ space));
+ if (space == NODE_TEX_VOXEL_SPACE_WORLD) {
+ compiler.add_node(tfm.x);
+ compiler.add_node(tfm.y);
+ compiler.add_node(tfm.z);
+ }
+ }
+ else {
+ if (use_density) {
+ compiler.add_node(NODE_VALUE_F, __float_as_int(0.0f), compiler.stack_assign(density_out));
+ }
+ if (use_color) {
+ compiler.add_node(NODE_VALUE_V, compiler.stack_assign(color_out));
+ compiler.add_node(
+ NODE_VALUE_V,
+ make_float3(TEX_IMAGE_MISSING_R, TEX_IMAGE_MISSING_G, TEX_IMAGE_MISSING_B));
+ }
+ }
+ }
+}
+
+void PointDensityTextureNode::compile(OSLCompiler &compiler)
+{
+ ShaderOutput *density_out = output("Density");
+ ShaderOutput *color_out = output("Color");
+
+ const bool use_density = !density_out->links.empty();
+ const bool use_color = !color_out->links.empty();
+
+ image_manager = compiler.image_manager;
+
+ if (use_density || use_color) {
+ add_image();
+
+ if (slot != -1) {
+ compiler.parameter("filename", string_printf("@i%d", slot).c_str());
+ }
+ if (space == NODE_TEX_VOXEL_SPACE_WORLD) {
+ compiler.parameter("mapping", tfm);
+ compiler.parameter("use_mapping", 1);
+ }
+ compiler.parameter(this, "interpolation");
+ compiler.add(this, "node_voxel_texture");
+ }
}
/* Normal */
NODE_DEFINE(NormalNode)
{
- NodeType* type = NodeType::add("normal", create, NodeType::SHADER);
+ NodeType *type = NodeType::add("normal", create, NodeType::SHADER);
- SOCKET_VECTOR(direction, "direction", make_float3(0.0f, 0.0f, 0.0f));
+ SOCKET_VECTOR(direction, "direction", make_float3(0.0f, 0.0f, 0.0f));
- SOCKET_IN_NORMAL(normal, "Normal", make_float3(0.0f, 0.0f, 0.0f));
+ SOCKET_IN_NORMAL(normal, "Normal", make_float3(0.0f, 0.0f, 0.0f));
- SOCKET_OUT_NORMAL(normal, "Normal");
- SOCKET_OUT_FLOAT(dot, "Dot");
+ SOCKET_OUT_NORMAL(normal, "Normal");
+ SOCKET_OUT_FLOAT(dot, "Dot");
- return type;
+ return type;
}
-NormalNode::NormalNode()
-: ShaderNode(node_type)
+NormalNode::NormalNode() : ShaderNode(node_type)
{
}
-void NormalNode::compile(SVMCompiler& compiler)
+void NormalNode::compile(SVMCompiler &compiler)
{
- ShaderInput *normal_in = input("Normal");
- ShaderOutput *normal_out = output("Normal");
- ShaderOutput *dot_out = output("Dot");
+ ShaderInput *normal_in = input("Normal");
+ ShaderOutput *normal_out = output("Normal");
+ ShaderOutput *dot_out = output("Dot");
- compiler.add_node(NODE_NORMAL,
- compiler.stack_assign(normal_in),
- compiler.stack_assign(normal_out),
- compiler.stack_assign(dot_out));
- compiler.add_node(
- __float_as_int(direction.x),
- __float_as_int(direction.y),
- __float_as_int(direction.z));
+ compiler.add_node(NODE_NORMAL,
+ compiler.stack_assign(normal_in),
+ compiler.stack_assign(normal_out),
+ compiler.stack_assign(dot_out));
+ compiler.add_node(
+ __float_as_int(direction.x), __float_as_int(direction.y), __float_as_int(direction.z));
}
-void NormalNode::compile(OSLCompiler& compiler)
+void NormalNode::compile(OSLCompiler &compiler)
{
- compiler.parameter(this, "direction");
- compiler.add(this, "node_normal");
+ compiler.parameter(this, "direction");
+ compiler.add(this, "node_normal");
}
/* Mapping */
NODE_DEFINE(MappingNode)
{
- NodeType* type = NodeType::add("mapping", create, NodeType::SHADER);
+ NodeType *type = NodeType::add("mapping", create, NodeType::SHADER);
- TEXTURE_MAPPING_DEFINE(MappingNode);
+ TEXTURE_MAPPING_DEFINE(MappingNode);
- SOCKET_IN_POINT(vector, "Vector", make_float3(0.0f, 0.0f, 0.0f));
- SOCKET_OUT_POINT(vector, "Vector");
+ SOCKET_IN_POINT(vector, "Vector", make_float3(0.0f, 0.0f, 0.0f));
+ SOCKET_OUT_POINT(vector, "Vector");
- return type;
+ return type;
}
-MappingNode::MappingNode()
-: ShaderNode(node_type)
+MappingNode::MappingNode() : ShaderNode(node_type)
{
}
-void MappingNode::compile(SVMCompiler& compiler)
+void MappingNode::compile(SVMCompiler &compiler)
{
- ShaderInput *vector_in = input("Vector");
- ShaderOutput *vector_out = output("Vector");
+ ShaderInput *vector_in = input("Vector");
+ ShaderOutput *vector_out = output("Vector");
- tex_mapping.compile(compiler, compiler.stack_assign(vector_in), compiler.stack_assign(vector_out));
+ tex_mapping.compile(
+ compiler, compiler.stack_assign(vector_in), compiler.stack_assign(vector_out));
}
-void MappingNode::compile(OSLCompiler& compiler)
+void MappingNode::compile(OSLCompiler &compiler)
{
- compiler.parameter("Matrix", tex_mapping.compute_transform());
- compiler.parameter_point("mapping_min", tex_mapping.min);
- compiler.parameter_point("mapping_max", tex_mapping.max);
- compiler.parameter("use_minmax", tex_mapping.use_minmax);
+ compiler.parameter("Matrix", tex_mapping.compute_transform());
+ compiler.parameter_point("mapping_min", tex_mapping.min);
+ compiler.parameter_point("mapping_max", tex_mapping.max);
+ compiler.parameter("use_minmax", tex_mapping.use_minmax);
- compiler.add(this, "node_mapping");
+ compiler.add(this, "node_mapping");
}
/* RGBToBW */
NODE_DEFINE(RGBToBWNode)
{
- NodeType* type = NodeType::add("rgb_to_bw", create, NodeType::SHADER);
+ NodeType *type = NodeType::add("rgb_to_bw", create, NodeType::SHADER);
- SOCKET_IN_COLOR(color, "Color", make_float3(0.0f, 0.0f, 0.0f));
- SOCKET_OUT_FLOAT(val, "Val");
+ SOCKET_IN_COLOR(color, "Color", make_float3(0.0f, 0.0f, 0.0f));
+ SOCKET_OUT_FLOAT(val, "Val");
- return type;
+ return type;
}
-RGBToBWNode::RGBToBWNode()
-: ShaderNode(node_type)
+RGBToBWNode::RGBToBWNode() : ShaderNode(node_type)
{
}
-void RGBToBWNode::constant_fold(const ConstantFolder& folder)
+void RGBToBWNode::constant_fold(const ConstantFolder &folder)
{
- if(folder.all_inputs_constant()) {
- float val = folder.scene->shader_manager->linear_rgb_to_gray(color);
- folder.make_constant(val);
- }
+ if (folder.all_inputs_constant()) {
+ float val = folder.scene->shader_manager->linear_rgb_to_gray(color);
+ folder.make_constant(val);
+ }
}
-void RGBToBWNode::compile(SVMCompiler& compiler)
+void RGBToBWNode::compile(SVMCompiler &compiler)
{
- compiler.add_node(NODE_CONVERT,
- NODE_CONVERT_CF,
- compiler.stack_assign(inputs[0]),
- compiler.stack_assign(outputs[0]));
+ compiler.add_node(NODE_CONVERT,
+ NODE_CONVERT_CF,
+ compiler.stack_assign(inputs[0]),
+ compiler.stack_assign(outputs[0]));
}
-void RGBToBWNode::compile(OSLCompiler& compiler)
+void RGBToBWNode::compile(OSLCompiler &compiler)
{
- compiler.add(this, "node_rgb_to_bw");
+ compiler.add(this, "node_rgb_to_bw");
}
/* Convert */
-const NodeType* ConvertNode::node_types[ConvertNode::MAX_TYPE][ConvertNode::MAX_TYPE];
+const NodeType *ConvertNode::node_types[ConvertNode::MAX_TYPE][ConvertNode::MAX_TYPE];
bool ConvertNode::initialized = ConvertNode::register_types();
-Node* ConvertNode::create(const NodeType *type)
+Node *ConvertNode::create(const NodeType *type)
{
- return new ConvertNode(type->inputs[0].type, type->outputs[0].type);
+ return new ConvertNode(type->inputs[0].type, type->outputs[0].type);
}
bool ConvertNode::register_types()
{
- const int num_types = 8;
- SocketType::Type types[num_types] = {SocketType::FLOAT,
- SocketType::INT,
- SocketType::COLOR,
- SocketType::VECTOR,
- SocketType::POINT,
- SocketType::NORMAL,
- SocketType::STRING,
- SocketType::CLOSURE};
-
- for(size_t i = 0; i < num_types; i++) {
- SocketType::Type from = types[i];
- ustring from_name(SocketType::type_name(from));
- ustring from_value_name("value_" + from_name.string());
-
- for(size_t j = 0; j < num_types; j++) {
- SocketType::Type to = types[j];
- ustring to_name(SocketType::type_name(to));
- ustring to_value_name("value_" + to_name.string());
-
- string node_name = "convert_" + from_name.string() + "_to_" + to_name.string();
- NodeType* type = NodeType::add(node_name.c_str(), create, NodeType::SHADER);
-
- type->register_input(from_value_name, from_value_name, from,
- SOCKET_OFFSETOF(ConvertNode, value_float), SocketType::zero_default_value(),
- NULL, NULL, SocketType::LINKABLE);
- type->register_output(to_value_name, to_value_name, to);
-
- assert(from < MAX_TYPE);
- assert(to < MAX_TYPE);
-
- node_types[from][to] = type;
- }
- }
-
- return true;
+ const int num_types = 8;
+ SocketType::Type types[num_types] = {SocketType::FLOAT,
+ SocketType::INT,
+ SocketType::COLOR,
+ SocketType::VECTOR,
+ SocketType::POINT,
+ SocketType::NORMAL,
+ SocketType::STRING,
+ SocketType::CLOSURE};
+
+ for (size_t i = 0; i < num_types; i++) {
+ SocketType::Type from = types[i];
+ ustring from_name(SocketType::type_name(from));
+ ustring from_value_name("value_" + from_name.string());
+
+ for (size_t j = 0; j < num_types; j++) {
+ SocketType::Type to = types[j];
+ ustring to_name(SocketType::type_name(to));
+ ustring to_value_name("value_" + to_name.string());
+
+ string node_name = "convert_" + from_name.string() + "_to_" + to_name.string();
+ NodeType *type = NodeType::add(node_name.c_str(), create, NodeType::SHADER);
+
+ type->register_input(from_value_name,
+ from_value_name,
+ from,
+ SOCKET_OFFSETOF(ConvertNode, value_float),
+ SocketType::zero_default_value(),
+ NULL,
+ NULL,
+ SocketType::LINKABLE);
+ type->register_output(to_value_name, to_value_name, to);
+
+ assert(from < MAX_TYPE);
+ assert(to < MAX_TYPE);
+
+ node_types[from][to] = type;
+ }
+ }
+
+ return true;
}
ConvertNode::ConvertNode(SocketType::Type from_, SocketType::Type to_, bool autoconvert)
-: ShaderNode(node_types[from_][to_])
-{
- from = from_;
- to = to_;
-
- if(from == to)
- special_type = SHADER_SPECIAL_TYPE_PROXY;
- else if(autoconvert)
- special_type = SHADER_SPECIAL_TYPE_AUTOCONVERT;
-}
-
-void ConvertNode::constant_fold(const ConstantFolder& folder)
-{
- /* proxy nodes should have been removed at this point */
- assert(special_type != SHADER_SPECIAL_TYPE_PROXY);
-
- /* TODO(DingTo): conversion from/to int is not supported yet, don't fold in that case */
-
- if(folder.all_inputs_constant()) {
- if(from == SocketType::FLOAT) {
- if(SocketType::is_float3(to)) {
- folder.make_constant(make_float3(value_float, value_float, value_float));
- }
- }
- else if(SocketType::is_float3(from)) {
- if(to == SocketType::FLOAT) {
- if(from == SocketType::COLOR) {
- /* color to float */
- float val = folder.scene->shader_manager->linear_rgb_to_gray(value_color);
- folder.make_constant(val);
- }
- else {
- /* vector/point/normal to float */
- folder.make_constant(average(value_vector));
- }
- }
- else if(SocketType::is_float3(to)) {
- folder.make_constant(value_color);
- }
- }
- }
- else {
- ShaderInput *in = inputs[0];
- ShaderNode *prev = in->link->parent;
-
- /* no-op conversion of A to B to A */
- if(prev->type == node_types[to][from]) {
- ShaderInput *prev_in = prev->inputs[0];
-
- if(SocketType::is_float3(from) && (to == SocketType::FLOAT || SocketType::is_float3(to)) && prev_in->link) {
- folder.bypass(prev_in->link);
- }
- }
- }
-}
-
-void ConvertNode::compile(SVMCompiler& compiler)
-{
- /* proxy nodes should have been removed at this point */
- assert(special_type != SHADER_SPECIAL_TYPE_PROXY);
-
- ShaderInput *in = inputs[0];
- ShaderOutput *out = outputs[0];
-
- if(from == SocketType::FLOAT) {
- if(to == SocketType::INT)
- /* float to int */
- compiler.add_node(NODE_CONVERT, NODE_CONVERT_FI, compiler.stack_assign(in), compiler.stack_assign(out));
- else
- /* float to float3 */
- compiler.add_node(NODE_CONVERT, NODE_CONVERT_FV, compiler.stack_assign(in), compiler.stack_assign(out));
- }
- else if(from == SocketType::INT) {
- if(to == SocketType::FLOAT)
- /* int to float */
- compiler.add_node(NODE_CONVERT, NODE_CONVERT_IF, compiler.stack_assign(in), compiler.stack_assign(out));
- else
- /* int to vector/point/normal */
- compiler.add_node(NODE_CONVERT, NODE_CONVERT_IV, compiler.stack_assign(in), compiler.stack_assign(out));
- }
- else if(to == SocketType::FLOAT) {
- if(from == SocketType::COLOR)
- /* color to float */
- compiler.add_node(NODE_CONVERT, NODE_CONVERT_CF, compiler.stack_assign(in), compiler.stack_assign(out));
- else
- /* vector/point/normal to float */
- compiler.add_node(NODE_CONVERT, NODE_CONVERT_VF, compiler.stack_assign(in), compiler.stack_assign(out));
- }
- else if(to == SocketType::INT) {
- if(from == SocketType::COLOR)
- /* color to int */
- compiler.add_node(NODE_CONVERT, NODE_CONVERT_CI, compiler.stack_assign(in), compiler.stack_assign(out));
- else
- /* vector/point/normal to int */
- compiler.add_node(NODE_CONVERT, NODE_CONVERT_VI, compiler.stack_assign(in), compiler.stack_assign(out));
- }
- else {
- /* float3 to float3 */
- if(in->link) {
- /* no op in SVM */
- compiler.stack_link(in, out);
- }
- else {
- /* set 0,0,0 value */
- compiler.add_node(NODE_VALUE_V, compiler.stack_assign(out));
- compiler.add_node(NODE_VALUE_V, value_color);
- }
- }
-}
-
-void ConvertNode::compile(OSLCompiler& compiler)
-{
- /* proxy nodes should have been removed at this point */
- assert(special_type != SHADER_SPECIAL_TYPE_PROXY);
-
- if(from == SocketType::FLOAT)
- compiler.add(this, "node_convert_from_float");
- else if(from == SocketType::INT)
- compiler.add(this, "node_convert_from_int");
- else if(from == SocketType::COLOR)
- compiler.add(this, "node_convert_from_color");
- else if(from == SocketType::VECTOR)
- compiler.add(this, "node_convert_from_vector");
- else if(from == SocketType::POINT)
- compiler.add(this, "node_convert_from_point");
- else if(from == SocketType::NORMAL)
- compiler.add(this, "node_convert_from_normal");
- else
- assert(0);
+ : ShaderNode(node_types[from_][to_])
+{
+ from = from_;
+ to = to_;
+
+ if (from == to)
+ special_type = SHADER_SPECIAL_TYPE_PROXY;
+ else if (autoconvert)
+ special_type = SHADER_SPECIAL_TYPE_AUTOCONVERT;
+}
+
+void ConvertNode::constant_fold(const ConstantFolder &folder)
+{
+ /* proxy nodes should have been removed at this point */
+ assert(special_type != SHADER_SPECIAL_TYPE_PROXY);
+
+ /* TODO(DingTo): conversion from/to int is not supported yet, don't fold in that case */
+
+ if (folder.all_inputs_constant()) {
+ if (from == SocketType::FLOAT) {
+ if (SocketType::is_float3(to)) {
+ folder.make_constant(make_float3(value_float, value_float, value_float));
+ }
+ }
+ else if (SocketType::is_float3(from)) {
+ if (to == SocketType::FLOAT) {
+ if (from == SocketType::COLOR) {
+ /* color to float */
+ float val = folder.scene->shader_manager->linear_rgb_to_gray(value_color);
+ folder.make_constant(val);
+ }
+ else {
+ /* vector/point/normal to float */
+ folder.make_constant(average(value_vector));
+ }
+ }
+ else if (SocketType::is_float3(to)) {
+ folder.make_constant(value_color);
+ }
+ }
+ }
+ else {
+ ShaderInput *in = inputs[0];
+ ShaderNode *prev = in->link->parent;
+
+ /* no-op conversion of A to B to A */
+ if (prev->type == node_types[to][from]) {
+ ShaderInput *prev_in = prev->inputs[0];
+
+ if (SocketType::is_float3(from) && (to == SocketType::FLOAT || SocketType::is_float3(to)) &&
+ prev_in->link) {
+ folder.bypass(prev_in->link);
+ }
+ }
+ }
+}
+
+void ConvertNode::compile(SVMCompiler &compiler)
+{
+ /* proxy nodes should have been removed at this point */
+ assert(special_type != SHADER_SPECIAL_TYPE_PROXY);
+
+ ShaderInput *in = inputs[0];
+ ShaderOutput *out = outputs[0];
+
+ if (from == SocketType::FLOAT) {
+ if (to == SocketType::INT)
+ /* float to int */
+ compiler.add_node(
+ NODE_CONVERT, NODE_CONVERT_FI, compiler.stack_assign(in), compiler.stack_assign(out));
+ else
+ /* float to float3 */
+ compiler.add_node(
+ NODE_CONVERT, NODE_CONVERT_FV, compiler.stack_assign(in), compiler.stack_assign(out));
+ }
+ else if (from == SocketType::INT) {
+ if (to == SocketType::FLOAT)
+ /* int to float */
+ compiler.add_node(
+ NODE_CONVERT, NODE_CONVERT_IF, compiler.stack_assign(in), compiler.stack_assign(out));
+ else
+ /* int to vector/point/normal */
+ compiler.add_node(
+ NODE_CONVERT, NODE_CONVERT_IV, compiler.stack_assign(in), compiler.stack_assign(out));
+ }
+ else if (to == SocketType::FLOAT) {
+ if (from == SocketType::COLOR)
+ /* color to float */
+ compiler.add_node(
+ NODE_CONVERT, NODE_CONVERT_CF, compiler.stack_assign(in), compiler.stack_assign(out));
+ else
+ /* vector/point/normal to float */
+ compiler.add_node(
+ NODE_CONVERT, NODE_CONVERT_VF, compiler.stack_assign(in), compiler.stack_assign(out));
+ }
+ else if (to == SocketType::INT) {
+ if (from == SocketType::COLOR)
+ /* color to int */
+ compiler.add_node(
+ NODE_CONVERT, NODE_CONVERT_CI, compiler.stack_assign(in), compiler.stack_assign(out));
+ else
+ /* vector/point/normal to int */
+ compiler.add_node(
+ NODE_CONVERT, NODE_CONVERT_VI, compiler.stack_assign(in), compiler.stack_assign(out));
+ }
+ else {
+ /* float3 to float3 */
+ if (in->link) {
+ /* no op in SVM */
+ compiler.stack_link(in, out);
+ }
+ else {
+ /* set 0,0,0 value */
+ compiler.add_node(NODE_VALUE_V, compiler.stack_assign(out));
+ compiler.add_node(NODE_VALUE_V, value_color);
+ }
+ }
+}
+
+void ConvertNode::compile(OSLCompiler &compiler)
+{
+ /* proxy nodes should have been removed at this point */
+ assert(special_type != SHADER_SPECIAL_TYPE_PROXY);
+
+ if (from == SocketType::FLOAT)
+ compiler.add(this, "node_convert_from_float");
+ else if (from == SocketType::INT)
+ compiler.add(this, "node_convert_from_int");
+ else if (from == SocketType::COLOR)
+ compiler.add(this, "node_convert_from_color");
+ else if (from == SocketType::VECTOR)
+ compiler.add(this, "node_convert_from_vector");
+ else if (from == SocketType::POINT)
+ compiler.add(this, "node_convert_from_point");
+ else if (from == SocketType::NORMAL)
+ compiler.add(this, "node_convert_from_normal");
+ else
+ assert(0);
}
/* Base type for all closure-type nodes */
-BsdfBaseNode::BsdfBaseNode(const NodeType *node_type)
- : ShaderNode(node_type)
+BsdfBaseNode::BsdfBaseNode(const NodeType *node_type) : ShaderNode(node_type)
{
- special_type = SHADER_SPECIAL_TYPE_CLOSURE;
+ special_type = SHADER_SPECIAL_TYPE_CLOSURE;
}
bool BsdfBaseNode::has_bump()
{
- /* detect if anything is plugged into the normal input besides the default */
- ShaderInput *normal_in = input("Normal");
- return (normal_in && normal_in->link &&
- normal_in->link->parent->special_type != SHADER_SPECIAL_TYPE_GEOMETRY);
+ /* detect if anything is plugged into the normal input besides the default */
+ ShaderInput *normal_in = input("Normal");
+ return (normal_in && normal_in->link &&
+ normal_in->link->parent->special_type != SHADER_SPECIAL_TYPE_GEOMETRY);
}
/* BSDF Closure */
-BsdfNode::BsdfNode(const NodeType *node_type)
-: BsdfBaseNode(node_type)
+BsdfNode::BsdfNode(const NodeType *node_type) : BsdfBaseNode(node_type)
{
}
-void BsdfNode::compile(SVMCompiler& compiler, ShaderInput *param1, ShaderInput *param2, ShaderInput *param3, ShaderInput *param4)
+void BsdfNode::compile(SVMCompiler &compiler,
+ ShaderInput *param1,
+ ShaderInput *param2,
+ ShaderInput *param3,
+ ShaderInput *param4)
{
- ShaderInput *color_in = input("Color");
- ShaderInput *normal_in = input("Normal");
- ShaderInput *tangent_in = input("Tangent");
+ ShaderInput *color_in = input("Color");
+ ShaderInput *normal_in = input("Normal");
+ ShaderInput *tangent_in = input("Tangent");
- if(color_in->link)
- compiler.add_node(NODE_CLOSURE_WEIGHT, compiler.stack_assign(color_in));
- else
- compiler.add_node(NODE_CLOSURE_SET_WEIGHT, color);
+ if (color_in->link)
+ compiler.add_node(NODE_CLOSURE_WEIGHT, compiler.stack_assign(color_in));
+ else
+ compiler.add_node(NODE_CLOSURE_SET_WEIGHT, color);
- int normal_offset = (normal_in) ? compiler.stack_assign_if_linked(normal_in) : SVM_STACK_INVALID;
- int tangent_offset = (tangent_in) ? compiler.stack_assign_if_linked(tangent_in) : SVM_STACK_INVALID;
- int param3_offset = (param3) ? compiler.stack_assign(param3) : SVM_STACK_INVALID;
- int param4_offset = (param4) ? compiler.stack_assign(param4) : SVM_STACK_INVALID;
+ int normal_offset = (normal_in) ? compiler.stack_assign_if_linked(normal_in) : SVM_STACK_INVALID;
+ int tangent_offset = (tangent_in) ? compiler.stack_assign_if_linked(tangent_in) :
+ SVM_STACK_INVALID;
+ int param3_offset = (param3) ? compiler.stack_assign(param3) : SVM_STACK_INVALID;
+ int param4_offset = (param4) ? compiler.stack_assign(param4) : SVM_STACK_INVALID;
- compiler.add_node(NODE_CLOSURE_BSDF,
- compiler.encode_uchar4(closure,
- (param1)? compiler.stack_assign(param1): SVM_STACK_INVALID,
- (param2)? compiler.stack_assign(param2): SVM_STACK_INVALID,
- compiler.closure_mix_weight_offset()),
- __float_as_int((param1)? get_float(param1->socket_type): 0.0f),
- __float_as_int((param2)? get_float(param2->socket_type): 0.0f));
+ compiler.add_node(
+ NODE_CLOSURE_BSDF,
+ compiler.encode_uchar4(closure,
+ (param1) ? compiler.stack_assign(param1) : SVM_STACK_INVALID,
+ (param2) ? compiler.stack_assign(param2) : SVM_STACK_INVALID,
+ compiler.closure_mix_weight_offset()),
+ __float_as_int((param1) ? get_float(param1->socket_type) : 0.0f),
+ __float_as_int((param2) ? get_float(param2->socket_type) : 0.0f));
- compiler.add_node(normal_offset, tangent_offset, param3_offset, param4_offset);
+ compiler.add_node(normal_offset, tangent_offset, param3_offset, param4_offset);
}
-void BsdfNode::compile(SVMCompiler& compiler)
+void BsdfNode::compile(SVMCompiler &compiler)
{
- compile(compiler, NULL, NULL);
+ compile(compiler, NULL, NULL);
}
-void BsdfNode::compile(OSLCompiler& /*compiler*/)
+void BsdfNode::compile(OSLCompiler & /*compiler*/)
{
- assert(0);
+ assert(0);
}
/* Anisotropic BSDF Closure */
NODE_DEFINE(AnisotropicBsdfNode)
{
- NodeType* type = NodeType::add("anisotropic_bsdf", create, NodeType::SHADER);
+ NodeType *type = NodeType::add("anisotropic_bsdf", create, NodeType::SHADER);
- SOCKET_IN_COLOR(color, "Color", make_float3(0.8f, 0.8f, 0.8f));
- SOCKET_IN_NORMAL(normal, "Normal", make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_NORMAL);
- SOCKET_IN_FLOAT(surface_mix_weight, "SurfaceMixWeight", 0.0f, SocketType::SVM_INTERNAL);
+ SOCKET_IN_COLOR(color, "Color", make_float3(0.8f, 0.8f, 0.8f));
+ SOCKET_IN_NORMAL(normal, "Normal", make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_NORMAL);
+ SOCKET_IN_FLOAT(surface_mix_weight, "SurfaceMixWeight", 0.0f, SocketType::SVM_INTERNAL);
- static NodeEnum distribution_enum;
- distribution_enum.insert("beckmann", CLOSURE_BSDF_MICROFACET_BECKMANN_ANISO_ID);
- distribution_enum.insert("GGX", CLOSURE_BSDF_MICROFACET_GGX_ANISO_ID);
- distribution_enum.insert("Multiscatter GGX", CLOSURE_BSDF_MICROFACET_MULTI_GGX_ANISO_ID);
- distribution_enum.insert("ashikhmin_shirley", CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ANISO_ID);
- SOCKET_ENUM(distribution, "Distribution", distribution_enum, CLOSURE_BSDF_MICROFACET_GGX_ANISO_ID);
+ static NodeEnum distribution_enum;
+ distribution_enum.insert("beckmann", CLOSURE_BSDF_MICROFACET_BECKMANN_ANISO_ID);
+ distribution_enum.insert("GGX", CLOSURE_BSDF_MICROFACET_GGX_ANISO_ID);
+ distribution_enum.insert("Multiscatter GGX", CLOSURE_BSDF_MICROFACET_MULTI_GGX_ANISO_ID);
+ distribution_enum.insert("ashikhmin_shirley", CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ANISO_ID);
+ SOCKET_ENUM(
+ distribution, "Distribution", distribution_enum, CLOSURE_BSDF_MICROFACET_GGX_ANISO_ID);
- SOCKET_IN_VECTOR(tangent, "Tangent", make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_TANGENT);
+ SOCKET_IN_VECTOR(tangent, "Tangent", make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_TANGENT);
- SOCKET_IN_FLOAT(roughness, "Roughness", 0.5f);
- SOCKET_IN_FLOAT(anisotropy, "Anisotropy", 0.5f);
- SOCKET_IN_FLOAT(rotation, "Rotation", 0.0f);
+ SOCKET_IN_FLOAT(roughness, "Roughness", 0.5f);
+ SOCKET_IN_FLOAT(anisotropy, "Anisotropy", 0.5f);
+ SOCKET_IN_FLOAT(rotation, "Rotation", 0.0f);
- SOCKET_OUT_CLOSURE(BSDF, "BSDF");
+ SOCKET_OUT_CLOSURE(BSDF, "BSDF");
- return type;
+ return type;
}
-AnisotropicBsdfNode::AnisotropicBsdfNode()
-: BsdfNode(node_type)
+AnisotropicBsdfNode::AnisotropicBsdfNode() : BsdfNode(node_type)
{
- closure = CLOSURE_BSDF_MICROFACET_GGX_ANISO_ID;
+ closure = CLOSURE_BSDF_MICROFACET_GGX_ANISO_ID;
}
void AnisotropicBsdfNode::attributes(Shader *shader, AttributeRequestSet *attributes)
{
- if(shader->has_surface) {
- ShaderInput *tangent_in = input("Tangent");
+ if (shader->has_surface) {
+ ShaderInput *tangent_in = input("Tangent");
- if(!tangent_in->link)
- attributes->add(ATTR_STD_GENERATED);
- }
+ if (!tangent_in->link)
+ attributes->add(ATTR_STD_GENERATED);
+ }
- ShaderNode::attributes(shader, attributes);
+ ShaderNode::attributes(shader, attributes);
}
-void AnisotropicBsdfNode::compile(SVMCompiler& compiler)
+void AnisotropicBsdfNode::compile(SVMCompiler &compiler)
{
- closure = distribution;
+ closure = distribution;
- if(closure == CLOSURE_BSDF_MICROFACET_MULTI_GGX_ANISO_ID)
- BsdfNode::compile(compiler, input("Roughness"), input("Anisotropy"), input("Rotation"), input("Color"));
- else
- BsdfNode::compile(compiler, input("Roughness"), input("Anisotropy"), input("Rotation"));
+ if (closure == CLOSURE_BSDF_MICROFACET_MULTI_GGX_ANISO_ID)
+ BsdfNode::compile(
+ compiler, input("Roughness"), input("Anisotropy"), input("Rotation"), input("Color"));
+ else
+ BsdfNode::compile(compiler, input("Roughness"), input("Anisotropy"), input("Rotation"));
}
-void AnisotropicBsdfNode::compile(OSLCompiler& compiler)
+void AnisotropicBsdfNode::compile(OSLCompiler &compiler)
{
- compiler.parameter(this, "distribution");
- compiler.add(this, "node_anisotropic_bsdf");
+ compiler.parameter(this, "distribution");
+ compiler.add(this, "node_anisotropic_bsdf");
}
/* Glossy BSDF Closure */
NODE_DEFINE(GlossyBsdfNode)
{
- NodeType* type = NodeType::add("glossy_bsdf", create, NodeType::SHADER);
+ NodeType *type = NodeType::add("glossy_bsdf", create, NodeType::SHADER);
- SOCKET_IN_COLOR(color, "Color", make_float3(0.8f, 0.8f, 0.8f));
- SOCKET_IN_NORMAL(normal, "Normal", make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_NORMAL);
- SOCKET_IN_FLOAT(surface_mix_weight, "SurfaceMixWeight", 0.0f, SocketType::SVM_INTERNAL);
+ SOCKET_IN_COLOR(color, "Color", make_float3(0.8f, 0.8f, 0.8f));
+ SOCKET_IN_NORMAL(normal, "Normal", make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_NORMAL);
+ SOCKET_IN_FLOAT(surface_mix_weight, "SurfaceMixWeight", 0.0f, SocketType::SVM_INTERNAL);
- static NodeEnum distribution_enum;
- distribution_enum.insert("sharp", CLOSURE_BSDF_REFLECTION_ID);
- distribution_enum.insert("beckmann", CLOSURE_BSDF_MICROFACET_BECKMANN_ID);
- distribution_enum.insert("GGX", CLOSURE_BSDF_MICROFACET_GGX_ID);
- distribution_enum.insert("ashikhmin_shirley", CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ID);
- distribution_enum.insert("Multiscatter GGX", CLOSURE_BSDF_MICROFACET_MULTI_GGX_ID);
- SOCKET_ENUM(distribution, "Distribution", distribution_enum, CLOSURE_BSDF_MICROFACET_GGX_ID);
- SOCKET_IN_FLOAT(roughness, "Roughness", 0.5f);
+ static NodeEnum distribution_enum;
+ distribution_enum.insert("sharp", CLOSURE_BSDF_REFLECTION_ID);
+ distribution_enum.insert("beckmann", CLOSURE_BSDF_MICROFACET_BECKMANN_ID);
+ distribution_enum.insert("GGX", CLOSURE_BSDF_MICROFACET_GGX_ID);
+ distribution_enum.insert("ashikhmin_shirley", CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ID);
+ distribution_enum.insert("Multiscatter GGX", CLOSURE_BSDF_MICROFACET_MULTI_GGX_ID);
+ SOCKET_ENUM(distribution, "Distribution", distribution_enum, CLOSURE_BSDF_MICROFACET_GGX_ID);
+ SOCKET_IN_FLOAT(roughness, "Roughness", 0.5f);
- SOCKET_OUT_CLOSURE(BSDF, "BSDF");
+ SOCKET_OUT_CLOSURE(BSDF, "BSDF");
- return type;
+ return type;
}
-GlossyBsdfNode::GlossyBsdfNode()
-: BsdfNode(node_type)
+GlossyBsdfNode::GlossyBsdfNode() : BsdfNode(node_type)
{
- closure = CLOSURE_BSDF_MICROFACET_GGX_ID;
- distribution_orig = NBUILTIN_CLOSURES;
+ closure = CLOSURE_BSDF_MICROFACET_GGX_ID;
+ distribution_orig = NBUILTIN_CLOSURES;
}
void GlossyBsdfNode::simplify_settings(Scene *scene)
{
- if(distribution_orig == NBUILTIN_CLOSURES) {
- roughness_orig = roughness;
- distribution_orig = distribution;
- }
- else {
- /* By default we use original values, so we don't worry about restoring
- * defaults later one and can only do override when needed.
- */
- roughness = roughness_orig;
- distribution = distribution_orig;
- }
- Integrator *integrator = scene->integrator;
- ShaderInput *roughness_input = input("Roughness");
- if(integrator->filter_glossy == 0.0f) {
- /* Fallback to Sharp closure for Roughness close to 0.
- * Note: Keep the epsilon in sync with kernel!
- */
- if(!roughness_input->link && roughness <= 1e-4f) {
- VLOG(1) << "Using sharp glossy BSDF.";
- distribution = CLOSURE_BSDF_REFLECTION_ID;
- }
- }
- else {
- /* If filter glossy is used we replace Sharp glossy with GGX so we can
- * benefit from closure blur to remove unwanted noise.
- */
- if(roughness_input->link == NULL &&
- distribution == CLOSURE_BSDF_REFLECTION_ID)
- {
- VLOG(1) << "Using GGX glossy with filter glossy.";
- distribution = CLOSURE_BSDF_MICROFACET_GGX_ID;
- roughness = 0.0f;
- }
- }
- closure = distribution;
+ if (distribution_orig == NBUILTIN_CLOSURES) {
+ roughness_orig = roughness;
+ distribution_orig = distribution;
+ }
+ else {
+ /* By default we use original values, so we don't worry about restoring
+ * defaults later one and can only do override when needed.
+ */
+ roughness = roughness_orig;
+ distribution = distribution_orig;
+ }
+ Integrator *integrator = scene->integrator;
+ ShaderInput *roughness_input = input("Roughness");
+ if (integrator->filter_glossy == 0.0f) {
+ /* Fallback to Sharp closure for Roughness close to 0.
+ * Note: Keep the epsilon in sync with kernel!
+ */
+ if (!roughness_input->link && roughness <= 1e-4f) {
+ VLOG(1) << "Using sharp glossy BSDF.";
+ distribution = CLOSURE_BSDF_REFLECTION_ID;
+ }
+ }
+ else {
+ /* If filter glossy is used we replace Sharp glossy with GGX so we can
+ * benefit from closure blur to remove unwanted noise.
+ */
+ if (roughness_input->link == NULL && distribution == CLOSURE_BSDF_REFLECTION_ID) {
+ VLOG(1) << "Using GGX glossy with filter glossy.";
+ distribution = CLOSURE_BSDF_MICROFACET_GGX_ID;
+ roughness = 0.0f;
+ }
+ }
+ closure = distribution;
}
bool GlossyBsdfNode::has_integrator_dependency()
{
- ShaderInput *roughness_input = input("Roughness");
- return !roughness_input->link &&
- (distribution == CLOSURE_BSDF_REFLECTION_ID || roughness <= 1e-4f);
+ ShaderInput *roughness_input = input("Roughness");
+ return !roughness_input->link &&
+ (distribution == CLOSURE_BSDF_REFLECTION_ID || roughness <= 1e-4f);
}
-void GlossyBsdfNode::compile(SVMCompiler& compiler)
+void GlossyBsdfNode::compile(SVMCompiler &compiler)
{
- closure = distribution;
+ closure = distribution;
- if(closure == CLOSURE_BSDF_REFLECTION_ID)
- BsdfNode::compile(compiler, NULL, NULL);
- else if(closure == CLOSURE_BSDF_MICROFACET_MULTI_GGX_ID)
- BsdfNode::compile(compiler, input("Roughness"), NULL, input("Color"));
- else
- BsdfNode::compile(compiler, input("Roughness"), NULL);
+ if (closure == CLOSURE_BSDF_REFLECTION_ID)
+ BsdfNode::compile(compiler, NULL, NULL);
+ else if (closure == CLOSURE_BSDF_MICROFACET_MULTI_GGX_ID)
+ BsdfNode::compile(compiler, input("Roughness"), NULL, input("Color"));
+ else
+ BsdfNode::compile(compiler, input("Roughness"), NULL);
}
-void GlossyBsdfNode::compile(OSLCompiler& compiler)
+void GlossyBsdfNode::compile(OSLCompiler &compiler)
{
- compiler.parameter(this, "distribution");
- compiler.add(this, "node_glossy_bsdf");
+ compiler.parameter(this, "distribution");
+ compiler.add(this, "node_glossy_bsdf");
}
/* Glass BSDF Closure */
NODE_DEFINE(GlassBsdfNode)
{
- NodeType* type = NodeType::add("glass_bsdf", create, NodeType::SHADER);
+ NodeType *type = NodeType::add("glass_bsdf", create, NodeType::SHADER);
- SOCKET_IN_COLOR(color, "Color", make_float3(0.8f, 0.8f, 0.8f));
- SOCKET_IN_NORMAL(normal, "Normal", make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_NORMAL);
- SOCKET_IN_FLOAT(surface_mix_weight, "SurfaceMixWeight", 0.0f, SocketType::SVM_INTERNAL);
+ SOCKET_IN_COLOR(color, "Color", make_float3(0.8f, 0.8f, 0.8f));
+ SOCKET_IN_NORMAL(normal, "Normal", make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_NORMAL);
+ SOCKET_IN_FLOAT(surface_mix_weight, "SurfaceMixWeight", 0.0f, SocketType::SVM_INTERNAL);
- static NodeEnum distribution_enum;
- distribution_enum.insert("sharp", CLOSURE_BSDF_SHARP_GLASS_ID);
- distribution_enum.insert("beckmann", CLOSURE_BSDF_MICROFACET_BECKMANN_GLASS_ID);
- distribution_enum.insert("GGX", CLOSURE_BSDF_MICROFACET_GGX_GLASS_ID);
- distribution_enum.insert("Multiscatter GGX", CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID);
- SOCKET_ENUM(distribution, "Distribution", distribution_enum, CLOSURE_BSDF_MICROFACET_GGX_GLASS_ID);
- SOCKET_IN_FLOAT(roughness, "Roughness", 0.0f);
- SOCKET_IN_FLOAT(IOR, "IOR", 0.3f);
+ static NodeEnum distribution_enum;
+ distribution_enum.insert("sharp", CLOSURE_BSDF_SHARP_GLASS_ID);
+ distribution_enum.insert("beckmann", CLOSURE_BSDF_MICROFACET_BECKMANN_GLASS_ID);
+ distribution_enum.insert("GGX", CLOSURE_BSDF_MICROFACET_GGX_GLASS_ID);
+ distribution_enum.insert("Multiscatter GGX", CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID);
+ SOCKET_ENUM(
+ distribution, "Distribution", distribution_enum, CLOSURE_BSDF_MICROFACET_GGX_GLASS_ID);
+ SOCKET_IN_FLOAT(roughness, "Roughness", 0.0f);
+ SOCKET_IN_FLOAT(IOR, "IOR", 0.3f);
- SOCKET_OUT_CLOSURE(BSDF, "BSDF");
+ SOCKET_OUT_CLOSURE(BSDF, "BSDF");
- return type;
+ return type;
}
-GlassBsdfNode::GlassBsdfNode()
-: BsdfNode(node_type)
+GlassBsdfNode::GlassBsdfNode() : BsdfNode(node_type)
{
- closure = CLOSURE_BSDF_SHARP_GLASS_ID;
- distribution_orig = NBUILTIN_CLOSURES;
+ closure = CLOSURE_BSDF_SHARP_GLASS_ID;
+ distribution_orig = NBUILTIN_CLOSURES;
}
void GlassBsdfNode::simplify_settings(Scene *scene)
{
- if(distribution_orig == NBUILTIN_CLOSURES) {
- roughness_orig = roughness;
- distribution_orig = distribution;
- }
- else {
- /* By default we use original values, so we don't worry about restoring
- * defaults later one and can only do override when needed.
- */
- roughness = roughness_orig;
- distribution = distribution_orig;
- }
- Integrator *integrator = scene->integrator;
- ShaderInput *roughness_input = input("Roughness");
- if(integrator->filter_glossy == 0.0f) {
- /* Fallback to Sharp closure for Roughness close to 0.
- * Note: Keep the epsilon in sync with kernel!
- */
- if(!roughness_input->link && roughness <= 1e-4f) {
- VLOG(1) << "Using sharp glass BSDF.";
- distribution = CLOSURE_BSDF_SHARP_GLASS_ID;
- }
- }
- else {
- /* If filter glossy is used we replace Sharp glossy with GGX so we can
- * benefit from closure blur to remove unwanted noise.
- */
- if(roughness_input->link == NULL &&
- distribution == CLOSURE_BSDF_SHARP_GLASS_ID)
- {
- VLOG(1) << "Using GGX glass with filter glossy.";
- distribution = CLOSURE_BSDF_MICROFACET_GGX_GLASS_ID;
- roughness = 0.0f;
- }
- }
- closure = distribution;
+ if (distribution_orig == NBUILTIN_CLOSURES) {
+ roughness_orig = roughness;
+ distribution_orig = distribution;
+ }
+ else {
+ /* By default we use original values, so we don't worry about restoring
+ * defaults later one and can only do override when needed.
+ */
+ roughness = roughness_orig;
+ distribution = distribution_orig;
+ }
+ Integrator *integrator = scene->integrator;
+ ShaderInput *roughness_input = input("Roughness");
+ if (integrator->filter_glossy == 0.0f) {
+ /* Fallback to Sharp closure for Roughness close to 0.
+ * Note: Keep the epsilon in sync with kernel!
+ */
+ if (!roughness_input->link && roughness <= 1e-4f) {
+ VLOG(1) << "Using sharp glass BSDF.";
+ distribution = CLOSURE_BSDF_SHARP_GLASS_ID;
+ }
+ }
+ else {
+ /* If filter glossy is used we replace Sharp glossy with GGX so we can
+ * benefit from closure blur to remove unwanted noise.
+ */
+ if (roughness_input->link == NULL && distribution == CLOSURE_BSDF_SHARP_GLASS_ID) {
+ VLOG(1) << "Using GGX glass with filter glossy.";
+ distribution = CLOSURE_BSDF_MICROFACET_GGX_GLASS_ID;
+ roughness = 0.0f;
+ }
+ }
+ closure = distribution;
}
bool GlassBsdfNode::has_integrator_dependency()
{
- ShaderInput *roughness_input = input("Roughness");
- return !roughness_input->link &&
- (distribution == CLOSURE_BSDF_SHARP_GLASS_ID || roughness <= 1e-4f);
+ ShaderInput *roughness_input = input("Roughness");
+ return !roughness_input->link &&
+ (distribution == CLOSURE_BSDF_SHARP_GLASS_ID || roughness <= 1e-4f);
}
-void GlassBsdfNode::compile(SVMCompiler& compiler)
+void GlassBsdfNode::compile(SVMCompiler &compiler)
{
- closure = distribution;
+ closure = distribution;
- if(closure == CLOSURE_BSDF_SHARP_GLASS_ID)
- BsdfNode::compile(compiler, NULL, input("IOR"));
- else if(closure == CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID)
- BsdfNode::compile(compiler, input("Roughness"), input("IOR"), input("Color"));
- else
- BsdfNode::compile(compiler, input("Roughness"), input("IOR"));
+ if (closure == CLOSURE_BSDF_SHARP_GLASS_ID)
+ BsdfNode::compile(compiler, NULL, input("IOR"));
+ else if (closure == CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID)
+ BsdfNode::compile(compiler, input("Roughness"), input("IOR"), input("Color"));
+ else
+ BsdfNode::compile(compiler, input("Roughness"), input("IOR"));
}
-void GlassBsdfNode::compile(OSLCompiler& compiler)
+void GlassBsdfNode::compile(OSLCompiler &compiler)
{
- compiler.parameter(this, "distribution");
- compiler.add(this, "node_glass_bsdf");
+ compiler.parameter(this, "distribution");
+ compiler.add(this, "node_glass_bsdf");
}
/* Refraction BSDF Closure */
NODE_DEFINE(RefractionBsdfNode)
{
- NodeType* type = NodeType::add("refraction_bsdf", create, NodeType::SHADER);
+ NodeType *type = NodeType::add("refraction_bsdf", create, NodeType::SHADER);
- SOCKET_IN_COLOR(color, "Color", make_float3(0.8f, 0.8f, 0.8f));
- SOCKET_IN_NORMAL(normal, "Normal", make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_NORMAL);
- SOCKET_IN_FLOAT(surface_mix_weight, "SurfaceMixWeight", 0.0f, SocketType::SVM_INTERNAL);
+ SOCKET_IN_COLOR(color, "Color", make_float3(0.8f, 0.8f, 0.8f));
+ SOCKET_IN_NORMAL(normal, "Normal", make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_NORMAL);
+ SOCKET_IN_FLOAT(surface_mix_weight, "SurfaceMixWeight", 0.0f, SocketType::SVM_INTERNAL);
- static NodeEnum distribution_enum;
- distribution_enum.insert("sharp", CLOSURE_BSDF_REFRACTION_ID);
- distribution_enum.insert("beckmann", CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID);
- distribution_enum.insert("GGX", CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID);
- SOCKET_ENUM(distribution, "Distribution", distribution_enum, CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID);
+ static NodeEnum distribution_enum;
+ distribution_enum.insert("sharp", CLOSURE_BSDF_REFRACTION_ID);
+ distribution_enum.insert("beckmann", CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID);
+ distribution_enum.insert("GGX", CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID);
+ SOCKET_ENUM(
+ distribution, "Distribution", distribution_enum, CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID);
- SOCKET_IN_FLOAT(roughness, "Roughness", 0.0f);
- SOCKET_IN_FLOAT(IOR, "IOR", 0.3f);
+ SOCKET_IN_FLOAT(roughness, "Roughness", 0.0f);
+ SOCKET_IN_FLOAT(IOR, "IOR", 0.3f);
- SOCKET_OUT_CLOSURE(BSDF, "BSDF");
+ SOCKET_OUT_CLOSURE(BSDF, "BSDF");
- return type;
+ return type;
}
-RefractionBsdfNode::RefractionBsdfNode()
-: BsdfNode(node_type)
+RefractionBsdfNode::RefractionBsdfNode() : BsdfNode(node_type)
{
- closure = CLOSURE_BSDF_REFRACTION_ID;
- distribution_orig = NBUILTIN_CLOSURES;
+ closure = CLOSURE_BSDF_REFRACTION_ID;
+ distribution_orig = NBUILTIN_CLOSURES;
}
void RefractionBsdfNode::simplify_settings(Scene *scene)
{
- if(distribution_orig == NBUILTIN_CLOSURES) {
- roughness_orig = roughness;
- distribution_orig = distribution;
- }
- else {
- /* By default we use original values, so we don't worry about restoring
- * defaults later one and can only do override when needed.
- */
- roughness = roughness_orig;
- distribution = distribution_orig;
- }
- Integrator *integrator = scene->integrator;
- ShaderInput *roughness_input = input("Roughness");
- if(integrator->filter_glossy == 0.0f) {
- /* Fallback to Sharp closure for Roughness close to 0.
- * Note: Keep the epsilon in sync with kernel!
- */
- if(!roughness_input->link && roughness <= 1e-4f) {
- VLOG(1) << "Using sharp refraction BSDF.";
- distribution = CLOSURE_BSDF_REFRACTION_ID;
- }
- }
- else {
- /* If filter glossy is used we replace Sharp glossy with GGX so we can
- * benefit from closure blur to remove unwanted noise.
- */
- if(roughness_input->link == NULL &&
- distribution == CLOSURE_BSDF_REFRACTION_ID)
- {
- VLOG(1) << "Using GGX refraction with filter glossy.";
- distribution = CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID;
- roughness = 0.0f;
- }
- }
- closure = distribution;
+ if (distribution_orig == NBUILTIN_CLOSURES) {
+ roughness_orig = roughness;
+ distribution_orig = distribution;
+ }
+ else {
+ /* By default we use original values, so we don't worry about restoring
+ * defaults later one and can only do override when needed.
+ */
+ roughness = roughness_orig;
+ distribution = distribution_orig;
+ }
+ Integrator *integrator = scene->integrator;
+ ShaderInput *roughness_input = input("Roughness");
+ if (integrator->filter_glossy == 0.0f) {
+ /* Fallback to Sharp closure for Roughness close to 0.
+ * Note: Keep the epsilon in sync with kernel!
+ */
+ if (!roughness_input->link && roughness <= 1e-4f) {
+ VLOG(1) << "Using sharp refraction BSDF.";
+ distribution = CLOSURE_BSDF_REFRACTION_ID;
+ }
+ }
+ else {
+ /* If filter glossy is used we replace Sharp glossy with GGX so we can
+ * benefit from closure blur to remove unwanted noise.
+ */
+ if (roughness_input->link == NULL && distribution == CLOSURE_BSDF_REFRACTION_ID) {
+ VLOG(1) << "Using GGX refraction with filter glossy.";
+ distribution = CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID;
+ roughness = 0.0f;
+ }
+ }
+ closure = distribution;
}
bool RefractionBsdfNode::has_integrator_dependency()
{
- ShaderInput *roughness_input = input("Roughness");
- return !roughness_input->link &&
- (distribution == CLOSURE_BSDF_REFRACTION_ID || roughness <= 1e-4f);
+ ShaderInput *roughness_input = input("Roughness");
+ return !roughness_input->link &&
+ (distribution == CLOSURE_BSDF_REFRACTION_ID || roughness <= 1e-4f);
}
-void RefractionBsdfNode::compile(SVMCompiler& compiler)
+void RefractionBsdfNode::compile(SVMCompiler &compiler)
{
- closure = distribution;
+ closure = distribution;
- if(closure == CLOSURE_BSDF_REFRACTION_ID)
- BsdfNode::compile(compiler, NULL, input("IOR"));
- else
- BsdfNode::compile(compiler, input("Roughness"), input("IOR"));
+ if (closure == CLOSURE_BSDF_REFRACTION_ID)
+ BsdfNode::compile(compiler, NULL, input("IOR"));
+ else
+ BsdfNode::compile(compiler, input("Roughness"), input("IOR"));
}
-void RefractionBsdfNode::compile(OSLCompiler& compiler)
+void RefractionBsdfNode::compile(OSLCompiler &compiler)
{
- compiler.parameter(this, "distribution");
- compiler.add(this, "node_refraction_bsdf");
+ compiler.parameter(this, "distribution");
+ compiler.add(this, "node_refraction_bsdf");
}
/* Toon BSDF Closure */
NODE_DEFINE(ToonBsdfNode)
{
- NodeType* type = NodeType::add("toon_bsdf", create, NodeType::SHADER);
+ NodeType *type = NodeType::add("toon_bsdf", create, NodeType::SHADER);
- SOCKET_IN_COLOR(color, "Color", make_float3(0.8f, 0.8f, 0.8f));
- SOCKET_IN_NORMAL(normal, "Normal", make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_NORMAL);
- SOCKET_IN_FLOAT(surface_mix_weight, "SurfaceMixWeight", 0.0f, SocketType::SVM_INTERNAL);
+ SOCKET_IN_COLOR(color, "Color", make_float3(0.8f, 0.8f, 0.8f));
+ SOCKET_IN_NORMAL(normal, "Normal", make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_NORMAL);
+ SOCKET_IN_FLOAT(surface_mix_weight, "SurfaceMixWeight", 0.0f, SocketType::SVM_INTERNAL);
- static NodeEnum component_enum;
- component_enum.insert("diffuse", CLOSURE_BSDF_DIFFUSE_TOON_ID);
- component_enum.insert("glossy", CLOSURE_BSDF_GLOSSY_TOON_ID);
- SOCKET_ENUM(component, "Component", component_enum, CLOSURE_BSDF_DIFFUSE_TOON_ID);
- SOCKET_IN_FLOAT(size, "Size", 0.5f);
- SOCKET_IN_FLOAT(smooth, "Smooth", 0.0f);
+ static NodeEnum component_enum;
+ component_enum.insert("diffuse", CLOSURE_BSDF_DIFFUSE_TOON_ID);
+ component_enum.insert("glossy", CLOSURE_BSDF_GLOSSY_TOON_ID);
+ SOCKET_ENUM(component, "Component", component_enum, CLOSURE_BSDF_DIFFUSE_TOON_ID);
+ SOCKET_IN_FLOAT(size, "Size", 0.5f);
+ SOCKET_IN_FLOAT(smooth, "Smooth", 0.0f);
- SOCKET_OUT_CLOSURE(BSDF, "BSDF");
+ SOCKET_OUT_CLOSURE(BSDF, "BSDF");
- return type;
+ return type;
}
-ToonBsdfNode::ToonBsdfNode()
-: BsdfNode(node_type)
+ToonBsdfNode::ToonBsdfNode() : BsdfNode(node_type)
{
- closure = CLOSURE_BSDF_DIFFUSE_TOON_ID;
+ closure = CLOSURE_BSDF_DIFFUSE_TOON_ID;
}
-void ToonBsdfNode::compile(SVMCompiler& compiler)
+void ToonBsdfNode::compile(SVMCompiler &compiler)
{
- closure = component;
+ closure = component;
- BsdfNode::compile(compiler, input("Size"), input("Smooth"));
+ BsdfNode::compile(compiler, input("Size"), input("Smooth"));
}
-void ToonBsdfNode::compile(OSLCompiler& compiler)
+void ToonBsdfNode::compile(OSLCompiler &compiler)
{
- compiler.parameter(this, "component");
- compiler.add(this, "node_toon_bsdf");
+ compiler.parameter(this, "component");
+ compiler.add(this, "node_toon_bsdf");
}
/* Velvet BSDF Closure */
NODE_DEFINE(VelvetBsdfNode)
{
- NodeType* type = NodeType::add("velvet_bsdf", create, NodeType::SHADER);
+ NodeType *type = NodeType::add("velvet_bsdf", create, NodeType::SHADER);
- SOCKET_IN_COLOR(color, "Color", make_float3(0.8f, 0.8f, 0.8f));
- SOCKET_IN_NORMAL(normal, "Normal", make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_NORMAL);
- SOCKET_IN_FLOAT(surface_mix_weight, "SurfaceMixWeight", 0.0f, SocketType::SVM_INTERNAL);
- SOCKET_IN_FLOAT(sigma, "Sigma", 1.0f);
+ SOCKET_IN_COLOR(color, "Color", make_float3(0.8f, 0.8f, 0.8f));
+ SOCKET_IN_NORMAL(normal, "Normal", make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_NORMAL);
+ SOCKET_IN_FLOAT(surface_mix_weight, "SurfaceMixWeight", 0.0f, SocketType::SVM_INTERNAL);
+ SOCKET_IN_FLOAT(sigma, "Sigma", 1.0f);
- SOCKET_OUT_CLOSURE(BSDF, "BSDF");
+ SOCKET_OUT_CLOSURE(BSDF, "BSDF");
- return type;
+ return type;
}
-VelvetBsdfNode::VelvetBsdfNode()
-: BsdfNode(node_type)
+VelvetBsdfNode::VelvetBsdfNode() : BsdfNode(node_type)
{
- closure = CLOSURE_BSDF_ASHIKHMIN_VELVET_ID;
+ closure = CLOSURE_BSDF_ASHIKHMIN_VELVET_ID;
}
-void VelvetBsdfNode::compile(SVMCompiler& compiler)
+void VelvetBsdfNode::compile(SVMCompiler &compiler)
{
- BsdfNode::compile(compiler, input("Sigma"), NULL);
+ BsdfNode::compile(compiler, input("Sigma"), NULL);
}
-void VelvetBsdfNode::compile(OSLCompiler& compiler)
+void VelvetBsdfNode::compile(OSLCompiler &compiler)
{
- compiler.add(this, "node_velvet_bsdf");
+ compiler.add(this, "node_velvet_bsdf");
}
/* Diffuse BSDF Closure */
NODE_DEFINE(DiffuseBsdfNode)
{
- NodeType* type = NodeType::add("diffuse_bsdf", create, NodeType::SHADER);
+ NodeType *type = NodeType::add("diffuse_bsdf", create, NodeType::SHADER);
- SOCKET_IN_COLOR(color, "Color", make_float3(0.8f, 0.8f, 0.8f));
- SOCKET_IN_NORMAL(normal, "Normal", make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_NORMAL);
- SOCKET_IN_FLOAT(surface_mix_weight, "SurfaceMixWeight", 0.0f, SocketType::SVM_INTERNAL);
- SOCKET_IN_FLOAT(roughness, "Roughness", 0.0f);
+ SOCKET_IN_COLOR(color, "Color", make_float3(0.8f, 0.8f, 0.8f));
+ SOCKET_IN_NORMAL(normal, "Normal", make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_NORMAL);
+ SOCKET_IN_FLOAT(surface_mix_weight, "SurfaceMixWeight", 0.0f, SocketType::SVM_INTERNAL);
+ SOCKET_IN_FLOAT(roughness, "Roughness", 0.0f);
- SOCKET_OUT_CLOSURE(BSDF, "BSDF");
+ SOCKET_OUT_CLOSURE(BSDF, "BSDF");
- return type;
+ return type;
}
-DiffuseBsdfNode::DiffuseBsdfNode()
-: BsdfNode(node_type)
+DiffuseBsdfNode::DiffuseBsdfNode() : BsdfNode(node_type)
{
- closure = CLOSURE_BSDF_DIFFUSE_ID;
+ closure = CLOSURE_BSDF_DIFFUSE_ID;
}
-void DiffuseBsdfNode::compile(SVMCompiler& compiler)
+void DiffuseBsdfNode::compile(SVMCompiler &compiler)
{
- BsdfNode::compile(compiler, input("Roughness"), NULL);
+ BsdfNode::compile(compiler, input("Roughness"), NULL);
}
-void DiffuseBsdfNode::compile(OSLCompiler& compiler)
+void DiffuseBsdfNode::compile(OSLCompiler &compiler)
{
- compiler.add(this, "node_diffuse_bsdf");
+ compiler.add(this, "node_diffuse_bsdf");
}
/* Disney principled BSDF Closure */
NODE_DEFINE(PrincipledBsdfNode)
{
- NodeType* type = NodeType::add("principled_bsdf", create, NodeType::SHADER);
-
- static NodeEnum distribution_enum;
- distribution_enum.insert("GGX", CLOSURE_BSDF_MICROFACET_GGX_GLASS_ID);
- distribution_enum.insert("Multiscatter GGX", CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID);
- SOCKET_ENUM(distribution, "Distribution", distribution_enum, CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID);
-
- static NodeEnum subsurface_method_enum;
- subsurface_method_enum.insert("burley", CLOSURE_BSSRDF_PRINCIPLED_ID);
- subsurface_method_enum.insert("random_walk", CLOSURE_BSSRDF_PRINCIPLED_RANDOM_WALK_ID);
- SOCKET_ENUM(subsurface_method, "Subsurface Method", subsurface_method_enum, CLOSURE_BSSRDF_PRINCIPLED_ID);
-
- SOCKET_IN_COLOR(base_color, "Base Color", make_float3(0.8f, 0.8f, 0.8f));
- SOCKET_IN_COLOR(subsurface_color, "Subsurface Color", make_float3(0.8f, 0.8f, 0.8f));
- SOCKET_IN_FLOAT(metallic, "Metallic", 0.0f);
- SOCKET_IN_FLOAT(subsurface, "Subsurface", 0.0f);
- SOCKET_IN_VECTOR(subsurface_radius, "Subsurface Radius", make_float3(0.1f, 0.1f, 0.1f));
- SOCKET_IN_FLOAT(specular, "Specular", 0.0f);
- SOCKET_IN_FLOAT(roughness, "Roughness", 0.5f);
- SOCKET_IN_FLOAT(specular_tint, "Specular Tint", 0.0f);
- SOCKET_IN_FLOAT(anisotropic, "Anisotropic", 0.0f);
- SOCKET_IN_FLOAT(sheen, "Sheen", 0.0f);
- SOCKET_IN_FLOAT(sheen_tint, "Sheen Tint", 0.0f);
- SOCKET_IN_FLOAT(clearcoat, "Clearcoat", 0.0f);
- SOCKET_IN_FLOAT(clearcoat_roughness, "Clearcoat Roughness", 0.03f);
- SOCKET_IN_FLOAT(ior, "IOR", 0.0f);
- SOCKET_IN_FLOAT(transmission, "Transmission", 0.0f);
- SOCKET_IN_FLOAT(transmission_roughness, "Transmission Roughness", 0.0f);
- SOCKET_IN_FLOAT(anisotropic_rotation, "Anisotropic Rotation", 0.0f);
- SOCKET_IN_NORMAL(normal, "Normal", make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_NORMAL);
- SOCKET_IN_NORMAL(clearcoat_normal, "Clearcoat Normal", make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_NORMAL);
- SOCKET_IN_NORMAL(tangent, "Tangent", make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_TANGENT);
- SOCKET_IN_FLOAT(surface_mix_weight, "SurfaceMixWeight", 0.0f, SocketType::SVM_INTERNAL);
-
- SOCKET_OUT_CLOSURE(BSDF, "BSDF");
-
- return type;
-}
-
-PrincipledBsdfNode::PrincipledBsdfNode()
- : BsdfBaseNode(node_type)
-{
- closure = CLOSURE_BSDF_PRINCIPLED_ID;
- distribution = CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID;
- distribution_orig = NBUILTIN_CLOSURES;
+ NodeType *type = NodeType::add("principled_bsdf", create, NodeType::SHADER);
+
+ static NodeEnum distribution_enum;
+ distribution_enum.insert("GGX", CLOSURE_BSDF_MICROFACET_GGX_GLASS_ID);
+ distribution_enum.insert("Multiscatter GGX", CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID);
+ SOCKET_ENUM(
+ distribution, "Distribution", distribution_enum, CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID);
+
+ static NodeEnum subsurface_method_enum;
+ subsurface_method_enum.insert("burley", CLOSURE_BSSRDF_PRINCIPLED_ID);
+ subsurface_method_enum.insert("random_walk", CLOSURE_BSSRDF_PRINCIPLED_RANDOM_WALK_ID);
+ SOCKET_ENUM(subsurface_method,
+ "Subsurface Method",
+ subsurface_method_enum,
+ CLOSURE_BSSRDF_PRINCIPLED_ID);
+
+ SOCKET_IN_COLOR(base_color, "Base Color", make_float3(0.8f, 0.8f, 0.8f));
+ SOCKET_IN_COLOR(subsurface_color, "Subsurface Color", make_float3(0.8f, 0.8f, 0.8f));
+ SOCKET_IN_FLOAT(metallic, "Metallic", 0.0f);
+ SOCKET_IN_FLOAT(subsurface, "Subsurface", 0.0f);
+ SOCKET_IN_VECTOR(subsurface_radius, "Subsurface Radius", make_float3(0.1f, 0.1f, 0.1f));
+ SOCKET_IN_FLOAT(specular, "Specular", 0.0f);
+ SOCKET_IN_FLOAT(roughness, "Roughness", 0.5f);
+ SOCKET_IN_FLOAT(specular_tint, "Specular Tint", 0.0f);
+ SOCKET_IN_FLOAT(anisotropic, "Anisotropic", 0.0f);
+ SOCKET_IN_FLOAT(sheen, "Sheen", 0.0f);
+ SOCKET_IN_FLOAT(sheen_tint, "Sheen Tint", 0.0f);
+ SOCKET_IN_FLOAT(clearcoat, "Clearcoat", 0.0f);
+ SOCKET_IN_FLOAT(clearcoat_roughness, "Clearcoat Roughness", 0.03f);
+ SOCKET_IN_FLOAT(ior, "IOR", 0.0f);
+ SOCKET_IN_FLOAT(transmission, "Transmission", 0.0f);
+ SOCKET_IN_FLOAT(transmission_roughness, "Transmission Roughness", 0.0f);
+ SOCKET_IN_FLOAT(anisotropic_rotation, "Anisotropic Rotation", 0.0f);
+ SOCKET_IN_NORMAL(normal, "Normal", make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_NORMAL);
+ SOCKET_IN_NORMAL(clearcoat_normal,
+ "Clearcoat Normal",
+ make_float3(0.0f, 0.0f, 0.0f),
+ SocketType::LINK_NORMAL);
+ SOCKET_IN_NORMAL(tangent, "Tangent", make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_TANGENT);
+ SOCKET_IN_FLOAT(surface_mix_weight, "SurfaceMixWeight", 0.0f, SocketType::SVM_INTERNAL);
+
+ SOCKET_OUT_CLOSURE(BSDF, "BSDF");
+
+ return type;
+}
+
+PrincipledBsdfNode::PrincipledBsdfNode() : BsdfBaseNode(node_type)
+{
+ closure = CLOSURE_BSDF_PRINCIPLED_ID;
+ distribution = CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID;
+ distribution_orig = NBUILTIN_CLOSURES;
}
bool PrincipledBsdfNode::has_surface_bssrdf()
{
- ShaderInput *subsurface_in = input("Subsurface");
- return (subsurface_in->link != NULL || subsurface > CLOSURE_WEIGHT_CUTOFF);
+ ShaderInput *subsurface_in = input("Subsurface");
+ return (subsurface_in->link != NULL || subsurface > CLOSURE_WEIGHT_CUTOFF);
}
void PrincipledBsdfNode::attributes(Shader *shader, AttributeRequestSet *attributes)
{
- if(shader->has_surface) {
- ShaderInput *tangent_in = input("Tangent");
-
- if(!tangent_in->link)
- attributes->add(ATTR_STD_GENERATED);
- }
-
- ShaderNode::attributes(shader, attributes);
-}
-
-void PrincipledBsdfNode::compile(SVMCompiler& compiler, ShaderInput *p_metallic, ShaderInput *p_subsurface, ShaderInput *p_subsurface_radius,
- ShaderInput *p_specular, ShaderInput *p_roughness, ShaderInput *p_specular_tint, ShaderInput *p_anisotropic,
- ShaderInput *p_sheen, ShaderInput *p_sheen_tint, ShaderInput *p_clearcoat, ShaderInput *p_clearcoat_roughness,
- ShaderInput *p_ior, ShaderInput *p_transmission, ShaderInput *p_anisotropic_rotation, ShaderInput *p_transmission_roughness)
-{
- ShaderInput *base_color_in = input("Base Color");
- ShaderInput *subsurface_color_in = input("Subsurface Color");
- ShaderInput *normal_in = input("Normal");
- ShaderInput *clearcoat_normal_in = input("Clearcoat Normal");
- ShaderInput *tangent_in = input("Tangent");
-
- float3 weight = make_float3(1.0f, 1.0f, 1.0f);
-
- compiler.add_node(NODE_CLOSURE_SET_WEIGHT, weight);
-
- int normal_offset = compiler.stack_assign_if_linked(normal_in);
- int clearcoat_normal_offset = compiler.stack_assign_if_linked(clearcoat_normal_in);
- int tangent_offset = compiler.stack_assign_if_linked(tangent_in);
- int specular_offset = compiler.stack_assign(p_specular);
- int roughness_offset = compiler.stack_assign(p_roughness);
- int specular_tint_offset = compiler.stack_assign(p_specular_tint);
- int anisotropic_offset = compiler.stack_assign(p_anisotropic);
- int sheen_offset = compiler.stack_assign(p_sheen);
- int sheen_tint_offset = compiler.stack_assign(p_sheen_tint);
- int clearcoat_offset = compiler.stack_assign(p_clearcoat);
- int clearcoat_roughness_offset = compiler.stack_assign(p_clearcoat_roughness);
- int ior_offset = compiler.stack_assign(p_ior);
- int transmission_offset = compiler.stack_assign(p_transmission);
- int transmission_roughness_offset = compiler.stack_assign(p_transmission_roughness);
- int anisotropic_rotation_offset = compiler.stack_assign(p_anisotropic_rotation);
- int subsurface_radius_offset = compiler.stack_assign(p_subsurface_radius);
-
- compiler.add_node(NODE_CLOSURE_BSDF,
- compiler.encode_uchar4(closure,
- compiler.stack_assign(p_metallic),
- compiler.stack_assign(p_subsurface),
- compiler.closure_mix_weight_offset()),
- __float_as_int((p_metallic) ? get_float(p_metallic->socket_type) : 0.0f),
- __float_as_int((p_subsurface) ? get_float(p_subsurface->socket_type) : 0.0f));
-
- compiler.add_node(normal_offset, tangent_offset,
- compiler.encode_uchar4(specular_offset, roughness_offset, specular_tint_offset, anisotropic_offset),
- compiler.encode_uchar4(sheen_offset, sheen_tint_offset, clearcoat_offset, clearcoat_roughness_offset));
-
- compiler.add_node(compiler.encode_uchar4(ior_offset, transmission_offset, anisotropic_rotation_offset, transmission_roughness_offset),
- distribution, subsurface_method, SVM_STACK_INVALID);
-
- float3 bc_default = get_float3(base_color_in->socket_type);
-
- compiler.add_node(((base_color_in->link) ? compiler.stack_assign(base_color_in) : SVM_STACK_INVALID),
- __float_as_int(bc_default.x), __float_as_int(bc_default.y), __float_as_int(bc_default.z));
-
- compiler.add_node(clearcoat_normal_offset, subsurface_radius_offset, SVM_STACK_INVALID, SVM_STACK_INVALID);
-
- float3 ss_default = get_float3(subsurface_color_in->socket_type);
-
- compiler.add_node(((subsurface_color_in->link) ? compiler.stack_assign(subsurface_color_in) : SVM_STACK_INVALID),
- __float_as_int(ss_default.x), __float_as_int(ss_default.y), __float_as_int(ss_default.z));
+ if (shader->has_surface) {
+ ShaderInput *tangent_in = input("Tangent");
+
+ if (!tangent_in->link)
+ attributes->add(ATTR_STD_GENERATED);
+ }
+
+ ShaderNode::attributes(shader, attributes);
+}
+
+void PrincipledBsdfNode::compile(SVMCompiler &compiler,
+ ShaderInput *p_metallic,
+ ShaderInput *p_subsurface,
+ ShaderInput *p_subsurface_radius,
+ ShaderInput *p_specular,
+ ShaderInput *p_roughness,
+ ShaderInput *p_specular_tint,
+ ShaderInput *p_anisotropic,
+ ShaderInput *p_sheen,
+ ShaderInput *p_sheen_tint,
+ ShaderInput *p_clearcoat,
+ ShaderInput *p_clearcoat_roughness,
+ ShaderInput *p_ior,
+ ShaderInput *p_transmission,
+ ShaderInput *p_anisotropic_rotation,
+ ShaderInput *p_transmission_roughness)
+{
+ ShaderInput *base_color_in = input("Base Color");
+ ShaderInput *subsurface_color_in = input("Subsurface Color");
+ ShaderInput *normal_in = input("Normal");
+ ShaderInput *clearcoat_normal_in = input("Clearcoat Normal");
+ ShaderInput *tangent_in = input("Tangent");
+
+ float3 weight = make_float3(1.0f, 1.0f, 1.0f);
+
+ compiler.add_node(NODE_CLOSURE_SET_WEIGHT, weight);
+
+ int normal_offset = compiler.stack_assign_if_linked(normal_in);
+ int clearcoat_normal_offset = compiler.stack_assign_if_linked(clearcoat_normal_in);
+ int tangent_offset = compiler.stack_assign_if_linked(tangent_in);
+ int specular_offset = compiler.stack_assign(p_specular);
+ int roughness_offset = compiler.stack_assign(p_roughness);
+ int specular_tint_offset = compiler.stack_assign(p_specular_tint);
+ int anisotropic_offset = compiler.stack_assign(p_anisotropic);
+ int sheen_offset = compiler.stack_assign(p_sheen);
+ int sheen_tint_offset = compiler.stack_assign(p_sheen_tint);
+ int clearcoat_offset = compiler.stack_assign(p_clearcoat);
+ int clearcoat_roughness_offset = compiler.stack_assign(p_clearcoat_roughness);
+ int ior_offset = compiler.stack_assign(p_ior);
+ int transmission_offset = compiler.stack_assign(p_transmission);
+ int transmission_roughness_offset = compiler.stack_assign(p_transmission_roughness);
+ int anisotropic_rotation_offset = compiler.stack_assign(p_anisotropic_rotation);
+ int subsurface_radius_offset = compiler.stack_assign(p_subsurface_radius);
+
+ compiler.add_node(NODE_CLOSURE_BSDF,
+ compiler.encode_uchar4(closure,
+ compiler.stack_assign(p_metallic),
+ compiler.stack_assign(p_subsurface),
+ compiler.closure_mix_weight_offset()),
+ __float_as_int((p_metallic) ? get_float(p_metallic->socket_type) : 0.0f),
+ __float_as_int((p_subsurface) ? get_float(p_subsurface->socket_type) : 0.0f));
+
+ compiler.add_node(
+ normal_offset,
+ tangent_offset,
+ compiler.encode_uchar4(
+ specular_offset, roughness_offset, specular_tint_offset, anisotropic_offset),
+ compiler.encode_uchar4(
+ sheen_offset, sheen_tint_offset, clearcoat_offset, clearcoat_roughness_offset));
+
+ compiler.add_node(compiler.encode_uchar4(ior_offset,
+ transmission_offset,
+ anisotropic_rotation_offset,
+ transmission_roughness_offset),
+ distribution,
+ subsurface_method,
+ SVM_STACK_INVALID);
+
+ float3 bc_default = get_float3(base_color_in->socket_type);
+
+ compiler.add_node(
+ ((base_color_in->link) ? compiler.stack_assign(base_color_in) : SVM_STACK_INVALID),
+ __float_as_int(bc_default.x),
+ __float_as_int(bc_default.y),
+ __float_as_int(bc_default.z));
+
+ compiler.add_node(
+ clearcoat_normal_offset, subsurface_radius_offset, SVM_STACK_INVALID, SVM_STACK_INVALID);
+
+ float3 ss_default = get_float3(subsurface_color_in->socket_type);
+
+ compiler.add_node(((subsurface_color_in->link) ? compiler.stack_assign(subsurface_color_in) :
+ SVM_STACK_INVALID),
+ __float_as_int(ss_default.x),
+ __float_as_int(ss_default.y),
+ __float_as_int(ss_default.z));
}
bool PrincipledBsdfNode::has_integrator_dependency()
{
- ShaderInput *roughness_input = input("Roughness");
- return !roughness_input->link && roughness <= 1e-4f;
+ ShaderInput *roughness_input = input("Roughness");
+ return !roughness_input->link && roughness <= 1e-4f;
}
-void PrincipledBsdfNode::compile(SVMCompiler& compiler)
+void PrincipledBsdfNode::compile(SVMCompiler &compiler)
{
- compile(compiler, input("Metallic"), input("Subsurface"), input("Subsurface Radius"), input("Specular"),
- input("Roughness"), input("Specular Tint"), input("Anisotropic"), input("Sheen"), input("Sheen Tint"),
- input("Clearcoat"), input("Clearcoat Roughness"), input("IOR"), input("Transmission"),
- input("Anisotropic Rotation"), input("Transmission Roughness"));
+ compile(compiler,
+ input("Metallic"),
+ input("Subsurface"),
+ input("Subsurface Radius"),
+ input("Specular"),
+ input("Roughness"),
+ input("Specular Tint"),
+ input("Anisotropic"),
+ input("Sheen"),
+ input("Sheen Tint"),
+ input("Clearcoat"),
+ input("Clearcoat Roughness"),
+ input("IOR"),
+ input("Transmission"),
+ input("Anisotropic Rotation"),
+ input("Transmission Roughness"));
}
-void PrincipledBsdfNode::compile(OSLCompiler& compiler)
+void PrincipledBsdfNode::compile(OSLCompiler &compiler)
{
- compiler.parameter(this, "distribution");
- compiler.parameter(this, "subsurface_method");
- compiler.add(this, "node_principled_bsdf");
+ compiler.parameter(this, "distribution");
+ compiler.parameter(this, "subsurface_method");
+ compiler.add(this, "node_principled_bsdf");
}
bool PrincipledBsdfNode::has_bssrdf_bump()
{
- return has_surface_bssrdf() && has_bump();
+ return has_surface_bssrdf() && has_bump();
}
/* Translucent BSDF Closure */
NODE_DEFINE(TranslucentBsdfNode)
{
- NodeType* type = NodeType::add("translucent_bsdf", create, NodeType::SHADER);
+ NodeType *type = NodeType::add("translucent_bsdf", create, NodeType::SHADER);
- SOCKET_IN_COLOR(color, "Color", make_float3(0.8f, 0.8f, 0.8f));
- SOCKET_IN_NORMAL(normal, "Normal", make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_NORMAL);
- SOCKET_IN_FLOAT(surface_mix_weight, "SurfaceMixWeight", 0.0f, SocketType::SVM_INTERNAL);
+ SOCKET_IN_COLOR(color, "Color", make_float3(0.8f, 0.8f, 0.8f));
+ SOCKET_IN_NORMAL(normal, "Normal", make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_NORMAL);
+ SOCKET_IN_FLOAT(surface_mix_weight, "SurfaceMixWeight", 0.0f, SocketType::SVM_INTERNAL);
- SOCKET_OUT_CLOSURE(BSDF, "BSDF");
+ SOCKET_OUT_CLOSURE(BSDF, "BSDF");
- return type;
+ return type;
}
-TranslucentBsdfNode::TranslucentBsdfNode()
-: BsdfNode(node_type)
+TranslucentBsdfNode::TranslucentBsdfNode() : BsdfNode(node_type)
{
- closure = CLOSURE_BSDF_TRANSLUCENT_ID;
+ closure = CLOSURE_BSDF_TRANSLUCENT_ID;
}
-void TranslucentBsdfNode::compile(SVMCompiler& compiler)
+void TranslucentBsdfNode::compile(SVMCompiler &compiler)
{
- BsdfNode::compile(compiler, NULL, NULL);
+ BsdfNode::compile(compiler, NULL, NULL);
}
-void TranslucentBsdfNode::compile(OSLCompiler& compiler)
+void TranslucentBsdfNode::compile(OSLCompiler &compiler)
{
- compiler.add(this, "node_translucent_bsdf");
+ compiler.add(this, "node_translucent_bsdf");
}
/* Transparent BSDF Closure */
NODE_DEFINE(TransparentBsdfNode)
{
- NodeType* type = NodeType::add("transparent_bsdf", create, NodeType::SHADER);
+ NodeType *type = NodeType::add("transparent_bsdf", create, NodeType::SHADER);
- SOCKET_IN_COLOR(color, "Color", make_float3(0.8f, 0.8f, 0.8f));
- SOCKET_IN_FLOAT(surface_mix_weight, "SurfaceMixWeight", 0.0f, SocketType::SVM_INTERNAL);
+ SOCKET_IN_COLOR(color, "Color", make_float3(0.8f, 0.8f, 0.8f));
+ SOCKET_IN_FLOAT(surface_mix_weight, "SurfaceMixWeight", 0.0f, SocketType::SVM_INTERNAL);
- SOCKET_OUT_CLOSURE(BSDF, "BSDF");
+ SOCKET_OUT_CLOSURE(BSDF, "BSDF");
- return type;
+ return type;
}
-TransparentBsdfNode::TransparentBsdfNode()
-: BsdfNode(node_type)
+TransparentBsdfNode::TransparentBsdfNode() : BsdfNode(node_type)
{
- closure = CLOSURE_BSDF_TRANSPARENT_ID;
+ closure = CLOSURE_BSDF_TRANSPARENT_ID;
}
-void TransparentBsdfNode::compile(SVMCompiler& compiler)
+void TransparentBsdfNode::compile(SVMCompiler &compiler)
{
- BsdfNode::compile(compiler, NULL, NULL);
+ BsdfNode::compile(compiler, NULL, NULL);
}
-void TransparentBsdfNode::compile(OSLCompiler& compiler)
+void TransparentBsdfNode::compile(OSLCompiler &compiler)
{
- compiler.add(this, "node_transparent_bsdf");
+ compiler.add(this, "node_transparent_bsdf");
}
/* Subsurface Scattering Closure */
NODE_DEFINE(SubsurfaceScatteringNode)
{
- NodeType* type = NodeType::add("subsurface_scattering", create, NodeType::SHADER);
+ NodeType *type = NodeType::add("subsurface_scattering", create, NodeType::SHADER);
- SOCKET_IN_COLOR(color, "Color", make_float3(0.8f, 0.8f, 0.8f));
- SOCKET_IN_NORMAL(normal, "Normal", make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_NORMAL);
- SOCKET_IN_FLOAT(surface_mix_weight, "SurfaceMixWeight", 0.0f, SocketType::SVM_INTERNAL);
+ SOCKET_IN_COLOR(color, "Color", make_float3(0.8f, 0.8f, 0.8f));
+ SOCKET_IN_NORMAL(normal, "Normal", make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_NORMAL);
+ SOCKET_IN_FLOAT(surface_mix_weight, "SurfaceMixWeight", 0.0f, SocketType::SVM_INTERNAL);
- static NodeEnum falloff_enum;
- falloff_enum.insert("cubic", CLOSURE_BSSRDF_CUBIC_ID);
- falloff_enum.insert("gaussian", CLOSURE_BSSRDF_GAUSSIAN_ID);
- falloff_enum.insert("burley", CLOSURE_BSSRDF_BURLEY_ID);
- falloff_enum.insert("random_walk", CLOSURE_BSSRDF_RANDOM_WALK_ID);
- SOCKET_ENUM(falloff, "Falloff", falloff_enum, CLOSURE_BSSRDF_BURLEY_ID);
- SOCKET_IN_FLOAT(scale, "Scale", 0.01f);
- SOCKET_IN_VECTOR(radius, "Radius", make_float3(0.1f, 0.1f, 0.1f));
- SOCKET_IN_FLOAT(sharpness, "Sharpness", 0.0f);
- SOCKET_IN_FLOAT(texture_blur, "Texture Blur", 1.0f);
+ static NodeEnum falloff_enum;
+ falloff_enum.insert("cubic", CLOSURE_BSSRDF_CUBIC_ID);
+ falloff_enum.insert("gaussian", CLOSURE_BSSRDF_GAUSSIAN_ID);
+ falloff_enum.insert("burley", CLOSURE_BSSRDF_BURLEY_ID);
+ falloff_enum.insert("random_walk", CLOSURE_BSSRDF_RANDOM_WALK_ID);
+ SOCKET_ENUM(falloff, "Falloff", falloff_enum, CLOSURE_BSSRDF_BURLEY_ID);
+ SOCKET_IN_FLOAT(scale, "Scale", 0.01f);
+ SOCKET_IN_VECTOR(radius, "Radius", make_float3(0.1f, 0.1f, 0.1f));
+ SOCKET_IN_FLOAT(sharpness, "Sharpness", 0.0f);
+ SOCKET_IN_FLOAT(texture_blur, "Texture Blur", 1.0f);
- SOCKET_OUT_CLOSURE(BSSRDF, "BSSRDF");
+ SOCKET_OUT_CLOSURE(BSSRDF, "BSSRDF");
- return type;
+ return type;
}
-SubsurfaceScatteringNode::SubsurfaceScatteringNode()
-: BsdfNode(node_type)
+SubsurfaceScatteringNode::SubsurfaceScatteringNode() : BsdfNode(node_type)
{
- closure = falloff;
+ closure = falloff;
}
-void SubsurfaceScatteringNode::compile(SVMCompiler& compiler)
+void SubsurfaceScatteringNode::compile(SVMCompiler &compiler)
{
- closure = falloff;
- BsdfNode::compile(compiler, input("Scale"), input("Texture Blur"), input("Radius"), input("Sharpness"));
+ closure = falloff;
+ BsdfNode::compile(
+ compiler, input("Scale"), input("Texture Blur"), input("Radius"), input("Sharpness"));
}
-void SubsurfaceScatteringNode::compile(OSLCompiler& compiler)
+void SubsurfaceScatteringNode::compile(OSLCompiler &compiler)
{
- closure = falloff;
- compiler.parameter(this, "falloff");
- compiler.add(this, "node_subsurface_scattering");
+ closure = falloff;
+ compiler.parameter(this, "falloff");
+ compiler.add(this, "node_subsurface_scattering");
}
bool SubsurfaceScatteringNode::has_bssrdf_bump()
{
- /* detect if anything is plugged into the normal input besides the default */
- ShaderInput *normal_in = input("Normal");
- return (normal_in->link && normal_in->link->parent->special_type != SHADER_SPECIAL_TYPE_GEOMETRY);
+ /* detect if anything is plugged into the normal input besides the default */
+ ShaderInput *normal_in = input("Normal");
+ return (normal_in->link &&
+ normal_in->link->parent->special_type != SHADER_SPECIAL_TYPE_GEOMETRY);
}
/* Emissive Closure */
NODE_DEFINE(EmissionNode)
{
- NodeType* type = NodeType::add("emission", create, NodeType::SHADER);
+ NodeType *type = NodeType::add("emission", create, NodeType::SHADER);
- SOCKET_IN_COLOR(color, "Color", make_float3(0.8f, 0.8f, 0.8f));
- SOCKET_IN_FLOAT(strength, "Strength", 10.0f);
- SOCKET_IN_FLOAT(surface_mix_weight, "SurfaceMixWeight", 0.0f, SocketType::SVM_INTERNAL);
+ SOCKET_IN_COLOR(color, "Color", make_float3(0.8f, 0.8f, 0.8f));
+ SOCKET_IN_FLOAT(strength, "Strength", 10.0f);
+ SOCKET_IN_FLOAT(surface_mix_weight, "SurfaceMixWeight", 0.0f, SocketType::SVM_INTERNAL);
- SOCKET_OUT_CLOSURE(emission, "Emission");
+ SOCKET_OUT_CLOSURE(emission, "Emission");
- return type;
+ return type;
}
-EmissionNode::EmissionNode()
-: ShaderNode(node_type)
+EmissionNode::EmissionNode() : ShaderNode(node_type)
{
}
-void EmissionNode::compile(SVMCompiler& compiler)
+void EmissionNode::compile(SVMCompiler &compiler)
{
- ShaderInput *color_in = input("Color");
- ShaderInput *strength_in = input("Strength");
+ ShaderInput *color_in = input("Color");
+ ShaderInput *strength_in = input("Strength");
- if(color_in->link || strength_in->link) {
- compiler.add_node(NODE_EMISSION_WEIGHT,
- compiler.stack_assign(color_in),
- compiler.stack_assign(strength_in));
- }
- else
- compiler.add_node(NODE_CLOSURE_SET_WEIGHT, color * strength);
+ if (color_in->link || strength_in->link) {
+ compiler.add_node(
+ NODE_EMISSION_WEIGHT, compiler.stack_assign(color_in), compiler.stack_assign(strength_in));
+ }
+ else
+ compiler.add_node(NODE_CLOSURE_SET_WEIGHT, color * strength);
- compiler.add_node(NODE_CLOSURE_EMISSION, compiler.closure_mix_weight_offset());
+ compiler.add_node(NODE_CLOSURE_EMISSION, compiler.closure_mix_weight_offset());
}
-void EmissionNode::compile(OSLCompiler& compiler)
+void EmissionNode::compile(OSLCompiler &compiler)
{
- compiler.add(this, "node_emission");
+ compiler.add(this, "node_emission");
}
-void EmissionNode::constant_fold(const ConstantFolder& folder)
+void EmissionNode::constant_fold(const ConstantFolder &folder)
{
- ShaderInput *color_in = input("Color");
- ShaderInput *strength_in = input("Strength");
+ ShaderInput *color_in = input("Color");
+ ShaderInput *strength_in = input("Strength");
- if((!color_in->link && color == make_float3(0.0f, 0.0f, 0.0f)) ||
- (!strength_in->link && strength == 0.0f))
- {
- folder.discard();
- }
+ if ((!color_in->link && color == make_float3(0.0f, 0.0f, 0.0f)) ||
+ (!strength_in->link && strength == 0.0f)) {
+ folder.discard();
+ }
}
/* Background Closure */
NODE_DEFINE(BackgroundNode)
{
- NodeType* type = NodeType::add("background_shader", create, NodeType::SHADER);
+ NodeType *type = NodeType::add("background_shader", create, NodeType::SHADER);
- SOCKET_IN_COLOR(color, "Color", make_float3(0.8f, 0.8f, 0.8f));
- SOCKET_IN_FLOAT(strength, "Strength", 1.0f);
- SOCKET_IN_FLOAT(surface_mix_weight, "SurfaceMixWeight", 0.0f, SocketType::SVM_INTERNAL);
+ SOCKET_IN_COLOR(color, "Color", make_float3(0.8f, 0.8f, 0.8f));
+ SOCKET_IN_FLOAT(strength, "Strength", 1.0f);
+ SOCKET_IN_FLOAT(surface_mix_weight, "SurfaceMixWeight", 0.0f, SocketType::SVM_INTERNAL);
- SOCKET_OUT_CLOSURE(background, "Background");
+ SOCKET_OUT_CLOSURE(background, "Background");
- return type;
+ return type;
}
-BackgroundNode::BackgroundNode()
-: ShaderNode(node_type)
+BackgroundNode::BackgroundNode() : ShaderNode(node_type)
{
}
-void BackgroundNode::compile(SVMCompiler& compiler)
+void BackgroundNode::compile(SVMCompiler &compiler)
{
- ShaderInput *color_in = input("Color");
- ShaderInput *strength_in = input("Strength");
+ ShaderInput *color_in = input("Color");
+ ShaderInput *strength_in = input("Strength");
- if(color_in->link || strength_in->link) {
- compiler.add_node(NODE_EMISSION_WEIGHT,
- compiler.stack_assign(color_in),
- compiler.stack_assign(strength_in));
- }
- else
- compiler.add_node(NODE_CLOSURE_SET_WEIGHT, color*strength);
+ if (color_in->link || strength_in->link) {
+ compiler.add_node(
+ NODE_EMISSION_WEIGHT, compiler.stack_assign(color_in), compiler.stack_assign(strength_in));
+ }
+ else
+ compiler.add_node(NODE_CLOSURE_SET_WEIGHT, color * strength);
- compiler.add_node(NODE_CLOSURE_BACKGROUND, compiler.closure_mix_weight_offset());
+ compiler.add_node(NODE_CLOSURE_BACKGROUND, compiler.closure_mix_weight_offset());
}
-void BackgroundNode::compile(OSLCompiler& compiler)
+void BackgroundNode::compile(OSLCompiler &compiler)
{
- compiler.add(this, "node_background");
+ compiler.add(this, "node_background");
}
-void BackgroundNode::constant_fold(const ConstantFolder& folder)
+void BackgroundNode::constant_fold(const ConstantFolder &folder)
{
- ShaderInput *color_in = input("Color");
- ShaderInput *strength_in = input("Strength");
+ ShaderInput *color_in = input("Color");
+ ShaderInput *strength_in = input("Strength");
- if((!color_in->link && color == make_float3(0.0f, 0.0f, 0.0f)) ||
- (!strength_in->link && strength == 0.0f))
- {
- folder.discard();
- }
+ if ((!color_in->link && color == make_float3(0.0f, 0.0f, 0.0f)) ||
+ (!strength_in->link && strength == 0.0f)) {
+ folder.discard();
+ }
}
/* Holdout Closure */
NODE_DEFINE(HoldoutNode)
{
- NodeType* type = NodeType::add("holdout", create, NodeType::SHADER);
+ NodeType *type = NodeType::add("holdout", create, NodeType::SHADER);
- SOCKET_IN_FLOAT(surface_mix_weight, "SurfaceMixWeight", 0.0f, SocketType::SVM_INTERNAL);
- SOCKET_IN_FLOAT(volume_mix_weight, "VolumeMixWeight", 0.0f, SocketType::SVM_INTERNAL);
+ SOCKET_IN_FLOAT(surface_mix_weight, "SurfaceMixWeight", 0.0f, SocketType::SVM_INTERNAL);
+ SOCKET_IN_FLOAT(volume_mix_weight, "VolumeMixWeight", 0.0f, SocketType::SVM_INTERNAL);
- SOCKET_OUT_CLOSURE(holdout, "Holdout");
+ SOCKET_OUT_CLOSURE(holdout, "Holdout");
- return type;
+ return type;
}
-HoldoutNode::HoldoutNode()
-: ShaderNode(node_type)
+HoldoutNode::HoldoutNode() : ShaderNode(node_type)
{
}
-void HoldoutNode::compile(SVMCompiler& compiler)
+void HoldoutNode::compile(SVMCompiler &compiler)
{
- float3 value = make_float3(1.0f, 1.0f, 1.0f);
+ float3 value = make_float3(1.0f, 1.0f, 1.0f);
- compiler.add_node(NODE_CLOSURE_SET_WEIGHT, value);
- compiler.add_node(NODE_CLOSURE_HOLDOUT, compiler.closure_mix_weight_offset());
+ compiler.add_node(NODE_CLOSURE_SET_WEIGHT, value);
+ compiler.add_node(NODE_CLOSURE_HOLDOUT, compiler.closure_mix_weight_offset());
}
-void HoldoutNode::compile(OSLCompiler& compiler)
+void HoldoutNode::compile(OSLCompiler &compiler)
{
- compiler.add(this, "node_holdout");
+ compiler.add(this, "node_holdout");
}
/* Ambient Occlusion */
NODE_DEFINE(AmbientOcclusionNode)
{
- NodeType* type = NodeType::add("ambient_occlusion", create, NodeType::SHADER);
+ NodeType *type = NodeType::add("ambient_occlusion", create, NodeType::SHADER);
- SOCKET_INT(samples, "Samples", 16);
+ SOCKET_INT(samples, "Samples", 16);
- SOCKET_IN_COLOR(color, "Color", make_float3(1.0f, 1.0f, 1.0f));
- SOCKET_IN_FLOAT(distance, "Distance", 1.0f);
- SOCKET_IN_NORMAL(normal, "Normal", make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_NORMAL);
+ SOCKET_IN_COLOR(color, "Color", make_float3(1.0f, 1.0f, 1.0f));
+ SOCKET_IN_FLOAT(distance, "Distance", 1.0f);
+ SOCKET_IN_NORMAL(normal, "Normal", make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_NORMAL);
- SOCKET_BOOLEAN(inside, "Inside", false);
- SOCKET_BOOLEAN(only_local, "Only Local", false);
+ SOCKET_BOOLEAN(inside, "Inside", false);
+ SOCKET_BOOLEAN(only_local, "Only Local", false);
- SOCKET_OUT_COLOR(color, "Color");
- SOCKET_OUT_FLOAT(ao, "AO");
+ SOCKET_OUT_COLOR(color, "Color");
+ SOCKET_OUT_FLOAT(ao, "AO");
- return type;
+ return type;
}
-AmbientOcclusionNode::AmbientOcclusionNode()
-: ShaderNode(node_type)
+AmbientOcclusionNode::AmbientOcclusionNode() : ShaderNode(node_type)
{
}
-void AmbientOcclusionNode::compile(SVMCompiler& compiler)
+void AmbientOcclusionNode::compile(SVMCompiler &compiler)
{
- ShaderInput *color_in = input("Color");
- ShaderInput *distance_in = input("Distance");
- ShaderInput *normal_in = input("Normal");
- ShaderOutput *color_out = output("Color");
- ShaderOutput *ao_out = output("AO");
+ ShaderInput *color_in = input("Color");
+ ShaderInput *distance_in = input("Distance");
+ ShaderInput *normal_in = input("Normal");
+ ShaderOutput *color_out = output("Color");
+ ShaderOutput *ao_out = output("AO");
- int flags = (inside? NODE_AO_INSIDE : 0) | (only_local? NODE_AO_ONLY_LOCAL : 0);
+ int flags = (inside ? NODE_AO_INSIDE : 0) | (only_local ? NODE_AO_ONLY_LOCAL : 0);
- if(!distance_in->link && distance == 0.0f) {
- flags |= NODE_AO_GLOBAL_RADIUS;
- }
+ if (!distance_in->link && distance == 0.0f) {
+ flags |= NODE_AO_GLOBAL_RADIUS;
+ }
- compiler.add_node(NODE_AMBIENT_OCCLUSION,
- compiler.encode_uchar4(flags,
- compiler.stack_assign_if_linked(distance_in),
- compiler.stack_assign_if_linked(normal_in),
- compiler.stack_assign(ao_out)),
- compiler.encode_uchar4(compiler.stack_assign(color_in),
- compiler.stack_assign(color_out),
- samples),
- __float_as_uint(distance));
+ compiler.add_node(NODE_AMBIENT_OCCLUSION,
+ compiler.encode_uchar4(flags,
+ compiler.stack_assign_if_linked(distance_in),
+ compiler.stack_assign_if_linked(normal_in),
+ compiler.stack_assign(ao_out)),
+ compiler.encode_uchar4(compiler.stack_assign(color_in),
+ compiler.stack_assign(color_out),
+ samples),
+ __float_as_uint(distance));
}
-void AmbientOcclusionNode::compile(OSLCompiler& compiler)
+void AmbientOcclusionNode::compile(OSLCompiler &compiler)
{
- compiler.parameter(this, "samples");
- compiler.parameter(this, "inside");
- compiler.parameter(this, "only_local");
- compiler.add(this, "node_ambient_occlusion");
+ compiler.parameter(this, "samples");
+ compiler.parameter(this, "inside");
+ compiler.parameter(this, "only_local");
+ compiler.add(this, "node_ambient_occlusion");
}
/* Volume Closure */
-VolumeNode::VolumeNode(const NodeType *node_type)
-: ShaderNode(node_type)
+VolumeNode::VolumeNode(const NodeType *node_type) : ShaderNode(node_type)
{
- closure = CLOSURE_VOLUME_HENYEY_GREENSTEIN_ID;
+ closure = CLOSURE_VOLUME_HENYEY_GREENSTEIN_ID;
}
-void VolumeNode::compile(SVMCompiler& compiler, ShaderInput *param1, ShaderInput *param2)
+void VolumeNode::compile(SVMCompiler &compiler, ShaderInput *param1, ShaderInput *param2)
{
- ShaderInput *color_in = input("Color");
+ ShaderInput *color_in = input("Color");
- if(color_in->link)
- compiler.add_node(NODE_CLOSURE_WEIGHT, compiler.stack_assign(color_in));
- else
- compiler.add_node(NODE_CLOSURE_SET_WEIGHT, color);
+ if (color_in->link)
+ compiler.add_node(NODE_CLOSURE_WEIGHT, compiler.stack_assign(color_in));
+ else
+ compiler.add_node(NODE_CLOSURE_SET_WEIGHT, color);
- compiler.add_node(NODE_CLOSURE_VOLUME,
- compiler.encode_uchar4(closure,
- (param1)? compiler.stack_assign(param1): SVM_STACK_INVALID,
- (param2)? compiler.stack_assign(param2): SVM_STACK_INVALID,
- compiler.closure_mix_weight_offset()),
- __float_as_int((param1)? get_float(param1->socket_type): 0.0f),
- __float_as_int((param2)? get_float(param2->socket_type): 0.0f));
+ compiler.add_node(
+ NODE_CLOSURE_VOLUME,
+ compiler.encode_uchar4(closure,
+ (param1) ? compiler.stack_assign(param1) : SVM_STACK_INVALID,
+ (param2) ? compiler.stack_assign(param2) : SVM_STACK_INVALID,
+ compiler.closure_mix_weight_offset()),
+ __float_as_int((param1) ? get_float(param1->socket_type) : 0.0f),
+ __float_as_int((param2) ? get_float(param2->socket_type) : 0.0f));
}
-void VolumeNode::compile(SVMCompiler& compiler)
+void VolumeNode::compile(SVMCompiler &compiler)
{
- compile(compiler, NULL, NULL);
+ compile(compiler, NULL, NULL);
}
-void VolumeNode::compile(OSLCompiler& /*compiler*/)
+void VolumeNode::compile(OSLCompiler & /*compiler*/)
{
- assert(0);
+ assert(0);
}
/* Absorption Volume Closure */
NODE_DEFINE(AbsorptionVolumeNode)
{
- NodeType* type = NodeType::add("absorption_volume", create, NodeType::SHADER);
+ NodeType *type = NodeType::add("absorption_volume", create, NodeType::SHADER);
- SOCKET_IN_COLOR(color, "Color", make_float3(0.8f, 0.8f, 0.8f));
- SOCKET_IN_FLOAT(density, "Density", 1.0f);
- SOCKET_IN_FLOAT(volume_mix_weight, "VolumeMixWeight", 0.0f, SocketType::SVM_INTERNAL);
+ SOCKET_IN_COLOR(color, "Color", make_float3(0.8f, 0.8f, 0.8f));
+ SOCKET_IN_FLOAT(density, "Density", 1.0f);
+ SOCKET_IN_FLOAT(volume_mix_weight, "VolumeMixWeight", 0.0f, SocketType::SVM_INTERNAL);
- SOCKET_OUT_CLOSURE(volume, "Volume");
+ SOCKET_OUT_CLOSURE(volume, "Volume");
- return type;
+ return type;
}
-AbsorptionVolumeNode::AbsorptionVolumeNode()
-: VolumeNode(node_type)
+AbsorptionVolumeNode::AbsorptionVolumeNode() : VolumeNode(node_type)
{
- closure = CLOSURE_VOLUME_ABSORPTION_ID;
+ closure = CLOSURE_VOLUME_ABSORPTION_ID;
}
-void AbsorptionVolumeNode::compile(SVMCompiler& compiler)
+void AbsorptionVolumeNode::compile(SVMCompiler &compiler)
{
- VolumeNode::compile(compiler, input("Density"), NULL);
+ VolumeNode::compile(compiler, input("Density"), NULL);
}
-void AbsorptionVolumeNode::compile(OSLCompiler& compiler)
+void AbsorptionVolumeNode::compile(OSLCompiler &compiler)
{
- compiler.add(this, "node_absorption_volume");
+ compiler.add(this, "node_absorption_volume");
}
/* Scatter Volume Closure */
NODE_DEFINE(ScatterVolumeNode)
{
- NodeType* type = NodeType::add("scatter_volume", create, NodeType::SHADER);
+ NodeType *type = NodeType::add("scatter_volume", create, NodeType::SHADER);
- SOCKET_IN_COLOR(color, "Color", make_float3(0.8f, 0.8f, 0.8f));
- SOCKET_IN_FLOAT(density, "Density", 1.0f);
- SOCKET_IN_FLOAT(anisotropy, "Anisotropy", 0.0f);
- SOCKET_IN_FLOAT(volume_mix_weight, "VolumeMixWeight", 0.0f, SocketType::SVM_INTERNAL);
+ SOCKET_IN_COLOR(color, "Color", make_float3(0.8f, 0.8f, 0.8f));
+ SOCKET_IN_FLOAT(density, "Density", 1.0f);
+ SOCKET_IN_FLOAT(anisotropy, "Anisotropy", 0.0f);
+ SOCKET_IN_FLOAT(volume_mix_weight, "VolumeMixWeight", 0.0f, SocketType::SVM_INTERNAL);
- SOCKET_OUT_CLOSURE(volume, "Volume");
+ SOCKET_OUT_CLOSURE(volume, "Volume");
- return type;
+ return type;
}
-ScatterVolumeNode::ScatterVolumeNode()
-: VolumeNode(node_type)
+ScatterVolumeNode::ScatterVolumeNode() : VolumeNode(node_type)
{
- closure = CLOSURE_VOLUME_HENYEY_GREENSTEIN_ID;
+ closure = CLOSURE_VOLUME_HENYEY_GREENSTEIN_ID;
}
-void ScatterVolumeNode::compile(SVMCompiler& compiler)
+void ScatterVolumeNode::compile(SVMCompiler &compiler)
{
- VolumeNode::compile(compiler, input("Density"), input("Anisotropy"));
+ VolumeNode::compile(compiler, input("Density"), input("Anisotropy"));
}
-void ScatterVolumeNode::compile(OSLCompiler& compiler)
+void ScatterVolumeNode::compile(OSLCompiler &compiler)
{
- compiler.add(this, "node_scatter_volume");
+ compiler.add(this, "node_scatter_volume");
}
/* Principled Volume Closure */
NODE_DEFINE(PrincipledVolumeNode)
{
- NodeType* type = NodeType::add("principled_volume", create, NodeType::SHADER);
+ NodeType *type = NodeType::add("principled_volume", create, NodeType::SHADER);
- SOCKET_IN_STRING(density_attribute, "Density Attribute", ustring());
- SOCKET_IN_STRING(color_attribute, "Color Attribute", ustring());
- SOCKET_IN_STRING(temperature_attribute, "Temperature Attribute", ustring());
+ SOCKET_IN_STRING(density_attribute, "Density Attribute", ustring());
+ SOCKET_IN_STRING(color_attribute, "Color Attribute", ustring());
+ SOCKET_IN_STRING(temperature_attribute, "Temperature Attribute", ustring());
- SOCKET_IN_COLOR(color, "Color", make_float3(0.5f, 0.5f, 0.5f));
- SOCKET_IN_FLOAT(density, "Density", 1.0f);
- SOCKET_IN_FLOAT(anisotropy, "Anisotropy", 0.0f);
- SOCKET_IN_COLOR(absorption_color, "Absorption Color", make_float3(0.0f, 0.0f, 0.0f));
- SOCKET_IN_FLOAT(emission_strength, "Emission Strength", 0.0f);
- SOCKET_IN_COLOR(emission_color, "Emission Color", make_float3(1.0f, 1.0f, 1.0f));
- SOCKET_IN_FLOAT(blackbody_intensity, "Blackbody Intensity", 0.0f);
- SOCKET_IN_COLOR(blackbody_tint, "Blackbody Tint", make_float3(1.0f, 1.0f, 1.0f));
- SOCKET_IN_FLOAT(temperature, "Temperature", 1500.0f);
- SOCKET_IN_FLOAT(volume_mix_weight, "VolumeMixWeight", 0.0f, SocketType::SVM_INTERNAL);
+ SOCKET_IN_COLOR(color, "Color", make_float3(0.5f, 0.5f, 0.5f));
+ SOCKET_IN_FLOAT(density, "Density", 1.0f);
+ SOCKET_IN_FLOAT(anisotropy, "Anisotropy", 0.0f);
+ SOCKET_IN_COLOR(absorption_color, "Absorption Color", make_float3(0.0f, 0.0f, 0.0f));
+ SOCKET_IN_FLOAT(emission_strength, "Emission Strength", 0.0f);
+ SOCKET_IN_COLOR(emission_color, "Emission Color", make_float3(1.0f, 1.0f, 1.0f));
+ SOCKET_IN_FLOAT(blackbody_intensity, "Blackbody Intensity", 0.0f);
+ SOCKET_IN_COLOR(blackbody_tint, "Blackbody Tint", make_float3(1.0f, 1.0f, 1.0f));
+ SOCKET_IN_FLOAT(temperature, "Temperature", 1500.0f);
+ SOCKET_IN_FLOAT(volume_mix_weight, "VolumeMixWeight", 0.0f, SocketType::SVM_INTERNAL);
- SOCKET_OUT_CLOSURE(volume, "Volume");
+ SOCKET_OUT_CLOSURE(volume, "Volume");
- return type;
+ return type;
}
-PrincipledVolumeNode::PrincipledVolumeNode()
-: VolumeNode(node_type)
+PrincipledVolumeNode::PrincipledVolumeNode() : VolumeNode(node_type)
{
- closure = CLOSURE_VOLUME_HENYEY_GREENSTEIN_ID;
+ closure = CLOSURE_VOLUME_HENYEY_GREENSTEIN_ID;
}
void PrincipledVolumeNode::attributes(Shader *shader, AttributeRequestSet *attributes)
{
- if(shader->has_volume) {
- ShaderInput *density_in = input("Density");
- ShaderInput *blackbody_in = input("Blackbody Intensity");
-
- if(density_in->link || density > 0.0f) {
- attributes->add_standard(density_attribute);
- attributes->add_standard(color_attribute);
- }
-
- if(blackbody_in->link || blackbody_intensity > 0.0f) {
- attributes->add_standard(temperature_attribute);
- }
-
- attributes->add(ATTR_STD_GENERATED_TRANSFORM);
- }
-
- ShaderNode::attributes(shader, attributes);
-}
-
-void PrincipledVolumeNode::compile(SVMCompiler& compiler)
-{
- ShaderInput *color_in = input("Color");
- ShaderInput *density_in = input("Density");
- ShaderInput *anisotropy_in = input("Anisotropy");
- ShaderInput *absorption_color_in = input("Absorption Color");
- ShaderInput *emission_in = input("Emission Strength");
- ShaderInput *emission_color_in = input("Emission Color");
- ShaderInput *blackbody_in = input("Blackbody Intensity");
- ShaderInput *blackbody_tint_in = input("Blackbody Tint");
- ShaderInput *temperature_in = input("Temperature");
-
- if(color_in->link)
- compiler.add_node(NODE_CLOSURE_WEIGHT, compiler.stack_assign(color_in));
- else
- compiler.add_node(NODE_CLOSURE_SET_WEIGHT, color);
-
- compiler.add_node(NODE_PRINCIPLED_VOLUME,
- compiler.encode_uchar4(
- compiler.stack_assign_if_linked(density_in),
- compiler.stack_assign_if_linked(anisotropy_in),
- compiler.stack_assign(absorption_color_in),
- compiler.closure_mix_weight_offset()),
- compiler.encode_uchar4(
- compiler.stack_assign_if_linked(emission_in),
- compiler.stack_assign(emission_color_in),
- compiler.stack_assign_if_linked(blackbody_in),
- compiler.stack_assign(temperature_in)),
- compiler.stack_assign(blackbody_tint_in));
-
- int attr_density = compiler.attribute_standard(density_attribute);
- int attr_color = compiler.attribute_standard(color_attribute);
- int attr_temperature = compiler.attribute_standard(temperature_attribute);
-
- compiler.add_node(
- __float_as_int(density),
- __float_as_int(anisotropy),
- __float_as_int(emission_strength),
- __float_as_int(blackbody_intensity));
-
- compiler.add_node(
- attr_density,
- attr_color,
- attr_temperature);
-}
-
-void PrincipledVolumeNode::compile(OSLCompiler& compiler)
-{
- if(Attribute::name_standard(density_attribute.c_str())) {
- density_attribute = ustring("geom:" + density_attribute.string());
- }
- if(Attribute::name_standard(color_attribute.c_str())) {
- color_attribute = ustring("geom:" + color_attribute.string());
- }
- if(Attribute::name_standard(temperature_attribute.c_str())) {
- temperature_attribute = ustring("geom:" + temperature_attribute.string());
- }
-
- compiler.add(this, "node_principled_volume");
+ if (shader->has_volume) {
+ ShaderInput *density_in = input("Density");
+ ShaderInput *blackbody_in = input("Blackbody Intensity");
+
+ if (density_in->link || density > 0.0f) {
+ attributes->add_standard(density_attribute);
+ attributes->add_standard(color_attribute);
+ }
+
+ if (blackbody_in->link || blackbody_intensity > 0.0f) {
+ attributes->add_standard(temperature_attribute);
+ }
+
+ attributes->add(ATTR_STD_GENERATED_TRANSFORM);
+ }
+
+ ShaderNode::attributes(shader, attributes);
+}
+
+void PrincipledVolumeNode::compile(SVMCompiler &compiler)
+{
+ ShaderInput *color_in = input("Color");
+ ShaderInput *density_in = input("Density");
+ ShaderInput *anisotropy_in = input("Anisotropy");
+ ShaderInput *absorption_color_in = input("Absorption Color");
+ ShaderInput *emission_in = input("Emission Strength");
+ ShaderInput *emission_color_in = input("Emission Color");
+ ShaderInput *blackbody_in = input("Blackbody Intensity");
+ ShaderInput *blackbody_tint_in = input("Blackbody Tint");
+ ShaderInput *temperature_in = input("Temperature");
+
+ if (color_in->link)
+ compiler.add_node(NODE_CLOSURE_WEIGHT, compiler.stack_assign(color_in));
+ else
+ compiler.add_node(NODE_CLOSURE_SET_WEIGHT, color);
+
+ compiler.add_node(NODE_PRINCIPLED_VOLUME,
+ compiler.encode_uchar4(compiler.stack_assign_if_linked(density_in),
+ compiler.stack_assign_if_linked(anisotropy_in),
+ compiler.stack_assign(absorption_color_in),
+ compiler.closure_mix_weight_offset()),
+ compiler.encode_uchar4(compiler.stack_assign_if_linked(emission_in),
+ compiler.stack_assign(emission_color_in),
+ compiler.stack_assign_if_linked(blackbody_in),
+ compiler.stack_assign(temperature_in)),
+ compiler.stack_assign(blackbody_tint_in));
+
+ int attr_density = compiler.attribute_standard(density_attribute);
+ int attr_color = compiler.attribute_standard(color_attribute);
+ int attr_temperature = compiler.attribute_standard(temperature_attribute);
+
+ compiler.add_node(__float_as_int(density),
+ __float_as_int(anisotropy),
+ __float_as_int(emission_strength),
+ __float_as_int(blackbody_intensity));
+
+ compiler.add_node(attr_density, attr_color, attr_temperature);
+}
+
+void PrincipledVolumeNode::compile(OSLCompiler &compiler)
+{
+ if (Attribute::name_standard(density_attribute.c_str())) {
+ density_attribute = ustring("geom:" + density_attribute.string());
+ }
+ if (Attribute::name_standard(color_attribute.c_str())) {
+ color_attribute = ustring("geom:" + color_attribute.string());
+ }
+ if (Attribute::name_standard(temperature_attribute.c_str())) {
+ temperature_attribute = ustring("geom:" + temperature_attribute.string());
+ }
+
+ compiler.add(this, "node_principled_volume");
}
/* Principled Hair BSDF Closure */
NODE_DEFINE(PrincipledHairBsdfNode)
{
- NodeType* type = NodeType::add("principled_hair_bsdf", create, NodeType::SHADER);
+ NodeType *type = NodeType::add("principled_hair_bsdf", create, NodeType::SHADER);
- /* Color parametrization specified as enum. */
- static NodeEnum parametrization_enum;
- parametrization_enum.insert("Direct coloring", NODE_PRINCIPLED_HAIR_REFLECTANCE);
- parametrization_enum.insert("Melanin concentration", NODE_PRINCIPLED_HAIR_PIGMENT_CONCENTRATION);
- parametrization_enum.insert("Absorption coefficient", NODE_PRINCIPLED_HAIR_DIRECT_ABSORPTION);
- SOCKET_ENUM(parametrization, "Parametrization", parametrization_enum, NODE_PRINCIPLED_HAIR_REFLECTANCE);
+ /* Color parametrization specified as enum. */
+ static NodeEnum parametrization_enum;
+ parametrization_enum.insert("Direct coloring", NODE_PRINCIPLED_HAIR_REFLECTANCE);
+ parametrization_enum.insert("Melanin concentration", NODE_PRINCIPLED_HAIR_PIGMENT_CONCENTRATION);
+ parametrization_enum.insert("Absorption coefficient", NODE_PRINCIPLED_HAIR_DIRECT_ABSORPTION);
+ SOCKET_ENUM(
+ parametrization, "Parametrization", parametrization_enum, NODE_PRINCIPLED_HAIR_REFLECTANCE);
- /* Initialize sockets to their default values. */
- SOCKET_IN_COLOR(color, "Color", make_float3(0.017513f, 0.005763f, 0.002059f));
- SOCKET_IN_FLOAT(melanin, "Melanin", 0.8f);
- SOCKET_IN_FLOAT(melanin_redness, "Melanin Redness", 1.0f);
- SOCKET_IN_COLOR(tint, "Tint", make_float3(1.f, 1.f, 1.f));
- SOCKET_IN_VECTOR(absorption_coefficient, "Absorption Coefficient", make_float3(0.245531f, 0.52f, 1.365f), SocketType::VECTOR);
+ /* Initialize sockets to their default values. */
+ SOCKET_IN_COLOR(color, "Color", make_float3(0.017513f, 0.005763f, 0.002059f));
+ SOCKET_IN_FLOAT(melanin, "Melanin", 0.8f);
+ SOCKET_IN_FLOAT(melanin_redness, "Melanin Redness", 1.0f);
+ SOCKET_IN_COLOR(tint, "Tint", make_float3(1.f, 1.f, 1.f));
+ SOCKET_IN_VECTOR(absorption_coefficient,
+ "Absorption Coefficient",
+ make_float3(0.245531f, 0.52f, 1.365f),
+ SocketType::VECTOR);
- SOCKET_IN_FLOAT(offset, "Offset", 2.f*M_PI_F/180.f);
- SOCKET_IN_FLOAT(roughness, "Roughness", 0.3f);
- SOCKET_IN_FLOAT(radial_roughness, "Radial Roughness", 0.3f);
- SOCKET_IN_FLOAT(coat, "Coat", 0.0f);
- SOCKET_IN_FLOAT(ior, "IOR", 1.55f);
+ SOCKET_IN_FLOAT(offset, "Offset", 2.f * M_PI_F / 180.f);
+ SOCKET_IN_FLOAT(roughness, "Roughness", 0.3f);
+ SOCKET_IN_FLOAT(radial_roughness, "Radial Roughness", 0.3f);
+ SOCKET_IN_FLOAT(coat, "Coat", 0.0f);
+ SOCKET_IN_FLOAT(ior, "IOR", 1.55f);
- SOCKET_IN_FLOAT(random_roughness, "Random Roughness", 0.0f);
- SOCKET_IN_FLOAT(random_color, "Random Color", 0.0f);
- SOCKET_IN_FLOAT(random, "Random", 0.0f);
+ SOCKET_IN_FLOAT(random_roughness, "Random Roughness", 0.0f);
+ SOCKET_IN_FLOAT(random_color, "Random Color", 0.0f);
+ SOCKET_IN_FLOAT(random, "Random", 0.0f);
- SOCKET_IN_NORMAL(normal, "Normal", make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_NORMAL);
- SOCKET_IN_FLOAT(surface_mix_weight, "SurfaceMixWeight", 0.0f, SocketType::SVM_INTERNAL);
+ SOCKET_IN_NORMAL(normal, "Normal", make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_NORMAL);
+ SOCKET_IN_FLOAT(surface_mix_weight, "SurfaceMixWeight", 0.0f, SocketType::SVM_INTERNAL);
- SOCKET_OUT_CLOSURE(BSDF, "BSDF");
+ SOCKET_OUT_CLOSURE(BSDF, "BSDF");
- return type;
+ return type;
}
-PrincipledHairBsdfNode::PrincipledHairBsdfNode()
-: BsdfBaseNode(node_type)
+PrincipledHairBsdfNode::PrincipledHairBsdfNode() : BsdfBaseNode(node_type)
{
- closure = CLOSURE_BSDF_HAIR_PRINCIPLED_ID;
+ closure = CLOSURE_BSDF_HAIR_PRINCIPLED_ID;
}
/* Enable retrieving Hair Info -> Random if Random isn't linked. */
void PrincipledHairBsdfNode::attributes(Shader *shader, AttributeRequestSet *attributes)
{
- if(!input("Random")->link) {
- attributes->add(ATTR_STD_CURVE_RANDOM);
- }
- ShaderNode::attributes(shader, attributes);
+ if (!input("Random")->link) {
+ attributes->add(ATTR_STD_CURVE_RANDOM);
+ }
+ ShaderNode::attributes(shader, attributes);
}
/* Prepares the input data for the SVM shader. */
-void PrincipledHairBsdfNode::compile(SVMCompiler& compiler)
-{
- compiler.add_node(NODE_CLOSURE_SET_WEIGHT, make_float3(1.0f, 1.0f, 1.0f));
-
- ShaderInput *roughness_in = input("Roughness");
- ShaderInput *radial_roughness_in = input("Radial Roughness");
- ShaderInput *random_roughness_in = input("Random Roughness");
- ShaderInput *offset_in = input("Offset");
- ShaderInput *coat_in = input("Coat");
- ShaderInput *ior_in = input("IOR");
- ShaderInput *melanin_in = input("Melanin");
- ShaderInput *melanin_redness_in = input("Melanin Redness");
- ShaderInput *random_color_in = input("Random Color");
-
- int color_ofs = compiler.stack_assign(input("Color"));
- int tint_ofs = compiler.stack_assign(input("Tint"));
- int absorption_coefficient_ofs = compiler.stack_assign(input("Absorption Coefficient"));
-
- ShaderInput *random_in = input("Random");
- int attr_random = random_in->link ? SVM_STACK_INVALID : compiler.attribute(ATTR_STD_CURVE_RANDOM);
-
- /* Encode all parameters into data nodes. */
- compiler.add_node(NODE_CLOSURE_BSDF,
- /* Socket IDs can be packed 4 at a time into a single data packet */
- compiler.encode_uchar4(closure,
- compiler.stack_assign_if_linked(roughness_in),
- compiler.stack_assign_if_linked(radial_roughness_in),
- compiler.closure_mix_weight_offset()),
- /* The rest are stored as unsigned integers */
- __float_as_uint(roughness),
- __float_as_uint(radial_roughness));
-
- compiler.add_node(compiler.stack_assign_if_linked(input("Normal")),
- compiler.encode_uchar4(
- compiler.stack_assign_if_linked(offset_in),
- compiler.stack_assign_if_linked(ior_in),
- color_ofs,
- parametrization),
- __float_as_uint(offset),
- __float_as_uint(ior));
-
- compiler.add_node(
- compiler.encode_uchar4(
- compiler.stack_assign_if_linked(coat_in),
- compiler.stack_assign_if_linked(melanin_in),
- compiler.stack_assign_if_linked(melanin_redness_in),
- absorption_coefficient_ofs),
- __float_as_uint(coat),
- __float_as_uint(melanin),
- __float_as_uint(melanin_redness));
-
- compiler.add_node(
- compiler.encode_uchar4(
- tint_ofs,
- compiler.stack_assign_if_linked(random_in),
- compiler.stack_assign_if_linked(random_color_in),
- compiler.stack_assign_if_linked(random_roughness_in)),
- __float_as_uint(random),
- __float_as_uint(random_color),
- __float_as_uint(random_roughness));
-
- compiler.add_node(
- compiler.encode_uchar4(
- SVM_STACK_INVALID,
- SVM_STACK_INVALID,
- SVM_STACK_INVALID,
- SVM_STACK_INVALID),
- attr_random,
- SVM_STACK_INVALID,
- SVM_STACK_INVALID);
+void PrincipledHairBsdfNode::compile(SVMCompiler &compiler)
+{
+ compiler.add_node(NODE_CLOSURE_SET_WEIGHT, make_float3(1.0f, 1.0f, 1.0f));
+
+ ShaderInput *roughness_in = input("Roughness");
+ ShaderInput *radial_roughness_in = input("Radial Roughness");
+ ShaderInput *random_roughness_in = input("Random Roughness");
+ ShaderInput *offset_in = input("Offset");
+ ShaderInput *coat_in = input("Coat");
+ ShaderInput *ior_in = input("IOR");
+ ShaderInput *melanin_in = input("Melanin");
+ ShaderInput *melanin_redness_in = input("Melanin Redness");
+ ShaderInput *random_color_in = input("Random Color");
+
+ int color_ofs = compiler.stack_assign(input("Color"));
+ int tint_ofs = compiler.stack_assign(input("Tint"));
+ int absorption_coefficient_ofs = compiler.stack_assign(input("Absorption Coefficient"));
+
+ ShaderInput *random_in = input("Random");
+ int attr_random = random_in->link ? SVM_STACK_INVALID :
+ compiler.attribute(ATTR_STD_CURVE_RANDOM);
+
+ /* Encode all parameters into data nodes. */
+ compiler.add_node(NODE_CLOSURE_BSDF,
+ /* Socket IDs can be packed 4 at a time into a single data packet */
+ compiler.encode_uchar4(closure,
+ compiler.stack_assign_if_linked(roughness_in),
+ compiler.stack_assign_if_linked(radial_roughness_in),
+ compiler.closure_mix_weight_offset()),
+ /* The rest are stored as unsigned integers */
+ __float_as_uint(roughness),
+ __float_as_uint(radial_roughness));
+
+ compiler.add_node(compiler.stack_assign_if_linked(input("Normal")),
+ compiler.encode_uchar4(compiler.stack_assign_if_linked(offset_in),
+ compiler.stack_assign_if_linked(ior_in),
+ color_ofs,
+ parametrization),
+ __float_as_uint(offset),
+ __float_as_uint(ior));
+
+ compiler.add_node(compiler.encode_uchar4(compiler.stack_assign_if_linked(coat_in),
+ compiler.stack_assign_if_linked(melanin_in),
+ compiler.stack_assign_if_linked(melanin_redness_in),
+ absorption_coefficient_ofs),
+ __float_as_uint(coat),
+ __float_as_uint(melanin),
+ __float_as_uint(melanin_redness));
+
+ compiler.add_node(compiler.encode_uchar4(tint_ofs,
+ compiler.stack_assign_if_linked(random_in),
+ compiler.stack_assign_if_linked(random_color_in),
+ compiler.stack_assign_if_linked(random_roughness_in)),
+ __float_as_uint(random),
+ __float_as_uint(random_color),
+ __float_as_uint(random_roughness));
+
+ compiler.add_node(
+ compiler.encode_uchar4(
+ SVM_STACK_INVALID, SVM_STACK_INVALID, SVM_STACK_INVALID, SVM_STACK_INVALID),
+ attr_random,
+ SVM_STACK_INVALID,
+ SVM_STACK_INVALID);
}
/* Prepares the input data for the OSL shader. */
-void PrincipledHairBsdfNode::compile(OSLCompiler& compiler)
+void PrincipledHairBsdfNode::compile(OSLCompiler &compiler)
{
- compiler.parameter(this, "parametrization");
- compiler.add(this, "node_principled_hair_bsdf");
+ compiler.parameter(this, "parametrization");
+ compiler.add(this, "node_principled_hair_bsdf");
}
/* Hair BSDF Closure */
NODE_DEFINE(HairBsdfNode)
{
- NodeType* type = NodeType::add("hair_bsdf", create, NodeType::SHADER);
+ NodeType *type = NodeType::add("hair_bsdf", create, NodeType::SHADER);
- SOCKET_IN_COLOR(color, "Color", make_float3(0.8f, 0.8f, 0.8f));
- SOCKET_IN_NORMAL(normal, "Normal", make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_NORMAL);
- SOCKET_IN_FLOAT(surface_mix_weight, "SurfaceMixWeight", 0.0f, SocketType::SVM_INTERNAL);
+ SOCKET_IN_COLOR(color, "Color", make_float3(0.8f, 0.8f, 0.8f));
+ SOCKET_IN_NORMAL(normal, "Normal", make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_NORMAL);
+ SOCKET_IN_FLOAT(surface_mix_weight, "SurfaceMixWeight", 0.0f, SocketType::SVM_INTERNAL);
- static NodeEnum component_enum;
- component_enum.insert("reflection", CLOSURE_BSDF_HAIR_REFLECTION_ID);
- component_enum.insert("transmission", CLOSURE_BSDF_HAIR_TRANSMISSION_ID);
- SOCKET_ENUM(component, "Component", component_enum, CLOSURE_BSDF_HAIR_REFLECTION_ID);
- SOCKET_IN_FLOAT(offset, "Offset", 0.0f);
- SOCKET_IN_FLOAT(roughness_u, "RoughnessU", 0.2f);
- SOCKET_IN_FLOAT(roughness_v, "RoughnessV", 0.2f);
- SOCKET_IN_VECTOR(tangent, "Tangent", make_float3(0.0f, 0.0f, 0.0f));
+ static NodeEnum component_enum;
+ component_enum.insert("reflection", CLOSURE_BSDF_HAIR_REFLECTION_ID);
+ component_enum.insert("transmission", CLOSURE_BSDF_HAIR_TRANSMISSION_ID);
+ SOCKET_ENUM(component, "Component", component_enum, CLOSURE_BSDF_HAIR_REFLECTION_ID);
+ SOCKET_IN_FLOAT(offset, "Offset", 0.0f);
+ SOCKET_IN_FLOAT(roughness_u, "RoughnessU", 0.2f);
+ SOCKET_IN_FLOAT(roughness_v, "RoughnessV", 0.2f);
+ SOCKET_IN_VECTOR(tangent, "Tangent", make_float3(0.0f, 0.0f, 0.0f));
- SOCKET_OUT_CLOSURE(BSDF, "BSDF");
+ SOCKET_OUT_CLOSURE(BSDF, "BSDF");
- return type;
+ return type;
}
-HairBsdfNode::HairBsdfNode()
-: BsdfNode(node_type)
+HairBsdfNode::HairBsdfNode() : BsdfNode(node_type)
{
- closure = CLOSURE_BSDF_HAIR_REFLECTION_ID;
+ closure = CLOSURE_BSDF_HAIR_REFLECTION_ID;
}
-void HairBsdfNode::compile(SVMCompiler& compiler)
+void HairBsdfNode::compile(SVMCompiler &compiler)
{
- closure = component;
+ closure = component;
- BsdfNode::compile(compiler, input("RoughnessU"), input("RoughnessV"), input("Offset"));
+ BsdfNode::compile(compiler, input("RoughnessU"), input("RoughnessV"), input("Offset"));
}
-void HairBsdfNode::compile(OSLCompiler& compiler)
+void HairBsdfNode::compile(OSLCompiler &compiler)
{
- compiler.parameter(this, "component");
- compiler.add(this, "node_hair_bsdf");
+ compiler.parameter(this, "component");
+ compiler.add(this, "node_hair_bsdf");
}
/* Geometry */
NODE_DEFINE(GeometryNode)
{
- NodeType* type = NodeType::add("geometry", create, NodeType::SHADER);
+ NodeType *type = NodeType::add("geometry", create, NodeType::SHADER);
- SOCKET_IN_NORMAL(normal_osl, "NormalIn", make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_NORMAL | SocketType::OSL_INTERNAL);
+ SOCKET_IN_NORMAL(normal_osl,
+ "NormalIn",
+ make_float3(0.0f, 0.0f, 0.0f),
+ SocketType::LINK_NORMAL | SocketType::OSL_INTERNAL);
- SOCKET_OUT_POINT(position, "Position");
- SOCKET_OUT_NORMAL(normal, "Normal");
- SOCKET_OUT_NORMAL(tangent, "Tangent");
- SOCKET_OUT_NORMAL(true_normal, "True Normal");
- SOCKET_OUT_VECTOR(incoming, "Incoming");
- SOCKET_OUT_POINT(parametric, "Parametric");
- SOCKET_OUT_FLOAT(backfacing, "Backfacing");
- SOCKET_OUT_FLOAT(pointiness, "Pointiness");
+ SOCKET_OUT_POINT(position, "Position");
+ SOCKET_OUT_NORMAL(normal, "Normal");
+ SOCKET_OUT_NORMAL(tangent, "Tangent");
+ SOCKET_OUT_NORMAL(true_normal, "True Normal");
+ SOCKET_OUT_VECTOR(incoming, "Incoming");
+ SOCKET_OUT_POINT(parametric, "Parametric");
+ SOCKET_OUT_FLOAT(backfacing, "Backfacing");
+ SOCKET_OUT_FLOAT(pointiness, "Pointiness");
- return type;
+ return type;
}
-GeometryNode::GeometryNode()
-: ShaderNode(node_type)
+GeometryNode::GeometryNode() : ShaderNode(node_type)
{
- special_type = SHADER_SPECIAL_TYPE_GEOMETRY;
+ special_type = SHADER_SPECIAL_TYPE_GEOMETRY;
}
void GeometryNode::attributes(Shader *shader, AttributeRequestSet *attributes)
{
- if(shader->has_surface) {
- if(!output("Tangent")->links.empty()) {
- attributes->add(ATTR_STD_GENERATED);
- }
- if(!output("Pointiness")->links.empty()) {
- attributes->add(ATTR_STD_POINTINESS);
- }
- }
-
- ShaderNode::attributes(shader, attributes);
-}
-
-void GeometryNode::compile(SVMCompiler& compiler)
-{
- ShaderOutput *out;
- ShaderNodeType geom_node = NODE_GEOMETRY;
- ShaderNodeType attr_node = NODE_ATTR;
-
- if(bump == SHADER_BUMP_DX) {
- geom_node = NODE_GEOMETRY_BUMP_DX;
- attr_node = NODE_ATTR_BUMP_DX;
- }
- else if(bump == SHADER_BUMP_DY) {
- geom_node = NODE_GEOMETRY_BUMP_DY;
- attr_node = NODE_ATTR_BUMP_DY;
- }
-
- out = output("Position");
- if(!out->links.empty()) {
- compiler.add_node(geom_node, NODE_GEOM_P, compiler.stack_assign(out));
- }
-
- out = output("Normal");
- if(!out->links.empty()) {
- compiler.add_node(geom_node, NODE_GEOM_N, compiler.stack_assign(out));
- }
-
- out = output("Tangent");
- if(!out->links.empty()) {
- compiler.add_node(geom_node, NODE_GEOM_T, compiler.stack_assign(out));
- }
-
- out = output("True Normal");
- if(!out->links.empty()) {
- compiler.add_node(geom_node, NODE_GEOM_Ng, compiler.stack_assign(out));
- }
-
- out = output("Incoming");
- if(!out->links.empty()) {
- compiler.add_node(geom_node, NODE_GEOM_I, compiler.stack_assign(out));
- }
-
- out = output("Parametric");
- if(!out->links.empty()) {
- compiler.add_node(geom_node, NODE_GEOM_uv, compiler.stack_assign(out));
- }
-
- out = output("Backfacing");
- if(!out->links.empty()) {
- compiler.add_node(NODE_LIGHT_PATH, NODE_LP_backfacing, compiler.stack_assign(out));
- }
-
- out = output("Pointiness");
- if(!out->links.empty()) {
- if(compiler.output_type() != SHADER_TYPE_VOLUME) {
- compiler.add_node(attr_node,
- ATTR_STD_POINTINESS,
- compiler.stack_assign(out),
- NODE_ATTR_FLOAT);
- }
- else {
- compiler.add_node(NODE_VALUE_F, __float_as_int(0.0f), compiler.stack_assign(out));
- }
- }
-}
-
-void GeometryNode::compile(OSLCompiler& compiler)
-{
- if(bump == SHADER_BUMP_DX)
- compiler.parameter("bump_offset", "dx");
- else if(bump == SHADER_BUMP_DY)
- compiler.parameter("bump_offset", "dy");
- else
- compiler.parameter("bump_offset", "center");
-
- compiler.add(this, "node_geometry");
+ if (shader->has_surface) {
+ if (!output("Tangent")->links.empty()) {
+ attributes->add(ATTR_STD_GENERATED);
+ }
+ if (!output("Pointiness")->links.empty()) {
+ attributes->add(ATTR_STD_POINTINESS);
+ }
+ }
+
+ ShaderNode::attributes(shader, attributes);
+}
+
+void GeometryNode::compile(SVMCompiler &compiler)
+{
+ ShaderOutput *out;
+ ShaderNodeType geom_node = NODE_GEOMETRY;
+ ShaderNodeType attr_node = NODE_ATTR;
+
+ if (bump == SHADER_BUMP_DX) {
+ geom_node = NODE_GEOMETRY_BUMP_DX;
+ attr_node = NODE_ATTR_BUMP_DX;
+ }
+ else if (bump == SHADER_BUMP_DY) {
+ geom_node = NODE_GEOMETRY_BUMP_DY;
+ attr_node = NODE_ATTR_BUMP_DY;
+ }
+
+ out = output("Position");
+ if (!out->links.empty()) {
+ compiler.add_node(geom_node, NODE_GEOM_P, compiler.stack_assign(out));
+ }
+
+ out = output("Normal");
+ if (!out->links.empty()) {
+ compiler.add_node(geom_node, NODE_GEOM_N, compiler.stack_assign(out));
+ }
+
+ out = output("Tangent");
+ if (!out->links.empty()) {
+ compiler.add_node(geom_node, NODE_GEOM_T, compiler.stack_assign(out));
+ }
+
+ out = output("True Normal");
+ if (!out->links.empty()) {
+ compiler.add_node(geom_node, NODE_GEOM_Ng, compiler.stack_assign(out));
+ }
+
+ out = output("Incoming");
+ if (!out->links.empty()) {
+ compiler.add_node(geom_node, NODE_GEOM_I, compiler.stack_assign(out));
+ }
+
+ out = output("Parametric");
+ if (!out->links.empty()) {
+ compiler.add_node(geom_node, NODE_GEOM_uv, compiler.stack_assign(out));
+ }
+
+ out = output("Backfacing");
+ if (!out->links.empty()) {
+ compiler.add_node(NODE_LIGHT_PATH, NODE_LP_backfacing, compiler.stack_assign(out));
+ }
+
+ out = output("Pointiness");
+ if (!out->links.empty()) {
+ if (compiler.output_type() != SHADER_TYPE_VOLUME) {
+ compiler.add_node(
+ attr_node, ATTR_STD_POINTINESS, compiler.stack_assign(out), NODE_ATTR_FLOAT);
+ }
+ else {
+ compiler.add_node(NODE_VALUE_F, __float_as_int(0.0f), compiler.stack_assign(out));
+ }
+ }
+}
+
+void GeometryNode::compile(OSLCompiler &compiler)
+{
+ if (bump == SHADER_BUMP_DX)
+ compiler.parameter("bump_offset", "dx");
+ else if (bump == SHADER_BUMP_DY)
+ compiler.parameter("bump_offset", "dy");
+ else
+ compiler.parameter("bump_offset", "center");
+
+ compiler.add(this, "node_geometry");
}
int GeometryNode::get_group()
{
- ShaderOutput *out;
- int result = ShaderNode::get_group();
+ ShaderOutput *out;
+ int result = ShaderNode::get_group();
- /* Backfacing uses NODE_LIGHT_PATH */
- out = output("Backfacing");
- if (!out->links.empty()) {
- result = max(result, NODE_GROUP_LEVEL_1);
- }
+ /* Backfacing uses NODE_LIGHT_PATH */
+ out = output("Backfacing");
+ if (!out->links.empty()) {
+ result = max(result, NODE_GROUP_LEVEL_1);
+ }
- return result;
+ return result;
}
/* TextureCoordinate */
NODE_DEFINE(TextureCoordinateNode)
{
- NodeType* type = NodeType::add("texture_coordinate", create, NodeType::SHADER);
+ NodeType *type = NodeType::add("texture_coordinate", create, NodeType::SHADER);
- SOCKET_BOOLEAN(from_dupli, "From Dupli", false);
- SOCKET_BOOLEAN(use_transform, "Use Transform", false);
- SOCKET_TRANSFORM(ob_tfm, "Object Transform", transform_identity());
+ SOCKET_BOOLEAN(from_dupli, "From Dupli", false);
+ SOCKET_BOOLEAN(use_transform, "Use Transform", false);
+ SOCKET_TRANSFORM(ob_tfm, "Object Transform", transform_identity());
- SOCKET_IN_NORMAL(normal_osl, "NormalIn", make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_NORMAL | SocketType::OSL_INTERNAL);
+ SOCKET_IN_NORMAL(normal_osl,
+ "NormalIn",
+ make_float3(0.0f, 0.0f, 0.0f),
+ SocketType::LINK_NORMAL | SocketType::OSL_INTERNAL);
- SOCKET_OUT_POINT(generated, "Generated");
- SOCKET_OUT_NORMAL(normal, "Normal");
- SOCKET_OUT_POINT(UV, "UV");
- SOCKET_OUT_POINT(object, "Object");
- SOCKET_OUT_POINT(camera, "Camera");
- SOCKET_OUT_POINT(window, "Window");
- SOCKET_OUT_NORMAL(reflection, "Reflection");
+ SOCKET_OUT_POINT(generated, "Generated");
+ SOCKET_OUT_NORMAL(normal, "Normal");
+ SOCKET_OUT_POINT(UV, "UV");
+ SOCKET_OUT_POINT(object, "Object");
+ SOCKET_OUT_POINT(camera, "Camera");
+ SOCKET_OUT_POINT(window, "Window");
+ SOCKET_OUT_NORMAL(reflection, "Reflection");
- return type;
+ return type;
}
-TextureCoordinateNode::TextureCoordinateNode()
-: ShaderNode(node_type)
+TextureCoordinateNode::TextureCoordinateNode() : ShaderNode(node_type)
{
}
void TextureCoordinateNode::attributes(Shader *shader, AttributeRequestSet *attributes)
{
- if(shader->has_surface) {
- if(!from_dupli) {
- if(!output("Generated")->links.empty())
- attributes->add(ATTR_STD_GENERATED);
- if(!output("UV")->links.empty())
- attributes->add(ATTR_STD_UV);
- }
- }
-
- if(shader->has_volume) {
- if(!from_dupli) {
- if(!output("Generated")->links.empty()) {
- attributes->add(ATTR_STD_GENERATED_TRANSFORM);
- }
- }
- }
-
- ShaderNode::attributes(shader, attributes);
-}
-
-void TextureCoordinateNode::compile(SVMCompiler& compiler)
-{
- ShaderOutput *out;
- ShaderNodeType texco_node = NODE_TEX_COORD;
- ShaderNodeType attr_node = NODE_ATTR;
- ShaderNodeType geom_node = NODE_GEOMETRY;
-
- if(bump == SHADER_BUMP_DX) {
- texco_node = NODE_TEX_COORD_BUMP_DX;
- attr_node = NODE_ATTR_BUMP_DX;
- geom_node = NODE_GEOMETRY_BUMP_DX;
- }
- else if(bump == SHADER_BUMP_DY) {
- texco_node = NODE_TEX_COORD_BUMP_DY;
- attr_node = NODE_ATTR_BUMP_DY;
- geom_node = NODE_GEOMETRY_BUMP_DY;
- }
-
- out = output("Generated");
- if(!out->links.empty()) {
- if(compiler.background) {
- compiler.add_node(geom_node, NODE_GEOM_P, compiler.stack_assign(out));
- }
- else {
- if(from_dupli) {
- compiler.add_node(texco_node, NODE_TEXCO_DUPLI_GENERATED, compiler.stack_assign(out));
- }
- else if(compiler.output_type() == SHADER_TYPE_VOLUME) {
- compiler.add_node(texco_node, NODE_TEXCO_VOLUME_GENERATED, compiler.stack_assign(out));
- }
- else {
- int attr = compiler.attribute(ATTR_STD_GENERATED);
- compiler.add_node(attr_node, attr, compiler.stack_assign(out), NODE_ATTR_FLOAT3);
- }
- }
- }
-
- out = output("Normal");
- if(!out->links.empty()) {
- compiler.add_node(texco_node, NODE_TEXCO_NORMAL, compiler.stack_assign(out));
- }
-
- out = output("UV");
- if(!out->links.empty()) {
- if(from_dupli) {
- compiler.add_node(texco_node, NODE_TEXCO_DUPLI_UV, compiler.stack_assign(out));
- }
- else {
- int attr = compiler.attribute(ATTR_STD_UV);
- compiler.add_node(attr_node, attr, compiler.stack_assign(out), NODE_ATTR_FLOAT3);
- }
- }
-
- out = output("Object");
- if(!out->links.empty()) {
- compiler.add_node(texco_node, NODE_TEXCO_OBJECT, compiler.stack_assign(out), use_transform);
- if(use_transform) {
- Transform ob_itfm = transform_inverse(ob_tfm);
- compiler.add_node(ob_itfm.x);
- compiler.add_node(ob_itfm.y);
- compiler.add_node(ob_itfm.z);
- }
- }
-
- out = output("Camera");
- if(!out->links.empty()) {
- compiler.add_node(texco_node, NODE_TEXCO_CAMERA, compiler.stack_assign(out));
- }
-
- out = output("Window");
- if(!out->links.empty()) {
- compiler.add_node(texco_node, NODE_TEXCO_WINDOW, compiler.stack_assign(out));
- }
-
- out = output("Reflection");
- if(!out->links.empty()) {
- if(compiler.background) {
- compiler.add_node(geom_node, NODE_GEOM_I, compiler.stack_assign(out));
- }
- else {
- compiler.add_node(texco_node, NODE_TEXCO_REFLECTION, compiler.stack_assign(out));
- }
- }
-}
-
-void TextureCoordinateNode::compile(OSLCompiler& compiler)
-{
- if(bump == SHADER_BUMP_DX)
- compiler.parameter("bump_offset", "dx");
- else if(bump == SHADER_BUMP_DY)
- compiler.parameter("bump_offset", "dy");
- else
- compiler.parameter("bump_offset", "center");
-
- if(compiler.background)
- compiler.parameter("is_background", true);
- if(compiler.output_type() == SHADER_TYPE_VOLUME)
- compiler.parameter("is_volume", true);
- compiler.parameter(this, "use_transform");
- Transform ob_itfm = transform_inverse(ob_tfm);
- compiler.parameter("object_itfm", ob_itfm);
-
- compiler.parameter(this, "from_dupli");
-
- compiler.add(this, "node_texture_coordinate");
+ if (shader->has_surface) {
+ if (!from_dupli) {
+ if (!output("Generated")->links.empty())
+ attributes->add(ATTR_STD_GENERATED);
+ if (!output("UV")->links.empty())
+ attributes->add(ATTR_STD_UV);
+ }
+ }
+
+ if (shader->has_volume) {
+ if (!from_dupli) {
+ if (!output("Generated")->links.empty()) {
+ attributes->add(ATTR_STD_GENERATED_TRANSFORM);
+ }
+ }
+ }
+
+ ShaderNode::attributes(shader, attributes);
+}
+
+void TextureCoordinateNode::compile(SVMCompiler &compiler)
+{
+ ShaderOutput *out;
+ ShaderNodeType texco_node = NODE_TEX_COORD;
+ ShaderNodeType attr_node = NODE_ATTR;
+ ShaderNodeType geom_node = NODE_GEOMETRY;
+
+ if (bump == SHADER_BUMP_DX) {
+ texco_node = NODE_TEX_COORD_BUMP_DX;
+ attr_node = NODE_ATTR_BUMP_DX;
+ geom_node = NODE_GEOMETRY_BUMP_DX;
+ }
+ else if (bump == SHADER_BUMP_DY) {
+ texco_node = NODE_TEX_COORD_BUMP_DY;
+ attr_node = NODE_ATTR_BUMP_DY;
+ geom_node = NODE_GEOMETRY_BUMP_DY;
+ }
+
+ out = output("Generated");
+ if (!out->links.empty()) {
+ if (compiler.background) {
+ compiler.add_node(geom_node, NODE_GEOM_P, compiler.stack_assign(out));
+ }
+ else {
+ if (from_dupli) {
+ compiler.add_node(texco_node, NODE_TEXCO_DUPLI_GENERATED, compiler.stack_assign(out));
+ }
+ else if (compiler.output_type() == SHADER_TYPE_VOLUME) {
+ compiler.add_node(texco_node, NODE_TEXCO_VOLUME_GENERATED, compiler.stack_assign(out));
+ }
+ else {
+ int attr = compiler.attribute(ATTR_STD_GENERATED);
+ compiler.add_node(attr_node, attr, compiler.stack_assign(out), NODE_ATTR_FLOAT3);
+ }
+ }
+ }
+
+ out = output("Normal");
+ if (!out->links.empty()) {
+ compiler.add_node(texco_node, NODE_TEXCO_NORMAL, compiler.stack_assign(out));
+ }
+
+ out = output("UV");
+ if (!out->links.empty()) {
+ if (from_dupli) {
+ compiler.add_node(texco_node, NODE_TEXCO_DUPLI_UV, compiler.stack_assign(out));
+ }
+ else {
+ int attr = compiler.attribute(ATTR_STD_UV);
+ compiler.add_node(attr_node, attr, compiler.stack_assign(out), NODE_ATTR_FLOAT3);
+ }
+ }
+
+ out = output("Object");
+ if (!out->links.empty()) {
+ compiler.add_node(texco_node, NODE_TEXCO_OBJECT, compiler.stack_assign(out), use_transform);
+ if (use_transform) {
+ Transform ob_itfm = transform_inverse(ob_tfm);
+ compiler.add_node(ob_itfm.x);
+ compiler.add_node(ob_itfm.y);
+ compiler.add_node(ob_itfm.z);
+ }
+ }
+
+ out = output("Camera");
+ if (!out->links.empty()) {
+ compiler.add_node(texco_node, NODE_TEXCO_CAMERA, compiler.stack_assign(out));
+ }
+
+ out = output("Window");
+ if (!out->links.empty()) {
+ compiler.add_node(texco_node, NODE_TEXCO_WINDOW, compiler.stack_assign(out));
+ }
+
+ out = output("Reflection");
+ if (!out->links.empty()) {
+ if (compiler.background) {
+ compiler.add_node(geom_node, NODE_GEOM_I, compiler.stack_assign(out));
+ }
+ else {
+ compiler.add_node(texco_node, NODE_TEXCO_REFLECTION, compiler.stack_assign(out));
+ }
+ }
+}
+
+void TextureCoordinateNode::compile(OSLCompiler &compiler)
+{
+ if (bump == SHADER_BUMP_DX)
+ compiler.parameter("bump_offset", "dx");
+ else if (bump == SHADER_BUMP_DY)
+ compiler.parameter("bump_offset", "dy");
+ else
+ compiler.parameter("bump_offset", "center");
+
+ if (compiler.background)
+ compiler.parameter("is_background", true);
+ if (compiler.output_type() == SHADER_TYPE_VOLUME)
+ compiler.parameter("is_volume", true);
+ compiler.parameter(this, "use_transform");
+ Transform ob_itfm = transform_inverse(ob_tfm);
+ compiler.parameter("object_itfm", ob_itfm);
+
+ compiler.parameter(this, "from_dupli");
+
+ compiler.add(this, "node_texture_coordinate");
}
/* UV Map */
NODE_DEFINE(UVMapNode)
{
- NodeType* type = NodeType::add("uvmap", create, NodeType::SHADER);
+ NodeType *type = NodeType::add("uvmap", create, NodeType::SHADER);
- SOCKET_STRING(attribute, "attribute", ustring());
- SOCKET_IN_BOOLEAN(from_dupli, "from dupli", false);
+ SOCKET_STRING(attribute, "attribute", ustring());
+ SOCKET_IN_BOOLEAN(from_dupli, "from dupli", false);
- SOCKET_OUT_POINT(UV, "UV");
+ SOCKET_OUT_POINT(UV, "UV");
- return type;
+ return type;
}
-UVMapNode::UVMapNode()
-: ShaderNode(node_type)
+UVMapNode::UVMapNode() : ShaderNode(node_type)
{
}
void UVMapNode::attributes(Shader *shader, AttributeRequestSet *attributes)
{
- if(shader->has_surface) {
- if(!from_dupli) {
- if(!output("UV")->links.empty()) {
- if(attribute != "")
- attributes->add(attribute);
- else
- attributes->add(ATTR_STD_UV);
- }
- }
- }
-
- ShaderNode::attributes(shader, attributes);
-}
-
-void UVMapNode::compile(SVMCompiler& compiler)
-{
- ShaderOutput *out = output("UV");
- ShaderNodeType texco_node = NODE_TEX_COORD;
- ShaderNodeType attr_node = NODE_ATTR;
- int attr;
-
- if(bump == SHADER_BUMP_DX) {
- texco_node = NODE_TEX_COORD_BUMP_DX;
- attr_node = NODE_ATTR_BUMP_DX;
- }
- else if(bump == SHADER_BUMP_DY) {
- texco_node = NODE_TEX_COORD_BUMP_DY;
- attr_node = NODE_ATTR_BUMP_DY;
- }
-
- if(!out->links.empty()) {
- if(from_dupli) {
- compiler.add_node(texco_node, NODE_TEXCO_DUPLI_UV, compiler.stack_assign(out));
- }
- else {
- if(attribute != "")
- attr = compiler.attribute(attribute);
- else
- attr = compiler.attribute(ATTR_STD_UV);
-
- compiler.add_node(attr_node, attr, compiler.stack_assign(out), NODE_ATTR_FLOAT3);
- }
- }
-}
-
-void UVMapNode::compile(OSLCompiler& compiler)
-{
- if(bump == SHADER_BUMP_DX)
- compiler.parameter("bump_offset", "dx");
- else if(bump == SHADER_BUMP_DY)
- compiler.parameter("bump_offset", "dy");
- else
- compiler.parameter("bump_offset", "center");
-
- compiler.parameter(this, "from_dupli");
- compiler.parameter(this, "attribute");
- compiler.add(this, "node_uv_map");
+ if (shader->has_surface) {
+ if (!from_dupli) {
+ if (!output("UV")->links.empty()) {
+ if (attribute != "")
+ attributes->add(attribute);
+ else
+ attributes->add(ATTR_STD_UV);
+ }
+ }
+ }
+
+ ShaderNode::attributes(shader, attributes);
+}
+
+void UVMapNode::compile(SVMCompiler &compiler)
+{
+ ShaderOutput *out = output("UV");
+ ShaderNodeType texco_node = NODE_TEX_COORD;
+ ShaderNodeType attr_node = NODE_ATTR;
+ int attr;
+
+ if (bump == SHADER_BUMP_DX) {
+ texco_node = NODE_TEX_COORD_BUMP_DX;
+ attr_node = NODE_ATTR_BUMP_DX;
+ }
+ else if (bump == SHADER_BUMP_DY) {
+ texco_node = NODE_TEX_COORD_BUMP_DY;
+ attr_node = NODE_ATTR_BUMP_DY;
+ }
+
+ if (!out->links.empty()) {
+ if (from_dupli) {
+ compiler.add_node(texco_node, NODE_TEXCO_DUPLI_UV, compiler.stack_assign(out));
+ }
+ else {
+ if (attribute != "")
+ attr = compiler.attribute(attribute);
+ else
+ attr = compiler.attribute(ATTR_STD_UV);
+
+ compiler.add_node(attr_node, attr, compiler.stack_assign(out), NODE_ATTR_FLOAT3);
+ }
+ }
+}
+
+void UVMapNode::compile(OSLCompiler &compiler)
+{
+ if (bump == SHADER_BUMP_DX)
+ compiler.parameter("bump_offset", "dx");
+ else if (bump == SHADER_BUMP_DY)
+ compiler.parameter("bump_offset", "dy");
+ else
+ compiler.parameter("bump_offset", "center");
+
+ compiler.parameter(this, "from_dupli");
+ compiler.parameter(this, "attribute");
+ compiler.add(this, "node_uv_map");
}
/* Light Path */
NODE_DEFINE(LightPathNode)
{
- NodeType* type = NodeType::add("light_path", create, NodeType::SHADER);
+ NodeType *type = NodeType::add("light_path", create, NodeType::SHADER);
- SOCKET_OUT_FLOAT(is_camera_ray, "Is Camera Ray");
- SOCKET_OUT_FLOAT(is_shadow_ray, "Is Shadow Ray");
- SOCKET_OUT_FLOAT(is_diffuse_ray, "Is Diffuse Ray");
- SOCKET_OUT_FLOAT(is_glossy_ray, "Is Glossy Ray");
- SOCKET_OUT_FLOAT(is_singular_ray, "Is Singular Ray");
- SOCKET_OUT_FLOAT(is_reflection_ray, "Is Reflection Ray");
- SOCKET_OUT_FLOAT(is_transmission_ray, "Is Transmission Ray");
- SOCKET_OUT_FLOAT(is_volume_scatter_ray, "Is Volume Scatter Ray");
- SOCKET_OUT_FLOAT(ray_length, "Ray Length");
- SOCKET_OUT_FLOAT(ray_depth, "Ray Depth");
- SOCKET_OUT_FLOAT(diffuse_depth, "Diffuse Depth");
- SOCKET_OUT_FLOAT(glossy_depth, "Glossy Depth");
- SOCKET_OUT_FLOAT(transparent_depth, "Transparent Depth");
- SOCKET_OUT_FLOAT(transmission_depth, "Transmission Depth");
+ SOCKET_OUT_FLOAT(is_camera_ray, "Is Camera Ray");
+ SOCKET_OUT_FLOAT(is_shadow_ray, "Is Shadow Ray");
+ SOCKET_OUT_FLOAT(is_diffuse_ray, "Is Diffuse Ray");
+ SOCKET_OUT_FLOAT(is_glossy_ray, "Is Glossy Ray");
+ SOCKET_OUT_FLOAT(is_singular_ray, "Is Singular Ray");
+ SOCKET_OUT_FLOAT(is_reflection_ray, "Is Reflection Ray");
+ SOCKET_OUT_FLOAT(is_transmission_ray, "Is Transmission Ray");
+ SOCKET_OUT_FLOAT(is_volume_scatter_ray, "Is Volume Scatter Ray");
+ SOCKET_OUT_FLOAT(ray_length, "Ray Length");
+ SOCKET_OUT_FLOAT(ray_depth, "Ray Depth");
+ SOCKET_OUT_FLOAT(diffuse_depth, "Diffuse Depth");
+ SOCKET_OUT_FLOAT(glossy_depth, "Glossy Depth");
+ SOCKET_OUT_FLOAT(transparent_depth, "Transparent Depth");
+ SOCKET_OUT_FLOAT(transmission_depth, "Transmission Depth");
- return type;
+ return type;
}
-LightPathNode::LightPathNode()
-: ShaderNode(node_type)
+LightPathNode::LightPathNode() : ShaderNode(node_type)
{
}
-void LightPathNode::compile(SVMCompiler& compiler)
+void LightPathNode::compile(SVMCompiler &compiler)
{
- ShaderOutput *out;
-
- out = output("Is Camera Ray");
- if(!out->links.empty()) {
- compiler.add_node(NODE_LIGHT_PATH, NODE_LP_camera, compiler.stack_assign(out));
- }
+ ShaderOutput *out;
- out = output("Is Shadow Ray");
- if(!out->links.empty()) {
- compiler.add_node(NODE_LIGHT_PATH, NODE_LP_shadow, compiler.stack_assign(out));
- }
+ out = output("Is Camera Ray");
+ if (!out->links.empty()) {
+ compiler.add_node(NODE_LIGHT_PATH, NODE_LP_camera, compiler.stack_assign(out));
+ }
- out = output("Is Diffuse Ray");
- if(!out->links.empty()) {
- compiler.add_node(NODE_LIGHT_PATH, NODE_LP_diffuse, compiler.stack_assign(out));
- }
+ out = output("Is Shadow Ray");
+ if (!out->links.empty()) {
+ compiler.add_node(NODE_LIGHT_PATH, NODE_LP_shadow, compiler.stack_assign(out));
+ }
- out = output("Is Glossy Ray");
- if(!out->links.empty()) {
- compiler.add_node(NODE_LIGHT_PATH, NODE_LP_glossy, compiler.stack_assign(out));
- }
+ out = output("Is Diffuse Ray");
+ if (!out->links.empty()) {
+ compiler.add_node(NODE_LIGHT_PATH, NODE_LP_diffuse, compiler.stack_assign(out));
+ }
- out = output("Is Singular Ray");
- if(!out->links.empty()) {
- compiler.add_node(NODE_LIGHT_PATH, NODE_LP_singular, compiler.stack_assign(out));
- }
+ out = output("Is Glossy Ray");
+ if (!out->links.empty()) {
+ compiler.add_node(NODE_LIGHT_PATH, NODE_LP_glossy, compiler.stack_assign(out));
+ }
- out = output("Is Reflection Ray");
- if(!out->links.empty()) {
- compiler.add_node(NODE_LIGHT_PATH, NODE_LP_reflection, compiler.stack_assign(out));
- }
+ out = output("Is Singular Ray");
+ if (!out->links.empty()) {
+ compiler.add_node(NODE_LIGHT_PATH, NODE_LP_singular, compiler.stack_assign(out));
+ }
+ out = output("Is Reflection Ray");
+ if (!out->links.empty()) {
+ compiler.add_node(NODE_LIGHT_PATH, NODE_LP_reflection, compiler.stack_assign(out));
+ }
- out = output("Is Transmission Ray");
- if(!out->links.empty()) {
- compiler.add_node(NODE_LIGHT_PATH, NODE_LP_transmission, compiler.stack_assign(out));
- }
+ out = output("Is Transmission Ray");
+ if (!out->links.empty()) {
+ compiler.add_node(NODE_LIGHT_PATH, NODE_LP_transmission, compiler.stack_assign(out));
+ }
- out = output("Is Volume Scatter Ray");
- if(!out->links.empty()) {
- compiler.add_node(NODE_LIGHT_PATH, NODE_LP_volume_scatter, compiler.stack_assign(out));
- }
+ out = output("Is Volume Scatter Ray");
+ if (!out->links.empty()) {
+ compiler.add_node(NODE_LIGHT_PATH, NODE_LP_volume_scatter, compiler.stack_assign(out));
+ }
- out = output("Ray Length");
- if(!out->links.empty()) {
- compiler.add_node(NODE_LIGHT_PATH, NODE_LP_ray_length, compiler.stack_assign(out));
- }
+ out = output("Ray Length");
+ if (!out->links.empty()) {
+ compiler.add_node(NODE_LIGHT_PATH, NODE_LP_ray_length, compiler.stack_assign(out));
+ }
- out = output("Ray Depth");
- if(!out->links.empty()) {
- compiler.add_node(NODE_LIGHT_PATH, NODE_LP_ray_depth, compiler.stack_assign(out));
- }
+ out = output("Ray Depth");
+ if (!out->links.empty()) {
+ compiler.add_node(NODE_LIGHT_PATH, NODE_LP_ray_depth, compiler.stack_assign(out));
+ }
- out = output("Diffuse Depth");
- if(!out->links.empty()) {
- compiler.add_node(NODE_LIGHT_PATH, NODE_LP_ray_diffuse, compiler.stack_assign(out));
- }
+ out = output("Diffuse Depth");
+ if (!out->links.empty()) {
+ compiler.add_node(NODE_LIGHT_PATH, NODE_LP_ray_diffuse, compiler.stack_assign(out));
+ }
- out = output("Glossy Depth");
- if(!out->links.empty()) {
- compiler.add_node(NODE_LIGHT_PATH, NODE_LP_ray_glossy, compiler.stack_assign(out));
- }
+ out = output("Glossy Depth");
+ if (!out->links.empty()) {
+ compiler.add_node(NODE_LIGHT_PATH, NODE_LP_ray_glossy, compiler.stack_assign(out));
+ }
- out = output("Transparent Depth");
- if(!out->links.empty()) {
- compiler.add_node(NODE_LIGHT_PATH, NODE_LP_ray_transparent, compiler.stack_assign(out));
- }
+ out = output("Transparent Depth");
+ if (!out->links.empty()) {
+ compiler.add_node(NODE_LIGHT_PATH, NODE_LP_ray_transparent, compiler.stack_assign(out));
+ }
- out = output("Transmission Depth");
- if(!out->links.empty()) {
- compiler.add_node(NODE_LIGHT_PATH, NODE_LP_ray_transmission, compiler.stack_assign(out));
- }
+ out = output("Transmission Depth");
+ if (!out->links.empty()) {
+ compiler.add_node(NODE_LIGHT_PATH, NODE_LP_ray_transmission, compiler.stack_assign(out));
+ }
}
-void LightPathNode::compile(OSLCompiler& compiler)
+void LightPathNode::compile(OSLCompiler &compiler)
{
- compiler.add(this, "node_light_path");
+ compiler.add(this, "node_light_path");
}
/* Light Falloff */
NODE_DEFINE(LightFalloffNode)
{
- NodeType* type = NodeType::add("light_falloff", create, NodeType::SHADER);
+ NodeType *type = NodeType::add("light_falloff", create, NodeType::SHADER);
- SOCKET_IN_FLOAT(strength, "Strength", 100.0f);
- SOCKET_IN_FLOAT(smooth, "Smooth", 0.0f);
+ SOCKET_IN_FLOAT(strength, "Strength", 100.0f);
+ SOCKET_IN_FLOAT(smooth, "Smooth", 0.0f);
- SOCKET_OUT_FLOAT(quadratic, "Quadratic");
- SOCKET_OUT_FLOAT(linear, "Linear");
- SOCKET_OUT_FLOAT(constant, "Constant");
+ SOCKET_OUT_FLOAT(quadratic, "Quadratic");
+ SOCKET_OUT_FLOAT(linear, "Linear");
+ SOCKET_OUT_FLOAT(constant, "Constant");
- return type;
+ return type;
}
-LightFalloffNode::LightFalloffNode()
-: ShaderNode(node_type)
+LightFalloffNode::LightFalloffNode() : ShaderNode(node_type)
{
}
-void LightFalloffNode::compile(SVMCompiler& compiler)
+void LightFalloffNode::compile(SVMCompiler &compiler)
{
- ShaderInput *strength_in = input("Strength");
- ShaderInput *smooth_in = input("Smooth");
+ ShaderInput *strength_in = input("Strength");
+ ShaderInput *smooth_in = input("Smooth");
- ShaderOutput *out = output("Quadratic");
- if(!out->links.empty()) {
- compiler.add_node(NODE_LIGHT_FALLOFF, NODE_LIGHT_FALLOFF_QUADRATIC,
- compiler.encode_uchar4(
- compiler.stack_assign(strength_in),
- compiler.stack_assign(smooth_in),
- compiler.stack_assign(out)));
- }
+ ShaderOutput *out = output("Quadratic");
+ if (!out->links.empty()) {
+ compiler.add_node(NODE_LIGHT_FALLOFF,
+ NODE_LIGHT_FALLOFF_QUADRATIC,
+ compiler.encode_uchar4(compiler.stack_assign(strength_in),
+ compiler.stack_assign(smooth_in),
+ compiler.stack_assign(out)));
+ }
- out = output("Linear");
- if(!out->links.empty()) {
- compiler.add_node(NODE_LIGHT_FALLOFF, NODE_LIGHT_FALLOFF_LINEAR,
- compiler.encode_uchar4(
- compiler.stack_assign(strength_in),
- compiler.stack_assign(smooth_in),
- compiler.stack_assign(out)));
- }
+ out = output("Linear");
+ if (!out->links.empty()) {
+ compiler.add_node(NODE_LIGHT_FALLOFF,
+ NODE_LIGHT_FALLOFF_LINEAR,
+ compiler.encode_uchar4(compiler.stack_assign(strength_in),
+ compiler.stack_assign(smooth_in),
+ compiler.stack_assign(out)));
+ }
- out = output("Constant");
- if(!out->links.empty()) {
- compiler.add_node(NODE_LIGHT_FALLOFF, NODE_LIGHT_FALLOFF_CONSTANT,
- compiler.encode_uchar4(
- compiler.stack_assign(strength_in),
- compiler.stack_assign(smooth_in),
- compiler.stack_assign(out)));
- }
+ out = output("Constant");
+ if (!out->links.empty()) {
+ compiler.add_node(NODE_LIGHT_FALLOFF,
+ NODE_LIGHT_FALLOFF_CONSTANT,
+ compiler.encode_uchar4(compiler.stack_assign(strength_in),
+ compiler.stack_assign(smooth_in),
+ compiler.stack_assign(out)));
+ }
}
-void LightFalloffNode::compile(OSLCompiler& compiler)
+void LightFalloffNode::compile(OSLCompiler &compiler)
{
- compiler.add(this, "node_light_falloff");
+ compiler.add(this, "node_light_falloff");
}
/* Object Info */
NODE_DEFINE(ObjectInfoNode)
{
- NodeType* type = NodeType::add("object_info", create, NodeType::SHADER);
+ NodeType *type = NodeType::add("object_info", create, NodeType::SHADER);
- SOCKET_OUT_VECTOR(location, "Location");
- SOCKET_OUT_FLOAT(object_index, "Object Index");
- SOCKET_OUT_FLOAT(material_index, "Material Index");
- SOCKET_OUT_FLOAT(random, "Random");
+ SOCKET_OUT_VECTOR(location, "Location");
+ SOCKET_OUT_FLOAT(object_index, "Object Index");
+ SOCKET_OUT_FLOAT(material_index, "Material Index");
+ SOCKET_OUT_FLOAT(random, "Random");
- return type;
+ return type;
}
-ObjectInfoNode::ObjectInfoNode()
-: ShaderNode(node_type)
+ObjectInfoNode::ObjectInfoNode() : ShaderNode(node_type)
{
}
-void ObjectInfoNode::compile(SVMCompiler& compiler)
+void ObjectInfoNode::compile(SVMCompiler &compiler)
{
- ShaderOutput *out = output("Location");
- if(!out->links.empty()) {
- compiler.add_node(NODE_OBJECT_INFO, NODE_INFO_OB_LOCATION, compiler.stack_assign(out));
- }
+ ShaderOutput *out = output("Location");
+ if (!out->links.empty()) {
+ compiler.add_node(NODE_OBJECT_INFO, NODE_INFO_OB_LOCATION, compiler.stack_assign(out));
+ }
- out = output("Object Index");
- if(!out->links.empty()) {
- compiler.add_node(NODE_OBJECT_INFO, NODE_INFO_OB_INDEX, compiler.stack_assign(out));
- }
+ out = output("Object Index");
+ if (!out->links.empty()) {
+ compiler.add_node(NODE_OBJECT_INFO, NODE_INFO_OB_INDEX, compiler.stack_assign(out));
+ }
- out = output("Material Index");
- if(!out->links.empty()) {
- compiler.add_node(NODE_OBJECT_INFO, NODE_INFO_MAT_INDEX, compiler.stack_assign(out));
- }
+ out = output("Material Index");
+ if (!out->links.empty()) {
+ compiler.add_node(NODE_OBJECT_INFO, NODE_INFO_MAT_INDEX, compiler.stack_assign(out));
+ }
- out = output("Random");
- if(!out->links.empty()) {
- compiler.add_node(NODE_OBJECT_INFO, NODE_INFO_OB_RANDOM, compiler.stack_assign(out));
- }
+ out = output("Random");
+ if (!out->links.empty()) {
+ compiler.add_node(NODE_OBJECT_INFO, NODE_INFO_OB_RANDOM, compiler.stack_assign(out));
+ }
}
-void ObjectInfoNode::compile(OSLCompiler& compiler)
+void ObjectInfoNode::compile(OSLCompiler &compiler)
{
- compiler.add(this, "node_object_info");
+ compiler.add(this, "node_object_info");
}
/* Particle Info */
NODE_DEFINE(ParticleInfoNode)
{
- NodeType* type = NodeType::add("particle_info", create, NodeType::SHADER);
+ NodeType *type = NodeType::add("particle_info", create, NodeType::SHADER);
- SOCKET_OUT_FLOAT(index, "Index");
- SOCKET_OUT_FLOAT(random, "Random");
- SOCKET_OUT_FLOAT(age, "Age");
- SOCKET_OUT_FLOAT(lifetime, "Lifetime");
- SOCKET_OUT_POINT(location, "Location");
-#if 0 /* not yet supported */
- SOCKET_OUT_QUATERNION(rotation, "Rotation");
+ SOCKET_OUT_FLOAT(index, "Index");
+ SOCKET_OUT_FLOAT(random, "Random");
+ SOCKET_OUT_FLOAT(age, "Age");
+ SOCKET_OUT_FLOAT(lifetime, "Lifetime");
+ SOCKET_OUT_POINT(location, "Location");
+#if 0 /* not yet supported */
+ SOCKET_OUT_QUATERNION(rotation, "Rotation");
#endif
- SOCKET_OUT_FLOAT(size, "Size");
- SOCKET_OUT_VECTOR(velocity, "Velocity");
- SOCKET_OUT_VECTOR(angular_velocity, "Angular Velocity");
+ SOCKET_OUT_FLOAT(size, "Size");
+ SOCKET_OUT_VECTOR(velocity, "Velocity");
+ SOCKET_OUT_VECTOR(angular_velocity, "Angular Velocity");
- return type;
+ return type;
}
-ParticleInfoNode::ParticleInfoNode()
-: ShaderNode(node_type)
+ParticleInfoNode::ParticleInfoNode() : ShaderNode(node_type)
{
}
void ParticleInfoNode::attributes(Shader *shader, AttributeRequestSet *attributes)
{
- if(!output("Index")->links.empty())
- attributes->add(ATTR_STD_PARTICLE);
- if(!output("Random")->links.empty())
- attributes->add(ATTR_STD_PARTICLE);
- if(!output("Age")->links.empty())
- attributes->add(ATTR_STD_PARTICLE);
- if(!output("Lifetime")->links.empty())
- attributes->add(ATTR_STD_PARTICLE);
- if(!output("Location")->links.empty())
- attributes->add(ATTR_STD_PARTICLE);
-#if 0 /* not yet supported */
- if(!output("Rotation")->links.empty())
- attributes->add(ATTR_STD_PARTICLE);
+ if (!output("Index")->links.empty())
+ attributes->add(ATTR_STD_PARTICLE);
+ if (!output("Random")->links.empty())
+ attributes->add(ATTR_STD_PARTICLE);
+ if (!output("Age")->links.empty())
+ attributes->add(ATTR_STD_PARTICLE);
+ if (!output("Lifetime")->links.empty())
+ attributes->add(ATTR_STD_PARTICLE);
+ if (!output("Location")->links.empty())
+ attributes->add(ATTR_STD_PARTICLE);
+#if 0 /* not yet supported */
+ if(!output("Rotation")->links.empty())
+ attributes->add(ATTR_STD_PARTICLE);
#endif
- if(!output("Size")->links.empty())
- attributes->add(ATTR_STD_PARTICLE);
- if(!output("Velocity")->links.empty())
- attributes->add(ATTR_STD_PARTICLE);
- if(!output("Angular Velocity")->links.empty())
- attributes->add(ATTR_STD_PARTICLE);
+ if (!output("Size")->links.empty())
+ attributes->add(ATTR_STD_PARTICLE);
+ if (!output("Velocity")->links.empty())
+ attributes->add(ATTR_STD_PARTICLE);
+ if (!output("Angular Velocity")->links.empty())
+ attributes->add(ATTR_STD_PARTICLE);
- ShaderNode::attributes(shader, attributes);
+ ShaderNode::attributes(shader, attributes);
}
-void ParticleInfoNode::compile(SVMCompiler& compiler)
+void ParticleInfoNode::compile(SVMCompiler &compiler)
{
- ShaderOutput *out;
+ ShaderOutput *out;
- out = output("Index");
- if(!out->links.empty()) {
- compiler.add_node(NODE_PARTICLE_INFO, NODE_INFO_PAR_INDEX, compiler.stack_assign(out));
- }
+ out = output("Index");
+ if (!out->links.empty()) {
+ compiler.add_node(NODE_PARTICLE_INFO, NODE_INFO_PAR_INDEX, compiler.stack_assign(out));
+ }
- out = output("Random");
- if(!out->links.empty()) {
- compiler.add_node(NODE_PARTICLE_INFO, NODE_INFO_PAR_RANDOM, compiler.stack_assign(out));
- }
+ out = output("Random");
+ if (!out->links.empty()) {
+ compiler.add_node(NODE_PARTICLE_INFO, NODE_INFO_PAR_RANDOM, compiler.stack_assign(out));
+ }
- out = output("Age");
- if(!out->links.empty()) {
- compiler.add_node(NODE_PARTICLE_INFO, NODE_INFO_PAR_AGE, compiler.stack_assign(out));
- }
+ out = output("Age");
+ if (!out->links.empty()) {
+ compiler.add_node(NODE_PARTICLE_INFO, NODE_INFO_PAR_AGE, compiler.stack_assign(out));
+ }
- out = output("Lifetime");
- if(!out->links.empty()) {
- compiler.add_node(NODE_PARTICLE_INFO, NODE_INFO_PAR_LIFETIME, compiler.stack_assign(out));
- }
+ out = output("Lifetime");
+ if (!out->links.empty()) {
+ compiler.add_node(NODE_PARTICLE_INFO, NODE_INFO_PAR_LIFETIME, compiler.stack_assign(out));
+ }
- out = output("Location");
- if(!out->links.empty()) {
- compiler.add_node(NODE_PARTICLE_INFO, NODE_INFO_PAR_LOCATION, compiler.stack_assign(out));
- }
+ out = output("Location");
+ if (!out->links.empty()) {
+ compiler.add_node(NODE_PARTICLE_INFO, NODE_INFO_PAR_LOCATION, compiler.stack_assign(out));
+ }
- /* quaternion data is not yet supported by Cycles */
+ /* quaternion data is not yet supported by Cycles */
#if 0
- out = output("Rotation");
- if(!out->links.empty()) {
- compiler.add_node(NODE_PARTICLE_INFO, NODE_INFO_PAR_ROTATION, compiler.stack_assign(out));
- }
+ out = output("Rotation");
+ if(!out->links.empty()) {
+ compiler.add_node(NODE_PARTICLE_INFO, NODE_INFO_PAR_ROTATION, compiler.stack_assign(out));
+ }
#endif
- out = output("Size");
- if(!out->links.empty()) {
- compiler.add_node(NODE_PARTICLE_INFO, NODE_INFO_PAR_SIZE, compiler.stack_assign(out));
- }
+ out = output("Size");
+ if (!out->links.empty()) {
+ compiler.add_node(NODE_PARTICLE_INFO, NODE_INFO_PAR_SIZE, compiler.stack_assign(out));
+ }
- out = output("Velocity");
- if(!out->links.empty()) {
- compiler.add_node(NODE_PARTICLE_INFO, NODE_INFO_PAR_VELOCITY, compiler.stack_assign(out));
- }
+ out = output("Velocity");
+ if (!out->links.empty()) {
+ compiler.add_node(NODE_PARTICLE_INFO, NODE_INFO_PAR_VELOCITY, compiler.stack_assign(out));
+ }
- out = output("Angular Velocity");
- if(!out->links.empty()) {
- compiler.add_node(NODE_PARTICLE_INFO, NODE_INFO_PAR_ANGULAR_VELOCITY, compiler.stack_assign(out));
- }
+ out = output("Angular Velocity");
+ if (!out->links.empty()) {
+ compiler.add_node(
+ NODE_PARTICLE_INFO, NODE_INFO_PAR_ANGULAR_VELOCITY, compiler.stack_assign(out));
+ }
}
-void ParticleInfoNode::compile(OSLCompiler& compiler)
+void ParticleInfoNode::compile(OSLCompiler &compiler)
{
- compiler.add(this, "node_particle_info");
+ compiler.add(this, "node_particle_info");
}
/* Hair Info */
NODE_DEFINE(HairInfoNode)
{
- NodeType* type = NodeType::add("hair_info", create, NodeType::SHADER);
+ NodeType *type = NodeType::add("hair_info", create, NodeType::SHADER);
- SOCKET_OUT_FLOAT(is_strand, "Is Strand");
- SOCKET_OUT_FLOAT(intercept, "Intercept");
- SOCKET_OUT_FLOAT(thickness, "Thickness");
- SOCKET_OUT_NORMAL(tangent_normal, "Tangent Normal");
+ SOCKET_OUT_FLOAT(is_strand, "Is Strand");
+ SOCKET_OUT_FLOAT(intercept, "Intercept");
+ SOCKET_OUT_FLOAT(thickness, "Thickness");
+ SOCKET_OUT_NORMAL(tangent_normal, "Tangent Normal");
#if 0 /*output for minimum hair width transparency - deactivated */
- SOCKET_OUT_FLOAT(fade, "Fade");
+ SOCKET_OUT_FLOAT(fade, "Fade");
#endif
- SOCKET_OUT_FLOAT(index, "Random");
+ SOCKET_OUT_FLOAT(index, "Random");
- return type;
+ return type;
}
-HairInfoNode::HairInfoNode()
-: ShaderNode(node_type)
+HairInfoNode::HairInfoNode() : ShaderNode(node_type)
{
}
void HairInfoNode::attributes(Shader *shader, AttributeRequestSet *attributes)
{
- if(shader->has_surface) {
- ShaderOutput *intercept_out = output("Intercept");
+ if (shader->has_surface) {
+ ShaderOutput *intercept_out = output("Intercept");
- if(!intercept_out->links.empty())
- attributes->add(ATTR_STD_CURVE_INTERCEPT);
+ if (!intercept_out->links.empty())
+ attributes->add(ATTR_STD_CURVE_INTERCEPT);
- if(!output("Random")->links.empty())
- attributes->add(ATTR_STD_CURVE_RANDOM);
- }
+ if (!output("Random")->links.empty())
+ attributes->add(ATTR_STD_CURVE_RANDOM);
+ }
- ShaderNode::attributes(shader, attributes);
+ ShaderNode::attributes(shader, attributes);
}
-void HairInfoNode::compile(SVMCompiler& compiler)
+void HairInfoNode::compile(SVMCompiler &compiler)
{
- ShaderOutput *out;
+ ShaderOutput *out;
- out = output("Is Strand");
- if(!out->links.empty()) {
- compiler.add_node(NODE_HAIR_INFO, NODE_INFO_CURVE_IS_STRAND, compiler.stack_assign(out));
- }
+ out = output("Is Strand");
+ if (!out->links.empty()) {
+ compiler.add_node(NODE_HAIR_INFO, NODE_INFO_CURVE_IS_STRAND, compiler.stack_assign(out));
+ }
- out = output("Intercept");
- if(!out->links.empty()) {
- int attr = compiler.attribute(ATTR_STD_CURVE_INTERCEPT);
- compiler.add_node(NODE_ATTR, attr, compiler.stack_assign(out), NODE_ATTR_FLOAT);
- }
+ out = output("Intercept");
+ if (!out->links.empty()) {
+ int attr = compiler.attribute(ATTR_STD_CURVE_INTERCEPT);
+ compiler.add_node(NODE_ATTR, attr, compiler.stack_assign(out), NODE_ATTR_FLOAT);
+ }
- out = output("Thickness");
- if(!out->links.empty()) {
- compiler.add_node(NODE_HAIR_INFO, NODE_INFO_CURVE_THICKNESS, compiler.stack_assign(out));
- }
+ out = output("Thickness");
+ if (!out->links.empty()) {
+ compiler.add_node(NODE_HAIR_INFO, NODE_INFO_CURVE_THICKNESS, compiler.stack_assign(out));
+ }
- out = output("Tangent Normal");
- if(!out->links.empty()) {
- compiler.add_node(NODE_HAIR_INFO, NODE_INFO_CURVE_TANGENT_NORMAL, compiler.stack_assign(out));
- }
+ out = output("Tangent Normal");
+ if (!out->links.empty()) {
+ compiler.add_node(NODE_HAIR_INFO, NODE_INFO_CURVE_TANGENT_NORMAL, compiler.stack_assign(out));
+ }
- /*out = output("Fade");
- if(!out->links.empty()) {
- compiler.add_node(NODE_HAIR_INFO, NODE_INFO_CURVE_FADE, compiler.stack_assign(out));
- }*/
+ /*out = output("Fade");
+ if(!out->links.empty()) {
+ compiler.add_node(NODE_HAIR_INFO, NODE_INFO_CURVE_FADE, compiler.stack_assign(out));
+ }*/
- out = output("Random");
- if(!out->links.empty()) {
- int attr = compiler.attribute(ATTR_STD_CURVE_RANDOM);
- compiler.add_node(NODE_ATTR, attr, compiler.stack_assign(out), NODE_ATTR_FLOAT);
- }
+ out = output("Random");
+ if (!out->links.empty()) {
+ int attr = compiler.attribute(ATTR_STD_CURVE_RANDOM);
+ compiler.add_node(NODE_ATTR, attr, compiler.stack_assign(out), NODE_ATTR_FLOAT);
+ }
}
-void HairInfoNode::compile(OSLCompiler& compiler)
+void HairInfoNode::compile(OSLCompiler &compiler)
{
- compiler.add(this, "node_hair_info");
+ compiler.add(this, "node_hair_info");
}
/* Value */
NODE_DEFINE(ValueNode)
{
- NodeType* type = NodeType::add("value", create, NodeType::SHADER);
+ NodeType *type = NodeType::add("value", create, NodeType::SHADER);
- SOCKET_FLOAT(value, "Value", 0.0f);
- SOCKET_OUT_FLOAT(value, "Value");
+ SOCKET_FLOAT(value, "Value", 0.0f);
+ SOCKET_OUT_FLOAT(value, "Value");
- return type;
+ return type;
}
-ValueNode::ValueNode()
-: ShaderNode(node_type)
+ValueNode::ValueNode() : ShaderNode(node_type)
{
}
-void ValueNode::constant_fold(const ConstantFolder& folder)
+void ValueNode::constant_fold(const ConstantFolder &folder)
{
- folder.make_constant(value);
+ folder.make_constant(value);
}
-void ValueNode::compile(SVMCompiler& compiler)
+void ValueNode::compile(SVMCompiler &compiler)
{
- ShaderOutput *val_out = output("Value");
+ ShaderOutput *val_out = output("Value");
- compiler.add_node(NODE_VALUE_F, __float_as_int(value), compiler.stack_assign(val_out));
+ compiler.add_node(NODE_VALUE_F, __float_as_int(value), compiler.stack_assign(val_out));
}
-void ValueNode::compile(OSLCompiler& compiler)
+void ValueNode::compile(OSLCompiler &compiler)
{
- compiler.parameter("value_value", value);
- compiler.add(this, "node_value");
+ compiler.parameter("value_value", value);
+ compiler.add(this, "node_value");
}
/* Color */
NODE_DEFINE(ColorNode)
{
- NodeType* type = NodeType::add("color", create, NodeType::SHADER);
+ NodeType *type = NodeType::add("color", create, NodeType::SHADER);
- SOCKET_COLOR(value, "Value", make_float3(0.0f, 0.0f, 0.0f));
- SOCKET_OUT_COLOR(color, "Color");
+ SOCKET_COLOR(value, "Value", make_float3(0.0f, 0.0f, 0.0f));
+ SOCKET_OUT_COLOR(color, "Color");
- return type;
+ return type;
}
-ColorNode::ColorNode()
-: ShaderNode(node_type)
+ColorNode::ColorNode() : ShaderNode(node_type)
{
}
-void ColorNode::constant_fold(const ConstantFolder& folder)
+void ColorNode::constant_fold(const ConstantFolder &folder)
{
- folder.make_constant(value);
+ folder.make_constant(value);
}
-void ColorNode::compile(SVMCompiler& compiler)
+void ColorNode::compile(SVMCompiler &compiler)
{
- ShaderOutput *color_out = output("Color");
+ ShaderOutput *color_out = output("Color");
- if(!color_out->links.empty()) {
- compiler.add_node(NODE_VALUE_V, compiler.stack_assign(color_out));
- compiler.add_node(NODE_VALUE_V, value);
- }
+ if (!color_out->links.empty()) {
+ compiler.add_node(NODE_VALUE_V, compiler.stack_assign(color_out));
+ compiler.add_node(NODE_VALUE_V, value);
+ }
}
-void ColorNode::compile(OSLCompiler& compiler)
+void ColorNode::compile(OSLCompiler &compiler)
{
- compiler.parameter_color("color_value", value);
+ compiler.parameter_color("color_value", value);
- compiler.add(this, "node_value");
+ compiler.add(this, "node_value");
}
/* Add Closure */
NODE_DEFINE(AddClosureNode)
{
- NodeType* type = NodeType::add("add_closure", create, NodeType::SHADER);
+ NodeType *type = NodeType::add("add_closure", create, NodeType::SHADER);
- SOCKET_IN_CLOSURE(closure1, "Closure1");
- SOCKET_IN_CLOSURE(closure2, "Closure2");
- SOCKET_OUT_CLOSURE(closure, "Closure");
+ SOCKET_IN_CLOSURE(closure1, "Closure1");
+ SOCKET_IN_CLOSURE(closure2, "Closure2");
+ SOCKET_OUT_CLOSURE(closure, "Closure");
- return type;
+ return type;
}
-AddClosureNode::AddClosureNode()
-: ShaderNode(node_type)
+AddClosureNode::AddClosureNode() : ShaderNode(node_type)
{
- special_type = SHADER_SPECIAL_TYPE_COMBINE_CLOSURE;
+ special_type = SHADER_SPECIAL_TYPE_COMBINE_CLOSURE;
}
-void AddClosureNode::compile(SVMCompiler& /*compiler*/)
+void AddClosureNode::compile(SVMCompiler & /*compiler*/)
{
- /* handled in the SVM compiler */
+ /* handled in the SVM compiler */
}
-void AddClosureNode::compile(OSLCompiler& compiler)
+void AddClosureNode::compile(OSLCompiler &compiler)
{
- compiler.add(this, "node_add_closure");
+ compiler.add(this, "node_add_closure");
}
-void AddClosureNode::constant_fold(const ConstantFolder& folder)
+void AddClosureNode::constant_fold(const ConstantFolder &folder)
{
- ShaderInput *closure1_in = input("Closure1");
- ShaderInput *closure2_in = input("Closure2");
+ ShaderInput *closure1_in = input("Closure1");
+ ShaderInput *closure2_in = input("Closure2");
- /* remove useless add closures nodes */
- if(!closure1_in->link) {
- folder.bypass_or_discard(closure2_in);
- }
- else if(!closure2_in->link) {
- folder.bypass_or_discard(closure1_in);
- }
+ /* remove useless add closures nodes */
+ if (!closure1_in->link) {
+ folder.bypass_or_discard(closure2_in);
+ }
+ else if (!closure2_in->link) {
+ folder.bypass_or_discard(closure1_in);
+ }
}
/* Mix Closure */
NODE_DEFINE(MixClosureNode)
{
- NodeType* type = NodeType::add("mix_closure", create, NodeType::SHADER);
+ NodeType *type = NodeType::add("mix_closure", create, NodeType::SHADER);
- SOCKET_IN_FLOAT(fac, "Fac", 0.5f);
- SOCKET_IN_CLOSURE(closure1, "Closure1");
- SOCKET_IN_CLOSURE(closure2, "Closure2");
+ SOCKET_IN_FLOAT(fac, "Fac", 0.5f);
+ SOCKET_IN_CLOSURE(closure1, "Closure1");
+ SOCKET_IN_CLOSURE(closure2, "Closure2");
- SOCKET_OUT_CLOSURE(closure, "Closure");
+ SOCKET_OUT_CLOSURE(closure, "Closure");
- return type;
+ return type;
}
-MixClosureNode::MixClosureNode()
-: ShaderNode(node_type)
+MixClosureNode::MixClosureNode() : ShaderNode(node_type)
{
- special_type = SHADER_SPECIAL_TYPE_COMBINE_CLOSURE;
+ special_type = SHADER_SPECIAL_TYPE_COMBINE_CLOSURE;
}
-void MixClosureNode::compile(SVMCompiler& /*compiler*/)
+void MixClosureNode::compile(SVMCompiler & /*compiler*/)
{
- /* handled in the SVM compiler */
+ /* handled in the SVM compiler */
}
-void MixClosureNode::compile(OSLCompiler& compiler)
+void MixClosureNode::compile(OSLCompiler &compiler)
{
- compiler.add(this, "node_mix_closure");
+ compiler.add(this, "node_mix_closure");
}
-void MixClosureNode::constant_fold(const ConstantFolder& folder)
+void MixClosureNode::constant_fold(const ConstantFolder &folder)
{
- ShaderInput *fac_in = input("Fac");
- ShaderInput *closure1_in = input("Closure1");
- ShaderInput *closure2_in = input("Closure2");
+ ShaderInput *fac_in = input("Fac");
+ ShaderInput *closure1_in = input("Closure1");
+ ShaderInput *closure2_in = input("Closure2");
- /* remove useless mix closures nodes */
- if(closure1_in->link == closure2_in->link) {
- folder.bypass_or_discard(closure1_in);
- }
- /* remove unused mix closure input when factor is 0.0 or 1.0
- * check for closure links and make sure factor link is disconnected */
- else if(!fac_in->link) {
- /* factor 0.0 */
- if(fac <= 0.0f) {
- folder.bypass_or_discard(closure1_in);
- }
- /* factor 1.0 */
- else if(fac >= 1.0f) {
- folder.bypass_or_discard(closure2_in);
- }
- }
+ /* remove useless mix closures nodes */
+ if (closure1_in->link == closure2_in->link) {
+ folder.bypass_or_discard(closure1_in);
+ }
+ /* remove unused mix closure input when factor is 0.0 or 1.0
+ * check for closure links and make sure factor link is disconnected */
+ else if (!fac_in->link) {
+ /* factor 0.0 */
+ if (fac <= 0.0f) {
+ folder.bypass_or_discard(closure1_in);
+ }
+ /* factor 1.0 */
+ else if (fac >= 1.0f) {
+ folder.bypass_or_discard(closure2_in);
+ }
+ }
}
/* Mix Closure */
NODE_DEFINE(MixClosureWeightNode)
{
- NodeType* type = NodeType::add("mix_closure_weight", create, NodeType::SHADER);
+ NodeType *type = NodeType::add("mix_closure_weight", create, NodeType::SHADER);
- SOCKET_IN_FLOAT(weight, "Weight", 1.0f);
- SOCKET_IN_FLOAT(fac, "Fac", 1.0f);
+ SOCKET_IN_FLOAT(weight, "Weight", 1.0f);
+ SOCKET_IN_FLOAT(fac, "Fac", 1.0f);
- SOCKET_OUT_FLOAT(weight1, "Weight1");
- SOCKET_OUT_FLOAT(weight2, "Weight2");
+ SOCKET_OUT_FLOAT(weight1, "Weight1");
+ SOCKET_OUT_FLOAT(weight2, "Weight2");
- return type;
+ return type;
}
-MixClosureWeightNode::MixClosureWeightNode()
-: ShaderNode(node_type)
+MixClosureWeightNode::MixClosureWeightNode() : ShaderNode(node_type)
{
}
-void MixClosureWeightNode::compile(SVMCompiler& compiler)
+void MixClosureWeightNode::compile(SVMCompiler &compiler)
{
- ShaderInput *weight_in = input("Weight");
- ShaderInput *fac_in = input("Fac");
- ShaderOutput *weight1_out = output("Weight1");
- ShaderOutput *weight2_out = output("Weight2");
+ ShaderInput *weight_in = input("Weight");
+ ShaderInput *fac_in = input("Fac");
+ ShaderOutput *weight1_out = output("Weight1");
+ ShaderOutput *weight2_out = output("Weight2");
- compiler.add_node(NODE_MIX_CLOSURE,
- compiler.encode_uchar4(
- compiler.stack_assign(fac_in),
- compiler.stack_assign(weight_in),
- compiler.stack_assign(weight1_out),
- compiler.stack_assign(weight2_out)));
+ compiler.add_node(NODE_MIX_CLOSURE,
+ compiler.encode_uchar4(compiler.stack_assign(fac_in),
+ compiler.stack_assign(weight_in),
+ compiler.stack_assign(weight1_out),
+ compiler.stack_assign(weight2_out)));
}
-void MixClosureWeightNode::compile(OSLCompiler& /*compiler*/)
+void MixClosureWeightNode::compile(OSLCompiler & /*compiler*/)
{
- assert(0);
+ assert(0);
}
/* Invert */
NODE_DEFINE(InvertNode)
{
- NodeType* type = NodeType::add("invert", create, NodeType::SHADER);
+ NodeType *type = NodeType::add("invert", create, NodeType::SHADER);
- SOCKET_IN_FLOAT(fac, "Fac", 1.0f);
- SOCKET_IN_COLOR(color, "Color", make_float3(0.0f, 0.0f, 0.0f));
+ SOCKET_IN_FLOAT(fac, "Fac", 1.0f);
+ SOCKET_IN_COLOR(color, "Color", make_float3(0.0f, 0.0f, 0.0f));
- SOCKET_OUT_COLOR(color, "Color");
+ SOCKET_OUT_COLOR(color, "Color");
- return type;
+ return type;
}
-InvertNode::InvertNode()
-: ShaderNode(node_type)
+InvertNode::InvertNode() : ShaderNode(node_type)
{
}
-void InvertNode::constant_fold(const ConstantFolder& folder)
+void InvertNode::constant_fold(const ConstantFolder &folder)
{
- ShaderInput *fac_in = input("Fac");
- ShaderInput *color_in = input("Color");
+ ShaderInput *fac_in = input("Fac");
+ ShaderInput *color_in = input("Color");
- if(!fac_in->link) {
- /* evaluate fully constant node */
- if(!color_in->link) {
- folder.make_constant(interp(color, make_float3(1.0f, 1.0f, 1.0f) - color, fac));
- }
- /* remove no-op node */
- else if(fac == 0.0f) {
- folder.bypass(color_in->link);
- }
- }
+ if (!fac_in->link) {
+ /* evaluate fully constant node */
+ if (!color_in->link) {
+ folder.make_constant(interp(color, make_float3(1.0f, 1.0f, 1.0f) - color, fac));
+ }
+ /* remove no-op node */
+ else if (fac == 0.0f) {
+ folder.bypass(color_in->link);
+ }
+ }
}
-void InvertNode::compile(SVMCompiler& compiler)
+void InvertNode::compile(SVMCompiler &compiler)
{
- ShaderInput *fac_in = input("Fac");
- ShaderInput *color_in = input("Color");
- ShaderOutput *color_out = output("Color");
+ ShaderInput *fac_in = input("Fac");
+ ShaderInput *color_in = input("Color");
+ ShaderOutput *color_out = output("Color");
- compiler.add_node(NODE_INVERT,
- compiler.stack_assign(fac_in),
- compiler.stack_assign(color_in),
- compiler.stack_assign(color_out));
+ compiler.add_node(NODE_INVERT,
+ compiler.stack_assign(fac_in),
+ compiler.stack_assign(color_in),
+ compiler.stack_assign(color_out));
}
-void InvertNode::compile(OSLCompiler& compiler)
+void InvertNode::compile(OSLCompiler &compiler)
{
- compiler.add(this, "node_invert");
+ compiler.add(this, "node_invert");
}
/* Mix */
NODE_DEFINE(MixNode)
{
- NodeType* type = NodeType::add("mix", create, NodeType::SHADER);
+ NodeType *type = NodeType::add("mix", create, NodeType::SHADER);
- static NodeEnum type_enum;
- type_enum.insert("mix", NODE_MIX_BLEND);
- type_enum.insert("add", NODE_MIX_ADD);
- type_enum.insert("multiply", NODE_MIX_MUL);
- type_enum.insert("screen", NODE_MIX_SCREEN);
- type_enum.insert("overlay", NODE_MIX_OVERLAY);
- type_enum.insert("subtract", NODE_MIX_SUB);
- type_enum.insert("divide", NODE_MIX_DIV);
- type_enum.insert("difference", NODE_MIX_DIFF);
- type_enum.insert("darken", NODE_MIX_DARK);
- type_enum.insert("lighten", NODE_MIX_LIGHT);
- type_enum.insert("dodge", NODE_MIX_DODGE);
- type_enum.insert("burn", NODE_MIX_BURN);
- type_enum.insert("hue", NODE_MIX_HUE);
- type_enum.insert("saturation", NODE_MIX_SAT);
- type_enum.insert("value", NODE_MIX_VAL);
- type_enum.insert("color", NODE_MIX_COLOR);
- type_enum.insert("soft_light", NODE_MIX_SOFT);
- type_enum.insert("linear_light", NODE_MIX_LINEAR);
- SOCKET_ENUM(type, "Type", type_enum, NODE_MIX_BLEND);
+ static NodeEnum type_enum;
+ type_enum.insert("mix", NODE_MIX_BLEND);
+ type_enum.insert("add", NODE_MIX_ADD);
+ type_enum.insert("multiply", NODE_MIX_MUL);
+ type_enum.insert("screen", NODE_MIX_SCREEN);
+ type_enum.insert("overlay", NODE_MIX_OVERLAY);
+ type_enum.insert("subtract", NODE_MIX_SUB);
+ type_enum.insert("divide", NODE_MIX_DIV);
+ type_enum.insert("difference", NODE_MIX_DIFF);
+ type_enum.insert("darken", NODE_MIX_DARK);
+ type_enum.insert("lighten", NODE_MIX_LIGHT);
+ type_enum.insert("dodge", NODE_MIX_DODGE);
+ type_enum.insert("burn", NODE_MIX_BURN);
+ type_enum.insert("hue", NODE_MIX_HUE);
+ type_enum.insert("saturation", NODE_MIX_SAT);
+ type_enum.insert("value", NODE_MIX_VAL);
+ type_enum.insert("color", NODE_MIX_COLOR);
+ type_enum.insert("soft_light", NODE_MIX_SOFT);
+ type_enum.insert("linear_light", NODE_MIX_LINEAR);
+ SOCKET_ENUM(type, "Type", type_enum, NODE_MIX_BLEND);
- SOCKET_BOOLEAN(use_clamp, "Use Clamp", false);
+ SOCKET_BOOLEAN(use_clamp, "Use Clamp", false);
- SOCKET_IN_FLOAT(fac, "Fac", 0.5f);
- SOCKET_IN_COLOR(color1, "Color1", make_float3(0.0f, 0.0f, 0.0f));
- SOCKET_IN_COLOR(color2, "Color2", make_float3(0.0f, 0.0f, 0.0f));
+ SOCKET_IN_FLOAT(fac, "Fac", 0.5f);
+ SOCKET_IN_COLOR(color1, "Color1", make_float3(0.0f, 0.0f, 0.0f));
+ SOCKET_IN_COLOR(color2, "Color2", make_float3(0.0f, 0.0f, 0.0f));
- SOCKET_OUT_COLOR(color, "Color");
+ SOCKET_OUT_COLOR(color, "Color");
- return type;
+ return type;
}
-MixNode::MixNode()
-: ShaderNode(node_type)
+MixNode::MixNode() : ShaderNode(node_type)
{
}
-void MixNode::compile(SVMCompiler& compiler)
+void MixNode::compile(SVMCompiler &compiler)
{
- ShaderInput *fac_in = input("Fac");
- ShaderInput *color1_in = input("Color1");
- ShaderInput *color2_in = input("Color2");
- ShaderOutput *color_out = output("Color");
+ ShaderInput *fac_in = input("Fac");
+ ShaderInput *color1_in = input("Color1");
+ ShaderInput *color2_in = input("Color2");
+ ShaderOutput *color_out = output("Color");
- compiler.add_node(NODE_MIX,
- compiler.stack_assign(fac_in),
- compiler.stack_assign(color1_in),
- compiler.stack_assign(color2_in));
- compiler.add_node(NODE_MIX, type, compiler.stack_assign(color_out));
+ compiler.add_node(NODE_MIX,
+ compiler.stack_assign(fac_in),
+ compiler.stack_assign(color1_in),
+ compiler.stack_assign(color2_in));
+ compiler.add_node(NODE_MIX, type, compiler.stack_assign(color_out));
- if(use_clamp) {
- compiler.add_node(NODE_MIX, 0, compiler.stack_assign(color_out));
- compiler.add_node(NODE_MIX, NODE_MIX_CLAMP, compiler.stack_assign(color_out));
- }
+ if (use_clamp) {
+ compiler.add_node(NODE_MIX, 0, compiler.stack_assign(color_out));
+ compiler.add_node(NODE_MIX, NODE_MIX_CLAMP, compiler.stack_assign(color_out));
+ }
}
-void MixNode::compile(OSLCompiler& compiler)
+void MixNode::compile(OSLCompiler &compiler)
{
- compiler.parameter(this, "type");
- compiler.parameter(this, "use_clamp");
- compiler.add(this, "node_mix");
+ compiler.parameter(this, "type");
+ compiler.parameter(this, "use_clamp");
+ compiler.add(this, "node_mix");
}
-void MixNode::constant_fold(const ConstantFolder& folder)
+void MixNode::constant_fold(const ConstantFolder &folder)
{
- if(folder.all_inputs_constant()) {
- folder.make_constant_clamp(svm_mix(type, fac, color1, color2), use_clamp);
- }
- else {
- folder.fold_mix(type, use_clamp);
- }
+ if (folder.all_inputs_constant()) {
+ folder.make_constant_clamp(svm_mix(type, fac, color1, color2), use_clamp);
+ }
+ else {
+ folder.fold_mix(type, use_clamp);
+ }
}
/* Combine RGB */
NODE_DEFINE(CombineRGBNode)
{
- NodeType* type = NodeType::add("combine_rgb", create, NodeType::SHADER);
+ NodeType *type = NodeType::add("combine_rgb", create, NodeType::SHADER);
- SOCKET_IN_FLOAT(r, "R", 0.0f);
- SOCKET_IN_FLOAT(g, "G", 0.0f);
- SOCKET_IN_FLOAT(b, "B", 0.0f);
+ SOCKET_IN_FLOAT(r, "R", 0.0f);
+ SOCKET_IN_FLOAT(g, "G", 0.0f);
+ SOCKET_IN_FLOAT(b, "B", 0.0f);
- SOCKET_OUT_COLOR(image, "Image");
+ SOCKET_OUT_COLOR(image, "Image");
- return type;
+ return type;
}
-CombineRGBNode::CombineRGBNode()
-: ShaderNode(node_type)
+CombineRGBNode::CombineRGBNode() : ShaderNode(node_type)
{
}
-void CombineRGBNode::constant_fold(const ConstantFolder& folder)
+void CombineRGBNode::constant_fold(const ConstantFolder &folder)
{
- if(folder.all_inputs_constant()) {
- folder.make_constant(make_float3(r, g, b));
- }
+ if (folder.all_inputs_constant()) {
+ folder.make_constant(make_float3(r, g, b));
+ }
}
-void CombineRGBNode::compile(SVMCompiler& compiler)
+void CombineRGBNode::compile(SVMCompiler &compiler)
{
- ShaderInput *red_in = input("R");
- ShaderInput *green_in = input("G");
- ShaderInput *blue_in = input("B");
- ShaderOutput *color_out = output("Image");
+ ShaderInput *red_in = input("R");
+ ShaderInput *green_in = input("G");
+ ShaderInput *blue_in = input("B");
+ ShaderOutput *color_out = output("Image");
- compiler.add_node(NODE_COMBINE_VECTOR,
- compiler.stack_assign(red_in), 0,
- compiler.stack_assign(color_out));
+ compiler.add_node(
+ NODE_COMBINE_VECTOR, compiler.stack_assign(red_in), 0, compiler.stack_assign(color_out));
- compiler.add_node(NODE_COMBINE_VECTOR,
- compiler.stack_assign(green_in), 1,
- compiler.stack_assign(color_out));
+ compiler.add_node(
+ NODE_COMBINE_VECTOR, compiler.stack_assign(green_in), 1, compiler.stack_assign(color_out));
- compiler.add_node(NODE_COMBINE_VECTOR,
- compiler.stack_assign(blue_in), 2,
- compiler.stack_assign(color_out));
+ compiler.add_node(
+ NODE_COMBINE_VECTOR, compiler.stack_assign(blue_in), 2, compiler.stack_assign(color_out));
}
-void CombineRGBNode::compile(OSLCompiler& compiler)
+void CombineRGBNode::compile(OSLCompiler &compiler)
{
- compiler.add(this, "node_combine_rgb");
+ compiler.add(this, "node_combine_rgb");
}
/* Combine XYZ */
NODE_DEFINE(CombineXYZNode)
{
- NodeType* type = NodeType::add("combine_xyz", create, NodeType::SHADER);
+ NodeType *type = NodeType::add("combine_xyz", create, NodeType::SHADER);
- SOCKET_IN_FLOAT(x, "X", 0.0f);
- SOCKET_IN_FLOAT(y, "Y", 0.0f);
- SOCKET_IN_FLOAT(z, "Z", 0.0f);
+ SOCKET_IN_FLOAT(x, "X", 0.0f);
+ SOCKET_IN_FLOAT(y, "Y", 0.0f);
+ SOCKET_IN_FLOAT(z, "Z", 0.0f);
- SOCKET_OUT_VECTOR(vector, "Vector");
+ SOCKET_OUT_VECTOR(vector, "Vector");
- return type;
+ return type;
}
-CombineXYZNode::CombineXYZNode()
-: ShaderNode(node_type)
+CombineXYZNode::CombineXYZNode() : ShaderNode(node_type)
{
}
-void CombineXYZNode::constant_fold(const ConstantFolder& folder)
+void CombineXYZNode::constant_fold(const ConstantFolder &folder)
{
- if(folder.all_inputs_constant()) {
- folder.make_constant(make_float3(x, y, z));
- }
+ if (folder.all_inputs_constant()) {
+ folder.make_constant(make_float3(x, y, z));
+ }
}
-void CombineXYZNode::compile(SVMCompiler& compiler)
+void CombineXYZNode::compile(SVMCompiler &compiler)
{
- ShaderInput *x_in = input("X");
- ShaderInput *y_in = input("Y");
- ShaderInput *z_in = input("Z");
- ShaderOutput *vector_out = output("Vector");
+ ShaderInput *x_in = input("X");
+ ShaderInput *y_in = input("Y");
+ ShaderInput *z_in = input("Z");
+ ShaderOutput *vector_out = output("Vector");
- compiler.add_node(NODE_COMBINE_VECTOR,
- compiler.stack_assign(x_in), 0,
- compiler.stack_assign(vector_out));
+ compiler.add_node(
+ NODE_COMBINE_VECTOR, compiler.stack_assign(x_in), 0, compiler.stack_assign(vector_out));
- compiler.add_node(NODE_COMBINE_VECTOR,
- compiler.stack_assign(y_in), 1,
- compiler.stack_assign(vector_out));
+ compiler.add_node(
+ NODE_COMBINE_VECTOR, compiler.stack_assign(y_in), 1, compiler.stack_assign(vector_out));
- compiler.add_node(NODE_COMBINE_VECTOR,
- compiler.stack_assign(z_in), 2,
- compiler.stack_assign(vector_out));
+ compiler.add_node(
+ NODE_COMBINE_VECTOR, compiler.stack_assign(z_in), 2, compiler.stack_assign(vector_out));
}
-void CombineXYZNode::compile(OSLCompiler& compiler)
+void CombineXYZNode::compile(OSLCompiler &compiler)
{
- compiler.add(this, "node_combine_xyz");
+ compiler.add(this, "node_combine_xyz");
}
/* Combine HSV */
NODE_DEFINE(CombineHSVNode)
{
- NodeType* type = NodeType::add("combine_hsv", create, NodeType::SHADER);
+ NodeType *type = NodeType::add("combine_hsv", create, NodeType::SHADER);
- SOCKET_IN_FLOAT(h, "H", 0.0f);
- SOCKET_IN_FLOAT(s, "S", 0.0f);
- SOCKET_IN_FLOAT(v, "V", 0.0f);
+ SOCKET_IN_FLOAT(h, "H", 0.0f);
+ SOCKET_IN_FLOAT(s, "S", 0.0f);
+ SOCKET_IN_FLOAT(v, "V", 0.0f);
- SOCKET_OUT_COLOR(color, "Color");
+ SOCKET_OUT_COLOR(color, "Color");
- return type;
+ return type;
}
-CombineHSVNode::CombineHSVNode()
-: ShaderNode(node_type)
+CombineHSVNode::CombineHSVNode() : ShaderNode(node_type)
{
}
-void CombineHSVNode::constant_fold(const ConstantFolder& folder)
+void CombineHSVNode::constant_fold(const ConstantFolder &folder)
{
- if(folder.all_inputs_constant()) {
- folder.make_constant(hsv_to_rgb(make_float3(h, s, v)));
- }
+ if (folder.all_inputs_constant()) {
+ folder.make_constant(hsv_to_rgb(make_float3(h, s, v)));
+ }
}
-void CombineHSVNode::compile(SVMCompiler& compiler)
+void CombineHSVNode::compile(SVMCompiler &compiler)
{
- ShaderInput *hue_in = input("H");
- ShaderInput *saturation_in = input("S");
- ShaderInput *value_in = input("V");
- ShaderOutput *color_out = output("Color");
+ ShaderInput *hue_in = input("H");
+ ShaderInput *saturation_in = input("S");
+ ShaderInput *value_in = input("V");
+ ShaderOutput *color_out = output("Color");
- compiler.add_node(NODE_COMBINE_HSV,
- compiler.stack_assign(hue_in),
- compiler.stack_assign(saturation_in),
- compiler.stack_assign(value_in));
- compiler.add_node(NODE_COMBINE_HSV,
- compiler.stack_assign(color_out));
+ compiler.add_node(NODE_COMBINE_HSV,
+ compiler.stack_assign(hue_in),
+ compiler.stack_assign(saturation_in),
+ compiler.stack_assign(value_in));
+ compiler.add_node(NODE_COMBINE_HSV, compiler.stack_assign(color_out));
}
-void CombineHSVNode::compile(OSLCompiler& compiler)
+void CombineHSVNode::compile(OSLCompiler &compiler)
{
- compiler.add(this, "node_combine_hsv");
+ compiler.add(this, "node_combine_hsv");
}
/* Gamma */
NODE_DEFINE(GammaNode)
{
- NodeType* type = NodeType::add("gamma", create, NodeType::SHADER);
+ NodeType *type = NodeType::add("gamma", create, NodeType::SHADER);
- SOCKET_IN_COLOR(color, "Color", make_float3(0.0f, 0.0f, 0.0f));
- SOCKET_IN_FLOAT(gamma, "Gamma", 1.0f);
- SOCKET_OUT_COLOR(color, "Color");
+ SOCKET_IN_COLOR(color, "Color", make_float3(0.0f, 0.0f, 0.0f));
+ SOCKET_IN_FLOAT(gamma, "Gamma", 1.0f);
+ SOCKET_OUT_COLOR(color, "Color");
- return type;
+ return type;
}
-GammaNode::GammaNode()
-: ShaderNode(node_type)
+GammaNode::GammaNode() : ShaderNode(node_type)
{
}
-void GammaNode::constant_fold(const ConstantFolder& folder)
+void GammaNode::constant_fold(const ConstantFolder &folder)
{
- if(folder.all_inputs_constant()) {
- folder.make_constant(svm_math_gamma_color(color, gamma));
- }
- else {
- ShaderInput *color_in = input("Color");
- ShaderInput *gamma_in = input("Gamma");
+ if (folder.all_inputs_constant()) {
+ folder.make_constant(svm_math_gamma_color(color, gamma));
+ }
+ else {
+ ShaderInput *color_in = input("Color");
+ ShaderInput *gamma_in = input("Gamma");
- /* 1 ^ X == X ^ 0 == 1 */
- if(folder.is_one(color_in) || folder.is_zero(gamma_in)) {
- folder.make_one();
- }
- /* X ^ 1 == X */
- else if(folder.is_one(gamma_in)) {
- folder.try_bypass_or_make_constant(color_in, false);
- }
- }
+ /* 1 ^ X == X ^ 0 == 1 */
+ if (folder.is_one(color_in) || folder.is_zero(gamma_in)) {
+ folder.make_one();
+ }
+ /* X ^ 1 == X */
+ else if (folder.is_one(gamma_in)) {
+ folder.try_bypass_or_make_constant(color_in, false);
+ }
+ }
}
-void GammaNode::compile(SVMCompiler& compiler)
+void GammaNode::compile(SVMCompiler &compiler)
{
- ShaderInput *color_in = input("Color");
- ShaderInput *gamma_in = input("Gamma");
- ShaderOutput *color_out = output("Color");
+ ShaderInput *color_in = input("Color");
+ ShaderInput *gamma_in = input("Gamma");
+ ShaderOutput *color_out = output("Color");
- compiler.add_node(NODE_GAMMA,
- compiler.stack_assign(gamma_in),
- compiler.stack_assign(color_in),
- compiler.stack_assign(color_out));
+ compiler.add_node(NODE_GAMMA,
+ compiler.stack_assign(gamma_in),
+ compiler.stack_assign(color_in),
+ compiler.stack_assign(color_out));
}
-void GammaNode::compile(OSLCompiler& compiler)
+void GammaNode::compile(OSLCompiler &compiler)
{
- compiler.add(this, "node_gamma");
+ compiler.add(this, "node_gamma");
}
/* Bright Contrast */
NODE_DEFINE(BrightContrastNode)
{
- NodeType* type = NodeType::add("brightness_contrast", create, NodeType::SHADER);
+ NodeType *type = NodeType::add("brightness_contrast", create, NodeType::SHADER);
- SOCKET_IN_COLOR(color, "Color", make_float3(0.0f, 0.0f, 0.0f));
- SOCKET_IN_FLOAT(bright, "Bright", 0.0f);
- SOCKET_IN_FLOAT(contrast, "Contrast", 0.0f);
+ SOCKET_IN_COLOR(color, "Color", make_float3(0.0f, 0.0f, 0.0f));
+ SOCKET_IN_FLOAT(bright, "Bright", 0.0f);
+ SOCKET_IN_FLOAT(contrast, "Contrast", 0.0f);
- SOCKET_OUT_COLOR(color, "Color");
+ SOCKET_OUT_COLOR(color, "Color");
- return type;
+ return type;
}
-BrightContrastNode::BrightContrastNode()
-: ShaderNode(node_type)
+BrightContrastNode::BrightContrastNode() : ShaderNode(node_type)
{
}
-void BrightContrastNode::constant_fold(const ConstantFolder& folder)
+void BrightContrastNode::constant_fold(const ConstantFolder &folder)
{
- if(folder.all_inputs_constant()) {
- folder.make_constant(svm_brightness_contrast(color, bright, contrast));
- }
+ if (folder.all_inputs_constant()) {
+ folder.make_constant(svm_brightness_contrast(color, bright, contrast));
+ }
}
-void BrightContrastNode::compile(SVMCompiler& compiler)
+void BrightContrastNode::compile(SVMCompiler &compiler)
{
- ShaderInput *color_in = input("Color");
- ShaderInput *bright_in = input("Bright");
- ShaderInput *contrast_in = input("Contrast");
- ShaderOutput *color_out = output("Color");
+ ShaderInput *color_in = input("Color");
+ ShaderInput *bright_in = input("Bright");
+ ShaderInput *contrast_in = input("Contrast");
+ ShaderOutput *color_out = output("Color");
- compiler.add_node(NODE_BRIGHTCONTRAST,
- compiler.stack_assign(color_in),
- compiler.stack_assign(color_out),
- compiler.encode_uchar4(
- compiler.stack_assign(bright_in),
- compiler.stack_assign(contrast_in)));
+ compiler.add_node(NODE_BRIGHTCONTRAST,
+ compiler.stack_assign(color_in),
+ compiler.stack_assign(color_out),
+ compiler.encode_uchar4(compiler.stack_assign(bright_in),
+ compiler.stack_assign(contrast_in)));
}
-void BrightContrastNode::compile(OSLCompiler& compiler)
+void BrightContrastNode::compile(OSLCompiler &compiler)
{
- compiler.add(this, "node_brightness");
+ compiler.add(this, "node_brightness");
}
/* Separate RGB */
NODE_DEFINE(SeparateRGBNode)
{
- NodeType* type = NodeType::add("separate_rgb", create, NodeType::SHADER);
+ NodeType *type = NodeType::add("separate_rgb", create, NodeType::SHADER);
- SOCKET_IN_COLOR(color, "Image", make_float3(0.0f, 0.0f, 0.0f));
+ SOCKET_IN_COLOR(color, "Image", make_float3(0.0f, 0.0f, 0.0f));
- SOCKET_OUT_FLOAT(r, "R");
- SOCKET_OUT_FLOAT(g, "G");
- SOCKET_OUT_FLOAT(b, "B");
+ SOCKET_OUT_FLOAT(r, "R");
+ SOCKET_OUT_FLOAT(g, "G");
+ SOCKET_OUT_FLOAT(b, "B");
- return type;
+ return type;
}
-SeparateRGBNode::SeparateRGBNode()
-: ShaderNode(node_type)
+SeparateRGBNode::SeparateRGBNode() : ShaderNode(node_type)
{
}
-void SeparateRGBNode::constant_fold(const ConstantFolder& folder)
+void SeparateRGBNode::constant_fold(const ConstantFolder &folder)
{
- if(folder.all_inputs_constant()) {
- for(int channel = 0; channel < 3; channel++) {
- if(outputs[channel] == folder.output) {
- folder.make_constant(color[channel]);
- return;
- }
- }
- }
+ if (folder.all_inputs_constant()) {
+ for (int channel = 0; channel < 3; channel++) {
+ if (outputs[channel] == folder.output) {
+ folder.make_constant(color[channel]);
+ return;
+ }
+ }
+ }
}
-void SeparateRGBNode::compile(SVMCompiler& compiler)
+void SeparateRGBNode::compile(SVMCompiler &compiler)
{
- ShaderInput *color_in = input("Image");
- ShaderOutput *red_out = output("R");
- ShaderOutput *green_out = output("G");
- ShaderOutput *blue_out = output("B");
+ ShaderInput *color_in = input("Image");
+ ShaderOutput *red_out = output("R");
+ ShaderOutput *green_out = output("G");
+ ShaderOutput *blue_out = output("B");
- compiler.add_node(NODE_SEPARATE_VECTOR,
- compiler.stack_assign(color_in), 0,
- compiler.stack_assign(red_out));
+ compiler.add_node(
+ NODE_SEPARATE_VECTOR, compiler.stack_assign(color_in), 0, compiler.stack_assign(red_out));
- compiler.add_node(NODE_SEPARATE_VECTOR,
- compiler.stack_assign(color_in), 1,
- compiler.stack_assign(green_out));
+ compiler.add_node(
+ NODE_SEPARATE_VECTOR, compiler.stack_assign(color_in), 1, compiler.stack_assign(green_out));
- compiler.add_node(NODE_SEPARATE_VECTOR,
- compiler.stack_assign(color_in), 2,
- compiler.stack_assign(blue_out));
+ compiler.add_node(
+ NODE_SEPARATE_VECTOR, compiler.stack_assign(color_in), 2, compiler.stack_assign(blue_out));
}
-void SeparateRGBNode::compile(OSLCompiler& compiler)
+void SeparateRGBNode::compile(OSLCompiler &compiler)
{
- compiler.add(this, "node_separate_rgb");
+ compiler.add(this, "node_separate_rgb");
}
/* Separate XYZ */
NODE_DEFINE(SeparateXYZNode)
{
- NodeType* type = NodeType::add("separate_xyz", create, NodeType::SHADER);
+ NodeType *type = NodeType::add("separate_xyz", create, NodeType::SHADER);
- SOCKET_IN_COLOR(vector, "Vector", make_float3(0.0f, 0.0f, 0.0f));
+ SOCKET_IN_COLOR(vector, "Vector", make_float3(0.0f, 0.0f, 0.0f));
- SOCKET_OUT_FLOAT(x, "X");
- SOCKET_OUT_FLOAT(y, "Y");
- SOCKET_OUT_FLOAT(z, "Z");
+ SOCKET_OUT_FLOAT(x, "X");
+ SOCKET_OUT_FLOAT(y, "Y");
+ SOCKET_OUT_FLOAT(z, "Z");
- return type;
+ return type;
}
-SeparateXYZNode::SeparateXYZNode()
-: ShaderNode(node_type)
+SeparateXYZNode::SeparateXYZNode() : ShaderNode(node_type)
{
}
-void SeparateXYZNode::constant_fold(const ConstantFolder& folder)
+void SeparateXYZNode::constant_fold(const ConstantFolder &folder)
{
- if(folder.all_inputs_constant()) {
- for(int channel = 0; channel < 3; channel++) {
- if(outputs[channel] == folder.output) {
- folder.make_constant(vector[channel]);
- return;
- }
- }
- }
+ if (folder.all_inputs_constant()) {
+ for (int channel = 0; channel < 3; channel++) {
+ if (outputs[channel] == folder.output) {
+ folder.make_constant(vector[channel]);
+ return;
+ }
+ }
+ }
}
-void SeparateXYZNode::compile(SVMCompiler& compiler)
+void SeparateXYZNode::compile(SVMCompiler &compiler)
{
- ShaderInput *vector_in = input("Vector");
- ShaderOutput *x_out = output("X");
- ShaderOutput *y_out = output("Y");
- ShaderOutput *z_out = output("Z");
+ ShaderInput *vector_in = input("Vector");
+ ShaderOutput *x_out = output("X");
+ ShaderOutput *y_out = output("Y");
+ ShaderOutput *z_out = output("Z");
- compiler.add_node(NODE_SEPARATE_VECTOR,
- compiler.stack_assign(vector_in), 0,
- compiler.stack_assign(x_out));
+ compiler.add_node(
+ NODE_SEPARATE_VECTOR, compiler.stack_assign(vector_in), 0, compiler.stack_assign(x_out));
- compiler.add_node(NODE_SEPARATE_VECTOR,
- compiler.stack_assign(vector_in), 1,
- compiler.stack_assign(y_out));
+ compiler.add_node(
+ NODE_SEPARATE_VECTOR, compiler.stack_assign(vector_in), 1, compiler.stack_assign(y_out));
- compiler.add_node(NODE_SEPARATE_VECTOR,
- compiler.stack_assign(vector_in), 2,
- compiler.stack_assign(z_out));
+ compiler.add_node(
+ NODE_SEPARATE_VECTOR, compiler.stack_assign(vector_in), 2, compiler.stack_assign(z_out));
}
-void SeparateXYZNode::compile(OSLCompiler& compiler)
+void SeparateXYZNode::compile(OSLCompiler &compiler)
{
- compiler.add(this, "node_separate_xyz");
+ compiler.add(this, "node_separate_xyz");
}
/* Separate HSV */
NODE_DEFINE(SeparateHSVNode)
{
- NodeType* type = NodeType::add("separate_hsv", create, NodeType::SHADER);
+ NodeType *type = NodeType::add("separate_hsv", create, NodeType::SHADER);
- SOCKET_IN_COLOR(color, "Color", make_float3(0.0f, 0.0f, 0.0f));
+ SOCKET_IN_COLOR(color, "Color", make_float3(0.0f, 0.0f, 0.0f));
- SOCKET_OUT_FLOAT(h, "H");
- SOCKET_OUT_FLOAT(s, "S");
- SOCKET_OUT_FLOAT(v, "V");
+ SOCKET_OUT_FLOAT(h, "H");
+ SOCKET_OUT_FLOAT(s, "S");
+ SOCKET_OUT_FLOAT(v, "V");
- return type;
+ return type;
}
-SeparateHSVNode::SeparateHSVNode()
-: ShaderNode(node_type)
+SeparateHSVNode::SeparateHSVNode() : ShaderNode(node_type)
{
}
-void SeparateHSVNode::constant_fold(const ConstantFolder& folder)
+void SeparateHSVNode::constant_fold(const ConstantFolder &folder)
{
- if(folder.all_inputs_constant()) {
- float3 hsv = rgb_to_hsv(color);
+ if (folder.all_inputs_constant()) {
+ float3 hsv = rgb_to_hsv(color);
- for(int channel = 0; channel < 3; channel++) {
- if(outputs[channel] == folder.output) {
- folder.make_constant(hsv[channel]);
- return;
- }
- }
- }
+ for (int channel = 0; channel < 3; channel++) {
+ if (outputs[channel] == folder.output) {
+ folder.make_constant(hsv[channel]);
+ return;
+ }
+ }
+ }
}
-void SeparateHSVNode::compile(SVMCompiler& compiler)
+void SeparateHSVNode::compile(SVMCompiler &compiler)
{
- ShaderInput *color_in = input("Color");
- ShaderOutput *hue_out = output("H");
- ShaderOutput *saturation_out = output("S");
- ShaderOutput *value_out = output("V");
+ ShaderInput *color_in = input("Color");
+ ShaderOutput *hue_out = output("H");
+ ShaderOutput *saturation_out = output("S");
+ ShaderOutput *value_out = output("V");
- compiler.add_node(NODE_SEPARATE_HSV,
- compiler.stack_assign(color_in),
- compiler.stack_assign(hue_out),
- compiler.stack_assign(saturation_out));
- compiler.add_node(NODE_SEPARATE_HSV,
- compiler.stack_assign(value_out));
+ compiler.add_node(NODE_SEPARATE_HSV,
+ compiler.stack_assign(color_in),
+ compiler.stack_assign(hue_out),
+ compiler.stack_assign(saturation_out));
+ compiler.add_node(NODE_SEPARATE_HSV, compiler.stack_assign(value_out));
}
-void SeparateHSVNode::compile(OSLCompiler& compiler)
+void SeparateHSVNode::compile(OSLCompiler &compiler)
{
- compiler.add(this, "node_separate_hsv");
+ compiler.add(this, "node_separate_hsv");
}
/* Hue Saturation Value */
NODE_DEFINE(HSVNode)
{
- NodeType* type = NodeType::add("hsv", create, NodeType::SHADER);
+ NodeType *type = NodeType::add("hsv", create, NodeType::SHADER);
- SOCKET_IN_FLOAT(hue, "Hue", 0.5f);
- SOCKET_IN_FLOAT(saturation, "Saturation", 1.0f);
- SOCKET_IN_FLOAT(value, "Value", 1.0f);
- SOCKET_IN_FLOAT(fac, "Fac", 1.0f);
- SOCKET_IN_COLOR(color, "Color", make_float3(0.0f, 0.0f, 0.0f));
+ SOCKET_IN_FLOAT(hue, "Hue", 0.5f);
+ SOCKET_IN_FLOAT(saturation, "Saturation", 1.0f);
+ SOCKET_IN_FLOAT(value, "Value", 1.0f);
+ SOCKET_IN_FLOAT(fac, "Fac", 1.0f);
+ SOCKET_IN_COLOR(color, "Color", make_float3(0.0f, 0.0f, 0.0f));
- SOCKET_OUT_COLOR(color, "Color");
+ SOCKET_OUT_COLOR(color, "Color");
- return type;
+ return type;
}
-HSVNode::HSVNode()
-: ShaderNode(node_type)
+HSVNode::HSVNode() : ShaderNode(node_type)
{
}
-void HSVNode::compile(SVMCompiler& compiler)
+void HSVNode::compile(SVMCompiler &compiler)
{
- ShaderInput *hue_in = input("Hue");
- ShaderInput *saturation_in = input("Saturation");
- ShaderInput *value_in = input("Value");
- ShaderInput *fac_in = input("Fac");
- ShaderInput *color_in = input("Color");
- ShaderOutput *color_out = output("Color");
+ ShaderInput *hue_in = input("Hue");
+ ShaderInput *saturation_in = input("Saturation");
+ ShaderInput *value_in = input("Value");
+ ShaderInput *fac_in = input("Fac");
+ ShaderInput *color_in = input("Color");
+ ShaderOutput *color_out = output("Color");
- compiler.add_node(NODE_HSV,
- compiler.encode_uchar4(
- compiler.stack_assign(color_in),
- compiler.stack_assign(fac_in),
- compiler.stack_assign(color_out)),
- compiler.encode_uchar4(
- compiler.stack_assign(hue_in),
- compiler.stack_assign(saturation_in),
- compiler.stack_assign(value_in)));
+ compiler.add_node(NODE_HSV,
+ compiler.encode_uchar4(compiler.stack_assign(color_in),
+ compiler.stack_assign(fac_in),
+ compiler.stack_assign(color_out)),
+ compiler.encode_uchar4(compiler.stack_assign(hue_in),
+ compiler.stack_assign(saturation_in),
+ compiler.stack_assign(value_in)));
}
-void HSVNode::compile(OSLCompiler& compiler)
+void HSVNode::compile(OSLCompiler &compiler)
{
- compiler.add(this, "node_hsv");
+ compiler.add(this, "node_hsv");
}
/* Attribute */
NODE_DEFINE(AttributeNode)
{
- NodeType* type = NodeType::add("attribute", create, NodeType::SHADER);
+ NodeType *type = NodeType::add("attribute", create, NodeType::SHADER);
- SOCKET_STRING(attribute, "Attribute", ustring());
+ SOCKET_STRING(attribute, "Attribute", ustring());
- SOCKET_OUT_COLOR(color, "Color");
- SOCKET_OUT_VECTOR(vector, "Vector");
- SOCKET_OUT_FLOAT(fac, "Fac");
+ SOCKET_OUT_COLOR(color, "Color");
+ SOCKET_OUT_VECTOR(vector, "Vector");
+ SOCKET_OUT_FLOAT(fac, "Fac");
- return type;
+ return type;
}
-AttributeNode::AttributeNode()
-: ShaderNode(node_type)
+AttributeNode::AttributeNode() : ShaderNode(node_type)
{
}
void AttributeNode::attributes(Shader *shader, AttributeRequestSet *attributes)
{
- ShaderOutput *color_out = output("Color");
- ShaderOutput *vector_out = output("Vector");
- ShaderOutput *fac_out = output("Fac");
+ ShaderOutput *color_out = output("Color");
+ ShaderOutput *vector_out = output("Vector");
+ ShaderOutput *fac_out = output("Fac");
- if(!color_out->links.empty() || !vector_out->links.empty() || !fac_out->links.empty()) {
- attributes->add_standard(attribute);
- }
+ if (!color_out->links.empty() || !vector_out->links.empty() || !fac_out->links.empty()) {
+ attributes->add_standard(attribute);
+ }
- if(shader->has_volume) {
- attributes->add(ATTR_STD_GENERATED_TRANSFORM);
- }
+ if (shader->has_volume) {
+ attributes->add(ATTR_STD_GENERATED_TRANSFORM);
+ }
- ShaderNode::attributes(shader, attributes);
+ ShaderNode::attributes(shader, attributes);
}
-void AttributeNode::compile(SVMCompiler& compiler)
+void AttributeNode::compile(SVMCompiler &compiler)
{
- ShaderOutput *color_out = output("Color");
- ShaderOutput *vector_out = output("Vector");
- ShaderOutput *fac_out = output("Fac");
- ShaderNodeType attr_node = NODE_ATTR;
- int attr = compiler.attribute_standard(attribute);
+ ShaderOutput *color_out = output("Color");
+ ShaderOutput *vector_out = output("Vector");
+ ShaderOutput *fac_out = output("Fac");
+ ShaderNodeType attr_node = NODE_ATTR;
+ int attr = compiler.attribute_standard(attribute);
- if(bump == SHADER_BUMP_DX)
- attr_node = NODE_ATTR_BUMP_DX;
- else if(bump == SHADER_BUMP_DY)
- attr_node = NODE_ATTR_BUMP_DY;
+ if (bump == SHADER_BUMP_DX)
+ attr_node = NODE_ATTR_BUMP_DX;
+ else if (bump == SHADER_BUMP_DY)
+ attr_node = NODE_ATTR_BUMP_DY;
- if(!color_out->links.empty() || !vector_out->links.empty()) {
- if(!color_out->links.empty()) {
- compiler.add_node(attr_node, attr, compiler.stack_assign(color_out), NODE_ATTR_FLOAT3);
- }
- if(!vector_out->links.empty()) {
- compiler.add_node(attr_node, attr, compiler.stack_assign(vector_out), NODE_ATTR_FLOAT3);
- }
- }
+ if (!color_out->links.empty() || !vector_out->links.empty()) {
+ if (!color_out->links.empty()) {
+ compiler.add_node(attr_node, attr, compiler.stack_assign(color_out), NODE_ATTR_FLOAT3);
+ }
+ if (!vector_out->links.empty()) {
+ compiler.add_node(attr_node, attr, compiler.stack_assign(vector_out), NODE_ATTR_FLOAT3);
+ }
+ }
- if(!fac_out->links.empty()) {
- compiler.add_node(attr_node, attr, compiler.stack_assign(fac_out), NODE_ATTR_FLOAT);
- }
+ if (!fac_out->links.empty()) {
+ compiler.add_node(attr_node, attr, compiler.stack_assign(fac_out), NODE_ATTR_FLOAT);
+ }
}
-void AttributeNode::compile(OSLCompiler& compiler)
+void AttributeNode::compile(OSLCompiler &compiler)
{
- if(bump == SHADER_BUMP_DX)
- compiler.parameter("bump_offset", "dx");
- else if(bump == SHADER_BUMP_DY)
- compiler.parameter("bump_offset", "dy");
- else
- compiler.parameter("bump_offset", "center");
+ if (bump == SHADER_BUMP_DX)
+ compiler.parameter("bump_offset", "dx");
+ else if (bump == SHADER_BUMP_DY)
+ compiler.parameter("bump_offset", "dy");
+ else
+ compiler.parameter("bump_offset", "center");
- if(Attribute::name_standard(attribute.c_str()) != ATTR_STD_NONE)
- compiler.parameter("name", (string("geom:") + attribute.c_str()).c_str());
- else
- compiler.parameter("name", attribute.c_str());
+ if (Attribute::name_standard(attribute.c_str()) != ATTR_STD_NONE)
+ compiler.parameter("name", (string("geom:") + attribute.c_str()).c_str());
+ else
+ compiler.parameter("name", attribute.c_str());
- compiler.add(this, "node_attribute");
+ compiler.add(this, "node_attribute");
}
/* Camera */
NODE_DEFINE(CameraNode)
{
- NodeType* type = NodeType::add("camera_info", create, NodeType::SHADER);
+ NodeType *type = NodeType::add("camera_info", create, NodeType::SHADER);
- SOCKET_OUT_VECTOR(view_vector, "View Vector");
- SOCKET_OUT_FLOAT(view_z_depth, "View Z Depth");
- SOCKET_OUT_FLOAT(view_distance, "View Distance");
+ SOCKET_OUT_VECTOR(view_vector, "View Vector");
+ SOCKET_OUT_FLOAT(view_z_depth, "View Z Depth");
+ SOCKET_OUT_FLOAT(view_distance, "View Distance");
- return type;
+ return type;
}
-CameraNode::CameraNode()
-: ShaderNode(node_type)
+CameraNode::CameraNode() : ShaderNode(node_type)
{
}
-void CameraNode::compile(SVMCompiler& compiler)
+void CameraNode::compile(SVMCompiler &compiler)
{
- ShaderOutput *vector_out = output("View Vector");
- ShaderOutput *z_depth_out = output("View Z Depth");
- ShaderOutput *distance_out = output("View Distance");
+ ShaderOutput *vector_out = output("View Vector");
+ ShaderOutput *z_depth_out = output("View Z Depth");
+ ShaderOutput *distance_out = output("View Distance");
- compiler.add_node(NODE_CAMERA,
- compiler.stack_assign(vector_out),
- compiler.stack_assign(z_depth_out),
- compiler.stack_assign(distance_out));
+ compiler.add_node(NODE_CAMERA,
+ compiler.stack_assign(vector_out),
+ compiler.stack_assign(z_depth_out),
+ compiler.stack_assign(distance_out));
}
-void CameraNode::compile(OSLCompiler& compiler)
+void CameraNode::compile(OSLCompiler &compiler)
{
- compiler.add(this, "node_camera");
+ compiler.add(this, "node_camera");
}
/* Fresnel */
NODE_DEFINE(FresnelNode)
{
- NodeType* type = NodeType::add("fresnel", create, NodeType::SHADER);
+ NodeType *type = NodeType::add("fresnel", create, NodeType::SHADER);
- SOCKET_IN_NORMAL(normal, "Normal", make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_NORMAL | SocketType::OSL_INTERNAL);
- SOCKET_IN_FLOAT(IOR, "IOR", 1.45f);
+ SOCKET_IN_NORMAL(normal,
+ "Normal",
+ make_float3(0.0f, 0.0f, 0.0f),
+ SocketType::LINK_NORMAL | SocketType::OSL_INTERNAL);
+ SOCKET_IN_FLOAT(IOR, "IOR", 1.45f);
- SOCKET_OUT_FLOAT(fac, "Fac");
+ SOCKET_OUT_FLOAT(fac, "Fac");
- return type;
+ return type;
}
-FresnelNode::FresnelNode()
-: ShaderNode(node_type)
+FresnelNode::FresnelNode() : ShaderNode(node_type)
{
}
-void FresnelNode::compile(SVMCompiler& compiler)
+void FresnelNode::compile(SVMCompiler &compiler)
{
- ShaderInput *normal_in = input("Normal");
- ShaderInput *IOR_in = input("IOR");
- ShaderOutput *fac_out = output("Fac");
+ ShaderInput *normal_in = input("Normal");
+ ShaderInput *IOR_in = input("IOR");
+ ShaderOutput *fac_out = output("Fac");
- compiler.add_node(NODE_FRESNEL,
- compiler.stack_assign(IOR_in),
- __float_as_int(IOR),
- compiler.encode_uchar4(
- compiler.stack_assign_if_linked(normal_in),
- compiler.stack_assign(fac_out)));
+ compiler.add_node(NODE_FRESNEL,
+ compiler.stack_assign(IOR_in),
+ __float_as_int(IOR),
+ compiler.encode_uchar4(compiler.stack_assign_if_linked(normal_in),
+ compiler.stack_assign(fac_out)));
}
-void FresnelNode::compile(OSLCompiler& compiler)
+void FresnelNode::compile(OSLCompiler &compiler)
{
- compiler.add(this, "node_fresnel");
+ compiler.add(this, "node_fresnel");
}
/* Layer Weight */
NODE_DEFINE(LayerWeightNode)
{
- NodeType* type = NodeType::add("layer_weight", create, NodeType::SHADER);
+ NodeType *type = NodeType::add("layer_weight", create, NodeType::SHADER);
- SOCKET_IN_NORMAL(normal, "Normal", make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_NORMAL | SocketType::OSL_INTERNAL);
- SOCKET_IN_FLOAT(blend, "Blend", 0.5f);
+ SOCKET_IN_NORMAL(normal,
+ "Normal",
+ make_float3(0.0f, 0.0f, 0.0f),
+ SocketType::LINK_NORMAL | SocketType::OSL_INTERNAL);
+ SOCKET_IN_FLOAT(blend, "Blend", 0.5f);
- SOCKET_OUT_FLOAT(fresnel, "Fresnel");
- SOCKET_OUT_FLOAT(facing, "Facing");
+ SOCKET_OUT_FLOAT(fresnel, "Fresnel");
+ SOCKET_OUT_FLOAT(facing, "Facing");
- return type;
+ return type;
}
-LayerWeightNode::LayerWeightNode()
-: ShaderNode(node_type)
+LayerWeightNode::LayerWeightNode() : ShaderNode(node_type)
{
}
-void LayerWeightNode::compile(SVMCompiler& compiler)
+void LayerWeightNode::compile(SVMCompiler &compiler)
{
- ShaderInput *normal_in = input("Normal");
- ShaderInput *blend_in = input("Blend");
- ShaderOutput *fresnel_out = output("Fresnel");
- ShaderOutput *facing_out = output("Facing");
+ ShaderInput *normal_in = input("Normal");
+ ShaderInput *blend_in = input("Blend");
+ ShaderOutput *fresnel_out = output("Fresnel");
+ ShaderOutput *facing_out = output("Facing");
- if(!fresnel_out->links.empty()) {
- compiler.add_node(NODE_LAYER_WEIGHT,
- compiler.stack_assign_if_linked(blend_in),
- __float_as_int(blend),
- compiler.encode_uchar4(NODE_LAYER_WEIGHT_FRESNEL,
- compiler.stack_assign_if_linked(normal_in),
- compiler.stack_assign(fresnel_out)));
- }
+ if (!fresnel_out->links.empty()) {
+ compiler.add_node(NODE_LAYER_WEIGHT,
+ compiler.stack_assign_if_linked(blend_in),
+ __float_as_int(blend),
+ compiler.encode_uchar4(NODE_LAYER_WEIGHT_FRESNEL,
+ compiler.stack_assign_if_linked(normal_in),
+ compiler.stack_assign(fresnel_out)));
+ }
- if(!facing_out->links.empty()) {
- compiler.add_node(NODE_LAYER_WEIGHT,
- compiler.stack_assign_if_linked(blend_in),
- __float_as_int(blend),
- compiler.encode_uchar4(NODE_LAYER_WEIGHT_FACING,
- compiler.stack_assign_if_linked(normal_in),
- compiler.stack_assign(facing_out)));
- }
+ if (!facing_out->links.empty()) {
+ compiler.add_node(NODE_LAYER_WEIGHT,
+ compiler.stack_assign_if_linked(blend_in),
+ __float_as_int(blend),
+ compiler.encode_uchar4(NODE_LAYER_WEIGHT_FACING,
+ compiler.stack_assign_if_linked(normal_in),
+ compiler.stack_assign(facing_out)));
+ }
}
-void LayerWeightNode::compile(OSLCompiler& compiler)
+void LayerWeightNode::compile(OSLCompiler &compiler)
{
- compiler.add(this, "node_layer_weight");
+ compiler.add(this, "node_layer_weight");
}
/* Wireframe */
NODE_DEFINE(WireframeNode)
{
- NodeType* type = NodeType::add("wireframe", create, NodeType::SHADER);
+ NodeType *type = NodeType::add("wireframe", create, NodeType::SHADER);
- SOCKET_BOOLEAN(use_pixel_size, "Use Pixel Size", false);
- SOCKET_IN_FLOAT(size, "Size", 0.01f);
- SOCKET_OUT_FLOAT(fac, "Fac");
+ SOCKET_BOOLEAN(use_pixel_size, "Use Pixel Size", false);
+ SOCKET_IN_FLOAT(size, "Size", 0.01f);
+ SOCKET_OUT_FLOAT(fac, "Fac");
- return type;
+ return type;
}
-WireframeNode::WireframeNode()
-: ShaderNode(node_type)
+WireframeNode::WireframeNode() : ShaderNode(node_type)
{
}
-void WireframeNode::compile(SVMCompiler& compiler)
+void WireframeNode::compile(SVMCompiler &compiler)
{
- ShaderInput *size_in = input("Size");
- ShaderOutput *fac_out = output("Fac");
- NodeBumpOffset bump_offset = NODE_BUMP_OFFSET_CENTER;
- if(bump == SHADER_BUMP_DX) {
- bump_offset = NODE_BUMP_OFFSET_DX;
- }
- else if(bump == SHADER_BUMP_DY) {
- bump_offset = NODE_BUMP_OFFSET_DY;
- }
- compiler.add_node(NODE_WIREFRAME,
- compiler.stack_assign(size_in),
- compiler.stack_assign(fac_out),
- compiler.encode_uchar4(use_pixel_size,
- bump_offset,
- 0, 0));
+ ShaderInput *size_in = input("Size");
+ ShaderOutput *fac_out = output("Fac");
+ NodeBumpOffset bump_offset = NODE_BUMP_OFFSET_CENTER;
+ if (bump == SHADER_BUMP_DX) {
+ bump_offset = NODE_BUMP_OFFSET_DX;
+ }
+ else if (bump == SHADER_BUMP_DY) {
+ bump_offset = NODE_BUMP_OFFSET_DY;
+ }
+ compiler.add_node(NODE_WIREFRAME,
+ compiler.stack_assign(size_in),
+ compiler.stack_assign(fac_out),
+ compiler.encode_uchar4(use_pixel_size, bump_offset, 0, 0));
}
-void WireframeNode::compile(OSLCompiler& compiler)
+void WireframeNode::compile(OSLCompiler &compiler)
{
- if(bump == SHADER_BUMP_DX) {
- compiler.parameter("bump_offset", "dx");
- }
- else if(bump == SHADER_BUMP_DY) {
- compiler.parameter("bump_offset", "dy");
- }
- else {
- compiler.parameter("bump_offset", "center");
- }
- compiler.parameter(this, "use_pixel_size");
- compiler.add(this, "node_wireframe");
+ if (bump == SHADER_BUMP_DX) {
+ compiler.parameter("bump_offset", "dx");
+ }
+ else if (bump == SHADER_BUMP_DY) {
+ compiler.parameter("bump_offset", "dy");
+ }
+ else {
+ compiler.parameter("bump_offset", "center");
+ }
+ compiler.parameter(this, "use_pixel_size");
+ compiler.add(this, "node_wireframe");
}
/* Wavelength */
NODE_DEFINE(WavelengthNode)
{
- NodeType* type = NodeType::add("wavelength", create, NodeType::SHADER);
+ NodeType *type = NodeType::add("wavelength", create, NodeType::SHADER);
- SOCKET_IN_FLOAT(wavelength, "Wavelength", 500.0f);
- SOCKET_OUT_COLOR(color, "Color");
+ SOCKET_IN_FLOAT(wavelength, "Wavelength", 500.0f);
+ SOCKET_OUT_COLOR(color, "Color");
- return type;
+ return type;
}
-WavelengthNode::WavelengthNode()
-: ShaderNode(node_type)
+WavelengthNode::WavelengthNode() : ShaderNode(node_type)
{
}
-void WavelengthNode::compile(SVMCompiler& compiler)
+void WavelengthNode::compile(SVMCompiler &compiler)
{
- ShaderInput *wavelength_in = input("Wavelength");
- ShaderOutput *color_out = output("Color");
+ ShaderInput *wavelength_in = input("Wavelength");
+ ShaderOutput *color_out = output("Color");
- compiler.add_node(NODE_WAVELENGTH,
- compiler.stack_assign(wavelength_in),
- compiler.stack_assign(color_out));
+ compiler.add_node(
+ NODE_WAVELENGTH, compiler.stack_assign(wavelength_in), compiler.stack_assign(color_out));
}
-void WavelengthNode::compile(OSLCompiler& compiler)
+void WavelengthNode::compile(OSLCompiler &compiler)
{
- compiler.add(this, "node_wavelength");
+ compiler.add(this, "node_wavelength");
}
/* Blackbody */
NODE_DEFINE(BlackbodyNode)
{
- NodeType* type = NodeType::add("blackbody", create, NodeType::SHADER);
+ NodeType *type = NodeType::add("blackbody", create, NodeType::SHADER);
- SOCKET_IN_FLOAT(temperature, "Temperature", 1200.0f);
- SOCKET_OUT_COLOR(color, "Color");
+ SOCKET_IN_FLOAT(temperature, "Temperature", 1200.0f);
+ SOCKET_OUT_COLOR(color, "Color");
- return type;
+ return type;
}
-BlackbodyNode::BlackbodyNode()
-: ShaderNode(node_type)
+BlackbodyNode::BlackbodyNode() : ShaderNode(node_type)
{
}
-void BlackbodyNode::constant_fold(const ConstantFolder& folder)
+void BlackbodyNode::constant_fold(const ConstantFolder &folder)
{
- if(folder.all_inputs_constant()) {
- folder.make_constant(svm_math_blackbody_color(temperature));
- }
+ if (folder.all_inputs_constant()) {
+ folder.make_constant(svm_math_blackbody_color(temperature));
+ }
}
-void BlackbodyNode::compile(SVMCompiler& compiler)
+void BlackbodyNode::compile(SVMCompiler &compiler)
{
- ShaderInput *temperature_in = input("Temperature");
- ShaderOutput *color_out = output("Color");
+ ShaderInput *temperature_in = input("Temperature");
+ ShaderOutput *color_out = output("Color");
- compiler.add_node(NODE_BLACKBODY,
- compiler.stack_assign(temperature_in),
- compiler.stack_assign(color_out));
+ compiler.add_node(
+ NODE_BLACKBODY, compiler.stack_assign(temperature_in), compiler.stack_assign(color_out));
}
-void BlackbodyNode::compile(OSLCompiler& compiler)
+void BlackbodyNode::compile(OSLCompiler &compiler)
{
- compiler.add(this, "node_blackbody");
+ compiler.add(this, "node_blackbody");
}
/* Output */
NODE_DEFINE(OutputNode)
{
- NodeType* type = NodeType::add("output", create, NodeType::SHADER);
+ NodeType *type = NodeType::add("output", create, NodeType::SHADER);
- SOCKET_IN_CLOSURE(surface, "Surface");
- SOCKET_IN_CLOSURE(volume, "Volume");
- SOCKET_IN_VECTOR(displacement, "Displacement", make_float3(0.0f, 0.0f, 0.0f));
- SOCKET_IN_NORMAL(normal, "Normal", make_float3(0.0f, 0.0f, 0.0f));
+ SOCKET_IN_CLOSURE(surface, "Surface");
+ SOCKET_IN_CLOSURE(volume, "Volume");
+ SOCKET_IN_VECTOR(displacement, "Displacement", make_float3(0.0f, 0.0f, 0.0f));
+ SOCKET_IN_NORMAL(normal, "Normal", make_float3(0.0f, 0.0f, 0.0f));
- return type;
+ return type;
}
-OutputNode::OutputNode()
-: ShaderNode(node_type)
+OutputNode::OutputNode() : ShaderNode(node_type)
{
- special_type = SHADER_SPECIAL_TYPE_OUTPUT;
+ special_type = SHADER_SPECIAL_TYPE_OUTPUT;
}
-void OutputNode::compile(SVMCompiler& compiler)
+void OutputNode::compile(SVMCompiler &compiler)
{
- if(compiler.output_type() == SHADER_TYPE_DISPLACEMENT) {
- ShaderInput *displacement_in = input("Displacement");
+ if (compiler.output_type() == SHADER_TYPE_DISPLACEMENT) {
+ ShaderInput *displacement_in = input("Displacement");
- if(displacement_in->link) {
- compiler.add_node(NODE_SET_DISPLACEMENT, compiler.stack_assign(displacement_in));
- }
- }
+ if (displacement_in->link) {
+ compiler.add_node(NODE_SET_DISPLACEMENT, compiler.stack_assign(displacement_in));
+ }
+ }
}
-void OutputNode::compile(OSLCompiler& compiler)
+void OutputNode::compile(OSLCompiler &compiler)
{
- if(compiler.output_type() == SHADER_TYPE_SURFACE)
- compiler.add(this, "node_output_surface");
- else if(compiler.output_type() == SHADER_TYPE_VOLUME)
- compiler.add(this, "node_output_volume");
- else if(compiler.output_type() == SHADER_TYPE_DISPLACEMENT)
- compiler.add(this, "node_output_displacement");
+ if (compiler.output_type() == SHADER_TYPE_SURFACE)
+ compiler.add(this, "node_output_surface");
+ else if (compiler.output_type() == SHADER_TYPE_VOLUME)
+ compiler.add(this, "node_output_volume");
+ else if (compiler.output_type() == SHADER_TYPE_DISPLACEMENT)
+ compiler.add(this, "node_output_displacement");
}
/* Math */
NODE_DEFINE(MathNode)
{
- NodeType* type = NodeType::add("math", create, NodeType::SHADER);
+ NodeType *type = NodeType::add("math", create, NodeType::SHADER);
- static NodeEnum type_enum;
- type_enum.insert("add", NODE_MATH_ADD);
- type_enum.insert("subtract", NODE_MATH_SUBTRACT);
- type_enum.insert("multiply", NODE_MATH_MULTIPLY);
- type_enum.insert("divide", NODE_MATH_DIVIDE);
- type_enum.insert("sine", NODE_MATH_SINE);
- type_enum.insert("cosine", NODE_MATH_COSINE);
- type_enum.insert("tangent", NODE_MATH_TANGENT);
- type_enum.insert("arcsine", NODE_MATH_ARCSINE);
- type_enum.insert("arccosine", NODE_MATH_ARCCOSINE);
- type_enum.insert("arctangent", NODE_MATH_ARCTANGENT);
- type_enum.insert("power", NODE_MATH_POWER);
- type_enum.insert("logarithm", NODE_MATH_LOGARITHM);
- type_enum.insert("minimum", NODE_MATH_MINIMUM);
- type_enum.insert("maximum", NODE_MATH_MAXIMUM);
- type_enum.insert("round", NODE_MATH_ROUND);
- type_enum.insert("less_than", NODE_MATH_LESS_THAN);
- type_enum.insert("greater_than", NODE_MATH_GREATER_THAN);
- type_enum.insert("modulo", NODE_MATH_MODULO);
- type_enum.insert("absolute", NODE_MATH_ABSOLUTE);
- type_enum.insert("arctan2", NODE_MATH_ARCTAN2);
- type_enum.insert("floor", NODE_MATH_FLOOR);
- type_enum.insert("ceil", NODE_MATH_CEIL);
- type_enum.insert("fract", NODE_MATH_FRACT);
- type_enum.insert("sqrt", NODE_MATH_SQRT);
- SOCKET_ENUM(type, "Type", type_enum, NODE_MATH_ADD);
+ static NodeEnum type_enum;
+ type_enum.insert("add", NODE_MATH_ADD);
+ type_enum.insert("subtract", NODE_MATH_SUBTRACT);
+ type_enum.insert("multiply", NODE_MATH_MULTIPLY);
+ type_enum.insert("divide", NODE_MATH_DIVIDE);
+ type_enum.insert("sine", NODE_MATH_SINE);
+ type_enum.insert("cosine", NODE_MATH_COSINE);
+ type_enum.insert("tangent", NODE_MATH_TANGENT);
+ type_enum.insert("arcsine", NODE_MATH_ARCSINE);
+ type_enum.insert("arccosine", NODE_MATH_ARCCOSINE);
+ type_enum.insert("arctangent", NODE_MATH_ARCTANGENT);
+ type_enum.insert("power", NODE_MATH_POWER);
+ type_enum.insert("logarithm", NODE_MATH_LOGARITHM);
+ type_enum.insert("minimum", NODE_MATH_MINIMUM);
+ type_enum.insert("maximum", NODE_MATH_MAXIMUM);
+ type_enum.insert("round", NODE_MATH_ROUND);
+ type_enum.insert("less_than", NODE_MATH_LESS_THAN);
+ type_enum.insert("greater_than", NODE_MATH_GREATER_THAN);
+ type_enum.insert("modulo", NODE_MATH_MODULO);
+ type_enum.insert("absolute", NODE_MATH_ABSOLUTE);
+ type_enum.insert("arctan2", NODE_MATH_ARCTAN2);
+ type_enum.insert("floor", NODE_MATH_FLOOR);
+ type_enum.insert("ceil", NODE_MATH_CEIL);
+ type_enum.insert("fract", NODE_MATH_FRACT);
+ type_enum.insert("sqrt", NODE_MATH_SQRT);
+ SOCKET_ENUM(type, "Type", type_enum, NODE_MATH_ADD);
- SOCKET_BOOLEAN(use_clamp, "Use Clamp", false);
+ SOCKET_BOOLEAN(use_clamp, "Use Clamp", false);
- SOCKET_IN_FLOAT(value1, "Value1", 0.0f);
- SOCKET_IN_FLOAT(value2, "Value2", 0.0f);
+ SOCKET_IN_FLOAT(value1, "Value1", 0.0f);
+ SOCKET_IN_FLOAT(value2, "Value2", 0.0f);
- SOCKET_OUT_FLOAT(value, "Value");
+ SOCKET_OUT_FLOAT(value, "Value");
- return type;
+ return type;
}
-MathNode::MathNode()
-: ShaderNode(node_type)
+MathNode::MathNode() : ShaderNode(node_type)
{
}
-void MathNode::constant_fold(const ConstantFolder& folder)
+void MathNode::constant_fold(const ConstantFolder &folder)
{
- if(folder.all_inputs_constant()) {
- folder.make_constant_clamp(svm_math(type, value1, value2), use_clamp);
- }
- else {
- folder.fold_math(type, use_clamp);
- }
+ if (folder.all_inputs_constant()) {
+ folder.make_constant_clamp(svm_math(type, value1, value2), use_clamp);
+ }
+ else {
+ folder.fold_math(type, use_clamp);
+ }
}
-void MathNode::compile(SVMCompiler& compiler)
+void MathNode::compile(SVMCompiler &compiler)
{
- ShaderInput *value1_in = input("Value1");
- ShaderInput *value2_in = input("Value2");
- ShaderOutput *value_out = output("Value");
+ ShaderInput *value1_in = input("Value1");
+ ShaderInput *value2_in = input("Value2");
+ ShaderOutput *value_out = output("Value");
- compiler.add_node(NODE_MATH, type, compiler.stack_assign(value1_in), compiler.stack_assign(value2_in));
- compiler.add_node(NODE_MATH, compiler.stack_assign(value_out));
+ compiler.add_node(
+ NODE_MATH, type, compiler.stack_assign(value1_in), compiler.stack_assign(value2_in));
+ compiler.add_node(NODE_MATH, compiler.stack_assign(value_out));
- if(use_clamp) {
- compiler.add_node(NODE_MATH, NODE_MATH_CLAMP, compiler.stack_assign(value_out));
- compiler.add_node(NODE_MATH, compiler.stack_assign(value_out));
- }
+ if (use_clamp) {
+ compiler.add_node(NODE_MATH, NODE_MATH_CLAMP, compiler.stack_assign(value_out));
+ compiler.add_node(NODE_MATH, compiler.stack_assign(value_out));
+ }
}
-void MathNode::compile(OSLCompiler& compiler)
+void MathNode::compile(OSLCompiler &compiler)
{
- compiler.parameter(this, "type");
- compiler.parameter(this, "use_clamp");
- compiler.add(this, "node_math");
+ compiler.parameter(this, "type");
+ compiler.parameter(this, "use_clamp");
+ compiler.add(this, "node_math");
}
/* VectorMath */
NODE_DEFINE(VectorMathNode)
{
- NodeType* type = NodeType::add("vector_math", create, NodeType::SHADER);
+ NodeType *type = NodeType::add("vector_math", create, NodeType::SHADER);
- static NodeEnum type_enum;
- type_enum.insert("add", NODE_VECTOR_MATH_ADD);
- type_enum.insert("subtract", NODE_VECTOR_MATH_SUBTRACT);
- type_enum.insert("average", NODE_VECTOR_MATH_AVERAGE);
- type_enum.insert("dot_product", NODE_VECTOR_MATH_DOT_PRODUCT);
- type_enum.insert("cross_product", NODE_VECTOR_MATH_CROSS_PRODUCT);
- type_enum.insert("normalize", NODE_VECTOR_MATH_NORMALIZE);
- SOCKET_ENUM(type, "Type", type_enum, NODE_VECTOR_MATH_ADD);
+ static NodeEnum type_enum;
+ type_enum.insert("add", NODE_VECTOR_MATH_ADD);
+ type_enum.insert("subtract", NODE_VECTOR_MATH_SUBTRACT);
+ type_enum.insert("average", NODE_VECTOR_MATH_AVERAGE);
+ type_enum.insert("dot_product", NODE_VECTOR_MATH_DOT_PRODUCT);
+ type_enum.insert("cross_product", NODE_VECTOR_MATH_CROSS_PRODUCT);
+ type_enum.insert("normalize", NODE_VECTOR_MATH_NORMALIZE);
+ SOCKET_ENUM(type, "Type", type_enum, NODE_VECTOR_MATH_ADD);
- SOCKET_IN_VECTOR(vector1, "Vector1", make_float3(0.0f, 0.0f, 0.0f));
- SOCKET_IN_VECTOR(vector2, "Vector2", make_float3(0.0f, 0.0f, 0.0f));
+ SOCKET_IN_VECTOR(vector1, "Vector1", make_float3(0.0f, 0.0f, 0.0f));
+ SOCKET_IN_VECTOR(vector2, "Vector2", make_float3(0.0f, 0.0f, 0.0f));
- SOCKET_OUT_FLOAT(value, "Value");
- SOCKET_OUT_VECTOR(vector, "Vector");
+ SOCKET_OUT_FLOAT(value, "Value");
+ SOCKET_OUT_VECTOR(vector, "Vector");
- return type;
+ return type;
}
-VectorMathNode::VectorMathNode()
-: ShaderNode(node_type)
+VectorMathNode::VectorMathNode() : ShaderNode(node_type)
{
}
-void VectorMathNode::constant_fold(const ConstantFolder& folder)
+void VectorMathNode::constant_fold(const ConstantFolder &folder)
{
- float value;
- float3 vector;
+ float value;
+ float3 vector;
- if(folder.all_inputs_constant()) {
- svm_vector_math(&value,
- &vector,
- type,
- vector1,
- vector2);
+ if (folder.all_inputs_constant()) {
+ svm_vector_math(&value, &vector, type, vector1, vector2);
- if(folder.output == output("Value")) {
- folder.make_constant(value);
- }
- else if(folder.output == output("Vector")) {
- folder.make_constant(vector);
- }
- }
- else {
- folder.fold_vector_math(type);
- }
+ if (folder.output == output("Value")) {
+ folder.make_constant(value);
+ }
+ else if (folder.output == output("Vector")) {
+ folder.make_constant(vector);
+ }
+ }
+ else {
+ folder.fold_vector_math(type);
+ }
}
-void VectorMathNode::compile(SVMCompiler& compiler)
+void VectorMathNode::compile(SVMCompiler &compiler)
{
- ShaderInput *vector1_in = input("Vector1");
- ShaderInput *vector2_in = input("Vector2");
- ShaderOutput *value_out = output("Value");
- ShaderOutput *vector_out = output("Vector");
+ ShaderInput *vector1_in = input("Vector1");
+ ShaderInput *vector2_in = input("Vector2");
+ ShaderOutput *value_out = output("Value");
+ ShaderOutput *vector_out = output("Vector");
- compiler.add_node(NODE_VECTOR_MATH,
- type,
- compiler.stack_assign(vector1_in),
- compiler.stack_assign(vector2_in));
- compiler.add_node(NODE_VECTOR_MATH,
- compiler.stack_assign(value_out),
- compiler.stack_assign(vector_out));
+ compiler.add_node(NODE_VECTOR_MATH,
+ type,
+ compiler.stack_assign(vector1_in),
+ compiler.stack_assign(vector2_in));
+ compiler.add_node(
+ NODE_VECTOR_MATH, compiler.stack_assign(value_out), compiler.stack_assign(vector_out));
}
-void VectorMathNode::compile(OSLCompiler& compiler)
+void VectorMathNode::compile(OSLCompiler &compiler)
{
- compiler.parameter(this, "type");
- compiler.add(this, "node_vector_math");
+ compiler.parameter(this, "type");
+ compiler.add(this, "node_vector_math");
}
/* VectorTransform */
NODE_DEFINE(VectorTransformNode)
{
- NodeType* type = NodeType::add("vector_transform", create, NodeType::SHADER);
+ NodeType *type = NodeType::add("vector_transform", create, NodeType::SHADER);
- static NodeEnum type_enum;
- type_enum.insert("vector", NODE_VECTOR_TRANSFORM_TYPE_VECTOR);
- type_enum.insert("point", NODE_VECTOR_TRANSFORM_TYPE_POINT);
- type_enum.insert("normal", NODE_VECTOR_TRANSFORM_TYPE_NORMAL);
- SOCKET_ENUM(type, "Type", type_enum, NODE_VECTOR_TRANSFORM_TYPE_VECTOR);
+ static NodeEnum type_enum;
+ type_enum.insert("vector", NODE_VECTOR_TRANSFORM_TYPE_VECTOR);
+ type_enum.insert("point", NODE_VECTOR_TRANSFORM_TYPE_POINT);
+ type_enum.insert("normal", NODE_VECTOR_TRANSFORM_TYPE_NORMAL);
+ SOCKET_ENUM(type, "Type", type_enum, NODE_VECTOR_TRANSFORM_TYPE_VECTOR);
- static NodeEnum space_enum;
- space_enum.insert("world", NODE_VECTOR_TRANSFORM_CONVERT_SPACE_WORLD);
- space_enum.insert("object", NODE_VECTOR_TRANSFORM_CONVERT_SPACE_OBJECT);
- space_enum.insert("camera", NODE_VECTOR_TRANSFORM_CONVERT_SPACE_CAMERA);
- SOCKET_ENUM(convert_from, "Convert From", space_enum, NODE_VECTOR_TRANSFORM_CONVERT_SPACE_WORLD);
- SOCKET_ENUM(convert_to, "Convert To", space_enum, NODE_VECTOR_TRANSFORM_CONVERT_SPACE_OBJECT);
+ static NodeEnum space_enum;
+ space_enum.insert("world", NODE_VECTOR_TRANSFORM_CONVERT_SPACE_WORLD);
+ space_enum.insert("object", NODE_VECTOR_TRANSFORM_CONVERT_SPACE_OBJECT);
+ space_enum.insert("camera", NODE_VECTOR_TRANSFORM_CONVERT_SPACE_CAMERA);
+ SOCKET_ENUM(convert_from, "Convert From", space_enum, NODE_VECTOR_TRANSFORM_CONVERT_SPACE_WORLD);
+ SOCKET_ENUM(convert_to, "Convert To", space_enum, NODE_VECTOR_TRANSFORM_CONVERT_SPACE_OBJECT);
- SOCKET_IN_VECTOR(vector, "Vector", make_float3(0.0f, 0.0f, 0.0f));
- SOCKET_OUT_VECTOR(vector, "Vector");
+ SOCKET_IN_VECTOR(vector, "Vector", make_float3(0.0f, 0.0f, 0.0f));
+ SOCKET_OUT_VECTOR(vector, "Vector");
- return type;
+ return type;
}
-VectorTransformNode::VectorTransformNode()
-: ShaderNode(node_type)
+VectorTransformNode::VectorTransformNode() : ShaderNode(node_type)
{
}
-void VectorTransformNode::compile(SVMCompiler& compiler)
+void VectorTransformNode::compile(SVMCompiler &compiler)
{
- ShaderInput *vector_in = input("Vector");
- ShaderOutput *vector_out = output("Vector");
+ ShaderInput *vector_in = input("Vector");
+ ShaderOutput *vector_out = output("Vector");
- compiler.add_node(NODE_VECTOR_TRANSFORM,
- compiler.encode_uchar4(type, convert_from, convert_to),
- compiler.encode_uchar4(compiler.stack_assign(vector_in),
- compiler.stack_assign(vector_out)));
+ compiler.add_node(
+ NODE_VECTOR_TRANSFORM,
+ compiler.encode_uchar4(type, convert_from, convert_to),
+ compiler.encode_uchar4(compiler.stack_assign(vector_in), compiler.stack_assign(vector_out)));
}
-void VectorTransformNode::compile(OSLCompiler& compiler)
+void VectorTransformNode::compile(OSLCompiler &compiler)
{
- compiler.parameter(this, "type");
- compiler.parameter(this, "convert_from");
- compiler.parameter(this, "convert_to");
- compiler.add(this, "node_vector_transform");
+ compiler.parameter(this, "type");
+ compiler.parameter(this, "convert_from");
+ compiler.parameter(this, "convert_to");
+ compiler.add(this, "node_vector_transform");
}
/* BumpNode */
NODE_DEFINE(BumpNode)
{
- NodeType* type = NodeType::add("bump", create, NodeType::SHADER);
+ NodeType *type = NodeType::add("bump", create, NodeType::SHADER);
- SOCKET_BOOLEAN(invert, "Invert", false);
- SOCKET_BOOLEAN(use_object_space, "UseObjectSpace", false);
+ SOCKET_BOOLEAN(invert, "Invert", false);
+ SOCKET_BOOLEAN(use_object_space, "UseObjectSpace", false);
- /* this input is used by the user, but after graph transform it is no longer
- * used and moved to sampler center/x/y instead */
- SOCKET_IN_FLOAT(height, "Height", 1.0f);
+ /* this input is used by the user, but after graph transform it is no longer
+ * used and moved to sampler center/x/y instead */
+ SOCKET_IN_FLOAT(height, "Height", 1.0f);
- SOCKET_IN_FLOAT(sample_center, "SampleCenter", 0.0f);
- SOCKET_IN_FLOAT(sample_x, "SampleX", 0.0f);
- SOCKET_IN_FLOAT(sample_y, "SampleY", 0.0f);
- SOCKET_IN_NORMAL(normal, "Normal", make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_NORMAL);
- SOCKET_IN_FLOAT(strength, "Strength", 1.0f);
- SOCKET_IN_FLOAT(distance, "Distance", 0.1f);
+ SOCKET_IN_FLOAT(sample_center, "SampleCenter", 0.0f);
+ SOCKET_IN_FLOAT(sample_x, "SampleX", 0.0f);
+ SOCKET_IN_FLOAT(sample_y, "SampleY", 0.0f);
+ SOCKET_IN_NORMAL(normal, "Normal", make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_NORMAL);
+ SOCKET_IN_FLOAT(strength, "Strength", 1.0f);
+ SOCKET_IN_FLOAT(distance, "Distance", 0.1f);
- SOCKET_OUT_NORMAL(normal, "Normal");
+ SOCKET_OUT_NORMAL(normal, "Normal");
- return type;
+ return type;
}
-BumpNode::BumpNode()
-: ShaderNode(node_type)
+BumpNode::BumpNode() : ShaderNode(node_type)
{
- special_type = SHADER_SPECIAL_TYPE_BUMP;
+ special_type = SHADER_SPECIAL_TYPE_BUMP;
}
-void BumpNode::compile(SVMCompiler& compiler)
+void BumpNode::compile(SVMCompiler &compiler)
{
- ShaderInput *center_in = input("SampleCenter");
- ShaderInput *dx_in = input("SampleX");
- ShaderInput *dy_in = input("SampleY");
- ShaderInput *normal_in = input("Normal");
- ShaderInput *strength_in = input("Strength");
- ShaderInput *distance_in = input("Distance");
- ShaderOutput *normal_out = output("Normal");
+ ShaderInput *center_in = input("SampleCenter");
+ ShaderInput *dx_in = input("SampleX");
+ ShaderInput *dy_in = input("SampleY");
+ ShaderInput *normal_in = input("Normal");
+ ShaderInput *strength_in = input("Strength");
+ ShaderInput *distance_in = input("Distance");
+ ShaderOutput *normal_out = output("Normal");
- /* pack all parameters in the node */
- compiler.add_node(NODE_SET_BUMP,
- compiler.encode_uchar4(
- compiler.stack_assign_if_linked(normal_in),
- compiler.stack_assign(distance_in),
- invert,
- use_object_space),
- compiler.encode_uchar4(
- compiler.stack_assign(center_in),
- compiler.stack_assign(dx_in),
- compiler.stack_assign(dy_in),
- compiler.stack_assign(strength_in)),
- compiler.stack_assign(normal_out));
+ /* pack all parameters in the node */
+ compiler.add_node(NODE_SET_BUMP,
+ compiler.encode_uchar4(compiler.stack_assign_if_linked(normal_in),
+ compiler.stack_assign(distance_in),
+ invert,
+ use_object_space),
+ compiler.encode_uchar4(compiler.stack_assign(center_in),
+ compiler.stack_assign(dx_in),
+ compiler.stack_assign(dy_in),
+ compiler.stack_assign(strength_in)),
+ compiler.stack_assign(normal_out));
}
-void BumpNode::compile(OSLCompiler& compiler)
+void BumpNode::compile(OSLCompiler &compiler)
{
- compiler.parameter(this, "invert");
- compiler.parameter(this, "use_object_space");
- compiler.add(this, "node_bump");
+ compiler.parameter(this, "invert");
+ compiler.parameter(this, "use_object_space");
+ compiler.add(this, "node_bump");
}
-void BumpNode::constant_fold(const ConstantFolder& folder)
+void BumpNode::constant_fold(const ConstantFolder &folder)
{
- ShaderInput *height_in = input("Height");
- ShaderInput *normal_in = input("Normal");
+ ShaderInput *height_in = input("Height");
+ ShaderInput *normal_in = input("Normal");
- if(height_in->link == NULL) {
- if(normal_in->link == NULL) {
- GeometryNode *geom = new GeometryNode();
- folder.graph->add(geom);
- folder.bypass(geom->output("Normal"));
- }
- else {
- folder.bypass(normal_in->link);
- }
- }
+ if (height_in->link == NULL) {
+ if (normal_in->link == NULL) {
+ GeometryNode *geom = new GeometryNode();
+ folder.graph->add(geom);
+ folder.bypass(geom->output("Normal"));
+ }
+ else {
+ folder.bypass(normal_in->link);
+ }
+ }
- /* TODO(sergey): Ignore bump with zero strength. */
+ /* TODO(sergey): Ignore bump with zero strength. */
}
-
/* Curve node */
-CurvesNode::CurvesNode(const NodeType *node_type)
-: ShaderNode(node_type)
+CurvesNode::CurvesNode(const NodeType *node_type) : ShaderNode(node_type)
{
}
-void CurvesNode::constant_fold(const ConstantFolder& folder, ShaderInput *value_in)
+void CurvesNode::constant_fold(const ConstantFolder &folder, ShaderInput *value_in)
{
- ShaderInput *fac_in = input("Fac");
+ ShaderInput *fac_in = input("Fac");
- /* evaluate fully constant node */
- if(folder.all_inputs_constant()) {
- if(curves.size() == 0) {
- return;
- }
+ /* evaluate fully constant node */
+ if (folder.all_inputs_constant()) {
+ if (curves.size() == 0) {
+ return;
+ }
- float3 pos = (value - make_float3(min_x, min_x, min_x)) / (max_x - min_x);
- float3 result;
+ float3 pos = (value - make_float3(min_x, min_x, min_x)) / (max_x - min_x);
+ float3 result;
- result[0] = rgb_ramp_lookup(curves.data(), pos[0], true, true, curves.size()).x;
- result[1] = rgb_ramp_lookup(curves.data(), pos[1], true, true, curves.size()).y;
- result[2] = rgb_ramp_lookup(curves.data(), pos[2], true, true, curves.size()).z;
+ result[0] = rgb_ramp_lookup(curves.data(), pos[0], true, true, curves.size()).x;
+ result[1] = rgb_ramp_lookup(curves.data(), pos[1], true, true, curves.size()).y;
+ result[2] = rgb_ramp_lookup(curves.data(), pos[2], true, true, curves.size()).z;
- folder.make_constant(interp(value, result, fac));
- }
- /* remove no-op node */
- else if(!fac_in->link && fac == 0.0f) {
- /* link is not null because otherwise all inputs are constant */
- folder.bypass(value_in->link);
- }
+ folder.make_constant(interp(value, result, fac));
+ }
+ /* remove no-op node */
+ else if (!fac_in->link && fac == 0.0f) {
+ /* link is not null because otherwise all inputs are constant */
+ folder.bypass(value_in->link);
+ }
}
-void CurvesNode::compile(SVMCompiler& compiler, int type, ShaderInput *value_in, ShaderOutput *value_out)
+void CurvesNode::compile(SVMCompiler &compiler,
+ int type,
+ ShaderInput *value_in,
+ ShaderOutput *value_out)
{
- if(curves.size() == 0)
- return;
+ if (curves.size() == 0)
+ return;
- ShaderInput *fac_in = input("Fac");
+ ShaderInput *fac_in = input("Fac");
- compiler.add_node(type,
- compiler.encode_uchar4(compiler.stack_assign(fac_in),
- compiler.stack_assign(value_in),
- compiler.stack_assign(value_out)),
- __float_as_int(min_x),
- __float_as_int(max_x));
+ compiler.add_node(type,
+ compiler.encode_uchar4(compiler.stack_assign(fac_in),
+ compiler.stack_assign(value_in),
+ compiler.stack_assign(value_out)),
+ __float_as_int(min_x),
+ __float_as_int(max_x));
- compiler.add_node(curves.size());
- for(int i = 0; i < curves.size(); i++)
- compiler.add_node(float3_to_float4(curves[i]));
+ compiler.add_node(curves.size());
+ for (int i = 0; i < curves.size(); i++)
+ compiler.add_node(float3_to_float4(curves[i]));
}
-void CurvesNode::compile(OSLCompiler& compiler, const char* name)
+void CurvesNode::compile(OSLCompiler &compiler, const char *name)
{
- if(curves.size() == 0)
- return;
+ if (curves.size() == 0)
+ return;
- compiler.parameter_color_array("ramp", curves);
- compiler.parameter(this, "min_x");
- compiler.parameter(this, "max_x");
- compiler.add(this, name);
+ compiler.parameter_color_array("ramp", curves);
+ compiler.parameter(this, "min_x");
+ compiler.parameter(this, "max_x");
+ compiler.add(this, name);
}
-void CurvesNode::compile(SVMCompiler& /*compiler*/)
+void CurvesNode::compile(SVMCompiler & /*compiler*/)
{
- assert(0);
+ assert(0);
}
-void CurvesNode::compile(OSLCompiler& /*compiler*/)
+void CurvesNode::compile(OSLCompiler & /*compiler*/)
{
- assert(0);
+ assert(0);
}
/* RGBCurvesNode */
NODE_DEFINE(RGBCurvesNode)
{
- NodeType* type = NodeType::add("rgb_curves", create, NodeType::SHADER);
+ NodeType *type = NodeType::add("rgb_curves", create, NodeType::SHADER);
- SOCKET_COLOR_ARRAY(curves, "Curves", array<float3>());
- SOCKET_FLOAT(min_x, "Min X", 0.0f);
- SOCKET_FLOAT(max_x, "Max X", 1.0f);
+ SOCKET_COLOR_ARRAY(curves, "Curves", array<float3>());
+ SOCKET_FLOAT(min_x, "Min X", 0.0f);
+ SOCKET_FLOAT(max_x, "Max X", 1.0f);
- SOCKET_IN_FLOAT(fac, "Fac", 0.0f);
- SOCKET_IN_COLOR(value, "Color", make_float3(0.0f, 0.0f, 0.0f));
+ SOCKET_IN_FLOAT(fac, "Fac", 0.0f);
+ SOCKET_IN_COLOR(value, "Color", make_float3(0.0f, 0.0f, 0.0f));
- SOCKET_OUT_COLOR(value, "Color");
+ SOCKET_OUT_COLOR(value, "Color");
- return type;
+ return type;
}
-RGBCurvesNode::RGBCurvesNode()
-: CurvesNode(node_type)
+RGBCurvesNode::RGBCurvesNode() : CurvesNode(node_type)
{
}
-void RGBCurvesNode::constant_fold(const ConstantFolder& folder)
+void RGBCurvesNode::constant_fold(const ConstantFolder &folder)
{
- CurvesNode::constant_fold(folder, input("Color"));
+ CurvesNode::constant_fold(folder, input("Color"));
}
-void RGBCurvesNode::compile(SVMCompiler& compiler)
+void RGBCurvesNode::compile(SVMCompiler &compiler)
{
- CurvesNode::compile(compiler, NODE_RGB_CURVES, input("Color"), output("Color"));
+ CurvesNode::compile(compiler, NODE_RGB_CURVES, input("Color"), output("Color"));
}
-void RGBCurvesNode::compile(OSLCompiler& compiler)
+void RGBCurvesNode::compile(OSLCompiler &compiler)
{
- CurvesNode::compile(compiler, "node_rgb_curves");
+ CurvesNode::compile(compiler, "node_rgb_curves");
}
/* VectorCurvesNode */
NODE_DEFINE(VectorCurvesNode)
{
- NodeType* type = NodeType::add("vector_curves", create, NodeType::SHADER);
+ NodeType *type = NodeType::add("vector_curves", create, NodeType::SHADER);
- SOCKET_VECTOR_ARRAY(curves, "Curves", array<float3>());
- SOCKET_FLOAT(min_x, "Min X", 0.0f);
- SOCKET_FLOAT(max_x, "Max X", 1.0f);
+ SOCKET_VECTOR_ARRAY(curves, "Curves", array<float3>());
+ SOCKET_FLOAT(min_x, "Min X", 0.0f);
+ SOCKET_FLOAT(max_x, "Max X", 1.0f);
- SOCKET_IN_FLOAT(fac, "Fac", 0.0f);
- SOCKET_IN_VECTOR(value, "Vector", make_float3(0.0f, 0.0f, 0.0f));
+ SOCKET_IN_FLOAT(fac, "Fac", 0.0f);
+ SOCKET_IN_VECTOR(value, "Vector", make_float3(0.0f, 0.0f, 0.0f));
- SOCKET_OUT_VECTOR(value, "Vector");
+ SOCKET_OUT_VECTOR(value, "Vector");
- return type;
+ return type;
}
-VectorCurvesNode::VectorCurvesNode()
-: CurvesNode(node_type)
+VectorCurvesNode::VectorCurvesNode() : CurvesNode(node_type)
{
}
-void VectorCurvesNode::constant_fold(const ConstantFolder& folder)
+void VectorCurvesNode::constant_fold(const ConstantFolder &folder)
{
- CurvesNode::constant_fold(folder, input("Vector"));
+ CurvesNode::constant_fold(folder, input("Vector"));
}
-void VectorCurvesNode::compile(SVMCompiler& compiler)
+void VectorCurvesNode::compile(SVMCompiler &compiler)
{
- CurvesNode::compile(compiler, NODE_VECTOR_CURVES, input("Vector"), output("Vector"));
+ CurvesNode::compile(compiler, NODE_VECTOR_CURVES, input("Vector"), output("Vector"));
}
-void VectorCurvesNode::compile(OSLCompiler& compiler)
+void VectorCurvesNode::compile(OSLCompiler &compiler)
{
- CurvesNode::compile(compiler, "node_vector_curves");
+ CurvesNode::compile(compiler, "node_vector_curves");
}
/* RGBRampNode */
NODE_DEFINE(RGBRampNode)
{
- NodeType* type = NodeType::add("rgb_ramp", create, NodeType::SHADER);
+ NodeType *type = NodeType::add("rgb_ramp", create, NodeType::SHADER);
- SOCKET_COLOR_ARRAY(ramp, "Ramp", array<float3>());
- SOCKET_FLOAT_ARRAY(ramp_alpha, "Ramp Alpha", array<float>());
- SOCKET_BOOLEAN(interpolate, "Interpolate", true);
+ SOCKET_COLOR_ARRAY(ramp, "Ramp", array<float3>());
+ SOCKET_FLOAT_ARRAY(ramp_alpha, "Ramp Alpha", array<float>());
+ SOCKET_BOOLEAN(interpolate, "Interpolate", true);
- SOCKET_IN_FLOAT(fac, "Fac", 0.0f);
+ SOCKET_IN_FLOAT(fac, "Fac", 0.0f);
- SOCKET_OUT_COLOR(color, "Color");
- SOCKET_OUT_FLOAT(alpha, "Alpha");
+ SOCKET_OUT_COLOR(color, "Color");
+ SOCKET_OUT_FLOAT(alpha, "Alpha");
- return type;
+ return type;
}
-RGBRampNode::RGBRampNode()
-: ShaderNode(node_type)
+RGBRampNode::RGBRampNode() : ShaderNode(node_type)
{
}
-void RGBRampNode::constant_fold(const ConstantFolder& folder)
+void RGBRampNode::constant_fold(const ConstantFolder &folder)
{
- if(ramp.size() == 0 || ramp.size() != ramp_alpha.size())
- return;
+ if (ramp.size() == 0 || ramp.size() != ramp_alpha.size())
+ return;
- if(folder.all_inputs_constant()) {
- float f = clamp(fac, 0.0f, 1.0f) * (ramp.size() - 1);
+ if (folder.all_inputs_constant()) {
+ float f = clamp(fac, 0.0f, 1.0f) * (ramp.size() - 1);
- /* clamp int as well in case of NaN */
- int i = clamp((int)f, 0, ramp.size()-1);
- float t = f - (float)i;
+ /* clamp int as well in case of NaN */
+ int i = clamp((int)f, 0, ramp.size() - 1);
+ float t = f - (float)i;
- bool use_lerp = interpolate && t > 0.0f;
+ bool use_lerp = interpolate && t > 0.0f;
- if(folder.output == output("Color")) {
- float3 color = rgb_ramp_lookup(ramp.data(), fac, use_lerp, false, ramp.size());
- folder.make_constant(color);
- }
- else if(folder.output == output("Alpha")) {
- float alpha = float_ramp_lookup(ramp_alpha.data(), fac, use_lerp, false, ramp_alpha.size());
- folder.make_constant(alpha);
- }
- }
+ if (folder.output == output("Color")) {
+ float3 color = rgb_ramp_lookup(ramp.data(), fac, use_lerp, false, ramp.size());
+ folder.make_constant(color);
+ }
+ else if (folder.output == output("Alpha")) {
+ float alpha = float_ramp_lookup(ramp_alpha.data(), fac, use_lerp, false, ramp_alpha.size());
+ folder.make_constant(alpha);
+ }
+ }
}
-void RGBRampNode::compile(SVMCompiler& compiler)
+void RGBRampNode::compile(SVMCompiler &compiler)
{
- if(ramp.size() == 0 || ramp.size() != ramp_alpha.size())
- return;
+ if (ramp.size() == 0 || ramp.size() != ramp_alpha.size())
+ return;
- ShaderInput *fac_in = input("Fac");
- ShaderOutput *color_out = output("Color");
- ShaderOutput *alpha_out = output("Alpha");
+ ShaderInput *fac_in = input("Fac");
+ ShaderOutput *color_out = output("Color");
+ ShaderOutput *alpha_out = output("Alpha");
- compiler.add_node(NODE_RGB_RAMP,
- compiler.encode_uchar4(
- compiler.stack_assign(fac_in),
- compiler.stack_assign_if_linked(color_out),
- compiler.stack_assign_if_linked(alpha_out)),
- interpolate);
+ compiler.add_node(NODE_RGB_RAMP,
+ compiler.encode_uchar4(compiler.stack_assign(fac_in),
+ compiler.stack_assign_if_linked(color_out),
+ compiler.stack_assign_if_linked(alpha_out)),
+ interpolate);
- compiler.add_node(ramp.size());
- for(int i = 0; i < ramp.size(); i++)
- compiler.add_node(make_float4(ramp[i].x, ramp[i].y, ramp[i].z, ramp_alpha[i]));
+ compiler.add_node(ramp.size());
+ for (int i = 0; i < ramp.size(); i++)
+ compiler.add_node(make_float4(ramp[i].x, ramp[i].y, ramp[i].z, ramp_alpha[i]));
}
-void RGBRampNode::compile(OSLCompiler& compiler)
+void RGBRampNode::compile(OSLCompiler &compiler)
{
- if(ramp.size() == 0 || ramp.size() != ramp_alpha.size())
- return;
+ if (ramp.size() == 0 || ramp.size() != ramp_alpha.size())
+ return;
- compiler.parameter_color_array("ramp_color", ramp);
- compiler.parameter_array("ramp_alpha", ramp_alpha.data(), ramp_alpha.size());
- compiler.parameter(this, "interpolate");
+ compiler.parameter_color_array("ramp_color", ramp);
+ compiler.parameter_array("ramp_alpha", ramp_alpha.data(), ramp_alpha.size());
+ compiler.parameter(this, "interpolate");
- compiler.add(this, "node_rgb_ramp");
+ compiler.add(this, "node_rgb_ramp");
}
/* Set Normal Node */
NODE_DEFINE(SetNormalNode)
{
- NodeType* type = NodeType::add("set_normal", create, NodeType::SHADER);
+ NodeType *type = NodeType::add("set_normal", create, NodeType::SHADER);
- SOCKET_IN_VECTOR(direction, "Direction", make_float3(0.0f, 0.0f, 0.0f));
- SOCKET_OUT_NORMAL(normal, "Normal");
+ SOCKET_IN_VECTOR(direction, "Direction", make_float3(0.0f, 0.0f, 0.0f));
+ SOCKET_OUT_NORMAL(normal, "Normal");
- return type;
+ return type;
}
-SetNormalNode::SetNormalNode()
-: ShaderNode(node_type)
+SetNormalNode::SetNormalNode() : ShaderNode(node_type)
{
}
-void SetNormalNode::compile(SVMCompiler& compiler)
+void SetNormalNode::compile(SVMCompiler &compiler)
{
- ShaderInput *direction_in = input("Direction");
- ShaderOutput *normal_out = output("Normal");
+ ShaderInput *direction_in = input("Direction");
+ ShaderOutput *normal_out = output("Normal");
- compiler.add_node(NODE_CLOSURE_SET_NORMAL,
- compiler.stack_assign(direction_in),
- compiler.stack_assign(normal_out));
+ compiler.add_node(NODE_CLOSURE_SET_NORMAL,
+ compiler.stack_assign(direction_in),
+ compiler.stack_assign(normal_out));
}
-void SetNormalNode::compile(OSLCompiler& compiler)
+void SetNormalNode::compile(OSLCompiler &compiler)
{
- compiler.add(this, "node_set_normal");
+ compiler.add(this, "node_set_normal");
}
/* OSLNode */
-OSLNode::OSLNode()
-: ShaderNode(new NodeType(NodeType::SHADER))
+OSLNode::OSLNode() : ShaderNode(new NodeType(NodeType::SHADER))
{
- special_type = SHADER_SPECIAL_TYPE_SCRIPT;
+ special_type = SHADER_SPECIAL_TYPE_SCRIPT;
}
OSLNode::~OSLNode()
{
- delete type;
+ delete type;
}
ShaderNode *OSLNode::clone() const
{
- return OSLNode::create(this->inputs.size(), this);
+ return OSLNode::create(this->inputs.size(), this);
}
-OSLNode* OSLNode::create(size_t num_inputs, const OSLNode *from)
+OSLNode *OSLNode::create(size_t num_inputs, const OSLNode *from)
{
- /* allocate space for the node itself and parameters, aligned to 16 bytes
- * assuming that's the most parameter types need */
- size_t node_size = align_up(sizeof(OSLNode), 16);
- size_t inputs_size = align_up(SocketType::max_size(), 16) * num_inputs;
+ /* allocate space for the node itself and parameters, aligned to 16 bytes
+ * assuming that's the most parameter types need */
+ size_t node_size = align_up(sizeof(OSLNode), 16);
+ size_t inputs_size = align_up(SocketType::max_size(), 16) * num_inputs;
- char *node_memory = (char*) operator new(node_size + inputs_size);
- memset(node_memory, 0, node_size + inputs_size);
+ char *node_memory = (char *)operator new(node_size + inputs_size);
+ memset(node_memory, 0, node_size + inputs_size);
- if(!from) {
- return new(node_memory) OSLNode();
- }
- else {
- /* copy input default values and node type for cloning */
- memcpy(node_memory + node_size, (char*)from + node_size, inputs_size);
+ if (!from) {
+ return new (node_memory) OSLNode();
+ }
+ else {
+ /* copy input default values and node type for cloning */
+ memcpy(node_memory + node_size, (char *)from + node_size, inputs_size);
- OSLNode *node = new(node_memory) OSLNode(*from);
- node->type = new NodeType(*(from->type));
- return node;
- }
+ OSLNode *node = new (node_memory) OSLNode(*from);
+ node->type = new NodeType(*(from->type));
+ return node;
+ }
}
-char* OSLNode::input_default_value()
+char *OSLNode::input_default_value()
{
- /* pointer to default value storage, which is the same as our actual value */
- size_t num_inputs = type->inputs.size();
- size_t inputs_size = align_up(SocketType::max_size(), 16) * num_inputs;
- return (char*)this + align_up(sizeof(OSLNode), 16) + inputs_size;
+ /* pointer to default value storage, which is the same as our actual value */
+ size_t num_inputs = type->inputs.size();
+ size_t inputs_size = align_up(SocketType::max_size(), 16) * num_inputs;
+ return (char *)this + align_up(sizeof(OSLNode), 16) + inputs_size;
}
void OSLNode::add_input(ustring name, SocketType::Type socket_type)
{
- char *memory = input_default_value();
- size_t offset = memory - (char*)this;
- const_cast<NodeType*>(type)->register_input(name, name, socket_type, offset, memory, NULL, NULL, SocketType::LINKABLE);
+ char *memory = input_default_value();
+ size_t offset = memory - (char *)this;
+ const_cast<NodeType *>(type)->register_input(
+ name, name, socket_type, offset, memory, NULL, NULL, SocketType::LINKABLE);
}
void OSLNode::add_output(ustring name, SocketType::Type socket_type)
{
- const_cast<NodeType*>(type)->register_output(name, name, socket_type);
+ const_cast<NodeType *>(type)->register_output(name, name, socket_type);
}
-void OSLNode::compile(SVMCompiler&)
+void OSLNode::compile(SVMCompiler &)
{
- /* doesn't work for SVM, obviously ... */
+ /* doesn't work for SVM, obviously ... */
}
-void OSLNode::compile(OSLCompiler& compiler)
+void OSLNode::compile(OSLCompiler &compiler)
{
- if(!filepath.empty())
- compiler.add(this, filepath.c_str(), true);
- else
- compiler.add(this, bytecode_hash.c_str(), false);
+ if (!filepath.empty())
+ compiler.add(this, filepath.c_str(), true);
+ else
+ compiler.add(this, bytecode_hash.c_str(), false);
}
/* Normal Map */
NODE_DEFINE(NormalMapNode)
{
- NodeType* type = NodeType::add("normal_map", create, NodeType::SHADER);
+ NodeType *type = NodeType::add("normal_map", create, NodeType::SHADER);
- static NodeEnum space_enum;
- space_enum.insert("tangent", NODE_NORMAL_MAP_TANGENT);
- space_enum.insert("object", NODE_NORMAL_MAP_OBJECT);
- space_enum.insert("world", NODE_NORMAL_MAP_WORLD);
- space_enum.insert("blender_object", NODE_NORMAL_MAP_BLENDER_OBJECT);
- space_enum.insert("blender_world", NODE_NORMAL_MAP_BLENDER_WORLD);
- SOCKET_ENUM(space, "Space", space_enum, NODE_NORMAL_MAP_TANGENT);
+ static NodeEnum space_enum;
+ space_enum.insert("tangent", NODE_NORMAL_MAP_TANGENT);
+ space_enum.insert("object", NODE_NORMAL_MAP_OBJECT);
+ space_enum.insert("world", NODE_NORMAL_MAP_WORLD);
+ space_enum.insert("blender_object", NODE_NORMAL_MAP_BLENDER_OBJECT);
+ space_enum.insert("blender_world", NODE_NORMAL_MAP_BLENDER_WORLD);
+ SOCKET_ENUM(space, "Space", space_enum, NODE_NORMAL_MAP_TANGENT);
- SOCKET_STRING(attribute, "Attribute", ustring());
+ SOCKET_STRING(attribute, "Attribute", ustring());
- SOCKET_IN_NORMAL(normal_osl, "NormalIn", make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_NORMAL | SocketType::OSL_INTERNAL);
- SOCKET_IN_FLOAT(strength, "Strength", 1.0f);
- SOCKET_IN_COLOR(color, "Color", make_float3(0.5f, 0.5f, 1.0f));
+ SOCKET_IN_NORMAL(normal_osl,
+ "NormalIn",
+ make_float3(0.0f, 0.0f, 0.0f),
+ SocketType::LINK_NORMAL | SocketType::OSL_INTERNAL);
+ SOCKET_IN_FLOAT(strength, "Strength", 1.0f);
+ SOCKET_IN_COLOR(color, "Color", make_float3(0.5f, 0.5f, 1.0f));
- SOCKET_OUT_NORMAL(normal, "Normal");
+ SOCKET_OUT_NORMAL(normal, "Normal");
- return type;
+ return type;
}
-NormalMapNode::NormalMapNode()
-: ShaderNode(node_type)
+NormalMapNode::NormalMapNode() : ShaderNode(node_type)
{
}
void NormalMapNode::attributes(Shader *shader, AttributeRequestSet *attributes)
{
- if(shader->has_surface && space == NODE_NORMAL_MAP_TANGENT) {
- if(attribute.empty()) {
- attributes->add(ATTR_STD_UV_TANGENT);
- attributes->add(ATTR_STD_UV_TANGENT_SIGN);
- }
- else {
- attributes->add(ustring((string(attribute.c_str()) + ".tangent").c_str()));
- attributes->add(ustring((string(attribute.c_str()) + ".tangent_sign").c_str()));
- }
-
- attributes->add(ATTR_STD_VERTEX_NORMAL);
- }
-
- ShaderNode::attributes(shader, attributes);
-}
-
-void NormalMapNode::compile(SVMCompiler& compiler)
-{
- ShaderInput *color_in = input("Color");
- ShaderInput *strength_in = input("Strength");
- ShaderOutput *normal_out = output("Normal");
- int attr = 0, attr_sign = 0;
-
- if(space == NODE_NORMAL_MAP_TANGENT) {
- if(attribute.empty()) {
- attr = compiler.attribute(ATTR_STD_UV_TANGENT);
- attr_sign = compiler.attribute(ATTR_STD_UV_TANGENT_SIGN);
- }
- else {
- attr = compiler.attribute(ustring((string(attribute.c_str()) + ".tangent").c_str()));
- attr_sign = compiler.attribute(ustring((string(attribute.c_str()) + ".tangent_sign").c_str()));
- }
- }
-
- compiler.add_node(NODE_NORMAL_MAP,
- compiler.encode_uchar4(
- compiler.stack_assign(color_in),
- compiler.stack_assign(strength_in),
- compiler.stack_assign(normal_out),
- space),
- attr, attr_sign);
-}
-
-void NormalMapNode::compile(OSLCompiler& compiler)
-{
- if(space == NODE_NORMAL_MAP_TANGENT) {
- if(attribute.empty()) {
- compiler.parameter("attr_name", ustring("geom:tangent"));
- compiler.parameter("attr_sign_name", ustring("geom:tangent_sign"));
- }
- else {
- compiler.parameter("attr_name", ustring((string(attribute.c_str()) + ".tangent").c_str()));
- compiler.parameter("attr_sign_name", ustring((string(attribute.c_str()) + ".tangent_sign").c_str()));
- }
- }
-
- compiler.parameter(this, "space");
- compiler.add(this, "node_normal_map");
+ if (shader->has_surface && space == NODE_NORMAL_MAP_TANGENT) {
+ if (attribute.empty()) {
+ attributes->add(ATTR_STD_UV_TANGENT);
+ attributes->add(ATTR_STD_UV_TANGENT_SIGN);
+ }
+ else {
+ attributes->add(ustring((string(attribute.c_str()) + ".tangent").c_str()));
+ attributes->add(ustring((string(attribute.c_str()) + ".tangent_sign").c_str()));
+ }
+
+ attributes->add(ATTR_STD_VERTEX_NORMAL);
+ }
+
+ ShaderNode::attributes(shader, attributes);
+}
+
+void NormalMapNode::compile(SVMCompiler &compiler)
+{
+ ShaderInput *color_in = input("Color");
+ ShaderInput *strength_in = input("Strength");
+ ShaderOutput *normal_out = output("Normal");
+ int attr = 0, attr_sign = 0;
+
+ if (space == NODE_NORMAL_MAP_TANGENT) {
+ if (attribute.empty()) {
+ attr = compiler.attribute(ATTR_STD_UV_TANGENT);
+ attr_sign = compiler.attribute(ATTR_STD_UV_TANGENT_SIGN);
+ }
+ else {
+ attr = compiler.attribute(ustring((string(attribute.c_str()) + ".tangent").c_str()));
+ attr_sign = compiler.attribute(
+ ustring((string(attribute.c_str()) + ".tangent_sign").c_str()));
+ }
+ }
+
+ compiler.add_node(NODE_NORMAL_MAP,
+ compiler.encode_uchar4(compiler.stack_assign(color_in),
+ compiler.stack_assign(strength_in),
+ compiler.stack_assign(normal_out),
+ space),
+ attr,
+ attr_sign);
+}
+
+void NormalMapNode::compile(OSLCompiler &compiler)
+{
+ if (space == NODE_NORMAL_MAP_TANGENT) {
+ if (attribute.empty()) {
+ compiler.parameter("attr_name", ustring("geom:tangent"));
+ compiler.parameter("attr_sign_name", ustring("geom:tangent_sign"));
+ }
+ else {
+ compiler.parameter("attr_name", ustring((string(attribute.c_str()) + ".tangent").c_str()));
+ compiler.parameter("attr_sign_name",
+ ustring((string(attribute.c_str()) + ".tangent_sign").c_str()));
+ }
+ }
+
+ compiler.parameter(this, "space");
+ compiler.add(this, "node_normal_map");
}
/* Tangent */
NODE_DEFINE(TangentNode)
{
- NodeType* type = NodeType::add("tangent", create, NodeType::SHADER);
+ NodeType *type = NodeType::add("tangent", create, NodeType::SHADER);
- static NodeEnum direction_type_enum;
- direction_type_enum.insert("radial", NODE_TANGENT_RADIAL);
- direction_type_enum.insert("uv_map", NODE_TANGENT_UVMAP);
- SOCKET_ENUM(direction_type, "Direction Type", direction_type_enum, NODE_TANGENT_RADIAL);
+ static NodeEnum direction_type_enum;
+ direction_type_enum.insert("radial", NODE_TANGENT_RADIAL);
+ direction_type_enum.insert("uv_map", NODE_TANGENT_UVMAP);
+ SOCKET_ENUM(direction_type, "Direction Type", direction_type_enum, NODE_TANGENT_RADIAL);
- static NodeEnum axis_enum;
- axis_enum.insert("x", NODE_TANGENT_AXIS_X);
- axis_enum.insert("y", NODE_TANGENT_AXIS_Y);
- axis_enum.insert("z", NODE_TANGENT_AXIS_Z);
- SOCKET_ENUM(axis, "Axis", axis_enum, NODE_TANGENT_AXIS_X);
+ static NodeEnum axis_enum;
+ axis_enum.insert("x", NODE_TANGENT_AXIS_X);
+ axis_enum.insert("y", NODE_TANGENT_AXIS_Y);
+ axis_enum.insert("z", NODE_TANGENT_AXIS_Z);
+ SOCKET_ENUM(axis, "Axis", axis_enum, NODE_TANGENT_AXIS_X);
- SOCKET_STRING(attribute, "Attribute", ustring());
+ SOCKET_STRING(attribute, "Attribute", ustring());
- SOCKET_IN_NORMAL(normal_osl, "NormalIn", make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_NORMAL | SocketType::OSL_INTERNAL);
- SOCKET_OUT_NORMAL(tangent, "Tangent");
+ SOCKET_IN_NORMAL(normal_osl,
+ "NormalIn",
+ make_float3(0.0f, 0.0f, 0.0f),
+ SocketType::LINK_NORMAL | SocketType::OSL_INTERNAL);
+ SOCKET_OUT_NORMAL(tangent, "Tangent");
- return type;
+ return type;
}
-TangentNode::TangentNode()
-: ShaderNode(node_type)
+TangentNode::TangentNode() : ShaderNode(node_type)
{
}
void TangentNode::attributes(Shader *shader, AttributeRequestSet *attributes)
{
- if(shader->has_surface) {
- if(direction_type == NODE_TANGENT_UVMAP) {
- if(attribute.empty())
- attributes->add(ATTR_STD_UV_TANGENT);
- else
- attributes->add(ustring((string(attribute.c_str()) + ".tangent").c_str()));
- }
- else
- attributes->add(ATTR_STD_GENERATED);
- }
+ if (shader->has_surface) {
+ if (direction_type == NODE_TANGENT_UVMAP) {
+ if (attribute.empty())
+ attributes->add(ATTR_STD_UV_TANGENT);
+ else
+ attributes->add(ustring((string(attribute.c_str()) + ".tangent").c_str()));
+ }
+ else
+ attributes->add(ATTR_STD_GENERATED);
+ }
- ShaderNode::attributes(shader, attributes);
+ ShaderNode::attributes(shader, attributes);
}
-void TangentNode::compile(SVMCompiler& compiler)
+void TangentNode::compile(SVMCompiler &compiler)
{
- ShaderOutput *tangent_out = output("Tangent");
- int attr;
+ ShaderOutput *tangent_out = output("Tangent");
+ int attr;
- if(direction_type == NODE_TANGENT_UVMAP) {
- if(attribute.empty())
- attr = compiler.attribute(ATTR_STD_UV_TANGENT);
- else
- attr = compiler.attribute(ustring((string(attribute.c_str()) + ".tangent").c_str()));
- }
- else
- attr = compiler.attribute(ATTR_STD_GENERATED);
+ if (direction_type == NODE_TANGENT_UVMAP) {
+ if (attribute.empty())
+ attr = compiler.attribute(ATTR_STD_UV_TANGENT);
+ else
+ attr = compiler.attribute(ustring((string(attribute.c_str()) + ".tangent").c_str()));
+ }
+ else
+ attr = compiler.attribute(ATTR_STD_GENERATED);
- compiler.add_node(NODE_TANGENT,
- compiler.encode_uchar4(
- compiler.stack_assign(tangent_out),
- direction_type,
- axis), attr);
+ compiler.add_node(
+ NODE_TANGENT,
+ compiler.encode_uchar4(compiler.stack_assign(tangent_out), direction_type, axis),
+ attr);
}
-void TangentNode::compile(OSLCompiler& compiler)
+void TangentNode::compile(OSLCompiler &compiler)
{
- if(direction_type == NODE_TANGENT_UVMAP) {
- if(attribute.empty())
- compiler.parameter("attr_name", ustring("geom:tangent"));
- else
- compiler.parameter("attr_name", ustring((string(attribute.c_str()) + ".tangent").c_str()));
- }
+ if (direction_type == NODE_TANGENT_UVMAP) {
+ if (attribute.empty())
+ compiler.parameter("attr_name", ustring("geom:tangent"));
+ else
+ compiler.parameter("attr_name", ustring((string(attribute.c_str()) + ".tangent").c_str()));
+ }
- compiler.parameter(this, "direction_type");
- compiler.parameter(this, "axis");
- compiler.add(this, "node_tangent");
+ compiler.parameter(this, "direction_type");
+ compiler.parameter(this, "axis");
+ compiler.add(this, "node_tangent");
}
/* Bevel */
NODE_DEFINE(BevelNode)
{
- NodeType* type = NodeType::add("bevel", create, NodeType::SHADER);
+ NodeType *type = NodeType::add("bevel", create, NodeType::SHADER);
- SOCKET_INT(samples, "Samples", 4);
+ SOCKET_INT(samples, "Samples", 4);
- SOCKET_IN_FLOAT(radius, "Radius", 0.05f);
- SOCKET_IN_NORMAL(normal, "Normal", make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_NORMAL);
+ SOCKET_IN_FLOAT(radius, "Radius", 0.05f);
+ SOCKET_IN_NORMAL(normal, "Normal", make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_NORMAL);
- SOCKET_OUT_NORMAL(bevel, "Normal");
+ SOCKET_OUT_NORMAL(bevel, "Normal");
- return type;
+ return type;
}
-BevelNode::BevelNode()
-: ShaderNode(node_type)
+BevelNode::BevelNode() : ShaderNode(node_type)
{
}
-void BevelNode::compile(SVMCompiler& compiler)
+void BevelNode::compile(SVMCompiler &compiler)
{
- ShaderInput *radius_in = input("Radius");
- ShaderInput *normal_in = input("Normal");
- ShaderOutput *normal_out = output("Normal");
+ ShaderInput *radius_in = input("Radius");
+ ShaderInput *normal_in = input("Normal");
+ ShaderOutput *normal_out = output("Normal");
- compiler.add_node(NODE_BEVEL,
- compiler.encode_uchar4(samples,
- compiler.stack_assign(radius_in),
- compiler.stack_assign_if_linked(normal_in),
- compiler.stack_assign(normal_out)));
+ compiler.add_node(NODE_BEVEL,
+ compiler.encode_uchar4(samples,
+ compiler.stack_assign(radius_in),
+ compiler.stack_assign_if_linked(normal_in),
+ compiler.stack_assign(normal_out)));
}
-void BevelNode::compile(OSLCompiler& compiler)
+void BevelNode::compile(OSLCompiler &compiler)
{
- compiler.parameter(this, "samples");
- compiler.add(this, "node_bevel");
+ compiler.parameter(this, "samples");
+ compiler.add(this, "node_bevel");
}
/* Displacement */
NODE_DEFINE(DisplacementNode)
{
- NodeType* type = NodeType::add("displacement", create, NodeType::SHADER);
+ NodeType *type = NodeType::add("displacement", create, NodeType::SHADER);
- static NodeEnum space_enum;
- space_enum.insert("object", NODE_NORMAL_MAP_OBJECT);
- space_enum.insert("world", NODE_NORMAL_MAP_WORLD);
+ static NodeEnum space_enum;
+ space_enum.insert("object", NODE_NORMAL_MAP_OBJECT);
+ space_enum.insert("world", NODE_NORMAL_MAP_WORLD);
- SOCKET_ENUM(space, "Space", space_enum, NODE_NORMAL_MAP_OBJECT);
+ SOCKET_ENUM(space, "Space", space_enum, NODE_NORMAL_MAP_OBJECT);
- SOCKET_IN_FLOAT(height, "Height", 0.0f);
- SOCKET_IN_FLOAT(midlevel, "Midlevel", 0.5f);
- SOCKET_IN_FLOAT(scale, "Scale", 1.0f);
- SOCKET_IN_NORMAL(normal, "Normal", make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_NORMAL);
+ SOCKET_IN_FLOAT(height, "Height", 0.0f);
+ SOCKET_IN_FLOAT(midlevel, "Midlevel", 0.5f);
+ SOCKET_IN_FLOAT(scale, "Scale", 1.0f);
+ SOCKET_IN_NORMAL(normal, "Normal", make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_NORMAL);
- SOCKET_OUT_VECTOR(displacement, "Displacement");
+ SOCKET_OUT_VECTOR(displacement, "Displacement");
- return type;
+ return type;
}
-DisplacementNode::DisplacementNode()
-: ShaderNode(node_type)
+DisplacementNode::DisplacementNode() : ShaderNode(node_type)
{
}
-void DisplacementNode::constant_fold(const ConstantFolder& folder)
+void DisplacementNode::constant_fold(const ConstantFolder &folder)
{
- if(folder.all_inputs_constant()) {
- if((height - midlevel == 0.0f) || (scale == 0.0f)) {
- folder.make_zero();
- }
- }
+ if (folder.all_inputs_constant()) {
+ if ((height - midlevel == 0.0f) || (scale == 0.0f)) {
+ folder.make_zero();
+ }
+ }
}
-void DisplacementNode::compile(SVMCompiler& compiler)
+void DisplacementNode::compile(SVMCompiler &compiler)
{
- ShaderInput *height_in = input("Height");
- ShaderInput *midlevel_in = input("Midlevel");
- ShaderInput *scale_in = input("Scale");
- ShaderInput *normal_in = input("Normal");
- ShaderOutput *displacement_out = output("Displacement");
+ ShaderInput *height_in = input("Height");
+ ShaderInput *midlevel_in = input("Midlevel");
+ ShaderInput *scale_in = input("Scale");
+ ShaderInput *normal_in = input("Normal");
+ ShaderOutput *displacement_out = output("Displacement");
- compiler.add_node(NODE_DISPLACEMENT,
- compiler.encode_uchar4(compiler.stack_assign(height_in),
- compiler.stack_assign(midlevel_in),
- compiler.stack_assign(scale_in),
- compiler.stack_assign_if_linked(normal_in)),
- compiler.stack_assign(displacement_out),
- space);
+ compiler.add_node(NODE_DISPLACEMENT,
+ compiler.encode_uchar4(compiler.stack_assign(height_in),
+ compiler.stack_assign(midlevel_in),
+ compiler.stack_assign(scale_in),
+ compiler.stack_assign_if_linked(normal_in)),
+ compiler.stack_assign(displacement_out),
+ space);
}
-void DisplacementNode::compile(OSLCompiler& compiler)
+void DisplacementNode::compile(OSLCompiler &compiler)
{
- compiler.parameter(this, "space");
- compiler.add(this, "node_displacement");
+ compiler.parameter(this, "space");
+ compiler.add(this, "node_displacement");
}
/* Vector Displacement */
NODE_DEFINE(VectorDisplacementNode)
{
- NodeType* type = NodeType::add("vector_displacement", create, NodeType::SHADER);
+ NodeType *type = NodeType::add("vector_displacement", create, NodeType::SHADER);
- static NodeEnum space_enum;
- space_enum.insert("tangent", NODE_NORMAL_MAP_TANGENT);
- space_enum.insert("object", NODE_NORMAL_MAP_OBJECT);
- space_enum.insert("world", NODE_NORMAL_MAP_WORLD);
+ static NodeEnum space_enum;
+ space_enum.insert("tangent", NODE_NORMAL_MAP_TANGENT);
+ space_enum.insert("object", NODE_NORMAL_MAP_OBJECT);
+ space_enum.insert("world", NODE_NORMAL_MAP_WORLD);
- SOCKET_ENUM(space, "Space", space_enum, NODE_NORMAL_MAP_TANGENT);
- SOCKET_STRING(attribute, "Attribute", ustring());
+ SOCKET_ENUM(space, "Space", space_enum, NODE_NORMAL_MAP_TANGENT);
+ SOCKET_STRING(attribute, "Attribute", ustring());
- SOCKET_IN_COLOR(vector, "Vector", make_float3(0.0f, 0.0f, 0.0f));
- SOCKET_IN_FLOAT(midlevel, "Midlevel", 0.0f);
- SOCKET_IN_FLOAT(scale, "Scale", 1.0f);
+ SOCKET_IN_COLOR(vector, "Vector", make_float3(0.0f, 0.0f, 0.0f));
+ SOCKET_IN_FLOAT(midlevel, "Midlevel", 0.0f);
+ SOCKET_IN_FLOAT(scale, "Scale", 1.0f);
- SOCKET_OUT_VECTOR(displacement, "Displacement");
+ SOCKET_OUT_VECTOR(displacement, "Displacement");
- return type;
+ return type;
}
-VectorDisplacementNode::VectorDisplacementNode()
-: ShaderNode(node_type)
+VectorDisplacementNode::VectorDisplacementNode() : ShaderNode(node_type)
{
}
-void VectorDisplacementNode::constant_fold(const ConstantFolder& folder)
+void VectorDisplacementNode::constant_fold(const ConstantFolder &folder)
{
- if(folder.all_inputs_constant()) {
- if((vector == make_float3(0.0f, 0.0f, 0.0f) && midlevel == 0.0f) ||
- (scale == 0.0f)) {
- folder.make_zero();
- }
- }
+ if (folder.all_inputs_constant()) {
+ if ((vector == make_float3(0.0f, 0.0f, 0.0f) && midlevel == 0.0f) || (scale == 0.0f)) {
+ folder.make_zero();
+ }
+ }
}
void VectorDisplacementNode::attributes(Shader *shader, AttributeRequestSet *attributes)
{
- if(shader->has_surface && space == NODE_NORMAL_MAP_TANGENT) {
- if(attribute.empty()) {
- attributes->add(ATTR_STD_UV_TANGENT);
- attributes->add(ATTR_STD_UV_TANGENT_SIGN);
- }
- else {
- attributes->add(ustring((string(attribute.c_str()) + ".tangent").c_str()));
- attributes->add(ustring((string(attribute.c_str()) + ".tangent_sign").c_str()));
- }
-
- attributes->add(ATTR_STD_VERTEX_NORMAL);
- }
-
- ShaderNode::attributes(shader, attributes);
-}
-
-void VectorDisplacementNode::compile(SVMCompiler& compiler)
-{
- ShaderInput *vector_in = input("Vector");
- ShaderInput *midlevel_in = input("Midlevel");
- ShaderInput *scale_in = input("Scale");
- ShaderOutput *displacement_out = output("Displacement");
- int attr = 0, attr_sign = 0;
-
- if(space == NODE_NORMAL_MAP_TANGENT) {
- if(attribute.empty()) {
- attr = compiler.attribute(ATTR_STD_UV_TANGENT);
- attr_sign = compiler.attribute(ATTR_STD_UV_TANGENT_SIGN);
- }
- else {
- attr = compiler.attribute(ustring((string(attribute.c_str()) + ".tangent").c_str()));
- attr_sign = compiler.attribute(ustring((string(attribute.c_str()) + ".tangent_sign").c_str()));
- }
- }
-
- compiler.add_node(NODE_VECTOR_DISPLACEMENT,
- compiler.encode_uchar4(compiler.stack_assign(vector_in),
- compiler.stack_assign(midlevel_in),
- compiler.stack_assign(scale_in),
- compiler.stack_assign(displacement_out)),
- attr, attr_sign);
-
- compiler.add_node(space);
-}
-
-void VectorDisplacementNode::compile(OSLCompiler& compiler)
-{
- if(space == NODE_NORMAL_MAP_TANGENT) {
- if(attribute.empty()) {
- compiler.parameter("attr_name", ustring("geom:tangent"));
- compiler.parameter("attr_sign_name", ustring("geom:tangent_sign"));
- }
- else {
- compiler.parameter("attr_name", ustring((string(attribute.c_str()) + ".tangent").c_str()));
- compiler.parameter("attr_sign_name", ustring((string(attribute.c_str()) + ".tangent_sign").c_str()));
- }
- }
-
- compiler.parameter(this, "space");
- compiler.add(this, "node_vector_displacement");
+ if (shader->has_surface && space == NODE_NORMAL_MAP_TANGENT) {
+ if (attribute.empty()) {
+ attributes->add(ATTR_STD_UV_TANGENT);
+ attributes->add(ATTR_STD_UV_TANGENT_SIGN);
+ }
+ else {
+ attributes->add(ustring((string(attribute.c_str()) + ".tangent").c_str()));
+ attributes->add(ustring((string(attribute.c_str()) + ".tangent_sign").c_str()));
+ }
+
+ attributes->add(ATTR_STD_VERTEX_NORMAL);
+ }
+
+ ShaderNode::attributes(shader, attributes);
+}
+
+void VectorDisplacementNode::compile(SVMCompiler &compiler)
+{
+ ShaderInput *vector_in = input("Vector");
+ ShaderInput *midlevel_in = input("Midlevel");
+ ShaderInput *scale_in = input("Scale");
+ ShaderOutput *displacement_out = output("Displacement");
+ int attr = 0, attr_sign = 0;
+
+ if (space == NODE_NORMAL_MAP_TANGENT) {
+ if (attribute.empty()) {
+ attr = compiler.attribute(ATTR_STD_UV_TANGENT);
+ attr_sign = compiler.attribute(ATTR_STD_UV_TANGENT_SIGN);
+ }
+ else {
+ attr = compiler.attribute(ustring((string(attribute.c_str()) + ".tangent").c_str()));
+ attr_sign = compiler.attribute(
+ ustring((string(attribute.c_str()) + ".tangent_sign").c_str()));
+ }
+ }
+
+ compiler.add_node(NODE_VECTOR_DISPLACEMENT,
+ compiler.encode_uchar4(compiler.stack_assign(vector_in),
+ compiler.stack_assign(midlevel_in),
+ compiler.stack_assign(scale_in),
+ compiler.stack_assign(displacement_out)),
+ attr,
+ attr_sign);
+
+ compiler.add_node(space);
+}
+
+void VectorDisplacementNode::compile(OSLCompiler &compiler)
+{
+ if (space == NODE_NORMAL_MAP_TANGENT) {
+ if (attribute.empty()) {
+ compiler.parameter("attr_name", ustring("geom:tangent"));
+ compiler.parameter("attr_sign_name", ustring("geom:tangent_sign"));
+ }
+ else {
+ compiler.parameter("attr_name", ustring((string(attribute.c_str()) + ".tangent").c_str()));
+ compiler.parameter("attr_sign_name",
+ ustring((string(attribute.c_str()) + ".tangent_sign").c_str()));
+ }
+ }
+
+ compiler.parameter(this, "space");
+ compiler.add(this, "node_vector_displacement");
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/render/nodes.h b/intern/cycles/render/nodes.h
index 5571c525e9a..7796711115e 100644
--- a/intern/cycles/render/nodes.h
+++ b/intern/cycles/render/nodes.h
@@ -33,1137 +33,1459 @@ class Shader;
/* Texture Mapping */
class TextureMapping {
-public:
- TextureMapping();
- Transform compute_transform();
- bool skip();
- void compile(SVMCompiler& compiler, int offset_in, int offset_out);
- int compile(SVMCompiler& compiler, ShaderInput *vector_in);
- void compile(OSLCompiler &compiler);
+ public:
+ TextureMapping();
+ Transform compute_transform();
+ bool skip();
+ void compile(SVMCompiler &compiler, int offset_in, int offset_out);
+ int compile(SVMCompiler &compiler, ShaderInput *vector_in);
+ void compile(OSLCompiler &compiler);
- int compile_begin(SVMCompiler& compiler, ShaderInput *vector_in);
- void compile_end(SVMCompiler& compiler, ShaderInput *vector_in, int vector_offset);
+ int compile_begin(SVMCompiler &compiler, ShaderInput *vector_in);
+ void compile_end(SVMCompiler &compiler, ShaderInput *vector_in, int vector_offset);
- float3 translation;
- float3 rotation;
- float3 scale;
+ float3 translation;
+ float3 rotation;
+ float3 scale;
- float3 min, max;
- bool use_minmax;
+ float3 min, max;
+ bool use_minmax;
- enum Type { POINT = 0, TEXTURE = 1, VECTOR = 2, NORMAL = 3 };
- Type type;
+ enum Type { POINT = 0, TEXTURE = 1, VECTOR = 2, NORMAL = 3 };
+ Type type;
- enum Mapping { NONE = 0, X = 1, Y = 2, Z = 3 };
- Mapping x_mapping, y_mapping, z_mapping;
+ enum Mapping { NONE = 0, X = 1, Y = 2, Z = 3 };
+ Mapping x_mapping, y_mapping, z_mapping;
- enum Projection { FLAT, CUBE, TUBE, SPHERE };
- Projection projection;
+ enum Projection { FLAT, CUBE, TUBE, SPHERE };
+ Projection projection;
};
/* Nodes */
class TextureNode : public ShaderNode {
-public:
- explicit TextureNode(const NodeType *node_type) : ShaderNode(node_type) {}
- TextureMapping tex_mapping;
+ public:
+ explicit TextureNode(const NodeType *node_type) : ShaderNode(node_type)
+ {
+ }
+ TextureMapping tex_mapping;
};
/* Any node which uses image manager's slot should be a subclass of this one. */
class ImageSlotTextureNode : public TextureNode {
-public:
- explicit ImageSlotTextureNode(const NodeType *node_type) : TextureNode(node_type) {
- special_type = SHADER_SPECIAL_TYPE_IMAGE_SLOT;
- }
- int slot;
+ public:
+ explicit ImageSlotTextureNode(const NodeType *node_type) : TextureNode(node_type)
+ {
+ special_type = SHADER_SPECIAL_TYPE_IMAGE_SLOT;
+ }
+ int slot;
};
class ImageTextureNode : public ImageSlotTextureNode {
-public:
- SHADER_NODE_NO_CLONE_CLASS(ImageTextureNode)
- ~ImageTextureNode();
- ShaderNode *clone() const;
- void attributes(Shader *shader, AttributeRequestSet *attributes);
- bool has_attribute_dependency() { return true; }
-
- ImageManager *image_manager;
- int is_float;
- bool is_linear;
- bool use_alpha;
- ustring filename;
- void *builtin_data;
- NodeImageColorSpace color_space;
- NodeImageProjection projection;
- InterpolationType interpolation;
- ExtensionType extension;
- float projection_blend;
- bool animated;
- float3 vector;
-
- virtual bool equals(const ShaderNode& other)
- {
- const ImageTextureNode& image_node = (const ImageTextureNode&)other;
- return ImageSlotTextureNode::equals(other) &&
- builtin_data == image_node.builtin_data &&
- animated == image_node.animated;
- }
+ public:
+ SHADER_NODE_NO_CLONE_CLASS(ImageTextureNode)
+ ~ImageTextureNode();
+ ShaderNode *clone() const;
+ void attributes(Shader *shader, AttributeRequestSet *attributes);
+ bool has_attribute_dependency()
+ {
+ return true;
+ }
+
+ ImageManager *image_manager;
+ int is_float;
+ bool is_linear;
+ bool use_alpha;
+ ustring filename;
+ void *builtin_data;
+ NodeImageColorSpace color_space;
+ NodeImageProjection projection;
+ InterpolationType interpolation;
+ ExtensionType extension;
+ float projection_blend;
+ bool animated;
+ float3 vector;
+
+ virtual bool equals(const ShaderNode &other)
+ {
+ const ImageTextureNode &image_node = (const ImageTextureNode &)other;
+ return ImageSlotTextureNode::equals(other) && builtin_data == image_node.builtin_data &&
+ animated == image_node.animated;
+ }
};
class EnvironmentTextureNode : public ImageSlotTextureNode {
-public:
- SHADER_NODE_NO_CLONE_CLASS(EnvironmentTextureNode)
- ~EnvironmentTextureNode();
- ShaderNode *clone() const;
- void attributes(Shader *shader, AttributeRequestSet *attributes);
- bool has_attribute_dependency() { return true; }
- virtual int get_group() { return NODE_GROUP_LEVEL_2; }
-
- ImageManager *image_manager;
- int is_float;
- bool is_linear;
- bool use_alpha;
- ustring filename;
- void *builtin_data;
- NodeImageColorSpace color_space;
- NodeEnvironmentProjection projection;
- InterpolationType interpolation;
- bool animated;
- float3 vector;
-
- virtual bool equals(const ShaderNode& other)
- {
- const EnvironmentTextureNode& env_node = (const EnvironmentTextureNode&)other;
- return ImageSlotTextureNode::equals(other) &&
- builtin_data == env_node.builtin_data &&
- animated == env_node.animated;
- }
+ public:
+ SHADER_NODE_NO_CLONE_CLASS(EnvironmentTextureNode)
+ ~EnvironmentTextureNode();
+ ShaderNode *clone() const;
+ void attributes(Shader *shader, AttributeRequestSet *attributes);
+ bool has_attribute_dependency()
+ {
+ return true;
+ }
+ virtual int get_group()
+ {
+ return NODE_GROUP_LEVEL_2;
+ }
+
+ ImageManager *image_manager;
+ int is_float;
+ bool is_linear;
+ bool use_alpha;
+ ustring filename;
+ void *builtin_data;
+ NodeImageColorSpace color_space;
+ NodeEnvironmentProjection projection;
+ InterpolationType interpolation;
+ bool animated;
+ float3 vector;
+
+ virtual bool equals(const ShaderNode &other)
+ {
+ const EnvironmentTextureNode &env_node = (const EnvironmentTextureNode &)other;
+ return ImageSlotTextureNode::equals(other) && builtin_data == env_node.builtin_data &&
+ animated == env_node.animated;
+ }
};
class SkyTextureNode : public TextureNode {
-public:
- SHADER_NODE_CLASS(SkyTextureNode)
+ public:
+ SHADER_NODE_CLASS(SkyTextureNode)
- virtual int get_group() { return NODE_GROUP_LEVEL_2; }
+ virtual int get_group()
+ {
+ return NODE_GROUP_LEVEL_2;
+ }
- NodeSkyType type;
- float3 sun_direction;
- float turbidity;
- float ground_albedo;
- float3 vector;
+ NodeSkyType type;
+ float3 sun_direction;
+ float turbidity;
+ float ground_albedo;
+ float3 vector;
};
class OutputNode : public ShaderNode {
-public:
- SHADER_NODE_CLASS(OutputNode)
+ public:
+ SHADER_NODE_CLASS(OutputNode)
- void *surface;
- void *volume;
- float3 displacement;
- float3 normal;
+ void *surface;
+ void *volume;
+ float3 displacement;
+ float3 normal;
- /* Don't allow output node de-duplication. */
- virtual bool equals(const ShaderNode& /*other*/) { return false; }
+ /* Don't allow output node de-duplication. */
+ virtual bool equals(const ShaderNode & /*other*/)
+ {
+ return false;
+ }
};
class GradientTextureNode : public TextureNode {
-public:
- SHADER_NODE_CLASS(GradientTextureNode)
+ public:
+ SHADER_NODE_CLASS(GradientTextureNode)
- virtual int get_group() { return NODE_GROUP_LEVEL_2; }
+ virtual int get_group()
+ {
+ return NODE_GROUP_LEVEL_2;
+ }
- NodeGradientType type;
- float3 vector;
+ NodeGradientType type;
+ float3 vector;
};
class NoiseTextureNode : public TextureNode {
-public:
- SHADER_NODE_CLASS(NoiseTextureNode)
+ public:
+ SHADER_NODE_CLASS(NoiseTextureNode)
- float scale, detail, distortion;
- float3 vector;
+ float scale, detail, distortion;
+ float3 vector;
};
class VoronoiTextureNode : public TextureNode {
-public:
- SHADER_NODE_CLASS(VoronoiTextureNode)
+ public:
+ SHADER_NODE_CLASS(VoronoiTextureNode)
- virtual int get_group() { return NODE_GROUP_LEVEL_2; }
+ virtual int get_group()
+ {
+ return NODE_GROUP_LEVEL_2;
+ }
- NodeVoronoiColoring coloring;
- NodeVoronoiDistanceMetric metric;
- NodeVoronoiFeature feature;
- float scale, exponent;
- float3 vector;
+ NodeVoronoiColoring coloring;
+ NodeVoronoiDistanceMetric metric;
+ NodeVoronoiFeature feature;
+ float scale, exponent;
+ float3 vector;
};
class MusgraveTextureNode : public TextureNode {
-public:
- SHADER_NODE_CLASS(MusgraveTextureNode)
+ public:
+ SHADER_NODE_CLASS(MusgraveTextureNode)
- virtual int get_group() { return NODE_GROUP_LEVEL_2; }
+ virtual int get_group()
+ {
+ return NODE_GROUP_LEVEL_2;
+ }
- NodeMusgraveType type;
- float scale, detail, dimension, lacunarity, offset, gain;
- float3 vector;
+ NodeMusgraveType type;
+ float scale, detail, dimension, lacunarity, offset, gain;
+ float3 vector;
};
class WaveTextureNode : public TextureNode {
-public:
- SHADER_NODE_CLASS(WaveTextureNode)
+ public:
+ SHADER_NODE_CLASS(WaveTextureNode)
- virtual int get_group() { return NODE_GROUP_LEVEL_2; }
+ virtual int get_group()
+ {
+ return NODE_GROUP_LEVEL_2;
+ }
- NodeWaveType type;
- NodeWaveProfile profile;
+ NodeWaveType type;
+ NodeWaveProfile profile;
- float scale, distortion, detail, detail_scale;
- float3 vector;
+ float scale, distortion, detail, detail_scale;
+ float3 vector;
};
class MagicTextureNode : public TextureNode {
-public:
- SHADER_NODE_CLASS(MagicTextureNode)
+ public:
+ SHADER_NODE_CLASS(MagicTextureNode)
- virtual int get_group() { return NODE_GROUP_LEVEL_2; }
+ virtual int get_group()
+ {
+ return NODE_GROUP_LEVEL_2;
+ }
- int depth;
- float3 vector;
- float scale, distortion;
+ int depth;
+ float3 vector;
+ float scale, distortion;
};
class CheckerTextureNode : public TextureNode {
-public:
- SHADER_NODE_CLASS(CheckerTextureNode)
+ public:
+ SHADER_NODE_CLASS(CheckerTextureNode)
- float3 vector, color1, color2;
- float scale;
+ float3 vector, color1, color2;
+ float scale;
- virtual int get_group() { return NODE_GROUP_LEVEL_2; }
+ virtual int get_group()
+ {
+ return NODE_GROUP_LEVEL_2;
+ }
};
class BrickTextureNode : public TextureNode {
-public:
- SHADER_NODE_CLASS(BrickTextureNode)
+ public:
+ SHADER_NODE_CLASS(BrickTextureNode)
- float offset, squash;
- int offset_frequency, squash_frequency;
+ float offset, squash;
+ int offset_frequency, squash_frequency;
- float3 color1, color2, mortar;
- float scale, mortar_size, mortar_smooth, bias, brick_width, row_height;
- float3 vector;
+ float3 color1, color2, mortar;
+ float scale, mortar_size, mortar_smooth, bias, brick_width, row_height;
+ float3 vector;
- virtual int get_group() { return NODE_GROUP_LEVEL_2; }
+ virtual int get_group()
+ {
+ return NODE_GROUP_LEVEL_2;
+ }
};
class PointDensityTextureNode : public ShaderNode {
-public:
- SHADER_NODE_NO_CLONE_CLASS(PointDensityTextureNode)
- virtual int get_group() { return NODE_GROUP_LEVEL_3; }
-
- ~PointDensityTextureNode();
- ShaderNode *clone() const;
- void attributes(Shader *shader, AttributeRequestSet *attributes);
- bool has_attribute_dependency() { return true; }
-
- bool has_spatial_varying() { return true; }
- bool has_object_dependency() { return true; }
-
- void add_image();
-
- ustring filename;
- NodeTexVoxelSpace space;
- InterpolationType interpolation;
- Transform tfm;
- float3 vector;
-
- ImageManager *image_manager;
- int slot;
- void *builtin_data;
-
- virtual bool equals(const ShaderNode& other) {
- const PointDensityTextureNode& point_dendity_node = (const PointDensityTextureNode&)other;
- return ShaderNode::equals(other) &&
- builtin_data == point_dendity_node.builtin_data;
- }
+ public:
+ SHADER_NODE_NO_CLONE_CLASS(PointDensityTextureNode)
+ virtual int get_group()
+ {
+ return NODE_GROUP_LEVEL_3;
+ }
+
+ ~PointDensityTextureNode();
+ ShaderNode *clone() const;
+ void attributes(Shader *shader, AttributeRequestSet *attributes);
+ bool has_attribute_dependency()
+ {
+ return true;
+ }
+
+ bool has_spatial_varying()
+ {
+ return true;
+ }
+ bool has_object_dependency()
+ {
+ return true;
+ }
+
+ void add_image();
+
+ ustring filename;
+ NodeTexVoxelSpace space;
+ InterpolationType interpolation;
+ Transform tfm;
+ float3 vector;
+
+ ImageManager *image_manager;
+ int slot;
+ void *builtin_data;
+
+ virtual bool equals(const ShaderNode &other)
+ {
+ const PointDensityTextureNode &point_dendity_node = (const PointDensityTextureNode &)other;
+ return ShaderNode::equals(other) && builtin_data == point_dendity_node.builtin_data;
+ }
};
class IESLightNode : public TextureNode {
-public:
- SHADER_NODE_NO_CLONE_CLASS(IESLightNode)
+ public:
+ SHADER_NODE_NO_CLONE_CLASS(IESLightNode)
- ~IESLightNode();
- ShaderNode *clone() const;
- virtual int get_group() { return NODE_GROUP_LEVEL_2; }
+ ~IESLightNode();
+ ShaderNode *clone() const;
+ virtual int get_group()
+ {
+ return NODE_GROUP_LEVEL_2;
+ }
- ustring filename;
- ustring ies;
+ ustring filename;
+ ustring ies;
- float strength;
- float3 vector;
+ float strength;
+ float3 vector;
-private:
- LightManager *light_manager;
- int slot;
+ private:
+ LightManager *light_manager;
+ int slot;
- void get_slot();
+ void get_slot();
};
class MappingNode : public ShaderNode {
-public:
- SHADER_NODE_CLASS(MappingNode)
- virtual int get_group() { return NODE_GROUP_LEVEL_2; }
+ public:
+ SHADER_NODE_CLASS(MappingNode)
+ virtual int get_group()
+ {
+ return NODE_GROUP_LEVEL_2;
+ }
- float3 vector;
- TextureMapping tex_mapping;
+ float3 vector;
+ TextureMapping tex_mapping;
};
class RGBToBWNode : public ShaderNode {
-public:
- SHADER_NODE_CLASS(RGBToBWNode)
- void constant_fold(const ConstantFolder& folder);
+ public:
+ SHADER_NODE_CLASS(RGBToBWNode)
+ void constant_fold(const ConstantFolder &folder);
- float3 color;
+ float3 color;
};
class ConvertNode : public ShaderNode {
-public:
- ConvertNode(SocketType::Type from, SocketType::Type to, bool autoconvert = false);
- SHADER_NODE_BASE_CLASS(ConvertNode)
+ public:
+ ConvertNode(SocketType::Type from, SocketType::Type to, bool autoconvert = false);
+ SHADER_NODE_BASE_CLASS(ConvertNode)
- void constant_fold(const ConstantFolder& folder);
+ void constant_fold(const ConstantFolder &folder);
- SocketType::Type from, to;
+ SocketType::Type from, to;
- union {
- float value_float;
- int value_int;
- float3 value_color;
- float3 value_vector;
- float3 value_point;
- float3 value_normal;
- };
- ustring value_string;
+ union {
+ float value_float;
+ int value_int;
+ float3 value_color;
+ float3 value_vector;
+ float3 value_point;
+ float3 value_normal;
+ };
+ ustring value_string;
-private:
- static const int MAX_TYPE = 12;
- static bool register_types();
- static Node* create(const NodeType *type);
- static const NodeType *node_types[MAX_TYPE][MAX_TYPE];
- static bool initialized;
+ private:
+ static const int MAX_TYPE = 12;
+ static bool register_types();
+ static Node *create(const NodeType *type);
+ static const NodeType *node_types[MAX_TYPE][MAX_TYPE];
+ static bool initialized;
};
class BsdfBaseNode : public ShaderNode {
-public:
- BsdfBaseNode(const NodeType *node_type);
+ public:
+ BsdfBaseNode(const NodeType *node_type);
- bool has_spatial_varying() { return true; }
- virtual ClosureType get_closure_type() { return closure; }
- virtual bool has_bump();
+ bool has_spatial_varying()
+ {
+ return true;
+ }
+ virtual ClosureType get_closure_type()
+ {
+ return closure;
+ }
+ virtual bool has_bump();
- virtual bool equals(const ShaderNode& /*other*/)
- {
- /* TODO(sergey): With some care BSDF nodes can be de-duplicated. */
- return false;
- }
+ virtual bool equals(const ShaderNode & /*other*/)
+ {
+ /* TODO(sergey): With some care BSDF nodes can be de-duplicated. */
+ return false;
+ }
- ClosureType closure;
+ ClosureType closure;
};
class BsdfNode : public BsdfBaseNode {
-public:
- explicit BsdfNode(const NodeType *node_type);
- SHADER_NODE_BASE_CLASS(BsdfNode)
+ public:
+ explicit BsdfNode(const NodeType *node_type);
+ SHADER_NODE_BASE_CLASS(BsdfNode)
- void compile(SVMCompiler& compiler, ShaderInput *param1, ShaderInput *param2, ShaderInput *param3 = NULL, ShaderInput *param4 = NULL);
+ void compile(SVMCompiler &compiler,
+ ShaderInput *param1,
+ ShaderInput *param2,
+ ShaderInput *param3 = NULL,
+ ShaderInput *param4 = NULL);
- float3 color;
- float3 normal;
- float surface_mix_weight;
+ float3 color;
+ float3 normal;
+ float surface_mix_weight;
};
class AnisotropicBsdfNode : public BsdfNode {
-public:
- SHADER_NODE_CLASS(AnisotropicBsdfNode)
+ public:
+ SHADER_NODE_CLASS(AnisotropicBsdfNode)
- float3 tangent;
- float roughness, anisotropy, rotation;
- ClosureType distribution;
+ float3 tangent;
+ float roughness, anisotropy, rotation;
+ ClosureType distribution;
- ClosureType get_closure_type() { return distribution; }
- void attributes(Shader *shader, AttributeRequestSet *attributes);
- bool has_attribute_dependency() { return true; }
+ ClosureType get_closure_type()
+ {
+ return distribution;
+ }
+ void attributes(Shader *shader, AttributeRequestSet *attributes);
+ bool has_attribute_dependency()
+ {
+ return true;
+ }
};
class DiffuseBsdfNode : public BsdfNode {
-public:
- SHADER_NODE_CLASS(DiffuseBsdfNode)
+ public:
+ SHADER_NODE_CLASS(DiffuseBsdfNode)
- float roughness;
+ float roughness;
};
/* Disney principled BRDF */
class PrincipledBsdfNode : public BsdfBaseNode {
-public:
- SHADER_NODE_CLASS(PrincipledBsdfNode)
-
- bool has_surface_bssrdf();
- bool has_bssrdf_bump();
- void compile(SVMCompiler& compiler, ShaderInput *metallic, ShaderInput *subsurface, ShaderInput *subsurface_radius,
- ShaderInput *specular, ShaderInput *roughness, ShaderInput *specular_tint, ShaderInput *anisotropic,
- ShaderInput *sheen, ShaderInput *sheen_tint, ShaderInput *clearcoat, ShaderInput *clearcoat_roughness,
- ShaderInput *ior, ShaderInput *transmission, ShaderInput *anisotropic_rotation, ShaderInput *transmission_roughness);
-
- float3 base_color;
- float3 subsurface_color, subsurface_radius;
- float metallic, subsurface, specular, roughness, specular_tint, anisotropic,
- sheen, sheen_tint, clearcoat, clearcoat_roughness, ior, transmission,
- anisotropic_rotation, transmission_roughness;
- float3 normal, clearcoat_normal, tangent;
- float surface_mix_weight;
- ClosureType distribution, distribution_orig;
- ClosureType subsurface_method;
-
- bool has_integrator_dependency();
- void attributes(Shader *shader, AttributeRequestSet *attributes);
- bool has_attribute_dependency() { return true; }
+ public:
+ SHADER_NODE_CLASS(PrincipledBsdfNode)
+
+ bool has_surface_bssrdf();
+ bool has_bssrdf_bump();
+ void compile(SVMCompiler &compiler,
+ ShaderInput *metallic,
+ ShaderInput *subsurface,
+ ShaderInput *subsurface_radius,
+ ShaderInput *specular,
+ ShaderInput *roughness,
+ ShaderInput *specular_tint,
+ ShaderInput *anisotropic,
+ ShaderInput *sheen,
+ ShaderInput *sheen_tint,
+ ShaderInput *clearcoat,
+ ShaderInput *clearcoat_roughness,
+ ShaderInput *ior,
+ ShaderInput *transmission,
+ ShaderInput *anisotropic_rotation,
+ ShaderInput *transmission_roughness);
+
+ float3 base_color;
+ float3 subsurface_color, subsurface_radius;
+ float metallic, subsurface, specular, roughness, specular_tint, anisotropic, sheen, sheen_tint,
+ clearcoat, clearcoat_roughness, ior, transmission, anisotropic_rotation,
+ transmission_roughness;
+ float3 normal, clearcoat_normal, tangent;
+ float surface_mix_weight;
+ ClosureType distribution, distribution_orig;
+ ClosureType subsurface_method;
+
+ bool has_integrator_dependency();
+ void attributes(Shader *shader, AttributeRequestSet *attributes);
+ bool has_attribute_dependency()
+ {
+ return true;
+ }
};
class TranslucentBsdfNode : public BsdfNode {
-public:
- SHADER_NODE_CLASS(TranslucentBsdfNode)
+ public:
+ SHADER_NODE_CLASS(TranslucentBsdfNode)
};
class TransparentBsdfNode : public BsdfNode {
-public:
- SHADER_NODE_CLASS(TransparentBsdfNode)
+ public:
+ SHADER_NODE_CLASS(TransparentBsdfNode)
- bool has_surface_transparent() { return true; }
+ bool has_surface_transparent()
+ {
+ return true;
+ }
};
class VelvetBsdfNode : public BsdfNode {
-public:
- SHADER_NODE_CLASS(VelvetBsdfNode)
+ public:
+ SHADER_NODE_CLASS(VelvetBsdfNode)
- float sigma;
+ float sigma;
};
class GlossyBsdfNode : public BsdfNode {
-public:
- SHADER_NODE_CLASS(GlossyBsdfNode)
+ public:
+ SHADER_NODE_CLASS(GlossyBsdfNode)
- void simplify_settings(Scene *scene);
- bool has_integrator_dependency();
- ClosureType get_closure_type() { return distribution; }
+ void simplify_settings(Scene *scene);
+ bool has_integrator_dependency();
+ ClosureType get_closure_type()
+ {
+ return distribution;
+ }
- float roughness, roughness_orig;
- ClosureType distribution, distribution_orig;
+ float roughness, roughness_orig;
+ ClosureType distribution, distribution_orig;
};
class GlassBsdfNode : public BsdfNode {
-public:
- SHADER_NODE_CLASS(GlassBsdfNode)
+ public:
+ SHADER_NODE_CLASS(GlassBsdfNode)
- void simplify_settings(Scene *scene);
- bool has_integrator_dependency();
- ClosureType get_closure_type() { return distribution; }
+ void simplify_settings(Scene *scene);
+ bool has_integrator_dependency();
+ ClosureType get_closure_type()
+ {
+ return distribution;
+ }
- float roughness, roughness_orig, IOR;
- ClosureType distribution, distribution_orig;
+ float roughness, roughness_orig, IOR;
+ ClosureType distribution, distribution_orig;
};
class RefractionBsdfNode : public BsdfNode {
-public:
- SHADER_NODE_CLASS(RefractionBsdfNode)
+ public:
+ SHADER_NODE_CLASS(RefractionBsdfNode)
- void simplify_settings(Scene *scene);
- bool has_integrator_dependency();
- ClosureType get_closure_type() { return distribution; }
+ void simplify_settings(Scene *scene);
+ bool has_integrator_dependency();
+ ClosureType get_closure_type()
+ {
+ return distribution;
+ }
- float roughness, roughness_orig, IOR;
- ClosureType distribution, distribution_orig;
+ float roughness, roughness_orig, IOR;
+ ClosureType distribution, distribution_orig;
};
class ToonBsdfNode : public BsdfNode {
-public:
- SHADER_NODE_CLASS(ToonBsdfNode)
+ public:
+ SHADER_NODE_CLASS(ToonBsdfNode)
- float smooth, size;
- ClosureType component;
+ float smooth, size;
+ ClosureType component;
};
class SubsurfaceScatteringNode : public BsdfNode {
-public:
- SHADER_NODE_CLASS(SubsurfaceScatteringNode)
- bool has_surface_bssrdf() { return true; }
- bool has_bssrdf_bump();
- ClosureType get_closure_type() { return falloff; }
-
- float scale;
- float3 radius;
- float sharpness;
- float texture_blur;
- ClosureType falloff;
+ public:
+ SHADER_NODE_CLASS(SubsurfaceScatteringNode)
+ bool has_surface_bssrdf()
+ {
+ return true;
+ }
+ bool has_bssrdf_bump();
+ ClosureType get_closure_type()
+ {
+ return falloff;
+ }
+
+ float scale;
+ float3 radius;
+ float sharpness;
+ float texture_blur;
+ ClosureType falloff;
};
class EmissionNode : public ShaderNode {
-public:
- SHADER_NODE_CLASS(EmissionNode)
- void constant_fold(const ConstantFolder& folder);
+ public:
+ SHADER_NODE_CLASS(EmissionNode)
+ void constant_fold(const ConstantFolder &folder);
- bool has_surface_emission() { return true; }
- bool has_volume_support() { return true; }
+ bool has_surface_emission()
+ {
+ return true;
+ }
+ bool has_volume_support()
+ {
+ return true;
+ }
- float3 color;
- float strength;
- float surface_mix_weight;
+ float3 color;
+ float strength;
+ float surface_mix_weight;
};
class BackgroundNode : public ShaderNode {
-public:
- SHADER_NODE_CLASS(BackgroundNode)
- void constant_fold(const ConstantFolder& folder);
+ public:
+ SHADER_NODE_CLASS(BackgroundNode)
+ void constant_fold(const ConstantFolder &folder);
- float3 color;
- float strength;
- float surface_mix_weight;
+ float3 color;
+ float strength;
+ float surface_mix_weight;
};
class HoldoutNode : public ShaderNode {
-public:
- SHADER_NODE_CLASS(HoldoutNode)
- virtual int get_group() { return NODE_GROUP_LEVEL_1; }
- virtual ClosureType get_closure_type() { return CLOSURE_HOLDOUT_ID; }
+ public:
+ SHADER_NODE_CLASS(HoldoutNode)
+ virtual int get_group()
+ {
+ return NODE_GROUP_LEVEL_1;
+ }
+ virtual ClosureType get_closure_type()
+ {
+ return CLOSURE_HOLDOUT_ID;
+ }
- float surface_mix_weight;
- float volume_mix_weight;
+ float surface_mix_weight;
+ float volume_mix_weight;
};
class AmbientOcclusionNode : public ShaderNode {
-public:
- SHADER_NODE_CLASS(AmbientOcclusionNode)
-
- bool has_spatial_varying() { return true; }
- virtual int get_group() { return NODE_GROUP_LEVEL_3; }
- virtual bool has_raytrace() { return true; }
-
- float3 color;
- float distance;
- float3 normal;
- int samples;
-
- bool only_local;
- bool inside;
+ public:
+ SHADER_NODE_CLASS(AmbientOcclusionNode)
+
+ bool has_spatial_varying()
+ {
+ return true;
+ }
+ virtual int get_group()
+ {
+ return NODE_GROUP_LEVEL_3;
+ }
+ virtual bool has_raytrace()
+ {
+ return true;
+ }
+
+ float3 color;
+ float distance;
+ float3 normal;
+ int samples;
+
+ bool only_local;
+ bool inside;
};
class VolumeNode : public ShaderNode {
-public:
- VolumeNode(const NodeType *node_type);
- SHADER_NODE_BASE_CLASS(VolumeNode)
-
- void compile(SVMCompiler& compiler, ShaderInput *param1, ShaderInput *param2);
- virtual int get_group() { return NODE_GROUP_LEVEL_1; }
- virtual int get_feature() {
- return ShaderNode::get_feature() | NODE_FEATURE_VOLUME;
- }
- virtual ClosureType get_closure_type() { return closure; }
- virtual bool has_volume_support() { return true; }
-
- float3 color;
- float density;
- float volume_mix_weight;
- ClosureType closure;
-
- virtual bool equals(const ShaderNode& /*other*/)
- {
- /* TODO(sergey): With some care Volume nodes can be de-duplicated. */
- return false;
- }
+ public:
+ VolumeNode(const NodeType *node_type);
+ SHADER_NODE_BASE_CLASS(VolumeNode)
+
+ void compile(SVMCompiler &compiler, ShaderInput *param1, ShaderInput *param2);
+ virtual int get_group()
+ {
+ return NODE_GROUP_LEVEL_1;
+ }
+ virtual int get_feature()
+ {
+ return ShaderNode::get_feature() | NODE_FEATURE_VOLUME;
+ }
+ virtual ClosureType get_closure_type()
+ {
+ return closure;
+ }
+ virtual bool has_volume_support()
+ {
+ return true;
+ }
+
+ float3 color;
+ float density;
+ float volume_mix_weight;
+ ClosureType closure;
+
+ virtual bool equals(const ShaderNode & /*other*/)
+ {
+ /* TODO(sergey): With some care Volume nodes can be de-duplicated. */
+ return false;
+ }
};
class AbsorptionVolumeNode : public VolumeNode {
-public:
- SHADER_NODE_CLASS(AbsorptionVolumeNode)
+ public:
+ SHADER_NODE_CLASS(AbsorptionVolumeNode)
};
class ScatterVolumeNode : public VolumeNode {
-public:
- SHADER_NODE_CLASS(ScatterVolumeNode)
+ public:
+ SHADER_NODE_CLASS(ScatterVolumeNode)
- float anisotropy;
+ float anisotropy;
};
class PrincipledVolumeNode : public VolumeNode {
-public:
- SHADER_NODE_CLASS(PrincipledVolumeNode)
- void attributes(Shader *shader, AttributeRequestSet *attributes);
- bool has_attribute_dependency() { return true; }
-
- ustring density_attribute;
- ustring color_attribute;
- ustring temperature_attribute;
-
- float anisotropy;
- float3 absorption_color;
- float emission_strength;
- float3 emission_color;
- float blackbody_intensity;
- float3 blackbody_tint;
- float temperature;
+ public:
+ SHADER_NODE_CLASS(PrincipledVolumeNode)
+ void attributes(Shader *shader, AttributeRequestSet *attributes);
+ bool has_attribute_dependency()
+ {
+ return true;
+ }
+
+ ustring density_attribute;
+ ustring color_attribute;
+ ustring temperature_attribute;
+
+ float anisotropy;
+ float3 absorption_color;
+ float emission_strength;
+ float3 emission_color;
+ float blackbody_intensity;
+ float3 blackbody_tint;
+ float temperature;
};
/* Interface between the I/O sockets and the SVM/OSL backend. */
class PrincipledHairBsdfNode : public BsdfBaseNode {
-public:
- SHADER_NODE_CLASS(PrincipledHairBsdfNode)
- void attributes(Shader *shader, AttributeRequestSet *attributes);
-
- /* Longitudinal roughness. */
- float roughness;
- /* Azimuthal roughness. */
- float radial_roughness;
- /* Randomization factor for roughnesses. */
- float random_roughness;
- /* Longitudinal roughness factor for only the diffuse bounce (shiny undercoat). */
- float coat;
- /* Index of reflection. */
- float ior;
- /* Cuticle tilt angle. */
- float offset;
- /* Direct coloring's color. */
- float3 color;
- /* Melanin concentration. */
- float melanin;
- /* Melanin redness ratio. */
- float melanin_redness;
- /* Dye color. */
- float3 tint;
- /* Randomization factor for melanin quantities. */
- float random_color;
- /* Absorption coefficient (unfiltered). */
- float3 absorption_coefficient;
-
- float3 normal;
- float surface_mix_weight;
- /* If linked, here will be the given random number. */
- float random;
- /* Selected coloring parametrization. */
- NodePrincipledHairParametrization parametrization;
+ public:
+ SHADER_NODE_CLASS(PrincipledHairBsdfNode)
+ void attributes(Shader *shader, AttributeRequestSet *attributes);
+
+ /* Longitudinal roughness. */
+ float roughness;
+ /* Azimuthal roughness. */
+ float radial_roughness;
+ /* Randomization factor for roughnesses. */
+ float random_roughness;
+ /* Longitudinal roughness factor for only the diffuse bounce (shiny undercoat). */
+ float coat;
+ /* Index of reflection. */
+ float ior;
+ /* Cuticle tilt angle. */
+ float offset;
+ /* Direct coloring's color. */
+ float3 color;
+ /* Melanin concentration. */
+ float melanin;
+ /* Melanin redness ratio. */
+ float melanin_redness;
+ /* Dye color. */
+ float3 tint;
+ /* Randomization factor for melanin quantities. */
+ float random_color;
+ /* Absorption coefficient (unfiltered). */
+ float3 absorption_coefficient;
+
+ float3 normal;
+ float surface_mix_weight;
+ /* If linked, here will be the given random number. */
+ float random;
+ /* Selected coloring parametrization. */
+ NodePrincipledHairParametrization parametrization;
};
class HairBsdfNode : public BsdfNode {
-public:
- SHADER_NODE_CLASS(HairBsdfNode)
- ClosureType get_closure_type() { return component; }
+ public:
+ SHADER_NODE_CLASS(HairBsdfNode)
+ ClosureType get_closure_type()
+ {
+ return component;
+ }
- ClosureType component;
- float offset;
- float roughness_u;
- float roughness_v;
- float3 tangent;
+ ClosureType component;
+ float offset;
+ float roughness_u;
+ float roughness_v;
+ float3 tangent;
};
class GeometryNode : public ShaderNode {
-public:
- SHADER_NODE_CLASS(GeometryNode)
- void attributes(Shader *shader, AttributeRequestSet *attributes);
- bool has_attribute_dependency() { return true; }
- bool has_spatial_varying() { return true; }
- int get_group();
-
- float3 normal_osl;
+ public:
+ SHADER_NODE_CLASS(GeometryNode)
+ void attributes(Shader *shader, AttributeRequestSet *attributes);
+ bool has_attribute_dependency()
+ {
+ return true;
+ }
+ bool has_spatial_varying()
+ {
+ return true;
+ }
+ int get_group();
+
+ float3 normal_osl;
};
class TextureCoordinateNode : public ShaderNode {
-public:
- SHADER_NODE_CLASS(TextureCoordinateNode)
- void attributes(Shader *shader, AttributeRequestSet *attributes);
- bool has_attribute_dependency() { return true; }
- bool has_spatial_varying() { return true; }
- bool has_object_dependency() { return use_transform; }
-
- float3 normal_osl;
- bool from_dupli;
- bool use_transform;
- Transform ob_tfm;
+ public:
+ SHADER_NODE_CLASS(TextureCoordinateNode)
+ void attributes(Shader *shader, AttributeRequestSet *attributes);
+ bool has_attribute_dependency()
+ {
+ return true;
+ }
+ bool has_spatial_varying()
+ {
+ return true;
+ }
+ bool has_object_dependency()
+ {
+ return use_transform;
+ }
+
+ float3 normal_osl;
+ bool from_dupli;
+ bool use_transform;
+ Transform ob_tfm;
};
class UVMapNode : public ShaderNode {
-public:
- SHADER_NODE_CLASS(UVMapNode)
- void attributes(Shader *shader, AttributeRequestSet *attributes);
- bool has_attribute_dependency() { return true; }
- bool has_spatial_varying() { return true; }
- virtual int get_group() { return NODE_GROUP_LEVEL_1; }
-
- ustring attribute;
- bool from_dupli;
+ public:
+ SHADER_NODE_CLASS(UVMapNode)
+ void attributes(Shader *shader, AttributeRequestSet *attributes);
+ bool has_attribute_dependency()
+ {
+ return true;
+ }
+ bool has_spatial_varying()
+ {
+ return true;
+ }
+ virtual int get_group()
+ {
+ return NODE_GROUP_LEVEL_1;
+ }
+
+ ustring attribute;
+ bool from_dupli;
};
class LightPathNode : public ShaderNode {
-public:
- SHADER_NODE_CLASS(LightPathNode)
- virtual int get_group() { return NODE_GROUP_LEVEL_1; }
+ public:
+ SHADER_NODE_CLASS(LightPathNode)
+ virtual int get_group()
+ {
+ return NODE_GROUP_LEVEL_1;
+ }
};
class LightFalloffNode : public ShaderNode {
-public:
- SHADER_NODE_CLASS(LightFalloffNode)
- bool has_spatial_varying() { return true; }
- virtual int get_group() { return NODE_GROUP_LEVEL_2; }
+ public:
+ SHADER_NODE_CLASS(LightFalloffNode)
+ bool has_spatial_varying()
+ {
+ return true;
+ }
+ virtual int get_group()
+ {
+ return NODE_GROUP_LEVEL_2;
+ }
- float strength;
- float smooth;
+ float strength;
+ float smooth;
};
class ObjectInfoNode : public ShaderNode {
-public:
- SHADER_NODE_CLASS(ObjectInfoNode)
- virtual int get_group() { return NODE_GROUP_LEVEL_1; }
+ public:
+ SHADER_NODE_CLASS(ObjectInfoNode)
+ virtual int get_group()
+ {
+ return NODE_GROUP_LEVEL_1;
+ }
};
class ParticleInfoNode : public ShaderNode {
-public:
- SHADER_NODE_CLASS(ParticleInfoNode)
- void attributes(Shader *shader, AttributeRequestSet *attributes);
- bool has_attribute_dependency() { return true; }
- virtual int get_group() { return NODE_GROUP_LEVEL_1; }
+ public:
+ SHADER_NODE_CLASS(ParticleInfoNode)
+ void attributes(Shader *shader, AttributeRequestSet *attributes);
+ bool has_attribute_dependency()
+ {
+ return true;
+ }
+ virtual int get_group()
+ {
+ return NODE_GROUP_LEVEL_1;
+ }
};
class HairInfoNode : public ShaderNode {
-public:
- SHADER_NODE_CLASS(HairInfoNode)
-
- void attributes(Shader *shader, AttributeRequestSet *attributes);
- bool has_attribute_dependency() { return true; }
- bool has_spatial_varying() { return true; }
- virtual int get_group() { return NODE_GROUP_LEVEL_1; }
- virtual int get_feature() {
- return ShaderNode::get_feature() | NODE_FEATURE_HAIR;
- }
+ public:
+ SHADER_NODE_CLASS(HairInfoNode)
+
+ void attributes(Shader *shader, AttributeRequestSet *attributes);
+ bool has_attribute_dependency()
+ {
+ return true;
+ }
+ bool has_spatial_varying()
+ {
+ return true;
+ }
+ virtual int get_group()
+ {
+ return NODE_GROUP_LEVEL_1;
+ }
+ virtual int get_feature()
+ {
+ return ShaderNode::get_feature() | NODE_FEATURE_HAIR;
+ }
};
class ValueNode : public ShaderNode {
-public:
- SHADER_NODE_CLASS(ValueNode)
+ public:
+ SHADER_NODE_CLASS(ValueNode)
- void constant_fold(const ConstantFolder& folder);
+ void constant_fold(const ConstantFolder &folder);
- float value;
+ float value;
};
class ColorNode : public ShaderNode {
-public:
- SHADER_NODE_CLASS(ColorNode)
+ public:
+ SHADER_NODE_CLASS(ColorNode)
- void constant_fold(const ConstantFolder& folder);
+ void constant_fold(const ConstantFolder &folder);
- float3 value;
+ float3 value;
};
class AddClosureNode : public ShaderNode {
-public:
- SHADER_NODE_CLASS(AddClosureNode)
- void constant_fold(const ConstantFolder& folder);
+ public:
+ SHADER_NODE_CLASS(AddClosureNode)
+ void constant_fold(const ConstantFolder &folder);
};
class MixClosureNode : public ShaderNode {
-public:
- SHADER_NODE_CLASS(MixClosureNode)
- void constant_fold(const ConstantFolder& folder);
+ public:
+ SHADER_NODE_CLASS(MixClosureNode)
+ void constant_fold(const ConstantFolder &folder);
- float fac;
+ float fac;
};
class MixClosureWeightNode : public ShaderNode {
-public:
- SHADER_NODE_CLASS(MixClosureWeightNode)
+ public:
+ SHADER_NODE_CLASS(MixClosureWeightNode)
- float weight;
- float fac;
+ float weight;
+ float fac;
};
class InvertNode : public ShaderNode {
-public:
- SHADER_NODE_CLASS(InvertNode)
- void constant_fold(const ConstantFolder& folder);
- virtual int get_group() { return NODE_GROUP_LEVEL_3; }
+ public:
+ SHADER_NODE_CLASS(InvertNode)
+ void constant_fold(const ConstantFolder &folder);
+ virtual int get_group()
+ {
+ return NODE_GROUP_LEVEL_3;
+ }
- float fac;
- float3 color;
+ float fac;
+ float3 color;
};
class MixNode : public ShaderNode {
-public:
- SHADER_NODE_CLASS(MixNode)
- void constant_fold(const ConstantFolder& folder);
+ public:
+ SHADER_NODE_CLASS(MixNode)
+ void constant_fold(const ConstantFolder &folder);
- virtual int get_group() { return NODE_GROUP_LEVEL_3; }
+ virtual int get_group()
+ {
+ return NODE_GROUP_LEVEL_3;
+ }
- NodeMix type;
- bool use_clamp;
- float3 color1;
- float3 color2;
- float fac;
+ NodeMix type;
+ bool use_clamp;
+ float3 color1;
+ float3 color2;
+ float fac;
};
class CombineRGBNode : public ShaderNode {
-public:
- SHADER_NODE_CLASS(CombineRGBNode)
- void constant_fold(const ConstantFolder& folder);
- virtual int get_group() { return NODE_GROUP_LEVEL_3; }
+ public:
+ SHADER_NODE_CLASS(CombineRGBNode)
+ void constant_fold(const ConstantFolder &folder);
+ virtual int get_group()
+ {
+ return NODE_GROUP_LEVEL_3;
+ }
- float r, g, b;
+ float r, g, b;
};
class CombineHSVNode : public ShaderNode {
-public:
- SHADER_NODE_CLASS(CombineHSVNode)
- void constant_fold(const ConstantFolder& folder);
- virtual int get_group() { return NODE_GROUP_LEVEL_3; }
+ public:
+ SHADER_NODE_CLASS(CombineHSVNode)
+ void constant_fold(const ConstantFolder &folder);
+ virtual int get_group()
+ {
+ return NODE_GROUP_LEVEL_3;
+ }
- float h, s, v;
+ float h, s, v;
};
class CombineXYZNode : public ShaderNode {
-public:
- SHADER_NODE_CLASS(CombineXYZNode)
- void constant_fold(const ConstantFolder& folder);
- virtual int get_group() { return NODE_GROUP_LEVEL_3; }
+ public:
+ SHADER_NODE_CLASS(CombineXYZNode)
+ void constant_fold(const ConstantFolder &folder);
+ virtual int get_group()
+ {
+ return NODE_GROUP_LEVEL_3;
+ }
- float x, y, z;
+ float x, y, z;
};
class GammaNode : public ShaderNode {
-public:
- SHADER_NODE_CLASS(GammaNode)
- void constant_fold(const ConstantFolder& folder);
- virtual int get_group() { return NODE_GROUP_LEVEL_1; }
+ public:
+ SHADER_NODE_CLASS(GammaNode)
+ void constant_fold(const ConstantFolder &folder);
+ virtual int get_group()
+ {
+ return NODE_GROUP_LEVEL_1;
+ }
- float3 color;
- float gamma;
+ float3 color;
+ float gamma;
};
class BrightContrastNode : public ShaderNode {
-public:
- SHADER_NODE_CLASS(BrightContrastNode)
- void constant_fold(const ConstantFolder& folder);
- virtual int get_group() { return NODE_GROUP_LEVEL_1; }
+ public:
+ SHADER_NODE_CLASS(BrightContrastNode)
+ void constant_fold(const ConstantFolder &folder);
+ virtual int get_group()
+ {
+ return NODE_GROUP_LEVEL_1;
+ }
- float3 color;
- float bright;
- float contrast;
+ float3 color;
+ float bright;
+ float contrast;
};
class SeparateRGBNode : public ShaderNode {
-public:
- SHADER_NODE_CLASS(SeparateRGBNode)
- void constant_fold(const ConstantFolder& folder);
- virtual int get_group() { return NODE_GROUP_LEVEL_3; }
+ public:
+ SHADER_NODE_CLASS(SeparateRGBNode)
+ void constant_fold(const ConstantFolder &folder);
+ virtual int get_group()
+ {
+ return NODE_GROUP_LEVEL_3;
+ }
- float3 color;
+ float3 color;
};
class SeparateHSVNode : public ShaderNode {
-public:
- SHADER_NODE_CLASS(SeparateHSVNode)
- void constant_fold(const ConstantFolder& folder);
- virtual int get_group() { return NODE_GROUP_LEVEL_3; }
+ public:
+ SHADER_NODE_CLASS(SeparateHSVNode)
+ void constant_fold(const ConstantFolder &folder);
+ virtual int get_group()
+ {
+ return NODE_GROUP_LEVEL_3;
+ }
- float3 color;
+ float3 color;
};
class SeparateXYZNode : public ShaderNode {
-public:
- SHADER_NODE_CLASS(SeparateXYZNode)
- void constant_fold(const ConstantFolder& folder);
- virtual int get_group() { return NODE_GROUP_LEVEL_3; }
+ public:
+ SHADER_NODE_CLASS(SeparateXYZNode)
+ void constant_fold(const ConstantFolder &folder);
+ virtual int get_group()
+ {
+ return NODE_GROUP_LEVEL_3;
+ }
- float3 vector;
+ float3 vector;
};
class HSVNode : public ShaderNode {
-public:
- SHADER_NODE_CLASS(HSVNode)
+ public:
+ SHADER_NODE_CLASS(HSVNode)
- float hue;
- float saturation;
- float value;
- float fac;
- float3 color;
+ float hue;
+ float saturation;
+ float value;
+ float fac;
+ float3 color;
};
class AttributeNode : public ShaderNode {
-public:
- SHADER_NODE_CLASS(AttributeNode)
- void attributes(Shader *shader, AttributeRequestSet *attributes);
- bool has_attribute_dependency() { return true; }
- bool has_spatial_varying() { return true; }
+ public:
+ SHADER_NODE_CLASS(AttributeNode)
+ void attributes(Shader *shader, AttributeRequestSet *attributes);
+ bool has_attribute_dependency()
+ {
+ return true;
+ }
+ bool has_spatial_varying()
+ {
+ return true;
+ }
- ustring attribute;
+ ustring attribute;
};
class CameraNode : public ShaderNode {
-public:
- SHADER_NODE_CLASS(CameraNode)
- bool has_spatial_varying() { return true; }
- virtual int get_group() { return NODE_GROUP_LEVEL_2; }
+ public:
+ SHADER_NODE_CLASS(CameraNode)
+ bool has_spatial_varying()
+ {
+ return true;
+ }
+ virtual int get_group()
+ {
+ return NODE_GROUP_LEVEL_2;
+ }
};
class FresnelNode : public ShaderNode {
-public:
- SHADER_NODE_CLASS(FresnelNode)
- bool has_spatial_varying() { return true; }
- virtual int get_group() { return NODE_GROUP_LEVEL_1; }
+ public:
+ SHADER_NODE_CLASS(FresnelNode)
+ bool has_spatial_varying()
+ {
+ return true;
+ }
+ virtual int get_group()
+ {
+ return NODE_GROUP_LEVEL_1;
+ }
- float3 normal;
- float IOR;
+ float3 normal;
+ float IOR;
};
class LayerWeightNode : public ShaderNode {
-public:
- SHADER_NODE_CLASS(LayerWeightNode)
- bool has_spatial_varying() { return true; }
- virtual int get_group() { return NODE_GROUP_LEVEL_1; }
+ public:
+ SHADER_NODE_CLASS(LayerWeightNode)
+ bool has_spatial_varying()
+ {
+ return true;
+ }
+ virtual int get_group()
+ {
+ return NODE_GROUP_LEVEL_1;
+ }
- float3 normal;
- float blend;
+ float3 normal;
+ float blend;
};
class WireframeNode : public ShaderNode {
-public:
- SHADER_NODE_CLASS(WireframeNode)
- bool has_spatial_varying() { return true; }
- virtual int get_group() { return NODE_GROUP_LEVEL_3; }
+ public:
+ SHADER_NODE_CLASS(WireframeNode)
+ bool has_spatial_varying()
+ {
+ return true;
+ }
+ virtual int get_group()
+ {
+ return NODE_GROUP_LEVEL_3;
+ }
- float size;
- bool use_pixel_size;
+ float size;
+ bool use_pixel_size;
};
class WavelengthNode : public ShaderNode {
-public:
- SHADER_NODE_CLASS(WavelengthNode)
- virtual int get_group() { return NODE_GROUP_LEVEL_3; }
+ public:
+ SHADER_NODE_CLASS(WavelengthNode)
+ virtual int get_group()
+ {
+ return NODE_GROUP_LEVEL_3;
+ }
- float wavelength;
+ float wavelength;
};
class BlackbodyNode : public ShaderNode {
-public:
- SHADER_NODE_CLASS(BlackbodyNode)
- void constant_fold(const ConstantFolder& folder);
- virtual int get_group() { return NODE_GROUP_LEVEL_3; }
+ public:
+ SHADER_NODE_CLASS(BlackbodyNode)
+ void constant_fold(const ConstantFolder &folder);
+ virtual int get_group()
+ {
+ return NODE_GROUP_LEVEL_3;
+ }
- float temperature;
+ float temperature;
};
class MathNode : public ShaderNode {
-public:
- SHADER_NODE_CLASS(MathNode)
- virtual int get_group() { return NODE_GROUP_LEVEL_1; }
- void constant_fold(const ConstantFolder& folder);
+ public:
+ SHADER_NODE_CLASS(MathNode)
+ virtual int get_group()
+ {
+ return NODE_GROUP_LEVEL_1;
+ }
+ void constant_fold(const ConstantFolder &folder);
- float value1;
- float value2;
- NodeMath type;
- bool use_clamp;
+ float value1;
+ float value2;
+ NodeMath type;
+ bool use_clamp;
};
class NormalNode : public ShaderNode {
-public:
- SHADER_NODE_CLASS(NormalNode)
- virtual int get_group() { return NODE_GROUP_LEVEL_2; }
+ public:
+ SHADER_NODE_CLASS(NormalNode)
+ virtual int get_group()
+ {
+ return NODE_GROUP_LEVEL_2;
+ }
- float3 direction;
- float3 normal;
+ float3 direction;
+ float3 normal;
};
class VectorMathNode : public ShaderNode {
-public:
- SHADER_NODE_CLASS(VectorMathNode)
- virtual int get_group() { return NODE_GROUP_LEVEL_1; }
- void constant_fold(const ConstantFolder& folder);
+ public:
+ SHADER_NODE_CLASS(VectorMathNode)
+ virtual int get_group()
+ {
+ return NODE_GROUP_LEVEL_1;
+ }
+ void constant_fold(const ConstantFolder &folder);
- float3 vector1;
- float3 vector2;
- NodeVectorMath type;
+ float3 vector1;
+ float3 vector2;
+ NodeVectorMath type;
};
class VectorTransformNode : public ShaderNode {
-public:
- SHADER_NODE_CLASS(VectorTransformNode)
+ public:
+ SHADER_NODE_CLASS(VectorTransformNode)
- virtual int get_group() { return NODE_GROUP_LEVEL_3; }
+ virtual int get_group()
+ {
+ return NODE_GROUP_LEVEL_3;
+ }
- NodeVectorTransformType type;
- NodeVectorTransformConvertSpace convert_from;
- NodeVectorTransformConvertSpace convert_to;
- float3 vector;
+ NodeVectorTransformType type;
+ NodeVectorTransformConvertSpace convert_from;
+ NodeVectorTransformConvertSpace convert_to;
+ float3 vector;
};
class BumpNode : public ShaderNode {
-public:
- SHADER_NODE_CLASS(BumpNode)
- void constant_fold(const ConstantFolder& folder);
- bool has_spatial_varying() { return true; }
- virtual int get_feature() {
- return NODE_FEATURE_BUMP;
- }
-
- bool invert;
- bool use_object_space;
- float height;
- float sample_center;
- float sample_x;
- float sample_y;
- float3 normal;
- float strength;
- float distance;
+ public:
+ SHADER_NODE_CLASS(BumpNode)
+ void constant_fold(const ConstantFolder &folder);
+ bool has_spatial_varying()
+ {
+ return true;
+ }
+ virtual int get_feature()
+ {
+ return NODE_FEATURE_BUMP;
+ }
+
+ bool invert;
+ bool use_object_space;
+ float height;
+ float sample_center;
+ float sample_x;
+ float sample_y;
+ float3 normal;
+ float strength;
+ float distance;
};
class CurvesNode : public ShaderNode {
-public:
- explicit CurvesNode(const NodeType *node_type);
- SHADER_NODE_BASE_CLASS(CurvesNode)
+ public:
+ explicit CurvesNode(const NodeType *node_type);
+ SHADER_NODE_BASE_CLASS(CurvesNode)
- virtual int get_group() { return NODE_GROUP_LEVEL_3; }
+ virtual int get_group()
+ {
+ return NODE_GROUP_LEVEL_3;
+ }
- array<float3> curves;
- float min_x, max_x, fac;
- float3 value;
+ array<float3> curves;
+ float min_x, max_x, fac;
+ float3 value;
-protected:
- using ShaderNode::constant_fold;
- void constant_fold(const ConstantFolder& folder, ShaderInput *value_in);
- void compile(SVMCompiler& compiler, int type, ShaderInput *value_in, ShaderOutput *value_out);
- void compile(OSLCompiler& compiler, const char *name);
+ protected:
+ using ShaderNode::constant_fold;
+ void constant_fold(const ConstantFolder &folder, ShaderInput *value_in);
+ void compile(SVMCompiler &compiler, int type, ShaderInput *value_in, ShaderOutput *value_out);
+ void compile(OSLCompiler &compiler, const char *name);
};
class RGBCurvesNode : public CurvesNode {
-public:
- SHADER_NODE_CLASS(RGBCurvesNode)
- void constant_fold(const ConstantFolder& folder);
+ public:
+ SHADER_NODE_CLASS(RGBCurvesNode)
+ void constant_fold(const ConstantFolder &folder);
};
class VectorCurvesNode : public CurvesNode {
-public:
- SHADER_NODE_CLASS(VectorCurvesNode)
- void constant_fold(const ConstantFolder& folder);
+ public:
+ SHADER_NODE_CLASS(VectorCurvesNode)
+ void constant_fold(const ConstantFolder &folder);
};
class RGBRampNode : public ShaderNode {
-public:
- SHADER_NODE_CLASS(RGBRampNode)
- void constant_fold(const ConstantFolder& folder);
- virtual int get_group() { return NODE_GROUP_LEVEL_1; }
+ public:
+ SHADER_NODE_CLASS(RGBRampNode)
+ void constant_fold(const ConstantFolder &folder);
+ virtual int get_group()
+ {
+ return NODE_GROUP_LEVEL_1;
+ }
- array<float3> ramp;
- array<float> ramp_alpha;
- float fac;
- bool interpolate;
+ array<float3> ramp;
+ array<float> ramp_alpha;
+ float fac;
+ bool interpolate;
};
class SetNormalNode : public ShaderNode {
-public:
- SHADER_NODE_CLASS(SetNormalNode)
- float3 direction;
+ public:
+ SHADER_NODE_CLASS(SetNormalNode)
+ float3 direction;
};
class OSLNode : public ShaderNode {
-public:
- static OSLNode *create(size_t num_inputs, const OSLNode *from = NULL);
- ~OSLNode();
+ public:
+ static OSLNode *create(size_t num_inputs, const OSLNode *from = NULL);
+ ~OSLNode();
- ShaderNode *clone() const;
+ ShaderNode *clone() const;
- char* input_default_value();
- void add_input(ustring name, SocketType::Type type);
- void add_output(ustring name, SocketType::Type type);
+ char *input_default_value();
+ void add_input(ustring name, SocketType::Type type);
+ void add_output(ustring name, SocketType::Type type);
- SHADER_NODE_NO_CLONE_CLASS(OSLNode)
+ SHADER_NODE_NO_CLONE_CLASS(OSLNode)
- /* ideally we could beter detect this, but we can't query this now */
- bool has_spatial_varying() { return true; }
- bool has_volume_support() { return true; }
+ /* ideally we could beter detect this, but we can't query this now */
+ bool has_spatial_varying()
+ {
+ return true;
+ }
+ bool has_volume_support()
+ {
+ return true;
+ }
- virtual bool equals(const ShaderNode& /*other*/) { return false; }
+ virtual bool equals(const ShaderNode & /*other*/)
+ {
+ return false;
+ }
- string filepath;
- string bytecode_hash;
+ string filepath;
+ string bytecode_hash;
};
class NormalMapNode : public ShaderNode {
-public:
- SHADER_NODE_CLASS(NormalMapNode)
- void attributes(Shader *shader, AttributeRequestSet *attributes);
- bool has_attribute_dependency() { return true; }
- bool has_spatial_varying() { return true; }
- virtual int get_group() { return NODE_GROUP_LEVEL_3; }
-
- NodeNormalMapSpace space;
- ustring attribute;
- float strength;
- float3 color;
- float3 normal_osl;
+ public:
+ SHADER_NODE_CLASS(NormalMapNode)
+ void attributes(Shader *shader, AttributeRequestSet *attributes);
+ bool has_attribute_dependency()
+ {
+ return true;
+ }
+ bool has_spatial_varying()
+ {
+ return true;
+ }
+ virtual int get_group()
+ {
+ return NODE_GROUP_LEVEL_3;
+ }
+
+ NodeNormalMapSpace space;
+ ustring attribute;
+ float strength;
+ float3 color;
+ float3 normal_osl;
};
class TangentNode : public ShaderNode {
-public:
- SHADER_NODE_CLASS(TangentNode)
- void attributes(Shader *shader, AttributeRequestSet *attributes);
- bool has_attribute_dependency() { return true; }
- bool has_spatial_varying() { return true; }
- virtual int get_group() { return NODE_GROUP_LEVEL_3; }
-
- NodeTangentDirectionType direction_type;
- NodeTangentAxis axis;
- ustring attribute;
- float3 normal_osl;
+ public:
+ SHADER_NODE_CLASS(TangentNode)
+ void attributes(Shader *shader, AttributeRequestSet *attributes);
+ bool has_attribute_dependency()
+ {
+ return true;
+ }
+ bool has_spatial_varying()
+ {
+ return true;
+ }
+ virtual int get_group()
+ {
+ return NODE_GROUP_LEVEL_3;
+ }
+
+ NodeTangentDirectionType direction_type;
+ NodeTangentAxis axis;
+ ustring attribute;
+ float3 normal_osl;
};
class BevelNode : public ShaderNode {
-public:
- SHADER_NODE_CLASS(BevelNode)
- bool has_spatial_varying() { return true; }
- virtual int get_group() { return NODE_GROUP_LEVEL_3; }
- virtual bool has_raytrace() { return true; }
-
- float radius;
- float3 normal;
- int samples;
+ public:
+ SHADER_NODE_CLASS(BevelNode)
+ bool has_spatial_varying()
+ {
+ return true;
+ }
+ virtual int get_group()
+ {
+ return NODE_GROUP_LEVEL_3;
+ }
+ virtual bool has_raytrace()
+ {
+ return true;
+ }
+
+ float radius;
+ float3 normal;
+ int samples;
};
class DisplacementNode : public ShaderNode {
-public:
- SHADER_NODE_CLASS(DisplacementNode)
- void constant_fold(const ConstantFolder& folder);
- virtual int get_feature() {
- return NODE_FEATURE_BUMP;
- }
+ public:
+ SHADER_NODE_CLASS(DisplacementNode)
+ void constant_fold(const ConstantFolder &folder);
+ virtual int get_feature()
+ {
+ return NODE_FEATURE_BUMP;
+ }
- NodeNormalMapSpace space;
- float height;
- float midlevel;
- float scale;
- float3 normal;
+ NodeNormalMapSpace space;
+ float height;
+ float midlevel;
+ float scale;
+ float3 normal;
};
class VectorDisplacementNode : public ShaderNode {
-public:
- SHADER_NODE_CLASS(VectorDisplacementNode)
- void attributes(Shader *shader, AttributeRequestSet *attributes);
- bool has_attribute_dependency() { return true; }
- void constant_fold(const ConstantFolder& folder);
- virtual int get_feature() {
- return NODE_FEATURE_BUMP;
- }
-
- NodeNormalMapSpace space;
- ustring attribute;
- float3 vector;
- float midlevel;
- float scale;
+ public:
+ SHADER_NODE_CLASS(VectorDisplacementNode)
+ void attributes(Shader *shader, AttributeRequestSet *attributes);
+ bool has_attribute_dependency()
+ {
+ return true;
+ }
+ void constant_fold(const ConstantFolder &folder);
+ virtual int get_feature()
+ {
+ return NODE_FEATURE_BUMP;
+ }
+
+ NodeNormalMapSpace space;
+ ustring attribute;
+ float3 vector;
+ float midlevel;
+ float scale;
};
CCL_NAMESPACE_END
-#endif /* __NODES_H__ */
+#endif /* __NODES_H__ */
diff --git a/intern/cycles/render/object.cpp b/intern/cycles/render/object.cpp
index b34d16c438b..6c6f8810412 100644
--- a/intern/cycles/render/object.cpp
+++ b/intern/cycles/render/object.cpp
@@ -38,77 +38,76 @@ CCL_NAMESPACE_BEGIN
/* Global state of object transform update. */
struct UpdateObjectTransformState {
- /* Global state used by device_update_object_transform().
- * Common for both threaded and non-threaded update.
- */
+ /* Global state used by device_update_object_transform().
+ * Common for both threaded and non-threaded update.
+ */
- /* Type of the motion required by the scene settings. */
- Scene::MotionType need_motion;
+ /* Type of the motion required by the scene settings. */
+ Scene::MotionType need_motion;
- /* Mapping from particle system to a index in packed particle array.
- * Only used for read.
- */
- map<ParticleSystem*, int> particle_offset;
+ /* Mapping from particle system to a index in packed particle array.
+ * Only used for read.
+ */
+ map<ParticleSystem *, int> particle_offset;
- /* Mesh area.
- * Used to avoid calculation of mesh area multiple times. Used for both
- * read and write. Acquire surface_area_lock to keep it all thread safe.
- */
- map<Mesh*, float> surface_area_map;
+ /* Mesh area.
+ * Used to avoid calculation of mesh area multiple times. Used for both
+ * read and write. Acquire surface_area_lock to keep it all thread safe.
+ */
+ map<Mesh *, float> surface_area_map;
- /* Motion offsets for each object. */
- array<uint> motion_offset;
+ /* Motion offsets for each object. */
+ array<uint> motion_offset;
- /* Packed object arrays. Those will be filled in. */
- uint *object_flag;
- KernelObject *objects;
- Transform *object_motion_pass;
- DecomposedTransform *object_motion;
+ /* Packed object arrays. Those will be filled in. */
+ uint *object_flag;
+ KernelObject *objects;
+ Transform *object_motion_pass;
+ DecomposedTransform *object_motion;
- /* Flags which will be synchronized to Integrator. */
- bool have_motion;
- bool have_curves;
+ /* Flags which will be synchronized to Integrator. */
+ bool have_motion;
+ bool have_curves;
- /* ** Scheduling queue. ** */
+ /* ** Scheduling queue. ** */
- Scene *scene;
+ Scene *scene;
- /* Some locks to keep everything thread-safe. */
- thread_spin_lock queue_lock;
- thread_spin_lock surface_area_lock;
+ /* Some locks to keep everything thread-safe. */
+ thread_spin_lock queue_lock;
+ thread_spin_lock surface_area_lock;
- /* First unused object index in the queue. */
- int queue_start_object;
+ /* First unused object index in the queue. */
+ int queue_start_object;
};
/* Object */
NODE_DEFINE(Object)
{
- NodeType* type = NodeType::add("object", create);
-
- SOCKET_NODE(mesh, "Mesh", &Mesh::node_type);
- SOCKET_TRANSFORM(tfm, "Transform", transform_identity());
- SOCKET_UINT(visibility, "Visibility", ~0);
- SOCKET_UINT(random_id, "Random ID", 0);
- SOCKET_INT(pass_id, "Pass ID", 0);
- SOCKET_BOOLEAN(use_holdout, "Use Holdout", false);
- SOCKET_BOOLEAN(hide_on_missing_motion, "Hide on Missing Motion", false);
- SOCKET_POINT(dupli_generated, "Dupli Generated", make_float3(0.0f, 0.0f, 0.0f));
- SOCKET_POINT2(dupli_uv, "Dupli UV", make_float2(0.0f, 0.0f));
- SOCKET_TRANSFORM_ARRAY(motion, "Motion", array<Transform>());
-
- SOCKET_BOOLEAN(is_shadow_catcher, "Shadow Catcher", false);
-
- return type;
+ NodeType *type = NodeType::add("object", create);
+
+ SOCKET_NODE(mesh, "Mesh", &Mesh::node_type);
+ SOCKET_TRANSFORM(tfm, "Transform", transform_identity());
+ SOCKET_UINT(visibility, "Visibility", ~0);
+ SOCKET_UINT(random_id, "Random ID", 0);
+ SOCKET_INT(pass_id, "Pass ID", 0);
+ SOCKET_BOOLEAN(use_holdout, "Use Holdout", false);
+ SOCKET_BOOLEAN(hide_on_missing_motion, "Hide on Missing Motion", false);
+ SOCKET_POINT(dupli_generated, "Dupli Generated", make_float3(0.0f, 0.0f, 0.0f));
+ SOCKET_POINT2(dupli_uv, "Dupli UV", make_float2(0.0f, 0.0f));
+ SOCKET_TRANSFORM_ARRAY(motion, "Motion", array<Transform>());
+
+ SOCKET_BOOLEAN(is_shadow_catcher, "Shadow Catcher", false);
+
+ return type;
}
-Object::Object()
-: Node(node_type)
+Object::Object() : Node(node_type)
{
- particle_system = NULL;
- particle_index = 0;
- bounds = BoundBox::empty;
+ particle_system = NULL;
+ particle_index = 0;
+ bounds = BoundBox::empty;
}
Object::~Object()
@@ -117,768 +116,762 @@ Object::~Object()
void Object::update_motion()
{
- if(!use_motion()) {
- return;
- }
-
- bool have_motion = false;
-
- for(size_t i = 0; i < motion.size(); i++) {
- if(motion[i] == transform_empty()) {
- if(hide_on_missing_motion) {
- /* Hide objects that have no valid previous or next
- * transform, for example particle that stop existing. It
- * would be better to handle this in the kernel and make
- * objects invisible outside certain motion steps. */
- tfm = transform_empty();
- motion.clear();
- return;
- }
- else {
- /* Otherwise just copy center motion. */
- motion[i] = tfm;
- }
- }
-
- /* Test if any of the transforms are actually different. */
- have_motion = have_motion || motion[i] != tfm;
- }
-
- /* Clear motion array if there is no actual motion. */
- if(!have_motion) {
- motion.clear();
- }
+ if (!use_motion()) {
+ return;
+ }
+
+ bool have_motion = false;
+
+ for (size_t i = 0; i < motion.size(); i++) {
+ if (motion[i] == transform_empty()) {
+ if (hide_on_missing_motion) {
+ /* Hide objects that have no valid previous or next
+ * transform, for example particle that stop existing. It
+ * would be better to handle this in the kernel and make
+ * objects invisible outside certain motion steps. */
+ tfm = transform_empty();
+ motion.clear();
+ return;
+ }
+ else {
+ /* Otherwise just copy center motion. */
+ motion[i] = tfm;
+ }
+ }
+
+ /* Test if any of the transforms are actually different. */
+ have_motion = have_motion || motion[i] != tfm;
+ }
+
+ /* Clear motion array if there is no actual motion. */
+ if (!have_motion) {
+ motion.clear();
+ }
}
void Object::compute_bounds(bool motion_blur)
{
- BoundBox mbounds = mesh->bounds;
-
- if(motion_blur && use_motion()) {
- array<DecomposedTransform> decomp(motion.size());
- transform_motion_decompose(decomp.data(), motion.data(), motion.size());
-
- bounds = BoundBox::empty;
-
- /* todo: this is really terrible. according to pbrt there is a better
- * way to find this iteratively, but did not find implementation yet
- * or try to implement myself */
- for(float t = 0.0f; t < 1.0f; t += (1.0f/128.0f)) {
- Transform ttfm;
-
- transform_motion_array_interpolate(&ttfm, decomp.data(), motion.size(), t);
- bounds.grow(mbounds.transformed(&ttfm));
- }
- }
- else {
- /* No motion blur case. */
- if(mesh->transform_applied) {
- bounds = mbounds;
- }
- else {
- bounds = mbounds.transformed(&tfm);
- }
- }
+ BoundBox mbounds = mesh->bounds;
+
+ if (motion_blur && use_motion()) {
+ array<DecomposedTransform> decomp(motion.size());
+ transform_motion_decompose(decomp.data(), motion.data(), motion.size());
+
+ bounds = BoundBox::empty;
+
+ /* todo: this is really terrible. according to pbrt there is a better
+ * way to find this iteratively, but did not find implementation yet
+ * or try to implement myself */
+ for (float t = 0.0f; t < 1.0f; t += (1.0f / 128.0f)) {
+ Transform ttfm;
+
+ transform_motion_array_interpolate(&ttfm, decomp.data(), motion.size(), t);
+ bounds.grow(mbounds.transformed(&ttfm));
+ }
+ }
+ else {
+ /* No motion blur case. */
+ if (mesh->transform_applied) {
+ bounds = mbounds;
+ }
+ else {
+ bounds = mbounds.transformed(&tfm);
+ }
+ }
}
void Object::apply_transform(bool apply_to_motion)
{
- if(!mesh || tfm == transform_identity())
- return;
-
- /* triangles */
- if(mesh->verts.size()) {
- /* store matrix to transform later. when accessing these as attributes we
- * do not want the transform to be applied for consistency between static
- * and dynamic BVH, so we do it on packing. */
- mesh->transform_normal = transform_transposed_inverse(tfm);
-
- /* apply to mesh vertices */
- for(size_t i = 0; i < mesh->verts.size(); i++)
- mesh->verts[i] = transform_point(&tfm, mesh->verts[i]);
-
- if(apply_to_motion) {
- Attribute *attr = mesh->attributes.find(ATTR_STD_MOTION_VERTEX_POSITION);
-
- if(attr) {
- size_t steps_size = mesh->verts.size() * (mesh->motion_steps - 1);
- float3 *vert_steps = attr->data_float3();
-
- for(size_t i = 0; i < steps_size; i++)
- vert_steps[i] = transform_point(&tfm, vert_steps[i]);
- }
-
- Attribute *attr_N = mesh->attributes.find(ATTR_STD_MOTION_VERTEX_NORMAL);
-
- if(attr_N) {
- Transform ntfm = mesh->transform_normal;
- size_t steps_size = mesh->verts.size() * (mesh->motion_steps - 1);
- float3 *normal_steps = attr_N->data_float3();
-
- for(size_t i = 0; i < steps_size; i++)
- normal_steps[i] = normalize(transform_direction(&ntfm, normal_steps[i]));
- }
- }
- }
-
- /* curves */
- if(mesh->curve_keys.size()) {
- /* compute uniform scale */
- float3 c0 = transform_get_column(&tfm, 0);
- float3 c1 = transform_get_column(&tfm, 1);
- float3 c2 = transform_get_column(&tfm, 2);
- float scalar = powf(fabsf(dot(cross(c0, c1), c2)), 1.0f/3.0f);
-
- /* apply transform to curve keys */
- for(size_t i = 0; i < mesh->curve_keys.size(); i++) {
- float3 co = transform_point(&tfm, mesh->curve_keys[i]);
- float radius = mesh->curve_radius[i] * scalar;
-
- /* scale for curve radius is only correct for uniform scale */
- mesh->curve_keys[i] = co;
- mesh->curve_radius[i] = radius;
- }
-
- if(apply_to_motion) {
- Attribute *curve_attr = mesh->curve_attributes.find(ATTR_STD_MOTION_VERTEX_POSITION);
-
- if(curve_attr) {
- /* apply transform to motion curve keys */
- size_t steps_size = mesh->curve_keys.size() * (mesh->motion_steps - 1);
- float4 *key_steps = curve_attr->data_float4();
-
- for(size_t i = 0; i < steps_size; i++) {
- float3 co = transform_point(&tfm, float4_to_float3(key_steps[i]));
- float radius = key_steps[i].w * scalar;
-
- /* scale for curve radius is only correct for uniform scale */
- key_steps[i] = float3_to_float4(co);
- key_steps[i].w = radius;
- }
- }
- }
- }
-
- /* we keep normals pointing in same direction on negative scale, notify
- * mesh about this in it (re)calculates normals */
- if(transform_negative_scale(tfm))
- mesh->transform_negative_scaled = true;
-
- if(bounds.valid()) {
- mesh->compute_bounds();
- compute_bounds(false);
- }
-
- /* tfm is not reset to identity, all code that uses it needs to check the
- * transform_applied boolean */
+ if (!mesh || tfm == transform_identity())
+ return;
+
+ /* triangles */
+ if (mesh->verts.size()) {
+ /* store matrix to transform later. when accessing these as attributes we
+ * do not want the transform to be applied for consistency between static
+ * and dynamic BVH, so we do it on packing. */
+ mesh->transform_normal = transform_transposed_inverse(tfm);
+
+ /* apply to mesh vertices */
+ for (size_t i = 0; i < mesh->verts.size(); i++)
+ mesh->verts[i] = transform_point(&tfm, mesh->verts[i]);
+
+ if (apply_to_motion) {
+ Attribute *attr = mesh->attributes.find(ATTR_STD_MOTION_VERTEX_POSITION);
+
+ if (attr) {
+ size_t steps_size = mesh->verts.size() * (mesh->motion_steps - 1);
+ float3 *vert_steps = attr->data_float3();
+
+ for (size_t i = 0; i < steps_size; i++)
+ vert_steps[i] = transform_point(&tfm, vert_steps[i]);
+ }
+
+ Attribute *attr_N = mesh->attributes.find(ATTR_STD_MOTION_VERTEX_NORMAL);
+
+ if (attr_N) {
+ Transform ntfm = mesh->transform_normal;
+ size_t steps_size = mesh->verts.size() * (mesh->motion_steps - 1);
+ float3 *normal_steps = attr_N->data_float3();
+
+ for (size_t i = 0; i < steps_size; i++)
+ normal_steps[i] = normalize(transform_direction(&ntfm, normal_steps[i]));
+ }
+ }
+ }
+
+ /* curves */
+ if (mesh->curve_keys.size()) {
+ /* compute uniform scale */
+ float3 c0 = transform_get_column(&tfm, 0);
+ float3 c1 = transform_get_column(&tfm, 1);
+ float3 c2 = transform_get_column(&tfm, 2);
+ float scalar = powf(fabsf(dot(cross(c0, c1), c2)), 1.0f / 3.0f);
+
+ /* apply transform to curve keys */
+ for (size_t i = 0; i < mesh->curve_keys.size(); i++) {
+ float3 co = transform_point(&tfm, mesh->curve_keys[i]);
+ float radius = mesh->curve_radius[i] * scalar;
+
+ /* scale for curve radius is only correct for uniform scale */
+ mesh->curve_keys[i] = co;
+ mesh->curve_radius[i] = radius;
+ }
+
+ if (apply_to_motion) {
+ Attribute *curve_attr = mesh->curve_attributes.find(ATTR_STD_MOTION_VERTEX_POSITION);
+
+ if (curve_attr) {
+ /* apply transform to motion curve keys */
+ size_t steps_size = mesh->curve_keys.size() * (mesh->motion_steps - 1);
+ float4 *key_steps = curve_attr->data_float4();
+
+ for (size_t i = 0; i < steps_size; i++) {
+ float3 co = transform_point(&tfm, float4_to_float3(key_steps[i]));
+ float radius = key_steps[i].w * scalar;
+
+ /* scale for curve radius is only correct for uniform scale */
+ key_steps[i] = float3_to_float4(co);
+ key_steps[i].w = radius;
+ }
+ }
+ }
+ }
+
+ /* we keep normals pointing in same direction on negative scale, notify
+ * mesh about this in it (re)calculates normals */
+ if (transform_negative_scale(tfm))
+ mesh->transform_negative_scaled = true;
+
+ if (bounds.valid()) {
+ mesh->compute_bounds();
+ compute_bounds(false);
+ }
+
+ /* tfm is not reset to identity, all code that uses it needs to check the
+ * transform_applied boolean */
}
void Object::tag_update(Scene *scene)
{
- if(mesh) {
- if(mesh->transform_applied)
- mesh->need_update = true;
-
- foreach(Shader *shader, mesh->used_shaders) {
- if(shader->use_mis && shader->has_surface_emission)
- scene->light_manager->need_update = true;
- }
- }
-
- scene->camera->need_flags_update = true;
- scene->curve_system_manager->need_update = true;
- scene->mesh_manager->need_update = true;
- scene->object_manager->need_update = true;
+ if (mesh) {
+ if (mesh->transform_applied)
+ mesh->need_update = true;
+
+ foreach (Shader *shader, mesh->used_shaders) {
+ if (shader->use_mis && shader->has_surface_emission)
+ scene->light_manager->need_update = true;
+ }
+ }
+
+ scene->camera->need_flags_update = true;
+ scene->curve_system_manager->need_update = true;
+ scene->mesh_manager->need_update = true;
+ scene->object_manager->need_update = true;
}
bool Object::use_motion() const
{
- return (motion.size() > 1);
+ return (motion.size() > 1);
}
float Object::motion_time(int step) const
{
- return (use_motion()) ? 2.0f * step / (motion.size() - 1) - 1.0f : 0.0f;
+ return (use_motion()) ? 2.0f * step / (motion.size() - 1) - 1.0f : 0.0f;
}
int Object::motion_step(float time) const
{
- if(use_motion()) {
- for(size_t step = 0; step < motion.size(); step++) {
- if(time == motion_time(step)) {
- return step;
- }
- }
- }
-
- return -1;
+ if (use_motion()) {
+ for (size_t step = 0; step < motion.size(); step++) {
+ if (time == motion_time(step)) {
+ return step;
+ }
+ }
+ }
+
+ return -1;
}
bool Object::is_traceable() const
{
- /* Mesh itself can be empty,can skip all such objects. */
- if(!bounds.valid() || bounds.size() == make_float3(0.0f, 0.0f, 0.0f)) {
- return false;
- }
- /* TODO(sergey): Check for mesh vertices/curves. visibility flags. */
- return true;
+ /* Mesh itself can be empty,can skip all such objects. */
+ if (!bounds.valid() || bounds.size() == make_float3(0.0f, 0.0f, 0.0f)) {
+ return false;
+ }
+ /* TODO(sergey): Check for mesh vertices/curves. visibility flags. */
+ return true;
}
-uint Object::visibility_for_tracing() const {
- uint trace_visibility = visibility;
- if(is_shadow_catcher) {
- trace_visibility &= ~PATH_RAY_SHADOW_NON_CATCHER;
- }
- else {
- trace_visibility &= ~PATH_RAY_SHADOW_CATCHER;
- }
- return trace_visibility;
+uint Object::visibility_for_tracing() const
+{
+ uint trace_visibility = visibility;
+ if (is_shadow_catcher) {
+ trace_visibility &= ~PATH_RAY_SHADOW_NON_CATCHER;
+ }
+ else {
+ trace_visibility &= ~PATH_RAY_SHADOW_CATCHER;
+ }
+ return trace_visibility;
}
int Object::get_device_index() const
{
- return index;
+ return index;
}
/* Object Manager */
ObjectManager::ObjectManager()
{
- need_update = true;
- need_flags_update = true;
+ need_update = true;
+ need_flags_update = true;
}
ObjectManager::~ObjectManager()
{
}
-void ObjectManager::device_update_object_transform(UpdateObjectTransformState *state,
- Object *ob)
+void ObjectManager::device_update_object_transform(UpdateObjectTransformState *state, Object *ob)
{
- KernelObject& kobject = state->objects[ob->index];
- Transform *object_motion_pass = state->object_motion_pass;
-
- Mesh *mesh = ob->mesh;
- uint flag = 0;
-
- /* Compute transformations. */
- Transform tfm = ob->tfm;
- Transform itfm = transform_inverse(tfm);
-
- /* Compute surface area. for uniform scale we can do avoid the many
- * transform calls and share computation for instances.
- *
- * TODO(brecht): Correct for displacement, and move to a better place.
- */
- float uniform_scale;
- float surface_area = 0.0f;
- float pass_id = ob->pass_id;
- float random_number = (float)ob->random_id * (1.0f/(float)0xFFFFFFFF);
- int particle_index = (ob->particle_system)
- ? ob->particle_index + state->particle_offset[ob->particle_system]
- : 0;
-
- if(transform_uniform_scale(tfm, uniform_scale)) {
- map<Mesh*, float>::iterator it;
-
- /* NOTE: This isn't fully optimal and could in theory lead to multiple
- * threads calculating area of the same mesh in parallel. However, this
- * also prevents suspending all the threads when some mesh's area is
- * not yet known.
- */
- state->surface_area_lock.lock();
- it = state->surface_area_map.find(mesh);
- state->surface_area_lock.unlock();
-
- if(it == state->surface_area_map.end()) {
- size_t num_triangles = mesh->num_triangles();
- for(size_t j = 0; j < num_triangles; j++) {
- Mesh::Triangle t = mesh->get_triangle(j);
- float3 p1 = mesh->verts[t.v[0]];
- float3 p2 = mesh->verts[t.v[1]];
- float3 p3 = mesh->verts[t.v[2]];
-
- surface_area += triangle_area(p1, p2, p3);
- }
-
- state->surface_area_lock.lock();
- state->surface_area_map[mesh] = surface_area;
- state->surface_area_lock.unlock();
- }
- else {
- surface_area = it->second;
- }
-
- surface_area *= uniform_scale;
- }
- else {
- size_t num_triangles = mesh->num_triangles();
- for(size_t j = 0; j < num_triangles; j++) {
- Mesh::Triangle t = mesh->get_triangle(j);
- float3 p1 = transform_point(&tfm, mesh->verts[t.v[0]]);
- float3 p2 = transform_point(&tfm, mesh->verts[t.v[1]]);
- float3 p3 = transform_point(&tfm, mesh->verts[t.v[2]]);
-
- surface_area += triangle_area(p1, p2, p3);
- }
- }
-
- kobject.tfm = tfm;
- kobject.itfm = itfm;
- kobject.surface_area = surface_area;
- kobject.pass_id = pass_id;
- kobject.random_number = random_number;
- kobject.particle_index = particle_index;
- kobject.motion_offset = 0;
-
- if(mesh->use_motion_blur) {
- state->have_motion = true;
- }
- if(mesh->attributes.find(ATTR_STD_MOTION_VERTEX_POSITION)) {
- flag |= SD_OBJECT_HAS_VERTEX_MOTION;
- }
-
- if(state->need_motion == Scene::MOTION_PASS) {
- /* Clear motion array if there is no actual motion. */
- ob->update_motion();
-
- /* Compute motion transforms. */
- Transform tfm_pre, tfm_post;
- if(ob->use_motion()) {
- tfm_pre = ob->motion[0];
- tfm_post = ob->motion[ob->motion.size() - 1];
- }
- else {
- tfm_pre = tfm;
- tfm_post = tfm;
- }
-
- /* Motion transformations, is world/object space depending if mesh
- * comes with deformed position in object space, or if we transform
- * the shading point in world space. */
- if(!mesh->attributes.find(ATTR_STD_MOTION_VERTEX_POSITION)) {
- tfm_pre = tfm_pre * itfm;
- tfm_post = tfm_post * itfm;
- }
-
- int motion_pass_offset = ob->index*OBJECT_MOTION_PASS_SIZE;
- object_motion_pass[motion_pass_offset + 0] = tfm_pre;
- object_motion_pass[motion_pass_offset + 1] = tfm_post;
- }
- else if(state->need_motion == Scene::MOTION_BLUR) {
- if(ob->use_motion()) {
- kobject.motion_offset = state->motion_offset[ob->index];
-
- /* Decompose transforms for interpolation. */
- DecomposedTransform *decomp = state->object_motion + kobject.motion_offset;
- transform_motion_decompose(decomp, ob->motion.data(), ob->motion.size());
- flag |= SD_OBJECT_MOTION;
- state->have_motion = true;
- }
- }
-
- /* Dupli object coords and motion info. */
- kobject.dupli_generated[0] = ob->dupli_generated[0];
- kobject.dupli_generated[1] = ob->dupli_generated[1];
- kobject.dupli_generated[2] = ob->dupli_generated[2];
- kobject.numkeys = mesh->curve_keys.size();
- kobject.dupli_uv[0] = ob->dupli_uv[0];
- kobject.dupli_uv[1] = ob->dupli_uv[1];
- int totalsteps = mesh->motion_steps;
- kobject.numsteps = (totalsteps - 1)/2;
- kobject.numverts = mesh->verts.size();
- kobject.patch_map_offset = 0;
- kobject.attribute_map_offset = 0;
- uint32_t hash_name = util_murmur_hash3(ob->name.c_str(), ob->name.length(), 0);
- uint32_t hash_asset = util_murmur_hash3(ob->asset_name.c_str(), ob->asset_name.length(), 0);
- kobject.cryptomatte_object = util_hash_to_float(hash_name);
- kobject.cryptomatte_asset = util_hash_to_float(hash_asset);
-
- /* Object flag. */
- if(ob->use_holdout) {
- flag |= SD_OBJECT_HOLDOUT_MASK;
- }
- state->object_flag[ob->index] = flag;
-
- /* Have curves. */
- if(mesh->num_curves()) {
- state->have_curves = true;
- }
+ KernelObject &kobject = state->objects[ob->index];
+ Transform *object_motion_pass = state->object_motion_pass;
+
+ Mesh *mesh = ob->mesh;
+ uint flag = 0;
+
+ /* Compute transformations. */
+ Transform tfm = ob->tfm;
+ Transform itfm = transform_inverse(tfm);
+
+ /* Compute surface area. for uniform scale we can do avoid the many
+ * transform calls and share computation for instances.
+ *
+ * TODO(brecht): Correct for displacement, and move to a better place.
+ */
+ float uniform_scale;
+ float surface_area = 0.0f;
+ float pass_id = ob->pass_id;
+ float random_number = (float)ob->random_id * (1.0f / (float)0xFFFFFFFF);
+ int particle_index = (ob->particle_system) ?
+ ob->particle_index + state->particle_offset[ob->particle_system] :
+ 0;
+
+ if (transform_uniform_scale(tfm, uniform_scale)) {
+ map<Mesh *, float>::iterator it;
+
+ /* NOTE: This isn't fully optimal and could in theory lead to multiple
+ * threads calculating area of the same mesh in parallel. However, this
+ * also prevents suspending all the threads when some mesh's area is
+ * not yet known.
+ */
+ state->surface_area_lock.lock();
+ it = state->surface_area_map.find(mesh);
+ state->surface_area_lock.unlock();
+
+ if (it == state->surface_area_map.end()) {
+ size_t num_triangles = mesh->num_triangles();
+ for (size_t j = 0; j < num_triangles; j++) {
+ Mesh::Triangle t = mesh->get_triangle(j);
+ float3 p1 = mesh->verts[t.v[0]];
+ float3 p2 = mesh->verts[t.v[1]];
+ float3 p3 = mesh->verts[t.v[2]];
+
+ surface_area += triangle_area(p1, p2, p3);
+ }
+
+ state->surface_area_lock.lock();
+ state->surface_area_map[mesh] = surface_area;
+ state->surface_area_lock.unlock();
+ }
+ else {
+ surface_area = it->second;
+ }
+
+ surface_area *= uniform_scale;
+ }
+ else {
+ size_t num_triangles = mesh->num_triangles();
+ for (size_t j = 0; j < num_triangles; j++) {
+ Mesh::Triangle t = mesh->get_triangle(j);
+ float3 p1 = transform_point(&tfm, mesh->verts[t.v[0]]);
+ float3 p2 = transform_point(&tfm, mesh->verts[t.v[1]]);
+ float3 p3 = transform_point(&tfm, mesh->verts[t.v[2]]);
+
+ surface_area += triangle_area(p1, p2, p3);
+ }
+ }
+
+ kobject.tfm = tfm;
+ kobject.itfm = itfm;
+ kobject.surface_area = surface_area;
+ kobject.pass_id = pass_id;
+ kobject.random_number = random_number;
+ kobject.particle_index = particle_index;
+ kobject.motion_offset = 0;
+
+ if (mesh->use_motion_blur) {
+ state->have_motion = true;
+ }
+ if (mesh->attributes.find(ATTR_STD_MOTION_VERTEX_POSITION)) {
+ flag |= SD_OBJECT_HAS_VERTEX_MOTION;
+ }
+
+ if (state->need_motion == Scene::MOTION_PASS) {
+ /* Clear motion array if there is no actual motion. */
+ ob->update_motion();
+
+ /* Compute motion transforms. */
+ Transform tfm_pre, tfm_post;
+ if (ob->use_motion()) {
+ tfm_pre = ob->motion[0];
+ tfm_post = ob->motion[ob->motion.size() - 1];
+ }
+ else {
+ tfm_pre = tfm;
+ tfm_post = tfm;
+ }
+
+ /* Motion transformations, is world/object space depending if mesh
+ * comes with deformed position in object space, or if we transform
+ * the shading point in world space. */
+ if (!mesh->attributes.find(ATTR_STD_MOTION_VERTEX_POSITION)) {
+ tfm_pre = tfm_pre * itfm;
+ tfm_post = tfm_post * itfm;
+ }
+
+ int motion_pass_offset = ob->index * OBJECT_MOTION_PASS_SIZE;
+ object_motion_pass[motion_pass_offset + 0] = tfm_pre;
+ object_motion_pass[motion_pass_offset + 1] = tfm_post;
+ }
+ else if (state->need_motion == Scene::MOTION_BLUR) {
+ if (ob->use_motion()) {
+ kobject.motion_offset = state->motion_offset[ob->index];
+
+ /* Decompose transforms for interpolation. */
+ DecomposedTransform *decomp = state->object_motion + kobject.motion_offset;
+ transform_motion_decompose(decomp, ob->motion.data(), ob->motion.size());
+ flag |= SD_OBJECT_MOTION;
+ state->have_motion = true;
+ }
+ }
+
+ /* Dupli object coords and motion info. */
+ kobject.dupli_generated[0] = ob->dupli_generated[0];
+ kobject.dupli_generated[1] = ob->dupli_generated[1];
+ kobject.dupli_generated[2] = ob->dupli_generated[2];
+ kobject.numkeys = mesh->curve_keys.size();
+ kobject.dupli_uv[0] = ob->dupli_uv[0];
+ kobject.dupli_uv[1] = ob->dupli_uv[1];
+ int totalsteps = mesh->motion_steps;
+ kobject.numsteps = (totalsteps - 1) / 2;
+ kobject.numverts = mesh->verts.size();
+ kobject.patch_map_offset = 0;
+ kobject.attribute_map_offset = 0;
+ uint32_t hash_name = util_murmur_hash3(ob->name.c_str(), ob->name.length(), 0);
+ uint32_t hash_asset = util_murmur_hash3(ob->asset_name.c_str(), ob->asset_name.length(), 0);
+ kobject.cryptomatte_object = util_hash_to_float(hash_name);
+ kobject.cryptomatte_asset = util_hash_to_float(hash_asset);
+
+ /* Object flag. */
+ if (ob->use_holdout) {
+ flag |= SD_OBJECT_HOLDOUT_MASK;
+ }
+ state->object_flag[ob->index] = flag;
+
+ /* Have curves. */
+ if (mesh->num_curves()) {
+ state->have_curves = true;
+ }
}
-bool ObjectManager::device_update_object_transform_pop_work(
- UpdateObjectTransformState *state,
- int *start_index,
- int *num_objects)
+bool ObjectManager::device_update_object_transform_pop_work(UpdateObjectTransformState *state,
+ int *start_index,
+ int *num_objects)
{
- /* Tweakable parameter, number of objects per chunk.
- * Too small value will cause some extra overhead due to spin lock,
- * too big value might not use all threads nicely.
- */
- static const int OBJECTS_PER_TASK = 32;
- bool have_work = false;
- state->queue_lock.lock();
- int num_scene_objects = state->scene->objects.size();
- if(state->queue_start_object < num_scene_objects) {
- int count = min(OBJECTS_PER_TASK,
- num_scene_objects - state->queue_start_object);
- *start_index = state->queue_start_object;
- *num_objects = count;
- state->queue_start_object += count;
- have_work = true;
- }
- state->queue_lock.unlock();
- return have_work;
+ /* Tweakable parameter, number of objects per chunk.
+ * Too small value will cause some extra overhead due to spin lock,
+ * too big value might not use all threads nicely.
+ */
+ static const int OBJECTS_PER_TASK = 32;
+ bool have_work = false;
+ state->queue_lock.lock();
+ int num_scene_objects = state->scene->objects.size();
+ if (state->queue_start_object < num_scene_objects) {
+ int count = min(OBJECTS_PER_TASK, num_scene_objects - state->queue_start_object);
+ *start_index = state->queue_start_object;
+ *num_objects = count;
+ state->queue_start_object += count;
+ have_work = true;
+ }
+ state->queue_lock.unlock();
+ return have_work;
}
-void ObjectManager::device_update_object_transform_task(
- UpdateObjectTransformState *state)
+void ObjectManager::device_update_object_transform_task(UpdateObjectTransformState *state)
{
- int start_index, num_objects;
- while(device_update_object_transform_pop_work(state,
- &start_index,
- &num_objects))
- {
- for(int i = 0; i < num_objects; ++i) {
- const int object_index = start_index + i;
- Object *ob = state->scene->objects[object_index];
- device_update_object_transform(state, ob);
- }
- }
+ int start_index, num_objects;
+ while (device_update_object_transform_pop_work(state, &start_index, &num_objects)) {
+ for (int i = 0; i < num_objects; ++i) {
+ const int object_index = start_index + i;
+ Object *ob = state->scene->objects[object_index];
+ device_update_object_transform(state, ob);
+ }
+ }
}
-void ObjectManager::device_update_transforms(DeviceScene *dscene,
- Scene *scene,
- Progress& progress)
+void ObjectManager::device_update_transforms(DeviceScene *dscene, Scene *scene, Progress &progress)
{
- UpdateObjectTransformState state;
- state.need_motion = scene->need_motion();
- state.have_motion = false;
- state.have_curves = false;
- state.scene = scene;
- state.queue_start_object = 0;
-
- state.objects = dscene->objects.alloc(scene->objects.size());
- state.object_flag = dscene->object_flag.alloc(scene->objects.size());
- state.object_motion = NULL;
- state.object_motion_pass = NULL;
-
- if(state.need_motion == Scene::MOTION_PASS) {
- state.object_motion_pass = dscene->object_motion_pass.alloc(OBJECT_MOTION_PASS_SIZE*scene->objects.size());
- }
- else if(state.need_motion == Scene::MOTION_BLUR) {
- /* Set object offsets into global object motion array. */
- uint *motion_offsets = state.motion_offset.resize(scene->objects.size());
- uint motion_offset = 0;
-
- foreach(Object *ob, scene->objects) {
- *motion_offsets = motion_offset;
- motion_offsets++;
-
- /* Clear motion array if there is no actual motion. */
- ob->update_motion();
- motion_offset += ob->motion.size();
- }
-
- state.object_motion = dscene->object_motion.alloc(motion_offset);
- }
-
- /* Particle system device offsets
- * 0 is dummy particle, index starts at 1.
- */
- int numparticles = 1;
- foreach(ParticleSystem *psys, scene->particle_systems) {
- state.particle_offset[psys] = numparticles;
- numparticles += psys->particles.size();
- }
-
- /* NOTE: If it's just a handful of objects we deal with them in a single
- * thread to avoid threading overhead. However, this threshold is might
- * need some tweaks to make mid-complex scenes optimal.
- */
- if(scene->objects.size() < 64) {
- foreach(Object *ob, scene->objects) {
- device_update_object_transform(&state, ob);
- if(progress.get_cancel()) {
- return;
- }
- }
- }
- else {
- const int num_threads = TaskScheduler::num_threads();
- TaskPool pool;
- for(int i = 0; i < num_threads; ++i) {
- pool.push(function_bind(
- &ObjectManager::device_update_object_transform_task,
- this,
- &state));
- }
- pool.wait_work();
- if(progress.get_cancel()) {
- return;
- }
- }
-
- dscene->objects.copy_to_device();
- if(state.need_motion == Scene::MOTION_PASS) {
- dscene->object_motion_pass.copy_to_device();
- }
- else if(state.need_motion == Scene::MOTION_BLUR) {
- dscene->object_motion.copy_to_device();
- }
-
- dscene->data.bvh.have_motion = state.have_motion;
- dscene->data.bvh.have_curves = state.have_curves;
- dscene->data.bvh.have_instancing = true;
+ UpdateObjectTransformState state;
+ state.need_motion = scene->need_motion();
+ state.have_motion = false;
+ state.have_curves = false;
+ state.scene = scene;
+ state.queue_start_object = 0;
+
+ state.objects = dscene->objects.alloc(scene->objects.size());
+ state.object_flag = dscene->object_flag.alloc(scene->objects.size());
+ state.object_motion = NULL;
+ state.object_motion_pass = NULL;
+
+ if (state.need_motion == Scene::MOTION_PASS) {
+ state.object_motion_pass = dscene->object_motion_pass.alloc(OBJECT_MOTION_PASS_SIZE *
+ scene->objects.size());
+ }
+ else if (state.need_motion == Scene::MOTION_BLUR) {
+ /* Set object offsets into global object motion array. */
+ uint *motion_offsets = state.motion_offset.resize(scene->objects.size());
+ uint motion_offset = 0;
+
+ foreach (Object *ob, scene->objects) {
+ *motion_offsets = motion_offset;
+ motion_offsets++;
+
+ /* Clear motion array if there is no actual motion. */
+ ob->update_motion();
+ motion_offset += ob->motion.size();
+ }
+
+ state.object_motion = dscene->object_motion.alloc(motion_offset);
+ }
+
+ /* Particle system device offsets
+ * 0 is dummy particle, index starts at 1.
+ */
+ int numparticles = 1;
+ foreach (ParticleSystem *psys, scene->particle_systems) {
+ state.particle_offset[psys] = numparticles;
+ numparticles += psys->particles.size();
+ }
+
+ /* NOTE: If it's just a handful of objects we deal with them in a single
+ * thread to avoid threading overhead. However, this threshold is might
+ * need some tweaks to make mid-complex scenes optimal.
+ */
+ if (scene->objects.size() < 64) {
+ foreach (Object *ob, scene->objects) {
+ device_update_object_transform(&state, ob);
+ if (progress.get_cancel()) {
+ return;
+ }
+ }
+ }
+ else {
+ const int num_threads = TaskScheduler::num_threads();
+ TaskPool pool;
+ for (int i = 0; i < num_threads; ++i) {
+ pool.push(function_bind(&ObjectManager::device_update_object_transform_task, this, &state));
+ }
+ pool.wait_work();
+ if (progress.get_cancel()) {
+ return;
+ }
+ }
+
+ dscene->objects.copy_to_device();
+ if (state.need_motion == Scene::MOTION_PASS) {
+ dscene->object_motion_pass.copy_to_device();
+ }
+ else if (state.need_motion == Scene::MOTION_BLUR) {
+ dscene->object_motion.copy_to_device();
+ }
+
+ dscene->data.bvh.have_motion = state.have_motion;
+ dscene->data.bvh.have_curves = state.have_curves;
+ dscene->data.bvh.have_instancing = true;
}
-void ObjectManager::device_update(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress)
+void ObjectManager::device_update(Device *device,
+ DeviceScene *dscene,
+ Scene *scene,
+ Progress &progress)
{
- if(!need_update)
- return;
+ if (!need_update)
+ return;
- VLOG(1) << "Total " << scene->objects.size() << " objects.";
+ VLOG(1) << "Total " << scene->objects.size() << " objects.";
- device_free(device, dscene);
+ device_free(device, dscene);
- if(scene->objects.size() == 0)
- return;
+ if (scene->objects.size() == 0)
+ return;
- /* Assign object IDs. */
- int index = 0;
- foreach(Object *object, scene->objects) {
- object->index = index++;
- }
+ /* Assign object IDs. */
+ int index = 0;
+ foreach (Object *object, scene->objects) {
+ object->index = index++;
+ }
- /* set object transform matrices, before applying static transforms */
- progress.set_status("Updating Objects", "Copying Transformations to device");
- device_update_transforms(dscene, scene, progress);
+ /* set object transform matrices, before applying static transforms */
+ progress.set_status("Updating Objects", "Copying Transformations to device");
+ device_update_transforms(dscene, scene, progress);
- if(progress.get_cancel()) return;
+ if (progress.get_cancel())
+ return;
- /* prepare for static BVH building */
- /* todo: do before to support getting object level coords? */
- if(scene->params.bvh_type == SceneParams::BVH_STATIC) {
- progress.set_status("Updating Objects", "Applying Static Transformations");
- apply_static_transforms(dscene, scene, progress);
- }
+ /* prepare for static BVH building */
+ /* todo: do before to support getting object level coords? */
+ if (scene->params.bvh_type == SceneParams::BVH_STATIC) {
+ progress.set_status("Updating Objects", "Applying Static Transformations");
+ apply_static_transforms(dscene, scene, progress);
+ }
}
-void ObjectManager::device_update_flags(Device *,
- DeviceScene *dscene,
- Scene *scene,
- Progress& /*progress*/,
- bool bounds_valid)
+void ObjectManager::device_update_flags(
+ Device *, DeviceScene *dscene, Scene *scene, Progress & /*progress*/, bool bounds_valid)
{
- if(!need_update && !need_flags_update)
- return;
-
- need_update = false;
- need_flags_update = false;
-
- if(scene->objects.size() == 0)
- return;
-
- /* Object info flag. */
- uint *object_flag = dscene->object_flag.data();
-
- /* Object volume intersection. */
- vector<Object *> volume_objects;
- bool has_volume_objects = false;
- foreach(Object *object, scene->objects) {
- if(object->mesh->has_volume) {
- if(bounds_valid) {
- volume_objects.push_back(object);
- }
- has_volume_objects = true;
- }
- }
-
- foreach(Object *object, scene->objects) {
- if(object->mesh->has_volume) {
- object_flag[object->index] |= SD_OBJECT_HAS_VOLUME;
- object_flag[object->index] &= ~SD_OBJECT_HAS_VOLUME_ATTRIBUTES;
-
- foreach(Attribute& attr, object->mesh->attributes.attributes) {
- if(attr.element == ATTR_ELEMENT_VOXEL) {
- object_flag[object->index] |= SD_OBJECT_HAS_VOLUME_ATTRIBUTES;
- }
- }
- }
- else {
- object_flag[object->index] &= ~(SD_OBJECT_HAS_VOLUME|SD_OBJECT_HAS_VOLUME_ATTRIBUTES);
- }
- if(object->is_shadow_catcher) {
- object_flag[object->index] |= SD_OBJECT_SHADOW_CATCHER;
- }
- else {
- object_flag[object->index] &= ~SD_OBJECT_SHADOW_CATCHER;
- }
-
- if(bounds_valid) {
- foreach(Object *volume_object, volume_objects) {
- if(object == volume_object) {
- continue;
- }
- if(object->bounds.intersects(volume_object->bounds)) {
- object_flag[object->index] |= SD_OBJECT_INTERSECTS_VOLUME;
- break;
- }
- }
- }
- else if(has_volume_objects) {
- /* Not really valid, but can't make more reliable in the case
- * of bounds not being up to date.
- */
- object_flag[object->index] |= SD_OBJECT_INTERSECTS_VOLUME;
- }
- }
-
- /* Copy object flag. */
- dscene->object_flag.copy_to_device();
+ if (!need_update && !need_flags_update)
+ return;
+
+ need_update = false;
+ need_flags_update = false;
+
+ if (scene->objects.size() == 0)
+ return;
+
+ /* Object info flag. */
+ uint *object_flag = dscene->object_flag.data();
+
+ /* Object volume intersection. */
+ vector<Object *> volume_objects;
+ bool has_volume_objects = false;
+ foreach (Object *object, scene->objects) {
+ if (object->mesh->has_volume) {
+ if (bounds_valid) {
+ volume_objects.push_back(object);
+ }
+ has_volume_objects = true;
+ }
+ }
+
+ foreach (Object *object, scene->objects) {
+ if (object->mesh->has_volume) {
+ object_flag[object->index] |= SD_OBJECT_HAS_VOLUME;
+ object_flag[object->index] &= ~SD_OBJECT_HAS_VOLUME_ATTRIBUTES;
+
+ foreach (Attribute &attr, object->mesh->attributes.attributes) {
+ if (attr.element == ATTR_ELEMENT_VOXEL) {
+ object_flag[object->index] |= SD_OBJECT_HAS_VOLUME_ATTRIBUTES;
+ }
+ }
+ }
+ else {
+ object_flag[object->index] &= ~(SD_OBJECT_HAS_VOLUME | SD_OBJECT_HAS_VOLUME_ATTRIBUTES);
+ }
+ if (object->is_shadow_catcher) {
+ object_flag[object->index] |= SD_OBJECT_SHADOW_CATCHER;
+ }
+ else {
+ object_flag[object->index] &= ~SD_OBJECT_SHADOW_CATCHER;
+ }
+
+ if (bounds_valid) {
+ foreach (Object *volume_object, volume_objects) {
+ if (object == volume_object) {
+ continue;
+ }
+ if (object->bounds.intersects(volume_object->bounds)) {
+ object_flag[object->index] |= SD_OBJECT_INTERSECTS_VOLUME;
+ break;
+ }
+ }
+ }
+ else if (has_volume_objects) {
+ /* Not really valid, but can't make more reliable in the case
+ * of bounds not being up to date.
+ */
+ object_flag[object->index] |= SD_OBJECT_INTERSECTS_VOLUME;
+ }
+ }
+
+ /* Copy object flag. */
+ dscene->object_flag.copy_to_device();
}
void ObjectManager::device_update_mesh_offsets(Device *, DeviceScene *dscene, Scene *scene)
{
- if(dscene->objects.size() == 0) {
- return;
- }
+ if (dscene->objects.size() == 0) {
+ return;
+ }
- KernelObject *kobjects = dscene->objects.data();
+ KernelObject *kobjects = dscene->objects.data();
- bool update = false;
+ bool update = false;
- foreach(Object *object, scene->objects) {
- Mesh* mesh = object->mesh;
+ foreach (Object *object, scene->objects) {
+ Mesh *mesh = object->mesh;
- if(mesh->patch_table) {
- uint patch_map_offset = 2*(mesh->patch_table_offset + mesh->patch_table->total_size() -
- mesh->patch_table->num_nodes * PATCH_NODE_SIZE) - mesh->patch_offset;
+ if (mesh->patch_table) {
+ uint patch_map_offset = 2 * (mesh->patch_table_offset + mesh->patch_table->total_size() -
+ mesh->patch_table->num_nodes * PATCH_NODE_SIZE) -
+ mesh->patch_offset;
- if(kobjects[object->index].patch_map_offset != patch_map_offset) {
- kobjects[object->index].patch_map_offset = patch_map_offset;
- update = true;
- }
- }
+ if (kobjects[object->index].patch_map_offset != patch_map_offset) {
+ kobjects[object->index].patch_map_offset = patch_map_offset;
+ update = true;
+ }
+ }
- if(kobjects[object->index].attribute_map_offset != mesh->attr_map_offset) {
- kobjects[object->index].attribute_map_offset = mesh->attr_map_offset;
- update = true;
- }
- }
+ if (kobjects[object->index].attribute_map_offset != mesh->attr_map_offset) {
+ kobjects[object->index].attribute_map_offset = mesh->attr_map_offset;
+ update = true;
+ }
+ }
- if(update) {
- dscene->objects.copy_to_device();
- }
+ if (update) {
+ dscene->objects.copy_to_device();
+ }
}
void ObjectManager::device_free(Device *, DeviceScene *dscene)
{
- dscene->objects.free();
- dscene->object_motion_pass.free();
- dscene->object_motion.free();
- dscene->object_flag.free();
+ dscene->objects.free();
+ dscene->object_motion_pass.free();
+ dscene->object_motion.free();
+ dscene->object_flag.free();
}
-void ObjectManager::apply_static_transforms(DeviceScene *dscene, Scene *scene, Progress& progress)
+void ObjectManager::apply_static_transforms(DeviceScene *dscene, Scene *scene, Progress &progress)
{
- /* todo: normals and displacement should be done before applying transform! */
- /* todo: create objects/meshes in right order! */
-
- /* counter mesh users */
- map<Mesh*, int> mesh_users;
- Scene::MotionType need_motion = scene->need_motion();
- bool motion_blur = need_motion == Scene::MOTION_BLUR;
- bool apply_to_motion = need_motion != Scene::MOTION_PASS;
- int i = 0;
- bool have_instancing = false;
-
- foreach(Object *object, scene->objects) {
- map<Mesh*, int>::iterator it = mesh_users.find(object->mesh);
-
- if(it == mesh_users.end())
- mesh_users[object->mesh] = 1;
- else
- it->second++;
- }
-
- if(progress.get_cancel()) return;
-
- uint *object_flag = dscene->object_flag.data();
-
- /* apply transforms for objects with single user meshes */
- foreach(Object *object, scene->objects) {
- /* Annoying feedback loop here: we can't use is_instanced() because
- * it'll use uninitialized transform_applied flag.
- *
- * Could be solved by moving reference counter to Mesh.
- */
- if((mesh_users[object->mesh] == 1 && !object->mesh->has_surface_bssrdf) &&
- !object->mesh->has_true_displacement() && object->mesh->subdivision_type == Mesh::SUBDIVISION_NONE)
- {
- if(!(motion_blur && object->use_motion())) {
- if(!object->mesh->transform_applied) {
- object->apply_transform(apply_to_motion);
- object->mesh->transform_applied = true;
-
- if(progress.get_cancel()) return;
- }
-
- object_flag[i] |= SD_OBJECT_TRANSFORM_APPLIED;
- if(object->mesh->transform_negative_scaled)
- object_flag[i] |= SD_OBJECT_NEGATIVE_SCALE_APPLIED;
- }
- else
- have_instancing = true;
- }
- else
- have_instancing = true;
-
- i++;
- }
-
- dscene->data.bvh.have_instancing = have_instancing;
+ /* todo: normals and displacement should be done before applying transform! */
+ /* todo: create objects/meshes in right order! */
+
+ /* counter mesh users */
+ map<Mesh *, int> mesh_users;
+ Scene::MotionType need_motion = scene->need_motion();
+ bool motion_blur = need_motion == Scene::MOTION_BLUR;
+ bool apply_to_motion = need_motion != Scene::MOTION_PASS;
+ int i = 0;
+ bool have_instancing = false;
+
+ foreach (Object *object, scene->objects) {
+ map<Mesh *, int>::iterator it = mesh_users.find(object->mesh);
+
+ if (it == mesh_users.end())
+ mesh_users[object->mesh] = 1;
+ else
+ it->second++;
+ }
+
+ if (progress.get_cancel())
+ return;
+
+ uint *object_flag = dscene->object_flag.data();
+
+ /* apply transforms for objects with single user meshes */
+ foreach (Object *object, scene->objects) {
+ /* Annoying feedback loop here: we can't use is_instanced() because
+ * it'll use uninitialized transform_applied flag.
+ *
+ * Could be solved by moving reference counter to Mesh.
+ */
+ if ((mesh_users[object->mesh] == 1 && !object->mesh->has_surface_bssrdf) &&
+ !object->mesh->has_true_displacement() &&
+ object->mesh->subdivision_type == Mesh::SUBDIVISION_NONE) {
+ if (!(motion_blur && object->use_motion())) {
+ if (!object->mesh->transform_applied) {
+ object->apply_transform(apply_to_motion);
+ object->mesh->transform_applied = true;
+
+ if (progress.get_cancel())
+ return;
+ }
+
+ object_flag[i] |= SD_OBJECT_TRANSFORM_APPLIED;
+ if (object->mesh->transform_negative_scaled)
+ object_flag[i] |= SD_OBJECT_NEGATIVE_SCALE_APPLIED;
+ }
+ else
+ have_instancing = true;
+ }
+ else
+ have_instancing = true;
+
+ i++;
+ }
+
+ dscene->data.bvh.have_instancing = have_instancing;
}
void ObjectManager::tag_update(Scene *scene)
{
- need_update = true;
- scene->curve_system_manager->need_update = true;
- scene->mesh_manager->need_update = true;
- scene->light_manager->need_update = true;
+ need_update = true;
+ scene->curve_system_manager->need_update = true;
+ scene->mesh_manager->need_update = true;
+ scene->light_manager->need_update = true;
}
string ObjectManager::get_cryptomatte_objects(Scene *scene)
{
- string manifest = "{";
-
- unordered_set<ustring, ustringHash> objects;
- foreach(Object *object, scene->objects) {
- if(objects.count(object->name)) {
- continue;
- }
- objects.insert(object->name);
- uint32_t hash_name = util_murmur_hash3(object->name.c_str(), object->name.length(), 0);
- manifest += string_printf("\"%s\":\"%08x\",", object->name.c_str(), hash_name);
- }
- manifest[manifest.size()-1] = '}';
- return manifest;
+ string manifest = "{";
+
+ unordered_set<ustring, ustringHash> objects;
+ foreach (Object *object, scene->objects) {
+ if (objects.count(object->name)) {
+ continue;
+ }
+ objects.insert(object->name);
+ uint32_t hash_name = util_murmur_hash3(object->name.c_str(), object->name.length(), 0);
+ manifest += string_printf("\"%s\":\"%08x\",", object->name.c_str(), hash_name);
+ }
+ manifest[manifest.size() - 1] = '}';
+ return manifest;
}
string ObjectManager::get_cryptomatte_assets(Scene *scene)
{
- string manifest = "{";
- unordered_set<ustring, ustringHash> assets;
- foreach(Object *ob, scene->objects) {
- if(assets.count(ob->asset_name)) {
- continue;
- }
- assets.insert(ob->asset_name);
- uint32_t hash_asset = util_murmur_hash3(ob->asset_name.c_str(), ob->asset_name.length(), 0);
- manifest += string_printf("\"%s\":\"%08x\",", ob->asset_name.c_str(), hash_asset);
- }
- manifest[manifest.size()-1] = '}';
- return manifest;
+ string manifest = "{";
+ unordered_set<ustring, ustringHash> assets;
+ foreach (Object *ob, scene->objects) {
+ if (assets.count(ob->asset_name)) {
+ continue;
+ }
+ assets.insert(ob->asset_name);
+ uint32_t hash_asset = util_murmur_hash3(ob->asset_name.c_str(), ob->asset_name.length(), 0);
+ manifest += string_printf("\"%s\":\"%08x\",", ob->asset_name.c_str(), hash_asset);
+ }
+ manifest[manifest.size() - 1] = '}';
+ return manifest;
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/render/object.h b/intern/cycles/render/object.h
index 134f0bc3577..2fd43900da1 100644
--- a/intern/cycles/render/object.h
+++ b/intern/cycles/render/object.h
@@ -43,105 +43,101 @@ class ObjectManager;
/* Object */
class Object : public Node {
-public:
- NODE_DECLARE
-
- Mesh *mesh;
- Transform tfm;
- BoundBox bounds;
- uint random_id;
- int pass_id;
- ustring asset_name;
- vector<ParamValue> attributes;
- uint visibility;
- array<Transform> motion;
- bool hide_on_missing_motion;
- bool use_holdout;
- bool is_shadow_catcher;
-
- float3 dupli_generated;
- float2 dupli_uv;
-
- ParticleSystem *particle_system;
- int particle_index;
-
- Object();
- ~Object();
-
- void tag_update(Scene *scene);
-
- void compute_bounds(bool motion_blur);
- void apply_transform(bool apply_to_motion);
-
- /* Convert between normalized -1..1 motion time and index
- * in the motion array. */
- bool use_motion() const;
- float motion_time(int step) const;
- int motion_step(float time) const;
- void update_motion();
-
- /* Check whether object is traceable and it worth adding it to
- * kernel scene.
- */
- bool is_traceable() const;
-
- /* Combine object's visibility with all possible internal run-time
- * determined flags which denotes trace-time visibility.
- */
- uint visibility_for_tracing() const;
-
- /* Returns the index that is used in the kernel for this object. */
- int get_device_index() const;
-
-protected:
- /* Specifies the position of the object in scene->objects and
- * in the device vectors. Gets set in device_update. */
- int index;
-
- friend class ObjectManager;
+ public:
+ NODE_DECLARE
+
+ Mesh *mesh;
+ Transform tfm;
+ BoundBox bounds;
+ uint random_id;
+ int pass_id;
+ ustring asset_name;
+ vector<ParamValue> attributes;
+ uint visibility;
+ array<Transform> motion;
+ bool hide_on_missing_motion;
+ bool use_holdout;
+ bool is_shadow_catcher;
+
+ float3 dupli_generated;
+ float2 dupli_uv;
+
+ ParticleSystem *particle_system;
+ int particle_index;
+
+ Object();
+ ~Object();
+
+ void tag_update(Scene *scene);
+
+ void compute_bounds(bool motion_blur);
+ void apply_transform(bool apply_to_motion);
+
+ /* Convert between normalized -1..1 motion time and index
+ * in the motion array. */
+ bool use_motion() const;
+ float motion_time(int step) const;
+ int motion_step(float time) const;
+ void update_motion();
+
+ /* Check whether object is traceable and it worth adding it to
+ * kernel scene.
+ */
+ bool is_traceable() const;
+
+ /* Combine object's visibility with all possible internal run-time
+ * determined flags which denotes trace-time visibility.
+ */
+ uint visibility_for_tracing() const;
+
+ /* Returns the index that is used in the kernel for this object. */
+ int get_device_index() const;
+
+ protected:
+ /* Specifies the position of the object in scene->objects and
+ * in the device vectors. Gets set in device_update. */
+ int index;
+
+ friend class ObjectManager;
};
/* Object Manager */
class ObjectManager {
-public:
- bool need_update;
- bool need_flags_update;
-
- ObjectManager();
- ~ObjectManager();
-
- void device_update(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress);
- void device_update_transforms(DeviceScene *dscene,
- Scene *scene,
- Progress& progress);
-
- void device_update_flags(Device *device,
- DeviceScene *dscene,
- Scene *scene,
- Progress& progress,
- bool bounds_valid = true);
- void device_update_mesh_offsets(Device *device, DeviceScene *dscene, Scene *scene);
-
- void device_free(Device *device, DeviceScene *dscene);
-
- void tag_update(Scene *scene);
-
- void apply_static_transforms(DeviceScene *dscene, Scene *scene, Progress& progress);
-
- string get_cryptomatte_objects(Scene *scene);
- string get_cryptomatte_assets(Scene *scene);
-
-protected:
- void device_update_object_transform(UpdateObjectTransformState *state,
- Object *ob);
- void device_update_object_transform_task(UpdateObjectTransformState *state);
- bool device_update_object_transform_pop_work(
- UpdateObjectTransformState *state,
- int *start_index,
- int *num_objects);
+ public:
+ bool need_update;
+ bool need_flags_update;
+
+ ObjectManager();
+ ~ObjectManager();
+
+ void device_update(Device *device, DeviceScene *dscene, Scene *scene, Progress &progress);
+ void device_update_transforms(DeviceScene *dscene, Scene *scene, Progress &progress);
+
+ void device_update_flags(Device *device,
+ DeviceScene *dscene,
+ Scene *scene,
+ Progress &progress,
+ bool bounds_valid = true);
+ void device_update_mesh_offsets(Device *device, DeviceScene *dscene, Scene *scene);
+
+ void device_free(Device *device, DeviceScene *dscene);
+
+ void tag_update(Scene *scene);
+
+ void apply_static_transforms(DeviceScene *dscene, Scene *scene, Progress &progress);
+
+ string get_cryptomatte_objects(Scene *scene);
+ string get_cryptomatte_assets(Scene *scene);
+
+ protected:
+ void device_update_object_transform(UpdateObjectTransformState *state, Object *ob);
+ void device_update_object_transform_task(UpdateObjectTransformState *state);
+ bool device_update_object_transform_pop_work(UpdateObjectTransformState *state,
+ int *start_index,
+ int *num_objects);
};
CCL_NAMESPACE_END
-#endif /* __OBJECT_H__ */
+#endif /* __OBJECT_H__ */
diff --git a/intern/cycles/render/osl.cpp b/intern/cycles/render/osl.cpp
index c603dc69a16..b66a46938be 100644
--- a/intern/cycles/render/osl.cpp
+++ b/intern/cycles/render/osl.cpp
@@ -25,16 +25,16 @@
#ifdef WITH_OSL
-#include "kernel/osl/osl_globals.h"
-#include "kernel/osl/osl_services.h"
-#include "kernel/osl/osl_shader.h"
+# include "kernel/osl/osl_globals.h"
+# include "kernel/osl/osl_services.h"
+# include "kernel/osl/osl_shader.h"
-#include "util/util_foreach.h"
-#include "util/util_logging.h"
-#include "util/util_md5.h"
-#include "util/util_path.h"
-#include "util/util_progress.h"
-#include "util/util_projection.h"
+# include "util/util_foreach.h"
+# include "util/util_logging.h"
+# include "util/util_md5.h"
+# include "util/util_path.h"
+# include "util/util_progress.h"
+# include "util/util_projection.h"
#endif
@@ -58,1151 +58,1140 @@ thread_mutex OSLShaderManager::ss_mutex;
OSLShaderManager::OSLShaderManager()
{
- texture_system_init();
- shading_system_init();
+ texture_system_init();
+ shading_system_init();
}
OSLShaderManager::~OSLShaderManager()
{
- shading_system_free();
- texture_system_free();
+ shading_system_free();
+ texture_system_free();
}
void OSLShaderManager::free_memory()
{
-#ifdef OSL_HAS_BLENDER_CLEANUP_FIX
- /* There is a problem with llvm+osl: The order global destructors across
- * different compilation units run cannot be guaranteed, on windows this means
- * that the llvm destructors run before the osl destructors, causing a crash
- * when the process exits. the OSL in svn has a special cleanup hack to
- * sidestep this behavior */
- OSL::pvt::LLVM_Util::Cleanup();
-#endif
+# ifdef OSL_HAS_BLENDER_CLEANUP_FIX
+ /* There is a problem with llvm+osl: The order global destructors across
+ * different compilation units run cannot be guaranteed, on windows this means
+ * that the llvm destructors run before the osl destructors, causing a crash
+ * when the process exits. the OSL in svn has a special cleanup hack to
+ * sidestep this behavior */
+ OSL::pvt::LLVM_Util::Cleanup();
+# endif
}
void OSLShaderManager::reset(Scene * /*scene*/)
{
- shading_system_free();
- shading_system_init();
+ shading_system_free();
+ shading_system_init();
}
-void OSLShaderManager::device_update(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress)
+void OSLShaderManager::device_update(Device *device,
+ DeviceScene *dscene,
+ Scene *scene,
+ Progress &progress)
{
- if(!need_update)
- return;
+ if (!need_update)
+ return;
- VLOG(1) << "Total " << scene->shaders.size() << " shaders.";
+ VLOG(1) << "Total " << scene->shaders.size() << " shaders.";
- device_free(device, dscene, scene);
+ device_free(device, dscene, scene);
- /* determine which shaders are in use */
- device_update_shaders_used(scene);
+ /* determine which shaders are in use */
+ device_update_shaders_used(scene);
- /* create shaders */
- OSLGlobals *og = (OSLGlobals*)device->osl_memory();
+ /* create shaders */
+ OSLGlobals *og = (OSLGlobals *)device->osl_memory();
- foreach(Shader *shader, scene->shaders) {
- assert(shader->graph);
+ foreach (Shader *shader, scene->shaders) {
+ assert(shader->graph);
- if(progress.get_cancel()) return;
+ if (progress.get_cancel())
+ return;
- /* we can only compile one shader at the time as the OSL ShadingSytem
- * has a single state, but we put the lock here so different renders can
- * compile shaders alternating */
- thread_scoped_lock lock(ss_mutex);
+ /* we can only compile one shader at the time as the OSL ShadingSytem
+ * has a single state, but we put the lock here so different renders can
+ * compile shaders alternating */
+ thread_scoped_lock lock(ss_mutex);
- OSLCompiler compiler((void*)this, (void*)ss,
- scene->image_manager,
- scene->light_manager);
- compiler.background = (shader == scene->default_background);
- compiler.compile(scene, og, shader);
+ OSLCompiler compiler((void *)this, (void *)ss, scene->image_manager, scene->light_manager);
+ compiler.background = (shader == scene->default_background);
+ compiler.compile(scene, og, shader);
- if(shader->use_mis && shader->has_surface_emission)
- scene->light_manager->need_update = true;
- }
+ if (shader->use_mis && shader->has_surface_emission)
+ scene->light_manager->need_update = true;
+ }
- /* setup shader engine */
- og->ss = ss;
- og->ts = ts;
- og->services = services;
+ /* setup shader engine */
+ og->ss = ss;
+ og->ts = ts;
+ og->services = services;
- int background_id = scene->shader_manager->get_shader_id(scene->default_background);
- og->background_state = og->surface_state[background_id & SHADER_MASK];
- og->use = true;
+ int background_id = scene->shader_manager->get_shader_id(scene->default_background);
+ og->background_state = og->surface_state[background_id & SHADER_MASK];
+ og->use = true;
- foreach(Shader *shader, scene->shaders)
- shader->need_update = false;
+ foreach (Shader *shader, scene->shaders)
+ shader->need_update = false;
- need_update = false;
+ need_update = false;
- /* set texture system */
- scene->image_manager->set_osl_texture_system((void*)ts);
+ /* set texture system */
+ scene->image_manager->set_osl_texture_system((void *)ts);
- device_update_common(device, dscene, scene, progress);
+ device_update_common(device, dscene, scene, progress);
- {
- /* Perform greedyjit optimization.
- *
- * This might waste time on optimizing gorups which are never actually
- * used, but this prevents OSL from allocating data on TLS at render
- * time.
- *
- * This is much better for us because this way we aren't required to
- * stop task scheduler threads to make sure all TLS is clean and don't
- * have issues with TLS data free accessing freed memory if task scheduler
- * is being freed after the Session is freed.
- */
- thread_scoped_lock lock(ss_shared_mutex);
- ss->optimize_all_groups();
- }
+ {
+ /* Perform greedyjit optimization.
+ *
+ * This might waste time on optimizing gorups which are never actually
+ * used, but this prevents OSL from allocating data on TLS at render
+ * time.
+ *
+ * This is much better for us because this way we aren't required to
+ * stop task scheduler threads to make sure all TLS is clean and don't
+ * have issues with TLS data free accessing freed memory if task scheduler
+ * is being freed after the Session is freed.
+ */
+ thread_scoped_lock lock(ss_shared_mutex);
+ ss->optimize_all_groups();
+ }
}
void OSLShaderManager::device_free(Device *device, DeviceScene *dscene, Scene *scene)
{
- OSLGlobals *og = (OSLGlobals*)device->osl_memory();
+ OSLGlobals *og = (OSLGlobals *)device->osl_memory();
- device_free_common(device, dscene, scene);
+ device_free_common(device, dscene, scene);
- /* clear shader engine */
- og->use = false;
- og->ss = NULL;
- og->ts = NULL;
+ /* clear shader engine */
+ og->use = false;
+ og->ss = NULL;
+ og->ts = NULL;
- og->surface_state.clear();
- og->volume_state.clear();
- og->displacement_state.clear();
- og->bump_state.clear();
- og->background_state.reset();
+ og->surface_state.clear();
+ og->volume_state.clear();
+ og->displacement_state.clear();
+ og->bump_state.clear();
+ og->background_state.reset();
}
void OSLShaderManager::texture_system_init()
{
- /* create texture system, shared between different renders to reduce memory usage */
- thread_scoped_lock lock(ts_shared_mutex);
+ /* create texture system, shared between different renders to reduce memory usage */
+ thread_scoped_lock lock(ts_shared_mutex);
- if(ts_shared_users == 0) {
- ts_shared = TextureSystem::create(true);
+ if (ts_shared_users == 0) {
+ ts_shared = TextureSystem::create(true);
- ts_shared->attribute("automip", 1);
- ts_shared->attribute("autotile", 64);
- ts_shared->attribute("gray_to_rgb", 1);
+ ts_shared->attribute("automip", 1);
+ ts_shared->attribute("autotile", 64);
+ ts_shared->attribute("gray_to_rgb", 1);
- /* effectively unlimited for now, until we support proper mipmap lookups */
- ts_shared->attribute("max_memory_MB", 16384);
- }
+ /* effectively unlimited for now, until we support proper mipmap lookups */
+ ts_shared->attribute("max_memory_MB", 16384);
+ }
- ts = ts_shared;
- ts_shared_users++;
+ ts = ts_shared;
+ ts_shared_users++;
}
void OSLShaderManager::texture_system_free()
{
- /* shared texture system decrease users and destroy if no longer used */
- thread_scoped_lock lock(ts_shared_mutex);
- ts_shared_users--;
+ /* shared texture system decrease users and destroy if no longer used */
+ thread_scoped_lock lock(ts_shared_mutex);
+ ts_shared_users--;
- if(ts_shared_users == 0) {
- ts_shared->invalidate_all(true);
- OSL::TextureSystem::destroy(ts_shared);
- ts_shared = NULL;
- }
+ if (ts_shared_users == 0) {
+ ts_shared->invalidate_all(true);
+ OSL::TextureSystem::destroy(ts_shared);
+ ts_shared = NULL;
+ }
- ts = NULL;
+ ts = NULL;
}
void OSLShaderManager::shading_system_init()
{
- /* create shading system, shared between different renders to reduce memory usage */
- thread_scoped_lock lock(ss_shared_mutex);
-
- if(ss_shared_users == 0) {
- services_shared = new OSLRenderServices();
-
- string shader_path = path_get("shader");
-#ifdef _WIN32
- /* Annoying thing, Cycles stores paths in UTF-8 codepage, so it can
- * operate with file paths with any character. This requires to use wide
- * char functions, but OSL uses old fashioned ANSI functions which means:
- *
- * - We have to convert our paths to ANSI before passing to OSL
- * - OSL can't be used when there's a multi-byte character in the path
- * to the shaders folder.
- */
- shader_path = string_to_ansi(shader_path);
-#endif
-
- ss_shared = new OSL::ShadingSystem(services_shared, ts_shared, &errhandler);
- ss_shared->attribute("lockgeom", 1);
- ss_shared->attribute("commonspace", "world");
- ss_shared->attribute("searchpath:shader", shader_path);
- ss_shared->attribute("greedyjit", 1);
-
- VLOG(1) << "Using shader search path: " << shader_path;
-
- /* our own ray types */
- static const char *raytypes[] = {
- "camera", /* PATH_RAY_CAMERA */
- "reflection", /* PATH_RAY_REFLECT */
- "refraction", /* PATH_RAY_TRANSMIT */
- "diffuse", /* PATH_RAY_DIFFUSE */
- "glossy", /* PATH_RAY_GLOSSY */
- "singular", /* PATH_RAY_SINGULAR */
- "transparent", /* PATH_RAY_TRANSPARENT */
-
- "shadow", /* PATH_RAY_SHADOW_OPAQUE_NON_CATCHER */
- "shadow", /* PATH_RAY_SHADOW_OPAQUE_CATCHER */
- "shadow", /* PATH_RAY_SHADOW_TRANSPARENT_NON_CATCHER */
- "shadow", /* PATH_RAY_SHADOW_TRANSPARENT_CATCHER */
-
- "__unused__",
- "volume_scatter", /* PATH_RAY_VOLUME_SCATTER */
- "__unused__",
-
- "__unused__",
- "diffuse_ancestor", /* PATH_RAY_DIFFUSE_ANCESTOR */
- "__unused__",
- "__unused__",
- "__unused__",
- "__unused__",
- "__unused__",
- "__unused__",
- "__unused__",
- };
-
- const int nraytypes = sizeof(raytypes)/sizeof(raytypes[0]);
- ss_shared->attribute("raytypes", TypeDesc(TypeDesc::STRING, nraytypes), raytypes);
-
- OSLShader::register_closures((OSLShadingSystem*)ss_shared);
-
- loaded_shaders.clear();
- }
-
- ss = ss_shared;
- services = services_shared;
- ss_shared_users++;
+ /* create shading system, shared between different renders to reduce memory usage */
+ thread_scoped_lock lock(ss_shared_mutex);
+
+ if (ss_shared_users == 0) {
+ services_shared = new OSLRenderServices();
+
+ string shader_path = path_get("shader");
+# ifdef _WIN32
+ /* Annoying thing, Cycles stores paths in UTF-8 codepage, so it can
+ * operate with file paths with any character. This requires to use wide
+ * char functions, but OSL uses old fashioned ANSI functions which means:
+ *
+ * - We have to convert our paths to ANSI before passing to OSL
+ * - OSL can't be used when there's a multi-byte character in the path
+ * to the shaders folder.
+ */
+ shader_path = string_to_ansi(shader_path);
+# endif
+
+ ss_shared = new OSL::ShadingSystem(services_shared, ts_shared, &errhandler);
+ ss_shared->attribute("lockgeom", 1);
+ ss_shared->attribute("commonspace", "world");
+ ss_shared->attribute("searchpath:shader", shader_path);
+ ss_shared->attribute("greedyjit", 1);
+
+ VLOG(1) << "Using shader search path: " << shader_path;
+
+ /* our own ray types */
+ static const char *raytypes[] = {
+ "camera", /* PATH_RAY_CAMERA */
+ "reflection", /* PATH_RAY_REFLECT */
+ "refraction", /* PATH_RAY_TRANSMIT */
+ "diffuse", /* PATH_RAY_DIFFUSE */
+ "glossy", /* PATH_RAY_GLOSSY */
+ "singular", /* PATH_RAY_SINGULAR */
+ "transparent", /* PATH_RAY_TRANSPARENT */
+
+ "shadow", /* PATH_RAY_SHADOW_OPAQUE_NON_CATCHER */
+ "shadow", /* PATH_RAY_SHADOW_OPAQUE_CATCHER */
+ "shadow", /* PATH_RAY_SHADOW_TRANSPARENT_NON_CATCHER */
+ "shadow", /* PATH_RAY_SHADOW_TRANSPARENT_CATCHER */
+
+ "__unused__", "volume_scatter", /* PATH_RAY_VOLUME_SCATTER */
+ "__unused__",
+
+ "__unused__", "diffuse_ancestor", /* PATH_RAY_DIFFUSE_ANCESTOR */
+ "__unused__", "__unused__", "__unused__", "__unused__",
+ "__unused__", "__unused__", "__unused__",
+ };
+
+ const int nraytypes = sizeof(raytypes) / sizeof(raytypes[0]);
+ ss_shared->attribute("raytypes", TypeDesc(TypeDesc::STRING, nraytypes), raytypes);
+
+ OSLShader::register_closures((OSLShadingSystem *)ss_shared);
+
+ loaded_shaders.clear();
+ }
+
+ ss = ss_shared;
+ services = services_shared;
+ ss_shared_users++;
}
void OSLShaderManager::shading_system_free()
{
- /* shared shading system decrease users and destroy if no longer used */
- thread_scoped_lock lock(ss_shared_mutex);
- ss_shared_users--;
+ /* shared shading system decrease users and destroy if no longer used */
+ thread_scoped_lock lock(ss_shared_mutex);
+ ss_shared_users--;
- if(ss_shared_users == 0) {
- delete ss_shared;
- ss_shared = NULL;
+ if (ss_shared_users == 0) {
+ delete ss_shared;
+ ss_shared = NULL;
- delete services_shared;
- services_shared = NULL;
- }
+ delete services_shared;
+ services_shared = NULL;
+ }
- ss = NULL;
- services = NULL;
+ ss = NULL;
+ services = NULL;
}
-bool OSLShaderManager::osl_compile(const string& inputfile, const string& outputfile)
+bool OSLShaderManager::osl_compile(const string &inputfile, const string &outputfile)
{
- vector<string> options;
- string stdosl_path;
- string shader_path = path_get("shader");
+ vector<string> options;
+ string stdosl_path;
+ string shader_path = path_get("shader");
- /* specify output file name */
- options.push_back("-o");
- options.push_back(outputfile);
+ /* specify output file name */
+ options.push_back("-o");
+ options.push_back(outputfile);
- /* specify standard include path */
- string include_path_arg = string("-I") + shader_path;
- options.push_back(include_path_arg);
+ /* specify standard include path */
+ string include_path_arg = string("-I") + shader_path;
+ options.push_back(include_path_arg);
- stdosl_path = path_get("shader/stdosl.h");
+ stdosl_path = path_get("shader/stdosl.h");
- /* compile */
- OSL::OSLCompiler *compiler = new OSL::OSLCompiler(&OSL::ErrorHandler::default_handler());
- bool ok = compiler->compile(string_view(inputfile), options, string_view(stdosl_path));
- delete compiler;
+ /* compile */
+ OSL::OSLCompiler *compiler = new OSL::OSLCompiler(&OSL::ErrorHandler::default_handler());
+ bool ok = compiler->compile(string_view(inputfile), options, string_view(stdosl_path));
+ delete compiler;
- return ok;
+ return ok;
}
-bool OSLShaderManager::osl_query(OSL::OSLQuery& query, const string& filepath)
+bool OSLShaderManager::osl_query(OSL::OSLQuery &query, const string &filepath)
{
- string searchpath = path_user_get("shaders");
- return query.open(filepath, searchpath);
+ string searchpath = path_user_get("shaders");
+ return query.open(filepath, searchpath);
}
-static string shader_filepath_hash(const string& filepath, uint64_t modified_time)
+static string shader_filepath_hash(const string &filepath, uint64_t modified_time)
{
- /* compute a hash from filepath and modified time to detect changes */
- MD5Hash md5;
- md5.append((const uint8_t*)filepath.c_str(), filepath.size());
- md5.append((const uint8_t*)&modified_time, sizeof(modified_time));
+ /* compute a hash from filepath and modified time to detect changes */
+ MD5Hash md5;
+ md5.append((const uint8_t *)filepath.c_str(), filepath.size());
+ md5.append((const uint8_t *)&modified_time, sizeof(modified_time));
- return md5.get_hex();
+ return md5.get_hex();
}
-const char *OSLShaderManager::shader_test_loaded(const string& hash)
+const char *OSLShaderManager::shader_test_loaded(const string &hash)
{
- map<string, OSLShaderInfo>::iterator it = loaded_shaders.find(hash);
- return (it == loaded_shaders.end())? NULL: it->first.c_str();
+ map<string, OSLShaderInfo>::iterator it = loaded_shaders.find(hash);
+ return (it == loaded_shaders.end()) ? NULL : it->first.c_str();
}
-OSLShaderInfo *OSLShaderManager::shader_loaded_info(const string& hash)
+OSLShaderInfo *OSLShaderManager::shader_loaded_info(const string &hash)
{
- map<string, OSLShaderInfo>::iterator it = loaded_shaders.find(hash);
- return (it == loaded_shaders.end())? NULL: &it->second;
+ map<string, OSLShaderInfo>::iterator it = loaded_shaders.find(hash);
+ return (it == loaded_shaders.end()) ? NULL : &it->second;
}
const char *OSLShaderManager::shader_load_filepath(string filepath)
{
- size_t len = filepath.size();
- string extension = filepath.substr(len - 4);
- uint64_t modified_time = path_modified_time(filepath);
-
- if(extension == ".osl") {
- /* .OSL File */
- string osopath = filepath.substr(0, len - 4) + ".oso";
- uint64_t oso_modified_time = path_modified_time(osopath);
-
- /* test if we have loaded the corresponding .OSO already */
- if(oso_modified_time != 0) {
- const char *hash = shader_test_loaded(shader_filepath_hash(osopath, oso_modified_time));
-
- if(hash)
- return hash;
- }
-
- /* autocompile .OSL to .OSO if needed */
- if(oso_modified_time == 0 || (oso_modified_time < modified_time)) {
- OSLShaderManager::osl_compile(filepath, osopath);
- modified_time = path_modified_time(osopath);
- }
- else
- modified_time = oso_modified_time;
-
- filepath = osopath;
- }
- else {
- if(extension == ".oso") {
- /* .OSO File, nothing to do */
- }
- else if(path_dirname(filepath) == "") {
- /* .OSO File in search path */
- filepath = path_join(path_user_get("shaders"), filepath + ".oso");
- }
- else {
- /* unknown file */
- return NULL;
- }
-
- /* test if we have loaded this .OSO already */
- const char *hash = shader_test_loaded(shader_filepath_hash(filepath, modified_time));
-
- if(hash)
- return hash;
- }
-
- /* read oso bytecode from file */
- string bytecode_hash = shader_filepath_hash(filepath, modified_time);
- string bytecode;
-
- if(!path_read_text(filepath, bytecode)) {
- fprintf(stderr, "Cycles shader graph: failed to read file %s\n", filepath.c_str());
- OSLShaderInfo info;
- loaded_shaders[bytecode_hash] = info; /* to avoid repeat tries */
- return NULL;
- }
-
- return shader_load_bytecode(bytecode_hash, bytecode);
+ size_t len = filepath.size();
+ string extension = filepath.substr(len - 4);
+ uint64_t modified_time = path_modified_time(filepath);
+
+ if (extension == ".osl") {
+ /* .OSL File */
+ string osopath = filepath.substr(0, len - 4) + ".oso";
+ uint64_t oso_modified_time = path_modified_time(osopath);
+
+ /* test if we have loaded the corresponding .OSO already */
+ if (oso_modified_time != 0) {
+ const char *hash = shader_test_loaded(shader_filepath_hash(osopath, oso_modified_time));
+
+ if (hash)
+ return hash;
+ }
+
+ /* autocompile .OSL to .OSO if needed */
+ if (oso_modified_time == 0 || (oso_modified_time < modified_time)) {
+ OSLShaderManager::osl_compile(filepath, osopath);
+ modified_time = path_modified_time(osopath);
+ }
+ else
+ modified_time = oso_modified_time;
+
+ filepath = osopath;
+ }
+ else {
+ if (extension == ".oso") {
+ /* .OSO File, nothing to do */
+ }
+ else if (path_dirname(filepath) == "") {
+ /* .OSO File in search path */
+ filepath = path_join(path_user_get("shaders"), filepath + ".oso");
+ }
+ else {
+ /* unknown file */
+ return NULL;
+ }
+
+ /* test if we have loaded this .OSO already */
+ const char *hash = shader_test_loaded(shader_filepath_hash(filepath, modified_time));
+
+ if (hash)
+ return hash;
+ }
+
+ /* read oso bytecode from file */
+ string bytecode_hash = shader_filepath_hash(filepath, modified_time);
+ string bytecode;
+
+ if (!path_read_text(filepath, bytecode)) {
+ fprintf(stderr, "Cycles shader graph: failed to read file %s\n", filepath.c_str());
+ OSLShaderInfo info;
+ loaded_shaders[bytecode_hash] = info; /* to avoid repeat tries */
+ return NULL;
+ }
+
+ return shader_load_bytecode(bytecode_hash, bytecode);
}
-const char *OSLShaderManager::shader_load_bytecode(const string& hash, const string& bytecode)
+const char *OSLShaderManager::shader_load_bytecode(const string &hash, const string &bytecode)
{
- ss->LoadMemoryCompiledShader(hash.c_str(), bytecode.c_str());
+ ss->LoadMemoryCompiledShader(hash.c_str(), bytecode.c_str());
- OSLShaderInfo info;
+ OSLShaderInfo info;
- if(!info.query.open_bytecode(bytecode)) {
- fprintf(stderr, "OSL query error: %s\n", info.query.geterror().c_str());
- }
+ if (!info.query.open_bytecode(bytecode)) {
+ fprintf(stderr, "OSL query error: %s\n", info.query.geterror().c_str());
+ }
- /* this is a bit weak, but works */
- info.has_surface_emission = (bytecode.find("\"emission\"") != string::npos);
- info.has_surface_transparent = (bytecode.find("\"transparent\"") != string::npos);
- info.has_surface_bssrdf = (bytecode.find("\"bssrdf\"") != string::npos);
+ /* this is a bit weak, but works */
+ info.has_surface_emission = (bytecode.find("\"emission\"") != string::npos);
+ info.has_surface_transparent = (bytecode.find("\"transparent\"") != string::npos);
+ info.has_surface_bssrdf = (bytecode.find("\"bssrdf\"") != string::npos);
- loaded_shaders[hash] = info;
+ loaded_shaders[hash] = info;
- return loaded_shaders.find(hash)->first.c_str();
+ return loaded_shaders.find(hash)->first.c_str();
}
-OSLNode *OSLShaderManager::osl_node(const std::string& filepath,
- const std::string& bytecode_hash,
- const std::string& bytecode)
+OSLNode *OSLShaderManager::osl_node(const std::string &filepath,
+ const std::string &bytecode_hash,
+ const std::string &bytecode)
{
- /* create query */
- const char *hash;
-
- if(!filepath.empty()) {
- hash = shader_load_filepath(filepath);
- }
- else {
- hash = shader_test_loaded(bytecode_hash);
- if(!hash)
- hash = shader_load_bytecode(bytecode_hash, bytecode);
- }
-
- if(!hash) {
- return NULL;
- }
-
- OSLShaderInfo *info = shader_loaded_info(hash);
-
- /* count number of inputs */
- size_t num_inputs = 0;
-
- for(int i = 0; i < info->query.nparams(); i++) {
- const OSL::OSLQuery::Parameter *param = info->query.getparam(i);
-
- /* skip unsupported types */
- if(param->varlenarray || param->isstruct || param->type.arraylen > 1)
- continue;
-
- if(!param->isoutput)
- num_inputs++;
- }
-
- /* create node */
- OSLNode *node = OSLNode::create(num_inputs);
-
- /* add new sockets from parameters */
- set<void*> used_sockets;
-
- for(int i = 0; i < info->query.nparams(); i++) {
- const OSL::OSLQuery::Parameter *param = info->query.getparam(i);
-
- /* skip unsupported types */
- if(param->varlenarray || param->isstruct || param->type.arraylen > 1)
- continue;
-
- SocketType::Type socket_type;
-
- if(param->isclosure) {
- socket_type = SocketType::CLOSURE;
- }
- else if(param->type.vecsemantics != TypeDesc::NOSEMANTICS) {
- if(param->type.vecsemantics == TypeDesc::COLOR)
- socket_type = SocketType::COLOR;
- else if(param->type.vecsemantics == TypeDesc::POINT)
- socket_type = SocketType::POINT;
- else if(param->type.vecsemantics == TypeDesc::VECTOR)
- socket_type = SocketType::VECTOR;
- else if(param->type.vecsemantics == TypeDesc::NORMAL)
- socket_type = SocketType::NORMAL;
- else
- continue;
-
- if(!param->isoutput && param->validdefault) {
- float3 *default_value = (float3*)node->input_default_value();
- default_value->x = param->fdefault[0];
- default_value->y = param->fdefault[1];
- default_value->z = param->fdefault[2];
- }
- }
- else if(param->type.aggregate == TypeDesc::SCALAR) {
- if(param->type.basetype == TypeDesc::INT) {
- socket_type = SocketType::INT;
-
- if(!param->isoutput && param->validdefault) {
- *(int*)node->input_default_value() = param->idefault[0];
- }
- }
- else if(param->type.basetype == TypeDesc::FLOAT) {
- socket_type = SocketType::FLOAT;
-
- if(!param->isoutput && param->validdefault) {
- *(float*)node->input_default_value() = param->fdefault[0];
- }
- }
- else if(param->type.basetype == TypeDesc::STRING) {
- socket_type = SocketType::STRING;
-
- if(!param->isoutput && param->validdefault) {
- *(ustring*)node->input_default_value() = param->sdefault[0];
- }
- }
- else
- continue;
- }
- else
- continue;
-
- if(param->isoutput) {
- node->add_output(param->name, socket_type);
- }
- else {
- node->add_input(param->name, socket_type);
- }
- }
-
- /* set bytcode hash or filepath */
- if(!bytecode_hash.empty()) {
- node->bytecode_hash = bytecode_hash;
- }
- else {
- node->filepath = filepath;
- }
-
- /* Generate inputs and outputs */
- node->create_inputs_outputs(node->type);
-
- return node;
+ /* create query */
+ const char *hash;
+
+ if (!filepath.empty()) {
+ hash = shader_load_filepath(filepath);
+ }
+ else {
+ hash = shader_test_loaded(bytecode_hash);
+ if (!hash)
+ hash = shader_load_bytecode(bytecode_hash, bytecode);
+ }
+
+ if (!hash) {
+ return NULL;
+ }
+
+ OSLShaderInfo *info = shader_loaded_info(hash);
+
+ /* count number of inputs */
+ size_t num_inputs = 0;
+
+ for (int i = 0; i < info->query.nparams(); i++) {
+ const OSL::OSLQuery::Parameter *param = info->query.getparam(i);
+
+ /* skip unsupported types */
+ if (param->varlenarray || param->isstruct || param->type.arraylen > 1)
+ continue;
+
+ if (!param->isoutput)
+ num_inputs++;
+ }
+
+ /* create node */
+ OSLNode *node = OSLNode::create(num_inputs);
+
+ /* add new sockets from parameters */
+ set<void *> used_sockets;
+
+ for (int i = 0; i < info->query.nparams(); i++) {
+ const OSL::OSLQuery::Parameter *param = info->query.getparam(i);
+
+ /* skip unsupported types */
+ if (param->varlenarray || param->isstruct || param->type.arraylen > 1)
+ continue;
+
+ SocketType::Type socket_type;
+
+ if (param->isclosure) {
+ socket_type = SocketType::CLOSURE;
+ }
+ else if (param->type.vecsemantics != TypeDesc::NOSEMANTICS) {
+ if (param->type.vecsemantics == TypeDesc::COLOR)
+ socket_type = SocketType::COLOR;
+ else if (param->type.vecsemantics == TypeDesc::POINT)
+ socket_type = SocketType::POINT;
+ else if (param->type.vecsemantics == TypeDesc::VECTOR)
+ socket_type = SocketType::VECTOR;
+ else if (param->type.vecsemantics == TypeDesc::NORMAL)
+ socket_type = SocketType::NORMAL;
+ else
+ continue;
+
+ if (!param->isoutput && param->validdefault) {
+ float3 *default_value = (float3 *)node->input_default_value();
+ default_value->x = param->fdefault[0];
+ default_value->y = param->fdefault[1];
+ default_value->z = param->fdefault[2];
+ }
+ }
+ else if (param->type.aggregate == TypeDesc::SCALAR) {
+ if (param->type.basetype == TypeDesc::INT) {
+ socket_type = SocketType::INT;
+
+ if (!param->isoutput && param->validdefault) {
+ *(int *)node->input_default_value() = param->idefault[0];
+ }
+ }
+ else if (param->type.basetype == TypeDesc::FLOAT) {
+ socket_type = SocketType::FLOAT;
+
+ if (!param->isoutput && param->validdefault) {
+ *(float *)node->input_default_value() = param->fdefault[0];
+ }
+ }
+ else if (param->type.basetype == TypeDesc::STRING) {
+ socket_type = SocketType::STRING;
+
+ if (!param->isoutput && param->validdefault) {
+ *(ustring *)node->input_default_value() = param->sdefault[0];
+ }
+ }
+ else
+ continue;
+ }
+ else
+ continue;
+
+ if (param->isoutput) {
+ node->add_output(param->name, socket_type);
+ }
+ else {
+ node->add_input(param->name, socket_type);
+ }
+ }
+
+ /* set bytcode hash or filepath */
+ if (!bytecode_hash.empty()) {
+ node->bytecode_hash = bytecode_hash;
+ }
+ else {
+ node->filepath = filepath;
+ }
+
+ /* Generate inputs and outputs */
+ node->create_inputs_outputs(node->type);
+
+ return node;
}
/* Graph Compiler */
-OSLCompiler::OSLCompiler(void *manager_, void *shadingsys_,
+OSLCompiler::OSLCompiler(void *manager_,
+ void *shadingsys_,
ImageManager *image_manager_,
LightManager *light_manager_)
{
- manager = manager_;
- shadingsys = shadingsys_;
- image_manager = image_manager_;
- light_manager = light_manager_;
- current_type = SHADER_TYPE_SURFACE;
- current_shader = NULL;
- background = false;
+ manager = manager_;
+ shadingsys = shadingsys_;
+ image_manager = image_manager_;
+ light_manager = light_manager_;
+ current_type = SHADER_TYPE_SURFACE;
+ current_shader = NULL;
+ background = false;
}
string OSLCompiler::id(ShaderNode *node)
{
- /* assign layer unique name based on pointer address + bump mode */
- stringstream stream;
- stream << "node_" << node->type->name << "_" << node;
+ /* assign layer unique name based on pointer address + bump mode */
+ stringstream stream;
+ stream << "node_" << node->type->name << "_" << node;
- return stream.str();
+ return stream.str();
}
string OSLCompiler::compatible_name(ShaderNode *node, ShaderInput *input)
{
- string sname(input->name().string());
- size_t i;
-
- /* strip whitespace */
- while((i = sname.find(" ")) != string::npos)
- sname.replace(i, 1, "");
-
- /* if output exists with the same name, add "In" suffix */
- foreach(ShaderOutput *output, node->outputs) {
- if(input->name() == output->name()) {
- sname += "In";
- break;
- }
- }
-
- return sname;
+ string sname(input->name().string());
+ size_t i;
+
+ /* strip whitespace */
+ while ((i = sname.find(" ")) != string::npos)
+ sname.replace(i, 1, "");
+
+ /* if output exists with the same name, add "In" suffix */
+ foreach (ShaderOutput *output, node->outputs) {
+ if (input->name() == output->name()) {
+ sname += "In";
+ break;
+ }
+ }
+
+ return sname;
}
string OSLCompiler::compatible_name(ShaderNode *node, ShaderOutput *output)
{
- string sname(output->name().string());
- size_t i;
-
- /* strip whitespace */
- while((i = sname.find(" ")) != string::npos)
- sname.replace(i, 1, "");
-
- /* if input exists with the same name, add "Out" suffix */
- foreach(ShaderInput *input, node->inputs) {
- if(input->name() == output->name()) {
- sname += "Out";
- break;
- }
- }
-
- return sname;
+ string sname(output->name().string());
+ size_t i;
+
+ /* strip whitespace */
+ while ((i = sname.find(" ")) != string::npos)
+ sname.replace(i, 1, "");
+
+ /* if input exists with the same name, add "Out" suffix */
+ foreach (ShaderInput *input, node->inputs) {
+ if (input->name() == output->name()) {
+ sname += "Out";
+ break;
+ }
+ }
+
+ return sname;
}
bool OSLCompiler::node_skip_input(ShaderNode *node, ShaderInput *input)
{
- /* exception for output node, only one input is actually used
- * depending on the current shader type */
-
- if(input->flags() & SocketType::SVM_INTERNAL)
- return true;
-
- if(node->special_type == SHADER_SPECIAL_TYPE_OUTPUT) {
- if(input->name() == "Surface" && current_type != SHADER_TYPE_SURFACE)
- return true;
- if(input->name() == "Volume" && current_type != SHADER_TYPE_VOLUME)
- return true;
- if(input->name() == "Displacement" && current_type != SHADER_TYPE_DISPLACEMENT)
- return true;
- if(input->name() == "Normal" && current_type != SHADER_TYPE_BUMP)
- return true;
- }
- else if(node->special_type == SHADER_SPECIAL_TYPE_BUMP) {
- if(input->name() == "Height")
- return true;
- }
- else if(current_type == SHADER_TYPE_DISPLACEMENT && input->link && input->link->parent->special_type == SHADER_SPECIAL_TYPE_BUMP)
- return true;
-
- return false;
+ /* exception for output node, only one input is actually used
+ * depending on the current shader type */
+
+ if (input->flags() & SocketType::SVM_INTERNAL)
+ return true;
+
+ if (node->special_type == SHADER_SPECIAL_TYPE_OUTPUT) {
+ if (input->name() == "Surface" && current_type != SHADER_TYPE_SURFACE)
+ return true;
+ if (input->name() == "Volume" && current_type != SHADER_TYPE_VOLUME)
+ return true;
+ if (input->name() == "Displacement" && current_type != SHADER_TYPE_DISPLACEMENT)
+ return true;
+ if (input->name() == "Normal" && current_type != SHADER_TYPE_BUMP)
+ return true;
+ }
+ else if (node->special_type == SHADER_SPECIAL_TYPE_BUMP) {
+ if (input->name() == "Height")
+ return true;
+ }
+ else if (current_type == SHADER_TYPE_DISPLACEMENT && input->link &&
+ input->link->parent->special_type == SHADER_SPECIAL_TYPE_BUMP)
+ return true;
+
+ return false;
}
void OSLCompiler::add(ShaderNode *node, const char *name, bool isfilepath)
{
- OSL::ShadingSystem *ss = (OSL::ShadingSystem*)shadingsys;
-
- /* load filepath */
- if(isfilepath) {
- name = ((OSLShaderManager*)manager)->shader_load_filepath(name);
-
- if(name == NULL)
- return;
- }
-
- /* pass in fixed parameter values */
- foreach(ShaderInput *input, node->inputs) {
- if(!input->link) {
- /* checks to untangle graphs */
- if(node_skip_input(node, input))
- continue;
- /* already has default value assigned */
- else if(input->flags() & SocketType::DEFAULT_LINK_MASK)
- continue;
-
- string param_name = compatible_name(node, input);
- const SocketType& socket = input->socket_type;
- switch(input->type()) {
- case SocketType::COLOR:
- parameter_color(param_name.c_str(), node->get_float3(socket));
- break;
- case SocketType::POINT:
- parameter_point(param_name.c_str(), node->get_float3(socket));
- break;
- case SocketType::VECTOR:
- parameter_vector(param_name.c_str(), node->get_float3(socket));
- break;
- case SocketType::NORMAL:
- parameter_normal(param_name.c_str(), node->get_float3(socket));
- break;
- case SocketType::FLOAT:
- parameter(param_name.c_str(), node->get_float(socket));
- break;
- case SocketType::INT:
- parameter(param_name.c_str(), node->get_int(socket));
- break;
- case SocketType::STRING:
- parameter(param_name.c_str(), node->get_string(socket));
- break;
- case SocketType::CLOSURE:
- case SocketType::UNDEFINED:
- default:
- break;
- }
- }
- }
-
- /* create shader of the appropriate type. OSL only distinguishes between "surface"
- * and "displacement" atm */
- if(current_type == SHADER_TYPE_SURFACE)
- ss->Shader("surface", name, id(node).c_str());
- else if(current_type == SHADER_TYPE_VOLUME)
- ss->Shader("surface", name, id(node).c_str());
- else if(current_type == SHADER_TYPE_DISPLACEMENT)
- ss->Shader("displacement", name, id(node).c_str());
- else if(current_type == SHADER_TYPE_BUMP)
- ss->Shader("displacement", name, id(node).c_str());
- else
- assert(0);
-
- /* link inputs to other nodes */
- foreach(ShaderInput *input, node->inputs) {
- if(input->link) {
- if(node_skip_input(node, input))
- continue;
-
- /* connect shaders */
- string id_from = id(input->link->parent);
- string id_to = id(node);
- string param_from = compatible_name(input->link->parent, input->link);
- string param_to = compatible_name(node, input);
-
- ss->ConnectShaders(id_from.c_str(), param_from.c_str(), id_to.c_str(), param_to.c_str());
- }
- }
-
- /* test if we shader contains specific closures */
- OSLShaderInfo *info = ((OSLShaderManager*)manager)->shader_loaded_info(name);
-
- if(current_type == SHADER_TYPE_SURFACE) {
- if(info) {
- if(info->has_surface_emission)
- current_shader->has_surface_emission = true;
- if(info->has_surface_transparent)
- current_shader->has_surface_transparent = true;
- if(info->has_surface_bssrdf) {
- current_shader->has_surface_bssrdf = true;
- current_shader->has_bssrdf_bump = true; /* can't detect yet */
- }
- current_shader->has_bump = true; /* can't detect yet */
- }
-
- if(node->has_spatial_varying()) {
- current_shader->has_surface_spatial_varying = true;
- }
- }
- else if(current_type == SHADER_TYPE_VOLUME) {
- if(node->has_spatial_varying())
- current_shader->has_volume_spatial_varying = true;
- }
-
- if(node->has_object_dependency()) {
- current_shader->has_object_dependency = true;
- }
-
- if(node->has_attribute_dependency()) {
- current_shader->has_attribute_dependency = true;
- }
-
- if(node->has_integrator_dependency()) {
- current_shader->has_integrator_dependency = true;
- }
+ OSL::ShadingSystem *ss = (OSL::ShadingSystem *)shadingsys;
+
+ /* load filepath */
+ if (isfilepath) {
+ name = ((OSLShaderManager *)manager)->shader_load_filepath(name);
+
+ if (name == NULL)
+ return;
+ }
+
+ /* pass in fixed parameter values */
+ foreach (ShaderInput *input, node->inputs) {
+ if (!input->link) {
+ /* checks to untangle graphs */
+ if (node_skip_input(node, input))
+ continue;
+ /* already has default value assigned */
+ else if (input->flags() & SocketType::DEFAULT_LINK_MASK)
+ continue;
+
+ string param_name = compatible_name(node, input);
+ const SocketType &socket = input->socket_type;
+ switch (input->type()) {
+ case SocketType::COLOR:
+ parameter_color(param_name.c_str(), node->get_float3(socket));
+ break;
+ case SocketType::POINT:
+ parameter_point(param_name.c_str(), node->get_float3(socket));
+ break;
+ case SocketType::VECTOR:
+ parameter_vector(param_name.c_str(), node->get_float3(socket));
+ break;
+ case SocketType::NORMAL:
+ parameter_normal(param_name.c_str(), node->get_float3(socket));
+ break;
+ case SocketType::FLOAT:
+ parameter(param_name.c_str(), node->get_float(socket));
+ break;
+ case SocketType::INT:
+ parameter(param_name.c_str(), node->get_int(socket));
+ break;
+ case SocketType::STRING:
+ parameter(param_name.c_str(), node->get_string(socket));
+ break;
+ case SocketType::CLOSURE:
+ case SocketType::UNDEFINED:
+ default:
+ break;
+ }
+ }
+ }
+
+ /* create shader of the appropriate type. OSL only distinguishes between "surface"
+ * and "displacement" atm */
+ if (current_type == SHADER_TYPE_SURFACE)
+ ss->Shader("surface", name, id(node).c_str());
+ else if (current_type == SHADER_TYPE_VOLUME)
+ ss->Shader("surface", name, id(node).c_str());
+ else if (current_type == SHADER_TYPE_DISPLACEMENT)
+ ss->Shader("displacement", name, id(node).c_str());
+ else if (current_type == SHADER_TYPE_BUMP)
+ ss->Shader("displacement", name, id(node).c_str());
+ else
+ assert(0);
+
+ /* link inputs to other nodes */
+ foreach (ShaderInput *input, node->inputs) {
+ if (input->link) {
+ if (node_skip_input(node, input))
+ continue;
+
+ /* connect shaders */
+ string id_from = id(input->link->parent);
+ string id_to = id(node);
+ string param_from = compatible_name(input->link->parent, input->link);
+ string param_to = compatible_name(node, input);
+
+ ss->ConnectShaders(id_from.c_str(), param_from.c_str(), id_to.c_str(), param_to.c_str());
+ }
+ }
+
+ /* test if we shader contains specific closures */
+ OSLShaderInfo *info = ((OSLShaderManager *)manager)->shader_loaded_info(name);
+
+ if (current_type == SHADER_TYPE_SURFACE) {
+ if (info) {
+ if (info->has_surface_emission)
+ current_shader->has_surface_emission = true;
+ if (info->has_surface_transparent)
+ current_shader->has_surface_transparent = true;
+ if (info->has_surface_bssrdf) {
+ current_shader->has_surface_bssrdf = true;
+ current_shader->has_bssrdf_bump = true; /* can't detect yet */
+ }
+ current_shader->has_bump = true; /* can't detect yet */
+ }
+
+ if (node->has_spatial_varying()) {
+ current_shader->has_surface_spatial_varying = true;
+ }
+ }
+ else if (current_type == SHADER_TYPE_VOLUME) {
+ if (node->has_spatial_varying())
+ current_shader->has_volume_spatial_varying = true;
+ }
+
+ if (node->has_object_dependency()) {
+ current_shader->has_object_dependency = true;
+ }
+
+ if (node->has_attribute_dependency()) {
+ current_shader->has_attribute_dependency = true;
+ }
+
+ if (node->has_integrator_dependency()) {
+ current_shader->has_integrator_dependency = true;
+ }
}
static TypeDesc array_typedesc(TypeDesc typedesc, int arraylength)
{
- return TypeDesc((TypeDesc::BASETYPE)typedesc.basetype,
- (TypeDesc::AGGREGATE)typedesc.aggregate,
- (TypeDesc::VECSEMANTICS)typedesc.vecsemantics,
- arraylength);
+ return TypeDesc((TypeDesc::BASETYPE)typedesc.basetype,
+ (TypeDesc::AGGREGATE)typedesc.aggregate,
+ (TypeDesc::VECSEMANTICS)typedesc.vecsemantics,
+ arraylength);
}
-void OSLCompiler::parameter(ShaderNode* node, const char *name)
+void OSLCompiler::parameter(ShaderNode *node, const char *name)
{
- OSL::ShadingSystem *ss = (OSL::ShadingSystem*)shadingsys;
- ustring uname = ustring(name);
- const SocketType& socket = *(node->type->find_input(uname));
-
- switch(socket.type)
- {
- case SocketType::BOOLEAN:
- {
- int value = node->get_bool(socket);
- ss->Parameter(name, TypeDesc::TypeInt, &value);
- break;
- }
- case SocketType::FLOAT:
- {
- float value = node->get_float(socket);
- ss->Parameter(uname, TypeDesc::TypeFloat, &value);
- break;
- }
- case SocketType::INT:
- {
- int value = node->get_int(socket);
- ss->Parameter(uname, TypeDesc::TypeInt, &value);
- break;
- }
- case SocketType::COLOR:
- {
- float3 value = node->get_float3(socket);
- ss->Parameter(uname, TypeDesc::TypeColor, &value);
- break;
- }
- case SocketType::VECTOR:
- {
- float3 value = node->get_float3(socket);
- ss->Parameter(uname, TypeDesc::TypeVector, &value);
- break;
- }
- case SocketType::POINT:
- {
- float3 value = node->get_float3(socket);
- ss->Parameter(uname, TypeDesc::TypePoint, &value);
- break;
- }
- case SocketType::NORMAL:
- {
- float3 value = node->get_float3(socket);
- ss->Parameter(uname, TypeDesc::TypeNormal, &value);
- break;
- }
- case SocketType::POINT2:
- {
- float2 value = node->get_float2(socket);
- ss->Parameter(uname, TypeDesc(TypeDesc::FLOAT, TypeDesc::VEC2, TypeDesc::POINT), &value);
- break;
- }
- case SocketType::STRING:
- {
- ustring value = node->get_string(socket);
- ss->Parameter(uname, TypeDesc::TypeString, &value);
- break;
- }
- case SocketType::ENUM:
- {
- ustring value = node->get_string(socket);
- ss->Parameter(uname, TypeDesc::TypeString, &value);
- break;
- }
- case SocketType::TRANSFORM:
- {
- Transform value = node->get_transform(socket);
- ProjectionTransform projection(value);
- projection = projection_transpose(projection);
- ss->Parameter(uname, TypeDesc::TypeMatrix, &projection);
- break;
- }
- case SocketType::BOOLEAN_ARRAY:
- {
- // OSL does not support booleans, so convert to int
- const array<bool>& value = node->get_bool_array(socket);
- array<int> intvalue(value.size());
- for(size_t i = 0; i < value.size(); i++)
- intvalue[i] = value[i];
- ss->Parameter(uname, array_typedesc(TypeDesc::TypeInt, value.size()), intvalue.data());
- break;
- }
- case SocketType::FLOAT_ARRAY:
- {
- const array<float>& value = node->get_float_array(socket);
- ss->Parameter(uname, array_typedesc(TypeDesc::TypeFloat, value.size()), value.data());
- break;
- }
- case SocketType::INT_ARRAY:
- {
- const array<int>& value = node->get_int_array(socket);
- ss->Parameter(uname, array_typedesc(TypeDesc::TypeInt, value.size()), value.data());
- break;
- }
- case SocketType::COLOR_ARRAY:
- case SocketType::VECTOR_ARRAY:
- case SocketType::POINT_ARRAY:
- case SocketType::NORMAL_ARRAY:
- {
- TypeDesc typedesc;
-
- switch(socket.type)
- {
- case SocketType::COLOR_ARRAY: typedesc = TypeDesc::TypeColor; break;
- case SocketType::VECTOR_ARRAY: typedesc = TypeDesc::TypeVector; break;
- case SocketType::POINT_ARRAY: typedesc = TypeDesc::TypePoint; break;
- case SocketType::NORMAL_ARRAY: typedesc = TypeDesc::TypeNormal; break;
- default: assert(0); break;
- }
-
- // convert to tightly packed array since float3 has padding
- const array<float3>& value = node->get_float3_array(socket);
- array<float> fvalue(value.size() * 3);
- for(size_t i = 0, j = 0; i < value.size(); i++) {
- fvalue[j++] = value[i].x;
- fvalue[j++] = value[i].y;
- fvalue[j++] = value[i].z;
- }
-
- ss->Parameter(uname, array_typedesc(typedesc, value.size()), fvalue.data());
- break;
- }
- case SocketType::POINT2_ARRAY:
- {
- const array<float2>& value = node->get_float2_array(socket);
- ss->Parameter(uname, array_typedesc(TypeDesc(TypeDesc::FLOAT, TypeDesc::VEC2, TypeDesc::POINT), value.size()), value.data());
- break;
- }
- case SocketType::STRING_ARRAY:
- {
- const array<ustring>& value = node->get_string_array(socket);
- ss->Parameter(uname, array_typedesc(TypeDesc::TypeString, value.size()), value.data());
- break;
- }
- case SocketType::TRANSFORM_ARRAY:
- {
- const array<Transform>& value = node->get_transform_array(socket);
- array<ProjectionTransform> fvalue(value.size());
- for(size_t i = 0; i < value.size(); i++) {
- fvalue[i] = projection_transpose(ProjectionTransform(value[i]));
- }
- ss->Parameter(uname, array_typedesc(TypeDesc::TypeMatrix, fvalue.size()), fvalue.data());
- break;
- }
- case SocketType::CLOSURE:
- case SocketType::NODE:
- case SocketType::NODE_ARRAY:
- case SocketType::UNDEFINED:
- case SocketType::UINT:
- {
- assert(0);
- break;
- }
- }
+ OSL::ShadingSystem *ss = (OSL::ShadingSystem *)shadingsys;
+ ustring uname = ustring(name);
+ const SocketType &socket = *(node->type->find_input(uname));
+
+ switch (socket.type) {
+ case SocketType::BOOLEAN: {
+ int value = node->get_bool(socket);
+ ss->Parameter(name, TypeDesc::TypeInt, &value);
+ break;
+ }
+ case SocketType::FLOAT: {
+ float value = node->get_float(socket);
+ ss->Parameter(uname, TypeDesc::TypeFloat, &value);
+ break;
+ }
+ case SocketType::INT: {
+ int value = node->get_int(socket);
+ ss->Parameter(uname, TypeDesc::TypeInt, &value);
+ break;
+ }
+ case SocketType::COLOR: {
+ float3 value = node->get_float3(socket);
+ ss->Parameter(uname, TypeDesc::TypeColor, &value);
+ break;
+ }
+ case SocketType::VECTOR: {
+ float3 value = node->get_float3(socket);
+ ss->Parameter(uname, TypeDesc::TypeVector, &value);
+ break;
+ }
+ case SocketType::POINT: {
+ float3 value = node->get_float3(socket);
+ ss->Parameter(uname, TypeDesc::TypePoint, &value);
+ break;
+ }
+ case SocketType::NORMAL: {
+ float3 value = node->get_float3(socket);
+ ss->Parameter(uname, TypeDesc::TypeNormal, &value);
+ break;
+ }
+ case SocketType::POINT2: {
+ float2 value = node->get_float2(socket);
+ ss->Parameter(uname, TypeDesc(TypeDesc::FLOAT, TypeDesc::VEC2, TypeDesc::POINT), &value);
+ break;
+ }
+ case SocketType::STRING: {
+ ustring value = node->get_string(socket);
+ ss->Parameter(uname, TypeDesc::TypeString, &value);
+ break;
+ }
+ case SocketType::ENUM: {
+ ustring value = node->get_string(socket);
+ ss->Parameter(uname, TypeDesc::TypeString, &value);
+ break;
+ }
+ case SocketType::TRANSFORM: {
+ Transform value = node->get_transform(socket);
+ ProjectionTransform projection(value);
+ projection = projection_transpose(projection);
+ ss->Parameter(uname, TypeDesc::TypeMatrix, &projection);
+ break;
+ }
+ case SocketType::BOOLEAN_ARRAY: {
+ // OSL does not support booleans, so convert to int
+ const array<bool> &value = node->get_bool_array(socket);
+ array<int> intvalue(value.size());
+ for (size_t i = 0; i < value.size(); i++)
+ intvalue[i] = value[i];
+ ss->Parameter(uname, array_typedesc(TypeDesc::TypeInt, value.size()), intvalue.data());
+ break;
+ }
+ case SocketType::FLOAT_ARRAY: {
+ const array<float> &value = node->get_float_array(socket);
+ ss->Parameter(uname, array_typedesc(TypeDesc::TypeFloat, value.size()), value.data());
+ break;
+ }
+ case SocketType::INT_ARRAY: {
+ const array<int> &value = node->get_int_array(socket);
+ ss->Parameter(uname, array_typedesc(TypeDesc::TypeInt, value.size()), value.data());
+ break;
+ }
+ case SocketType::COLOR_ARRAY:
+ case SocketType::VECTOR_ARRAY:
+ case SocketType::POINT_ARRAY:
+ case SocketType::NORMAL_ARRAY: {
+ TypeDesc typedesc;
+
+ switch (socket.type) {
+ case SocketType::COLOR_ARRAY:
+ typedesc = TypeDesc::TypeColor;
+ break;
+ case SocketType::VECTOR_ARRAY:
+ typedesc = TypeDesc::TypeVector;
+ break;
+ case SocketType::POINT_ARRAY:
+ typedesc = TypeDesc::TypePoint;
+ break;
+ case SocketType::NORMAL_ARRAY:
+ typedesc = TypeDesc::TypeNormal;
+ break;
+ default:
+ assert(0);
+ break;
+ }
+
+ // convert to tightly packed array since float3 has padding
+ const array<float3> &value = node->get_float3_array(socket);
+ array<float> fvalue(value.size() * 3);
+ for (size_t i = 0, j = 0; i < value.size(); i++) {
+ fvalue[j++] = value[i].x;
+ fvalue[j++] = value[i].y;
+ fvalue[j++] = value[i].z;
+ }
+
+ ss->Parameter(uname, array_typedesc(typedesc, value.size()), fvalue.data());
+ break;
+ }
+ case SocketType::POINT2_ARRAY: {
+ const array<float2> &value = node->get_float2_array(socket);
+ ss->Parameter(
+ uname,
+ array_typedesc(TypeDesc(TypeDesc::FLOAT, TypeDesc::VEC2, TypeDesc::POINT), value.size()),
+ value.data());
+ break;
+ }
+ case SocketType::STRING_ARRAY: {
+ const array<ustring> &value = node->get_string_array(socket);
+ ss->Parameter(uname, array_typedesc(TypeDesc::TypeString, value.size()), value.data());
+ break;
+ }
+ case SocketType::TRANSFORM_ARRAY: {
+ const array<Transform> &value = node->get_transform_array(socket);
+ array<ProjectionTransform> fvalue(value.size());
+ for (size_t i = 0; i < value.size(); i++) {
+ fvalue[i] = projection_transpose(ProjectionTransform(value[i]));
+ }
+ ss->Parameter(uname, array_typedesc(TypeDesc::TypeMatrix, fvalue.size()), fvalue.data());
+ break;
+ }
+ case SocketType::CLOSURE:
+ case SocketType::NODE:
+ case SocketType::NODE_ARRAY:
+ case SocketType::UNDEFINED:
+ case SocketType::UINT: {
+ assert(0);
+ break;
+ }
+ }
}
void OSLCompiler::parameter(const char *name, float f)
{
- OSL::ShadingSystem *ss = (OSL::ShadingSystem*)shadingsys;
- ss->Parameter(name, TypeDesc::TypeFloat, &f);
+ OSL::ShadingSystem *ss = (OSL::ShadingSystem *)shadingsys;
+ ss->Parameter(name, TypeDesc::TypeFloat, &f);
}
void OSLCompiler::parameter_color(const char *name, float3 f)
{
- OSL::ShadingSystem *ss = (OSL::ShadingSystem*)shadingsys;
- ss->Parameter(name, TypeDesc::TypeColor, &f);
+ OSL::ShadingSystem *ss = (OSL::ShadingSystem *)shadingsys;
+ ss->Parameter(name, TypeDesc::TypeColor, &f);
}
void OSLCompiler::parameter_point(const char *name, float3 f)
{
- OSL::ShadingSystem *ss = (OSL::ShadingSystem*)shadingsys;
- ss->Parameter(name, TypeDesc::TypePoint, &f);
+ OSL::ShadingSystem *ss = (OSL::ShadingSystem *)shadingsys;
+ ss->Parameter(name, TypeDesc::TypePoint, &f);
}
void OSLCompiler::parameter_normal(const char *name, float3 f)
{
- OSL::ShadingSystem *ss = (OSL::ShadingSystem*)shadingsys;
- ss->Parameter(name, TypeDesc::TypeNormal, &f);
+ OSL::ShadingSystem *ss = (OSL::ShadingSystem *)shadingsys;
+ ss->Parameter(name, TypeDesc::TypeNormal, &f);
}
void OSLCompiler::parameter_vector(const char *name, float3 f)
{
- OSL::ShadingSystem *ss = (OSL::ShadingSystem*)shadingsys;
- ss->Parameter(name, TypeDesc::TypeVector, &f);
+ OSL::ShadingSystem *ss = (OSL::ShadingSystem *)shadingsys;
+ ss->Parameter(name, TypeDesc::TypeVector, &f);
}
void OSLCompiler::parameter(const char *name, int f)
{
- OSL::ShadingSystem *ss = (OSL::ShadingSystem*)shadingsys;
- ss->Parameter(name, TypeDesc::TypeInt, &f);
+ OSL::ShadingSystem *ss = (OSL::ShadingSystem *)shadingsys;
+ ss->Parameter(name, TypeDesc::TypeInt, &f);
}
void OSLCompiler::parameter(const char *name, const char *s)
{
- OSL::ShadingSystem *ss = (OSL::ShadingSystem*)shadingsys;
- ss->Parameter(name, TypeDesc::TypeString, &s);
+ OSL::ShadingSystem *ss = (OSL::ShadingSystem *)shadingsys;
+ ss->Parameter(name, TypeDesc::TypeString, &s);
}
void OSLCompiler::parameter(const char *name, ustring s)
{
- OSL::ShadingSystem *ss = (OSL::ShadingSystem*)shadingsys;
- const char *str = s.c_str();
- ss->Parameter(name, TypeDesc::TypeString, &str);
+ OSL::ShadingSystem *ss = (OSL::ShadingSystem *)shadingsys;
+ const char *str = s.c_str();
+ ss->Parameter(name, TypeDesc::TypeString, &str);
}
-void OSLCompiler::parameter(const char *name, const Transform& tfm)
+void OSLCompiler::parameter(const char *name, const Transform &tfm)
{
- OSL::ShadingSystem *ss = (OSL::ShadingSystem*)shadingsys;
- ProjectionTransform projection(tfm);
- projection = projection_transpose(projection);
- ss->Parameter(name, TypeDesc::TypeMatrix, (float*)&projection);
+ OSL::ShadingSystem *ss = (OSL::ShadingSystem *)shadingsys;
+ ProjectionTransform projection(tfm);
+ projection = projection_transpose(projection);
+ ss->Parameter(name, TypeDesc::TypeMatrix, (float *)&projection);
}
void OSLCompiler::parameter_array(const char *name, const float f[], int arraylen)
{
- OSL::ShadingSystem *ss = (OSL::ShadingSystem*)shadingsys;
- TypeDesc type = TypeDesc::TypeFloat;
- type.arraylen = arraylen;
- ss->Parameter(name, type, f);
+ OSL::ShadingSystem *ss = (OSL::ShadingSystem *)shadingsys;
+ TypeDesc type = TypeDesc::TypeFloat;
+ type.arraylen = arraylen;
+ ss->Parameter(name, type, f);
}
-void OSLCompiler::parameter_color_array(const char *name, const array<float3>& f)
+void OSLCompiler::parameter_color_array(const char *name, const array<float3> &f)
{
- /* NB: cycles float3 type is actually 4 floats! need to use an explicit array */
- array<float[3]> table(f.size());
-
- for(int i = 0; i < f.size(); ++i) {
- table[i][0] = f[i].x;
- table[i][1] = f[i].y;
- table[i][2] = f[i].z;
- }
-
- OSL::ShadingSystem *ss = (OSL::ShadingSystem*)shadingsys;
- TypeDesc type = TypeDesc::TypeColor;
- type.arraylen = table.size();
- ss->Parameter(name, type, table.data());
+ /* NB: cycles float3 type is actually 4 floats! need to use an explicit array */
+ array<float[3]> table(f.size());
+
+ for (int i = 0; i < f.size(); ++i) {
+ table[i][0] = f[i].x;
+ table[i][1] = f[i].y;
+ table[i][2] = f[i].z;
+ }
+
+ OSL::ShadingSystem *ss = (OSL::ShadingSystem *)shadingsys;
+ TypeDesc type = TypeDesc::TypeColor;
+ type.arraylen = table.size();
+ ss->Parameter(name, type, table.data());
}
void OSLCompiler::parameter_attribute(const char *name, ustring s)
{
- if(Attribute::name_standard(s.c_str()))
- parameter(name, (string("geom:") + s.c_str()).c_str());
- else
- parameter(name, s.c_str());
+ if (Attribute::name_standard(s.c_str()))
+ parameter(name, (string("geom:") + s.c_str()).c_str());
+ else
+ parameter(name, s.c_str());
}
-void OSLCompiler::find_dependencies(ShaderNodeSet& dependencies, ShaderInput *input)
+void OSLCompiler::find_dependencies(ShaderNodeSet &dependencies, ShaderInput *input)
{
- ShaderNode *node = (input->link)? input->link->parent: NULL;
+ ShaderNode *node = (input->link) ? input->link->parent : NULL;
- if(node != NULL && dependencies.find(node) == dependencies.end()) {
- foreach(ShaderInput *in, node->inputs)
- if(!node_skip_input(node, in))
- find_dependencies(dependencies, in);
+ if (node != NULL && dependencies.find(node) == dependencies.end()) {
+ foreach (ShaderInput *in, node->inputs)
+ if (!node_skip_input(node, in))
+ find_dependencies(dependencies, in);
- dependencies.insert(node);
- }
+ dependencies.insert(node);
+ }
}
-void OSLCompiler::generate_nodes(const ShaderNodeSet& nodes)
+void OSLCompiler::generate_nodes(const ShaderNodeSet &nodes)
{
- ShaderNodeSet done;
- bool nodes_done;
-
- do {
- nodes_done = true;
-
- foreach(ShaderNode *node, nodes) {
- if(done.find(node) == done.end()) {
- bool inputs_done = true;
-
- foreach(ShaderInput *input, node->inputs)
- if(!node_skip_input(node, input))
- if(input->link && done.find(input->link->parent) == done.end())
- inputs_done = false;
-
- if(inputs_done) {
- node->compile(*this);
- done.insert(node);
-
- if(current_type == SHADER_TYPE_SURFACE) {
- if(node->has_surface_emission())
- current_shader->has_surface_emission = true;
- if(node->has_surface_transparent())
- current_shader->has_surface_transparent = true;
- if(node->has_spatial_varying())
- current_shader->has_surface_spatial_varying = true;
- if(node->has_surface_bssrdf()) {
- current_shader->has_surface_bssrdf = true;
- if(node->has_bssrdf_bump())
- current_shader->has_bssrdf_bump = true;
- }
- if(node->has_bump()) {
- current_shader->has_bump = true;
- }
- }
- else if(current_type == SHADER_TYPE_VOLUME) {
- if(node->has_spatial_varying())
- current_shader->has_volume_spatial_varying = true;
- }
- }
- else
- nodes_done = false;
- }
- }
- } while(!nodes_done);
+ ShaderNodeSet done;
+ bool nodes_done;
+
+ do {
+ nodes_done = true;
+
+ foreach (ShaderNode *node, nodes) {
+ if (done.find(node) == done.end()) {
+ bool inputs_done = true;
+
+ foreach (ShaderInput *input, node->inputs)
+ if (!node_skip_input(node, input))
+ if (input->link && done.find(input->link->parent) == done.end())
+ inputs_done = false;
+
+ if (inputs_done) {
+ node->compile(*this);
+ done.insert(node);
+
+ if (current_type == SHADER_TYPE_SURFACE) {
+ if (node->has_surface_emission())
+ current_shader->has_surface_emission = true;
+ if (node->has_surface_transparent())
+ current_shader->has_surface_transparent = true;
+ if (node->has_spatial_varying())
+ current_shader->has_surface_spatial_varying = true;
+ if (node->has_surface_bssrdf()) {
+ current_shader->has_surface_bssrdf = true;
+ if (node->has_bssrdf_bump())
+ current_shader->has_bssrdf_bump = true;
+ }
+ if (node->has_bump()) {
+ current_shader->has_bump = true;
+ }
+ }
+ else if (current_type == SHADER_TYPE_VOLUME) {
+ if (node->has_spatial_varying())
+ current_shader->has_volume_spatial_varying = true;
+ }
+ }
+ else
+ nodes_done = false;
+ }
+ }
+ } while (!nodes_done);
}
OSL::ShaderGroupRef OSLCompiler::compile_type(Shader *shader, ShaderGraph *graph, ShaderType type)
{
- OSL::ShadingSystem *ss = (OSL::ShadingSystem*)shadingsys;
-
- current_type = type;
-
- OSL::ShaderGroupRef group = ss->ShaderGroupBegin(shader->name.c_str());
-
- ShaderNode *output = graph->output();
- ShaderNodeSet dependencies;
-
- if(type == SHADER_TYPE_SURFACE) {
- /* generate surface shader */
- find_dependencies(dependencies, output->input("Surface"));
- generate_nodes(dependencies);
- output->compile(*this);
- }
- else if(type == SHADER_TYPE_BUMP) {
- /* generate bump shader */
- find_dependencies(dependencies, output->input("Normal"));
- generate_nodes(dependencies);
- output->compile(*this);
- }
- else if(type == SHADER_TYPE_VOLUME) {
- /* generate volume shader */
- find_dependencies(dependencies, output->input("Volume"));
- generate_nodes(dependencies);
- output->compile(*this);
- }
- else if(type == SHADER_TYPE_DISPLACEMENT) {
- /* generate displacement shader */
- find_dependencies(dependencies, output->input("Displacement"));
- generate_nodes(dependencies);
- output->compile(*this);
- }
- else
- assert(0);
-
- ss->ShaderGroupEnd();
-
- return group;
+ OSL::ShadingSystem *ss = (OSL::ShadingSystem *)shadingsys;
+
+ current_type = type;
+
+ OSL::ShaderGroupRef group = ss->ShaderGroupBegin(shader->name.c_str());
+
+ ShaderNode *output = graph->output();
+ ShaderNodeSet dependencies;
+
+ if (type == SHADER_TYPE_SURFACE) {
+ /* generate surface shader */
+ find_dependencies(dependencies, output->input("Surface"));
+ generate_nodes(dependencies);
+ output->compile(*this);
+ }
+ else if (type == SHADER_TYPE_BUMP) {
+ /* generate bump shader */
+ find_dependencies(dependencies, output->input("Normal"));
+ generate_nodes(dependencies);
+ output->compile(*this);
+ }
+ else if (type == SHADER_TYPE_VOLUME) {
+ /* generate volume shader */
+ find_dependencies(dependencies, output->input("Volume"));
+ generate_nodes(dependencies);
+ output->compile(*this);
+ }
+ else if (type == SHADER_TYPE_DISPLACEMENT) {
+ /* generate displacement shader */
+ find_dependencies(dependencies, output->input("Displacement"));
+ generate_nodes(dependencies);
+ output->compile(*this);
+ }
+ else
+ assert(0);
+
+ ss->ShaderGroupEnd();
+
+ return group;
}
void OSLCompiler::compile(Scene *scene, OSLGlobals *og, Shader *shader)
{
- if(shader->need_update) {
- ShaderGraph *graph = shader->graph;
- ShaderNode *output = (graph)? graph->output(): NULL;
-
- bool has_bump = (shader->displacement_method != DISPLACE_TRUE) &&
- output->input("Surface")->link && output->input("Displacement")->link;
-
- /* finalize */
- shader->graph->finalize(scene,
- has_bump,
- shader->has_integrator_dependency,
- shader->displacement_method == DISPLACE_BOTH);
-
- current_shader = shader;
-
- shader->has_surface = false;
- shader->has_surface_emission = false;
- shader->has_surface_transparent = false;
- shader->has_surface_bssrdf = false;
- shader->has_bump = has_bump;
- shader->has_bssrdf_bump = has_bump;
- shader->has_volume = false;
- shader->has_displacement = false;
- shader->has_surface_spatial_varying = false;
- shader->has_volume_spatial_varying = false;
- shader->has_object_dependency = false;
- shader->has_attribute_dependency = false;
- shader->has_integrator_dependency = false;
-
- /* generate surface shader */
- if(shader->used && graph && output->input("Surface")->link) {
- shader->osl_surface_ref = compile_type(shader, shader->graph, SHADER_TYPE_SURFACE);
-
- if(has_bump)
- shader->osl_surface_bump_ref = compile_type(shader, shader->graph, SHADER_TYPE_BUMP);
- else
- shader->osl_surface_bump_ref = OSL::ShaderGroupRef();
-
- shader->has_surface = true;
- }
- else {
- shader->osl_surface_ref = OSL::ShaderGroupRef();
- shader->osl_surface_bump_ref = OSL::ShaderGroupRef();
- }
-
- /* generate volume shader */
- if(shader->used && graph && output->input("Volume")->link) {
- shader->osl_volume_ref = compile_type(shader, shader->graph, SHADER_TYPE_VOLUME);
- shader->has_volume = true;
- }
- else
- shader->osl_volume_ref = OSL::ShaderGroupRef();
-
- /* generate displacement shader */
- if(shader->used && graph && output->input("Displacement")->link) {
- shader->osl_displacement_ref = compile_type(shader, shader->graph, SHADER_TYPE_DISPLACEMENT);
- shader->has_displacement = true;
- }
- else
- shader->osl_displacement_ref = OSL::ShaderGroupRef();
- }
-
- /* push state to array for lookup */
- og->surface_state.push_back(shader->osl_surface_ref);
- og->volume_state.push_back(shader->osl_volume_ref);
- og->displacement_state.push_back(shader->osl_displacement_ref);
- og->bump_state.push_back(shader->osl_surface_bump_ref);
+ if (shader->need_update) {
+ ShaderGraph *graph = shader->graph;
+ ShaderNode *output = (graph) ? graph->output() : NULL;
+
+ bool has_bump = (shader->displacement_method != DISPLACE_TRUE) &&
+ output->input("Surface")->link && output->input("Displacement")->link;
+
+ /* finalize */
+ shader->graph->finalize(scene,
+ has_bump,
+ shader->has_integrator_dependency,
+ shader->displacement_method == DISPLACE_BOTH);
+
+ current_shader = shader;
+
+ shader->has_surface = false;
+ shader->has_surface_emission = false;
+ shader->has_surface_transparent = false;
+ shader->has_surface_bssrdf = false;
+ shader->has_bump = has_bump;
+ shader->has_bssrdf_bump = has_bump;
+ shader->has_volume = false;
+ shader->has_displacement = false;
+ shader->has_surface_spatial_varying = false;
+ shader->has_volume_spatial_varying = false;
+ shader->has_object_dependency = false;
+ shader->has_attribute_dependency = false;
+ shader->has_integrator_dependency = false;
+
+ /* generate surface shader */
+ if (shader->used && graph && output->input("Surface")->link) {
+ shader->osl_surface_ref = compile_type(shader, shader->graph, SHADER_TYPE_SURFACE);
+
+ if (has_bump)
+ shader->osl_surface_bump_ref = compile_type(shader, shader->graph, SHADER_TYPE_BUMP);
+ else
+ shader->osl_surface_bump_ref = OSL::ShaderGroupRef();
+
+ shader->has_surface = true;
+ }
+ else {
+ shader->osl_surface_ref = OSL::ShaderGroupRef();
+ shader->osl_surface_bump_ref = OSL::ShaderGroupRef();
+ }
+
+ /* generate volume shader */
+ if (shader->used && graph && output->input("Volume")->link) {
+ shader->osl_volume_ref = compile_type(shader, shader->graph, SHADER_TYPE_VOLUME);
+ shader->has_volume = true;
+ }
+ else
+ shader->osl_volume_ref = OSL::ShaderGroupRef();
+
+ /* generate displacement shader */
+ if (shader->used && graph && output->input("Displacement")->link) {
+ shader->osl_displacement_ref = compile_type(shader, shader->graph, SHADER_TYPE_DISPLACEMENT);
+ shader->has_displacement = true;
+ }
+ else
+ shader->osl_displacement_ref = OSL::ShaderGroupRef();
+ }
+
+ /* push state to array for lookup */
+ og->surface_state.push_back(shader->osl_surface_ref);
+ og->volume_state.push_back(shader->osl_volume_ref);
+ og->displacement_state.push_back(shader->osl_displacement_ref);
+ og->bump_state.push_back(shader->osl_surface_bump_ref);
}
#else
@@ -1247,7 +1236,7 @@ void OSLCompiler::parameter(const char * /*name*/, ustring /*s*/)
{
}
-void OSLCompiler::parameter(const char * /*name*/, const Transform& /*tfm*/)
+void OSLCompiler::parameter(const char * /*name*/, const Transform & /*tfm*/)
{
}
@@ -1255,10 +1244,10 @@ void OSLCompiler::parameter_array(const char * /*name*/, const float /*f*/[], in
{
}
-void OSLCompiler::parameter_color_array(const char * /*name*/, const array<float3>& /*f*/)
+void OSLCompiler::parameter_color_array(const char * /*name*/, const array<float3> & /*f*/)
{
}
-#endif /* WITH_OSL */
+#endif /* WITH_OSL */
CCL_NAMESPACE_END
diff --git a/intern/cycles/render/osl.h b/intern/cycles/render/osl.h
index 93cc3139608..aec518a6c2b 100644
--- a/intern/cycles/render/osl.h
+++ b/intern/cycles/render/osl.h
@@ -27,10 +27,10 @@
#include "render/shader.h"
#ifdef WITH_OSL
-#include <OSL/llvm_util.h>
-#include <OSL/oslcomp.h>
-#include <OSL/oslexec.h>
-#include <OSL/oslquery.h>
+# include <OSL/llvm_util.h>
+# include <OSL/oslcomp.h>
+# include <OSL/oslexec.h>
+# include <OSL/oslquery.h>
#endif
CCL_NAMESPACE_BEGIN
@@ -52,70 +52,73 @@ class ShaderOutput;
* to auto detect closures in the shader for MIS and transparent shadows */
struct OSLShaderInfo {
- OSLShaderInfo()
- : has_surface_emission(false), has_surface_transparent(false),
- has_surface_bssrdf(false)
- {}
-
- OSL::OSLQuery query;
- bool has_surface_emission;
- bool has_surface_transparent;
- bool has_surface_bssrdf;
+ OSLShaderInfo()
+ : has_surface_emission(false), has_surface_transparent(false), has_surface_bssrdf(false)
+ {
+ }
+
+ OSL::OSLQuery query;
+ bool has_surface_emission;
+ bool has_surface_transparent;
+ bool has_surface_bssrdf;
};
/* Shader Manage */
class OSLShaderManager : public ShaderManager {
-public:
- OSLShaderManager();
- ~OSLShaderManager();
-
- static void free_memory();
-
- void reset(Scene *scene);
-
- bool use_osl() { return true; }
-
- void device_update(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress);
- void device_free(Device *device, DeviceScene *dscene, Scene *scene);
-
- /* osl compile and query */
- static bool osl_compile(const string& inputfile, const string& outputfile);
- static bool osl_query(OSL::OSLQuery& query, const string& filepath);
-
- /* shader file loading, all functions return pointer to hash string if found */
- const char *shader_test_loaded(const string& hash);
- const char *shader_load_bytecode(const string& hash, const string& bytecode);
- const char *shader_load_filepath(string filepath);
- OSLShaderInfo *shader_loaded_info(const string& hash);
-
- /* create OSL node using OSLQuery */
- OSLNode *osl_node(const std::string& filepath,
- const std::string& bytecode_hash = "",
- const std::string& bytecode = "");
-
-protected:
- void texture_system_init();
- void texture_system_free();
-
- void shading_system_init();
- void shading_system_free();
-
- OSL::ShadingSystem *ss;
- OSL::TextureSystem *ts;
- OSLRenderServices *services;
- OSL::ErrorHandler errhandler;
- map<string, OSLShaderInfo> loaded_shaders;
-
- static OSL::TextureSystem *ts_shared;
- static thread_mutex ts_shared_mutex;
- static int ts_shared_users;
-
- static OSL::ShadingSystem *ss_shared;
- static OSLRenderServices *services_shared;
- static thread_mutex ss_shared_mutex;
- static thread_mutex ss_mutex;
- static int ss_shared_users;
+ public:
+ OSLShaderManager();
+ ~OSLShaderManager();
+
+ static void free_memory();
+
+ void reset(Scene *scene);
+
+ bool use_osl()
+ {
+ return true;
+ }
+
+ void device_update(Device *device, DeviceScene *dscene, Scene *scene, Progress &progress);
+ void device_free(Device *device, DeviceScene *dscene, Scene *scene);
+
+ /* osl compile and query */
+ static bool osl_compile(const string &inputfile, const string &outputfile);
+ static bool osl_query(OSL::OSLQuery &query, const string &filepath);
+
+ /* shader file loading, all functions return pointer to hash string if found */
+ const char *shader_test_loaded(const string &hash);
+ const char *shader_load_bytecode(const string &hash, const string &bytecode);
+ const char *shader_load_filepath(string filepath);
+ OSLShaderInfo *shader_loaded_info(const string &hash);
+
+ /* create OSL node using OSLQuery */
+ OSLNode *osl_node(const std::string &filepath,
+ const std::string &bytecode_hash = "",
+ const std::string &bytecode = "");
+
+ protected:
+ void texture_system_init();
+ void texture_system_free();
+
+ void shading_system_init();
+ void shading_system_free();
+
+ OSL::ShadingSystem *ss;
+ OSL::TextureSystem *ts;
+ OSLRenderServices *services;
+ OSL::ErrorHandler errhandler;
+ map<string, OSLShaderInfo> loaded_shaders;
+
+ static OSL::TextureSystem *ts_shared;
+ static thread_mutex ts_shared_mutex;
+ static int ts_shared_users;
+
+ static OSL::ShadingSystem *ss_shared;
+ static OSLRenderServices *services_shared;
+ static thread_mutex ss_shared_mutex;
+ static thread_mutex ss_mutex;
+ static int ss_shared_users;
};
#endif
@@ -123,55 +126,59 @@ protected:
/* Graph Compiler */
class OSLCompiler {
-public:
- OSLCompiler(void *manager, void *shadingsys,
- ImageManager *image_manager,
- LightManager *light_manager);
- void compile(Scene *scene, OSLGlobals *og, Shader *shader);
-
- void add(ShaderNode *node, const char *name, bool isfilepath = false);
-
- void parameter(ShaderNode *node, const char *name);
-
- void parameter(const char *name, float f);
- void parameter_color(const char *name, float3 f);
- void parameter_vector(const char *name, float3 f);
- void parameter_normal(const char *name, float3 f);
- void parameter_point(const char *name, float3 f);
- void parameter(const char *name, int f);
- void parameter(const char *name, const char *s);
- void parameter(const char *name, ustring str);
- void parameter(const char *name, const Transform& tfm);
-
- void parameter_array(const char *name, const float f[], int arraylen);
- void parameter_color_array(const char *name, const array<float3>& f);
-
- void parameter_attribute(const char *name, ustring s);
-
- ShaderType output_type() { return current_type; }
-
- bool background;
- ImageManager *image_manager;
- LightManager *light_manager;
-
-private:
+ public:
+ OSLCompiler(void *manager,
+ void *shadingsys,
+ ImageManager *image_manager,
+ LightManager *light_manager);
+ void compile(Scene *scene, OSLGlobals *og, Shader *shader);
+
+ void add(ShaderNode *node, const char *name, bool isfilepath = false);
+
+ void parameter(ShaderNode *node, const char *name);
+
+ void parameter(const char *name, float f);
+ void parameter_color(const char *name, float3 f);
+ void parameter_vector(const char *name, float3 f);
+ void parameter_normal(const char *name, float3 f);
+ void parameter_point(const char *name, float3 f);
+ void parameter(const char *name, int f);
+ void parameter(const char *name, const char *s);
+ void parameter(const char *name, ustring str);
+ void parameter(const char *name, const Transform &tfm);
+
+ void parameter_array(const char *name, const float f[], int arraylen);
+ void parameter_color_array(const char *name, const array<float3> &f);
+
+ void parameter_attribute(const char *name, ustring s);
+
+ ShaderType output_type()
+ {
+ return current_type;
+ }
+
+ bool background;
+ ImageManager *image_manager;
+ LightManager *light_manager;
+
+ private:
#ifdef WITH_OSL
- string id(ShaderNode *node);
- OSL::ShaderGroupRef compile_type(Shader *shader, ShaderGraph *graph, ShaderType type);
- bool node_skip_input(ShaderNode *node, ShaderInput *input);
- string compatible_name(ShaderNode *node, ShaderInput *input);
- string compatible_name(ShaderNode *node, ShaderOutput *output);
-
- void find_dependencies(ShaderNodeSet& dependencies, ShaderInput *input);
- void generate_nodes(const ShaderNodeSet& nodes);
+ string id(ShaderNode *node);
+ OSL::ShaderGroupRef compile_type(Shader *shader, ShaderGraph *graph, ShaderType type);
+ bool node_skip_input(ShaderNode *node, ShaderInput *input);
+ string compatible_name(ShaderNode *node, ShaderInput *input);
+ string compatible_name(ShaderNode *node, ShaderOutput *output);
+
+ void find_dependencies(ShaderNodeSet &dependencies, ShaderInput *input);
+ void generate_nodes(const ShaderNodeSet &nodes);
#endif
- void *shadingsys;
- void *manager;
- ShaderType current_type;
- Shader *current_shader;
+ void *shadingsys;
+ void *manager;
+ ShaderType current_type;
+ Shader *current_shader;
};
CCL_NAMESPACE_END
-#endif /* __OSL_H__ */
+#endif /* __OSL_H__ */
diff --git a/intern/cycles/render/particles.cpp b/intern/cycles/render/particles.cpp
index 0583556c8a9..8335404b197 100644
--- a/intern/cycles/render/particles.cpp
+++ b/intern/cycles/render/particles.cpp
@@ -39,86 +39,93 @@ ParticleSystem::~ParticleSystem()
void ParticleSystem::tag_update(Scene *scene)
{
- scene->particle_system_manager->need_update = true;
+ scene->particle_system_manager->need_update = true;
}
/* Particle System Manager */
ParticleSystemManager::ParticleSystemManager()
{
- need_update = true;
+ need_update = true;
}
ParticleSystemManager::~ParticleSystemManager()
{
}
-void ParticleSystemManager::device_update_particles(Device *, DeviceScene *dscene, Scene *scene, Progress& progress)
+void ParticleSystemManager::device_update_particles(Device *,
+ DeviceScene *dscene,
+ Scene *scene,
+ Progress &progress)
{
- /* count particles.
- * adds one dummy particle at the beginning to avoid invalid lookups,
- * in case a shader uses particle info without actual particle data. */
- int num_particles = 1;
- for(size_t j = 0; j < scene->particle_systems.size(); j++)
- num_particles += scene->particle_systems[j]->particles.size();
-
- KernelParticle *kparticles = dscene->particles.alloc(num_particles);
-
- /* dummy particle */
- memset(kparticles, 0, sizeof(KernelParticle));
-
- int i = 1;
- for(size_t j = 0; j < scene->particle_systems.size(); j++) {
- ParticleSystem *psys = scene->particle_systems[j];
-
- for(size_t k = 0; k < psys->particles.size(); k++) {
- /* pack in texture */
- Particle& pa = psys->particles[k];
-
- kparticles[i].index = pa.index;
- kparticles[i].age = pa.age;
- kparticles[i].lifetime = pa.lifetime;
- kparticles[i].size = pa.size;
- kparticles[i].rotation = pa.rotation;
- kparticles[i].location = float3_to_float4(pa.location);
- kparticles[i].velocity = float3_to_float4(pa.velocity);
- kparticles[i].angular_velocity = float3_to_float4(pa.angular_velocity);
-
- i++;
-
- if(progress.get_cancel()) return;
- }
- }
-
- dscene->particles.copy_to_device();
+ /* count particles.
+ * adds one dummy particle at the beginning to avoid invalid lookups,
+ * in case a shader uses particle info without actual particle data. */
+ int num_particles = 1;
+ for (size_t j = 0; j < scene->particle_systems.size(); j++)
+ num_particles += scene->particle_systems[j]->particles.size();
+
+ KernelParticle *kparticles = dscene->particles.alloc(num_particles);
+
+ /* dummy particle */
+ memset(kparticles, 0, sizeof(KernelParticle));
+
+ int i = 1;
+ for (size_t j = 0; j < scene->particle_systems.size(); j++) {
+ ParticleSystem *psys = scene->particle_systems[j];
+
+ for (size_t k = 0; k < psys->particles.size(); k++) {
+ /* pack in texture */
+ Particle &pa = psys->particles[k];
+
+ kparticles[i].index = pa.index;
+ kparticles[i].age = pa.age;
+ kparticles[i].lifetime = pa.lifetime;
+ kparticles[i].size = pa.size;
+ kparticles[i].rotation = pa.rotation;
+ kparticles[i].location = float3_to_float4(pa.location);
+ kparticles[i].velocity = float3_to_float4(pa.velocity);
+ kparticles[i].angular_velocity = float3_to_float4(pa.angular_velocity);
+
+ i++;
+
+ if (progress.get_cancel())
+ return;
+ }
+ }
+
+ dscene->particles.copy_to_device();
}
-void ParticleSystemManager::device_update(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress)
+void ParticleSystemManager::device_update(Device *device,
+ DeviceScene *dscene,
+ Scene *scene,
+ Progress &progress)
{
- if(!need_update)
- return;
+ if (!need_update)
+ return;
- VLOG(1) << "Total " << scene->particle_systems.size()
- << " particle systems.";
+ VLOG(1) << "Total " << scene->particle_systems.size() << " particle systems.";
- device_free(device, dscene);
+ device_free(device, dscene);
- progress.set_status("Updating Particle Systems", "Copying Particles to device");
- device_update_particles(device, dscene, scene, progress);
+ progress.set_status("Updating Particle Systems", "Copying Particles to device");
+ device_update_particles(device, dscene, scene, progress);
- if(progress.get_cancel()) return;
+ if (progress.get_cancel())
+ return;
- need_update = false;
+ need_update = false;
}
void ParticleSystemManager::device_free(Device *, DeviceScene *dscene)
{
- dscene->particles.free();
+ dscene->particles.free();
}
void ParticleSystemManager::tag_update(Scene * /*scene*/)
{
- need_update = true;
+ need_update = true;
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/render/particles.h b/intern/cycles/render/particles.h
index 27821907af0..65663c31c37 100644
--- a/intern/cycles/render/particles.h
+++ b/intern/cycles/render/particles.h
@@ -30,42 +30,45 @@ class Scene;
/* Particle System */
struct Particle {
- int index;
- float age;
- float lifetime;
- float3 location;
- float4 rotation;
- float size;
- float3 velocity;
- float3 angular_velocity;
+ int index;
+ float age;
+ float lifetime;
+ float3 location;
+ float4 rotation;
+ float size;
+ float3 velocity;
+ float3 angular_velocity;
};
class ParticleSystem {
-public:
- ParticleSystem();
- ~ParticleSystem();
+ public:
+ ParticleSystem();
+ ~ParticleSystem();
- void tag_update(Scene *scene);
+ void tag_update(Scene *scene);
- array<Particle> particles;
+ array<Particle> particles;
};
/* ParticleSystem Manager */
class ParticleSystemManager {
-public:
- bool need_update;
+ public:
+ bool need_update;
- ParticleSystemManager();
- ~ParticleSystemManager();
+ ParticleSystemManager();
+ ~ParticleSystemManager();
- void device_update_particles(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress);
- void device_update(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress);
- void device_free(Device *device, DeviceScene *dscene);
+ void device_update_particles(Device *device,
+ DeviceScene *dscene,
+ Scene *scene,
+ Progress &progress);
+ void device_update(Device *device, DeviceScene *dscene, Scene *scene, Progress &progress);
+ void device_free(Device *device, DeviceScene *dscene);
- void tag_update(Scene *scene);
+ void tag_update(Scene *scene);
};
CCL_NAMESPACE_END
-#endif /* __PARTICLES_H__ */
+#endif /* __PARTICLES_H__ */
diff --git a/intern/cycles/render/scene.cpp b/intern/cycles/render/scene.cpp
index 1f551f206ef..1e75fa0f99b 100644
--- a/intern/cycles/render/scene.cpp
+++ b/intern/cycles/render/scene.cpp
@@ -41,352 +41,359 @@
CCL_NAMESPACE_BEGIN
DeviceScene::DeviceScene(Device *device)
-: bvh_nodes(device, "__bvh_nodes", MEM_TEXTURE),
- bvh_leaf_nodes(device, "__bvh_leaf_nodes", MEM_TEXTURE),
- object_node(device, "__object_node", MEM_TEXTURE),
- prim_tri_index(device, "__prim_tri_index", MEM_TEXTURE),
- prim_tri_verts(device, "__prim_tri_verts", MEM_TEXTURE),
- prim_type(device, "__prim_type", MEM_TEXTURE),
- prim_visibility(device, "__prim_visibility", MEM_TEXTURE),
- prim_index(device, "__prim_index", MEM_TEXTURE),
- prim_object(device, "__prim_object", MEM_TEXTURE),
- prim_time(device, "__prim_time", MEM_TEXTURE),
- tri_shader(device, "__tri_shader", MEM_TEXTURE),
- tri_vnormal(device, "__tri_vnormal", MEM_TEXTURE),
- tri_vindex(device, "__tri_vindex", MEM_TEXTURE),
- tri_patch(device, "__tri_patch", MEM_TEXTURE),
- tri_patch_uv(device, "__tri_patch_uv", MEM_TEXTURE),
- curves(device, "__curves", MEM_TEXTURE),
- curve_keys(device, "__curve_keys", MEM_TEXTURE),
- patches(device, "__patches", MEM_TEXTURE),
- objects(device, "__objects", MEM_TEXTURE),
- object_motion_pass(device, "__object_motion_pass", MEM_TEXTURE),
- object_motion(device, "__object_motion", MEM_TEXTURE),
- object_flag(device, "__object_flag", MEM_TEXTURE),
- camera_motion(device, "__camera_motion", MEM_TEXTURE),
- attributes_map(device, "__attributes_map", MEM_TEXTURE),
- attributes_float(device, "__attributes_float", MEM_TEXTURE),
- attributes_float2(device, "__attributes_float2", MEM_TEXTURE),
- attributes_float3(device, "__attributes_float3", MEM_TEXTURE),
- attributes_uchar4(device, "__attributes_uchar4", MEM_TEXTURE),
- light_distribution(device, "__light_distribution", MEM_TEXTURE),
- lights(device, "__lights", MEM_TEXTURE),
- light_background_marginal_cdf(device, "__light_background_marginal_cdf", MEM_TEXTURE),
- light_background_conditional_cdf(device, "__light_background_conditional_cdf", MEM_TEXTURE),
- particles(device, "__particles", MEM_TEXTURE),
- svm_nodes(device, "__svm_nodes", MEM_TEXTURE),
- shaders(device, "__shaders", MEM_TEXTURE),
- lookup_table(device, "__lookup_table", MEM_TEXTURE),
- sobol_directions(device, "__sobol_directions", MEM_TEXTURE),
- ies_lights(device, "__ies", MEM_TEXTURE)
+ : bvh_nodes(device, "__bvh_nodes", MEM_TEXTURE),
+ bvh_leaf_nodes(device, "__bvh_leaf_nodes", MEM_TEXTURE),
+ object_node(device, "__object_node", MEM_TEXTURE),
+ prim_tri_index(device, "__prim_tri_index", MEM_TEXTURE),
+ prim_tri_verts(device, "__prim_tri_verts", MEM_TEXTURE),
+ prim_type(device, "__prim_type", MEM_TEXTURE),
+ prim_visibility(device, "__prim_visibility", MEM_TEXTURE),
+ prim_index(device, "__prim_index", MEM_TEXTURE),
+ prim_object(device, "__prim_object", MEM_TEXTURE),
+ prim_time(device, "__prim_time", MEM_TEXTURE),
+ tri_shader(device, "__tri_shader", MEM_TEXTURE),
+ tri_vnormal(device, "__tri_vnormal", MEM_TEXTURE),
+ tri_vindex(device, "__tri_vindex", MEM_TEXTURE),
+ tri_patch(device, "__tri_patch", MEM_TEXTURE),
+ tri_patch_uv(device, "__tri_patch_uv", MEM_TEXTURE),
+ curves(device, "__curves", MEM_TEXTURE),
+ curve_keys(device, "__curve_keys", MEM_TEXTURE),
+ patches(device, "__patches", MEM_TEXTURE),
+ objects(device, "__objects", MEM_TEXTURE),
+ object_motion_pass(device, "__object_motion_pass", MEM_TEXTURE),
+ object_motion(device, "__object_motion", MEM_TEXTURE),
+ object_flag(device, "__object_flag", MEM_TEXTURE),
+ camera_motion(device, "__camera_motion", MEM_TEXTURE),
+ attributes_map(device, "__attributes_map", MEM_TEXTURE),
+ attributes_float(device, "__attributes_float", MEM_TEXTURE),
+ attributes_float2(device, "__attributes_float2", MEM_TEXTURE),
+ attributes_float3(device, "__attributes_float3", MEM_TEXTURE),
+ attributes_uchar4(device, "__attributes_uchar4", MEM_TEXTURE),
+ light_distribution(device, "__light_distribution", MEM_TEXTURE),
+ lights(device, "__lights", MEM_TEXTURE),
+ light_background_marginal_cdf(device, "__light_background_marginal_cdf", MEM_TEXTURE),
+ light_background_conditional_cdf(device, "__light_background_conditional_cdf", MEM_TEXTURE),
+ particles(device, "__particles", MEM_TEXTURE),
+ svm_nodes(device, "__svm_nodes", MEM_TEXTURE),
+ shaders(device, "__shaders", MEM_TEXTURE),
+ lookup_table(device, "__lookup_table", MEM_TEXTURE),
+ sobol_directions(device, "__sobol_directions", MEM_TEXTURE),
+ ies_lights(device, "__ies", MEM_TEXTURE)
{
- memset((void*)&data, 0, sizeof(data));
+ memset((void *)&data, 0, sizeof(data));
}
-Scene::Scene(const SceneParams& params_, Device *device)
- : name("Scene"),
- device(device),
- dscene(device),
- params(params_)
+Scene::Scene(const SceneParams &params_, Device *device)
+ : name("Scene"), device(device), dscene(device), params(params_)
{
- memset((void *)&dscene.data, 0, sizeof(dscene.data));
-
- camera = new Camera();
- dicing_camera = new Camera();
- lookup_tables = new LookupTables();
- film = new Film();
- background = new Background();
- light_manager = new LightManager();
- mesh_manager = new MeshManager();
- object_manager = new ObjectManager();
- integrator = new Integrator();
- image_manager = new ImageManager(device->info);
- particle_system_manager = new ParticleSystemManager();
- curve_system_manager = new CurveSystemManager();
- bake_manager = new BakeManager();
-
- /* OSL only works on the CPU */
- if(device->info.has_osl)
- shader_manager = ShaderManager::create(this, params.shadingsystem);
- else
- shader_manager = ShaderManager::create(this, SHADINGSYSTEM_SVM);
+ memset((void *)&dscene.data, 0, sizeof(dscene.data));
+
+ camera = new Camera();
+ dicing_camera = new Camera();
+ lookup_tables = new LookupTables();
+ film = new Film();
+ background = new Background();
+ light_manager = new LightManager();
+ mesh_manager = new MeshManager();
+ object_manager = new ObjectManager();
+ integrator = new Integrator();
+ image_manager = new ImageManager(device->info);
+ particle_system_manager = new ParticleSystemManager();
+ curve_system_manager = new CurveSystemManager();
+ bake_manager = new BakeManager();
+
+ /* OSL only works on the CPU */
+ if (device->info.has_osl)
+ shader_manager = ShaderManager::create(this, params.shadingsystem);
+ else
+ shader_manager = ShaderManager::create(this, SHADINGSYSTEM_SVM);
}
Scene::~Scene()
{
- free_memory(true);
+ free_memory(true);
}
void Scene::free_memory(bool final)
{
- foreach(Shader *s, shaders)
- delete s;
- foreach(Mesh *m, meshes)
- delete m;
- foreach(Object *o, objects)
- delete o;
- foreach(Light *l, lights)
- delete l;
- foreach(ParticleSystem *p, particle_systems)
- delete p;
-
- shaders.clear();
- meshes.clear();
- objects.clear();
- lights.clear();
- particle_systems.clear();
-
- if(device) {
- camera->device_free(device, &dscene, this);
- film->device_free(device, &dscene, this);
- background->device_free(device, &dscene);
- integrator->device_free(device, &dscene);
-
- object_manager->device_free(device, &dscene);
- mesh_manager->device_free(device, &dscene);
- shader_manager->device_free(device, &dscene, this);
- light_manager->device_free(device, &dscene);
-
- particle_system_manager->device_free(device, &dscene);
- curve_system_manager->device_free(device, &dscene);
-
- bake_manager->device_free(device, &dscene);
-
- if(!params.persistent_data || final)
- image_manager->device_free(device);
- else
- image_manager->device_free_builtin(device);
-
- lookup_tables->device_free(device, &dscene);
- }
-
- if(final) {
- delete lookup_tables;
- delete camera;
- delete dicing_camera;
- delete film;
- delete background;
- delete integrator;
- delete object_manager;
- delete mesh_manager;
- delete shader_manager;
- delete light_manager;
- delete particle_system_manager;
- delete curve_system_manager;
- delete image_manager;
- delete bake_manager;
- }
+ foreach (Shader *s, shaders)
+ delete s;
+ foreach (Mesh *m, meshes)
+ delete m;
+ foreach (Object *o, objects)
+ delete o;
+ foreach (Light *l, lights)
+ delete l;
+ foreach (ParticleSystem *p, particle_systems)
+ delete p;
+
+ shaders.clear();
+ meshes.clear();
+ objects.clear();
+ lights.clear();
+ particle_systems.clear();
+
+ if (device) {
+ camera->device_free(device, &dscene, this);
+ film->device_free(device, &dscene, this);
+ background->device_free(device, &dscene);
+ integrator->device_free(device, &dscene);
+
+ object_manager->device_free(device, &dscene);
+ mesh_manager->device_free(device, &dscene);
+ shader_manager->device_free(device, &dscene, this);
+ light_manager->device_free(device, &dscene);
+
+ particle_system_manager->device_free(device, &dscene);
+ curve_system_manager->device_free(device, &dscene);
+
+ bake_manager->device_free(device, &dscene);
+
+ if (!params.persistent_data || final)
+ image_manager->device_free(device);
+ else
+ image_manager->device_free_builtin(device);
+
+ lookup_tables->device_free(device, &dscene);
+ }
+
+ if (final) {
+ delete lookup_tables;
+ delete camera;
+ delete dicing_camera;
+ delete film;
+ delete background;
+ delete integrator;
+ delete object_manager;
+ delete mesh_manager;
+ delete shader_manager;
+ delete light_manager;
+ delete particle_system_manager;
+ delete curve_system_manager;
+ delete image_manager;
+ delete bake_manager;
+ }
}
-void Scene::device_update(Device *device_, Progress& progress)
+void Scene::device_update(Device *device_, Progress &progress)
{
- if(!device)
- device = device_;
+ if (!device)
+ device = device_;
- bool print_stats = need_data_update();
+ bool print_stats = need_data_update();
- /* The order of updates is important, because there's dependencies between
- * the different managers, using data computed by previous managers.
- *
- * - Image manager uploads images used by shaders.
- * - Camera may be used for adaptive subdivision.
- * - Displacement shader must have all shader data available.
- * - Light manager needs lookup tables and final mesh data to compute emission CDF.
- * - Film needs light manager to run for use_light_visibility
- * - Lookup tables are done a second time to handle film tables
- */
+ /* The order of updates is important, because there's dependencies between
+ * the different managers, using data computed by previous managers.
+ *
+ * - Image manager uploads images used by shaders.
+ * - Camera may be used for adaptive subdivision.
+ * - Displacement shader must have all shader data available.
+ * - Light manager needs lookup tables and final mesh data to compute emission CDF.
+ * - Film needs light manager to run for use_light_visibility
+ * - Lookup tables are done a second time to handle film tables
+ */
- progress.set_status("Updating Shaders");
- shader_manager->device_update(device, &dscene, this, progress);
+ progress.set_status("Updating Shaders");
+ shader_manager->device_update(device, &dscene, this, progress);
- if(progress.get_cancel() || device->have_error()) return;
+ if (progress.get_cancel() || device->have_error())
+ return;
- progress.set_status("Updating Background");
- background->device_update(device, &dscene, this);
+ progress.set_status("Updating Background");
+ background->device_update(device, &dscene, this);
- if(progress.get_cancel() || device->have_error()) return;
+ if (progress.get_cancel() || device->have_error())
+ return;
- progress.set_status("Updating Camera");
- camera->device_update(device, &dscene, this);
+ progress.set_status("Updating Camera");
+ camera->device_update(device, &dscene, this);
- if(progress.get_cancel() || device->have_error()) return;
+ if (progress.get_cancel() || device->have_error())
+ return;
- mesh_manager->device_update_preprocess(device, this, progress);
+ mesh_manager->device_update_preprocess(device, this, progress);
- if(progress.get_cancel() || device->have_error()) return;
+ if (progress.get_cancel() || device->have_error())
+ return;
- progress.set_status("Updating Objects");
- object_manager->device_update(device, &dscene, this, progress);
+ progress.set_status("Updating Objects");
+ object_manager->device_update(device, &dscene, this, progress);
- if(progress.get_cancel() || device->have_error()) return;
+ if (progress.get_cancel() || device->have_error())
+ return;
- progress.set_status("Updating Hair Systems");
- curve_system_manager->device_update(device, &dscene, this, progress);
+ progress.set_status("Updating Hair Systems");
+ curve_system_manager->device_update(device, &dscene, this, progress);
- if(progress.get_cancel() || device->have_error()) return;
+ if (progress.get_cancel() || device->have_error())
+ return;
- progress.set_status("Updating Particle Systems");
- particle_system_manager->device_update(device, &dscene, this, progress);
+ progress.set_status("Updating Particle Systems");
+ particle_system_manager->device_update(device, &dscene, this, progress);
- if(progress.get_cancel() || device->have_error()) return;
+ if (progress.get_cancel() || device->have_error())
+ return;
- progress.set_status("Updating Meshes");
- mesh_manager->device_update(device, &dscene, this, progress);
+ progress.set_status("Updating Meshes");
+ mesh_manager->device_update(device, &dscene, this, progress);
- if(progress.get_cancel() || device->have_error()) return;
+ if (progress.get_cancel() || device->have_error())
+ return;
- progress.set_status("Updating Objects Flags");
- object_manager->device_update_flags(device, &dscene, this, progress);
+ progress.set_status("Updating Objects Flags");
+ object_manager->device_update_flags(device, &dscene, this, progress);
- if(progress.get_cancel() || device->have_error()) return;
+ if (progress.get_cancel() || device->have_error())
+ return;
- progress.set_status("Updating Images");
- image_manager->device_update(device, this, progress);
+ progress.set_status("Updating Images");
+ image_manager->device_update(device, this, progress);
- if(progress.get_cancel() || device->have_error()) return;
+ if (progress.get_cancel() || device->have_error())
+ return;
- progress.set_status("Updating Camera Volume");
- camera->device_update_volume(device, &dscene, this);
+ progress.set_status("Updating Camera Volume");
+ camera->device_update_volume(device, &dscene, this);
- if(progress.get_cancel() || device->have_error()) return;
+ if (progress.get_cancel() || device->have_error())
+ return;
- progress.set_status("Updating Lookup Tables");
- lookup_tables->device_update(device, &dscene);
+ progress.set_status("Updating Lookup Tables");
+ lookup_tables->device_update(device, &dscene);
- if(progress.get_cancel() || device->have_error()) return;
+ if (progress.get_cancel() || device->have_error())
+ return;
- progress.set_status("Updating Lights");
- light_manager->device_update(device, &dscene, this, progress);
+ progress.set_status("Updating Lights");
+ light_manager->device_update(device, &dscene, this, progress);
- if(progress.get_cancel() || device->have_error()) return;
+ if (progress.get_cancel() || device->have_error())
+ return;
- progress.set_status("Updating Integrator");
- integrator->device_update(device, &dscene, this);
+ progress.set_status("Updating Integrator");
+ integrator->device_update(device, &dscene, this);
- if(progress.get_cancel() || device->have_error()) return;
+ if (progress.get_cancel() || device->have_error())
+ return;
- progress.set_status("Updating Film");
- film->device_update(device, &dscene, this);
+ progress.set_status("Updating Film");
+ film->device_update(device, &dscene, this);
- if(progress.get_cancel() || device->have_error()) return;
+ if (progress.get_cancel() || device->have_error())
+ return;
- progress.set_status("Updating Lookup Tables");
- lookup_tables->device_update(device, &dscene);
+ progress.set_status("Updating Lookup Tables");
+ lookup_tables->device_update(device, &dscene);
- if(progress.get_cancel() || device->have_error()) return;
+ if (progress.get_cancel() || device->have_error())
+ return;
- progress.set_status("Updating Baking");
- bake_manager->device_update(device, &dscene, this, progress);
+ progress.set_status("Updating Baking");
+ bake_manager->device_update(device, &dscene, this, progress);
- if(progress.get_cancel() || device->have_error()) return;
+ if (progress.get_cancel() || device->have_error())
+ return;
- if(device->have_error() == false) {
- progress.set_status("Updating Device", "Writing constant memory");
- device->const_copy_to("__data", &dscene.data, sizeof(dscene.data));
- }
+ if (device->have_error() == false) {
+ progress.set_status("Updating Device", "Writing constant memory");
+ device->const_copy_to("__data", &dscene.data, sizeof(dscene.data));
+ }
- if(print_stats) {
- size_t mem_used = util_guarded_get_mem_used();
- size_t mem_peak = util_guarded_get_mem_peak();
+ if (print_stats) {
+ size_t mem_used = util_guarded_get_mem_used();
+ size_t mem_peak = util_guarded_get_mem_peak();
- VLOG(1) << "System memory statistics after full device sync:\n"
- << " Usage: " << string_human_readable_number(mem_used)
- << " (" << string_human_readable_size(mem_used) << ")\n"
- << " Peak: " << string_human_readable_number(mem_peak)
- << " (" << string_human_readable_size(mem_peak) << ")";
- }
+ VLOG(1) << "System memory statistics after full device sync:\n"
+ << " Usage: " << string_human_readable_number(mem_used) << " ("
+ << string_human_readable_size(mem_used) << ")\n"
+ << " Peak: " << string_human_readable_number(mem_peak) << " ("
+ << string_human_readable_size(mem_peak) << ")";
+ }
}
Scene::MotionType Scene::need_motion()
{
- if(integrator->motion_blur)
- return MOTION_BLUR;
- else if(Pass::contains(film->passes, PASS_MOTION))
- return MOTION_PASS;
- else
- return MOTION_NONE;
+ if (integrator->motion_blur)
+ return MOTION_BLUR;
+ else if (Pass::contains(film->passes, PASS_MOTION))
+ return MOTION_PASS;
+ else
+ return MOTION_NONE;
}
float Scene::motion_shutter_time()
{
- if(need_motion() == Scene::MOTION_PASS)
- return 2.0f;
- else
- return camera->shuttertime;
+ if (need_motion() == Scene::MOTION_PASS)
+ return 2.0f;
+ else
+ return camera->shuttertime;
}
bool Scene::need_global_attribute(AttributeStandard std)
{
- if(std == ATTR_STD_UV)
- return Pass::contains(film->passes, PASS_UV);
- else if(std == ATTR_STD_MOTION_VERTEX_POSITION)
- return need_motion() != MOTION_NONE;
- else if(std == ATTR_STD_MOTION_VERTEX_NORMAL)
- return need_motion() == MOTION_BLUR;
-
- return false;
+ if (std == ATTR_STD_UV)
+ return Pass::contains(film->passes, PASS_UV);
+ else if (std == ATTR_STD_MOTION_VERTEX_POSITION)
+ return need_motion() != MOTION_NONE;
+ else if (std == ATTR_STD_MOTION_VERTEX_NORMAL)
+ return need_motion() == MOTION_BLUR;
+
+ return false;
}
-void Scene::need_global_attributes(AttributeRequestSet& attributes)
+void Scene::need_global_attributes(AttributeRequestSet &attributes)
{
- for(int std = ATTR_STD_NONE; std < ATTR_STD_NUM; std++)
- if(need_global_attribute((AttributeStandard)std))
- attributes.add((AttributeStandard)std);
+ for (int std = ATTR_STD_NONE; std < ATTR_STD_NUM; std++)
+ if (need_global_attribute((AttributeStandard)std))
+ attributes.add((AttributeStandard)std);
}
bool Scene::need_update()
{
- return (need_reset() || film->need_update);
+ return (need_reset() || film->need_update);
}
bool Scene::need_data_update()
{
- return (background->need_update
- || image_manager->need_update
- || object_manager->need_update
- || mesh_manager->need_update
- || light_manager->need_update
- || lookup_tables->need_update
- || integrator->need_update
- || shader_manager->need_update
- || particle_system_manager->need_update
- || curve_system_manager->need_update
- || bake_manager->need_update
- || film->need_update);
+ return (background->need_update || image_manager->need_update || object_manager->need_update ||
+ mesh_manager->need_update || light_manager->need_update || lookup_tables->need_update ||
+ integrator->need_update || shader_manager->need_update ||
+ particle_system_manager->need_update || curve_system_manager->need_update ||
+ bake_manager->need_update || film->need_update);
}
bool Scene::need_reset()
{
- return need_data_update() || camera->need_update;
+ return need_data_update() || camera->need_update;
}
void Scene::reset()
{
- shader_manager->reset(this);
- shader_manager->add_default(this);
-
- /* ensure all objects are updated */
- camera->tag_update();
- dicing_camera->tag_update();
- film->tag_update(this);
- background->tag_update(this);
- integrator->tag_update(this);
- object_manager->tag_update(this);
- mesh_manager->tag_update(this);
- light_manager->tag_update(this);
- particle_system_manager->tag_update(this);
- curve_system_manager->tag_update(this);
+ shader_manager->reset(this);
+ shader_manager->add_default(this);
+
+ /* ensure all objects are updated */
+ camera->tag_update();
+ dicing_camera->tag_update();
+ film->tag_update(this);
+ background->tag_update(this);
+ integrator->tag_update(this);
+ object_manager->tag_update(this);
+ mesh_manager->tag_update(this);
+ light_manager->tag_update(this);
+ particle_system_manager->tag_update(this);
+ curve_system_manager->tag_update(this);
}
void Scene::device_free()
{
- free_memory(false);
+ free_memory(false);
}
void Scene::collect_statistics(RenderStats *stats)
{
- mesh_manager->collect_statistics(this, stats);
- image_manager->collect_statistics(stats);
+ mesh_manager->collect_statistics(this, stats);
+ image_manager->collect_statistics(stats);
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/render/scene.h b/intern/cycles/render/scene.h
index e43800fe5c4..45997bccf5d 100644
--- a/intern/cycles/render/scene.h
+++ b/intern/cycles/render/scene.h
@@ -61,215 +61,215 @@ class RenderStats;
/* Scene Device Data */
class DeviceScene {
-public:
- /* BVH */
- device_vector<int4> bvh_nodes;
- device_vector<int4> bvh_leaf_nodes;
- device_vector<int> object_node;
- device_vector<uint> prim_tri_index;
- device_vector<float4> prim_tri_verts;
- device_vector<int> prim_type;
- device_vector<uint> prim_visibility;
- device_vector<int> prim_index;
- device_vector<int> prim_object;
- device_vector<float2> prim_time;
-
- /* mesh */
- device_vector<uint> tri_shader;
- device_vector<float4> tri_vnormal;
- device_vector<uint4> tri_vindex;
- device_vector<uint> tri_patch;
- device_vector<float2> tri_patch_uv;
-
- device_vector<float4> curves;
- device_vector<float4> curve_keys;
-
- device_vector<uint> patches;
-
- /* objects */
- device_vector<KernelObject> objects;
- device_vector<Transform> object_motion_pass;
- device_vector<DecomposedTransform> object_motion;
- device_vector<uint> object_flag;
-
- /* cameras */
- device_vector<DecomposedTransform> camera_motion;
-
- /* attributes */
- device_vector<uint4> attributes_map;
- device_vector<float> attributes_float;
- device_vector<float2> attributes_float2;
- device_vector<float4> attributes_float3;
- device_vector<uchar4> attributes_uchar4;
-
- /* lights */
- device_vector<KernelLightDistribution> light_distribution;
- device_vector<KernelLight> lights;
- device_vector<float2> light_background_marginal_cdf;
- device_vector<float2> light_background_conditional_cdf;
-
- /* particles */
- device_vector<KernelParticle> particles;
-
- /* shaders */
- device_vector<int4> svm_nodes;
- device_vector<KernelShader> shaders;
-
- /* lookup tables */
- device_vector<float> lookup_table;
-
- /* integrator */
- device_vector<uint> sobol_directions;
-
- /* ies lights */
- device_vector<float> ies_lights;
-
- KernelData data;
-
- DeviceScene(Device *device);
+ public:
+ /* BVH */
+ device_vector<int4> bvh_nodes;
+ device_vector<int4> bvh_leaf_nodes;
+ device_vector<int> object_node;
+ device_vector<uint> prim_tri_index;
+ device_vector<float4> prim_tri_verts;
+ device_vector<int> prim_type;
+ device_vector<uint> prim_visibility;
+ device_vector<int> prim_index;
+ device_vector<int> prim_object;
+ device_vector<float2> prim_time;
+
+ /* mesh */
+ device_vector<uint> tri_shader;
+ device_vector<float4> tri_vnormal;
+ device_vector<uint4> tri_vindex;
+ device_vector<uint> tri_patch;
+ device_vector<float2> tri_patch_uv;
+
+ device_vector<float4> curves;
+ device_vector<float4> curve_keys;
+
+ device_vector<uint> patches;
+
+ /* objects */
+ device_vector<KernelObject> objects;
+ device_vector<Transform> object_motion_pass;
+ device_vector<DecomposedTransform> object_motion;
+ device_vector<uint> object_flag;
+
+ /* cameras */
+ device_vector<DecomposedTransform> camera_motion;
+
+ /* attributes */
+ device_vector<uint4> attributes_map;
+ device_vector<float> attributes_float;
+ device_vector<float2> attributes_float2;
+ device_vector<float4> attributes_float3;
+ device_vector<uchar4> attributes_uchar4;
+
+ /* lights */
+ device_vector<KernelLightDistribution> light_distribution;
+ device_vector<KernelLight> lights;
+ device_vector<float2> light_background_marginal_cdf;
+ device_vector<float2> light_background_conditional_cdf;
+
+ /* particles */
+ device_vector<KernelParticle> particles;
+
+ /* shaders */
+ device_vector<int4> svm_nodes;
+ device_vector<KernelShader> shaders;
+
+ /* lookup tables */
+ device_vector<float> lookup_table;
+
+ /* integrator */
+ device_vector<uint> sobol_directions;
+
+ /* ies lights */
+ device_vector<float> ies_lights;
+
+ KernelData data;
+
+ DeviceScene(Device *device);
};
/* Scene Parameters */
class SceneParams {
-public:
- /* Type of BVH, in terms whether it is supported dynamic updates of meshes
- * or whether modifying geometry requires full BVH rebuild.
- */
- enum BVHType {
- /* BVH supports dynamic updates of geometry.
- *
- * Faster for updating BVH tree when doing modifications in viewport,
- * but slower for rendering.
- */
- BVH_DYNAMIC = 0,
- /* BVH tree is calculated for specific scene, updates in geometry
- * requires full tree rebuild.
- *
- * Slower to update BVH tree when modifying objects in viewport, also
- * slower to build final BVH tree but gives best possible render speed.
- */
- BVH_STATIC = 1,
-
- BVH_NUM_TYPES,
- };
-
- ShadingSystem shadingsystem;
-
- /* Requested BVH layout.
- *
- * If it's not supported by the device, the widest one from supported ones
- * will be used, but BVH wider than this one will never be used.
- */
- BVHLayout bvh_layout;
-
- BVHType bvh_type;
- bool use_bvh_spatial_split;
- bool use_bvh_unaligned_nodes;
- int num_bvh_time_steps;
- bool persistent_data;
- int texture_limit;
-
- SceneParams()
- {
- shadingsystem = SHADINGSYSTEM_SVM;
- bvh_layout = BVH_LAYOUT_BVH2;
- bvh_type = BVH_DYNAMIC;
- use_bvh_spatial_split = false;
- use_bvh_unaligned_nodes = true;
- num_bvh_time_steps = 0;
- persistent_data = false;
- texture_limit = 0;
- }
-
- bool modified(const SceneParams& params)
- { return !(shadingsystem == params.shadingsystem
- && bvh_layout == params.bvh_layout
- && bvh_type == params.bvh_type
- && use_bvh_spatial_split == params.use_bvh_spatial_split
- && use_bvh_unaligned_nodes == params.use_bvh_unaligned_nodes
- && num_bvh_time_steps == params.num_bvh_time_steps
- && persistent_data == params.persistent_data
- && texture_limit == params.texture_limit); }
+ public:
+ /* Type of BVH, in terms whether it is supported dynamic updates of meshes
+ * or whether modifying geometry requires full BVH rebuild.
+ */
+ enum BVHType {
+ /* BVH supports dynamic updates of geometry.
+ *
+ * Faster for updating BVH tree when doing modifications in viewport,
+ * but slower for rendering.
+ */
+ BVH_DYNAMIC = 0,
+ /* BVH tree is calculated for specific scene, updates in geometry
+ * requires full tree rebuild.
+ *
+ * Slower to update BVH tree when modifying objects in viewport, also
+ * slower to build final BVH tree but gives best possible render speed.
+ */
+ BVH_STATIC = 1,
+
+ BVH_NUM_TYPES,
+ };
+
+ ShadingSystem shadingsystem;
+
+ /* Requested BVH layout.
+ *
+ * If it's not supported by the device, the widest one from supported ones
+ * will be used, but BVH wider than this one will never be used.
+ */
+ BVHLayout bvh_layout;
+
+ BVHType bvh_type;
+ bool use_bvh_spatial_split;
+ bool use_bvh_unaligned_nodes;
+ int num_bvh_time_steps;
+ bool persistent_data;
+ int texture_limit;
+
+ SceneParams()
+ {
+ shadingsystem = SHADINGSYSTEM_SVM;
+ bvh_layout = BVH_LAYOUT_BVH2;
+ bvh_type = BVH_DYNAMIC;
+ use_bvh_spatial_split = false;
+ use_bvh_unaligned_nodes = true;
+ num_bvh_time_steps = 0;
+ persistent_data = false;
+ texture_limit = 0;
+ }
+
+ bool modified(const SceneParams &params)
+ {
+ return !(shadingsystem == params.shadingsystem && bvh_layout == params.bvh_layout &&
+ bvh_type == params.bvh_type &&
+ use_bvh_spatial_split == params.use_bvh_spatial_split &&
+ use_bvh_unaligned_nodes == params.use_bvh_unaligned_nodes &&
+ num_bvh_time_steps == params.num_bvh_time_steps &&
+ persistent_data == params.persistent_data && texture_limit == params.texture_limit);
+ }
};
/* Scene */
class Scene {
-public:
- /* Optional name. Is used for logging and reporting. */
- string name;
-
- /* data */
- Camera *camera;
- Camera *dicing_camera;
- LookupTables *lookup_tables;
- Film *film;
- Background *background;
- Integrator *integrator;
-
- /* data lists */
- vector<Object*> objects;
- vector<Mesh*> meshes;
- vector<Shader*> shaders;
- vector<Light*> lights;
- vector<ParticleSystem*> particle_systems;
-
- /* data managers */
- ImageManager *image_manager;
- LightManager *light_manager;
- ShaderManager *shader_manager;
- MeshManager *mesh_manager;
- ObjectManager *object_manager;
- ParticleSystemManager *particle_system_manager;
- CurveSystemManager *curve_system_manager;
- BakeManager *bake_manager;
-
- /* default shaders */
- Shader *default_surface;
- Shader *default_light;
- Shader *default_background;
- Shader *default_empty;
-
- /* device */
- Device *device;
- DeviceScene dscene;
-
- /* parameters */
- SceneParams params;
-
- /* mutex must be locked manually by callers */
- thread_mutex mutex;
-
- Scene(const SceneParams& params, Device *device);
- ~Scene();
-
- void device_update(Device *device, Progress& progress);
-
- bool need_global_attribute(AttributeStandard std);
- void need_global_attributes(AttributeRequestSet& attributes);
-
- enum MotionType { MOTION_NONE = 0, MOTION_PASS, MOTION_BLUR };
- MotionType need_motion();
- float motion_shutter_time();
-
- bool need_update();
- bool need_reset();
-
- void reset();
- void device_free();
-
- void collect_statistics(RenderStats *stats);
-
-protected:
- /* Check if some heavy data worth logging was updated.
- * Mainly used to suppress extra annoying logging.
- */
- bool need_data_update();
-
- void free_memory(bool final);
+ public:
+ /* Optional name. Is used for logging and reporting. */
+ string name;
+
+ /* data */
+ Camera *camera;
+ Camera *dicing_camera;
+ LookupTables *lookup_tables;
+ Film *film;
+ Background *background;
+ Integrator *integrator;
+
+ /* data lists */
+ vector<Object *> objects;
+ vector<Mesh *> meshes;
+ vector<Shader *> shaders;
+ vector<Light *> lights;
+ vector<ParticleSystem *> particle_systems;
+
+ /* data managers */
+ ImageManager *image_manager;
+ LightManager *light_manager;
+ ShaderManager *shader_manager;
+ MeshManager *mesh_manager;
+ ObjectManager *object_manager;
+ ParticleSystemManager *particle_system_manager;
+ CurveSystemManager *curve_system_manager;
+ BakeManager *bake_manager;
+
+ /* default shaders */
+ Shader *default_surface;
+ Shader *default_light;
+ Shader *default_background;
+ Shader *default_empty;
+
+ /* device */
+ Device *device;
+ DeviceScene dscene;
+
+ /* parameters */
+ SceneParams params;
+
+ /* mutex must be locked manually by callers */
+ thread_mutex mutex;
+
+ Scene(const SceneParams &params, Device *device);
+ ~Scene();
+
+ void device_update(Device *device, Progress &progress);
+
+ bool need_global_attribute(AttributeStandard std);
+ void need_global_attributes(AttributeRequestSet &attributes);
+
+ enum MotionType { MOTION_NONE = 0, MOTION_PASS, MOTION_BLUR };
+ MotionType need_motion();
+ float motion_shutter_time();
+
+ bool need_update();
+ bool need_reset();
+
+ void reset();
+ void device_free();
+
+ void collect_statistics(RenderStats *stats);
+
+ protected:
+ /* Check if some heavy data worth logging was updated.
+ * Mainly used to suppress extra annoying logging.
+ */
+ bool need_data_update();
+
+ void free_memory(bool final);
};
CCL_NAMESPACE_END
-#endif /* __SCENE_H__ */
+#endif /* __SCENE_H__ */
diff --git a/intern/cycles/render/session.cpp b/intern/cycles/render/session.cpp
index e88d960d9d2..29eb779a7d6 100644
--- a/intern/cycles/render/session.cpp
+++ b/intern/cycles/render/session.cpp
@@ -43,1121 +43,1122 @@ CCL_NAMESPACE_BEGIN
* progressive refine and viewport rendering does requires tiles to
* always be allocated for the same device
*/
-Session::Session(const SessionParams& params_)
-: params(params_),
- tile_manager(params.progressive, params.samples, params.tile_size, params.start_resolution,
- params.background == false || params.progressive_refine, params.background, params.tile_order,
- max(params.device.multi_devices.size(), 1), params.pixel_size),
- stats(),
- profiler()
+Session::Session(const SessionParams &params_)
+ : params(params_),
+ tile_manager(params.progressive,
+ params.samples,
+ params.tile_size,
+ params.start_resolution,
+ params.background == false || params.progressive_refine,
+ params.background,
+ params.tile_order,
+ max(params.device.multi_devices.size(), 1),
+ params.pixel_size),
+ stats(),
+ profiler()
{
- device_use_gl = ((params.device.type != DEVICE_CPU) && !params.background);
+ device_use_gl = ((params.device.type != DEVICE_CPU) && !params.background);
- TaskScheduler::init(params.threads);
+ TaskScheduler::init(params.threads);
- device = Device::create(params.device, stats, profiler, params.background);
+ device = Device::create(params.device, stats, profiler, params.background);
- if(params.background && !params.write_render_cb) {
- buffers = NULL;
- display = NULL;
- }
- else {
- buffers = new RenderBuffers(device);
- display = new DisplayBuffer(device, params.display_buffer_linear);
- }
+ if (params.background && !params.write_render_cb) {
+ buffers = NULL;
+ display = NULL;
+ }
+ else {
+ buffers = new RenderBuffers(device);
+ display = new DisplayBuffer(device, params.display_buffer_linear);
+ }
- session_thread = NULL;
- scene = NULL;
+ session_thread = NULL;
+ scene = NULL;
- reset_time = 0.0;
- last_update_time = 0.0;
+ reset_time = 0.0;
+ last_update_time = 0.0;
- delayed_reset.do_reset = false;
- delayed_reset.samples = 0;
+ delayed_reset.do_reset = false;
+ delayed_reset.samples = 0;
- display_outdated = false;
- gpu_draw_ready = false;
- gpu_need_tonemap = false;
- pause = false;
- kernels_loaded = false;
+ display_outdated = false;
+ gpu_draw_ready = false;
+ gpu_need_tonemap = false;
+ pause = false;
+ kernels_loaded = false;
- /* TODO(sergey): Check if it's indeed optimal value for the split kernel. */
- max_closure_global = 1;
+ /* TODO(sergey): Check if it's indeed optimal value for the split kernel. */
+ max_closure_global = 1;
}
Session::~Session()
{
- if(session_thread) {
- /* wait for session thread to end */
- progress.set_cancel("Exiting");
+ if (session_thread) {
+ /* wait for session thread to end */
+ progress.set_cancel("Exiting");
- gpu_need_tonemap = false;
- gpu_need_tonemap_cond.notify_all();
+ gpu_need_tonemap = false;
+ gpu_need_tonemap_cond.notify_all();
- {
- thread_scoped_lock pause_lock(pause_mutex);
- pause = false;
- }
- pause_cond.notify_all();
+ {
+ thread_scoped_lock pause_lock(pause_mutex);
+ pause = false;
+ }
+ pause_cond.notify_all();
- wait();
- }
+ wait();
+ }
- if(params.write_render_cb) {
- /* tonemap and write out image if requested */
- delete display;
+ if (params.write_render_cb) {
+ /* tonemap and write out image if requested */
+ delete display;
- display = new DisplayBuffer(device, false);
- display->reset(buffers->params);
- tonemap(params.samples);
+ display = new DisplayBuffer(device, false);
+ display->reset(buffers->params);
+ tonemap(params.samples);
- int w = display->draw_width;
- int h = display->draw_height;
- uchar4 *pixels = display->rgba_byte.copy_from_device(0, w, h);
- params.write_render_cb((uchar*)pixels, w, h, 4);
- }
+ int w = display->draw_width;
+ int h = display->draw_height;
+ uchar4 *pixels = display->rgba_byte.copy_from_device(0, w, h);
+ params.write_render_cb((uchar *)pixels, w, h, 4);
+ }
- /* clean up */
- tile_manager.device_free();
+ /* clean up */
+ tile_manager.device_free();
- delete buffers;
- delete display;
- delete scene;
- delete device;
+ delete buffers;
+ delete display;
+ delete scene;
+ delete device;
- TaskScheduler::exit();
+ TaskScheduler::exit();
}
void Session::start()
{
- if (!session_thread) {
- session_thread = new thread(function_bind(&Session::run, this));
- }
+ if (!session_thread) {
+ session_thread = new thread(function_bind(&Session::run, this));
+ }
}
bool Session::ready_to_reset()
{
- double dt = time_dt() - reset_time;
+ double dt = time_dt() - reset_time;
- if(!display_outdated)
- return (dt > params.reset_timeout);
- else
- return (dt > params.cancel_timeout);
+ if (!display_outdated)
+ return (dt > params.reset_timeout);
+ else
+ return (dt > params.cancel_timeout);
}
/* GPU Session */
-void Session::reset_gpu(BufferParams& buffer_params, int samples)
+void Session::reset_gpu(BufferParams &buffer_params, int samples)
{
- thread_scoped_lock pause_lock(pause_mutex);
+ thread_scoped_lock pause_lock(pause_mutex);
- /* block for buffer access and reset immediately. we can't do this
- * in the thread, because we need to allocate an OpenGL buffer, and
- * that only works in the main thread */
- thread_scoped_lock display_lock(display_mutex);
- thread_scoped_lock buffers_lock(buffers_mutex);
+ /* block for buffer access and reset immediately. we can't do this
+ * in the thread, because we need to allocate an OpenGL buffer, and
+ * that only works in the main thread */
+ thread_scoped_lock display_lock(display_mutex);
+ thread_scoped_lock buffers_lock(buffers_mutex);
- display_outdated = true;
- reset_time = time_dt();
+ display_outdated = true;
+ reset_time = time_dt();
- reset_(buffer_params, samples);
+ reset_(buffer_params, samples);
- gpu_need_tonemap = false;
- gpu_need_tonemap_cond.notify_all();
+ gpu_need_tonemap = false;
+ gpu_need_tonemap_cond.notify_all();
- pause_cond.notify_all();
+ pause_cond.notify_all();
}
-bool Session::draw_gpu(BufferParams& buffer_params, DeviceDrawParams& draw_params)
+bool Session::draw_gpu(BufferParams &buffer_params, DeviceDrawParams &draw_params)
{
- /* block for buffer access */
- thread_scoped_lock display_lock(display_mutex);
-
- /* first check we already rendered something */
- if(gpu_draw_ready) {
- /* then verify the buffers have the expected size, so we don't
- * draw previous results in a resized window */
- if(!buffer_params.modified(display->params)) {
- /* for CUDA we need to do tonemapping still, since we can
- * only access GL buffers from the main thread */
- if(gpu_need_tonemap) {
- thread_scoped_lock buffers_lock(buffers_mutex);
- tonemap(tile_manager.state.sample);
- gpu_need_tonemap = false;
- gpu_need_tonemap_cond.notify_all();
- }
-
- display->draw(device, draw_params);
-
- if(display_outdated && (time_dt() - reset_time) > params.text_timeout)
- return false;
-
- return true;
- }
- }
-
- return false;
+ /* block for buffer access */
+ thread_scoped_lock display_lock(display_mutex);
+
+ /* first check we already rendered something */
+ if (gpu_draw_ready) {
+ /* then verify the buffers have the expected size, so we don't
+ * draw previous results in a resized window */
+ if (!buffer_params.modified(display->params)) {
+ /* for CUDA we need to do tonemapping still, since we can
+ * only access GL buffers from the main thread */
+ if (gpu_need_tonemap) {
+ thread_scoped_lock buffers_lock(buffers_mutex);
+ tonemap(tile_manager.state.sample);
+ gpu_need_tonemap = false;
+ gpu_need_tonemap_cond.notify_all();
+ }
+
+ display->draw(device, draw_params);
+
+ if (display_outdated && (time_dt() - reset_time) > params.text_timeout)
+ return false;
+
+ return true;
+ }
+ }
+
+ return false;
}
void Session::run_gpu()
{
- bool tiles_written = false;
-
- reset_time = time_dt();
- last_update_time = time_dt();
-
- progress.set_render_start_time();
-
- while(!progress.get_cancel()) {
- /* advance to next tile */
- bool no_tiles = !tile_manager.next();
-
- DeviceKernelStatus kernel_state = DEVICE_KERNEL_UNKNOWN;
- if (no_tiles) {
- kernel_state = device->get_active_kernel_switch_state();
- }
-
- if(params.background) {
- /* if no work left and in background mode, we can stop immediately */
- if(no_tiles) {
- progress.set_status("Finished");
- break;
- }
- }
-
- /* Don't go in pause mode when image was rendered with preview kernels
- * When feature kernels become available the session will be resetted. */
- else if (no_tiles && kernel_state == DEVICE_KERNEL_WAITING_FOR_FEATURE_KERNEL) {
- time_sleep(0.1);
- }
- else if (no_tiles && kernel_state == DEVICE_KERNEL_FEATURE_KERNEL_AVAILABLE) {
- reset_gpu(tile_manager.params, params.samples);
- }
-
- else {
- /* if in interactive mode, and we are either paused or done for now,
- * wait for pause condition notify to wake up again */
- thread_scoped_lock pause_lock(pause_mutex);
-
- if(!pause && !tile_manager.done()) {
- /* reset could have happened after no_tiles was set, before this lock.
- * in this case we shall not wait for pause condition
- */
- }
- else if(pause || no_tiles) {
- update_status_time(pause, no_tiles);
-
- while(1) {
- scoped_timer pause_timer;
- pause_cond.wait(pause_lock);
- if(pause) {
- progress.add_skip_time(pause_timer, params.background);
- }
-
- update_status_time(pause, no_tiles);
- progress.set_update();
-
- if(!pause)
- break;
- }
- }
-
- if(progress.get_cancel())
- break;
- }
-
- if(!no_tiles) {
- /* update scene */
- scoped_timer update_timer;
- if(update_scene()) {
- profiler.reset(scene->shaders.size(), scene->objects.size());
- }
- progress.add_skip_time(update_timer, params.background);
-
- if(!device->error_message().empty())
- progress.set_error(device->error_message());
-
- if(progress.get_cancel())
- break;
- }
-
- if(!no_tiles) {
- /* buffers mutex is locked entirely while rendering each
- * sample, and released/reacquired on each iteration to allow
- * reset and draw in between */
- thread_scoped_lock buffers_lock(buffers_mutex);
-
- /* update status and timing */
- update_status_time();
-
- /* render */
- render();
-
- device->task_wait();
-
- if(!device->error_message().empty())
- progress.set_cancel(device->error_message());
-
- /* update status and timing */
- update_status_time();
-
- gpu_need_tonemap = true;
- gpu_draw_ready = true;
- progress.set_update();
-
- /* wait for tonemap */
- if(!params.background) {
- while(gpu_need_tonemap) {
- if(progress.get_cancel())
- break;
-
- gpu_need_tonemap_cond.wait(buffers_lock);
- }
- }
-
- if(!device->error_message().empty())
- progress.set_error(device->error_message());
-
- tiles_written = update_progressive_refine(progress.get_cancel());
-
- if(progress.get_cancel())
- break;
- }
- }
-
- if(!tiles_written)
- update_progressive_refine(true);
+ bool tiles_written = false;
+
+ reset_time = time_dt();
+ last_update_time = time_dt();
+
+ progress.set_render_start_time();
+
+ while (!progress.get_cancel()) {
+ /* advance to next tile */
+ bool no_tiles = !tile_manager.next();
+
+ DeviceKernelStatus kernel_state = DEVICE_KERNEL_UNKNOWN;
+ if (no_tiles) {
+ kernel_state = device->get_active_kernel_switch_state();
+ }
+
+ if (params.background) {
+ /* if no work left and in background mode, we can stop immediately */
+ if (no_tiles) {
+ progress.set_status("Finished");
+ break;
+ }
+ }
+
+ /* Don't go in pause mode when image was rendered with preview kernels
+ * When feature kernels become available the session will be resetted. */
+ else if (no_tiles && kernel_state == DEVICE_KERNEL_WAITING_FOR_FEATURE_KERNEL) {
+ time_sleep(0.1);
+ }
+ else if (no_tiles && kernel_state == DEVICE_KERNEL_FEATURE_KERNEL_AVAILABLE) {
+ reset_gpu(tile_manager.params, params.samples);
+ }
+
+ else {
+ /* if in interactive mode, and we are either paused or done for now,
+ * wait for pause condition notify to wake up again */
+ thread_scoped_lock pause_lock(pause_mutex);
+
+ if (!pause && !tile_manager.done()) {
+ /* reset could have happened after no_tiles was set, before this lock.
+ * in this case we shall not wait for pause condition
+ */
+ }
+ else if (pause || no_tiles) {
+ update_status_time(pause, no_tiles);
+
+ while (1) {
+ scoped_timer pause_timer;
+ pause_cond.wait(pause_lock);
+ if (pause) {
+ progress.add_skip_time(pause_timer, params.background);
+ }
+
+ update_status_time(pause, no_tiles);
+ progress.set_update();
+
+ if (!pause)
+ break;
+ }
+ }
+
+ if (progress.get_cancel())
+ break;
+ }
+
+ if (!no_tiles) {
+ /* update scene */
+ scoped_timer update_timer;
+ if (update_scene()) {
+ profiler.reset(scene->shaders.size(), scene->objects.size());
+ }
+ progress.add_skip_time(update_timer, params.background);
+
+ if (!device->error_message().empty())
+ progress.set_error(device->error_message());
+
+ if (progress.get_cancel())
+ break;
+ }
+
+ if (!no_tiles) {
+ /* buffers mutex is locked entirely while rendering each
+ * sample, and released/reacquired on each iteration to allow
+ * reset and draw in between */
+ thread_scoped_lock buffers_lock(buffers_mutex);
+
+ /* update status and timing */
+ update_status_time();
+
+ /* render */
+ render();
+
+ device->task_wait();
+
+ if (!device->error_message().empty())
+ progress.set_cancel(device->error_message());
+
+ /* update status and timing */
+ update_status_time();
+
+ gpu_need_tonemap = true;
+ gpu_draw_ready = true;
+ progress.set_update();
+
+ /* wait for tonemap */
+ if (!params.background) {
+ while (gpu_need_tonemap) {
+ if (progress.get_cancel())
+ break;
+
+ gpu_need_tonemap_cond.wait(buffers_lock);
+ }
+ }
+
+ if (!device->error_message().empty())
+ progress.set_error(device->error_message());
+
+ tiles_written = update_progressive_refine(progress.get_cancel());
+
+ if (progress.get_cancel())
+ break;
+ }
+ }
+
+ if (!tiles_written)
+ update_progressive_refine(true);
}
/* CPU Session */
-void Session::reset_cpu(BufferParams& buffer_params, int samples)
+void Session::reset_cpu(BufferParams &buffer_params, int samples)
{
- thread_scoped_lock reset_lock(delayed_reset.mutex);
- thread_scoped_lock pause_lock(pause_mutex);
+ thread_scoped_lock reset_lock(delayed_reset.mutex);
+ thread_scoped_lock pause_lock(pause_mutex);
- display_outdated = true;
- reset_time = time_dt();
+ display_outdated = true;
+ reset_time = time_dt();
- delayed_reset.params = buffer_params;
- delayed_reset.samples = samples;
- delayed_reset.do_reset = true;
- device->task_cancel();
+ delayed_reset.params = buffer_params;
+ delayed_reset.samples = samples;
+ delayed_reset.do_reset = true;
+ device->task_cancel();
- pause_cond.notify_all();
+ pause_cond.notify_all();
}
-bool Session::draw_cpu(BufferParams& buffer_params, DeviceDrawParams& draw_params)
+bool Session::draw_cpu(BufferParams &buffer_params, DeviceDrawParams &draw_params)
{
- thread_scoped_lock display_lock(display_mutex);
+ thread_scoped_lock display_lock(display_mutex);
- /* first check we already rendered something */
- if(display->draw_ready()) {
- /* then verify the buffers have the expected size, so we don't
- * draw previous results in a resized window */
- if(!buffer_params.modified(display->params)) {
- display->draw(device, draw_params);
+ /* first check we already rendered something */
+ if (display->draw_ready()) {
+ /* then verify the buffers have the expected size, so we don't
+ * draw previous results in a resized window */
+ if (!buffer_params.modified(display->params)) {
+ display->draw(device, draw_params);
- if(display_outdated && (time_dt() - reset_time) > params.text_timeout)
- return false;
+ if (display_outdated && (time_dt() - reset_time) > params.text_timeout)
+ return false;
- return true;
- }
- }
+ return true;
+ }
+ }
- return false;
+ return false;
}
-bool Session::acquire_tile(Device *tile_device, RenderTile& rtile)
+bool Session::acquire_tile(Device *tile_device, RenderTile &rtile)
{
- if(progress.get_cancel()) {
- if(params.progressive_refine == false) {
- /* for progressive refine current sample should be finished for all tiles */
- return false;
- }
- }
-
- thread_scoped_lock tile_lock(tile_mutex);
-
- /* get next tile from manager */
- Tile *tile;
- int device_num = device->device_number(tile_device);
-
- if(!tile_manager.next_tile(tile, device_num))
- return false;
-
- /* fill render tile */
- rtile.x = tile_manager.state.buffer.full_x + tile->x;
- rtile.y = tile_manager.state.buffer.full_y + tile->y;
- rtile.w = tile->w;
- rtile.h = tile->h;
- rtile.start_sample = tile_manager.state.sample;
- rtile.num_samples = tile_manager.state.num_samples;
- rtile.resolution = tile_manager.state.resolution_divider;
- rtile.tile_index = tile->index;
- rtile.task = (tile->state == Tile::DENOISE)? RenderTile::DENOISE: RenderTile::PATH_TRACE;
-
- tile_lock.unlock();
-
- /* in case of a permanent buffer, return it, otherwise we will allocate
- * a new temporary buffer */
- if(buffers) {
- tile_manager.state.buffer.get_offset_stride(rtile.offset, rtile.stride);
-
- rtile.buffer = buffers->buffer.device_pointer;
- rtile.buffers = buffers;
-
- device->map_tile(tile_device, rtile);
-
- return true;
- }
-
- if(tile->buffers == NULL) {
- /* fill buffer parameters */
- BufferParams buffer_params = tile_manager.params;
- buffer_params.full_x = rtile.x;
- buffer_params.full_y = rtile.y;
- buffer_params.width = rtile.w;
- buffer_params.height = rtile.h;
-
- /* allocate buffers */
- tile->buffers = new RenderBuffers(tile_device);
- tile->buffers->reset(buffer_params);
- }
-
- tile->buffers->params.get_offset_stride(rtile.offset, rtile.stride);
-
- rtile.buffer = tile->buffers->buffer.device_pointer;
- rtile.buffers = tile->buffers;
- rtile.sample = tile_manager.state.sample;
-
- /* this will tag tile as IN PROGRESS in blender-side render pipeline,
- * which is needed to highlight currently rendering tile before first
- * sample was processed for it
- */
- update_tile_sample(rtile);
-
- return true;
+ if (progress.get_cancel()) {
+ if (params.progressive_refine == false) {
+ /* for progressive refine current sample should be finished for all tiles */
+ return false;
+ }
+ }
+
+ thread_scoped_lock tile_lock(tile_mutex);
+
+ /* get next tile from manager */
+ Tile *tile;
+ int device_num = device->device_number(tile_device);
+
+ if (!tile_manager.next_tile(tile, device_num))
+ return false;
+
+ /* fill render tile */
+ rtile.x = tile_manager.state.buffer.full_x + tile->x;
+ rtile.y = tile_manager.state.buffer.full_y + tile->y;
+ rtile.w = tile->w;
+ rtile.h = tile->h;
+ rtile.start_sample = tile_manager.state.sample;
+ rtile.num_samples = tile_manager.state.num_samples;
+ rtile.resolution = tile_manager.state.resolution_divider;
+ rtile.tile_index = tile->index;
+ rtile.task = (tile->state == Tile::DENOISE) ? RenderTile::DENOISE : RenderTile::PATH_TRACE;
+
+ tile_lock.unlock();
+
+ /* in case of a permanent buffer, return it, otherwise we will allocate
+ * a new temporary buffer */
+ if (buffers) {
+ tile_manager.state.buffer.get_offset_stride(rtile.offset, rtile.stride);
+
+ rtile.buffer = buffers->buffer.device_pointer;
+ rtile.buffers = buffers;
+
+ device->map_tile(tile_device, rtile);
+
+ return true;
+ }
+
+ if (tile->buffers == NULL) {
+ /* fill buffer parameters */
+ BufferParams buffer_params = tile_manager.params;
+ buffer_params.full_x = rtile.x;
+ buffer_params.full_y = rtile.y;
+ buffer_params.width = rtile.w;
+ buffer_params.height = rtile.h;
+
+ /* allocate buffers */
+ tile->buffers = new RenderBuffers(tile_device);
+ tile->buffers->reset(buffer_params);
+ }
+
+ tile->buffers->params.get_offset_stride(rtile.offset, rtile.stride);
+
+ rtile.buffer = tile->buffers->buffer.device_pointer;
+ rtile.buffers = tile->buffers;
+ rtile.sample = tile_manager.state.sample;
+
+ /* this will tag tile as IN PROGRESS in blender-side render pipeline,
+ * which is needed to highlight currently rendering tile before first
+ * sample was processed for it
+ */
+ update_tile_sample(rtile);
+
+ return true;
}
-void Session::update_tile_sample(RenderTile& rtile)
+void Session::update_tile_sample(RenderTile &rtile)
{
- thread_scoped_lock tile_lock(tile_mutex);
+ thread_scoped_lock tile_lock(tile_mutex);
- if(update_render_tile_cb) {
- if(params.progressive_refine == false) {
- /* todo: optimize this by making it thread safe and removing lock */
+ if (update_render_tile_cb) {
+ if (params.progressive_refine == false) {
+ /* todo: optimize this by making it thread safe and removing lock */
- update_render_tile_cb(rtile, true);
- }
- }
+ update_render_tile_cb(rtile, true);
+ }
+ }
- update_status_time();
+ update_status_time();
}
-void Session::release_tile(RenderTile& rtile)
+void Session::release_tile(RenderTile &rtile)
{
- thread_scoped_lock tile_lock(tile_mutex);
+ thread_scoped_lock tile_lock(tile_mutex);
- progress.add_finished_tile(rtile.task == RenderTile::DENOISE);
+ progress.add_finished_tile(rtile.task == RenderTile::DENOISE);
- bool delete_tile;
+ bool delete_tile;
- if(tile_manager.finish_tile(rtile.tile_index, delete_tile)) {
- if(write_render_tile_cb && params.progressive_refine == false) {
- write_render_tile_cb(rtile);
- }
+ if (tile_manager.finish_tile(rtile.tile_index, delete_tile)) {
+ if (write_render_tile_cb && params.progressive_refine == false) {
+ write_render_tile_cb(rtile);
+ }
- if(delete_tile) {
- delete rtile.buffers;
- tile_manager.state.tiles[rtile.tile_index].buffers = NULL;
- }
- }
- else {
- if(update_render_tile_cb && params.progressive_refine == false) {
- update_render_tile_cb(rtile, false);
- }
- }
+ if (delete_tile) {
+ delete rtile.buffers;
+ tile_manager.state.tiles[rtile.tile_index].buffers = NULL;
+ }
+ }
+ else {
+ if (update_render_tile_cb && params.progressive_refine == false) {
+ update_render_tile_cb(rtile, false);
+ }
+ }
- update_status_time();
+ update_status_time();
}
void Session::map_neighbor_tiles(RenderTile *tiles, Device *tile_device)
{
- thread_scoped_lock tile_lock(tile_mutex);
-
- int center_idx = tiles[4].tile_index;
- assert(tile_manager.state.tiles[center_idx].state == Tile::DENOISE);
- BufferParams buffer_params = tile_manager.params;
- int4 image_region = make_int4(buffer_params.full_x, buffer_params.full_y,
- buffer_params.full_x + buffer_params.width, buffer_params.full_y + buffer_params.height);
-
- for(int dy = -1, i = 0; dy <= 1; dy++) {
- for(int dx = -1; dx <= 1; dx++, i++) {
- int px = tiles[4].x + dx*params.tile_size.x;
- int py = tiles[4].y + dy*params.tile_size.y;
- if(px >= image_region.x && py >= image_region.y &&
- px < image_region.z && py < image_region.w) {
- int tile_index = center_idx + dy*tile_manager.state.tile_stride + dx;
- Tile *tile = &tile_manager.state.tiles[tile_index];
- assert(tile->buffers);
-
- tiles[i].buffer = tile->buffers->buffer.device_pointer;
- tiles[i].x = tile_manager.state.buffer.full_x + tile->x;
- tiles[i].y = tile_manager.state.buffer.full_y + tile->y;
- tiles[i].w = tile->w;
- tiles[i].h = tile->h;
- tiles[i].buffers = tile->buffers;
-
- tile->buffers->params.get_offset_stride(tiles[i].offset, tiles[i].stride);
- }
- else {
- tiles[i].buffer = (device_ptr)NULL;
- tiles[i].buffers = NULL;
- tiles[i].x = clamp(px, image_region.x, image_region.z);
- tiles[i].y = clamp(py, image_region.y, image_region.w);
- tiles[i].w = tiles[i].h = 0;
- }
- }
- }
-
- assert(tiles[4].buffers);
- device->map_neighbor_tiles(tile_device, tiles);
-
- /* The denoised result is written back to the original tile. */
- tiles[9] = tiles[4];
+ thread_scoped_lock tile_lock(tile_mutex);
+
+ int center_idx = tiles[4].tile_index;
+ assert(tile_manager.state.tiles[center_idx].state == Tile::DENOISE);
+ BufferParams buffer_params = tile_manager.params;
+ int4 image_region = make_int4(buffer_params.full_x,
+ buffer_params.full_y,
+ buffer_params.full_x + buffer_params.width,
+ buffer_params.full_y + buffer_params.height);
+
+ for (int dy = -1, i = 0; dy <= 1; dy++) {
+ for (int dx = -1; dx <= 1; dx++, i++) {
+ int px = tiles[4].x + dx * params.tile_size.x;
+ int py = tiles[4].y + dy * params.tile_size.y;
+ if (px >= image_region.x && py >= image_region.y && px < image_region.z &&
+ py < image_region.w) {
+ int tile_index = center_idx + dy * tile_manager.state.tile_stride + dx;
+ Tile *tile = &tile_manager.state.tiles[tile_index];
+ assert(tile->buffers);
+
+ tiles[i].buffer = tile->buffers->buffer.device_pointer;
+ tiles[i].x = tile_manager.state.buffer.full_x + tile->x;
+ tiles[i].y = tile_manager.state.buffer.full_y + tile->y;
+ tiles[i].w = tile->w;
+ tiles[i].h = tile->h;
+ tiles[i].buffers = tile->buffers;
+
+ tile->buffers->params.get_offset_stride(tiles[i].offset, tiles[i].stride);
+ }
+ else {
+ tiles[i].buffer = (device_ptr)NULL;
+ tiles[i].buffers = NULL;
+ tiles[i].x = clamp(px, image_region.x, image_region.z);
+ tiles[i].y = clamp(py, image_region.y, image_region.w);
+ tiles[i].w = tiles[i].h = 0;
+ }
+ }
+ }
+
+ assert(tiles[4].buffers);
+ device->map_neighbor_tiles(tile_device, tiles);
+
+ /* The denoised result is written back to the original tile. */
+ tiles[9] = tiles[4];
}
void Session::unmap_neighbor_tiles(RenderTile *tiles, Device *tile_device)
{
- thread_scoped_lock tile_lock(tile_mutex);
- device->unmap_neighbor_tiles(tile_device, tiles);
+ thread_scoped_lock tile_lock(tile_mutex);
+ device->unmap_neighbor_tiles(tile_device, tiles);
}
void Session::run_cpu()
{
- bool tiles_written = false;
-
- last_update_time = time_dt();
-
- {
- /* reset once to start */
- thread_scoped_lock reset_lock(delayed_reset.mutex);
- thread_scoped_lock buffers_lock(buffers_mutex);
- thread_scoped_lock display_lock(display_mutex);
-
- reset_(delayed_reset.params, delayed_reset.samples);
- delayed_reset.do_reset = false;
- }
-
- while(!progress.get_cancel()) {
- /* advance to next tile */
- bool no_tiles = !tile_manager.next();
- bool need_tonemap = false;
-
- DeviceKernelStatus kernel_state = DEVICE_KERNEL_UNKNOWN;
- if (no_tiles) {
- kernel_state = device->get_active_kernel_switch_state();
- }
-
- if(params.background) {
- /* if no work left and in background mode, we can stop immediately */
- if(no_tiles) {
- progress.set_status("Finished");
- break;
- }
- }
-
- /* Don't go in pause mode when preview kernels are used
- * When feature kernels become available the session will be resetted. */
- else if (no_tiles && kernel_state == DEVICE_KERNEL_WAITING_FOR_FEATURE_KERNEL) {
- time_sleep(0.1);
- }
- else if (no_tiles && kernel_state == DEVICE_KERNEL_FEATURE_KERNEL_AVAILABLE) {
- reset_cpu(tile_manager.params, params.samples);
- }
-
- else {
- /* if in interactive mode, and we are either paused or done for now,
- * wait for pause condition notify to wake up again */
- thread_scoped_lock pause_lock(pause_mutex);
-
- if(!pause && delayed_reset.do_reset) {
- /* reset once to start */
- thread_scoped_lock reset_lock(delayed_reset.mutex);
- thread_scoped_lock buffers_lock(buffers_mutex);
- thread_scoped_lock display_lock(display_mutex);
-
- reset_(delayed_reset.params, delayed_reset.samples);
- delayed_reset.do_reset = false;
- }
- else if(pause || no_tiles) {
- update_status_time(pause, no_tiles);
-
- while(1) {
- scoped_timer pause_timer;
- pause_cond.wait(pause_lock);
- if(pause) {
- progress.add_skip_time(pause_timer, params.background);
- }
-
- update_status_time(pause, no_tiles);
- progress.set_update();
-
- if(!pause)
- break;
- }
- }
-
- if(progress.get_cancel())
- break;
- }
-
- if(!no_tiles) {
- /* buffers mutex is locked entirely while rendering each
- * sample, and released/reacquired on each iteration to allow
- * reset and draw in between */
- thread_scoped_lock buffers_lock(buffers_mutex);
-
- /* update scene */
- scoped_timer update_timer;
- if(update_scene()) {
- profiler.reset(scene->shaders.size(), scene->objects.size());
- }
- progress.add_skip_time(update_timer, params.background);
-
- if(!device->error_message().empty())
- progress.set_error(device->error_message());
-
- if(progress.get_cancel())
- break;
-
- /* update status and timing */
- update_status_time();
-
- /* render */
- render();
-
- /* update status and timing */
- update_status_time();
-
- if(!params.background)
- need_tonemap = true;
-
- if(!device->error_message().empty())
- progress.set_error(device->error_message());
- }
-
- device->task_wait();
-
- {
- thread_scoped_lock reset_lock(delayed_reset.mutex);
- thread_scoped_lock buffers_lock(buffers_mutex);
- thread_scoped_lock display_lock(display_mutex);
-
- if(delayed_reset.do_reset) {
- /* reset rendering if request from main thread */
- delayed_reset.do_reset = false;
- reset_(delayed_reset.params, delayed_reset.samples);
- }
- else if(need_tonemap) {
- /* tonemap only if we do not reset, we don't we don't
- * want to show the result of an incomplete sample */
- tonemap(tile_manager.state.sample);
- }
-
- if(!device->error_message().empty())
- progress.set_error(device->error_message());
-
- tiles_written = update_progressive_refine(progress.get_cancel());
- }
-
- progress.set_update();
- }
-
- if(!tiles_written)
- update_progressive_refine(true);
+ bool tiles_written = false;
+
+ last_update_time = time_dt();
+
+ {
+ /* reset once to start */
+ thread_scoped_lock reset_lock(delayed_reset.mutex);
+ thread_scoped_lock buffers_lock(buffers_mutex);
+ thread_scoped_lock display_lock(display_mutex);
+
+ reset_(delayed_reset.params, delayed_reset.samples);
+ delayed_reset.do_reset = false;
+ }
+
+ while (!progress.get_cancel()) {
+ /* advance to next tile */
+ bool no_tiles = !tile_manager.next();
+ bool need_tonemap = false;
+
+ DeviceKernelStatus kernel_state = DEVICE_KERNEL_UNKNOWN;
+ if (no_tiles) {
+ kernel_state = device->get_active_kernel_switch_state();
+ }
+
+ if (params.background) {
+ /* if no work left and in background mode, we can stop immediately */
+ if (no_tiles) {
+ progress.set_status("Finished");
+ break;
+ }
+ }
+
+ /* Don't go in pause mode when preview kernels are used
+ * When feature kernels become available the session will be resetted. */
+ else if (no_tiles && kernel_state == DEVICE_KERNEL_WAITING_FOR_FEATURE_KERNEL) {
+ time_sleep(0.1);
+ }
+ else if (no_tiles && kernel_state == DEVICE_KERNEL_FEATURE_KERNEL_AVAILABLE) {
+ reset_cpu(tile_manager.params, params.samples);
+ }
+
+ else {
+ /* if in interactive mode, and we are either paused or done for now,
+ * wait for pause condition notify to wake up again */
+ thread_scoped_lock pause_lock(pause_mutex);
+
+ if (!pause && delayed_reset.do_reset) {
+ /* reset once to start */
+ thread_scoped_lock reset_lock(delayed_reset.mutex);
+ thread_scoped_lock buffers_lock(buffers_mutex);
+ thread_scoped_lock display_lock(display_mutex);
+
+ reset_(delayed_reset.params, delayed_reset.samples);
+ delayed_reset.do_reset = false;
+ }
+ else if (pause || no_tiles) {
+ update_status_time(pause, no_tiles);
+
+ while (1) {
+ scoped_timer pause_timer;
+ pause_cond.wait(pause_lock);
+ if (pause) {
+ progress.add_skip_time(pause_timer, params.background);
+ }
+
+ update_status_time(pause, no_tiles);
+ progress.set_update();
+
+ if (!pause)
+ break;
+ }
+ }
+
+ if (progress.get_cancel())
+ break;
+ }
+
+ if (!no_tiles) {
+ /* buffers mutex is locked entirely while rendering each
+ * sample, and released/reacquired on each iteration to allow
+ * reset and draw in between */
+ thread_scoped_lock buffers_lock(buffers_mutex);
+
+ /* update scene */
+ scoped_timer update_timer;
+ if (update_scene()) {
+ profiler.reset(scene->shaders.size(), scene->objects.size());
+ }
+ progress.add_skip_time(update_timer, params.background);
+
+ if (!device->error_message().empty())
+ progress.set_error(device->error_message());
+
+ if (progress.get_cancel())
+ break;
+
+ /* update status and timing */
+ update_status_time();
+
+ /* render */
+ render();
+
+ /* update status and timing */
+ update_status_time();
+
+ if (!params.background)
+ need_tonemap = true;
+
+ if (!device->error_message().empty())
+ progress.set_error(device->error_message());
+ }
+
+ device->task_wait();
+
+ {
+ thread_scoped_lock reset_lock(delayed_reset.mutex);
+ thread_scoped_lock buffers_lock(buffers_mutex);
+ thread_scoped_lock display_lock(display_mutex);
+
+ if (delayed_reset.do_reset) {
+ /* reset rendering if request from main thread */
+ delayed_reset.do_reset = false;
+ reset_(delayed_reset.params, delayed_reset.samples);
+ }
+ else if (need_tonemap) {
+ /* tonemap only if we do not reset, we don't we don't
+ * want to show the result of an incomplete sample */
+ tonemap(tile_manager.state.sample);
+ }
+
+ if (!device->error_message().empty())
+ progress.set_error(device->error_message());
+
+ tiles_written = update_progressive_refine(progress.get_cancel());
+ }
+
+ progress.set_update();
+ }
+
+ if (!tiles_written)
+ update_progressive_refine(true);
}
DeviceRequestedFeatures Session::get_requested_device_features()
{
- /* TODO(sergey): Consider moving this to the Scene level. */
- DeviceRequestedFeatures requested_features;
- requested_features.experimental = params.experimental;
-
- scene->shader_manager->get_requested_features(
- scene,
- &requested_features);
-
- /* This features are not being tweaked as often as shaders,
- * so could be done selective magic for the viewport as well.
- */
- bool use_motion = scene->need_motion() == Scene::MotionType::MOTION_BLUR;
- requested_features.use_hair = false;
- requested_features.use_object_motion = false;
- requested_features.use_camera_motion = use_motion && scene->camera->use_motion();
- foreach(Object *object, scene->objects) {
- Mesh *mesh = object->mesh;
- if(mesh->num_curves()) {
- requested_features.use_hair = true;
- }
- if (use_motion) {
- requested_features.use_object_motion |= object->use_motion() | mesh->use_motion_blur;
- requested_features.use_camera_motion |= mesh->use_motion_blur;
- }
+ /* TODO(sergey): Consider moving this to the Scene level. */
+ DeviceRequestedFeatures requested_features;
+ requested_features.experimental = params.experimental;
+
+ scene->shader_manager->get_requested_features(scene, &requested_features);
+
+ /* This features are not being tweaked as often as shaders,
+ * so could be done selective magic for the viewport as well.
+ */
+ bool use_motion = scene->need_motion() == Scene::MotionType::MOTION_BLUR;
+ requested_features.use_hair = false;
+ requested_features.use_object_motion = false;
+ requested_features.use_camera_motion = use_motion && scene->camera->use_motion();
+ foreach (Object *object, scene->objects) {
+ Mesh *mesh = object->mesh;
+ if (mesh->num_curves()) {
+ requested_features.use_hair = true;
+ }
+ if (use_motion) {
+ requested_features.use_object_motion |= object->use_motion() | mesh->use_motion_blur;
+ requested_features.use_camera_motion |= mesh->use_motion_blur;
+ }
#ifdef WITH_OPENSUBDIV
- if(mesh->subdivision_type != Mesh::SUBDIVISION_NONE) {
- requested_features.use_patch_evaluation = true;
- }
+ if (mesh->subdivision_type != Mesh::SUBDIVISION_NONE) {
+ requested_features.use_patch_evaluation = true;
+ }
#endif
- if(object->is_shadow_catcher) {
- requested_features.use_shadow_tricks = true;
- }
- requested_features.use_true_displacement |= mesh->has_true_displacement();
- }
-
- requested_features.use_background_light = scene->light_manager->has_background_light(scene);
-
- BakeManager *bake_manager = scene->bake_manager;
- requested_features.use_baking = bake_manager->get_baking();
- requested_features.use_integrator_branched = (scene->integrator->method == Integrator::BRANCHED_PATH);
- if(params.run_denoising) {
- requested_features.use_denoising = true;
- requested_features.use_shadow_tricks = true;
- }
-
- return requested_features;
+ if (object->is_shadow_catcher) {
+ requested_features.use_shadow_tricks = true;
+ }
+ requested_features.use_true_displacement |= mesh->has_true_displacement();
+ }
+
+ requested_features.use_background_light = scene->light_manager->has_background_light(scene);
+
+ BakeManager *bake_manager = scene->bake_manager;
+ requested_features.use_baking = bake_manager->get_baking();
+ requested_features.use_integrator_branched = (scene->integrator->method ==
+ Integrator::BRANCHED_PATH);
+ if (params.run_denoising) {
+ requested_features.use_denoising = true;
+ requested_features.use_shadow_tricks = true;
+ }
+
+ return requested_features;
}
bool Session::load_kernels(bool lock_scene)
{
- thread_scoped_lock scene_lock;
- if(lock_scene) {
- scene_lock = thread_scoped_lock(scene->mutex);
- }
-
- DeviceRequestedFeatures requested_features = get_requested_device_features();
-
- if(!kernels_loaded || loaded_kernel_features.modified(requested_features)) {
- progress.set_status("Loading render kernels (may take a few minutes the first time)");
-
- scoped_timer timer;
-
- VLOG(2) << "Requested features:\n" << requested_features;
- if(!device->load_kernels(requested_features)) {
- string message = device->error_message();
- if(message.empty())
- message = "Failed loading render kernel, see console for errors";
-
- progress.set_error(message);
- progress.set_status("Error", message);
- progress.set_update();
- return false;
- }
-
- progress.add_skip_time(timer, false);
- VLOG(1) << "Total time spent loading kernels: " << time_dt() - timer.get_start();
-
- kernels_loaded = true;
- loaded_kernel_features = requested_features;
- return true;
- }
- return false;
+ thread_scoped_lock scene_lock;
+ if (lock_scene) {
+ scene_lock = thread_scoped_lock(scene->mutex);
+ }
+
+ DeviceRequestedFeatures requested_features = get_requested_device_features();
+
+ if (!kernels_loaded || loaded_kernel_features.modified(requested_features)) {
+ progress.set_status("Loading render kernels (may take a few minutes the first time)");
+
+ scoped_timer timer;
+
+ VLOG(2) << "Requested features:\n" << requested_features;
+ if (!device->load_kernels(requested_features)) {
+ string message = device->error_message();
+ if (message.empty())
+ message = "Failed loading render kernel, see console for errors";
+
+ progress.set_error(message);
+ progress.set_status("Error", message);
+ progress.set_update();
+ return false;
+ }
+
+ progress.add_skip_time(timer, false);
+ VLOG(1) << "Total time spent loading kernels: " << time_dt() - timer.get_start();
+
+ kernels_loaded = true;
+ loaded_kernel_features = requested_features;
+ return true;
+ }
+ return false;
}
void Session::run()
{
- if(params.use_profiling && (params.device.type == DEVICE_CPU)) {
- profiler.start();
- }
-
- /* session thread loop */
- progress.set_status("Waiting for render to start");
-
- /* run */
- if(!progress.get_cancel()) {
- /* reset number of rendered samples */
- progress.reset_sample();
-
- if(device_use_gl)
- run_gpu();
- else
- run_cpu();
- }
-
- profiler.stop();
-
- /* progress update */
- if(progress.get_cancel())
- progress.set_status("Cancel", progress.get_cancel_message());
- else
- progress.set_update();
+ if (params.use_profiling && (params.device.type == DEVICE_CPU)) {
+ profiler.start();
+ }
+
+ /* session thread loop */
+ progress.set_status("Waiting for render to start");
+
+ /* run */
+ if (!progress.get_cancel()) {
+ /* reset number of rendered samples */
+ progress.reset_sample();
+
+ if (device_use_gl)
+ run_gpu();
+ else
+ run_cpu();
+ }
+
+ profiler.stop();
+
+ /* progress update */
+ if (progress.get_cancel())
+ progress.set_status("Cancel", progress.get_cancel_message());
+ else
+ progress.set_update();
}
-bool Session::draw(BufferParams& buffer_params, DeviceDrawParams &draw_params)
+bool Session::draw(BufferParams &buffer_params, DeviceDrawParams &draw_params)
{
- if(device_use_gl)
- return draw_gpu(buffer_params, draw_params);
- else
- return draw_cpu(buffer_params, draw_params);
+ if (device_use_gl)
+ return draw_gpu(buffer_params, draw_params);
+ else
+ return draw_cpu(buffer_params, draw_params);
}
-void Session::reset_(BufferParams& buffer_params, int samples)
+void Session::reset_(BufferParams &buffer_params, int samples)
{
- if(buffers && buffer_params.modified(tile_manager.params)) {
- gpu_draw_ready = false;
- buffers->reset(buffer_params);
- if(display) {
- display->reset(buffer_params);
- }
- }
-
- tile_manager.reset(buffer_params, samples);
- progress.reset_sample();
-
- bool show_progress = params.background || tile_manager.get_num_effective_samples() != INT_MAX;
- progress.set_total_pixel_samples(show_progress? tile_manager.state.total_pixel_samples : 0);
-
- if(!params.background)
- progress.set_start_time();
- progress.set_render_start_time();
+ if (buffers && buffer_params.modified(tile_manager.params)) {
+ gpu_draw_ready = false;
+ buffers->reset(buffer_params);
+ if (display) {
+ display->reset(buffer_params);
+ }
+ }
+
+ tile_manager.reset(buffer_params, samples);
+ progress.reset_sample();
+
+ bool show_progress = params.background || tile_manager.get_num_effective_samples() != INT_MAX;
+ progress.set_total_pixel_samples(show_progress ? tile_manager.state.total_pixel_samples : 0);
+
+ if (!params.background)
+ progress.set_start_time();
+ progress.set_render_start_time();
}
-void Session::reset(BufferParams& buffer_params, int samples)
+void Session::reset(BufferParams &buffer_params, int samples)
{
- if(device_use_gl)
- reset_gpu(buffer_params, samples);
- else
- reset_cpu(buffer_params, samples);
+ if (device_use_gl)
+ reset_gpu(buffer_params, samples);
+ else
+ reset_cpu(buffer_params, samples);
}
void Session::set_samples(int samples)
{
- if(samples != params.samples) {
- params.samples = samples;
- tile_manager.set_samples(samples);
-
- {
- thread_scoped_lock pause_lock(pause_mutex);
- }
- pause_cond.notify_all();
- }
+ if (samples != params.samples) {
+ params.samples = samples;
+ tile_manager.set_samples(samples);
+
+ {
+ thread_scoped_lock pause_lock(pause_mutex);
+ }
+ pause_cond.notify_all();
+ }
}
void Session::set_pause(bool pause_)
{
- bool notify = false;
+ bool notify = false;
- {
- thread_scoped_lock pause_lock(pause_mutex);
+ {
+ thread_scoped_lock pause_lock(pause_mutex);
- if(pause != pause_) {
- pause = pause_;
- notify = true;
- }
- }
+ if (pause != pause_) {
+ pause = pause_;
+ notify = true;
+ }
+ }
- if(notify)
- pause_cond.notify_all();
+ if (notify)
+ pause_cond.notify_all();
}
void Session::wait()
{
- if (session_thread) {
- session_thread->join();
- delete session_thread;
- }
+ if (session_thread) {
+ session_thread->join();
+ delete session_thread;
+ }
- session_thread = NULL;
+ session_thread = NULL;
}
bool Session::update_scene()
{
- thread_scoped_lock scene_lock(scene->mutex);
-
- /* update camera if dimensions changed for progressive render. the camera
- * knows nothing about progressive or cropped rendering, it just gets the
- * image dimensions passed in */
- Camera *cam = scene->camera;
- int width = tile_manager.state.buffer.full_width;
- int height = tile_manager.state.buffer.full_height;
- int resolution = tile_manager.state.resolution_divider;
-
- if(width != cam->width || height != cam->height) {
- cam->width = width;
- cam->height = height;
- cam->resolution = resolution;
- cam->tag_update();
- }
-
- /* number of samples is needed by multi jittered
- * sampling pattern and by baking */
- Integrator *integrator = scene->integrator;
- BakeManager *bake_manager = scene->bake_manager;
-
- if(integrator->sampling_pattern == SAMPLING_PATTERN_CMJ ||
- bake_manager->get_baking())
- {
- int aa_samples = tile_manager.num_samples;
-
- if(aa_samples != integrator->aa_samples) {
- integrator->aa_samples = aa_samples;
- integrator->tag_update(scene);
- }
- }
-
- /* update scene */
- if(scene->need_update()) {
- bool new_kernels_needed = load_kernels(false);
-
- /* Update max_closures. */
- KernelIntegrator *kintegrator = &scene->dscene.data.integrator;
- if(params.background) {
- kintegrator->max_closures = get_max_closure_count();
- }
- else {
- /* Currently viewport render is faster with higher max_closures, needs investigating. */
- kintegrator->max_closures = MAX_CLOSURE;
- }
-
- progress.set_status("Updating Scene");
- MEM_GUARDED_CALL(&progress, scene->device_update, device, progress);
-
- DeviceKernelStatus kernel_switch_status = device->get_active_kernel_switch_state();
- bool kernel_switch_needed = kernel_switch_status == DEVICE_KERNEL_FEATURE_KERNEL_AVAILABLE ||
- kernel_switch_status == DEVICE_KERNEL_FEATURE_KERNEL_INVALID;
- if (kernel_switch_status == DEVICE_KERNEL_WAITING_FOR_FEATURE_KERNEL) {
- progress.set_kernel_status("Compiling render kernels");
- }
- if (new_kernels_needed || kernel_switch_needed) {
- progress.set_kernel_status("Compiling render kernels");
- device->wait_for_availability(loaded_kernel_features);
- progress.set_kernel_status("");
- }
-
- if (kernel_switch_needed) {
- reset(tile_manager.params, params.samples);
- }
- return true;
- }
- return false;
+ thread_scoped_lock scene_lock(scene->mutex);
+
+ /* update camera if dimensions changed for progressive render. the camera
+ * knows nothing about progressive or cropped rendering, it just gets the
+ * image dimensions passed in */
+ Camera *cam = scene->camera;
+ int width = tile_manager.state.buffer.full_width;
+ int height = tile_manager.state.buffer.full_height;
+ int resolution = tile_manager.state.resolution_divider;
+
+ if (width != cam->width || height != cam->height) {
+ cam->width = width;
+ cam->height = height;
+ cam->resolution = resolution;
+ cam->tag_update();
+ }
+
+ /* number of samples is needed by multi jittered
+ * sampling pattern and by baking */
+ Integrator *integrator = scene->integrator;
+ BakeManager *bake_manager = scene->bake_manager;
+
+ if (integrator->sampling_pattern == SAMPLING_PATTERN_CMJ || bake_manager->get_baking()) {
+ int aa_samples = tile_manager.num_samples;
+
+ if (aa_samples != integrator->aa_samples) {
+ integrator->aa_samples = aa_samples;
+ integrator->tag_update(scene);
+ }
+ }
+
+ /* update scene */
+ if (scene->need_update()) {
+ bool new_kernels_needed = load_kernels(false);
+
+ /* Update max_closures. */
+ KernelIntegrator *kintegrator = &scene->dscene.data.integrator;
+ if (params.background) {
+ kintegrator->max_closures = get_max_closure_count();
+ }
+ else {
+ /* Currently viewport render is faster with higher max_closures, needs investigating. */
+ kintegrator->max_closures = MAX_CLOSURE;
+ }
+
+ progress.set_status("Updating Scene");
+ MEM_GUARDED_CALL(&progress, scene->device_update, device, progress);
+
+ DeviceKernelStatus kernel_switch_status = device->get_active_kernel_switch_state();
+ bool kernel_switch_needed = kernel_switch_status == DEVICE_KERNEL_FEATURE_KERNEL_AVAILABLE ||
+ kernel_switch_status == DEVICE_KERNEL_FEATURE_KERNEL_INVALID;
+ if (kernel_switch_status == DEVICE_KERNEL_WAITING_FOR_FEATURE_KERNEL) {
+ progress.set_kernel_status("Compiling render kernels");
+ }
+ if (new_kernels_needed || kernel_switch_needed) {
+ progress.set_kernel_status("Compiling render kernels");
+ device->wait_for_availability(loaded_kernel_features);
+ progress.set_kernel_status("");
+ }
+
+ if (kernel_switch_needed) {
+ reset(tile_manager.params, params.samples);
+ }
+ return true;
+ }
+ return false;
}
void Session::update_status_time(bool show_pause, bool show_done)
{
- int progressive_sample = tile_manager.state.sample;
- int num_samples = tile_manager.get_num_effective_samples();
-
- int tile = progress.get_rendered_tiles();
- int num_tiles = tile_manager.state.num_tiles;
-
- /* update status */
- string status, substatus;
-
- if(!params.progressive) {
- const bool is_cpu = params.device.type == DEVICE_CPU;
- const bool rendering_finished = (tile == num_tiles);
- const bool is_last_tile = (tile + 1) == num_tiles;
-
- substatus = string_printf("Rendered %d/%d Tiles", tile, num_tiles);
-
- if(!rendering_finished && (device->show_samples() || (is_cpu && is_last_tile))) {
- /* Some devices automatically support showing the sample number:
- * - CUDADevice
- * - OpenCLDevice when using the megakernel (the split kernel renders multiple
- * samples at the same time, so the current sample isn't really defined)
- * - CPUDevice when using one thread
- * For these devices, the current sample is always shown.
- *
- * The other option is when the last tile is currently being rendered by the CPU.
- */
- substatus += string_printf(", Sample %d/%d", progress.get_current_sample(), num_samples);
- }
- if(params.full_denoising) {
- substatus += string_printf(", Denoised %d tiles", progress.get_denoised_tiles());
- }
- else if(params.run_denoising) {
- substatus += string_printf(", Prefiltered %d tiles", progress.get_denoised_tiles());
- }
- }
- else if(tile_manager.num_samples == INT_MAX)
- substatus = string_printf("Path Tracing Sample %d", progressive_sample+1);
- else
- substatus = string_printf("Path Tracing Sample %d/%d",
- progressive_sample+1,
- num_samples);
-
- if(show_pause) {
- status = "Rendering Paused";
- }
- else if(show_done) {
- status = "Rendering Done";
- progress.set_end_time(); /* Save end time so that further calls to get_time are accurate. */
- }
- else {
- status = substatus;
- substatus.clear();
- }
-
- progress.set_status(status, substatus);
+ int progressive_sample = tile_manager.state.sample;
+ int num_samples = tile_manager.get_num_effective_samples();
+
+ int tile = progress.get_rendered_tiles();
+ int num_tiles = tile_manager.state.num_tiles;
+
+ /* update status */
+ string status, substatus;
+
+ if (!params.progressive) {
+ const bool is_cpu = params.device.type == DEVICE_CPU;
+ const bool rendering_finished = (tile == num_tiles);
+ const bool is_last_tile = (tile + 1) == num_tiles;
+
+ substatus = string_printf("Rendered %d/%d Tiles", tile, num_tiles);
+
+ if (!rendering_finished && (device->show_samples() || (is_cpu && is_last_tile))) {
+ /* Some devices automatically support showing the sample number:
+ * - CUDADevice
+ * - OpenCLDevice when using the megakernel (the split kernel renders multiple
+ * samples at the same time, so the current sample isn't really defined)
+ * - CPUDevice when using one thread
+ * For these devices, the current sample is always shown.
+ *
+ * The other option is when the last tile is currently being rendered by the CPU.
+ */
+ substatus += string_printf(", Sample %d/%d", progress.get_current_sample(), num_samples);
+ }
+ if (params.full_denoising) {
+ substatus += string_printf(", Denoised %d tiles", progress.get_denoised_tiles());
+ }
+ else if (params.run_denoising) {
+ substatus += string_printf(", Prefiltered %d tiles", progress.get_denoised_tiles());
+ }
+ }
+ else if (tile_manager.num_samples == INT_MAX)
+ substatus = string_printf("Path Tracing Sample %d", progressive_sample + 1);
+ else
+ substatus = string_printf("Path Tracing Sample %d/%d", progressive_sample + 1, num_samples);
+
+ if (show_pause) {
+ status = "Rendering Paused";
+ }
+ else if (show_done) {
+ status = "Rendering Done";
+ progress.set_end_time(); /* Save end time so that further calls to get_time are accurate. */
+ }
+ else {
+ status = substatus;
+ substatus.clear();
+ }
+
+ progress.set_status(status, substatus);
}
void Session::render()
{
- /* Clear buffers. */
- if(buffers && tile_manager.state.sample == tile_manager.range_start_sample) {
- buffers->zero();
- }
-
- /* Add path trace task. */
- DeviceTask task(DeviceTask::RENDER);
-
- task.acquire_tile = function_bind(&Session::acquire_tile, this, _1, _2);
- task.release_tile = function_bind(&Session::release_tile, this, _1);
- task.map_neighbor_tiles = function_bind(&Session::map_neighbor_tiles, this, _1, _2);
- task.unmap_neighbor_tiles = function_bind(&Session::unmap_neighbor_tiles, this, _1, _2);
- task.get_cancel = function_bind(&Progress::get_cancel, &this->progress);
- task.update_tile_sample = function_bind(&Session::update_tile_sample, this, _1);
- task.update_progress_sample = function_bind(&Progress::add_samples, &this->progress, _1, _2);
- task.need_finish_queue = params.progressive_refine;
- task.integrator_branched = scene->integrator->method == Integrator::BRANCHED_PATH;
- task.requested_tile_size = params.tile_size;
- task.passes_size = tile_manager.params.get_passes_size();
-
- if(params.run_denoising) {
- task.denoising = params.denoising;
-
- assert(!scene->film->need_update);
- task.pass_stride = scene->film->pass_stride;
- task.target_pass_stride = task.pass_stride;
- task.pass_denoising_data = scene->film->denoising_data_offset;
- task.pass_denoising_clean = scene->film->denoising_clean_offset;
-
- task.denoising_from_render = true;
- task.denoising_do_filter = params.full_denoising;
- task.denoising_write_passes = params.write_denoising_passes;
- }
-
- device->task_add(task);
+ /* Clear buffers. */
+ if (buffers && tile_manager.state.sample == tile_manager.range_start_sample) {
+ buffers->zero();
+ }
+
+ /* Add path trace task. */
+ DeviceTask task(DeviceTask::RENDER);
+
+ task.acquire_tile = function_bind(&Session::acquire_tile, this, _1, _2);
+ task.release_tile = function_bind(&Session::release_tile, this, _1);
+ task.map_neighbor_tiles = function_bind(&Session::map_neighbor_tiles, this, _1, _2);
+ task.unmap_neighbor_tiles = function_bind(&Session::unmap_neighbor_tiles, this, _1, _2);
+ task.get_cancel = function_bind(&Progress::get_cancel, &this->progress);
+ task.update_tile_sample = function_bind(&Session::update_tile_sample, this, _1);
+ task.update_progress_sample = function_bind(&Progress::add_samples, &this->progress, _1, _2);
+ task.need_finish_queue = params.progressive_refine;
+ task.integrator_branched = scene->integrator->method == Integrator::BRANCHED_PATH;
+ task.requested_tile_size = params.tile_size;
+ task.passes_size = tile_manager.params.get_passes_size();
+
+ if (params.run_denoising) {
+ task.denoising = params.denoising;
+
+ assert(!scene->film->need_update);
+ task.pass_stride = scene->film->pass_stride;
+ task.target_pass_stride = task.pass_stride;
+ task.pass_denoising_data = scene->film->denoising_data_offset;
+ task.pass_denoising_clean = scene->film->denoising_clean_offset;
+
+ task.denoising_from_render = true;
+ task.denoising_do_filter = params.full_denoising;
+ task.denoising_write_passes = params.write_denoising_passes;
+ }
+
+ device->task_add(task);
}
void Session::tonemap(int sample)
{
- /* add tonemap task */
- DeviceTask task(DeviceTask::FILM_CONVERT);
-
- task.x = tile_manager.state.buffer.full_x;
- task.y = tile_manager.state.buffer.full_y;
- task.w = tile_manager.state.buffer.width;
- task.h = tile_manager.state.buffer.height;
- task.rgba_byte = display->rgba_byte.device_pointer;
- task.rgba_half = display->rgba_half.device_pointer;
- task.buffer = buffers->buffer.device_pointer;
- task.sample = sample;
- tile_manager.state.buffer.get_offset_stride(task.offset, task.stride);
-
- if(task.w > 0 && task.h > 0) {
- device->task_add(task);
- device->task_wait();
-
- /* set display to new size */
- display->draw_set(task.w, task.h);
- }
-
- display_outdated = false;
+ /* add tonemap task */
+ DeviceTask task(DeviceTask::FILM_CONVERT);
+
+ task.x = tile_manager.state.buffer.full_x;
+ task.y = tile_manager.state.buffer.full_y;
+ task.w = tile_manager.state.buffer.width;
+ task.h = tile_manager.state.buffer.height;
+ task.rgba_byte = display->rgba_byte.device_pointer;
+ task.rgba_half = display->rgba_half.device_pointer;
+ task.buffer = buffers->buffer.device_pointer;
+ task.sample = sample;
+ tile_manager.state.buffer.get_offset_stride(task.offset, task.stride);
+
+ if (task.w > 0 && task.h > 0) {
+ device->task_add(task);
+ device->task_wait();
+
+ /* set display to new size */
+ display->draw_set(task.w, task.h);
+ }
+
+ display_outdated = false;
}
bool Session::update_progressive_refine(bool cancel)
{
- int sample = tile_manager.state.sample + 1;
- bool write = sample == tile_manager.num_samples || cancel;
-
- double current_time = time_dt();
-
- if(current_time - last_update_time < params.progressive_update_timeout) {
- /* if last sample was processed, we need to write buffers anyway */
- if(!write && sample != 1)
- return false;
- }
-
- if(params.progressive_refine) {
- foreach(Tile& tile, tile_manager.state.tiles) {
- if(!tile.buffers) {
- continue;
- }
-
- RenderTile rtile;
- rtile.x = tile_manager.state.buffer.full_x + tile.x;
- rtile.y = tile_manager.state.buffer.full_y + tile.y;
- rtile.w = tile.w;
- rtile.h = tile.h;
- rtile.sample = sample;
- rtile.buffers = tile.buffers;
-
- if(write) {
- if(write_render_tile_cb)
- write_render_tile_cb(rtile);
- }
- else {
- if(update_render_tile_cb)
- update_render_tile_cb(rtile, true);
- }
- }
- }
-
- last_update_time = current_time;
-
- return write;
+ int sample = tile_manager.state.sample + 1;
+ bool write = sample == tile_manager.num_samples || cancel;
+
+ double current_time = time_dt();
+
+ if (current_time - last_update_time < params.progressive_update_timeout) {
+ /* if last sample was processed, we need to write buffers anyway */
+ if (!write && sample != 1)
+ return false;
+ }
+
+ if (params.progressive_refine) {
+ foreach (Tile &tile, tile_manager.state.tiles) {
+ if (!tile.buffers) {
+ continue;
+ }
+
+ RenderTile rtile;
+ rtile.x = tile_manager.state.buffer.full_x + tile.x;
+ rtile.y = tile_manager.state.buffer.full_y + tile.y;
+ rtile.w = tile.w;
+ rtile.h = tile.h;
+ rtile.sample = sample;
+ rtile.buffers = tile.buffers;
+
+ if (write) {
+ if (write_render_tile_cb)
+ write_render_tile_cb(rtile);
+ }
+ else {
+ if (update_render_tile_cb)
+ update_render_tile_cb(rtile, true);
+ }
+ }
+ }
+
+ last_update_time = current_time;
+
+ return write;
}
void Session::device_free()
{
- scene->device_free();
+ scene->device_free();
- tile_manager.device_free();
+ tile_manager.device_free();
- /* used from background render only, so no need to
- * re-create render/display buffers here
- */
+ /* used from background render only, so no need to
+ * re-create render/display buffers here
+ */
}
void Session::collect_statistics(RenderStats *render_stats)
{
- scene->collect_statistics(render_stats);
- if(params.use_profiling && (params.device.type == DEVICE_CPU)) {
- render_stats->collect_profiling(scene, profiler);
- }
+ scene->collect_statistics(render_stats);
+ if (params.use_profiling && (params.device.type == DEVICE_CPU)) {
+ render_stats->collect_profiling(scene, profiler);
+ }
}
int Session::get_max_closure_count()
{
- if (scene->shader_manager->use_osl()) {
- /* OSL always needs the maximum as we can't predict the
- * number of closures a shader might generate. */
- return MAX_CLOSURE;
- }
-
- int max_closures = 0;
- for(int i = 0; i < scene->shaders.size(); i++) {
- int num_closures = scene->shaders[i]->graph->get_num_closures();
- max_closures = max(max_closures, num_closures);
- }
- max_closure_global = max(max_closure_global, max_closures);
-
- if (max_closure_global > MAX_CLOSURE) {
- /* This is usually harmless as more complex shader tend to get many
- * closures discarded due to mixing or low weights. We need to limit
- * to MAX_CLOSURE as this is hardcoded in CPU/mega kernels, and it
- * avoids excessive memory usage for split kernels. */
- VLOG(2) << "Maximum number of closures exceeded: "
- << max_closure_global
- << " > "
- << MAX_CLOSURE;
-
- max_closure_global = MAX_CLOSURE;
- }
-
- return max_closure_global;
+ if (scene->shader_manager->use_osl()) {
+ /* OSL always needs the maximum as we can't predict the
+ * number of closures a shader might generate. */
+ return MAX_CLOSURE;
+ }
+
+ int max_closures = 0;
+ for (int i = 0; i < scene->shaders.size(); i++) {
+ int num_closures = scene->shaders[i]->graph->get_num_closures();
+ max_closures = max(max_closures, num_closures);
+ }
+ max_closure_global = max(max_closure_global, max_closures);
+
+ if (max_closure_global > MAX_CLOSURE) {
+ /* This is usually harmless as more complex shader tend to get many
+ * closures discarded due to mixing or low weights. We need to limit
+ * to MAX_CLOSURE as this is hardcoded in CPU/mega kernels, and it
+ * avoids excessive memory usage for split kernels. */
+ VLOG(2) << "Maximum number of closures exceeded: " << max_closure_global << " > "
+ << MAX_CLOSURE;
+
+ max_closure_global = MAX_CLOSURE;
+ }
+
+ return max_closure_global;
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/render/session.h b/intern/cycles/render/session.h
index 404b7b7a945..60d8f7a8b14 100644
--- a/intern/cycles/render/session.h
+++ b/intern/cycles/render/session.h
@@ -42,91 +42,83 @@ class Scene;
/* Session Parameters */
class SessionParams {
-public:
- DeviceInfo device;
- bool background;
- bool progressive_refine;
-
- bool progressive;
- bool experimental;
- int samples;
- int2 tile_size;
- TileOrder tile_order;
- int start_resolution;
- int pixel_size;
- int threads;
-
- bool use_profiling;
-
- bool display_buffer_linear;
-
- bool run_denoising;
- bool write_denoising_passes;
- bool full_denoising;
- DenoiseParams denoising;
-
- double cancel_timeout;
- double reset_timeout;
- double text_timeout;
- double progressive_update_timeout;
-
- ShadingSystem shadingsystem;
-
- function<bool(const uchar *pixels,
- int width,
- int height,
- int channels)> write_render_cb;
-
- SessionParams()
- {
- background = false;
- progressive_refine = false;
-
- progressive = false;
- experimental = false;
- samples = 1024;
- tile_size = make_int2(64, 64);
- start_resolution = INT_MAX;
- pixel_size = 1;
- threads = 0;
-
- use_profiling = false;
-
- run_denoising = false;
- write_denoising_passes = false;
- full_denoising = false;
-
- display_buffer_linear = false;
-
- cancel_timeout = 0.1;
- reset_timeout = 0.1;
- text_timeout = 1.0;
- progressive_update_timeout = 1.0;
-
- shadingsystem = SHADINGSYSTEM_SVM;
- tile_order = TILE_CENTER;
- }
-
- bool modified(const SessionParams& params)
- { return !(device == params.device
- && background == params.background
- && progressive_refine == params.progressive_refine
- /* && samples == params.samples */
- && progressive == params.progressive
- && experimental == params.experimental
- && tile_size == params.tile_size
- && start_resolution == params.start_resolution
- && pixel_size == params.pixel_size
- && threads == params.threads
- && use_profiling == params.use_profiling
- && display_buffer_linear == params.display_buffer_linear
- && cancel_timeout == params.cancel_timeout
- && reset_timeout == params.reset_timeout
- && text_timeout == params.text_timeout
- && progressive_update_timeout == params.progressive_update_timeout
- && tile_order == params.tile_order
- && shadingsystem == params.shadingsystem); }
-
+ public:
+ DeviceInfo device;
+ bool background;
+ bool progressive_refine;
+
+ bool progressive;
+ bool experimental;
+ int samples;
+ int2 tile_size;
+ TileOrder tile_order;
+ int start_resolution;
+ int pixel_size;
+ int threads;
+
+ bool use_profiling;
+
+ bool display_buffer_linear;
+
+ bool run_denoising;
+ bool write_denoising_passes;
+ bool full_denoising;
+ DenoiseParams denoising;
+
+ double cancel_timeout;
+ double reset_timeout;
+ double text_timeout;
+ double progressive_update_timeout;
+
+ ShadingSystem shadingsystem;
+
+ function<bool(const uchar *pixels, int width, int height, int channels)> write_render_cb;
+
+ SessionParams()
+ {
+ background = false;
+ progressive_refine = false;
+
+ progressive = false;
+ experimental = false;
+ samples = 1024;
+ tile_size = make_int2(64, 64);
+ start_resolution = INT_MAX;
+ pixel_size = 1;
+ threads = 0;
+
+ use_profiling = false;
+
+ run_denoising = false;
+ write_denoising_passes = false;
+ full_denoising = false;
+
+ display_buffer_linear = false;
+
+ cancel_timeout = 0.1;
+ reset_timeout = 0.1;
+ text_timeout = 1.0;
+ progressive_update_timeout = 1.0;
+
+ shadingsystem = SHADINGSYSTEM_SVM;
+ tile_order = TILE_CENTER;
+ }
+
+ bool modified(const SessionParams &params)
+ {
+ return !(device == params.device && background == params.background &&
+ progressive_refine == params.progressive_refine
+ /* && samples == params.samples */
+ && progressive == params.progressive && experimental == params.experimental &&
+ tile_size == params.tile_size && start_resolution == params.start_resolution &&
+ pixel_size == params.pixel_size && threads == params.threads &&
+ use_profiling == params.use_profiling &&
+ display_buffer_linear == params.display_buffer_linear &&
+ cancel_timeout == params.cancel_timeout && reset_timeout == params.reset_timeout &&
+ text_timeout == params.text_timeout &&
+ progressive_update_timeout == params.progressive_update_timeout &&
+ tile_order == params.tile_order && shadingsystem == params.shadingsystem);
+ }
};
/* Session
@@ -135,111 +127,111 @@ public:
* control loop and dispatching tasks. */
class Session {
-public:
- Device *device;
- Scene *scene;
- RenderBuffers *buffers;
- DisplayBuffer *display;
- Progress progress;
- SessionParams params;
- TileManager tile_manager;
- Stats stats;
- Profiler profiler;
+ public:
+ Device *device;
+ Scene *scene;
+ RenderBuffers *buffers;
+ DisplayBuffer *display;
+ Progress progress;
+ SessionParams params;
+ TileManager tile_manager;
+ Stats stats;
+ Profiler profiler;
- function<void(RenderTile&)> write_render_tile_cb;
- function<void(RenderTile&, bool)> update_render_tile_cb;
+ function<void(RenderTile &)> write_render_tile_cb;
+ function<void(RenderTile &, bool)> update_render_tile_cb;
- explicit Session(const SessionParams& params);
- ~Session();
+ explicit Session(const SessionParams &params);
+ ~Session();
- void start();
- bool draw(BufferParams& params, DeviceDrawParams& draw_params);
- void wait();
+ void start();
+ bool draw(BufferParams &params, DeviceDrawParams &draw_params);
+ void wait();
- bool ready_to_reset();
- void reset(BufferParams& params, int samples);
- void set_samples(int samples);
- void set_pause(bool pause);
+ bool ready_to_reset();
+ void reset(BufferParams &params, int samples);
+ void set_samples(int samples);
+ void set_pause(bool pause);
- bool update_scene();
- bool load_kernels(bool lock_scene=true);
+ bool update_scene();
+ bool load_kernels(bool lock_scene = true);
- void device_free();
+ void device_free();
- /* Returns the rendering progress or 0 if no progress can be determined
- * (for example, when rendering with unlimited samples). */
- float get_progress();
+ /* Returns the rendering progress or 0 if no progress can be determined
+ * (for example, when rendering with unlimited samples). */
+ float get_progress();
- void collect_statistics(RenderStats *stats);
+ void collect_statistics(RenderStats *stats);
-protected:
- struct DelayedReset {
- thread_mutex mutex;
- bool do_reset;
- BufferParams params;
- int samples;
- } delayed_reset;
+ protected:
+ struct DelayedReset {
+ thread_mutex mutex;
+ bool do_reset;
+ BufferParams params;
+ int samples;
+ } delayed_reset;
- void run();
+ void run();
- void update_status_time(bool show_pause = false, bool show_done = false);
+ void update_status_time(bool show_pause = false, bool show_done = false);
- void tonemap(int sample);
- void render();
- void reset_(BufferParams& params, int samples);
+ void tonemap(int sample);
+ void render();
+ void reset_(BufferParams &params, int samples);
- void run_cpu();
- bool draw_cpu(BufferParams& params, DeviceDrawParams& draw_params);
- void reset_cpu(BufferParams& params, int samples);
+ void run_cpu();
+ bool draw_cpu(BufferParams &params, DeviceDrawParams &draw_params);
+ void reset_cpu(BufferParams &params, int samples);
- void run_gpu();
- bool draw_gpu(BufferParams& params, DeviceDrawParams& draw_params);
- void reset_gpu(BufferParams& params, int samples);
+ void run_gpu();
+ bool draw_gpu(BufferParams &params, DeviceDrawParams &draw_params);
+ void reset_gpu(BufferParams &params, int samples);
- bool acquire_tile(Device *tile_device, RenderTile& tile);
- void update_tile_sample(RenderTile& tile);
- void release_tile(RenderTile& tile);
+ bool acquire_tile(Device *tile_device, RenderTile &tile);
+ void update_tile_sample(RenderTile &tile);
+ void release_tile(RenderTile &tile);
- void map_neighbor_tiles(RenderTile *tiles, Device *tile_device);
- void unmap_neighbor_tiles(RenderTile *tiles, Device *tile_device);
+ void map_neighbor_tiles(RenderTile *tiles, Device *tile_device);
+ void unmap_neighbor_tiles(RenderTile *tiles, Device *tile_device);
- bool device_use_gl;
+ bool device_use_gl;
- thread *session_thread;
+ thread *session_thread;
- volatile bool display_outdated;
+ volatile bool display_outdated;
- volatile bool gpu_draw_ready;
- volatile bool gpu_need_tonemap;
- thread_condition_variable gpu_need_tonemap_cond;
+ volatile bool gpu_draw_ready;
+ volatile bool gpu_need_tonemap;
+ thread_condition_variable gpu_need_tonemap_cond;
- bool pause;
- thread_condition_variable pause_cond;
- thread_mutex pause_mutex;
- thread_mutex tile_mutex;
- thread_mutex buffers_mutex;
- thread_mutex display_mutex;
+ bool pause;
+ thread_condition_variable pause_cond;
+ thread_mutex pause_mutex;
+ thread_mutex tile_mutex;
+ thread_mutex buffers_mutex;
+ thread_mutex display_mutex;
- bool kernels_loaded;
- DeviceRequestedFeatures loaded_kernel_features;
+ bool kernels_loaded;
+ DeviceRequestedFeatures loaded_kernel_features;
- double reset_time;
+ double reset_time;
- /* progressive refine */
- double last_update_time;
- bool update_progressive_refine(bool cancel);
+ /* progressive refine */
+ double last_update_time;
+ bool update_progressive_refine(bool cancel);
- DeviceRequestedFeatures get_requested_device_features();
+ DeviceRequestedFeatures get_requested_device_features();
- /* ** Split kernel routines ** */
+ /* ** Split kernel routines ** */
- /* Maximumnumber of closure during session lifetime. */
- int max_closure_global;
+ /* Maximumnumber of closure during session lifetime. */
+ int max_closure_global;
- /* Get maximum number of closures to be used in kernel. */
- int get_max_closure_count();
+ /* Get maximum number of closures to be used in kernel. */
+ int get_max_closure_count();
};
CCL_NAMESPACE_END
-#endif /* __SESSION_H__ */
+#endif /* __SESSION_H__ */
diff --git a/intern/cycles/render/shader.cpp b/intern/cycles/render/shader.cpp
index 3c94f2dfb59..ac3303cbfeb 100644
--- a/intern/cycles/render/shader.cpp
+++ b/intern/cycles/render/shader.cpp
@@ -48,16 +48,15 @@ bool ShaderManager::beckmann_table_ready = false;
/* 2D slope distribution (alpha = 1.0) */
static float beckmann_table_P22(const float slope_x, const float slope_y)
{
- return expf(-(slope_x*slope_x + slope_y*slope_y));
+ return expf(-(slope_x * slope_x + slope_y * slope_y));
}
/* maximal slope amplitude (range that contains 99.99% of the distribution) */
static float beckmann_table_slope_max()
{
- return 6.0;
+ return 6.0;
}
-
/* MSVC 2015 needs this ugly hack to prevent a codegen bug on x86
* see T50176 for details
*/
@@ -74,327 +73,331 @@ static float beckmann_table_slope_max()
*/
static void beckmann_table_rows(float *table, int row_from, int row_to)
{
- /* allocate temporary data */
- const int DATA_TMP_SIZE = 512;
- vector<double> slope_x(DATA_TMP_SIZE);
- vector<double> CDF_P22_omega_i(DATA_TMP_SIZE);
-
- /* loop over incident directions */
- for(int index_theta = row_from; index_theta < row_to; index_theta++) {
- /* incident vector */
- const float cos_theta = index_theta / (BECKMANN_TABLE_SIZE - 1.0f);
- const float sin_theta = safe_sqrtf(1.0f - cos_theta*cos_theta);
-
- /* for a given incident vector
- * integrate P22_{omega_i}(x_slope, 1, 1), Eq. (10) */
- slope_x[0] = (double)-beckmann_table_slope_max();
- CDF_P22_omega_i[0] = 0;
-
- for(MSVC_VOLATILE int index_slope_x = 1; index_slope_x < DATA_TMP_SIZE; ++index_slope_x) {
- /* slope_x */
- slope_x[index_slope_x] = (double)(-beckmann_table_slope_max() + 2.0f * beckmann_table_slope_max() * index_slope_x/(DATA_TMP_SIZE - 1.0f));
-
- /* dot product with incident vector */
- float dot_product = fmaxf(0.0f, -(float)slope_x[index_slope_x]*sin_theta + cos_theta);
- /* marginalize P22_{omega_i}(x_slope, 1, 1), Eq. (10) */
- float P22_omega_i = 0.0f;
-
- for(int j = 0; j < 100; ++j) {
- float slope_y = -beckmann_table_slope_max() + 2.0f * beckmann_table_slope_max() * j * (1.0f/99.0f);
- P22_omega_i += dot_product * beckmann_table_P22((float)slope_x[index_slope_x], slope_y);
- }
-
- /* CDF of P22_{omega_i}(x_slope, 1, 1), Eq. (10) */
- CDF_P22_omega_i[index_slope_x] = CDF_P22_omega_i[index_slope_x - 1] + (double)P22_omega_i;
- }
-
- /* renormalize CDF_P22_omega_i */
- for(int index_slope_x = 1; index_slope_x < DATA_TMP_SIZE; ++index_slope_x)
- CDF_P22_omega_i[index_slope_x] /= CDF_P22_omega_i[DATA_TMP_SIZE - 1];
-
- /* loop over random number U1 */
- int index_slope_x = 0;
-
- for(int index_U = 0; index_U < BECKMANN_TABLE_SIZE; ++index_U) {
- const double U = 0.0000001 + 0.9999998 * index_U / (double)(BECKMANN_TABLE_SIZE - 1);
-
- /* inverse CDF_P22_omega_i, solve Eq.(11) */
- while(CDF_P22_omega_i[index_slope_x] <= U)
- ++index_slope_x;
-
- const double interp =
- (CDF_P22_omega_i[index_slope_x] - U) /
- (CDF_P22_omega_i[index_slope_x] - CDF_P22_omega_i[index_slope_x - 1]);
-
- /* store value */
- table[index_U + index_theta*BECKMANN_TABLE_SIZE] = (float)(
- interp * slope_x[index_slope_x - 1] +
- (1.0 - interp) * slope_x[index_slope_x]);
- }
- }
+ /* allocate temporary data */
+ const int DATA_TMP_SIZE = 512;
+ vector<double> slope_x(DATA_TMP_SIZE);
+ vector<double> CDF_P22_omega_i(DATA_TMP_SIZE);
+
+ /* loop over incident directions */
+ for (int index_theta = row_from; index_theta < row_to; index_theta++) {
+ /* incident vector */
+ const float cos_theta = index_theta / (BECKMANN_TABLE_SIZE - 1.0f);
+ const float sin_theta = safe_sqrtf(1.0f - cos_theta * cos_theta);
+
+ /* for a given incident vector
+ * integrate P22_{omega_i}(x_slope, 1, 1), Eq. (10) */
+ slope_x[0] = (double)-beckmann_table_slope_max();
+ CDF_P22_omega_i[0] = 0;
+
+ for (MSVC_VOLATILE int index_slope_x = 1; index_slope_x < DATA_TMP_SIZE; ++index_slope_x) {
+ /* slope_x */
+ slope_x[index_slope_x] = (double)(-beckmann_table_slope_max() +
+ 2.0f * beckmann_table_slope_max() * index_slope_x /
+ (DATA_TMP_SIZE - 1.0f));
+
+ /* dot product with incident vector */
+ float dot_product = fmaxf(0.0f, -(float)slope_x[index_slope_x] * sin_theta + cos_theta);
+ /* marginalize P22_{omega_i}(x_slope, 1, 1), Eq. (10) */
+ float P22_omega_i = 0.0f;
+
+ for (int j = 0; j < 100; ++j) {
+ float slope_y = -beckmann_table_slope_max() +
+ 2.0f * beckmann_table_slope_max() * j * (1.0f / 99.0f);
+ P22_omega_i += dot_product * beckmann_table_P22((float)slope_x[index_slope_x], slope_y);
+ }
+
+ /* CDF of P22_{omega_i}(x_slope, 1, 1), Eq. (10) */
+ CDF_P22_omega_i[index_slope_x] = CDF_P22_omega_i[index_slope_x - 1] + (double)P22_omega_i;
+ }
+
+ /* renormalize CDF_P22_omega_i */
+ for (int index_slope_x = 1; index_slope_x < DATA_TMP_SIZE; ++index_slope_x)
+ CDF_P22_omega_i[index_slope_x] /= CDF_P22_omega_i[DATA_TMP_SIZE - 1];
+
+ /* loop over random number U1 */
+ int index_slope_x = 0;
+
+ for (int index_U = 0; index_U < BECKMANN_TABLE_SIZE; ++index_U) {
+ const double U = 0.0000001 + 0.9999998 * index_U / (double)(BECKMANN_TABLE_SIZE - 1);
+
+ /* inverse CDF_P22_omega_i, solve Eq.(11) */
+ while (CDF_P22_omega_i[index_slope_x] <= U)
+ ++index_slope_x;
+
+ const double interp = (CDF_P22_omega_i[index_slope_x] - U) /
+ (CDF_P22_omega_i[index_slope_x] - CDF_P22_omega_i[index_slope_x - 1]);
+
+ /* store value */
+ table[index_U + index_theta * BECKMANN_TABLE_SIZE] =
+ (float)(interp * slope_x[index_slope_x - 1] + (1.0 - interp) * slope_x[index_slope_x]);
+ }
+ }
}
#undef MSVC_VOLATILE
-static void beckmann_table_build(vector<float>& table)
+static void beckmann_table_build(vector<float> &table)
{
- table.resize(BECKMANN_TABLE_SIZE*BECKMANN_TABLE_SIZE);
+ table.resize(BECKMANN_TABLE_SIZE * BECKMANN_TABLE_SIZE);
- /* multithreaded build */
- TaskPool pool;
+ /* multithreaded build */
+ TaskPool pool;
- for(int i = 0; i < BECKMANN_TABLE_SIZE; i+=8)
- pool.push(function_bind(&beckmann_table_rows, &table[0], i, i+8));
+ for (int i = 0; i < BECKMANN_TABLE_SIZE; i += 8)
+ pool.push(function_bind(&beckmann_table_rows, &table[0], i, i + 8));
- pool.wait_work();
+ pool.wait_work();
}
/* Shader */
NODE_DEFINE(Shader)
{
- NodeType* type = NodeType::add("shader", create);
-
- SOCKET_BOOLEAN(use_mis, "Use MIS", true);
- SOCKET_BOOLEAN(use_transparent_shadow, "Use Transparent Shadow", true);
- SOCKET_BOOLEAN(heterogeneous_volume, "Heterogeneous Volume", true);
-
- static NodeEnum volume_sampling_method_enum;
- volume_sampling_method_enum.insert("distance", VOLUME_SAMPLING_DISTANCE);
- volume_sampling_method_enum.insert("equiangular", VOLUME_SAMPLING_EQUIANGULAR);
- volume_sampling_method_enum.insert("multiple_importance", VOLUME_SAMPLING_MULTIPLE_IMPORTANCE);
- SOCKET_ENUM(volume_sampling_method, "Volume Sampling Method", volume_sampling_method_enum, VOLUME_SAMPLING_DISTANCE);
-
- static NodeEnum volume_interpolation_method_enum;
- volume_interpolation_method_enum.insert("linear", VOLUME_INTERPOLATION_LINEAR);
- volume_interpolation_method_enum.insert("cubic", VOLUME_INTERPOLATION_CUBIC);
- SOCKET_ENUM(volume_interpolation_method, "Volume Interpolation Method", volume_interpolation_method_enum, VOLUME_INTERPOLATION_LINEAR);
-
- static NodeEnum displacement_method_enum;
- displacement_method_enum.insert("bump", DISPLACE_BUMP);
- displacement_method_enum.insert("true", DISPLACE_TRUE);
- displacement_method_enum.insert("both", DISPLACE_BOTH);
- SOCKET_ENUM(displacement_method, "Displacement Method", displacement_method_enum, DISPLACE_BUMP);
-
- return type;
+ NodeType *type = NodeType::add("shader", create);
+
+ SOCKET_BOOLEAN(use_mis, "Use MIS", true);
+ SOCKET_BOOLEAN(use_transparent_shadow, "Use Transparent Shadow", true);
+ SOCKET_BOOLEAN(heterogeneous_volume, "Heterogeneous Volume", true);
+
+ static NodeEnum volume_sampling_method_enum;
+ volume_sampling_method_enum.insert("distance", VOLUME_SAMPLING_DISTANCE);
+ volume_sampling_method_enum.insert("equiangular", VOLUME_SAMPLING_EQUIANGULAR);
+ volume_sampling_method_enum.insert("multiple_importance", VOLUME_SAMPLING_MULTIPLE_IMPORTANCE);
+ SOCKET_ENUM(volume_sampling_method,
+ "Volume Sampling Method",
+ volume_sampling_method_enum,
+ VOLUME_SAMPLING_DISTANCE);
+
+ static NodeEnum volume_interpolation_method_enum;
+ volume_interpolation_method_enum.insert("linear", VOLUME_INTERPOLATION_LINEAR);
+ volume_interpolation_method_enum.insert("cubic", VOLUME_INTERPOLATION_CUBIC);
+ SOCKET_ENUM(volume_interpolation_method,
+ "Volume Interpolation Method",
+ volume_interpolation_method_enum,
+ VOLUME_INTERPOLATION_LINEAR);
+
+ static NodeEnum displacement_method_enum;
+ displacement_method_enum.insert("bump", DISPLACE_BUMP);
+ displacement_method_enum.insert("true", DISPLACE_TRUE);
+ displacement_method_enum.insert("both", DISPLACE_BOTH);
+ SOCKET_ENUM(displacement_method, "Displacement Method", displacement_method_enum, DISPLACE_BUMP);
+
+ return type;
}
-Shader::Shader()
-: Node(node_type)
+Shader::Shader() : Node(node_type)
{
- pass_id = 0;
-
- graph = NULL;
-
- has_surface = false;
- has_surface_transparent = false;
- has_surface_emission = false;
- has_surface_bssrdf = false;
- has_volume = false;
- has_displacement = false;
- has_bump = false;
- has_bssrdf_bump = false;
- has_surface_spatial_varying = false;
- has_volume_spatial_varying = false;
- has_object_dependency = false;
- has_attribute_dependency = false;
- has_integrator_dependency = false;
- has_volume_connected = false;
-
- displacement_method = DISPLACE_BUMP;
-
- id = -1;
- used = false;
-
- need_update = true;
- need_update_mesh = true;
- need_sync_object = false;
+ pass_id = 0;
+
+ graph = NULL;
+
+ has_surface = false;
+ has_surface_transparent = false;
+ has_surface_emission = false;
+ has_surface_bssrdf = false;
+ has_volume = false;
+ has_displacement = false;
+ has_bump = false;
+ has_bssrdf_bump = false;
+ has_surface_spatial_varying = false;
+ has_volume_spatial_varying = false;
+ has_object_dependency = false;
+ has_attribute_dependency = false;
+ has_integrator_dependency = false;
+ has_volume_connected = false;
+
+ displacement_method = DISPLACE_BUMP;
+
+ id = -1;
+ used = false;
+
+ need_update = true;
+ need_update_mesh = true;
+ need_sync_object = false;
}
Shader::~Shader()
{
- delete graph;
+ delete graph;
}
bool Shader::is_constant_emission(float3 *emission)
{
- ShaderInput *surf = graph->output()->input("Surface");
+ ShaderInput *surf = graph->output()->input("Surface");
- if(surf->link == NULL) {
- return false;
- }
+ if (surf->link == NULL) {
+ return false;
+ }
- if(surf->link->parent->type == EmissionNode::node_type) {
- EmissionNode *node = (EmissionNode*) surf->link->parent;
+ if (surf->link->parent->type == EmissionNode::node_type) {
+ EmissionNode *node = (EmissionNode *)surf->link->parent;
- assert(node->input("Color"));
- assert(node->input("Strength"));
+ assert(node->input("Color"));
+ assert(node->input("Strength"));
- if(node->input("Color")->link || node->input("Strength")->link) {
- return false;
- }
+ if (node->input("Color")->link || node->input("Strength")->link) {
+ return false;
+ }
- *emission = node->color*node->strength;
- }
- else if(surf->link->parent->type == BackgroundNode::node_type) {
- BackgroundNode *node = (BackgroundNode*) surf->link->parent;
+ *emission = node->color * node->strength;
+ }
+ else if (surf->link->parent->type == BackgroundNode::node_type) {
+ BackgroundNode *node = (BackgroundNode *)surf->link->parent;
- assert(node->input("Color"));
- assert(node->input("Strength"));
+ assert(node->input("Color"));
+ assert(node->input("Strength"));
- if(node->input("Color")->link || node->input("Strength")->link) {
- return false;
- }
+ if (node->input("Color")->link || node->input("Strength")->link) {
+ return false;
+ }
- *emission = node->color*node->strength;
- }
- else {
- return false;
- }
+ *emission = node->color * node->strength;
+ }
+ else {
+ return false;
+ }
- return true;
+ return true;
}
void Shader::set_graph(ShaderGraph *graph_)
{
- /* do this here already so that we can detect if mesh or object attributes
- * are needed, since the node attribute callbacks check if their sockets
- * are connected but proxy nodes should not count */
- if(graph_) {
- graph_->remove_proxy_nodes();
-
- if(displacement_method != DISPLACE_BUMP) {
- graph_->compute_displacement_hash();
- }
- }
-
- /* update geometry if displacement changed */
- if(displacement_method != DISPLACE_BUMP) {
- const char *old_hash = (graph)? graph->displacement_hash.c_str() : "";
- const char *new_hash = (graph_)? graph_->displacement_hash.c_str() : "";
-
- if(strcmp(old_hash, new_hash) != 0) {
- need_update_mesh = true;
- }
- }
-
- /* assign graph */
- delete graph;
- graph = graph_;
-
- /* Store info here before graph optimization to make sure that
- * nodes that get optimized away still count. */
- has_volume_connected = (graph->output()->input("Volume")->link != NULL);
+ /* do this here already so that we can detect if mesh or object attributes
+ * are needed, since the node attribute callbacks check if their sockets
+ * are connected but proxy nodes should not count */
+ if (graph_) {
+ graph_->remove_proxy_nodes();
+
+ if (displacement_method != DISPLACE_BUMP) {
+ graph_->compute_displacement_hash();
+ }
+ }
+
+ /* update geometry if displacement changed */
+ if (displacement_method != DISPLACE_BUMP) {
+ const char *old_hash = (graph) ? graph->displacement_hash.c_str() : "";
+ const char *new_hash = (graph_) ? graph_->displacement_hash.c_str() : "";
+
+ if (strcmp(old_hash, new_hash) != 0) {
+ need_update_mesh = true;
+ }
+ }
+
+ /* assign graph */
+ delete graph;
+ graph = graph_;
+
+ /* Store info here before graph optimization to make sure that
+ * nodes that get optimized away still count. */
+ has_volume_connected = (graph->output()->input("Volume")->link != NULL);
}
void Shader::tag_update(Scene *scene)
{
- /* update tag */
- need_update = true;
- scene->shader_manager->need_update = true;
-
- /* if the shader previously was emissive, update light distribution,
- * if the new shader is emissive, a light manager update tag will be
- * done in the shader manager device update. */
- if(use_mis && has_surface_emission)
- scene->light_manager->need_update = true;
-
- /* Special handle of background MIS light for now: for some reason it
- * has use_mis set to false. We are quite close to release now, so
- * better to be safe.
- */
- if(this == scene->default_background &&
- scene->light_manager->has_background_light(scene))
- {
- scene->light_manager->need_update = true;
- }
-
- /* quick detection of which kind of shaders we have to avoid loading
- * e.g. surface attributes when there is only a volume shader. this could
- * be more fine grained but it's better than nothing */
- OutputNode *output = graph->output();
- bool prev_has_volume = has_volume;
- has_surface = has_surface || output->input("Surface")->link;
- has_volume = has_volume || output->input("Volume")->link;
- has_displacement = has_displacement || output->input("Displacement")->link;
-
- /* get requested attributes. this could be optimized by pruning unused
- * nodes here already, but that's the job of the shader manager currently,
- * and may not be so great for interactive rendering where you temporarily
- * disconnect a node */
-
- AttributeRequestSet prev_attributes = attributes;
-
- attributes.clear();
- foreach(ShaderNode *node, graph->nodes)
- node->attributes(this, &attributes);
-
- if(has_displacement && displacement_method == DISPLACE_BOTH) {
- attributes.add(ATTR_STD_POSITION_UNDISPLACED);
- }
-
- /* compare if the attributes changed, mesh manager will check
- * need_update_mesh, update the relevant meshes and clear it. */
- if(attributes.modified(prev_attributes)) {
- need_update_mesh = true;
- scene->mesh_manager->need_update = true;
- }
-
- if(has_volume != prev_has_volume) {
- scene->mesh_manager->need_flags_update = true;
- scene->object_manager->need_flags_update = true;
- }
+ /* update tag */
+ need_update = true;
+ scene->shader_manager->need_update = true;
+
+ /* if the shader previously was emissive, update light distribution,
+ * if the new shader is emissive, a light manager update tag will be
+ * done in the shader manager device update. */
+ if (use_mis && has_surface_emission)
+ scene->light_manager->need_update = true;
+
+ /* Special handle of background MIS light for now: for some reason it
+ * has use_mis set to false. We are quite close to release now, so
+ * better to be safe.
+ */
+ if (this == scene->default_background && scene->light_manager->has_background_light(scene)) {
+ scene->light_manager->need_update = true;
+ }
+
+ /* quick detection of which kind of shaders we have to avoid loading
+ * e.g. surface attributes when there is only a volume shader. this could
+ * be more fine grained but it's better than nothing */
+ OutputNode *output = graph->output();
+ bool prev_has_volume = has_volume;
+ has_surface = has_surface || output->input("Surface")->link;
+ has_volume = has_volume || output->input("Volume")->link;
+ has_displacement = has_displacement || output->input("Displacement")->link;
+
+ /* get requested attributes. this could be optimized by pruning unused
+ * nodes here already, but that's the job of the shader manager currently,
+ * and may not be so great for interactive rendering where you temporarily
+ * disconnect a node */
+
+ AttributeRequestSet prev_attributes = attributes;
+
+ attributes.clear();
+ foreach (ShaderNode *node, graph->nodes)
+ node->attributes(this, &attributes);
+
+ if (has_displacement && displacement_method == DISPLACE_BOTH) {
+ attributes.add(ATTR_STD_POSITION_UNDISPLACED);
+ }
+
+ /* compare if the attributes changed, mesh manager will check
+ * need_update_mesh, update the relevant meshes and clear it. */
+ if (attributes.modified(prev_attributes)) {
+ need_update_mesh = true;
+ scene->mesh_manager->need_update = true;
+ }
+
+ if (has_volume != prev_has_volume) {
+ scene->mesh_manager->need_flags_update = true;
+ scene->object_manager->need_flags_update = true;
+ }
}
void Shader::tag_used(Scene *scene)
{
- /* if an unused shader suddenly gets used somewhere, it needs to be
- * recompiled because it was skipped for compilation before */
- if(!used) {
- need_update = true;
- scene->shader_manager->need_update = true;
- }
+ /* if an unused shader suddenly gets used somewhere, it needs to be
+ * recompiled because it was skipped for compilation before */
+ if (!used) {
+ need_update = true;
+ scene->shader_manager->need_update = true;
+ }
}
/* Shader Manager */
ShaderManager::ShaderManager()
{
- need_update = true;
- beckmann_table_offset = TABLE_OFFSET_INVALID;
+ need_update = true;
+ beckmann_table_offset = TABLE_OFFSET_INVALID;
- xyz_to_r = make_float3( 3.2404542f, -1.5371385f, -0.4985314f);
- xyz_to_g = make_float3(-0.9692660f, 1.8760108f, 0.0415560f);
- xyz_to_b = make_float3( 0.0556434f, -0.2040259f, 1.0572252f);
- rgb_to_y = make_float3( 0.2126729f, 0.7151522f, 0.0721750f);
+ xyz_to_r = make_float3(3.2404542f, -1.5371385f, -0.4985314f);
+ xyz_to_g = make_float3(-0.9692660f, 1.8760108f, 0.0415560f);
+ xyz_to_b = make_float3(0.0556434f, -0.2040259f, 1.0572252f);
+ rgb_to_y = make_float3(0.2126729f, 0.7151522f, 0.0721750f);
#ifdef WITH_OCIO
- OCIO::ConstConfigRcPtr config = OCIO::GetCurrentConfig();
- if(config) {
- if(config->hasRole("XYZ") && config->hasRole("scene_linear")) {
- OCIO::ConstProcessorRcPtr to_rgb_processor = config->getProcessor("XYZ", "scene_linear");
- OCIO::ConstProcessorRcPtr to_xyz_processor = config->getProcessor("scene_linear", "XYZ");
- if(to_rgb_processor && to_xyz_processor) {
- float r[] = {1.0f, 0.0f, 0.0f};
- float g[] = {0.0f, 1.0f, 0.0f};
- float b[] = {0.0f, 0.0f, 1.0f};
- to_xyz_processor->applyRGB(r);
- to_xyz_processor->applyRGB(g);
- to_xyz_processor->applyRGB(b);
- rgb_to_y = make_float3(r[1], g[1], b[1]);
-
- float x[] = {1.0f, 0.0f, 0.0f};
- float y[] = {0.0f, 1.0f, 0.0f};
- float z[] = {0.0f, 0.0f, 1.0f};
- to_rgb_processor->applyRGB(x);
- to_rgb_processor->applyRGB(y);
- to_rgb_processor->applyRGB(z);
- xyz_to_r = make_float3(x[0], y[0], z[0]);
- xyz_to_g = make_float3(x[1], y[1], z[1]);
- xyz_to_b = make_float3(x[2], y[2], z[2]);
- }
- }
- }
+ OCIO::ConstConfigRcPtr config = OCIO::GetCurrentConfig();
+ if (config) {
+ if (config->hasRole("XYZ") && config->hasRole("scene_linear")) {
+ OCIO::ConstProcessorRcPtr to_rgb_processor = config->getProcessor("XYZ", "scene_linear");
+ OCIO::ConstProcessorRcPtr to_xyz_processor = config->getProcessor("scene_linear", "XYZ");
+ if (to_rgb_processor && to_xyz_processor) {
+ float r[] = {1.0f, 0.0f, 0.0f};
+ float g[] = {0.0f, 1.0f, 0.0f};
+ float b[] = {0.0f, 0.0f, 1.0f};
+ to_xyz_processor->applyRGB(r);
+ to_xyz_processor->applyRGB(g);
+ to_xyz_processor->applyRGB(b);
+ rgb_to_y = make_float3(r[1], g[1], b[1]);
+
+ float x[] = {1.0f, 0.0f, 0.0f};
+ float y[] = {0.0f, 1.0f, 0.0f};
+ float z[] = {0.0f, 0.0f, 1.0f};
+ to_rgb_processor->applyRGB(x);
+ to_rgb_processor->applyRGB(y);
+ to_rgb_processor->applyRGB(z);
+ xyz_to_r = make_float3(x[0], y[0], z[0]);
+ xyz_to_g = make_float3(x[1], y[1], z[1]);
+ xyz_to_b = make_float3(x[2], y[2], z[2]);
+ }
+ }
+ }
#endif
}
@@ -404,337 +407,337 @@ ShaderManager::~ShaderManager()
ShaderManager *ShaderManager::create(Scene *scene, int shadingsystem)
{
- ShaderManager *manager;
+ ShaderManager *manager;
- (void) shadingsystem; /* Ignored when built without OSL. */
+ (void)shadingsystem; /* Ignored when built without OSL. */
#ifdef WITH_OSL
- if(shadingsystem == SHADINGSYSTEM_OSL) {
- manager = new OSLShaderManager();
- }
- else
+ if (shadingsystem == SHADINGSYSTEM_OSL) {
+ manager = new OSLShaderManager();
+ }
+ else
#endif
- {
- manager = new SVMShaderManager();
- }
+ {
+ manager = new SVMShaderManager();
+ }
- add_default(scene);
+ add_default(scene);
- return manager;
+ return manager;
}
uint ShaderManager::get_attribute_id(ustring name)
{
- thread_scoped_spin_lock lock(attribute_lock_);
+ thread_scoped_spin_lock lock(attribute_lock_);
- /* get a unique id for each name, for SVM attribute lookup */
- AttributeIDMap::iterator it = unique_attribute_id.find(name);
+ /* get a unique id for each name, for SVM attribute lookup */
+ AttributeIDMap::iterator it = unique_attribute_id.find(name);
- if(it != unique_attribute_id.end())
- return it->second;
+ if (it != unique_attribute_id.end())
+ return it->second;
- uint id = (uint)ATTR_STD_NUM + unique_attribute_id.size();
- unique_attribute_id[name] = id;
- return id;
+ uint id = (uint)ATTR_STD_NUM + unique_attribute_id.size();
+ unique_attribute_id[name] = id;
+ return id;
}
uint ShaderManager::get_attribute_id(AttributeStandard std)
{
- return (uint)std;
+ return (uint)std;
}
int ShaderManager::get_shader_id(Shader *shader, bool smooth)
{
- /* get a shader id to pass to the kernel */
- int id = shader->id;
+ /* get a shader id to pass to the kernel */
+ int id = shader->id;
- /* smooth flag */
- if(smooth)
- id |= SHADER_SMOOTH_NORMAL;
+ /* smooth flag */
+ if (smooth)
+ id |= SHADER_SMOOTH_NORMAL;
- /* default flags */
- id |= SHADER_CAST_SHADOW|SHADER_AREA_LIGHT;
+ /* default flags */
+ id |= SHADER_CAST_SHADOW | SHADER_AREA_LIGHT;
- return id;
+ return id;
}
void ShaderManager::device_update_shaders_used(Scene *scene)
{
- /* figure out which shaders are in use, so SVM/OSL can skip compiling them
- * for speed and avoid loading image textures into memory */
- uint id = 0;
- foreach(Shader *shader, scene->shaders) {
- shader->used = false;
- shader->id = id++;
- }
-
- scene->default_surface->used = true;
- scene->default_light->used = true;
- scene->default_background->used = true;
- scene->default_empty->used = true;
-
- if(scene->background->shader)
- scene->background->shader->used = true;
-
- foreach(Mesh *mesh, scene->meshes)
- foreach(Shader *shader, mesh->used_shaders)
- shader->used = true;
-
- foreach(Light *light, scene->lights)
- if(light->shader)
- light->shader->used = true;
+ /* figure out which shaders are in use, so SVM/OSL can skip compiling them
+ * for speed and avoid loading image textures into memory */
+ uint id = 0;
+ foreach (Shader *shader, scene->shaders) {
+ shader->used = false;
+ shader->id = id++;
+ }
+
+ scene->default_surface->used = true;
+ scene->default_light->used = true;
+ scene->default_background->used = true;
+ scene->default_empty->used = true;
+
+ if (scene->background->shader)
+ scene->background->shader->used = true;
+
+ foreach (Mesh *mesh, scene->meshes)
+ foreach (Shader *shader, mesh->used_shaders)
+ shader->used = true;
+
+ foreach (Light *light, scene->lights)
+ if (light->shader)
+ light->shader->used = true;
}
void ShaderManager::device_update_common(Device *device,
DeviceScene *dscene,
Scene *scene,
- Progress& /*progress*/)
+ Progress & /*progress*/)
{
- dscene->shaders.free();
-
- if(scene->shaders.size() == 0)
- return;
-
- KernelShader *kshader = dscene->shaders.alloc(scene->shaders.size());
- bool has_volumes = false;
- bool has_transparent_shadow = false;
-
- foreach(Shader *shader, scene->shaders) {
- uint flag = 0;
-
- if(shader->use_mis)
- flag |= SD_USE_MIS;
- if(shader->has_surface_transparent && shader->use_transparent_shadow)
- flag |= SD_HAS_TRANSPARENT_SHADOW;
- if(shader->has_volume) {
- flag |= SD_HAS_VOLUME;
- has_volumes = true;
-
- /* todo: this could check more fine grained, to skip useless volumes
- * enclosed inside an opaque bsdf.
- */
- flag |= SD_HAS_TRANSPARENT_SHADOW;
- }
- /* in this case we can assume transparent surface */
- if(shader->has_volume_connected && !shader->has_surface)
- flag |= SD_HAS_ONLY_VOLUME;
- if(shader->heterogeneous_volume && shader->has_volume_spatial_varying)
- flag |= SD_HETEROGENEOUS_VOLUME;
- if(shader->has_attribute_dependency)
- flag |= SD_NEED_ATTRIBUTES;
- if(shader->has_bssrdf_bump)
- flag |= SD_HAS_BSSRDF_BUMP;
- if(device->info.has_volume_decoupled) {
- if(shader->volume_sampling_method == VOLUME_SAMPLING_EQUIANGULAR)
- flag |= SD_VOLUME_EQUIANGULAR;
- if(shader->volume_sampling_method == VOLUME_SAMPLING_MULTIPLE_IMPORTANCE)
- flag |= SD_VOLUME_MIS;
- }
- if(shader->volume_interpolation_method == VOLUME_INTERPOLATION_CUBIC)
- flag |= SD_VOLUME_CUBIC;
- if(shader->has_bump)
- flag |= SD_HAS_BUMP;
- if(shader->displacement_method != DISPLACE_BUMP)
- flag |= SD_HAS_DISPLACEMENT;
-
- /* constant emission check */
- float3 constant_emission = make_float3(0.0f, 0.0f, 0.0f);
- if(shader->is_constant_emission(&constant_emission))
- flag |= SD_HAS_CONSTANT_EMISSION;
-
- uint32_t cryptomatte_id = util_murmur_hash3(shader->name.c_str(), shader->name.length(), 0);
-
- /* regular shader */
- kshader->flags = flag;
- kshader->pass_id = shader->pass_id;
- kshader->constant_emission[0] = constant_emission.x;
- kshader->constant_emission[1] = constant_emission.y;
- kshader->constant_emission[2] = constant_emission.z;
- kshader->cryptomatte_id = util_hash_to_float(cryptomatte_id);
- kshader++;
-
- has_transparent_shadow |= (flag & SD_HAS_TRANSPARENT_SHADOW) != 0;
- }
-
- dscene->shaders.copy_to_device();
-
- /* lookup tables */
- KernelTables *ktables = &dscene->data.tables;
-
- /* beckmann lookup table */
- if(beckmann_table_offset == TABLE_OFFSET_INVALID) {
- if(!beckmann_table_ready) {
- thread_scoped_lock lock(lookup_table_mutex);
- if(!beckmann_table_ready) {
- beckmann_table_build(beckmann_table);
- beckmann_table_ready = true;
- }
- }
- beckmann_table_offset = scene->lookup_tables->add_table(dscene, beckmann_table);
- }
- ktables->beckmann_offset = (int)beckmann_table_offset;
-
- /* integrator */
- KernelIntegrator *kintegrator = &dscene->data.integrator;
- kintegrator->use_volumes = has_volumes;
- /* TODO(sergey): De-duplicate with flags set in integrator.cpp. */
- kintegrator->transparent_shadows = has_transparent_shadow;
-
- /* film */
- KernelFilm *kfilm = &dscene->data.film;
- /* color space, needs to be here because e.g. displacement shaders could depend on it */
- kfilm->xyz_to_r = float3_to_float4(xyz_to_r);
- kfilm->xyz_to_g = float3_to_float4(xyz_to_g);
- kfilm->xyz_to_b = float3_to_float4(xyz_to_b);
- kfilm->rgb_to_y = float3_to_float4(rgb_to_y);
+ dscene->shaders.free();
+
+ if (scene->shaders.size() == 0)
+ return;
+
+ KernelShader *kshader = dscene->shaders.alloc(scene->shaders.size());
+ bool has_volumes = false;
+ bool has_transparent_shadow = false;
+
+ foreach (Shader *shader, scene->shaders) {
+ uint flag = 0;
+
+ if (shader->use_mis)
+ flag |= SD_USE_MIS;
+ if (shader->has_surface_transparent && shader->use_transparent_shadow)
+ flag |= SD_HAS_TRANSPARENT_SHADOW;
+ if (shader->has_volume) {
+ flag |= SD_HAS_VOLUME;
+ has_volumes = true;
+
+ /* todo: this could check more fine grained, to skip useless volumes
+ * enclosed inside an opaque bsdf.
+ */
+ flag |= SD_HAS_TRANSPARENT_SHADOW;
+ }
+ /* in this case we can assume transparent surface */
+ if (shader->has_volume_connected && !shader->has_surface)
+ flag |= SD_HAS_ONLY_VOLUME;
+ if (shader->heterogeneous_volume && shader->has_volume_spatial_varying)
+ flag |= SD_HETEROGENEOUS_VOLUME;
+ if (shader->has_attribute_dependency)
+ flag |= SD_NEED_ATTRIBUTES;
+ if (shader->has_bssrdf_bump)
+ flag |= SD_HAS_BSSRDF_BUMP;
+ if (device->info.has_volume_decoupled) {
+ if (shader->volume_sampling_method == VOLUME_SAMPLING_EQUIANGULAR)
+ flag |= SD_VOLUME_EQUIANGULAR;
+ if (shader->volume_sampling_method == VOLUME_SAMPLING_MULTIPLE_IMPORTANCE)
+ flag |= SD_VOLUME_MIS;
+ }
+ if (shader->volume_interpolation_method == VOLUME_INTERPOLATION_CUBIC)
+ flag |= SD_VOLUME_CUBIC;
+ if (shader->has_bump)
+ flag |= SD_HAS_BUMP;
+ if (shader->displacement_method != DISPLACE_BUMP)
+ flag |= SD_HAS_DISPLACEMENT;
+
+ /* constant emission check */
+ float3 constant_emission = make_float3(0.0f, 0.0f, 0.0f);
+ if (shader->is_constant_emission(&constant_emission))
+ flag |= SD_HAS_CONSTANT_EMISSION;
+
+ uint32_t cryptomatte_id = util_murmur_hash3(shader->name.c_str(), shader->name.length(), 0);
+
+ /* regular shader */
+ kshader->flags = flag;
+ kshader->pass_id = shader->pass_id;
+ kshader->constant_emission[0] = constant_emission.x;
+ kshader->constant_emission[1] = constant_emission.y;
+ kshader->constant_emission[2] = constant_emission.z;
+ kshader->cryptomatte_id = util_hash_to_float(cryptomatte_id);
+ kshader++;
+
+ has_transparent_shadow |= (flag & SD_HAS_TRANSPARENT_SHADOW) != 0;
+ }
+
+ dscene->shaders.copy_to_device();
+
+ /* lookup tables */
+ KernelTables *ktables = &dscene->data.tables;
+
+ /* beckmann lookup table */
+ if (beckmann_table_offset == TABLE_OFFSET_INVALID) {
+ if (!beckmann_table_ready) {
+ thread_scoped_lock lock(lookup_table_mutex);
+ if (!beckmann_table_ready) {
+ beckmann_table_build(beckmann_table);
+ beckmann_table_ready = true;
+ }
+ }
+ beckmann_table_offset = scene->lookup_tables->add_table(dscene, beckmann_table);
+ }
+ ktables->beckmann_offset = (int)beckmann_table_offset;
+
+ /* integrator */
+ KernelIntegrator *kintegrator = &dscene->data.integrator;
+ kintegrator->use_volumes = has_volumes;
+ /* TODO(sergey): De-duplicate with flags set in integrator.cpp. */
+ kintegrator->transparent_shadows = has_transparent_shadow;
+
+ /* film */
+ KernelFilm *kfilm = &dscene->data.film;
+ /* color space, needs to be here because e.g. displacement shaders could depend on it */
+ kfilm->xyz_to_r = float3_to_float4(xyz_to_r);
+ kfilm->xyz_to_g = float3_to_float4(xyz_to_g);
+ kfilm->xyz_to_b = float3_to_float4(xyz_to_b);
+ kfilm->rgb_to_y = float3_to_float4(rgb_to_y);
}
void ShaderManager::device_free_common(Device *, DeviceScene *dscene, Scene *scene)
{
- scene->lookup_tables->remove_table(&beckmann_table_offset);
+ scene->lookup_tables->remove_table(&beckmann_table_offset);
- dscene->shaders.free();
+ dscene->shaders.free();
}
void ShaderManager::add_default(Scene *scene)
{
- /* default surface */
- {
- ShaderGraph *graph = new ShaderGraph();
-
- DiffuseBsdfNode *diffuse = new DiffuseBsdfNode();
- diffuse->color = make_float3(0.8f, 0.8f, 0.8f);
- graph->add(diffuse);
-
- graph->connect(diffuse->output("BSDF"), graph->output()->input("Surface"));
-
- Shader *shader = new Shader();
- shader->name = "default_surface";
- shader->graph = graph;
- scene->shaders.push_back(shader);
- scene->default_surface = shader;
- }
-
- /* default light */
- {
- ShaderGraph *graph = new ShaderGraph();
-
- EmissionNode *emission = new EmissionNode();
- emission->color = make_float3(0.8f, 0.8f, 0.8f);
- emission->strength = 0.0f;
- graph->add(emission);
-
- graph->connect(emission->output("Emission"), graph->output()->input("Surface"));
-
- Shader *shader = new Shader();
- shader->name = "default_light";
- shader->graph = graph;
- scene->shaders.push_back(shader);
- scene->default_light = shader;
- }
-
- /* default background */
- {
- ShaderGraph *graph = new ShaderGraph();
-
- Shader *shader = new Shader();
- shader->name = "default_background";
- shader->graph = graph;
- scene->shaders.push_back(shader);
- scene->default_background = shader;
- }
-
- /* default empty */
- {
- ShaderGraph *graph = new ShaderGraph();
-
- Shader *shader = new Shader();
- shader->name = "default_empty";
- shader->graph = graph;
- scene->shaders.push_back(shader);
- scene->default_empty = shader;
- }
+ /* default surface */
+ {
+ ShaderGraph *graph = new ShaderGraph();
+
+ DiffuseBsdfNode *diffuse = new DiffuseBsdfNode();
+ diffuse->color = make_float3(0.8f, 0.8f, 0.8f);
+ graph->add(diffuse);
+
+ graph->connect(diffuse->output("BSDF"), graph->output()->input("Surface"));
+
+ Shader *shader = new Shader();
+ shader->name = "default_surface";
+ shader->graph = graph;
+ scene->shaders.push_back(shader);
+ scene->default_surface = shader;
+ }
+
+ /* default light */
+ {
+ ShaderGraph *graph = new ShaderGraph();
+
+ EmissionNode *emission = new EmissionNode();
+ emission->color = make_float3(0.8f, 0.8f, 0.8f);
+ emission->strength = 0.0f;
+ graph->add(emission);
+
+ graph->connect(emission->output("Emission"), graph->output()->input("Surface"));
+
+ Shader *shader = new Shader();
+ shader->name = "default_light";
+ shader->graph = graph;
+ scene->shaders.push_back(shader);
+ scene->default_light = shader;
+ }
+
+ /* default background */
+ {
+ ShaderGraph *graph = new ShaderGraph();
+
+ Shader *shader = new Shader();
+ shader->name = "default_background";
+ shader->graph = graph;
+ scene->shaders.push_back(shader);
+ scene->default_background = shader;
+ }
+
+ /* default empty */
+ {
+ ShaderGraph *graph = new ShaderGraph();
+
+ Shader *shader = new Shader();
+ shader->name = "default_empty";
+ shader->graph = graph;
+ scene->shaders.push_back(shader);
+ scene->default_empty = shader;
+ }
}
void ShaderManager::get_requested_graph_features(ShaderGraph *graph,
DeviceRequestedFeatures *requested_features)
{
- foreach(ShaderNode *node, graph->nodes) {
- requested_features->max_nodes_group = max(requested_features->max_nodes_group,
- node->get_group());
- requested_features->nodes_features |= node->get_feature();
- if(node->special_type == SHADER_SPECIAL_TYPE_CLOSURE) {
- BsdfBaseNode *bsdf_node = static_cast<BsdfBaseNode*>(node);
- if(CLOSURE_IS_VOLUME(bsdf_node->closure)) {
- requested_features->nodes_features |= NODE_FEATURE_VOLUME;
- }
- else if(CLOSURE_IS_PRINCIPLED(bsdf_node->closure)) {
- requested_features->use_principled = true;
- }
- }
- if(node->has_surface_bssrdf()) {
- requested_features->use_subsurface = true;
- }
- if(node->has_surface_transparent()) {
- requested_features->use_transparent = true;
- }
- if(node->has_raytrace()) {
- requested_features->use_shader_raytrace = true;
- }
- }
+ foreach (ShaderNode *node, graph->nodes) {
+ requested_features->max_nodes_group = max(requested_features->max_nodes_group,
+ node->get_group());
+ requested_features->nodes_features |= node->get_feature();
+ if (node->special_type == SHADER_SPECIAL_TYPE_CLOSURE) {
+ BsdfBaseNode *bsdf_node = static_cast<BsdfBaseNode *>(node);
+ if (CLOSURE_IS_VOLUME(bsdf_node->closure)) {
+ requested_features->nodes_features |= NODE_FEATURE_VOLUME;
+ }
+ else if (CLOSURE_IS_PRINCIPLED(bsdf_node->closure)) {
+ requested_features->use_principled = true;
+ }
+ }
+ if (node->has_surface_bssrdf()) {
+ requested_features->use_subsurface = true;
+ }
+ if (node->has_surface_transparent()) {
+ requested_features->use_transparent = true;
+ }
+ if (node->has_raytrace()) {
+ requested_features->use_shader_raytrace = true;
+ }
+ }
}
void ShaderManager::get_requested_features(Scene *scene,
DeviceRequestedFeatures *requested_features)
{
- requested_features->max_nodes_group = NODE_GROUP_LEVEL_0;
- requested_features->nodes_features = 0;
- for(int i = 0; i < scene->shaders.size(); i++) {
- Shader *shader = scene->shaders[i];
- /* Gather requested features from all the nodes from the graph nodes. */
- get_requested_graph_features(shader->graph, requested_features);
- ShaderNode *output_node = shader->graph->output();
- if(output_node->input("Displacement")->link != NULL) {
- requested_features->nodes_features |= NODE_FEATURE_BUMP;
- if(shader->displacement_method == DISPLACE_BOTH) {
- requested_features->nodes_features |= NODE_FEATURE_BUMP_STATE;
- }
- }
- /* On top of volume nodes, also check if we need volume sampling because
- * e.g. an Emission node would slip through the NODE_FEATURE_VOLUME check */
- if(shader->has_volume)
- requested_features->use_volume |= true;
- }
+ requested_features->max_nodes_group = NODE_GROUP_LEVEL_0;
+ requested_features->nodes_features = 0;
+ for (int i = 0; i < scene->shaders.size(); i++) {
+ Shader *shader = scene->shaders[i];
+ /* Gather requested features from all the nodes from the graph nodes. */
+ get_requested_graph_features(shader->graph, requested_features);
+ ShaderNode *output_node = shader->graph->output();
+ if (output_node->input("Displacement")->link != NULL) {
+ requested_features->nodes_features |= NODE_FEATURE_BUMP;
+ if (shader->displacement_method == DISPLACE_BOTH) {
+ requested_features->nodes_features |= NODE_FEATURE_BUMP_STATE;
+ }
+ }
+ /* On top of volume nodes, also check if we need volume sampling because
+ * e.g. an Emission node would slip through the NODE_FEATURE_VOLUME check */
+ if (shader->has_volume)
+ requested_features->use_volume |= true;
+ }
}
void ShaderManager::free_memory()
{
- beckmann_table.free_memory();
+ beckmann_table.free_memory();
#ifdef WITH_OSL
- OSLShaderManager::free_memory();
+ OSLShaderManager::free_memory();
#endif
}
float ShaderManager::linear_rgb_to_gray(float3 c)
{
- return dot(c, rgb_to_y);
+ return dot(c, rgb_to_y);
}
string ShaderManager::get_cryptomatte_materials(Scene *scene)
{
- string manifest = "{";
- unordered_set<ustring, ustringHash> materials;
- foreach(Shader *shader, scene->shaders) {
- if(materials.count(shader->name)) {
- continue;
- }
- materials.insert(shader->name);
- uint32_t cryptomatte_id = util_murmur_hash3(shader->name.c_str(), shader->name.length(), 0);
- manifest += string_printf("\"%s\":\"%08x\",", shader->name.c_str(), cryptomatte_id);
- }
- manifest[manifest.size()-1] = '}';
- return manifest;
+ string manifest = "{";
+ unordered_set<ustring, ustringHash> materials;
+ foreach (Shader *shader, scene->shaders) {
+ if (materials.count(shader->name)) {
+ continue;
+ }
+ materials.insert(shader->name);
+ uint32_t cryptomatte_id = util_murmur_hash3(shader->name.c_str(), shader->name.length(), 0);
+ manifest += string_printf("\"%s\":\"%08x\",", shader->name.c_str(), cryptomatte_id);
+ }
+ manifest[manifest.size() - 1] = '}';
+ return manifest;
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/render/shader.h b/intern/cycles/render/shader.h
index 05772b9a9cd..600b0cc59d4 100644
--- a/intern/cycles/render/shader.h
+++ b/intern/cycles/render/shader.h
@@ -45,33 +45,30 @@ class Scene;
class ShaderGraph;
struct float3;
-enum ShadingSystem {
- SHADINGSYSTEM_OSL,
- SHADINGSYSTEM_SVM
-};
+enum ShadingSystem { SHADINGSYSTEM_OSL, SHADINGSYSTEM_SVM };
/* Keep those in sync with the python-defined enum. */
enum VolumeSampling {
- VOLUME_SAMPLING_DISTANCE = 0,
- VOLUME_SAMPLING_EQUIANGULAR = 1,
- VOLUME_SAMPLING_MULTIPLE_IMPORTANCE = 2,
+ VOLUME_SAMPLING_DISTANCE = 0,
+ VOLUME_SAMPLING_EQUIANGULAR = 1,
+ VOLUME_SAMPLING_MULTIPLE_IMPORTANCE = 2,
- VOLUME_NUM_SAMPLING,
+ VOLUME_NUM_SAMPLING,
};
enum VolumeInterpolation {
- VOLUME_INTERPOLATION_LINEAR = 0,
- VOLUME_INTERPOLATION_CUBIC = 1,
+ VOLUME_INTERPOLATION_LINEAR = 0,
+ VOLUME_INTERPOLATION_CUBIC = 1,
- VOLUME_NUM_INTERPOLATION,
+ VOLUME_NUM_INTERPOLATION,
};
enum DisplacementMethod {
- DISPLACE_BUMP = 0,
- DISPLACE_TRUE = 1,
- DISPLACE_BOTH = 2,
+ DISPLACE_BUMP = 0,
+ DISPLACE_TRUE = 1,
+ DISPLACE_BOTH = 2,
- DISPLACE_NUM_METHODS,
+ DISPLACE_NUM_METHODS,
};
/* Shader describing the appearance of a Mesh, Light or Background.
@@ -81,78 +78,78 @@ enum DisplacementMethod {
* separately. */
class Shader : public Node {
-public:
- NODE_DECLARE
-
- int pass_id;
-
- /* shader graph */
- ShaderGraph *graph;
-
- /* sampling */
- bool use_mis;
- bool use_transparent_shadow;
- bool heterogeneous_volume;
- VolumeSampling volume_sampling_method;
- int volume_interpolation_method;
-
- /* synchronization */
- bool need_update;
- bool need_update_mesh;
- bool need_sync_object;
-
- /* If the shader has only volume components, the surface is assumed to
- * be transparent.
- * However, graph optimization might remove the volume subgraph, but
- * since the user connected something to the volume output the surface
- * should still be transparent.
- * Therefore, has_volume_connected stores whether some volume subtree
- * was connected before optimization. */
- bool has_volume_connected;
-
- /* information about shader after compiling */
- bool has_surface;
- bool has_surface_emission;
- bool has_surface_transparent;
- bool has_volume;
- bool has_displacement;
- bool has_surface_bssrdf;
- bool has_bump;
- bool has_bssrdf_bump;
- bool has_surface_spatial_varying;
- bool has_volume_spatial_varying;
- bool has_object_dependency;
- bool has_attribute_dependency;
- bool has_integrator_dependency;
-
- /* displacement */
- DisplacementMethod displacement_method;
-
- /* requested mesh attributes */
- AttributeRequestSet attributes;
-
- /* determined before compiling */
- uint id;
- bool used;
+ public:
+ NODE_DECLARE
+
+ int pass_id;
+
+ /* shader graph */
+ ShaderGraph *graph;
+
+ /* sampling */
+ bool use_mis;
+ bool use_transparent_shadow;
+ bool heterogeneous_volume;
+ VolumeSampling volume_sampling_method;
+ int volume_interpolation_method;
+
+ /* synchronization */
+ bool need_update;
+ bool need_update_mesh;
+ bool need_sync_object;
+
+ /* If the shader has only volume components, the surface is assumed to
+ * be transparent.
+ * However, graph optimization might remove the volume subgraph, but
+ * since the user connected something to the volume output the surface
+ * should still be transparent.
+ * Therefore, has_volume_connected stores whether some volume subtree
+ * was connected before optimization. */
+ bool has_volume_connected;
+
+ /* information about shader after compiling */
+ bool has_surface;
+ bool has_surface_emission;
+ bool has_surface_transparent;
+ bool has_volume;
+ bool has_displacement;
+ bool has_surface_bssrdf;
+ bool has_bump;
+ bool has_bssrdf_bump;
+ bool has_surface_spatial_varying;
+ bool has_volume_spatial_varying;
+ bool has_object_dependency;
+ bool has_attribute_dependency;
+ bool has_integrator_dependency;
+
+ /* displacement */
+ DisplacementMethod displacement_method;
+
+ /* requested mesh attributes */
+ AttributeRequestSet attributes;
+
+ /* determined before compiling */
+ uint id;
+ bool used;
#ifdef WITH_OSL
- /* osl shading state references */
- OSL::ShaderGroupRef osl_surface_ref;
- OSL::ShaderGroupRef osl_surface_bump_ref;
- OSL::ShaderGroupRef osl_volume_ref;
- OSL::ShaderGroupRef osl_displacement_ref;
+ /* osl shading state references */
+ OSL::ShaderGroupRef osl_surface_ref;
+ OSL::ShaderGroupRef osl_surface_bump_ref;
+ OSL::ShaderGroupRef osl_volume_ref;
+ OSL::ShaderGroupRef osl_displacement_ref;
#endif
- Shader();
- ~Shader();
+ Shader();
+ ~Shader();
- /* Checks whether the shader consists of just a emission node with fixed inputs that's connected directly to the output.
- * If yes, it sets the content of emission to the constant value (color * strength), which is then used for speeding up light evaluation. */
- bool is_constant_emission(float3* emission);
+ /* Checks whether the shader consists of just a emission node with fixed inputs that's connected directly to the output.
+ * If yes, it sets the content of emission to the constant value (color * strength), which is then used for speeding up light evaluation. */
+ bool is_constant_emission(float3 *emission);
- void set_graph(ShaderGraph *graph);
- void tag_update(Scene *scene);
- void tag_used(Scene *scene);
+ void set_graph(ShaderGraph *graph);
+ void tag_update(Scene *scene);
+ void tag_used(Scene *scene);
};
/* Shader Manager virtual base class
@@ -161,68 +158,73 @@ public:
* shader compiling and device updating. */
class ShaderManager {
-public:
- bool need_update;
+ public:
+ bool need_update;
- static ShaderManager *create(Scene *scene, int shadingsystem);
- virtual ~ShaderManager();
+ static ShaderManager *create(Scene *scene, int shadingsystem);
+ virtual ~ShaderManager();
- virtual void reset(Scene *scene) = 0;
+ virtual void reset(Scene *scene) = 0;
- virtual bool use_osl() { return false; }
+ virtual bool use_osl()
+ {
+ return false;
+ }
- /* device update */
- virtual void device_update(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress) = 0;
- virtual void device_free(Device *device, DeviceScene *dscene, Scene *scene) = 0;
+ /* device update */
+ virtual void device_update(Device *device,
+ DeviceScene *dscene,
+ Scene *scene,
+ Progress &progress) = 0;
+ virtual void device_free(Device *device, DeviceScene *dscene, Scene *scene) = 0;
- void device_update_shaders_used(Scene *scene);
- void device_update_common(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress);
- void device_free_common(Device *device, DeviceScene *dscene, Scene *scene);
+ void device_update_shaders_used(Scene *scene);
+ void device_update_common(Device *device, DeviceScene *dscene, Scene *scene, Progress &progress);
+ void device_free_common(Device *device, DeviceScene *dscene, Scene *scene);
- /* get globally unique id for a type of attribute */
- uint get_attribute_id(ustring name);
- uint get_attribute_id(AttributeStandard std);
+ /* get globally unique id for a type of attribute */
+ uint get_attribute_id(ustring name);
+ uint get_attribute_id(AttributeStandard std);
- /* get shader id for mesh faces */
- int get_shader_id(Shader *shader, bool smooth = false);
+ /* get shader id for mesh faces */
+ int get_shader_id(Shader *shader, bool smooth = false);
- /* add default shaders to scene, to use as default for things that don't
- * have any shader assigned explicitly */
- static void add_default(Scene *scene);
+ /* add default shaders to scene, to use as default for things that don't
+ * have any shader assigned explicitly */
+ static void add_default(Scene *scene);
- /* Selective nodes compilation. */
- void get_requested_features(Scene *scene,
- DeviceRequestedFeatures *requested_features);
+ /* Selective nodes compilation. */
+ void get_requested_features(Scene *scene, DeviceRequestedFeatures *requested_features);
- static void free_memory();
+ static void free_memory();
- float linear_rgb_to_gray(float3 c);
+ float linear_rgb_to_gray(float3 c);
- string get_cryptomatte_materials(Scene *scene);
+ string get_cryptomatte_materials(Scene *scene);
-protected:
- ShaderManager();
+ protected:
+ ShaderManager();
- typedef unordered_map<ustring, uint, ustringHash> AttributeIDMap;
- AttributeIDMap unique_attribute_id;
+ typedef unordered_map<ustring, uint, ustringHash> AttributeIDMap;
+ AttributeIDMap unique_attribute_id;
- static thread_mutex lookup_table_mutex;
- static vector<float> beckmann_table;
- static bool beckmann_table_ready;
+ static thread_mutex lookup_table_mutex;
+ static vector<float> beckmann_table;
+ static bool beckmann_table_ready;
- size_t beckmann_table_offset;
+ size_t beckmann_table_offset;
- void get_requested_graph_features(ShaderGraph *graph,
- DeviceRequestedFeatures *requested_features);
+ void get_requested_graph_features(ShaderGraph *graph,
+ DeviceRequestedFeatures *requested_features);
- thread_spin_lock attribute_lock_;
+ thread_spin_lock attribute_lock_;
- float3 xyz_to_r;
- float3 xyz_to_g;
- float3 xyz_to_b;
- float3 rgb_to_y;
+ float3 xyz_to_r;
+ float3 xyz_to_g;
+ float3 xyz_to_b;
+ float3 rgb_to_y;
};
CCL_NAMESPACE_END
-#endif /* __SHADER_H__ */
+#endif /* __SHADER_H__ */
diff --git a/intern/cycles/render/sobol.h b/intern/cycles/render/sobol.h
index ce7a28587f2..d38857d2b35 100644
--- a/intern/cycles/render/sobol.h
+++ b/intern/cycles/render/sobol.h
@@ -28,4 +28,4 @@ void sobol_generate_direction_vectors(uint vectors[][SOBOL_BITS], int dimensions
CCL_NAMESPACE_END
-#endif /* __SOBOL_H__ */
+#endif /* __SOBOL_H__ */
diff --git a/intern/cycles/render/stats.cpp b/intern/cycles/render/stats.cpp
index 4245745944d..0937b95a891 100644
--- a/intern/cycles/render/stats.cpp
+++ b/intern/cycles/render/stats.cpp
@@ -28,284 +28,293 @@ static int kIndentNumSpaces = 2;
namespace {
-bool namedSizeEntryComparator(const NamedSizeEntry& a, const NamedSizeEntry& b)
+bool namedSizeEntryComparator(const NamedSizeEntry &a, const NamedSizeEntry &b)
{
- /* We sort in descending order. */
- return a.size > b.size;
+ /* We sort in descending order. */
+ return a.size > b.size;
}
-bool namedTimeSampleEntryComparator(const NamedNestedSampleStats& a, const NamedNestedSampleStats& b)
+bool namedTimeSampleEntryComparator(const NamedNestedSampleStats &a,
+ const NamedNestedSampleStats &b)
{
- return a.sum_samples > b.sum_samples;
+ return a.sum_samples > b.sum_samples;
}
-bool namedSampleCountPairComparator(const NamedSampleCountPair& a, const NamedSampleCountPair& b)
+bool namedSampleCountPairComparator(const NamedSampleCountPair &a, const NamedSampleCountPair &b)
{
- return a.samples > b.samples;
+ return a.samples > b.samples;
}
} // namespace
-NamedSizeEntry::NamedSizeEntry()
- : name(""),
- size(0) {
+NamedSizeEntry::NamedSizeEntry() : name(""), size(0)
+{
}
-NamedSizeEntry::NamedSizeEntry(const string& name, size_t size)
- : name(name),
- size(size) {
+NamedSizeEntry::NamedSizeEntry(const string &name, size_t size) : name(name), size(size)
+{
}
/* Named size statistics. */
-NamedSizeStats::NamedSizeStats()
- : total_size(0) {
+NamedSizeStats::NamedSizeStats() : total_size(0)
+{
}
-void NamedSizeStats::add_entry(const NamedSizeEntry& entry) {
- total_size += entry.size;
- entries.push_back(entry);
+void NamedSizeStats::add_entry(const NamedSizeEntry &entry)
+{
+ total_size += entry.size;
+ entries.push_back(entry);
}
string NamedSizeStats::full_report(int indent_level)
{
- const string indent(indent_level * kIndentNumSpaces, ' ');
- const string double_indent = indent + indent;
- string result = "";
- result += string_printf("%sTotal memory: %s (%s)\n",
- indent.c_str(),
- string_human_readable_size(total_size).c_str(),
- string_human_readable_number(total_size).c_str());
- sort(entries.begin(), entries.end(), namedSizeEntryComparator);
- foreach(const NamedSizeEntry& entry, entries) {
- result += string_printf(
- "%s%-32s %s (%s)\n",
- double_indent.c_str(),
- entry.name.c_str(),
- string_human_readable_size(entry.size).c_str(),
- string_human_readable_number(entry.size).c_str());
- }
- return result;
+ const string indent(indent_level * kIndentNumSpaces, ' ');
+ const string double_indent = indent + indent;
+ string result = "";
+ result += string_printf("%sTotal memory: %s (%s)\n",
+ indent.c_str(),
+ string_human_readable_size(total_size).c_str(),
+ string_human_readable_number(total_size).c_str());
+ sort(entries.begin(), entries.end(), namedSizeEntryComparator);
+ foreach (const NamedSizeEntry &entry, entries) {
+ result += string_printf("%s%-32s %s (%s)\n",
+ double_indent.c_str(),
+ entry.name.c_str(),
+ string_human_readable_size(entry.size).c_str(),
+ string_human_readable_number(entry.size).c_str());
+ }
+ return result;
}
/* Named time sample statistics. */
-NamedNestedSampleStats::NamedNestedSampleStats()
- : name(""), self_samples(0), sum_samples(0)
-{}
+NamedNestedSampleStats::NamedNestedSampleStats() : name(""), self_samples(0), sum_samples(0)
+{
+}
-NamedNestedSampleStats::NamedNestedSampleStats(const string& name, uint64_t samples)
- : name(name), self_samples(samples), sum_samples(samples)
-{}
+NamedNestedSampleStats::NamedNestedSampleStats(const string &name, uint64_t samples)
+ : name(name), self_samples(samples), sum_samples(samples)
+{
+}
-NamedNestedSampleStats& NamedNestedSampleStats::add_entry(const string& name_, uint64_t samples_)
+NamedNestedSampleStats &NamedNestedSampleStats::add_entry(const string &name_, uint64_t samples_)
{
- entries.push_back(NamedNestedSampleStats(name_, samples_));
- return entries[entries.size()-1];
+ entries.push_back(NamedNestedSampleStats(name_, samples_));
+ return entries[entries.size() - 1];
}
void NamedNestedSampleStats::update_sum()
{
- sum_samples = self_samples;
- foreach(NamedNestedSampleStats& entry, entries) {
- entry.update_sum();
- sum_samples += entry.sum_samples;
- }
+ sum_samples = self_samples;
+ foreach (NamedNestedSampleStats &entry, entries) {
+ entry.update_sum();
+ sum_samples += entry.sum_samples;
+ }
}
string NamedNestedSampleStats::full_report(int indent_level, uint64_t total_samples)
{
- update_sum();
-
- if(total_samples == 0) {
- total_samples = sum_samples;
- }
-
- const string indent(indent_level * kIndentNumSpaces, ' ');
-
- const double sum_percent = 100*((double) sum_samples) / total_samples;
- const double sum_seconds = sum_samples * 0.001;
- const double self_percent = 100*((double) self_samples) / total_samples;
- const double self_seconds = self_samples * 0.001;
- string info = string_printf("%-32s: Total %3.2f%% (%.2fs), Self %3.2f%% (%.2fs)\n",
- name.c_str(),
- sum_percent,
- sum_seconds,
- self_percent,
- self_seconds);
- string result = indent + info;
-
- sort(entries.begin(), entries.end(), namedTimeSampleEntryComparator);
- foreach(NamedNestedSampleStats& entry, entries) {
- result += entry.full_report(indent_level + 1, total_samples);
- }
- return result;
+ update_sum();
+
+ if (total_samples == 0) {
+ total_samples = sum_samples;
+ }
+
+ const string indent(indent_level * kIndentNumSpaces, ' ');
+
+ const double sum_percent = 100 * ((double)sum_samples) / total_samples;
+ const double sum_seconds = sum_samples * 0.001;
+ const double self_percent = 100 * ((double)self_samples) / total_samples;
+ const double self_seconds = self_samples * 0.001;
+ string info = string_printf("%-32s: Total %3.2f%% (%.2fs), Self %3.2f%% (%.2fs)\n",
+ name.c_str(),
+ sum_percent,
+ sum_seconds,
+ self_percent,
+ self_seconds);
+ string result = indent + info;
+
+ sort(entries.begin(), entries.end(), namedTimeSampleEntryComparator);
+ foreach (NamedNestedSampleStats &entry, entries) {
+ result += entry.full_report(indent_level + 1, total_samples);
+ }
+ return result;
}
/* Named sample count pairs. */
-NamedSampleCountPair::NamedSampleCountPair(const ustring& name, uint64_t samples, uint64_t hits)
- : name(name), samples(samples), hits(hits)
-{}
+NamedSampleCountPair::NamedSampleCountPair(const ustring &name, uint64_t samples, uint64_t hits)
+ : name(name), samples(samples), hits(hits)
+{
+}
NamedSampleCountStats::NamedSampleCountStats()
-{}
+{
+}
-void NamedSampleCountStats::add(const ustring& name, uint64_t samples, uint64_t hits)
+void NamedSampleCountStats::add(const ustring &name, uint64_t samples, uint64_t hits)
{
- entry_map::iterator entry = entries.find(name);
- if(entry != entries.end()) {
- entry->second.samples += samples;
- entry->second.hits += hits;
- return;
- }
- entries.emplace(name, NamedSampleCountPair(name, samples, hits));
+ entry_map::iterator entry = entries.find(name);
+ if (entry != entries.end()) {
+ entry->second.samples += samples;
+ entry->second.hits += hits;
+ return;
+ }
+ entries.emplace(name, NamedSampleCountPair(name, samples, hits));
}
string NamedSampleCountStats::full_report(int indent_level)
{
- const string indent(indent_level * kIndentNumSpaces, ' ');
+ const string indent(indent_level * kIndentNumSpaces, ' ');
- vector<NamedSampleCountPair> sorted_entries;
- sorted_entries.reserve(entries.size());
+ vector<NamedSampleCountPair> sorted_entries;
+ sorted_entries.reserve(entries.size());
- uint64_t total_hits = 0, total_samples = 0;
- foreach(entry_map::const_reference entry, entries) {
- const NamedSampleCountPair &pair = entry.second;
+ uint64_t total_hits = 0, total_samples = 0;
+ foreach (entry_map::const_reference entry, entries) {
+ const NamedSampleCountPair &pair = entry.second;
- total_hits += pair.hits;
- total_samples += pair.samples;
+ total_hits += pair.hits;
+ total_samples += pair.samples;
- sorted_entries.push_back(pair);
- }
- const double avg_samples_per_hit = ((double) total_samples) / total_hits;
+ sorted_entries.push_back(pair);
+ }
+ const double avg_samples_per_hit = ((double)total_samples) / total_hits;
- sort(sorted_entries.begin(), sorted_entries.end(), namedSampleCountPairComparator);
+ sort(sorted_entries.begin(), sorted_entries.end(), namedSampleCountPairComparator);
- string result = "";
- foreach(const NamedSampleCountPair& entry, sorted_entries) {
- const double seconds = entry.samples * 0.001;
- const double relative = ((double) entry.samples) / (entry.hits * avg_samples_per_hit);
+ string result = "";
+ foreach (const NamedSampleCountPair &entry, sorted_entries) {
+ const double seconds = entry.samples * 0.001;
+ const double relative = ((double)entry.samples) / (entry.hits * avg_samples_per_hit);
- result += indent + string_printf("%-32s: %.2fs (Relative cost: %.2f)\n",
- entry.name.c_str(),
- seconds,
- relative);
- }
- return result;
+ result += indent +
+ string_printf(
+ "%-32s: %.2fs (Relative cost: %.2f)\n", entry.name.c_str(), seconds, relative);
+ }
+ return result;
}
/* Mesh statistics. */
-MeshStats::MeshStats() {
+MeshStats::MeshStats()
+{
}
string MeshStats::full_report(int indent_level)
{
- const string indent(indent_level * kIndentNumSpaces, ' ');
- string result = "";
- result += indent + "Geometry:\n" + geometry.full_report(indent_level + 1);
- return result;
+ const string indent(indent_level * kIndentNumSpaces, ' ');
+ string result = "";
+ result += indent + "Geometry:\n" + geometry.full_report(indent_level + 1);
+ return result;
}
/* Image statistics. */
-ImageStats::ImageStats() {
+ImageStats::ImageStats()
+{
}
string ImageStats::full_report(int indent_level)
{
- const string indent(indent_level * kIndentNumSpaces, ' ');
- string result = "";
- result += indent + "Textures:\n" + textures.full_report(indent_level + 1);
- return result;
+ const string indent(indent_level * kIndentNumSpaces, ' ');
+ string result = "";
+ result += indent + "Textures:\n" + textures.full_report(indent_level + 1);
+ return result;
}
/* Overall statistics. */
-RenderStats::RenderStats() {
- has_profiling = false;
+RenderStats::RenderStats()
+{
+ has_profiling = false;
}
-void RenderStats::collect_profiling(Scene *scene, Profiler& prof)
+void RenderStats::collect_profiling(Scene *scene, Profiler &prof)
{
- has_profiling = true;
-
- kernel = NamedNestedSampleStats("Total render time", prof.get_event(PROFILING_UNKNOWN));
-
- kernel.add_entry("Ray setup", prof.get_event(PROFILING_RAY_SETUP));
- kernel.add_entry("Result writing", prof.get_event(PROFILING_WRITE_RESULT));
-
- NamedNestedSampleStats &integrator = kernel.add_entry("Path integration", prof.get_event(PROFILING_PATH_INTEGRATE));
- integrator.add_entry("Scene intersection", prof.get_event(PROFILING_SCENE_INTERSECT));
- integrator.add_entry("Indirect emission", prof.get_event(PROFILING_INDIRECT_EMISSION));
- integrator.add_entry("Volumes", prof.get_event(PROFILING_VOLUME));
-
- NamedNestedSampleStats &shading = integrator.add_entry("Shading", 0);
- shading.add_entry("Shader Setup", prof.get_event(PROFILING_SHADER_SETUP));
- shading.add_entry("Shader Eval", prof.get_event(PROFILING_SHADER_EVAL));
- shading.add_entry("Shader Apply", prof.get_event(PROFILING_SHADER_APPLY));
- shading.add_entry("Ambient Occlusion", prof.get_event(PROFILING_AO));
- shading.add_entry("Subsurface", prof.get_event(PROFILING_SUBSURFACE));
-
- integrator.add_entry("Connect Light", prof.get_event(PROFILING_CONNECT_LIGHT));
- integrator.add_entry("Surface Bounce", prof.get_event(PROFILING_SURFACE_BOUNCE));
-
- NamedNestedSampleStats &intersection = kernel.add_entry("Intersection", 0);
- intersection.add_entry("Full Intersection", prof.get_event(PROFILING_INTERSECT));
- intersection.add_entry("Local Intersection", prof.get_event(PROFILING_INTERSECT_LOCAL));
- intersection.add_entry("Shadow All Intersection", prof.get_event(PROFILING_INTERSECT_SHADOW_ALL));
- intersection.add_entry("Volume Intersection", prof.get_event(PROFILING_INTERSECT_VOLUME));
- intersection.add_entry("Volume All Intersection", prof.get_event(PROFILING_INTERSECT_VOLUME_ALL));
-
- NamedNestedSampleStats &closure = kernel.add_entry("Closures", 0);
- closure.add_entry("Surface Closure Evaluation", prof.get_event(PROFILING_CLOSURE_EVAL));
- closure.add_entry("Surface Closure Sampling", prof.get_event(PROFILING_CLOSURE_SAMPLE));
- closure.add_entry("Volume Closure Evaluation", prof.get_event(PROFILING_CLOSURE_VOLUME_EVAL));
- closure.add_entry("Volume Closure Sampling", prof.get_event(PROFILING_CLOSURE_VOLUME_SAMPLE));
-
- NamedNestedSampleStats &denoising = kernel.add_entry("Denoising", prof.get_event(PROFILING_DENOISING));
- denoising.add_entry("Construct Transform", prof.get_event(PROFILING_DENOISING_CONSTRUCT_TRANSFORM));
- denoising.add_entry("Reconstruct", prof.get_event(PROFILING_DENOISING_RECONSTRUCT));
-
- NamedNestedSampleStats &prefilter = denoising.add_entry("Prefiltering", 0);
- prefilter.add_entry("Divide Shadow", prof.get_event(PROFILING_DENOISING_DIVIDE_SHADOW));
- prefilter.add_entry("Non-Local means", prof.get_event(PROFILING_DENOISING_NON_LOCAL_MEANS));
- prefilter.add_entry("Get Feature", prof.get_event(PROFILING_DENOISING_GET_FEATURE));
- prefilter.add_entry("Detect Outliers", prof.get_event(PROFILING_DENOISING_DETECT_OUTLIERS));
- prefilter.add_entry("Combine Halves", prof.get_event(PROFILING_DENOISING_COMBINE_HALVES));
-
- shaders.entries.clear();
- foreach(Shader *shader, scene->shaders) {
- uint64_t samples, hits;
- if(prof.get_shader(shader->id, samples, hits)) {
- shaders.add(shader->name, samples, hits);
- }
- }
-
- objects.entries.clear();
- foreach(Object *object, scene->objects) {
- uint64_t samples, hits;
- if(prof.get_object(object->get_device_index(), samples, hits)) {
- objects.add(object->name, samples, hits);
- }
- }
+ has_profiling = true;
+
+ kernel = NamedNestedSampleStats("Total render time", prof.get_event(PROFILING_UNKNOWN));
+
+ kernel.add_entry("Ray setup", prof.get_event(PROFILING_RAY_SETUP));
+ kernel.add_entry("Result writing", prof.get_event(PROFILING_WRITE_RESULT));
+
+ NamedNestedSampleStats &integrator = kernel.add_entry("Path integration",
+ prof.get_event(PROFILING_PATH_INTEGRATE));
+ integrator.add_entry("Scene intersection", prof.get_event(PROFILING_SCENE_INTERSECT));
+ integrator.add_entry("Indirect emission", prof.get_event(PROFILING_INDIRECT_EMISSION));
+ integrator.add_entry("Volumes", prof.get_event(PROFILING_VOLUME));
+
+ NamedNestedSampleStats &shading = integrator.add_entry("Shading", 0);
+ shading.add_entry("Shader Setup", prof.get_event(PROFILING_SHADER_SETUP));
+ shading.add_entry("Shader Eval", prof.get_event(PROFILING_SHADER_EVAL));
+ shading.add_entry("Shader Apply", prof.get_event(PROFILING_SHADER_APPLY));
+ shading.add_entry("Ambient Occlusion", prof.get_event(PROFILING_AO));
+ shading.add_entry("Subsurface", prof.get_event(PROFILING_SUBSURFACE));
+
+ integrator.add_entry("Connect Light", prof.get_event(PROFILING_CONNECT_LIGHT));
+ integrator.add_entry("Surface Bounce", prof.get_event(PROFILING_SURFACE_BOUNCE));
+
+ NamedNestedSampleStats &intersection = kernel.add_entry("Intersection", 0);
+ intersection.add_entry("Full Intersection", prof.get_event(PROFILING_INTERSECT));
+ intersection.add_entry("Local Intersection", prof.get_event(PROFILING_INTERSECT_LOCAL));
+ intersection.add_entry("Shadow All Intersection",
+ prof.get_event(PROFILING_INTERSECT_SHADOW_ALL));
+ intersection.add_entry("Volume Intersection", prof.get_event(PROFILING_INTERSECT_VOLUME));
+ intersection.add_entry("Volume All Intersection",
+ prof.get_event(PROFILING_INTERSECT_VOLUME_ALL));
+
+ NamedNestedSampleStats &closure = kernel.add_entry("Closures", 0);
+ closure.add_entry("Surface Closure Evaluation", prof.get_event(PROFILING_CLOSURE_EVAL));
+ closure.add_entry("Surface Closure Sampling", prof.get_event(PROFILING_CLOSURE_SAMPLE));
+ closure.add_entry("Volume Closure Evaluation", prof.get_event(PROFILING_CLOSURE_VOLUME_EVAL));
+ closure.add_entry("Volume Closure Sampling", prof.get_event(PROFILING_CLOSURE_VOLUME_SAMPLE));
+
+ NamedNestedSampleStats &denoising = kernel.add_entry("Denoising",
+ prof.get_event(PROFILING_DENOISING));
+ denoising.add_entry("Construct Transform",
+ prof.get_event(PROFILING_DENOISING_CONSTRUCT_TRANSFORM));
+ denoising.add_entry("Reconstruct", prof.get_event(PROFILING_DENOISING_RECONSTRUCT));
+
+ NamedNestedSampleStats &prefilter = denoising.add_entry("Prefiltering", 0);
+ prefilter.add_entry("Divide Shadow", prof.get_event(PROFILING_DENOISING_DIVIDE_SHADOW));
+ prefilter.add_entry("Non-Local means", prof.get_event(PROFILING_DENOISING_NON_LOCAL_MEANS));
+ prefilter.add_entry("Get Feature", prof.get_event(PROFILING_DENOISING_GET_FEATURE));
+ prefilter.add_entry("Detect Outliers", prof.get_event(PROFILING_DENOISING_DETECT_OUTLIERS));
+ prefilter.add_entry("Combine Halves", prof.get_event(PROFILING_DENOISING_COMBINE_HALVES));
+
+ shaders.entries.clear();
+ foreach (Shader *shader, scene->shaders) {
+ uint64_t samples, hits;
+ if (prof.get_shader(shader->id, samples, hits)) {
+ shaders.add(shader->name, samples, hits);
+ }
+ }
+
+ objects.entries.clear();
+ foreach (Object *object, scene->objects) {
+ uint64_t samples, hits;
+ if (prof.get_object(object->get_device_index(), samples, hits)) {
+ objects.add(object->name, samples, hits);
+ }
+ }
}
string RenderStats::full_report()
{
- string result = "";
- result += "Mesh statistics:\n" + mesh.full_report(1);
- result += "Image statistics:\n" + image.full_report(1);
- if(has_profiling) {
- result += "Kernel statistics:\n" + kernel.full_report(1);
- result += "Shader statistics:\n" + shaders.full_report(1);
- result += "Object statistics:\n" + objects.full_report(1);
- }
- else {
- result += "Profiling information not available (only works with CPU rendering)";
- }
- return result;
+ string result = "";
+ result += "Mesh statistics:\n" + mesh.full_report(1);
+ result += "Image statistics:\n" + image.full_report(1);
+ if (has_profiling) {
+ result += "Kernel statistics:\n" + kernel.full_report(1);
+ result += "Shader statistics:\n" + shaders.full_report(1);
+ result += "Object statistics:\n" + objects.full_report(1);
+ }
+ else {
+ result += "Profiling information not available (only works with CPU rendering)";
+ }
+ return result;
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/render/stats.h b/intern/cycles/render/stats.h
index 33fe1f4b185..f1bf1903483 100644
--- a/intern/cycles/render/stats.h
+++ b/intern/cycles/render/stats.h
@@ -33,12 +33,12 @@ CCL_NAMESPACE_BEGIN
* avoiding duplicating code for things like sorting.
*/
class NamedSizeEntry {
-public:
- NamedSizeEntry();
- NamedSizeEntry(const string& name, size_t size);
+ public:
+ NamedSizeEntry();
+ NamedSizeEntry(const string &name, size_t size);
- string name;
- size_t size;
+ string name;
+ size_t size;
};
/* Container of named size entries. Used, for example, to store per-mesh memory
@@ -46,115 +46,115 @@ public:
* container.
*/
class NamedSizeStats {
-public:
- NamedSizeStats();
+ public:
+ NamedSizeStats();
- /* Add entry to the statistics. */
- void add_entry(const NamedSizeEntry& entry);
+ /* Add entry to the statistics. */
+ void add_entry(const NamedSizeEntry &entry);
- /* Generate full human-readable report. */
- string full_report(int indent_level = 0);
+ /* Generate full human-readable report. */
+ string full_report(int indent_level = 0);
- /* Total size of all entries. */
- size_t total_size;
+ /* Total size of all entries. */
+ size_t total_size;
- /* NOTE: Is fine to read directly, but for adding use add_entry(), which
- * makes sure all accumulating values are properly updated.
- */
- vector<NamedSizeEntry> entries;
+ /* NOTE: Is fine to read directly, but for adding use add_entry(), which
+ * makes sure all accumulating values are properly updated.
+ */
+ vector<NamedSizeEntry> entries;
};
class NamedNestedSampleStats {
-public:
- NamedNestedSampleStats();
- NamedNestedSampleStats(const string& name, uint64_t samples);
+ public:
+ NamedNestedSampleStats();
+ NamedNestedSampleStats(const string &name, uint64_t samples);
- NamedNestedSampleStats& add_entry(const string& name, uint64_t samples);
+ NamedNestedSampleStats &add_entry(const string &name, uint64_t samples);
- /* Updates sum_samples recursively. */
- void update_sum();
+ /* Updates sum_samples recursively. */
+ void update_sum();
- string full_report(int indent_level = 0, uint64_t total_samples = 0);
+ string full_report(int indent_level = 0, uint64_t total_samples = 0);
- string name;
+ string name;
- /* self_samples contains only the samples that this specific event got,
- * while sum_samples also includes the samples of all sub-entries. */
- uint64_t self_samples, sum_samples;
+ /* self_samples contains only the samples that this specific event got,
+ * while sum_samples also includes the samples of all sub-entries. */
+ uint64_t self_samples, sum_samples;
- vector<NamedNestedSampleStats> entries;
+ vector<NamedNestedSampleStats> entries;
};
/* Named entry containing both a time-sample count for objects of a type and a
* total count of processed items.
* This allows to estimate the time spent per item. */
class NamedSampleCountPair {
-public:
- NamedSampleCountPair(const ustring& name, uint64_t samples, uint64_t hits);
+ public:
+ NamedSampleCountPair(const ustring &name, uint64_t samples, uint64_t hits);
- ustring name;
- uint64_t samples;
- uint64_t hits;
+ ustring name;
+ uint64_t samples;
+ uint64_t hits;
};
/* Contains statistics about pairs of samples and counts as described above. */
class NamedSampleCountStats {
-public:
- NamedSampleCountStats();
+ public:
+ NamedSampleCountStats();
- string full_report(int indent_level = 0);
- void add(const ustring& name, uint64_t samples, uint64_t hits);
+ string full_report(int indent_level = 0);
+ void add(const ustring &name, uint64_t samples, uint64_t hits);
- typedef unordered_map<ustring, NamedSampleCountPair, ustringHash> entry_map;
- entry_map entries;
+ typedef unordered_map<ustring, NamedSampleCountPair, ustringHash> entry_map;
+ entry_map entries;
};
/* Statistics about mesh in the render database. */
class MeshStats {
-public:
- MeshStats();
+ public:
+ MeshStats();
- /* Generate full human-readable report. */
- string full_report(int indent_level = 0);
+ /* Generate full human-readable report. */
+ string full_report(int indent_level = 0);
- /* Input geometry statistics, this is what is coming as an input to render
- * from. say, Blender. This does not include runtime or engine specific
- * memory like BVH.
- */
- NamedSizeStats geometry;
+ /* Input geometry statistics, this is what is coming as an input to render
+ * from. say, Blender. This does not include runtime or engine specific
+ * memory like BVH.
+ */
+ NamedSizeStats geometry;
};
/* Statistics about images held in memory. */
class ImageStats {
-public:
- ImageStats();
+ public:
+ ImageStats();
- /* Generate full human-readable report. */
- string full_report(int indent_level = 0);
+ /* Generate full human-readable report. */
+ string full_report(int indent_level = 0);
- NamedSizeStats textures;
+ NamedSizeStats textures;
};
/* Render process statistics. */
class RenderStats {
-public:
- RenderStats();
+ public:
+ RenderStats();
- /* Return full report as string. */
- string full_report();
+ /* Return full report as string. */
+ string full_report();
- /* Collect kernel sampling information from Stats. */
- void collect_profiling(Scene *scene, Profiler& prof);
+ /* Collect kernel sampling information from Stats. */
+ void collect_profiling(Scene *scene, Profiler &prof);
- bool has_profiling;
+ bool has_profiling;
- MeshStats mesh;
- ImageStats image;
- NamedNestedSampleStats kernel;
- NamedSampleCountStats shaders;
- NamedSampleCountStats objects;
+ MeshStats mesh;
+ ImageStats image;
+ NamedNestedSampleStats kernel;
+ NamedSampleCountStats shaders;
+ NamedSampleCountStats objects;
};
CCL_NAMESPACE_END
-#endif /* __RENDER_STATS_H__ */
+#endif /* __RENDER_STATS_H__ */
diff --git a/intern/cycles/render/svm.cpp b/intern/cycles/render/svm.cpp
index 360b2b461cf..d8e3e24f39e 100644
--- a/intern/cycles/render/svm.cpp
+++ b/intern/cycles/render/svm.cpp
@@ -49,107 +49,106 @@ void SVMShaderManager::device_update_shader(Scene *scene,
Progress *progress,
array<int4> *global_svm_nodes)
{
- if(progress->get_cancel()) {
- return;
- }
- assert(shader->graph);
+ if (progress->get_cancel()) {
+ return;
+ }
+ assert(shader->graph);
- array<int4> svm_nodes;
- svm_nodes.push_back_slow(make_int4(NODE_SHADER_JUMP, 0, 0, 0));
+ array<int4> svm_nodes;
+ svm_nodes.push_back_slow(make_int4(NODE_SHADER_JUMP, 0, 0, 0));
- SVMCompiler::Summary summary;
- SVMCompiler compiler(scene->shader_manager, scene->image_manager, scene->light_manager);
- compiler.background = (shader == scene->default_background);
- compiler.compile(scene, shader, svm_nodes, 0, &summary);
+ SVMCompiler::Summary summary;
+ SVMCompiler compiler(scene->shader_manager, scene->image_manager, scene->light_manager);
+ compiler.background = (shader == scene->default_background);
+ compiler.compile(scene, shader, svm_nodes, 0, &summary);
- VLOG(2) << "Compilation summary:\n"
- << "Shader name: " << shader->name << "\n"
- << summary.full_report();
+ VLOG(2) << "Compilation summary:\n"
+ << "Shader name: " << shader->name << "\n"
+ << summary.full_report();
- nodes_lock_.lock();
- if(shader->use_mis && shader->has_surface_emission) {
- scene->light_manager->need_update = true;
- }
+ nodes_lock_.lock();
+ if (shader->use_mis && shader->has_surface_emission) {
+ scene->light_manager->need_update = true;
+ }
- /* The copy needs to be done inside the lock, if another thread resizes the array
- * while memcpy is running, it'll be copying into possibly invalid/freed ram.
- */
- size_t global_nodes_size = global_svm_nodes->size();
- global_svm_nodes->resize(global_nodes_size + svm_nodes.size());
+ /* The copy needs to be done inside the lock, if another thread resizes the array
+ * while memcpy is running, it'll be copying into possibly invalid/freed ram.
+ */
+ size_t global_nodes_size = global_svm_nodes->size();
+ global_svm_nodes->resize(global_nodes_size + svm_nodes.size());
- /* Offset local SVM nodes to a global address space. */
- int4& jump_node = (*global_svm_nodes)[shader->id];
- jump_node.y = svm_nodes[0].y + global_nodes_size - 1;
- jump_node.z = svm_nodes[0].z + global_nodes_size - 1;
- jump_node.w = svm_nodes[0].w + global_nodes_size - 1;
- /* Copy new nodes to global storage. */
- memcpy(&(*global_svm_nodes)[global_nodes_size],
- &svm_nodes[1],
- sizeof(int4) * (svm_nodes.size() - 1));
- nodes_lock_.unlock();
+ /* Offset local SVM nodes to a global address space. */
+ int4 &jump_node = (*global_svm_nodes)[shader->id];
+ jump_node.y = svm_nodes[0].y + global_nodes_size - 1;
+ jump_node.z = svm_nodes[0].z + global_nodes_size - 1;
+ jump_node.w = svm_nodes[0].w + global_nodes_size - 1;
+ /* Copy new nodes to global storage. */
+ memcpy(&(*global_svm_nodes)[global_nodes_size],
+ &svm_nodes[1],
+ sizeof(int4) * (svm_nodes.size() - 1));
+ nodes_lock_.unlock();
}
-void SVMShaderManager::device_update(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress)
+void SVMShaderManager::device_update(Device *device,
+ DeviceScene *dscene,
+ Scene *scene,
+ Progress &progress)
{
- if(!need_update)
- return;
+ if (!need_update)
+ return;
- VLOG(1) << "Total " << scene->shaders.size() << " shaders.";
+ VLOG(1) << "Total " << scene->shaders.size() << " shaders.";
- double start_time = time_dt();
+ double start_time = time_dt();
- /* test if we need to update */
- device_free(device, dscene, scene);
+ /* test if we need to update */
+ device_free(device, dscene, scene);
- /* determine which shaders are in use */
- device_update_shaders_used(scene);
+ /* determine which shaders are in use */
+ device_update_shaders_used(scene);
- /* svm_nodes */
- array<int4> svm_nodes;
- size_t i;
+ /* svm_nodes */
+ array<int4> svm_nodes;
+ size_t i;
- for(i = 0; i < scene->shaders.size(); i++) {
- svm_nodes.push_back_slow(make_int4(NODE_SHADER_JUMP, 0, 0, 0));
- }
+ for (i = 0; i < scene->shaders.size(); i++) {
+ svm_nodes.push_back_slow(make_int4(NODE_SHADER_JUMP, 0, 0, 0));
+ }
- TaskPool task_pool;
- foreach(Shader *shader, scene->shaders) {
- task_pool.push(function_bind(&SVMShaderManager::device_update_shader,
- this,
- scene,
- shader,
- &progress,
- &svm_nodes),
- false);
- }
- task_pool.wait_work();
+ TaskPool task_pool;
+ foreach (Shader *shader, scene->shaders) {
+ task_pool.push(
+ function_bind(
+ &SVMShaderManager::device_update_shader, this, scene, shader, &progress, &svm_nodes),
+ false);
+ }
+ task_pool.wait_work();
- if(progress.get_cancel()) {
- return;
- }
+ if (progress.get_cancel()) {
+ return;
+ }
- dscene->svm_nodes.steal_data(svm_nodes);
- dscene->svm_nodes.copy_to_device();
+ dscene->svm_nodes.steal_data(svm_nodes);
+ dscene->svm_nodes.copy_to_device();
- for(i = 0; i < scene->shaders.size(); i++) {
- Shader *shader = scene->shaders[i];
- shader->need_update = false;
- }
+ for (i = 0; i < scene->shaders.size(); i++) {
+ Shader *shader = scene->shaders[i];
+ shader->need_update = false;
+ }
- device_update_common(device, dscene, scene, progress);
+ device_update_common(device, dscene, scene, progress);
- need_update = false;
+ need_update = false;
- VLOG(1) << "Shader manager updated "
- << scene->shaders.size() << " shaders in "
- << time_dt() - start_time << " seconds.";
+ VLOG(1) << "Shader manager updated " << scene->shaders.size() << " shaders in "
+ << time_dt() - start_time << " seconds.";
}
void SVMShaderManager::device_free(Device *device, DeviceScene *dscene, Scene *scene)
{
- device_free_common(device, dscene, scene);
+ device_free_common(device, dscene, scene);
- dscene->svm_nodes.free();
+ dscene->svm_nodes.free();
}
/* Graph Compiler */
@@ -158,772 +157,751 @@ SVMCompiler::SVMCompiler(ShaderManager *shader_manager_,
ImageManager *image_manager_,
LightManager *light_manager_)
{
- shader_manager = shader_manager_;
- image_manager = image_manager_;
- light_manager = light_manager_;
- max_stack_use = 0;
- current_type = SHADER_TYPE_SURFACE;
- current_shader = NULL;
- current_graph = NULL;
- background = false;
- mix_weight_offset = SVM_STACK_INVALID;
- compile_failed = false;
+ shader_manager = shader_manager_;
+ image_manager = image_manager_;
+ light_manager = light_manager_;
+ max_stack_use = 0;
+ current_type = SHADER_TYPE_SURFACE;
+ current_shader = NULL;
+ current_graph = NULL;
+ background = false;
+ mix_weight_offset = SVM_STACK_INVALID;
+ compile_failed = false;
}
int SVMCompiler::stack_size(SocketType::Type type)
{
- int size = 0;
-
- switch(type) {
- case SocketType::FLOAT:
- case SocketType::INT:
- size = 1;
- break;
- case SocketType::COLOR:
- case SocketType::VECTOR:
- case SocketType::NORMAL:
- case SocketType::POINT:
- size = 3;
- break;
- case SocketType::CLOSURE:
- size = 0;
- break;
- default:
- assert(0);
- break;
- }
-
- return size;
+ int size = 0;
+
+ switch (type) {
+ case SocketType::FLOAT:
+ case SocketType::INT:
+ size = 1;
+ break;
+ case SocketType::COLOR:
+ case SocketType::VECTOR:
+ case SocketType::NORMAL:
+ case SocketType::POINT:
+ size = 3;
+ break;
+ case SocketType::CLOSURE:
+ size = 0;
+ break;
+ default:
+ assert(0);
+ break;
+ }
+
+ return size;
}
int SVMCompiler::stack_find_offset(int size)
{
- int offset = -1;
+ int offset = -1;
- /* find free space in stack & mark as used */
- for(int i = 0, num_unused = 0; i < SVM_STACK_SIZE; i++) {
- if(active_stack.users[i]) num_unused = 0;
- else num_unused++;
+ /* find free space in stack & mark as used */
+ for (int i = 0, num_unused = 0; i < SVM_STACK_SIZE; i++) {
+ if (active_stack.users[i])
+ num_unused = 0;
+ else
+ num_unused++;
- if(num_unused == size) {
- offset = i+1 - size;
- max_stack_use = max(i+1, max_stack_use);
+ if (num_unused == size) {
+ offset = i + 1 - size;
+ max_stack_use = max(i + 1, max_stack_use);
- while(i >= offset)
- active_stack.users[i--] = 1;
+ while (i >= offset)
+ active_stack.users[i--] = 1;
- return offset;
- }
- }
+ return offset;
+ }
+ }
- if(!compile_failed) {
- compile_failed = true;
- fprintf(stderr, "Cycles: out of SVM stack space, shader \"%s\" too big.\n", current_shader->name.c_str());
- }
+ if (!compile_failed) {
+ compile_failed = true;
+ fprintf(stderr,
+ "Cycles: out of SVM stack space, shader \"%s\" too big.\n",
+ current_shader->name.c_str());
+ }
- return 0;
+ return 0;
}
int SVMCompiler::stack_find_offset(SocketType::Type type)
{
- return stack_find_offset(stack_size(type));
+ return stack_find_offset(stack_size(type));
}
void SVMCompiler::stack_clear_offset(SocketType::Type type, int offset)
{
- int size = stack_size(type);
+ int size = stack_size(type);
- for(int i = 0; i < size; i++)
- active_stack.users[offset + i]--;
+ for (int i = 0; i < size; i++)
+ active_stack.users[offset + i]--;
}
int SVMCompiler::stack_assign(ShaderInput *input)
{
- /* stack offset assign? */
- if(input->stack_offset == SVM_STACK_INVALID) {
- if(input->link) {
- /* linked to output -> use output offset */
- assert(input->link->stack_offset != SVM_STACK_INVALID);
- input->stack_offset = input->link->stack_offset;
- }
- else {
- Node *node = input->parent;
-
- /* not linked to output -> add nodes to load default value */
- input->stack_offset = stack_find_offset(input->type());
-
- if(input->type() == SocketType::FLOAT) {
- add_node(NODE_VALUE_F, __float_as_int(node->get_float(input->socket_type)), input->stack_offset);
- }
- else if(input->type() == SocketType::INT) {
- add_node(NODE_VALUE_F, node->get_int(input->socket_type), input->stack_offset);
- }
- else if(input->type() == SocketType::VECTOR ||
- input->type() == SocketType::NORMAL ||
- input->type() == SocketType::POINT ||
- input->type() == SocketType::COLOR)
- {
-
- add_node(NODE_VALUE_V, input->stack_offset);
- add_node(NODE_VALUE_V, node->get_float3(input->socket_type));
- }
- else /* should not get called for closure */
- assert(0);
- }
- }
-
- return input->stack_offset;
+ /* stack offset assign? */
+ if (input->stack_offset == SVM_STACK_INVALID) {
+ if (input->link) {
+ /* linked to output -> use output offset */
+ assert(input->link->stack_offset != SVM_STACK_INVALID);
+ input->stack_offset = input->link->stack_offset;
+ }
+ else {
+ Node *node = input->parent;
+
+ /* not linked to output -> add nodes to load default value */
+ input->stack_offset = stack_find_offset(input->type());
+
+ if (input->type() == SocketType::FLOAT) {
+ add_node(NODE_VALUE_F,
+ __float_as_int(node->get_float(input->socket_type)),
+ input->stack_offset);
+ }
+ else if (input->type() == SocketType::INT) {
+ add_node(NODE_VALUE_F, node->get_int(input->socket_type), input->stack_offset);
+ }
+ else if (input->type() == SocketType::VECTOR || input->type() == SocketType::NORMAL ||
+ input->type() == SocketType::POINT || input->type() == SocketType::COLOR) {
+
+ add_node(NODE_VALUE_V, input->stack_offset);
+ add_node(NODE_VALUE_V, node->get_float3(input->socket_type));
+ }
+ else /* should not get called for closure */
+ assert(0);
+ }
+ }
+
+ return input->stack_offset;
}
int SVMCompiler::stack_assign(ShaderOutput *output)
{
- /* if no stack offset assigned yet, find one */
- if(output->stack_offset == SVM_STACK_INVALID)
- output->stack_offset = stack_find_offset(output->type());
+ /* if no stack offset assigned yet, find one */
+ if (output->stack_offset == SVM_STACK_INVALID)
+ output->stack_offset = stack_find_offset(output->type());
- return output->stack_offset;
+ return output->stack_offset;
}
int SVMCompiler::stack_assign_if_linked(ShaderInput *input)
{
- if(input->link)
- return stack_assign(input);
+ if (input->link)
+ return stack_assign(input);
- return SVM_STACK_INVALID;
+ return SVM_STACK_INVALID;
}
int SVMCompiler::stack_assign_if_linked(ShaderOutput *output)
{
- if(!output->links.empty())
- return stack_assign(output);
+ if (!output->links.empty())
+ return stack_assign(output);
- return SVM_STACK_INVALID;
+ return SVM_STACK_INVALID;
}
void SVMCompiler::stack_link(ShaderInput *input, ShaderOutput *output)
{
- if(output->stack_offset == SVM_STACK_INVALID) {
- assert(input->link);
- assert(stack_size(output->type()) == stack_size(input->link->type()));
+ if (output->stack_offset == SVM_STACK_INVALID) {
+ assert(input->link);
+ assert(stack_size(output->type()) == stack_size(input->link->type()));
- output->stack_offset = input->link->stack_offset;
+ output->stack_offset = input->link->stack_offset;
- int size = stack_size(output->type());
+ int size = stack_size(output->type());
- for(int i = 0; i < size; i++)
- active_stack.users[output->stack_offset + i]++;
- }
+ for (int i = 0; i < size; i++)
+ active_stack.users[output->stack_offset + i]++;
+ }
}
-void SVMCompiler::stack_clear_users(ShaderNode *node, ShaderNodeSet& done)
+void SVMCompiler::stack_clear_users(ShaderNode *node, ShaderNodeSet &done)
{
- /* optimization we should add:
- * find and lower user counts for outputs for which all inputs are done.
- * this is done before the node is compiled, under the assumption that the
- * node will first load all inputs from the stack and then writes its
- * outputs. this used to work, but was disabled because it gave trouble
- * with inputs getting stack positions assigned */
+ /* optimization we should add:
+ * find and lower user counts for outputs for which all inputs are done.
+ * this is done before the node is compiled, under the assumption that the
+ * node will first load all inputs from the stack and then writes its
+ * outputs. this used to work, but was disabled because it gave trouble
+ * with inputs getting stack positions assigned */
- foreach(ShaderInput *input, node->inputs) {
- ShaderOutput *output = input->link;
+ foreach (ShaderInput *input, node->inputs) {
+ ShaderOutput *output = input->link;
- if(output && output->stack_offset != SVM_STACK_INVALID) {
- bool all_done = true;
+ if (output && output->stack_offset != SVM_STACK_INVALID) {
+ bool all_done = true;
- /* optimization we should add: verify if in->parent is actually used */
- foreach(ShaderInput *in, output->links)
- if(in->parent != node && done.find(in->parent) == done.end())
- all_done = false;
+ /* optimization we should add: verify if in->parent is actually used */
+ foreach (ShaderInput *in, output->links)
+ if (in->parent != node && done.find(in->parent) == done.end())
+ all_done = false;
- if(all_done) {
- stack_clear_offset(output->type(), output->stack_offset);
- output->stack_offset = SVM_STACK_INVALID;
+ if (all_done) {
+ stack_clear_offset(output->type(), output->stack_offset);
+ output->stack_offset = SVM_STACK_INVALID;
- foreach(ShaderInput *in, output->links)
- in->stack_offset = SVM_STACK_INVALID;
- }
- }
- }
+ foreach (ShaderInput *in, output->links)
+ in->stack_offset = SVM_STACK_INVALID;
+ }
+ }
+ }
}
void SVMCompiler::stack_clear_temporary(ShaderNode *node)
{
- foreach(ShaderInput *input, node->inputs) {
- if(!input->link && input->stack_offset != SVM_STACK_INVALID) {
- stack_clear_offset(input->type(), input->stack_offset);
- input->stack_offset = SVM_STACK_INVALID;
- }
- }
+ foreach (ShaderInput *input, node->inputs) {
+ if (!input->link && input->stack_offset != SVM_STACK_INVALID) {
+ stack_clear_offset(input->type(), input->stack_offset);
+ input->stack_offset = SVM_STACK_INVALID;
+ }
+ }
}
uint SVMCompiler::encode_uchar4(uint x, uint y, uint z, uint w)
{
- assert(x <= 255);
- assert(y <= 255);
- assert(z <= 255);
- assert(w <= 255);
+ assert(x <= 255);
+ assert(y <= 255);
+ assert(z <= 255);
+ assert(w <= 255);
- return (x) | (y << 8) | (z << 16) | (w << 24);
+ return (x) | (y << 8) | (z << 16) | (w << 24);
}
void SVMCompiler::add_node(int a, int b, int c, int d)
{
- current_svm_nodes.push_back_slow(make_int4(a, b, c, d));
+ current_svm_nodes.push_back_slow(make_int4(a, b, c, d));
}
void SVMCompiler::add_node(ShaderNodeType type, int a, int b, int c)
{
- current_svm_nodes.push_back_slow(make_int4(type, a, b, c));
+ current_svm_nodes.push_back_slow(make_int4(type, a, b, c));
}
-void SVMCompiler::add_node(ShaderNodeType type, const float3& f)
+void SVMCompiler::add_node(ShaderNodeType type, const float3 &f)
{
- current_svm_nodes.push_back_slow(make_int4(type,
- __float_as_int(f.x),
- __float_as_int(f.y),
- __float_as_int(f.z)));
+ current_svm_nodes.push_back_slow(
+ make_int4(type, __float_as_int(f.x), __float_as_int(f.y), __float_as_int(f.z)));
}
-void SVMCompiler::add_node(const float4& f)
+void SVMCompiler::add_node(const float4 &f)
{
- current_svm_nodes.push_back_slow(make_int4(
- __float_as_int(f.x),
- __float_as_int(f.y),
- __float_as_int(f.z),
- __float_as_int(f.w)));
+ current_svm_nodes.push_back_slow(make_int4(
+ __float_as_int(f.x), __float_as_int(f.y), __float_as_int(f.z), __float_as_int(f.w)));
}
uint SVMCompiler::attribute(ustring name)
{
- return shader_manager->get_attribute_id(name);
+ return shader_manager->get_attribute_id(name);
}
uint SVMCompiler::attribute(AttributeStandard std)
{
- return shader_manager->get_attribute_id(std);
+ return shader_manager->get_attribute_id(std);
}
uint SVMCompiler::attribute_standard(ustring name)
{
- AttributeStandard std = Attribute::name_standard(name.c_str());
- return (std)? attribute(std): attribute(name);
+ AttributeStandard std = Attribute::name_standard(name.c_str());
+ return (std) ? attribute(std) : attribute(name);
}
-void SVMCompiler::find_dependencies(ShaderNodeSet& dependencies,
- const ShaderNodeSet& done,
+void SVMCompiler::find_dependencies(ShaderNodeSet &dependencies,
+ const ShaderNodeSet &done,
ShaderInput *input,
ShaderNode *skip_node)
{
- ShaderNode *node = (input->link)? input->link->parent: NULL;
- if(node != NULL &&
- done.find(node) == done.end() &&
- node != skip_node &&
- dependencies.find(node) == dependencies.end())
- {
- foreach(ShaderInput *in, node->inputs) {
- find_dependencies(dependencies, done, in, skip_node);
- }
- dependencies.insert(node);
- }
-}
-
-void SVMCompiler::generate_node(ShaderNode *node, ShaderNodeSet& done)
-{
- node->compile(*this);
- stack_clear_users(node, done);
- stack_clear_temporary(node);
-
- if(current_type == SHADER_TYPE_SURFACE) {
- if(node->has_spatial_varying())
- current_shader->has_surface_spatial_varying = true;
- }
- else if(current_type == SHADER_TYPE_VOLUME) {
- if(node->has_spatial_varying())
- current_shader->has_volume_spatial_varying = true;
- }
-
- if(node->has_object_dependency()) {
- current_shader->has_object_dependency = true;
- }
-
- if(node->has_attribute_dependency()) {
- current_shader->has_attribute_dependency = true;
- }
-
- if(node->has_integrator_dependency()) {
- current_shader->has_integrator_dependency = true;
- }
-}
-
-void SVMCompiler::generate_svm_nodes(const ShaderNodeSet& nodes,
- CompilerState *state)
-{
- ShaderNodeSet& done = state->nodes_done;
- vector<bool>& done_flag = state->nodes_done_flag;
-
- bool nodes_done;
- do {
- nodes_done = true;
-
- foreach(ShaderNode *node, nodes) {
- if(!done_flag[node->id]) {
- bool inputs_done = true;
-
- foreach(ShaderInput *input, node->inputs) {
- if(input->link && !done_flag[input->link->parent->id]) {
- inputs_done = false;
- }
- }
- if(inputs_done) {
- generate_node(node, done);
- done.insert(node);
- done_flag[node->id] = true;
- }
- else {
- nodes_done = false;
- }
- }
- }
- } while(!nodes_done);
-}
-
-void SVMCompiler::generate_closure_node(ShaderNode *node,
- CompilerState *state)
-{
- /* execute dependencies for closure */
- foreach(ShaderInput *in, node->inputs) {
- if(in->link != NULL) {
- ShaderNodeSet dependencies;
- find_dependencies(dependencies, state->nodes_done, in);
- generate_svm_nodes(dependencies, state);
- }
- }
-
- /* closure mix weight */
- const char *weight_name = (current_type == SHADER_TYPE_VOLUME)? "VolumeMixWeight": "SurfaceMixWeight";
- ShaderInput *weight_in = node->input(weight_name);
-
- if(weight_in && (weight_in->link || node->get_float(weight_in->socket_type) != 1.0f))
- mix_weight_offset = stack_assign(weight_in);
- else
- mix_weight_offset = SVM_STACK_INVALID;
-
- /* compile closure itself */
- generate_node(node, state->nodes_done);
-
- mix_weight_offset = SVM_STACK_INVALID;
-
- if(current_type == SHADER_TYPE_SURFACE) {
- if(node->has_surface_emission())
- current_shader->has_surface_emission = true;
- if(node->has_surface_transparent())
- current_shader->has_surface_transparent = true;
- if(node->has_surface_bssrdf()) {
- current_shader->has_surface_bssrdf = true;
- if(node->has_bssrdf_bump())
- current_shader->has_bssrdf_bump = true;
- }
- if(node->has_bump()) {
- current_shader->has_bump = true;
- }
- }
+ ShaderNode *node = (input->link) ? input->link->parent : NULL;
+ if (node != NULL && done.find(node) == done.end() && node != skip_node &&
+ dependencies.find(node) == dependencies.end()) {
+ foreach (ShaderInput *in, node->inputs) {
+ find_dependencies(dependencies, done, in, skip_node);
+ }
+ dependencies.insert(node);
+ }
+}
+
+void SVMCompiler::generate_node(ShaderNode *node, ShaderNodeSet &done)
+{
+ node->compile(*this);
+ stack_clear_users(node, done);
+ stack_clear_temporary(node);
+
+ if (current_type == SHADER_TYPE_SURFACE) {
+ if (node->has_spatial_varying())
+ current_shader->has_surface_spatial_varying = true;
+ }
+ else if (current_type == SHADER_TYPE_VOLUME) {
+ if (node->has_spatial_varying())
+ current_shader->has_volume_spatial_varying = true;
+ }
+
+ if (node->has_object_dependency()) {
+ current_shader->has_object_dependency = true;
+ }
+
+ if (node->has_attribute_dependency()) {
+ current_shader->has_attribute_dependency = true;
+ }
+
+ if (node->has_integrator_dependency()) {
+ current_shader->has_integrator_dependency = true;
+ }
+}
+
+void SVMCompiler::generate_svm_nodes(const ShaderNodeSet &nodes, CompilerState *state)
+{
+ ShaderNodeSet &done = state->nodes_done;
+ vector<bool> &done_flag = state->nodes_done_flag;
+
+ bool nodes_done;
+ do {
+ nodes_done = true;
+
+ foreach (ShaderNode *node, nodes) {
+ if (!done_flag[node->id]) {
+ bool inputs_done = true;
+
+ foreach (ShaderInput *input, node->inputs) {
+ if (input->link && !done_flag[input->link->parent->id]) {
+ inputs_done = false;
+ }
+ }
+ if (inputs_done) {
+ generate_node(node, done);
+ done.insert(node);
+ done_flag[node->id] = true;
+ }
+ else {
+ nodes_done = false;
+ }
+ }
+ }
+ } while (!nodes_done);
+}
+
+void SVMCompiler::generate_closure_node(ShaderNode *node, CompilerState *state)
+{
+ /* execute dependencies for closure */
+ foreach (ShaderInput *in, node->inputs) {
+ if (in->link != NULL) {
+ ShaderNodeSet dependencies;
+ find_dependencies(dependencies, state->nodes_done, in);
+ generate_svm_nodes(dependencies, state);
+ }
+ }
+
+ /* closure mix weight */
+ const char *weight_name = (current_type == SHADER_TYPE_VOLUME) ? "VolumeMixWeight" :
+ "SurfaceMixWeight";
+ ShaderInput *weight_in = node->input(weight_name);
+
+ if (weight_in && (weight_in->link || node->get_float(weight_in->socket_type) != 1.0f))
+ mix_weight_offset = stack_assign(weight_in);
+ else
+ mix_weight_offset = SVM_STACK_INVALID;
+
+ /* compile closure itself */
+ generate_node(node, state->nodes_done);
+
+ mix_weight_offset = SVM_STACK_INVALID;
+
+ if (current_type == SHADER_TYPE_SURFACE) {
+ if (node->has_surface_emission())
+ current_shader->has_surface_emission = true;
+ if (node->has_surface_transparent())
+ current_shader->has_surface_transparent = true;
+ if (node->has_surface_bssrdf()) {
+ current_shader->has_surface_bssrdf = true;
+ if (node->has_bssrdf_bump())
+ current_shader->has_bssrdf_bump = true;
+ }
+ if (node->has_bump()) {
+ current_shader->has_bump = true;
+ }
+ }
}
void SVMCompiler::generated_shared_closure_nodes(ShaderNode *root_node,
ShaderNode *node,
CompilerState *state,
- const ShaderNodeSet& shared)
-{
- if(shared.find(node) != shared.end()) {
- generate_multi_closure(root_node, node, state);
- }
- else {
- foreach(ShaderInput *in, node->inputs) {
- if(in->type() == SocketType::CLOSURE && in->link)
- generated_shared_closure_nodes(root_node,
- in->link->parent,
- state,
- shared);
- }
- }
+ const ShaderNodeSet &shared)
+{
+ if (shared.find(node) != shared.end()) {
+ generate_multi_closure(root_node, node, state);
+ }
+ else {
+ foreach (ShaderInput *in, node->inputs) {
+ if (in->type() == SocketType::CLOSURE && in->link)
+ generated_shared_closure_nodes(root_node, in->link->parent, state, shared);
+ }
+ }
}
void SVMCompiler::generate_multi_closure(ShaderNode *root_node,
ShaderNode *node,
CompilerState *state)
{
- /* only generate once */
- if(state->closure_done.find(node) != state->closure_done.end())
- return;
-
- state->closure_done.insert(node);
-
- if(node->special_type == SHADER_SPECIAL_TYPE_COMBINE_CLOSURE) {
- /* weighting is already taken care of in ShaderGraph::transform_multi_closure */
- ShaderInput *cl1in = node->input("Closure1");
- ShaderInput *cl2in = node->input("Closure2");
- ShaderInput *facin = node->input("Fac");
-
- /* skip empty mix/add closure nodes */
- if(!cl1in->link && !cl2in->link)
- return;
-
- if(facin && facin->link) {
- /* mix closure: generate instructions to compute mix weight */
- ShaderNodeSet dependencies;
- find_dependencies(dependencies, state->nodes_done, facin);
- generate_svm_nodes(dependencies, state);
-
- /* execute shared dependencies. this is needed to allow skipping
- * of zero weight closures and their dependencies later, so we
- * ensure that they only skip dependencies that are unique to them */
- ShaderNodeSet cl1deps, cl2deps, shareddeps;
-
- find_dependencies(cl1deps, state->nodes_done, cl1in);
- find_dependencies(cl2deps, state->nodes_done, cl2in);
-
- ShaderNodeIDComparator node_id_comp;
- set_intersection(cl1deps.begin(), cl1deps.end(),
- cl2deps.begin(), cl2deps.end(),
- std::inserter(shareddeps, shareddeps.begin()),
- node_id_comp);
-
- /* it's possible some nodes are not shared between this mix node
- * inputs, but still needed to be always executed, this mainly
- * happens when a node of current subbranch is used by a parent
- * node or so */
- if(root_node != node) {
- foreach(ShaderInput *in, root_node->inputs) {
- ShaderNodeSet rootdeps;
- find_dependencies(rootdeps, state->nodes_done, in, node);
- set_intersection(rootdeps.begin(), rootdeps.end(),
- cl1deps.begin(), cl1deps.end(),
- std::inserter(shareddeps, shareddeps.begin()),
- node_id_comp);
- set_intersection(rootdeps.begin(), rootdeps.end(),
- cl2deps.begin(), cl2deps.end(),
- std::inserter(shareddeps, shareddeps.begin()),
- node_id_comp);
- }
- }
-
- if(!shareddeps.empty()) {
- if(cl1in->link) {
- generated_shared_closure_nodes(root_node,
- cl1in->link->parent,
- state,
- shareddeps);
- }
- if(cl2in->link) {
- generated_shared_closure_nodes(root_node,
- cl2in->link->parent,
- state,
- shareddeps);
- }
-
- generate_svm_nodes(shareddeps, state);
- }
-
- /* generate instructions for input closure 1 */
- if(cl1in->link) {
- /* Add instruction to skip closure and its dependencies if mix
- * weight is zero.
- */
- current_svm_nodes.push_back_slow(make_int4(NODE_JUMP_IF_ONE,
- 0,
- stack_assign(facin),
- 0));
- int node_jump_skip_index = current_svm_nodes.size() - 1;
-
- generate_multi_closure(root_node, cl1in->link->parent, state);
-
- /* Fill in jump instruction location to be after closure. */
- current_svm_nodes[node_jump_skip_index].y =
- current_svm_nodes.size() - node_jump_skip_index - 1;
- }
-
- /* generate instructions for input closure 2 */
- if(cl2in->link) {
- /* Add instruction to skip closure and its dependencies if mix
- * weight is zero.
- */
- current_svm_nodes.push_back_slow(make_int4(NODE_JUMP_IF_ZERO,
- 0,
- stack_assign(facin),
- 0));
- int node_jump_skip_index = current_svm_nodes.size() - 1;
-
- generate_multi_closure(root_node, cl2in->link->parent, state);
-
- /* Fill in jump instruction location to be after closure. */
- current_svm_nodes[node_jump_skip_index].y =
- current_svm_nodes.size() - node_jump_skip_index - 1;
- }
-
- /* unassign */
- facin->stack_offset = SVM_STACK_INVALID;
- }
- else {
- /* execute closures and their dependencies, no runtime checks
- * to skip closures here because was already optimized due to
- * fixed weight or add closure that always needs both */
- if(cl1in->link)
- generate_multi_closure(root_node, cl1in->link->parent, state);
- if(cl2in->link)
- generate_multi_closure(root_node, cl2in->link->parent, state);
- }
- }
- else {
- generate_closure_node(node, state);
- }
-
- state->nodes_done.insert(node);
- state->nodes_done_flag[node->id] = true;
+ /* only generate once */
+ if (state->closure_done.find(node) != state->closure_done.end())
+ return;
+
+ state->closure_done.insert(node);
+
+ if (node->special_type == SHADER_SPECIAL_TYPE_COMBINE_CLOSURE) {
+ /* weighting is already taken care of in ShaderGraph::transform_multi_closure */
+ ShaderInput *cl1in = node->input("Closure1");
+ ShaderInput *cl2in = node->input("Closure2");
+ ShaderInput *facin = node->input("Fac");
+
+ /* skip empty mix/add closure nodes */
+ if (!cl1in->link && !cl2in->link)
+ return;
+
+ if (facin && facin->link) {
+ /* mix closure: generate instructions to compute mix weight */
+ ShaderNodeSet dependencies;
+ find_dependencies(dependencies, state->nodes_done, facin);
+ generate_svm_nodes(dependencies, state);
+
+ /* execute shared dependencies. this is needed to allow skipping
+ * of zero weight closures and their dependencies later, so we
+ * ensure that they only skip dependencies that are unique to them */
+ ShaderNodeSet cl1deps, cl2deps, shareddeps;
+
+ find_dependencies(cl1deps, state->nodes_done, cl1in);
+ find_dependencies(cl2deps, state->nodes_done, cl2in);
+
+ ShaderNodeIDComparator node_id_comp;
+ set_intersection(cl1deps.begin(),
+ cl1deps.end(),
+ cl2deps.begin(),
+ cl2deps.end(),
+ std::inserter(shareddeps, shareddeps.begin()),
+ node_id_comp);
+
+ /* it's possible some nodes are not shared between this mix node
+ * inputs, but still needed to be always executed, this mainly
+ * happens when a node of current subbranch is used by a parent
+ * node or so */
+ if (root_node != node) {
+ foreach (ShaderInput *in, root_node->inputs) {
+ ShaderNodeSet rootdeps;
+ find_dependencies(rootdeps, state->nodes_done, in, node);
+ set_intersection(rootdeps.begin(),
+ rootdeps.end(),
+ cl1deps.begin(),
+ cl1deps.end(),
+ std::inserter(shareddeps, shareddeps.begin()),
+ node_id_comp);
+ set_intersection(rootdeps.begin(),
+ rootdeps.end(),
+ cl2deps.begin(),
+ cl2deps.end(),
+ std::inserter(shareddeps, shareddeps.begin()),
+ node_id_comp);
+ }
+ }
+
+ if (!shareddeps.empty()) {
+ if (cl1in->link) {
+ generated_shared_closure_nodes(root_node, cl1in->link->parent, state, shareddeps);
+ }
+ if (cl2in->link) {
+ generated_shared_closure_nodes(root_node, cl2in->link->parent, state, shareddeps);
+ }
+
+ generate_svm_nodes(shareddeps, state);
+ }
+
+ /* generate instructions for input closure 1 */
+ if (cl1in->link) {
+ /* Add instruction to skip closure and its dependencies if mix
+ * weight is zero.
+ */
+ current_svm_nodes.push_back_slow(make_int4(NODE_JUMP_IF_ONE, 0, stack_assign(facin), 0));
+ int node_jump_skip_index = current_svm_nodes.size() - 1;
+
+ generate_multi_closure(root_node, cl1in->link->parent, state);
+
+ /* Fill in jump instruction location to be after closure. */
+ current_svm_nodes[node_jump_skip_index].y = current_svm_nodes.size() -
+ node_jump_skip_index - 1;
+ }
+
+ /* generate instructions for input closure 2 */
+ if (cl2in->link) {
+ /* Add instruction to skip closure and its dependencies if mix
+ * weight is zero.
+ */
+ current_svm_nodes.push_back_slow(make_int4(NODE_JUMP_IF_ZERO, 0, stack_assign(facin), 0));
+ int node_jump_skip_index = current_svm_nodes.size() - 1;
+
+ generate_multi_closure(root_node, cl2in->link->parent, state);
+
+ /* Fill in jump instruction location to be after closure. */
+ current_svm_nodes[node_jump_skip_index].y = current_svm_nodes.size() -
+ node_jump_skip_index - 1;
+ }
+
+ /* unassign */
+ facin->stack_offset = SVM_STACK_INVALID;
+ }
+ else {
+ /* execute closures and their dependencies, no runtime checks
+ * to skip closures here because was already optimized due to
+ * fixed weight or add closure that always needs both */
+ if (cl1in->link)
+ generate_multi_closure(root_node, cl1in->link->parent, state);
+ if (cl2in->link)
+ generate_multi_closure(root_node, cl2in->link->parent, state);
+ }
+ }
+ else {
+ generate_closure_node(node, state);
+ }
+
+ state->nodes_done.insert(node);
+ state->nodes_done_flag[node->id] = true;
}
-
void SVMCompiler::compile_type(Shader *shader, ShaderGraph *graph, ShaderType type)
{
- /* Converting a shader graph into svm_nodes that can be executed
- * sequentially on the virtual machine is fairly simple. We can keep
- * looping over nodes and each time all the inputs of a node are
- * ready, we add svm_nodes for it that read the inputs from the
- * stack and write outputs back to the stack.
- *
- * With the SVM, we always sample only a single closure. We can think
- * of all closures nodes as a binary tree with mix closures as inner
- * nodes and other closures as leafs. The SVM will traverse that tree,
- * each time deciding to go left or right depending on the mix weights,
- * until a closure is found.
- *
- * We only execute nodes that are needed for the mix weights and chosen
- * closure.
- */
-
- current_type = type;
- current_graph = graph;
-
- /* get input in output node */
- ShaderNode *node = graph->output();
- ShaderInput *clin = NULL;
-
- switch(type) {
- case SHADER_TYPE_SURFACE:
- clin = node->input("Surface");
- break;
- case SHADER_TYPE_VOLUME:
- clin = node->input("Volume");
- break;
- case SHADER_TYPE_DISPLACEMENT:
- clin = node->input("Displacement");
- break;
- case SHADER_TYPE_BUMP:
- clin = node->input("Normal");
- break;
- default:
- assert(0);
- break;
- }
-
- /* clear all compiler state */
- memset((void *)&active_stack, 0, sizeof(active_stack));
- current_svm_nodes.clear();
-
- foreach(ShaderNode *node_iter, graph->nodes) {
- foreach(ShaderInput *input, node_iter->inputs)
- input->stack_offset = SVM_STACK_INVALID;
- foreach(ShaderOutput *output, node_iter->outputs)
- output->stack_offset = SVM_STACK_INVALID;
- }
-
- /* for the bump shader we need add a node to store the shader state */
- bool need_bump_state = (type == SHADER_TYPE_BUMP) && (shader->displacement_method == DISPLACE_BOTH);
- int bump_state_offset = SVM_STACK_INVALID;
- if(need_bump_state) {
- bump_state_offset = stack_find_offset(SVM_BUMP_EVAL_STATE_SIZE);
- add_node(NODE_ENTER_BUMP_EVAL, bump_state_offset);
- }
-
- if(shader->used) {
- if(clin->link) {
- bool generate = false;
-
- switch(type) {
- case SHADER_TYPE_SURFACE: /* generate surface shader */
- generate = true;
- shader->has_surface = true;
- break;
- case SHADER_TYPE_VOLUME: /* generate volume shader */
- generate = true;
- shader->has_volume = true;
- break;
- case SHADER_TYPE_DISPLACEMENT: /* generate displacement shader */
- generate = true;
- shader->has_displacement = true;
- break;
- case SHADER_TYPE_BUMP: /* generate bump shader */
- generate = true;
- break;
- default:
- break;
- }
-
- if(generate) {
- CompilerState state(graph);
- generate_multi_closure(clin->link->parent,
- clin->link->parent,
- &state);
- }
- }
-
- /* compile output node */
- node->compile(*this);
- }
-
- /* add node to restore state after bump shader has finished */
- if(need_bump_state) {
- add_node(NODE_LEAVE_BUMP_EVAL, bump_state_offset);
- }
-
- /* if compile failed, generate empty shader */
- if(compile_failed) {
- current_svm_nodes.clear();
- compile_failed = false;
- }
-
- /* for bump shaders we fall thru to the surface shader, but if this is any other kind of shader it ends here */
- if(type != SHADER_TYPE_BUMP) {
- add_node(NODE_END, 0, 0, 0);
- }
-}
-
-void SVMCompiler::compile(Scene *scene,
- Shader *shader,
- array<int4>& svm_nodes,
- int index,
- Summary *summary)
-{
- /* copy graph for shader with bump mapping */
- ShaderNode *output = shader->graph->output();
- int start_num_svm_nodes = svm_nodes.size();
-
- const double time_start = time_dt();
-
- bool has_bump = (shader->displacement_method != DISPLACE_TRUE) &&
- output->input("Surface")->link && output->input("Displacement")->link;
-
- /* finalize */
- {
- scoped_timer timer((summary != NULL)? &summary->time_finalize: NULL);
- shader->graph->finalize(scene,
- has_bump,
- shader->has_integrator_dependency,
- shader->displacement_method == DISPLACE_BOTH);
- }
-
- current_shader = shader;
-
- shader->has_surface = false;
- shader->has_surface_emission = false;
- shader->has_surface_transparent = false;
- shader->has_surface_bssrdf = false;
- shader->has_bump = has_bump;
- shader->has_bssrdf_bump = has_bump;
- shader->has_volume = false;
- shader->has_displacement = false;
- shader->has_surface_spatial_varying = false;
- shader->has_volume_spatial_varying = false;
- shader->has_object_dependency = false;
- shader->has_attribute_dependency = false;
- shader->has_integrator_dependency = false;
-
- /* generate bump shader */
- if(has_bump) {
- scoped_timer timer((summary != NULL)? &summary->time_generate_bump: NULL);
- compile_type(shader, shader->graph, SHADER_TYPE_BUMP);
- svm_nodes[index].y = svm_nodes.size();
- svm_nodes.append(current_svm_nodes);
- }
-
- /* generate surface shader */
- {
- scoped_timer timer((summary != NULL)? &summary->time_generate_surface: NULL);
- compile_type(shader, shader->graph, SHADER_TYPE_SURFACE);
- /* only set jump offset if there's no bump shader, as the bump shader will fall thru to this one if it exists */
- if(!has_bump) {
- svm_nodes[index].y = svm_nodes.size();
- }
- svm_nodes.append(current_svm_nodes);
- }
-
- /* generate volume shader */
- {
- scoped_timer timer((summary != NULL)? &summary->time_generate_volume: NULL);
- compile_type(shader, shader->graph, SHADER_TYPE_VOLUME);
- svm_nodes[index].z = svm_nodes.size();
- svm_nodes.append(current_svm_nodes);
- }
-
- /* generate displacement shader */
- {
- scoped_timer timer((summary != NULL)? &summary->time_generate_displacement: NULL);
- compile_type(shader, shader->graph, SHADER_TYPE_DISPLACEMENT);
- svm_nodes[index].w = svm_nodes.size();
- svm_nodes.append(current_svm_nodes);
- }
-
- /* Fill in summary information. */
- if(summary != NULL) {
- summary->time_total = time_dt() - time_start;
- summary->peak_stack_usage = max_stack_use;
- summary->num_svm_nodes = svm_nodes.size() - start_num_svm_nodes;
- }
+ /* Converting a shader graph into svm_nodes that can be executed
+ * sequentially on the virtual machine is fairly simple. We can keep
+ * looping over nodes and each time all the inputs of a node are
+ * ready, we add svm_nodes for it that read the inputs from the
+ * stack and write outputs back to the stack.
+ *
+ * With the SVM, we always sample only a single closure. We can think
+ * of all closures nodes as a binary tree with mix closures as inner
+ * nodes and other closures as leafs. The SVM will traverse that tree,
+ * each time deciding to go left or right depending on the mix weights,
+ * until a closure is found.
+ *
+ * We only execute nodes that are needed for the mix weights and chosen
+ * closure.
+ */
+
+ current_type = type;
+ current_graph = graph;
+
+ /* get input in output node */
+ ShaderNode *node = graph->output();
+ ShaderInput *clin = NULL;
+
+ switch (type) {
+ case SHADER_TYPE_SURFACE:
+ clin = node->input("Surface");
+ break;
+ case SHADER_TYPE_VOLUME:
+ clin = node->input("Volume");
+ break;
+ case SHADER_TYPE_DISPLACEMENT:
+ clin = node->input("Displacement");
+ break;
+ case SHADER_TYPE_BUMP:
+ clin = node->input("Normal");
+ break;
+ default:
+ assert(0);
+ break;
+ }
+
+ /* clear all compiler state */
+ memset((void *)&active_stack, 0, sizeof(active_stack));
+ current_svm_nodes.clear();
+
+ foreach (ShaderNode *node_iter, graph->nodes) {
+ foreach (ShaderInput *input, node_iter->inputs)
+ input->stack_offset = SVM_STACK_INVALID;
+ foreach (ShaderOutput *output, node_iter->outputs)
+ output->stack_offset = SVM_STACK_INVALID;
+ }
+
+ /* for the bump shader we need add a node to store the shader state */
+ bool need_bump_state = (type == SHADER_TYPE_BUMP) &&
+ (shader->displacement_method == DISPLACE_BOTH);
+ int bump_state_offset = SVM_STACK_INVALID;
+ if (need_bump_state) {
+ bump_state_offset = stack_find_offset(SVM_BUMP_EVAL_STATE_SIZE);
+ add_node(NODE_ENTER_BUMP_EVAL, bump_state_offset);
+ }
+
+ if (shader->used) {
+ if (clin->link) {
+ bool generate = false;
+
+ switch (type) {
+ case SHADER_TYPE_SURFACE: /* generate surface shader */
+ generate = true;
+ shader->has_surface = true;
+ break;
+ case SHADER_TYPE_VOLUME: /* generate volume shader */
+ generate = true;
+ shader->has_volume = true;
+ break;
+ case SHADER_TYPE_DISPLACEMENT: /* generate displacement shader */
+ generate = true;
+ shader->has_displacement = true;
+ break;
+ case SHADER_TYPE_BUMP: /* generate bump shader */
+ generate = true;
+ break;
+ default:
+ break;
+ }
+
+ if (generate) {
+ CompilerState state(graph);
+ generate_multi_closure(clin->link->parent, clin->link->parent, &state);
+ }
+ }
+
+ /* compile output node */
+ node->compile(*this);
+ }
+
+ /* add node to restore state after bump shader has finished */
+ if (need_bump_state) {
+ add_node(NODE_LEAVE_BUMP_EVAL, bump_state_offset);
+ }
+
+ /* if compile failed, generate empty shader */
+ if (compile_failed) {
+ current_svm_nodes.clear();
+ compile_failed = false;
+ }
+
+ /* for bump shaders we fall thru to the surface shader, but if this is any other kind of shader it ends here */
+ if (type != SHADER_TYPE_BUMP) {
+ add_node(NODE_END, 0, 0, 0);
+ }
+}
+
+void SVMCompiler::compile(
+ Scene *scene, Shader *shader, array<int4> &svm_nodes, int index, Summary *summary)
+{
+ /* copy graph for shader with bump mapping */
+ ShaderNode *output = shader->graph->output();
+ int start_num_svm_nodes = svm_nodes.size();
+
+ const double time_start = time_dt();
+
+ bool has_bump = (shader->displacement_method != DISPLACE_TRUE) &&
+ output->input("Surface")->link && output->input("Displacement")->link;
+
+ /* finalize */
+ {
+ scoped_timer timer((summary != NULL) ? &summary->time_finalize : NULL);
+ shader->graph->finalize(scene,
+ has_bump,
+ shader->has_integrator_dependency,
+ shader->displacement_method == DISPLACE_BOTH);
+ }
+
+ current_shader = shader;
+
+ shader->has_surface = false;
+ shader->has_surface_emission = false;
+ shader->has_surface_transparent = false;
+ shader->has_surface_bssrdf = false;
+ shader->has_bump = has_bump;
+ shader->has_bssrdf_bump = has_bump;
+ shader->has_volume = false;
+ shader->has_displacement = false;
+ shader->has_surface_spatial_varying = false;
+ shader->has_volume_spatial_varying = false;
+ shader->has_object_dependency = false;
+ shader->has_attribute_dependency = false;
+ shader->has_integrator_dependency = false;
+
+ /* generate bump shader */
+ if (has_bump) {
+ scoped_timer timer((summary != NULL) ? &summary->time_generate_bump : NULL);
+ compile_type(shader, shader->graph, SHADER_TYPE_BUMP);
+ svm_nodes[index].y = svm_nodes.size();
+ svm_nodes.append(current_svm_nodes);
+ }
+
+ /* generate surface shader */
+ {
+ scoped_timer timer((summary != NULL) ? &summary->time_generate_surface : NULL);
+ compile_type(shader, shader->graph, SHADER_TYPE_SURFACE);
+ /* only set jump offset if there's no bump shader, as the bump shader will fall thru to this one if it exists */
+ if (!has_bump) {
+ svm_nodes[index].y = svm_nodes.size();
+ }
+ svm_nodes.append(current_svm_nodes);
+ }
+
+ /* generate volume shader */
+ {
+ scoped_timer timer((summary != NULL) ? &summary->time_generate_volume : NULL);
+ compile_type(shader, shader->graph, SHADER_TYPE_VOLUME);
+ svm_nodes[index].z = svm_nodes.size();
+ svm_nodes.append(current_svm_nodes);
+ }
+
+ /* generate displacement shader */
+ {
+ scoped_timer timer((summary != NULL) ? &summary->time_generate_displacement : NULL);
+ compile_type(shader, shader->graph, SHADER_TYPE_DISPLACEMENT);
+ svm_nodes[index].w = svm_nodes.size();
+ svm_nodes.append(current_svm_nodes);
+ }
+
+ /* Fill in summary information. */
+ if (summary != NULL) {
+ summary->time_total = time_dt() - time_start;
+ summary->peak_stack_usage = max_stack_use;
+ summary->num_svm_nodes = svm_nodes.size() - start_num_svm_nodes;
+ }
}
/* Compiler summary implementation. */
SVMCompiler::Summary::Summary()
- : num_svm_nodes(0),
- peak_stack_usage(0),
- time_finalize(0.0),
- time_generate_surface(0.0),
- time_generate_bump(0.0),
- time_generate_volume(0.0),
- time_generate_displacement(0.0),
- time_total(0.0)
+ : num_svm_nodes(0),
+ peak_stack_usage(0),
+ time_finalize(0.0),
+ time_generate_surface(0.0),
+ time_generate_bump(0.0),
+ time_generate_volume(0.0),
+ time_generate_displacement(0.0),
+ time_total(0.0)
{
}
string SVMCompiler::Summary::full_report() const
{
- string report = "";
- report += string_printf("Number of SVM nodes: %d\n", num_svm_nodes);
- report += string_printf("Peak stack usage: %d\n", peak_stack_usage);
+ string report = "";
+ report += string_printf("Number of SVM nodes: %d\n", num_svm_nodes);
+ report += string_printf("Peak stack usage: %d\n", peak_stack_usage);
- report += string_printf("Time (in seconds):\n");
- report += string_printf("Finalize: %f\n", time_finalize);
- report += string_printf(" Surface: %f\n", time_generate_surface);
- report += string_printf(" Bump: %f\n", time_generate_bump);
- report += string_printf(" Volume: %f\n", time_generate_volume);
- report += string_printf(" Displacement: %f\n", time_generate_displacement);
- report += string_printf("Generate: %f\n", time_generate_surface +
- time_generate_bump +
- time_generate_volume +
- time_generate_displacement);
- report += string_printf("Total: %f\n", time_total);
+ report += string_printf("Time (in seconds):\n");
+ report += string_printf("Finalize: %f\n", time_finalize);
+ report += string_printf(" Surface: %f\n", time_generate_surface);
+ report += string_printf(" Bump: %f\n", time_generate_bump);
+ report += string_printf(" Volume: %f\n", time_generate_volume);
+ report += string_printf(" Displacement: %f\n", time_generate_displacement);
+ report += string_printf("Generate: %f\n",
+ time_generate_surface + time_generate_bump + time_generate_volume +
+ time_generate_displacement);
+ report += string_printf("Total: %f\n", time_total);
- return report;
+ return report;
}
/* Global state of the compiler. */
SVMCompiler::CompilerState::CompilerState(ShaderGraph *graph)
{
- int max_id = 0;
- foreach(ShaderNode *node, graph->nodes) {
- max_id = max(node->id, max_id);
- }
- nodes_done_flag.resize(max_id + 1, false);
+ int max_id = 0;
+ foreach (ShaderNode *node, graph->nodes) {
+ max_id = max(node->id, max_id);
+ }
+ nodes_done_flag.resize(max_id + 1, false);
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/render/svm.h b/intern/cycles/render/svm.h
index ddf35602fa6..d6964fb158b 100644
--- a/intern/cycles/render/svm.h
+++ b/intern/cycles/render/svm.h
@@ -40,186 +40,196 @@ class ShaderOutput;
/* Shader Manager */
class SVMShaderManager : public ShaderManager {
-public:
- SVMShaderManager();
- ~SVMShaderManager();
+ public:
+ SVMShaderManager();
+ ~SVMShaderManager();
- void reset(Scene *scene);
+ void reset(Scene *scene);
- void device_update(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress);
- void device_free(Device *device, DeviceScene *dscene, Scene *scene);
+ void device_update(Device *device, DeviceScene *dscene, Scene *scene, Progress &progress);
+ void device_free(Device *device, DeviceScene *dscene, Scene *scene);
-protected:
- /* Lock used to synchronize threaded nodes compilation. */
- thread_spin_lock nodes_lock_;
+ protected:
+ /* Lock used to synchronize threaded nodes compilation. */
+ thread_spin_lock nodes_lock_;
- void device_update_shader(Scene *scene,
- Shader *shader,
- Progress *progress,
- array<int4> *global_svm_nodes);
+ void device_update_shader(Scene *scene,
+ Shader *shader,
+ Progress *progress,
+ array<int4> *global_svm_nodes);
};
/* Graph Compiler */
class SVMCompiler {
-public:
- struct Summary {
- Summary();
-
- /* Number of SVM nodes shader was compiled into. */
- int num_svm_nodes;
-
- /* Peak stack usage during shader evaluation. */
- int peak_stack_usage;
-
- /* Time spent on surface graph finalization. */
- double time_finalize;
-
- /* Time spent on generating SVM nodes for surface shader. */
- double time_generate_surface;
-
- /* Time spent on generating SVM nodes for bump shader. */
- double time_generate_bump;
-
- /* Time spent on generating SVM nodes for volume shader. */
- double time_generate_volume;
-
- /* Time spent on generating SVM nodes for displacement shader. */
- double time_generate_displacement;
-
- /* Total time spent on all routines. */
- double time_total;
-
- /* A full multiline description of the state of the compiler after
- * compilation.
- */
- string full_report() const;
- };
-
- SVMCompiler(ShaderManager *shader_manager,
- ImageManager *image_manager,
- LightManager *light_manager);
- void compile(Scene *scene,
- Shader *shader,
- array<int4>& svm_nodes,
- int index,
- Summary *summary = NULL);
-
- int stack_assign(ShaderOutput *output);
- int stack_assign(ShaderInput *input);
- int stack_assign_if_linked(ShaderInput *input);
- int stack_assign_if_linked(ShaderOutput *output);
- int stack_find_offset(int size);
- int stack_find_offset(SocketType::Type type);
- void stack_clear_offset(SocketType::Type type, int offset);
- void stack_link(ShaderInput *input, ShaderOutput *output);
-
- void add_node(ShaderNodeType type, int a = 0, int b = 0, int c = 0);
- void add_node(int a = 0, int b = 0, int c = 0, int d = 0);
- void add_node(ShaderNodeType type, const float3& f);
- void add_node(const float4& f);
- uint attribute(ustring name);
- uint attribute(AttributeStandard std);
- uint attribute_standard(ustring name);
- uint encode_uchar4(uint x, uint y = 0, uint z = 0, uint w = 0);
- uint closure_mix_weight_offset() { return mix_weight_offset; }
-
- ShaderType output_type() { return current_type; }
-
- ImageManager *image_manager;
- ShaderManager *shader_manager;
- LightManager *light_manager;
- bool background;
-
-protected:
- /* stack */
- struct Stack {
- Stack() { memset(users, 0, sizeof(users)); }
- Stack(const Stack& other) { memcpy(users, other.users, sizeof(users)); }
- Stack& operator=(const Stack& other) { memcpy(users, other.users, sizeof(users)); return *this; }
-
- bool empty()
- {
- for(int i = 0; i < SVM_STACK_SIZE; i++)
- if(users[i])
- return false;
-
- return true;
- }
-
- void print()
- {
- printf("stack <");
-
- for(int i = 0; i < SVM_STACK_SIZE; i++)
- printf((users[i])? "*": " ");
-
- printf(">\n");
- }
-
- int users[SVM_STACK_SIZE];
- };
-
- /* Global state of the compiler accessible from the compilation routines. */
- struct CompilerState {
- explicit CompilerState(ShaderGraph *graph);
-
- /* ** Global state, used by various compilation steps. ** */
-
- /* Set of nodes which were already compiled. */
- ShaderNodeSet nodes_done;
-
- /* Set of closures which were already compiled. */
- ShaderNodeSet closure_done;
-
- /* ** SVM nodes generation state ** */
-
- /* Flag whether the node with corresponding ID was already compiled or
- * not. Array element with index i corresponds to a node with such if.
- *
- * TODO(sergey): This is actually a copy of nodes_done just in another
- * notation. We can de-duplicate this storage actually after switching
- * all areas to use this flags array.
- */
- vector<bool> nodes_done_flag;
- };
-
- void stack_clear_temporary(ShaderNode *node);
- int stack_size(SocketType::Type type);
- void stack_clear_users(ShaderNode *node, ShaderNodeSet& done);
-
- /* single closure */
- void find_dependencies(ShaderNodeSet& dependencies,
- const ShaderNodeSet& done,
- ShaderInput *input,
- ShaderNode *skip_node = NULL);
- void generate_node(ShaderNode *node, ShaderNodeSet& done);
- void generate_closure_node(ShaderNode *node, CompilerState *state);
- void generated_shared_closure_nodes(ShaderNode *root_node,
- ShaderNode *node,
- CompilerState *state,
- const ShaderNodeSet& shared);
- void generate_svm_nodes(const ShaderNodeSet& nodes,
- CompilerState *state);
-
- /* multi closure */
- void generate_multi_closure(ShaderNode *root_node,
- ShaderNode *node,
- CompilerState *state);
-
- /* compile */
- void compile_type(Shader *shader, ShaderGraph *graph, ShaderType type);
-
- array<int4> current_svm_nodes;
- ShaderType current_type;
- Shader *current_shader;
- ShaderGraph *current_graph;
- Stack active_stack;
- int max_stack_use;
- uint mix_weight_offset;
- bool compile_failed;
+ public:
+ struct Summary {
+ Summary();
+
+ /* Number of SVM nodes shader was compiled into. */
+ int num_svm_nodes;
+
+ /* Peak stack usage during shader evaluation. */
+ int peak_stack_usage;
+
+ /* Time spent on surface graph finalization. */
+ double time_finalize;
+
+ /* Time spent on generating SVM nodes for surface shader. */
+ double time_generate_surface;
+
+ /* Time spent on generating SVM nodes for bump shader. */
+ double time_generate_bump;
+
+ /* Time spent on generating SVM nodes for volume shader. */
+ double time_generate_volume;
+
+ /* Time spent on generating SVM nodes for displacement shader. */
+ double time_generate_displacement;
+
+ /* Total time spent on all routines. */
+ double time_total;
+
+ /* A full multiline description of the state of the compiler after
+ * compilation.
+ */
+ string full_report() const;
+ };
+
+ SVMCompiler(ShaderManager *shader_manager,
+ ImageManager *image_manager,
+ LightManager *light_manager);
+ void compile(
+ Scene *scene, Shader *shader, array<int4> &svm_nodes, int index, Summary *summary = NULL);
+
+ int stack_assign(ShaderOutput *output);
+ int stack_assign(ShaderInput *input);
+ int stack_assign_if_linked(ShaderInput *input);
+ int stack_assign_if_linked(ShaderOutput *output);
+ int stack_find_offset(int size);
+ int stack_find_offset(SocketType::Type type);
+ void stack_clear_offset(SocketType::Type type, int offset);
+ void stack_link(ShaderInput *input, ShaderOutput *output);
+
+ void add_node(ShaderNodeType type, int a = 0, int b = 0, int c = 0);
+ void add_node(int a = 0, int b = 0, int c = 0, int d = 0);
+ void add_node(ShaderNodeType type, const float3 &f);
+ void add_node(const float4 &f);
+ uint attribute(ustring name);
+ uint attribute(AttributeStandard std);
+ uint attribute_standard(ustring name);
+ uint encode_uchar4(uint x, uint y = 0, uint z = 0, uint w = 0);
+ uint closure_mix_weight_offset()
+ {
+ return mix_weight_offset;
+ }
+
+ ShaderType output_type()
+ {
+ return current_type;
+ }
+
+ ImageManager *image_manager;
+ ShaderManager *shader_manager;
+ LightManager *light_manager;
+ bool background;
+
+ protected:
+ /* stack */
+ struct Stack {
+ Stack()
+ {
+ memset(users, 0, sizeof(users));
+ }
+ Stack(const Stack &other)
+ {
+ memcpy(users, other.users, sizeof(users));
+ }
+ Stack &operator=(const Stack &other)
+ {
+ memcpy(users, other.users, sizeof(users));
+ return *this;
+ }
+
+ bool empty()
+ {
+ for (int i = 0; i < SVM_STACK_SIZE; i++)
+ if (users[i])
+ return false;
+
+ return true;
+ }
+
+ void print()
+ {
+ printf("stack <");
+
+ for (int i = 0; i < SVM_STACK_SIZE; i++)
+ printf((users[i]) ? "*" : " ");
+
+ printf(">\n");
+ }
+
+ int users[SVM_STACK_SIZE];
+ };
+
+ /* Global state of the compiler accessible from the compilation routines. */
+ struct CompilerState {
+ explicit CompilerState(ShaderGraph *graph);
+
+ /* ** Global state, used by various compilation steps. ** */
+
+ /* Set of nodes which were already compiled. */
+ ShaderNodeSet nodes_done;
+
+ /* Set of closures which were already compiled. */
+ ShaderNodeSet closure_done;
+
+ /* ** SVM nodes generation state ** */
+
+ /* Flag whether the node with corresponding ID was already compiled or
+ * not. Array element with index i corresponds to a node with such if.
+ *
+ * TODO(sergey): This is actually a copy of nodes_done just in another
+ * notation. We can de-duplicate this storage actually after switching
+ * all areas to use this flags array.
+ */
+ vector<bool> nodes_done_flag;
+ };
+
+ void stack_clear_temporary(ShaderNode *node);
+ int stack_size(SocketType::Type type);
+ void stack_clear_users(ShaderNode *node, ShaderNodeSet &done);
+
+ /* single closure */
+ void find_dependencies(ShaderNodeSet &dependencies,
+ const ShaderNodeSet &done,
+ ShaderInput *input,
+ ShaderNode *skip_node = NULL);
+ void generate_node(ShaderNode *node, ShaderNodeSet &done);
+ void generate_closure_node(ShaderNode *node, CompilerState *state);
+ void generated_shared_closure_nodes(ShaderNode *root_node,
+ ShaderNode *node,
+ CompilerState *state,
+ const ShaderNodeSet &shared);
+ void generate_svm_nodes(const ShaderNodeSet &nodes, CompilerState *state);
+
+ /* multi closure */
+ void generate_multi_closure(ShaderNode *root_node, ShaderNode *node, CompilerState *state);
+
+ /* compile */
+ void compile_type(Shader *shader, ShaderGraph *graph, ShaderType type);
+
+ array<int4> current_svm_nodes;
+ ShaderType current_type;
+ Shader *current_shader;
+ ShaderGraph *current_graph;
+ Stack active_stack;
+ int max_stack_use;
+ uint mix_weight_offset;
+ bool compile_failed;
};
CCL_NAMESPACE_END
-#endif /* __SVM_H__ */
+#endif /* __SVM_H__ */
diff --git a/intern/cycles/render/tables.cpp b/intern/cycles/render/tables.cpp
index ddbb138f059..d88925939e3 100644
--- a/intern/cycles/render/tables.cpp
+++ b/intern/cycles/render/tables.cpp
@@ -26,92 +26,92 @@ CCL_NAMESPACE_BEGIN
LookupTables::LookupTables()
{
- need_update = true;
+ need_update = true;
}
LookupTables::~LookupTables()
{
- assert(lookup_tables.size() == 0);
+ assert(lookup_tables.size() == 0);
}
void LookupTables::device_update(Device *, DeviceScene *dscene)
{
- if(!need_update)
- return;
+ if (!need_update)
+ return;
- VLOG(1) << "Total " << lookup_tables.size() << " lookup tables.";
+ VLOG(1) << "Total " << lookup_tables.size() << " lookup tables.";
- if(lookup_tables.size() > 0)
- dscene->lookup_table.copy_to_device();
+ if (lookup_tables.size() > 0)
+ dscene->lookup_table.copy_to_device();
- need_update = false;
+ need_update = false;
}
void LookupTables::device_free(Device *, DeviceScene *dscene)
{
- dscene->lookup_table.free();
+ dscene->lookup_table.free();
}
static size_t round_up_to_multiple(size_t size, size_t chunk)
{
- return ((size + chunk - 1)/chunk) * chunk;
+ return ((size + chunk - 1) / chunk) * chunk;
}
-size_t LookupTables::add_table(DeviceScene *dscene, vector<float>& data)
+size_t LookupTables::add_table(DeviceScene *dscene, vector<float> &data)
{
- assert(data.size() > 0);
+ assert(data.size() > 0);
- need_update = true;
+ need_update = true;
- Table new_table;
- new_table.offset = 0;
- new_table.size = round_up_to_multiple(data.size(), TABLE_CHUNK_SIZE);
+ Table new_table;
+ new_table.offset = 0;
+ new_table.size = round_up_to_multiple(data.size(), TABLE_CHUNK_SIZE);
- /* find space to put lookup table */
- list<Table>::iterator table;
+ /* find space to put lookup table */
+ list<Table>::iterator table;
- for(table = lookup_tables.begin(); table != lookup_tables.end(); table++) {
- if(new_table.offset + new_table.size <= table->offset) {
- lookup_tables.insert(table, new_table);
- break;
- }
- else
- new_table.offset = table->offset + table->size;
- }
+ for (table = lookup_tables.begin(); table != lookup_tables.end(); table++) {
+ if (new_table.offset + new_table.size <= table->offset) {
+ lookup_tables.insert(table, new_table);
+ break;
+ }
+ else
+ new_table.offset = table->offset + table->size;
+ }
- if(table == lookup_tables.end()) {
- /* add at the end */
- lookup_tables.push_back(new_table);
- dscene->lookup_table.resize(new_table.offset + new_table.size);
- }
+ if (table == lookup_tables.end()) {
+ /* add at the end */
+ lookup_tables.push_back(new_table);
+ dscene->lookup_table.resize(new_table.offset + new_table.size);
+ }
- /* copy table data and return offset */
- float *dtable = dscene->lookup_table.data();
- memcpy(dtable + new_table.offset, &data[0], sizeof(float) * data.size());
+ /* copy table data and return offset */
+ float *dtable = dscene->lookup_table.data();
+ memcpy(dtable + new_table.offset, &data[0], sizeof(float) * data.size());
- return new_table.offset;
+ return new_table.offset;
}
void LookupTables::remove_table(size_t *offset)
{
- if(*offset == TABLE_OFFSET_INVALID) {
- /* The table isn't even allocated, so just return here. */
- return;
- }
+ if (*offset == TABLE_OFFSET_INVALID) {
+ /* The table isn't even allocated, so just return here. */
+ return;
+ }
- need_update = true;
+ need_update = true;
- list<Table>::iterator table;
+ list<Table>::iterator table;
- for(table = lookup_tables.begin(); table != lookup_tables.end(); table++) {
- if(table->offset == *offset) {
- lookup_tables.erase(table);
- *offset = TABLE_OFFSET_INVALID;
- return;
- }
- }
+ for (table = lookup_tables.begin(); table != lookup_tables.end(); table++) {
+ if (table->offset == *offset) {
+ lookup_tables.erase(table);
+ *offset = TABLE_OFFSET_INVALID;
+ return;
+ }
+ }
- assert(table != lookup_tables.end());
+ assert(table != lookup_tables.end());
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/render/tables.h b/intern/cycles/render/tables.h
index 709333cb1b6..12b59bb0aeb 100644
--- a/intern/cycles/render/tables.h
+++ b/intern/cycles/render/tables.h
@@ -29,25 +29,25 @@ enum { TABLE_CHUNK_SIZE = 256 };
enum { TABLE_OFFSET_INVALID = -1 };
class LookupTables {
-public:
- struct Table {
- size_t offset;
- size_t size;
- };
+ public:
+ struct Table {
+ size_t offset;
+ size_t size;
+ };
- bool need_update;
- list<Table> lookup_tables;
+ bool need_update;
+ list<Table> lookup_tables;
- LookupTables();
- ~LookupTables();
+ LookupTables();
+ ~LookupTables();
- void device_update(Device *device, DeviceScene *dscene);
- void device_free(Device *device, DeviceScene *dscene);
+ void device_update(Device *device, DeviceScene *dscene);
+ void device_free(Device *device, DeviceScene *dscene);
- size_t add_table(DeviceScene *dscene, vector<float>& data);
- void remove_table(size_t *offset);
+ size_t add_table(DeviceScene *dscene, vector<float> &data);
+ void remove_table(size_t *offset);
};
CCL_NAMESPACE_END
-#endif /* __TABLES_H__ */
+#endif /* __TABLES_H__ */
diff --git a/intern/cycles/render/tile.cpp b/intern/cycles/render/tile.cpp
index dc863b067b0..3148b5ef664 100644
--- a/intern/cycles/render/tile.cpp
+++ b/intern/cycles/render/tile.cpp
@@ -25,89 +25,93 @@ CCL_NAMESPACE_BEGIN
namespace {
class TileComparator {
-public:
- TileComparator(TileOrder order_, int2 center_, Tile *tiles_)
- : order(order_),
- center(center_),
- tiles(tiles_)
- {}
-
- bool operator()(int a, int b)
- {
- switch(order) {
- case TILE_CENTER:
- {
- float2 dist_a = make_float2(center.x - (tiles[a].x + tiles[a].w/2),
- center.y - (tiles[a].y + tiles[a].h/2));
- float2 dist_b = make_float2(center.x - (tiles[b].x + tiles[b].w/2),
- center.y - (tiles[b].y + tiles[b].h/2));
- return dot(dist_a, dist_a) < dot(dist_b, dist_b);
- }
- case TILE_LEFT_TO_RIGHT:
- return (tiles[a].x == tiles[b].x)? (tiles[a].y < tiles[b].y): (tiles[a].x < tiles[b].x);
- case TILE_RIGHT_TO_LEFT:
- return (tiles[a].x == tiles[b].x)? (tiles[a].y < tiles[b].y): (tiles[a].x > tiles[b].x);
- case TILE_TOP_TO_BOTTOM:
- return (tiles[a].y == tiles[b].y)? (tiles[a].x < tiles[b].x): (tiles[a].y > tiles[b].y);
- case TILE_BOTTOM_TO_TOP:
- default:
- return (tiles[a].y == tiles[b].y)? (tiles[a].x < tiles[b].x): (tiles[a].y < tiles[b].y);
- }
- }
-
-protected:
- TileOrder order;
- int2 center;
- Tile *tiles;
+ public:
+ TileComparator(TileOrder order_, int2 center_, Tile *tiles_)
+ : order(order_), center(center_), tiles(tiles_)
+ {
+ }
+
+ bool operator()(int a, int b)
+ {
+ switch (order) {
+ case TILE_CENTER: {
+ float2 dist_a = make_float2(center.x - (tiles[a].x + tiles[a].w / 2),
+ center.y - (tiles[a].y + tiles[a].h / 2));
+ float2 dist_b = make_float2(center.x - (tiles[b].x + tiles[b].w / 2),
+ center.y - (tiles[b].y + tiles[b].h / 2));
+ return dot(dist_a, dist_a) < dot(dist_b, dist_b);
+ }
+ case TILE_LEFT_TO_RIGHT:
+ return (tiles[a].x == tiles[b].x) ? (tiles[a].y < tiles[b].y) : (tiles[a].x < tiles[b].x);
+ case TILE_RIGHT_TO_LEFT:
+ return (tiles[a].x == tiles[b].x) ? (tiles[a].y < tiles[b].y) : (tiles[a].x > tiles[b].x);
+ case TILE_TOP_TO_BOTTOM:
+ return (tiles[a].y == tiles[b].y) ? (tiles[a].x < tiles[b].x) : (tiles[a].y > tiles[b].y);
+ case TILE_BOTTOM_TO_TOP:
+ default:
+ return (tiles[a].y == tiles[b].y) ? (tiles[a].x < tiles[b].x) : (tiles[a].y < tiles[b].y);
+ }
+ }
+
+ protected:
+ TileOrder order;
+ int2 center;
+ Tile *tiles;
};
inline int2 hilbert_index_to_pos(int n, int d)
{
- int2 r, xy = make_int2(0, 0);
- for(int s = 1; s < n; s *= 2) {
- r.x = (d >> 1) & 1;
- r.y = (d ^ r.x) & 1;
- if(!r.y) {
- if(r.x) {
- xy = make_int2(s-1, s-1) - xy;
- }
- swap(xy.x, xy.y);
- }
- xy += r*make_int2(s, s);
- d >>= 2;
- }
- return xy;
+ int2 r, xy = make_int2(0, 0);
+ for (int s = 1; s < n; s *= 2) {
+ r.x = (d >> 1) & 1;
+ r.y = (d ^ r.x) & 1;
+ if (!r.y) {
+ if (r.x) {
+ xy = make_int2(s - 1, s - 1) - xy;
+ }
+ swap(xy.x, xy.y);
+ }
+ xy += r * make_int2(s, s);
+ d >>= 2;
+ }
+ return xy;
}
enum SpiralDirection {
- DIRECTION_UP,
- DIRECTION_LEFT,
- DIRECTION_DOWN,
- DIRECTION_RIGHT,
+ DIRECTION_UP,
+ DIRECTION_LEFT,
+ DIRECTION_DOWN,
+ DIRECTION_RIGHT,
};
-} /* namespace */
-
-TileManager::TileManager(bool progressive_, int num_samples_, int2 tile_size_, int start_resolution_,
- bool preserve_tile_device_, bool background_, TileOrder tile_order_,
- int num_devices_, int pixel_size_)
+} /* namespace */
+
+TileManager::TileManager(bool progressive_,
+ int num_samples_,
+ int2 tile_size_,
+ int start_resolution_,
+ bool preserve_tile_device_,
+ bool background_,
+ TileOrder tile_order_,
+ int num_devices_,
+ int pixel_size_)
{
- progressive = progressive_;
- tile_size = tile_size_;
- tile_order = tile_order_;
- start_resolution = start_resolution_;
- pixel_size = pixel_size_;
- num_samples = num_samples_;
- num_devices = num_devices_;
- preserve_tile_device = preserve_tile_device_;
- background = background_;
- schedule_denoising = false;
-
- range_start_sample = 0;
- range_num_samples = -1;
-
- BufferParams buffer_params;
- reset(buffer_params, 0);
+ progressive = progressive_;
+ tile_size = tile_size_;
+ tile_order = tile_order_;
+ start_resolution = start_resolution_;
+ pixel_size = pixel_size_;
+ num_samples = num_samples_;
+ num_devices = num_devices_;
+ preserve_tile_device = preserve_tile_device_;
+ background = background_;
+ schedule_denoising = false;
+
+ range_start_sample = 0;
+ range_num_samples = -1;
+
+ BufferParams buffer_params;
+ reset(buffer_params, 0);
}
TileManager::~TileManager()
@@ -116,422 +120,422 @@ TileManager::~TileManager()
void TileManager::device_free()
{
- if(schedule_denoising || progressive) {
- for(int i = 0; i < state.tiles.size(); i++) {
- delete state.tiles[i].buffers;
- state.tiles[i].buffers = NULL;
- }
- }
-
- state.tiles.clear();
+ if (schedule_denoising || progressive) {
+ for (int i = 0; i < state.tiles.size(); i++) {
+ delete state.tiles[i].buffers;
+ state.tiles[i].buffers = NULL;
+ }
+ }
+
+ state.tiles.clear();
}
static int get_divider(int w, int h, int start_resolution)
{
- int divider = 1;
- if(start_resolution != INT_MAX) {
- while(w*h > start_resolution*start_resolution) {
- w = max(1, w/2);
- h = max(1, h/2);
-
- divider <<= 1;
- }
- }
- return divider;
+ int divider = 1;
+ if (start_resolution != INT_MAX) {
+ while (w * h > start_resolution * start_resolution) {
+ w = max(1, w / 2);
+ h = max(1, h / 2);
+
+ divider <<= 1;
+ }
+ }
+ return divider;
}
-void TileManager::reset(BufferParams& params_, int num_samples_)
+void TileManager::reset(BufferParams &params_, int num_samples_)
{
- params = params_;
-
- set_samples(num_samples_);
-
- state.buffer = BufferParams();
- state.sample = range_start_sample - 1;
- state.num_tiles = 0;
- state.num_samples = 0;
- state.resolution_divider = get_divider(params.width, params.height, start_resolution);
- state.render_tiles.clear();
- state.denoising_tiles.clear();
- device_free();
+ params = params_;
+
+ set_samples(num_samples_);
+
+ state.buffer = BufferParams();
+ state.sample = range_start_sample - 1;
+ state.num_tiles = 0;
+ state.num_samples = 0;
+ state.resolution_divider = get_divider(params.width, params.height, start_resolution);
+ state.render_tiles.clear();
+ state.denoising_tiles.clear();
+ device_free();
}
void TileManager::set_samples(int num_samples_)
{
- num_samples = num_samples_;
-
- /* No real progress indication is possible when using unlimited samples. */
- if(num_samples == INT_MAX) {
- state.total_pixel_samples = 0;
- }
- else {
- uint64_t pixel_samples = 0;
- /* While rendering in the viewport, the initial preview resolution is increased to the native resolution
- * before the actual rendering begins. Therefore, additional pixel samples will be rendered. */
- int divider = max(get_divider(params.width, params.height, start_resolution) / 2, pixel_size);
- while(divider > pixel_size) {
- int image_w = max(1, params.width/divider);
- int image_h = max(1, params.height/divider);
- pixel_samples += image_w * image_h;
- divider >>= 1;
- }
-
- int image_w = max(1, params.width/divider);
- int image_h = max(1, params.height/divider);
- state.total_pixel_samples = pixel_samples + (uint64_t)get_num_effective_samples() * image_w*image_h;
- if(schedule_denoising) {
- state.total_pixel_samples += params.width*params.height;
- }
- }
+ num_samples = num_samples_;
+
+ /* No real progress indication is possible when using unlimited samples. */
+ if (num_samples == INT_MAX) {
+ state.total_pixel_samples = 0;
+ }
+ else {
+ uint64_t pixel_samples = 0;
+ /* While rendering in the viewport, the initial preview resolution is increased to the native resolution
+ * before the actual rendering begins. Therefore, additional pixel samples will be rendered. */
+ int divider = max(get_divider(params.width, params.height, start_resolution) / 2, pixel_size);
+ while (divider > pixel_size) {
+ int image_w = max(1, params.width / divider);
+ int image_h = max(1, params.height / divider);
+ pixel_samples += image_w * image_h;
+ divider >>= 1;
+ }
+
+ int image_w = max(1, params.width / divider);
+ int image_h = max(1, params.height / divider);
+ state.total_pixel_samples = pixel_samples +
+ (uint64_t)get_num_effective_samples() * image_w * image_h;
+ if (schedule_denoising) {
+ state.total_pixel_samples += params.width * params.height;
+ }
+ }
}
/* If sliced is false, splits image into tiles and assigns equal amount of tiles to every render device.
* If sliced is true, slice image into as much pieces as how many devices are rendering this image. */
int TileManager::gen_tiles(bool sliced)
{
- int resolution = state.resolution_divider;
- int image_w = max(1, params.width/resolution);
- int image_h = max(1, params.height/resolution);
- int2 center = make_int2(image_w/2, image_h/2);
-
- int num_logical_devices = preserve_tile_device? num_devices: 1;
- int num = min(image_h, num_logical_devices);
- int slice_num = sliced? num: 1;
- int tile_w = (tile_size.x >= image_w) ? 1 : divide_up(image_w, tile_size.x);
-
- device_free();
- state.render_tiles.clear();
- state.denoising_tiles.clear();
- state.render_tiles.resize(num);
- state.denoising_tiles.resize(num);
- state.tile_stride = tile_w;
- vector<list<int> >::iterator tile_list;
- tile_list = state.render_tiles.begin();
-
- if(tile_order == TILE_HILBERT_SPIRAL) {
- assert(!sliced);
-
- int tile_h = (tile_size.y >= image_h) ? 1 : divide_up(image_h, tile_size.y);
- state.tiles.resize(tile_w*tile_h);
-
- /* Size of blocks in tiles, must be a power of 2 */
- const int hilbert_size = (max(tile_size.x, tile_size.y) <= 12)? 8: 4;
-
- int tiles_per_device = divide_up(tile_w * tile_h, num);
- int cur_device = 0, cur_tiles = 0;
-
- int2 block_size = tile_size * make_int2(hilbert_size, hilbert_size);
- /* Number of blocks to fill the image */
- int blocks_x = (block_size.x >= image_w)? 1: divide_up(image_w, block_size.x);
- int blocks_y = (block_size.y >= image_h)? 1: divide_up(image_h, block_size.y);
- int n = max(blocks_x, blocks_y) | 0x1; /* Side length of the spiral (must be odd) */
- /* Offset of spiral (to keep it centered) */
- int2 offset = make_int2((image_w - n*block_size.x)/2, (image_h - n*block_size.y)/2);
- offset = (offset / tile_size) * tile_size; /* Round to tile border. */
-
- int2 block = make_int2(0, 0); /* Current block */
- SpiralDirection prev_dir = DIRECTION_UP, dir = DIRECTION_UP;
- for(int i = 0;;) {
- /* Generate the tiles in the current block. */
- for(int hilbert_index = 0; hilbert_index < hilbert_size*hilbert_size; hilbert_index++) {
- int2 tile, hilbert_pos = hilbert_index_to_pos(hilbert_size, hilbert_index);
- /* Rotate block according to spiral direction. */
- if(prev_dir == DIRECTION_UP && dir == DIRECTION_UP) {
- tile = make_int2(hilbert_pos.y, hilbert_pos.x);
- }
- else if(dir == DIRECTION_LEFT || prev_dir == DIRECTION_LEFT) {
- tile = hilbert_pos;
- }
- else if(dir == DIRECTION_DOWN) {
- tile = make_int2(hilbert_size-1-hilbert_pos.y, hilbert_size-1-hilbert_pos.x);
- }
- else {
- tile = make_int2(hilbert_size-1-hilbert_pos.x, hilbert_size-1-hilbert_pos.y);
- }
-
- int2 pos = block*block_size + tile*tile_size + offset;
- /* Only add tiles which are in the image (tiles outside of the image can be generated since the spiral is always square). */
- if(pos.x >= 0 && pos.y >= 0 && pos.x < image_w && pos.y < image_h) {
- int w = min(tile_size.x, image_w - pos.x);
- int h = min(tile_size.y, image_h - pos.y);
- int2 ipos = pos / tile_size;
- int idx = ipos.y*tile_w + ipos.x;
- state.tiles[idx] = Tile(idx, pos.x, pos.y, w, h, cur_device, Tile::RENDER);
- tile_list->push_front(idx);
- cur_tiles++;
-
- if(cur_tiles == tiles_per_device) {
- tile_list++;
- cur_tiles = 0;
- cur_device++;
- }
- }
- }
-
- /* Stop as soon as the spiral has reached the center block. */
- if(block.x == (n-1)/2 && block.y == (n-1)/2)
- break;
-
- /* Advance to next block. */
- prev_dir = dir;
- switch(dir) {
- case DIRECTION_UP:
- block.y++;
- if(block.y == (n-i-1)) {
- dir = DIRECTION_LEFT;
- }
- break;
- case DIRECTION_LEFT:
- block.x++;
- if(block.x == (n-i-1)) {
- dir = DIRECTION_DOWN;
- }
- break;
- case DIRECTION_DOWN:
- block.y--;
- if(block.y == i) {
- dir = DIRECTION_RIGHT;
- }
- break;
- case DIRECTION_RIGHT:
- block.x--;
- if(block.x == i+1) {
- dir = DIRECTION_UP;
- i++;
- }
- break;
- }
- }
- return tile_w*tile_h;
- }
-
- int idx = 0;
- for(int slice = 0; slice < slice_num; slice++) {
- int slice_y = (image_h/slice_num)*slice;
- int slice_h = (slice == slice_num-1)? image_h - slice*(image_h/slice_num): image_h/slice_num;
-
- int tile_h = (tile_size.y >= slice_h)? 1: divide_up(slice_h, tile_size.y);
-
- int tiles_per_device = divide_up(tile_w * tile_h, num);
- int cur_device = 0, cur_tiles = 0;
-
- for(int tile_y = 0; tile_y < tile_h; tile_y++) {
- for(int tile_x = 0; tile_x < tile_w; tile_x++, idx++) {
- int x = tile_x * tile_size.x;
- int y = tile_y * tile_size.y;
- int w = (tile_x == tile_w-1)? image_w - x: tile_size.x;
- int h = (tile_y == tile_h-1)? slice_h - y: tile_size.y;
-
- state.tiles.push_back(Tile(idx, x, y + slice_y, w, h, sliced? slice: cur_device, Tile::RENDER));
- tile_list->push_back(idx);
-
- if(!sliced) {
- cur_tiles++;
-
- if(cur_tiles == tiles_per_device) {
- /* Tiles are already generated in Bottom-to-Top order, so no sort is necessary in that case. */
- if(tile_order != TILE_BOTTOM_TO_TOP) {
- tile_list->sort(TileComparator(tile_order, center, &state.tiles[0]));
- }
- tile_list++;
- cur_tiles = 0;
- cur_device++;
- }
- }
- }
- }
- if(sliced) {
- tile_list++;
- }
- }
-
- return idx;
+ int resolution = state.resolution_divider;
+ int image_w = max(1, params.width / resolution);
+ int image_h = max(1, params.height / resolution);
+ int2 center = make_int2(image_w / 2, image_h / 2);
+
+ int num_logical_devices = preserve_tile_device ? num_devices : 1;
+ int num = min(image_h, num_logical_devices);
+ int slice_num = sliced ? num : 1;
+ int tile_w = (tile_size.x >= image_w) ? 1 : divide_up(image_w, tile_size.x);
+
+ device_free();
+ state.render_tiles.clear();
+ state.denoising_tiles.clear();
+ state.render_tiles.resize(num);
+ state.denoising_tiles.resize(num);
+ state.tile_stride = tile_w;
+ vector<list<int>>::iterator tile_list;
+ tile_list = state.render_tiles.begin();
+
+ if (tile_order == TILE_HILBERT_SPIRAL) {
+ assert(!sliced);
+
+ int tile_h = (tile_size.y >= image_h) ? 1 : divide_up(image_h, tile_size.y);
+ state.tiles.resize(tile_w * tile_h);
+
+ /* Size of blocks in tiles, must be a power of 2 */
+ const int hilbert_size = (max(tile_size.x, tile_size.y) <= 12) ? 8 : 4;
+
+ int tiles_per_device = divide_up(tile_w * tile_h, num);
+ int cur_device = 0, cur_tiles = 0;
+
+ int2 block_size = tile_size * make_int2(hilbert_size, hilbert_size);
+ /* Number of blocks to fill the image */
+ int blocks_x = (block_size.x >= image_w) ? 1 : divide_up(image_w, block_size.x);
+ int blocks_y = (block_size.y >= image_h) ? 1 : divide_up(image_h, block_size.y);
+ int n = max(blocks_x, blocks_y) | 0x1; /* Side length of the spiral (must be odd) */
+ /* Offset of spiral (to keep it centered) */
+ int2 offset = make_int2((image_w - n * block_size.x) / 2, (image_h - n * block_size.y) / 2);
+ offset = (offset / tile_size) * tile_size; /* Round to tile border. */
+
+ int2 block = make_int2(0, 0); /* Current block */
+ SpiralDirection prev_dir = DIRECTION_UP, dir = DIRECTION_UP;
+ for (int i = 0;;) {
+ /* Generate the tiles in the current block. */
+ for (int hilbert_index = 0; hilbert_index < hilbert_size * hilbert_size; hilbert_index++) {
+ int2 tile, hilbert_pos = hilbert_index_to_pos(hilbert_size, hilbert_index);
+ /* Rotate block according to spiral direction. */
+ if (prev_dir == DIRECTION_UP && dir == DIRECTION_UP) {
+ tile = make_int2(hilbert_pos.y, hilbert_pos.x);
+ }
+ else if (dir == DIRECTION_LEFT || prev_dir == DIRECTION_LEFT) {
+ tile = hilbert_pos;
+ }
+ else if (dir == DIRECTION_DOWN) {
+ tile = make_int2(hilbert_size - 1 - hilbert_pos.y, hilbert_size - 1 - hilbert_pos.x);
+ }
+ else {
+ tile = make_int2(hilbert_size - 1 - hilbert_pos.x, hilbert_size - 1 - hilbert_pos.y);
+ }
+
+ int2 pos = block * block_size + tile * tile_size + offset;
+ /* Only add tiles which are in the image (tiles outside of the image can be generated since the spiral is always square). */
+ if (pos.x >= 0 && pos.y >= 0 && pos.x < image_w && pos.y < image_h) {
+ int w = min(tile_size.x, image_w - pos.x);
+ int h = min(tile_size.y, image_h - pos.y);
+ int2 ipos = pos / tile_size;
+ int idx = ipos.y * tile_w + ipos.x;
+ state.tiles[idx] = Tile(idx, pos.x, pos.y, w, h, cur_device, Tile::RENDER);
+ tile_list->push_front(idx);
+ cur_tiles++;
+
+ if (cur_tiles == tiles_per_device) {
+ tile_list++;
+ cur_tiles = 0;
+ cur_device++;
+ }
+ }
+ }
+
+ /* Stop as soon as the spiral has reached the center block. */
+ if (block.x == (n - 1) / 2 && block.y == (n - 1) / 2)
+ break;
+
+ /* Advance to next block. */
+ prev_dir = dir;
+ switch (dir) {
+ case DIRECTION_UP:
+ block.y++;
+ if (block.y == (n - i - 1)) {
+ dir = DIRECTION_LEFT;
+ }
+ break;
+ case DIRECTION_LEFT:
+ block.x++;
+ if (block.x == (n - i - 1)) {
+ dir = DIRECTION_DOWN;
+ }
+ break;
+ case DIRECTION_DOWN:
+ block.y--;
+ if (block.y == i) {
+ dir = DIRECTION_RIGHT;
+ }
+ break;
+ case DIRECTION_RIGHT:
+ block.x--;
+ if (block.x == i + 1) {
+ dir = DIRECTION_UP;
+ i++;
+ }
+ break;
+ }
+ }
+ return tile_w * tile_h;
+ }
+
+ int idx = 0;
+ for (int slice = 0; slice < slice_num; slice++) {
+ int slice_y = (image_h / slice_num) * slice;
+ int slice_h = (slice == slice_num - 1) ? image_h - slice * (image_h / slice_num) :
+ image_h / slice_num;
+
+ int tile_h = (tile_size.y >= slice_h) ? 1 : divide_up(slice_h, tile_size.y);
+
+ int tiles_per_device = divide_up(tile_w * tile_h, num);
+ int cur_device = 0, cur_tiles = 0;
+
+ for (int tile_y = 0; tile_y < tile_h; tile_y++) {
+ for (int tile_x = 0; tile_x < tile_w; tile_x++, idx++) {
+ int x = tile_x * tile_size.x;
+ int y = tile_y * tile_size.y;
+ int w = (tile_x == tile_w - 1) ? image_w - x : tile_size.x;
+ int h = (tile_y == tile_h - 1) ? slice_h - y : tile_size.y;
+
+ state.tiles.push_back(
+ Tile(idx, x, y + slice_y, w, h, sliced ? slice : cur_device, Tile::RENDER));
+ tile_list->push_back(idx);
+
+ if (!sliced) {
+ cur_tiles++;
+
+ if (cur_tiles == tiles_per_device) {
+ /* Tiles are already generated in Bottom-to-Top order, so no sort is necessary in that case. */
+ if (tile_order != TILE_BOTTOM_TO_TOP) {
+ tile_list->sort(TileComparator(tile_order, center, &state.tiles[0]));
+ }
+ tile_list++;
+ cur_tiles = 0;
+ cur_device++;
+ }
+ }
+ }
+ }
+ if (sliced) {
+ tile_list++;
+ }
+ }
+
+ return idx;
}
void TileManager::gen_render_tiles()
{
- /* Regenerate just the render tiles for progressive render. */
- foreach(Tile& tile, state.tiles) {
- state.render_tiles[tile.device].push_back(tile.index);
- }
+ /* Regenerate just the render tiles for progressive render. */
+ foreach (Tile &tile, state.tiles) {
+ state.render_tiles[tile.device].push_back(tile.index);
+ }
}
void TileManager::set_tiles()
{
- int resolution = state.resolution_divider;
- int image_w = max(1, params.width/resolution);
- int image_h = max(1, params.height/resolution);
+ int resolution = state.resolution_divider;
+ int image_w = max(1, params.width / resolution);
+ int image_h = max(1, params.height / resolution);
- state.num_tiles = gen_tiles(!background);
+ state.num_tiles = gen_tiles(!background);
- state.buffer.width = image_w;
- state.buffer.height = image_h;
+ state.buffer.width = image_w;
+ state.buffer.height = image_h;
- state.buffer.full_x = params.full_x/resolution;
- state.buffer.full_y = params.full_y/resolution;
- state.buffer.full_width = max(1, params.full_width/resolution);
- state.buffer.full_height = max(1, params.full_height/resolution);
+ state.buffer.full_x = params.full_x / resolution;
+ state.buffer.full_y = params.full_y / resolution;
+ state.buffer.full_width = max(1, params.full_width / resolution);
+ state.buffer.full_height = max(1, params.full_height / resolution);
}
int TileManager::get_neighbor_index(int index, int neighbor)
{
- static const int dx[] = {-1, 0, 1, -1, 1, -1, 0, 1, 0}, dy[] = {-1, -1, -1, 0, 0, 1, 1, 1, 0};
+ static const int dx[] = {-1, 0, 1, -1, 1, -1, 0, 1, 0}, dy[] = {-1, -1, -1, 0, 0, 1, 1, 1, 0};
- int resolution = state.resolution_divider;
- int image_w = max(1, params.width/resolution);
- int image_h = max(1, params.height/resolution);
- int tile_w = (tile_size.x >= image_w)? 1: divide_up(image_w, tile_size.x);
- int tile_h = (tile_size.y >= image_h)? 1: divide_up(image_h, tile_size.y);
+ int resolution = state.resolution_divider;
+ int image_w = max(1, params.width / resolution);
+ int image_h = max(1, params.height / resolution);
+ int tile_w = (tile_size.x >= image_w) ? 1 : divide_up(image_w, tile_size.x);
+ int tile_h = (tile_size.y >= image_h) ? 1 : divide_up(image_h, tile_size.y);
- int nx = state.tiles[index].x/tile_size.x + dx[neighbor], ny = state.tiles[index].y/tile_size.y + dy[neighbor];
- if(nx < 0 || ny < 0 || nx >= tile_w || ny >= tile_h)
- return -1;
+ int nx = state.tiles[index].x / tile_size.x + dx[neighbor],
+ ny = state.tiles[index].y / tile_size.y + dy[neighbor];
+ if (nx < 0 || ny < 0 || nx >= tile_w || ny >= tile_h)
+ return -1;
- return ny*state.tile_stride + nx;
+ return ny * state.tile_stride + nx;
}
/* Checks whether all neighbors of a tile (as well as the tile itself) are at least at state min_state. */
bool TileManager::check_neighbor_state(int index, Tile::State min_state)
{
- if(index < 0 || state.tiles[index].state < min_state) {
- return false;
- }
- for(int neighbor = 0; neighbor < 9; neighbor++) {
- int nindex = get_neighbor_index(index, neighbor);
- /* Out-of-bounds tiles don't matter. */
- if(nindex >= 0 && state.tiles[nindex].state < min_state) {
- return false;
- }
- }
-
- return true;
+ if (index < 0 || state.tiles[index].state < min_state) {
+ return false;
+ }
+ for (int neighbor = 0; neighbor < 9; neighbor++) {
+ int nindex = get_neighbor_index(index, neighbor);
+ /* Out-of-bounds tiles don't matter. */
+ if (nindex >= 0 && state.tiles[nindex].state < min_state) {
+ return false;
+ }
+ }
+
+ return true;
}
/* Returns whether the tile should be written (and freed if no denoising is used) instead of updating. */
bool TileManager::finish_tile(int index, bool &delete_tile)
{
- delete_tile = false;
-
- if(progressive) {
- return true;
- }
-
- switch(state.tiles[index].state) {
- case Tile::RENDER:
- {
- if(!schedule_denoising) {
- state.tiles[index].state = Tile::DONE;
- delete_tile = true;
- return true;
- }
- state.tiles[index].state = Tile::RENDERED;
- /* For each neighbor and the tile itself, check whether all of its neighbors have been rendered. If yes, it can be denoised. */
- for(int neighbor = 0; neighbor < 9; neighbor++) {
- int nindex = get_neighbor_index(index, neighbor);
- if(check_neighbor_state(nindex, Tile::RENDERED)) {
- state.tiles[nindex].state = Tile::DENOISE;
- state.denoising_tiles[state.tiles[nindex].device].push_back(nindex);
- }
- }
- return false;
- }
- case Tile::DENOISE:
- {
- state.tiles[index].state = Tile::DENOISED;
- /* For each neighbor and the tile itself, check whether all of its neighbors have been denoised. If yes, it can be freed. */
- for(int neighbor = 0; neighbor < 9; neighbor++) {
- int nindex = get_neighbor_index(index, neighbor);
- if(check_neighbor_state(nindex, Tile::DENOISED)) {
- state.tiles[nindex].state = Tile::DONE;
- /* It can happen that the tile just finished denoising and already can be freed here.
- * However, in that case it still has to be written before deleting, so we can't delete it yet. */
- if(neighbor == 8) {
- delete_tile = true;
- }
- else {
- delete state.tiles[nindex].buffers;
- state.tiles[nindex].buffers = NULL;
- }
- }
- }
- return true;
- }
- default:
- assert(false);
- return true;
- }
+ delete_tile = false;
+
+ if (progressive) {
+ return true;
+ }
+
+ switch (state.tiles[index].state) {
+ case Tile::RENDER: {
+ if (!schedule_denoising) {
+ state.tiles[index].state = Tile::DONE;
+ delete_tile = true;
+ return true;
+ }
+ state.tiles[index].state = Tile::RENDERED;
+ /* For each neighbor and the tile itself, check whether all of its neighbors have been rendered. If yes, it can be denoised. */
+ for (int neighbor = 0; neighbor < 9; neighbor++) {
+ int nindex = get_neighbor_index(index, neighbor);
+ if (check_neighbor_state(nindex, Tile::RENDERED)) {
+ state.tiles[nindex].state = Tile::DENOISE;
+ state.denoising_tiles[state.tiles[nindex].device].push_back(nindex);
+ }
+ }
+ return false;
+ }
+ case Tile::DENOISE: {
+ state.tiles[index].state = Tile::DENOISED;
+ /* For each neighbor and the tile itself, check whether all of its neighbors have been denoised. If yes, it can be freed. */
+ for (int neighbor = 0; neighbor < 9; neighbor++) {
+ int nindex = get_neighbor_index(index, neighbor);
+ if (check_neighbor_state(nindex, Tile::DENOISED)) {
+ state.tiles[nindex].state = Tile::DONE;
+ /* It can happen that the tile just finished denoising and already can be freed here.
+ * However, in that case it still has to be written before deleting, so we can't delete it yet. */
+ if (neighbor == 8) {
+ delete_tile = true;
+ }
+ else {
+ delete state.tiles[nindex].buffers;
+ state.tiles[nindex].buffers = NULL;
+ }
+ }
+ }
+ return true;
+ }
+ default:
+ assert(false);
+ return true;
+ }
}
-bool TileManager::next_tile(Tile* &tile, int device)
+bool TileManager::next_tile(Tile *&tile, int device)
{
- int logical_device = preserve_tile_device? device: 0;
+ int logical_device = preserve_tile_device ? device : 0;
- if(logical_device >= state.render_tiles.size())
- return false;
+ if (logical_device >= state.render_tiles.size())
+ return false;
- if(!state.denoising_tiles[logical_device].empty()) {
- int idx = state.denoising_tiles[logical_device].front();
- state.denoising_tiles[logical_device].pop_front();
- tile = &state.tiles[idx];
- return true;
- }
+ if (!state.denoising_tiles[logical_device].empty()) {
+ int idx = state.denoising_tiles[logical_device].front();
+ state.denoising_tiles[logical_device].pop_front();
+ tile = &state.tiles[idx];
+ return true;
+ }
- if(state.render_tiles[logical_device].empty())
- return false;
+ if (state.render_tiles[logical_device].empty())
+ return false;
- int idx = state.render_tiles[logical_device].front();
- state.render_tiles[logical_device].pop_front();
- tile = &state.tiles[idx];
- return true;
+ int idx = state.render_tiles[logical_device].front();
+ state.render_tiles[logical_device].pop_front();
+ tile = &state.tiles[idx];
+ return true;
}
bool TileManager::done()
{
- int end_sample = (range_num_samples == -1)
- ? num_samples
- : range_start_sample + range_num_samples;
- return (state.resolution_divider == pixel_size) &&
- (state.sample+state.num_samples >= end_sample);
+ int end_sample = (range_num_samples == -1) ? num_samples :
+ range_start_sample + range_num_samples;
+ return (state.resolution_divider == pixel_size) &&
+ (state.sample + state.num_samples >= end_sample);
}
bool TileManager::next()
{
- if(done())
- return false;
-
- if(progressive && state.resolution_divider > pixel_size) {
- state.sample = 0;
- state.resolution_divider = max(state.resolution_divider/2, pixel_size);
- state.num_samples = 1;
- set_tiles();
- }
- else {
- state.sample++;
-
- if(progressive)
- state.num_samples = 1;
- else if(range_num_samples == -1)
- state.num_samples = num_samples;
- else
- state.num_samples = range_num_samples;
-
- state.resolution_divider = pixel_size;
-
- if(state.sample == range_start_sample) {
- set_tiles();
- }
- else {
- gen_render_tiles();
- }
- }
-
- return true;
+ if (done())
+ return false;
+
+ if (progressive && state.resolution_divider > pixel_size) {
+ state.sample = 0;
+ state.resolution_divider = max(state.resolution_divider / 2, pixel_size);
+ state.num_samples = 1;
+ set_tiles();
+ }
+ else {
+ state.sample++;
+
+ if (progressive)
+ state.num_samples = 1;
+ else if (range_num_samples == -1)
+ state.num_samples = num_samples;
+ else
+ state.num_samples = range_num_samples;
+
+ state.resolution_divider = pixel_size;
+
+ if (state.sample == range_start_sample) {
+ set_tiles();
+ }
+ else {
+ gen_render_tiles();
+ }
+ }
+
+ return true;
}
int TileManager::get_num_effective_samples()
{
- return (range_num_samples == -1) ? num_samples
- : range_num_samples;
+ return (range_num_samples == -1) ? num_samples : range_num_samples;
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/render/tile.h b/intern/cycles/render/tile.h
index 2835c793073..017c1af0ead 100644
--- a/intern/cycles/render/tile.h
+++ b/intern/cycles/render/tile.h
@@ -27,131 +27,144 @@ CCL_NAMESPACE_BEGIN
/* Tile */
class Tile {
-public:
- int index;
- int x, y, w, h;
- int device;
- /* RENDER: The tile has to be rendered.
- * RENDERED: The tile has been rendered, but can't be denoised yet (waiting for neighbors).
- * DENOISE: The tile can be denoised now.
- * DENOISED: The tile has been denoised, but can't be freed yet (waiting for neighbors).
- * DONE: The tile is finished and has been freed. */
- typedef enum { RENDER = 0, RENDERED, DENOISE, DENOISED, DONE } State;
- State state;
- RenderBuffers *buffers;
-
- Tile()
- {}
-
- Tile(int index_, int x_, int y_, int w_, int h_, int device_, State state_ = RENDER)
- : index(index_), x(x_), y(y_), w(w_), h(h_), device(device_), state(state_), buffers(NULL) {}
+ public:
+ int index;
+ int x, y, w, h;
+ int device;
+ /* RENDER: The tile has to be rendered.
+ * RENDERED: The tile has been rendered, but can't be denoised yet (waiting for neighbors).
+ * DENOISE: The tile can be denoised now.
+ * DENOISED: The tile has been denoised, but can't be freed yet (waiting for neighbors).
+ * DONE: The tile is finished and has been freed. */
+ typedef enum { RENDER = 0, RENDERED, DENOISE, DENOISED, DONE } State;
+ State state;
+ RenderBuffers *buffers;
+
+ Tile()
+ {
+ }
+
+ Tile(int index_, int x_, int y_, int w_, int h_, int device_, State state_ = RENDER)
+ : index(index_), x(x_), y(y_), w(w_), h(h_), device(device_), state(state_), buffers(NULL)
+ {
+ }
};
/* Tile order */
/* Note: this should match enum_tile_order in properties.py */
enum TileOrder {
- TILE_CENTER = 0,
- TILE_RIGHT_TO_LEFT = 1,
- TILE_LEFT_TO_RIGHT = 2,
- TILE_TOP_TO_BOTTOM = 3,
- TILE_BOTTOM_TO_TOP = 4,
- TILE_HILBERT_SPIRAL = 5,
+ TILE_CENTER = 0,
+ TILE_RIGHT_TO_LEFT = 1,
+ TILE_LEFT_TO_RIGHT = 2,
+ TILE_TOP_TO_BOTTOM = 3,
+ TILE_BOTTOM_TO_TOP = 4,
+ TILE_HILBERT_SPIRAL = 5,
};
/* Tile Manager */
class TileManager {
-public:
- BufferParams params;
-
- struct State {
- vector<Tile> tiles;
- int tile_stride;
- BufferParams buffer;
- int sample;
- int num_samples;
- int resolution_divider;
- int num_tiles;
-
- /* Total samples over all pixels: Generally num_samples*num_pixels,
- * but can be higher due to the initial resolution division for previews. */
- uint64_t total_pixel_samples;
-
- /* These lists contain the indices of the tiles to be rendered/denoised and are used
- * when acquiring a new tile for the device.
- * Each list in each vector is for one logical device. */
- vector<list<int> > render_tiles;
- vector<list<int> > denoising_tiles;
- } state;
-
- int num_samples;
-
- TileManager(bool progressive, int num_samples, int2 tile_size, int start_resolution,
- bool preserve_tile_device, bool background, TileOrder tile_order, int num_devices = 1, int pixel_size = 1);
- ~TileManager();
-
- void device_free();
- void reset(BufferParams& params, int num_samples);
- void set_samples(int num_samples);
- bool next();
- bool next_tile(Tile* &tile, int device = 0);
- bool finish_tile(int index, bool& delete_tile);
- bool done();
-
- void set_tile_order(TileOrder tile_order_) { tile_order = tile_order_; }
-
- /* ** Sample range rendering. ** */
-
- /* Start sample in the range. */
- int range_start_sample;
-
- /* Number to samples in the rendering range. */
- int range_num_samples;
-
- /* Get number of actual samples to render. */
- int get_num_effective_samples();
-
- /* Schedule tiles for denoising after they've been rendered. */
- bool schedule_denoising;
-protected:
-
- void set_tiles();
-
- bool progressive;
- int2 tile_size;
- TileOrder tile_order;
- int start_resolution;
- int pixel_size;
- int num_devices;
-
- /* in some cases it is important that the same tile will be returned for the same
- * device it was originally generated for (i.e. viewport rendering when buffer is
- * allocating once for tile and then always used by it)
- *
- * in other cases any tile could be handled by any device (i.e. final rendering
- * without progressive refine)
- */
- bool preserve_tile_device;
-
- /* for background render tiles should exactly match render parts generated from
- * blender side, which means image first gets split into tiles and then tiles are
- * assigning to render devices
- *
- * however viewport rendering expects tiles to be allocated in a special way,
- * meaning image is being sliced horizontally first and every device handles
- * it's own slice
- */
- bool background;
-
- /* Generate tile list, return number of tiles. */
- int gen_tiles(bool sliced);
- void gen_render_tiles();
-
- int get_neighbor_index(int index, int neighbor);
- bool check_neighbor_state(int index, Tile::State state);
+ public:
+ BufferParams params;
+
+ struct State {
+ vector<Tile> tiles;
+ int tile_stride;
+ BufferParams buffer;
+ int sample;
+ int num_samples;
+ int resolution_divider;
+ int num_tiles;
+
+ /* Total samples over all pixels: Generally num_samples*num_pixels,
+ * but can be higher due to the initial resolution division for previews. */
+ uint64_t total_pixel_samples;
+
+ /* These lists contain the indices of the tiles to be rendered/denoised and are used
+ * when acquiring a new tile for the device.
+ * Each list in each vector is for one logical device. */
+ vector<list<int>> render_tiles;
+ vector<list<int>> denoising_tiles;
+ } state;
+
+ int num_samples;
+
+ TileManager(bool progressive,
+ int num_samples,
+ int2 tile_size,
+ int start_resolution,
+ bool preserve_tile_device,
+ bool background,
+ TileOrder tile_order,
+ int num_devices = 1,
+ int pixel_size = 1);
+ ~TileManager();
+
+ void device_free();
+ void reset(BufferParams &params, int num_samples);
+ void set_samples(int num_samples);
+ bool next();
+ bool next_tile(Tile *&tile, int device = 0);
+ bool finish_tile(int index, bool &delete_tile);
+ bool done();
+
+ void set_tile_order(TileOrder tile_order_)
+ {
+ tile_order = tile_order_;
+ }
+
+ /* ** Sample range rendering. ** */
+
+ /* Start sample in the range. */
+ int range_start_sample;
+
+ /* Number to samples in the rendering range. */
+ int range_num_samples;
+
+ /* Get number of actual samples to render. */
+ int get_num_effective_samples();
+
+ /* Schedule tiles for denoising after they've been rendered. */
+ bool schedule_denoising;
+
+ protected:
+ void set_tiles();
+
+ bool progressive;
+ int2 tile_size;
+ TileOrder tile_order;
+ int start_resolution;
+ int pixel_size;
+ int num_devices;
+
+ /* in some cases it is important that the same tile will be returned for the same
+ * device it was originally generated for (i.e. viewport rendering when buffer is
+ * allocating once for tile and then always used by it)
+ *
+ * in other cases any tile could be handled by any device (i.e. final rendering
+ * without progressive refine)
+ */
+ bool preserve_tile_device;
+
+ /* for background render tiles should exactly match render parts generated from
+ * blender side, which means image first gets split into tiles and then tiles are
+ * assigning to render devices
+ *
+ * however viewport rendering expects tiles to be allocated in a special way,
+ * meaning image is being sliced horizontally first and every device handles
+ * it's own slice
+ */
+ bool background;
+
+ /* Generate tile list, return number of tiles. */
+ int gen_tiles(bool sliced);
+ void gen_render_tiles();
+
+ int get_neighbor_index(int index, int neighbor);
+ bool check_neighbor_state(int index, Tile::State state);
};
CCL_NAMESPACE_END
-#endif /* __TILE_H__ */
+#endif /* __TILE_H__ */
diff --git a/intern/cycles/subd/CMakeLists.txt b/intern/cycles/subd/CMakeLists.txt
index 9669bdede7e..f5ceaa0436d 100644
--- a/intern/cycles/subd/CMakeLists.txt
+++ b/intern/cycles/subd/CMakeLists.txt
@@ -1,6 +1,6 @@
set(INC
- ..
+ ..
)
set(INC_SYS
@@ -8,17 +8,17 @@ set(INC_SYS
)
set(SRC
- subd_dice.cpp
- subd_patch.cpp
- subd_split.cpp
- subd_patch_table.cpp
+ subd_dice.cpp
+ subd_patch.cpp
+ subd_split.cpp
+ subd_patch_table.cpp
)
set(SRC_HEADERS
- subd_dice.h
- subd_patch.h
- subd_patch_table.h
- subd_split.h
+ subd_dice.h
+ subd_patch.h
+ subd_patch_table.h
+ subd_split.h
)
set(LIB
diff --git a/intern/cycles/subd/subd_dice.cpp b/intern/cycles/subd/subd_dice.cpp
index c5ac54cfcc8..6b062ecfea2 100644
--- a/intern/cycles/subd/subd_dice.cpp
+++ b/intern/cycles/subd/subd_dice.cpp
@@ -24,327 +24,335 @@ CCL_NAMESPACE_BEGIN
/* EdgeDice Base */
-EdgeDice::EdgeDice(const SubdParams& params_)
-: params(params_)
+EdgeDice::EdgeDice(const SubdParams &params_) : params(params_)
{
- mesh_P = NULL;
- mesh_N = NULL;
- vert_offset = 0;
+ mesh_P = NULL;
+ mesh_N = NULL;
+ vert_offset = 0;
- params.mesh->attributes.add(ATTR_STD_VERTEX_NORMAL);
+ params.mesh->attributes.add(ATTR_STD_VERTEX_NORMAL);
- if(params.ptex) {
- params.mesh->attributes.add(ATTR_STD_PTEX_UV);
- params.mesh->attributes.add(ATTR_STD_PTEX_FACE_ID);
- }
+ if (params.ptex) {
+ params.mesh->attributes.add(ATTR_STD_PTEX_UV);
+ params.mesh->attributes.add(ATTR_STD_PTEX_FACE_ID);
+ }
}
void EdgeDice::reserve(int num_verts)
{
- Mesh *mesh = params.mesh;
+ Mesh *mesh = params.mesh;
- vert_offset = mesh->verts.size();
- tri_offset = mesh->num_triangles();
+ vert_offset = mesh->verts.size();
+ tri_offset = mesh->num_triangles();
- /* todo: optimize so we can reserve in advance, this is like push_back_slow() */
- if(vert_offset + num_verts > mesh->verts.capacity()) {
- mesh->reserve_mesh(size_t((vert_offset + num_verts) * 1.2), mesh->num_triangles());
- }
+ /* todo: optimize so we can reserve in advance, this is like push_back_slow() */
+ if (vert_offset + num_verts > mesh->verts.capacity()) {
+ mesh->reserve_mesh(size_t((vert_offset + num_verts) * 1.2), mesh->num_triangles());
+ }
- mesh->resize_mesh(vert_offset + num_verts, tri_offset);
+ mesh->resize_mesh(vert_offset + num_verts, tri_offset);
- Attribute *attr_vN = mesh->attributes.add(ATTR_STD_VERTEX_NORMAL);
+ Attribute *attr_vN = mesh->attributes.add(ATTR_STD_VERTEX_NORMAL);
- mesh_P = mesh->verts.data();
- mesh_N = attr_vN->data_float3();
+ mesh_P = mesh->verts.data();
+ mesh_N = attr_vN->data_float3();
}
int EdgeDice::add_vert(Patch *patch, float2 uv)
{
- float3 P, N;
+ float3 P, N;
- patch->eval(&P, NULL, NULL, &N, uv.x, uv.y);
+ patch->eval(&P, NULL, NULL, &N, uv.x, uv.y);
- assert(vert_offset < params.mesh->verts.size());
+ assert(vert_offset < params.mesh->verts.size());
- mesh_P[vert_offset] = P;
- mesh_N[vert_offset] = N;
- params.mesh->vert_patch_uv[vert_offset] = make_float2(uv.x, uv.y);
+ mesh_P[vert_offset] = P;
+ mesh_N[vert_offset] = N;
+ params.mesh->vert_patch_uv[vert_offset] = make_float2(uv.x, uv.y);
- if(params.ptex) {
- Attribute *attr_ptex_uv = params.mesh->attributes.add(ATTR_STD_PTEX_UV);
- params.mesh->attributes.resize();
+ if (params.ptex) {
+ Attribute *attr_ptex_uv = params.mesh->attributes.add(ATTR_STD_PTEX_UV);
+ params.mesh->attributes.resize();
- float3 *ptex_uv = attr_ptex_uv->data_float3();
- ptex_uv[vert_offset] = make_float3(uv.x, uv.y, 0.0f);
- }
+ float3 *ptex_uv = attr_ptex_uv->data_float3();
+ ptex_uv[vert_offset] = make_float3(uv.x, uv.y, 0.0f);
+ }
- params.mesh->num_subd_verts++;
+ params.mesh->num_subd_verts++;
- return vert_offset++;
+ return vert_offset++;
}
void EdgeDice::add_triangle(Patch *patch, int v0, int v1, int v2)
{
- Mesh *mesh = params.mesh;
+ Mesh *mesh = params.mesh;
- /* todo: optimize so we can reserve in advance, this is like push_back_slow() */
- if(mesh->triangles.size() == mesh->triangles.capacity())
- mesh->reserve_mesh(mesh->verts.size(), size_t(max(mesh->num_triangles() + 1, 1) * 1.2));
+ /* todo: optimize so we can reserve in advance, this is like push_back_slow() */
+ if (mesh->triangles.size() == mesh->triangles.capacity())
+ mesh->reserve_mesh(mesh->verts.size(), size_t(max(mesh->num_triangles() + 1, 1) * 1.2));
- mesh->add_triangle(v0, v1, v2, patch->shader, true);
- params.mesh->triangle_patch[params.mesh->num_triangles()-1] = patch->patch_index;
+ mesh->add_triangle(v0, v1, v2, patch->shader, true);
+ params.mesh->triangle_patch[params.mesh->num_triangles() - 1] = patch->patch_index;
- if(params.ptex) {
- Attribute *attr_ptex_face_id = params.mesh->attributes.add(ATTR_STD_PTEX_FACE_ID);
- params.mesh->attributes.resize();
+ if (params.ptex) {
+ Attribute *attr_ptex_face_id = params.mesh->attributes.add(ATTR_STD_PTEX_FACE_ID);
+ params.mesh->attributes.resize();
- float *ptex_face_id = attr_ptex_face_id->data_float();
- ptex_face_id[tri_offset] = (float)patch->ptex_face_id();
- }
+ float *ptex_face_id = attr_ptex_face_id->data_float();
+ ptex_face_id[tri_offset] = (float)patch->ptex_face_id();
+ }
- tri_offset++;
+ tri_offset++;
}
-void EdgeDice::stitch_triangles(Patch *patch, vector<int>& outer, vector<int>& inner)
+void EdgeDice::stitch_triangles(Patch *patch, vector<int> &outer, vector<int> &inner)
{
- if(inner.size() == 0 || outer.size() == 0)
- return; // XXX avoid crashes for Mu or Mv == 1, missing polygons
-
- /* stitch together two arrays of verts with triangles. at each step,
- * we compare using the next verts on both sides, to find the split
- * direction with the smallest diagonal, and use that in order to keep
- * the triangle shape reasonable. */
- for(size_t i = 0, j = 0; i+1 < inner.size() || j+1 < outer.size();) {
- int v0, v1, v2;
-
- v0 = inner[i];
- v1 = outer[j];
-
- if(j+1 == outer.size()) {
- v2 = inner[++i];
- }
- else if(i+1 == inner.size()) {
- v2 = outer[++j];
- }
- else {
- /* length of diagonals */
- float len1 = len_squared(mesh_P[inner[i]] - mesh_P[outer[j+1]]);
- float len2 = len_squared(mesh_P[outer[j]] - mesh_P[inner[i+1]]);
-
- /* use smallest diagonal */
- if(len1 < len2)
- v2 = outer[++j];
- else
- v2 = inner[++i];
- }
-
- add_triangle(patch, v0, v1, v2);
- }
+ if (inner.size() == 0 || outer.size() == 0)
+ return; // XXX avoid crashes for Mu or Mv == 1, missing polygons
+
+ /* stitch together two arrays of verts with triangles. at each step,
+ * we compare using the next verts on both sides, to find the split
+ * direction with the smallest diagonal, and use that in order to keep
+ * the triangle shape reasonable. */
+ for (size_t i = 0, j = 0; i + 1 < inner.size() || j + 1 < outer.size();) {
+ int v0, v1, v2;
+
+ v0 = inner[i];
+ v1 = outer[j];
+
+ if (j + 1 == outer.size()) {
+ v2 = inner[++i];
+ }
+ else if (i + 1 == inner.size()) {
+ v2 = outer[++j];
+ }
+ else {
+ /* length of diagonals */
+ float len1 = len_squared(mesh_P[inner[i]] - mesh_P[outer[j + 1]]);
+ float len2 = len_squared(mesh_P[outer[j]] - mesh_P[inner[i + 1]]);
+
+ /* use smallest diagonal */
+ if (len1 < len2)
+ v2 = outer[++j];
+ else
+ v2 = inner[++i];
+ }
+
+ add_triangle(patch, v0, v1, v2);
+ }
}
/* QuadDice */
-QuadDice::QuadDice(const SubdParams& params_)
-: EdgeDice(params_)
+QuadDice::QuadDice(const SubdParams &params_) : EdgeDice(params_)
{
}
-void QuadDice::reserve(EdgeFactors& ef, int Mu, int Mv)
+void QuadDice::reserve(EdgeFactors &ef, int Mu, int Mv)
{
- /* XXX need to make this also work for edge factor 0 and 1 */
- int num_verts = (ef.tu0 + ef.tu1 + ef.tv0 + ef.tv1) + (Mu - 1)*(Mv - 1);
- EdgeDice::reserve(num_verts);
+ /* XXX need to make this also work for edge factor 0 and 1 */
+ int num_verts = (ef.tu0 + ef.tu1 + ef.tv0 + ef.tv1) + (Mu - 1) * (Mv - 1);
+ EdgeDice::reserve(num_verts);
}
-float2 QuadDice::map_uv(SubPatch& sub, float u, float v)
+float2 QuadDice::map_uv(SubPatch &sub, float u, float v)
{
- /* map UV from subpatch to patch parametric coordinates */
- float2 d0 = interp(sub.P00, sub.P01, v);
- float2 d1 = interp(sub.P10, sub.P11, v);
- return interp(d0, d1, u);
+ /* map UV from subpatch to patch parametric coordinates */
+ float2 d0 = interp(sub.P00, sub.P01, v);
+ float2 d1 = interp(sub.P10, sub.P11, v);
+ return interp(d0, d1, u);
}
-float3 QuadDice::eval_projected(SubPatch& sub, float u, float v)
+float3 QuadDice::eval_projected(SubPatch &sub, float u, float v)
{
- float2 uv = map_uv(sub, u, v);
- float3 P;
+ float2 uv = map_uv(sub, u, v);
+ float3 P;
- sub.patch->eval(&P, NULL, NULL, NULL, uv.x, uv.y);
- if(params.camera)
- P = transform_perspective(&params.camera->worldtoraster, P);
+ sub.patch->eval(&P, NULL, NULL, NULL, uv.x, uv.y);
+ if (params.camera)
+ P = transform_perspective(&params.camera->worldtoraster, P);
- return P;
+ return P;
}
-int QuadDice::add_vert(SubPatch& sub, float u, float v)
+int QuadDice::add_vert(SubPatch &sub, float u, float v)
{
- return EdgeDice::add_vert(sub.patch, map_uv(sub, u, v));
+ return EdgeDice::add_vert(sub.patch, map_uv(sub, u, v));
}
-void QuadDice::add_side_u(SubPatch& sub,
- vector<int>& outer, vector<int>& inner,
- int Mu, int Mv, int tu, int side, int offset)
+void QuadDice::add_side_u(SubPatch &sub,
+ vector<int> &outer,
+ vector<int> &inner,
+ int Mu,
+ int Mv,
+ int tu,
+ int side,
+ int offset)
{
- outer.clear();
- inner.clear();
+ outer.clear();
+ inner.clear();
- /* set verts on the edge of the patch */
- outer.push_back(offset + ((side)? 2: 0));
+ /* set verts on the edge of the patch */
+ outer.push_back(offset + ((side) ? 2 : 0));
- for(int i = 1; i < tu; i++) {
- float u = i/(float)tu;
- float v = (side)? 1.0f: 0.0f;
+ for (int i = 1; i < tu; i++) {
+ float u = i / (float)tu;
+ float v = (side) ? 1.0f : 0.0f;
- outer.push_back(add_vert(sub, u, v));
- }
+ outer.push_back(add_vert(sub, u, v));
+ }
- outer.push_back(offset + ((side)? 3: 1));
+ outer.push_back(offset + ((side) ? 3 : 1));
- /* set verts on the edge of the inner grid */
- for(int i = 0; i < Mu-1; i++) {
- int j = (side)? Mv-1-1: 0;
- inner.push_back(offset + 4 + i + j*(Mu-1));
- }
+ /* set verts on the edge of the inner grid */
+ for (int i = 0; i < Mu - 1; i++) {
+ int j = (side) ? Mv - 1 - 1 : 0;
+ inner.push_back(offset + 4 + i + j * (Mu - 1));
+ }
}
-void QuadDice::add_side_v(SubPatch& sub,
- vector<int>& outer, vector<int>& inner,
- int Mu, int Mv, int tv, int side, int offset)
+void QuadDice::add_side_v(SubPatch &sub,
+ vector<int> &outer,
+ vector<int> &inner,
+ int Mu,
+ int Mv,
+ int tv,
+ int side,
+ int offset)
{
- outer.clear();
- inner.clear();
+ outer.clear();
+ inner.clear();
- /* set verts on the edge of the patch */
- outer.push_back(offset + ((side)? 1: 0));
+ /* set verts on the edge of the patch */
+ outer.push_back(offset + ((side) ? 1 : 0));
- for(int j = 1; j < tv; j++) {
- float u = (side)? 1.0f: 0.0f;
- float v = j/(float)tv;
+ for (int j = 1; j < tv; j++) {
+ float u = (side) ? 1.0f : 0.0f;
+ float v = j / (float)tv;
- outer.push_back(add_vert(sub, u, v));
- }
+ outer.push_back(add_vert(sub, u, v));
+ }
- outer.push_back(offset + ((side)? 3: 2));
+ outer.push_back(offset + ((side) ? 3 : 2));
- /* set verts on the edge of the inner grid */
- for(int j = 0; j < Mv-1; j++) {
- int i = (side)? Mu-1-1: 0;
- inner.push_back(offset + 4 + i + j*(Mu-1));
- }
+ /* set verts on the edge of the inner grid */
+ for (int j = 0; j < Mv - 1; j++) {
+ int i = (side) ? Mu - 1 - 1 : 0;
+ inner.push_back(offset + 4 + i + j * (Mu - 1));
+ }
}
-float QuadDice::quad_area(const float3& a, const float3& b, const float3& c, const float3& d)
+float QuadDice::quad_area(const float3 &a, const float3 &b, const float3 &c, const float3 &d)
{
- return triangle_area(a, b, d) + triangle_area(a, d, c);
+ return triangle_area(a, b, d) + triangle_area(a, d, c);
}
-float QuadDice::scale_factor(SubPatch& sub, EdgeFactors& ef, int Mu, int Mv)
+float QuadDice::scale_factor(SubPatch &sub, EdgeFactors &ef, int Mu, int Mv)
{
- /* estimate area as 4x largest of 4 quads */
- float3 P[3][3];
-
- for(int i = 0; i < 3; i++)
- for(int j = 0; j < 3; j++)
- P[i][j] = eval_projected(sub, i*0.5f, j*0.5f);
-
- float A1 = quad_area(P[0][0], P[1][0], P[0][1], P[1][1]);
- float A2 = quad_area(P[1][0], P[2][0], P[1][1], P[2][1]);
- float A3 = quad_area(P[0][1], P[1][1], P[0][2], P[1][2]);
- float A4 = quad_area(P[1][1], P[2][1], P[1][2], P[2][2]);
- float Apatch = max(A1, max(A2, max(A3, A4)))*4.0f;
-
- /* solve for scaling factor */
- float Atri = params.dicing_rate*params.dicing_rate*0.5f;
- float Ntris = Apatch/Atri;
-
- // XXX does the -sqrt solution matter
- // XXX max(D, 0.0) is highly suspicious, need to test cases
- // where D goes negative
- float N = 0.5f*(Ntris - (ef.tu0 + ef.tu1 + ef.tv0 + ef.tv1));
- float D = 4.0f*N*Mu*Mv + (Mu + Mv)*(Mu + Mv);
- float S = (Mu + Mv + sqrtf(max(D, 0.0f)))/(2*Mu*Mv);
-
- return S;
+ /* estimate area as 4x largest of 4 quads */
+ float3 P[3][3];
+
+ for (int i = 0; i < 3; i++)
+ for (int j = 0; j < 3; j++)
+ P[i][j] = eval_projected(sub, i * 0.5f, j * 0.5f);
+
+ float A1 = quad_area(P[0][0], P[1][0], P[0][1], P[1][1]);
+ float A2 = quad_area(P[1][0], P[2][0], P[1][1], P[2][1]);
+ float A3 = quad_area(P[0][1], P[1][1], P[0][2], P[1][2]);
+ float A4 = quad_area(P[1][1], P[2][1], P[1][2], P[2][2]);
+ float Apatch = max(A1, max(A2, max(A3, A4))) * 4.0f;
+
+ /* solve for scaling factor */
+ float Atri = params.dicing_rate * params.dicing_rate * 0.5f;
+ float Ntris = Apatch / Atri;
+
+ // XXX does the -sqrt solution matter
+ // XXX max(D, 0.0) is highly suspicious, need to test cases
+ // where D goes negative
+ float N = 0.5f * (Ntris - (ef.tu0 + ef.tu1 + ef.tv0 + ef.tv1));
+ float D = 4.0f * N * Mu * Mv + (Mu + Mv) * (Mu + Mv);
+ float S = (Mu + Mv + sqrtf(max(D, 0.0f))) / (2 * Mu * Mv);
+
+ return S;
}
-void QuadDice::add_corners(SubPatch& sub)
+void QuadDice::add_corners(SubPatch &sub)
{
- /* add verts for patch corners */
- add_vert(sub, 0.0f, 0.0f);
- add_vert(sub, 1.0f, 0.0f);
- add_vert(sub, 0.0f, 1.0f);
- add_vert(sub, 1.0f, 1.0f);
+ /* add verts for patch corners */
+ add_vert(sub, 0.0f, 0.0f);
+ add_vert(sub, 1.0f, 0.0f);
+ add_vert(sub, 0.0f, 1.0f);
+ add_vert(sub, 1.0f, 1.0f);
}
-void QuadDice::add_grid(SubPatch& sub, int Mu, int Mv, int offset)
+void QuadDice::add_grid(SubPatch &sub, int Mu, int Mv, int offset)
{
- /* create inner grid */
- float du = 1.0f/(float)Mu;
- float dv = 1.0f/(float)Mv;
-
- for(int j = 1; j < Mv; j++) {
- for(int i = 1; i < Mu; i++) {
- float u = i*du;
- float v = j*dv;
-
- add_vert(sub, u, v);
-
- if(i < Mu-1 && j < Mv-1) {
- int i1 = offset + 4 + (i-1) + (j-1)*(Mu-1);
- int i2 = offset + 4 + i + (j-1)*(Mu-1);
- int i3 = offset + 4 + i + j*(Mu-1);
- int i4 = offset + 4 + (i-1) + j*(Mu-1);
-
- add_triangle(sub.patch, i1, i2, i3);
- add_triangle(sub.patch, i1, i3, i4);
- }
- }
- }
+ /* create inner grid */
+ float du = 1.0f / (float)Mu;
+ float dv = 1.0f / (float)Mv;
+
+ for (int j = 1; j < Mv; j++) {
+ for (int i = 1; i < Mu; i++) {
+ float u = i * du;
+ float v = j * dv;
+
+ add_vert(sub, u, v);
+
+ if (i < Mu - 1 && j < Mv - 1) {
+ int i1 = offset + 4 + (i - 1) + (j - 1) * (Mu - 1);
+ int i2 = offset + 4 + i + (j - 1) * (Mu - 1);
+ int i3 = offset + 4 + i + j * (Mu - 1);
+ int i4 = offset + 4 + (i - 1) + j * (Mu - 1);
+
+ add_triangle(sub.patch, i1, i2, i3);
+ add_triangle(sub.patch, i1, i3, i4);
+ }
+ }
+ }
}
-void QuadDice::dice(SubPatch& sub, EdgeFactors& ef)
+void QuadDice::dice(SubPatch &sub, EdgeFactors &ef)
{
- /* compute inner grid size with scale factor */
- int Mu = max(ef.tu0, ef.tu1);
- int Mv = max(ef.tv0, ef.tv1);
+ /* compute inner grid size with scale factor */
+ int Mu = max(ef.tu0, ef.tu1);
+ int Mv = max(ef.tv0, ef.tv1);
#if 0 /* Doesnt work very well, especially at grazing angles. */
- float S = scale_factor(sub, ef, Mu, Mv);
+ float S = scale_factor(sub, ef, Mu, Mv);
#else
- float S = 1.0f;
+ float S = 1.0f;
#endif
- Mu = max((int)ceil(S*Mu), 2); // XXX handle 0 & 1?
- Mv = max((int)ceil(S*Mv), 2); // XXX handle 0 & 1?
+ Mu = max((int)ceil(S * Mu), 2); // XXX handle 0 & 1?
+ Mv = max((int)ceil(S * Mv), 2); // XXX handle 0 & 1?
- /* reserve space for new verts */
- int offset = params.mesh->verts.size();
- reserve(ef, Mu, Mv);
+ /* reserve space for new verts */
+ int offset = params.mesh->verts.size();
+ reserve(ef, Mu, Mv);
- /* corners and inner grid */
- add_corners(sub);
- add_grid(sub, Mu, Mv, offset);
+ /* corners and inner grid */
+ add_corners(sub);
+ add_grid(sub, Mu, Mv, offset);
- /* bottom side */
- vector<int> outer, inner;
+ /* bottom side */
+ vector<int> outer, inner;
- add_side_u(sub, outer, inner, Mu, Mv, ef.tu0, 0, offset);
- stitch_triangles(sub.patch, outer, inner);
+ add_side_u(sub, outer, inner, Mu, Mv, ef.tu0, 0, offset);
+ stitch_triangles(sub.patch, outer, inner);
- /* top side */
- add_side_u(sub, outer, inner, Mu, Mv, ef.tu1, 1, offset);
- stitch_triangles(sub.patch, inner, outer);
+ /* top side */
+ add_side_u(sub, outer, inner, Mu, Mv, ef.tu1, 1, offset);
+ stitch_triangles(sub.patch, inner, outer);
- /* left side */
- add_side_v(sub, outer, inner, Mu, Mv, ef.tv0, 0, offset);
- stitch_triangles(sub.patch, inner, outer);
+ /* left side */
+ add_side_v(sub, outer, inner, Mu, Mv, ef.tv0, 0, offset);
+ stitch_triangles(sub.patch, inner, outer);
- /* right side */
- add_side_v(sub, outer, inner, Mu, Mv, ef.tv1, 1, offset);
- stitch_triangles(sub.patch, outer, inner);
+ /* right side */
+ add_side_v(sub, outer, inner, Mu, Mv, ef.tv1, 1, offset);
+ stitch_triangles(sub.patch, outer, inner);
- assert(vert_offset == params.mesh->verts.size());
+ assert(vert_offset == params.mesh->verts.size());
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/subd/subd_dice.h b/intern/cycles/subd/subd_dice.h
index 2bef8d4cf8d..eee54e01861 100644
--- a/intern/cycles/subd/subd_dice.h
+++ b/intern/cycles/subd/subd_dice.h
@@ -32,48 +32,47 @@ class Mesh;
class Patch;
struct SubdParams {
- Mesh *mesh;
- bool ptex;
-
- int test_steps;
- int split_threshold;
- float dicing_rate;
- int max_level;
- Camera *camera;
- Transform objecttoworld;
-
- SubdParams(Mesh *mesh_, bool ptex_ = false)
- {
- mesh = mesh_;
- ptex = ptex_;
-
- test_steps = 3;
- split_threshold = 1;
- dicing_rate = 1.0f;
- max_level = 12;
- camera = NULL;
- }
-
+ Mesh *mesh;
+ bool ptex;
+
+ int test_steps;
+ int split_threshold;
+ float dicing_rate;
+ int max_level;
+ Camera *camera;
+ Transform objecttoworld;
+
+ SubdParams(Mesh *mesh_, bool ptex_ = false)
+ {
+ mesh = mesh_;
+ ptex = ptex_;
+
+ test_steps = 3;
+ split_threshold = 1;
+ dicing_rate = 1.0f;
+ max_level = 12;
+ camera = NULL;
+ }
};
/* EdgeDice Base */
class EdgeDice {
-public:
- SubdParams params;
- float3 *mesh_P;
- float3 *mesh_N;
- size_t vert_offset;
- size_t tri_offset;
+ public:
+ SubdParams params;
+ float3 *mesh_P;
+ float3 *mesh_N;
+ size_t vert_offset;
+ size_t tri_offset;
- explicit EdgeDice(const SubdParams& params);
+ explicit EdgeDice(const SubdParams &params);
- void reserve(int num_verts);
+ void reserve(int num_verts);
- int add_vert(Patch *patch, float2 uv);
- void add_triangle(Patch *patch, int v0, int v1, int v2);
+ int add_vert(Patch *patch, float2 uv);
+ void add_triangle(Patch *patch, int v0, int v1, int v2);
- void stitch_triangles(Patch *patch, vector<int>& outer, vector<int>& inner);
+ void stitch_triangles(Patch *patch, vector<int> &outer, vector<int> &inner);
};
/* Quad EdgeDice
@@ -90,48 +89,58 @@ public:
*/
class QuadDice : public EdgeDice {
-public:
- struct SubPatch {
- Patch *patch;
-
- float2 P00;
- float2 P10;
- float2 P01;
- float2 P11;
- };
-
- struct EdgeFactors {
- int tu0;
- int tu1;
- int tv0;
- int tv1;
- };
-
- explicit QuadDice(const SubdParams& params);
-
- void reserve(EdgeFactors& ef, int Mu, int Mv);
- float3 eval_projected(SubPatch& sub, float u, float v);
-
- float2 map_uv(SubPatch& sub, float u, float v);
- int add_vert(SubPatch& sub, float u, float v);
-
- void add_corners(SubPatch& sub);
- void add_grid(SubPatch& sub, int Mu, int Mv, int offset);
-
- void add_side_u(SubPatch& sub,
- vector<int>& outer, vector<int>& inner,
- int Mu, int Mv, int tu, int side, int offset);
-
- void add_side_v(SubPatch& sub,
- vector<int>& outer, vector<int>& inner,
- int Mu, int Mv, int tv, int side, int offset);
-
- float quad_area(const float3& a, const float3& b, const float3& c, const float3& d);
- float scale_factor(SubPatch& sub, EdgeFactors& ef, int Mu, int Mv);
-
- void dice(SubPatch& sub, EdgeFactors& ef);
+ public:
+ struct SubPatch {
+ Patch *patch;
+
+ float2 P00;
+ float2 P10;
+ float2 P01;
+ float2 P11;
+ };
+
+ struct EdgeFactors {
+ int tu0;
+ int tu1;
+ int tv0;
+ int tv1;
+ };
+
+ explicit QuadDice(const SubdParams &params);
+
+ void reserve(EdgeFactors &ef, int Mu, int Mv);
+ float3 eval_projected(SubPatch &sub, float u, float v);
+
+ float2 map_uv(SubPatch &sub, float u, float v);
+ int add_vert(SubPatch &sub, float u, float v);
+
+ void add_corners(SubPatch &sub);
+ void add_grid(SubPatch &sub, int Mu, int Mv, int offset);
+
+ void add_side_u(SubPatch &sub,
+ vector<int> &outer,
+ vector<int> &inner,
+ int Mu,
+ int Mv,
+ int tu,
+ int side,
+ int offset);
+
+ void add_side_v(SubPatch &sub,
+ vector<int> &outer,
+ vector<int> &inner,
+ int Mu,
+ int Mv,
+ int tv,
+ int side,
+ int offset);
+
+ float quad_area(const float3 &a, const float3 &b, const float3 &c, const float3 &d);
+ float scale_factor(SubPatch &sub, EdgeFactors &ef, int Mu, int Mv);
+
+ void dice(SubPatch &sub, EdgeFactors &ef);
};
CCL_NAMESPACE_END
-#endif /* __SUBD_DICE_H__ */
+#endif /* __SUBD_DICE_H__ */
diff --git a/intern/cycles/subd/subd_patch.cpp b/intern/cycles/subd/subd_patch.cpp
index f8f5aa25d19..a975b7b6342 100644
--- a/intern/cycles/subd/subd_patch.cpp
+++ b/intern/cycles/subd/subd_patch.cpp
@@ -29,89 +29,93 @@ CCL_NAMESPACE_BEGIN
static void decasteljau_cubic(float3 *P, float3 *dt, float t, const float3 cp[4])
{
- float3 d0 = cp[0] + t*(cp[1] - cp[0]);
- float3 d1 = cp[1] + t*(cp[2] - cp[1]);
- float3 d2 = cp[2] + t*(cp[3] - cp[2]);
+ float3 d0 = cp[0] + t * (cp[1] - cp[0]);
+ float3 d1 = cp[1] + t * (cp[2] - cp[1]);
+ float3 d2 = cp[2] + t * (cp[3] - cp[2]);
- d0 += t*(d1 - d0);
- d1 += t*(d2 - d1);
+ d0 += t * (d1 - d0);
+ d1 += t * (d2 - d1);
- *P = d0 + t*(d1 - d0);
- if(dt) *dt = d1 - d0;
+ *P = d0 + t * (d1 - d0);
+ if (dt)
+ *dt = d1 - d0;
}
-static void decasteljau_bicubic(float3 *P, float3 *du, float3 *dv, const float3 cp[16], float u, float v)
+static void decasteljau_bicubic(
+ float3 *P, float3 *du, float3 *dv, const float3 cp[16], float u, float v)
{
- float3 ucp[4], utn[4];
-
- /* interpolate over u */
- decasteljau_cubic(ucp+0, utn+0, u, cp);
- decasteljau_cubic(ucp+1, utn+1, u, cp+4);
- decasteljau_cubic(ucp+2, utn+2, u, cp+8);
- decasteljau_cubic(ucp+3, utn+3, u, cp+12);
-
- /* interpolate over v */
- decasteljau_cubic(P, dv, v, ucp);
- if(du) decasteljau_cubic(du, NULL, v, utn);
+ float3 ucp[4], utn[4];
+
+ /* interpolate over u */
+ decasteljau_cubic(ucp + 0, utn + 0, u, cp);
+ decasteljau_cubic(ucp + 1, utn + 1, u, cp + 4);
+ decasteljau_cubic(ucp + 2, utn + 2, u, cp + 8);
+ decasteljau_cubic(ucp + 3, utn + 3, u, cp + 12);
+
+ /* interpolate over v */
+ decasteljau_cubic(P, dv, v, ucp);
+ if (du)
+ decasteljau_cubic(du, NULL, v, utn);
}
/* Linear Quad Patch */
void LinearQuadPatch::eval(float3 *P, float3 *dPdu, float3 *dPdv, float3 *N, float u, float v)
{
- float3 d0 = interp(hull[0], hull[1], u);
- float3 d1 = interp(hull[2], hull[3], u);
+ float3 d0 = interp(hull[0], hull[1], u);
+ float3 d1 = interp(hull[2], hull[3], u);
- *P = interp(d0, d1, v);
+ *P = interp(d0, d1, v);
- if(dPdu && dPdv) {
- *dPdu = interp(hull[1] - hull[0], hull[3] - hull[2], v);
- *dPdv = interp(hull[2] - hull[0], hull[3] - hull[1], u);
- }
+ if (dPdu && dPdv) {
+ *dPdu = interp(hull[1] - hull[0], hull[3] - hull[2], v);
+ *dPdv = interp(hull[2] - hull[0], hull[3] - hull[1], u);
+ }
- if(N) {
- *N = normalize(interp(interp(normals[0], normals[1], u), interp(normals[2], normals[3], u), v));
- }
+ if (N) {
+ *N = normalize(
+ interp(interp(normals[0], normals[1], u), interp(normals[2], normals[3], u), v));
+ }
}
BoundBox LinearQuadPatch::bound()
{
- BoundBox bbox = BoundBox::empty;
+ BoundBox bbox = BoundBox::empty;
- for(int i = 0; i < 4; i++)
- bbox.grow(hull[i]);
+ for (int i = 0; i < 4; i++)
+ bbox.grow(hull[i]);
- return bbox;
+ return bbox;
}
/* Bicubic Patch */
void BicubicPatch::eval(float3 *P, float3 *dPdu, float3 *dPdv, float3 *N, float u, float v)
{
- if(N) {
- float3 dPdu_, dPdv_;
- decasteljau_bicubic(P, &dPdu_, &dPdv_, hull, u, v);
-
- if(dPdu && dPdv) {
- *dPdu = dPdu_;
- *dPdv = dPdv_;
- }
-
- *N = normalize(cross(dPdu_, dPdv_));
- }
- else {
- decasteljau_bicubic(P, dPdu, dPdv, hull, u, v);
- }
+ if (N) {
+ float3 dPdu_, dPdv_;
+ decasteljau_bicubic(P, &dPdu_, &dPdv_, hull, u, v);
+
+ if (dPdu && dPdv) {
+ *dPdu = dPdu_;
+ *dPdv = dPdv_;
+ }
+
+ *N = normalize(cross(dPdu_, dPdv_));
+ }
+ else {
+ decasteljau_bicubic(P, dPdu, dPdv, hull, u, v);
+ }
}
BoundBox BicubicPatch::bound()
{
- BoundBox bbox = BoundBox::empty;
+ BoundBox bbox = BoundBox::empty;
- for(int i = 0; i < 16; i++)
- bbox.grow(hull[i]);
+ for (int i = 0; i < 16; i++)
+ bbox.grow(hull[i]);
- return bbox;
+ return bbox;
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/subd/subd_patch.h b/intern/cycles/subd/subd_patch.h
index 84100139f2c..5209d4d0b07 100644
--- a/intern/cycles/subd/subd_patch.h
+++ b/intern/cycles/subd/subd_patch.h
@@ -23,37 +23,42 @@
CCL_NAMESPACE_BEGIN
class Patch {
-public:
- virtual ~Patch() {}
- virtual void eval(float3 *P, float3 *dPdu, float3 *dPdv, float3 *N, float u, float v) = 0;
- virtual BoundBox bound() = 0;
- virtual int ptex_face_id() { return -1; }
-
- int patch_index;
- int shader;
+ public:
+ virtual ~Patch()
+ {
+ }
+ virtual void eval(float3 *P, float3 *dPdu, float3 *dPdv, float3 *N, float u, float v) = 0;
+ virtual BoundBox bound() = 0;
+ virtual int ptex_face_id()
+ {
+ return -1;
+ }
+
+ int patch_index;
+ int shader;
};
/* Linear Quad Patch */
class LinearQuadPatch : public Patch {
-public:
- float3 hull[4];
- float3 normals[4];
+ public:
+ float3 hull[4];
+ float3 normals[4];
- void eval(float3 *P, float3 *dPdu, float3 *dPdv, float3 *N, float u, float v);
- BoundBox bound();
+ void eval(float3 *P, float3 *dPdu, float3 *dPdv, float3 *N, float u, float v);
+ BoundBox bound();
};
/* Bicubic Patch */
class BicubicPatch : public Patch {
-public:
- float3 hull[16];
+ public:
+ float3 hull[16];
- void eval(float3 *P, float3 *dPdu, float3 *dPdv, float3 *N, float u, float v);
- BoundBox bound();
+ void eval(float3 *P, float3 *dPdu, float3 *dPdv, float3 *N, float u, float v);
+ BoundBox bound();
};
CCL_NAMESPACE_END
-#endif /* __SUBD_PATCH_H__ */
+#endif /* __SUBD_PATCH_H__ */
diff --git a/intern/cycles/subd/subd_patch_table.cpp b/intern/cycles/subd/subd_patch_table.cpp
index f9671ee144d..4e873375725 100644
--- a/intern/cycles/subd/subd_patch_table.cpp
+++ b/intern/cycles/subd/subd_patch_table.cpp
@@ -30,7 +30,7 @@
#include "util/util_math.h"
#ifdef WITH_OPENSUBDIV
-#include <opensubdiv/far/patchTable.h>
+# include <opensubdiv/far/patchTable.h>
#endif
CCL_NAMESPACE_BEGIN
@@ -42,144 +42,146 @@ using namespace OpenSubdiv;
/* functions for building patch maps */
struct PatchMapQuadNode {
- /* sets all the children to point to the patch of index */
- void set_child(int index)
- {
- for(int i = 0; i < 4; i++) {
- children[i] = index | PATCH_MAP_NODE_IS_SET | PATCH_MAP_NODE_IS_LEAF;
- }
- }
-
- /* sets the child in quadrant to point to the node or patch of the given index */
- void set_child(unsigned char quadrant, int index, bool is_leaf=true)
- {
- assert(quadrant < 4);
- children[quadrant] = index | PATCH_MAP_NODE_IS_SET | (is_leaf ? PATCH_MAP_NODE_IS_LEAF : 0);
- }
-
- uint children[4];
+ /* sets all the children to point to the patch of index */
+ void set_child(int index)
+ {
+ for (int i = 0; i < 4; i++) {
+ children[i] = index | PATCH_MAP_NODE_IS_SET | PATCH_MAP_NODE_IS_LEAF;
+ }
+ }
+
+ /* sets the child in quadrant to point to the node or patch of the given index */
+ void set_child(unsigned char quadrant, int index, bool is_leaf = true)
+ {
+ assert(quadrant < 4);
+ children[quadrant] = index | PATCH_MAP_NODE_IS_SET | (is_leaf ? PATCH_MAP_NODE_IS_LEAF : 0);
+ }
+
+ uint children[4];
};
-template<class T>
-static int resolve_quadrant(T& median, T& u, T& v)
+template<class T> static int resolve_quadrant(T &median, T &u, T &v)
{
- int quadrant = -1;
-
- if(u < median) {
- if(v < median) {
- quadrant = 0;
- }
- else {
- quadrant = 1;
- v -= median;
- }
- }
- else {
- if(v < median) {
- quadrant = 3;
- }
- else {
- quadrant = 2;
- v -= median;
- }
- u -= median;
- }
-
- return quadrant;
+ int quadrant = -1;
+
+ if (u < median) {
+ if (v < median) {
+ quadrant = 0;
+ }
+ else {
+ quadrant = 1;
+ v -= median;
+ }
+ }
+ else {
+ if (v < median) {
+ quadrant = 3;
+ }
+ else {
+ quadrant = 2;
+ v -= median;
+ }
+ u -= median;
+ }
+
+ return quadrant;
}
-static void build_patch_map(PackedPatchTable& table, OpenSubdiv::Far::PatchTable* patch_table, int offset)
+static void build_patch_map(PackedPatchTable &table,
+ OpenSubdiv::Far::PatchTable *patch_table,
+ int offset)
{
- int num_faces = 0;
-
- for(int array = 0; array < table.num_arrays; array++) {
- Far::ConstPatchParamArray params = patch_table->GetPatchParams(array);
-
- for(int j = 0; j < patch_table->GetNumPatches(array); j++) {
- num_faces = max(num_faces, (int)params[j].GetFaceId());
- }
- }
- num_faces++;
-
- vector<PatchMapQuadNode> quadtree;
- quadtree.reserve(num_faces + table.num_patches);
- quadtree.resize(num_faces);
-
- /* adjust offsets to make indices relative to the table */
- int handle_index = -(table.num_patches * PATCH_HANDLE_SIZE);
- offset += table.total_size();
-
- /* populate the quadtree from the FarPatchArrays sub-patches */
- for(int array = 0; array < table.num_arrays; array++) {
- Far::ConstPatchParamArray params = patch_table->GetPatchParams(array);
-
- for(int i = 0; i < patch_table->GetNumPatches(array); i++, handle_index += PATCH_HANDLE_SIZE) {
- const Far::PatchParam& param = params[i];
- unsigned short depth = param.GetDepth();
-
- PatchMapQuadNode* node = &quadtree[params[i].GetFaceId()];
-
- if(depth == (param.NonQuadRoot() ? 1 : 0)) {
- /* special case : regular BSpline face w/ no sub-patches */
- node->set_child(handle_index + offset);
- continue;
- }
-
- int u = param.GetU();
- int v = param.GetV();
- int pdepth = param.NonQuadRoot() ? depth-2 : depth-1;
- int half = 1 << pdepth;
-
- for(int j = 0; j < depth; j++) {
- int delta = half >> 1;
-
- int quadrant = resolve_quadrant(half, u, v);
- assert(quadrant >= 0);
-
- half = delta;
-
- if(j == pdepth) {
- /* we have reached the depth of the sub-patch : add a leaf */
- assert(!(node->children[quadrant] & PATCH_MAP_NODE_IS_SET));
- node->set_child(quadrant, handle_index + offset, true);
- break;
- }
- else {
- /* travel down the child node of the corresponding quadrant */
- if(!(node->children[quadrant] & PATCH_MAP_NODE_IS_SET)) {
- /* create a new branch in the quadrant */
- quadtree.push_back(PatchMapQuadNode());
-
- int idx = (int)quadtree.size() - 1;
- node->set_child(quadrant, idx*4 + offset, false);
-
- node = &quadtree[idx];
- }
- else {
- /* travel down an existing branch */
- uint idx = node->children[quadrant] & PATCH_MAP_NODE_INDEX_MASK;
- node = &(quadtree[(idx - offset)/4]);
- }
- }
- }
- }
- }
-
- /* copy into table */
- assert(table.table.size() == table.total_size());
- uint map_offset = table.total_size();
-
- table.num_nodes = quadtree.size() * 4;
- table.table.resize(table.total_size());
-
- uint* data = &table.table[map_offset];
-
- for(int i = 0; i < quadtree.size(); i++) {
- for(int j = 0; j < 4; j++) {
- assert(quadtree[i].children[j] & PATCH_MAP_NODE_IS_SET);
- *(data++) = quadtree[i].children[j];
- }
- }
+ int num_faces = 0;
+
+ for (int array = 0; array < table.num_arrays; array++) {
+ Far::ConstPatchParamArray params = patch_table->GetPatchParams(array);
+
+ for (int j = 0; j < patch_table->GetNumPatches(array); j++) {
+ num_faces = max(num_faces, (int)params[j].GetFaceId());
+ }
+ }
+ num_faces++;
+
+ vector<PatchMapQuadNode> quadtree;
+ quadtree.reserve(num_faces + table.num_patches);
+ quadtree.resize(num_faces);
+
+ /* adjust offsets to make indices relative to the table */
+ int handle_index = -(table.num_patches * PATCH_HANDLE_SIZE);
+ offset += table.total_size();
+
+ /* populate the quadtree from the FarPatchArrays sub-patches */
+ for (int array = 0; array < table.num_arrays; array++) {
+ Far::ConstPatchParamArray params = patch_table->GetPatchParams(array);
+
+ for (int i = 0; i < patch_table->GetNumPatches(array);
+ i++, handle_index += PATCH_HANDLE_SIZE) {
+ const Far::PatchParam &param = params[i];
+ unsigned short depth = param.GetDepth();
+
+ PatchMapQuadNode *node = &quadtree[params[i].GetFaceId()];
+
+ if (depth == (param.NonQuadRoot() ? 1 : 0)) {
+ /* special case : regular BSpline face w/ no sub-patches */
+ node->set_child(handle_index + offset);
+ continue;
+ }
+
+ int u = param.GetU();
+ int v = param.GetV();
+ int pdepth = param.NonQuadRoot() ? depth - 2 : depth - 1;
+ int half = 1 << pdepth;
+
+ for (int j = 0; j < depth; j++) {
+ int delta = half >> 1;
+
+ int quadrant = resolve_quadrant(half, u, v);
+ assert(quadrant >= 0);
+
+ half = delta;
+
+ if (j == pdepth) {
+ /* we have reached the depth of the sub-patch : add a leaf */
+ assert(!(node->children[quadrant] & PATCH_MAP_NODE_IS_SET));
+ node->set_child(quadrant, handle_index + offset, true);
+ break;
+ }
+ else {
+ /* travel down the child node of the corresponding quadrant */
+ if (!(node->children[quadrant] & PATCH_MAP_NODE_IS_SET)) {
+ /* create a new branch in the quadrant */
+ quadtree.push_back(PatchMapQuadNode());
+
+ int idx = (int)quadtree.size() - 1;
+ node->set_child(quadrant, idx * 4 + offset, false);
+
+ node = &quadtree[idx];
+ }
+ else {
+ /* travel down an existing branch */
+ uint idx = node->children[quadrant] & PATCH_MAP_NODE_INDEX_MASK;
+ node = &(quadtree[(idx - offset) / 4]);
+ }
+ }
+ }
+ }
+ }
+
+ /* copy into table */
+ assert(table.table.size() == table.total_size());
+ uint map_offset = table.total_size();
+
+ table.num_nodes = quadtree.size() * 4;
+ table.table.resize(table.total_size());
+
+ uint *data = &table.table[map_offset];
+
+ for (int i = 0; i < quadtree.size(); i++) {
+ for (int j = 0; j < 4; j++) {
+ assert(quadtree[i].children[j] & PATCH_MAP_NODE_IS_SET);
+ *(data++) = quadtree[i].children[j];
+ }
+ }
}
#endif
@@ -188,108 +190,106 @@ static void build_patch_map(PackedPatchTable& table, OpenSubdiv::Far::PatchTable
size_t PackedPatchTable::total_size()
{
- return num_arrays * PATCH_ARRAY_SIZE +
- num_indices +
- num_patches * (PATCH_PARAM_SIZE + PATCH_HANDLE_SIZE) +
- num_nodes * PATCH_NODE_SIZE;
+ return num_arrays * PATCH_ARRAY_SIZE + num_indices +
+ num_patches * (PATCH_PARAM_SIZE + PATCH_HANDLE_SIZE) + num_nodes * PATCH_NODE_SIZE;
}
-void PackedPatchTable::pack(Far::PatchTable* patch_table, int offset)
+void PackedPatchTable::pack(Far::PatchTable *patch_table, int offset)
{
- num_arrays = 0;
- num_patches = 0;
- num_indices = 0;
- num_nodes = 0;
+ num_arrays = 0;
+ num_patches = 0;
+ num_indices = 0;
+ num_nodes = 0;
#ifdef WITH_OPENSUBDIV
- num_arrays = patch_table->GetNumPatchArrays();
+ num_arrays = patch_table->GetNumPatchArrays();
- for(int i = 0; i < num_arrays; i++) {
- int patches = patch_table->GetNumPatches(i);
- int num_control = patch_table->GetPatchArrayDescriptor(i).GetNumControlVertices();
+ for (int i = 0; i < num_arrays; i++) {
+ int patches = patch_table->GetNumPatches(i);
+ int num_control = patch_table->GetPatchArrayDescriptor(i).GetNumControlVertices();
- num_patches += patches;
- num_indices += patches * num_control;
- }
+ num_patches += patches;
+ num_indices += patches * num_control;
+ }
- table.resize(total_size());
- uint* data = table.data();
+ table.resize(total_size());
+ uint *data = table.data();
- uint* array = data;
- uint* index = array + num_arrays * PATCH_ARRAY_SIZE;
- uint* param = index + num_indices;
- uint* handle = param + num_patches * PATCH_PARAM_SIZE;
+ uint *array = data;
+ uint *index = array + num_arrays * PATCH_ARRAY_SIZE;
+ uint *param = index + num_indices;
+ uint *handle = param + num_patches * PATCH_PARAM_SIZE;
- uint current_param = 0;
+ uint current_param = 0;
- for(int i = 0; i < num_arrays; i++) {
- *(array++) = patch_table->GetPatchArrayDescriptor(i).GetType();
- *(array++) = patch_table->GetNumPatches(i);
- *(array++) = (index - data) + offset;
- *(array++) = (param - data) + offset;
+ for (int i = 0; i < num_arrays; i++) {
+ *(array++) = patch_table->GetPatchArrayDescriptor(i).GetType();
+ *(array++) = patch_table->GetNumPatches(i);
+ *(array++) = (index - data) + offset;
+ *(array++) = (param - data) + offset;
- Far::ConstIndexArray indices = patch_table->GetPatchArrayVertices(i);
+ Far::ConstIndexArray indices = patch_table->GetPatchArrayVertices(i);
- for(int j = 0; j < indices.size(); j++) {
- *(index++) = indices[j];
- }
+ for (int j = 0; j < indices.size(); j++) {
+ *(index++) = indices[j];
+ }
- const Far::PatchParamTable& param_table = patch_table->GetPatchParamTable();
+ const Far::PatchParamTable &param_table = patch_table->GetPatchParamTable();
- int num_control = patch_table->GetPatchArrayDescriptor(i).GetNumControlVertices();
- int patches = patch_table->GetNumPatches(i);
+ int num_control = patch_table->GetPatchArrayDescriptor(i).GetNumControlVertices();
+ int patches = patch_table->GetNumPatches(i);
- for(int j = 0; j < patches; j++, current_param++) {
- *(param++) = param_table[current_param].field0;
- *(param++) = param_table[current_param].field1;
+ for (int j = 0; j < patches; j++, current_param++) {
+ *(param++) = param_table[current_param].field0;
+ *(param++) = param_table[current_param].field1;
- *(handle++) = (array - data) - PATCH_ARRAY_SIZE + offset;
- *(handle++) = (param - data) - PATCH_PARAM_SIZE + offset;
- *(handle++) = j * num_control;
- }
- }
+ *(handle++) = (array - data) - PATCH_ARRAY_SIZE + offset;
+ *(handle++) = (param - data) - PATCH_PARAM_SIZE + offset;
+ *(handle++) = j * num_control;
+ }
+ }
- build_patch_map(*this, patch_table, offset);
+ build_patch_map(*this, patch_table, offset);
#else
- (void) patch_table;
- (void) offset;
+ (void)patch_table;
+ (void)offset;
#endif
}
-void PackedPatchTable::copy_adjusting_offsets(uint* dest, int doffset)
+void PackedPatchTable::copy_adjusting_offsets(uint *dest, int doffset)
{
- uint* src = table.data();
-
- /* arrays */
- for(int i = 0; i < num_arrays; i++) {
- *(dest++) = *(src++);
- *(dest++) = *(src++);
- *(dest++) = *(src++) + doffset;
- *(dest++) = *(src++) + doffset;
- }
-
- /* indices */
- for(int i = 0; i < num_indices; i++) {
- *(dest++) = *(src++);
- }
-
- /* params */
- for(int i = 0; i < num_patches; i++) {
- *(dest++) = *(src++);
- *(dest++) = *(src++);
- }
-
- /* handles */
- for(int i = 0; i < num_patches; i++) {
- *(dest++) = *(src++) + doffset;
- *(dest++) = *(src++) + doffset;
- *(dest++) = *(src++);
- }
-
- /* nodes */
- for(int i = 0; i < num_nodes; i++) {
- *(dest++) = *(src++) + doffset;
- }
+ uint *src = table.data();
+
+ /* arrays */
+ for (int i = 0; i < num_arrays; i++) {
+ *(dest++) = *(src++);
+ *(dest++) = *(src++);
+ *(dest++) = *(src++) + doffset;
+ *(dest++) = *(src++) + doffset;
+ }
+
+ /* indices */
+ for (int i = 0; i < num_indices; i++) {
+ *(dest++) = *(src++);
+ }
+
+ /* params */
+ for (int i = 0; i < num_patches; i++) {
+ *(dest++) = *(src++);
+ *(dest++) = *(src++);
+ }
+
+ /* handles */
+ for (int i = 0; i < num_patches; i++) {
+ *(dest++) = *(src++) + doffset;
+ *(dest++) = *(src++) + doffset;
+ *(dest++) = *(src++);
+ }
+
+ /* nodes */
+ for (int i = 0; i < num_nodes; i++) {
+ *(dest++) = *(src++) + doffset;
+ }
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/subd/subd_patch_table.h b/intern/cycles/subd/subd_patch_table.h
index 1765578c42e..118d410f8f0 100644
--- a/intern/cycles/subd/subd_patch_table.h
+++ b/intern/cycles/subd/subd_patch_table.h
@@ -21,11 +21,11 @@
#include "util/util_types.h"
#ifdef WITH_OPENSUBDIV
-#ifdef _MSC_VER
-# include "iso646.h"
-#endif
+# ifdef _MSC_VER
+# include "iso646.h"
+# endif
-#include <opensubdiv/far/patchTable.h>
+# include <opensubdiv/far/patchTable.h>
#endif
CCL_NAMESPACE_BEGIN
@@ -34,7 +34,9 @@ CCL_NAMESPACE_BEGIN
using namespace OpenSubdiv;
#else
/* forward declare for when OpenSubdiv is unavailable */
-namespace Far { struct PatchTable; }
+namespace Far {
+struct PatchTable;
+}
#endif
#define PATCH_ARRAY_SIZE 4
@@ -43,20 +45,20 @@ namespace Far { struct PatchTable; }
#define PATCH_NODE_SIZE 1
struct PackedPatchTable {
- array<uint> table;
+ array<uint> table;
- size_t num_arrays;
- size_t num_indices;
- size_t num_patches;
- size_t num_nodes;
+ size_t num_arrays;
+ size_t num_indices;
+ size_t num_patches;
+ size_t num_nodes;
- /* calculated size from num_* members */
- size_t total_size();
+ /* calculated size from num_* members */
+ size_t total_size();
- void pack(Far::PatchTable* patch_table, int offset = 0);
- void copy_adjusting_offsets(uint* dest, int doffset);
+ void pack(Far::PatchTable *patch_table, int offset = 0);
+ void copy_adjusting_offsets(uint *dest, int doffset);
};
CCL_NAMESPACE_END
-#endif /* __SUBD_PATCH_TABLE_H__ */
+#endif /* __SUBD_PATCH_TABLE_H__ */
diff --git a/intern/cycles/subd/subd_split.cpp b/intern/cycles/subd/subd_split.cpp
index 76261243359..803363bc240 100644
--- a/intern/cycles/subd/subd_split.cpp
+++ b/intern/cycles/subd/subd_split.cpp
@@ -28,233 +28,230 @@ CCL_NAMESPACE_BEGIN
/* DiagSplit */
-DiagSplit::DiagSplit(const SubdParams& params_)
-: params(params_)
+DiagSplit::DiagSplit(const SubdParams &params_) : params(params_)
{
}
-void DiagSplit::dispatch(QuadDice::SubPatch& sub, QuadDice::EdgeFactors& ef)
+void DiagSplit::dispatch(QuadDice::SubPatch &sub, QuadDice::EdgeFactors &ef)
{
- subpatches_quad.push_back(sub);
- edgefactors_quad.push_back(ef);
+ subpatches_quad.push_back(sub);
+ edgefactors_quad.push_back(ef);
}
float3 DiagSplit::to_world(Patch *patch, float2 uv)
{
- float3 P;
+ float3 P;
- patch->eval(&P, NULL, NULL, NULL, uv.x, uv.y);
- if(params.camera)
- P = transform_point(&params.objecttoworld, P);
+ patch->eval(&P, NULL, NULL, NULL, uv.x, uv.y);
+ if (params.camera)
+ P = transform_point(&params.objecttoworld, P);
- return P;
+ return P;
}
int DiagSplit::T(Patch *patch, float2 Pstart, float2 Pend)
{
- float3 Plast = make_float3(0.0f, 0.0f, 0.0f);
- float Lsum = 0.0f;
- float Lmax = 0.0f;
+ float3 Plast = make_float3(0.0f, 0.0f, 0.0f);
+ float Lsum = 0.0f;
+ float Lmax = 0.0f;
- for(int i = 0; i < params.test_steps; i++) {
- float t = i/(float)(params.test_steps-1);
+ for (int i = 0; i < params.test_steps; i++) {
+ float t = i / (float)(params.test_steps - 1);
- float3 P = to_world(patch, Pstart + t*(Pend - Pstart));
+ float3 P = to_world(patch, Pstart + t * (Pend - Pstart));
- if(i > 0) {
- float L;
+ if (i > 0) {
+ float L;
- if(!params.camera) {
- L = len(P - Plast);
- }
- else {
- Camera* cam = params.camera;
+ if (!params.camera) {
+ L = len(P - Plast);
+ }
+ else {
+ Camera *cam = params.camera;
- float pixel_width = cam->world_to_raster_size((P + Plast) * 0.5f);
- L = len(P - Plast) / pixel_width;
- }
+ float pixel_width = cam->world_to_raster_size((P + Plast) * 0.5f);
+ L = len(P - Plast) / pixel_width;
+ }
- Lsum += L;
- Lmax = max(L, Lmax);
- }
+ Lsum += L;
+ Lmax = max(L, Lmax);
+ }
- Plast = P;
- }
+ Plast = P;
+ }
- int tmin = (int)ceil(Lsum/params.dicing_rate);
- int tmax = (int)ceil((params.test_steps-1)*Lmax/params.dicing_rate); // XXX paper says N instead of N-1, seems wrong?
+ int tmin = (int)ceil(Lsum / params.dicing_rate);
+ int tmax = (int)ceil((params.test_steps - 1) * Lmax /
+ params.dicing_rate); // XXX paper says N instead of N-1, seems wrong?
- if(tmax - tmin > params.split_threshold)
- return DSPLIT_NON_UNIFORM;
+ if (tmax - tmin > params.split_threshold)
+ return DSPLIT_NON_UNIFORM;
- return tmax;
+ return tmax;
}
-void DiagSplit::partition_edge(Patch *patch, float2 *P, int *t0, int *t1, float2 Pstart, float2 Pend, int t)
+void DiagSplit::partition_edge(
+ Patch *patch, float2 *P, int *t0, int *t1, float2 Pstart, float2 Pend, int t)
{
- if(t == DSPLIT_NON_UNIFORM) {
- *P = (Pstart + Pend)*0.5f;
- *t0 = T(patch, Pstart, *P);
- *t1 = T(patch, *P, Pend);
- }
- else {
- int I = (int)floor((float)t*0.5f);
- *P = interp(Pstart, Pend, (t == 0)? 0: I/(float)t); /* XXX is t faces or verts */
- *t0 = I;
- *t1 = t - I;
- }
+ if (t == DSPLIT_NON_UNIFORM) {
+ *P = (Pstart + Pend) * 0.5f;
+ *t0 = T(patch, Pstart, *P);
+ *t1 = T(patch, *P, Pend);
+ }
+ else {
+ int I = (int)floor((float)t * 0.5f);
+ *P = interp(Pstart, Pend, (t == 0) ? 0 : I / (float)t); /* XXX is t faces or verts */
+ *t0 = I;
+ *t1 = t - I;
+ }
}
-static void limit_edge_factors(const QuadDice::SubPatch& sub, QuadDice::EdgeFactors& ef, int max_t)
+static void limit_edge_factors(const QuadDice::SubPatch &sub, QuadDice::EdgeFactors &ef, int max_t)
{
- float2 P00 = sub.P00;
- float2 P01 = sub.P01;
- float2 P10 = sub.P10;
- float2 P11 = sub.P11;
-
- int tu0 = int(max_t * len(P10 - P00));
- int tu1 = int(max_t * len(P11 - P01));
- int tv0 = int(max_t * len(P01 - P00));
- int tv1 = int(max_t * len(P11 - P10));
-
- ef.tu0 = tu0 <= 1 ? 1 : min(ef.tu0, tu0);
- ef.tu1 = tu1 <= 1 ? 1 : min(ef.tu1, tu1);
- ef.tv0 = tv0 <= 1 ? 1 : min(ef.tv0, tv0);
- ef.tv1 = tv1 <= 1 ? 1 : min(ef.tv1, tv1);
+ float2 P00 = sub.P00;
+ float2 P01 = sub.P01;
+ float2 P10 = sub.P10;
+ float2 P11 = sub.P11;
+
+ int tu0 = int(max_t * len(P10 - P00));
+ int tu1 = int(max_t * len(P11 - P01));
+ int tv0 = int(max_t * len(P01 - P00));
+ int tv1 = int(max_t * len(P11 - P10));
+
+ ef.tu0 = tu0 <= 1 ? 1 : min(ef.tu0, tu0);
+ ef.tu1 = tu1 <= 1 ? 1 : min(ef.tu1, tu1);
+ ef.tv0 = tv0 <= 1 ? 1 : min(ef.tv0, tv0);
+ ef.tv1 = tv1 <= 1 ? 1 : min(ef.tv1, tv1);
}
-void DiagSplit::split(QuadDice::SubPatch& sub, QuadDice::EdgeFactors& ef, int depth)
+void DiagSplit::split(QuadDice::SubPatch &sub, QuadDice::EdgeFactors &ef, int depth)
{
- if(depth > 32) {
- /* We should never get here, but just in case end recursion safely. */
- ef.tu0 = 1;
- ef.tu1 = 1;
- ef.tv0 = 1;
- ef.tv1 = 1;
+ if (depth > 32) {
+ /* We should never get here, but just in case end recursion safely. */
+ ef.tu0 = 1;
+ ef.tu1 = 1;
+ ef.tv0 = 1;
+ ef.tv1 = 1;
- dispatch(sub, ef);
- return;
- }
+ dispatch(sub, ef);
+ return;
+ }
- bool split_u = (ef.tu0 == DSPLIT_NON_UNIFORM || ef.tu1 == DSPLIT_NON_UNIFORM);
- bool split_v = (ef.tv0 == DSPLIT_NON_UNIFORM || ef.tv1 == DSPLIT_NON_UNIFORM);
+ bool split_u = (ef.tu0 == DSPLIT_NON_UNIFORM || ef.tu1 == DSPLIT_NON_UNIFORM);
+ bool split_v = (ef.tv0 == DSPLIT_NON_UNIFORM || ef.tv1 == DSPLIT_NON_UNIFORM);
- /* Split subpatches such that the ratio of T for opposite edges doesn't
+ /* Split subpatches such that the ratio of T for opposite edges doesn't
* exceed 1.5, this reduces over tessellation for some patches
- */
- bool tmp_split_v = split_v;
- if(!split_u && min(ef.tu0, ef.tu1) > 8 && min(ef.tu0, ef.tu1)*1.5f < max(ef.tu0, ef.tu1))
- split_v = true;
- if(!tmp_split_v && min(ef.tu0, ef.tu1) > 8 && min(ef.tv0, ef.tv1)*1.5f < max(ef.tv0, ef.tv1))
- split_u = true;
-
- /* alternate axis */
- if(split_u && split_v) {
- split_u = depth % 2;
- }
-
- if(split_u) {
- /* partition edges */
- QuadDice::EdgeFactors ef0, ef1;
- float2 Pu0, Pu1;
-
- partition_edge(sub.patch,
- &Pu0, &ef0.tu0, &ef1.tu0, sub.P00, sub.P10, ef.tu0);
- partition_edge(sub.patch,
- &Pu1, &ef0.tu1, &ef1.tu1, sub.P01, sub.P11, ef.tu1);
-
- /* split */
- int tsplit = T(sub.patch, Pu0, Pu1);
- ef0.tv0 = ef.tv0;
- ef0.tv1 = tsplit;
-
- ef1.tv0 = tsplit;
- ef1.tv1 = ef.tv1;
-
- /* create subpatches */
- QuadDice::SubPatch sub0 = {sub.patch, sub.P00, Pu0, sub.P01, Pu1};
- QuadDice::SubPatch sub1 = {sub.patch, Pu0, sub.P10, Pu1, sub.P11};
-
- limit_edge_factors(sub0, ef0, 1 << params.max_level);
- limit_edge_factors(sub1, ef1, 1 << params.max_level);
-
- split(sub0, ef0, depth+1);
- split(sub1, ef1, depth+1);
- }
- else if(split_v) {
- /* partition edges */
- QuadDice::EdgeFactors ef0, ef1;
- float2 Pv0, Pv1;
-
- partition_edge(sub.patch,
- &Pv0, &ef0.tv0, &ef1.tv0, sub.P00, sub.P01, ef.tv0);
- partition_edge(sub.patch,
- &Pv1, &ef0.tv1, &ef1.tv1, sub.P10, sub.P11, ef.tv1);
-
- /* split */
- int tsplit = T(sub.patch, Pv0, Pv1);
- ef0.tu0 = ef.tu0;
- ef0.tu1 = tsplit;
-
- ef1.tu0 = tsplit;
- ef1.tu1 = ef.tu1;
-
- /* create subpatches */
- QuadDice::SubPatch sub0 = {sub.patch, sub.P00, sub.P10, Pv0, Pv1};
- QuadDice::SubPatch sub1 = {sub.patch, Pv0, Pv1, sub.P01, sub.P11};
-
- limit_edge_factors(sub0, ef0, 1 << params.max_level);
- limit_edge_factors(sub1, ef1, 1 << params.max_level);
-
- split(sub0, ef0, depth+1);
- split(sub1, ef1, depth+1);
- }
- else {
- dispatch(sub, ef);
- }
+ */
+ bool tmp_split_v = split_v;
+ if (!split_u && min(ef.tu0, ef.tu1) > 8 && min(ef.tu0, ef.tu1) * 1.5f < max(ef.tu0, ef.tu1))
+ split_v = true;
+ if (!tmp_split_v && min(ef.tu0, ef.tu1) > 8 && min(ef.tv0, ef.tv1) * 1.5f < max(ef.tv0, ef.tv1))
+ split_u = true;
+
+ /* alternate axis */
+ if (split_u && split_v) {
+ split_u = depth % 2;
+ }
+
+ if (split_u) {
+ /* partition edges */
+ QuadDice::EdgeFactors ef0, ef1;
+ float2 Pu0, Pu1;
+
+ partition_edge(sub.patch, &Pu0, &ef0.tu0, &ef1.tu0, sub.P00, sub.P10, ef.tu0);
+ partition_edge(sub.patch, &Pu1, &ef0.tu1, &ef1.tu1, sub.P01, sub.P11, ef.tu1);
+
+ /* split */
+ int tsplit = T(sub.patch, Pu0, Pu1);
+ ef0.tv0 = ef.tv0;
+ ef0.tv1 = tsplit;
+
+ ef1.tv0 = tsplit;
+ ef1.tv1 = ef.tv1;
+
+ /* create subpatches */
+ QuadDice::SubPatch sub0 = {sub.patch, sub.P00, Pu0, sub.P01, Pu1};
+ QuadDice::SubPatch sub1 = {sub.patch, Pu0, sub.P10, Pu1, sub.P11};
+
+ limit_edge_factors(sub0, ef0, 1 << params.max_level);
+ limit_edge_factors(sub1, ef1, 1 << params.max_level);
+
+ split(sub0, ef0, depth + 1);
+ split(sub1, ef1, depth + 1);
+ }
+ else if (split_v) {
+ /* partition edges */
+ QuadDice::EdgeFactors ef0, ef1;
+ float2 Pv0, Pv1;
+
+ partition_edge(sub.patch, &Pv0, &ef0.tv0, &ef1.tv0, sub.P00, sub.P01, ef.tv0);
+ partition_edge(sub.patch, &Pv1, &ef0.tv1, &ef1.tv1, sub.P10, sub.P11, ef.tv1);
+
+ /* split */
+ int tsplit = T(sub.patch, Pv0, Pv1);
+ ef0.tu0 = ef.tu0;
+ ef0.tu1 = tsplit;
+
+ ef1.tu0 = tsplit;
+ ef1.tu1 = ef.tu1;
+
+ /* create subpatches */
+ QuadDice::SubPatch sub0 = {sub.patch, sub.P00, sub.P10, Pv0, Pv1};
+ QuadDice::SubPatch sub1 = {sub.patch, Pv0, Pv1, sub.P01, sub.P11};
+
+ limit_edge_factors(sub0, ef0, 1 << params.max_level);
+ limit_edge_factors(sub1, ef1, 1 << params.max_level);
+
+ split(sub0, ef0, depth + 1);
+ split(sub1, ef1, depth + 1);
+ }
+ else {
+ dispatch(sub, ef);
+ }
}
void DiagSplit::split_quad(Patch *patch, QuadDice::SubPatch *subpatch)
{
- QuadDice::SubPatch sub_split;
- QuadDice::EdgeFactors ef_split;
+ QuadDice::SubPatch sub_split;
+ QuadDice::EdgeFactors ef_split;
- if(subpatch) {
- sub_split = *subpatch;
- }
- else {
- sub_split.patch = patch;
- sub_split.P00 = make_float2(0.0f, 0.0f);
- sub_split.P10 = make_float2(1.0f, 0.0f);
- sub_split.P01 = make_float2(0.0f, 1.0f);
- sub_split.P11 = make_float2(1.0f, 1.0f);
- }
+ if (subpatch) {
+ sub_split = *subpatch;
+ }
+ else {
+ sub_split.patch = patch;
+ sub_split.P00 = make_float2(0.0f, 0.0f);
+ sub_split.P10 = make_float2(1.0f, 0.0f);
+ sub_split.P01 = make_float2(0.0f, 1.0f);
+ sub_split.P11 = make_float2(1.0f, 1.0f);
+ }
- ef_split.tu0 = T(patch, sub_split.P00, sub_split.P10);
- ef_split.tu1 = T(patch, sub_split.P01, sub_split.P11);
- ef_split.tv0 = T(patch, sub_split.P00, sub_split.P01);
- ef_split.tv1 = T(patch, sub_split.P10, sub_split.P11);
+ ef_split.tu0 = T(patch, sub_split.P00, sub_split.P10);
+ ef_split.tu1 = T(patch, sub_split.P01, sub_split.P11);
+ ef_split.tv0 = T(patch, sub_split.P00, sub_split.P01);
+ ef_split.tv1 = T(patch, sub_split.P10, sub_split.P11);
- limit_edge_factors(sub_split, ef_split, 1 << params.max_level);
+ limit_edge_factors(sub_split, ef_split, 1 << params.max_level);
- split(sub_split, ef_split);
+ split(sub_split, ef_split);
- QuadDice dice(params);
+ QuadDice dice(params);
- for(size_t i = 0; i < subpatches_quad.size(); i++) {
- QuadDice::SubPatch& sub = subpatches_quad[i];
- QuadDice::EdgeFactors& ef = edgefactors_quad[i];
+ for (size_t i = 0; i < subpatches_quad.size(); i++) {
+ QuadDice::SubPatch &sub = subpatches_quad[i];
+ QuadDice::EdgeFactors &ef = edgefactors_quad[i];
- ef.tu0 = max(ef.tu0, 1);
- ef.tu1 = max(ef.tu1, 1);
- ef.tv0 = max(ef.tv0, 1);
- ef.tv1 = max(ef.tv1, 1);
+ ef.tu0 = max(ef.tu0, 1);
+ ef.tu1 = max(ef.tu1, 1);
+ ef.tv0 = max(ef.tv0, 1);
+ ef.tv1 = max(ef.tv1, 1);
- dice.dice(sub, ef);
- }
+ dice.dice(sub, ef);
+ }
- subpatches_quad.clear();
- edgefactors_quad.clear();
+ subpatches_quad.clear();
+ edgefactors_quad.clear();
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/subd/subd_split.h b/intern/cycles/subd/subd_split.h
index 3368c93944b..6e68d8ee598 100644
--- a/intern/cycles/subd/subd_split.h
+++ b/intern/cycles/subd/subd_split.h
@@ -35,25 +35,25 @@ class Patch;
#define DSPLIT_NON_UNIFORM -1
class DiagSplit {
-public:
- vector<QuadDice::SubPatch> subpatches_quad;
- vector<QuadDice::EdgeFactors> edgefactors_quad;
+ public:
+ vector<QuadDice::SubPatch> subpatches_quad;
+ vector<QuadDice::EdgeFactors> edgefactors_quad;
- SubdParams params;
+ SubdParams params;
- explicit DiagSplit(const SubdParams& params);
+ explicit DiagSplit(const SubdParams &params);
- float3 to_world(Patch *patch, float2 uv);
- int T(Patch *patch, float2 Pstart, float2 Pend);
- void partition_edge(Patch *patch, float2 *P, int *t0, int *t1,
- float2 Pstart, float2 Pend, int t);
+ float3 to_world(Patch *patch, float2 uv);
+ int T(Patch *patch, float2 Pstart, float2 Pend);
+ void partition_edge(
+ Patch *patch, float2 *P, int *t0, int *t1, float2 Pstart, float2 Pend, int t);
- void dispatch(QuadDice::SubPatch& sub, QuadDice::EdgeFactors& ef);
- void split(QuadDice::SubPatch& sub, QuadDice::EdgeFactors& ef, int depth=0);
+ void dispatch(QuadDice::SubPatch &sub, QuadDice::EdgeFactors &ef);
+ void split(QuadDice::SubPatch &sub, QuadDice::EdgeFactors &ef, int depth = 0);
- void split_quad(Patch *patch, QuadDice::SubPatch *subpatch=NULL);
+ void split_quad(Patch *patch, QuadDice::SubPatch *subpatch = NULL);
};
CCL_NAMESPACE_END
-#endif /* __SUBD_SPLIT_H__ */
+#endif /* __SUBD_SPLIT_H__ */
diff --git a/intern/cycles/test/CMakeLists.txt b/intern/cycles/test/CMakeLists.txt
index 73fe590f8ae..98fcc8cd15e 100644
--- a/intern/cycles/test/CMakeLists.txt
+++ b/intern/cycles/test/CMakeLists.txt
@@ -1,87 +1,87 @@
if(WITH_GTESTS)
- Include(GTestTesting)
+ Include(GTestTesting)
- # Otherwise we get warnings here that we cant fix in external projects
- remove_strict_flags()
+ # Otherwise we get warnings here that we cant fix in external projects
+ remove_strict_flags()
endif()
macro(CYCLES_TEST SRC EXTRA_LIBS)
- if(WITH_GTESTS)
- BLENDER_SRC_GTEST("cycles_${SRC}" "${SRC}_test.cpp" "${EXTRA_LIBS}")
- endif()
+ if(WITH_GTESTS)
+ BLENDER_SRC_GTEST("cycles_${SRC}" "${SRC}_test.cpp" "${EXTRA_LIBS}")
+ endif()
endmacro()
set(INC
- .
- ..
- ../device
- ../graph
- ../kernel
- ../render
- ../util
+ .
+ ..
+ ../device
+ ../graph
+ ../kernel
+ ../render
+ ../util
)
set(ALL_CYCLES_LIBRARIES
- cycles_device
- cycles_kernel
- cycles_render
- cycles_bvh
- cycles_graph
- cycles_subd
- cycles_util
- extern_clew
- ${BLENDER_GL_LIBRARIES}
- ${BLENDER_GLEW_LIBRARIES}
- ${CYCLES_APP_GLEW_LIBRARY}
- ${OPENIMAGEIO_LIBRARIES}
+ cycles_device
+ cycles_kernel
+ cycles_render
+ cycles_bvh
+ cycles_graph
+ cycles_subd
+ cycles_util
+ extern_clew
+ ${BLENDER_GL_LIBRARIES}
+ ${BLENDER_GLEW_LIBRARIES}
+ ${CYCLES_APP_GLEW_LIBRARY}
+ ${OPENIMAGEIO_LIBRARIES}
)
if(WITH_CYCLES_OSL)
- list(APPEND ALL_CYCLES_LIBRARIES
- cycles_kernel_osl
- ${OSL_LIBRARIES}
- ${LLVM_LIBRARIES}
- )
+ list(APPEND ALL_CYCLES_LIBRARIES
+ cycles_kernel_osl
+ ${OSL_LIBRARIES}
+ ${LLVM_LIBRARIES}
+ )
endif()
if(WITH_OPENCOLORIO)
- list(APPEND ALL_CYCLES_LIBRARIES
- ${OPENCOLORIO_LIBRARIES}
- )
+ list(APPEND ALL_CYCLES_LIBRARIES
+ ${OPENCOLORIO_LIBRARIES}
+ )
endif()
if(WITH_IMAGE_OPENJPEG)
- list(APPEND ALL_CYCLES_LIBRARIES ${OPENJPEG_LIBRARIES})
+ list(APPEND ALL_CYCLES_LIBRARIES ${OPENJPEG_LIBRARIES})
endif()
if(WITH_OPENSUBDIV)
- add_definitions(-DWITH_OPENSUBDIV)
- include_directories(
- SYSTEM
- ${OPENSUBDIV_INCLUDE_DIR}
- )
- list(APPEND ALL_CYCLES_LIBRARIES
- ${OPENSUBDIV_LIBRARIES}
- )
+ add_definitions(-DWITH_OPENSUBDIV)
+ include_directories(
+ SYSTEM
+ ${OPENSUBDIV_INCLUDE_DIR}
+ )
+ list(APPEND ALL_CYCLES_LIBRARIES
+ ${OPENSUBDIV_LIBRARIES}
+ )
endif()
if(WITH_CYCLES_EMBREE)
- list(APPEND ALL_CYCLES_LIBRARIES
- ${EMBREE_LIBRARIES}
- )
+ list(APPEND ALL_CYCLES_LIBRARIES
+ ${EMBREE_LIBRARIES}
+ )
endif()
if(WITH_CUDA_DYNLOAD)
- list(APPEND ALL_CYCLES_LIBRARIES extern_cuew)
+ list(APPEND ALL_CYCLES_LIBRARIES extern_cuew)
else()
- list(APPEND ALL_CYCLES_LIBRARIES ${CUDA_CUDA_LIBRARY})
+ list(APPEND ALL_CYCLES_LIBRARIES ${CUDA_CUDA_LIBRARY})
endif()
if(NOT CYCLES_STANDALONE_REPOSITORY)
- list(APPEND ALL_CYCLES_LIBRARIES bf_intern_glew_mx bf_intern_guardedalloc ${GLEW_LIBRARY})
+ list(APPEND ALL_CYCLES_LIBRARIES bf_intern_glew_mx bf_intern_guardedalloc ${GLEW_LIBRARY})
endif()
list(APPEND ALL_CYCLES_LIBRARIES
- ${BOOST_LIBRARIES}
- ${PNG_LIBRARIES}
- ${JPEG_LIBRARIES}
- ${ZLIB_LIBRARIES}
- ${TIFF_LIBRARY}
- ${OPENIMAGEIO_LIBRARIES}
- ${OPENEXR_LIBRARIES}
+ ${BOOST_LIBRARIES}
+ ${PNG_LIBRARIES}
+ ${JPEG_LIBRARIES}
+ ${ZLIB_LIBRARIES}
+ ${TIFF_LIBRARY}
+ ${OPENIMAGEIO_LIBRARIES}
+ ${OPENEXR_LIBRARIES}
)
include_directories(${INC})
diff --git a/intern/cycles/test/render_graph_finalize_test.cpp b/intern/cycles/test/render_graph_finalize_test.cpp
index 5f60411758d..7fb92bfb862 100644
--- a/intern/cycles/test/render_graph_finalize_test.cpp
+++ b/intern/cycles/test/render_graph_finalize_test.cpp
@@ -25,214 +25,199 @@
#include "util/util_string.h"
#include "util/util_vector.h"
+using testing::_;
using testing::AnyNumber;
using testing::HasSubstr;
using testing::ScopedMockLog;
-using testing::_;
CCL_NAMESPACE_BEGIN
namespace {
-template<typename T>
-class ShaderNodeBuilder {
-public:
- ShaderNodeBuilder(const string& name)
- : name_(name)
- {
- node_ = new T();
- node_->name = name;
- }
-
- const string& name() const {
- return name_;
- }
-
- ShaderNode *node() const {
- return node_;
- }
-
- template<typename V>
- ShaderNodeBuilder& set(const string& input_name, V value)
- {
- ShaderInput *input_socket = node_->input(input_name.c_str());
- EXPECT_NE((void*)NULL, input_socket);
- input_socket->set(value);
- return *this;
- }
-
- template<typename T2, typename V>
- ShaderNodeBuilder& set(V T2::*pfield, V value)
- {
- static_cast<T*>(node_)->*pfield = value;
- return *this;
- }
-
-protected:
- string name_;
- ShaderNode *node_;
+template<typename T> class ShaderNodeBuilder {
+ public:
+ ShaderNodeBuilder(const string &name) : name_(name)
+ {
+ node_ = new T();
+ node_->name = name;
+ }
+
+ const string &name() const
+ {
+ return name_;
+ }
+
+ ShaderNode *node() const
+ {
+ return node_;
+ }
+
+ template<typename V> ShaderNodeBuilder &set(const string &input_name, V value)
+ {
+ ShaderInput *input_socket = node_->input(input_name.c_str());
+ EXPECT_NE((void *)NULL, input_socket);
+ input_socket->set(value);
+ return *this;
+ }
+
+ template<typename T2, typename V> ShaderNodeBuilder &set(V T2::*pfield, V value)
+ {
+ static_cast<T *>(node_)->*pfield = value;
+ return *this;
+ }
+
+ protected:
+ string name_;
+ ShaderNode *node_;
};
class ShaderGraphBuilder {
-public:
- ShaderGraphBuilder(ShaderGraph *graph)
- : graph_(graph)
- {
- node_map_["Output"] = graph->output();
- }
-
- ShaderNode *find_node(const string& name)
- {
- map<string, ShaderNode *>::iterator it = node_map_.find(name);
- if(it == node_map_.end()) {
- return NULL;
- }
- return it->second;
- }
-
- template<typename T>
- ShaderGraphBuilder& add_node(const T& node)
- {
- EXPECT_EQ(find_node(node.name()), (void*)NULL);
- graph_->add(node.node());
- node_map_[node.name()] = node.node();
- return *this;
- }
-
- ShaderGraphBuilder& add_connection(const string& from,
- const string& to)
- {
- vector<string> tokens_from, tokens_to;
- string_split(tokens_from, from, "::");
- string_split(tokens_to, to, "::");
- EXPECT_EQ(tokens_from.size(), 2);
- EXPECT_EQ(tokens_to.size(), 2);
- ShaderNode *node_from = find_node(tokens_from[0]),
- *node_to = find_node(tokens_to[0]);
- EXPECT_NE((void*)NULL, node_from);
- EXPECT_NE((void*)NULL, node_to);
- EXPECT_NE(node_from, node_to);
- ShaderOutput *socket_from = node_from->output(tokens_from[1].c_str());
- ShaderInput *socket_to = node_to->input(tokens_to[1].c_str());
- EXPECT_NE((void*)NULL, socket_from);
- EXPECT_NE((void*)NULL, socket_to);
- graph_->connect(socket_from, socket_to);
- return *this;
- }
-
- /* Common input/output boilerplate. */
- ShaderGraphBuilder& add_attribute(const string &name)
- {
- return (*this)
- .add_node(ShaderNodeBuilder<AttributeNode>(name)
- .set(&AttributeNode::attribute, ustring(name)));
- }
-
- ShaderGraphBuilder& output_closure(const string& from)
- {
- return (*this).add_connection(from, "Output::Surface");
- }
-
- ShaderGraphBuilder& output_color(const string& from)
- {
- return (*this)
- .add_node(ShaderNodeBuilder<EmissionNode>("EmissionNode"))
- .add_connection(from, "EmissionNode::Color")
- .output_closure("EmissionNode::Emission");
- }
-
- ShaderGraphBuilder& output_value(const string& from)
- {
- return (*this)
- .add_node(ShaderNodeBuilder<EmissionNode>("EmissionNode"))
- .add_connection(from, "EmissionNode::Strength")
- .output_closure("EmissionNode::Emission");
- }
-
-protected:
- ShaderGraph *graph_;
- map<string, ShaderNode *> node_map_;
+ public:
+ ShaderGraphBuilder(ShaderGraph *graph) : graph_(graph)
+ {
+ node_map_["Output"] = graph->output();
+ }
+
+ ShaderNode *find_node(const string &name)
+ {
+ map<string, ShaderNode *>::iterator it = node_map_.find(name);
+ if (it == node_map_.end()) {
+ return NULL;
+ }
+ return it->second;
+ }
+
+ template<typename T> ShaderGraphBuilder &add_node(const T &node)
+ {
+ EXPECT_EQ(find_node(node.name()), (void *)NULL);
+ graph_->add(node.node());
+ node_map_[node.name()] = node.node();
+ return *this;
+ }
+
+ ShaderGraphBuilder &add_connection(const string &from, const string &to)
+ {
+ vector<string> tokens_from, tokens_to;
+ string_split(tokens_from, from, "::");
+ string_split(tokens_to, to, "::");
+ EXPECT_EQ(tokens_from.size(), 2);
+ EXPECT_EQ(tokens_to.size(), 2);
+ ShaderNode *node_from = find_node(tokens_from[0]), *node_to = find_node(tokens_to[0]);
+ EXPECT_NE((void *)NULL, node_from);
+ EXPECT_NE((void *)NULL, node_to);
+ EXPECT_NE(node_from, node_to);
+ ShaderOutput *socket_from = node_from->output(tokens_from[1].c_str());
+ ShaderInput *socket_to = node_to->input(tokens_to[1].c_str());
+ EXPECT_NE((void *)NULL, socket_from);
+ EXPECT_NE((void *)NULL, socket_to);
+ graph_->connect(socket_from, socket_to);
+ return *this;
+ }
+
+ /* Common input/output boilerplate. */
+ ShaderGraphBuilder &add_attribute(const string &name)
+ {
+ return (*this).add_node(
+ ShaderNodeBuilder<AttributeNode>(name).set(&AttributeNode::attribute, ustring(name)));
+ }
+
+ ShaderGraphBuilder &output_closure(const string &from)
+ {
+ return (*this).add_connection(from, "Output::Surface");
+ }
+
+ ShaderGraphBuilder &output_color(const string &from)
+ {
+ return (*this)
+ .add_node(ShaderNodeBuilder<EmissionNode>("EmissionNode"))
+ .add_connection(from, "EmissionNode::Color")
+ .output_closure("EmissionNode::Emission");
+ }
+
+ ShaderGraphBuilder &output_value(const string &from)
+ {
+ return (*this)
+ .add_node(ShaderNodeBuilder<EmissionNode>("EmissionNode"))
+ .add_connection(from, "EmissionNode::Strength")
+ .output_closure("EmissionNode::Emission");
+ }
+
+ protected:
+ ShaderGraph *graph_;
+ map<string, ShaderNode *> node_map_;
};
} // namespace
-class RenderGraph : public testing::Test
-{
-protected:
- ScopedMockLog log;
- Stats stats;
- Profiler profiler;
- DeviceInfo device_info;
- Device *device_cpu;
- SceneParams scene_params;
- Scene *scene;
- ShaderGraph graph;
- ShaderGraphBuilder builder;
-
- RenderGraph()
- : testing::Test(),
- builder(&graph)
- {
- }
-
- virtual void SetUp()
- {
- util_logging_start();
- util_logging_verbosity_set(1);
-
- device_cpu = Device::create(device_info, stats, profiler, true);
- scene = new Scene(scene_params, device_cpu);
- }
-
- virtual void TearDown()
- {
- delete scene;
- delete device_cpu;
- }
+class RenderGraph : public testing::Test {
+ protected:
+ ScopedMockLog log;
+ Stats stats;
+ Profiler profiler;
+ DeviceInfo device_info;
+ Device *device_cpu;
+ SceneParams scene_params;
+ Scene *scene;
+ ShaderGraph graph;
+ ShaderGraphBuilder builder;
+
+ RenderGraph() : testing::Test(), builder(&graph)
+ {
+ }
+
+ virtual void SetUp()
+ {
+ util_logging_start();
+ util_logging_verbosity_set(1);
+
+ device_cpu = Device::create(device_info, stats, profiler, true);
+ scene = new Scene(scene_params, device_cpu);
+ }
+
+ virtual void TearDown()
+ {
+ delete scene;
+ delete device_cpu;
+ }
};
-#define EXPECT_ANY_MESSAGE(log) \
- EXPECT_CALL(log, Log(_, _, _)).Times(AnyNumber()); \
+#define EXPECT_ANY_MESSAGE(log) EXPECT_CALL(log, Log(_, _, _)).Times(AnyNumber());
#define CORRECT_INFO_MESSAGE(log, message) \
- EXPECT_CALL(log, Log(google::INFO, _, HasSubstr(message)));
+ EXPECT_CALL(log, Log(google::INFO, _, HasSubstr(message)));
#define INVALID_INFO_MESSAGE(log, message) \
- EXPECT_CALL(log, Log(google::INFO, _, HasSubstr(message))).Times(0);
+ EXPECT_CALL(log, Log(google::INFO, _, HasSubstr(message))).Times(0);
/*
* Test deduplication of nodes that have inputs, some of them folded.
*/
TEST_F(RenderGraph, deduplicate_deep)
{
- EXPECT_ANY_MESSAGE(log);
- CORRECT_INFO_MESSAGE(log, "Folding Value1::Value to constant (0.8).");
- CORRECT_INFO_MESSAGE(log, "Folding Value2::Value to constant (0.8).");
- CORRECT_INFO_MESSAGE(log, "Deduplicated 2 nodes.");
-
- builder
- .add_node(ShaderNodeBuilder<GeometryNode>("Geometry1"))
- .add_node(ShaderNodeBuilder<GeometryNode>("Geometry2"))
- .add_node(ShaderNodeBuilder<ValueNode>("Value1")
- .set(&ValueNode::value, 0.8f))
- .add_node(ShaderNodeBuilder<ValueNode>("Value2")
- .set(&ValueNode::value, 0.8f))
- .add_node(ShaderNodeBuilder<NoiseTextureNode>("Noise1"))
- .add_node(ShaderNodeBuilder<NoiseTextureNode>("Noise2"))
- .add_node(ShaderNodeBuilder<MixNode>("Mix")
- .set(&MixNode::type, NODE_MIX_BLEND)
- .set("Fac", 0.5f))
- .add_connection("Geometry1::Parametric", "Noise1::Vector")
- .add_connection("Value1::Value", "Noise1::Scale")
- .add_connection("Noise1::Color", "Mix::Color1")
- .add_connection("Geometry2::Parametric", "Noise2::Vector")
- .add_connection("Value2::Value", "Noise2::Scale")
- .add_connection("Noise2::Color", "Mix::Color2")
- .output_color("Mix::Color");
-
- graph.finalize(scene);
-
- EXPECT_EQ(graph.nodes.size(), 5);
+ EXPECT_ANY_MESSAGE(log);
+ CORRECT_INFO_MESSAGE(log, "Folding Value1::Value to constant (0.8).");
+ CORRECT_INFO_MESSAGE(log, "Folding Value2::Value to constant (0.8).");
+ CORRECT_INFO_MESSAGE(log, "Deduplicated 2 nodes.");
+
+ builder.add_node(ShaderNodeBuilder<GeometryNode>("Geometry1"))
+ .add_node(ShaderNodeBuilder<GeometryNode>("Geometry2"))
+ .add_node(ShaderNodeBuilder<ValueNode>("Value1").set(&ValueNode::value, 0.8f))
+ .add_node(ShaderNodeBuilder<ValueNode>("Value2").set(&ValueNode::value, 0.8f))
+ .add_node(ShaderNodeBuilder<NoiseTextureNode>("Noise1"))
+ .add_node(ShaderNodeBuilder<NoiseTextureNode>("Noise2"))
+ .add_node(
+ ShaderNodeBuilder<MixNode>("Mix").set(&MixNode::type, NODE_MIX_BLEND).set("Fac", 0.5f))
+ .add_connection("Geometry1::Parametric", "Noise1::Vector")
+ .add_connection("Value1::Value", "Noise1::Scale")
+ .add_connection("Noise1::Color", "Mix::Color1")
+ .add_connection("Geometry2::Parametric", "Noise2::Vector")
+ .add_connection("Value2::Value", "Noise2::Scale")
+ .add_connection("Noise2::Color", "Mix::Color2")
+ .output_color("Mix::Color");
+
+ graph.finalize(scene);
+
+ EXPECT_EQ(graph.nodes.size(), 5);
}
/*
@@ -240,16 +225,17 @@ TEST_F(RenderGraph, deduplicate_deep)
*/
TEST_F(RenderGraph, constant_fold_rgb_to_bw)
{
- EXPECT_ANY_MESSAGE(log);
- CORRECT_INFO_MESSAGE(log, "Folding RGBToBWNodeNode::Val to constant (0.8).");
- CORRECT_INFO_MESSAGE(log, "Folding convert_float_to_color::value_color to constant (0.8, 0.8, 0.8).");
+ EXPECT_ANY_MESSAGE(log);
+ CORRECT_INFO_MESSAGE(log, "Folding RGBToBWNodeNode::Val to constant (0.8).");
+ CORRECT_INFO_MESSAGE(log,
+ "Folding convert_float_to_color::value_color to constant (0.8, 0.8, 0.8).");
- builder
- .add_node(ShaderNodeBuilder<RGBToBWNode>("RGBToBWNodeNode")
- .set("Color", make_float3(0.8f, 0.8f, 0.8f)))
- .output_color("RGBToBWNodeNode::Val");
+ builder
+ .add_node(ShaderNodeBuilder<RGBToBWNode>("RGBToBWNodeNode")
+ .set("Color", make_float3(0.8f, 0.8f, 0.8f)))
+ .output_color("RGBToBWNodeNode::Val");
- graph.finalize(scene);
+ graph.finalize(scene);
}
/*
@@ -258,28 +244,26 @@ TEST_F(RenderGraph, constant_fold_rgb_to_bw)
*/
TEST_F(RenderGraph, constant_fold_emission1)
{
- EXPECT_ANY_MESSAGE(log);
- CORRECT_INFO_MESSAGE(log, "Discarding closure Emission.");
+ EXPECT_ANY_MESSAGE(log);
+ CORRECT_INFO_MESSAGE(log, "Discarding closure Emission.");
- builder
- .add_node(ShaderNodeBuilder<EmissionNode>("Emission")
- .set("Color", make_float3(0.0f, 0.0f, 0.0f)))
- .output_closure("Emission::Emission");
+ builder
+ .add_node(
+ ShaderNodeBuilder<EmissionNode>("Emission").set("Color", make_float3(0.0f, 0.0f, 0.0f)))
+ .output_closure("Emission::Emission");
- graph.finalize(scene);
+ graph.finalize(scene);
}
TEST_F(RenderGraph, constant_fold_emission2)
{
- EXPECT_ANY_MESSAGE(log);
- CORRECT_INFO_MESSAGE(log, "Discarding closure Emission.");
+ EXPECT_ANY_MESSAGE(log);
+ CORRECT_INFO_MESSAGE(log, "Discarding closure Emission.");
- builder
- .add_node(ShaderNodeBuilder<EmissionNode>("Emission")
- .set("Strength", 0.0f))
- .output_closure("Emission::Emission");
+ builder.add_node(ShaderNodeBuilder<EmissionNode>("Emission").set("Strength", 0.0f))
+ .output_closure("Emission::Emission");
- graph.finalize(scene);
+ graph.finalize(scene);
}
/*
@@ -288,28 +272,26 @@ TEST_F(RenderGraph, constant_fold_emission2)
*/
TEST_F(RenderGraph, constant_fold_background1)
{
- EXPECT_ANY_MESSAGE(log);
- CORRECT_INFO_MESSAGE(log, "Discarding closure Background.");
+ EXPECT_ANY_MESSAGE(log);
+ CORRECT_INFO_MESSAGE(log, "Discarding closure Background.");
- builder
- .add_node(ShaderNodeBuilder<BackgroundNode>("Background")
- .set("Color", make_float3(0.0f, 0.0f, 0.0f)))
- .output_closure("Background::Background");
+ builder
+ .add_node(ShaderNodeBuilder<BackgroundNode>("Background")
+ .set("Color", make_float3(0.0f, 0.0f, 0.0f)))
+ .output_closure("Background::Background");
- graph.finalize(scene);
+ graph.finalize(scene);
}
TEST_F(RenderGraph, constant_fold_background2)
{
- EXPECT_ANY_MESSAGE(log);
- CORRECT_INFO_MESSAGE(log, "Discarding closure Background.");
+ EXPECT_ANY_MESSAGE(log);
+ CORRECT_INFO_MESSAGE(log, "Discarding closure Background.");
- builder
- .add_node(ShaderNodeBuilder<BackgroundNode>("Background")
- .set("Strength", 0.0f))
- .output_closure("Background::Background");
+ builder.add_node(ShaderNodeBuilder<BackgroundNode>("Background").set("Strength", 0.0f))
+ .output_closure("Background::Background");
- graph.finalize(scene);
+ graph.finalize(scene);
}
/*
@@ -318,23 +300,22 @@ TEST_F(RenderGraph, constant_fold_background2)
*/
TEST_F(RenderGraph, constant_fold_shader_add)
{
- EXPECT_ANY_MESSAGE(log);
- CORRECT_INFO_MESSAGE(log, "Folding AddClosure1::Closure to socket Diffuse::BSDF.");
- CORRECT_INFO_MESSAGE(log, "Folding AddClosure2::Closure to socket Diffuse::BSDF.");
- INVALID_INFO_MESSAGE(log, "Folding AddClosure3");
+ EXPECT_ANY_MESSAGE(log);
+ CORRECT_INFO_MESSAGE(log, "Folding AddClosure1::Closure to socket Diffuse::BSDF.");
+ CORRECT_INFO_MESSAGE(log, "Folding AddClosure2::Closure to socket Diffuse::BSDF.");
+ INVALID_INFO_MESSAGE(log, "Folding AddClosure3");
- builder
- .add_node(ShaderNodeBuilder<DiffuseBsdfNode>("Diffuse"))
- .add_node(ShaderNodeBuilder<AddClosureNode>("AddClosure1"))
- .add_node(ShaderNodeBuilder<AddClosureNode>("AddClosure2"))
- .add_node(ShaderNodeBuilder<AddClosureNode>("AddClosure3"))
- .add_connection("Diffuse::BSDF", "AddClosure1::Closure1")
- .add_connection("Diffuse::BSDF", "AddClosure2::Closure2")
- .add_connection("AddClosure1::Closure", "AddClosure3::Closure1")
- .add_connection("AddClosure2::Closure", "AddClosure3::Closure2")
- .output_closure("AddClosure3::Closure");
+ builder.add_node(ShaderNodeBuilder<DiffuseBsdfNode>("Diffuse"))
+ .add_node(ShaderNodeBuilder<AddClosureNode>("AddClosure1"))
+ .add_node(ShaderNodeBuilder<AddClosureNode>("AddClosure2"))
+ .add_node(ShaderNodeBuilder<AddClosureNode>("AddClosure3"))
+ .add_connection("Diffuse::BSDF", "AddClosure1::Closure1")
+ .add_connection("Diffuse::BSDF", "AddClosure2::Closure2")
+ .add_connection("AddClosure1::Closure", "AddClosure3::Closure1")
+ .add_connection("AddClosure2::Closure", "AddClosure3::Closure2")
+ .output_closure("AddClosure3::Closure");
- graph.finalize(scene);
+ graph.finalize(scene);
}
/*
@@ -344,30 +325,27 @@ TEST_F(RenderGraph, constant_fold_shader_add)
*/
TEST_F(RenderGraph, constant_fold_shader_mix)
{
- EXPECT_ANY_MESSAGE(log);
- CORRECT_INFO_MESSAGE(log, "Folding MixClosure1::Closure to socket Diffuse::BSDF.");
- CORRECT_INFO_MESSAGE(log, "Folding MixClosure2::Closure to socket Diffuse::BSDF.");
- CORRECT_INFO_MESSAGE(log, "Folding MixClosure3::Closure to socket Diffuse::BSDF.");
-
- builder
- .add_attribute("Attribute")
- .add_node(ShaderNodeBuilder<DiffuseBsdfNode>("Diffuse"))
- /* choose left */
- .add_node(ShaderNodeBuilder<MixClosureNode>("MixClosure1")
- .set("Fac", 0.0f))
- .add_connection("Diffuse::BSDF", "MixClosure1::Closure1")
- /* choose right */
- .add_node(ShaderNodeBuilder<MixClosureNode>("MixClosure2")
- .set("Fac", 1.0f))
- .add_connection("Diffuse::BSDF", "MixClosure2::Closure2")
- /* both inputs folded the same */
- .add_node(ShaderNodeBuilder<MixClosureNode>("MixClosure3"))
- .add_connection("Attribute::Fac", "MixClosure3::Fac")
- .add_connection("MixClosure1::Closure", "MixClosure3::Closure1")
- .add_connection("MixClosure2::Closure", "MixClosure3::Closure2")
- .output_closure("MixClosure3::Closure");
-
- graph.finalize(scene);
+ EXPECT_ANY_MESSAGE(log);
+ CORRECT_INFO_MESSAGE(log, "Folding MixClosure1::Closure to socket Diffuse::BSDF.");
+ CORRECT_INFO_MESSAGE(log, "Folding MixClosure2::Closure to socket Diffuse::BSDF.");
+ CORRECT_INFO_MESSAGE(log, "Folding MixClosure3::Closure to socket Diffuse::BSDF.");
+
+ builder.add_attribute("Attribute")
+ .add_node(ShaderNodeBuilder<DiffuseBsdfNode>("Diffuse"))
+ /* choose left */
+ .add_node(ShaderNodeBuilder<MixClosureNode>("MixClosure1").set("Fac", 0.0f))
+ .add_connection("Diffuse::BSDF", "MixClosure1::Closure1")
+ /* choose right */
+ .add_node(ShaderNodeBuilder<MixClosureNode>("MixClosure2").set("Fac", 1.0f))
+ .add_connection("Diffuse::BSDF", "MixClosure2::Closure2")
+ /* both inputs folded the same */
+ .add_node(ShaderNodeBuilder<MixClosureNode>("MixClosure3"))
+ .add_connection("Attribute::Fac", "MixClosure3::Fac")
+ .add_connection("MixClosure1::Closure", "MixClosure3::Closure1")
+ .add_connection("MixClosure2::Closure", "MixClosure3::Closure2")
+ .output_closure("MixClosure3::Closure");
+
+ graph.finalize(scene);
}
/*
@@ -376,16 +354,16 @@ TEST_F(RenderGraph, constant_fold_shader_mix)
*/
TEST_F(RenderGraph, constant_fold_invert)
{
- EXPECT_ANY_MESSAGE(log);
- CORRECT_INFO_MESSAGE(log, "Folding Invert::Color to constant (0.68, 0.5, 0.32).");
+ EXPECT_ANY_MESSAGE(log);
+ CORRECT_INFO_MESSAGE(log, "Folding Invert::Color to constant (0.68, 0.5, 0.32).");
- builder
- .add_node(ShaderNodeBuilder<InvertNode>("Invert")
- .set("Fac", 0.8f)
- .set("Color", make_float3(0.2f, 0.5f, 0.8f)))
- .output_color("Invert::Color");
+ builder
+ .add_node(ShaderNodeBuilder<InvertNode>("Invert")
+ .set("Fac", 0.8f)
+ .set("Color", make_float3(0.2f, 0.5f, 0.8f)))
+ .output_color("Invert::Color");
- graph.finalize(scene);
+ graph.finalize(scene);
}
/*
@@ -394,17 +372,15 @@ TEST_F(RenderGraph, constant_fold_invert)
*/
TEST_F(RenderGraph, constant_fold_invert_fac_0)
{
- EXPECT_ANY_MESSAGE(log);
- CORRECT_INFO_MESSAGE(log, "Folding Invert::Color to socket Attribute::Color.");
+ EXPECT_ANY_MESSAGE(log);
+ CORRECT_INFO_MESSAGE(log, "Folding Invert::Color to socket Attribute::Color.");
- builder
- .add_attribute("Attribute")
- .add_node(ShaderNodeBuilder<InvertNode>("Invert")
- .set("Fac", 0.0f))
- .add_connection("Attribute::Color", "Invert::Color")
- .output_color("Invert::Color");
+ builder.add_attribute("Attribute")
+ .add_node(ShaderNodeBuilder<InvertNode>("Invert").set("Fac", 0.0f))
+ .add_connection("Attribute::Color", "Invert::Color")
+ .output_color("Invert::Color");
- graph.finalize(scene);
+ graph.finalize(scene);
}
/*
@@ -413,16 +389,16 @@ TEST_F(RenderGraph, constant_fold_invert_fac_0)
*/
TEST_F(RenderGraph, constant_fold_invert_fac_0_const)
{
- EXPECT_ANY_MESSAGE(log);
- CORRECT_INFO_MESSAGE(log, "Folding Invert::Color to constant (0.2, 0.5, 0.8).");
+ EXPECT_ANY_MESSAGE(log);
+ CORRECT_INFO_MESSAGE(log, "Folding Invert::Color to constant (0.2, 0.5, 0.8).");
- builder
- .add_node(ShaderNodeBuilder<InvertNode>("Invert")
- .set("Fac", 0.0f)
- .set("Color", make_float3(0.2f, 0.5f, 0.8f)))
- .output_color("Invert::Color");
+ builder
+ .add_node(ShaderNodeBuilder<InvertNode>("Invert")
+ .set("Fac", 0.0f)
+ .set("Color", make_float3(0.2f, 0.5f, 0.8f)))
+ .output_color("Invert::Color");
- graph.finalize(scene);
+ graph.finalize(scene);
}
/*
@@ -431,19 +407,19 @@ TEST_F(RenderGraph, constant_fold_invert_fac_0_const)
*/
TEST_F(RenderGraph, constant_fold_mix_add)
{
- EXPECT_ANY_MESSAGE(log);
- CORRECT_INFO_MESSAGE(log, "Folding MixAdd::Color to constant (0.62, 1.14, 1.42).");
+ EXPECT_ANY_MESSAGE(log);
+ CORRECT_INFO_MESSAGE(log, "Folding MixAdd::Color to constant (0.62, 1.14, 1.42).");
- builder
- .add_node(ShaderNodeBuilder<MixNode>("MixAdd")
- .set(&MixNode::type, NODE_MIX_ADD)
- .set(&MixNode::use_clamp, false)
- .set("Fac", 0.8f)
- .set("Color1", make_float3(0.3, 0.5, 0.7))
- .set("Color2", make_float3(0.4, 0.8, 0.9)))
- .output_color("MixAdd::Color");
+ builder
+ .add_node(ShaderNodeBuilder<MixNode>("MixAdd")
+ .set(&MixNode::type, NODE_MIX_ADD)
+ .set(&MixNode::use_clamp, false)
+ .set("Fac", 0.8f)
+ .set("Color1", make_float3(0.3, 0.5, 0.7))
+ .set("Color2", make_float3(0.4, 0.8, 0.9)))
+ .output_color("MixAdd::Color");
- graph.finalize(scene);
+ graph.finalize(scene);
}
/*
@@ -452,19 +428,19 @@ TEST_F(RenderGraph, constant_fold_mix_add)
*/
TEST_F(RenderGraph, constant_fold_mix_add_clamp)
{
- EXPECT_ANY_MESSAGE(log);
- CORRECT_INFO_MESSAGE(log, "Folding MixAdd::Color to constant (0.62, 1, 1).");
+ EXPECT_ANY_MESSAGE(log);
+ CORRECT_INFO_MESSAGE(log, "Folding MixAdd::Color to constant (0.62, 1, 1).");
- builder
- .add_node(ShaderNodeBuilder<MixNode>("MixAdd")
- .set(&MixNode::type, NODE_MIX_ADD)
- .set(&MixNode::use_clamp, true)
- .set("Fac", 0.8f)
- .set("Color1", make_float3(0.3, 0.5, 0.7))
- .set("Color2", make_float3(0.4, 0.8, 0.9)))
- .output_color("MixAdd::Color");
+ builder
+ .add_node(ShaderNodeBuilder<MixNode>("MixAdd")
+ .set(&MixNode::type, NODE_MIX_ADD)
+ .set(&MixNode::use_clamp, true)
+ .set("Fac", 0.8f)
+ .set("Color1", make_float3(0.3, 0.5, 0.7))
+ .set("Color2", make_float3(0.4, 0.8, 0.9)))
+ .output_color("MixAdd::Color");
- graph.finalize(scene);
+ graph.finalize(scene);
}
/*
@@ -473,21 +449,20 @@ TEST_F(RenderGraph, constant_fold_mix_add_clamp)
*/
TEST_F(RenderGraph, constant_fold_part_mix_dodge_no_fac_0)
{
- EXPECT_ANY_MESSAGE(log);
- INVALID_INFO_MESSAGE(log, "Folding ");
+ EXPECT_ANY_MESSAGE(log);
+ INVALID_INFO_MESSAGE(log, "Folding ");
- builder
- .add_attribute("Attribute1")
- .add_attribute("Attribute2")
- .add_node(ShaderNodeBuilder<MixNode>("Mix")
- .set(&MixNode::type, NODE_MIX_DODGE)
- .set(&MixNode::use_clamp, false)
- .set("Fac", 0.0f))
- .add_connection("Attribute1::Color", "Mix::Color1")
- .add_connection("Attribute2::Color", "Mix::Color2")
- .output_color("Mix::Color");
+ builder.add_attribute("Attribute1")
+ .add_attribute("Attribute2")
+ .add_node(ShaderNodeBuilder<MixNode>("Mix")
+ .set(&MixNode::type, NODE_MIX_DODGE)
+ .set(&MixNode::use_clamp, false)
+ .set("Fac", 0.0f))
+ .add_connection("Attribute1::Color", "Mix::Color1")
+ .add_connection("Attribute2::Color", "Mix::Color2")
+ .output_color("Mix::Color");
- graph.finalize(scene);
+ graph.finalize(scene);
}
/*
@@ -496,21 +471,20 @@ TEST_F(RenderGraph, constant_fold_part_mix_dodge_no_fac_0)
*/
TEST_F(RenderGraph, constant_fold_part_mix_light_no_fac_0)
{
- EXPECT_ANY_MESSAGE(log);
- INVALID_INFO_MESSAGE(log, "Folding ");
+ EXPECT_ANY_MESSAGE(log);
+ INVALID_INFO_MESSAGE(log, "Folding ");
- builder
- .add_attribute("Attribute1")
- .add_attribute("Attribute2")
- .add_node(ShaderNodeBuilder<MixNode>("Mix")
- .set(&MixNode::type, NODE_MIX_LIGHT)
- .set(&MixNode::use_clamp, false)
- .set("Fac", 0.0f))
- .add_connection("Attribute1::Color", "Mix::Color1")
- .add_connection("Attribute2::Color", "Mix::Color2")
- .output_color("Mix::Color");
+ builder.add_attribute("Attribute1")
+ .add_attribute("Attribute2")
+ .add_node(ShaderNodeBuilder<MixNode>("Mix")
+ .set(&MixNode::type, NODE_MIX_LIGHT)
+ .set(&MixNode::use_clamp, false)
+ .set("Fac", 0.0f))
+ .add_connection("Attribute1::Color", "Mix::Color1")
+ .add_connection("Attribute2::Color", "Mix::Color2")
+ .output_color("Mix::Color");
- graph.finalize(scene);
+ graph.finalize(scene);
}
/*
@@ -519,21 +493,20 @@ TEST_F(RenderGraph, constant_fold_part_mix_light_no_fac_0)
*/
TEST_F(RenderGraph, constant_fold_part_mix_burn_no_fac_0)
{
- EXPECT_ANY_MESSAGE(log);
- INVALID_INFO_MESSAGE(log, "Folding ");
+ EXPECT_ANY_MESSAGE(log);
+ INVALID_INFO_MESSAGE(log, "Folding ");
- builder
- .add_attribute("Attribute1")
- .add_attribute("Attribute2")
- .add_node(ShaderNodeBuilder<MixNode>("Mix")
- .set(&MixNode::type, NODE_MIX_BURN)
- .set(&MixNode::use_clamp, false)
- .set("Fac", 0.0f))
- .add_connection("Attribute1::Color", "Mix::Color1")
- .add_connection("Attribute2::Color", "Mix::Color2")
- .output_color("Mix::Color");
+ builder.add_attribute("Attribute1")
+ .add_attribute("Attribute2")
+ .add_node(ShaderNodeBuilder<MixNode>("Mix")
+ .set(&MixNode::type, NODE_MIX_BURN)
+ .set(&MixNode::use_clamp, false)
+ .set("Fac", 0.0f))
+ .add_connection("Attribute1::Color", "Mix::Color1")
+ .add_connection("Attribute2::Color", "Mix::Color2")
+ .output_color("Mix::Color");
- graph.finalize(scene);
+ graph.finalize(scene);
}
/*
@@ -542,21 +515,20 @@ TEST_F(RenderGraph, constant_fold_part_mix_burn_no_fac_0)
*/
TEST_F(RenderGraph, constant_fold_part_mix_blend_clamped_no_fac_0)
{
- EXPECT_ANY_MESSAGE(log);
- INVALID_INFO_MESSAGE(log, "Folding ");
+ EXPECT_ANY_MESSAGE(log);
+ INVALID_INFO_MESSAGE(log, "Folding ");
- builder
- .add_attribute("Attribute1")
- .add_attribute("Attribute2")
- .add_node(ShaderNodeBuilder<MixNode>("Mix")
- .set(&MixNode::type, NODE_MIX_BLEND)
- .set(&MixNode::use_clamp, true)
- .set("Fac", 0.0f))
- .add_connection("Attribute1::Color", "Mix::Color1")
- .add_connection("Attribute2::Color", "Mix::Color2")
- .output_color("Mix::Color");
+ builder.add_attribute("Attribute1")
+ .add_attribute("Attribute2")
+ .add_node(ShaderNodeBuilder<MixNode>("Mix")
+ .set(&MixNode::type, NODE_MIX_BLEND)
+ .set(&MixNode::use_clamp, true)
+ .set("Fac", 0.0f))
+ .add_connection("Attribute1::Color", "Mix::Color1")
+ .add_connection("Attribute2::Color", "Mix::Color2")
+ .output_color("Mix::Color");
- graph.finalize(scene);
+ graph.finalize(scene);
}
/*
@@ -566,38 +538,37 @@ TEST_F(RenderGraph, constant_fold_part_mix_blend_clamped_no_fac_0)
*/
TEST_F(RenderGraph, constant_fold_part_mix_blend)
{
- EXPECT_ANY_MESSAGE(log);
- CORRECT_INFO_MESSAGE(log, "Folding MixBlend1::Color to socket Attribute1::Color.");
- CORRECT_INFO_MESSAGE(log, "Folding MixBlend2::Color to socket Attribute1::Color.");
- CORRECT_INFO_MESSAGE(log, "Folding MixBlend3::Color to socket Attribute1::Color.");
-
- builder
- .add_attribute("Attribute1")
- .add_attribute("Attribute2")
- /* choose left */
- .add_node(ShaderNodeBuilder<MixNode>("MixBlend1")
- .set(&MixNode::type, NODE_MIX_BLEND)
- .set(&MixNode::use_clamp, false)
- .set("Fac", 0.0f))
- .add_connection("Attribute1::Color", "MixBlend1::Color1")
- .add_connection("Attribute2::Color", "MixBlend1::Color2")
- /* choose right */
- .add_node(ShaderNodeBuilder<MixNode>("MixBlend2")
- .set(&MixNode::type, NODE_MIX_BLEND)
- .set(&MixNode::use_clamp, false)
- .set("Fac", 1.0f))
- .add_connection("Attribute1::Color", "MixBlend2::Color2")
- .add_connection("Attribute2::Color", "MixBlend2::Color1")
- /* both inputs folded to Attribute1 */
- .add_node(ShaderNodeBuilder<MixNode>("MixBlend3")
- .set(&MixNode::type, NODE_MIX_BLEND)
- .set(&MixNode::use_clamp, false))
- .add_connection("Attribute1::Fac", "MixBlend3::Fac")
- .add_connection("MixBlend1::Color", "MixBlend3::Color1")
- .add_connection("MixBlend2::Color", "MixBlend3::Color2")
- .output_color("MixBlend3::Color");
-
- graph.finalize(scene);
+ EXPECT_ANY_MESSAGE(log);
+ CORRECT_INFO_MESSAGE(log, "Folding MixBlend1::Color to socket Attribute1::Color.");
+ CORRECT_INFO_MESSAGE(log, "Folding MixBlend2::Color to socket Attribute1::Color.");
+ CORRECT_INFO_MESSAGE(log, "Folding MixBlend3::Color to socket Attribute1::Color.");
+
+ builder.add_attribute("Attribute1")
+ .add_attribute("Attribute2")
+ /* choose left */
+ .add_node(ShaderNodeBuilder<MixNode>("MixBlend1")
+ .set(&MixNode::type, NODE_MIX_BLEND)
+ .set(&MixNode::use_clamp, false)
+ .set("Fac", 0.0f))
+ .add_connection("Attribute1::Color", "MixBlend1::Color1")
+ .add_connection("Attribute2::Color", "MixBlend1::Color2")
+ /* choose right */
+ .add_node(ShaderNodeBuilder<MixNode>("MixBlend2")
+ .set(&MixNode::type, NODE_MIX_BLEND)
+ .set(&MixNode::use_clamp, false)
+ .set("Fac", 1.0f))
+ .add_connection("Attribute1::Color", "MixBlend2::Color2")
+ .add_connection("Attribute2::Color", "MixBlend2::Color1")
+ /* both inputs folded to Attribute1 */
+ .add_node(ShaderNodeBuilder<MixNode>("MixBlend3")
+ .set(&MixNode::type, NODE_MIX_BLEND)
+ .set(&MixNode::use_clamp, false))
+ .add_connection("Attribute1::Fac", "MixBlend3::Fac")
+ .add_connection("MixBlend1::Color", "MixBlend3::Color1")
+ .add_connection("MixBlend2::Color", "MixBlend3::Color2")
+ .output_color("MixBlend3::Color");
+
+ graph.finalize(scene);
}
/*
@@ -606,20 +577,19 @@ TEST_F(RenderGraph, constant_fold_part_mix_blend)
*/
TEST_F(RenderGraph, constant_fold_part_mix_sub_same_fac_bad)
{
- EXPECT_ANY_MESSAGE(log);
- INVALID_INFO_MESSAGE(log, "Folding Mix::");
+ EXPECT_ANY_MESSAGE(log);
+ INVALID_INFO_MESSAGE(log, "Folding Mix::");
- builder
- .add_attribute("Attribute")
- .add_node(ShaderNodeBuilder<MixNode>("Mix")
- .set(&MixNode::type, NODE_MIX_SUB)
- .set(&MixNode::use_clamp, true)
- .set("Fac", 0.5f))
- .add_connection("Attribute::Color", "Mix::Color1")
- .add_connection("Attribute::Color", "Mix::Color2")
- .output_color("Mix::Color");
+ builder.add_attribute("Attribute")
+ .add_node(ShaderNodeBuilder<MixNode>("Mix")
+ .set(&MixNode::type, NODE_MIX_SUB)
+ .set(&MixNode::use_clamp, true)
+ .set("Fac", 0.5f))
+ .add_connection("Attribute::Color", "Mix::Color1")
+ .add_connection("Attribute::Color", "Mix::Color2")
+ .output_color("Mix::Color");
- graph.finalize(scene);
+ graph.finalize(scene);
}
/*
@@ -628,76 +598,77 @@ TEST_F(RenderGraph, constant_fold_part_mix_sub_same_fac_bad)
*/
TEST_F(RenderGraph, constant_fold_part_mix_sub_same_fac_1)
{
- EXPECT_ANY_MESSAGE(log);
- CORRECT_INFO_MESSAGE(log, "Folding Mix::Color to constant (0, 0, 0).");
+ EXPECT_ANY_MESSAGE(log);
+ CORRECT_INFO_MESSAGE(log, "Folding Mix::Color to constant (0, 0, 0).");
- builder
- .add_attribute("Attribute")
- .add_node(ShaderNodeBuilder<MixNode>("Mix")
- .set(&MixNode::type, NODE_MIX_SUB)
- .set(&MixNode::use_clamp, true)
- .set("Fac", 1.0f))
- .add_connection("Attribute::Color", "Mix::Color1")
- .add_connection("Attribute::Color", "Mix::Color2")
- .output_color("Mix::Color");
+ builder.add_attribute("Attribute")
+ .add_node(ShaderNodeBuilder<MixNode>("Mix")
+ .set(&MixNode::type, NODE_MIX_SUB)
+ .set(&MixNode::use_clamp, true)
+ .set("Fac", 1.0f))
+ .add_connection("Attribute::Color", "Mix::Color1")
+ .add_connection("Attribute::Color", "Mix::Color2")
+ .output_color("Mix::Color");
- graph.finalize(scene);
+ graph.finalize(scene);
}
/*
* Graph for testing partial folds of MixRGB with one constant argument.
* Includes 4 tests: constant on each side with fac either unknown or 1.
*/
-static void build_mix_partial_test_graph(ShaderGraphBuilder &builder, NodeMix type, float3 constval)
-{
- builder
- .add_attribute("Attribute")
- /* constant on the left */
- .add_node(ShaderNodeBuilder<MixNode>("Mix_Cx_Fx")
- .set(&MixNode::type, type)
- .set(&MixNode::use_clamp, false)
- .set("Color1", constval))
- .add_node(ShaderNodeBuilder<MixNode>("Mix_Cx_F1")
- .set(&MixNode::type, type)
- .set(&MixNode::use_clamp, false)
- .set("Color1", constval)
- .set("Fac", 1.0f))
- .add_connection("Attribute::Fac", "Mix_Cx_Fx::Fac")
- .add_connection("Attribute::Color", "Mix_Cx_Fx::Color2")
- .add_connection("Attribute::Color", "Mix_Cx_F1::Color2")
- /* constant on the right */
- .add_node(ShaderNodeBuilder<MixNode>("Mix_xC_Fx")
- .set(&MixNode::type, type)
- .set(&MixNode::use_clamp, false)
- .set("Color2", constval))
- .add_node(ShaderNodeBuilder<MixNode>("Mix_xC_F1")
- .set(&MixNode::type, type)
- .set(&MixNode::use_clamp, false)
- .set("Color2", constval)
- .set("Fac", 1.0f))
- .add_connection("Attribute::Fac", "Mix_xC_Fx::Fac")
- .add_connection("Attribute::Color", "Mix_xC_Fx::Color1")
- .add_connection("Attribute::Color", "Mix_xC_F1::Color1")
- /* results of actual tests simply added up to connect to output */
- .add_node(ShaderNodeBuilder<MixNode>("Out12")
- .set(&MixNode::type, NODE_MIX_ADD)
- .set(&MixNode::use_clamp, true)
- .set("Fac", 1.0f))
- .add_node(ShaderNodeBuilder<MixNode>("Out34")
- .set(&MixNode::type, NODE_MIX_ADD)
- .set(&MixNode::use_clamp, true)
- .set("Fac", 1.0f))
- .add_node(ShaderNodeBuilder<MixNode>("Out1234")
- .set(&MixNode::type, NODE_MIX_ADD)
- .set(&MixNode::use_clamp, true)
- .set("Fac", 1.0f))
- .add_connection("Mix_Cx_Fx::Color", "Out12::Color1")
- .add_connection("Mix_Cx_F1::Color", "Out12::Color2")
- .add_connection("Mix_xC_Fx::Color", "Out34::Color1")
- .add_connection("Mix_xC_F1::Color", "Out34::Color2")
- .add_connection("Out12::Color", "Out1234::Color1")
- .add_connection("Out34::Color", "Out1234::Color2")
- .output_color("Out1234::Color");
+static void build_mix_partial_test_graph(ShaderGraphBuilder &builder,
+ NodeMix type,
+ float3 constval)
+{
+ builder
+ .add_attribute("Attribute")
+ /* constant on the left */
+ .add_node(ShaderNodeBuilder<MixNode>("Mix_Cx_Fx")
+ .set(&MixNode::type, type)
+ .set(&MixNode::use_clamp, false)
+ .set("Color1", constval))
+ .add_node(ShaderNodeBuilder<MixNode>("Mix_Cx_F1")
+ .set(&MixNode::type, type)
+ .set(&MixNode::use_clamp, false)
+ .set("Color1", constval)
+ .set("Fac", 1.0f))
+ .add_connection("Attribute::Fac", "Mix_Cx_Fx::Fac")
+ .add_connection("Attribute::Color", "Mix_Cx_Fx::Color2")
+ .add_connection("Attribute::Color", "Mix_Cx_F1::Color2")
+ /* constant on the right */
+ .add_node(ShaderNodeBuilder<MixNode>("Mix_xC_Fx")
+ .set(&MixNode::type, type)
+ .set(&MixNode::use_clamp, false)
+ .set("Color2", constval))
+ .add_node(ShaderNodeBuilder<MixNode>("Mix_xC_F1")
+ .set(&MixNode::type, type)
+ .set(&MixNode::use_clamp, false)
+ .set("Color2", constval)
+ .set("Fac", 1.0f))
+ .add_connection("Attribute::Fac", "Mix_xC_Fx::Fac")
+ .add_connection("Attribute::Color", "Mix_xC_Fx::Color1")
+ .add_connection("Attribute::Color", "Mix_xC_F1::Color1")
+ /* results of actual tests simply added up to connect to output */
+ .add_node(ShaderNodeBuilder<MixNode>("Out12")
+ .set(&MixNode::type, NODE_MIX_ADD)
+ .set(&MixNode::use_clamp, true)
+ .set("Fac", 1.0f))
+ .add_node(ShaderNodeBuilder<MixNode>("Out34")
+ .set(&MixNode::type, NODE_MIX_ADD)
+ .set(&MixNode::use_clamp, true)
+ .set("Fac", 1.0f))
+ .add_node(ShaderNodeBuilder<MixNode>("Out1234")
+ .set(&MixNode::type, NODE_MIX_ADD)
+ .set(&MixNode::use_clamp, true)
+ .set("Fac", 1.0f))
+ .add_connection("Mix_Cx_Fx::Color", "Out12::Color1")
+ .add_connection("Mix_Cx_F1::Color", "Out12::Color2")
+ .add_connection("Mix_xC_Fx::Color", "Out34::Color1")
+ .add_connection("Mix_xC_F1::Color", "Out34::Color2")
+ .add_connection("Out12::Color", "Out1234::Color1")
+ .add_connection("Out34::Color", "Out1234::Color2")
+ .output_color("Out1234::Color");
}
/*
@@ -705,17 +676,17 @@ static void build_mix_partial_test_graph(ShaderGraphBuilder &builder, NodeMix ty
*/
TEST_F(RenderGraph, constant_fold_part_mix_add_0)
{
- EXPECT_ANY_MESSAGE(log);
- /* 0 + X (fac 1) == X */
- INVALID_INFO_MESSAGE(log, "Folding Mix_Cx_Fx::Color");
- CORRECT_INFO_MESSAGE(log, "Folding Mix_Cx_F1::Color to socket Attribute::Color.");
- /* X + 0 (fac ?) == X */
- CORRECT_INFO_MESSAGE(log, "Folding Mix_xC_Fx::Color to socket Attribute::Color.");
- CORRECT_INFO_MESSAGE(log, "Folding Mix_xC_F1::Color to socket Attribute::Color.");
- INVALID_INFO_MESSAGE(log, "Folding Out");
+ EXPECT_ANY_MESSAGE(log);
+ /* 0 + X (fac 1) == X */
+ INVALID_INFO_MESSAGE(log, "Folding Mix_Cx_Fx::Color");
+ CORRECT_INFO_MESSAGE(log, "Folding Mix_Cx_F1::Color to socket Attribute::Color.");
+ /* X + 0 (fac ?) == X */
+ CORRECT_INFO_MESSAGE(log, "Folding Mix_xC_Fx::Color to socket Attribute::Color.");
+ CORRECT_INFO_MESSAGE(log, "Folding Mix_xC_F1::Color to socket Attribute::Color.");
+ INVALID_INFO_MESSAGE(log, "Folding Out");
- build_mix_partial_test_graph(builder, NODE_MIX_ADD, make_float3(0, 0, 0));
- graph.finalize(scene);
+ build_mix_partial_test_graph(builder, NODE_MIX_ADD, make_float3(0, 0, 0));
+ graph.finalize(scene);
}
/*
@@ -723,16 +694,16 @@ TEST_F(RenderGraph, constant_fold_part_mix_add_0)
*/
TEST_F(RenderGraph, constant_fold_part_mix_sub_0)
{
- EXPECT_ANY_MESSAGE(log);
- INVALID_INFO_MESSAGE(log, "Folding Mix_Cx_Fx::Color");
- INVALID_INFO_MESSAGE(log, "Folding Mix_Cx_F1::Color");
- /* X - 0 (fac ?) == X */
- CORRECT_INFO_MESSAGE(log, "Folding Mix_xC_Fx::Color to socket Attribute::Color.");
- CORRECT_INFO_MESSAGE(log, "Folding Mix_xC_F1::Color to socket Attribute::Color.");
- INVALID_INFO_MESSAGE(log, "Folding Out");
+ EXPECT_ANY_MESSAGE(log);
+ INVALID_INFO_MESSAGE(log, "Folding Mix_Cx_Fx::Color");
+ INVALID_INFO_MESSAGE(log, "Folding Mix_Cx_F1::Color");
+ /* X - 0 (fac ?) == X */
+ CORRECT_INFO_MESSAGE(log, "Folding Mix_xC_Fx::Color to socket Attribute::Color.");
+ CORRECT_INFO_MESSAGE(log, "Folding Mix_xC_F1::Color to socket Attribute::Color.");
+ INVALID_INFO_MESSAGE(log, "Folding Out");
- build_mix_partial_test_graph(builder, NODE_MIX_SUB, make_float3(0, 0, 0));
- graph.finalize(scene);
+ build_mix_partial_test_graph(builder, NODE_MIX_SUB, make_float3(0, 0, 0));
+ graph.finalize(scene);
}
/*
@@ -740,17 +711,17 @@ TEST_F(RenderGraph, constant_fold_part_mix_sub_0)
*/
TEST_F(RenderGraph, constant_fold_part_mix_mul_1)
{
- EXPECT_ANY_MESSAGE(log);
- /* 1 * X (fac 1) == X */
- INVALID_INFO_MESSAGE(log, "Folding Mix_Cx_Fx::Color");
- CORRECT_INFO_MESSAGE(log, "Folding Mix_Cx_F1::Color to socket Attribute::Color.");
- /* X * 1 (fac ?) == X */
- CORRECT_INFO_MESSAGE(log, "Folding Mix_xC_Fx::Color to socket Attribute::Color.");
- CORRECT_INFO_MESSAGE(log, "Folding Mix_xC_F1::Color to socket Attribute::Color.");
- INVALID_INFO_MESSAGE(log, "Folding Out");
+ EXPECT_ANY_MESSAGE(log);
+ /* 1 * X (fac 1) == X */
+ INVALID_INFO_MESSAGE(log, "Folding Mix_Cx_Fx::Color");
+ CORRECT_INFO_MESSAGE(log, "Folding Mix_Cx_F1::Color to socket Attribute::Color.");
+ /* X * 1 (fac ?) == X */
+ CORRECT_INFO_MESSAGE(log, "Folding Mix_xC_Fx::Color to socket Attribute::Color.");
+ CORRECT_INFO_MESSAGE(log, "Folding Mix_xC_F1::Color to socket Attribute::Color.");
+ INVALID_INFO_MESSAGE(log, "Folding Out");
- build_mix_partial_test_graph(builder, NODE_MIX_MUL, make_float3(1, 1, 1));
- graph.finalize(scene);
+ build_mix_partial_test_graph(builder, NODE_MIX_MUL, make_float3(1, 1, 1));
+ graph.finalize(scene);
}
/*
@@ -758,16 +729,16 @@ TEST_F(RenderGraph, constant_fold_part_mix_mul_1)
*/
TEST_F(RenderGraph, constant_fold_part_mix_div_1)
{
- EXPECT_ANY_MESSAGE(log);
- INVALID_INFO_MESSAGE(log, "Folding Mix_Cx_Fx::Color");
- INVALID_INFO_MESSAGE(log, "Folding Mix_Cx_F1::Color");
- /* X / 1 (fac ?) == X */
- CORRECT_INFO_MESSAGE(log, "Folding Mix_xC_Fx::Color to socket Attribute::Color.");
- CORRECT_INFO_MESSAGE(log, "Folding Mix_xC_F1::Color to socket Attribute::Color.");
- INVALID_INFO_MESSAGE(log, "Folding Out");
+ EXPECT_ANY_MESSAGE(log);
+ INVALID_INFO_MESSAGE(log, "Folding Mix_Cx_Fx::Color");
+ INVALID_INFO_MESSAGE(log, "Folding Mix_Cx_F1::Color");
+ /* X / 1 (fac ?) == X */
+ CORRECT_INFO_MESSAGE(log, "Folding Mix_xC_Fx::Color to socket Attribute::Color.");
+ CORRECT_INFO_MESSAGE(log, "Folding Mix_xC_F1::Color to socket Attribute::Color.");
+ INVALID_INFO_MESSAGE(log, "Folding Out");
- build_mix_partial_test_graph(builder, NODE_MIX_DIV, make_float3(1, 1, 1));
- graph.finalize(scene);
+ build_mix_partial_test_graph(builder, NODE_MIX_DIV, make_float3(1, 1, 1));
+ graph.finalize(scene);
}
/*
@@ -775,19 +746,19 @@ TEST_F(RenderGraph, constant_fold_part_mix_div_1)
*/
TEST_F(RenderGraph, constant_fold_part_mix_mul_0)
{
- EXPECT_ANY_MESSAGE(log);
- /* 0 * ? (fac ?) == 0 */
- CORRECT_INFO_MESSAGE(log, "Folding Mix_Cx_Fx::Color to constant (0, 0, 0).");
- CORRECT_INFO_MESSAGE(log, "Folding Mix_Cx_F1::Color to constant (0, 0, 0).");
- /* ? * 0 (fac 1) == 0 */
- INVALID_INFO_MESSAGE(log, "Folding Mix_xC_Fx::Color");
- CORRECT_INFO_MESSAGE(log, "Folding Mix_xC_F1::Color to constant (0, 0, 0).");
+ EXPECT_ANY_MESSAGE(log);
+ /* 0 * ? (fac ?) == 0 */
+ CORRECT_INFO_MESSAGE(log, "Folding Mix_Cx_Fx::Color to constant (0, 0, 0).");
+ CORRECT_INFO_MESSAGE(log, "Folding Mix_Cx_F1::Color to constant (0, 0, 0).");
+ /* ? * 0 (fac 1) == 0 */
+ INVALID_INFO_MESSAGE(log, "Folding Mix_xC_Fx::Color");
+ CORRECT_INFO_MESSAGE(log, "Folding Mix_xC_F1::Color to constant (0, 0, 0).");
- CORRECT_INFO_MESSAGE(log, "Folding Out12::Color to constant (0, 0, 0).");
- INVALID_INFO_MESSAGE(log, "Folding Out1234");
+ CORRECT_INFO_MESSAGE(log, "Folding Out12::Color to constant (0, 0, 0).");
+ INVALID_INFO_MESSAGE(log, "Folding Out1234");
- build_mix_partial_test_graph(builder, NODE_MIX_MUL, make_float3(0, 0, 0));
- graph.finalize(scene);
+ build_mix_partial_test_graph(builder, NODE_MIX_MUL, make_float3(0, 0, 0));
+ graph.finalize(scene);
}
/*
@@ -795,18 +766,18 @@ TEST_F(RenderGraph, constant_fold_part_mix_mul_0)
*/
TEST_F(RenderGraph, constant_fold_part_mix_div_0)
{
- EXPECT_ANY_MESSAGE(log);
- /* 0 / ? (fac ?) == 0 */
- CORRECT_INFO_MESSAGE(log, "Folding Mix_Cx_Fx::Color to constant (0, 0, 0).");
- CORRECT_INFO_MESSAGE(log, "Folding Mix_Cx_F1::Color to constant (0, 0, 0).");
- INVALID_INFO_MESSAGE(log, "Folding Mix_xC_Fx::Color");
- INVALID_INFO_MESSAGE(log, "Folding Mix_xC_F1::Color");
+ EXPECT_ANY_MESSAGE(log);
+ /* 0 / ? (fac ?) == 0 */
+ CORRECT_INFO_MESSAGE(log, "Folding Mix_Cx_Fx::Color to constant (0, 0, 0).");
+ CORRECT_INFO_MESSAGE(log, "Folding Mix_Cx_F1::Color to constant (0, 0, 0).");
+ INVALID_INFO_MESSAGE(log, "Folding Mix_xC_Fx::Color");
+ INVALID_INFO_MESSAGE(log, "Folding Mix_xC_F1::Color");
- CORRECT_INFO_MESSAGE(log, "Folding Out12::Color to constant (0, 0, 0).");
- INVALID_INFO_MESSAGE(log, "Folding Out1234");
+ CORRECT_INFO_MESSAGE(log, "Folding Out12::Color to constant (0, 0, 0).");
+ INVALID_INFO_MESSAGE(log, "Folding Out1234");
- build_mix_partial_test_graph(builder, NODE_MIX_DIV, make_float3(0, 0, 0));
- graph.finalize(scene);
+ build_mix_partial_test_graph(builder, NODE_MIX_DIV, make_float3(0, 0, 0));
+ graph.finalize(scene);
}
/*
@@ -814,22 +785,22 @@ TEST_F(RenderGraph, constant_fold_part_mix_div_0)
*/
TEST_F(RenderGraph, constant_fold_separate_combine_rgb)
{
- EXPECT_ANY_MESSAGE(log);
- CORRECT_INFO_MESSAGE(log, "Folding SeparateRGB::R to constant (0.3).");
- CORRECT_INFO_MESSAGE(log, "Folding SeparateRGB::G to constant (0.5).");
- CORRECT_INFO_MESSAGE(log, "Folding SeparateRGB::B to constant (0.7).");
- CORRECT_INFO_MESSAGE(log, "Folding CombineRGB::Image to constant (0.3, 0.5, 0.7).");
+ EXPECT_ANY_MESSAGE(log);
+ CORRECT_INFO_MESSAGE(log, "Folding SeparateRGB::R to constant (0.3).");
+ CORRECT_INFO_MESSAGE(log, "Folding SeparateRGB::G to constant (0.5).");
+ CORRECT_INFO_MESSAGE(log, "Folding SeparateRGB::B to constant (0.7).");
+ CORRECT_INFO_MESSAGE(log, "Folding CombineRGB::Image to constant (0.3, 0.5, 0.7).");
- builder
- .add_node(ShaderNodeBuilder<SeparateRGBNode>("SeparateRGB")
- .set("Image", make_float3(0.3f, 0.5f, 0.7f)))
- .add_node(ShaderNodeBuilder<CombineRGBNode>("CombineRGB"))
- .add_connection("SeparateRGB::R", "CombineRGB::R")
- .add_connection("SeparateRGB::G", "CombineRGB::G")
- .add_connection("SeparateRGB::B", "CombineRGB::B")
- .output_color("CombineRGB::Image");
+ builder
+ .add_node(ShaderNodeBuilder<SeparateRGBNode>("SeparateRGB")
+ .set("Image", make_float3(0.3f, 0.5f, 0.7f)))
+ .add_node(ShaderNodeBuilder<CombineRGBNode>("CombineRGB"))
+ .add_connection("SeparateRGB::R", "CombineRGB::R")
+ .add_connection("SeparateRGB::G", "CombineRGB::G")
+ .add_connection("SeparateRGB::B", "CombineRGB::B")
+ .output_color("CombineRGB::Image");
- graph.finalize(scene);
+ graph.finalize(scene);
}
/*
@@ -837,23 +808,24 @@ TEST_F(RenderGraph, constant_fold_separate_combine_rgb)
*/
TEST_F(RenderGraph, constant_fold_separate_combine_xyz)
{
- EXPECT_ANY_MESSAGE(log);
- CORRECT_INFO_MESSAGE(log, "Folding SeparateXYZ::X to constant (0.3).");
- CORRECT_INFO_MESSAGE(log, "Folding SeparateXYZ::Y to constant (0.5).");
- CORRECT_INFO_MESSAGE(log, "Folding SeparateXYZ::Z to constant (0.7).");
- CORRECT_INFO_MESSAGE(log, "Folding CombineXYZ::Vector to constant (0.3, 0.5, 0.7).");
- CORRECT_INFO_MESSAGE(log, "Folding convert_vector_to_color::value_color to constant (0.3, 0.5, 0.7).");
+ EXPECT_ANY_MESSAGE(log);
+ CORRECT_INFO_MESSAGE(log, "Folding SeparateXYZ::X to constant (0.3).");
+ CORRECT_INFO_MESSAGE(log, "Folding SeparateXYZ::Y to constant (0.5).");
+ CORRECT_INFO_MESSAGE(log, "Folding SeparateXYZ::Z to constant (0.7).");
+ CORRECT_INFO_MESSAGE(log, "Folding CombineXYZ::Vector to constant (0.3, 0.5, 0.7).");
+ CORRECT_INFO_MESSAGE(
+ log, "Folding convert_vector_to_color::value_color to constant (0.3, 0.5, 0.7).");
- builder
- .add_node(ShaderNodeBuilder<SeparateXYZNode>("SeparateXYZ")
- .set("Vector", make_float3(0.3f, 0.5f, 0.7f)))
- .add_node(ShaderNodeBuilder<CombineXYZNode>("CombineXYZ"))
- .add_connection("SeparateXYZ::X", "CombineXYZ::X")
- .add_connection("SeparateXYZ::Y", "CombineXYZ::Y")
- .add_connection("SeparateXYZ::Z", "CombineXYZ::Z")
- .output_color("CombineXYZ::Vector");
+ builder
+ .add_node(ShaderNodeBuilder<SeparateXYZNode>("SeparateXYZ")
+ .set("Vector", make_float3(0.3f, 0.5f, 0.7f)))
+ .add_node(ShaderNodeBuilder<CombineXYZNode>("CombineXYZ"))
+ .add_connection("SeparateXYZ::X", "CombineXYZ::X")
+ .add_connection("SeparateXYZ::Y", "CombineXYZ::Y")
+ .add_connection("SeparateXYZ::Z", "CombineXYZ::Z")
+ .output_color("CombineXYZ::Vector");
- graph.finalize(scene);
+ graph.finalize(scene);
}
/*
@@ -861,22 +833,22 @@ TEST_F(RenderGraph, constant_fold_separate_combine_xyz)
*/
TEST_F(RenderGraph, constant_fold_separate_combine_hsv)
{
- EXPECT_ANY_MESSAGE(log);
- CORRECT_INFO_MESSAGE(log, "Folding SeparateHSV::H to constant (0.583333).");
- CORRECT_INFO_MESSAGE(log, "Folding SeparateHSV::S to constant (0.571429).");
- CORRECT_INFO_MESSAGE(log, "Folding SeparateHSV::V to constant (0.7).");
- CORRECT_INFO_MESSAGE(log, "Folding CombineHSV::Color to constant (0.3, 0.5, 0.7).");
+ EXPECT_ANY_MESSAGE(log);
+ CORRECT_INFO_MESSAGE(log, "Folding SeparateHSV::H to constant (0.583333).");
+ CORRECT_INFO_MESSAGE(log, "Folding SeparateHSV::S to constant (0.571429).");
+ CORRECT_INFO_MESSAGE(log, "Folding SeparateHSV::V to constant (0.7).");
+ CORRECT_INFO_MESSAGE(log, "Folding CombineHSV::Color to constant (0.3, 0.5, 0.7).");
- builder
- .add_node(ShaderNodeBuilder<SeparateHSVNode>("SeparateHSV")
- .set("Color", make_float3(0.3f, 0.5f, 0.7f)))
- .add_node(ShaderNodeBuilder<CombineHSVNode>("CombineHSV"))
- .add_connection("SeparateHSV::H", "CombineHSV::H")
- .add_connection("SeparateHSV::S", "CombineHSV::S")
- .add_connection("SeparateHSV::V", "CombineHSV::V")
- .output_color("CombineHSV::Color");
+ builder
+ .add_node(ShaderNodeBuilder<SeparateHSVNode>("SeparateHSV")
+ .set("Color", make_float3(0.3f, 0.5f, 0.7f)))
+ .add_node(ShaderNodeBuilder<CombineHSVNode>("CombineHSV"))
+ .add_connection("SeparateHSV::H", "CombineHSV::H")
+ .add_connection("SeparateHSV::S", "CombineHSV::S")
+ .add_connection("SeparateHSV::V", "CombineHSV::V")
+ .output_color("CombineHSV::Color");
- graph.finalize(scene);
+ graph.finalize(scene);
}
/*
@@ -884,16 +856,16 @@ TEST_F(RenderGraph, constant_fold_separate_combine_hsv)
*/
TEST_F(RenderGraph, constant_fold_gamma)
{
- EXPECT_ANY_MESSAGE(log);
- CORRECT_INFO_MESSAGE(log, "Folding Gamma::Color to constant (0.164317, 0.353553, 0.585662).");
+ EXPECT_ANY_MESSAGE(log);
+ CORRECT_INFO_MESSAGE(log, "Folding Gamma::Color to constant (0.164317, 0.353553, 0.585662).");
- builder
- .add_node(ShaderNodeBuilder<GammaNode>("Gamma")
- .set("Color", make_float3(0.3f, 0.5f, 0.7f))
- .set("Gamma", 1.5f))
- .output_color("Gamma::Color");
+ builder
+ .add_node(ShaderNodeBuilder<GammaNode>("Gamma")
+ .set("Color", make_float3(0.3f, 0.5f, 0.7f))
+ .set("Gamma", 1.5f))
+ .output_color("Gamma::Color");
- graph.finalize(scene);
+ graph.finalize(scene);
}
/*
@@ -901,30 +873,29 @@ TEST_F(RenderGraph, constant_fold_gamma)
*/
TEST_F(RenderGraph, constant_fold_gamma_part_0)
{
- EXPECT_ANY_MESSAGE(log);
- INVALID_INFO_MESSAGE(log, "Folding Gamma_Cx::");
- CORRECT_INFO_MESSAGE(log, "Folding Gamma_xC::Color to constant (1, 1, 1).");
-
- builder
- .add_attribute("Attribute")
- /* constant on the left */
- .add_node(ShaderNodeBuilder<GammaNode>("Gamma_Cx")
- .set("Color", make_float3(0.0f, 0.0f, 0.0f)))
- .add_connection("Attribute::Fac", "Gamma_Cx::Gamma")
- /* constant on the right */
- .add_node(ShaderNodeBuilder<GammaNode>("Gamma_xC")
- .set("Gamma", 0.0f))
- .add_connection("Attribute::Color", "Gamma_xC::Color")
- /* output sum */
- .add_node(ShaderNodeBuilder<MixNode>("Out")
- .set(&MixNode::type, NODE_MIX_ADD)
- .set(&MixNode::use_clamp, true)
- .set("Fac", 1.0f))
- .add_connection("Gamma_Cx::Color", "Out::Color1")
- .add_connection("Gamma_xC::Color", "Out::Color2")
- .output_color("Out::Color");
-
- graph.finalize(scene);
+ EXPECT_ANY_MESSAGE(log);
+ INVALID_INFO_MESSAGE(log, "Folding Gamma_Cx::");
+ CORRECT_INFO_MESSAGE(log, "Folding Gamma_xC::Color to constant (1, 1, 1).");
+
+ builder
+ .add_attribute("Attribute")
+ /* constant on the left */
+ .add_node(
+ ShaderNodeBuilder<GammaNode>("Gamma_Cx").set("Color", make_float3(0.0f, 0.0f, 0.0f)))
+ .add_connection("Attribute::Fac", "Gamma_Cx::Gamma")
+ /* constant on the right */
+ .add_node(ShaderNodeBuilder<GammaNode>("Gamma_xC").set("Gamma", 0.0f))
+ .add_connection("Attribute::Color", "Gamma_xC::Color")
+ /* output sum */
+ .add_node(ShaderNodeBuilder<MixNode>("Out")
+ .set(&MixNode::type, NODE_MIX_ADD)
+ .set(&MixNode::use_clamp, true)
+ .set("Fac", 1.0f))
+ .add_connection("Gamma_Cx::Color", "Out::Color1")
+ .add_connection("Gamma_xC::Color", "Out::Color2")
+ .output_color("Out::Color");
+
+ graph.finalize(scene);
}
/*
@@ -932,30 +903,29 @@ TEST_F(RenderGraph, constant_fold_gamma_part_0)
*/
TEST_F(RenderGraph, constant_fold_gamma_part_1)
{
- EXPECT_ANY_MESSAGE(log);
- CORRECT_INFO_MESSAGE(log, "Folding Gamma_Cx::Color to constant (1, 1, 1).");
- CORRECT_INFO_MESSAGE(log, "Folding Gamma_xC::Color to socket Attribute::Color.");
-
- builder
- .add_attribute("Attribute")
- /* constant on the left */
- .add_node(ShaderNodeBuilder<GammaNode>("Gamma_Cx")
- .set("Color", make_float3(1.0f, 1.0f, 1.0f)))
- .add_connection("Attribute::Fac", "Gamma_Cx::Gamma")
- /* constant on the right */
- .add_node(ShaderNodeBuilder<GammaNode>("Gamma_xC")
- .set("Gamma", 1.0f))
- .add_connection("Attribute::Color", "Gamma_xC::Color")
- /* output sum */
- .add_node(ShaderNodeBuilder<MixNode>("Out")
- .set(&MixNode::type, NODE_MIX_ADD)
- .set(&MixNode::use_clamp, true)
- .set("Fac", 1.0f))
- .add_connection("Gamma_Cx::Color", "Out::Color1")
- .add_connection("Gamma_xC::Color", "Out::Color2")
- .output_color("Out::Color");
-
- graph.finalize(scene);
+ EXPECT_ANY_MESSAGE(log);
+ CORRECT_INFO_MESSAGE(log, "Folding Gamma_Cx::Color to constant (1, 1, 1).");
+ CORRECT_INFO_MESSAGE(log, "Folding Gamma_xC::Color to socket Attribute::Color.");
+
+ builder
+ .add_attribute("Attribute")
+ /* constant on the left */
+ .add_node(
+ ShaderNodeBuilder<GammaNode>("Gamma_Cx").set("Color", make_float3(1.0f, 1.0f, 1.0f)))
+ .add_connection("Attribute::Fac", "Gamma_Cx::Gamma")
+ /* constant on the right */
+ .add_node(ShaderNodeBuilder<GammaNode>("Gamma_xC").set("Gamma", 1.0f))
+ .add_connection("Attribute::Color", "Gamma_xC::Color")
+ /* output sum */
+ .add_node(ShaderNodeBuilder<MixNode>("Out")
+ .set(&MixNode::type, NODE_MIX_ADD)
+ .set(&MixNode::use_clamp, true)
+ .set("Fac", 1.0f))
+ .add_connection("Gamma_Cx::Color", "Out::Color1")
+ .add_connection("Gamma_xC::Color", "Out::Color2")
+ .output_color("Out::Color");
+
+ graph.finalize(scene);
}
/*
@@ -963,17 +933,17 @@ TEST_F(RenderGraph, constant_fold_gamma_part_1)
*/
TEST_F(RenderGraph, constant_fold_bright_contrast)
{
- EXPECT_ANY_MESSAGE(log);
- CORRECT_INFO_MESSAGE(log, "Folding BrightContrast::Color to constant (0.16, 0.6, 1.04).");
+ EXPECT_ANY_MESSAGE(log);
+ CORRECT_INFO_MESSAGE(log, "Folding BrightContrast::Color to constant (0.16, 0.6, 1.04).");
- builder
- .add_node(ShaderNodeBuilder<BrightContrastNode>("BrightContrast")
- .set("Color", make_float3(0.3f, 0.5f, 0.7f))
- .set("Bright", 0.1f)
- .set("Contrast", 1.2f))
- .output_color("BrightContrast::Color");
+ builder
+ .add_node(ShaderNodeBuilder<BrightContrastNode>("BrightContrast")
+ .set("Color", make_float3(0.3f, 0.5f, 0.7f))
+ .set("Bright", 0.1f)
+ .set("Contrast", 1.2f))
+ .output_color("BrightContrast::Color");
- graph.finalize(scene);
+ graph.finalize(scene);
}
/*
@@ -981,15 +951,13 @@ TEST_F(RenderGraph, constant_fold_bright_contrast)
*/
TEST_F(RenderGraph, constant_fold_blackbody)
{
- EXPECT_ANY_MESSAGE(log);
- CORRECT_INFO_MESSAGE(log, "Folding Blackbody::Color to constant (3.94163, 0.226523, 0).");
+ EXPECT_ANY_MESSAGE(log);
+ CORRECT_INFO_MESSAGE(log, "Folding Blackbody::Color to constant (3.94163, 0.226523, 0).");
- builder
- .add_node(ShaderNodeBuilder<BlackbodyNode>("Blackbody")
- .set("Temperature", 1200.0f))
- .output_color("Blackbody::Color");
+ builder.add_node(ShaderNodeBuilder<BlackbodyNode>("Blackbody").set("Temperature", 1200.0f))
+ .output_color("Blackbody::Color");
- graph.finalize(scene);
+ graph.finalize(scene);
}
/*
@@ -997,18 +965,18 @@ TEST_F(RenderGraph, constant_fold_blackbody)
*/
TEST_F(RenderGraph, constant_fold_math)
{
- EXPECT_ANY_MESSAGE(log);
- CORRECT_INFO_MESSAGE(log, "Folding Math::Value to constant (1.6).");
+ EXPECT_ANY_MESSAGE(log);
+ CORRECT_INFO_MESSAGE(log, "Folding Math::Value to constant (1.6).");
- builder
- .add_node(ShaderNodeBuilder<MathNode>("Math")
- .set(&MathNode::type, NODE_MATH_ADD)
- .set(&MathNode::use_clamp, false)
- .set("Value1", 0.7f)
- .set("Value2", 0.9f))
- .output_value("Math::Value");
+ builder
+ .add_node(ShaderNodeBuilder<MathNode>("Math")
+ .set(&MathNode::type, NODE_MATH_ADD)
+ .set(&MathNode::use_clamp, false)
+ .set("Value1", 0.7f)
+ .set("Value2", 0.9f))
+ .output_value("Math::Value");
- graph.finalize(scene);
+ graph.finalize(scene);
}
/*
@@ -1016,47 +984,49 @@ TEST_F(RenderGraph, constant_fold_math)
*/
TEST_F(RenderGraph, constant_fold_math_clamp)
{
- EXPECT_ANY_MESSAGE(log);
- CORRECT_INFO_MESSAGE(log, "Folding Math::Value to constant (1).");
+ EXPECT_ANY_MESSAGE(log);
+ CORRECT_INFO_MESSAGE(log, "Folding Math::Value to constant (1).");
- builder
- .add_node(ShaderNodeBuilder<MathNode>("Math")
- .set(&MathNode::type, NODE_MATH_ADD)
- .set(&MathNode::use_clamp, true)
- .set("Value1", 0.7f)
- .set("Value2", 0.9f))
- .output_value("Math::Value");
+ builder
+ .add_node(ShaderNodeBuilder<MathNode>("Math")
+ .set(&MathNode::type, NODE_MATH_ADD)
+ .set(&MathNode::use_clamp, true)
+ .set("Value1", 0.7f)
+ .set("Value2", 0.9f))
+ .output_value("Math::Value");
- graph.finalize(scene);
+ graph.finalize(scene);
}
/*
* Graph for testing partial folds of Math with one constant argument.
* Includes 2 tests: constant on each side.
*/
-static void build_math_partial_test_graph(ShaderGraphBuilder &builder, NodeMath type, float constval)
-{
- builder
- .add_attribute("Attribute")
- /* constant on the left */
- .add_node(ShaderNodeBuilder<MathNode>("Math_Cx")
- .set(&MathNode::type, type)
- .set(&MathNode::use_clamp, false)
- .set("Value1", constval))
- .add_connection("Attribute::Fac", "Math_Cx::Value2")
- /* constant on the right */
- .add_node(ShaderNodeBuilder<MathNode>("Math_xC")
- .set(&MathNode::type, type)
- .set(&MathNode::use_clamp, false)
- .set("Value2", constval))
- .add_connection("Attribute::Fac", "Math_xC::Value1")
- /* output sum */
- .add_node(ShaderNodeBuilder<MathNode>("Out")
- .set(&MathNode::type, NODE_MATH_ADD)
- .set(&MathNode::use_clamp, true))
- .add_connection("Math_Cx::Value", "Out::Value1")
- .add_connection("Math_xC::Value", "Out::Value2")
- .output_value("Out::Value");
+static void build_math_partial_test_graph(ShaderGraphBuilder &builder,
+ NodeMath type,
+ float constval)
+{
+ builder
+ .add_attribute("Attribute")
+ /* constant on the left */
+ .add_node(ShaderNodeBuilder<MathNode>("Math_Cx")
+ .set(&MathNode::type, type)
+ .set(&MathNode::use_clamp, false)
+ .set("Value1", constval))
+ .add_connection("Attribute::Fac", "Math_Cx::Value2")
+ /* constant on the right */
+ .add_node(ShaderNodeBuilder<MathNode>("Math_xC")
+ .set(&MathNode::type, type)
+ .set(&MathNode::use_clamp, false)
+ .set("Value2", constval))
+ .add_connection("Attribute::Fac", "Math_xC::Value1")
+ /* output sum */
+ .add_node(ShaderNodeBuilder<MathNode>("Out")
+ .set(&MathNode::type, NODE_MATH_ADD)
+ .set(&MathNode::use_clamp, true))
+ .add_connection("Math_Cx::Value", "Out::Value1")
+ .add_connection("Math_xC::Value", "Out::Value2")
+ .output_value("Out::Value");
}
/*
@@ -1064,14 +1034,14 @@ static void build_math_partial_test_graph(ShaderGraphBuilder &builder, NodeMath
*/
TEST_F(RenderGraph, constant_fold_part_math_add_0)
{
- EXPECT_ANY_MESSAGE(log);
- /* X + 0 == 0 + X == X */
- CORRECT_INFO_MESSAGE(log, "Folding Math_Cx::Value to socket Attribute::Fac.");
- CORRECT_INFO_MESSAGE(log, "Folding Math_xC::Value to socket Attribute::Fac.");
- INVALID_INFO_MESSAGE(log, "Folding Out::");
+ EXPECT_ANY_MESSAGE(log);
+ /* X + 0 == 0 + X == X */
+ CORRECT_INFO_MESSAGE(log, "Folding Math_Cx::Value to socket Attribute::Fac.");
+ CORRECT_INFO_MESSAGE(log, "Folding Math_xC::Value to socket Attribute::Fac.");
+ INVALID_INFO_MESSAGE(log, "Folding Out::");
- build_math_partial_test_graph(builder, NODE_MATH_ADD, 0.0f);
- graph.finalize(scene);
+ build_math_partial_test_graph(builder, NODE_MATH_ADD, 0.0f);
+ graph.finalize(scene);
}
/*
@@ -1079,14 +1049,14 @@ TEST_F(RenderGraph, constant_fold_part_math_add_0)
*/
TEST_F(RenderGraph, constant_fold_part_math_sub_0)
{
- EXPECT_ANY_MESSAGE(log);
- /* X - 0 == X */
- INVALID_INFO_MESSAGE(log, "Folding Math_Cx::");
- CORRECT_INFO_MESSAGE(log, "Folding Math_xC::Value to socket Attribute::Fac.");
- INVALID_INFO_MESSAGE(log, "Folding Out::");
+ EXPECT_ANY_MESSAGE(log);
+ /* X - 0 == X */
+ INVALID_INFO_MESSAGE(log, "Folding Math_Cx::");
+ CORRECT_INFO_MESSAGE(log, "Folding Math_xC::Value to socket Attribute::Fac.");
+ INVALID_INFO_MESSAGE(log, "Folding Out::");
- build_math_partial_test_graph(builder, NODE_MATH_SUBTRACT, 0.0f);
- graph.finalize(scene);
+ build_math_partial_test_graph(builder, NODE_MATH_SUBTRACT, 0.0f);
+ graph.finalize(scene);
}
/*
@@ -1094,14 +1064,14 @@ TEST_F(RenderGraph, constant_fold_part_math_sub_0)
*/
TEST_F(RenderGraph, constant_fold_part_math_mul_1)
{
- EXPECT_ANY_MESSAGE(log);
- /* X * 1 == 1 * X == X */
- CORRECT_INFO_MESSAGE(log, "Folding Math_Cx::Value to socket Attribute::Fac.");
- CORRECT_INFO_MESSAGE(log, "Folding Math_xC::Value to socket Attribute::Fac.");
- INVALID_INFO_MESSAGE(log, "Folding Out::");
+ EXPECT_ANY_MESSAGE(log);
+ /* X * 1 == 1 * X == X */
+ CORRECT_INFO_MESSAGE(log, "Folding Math_Cx::Value to socket Attribute::Fac.");
+ CORRECT_INFO_MESSAGE(log, "Folding Math_xC::Value to socket Attribute::Fac.");
+ INVALID_INFO_MESSAGE(log, "Folding Out::");
- build_math_partial_test_graph(builder, NODE_MATH_MULTIPLY, 1.0f);
- graph.finalize(scene);
+ build_math_partial_test_graph(builder, NODE_MATH_MULTIPLY, 1.0f);
+ graph.finalize(scene);
}
/*
@@ -1109,14 +1079,14 @@ TEST_F(RenderGraph, constant_fold_part_math_mul_1)
*/
TEST_F(RenderGraph, constant_fold_part_math_div_1)
{
- EXPECT_ANY_MESSAGE(log);
- /* X / 1 == X */
- INVALID_INFO_MESSAGE(log, "Folding Math_Cx::");
- CORRECT_INFO_MESSAGE(log, "Folding Math_xC::Value to socket Attribute::Fac.");
- INVALID_INFO_MESSAGE(log, "Folding Out::");
+ EXPECT_ANY_MESSAGE(log);
+ /* X / 1 == X */
+ INVALID_INFO_MESSAGE(log, "Folding Math_Cx::");
+ CORRECT_INFO_MESSAGE(log, "Folding Math_xC::Value to socket Attribute::Fac.");
+ INVALID_INFO_MESSAGE(log, "Folding Out::");
- build_math_partial_test_graph(builder, NODE_MATH_DIVIDE, 1.0f);
- graph.finalize(scene);
+ build_math_partial_test_graph(builder, NODE_MATH_DIVIDE, 1.0f);
+ graph.finalize(scene);
}
/*
@@ -1124,15 +1094,15 @@ TEST_F(RenderGraph, constant_fold_part_math_div_1)
*/
TEST_F(RenderGraph, constant_fold_part_math_mul_0)
{
- EXPECT_ANY_MESSAGE(log);
- /* X * 0 == 0 * X == 0 */
- CORRECT_INFO_MESSAGE(log, "Folding Math_Cx::Value to constant (0).");
- CORRECT_INFO_MESSAGE(log, "Folding Math_xC::Value to constant (0).");
- CORRECT_INFO_MESSAGE(log, "Folding Out::Value to constant (0)");
- CORRECT_INFO_MESSAGE(log, "Discarding closure EmissionNode.");
+ EXPECT_ANY_MESSAGE(log);
+ /* X * 0 == 0 * X == 0 */
+ CORRECT_INFO_MESSAGE(log, "Folding Math_Cx::Value to constant (0).");
+ CORRECT_INFO_MESSAGE(log, "Folding Math_xC::Value to constant (0).");
+ CORRECT_INFO_MESSAGE(log, "Folding Out::Value to constant (0)");
+ CORRECT_INFO_MESSAGE(log, "Discarding closure EmissionNode.");
- build_math_partial_test_graph(builder, NODE_MATH_MULTIPLY, 0.0f);
- graph.finalize(scene);
+ build_math_partial_test_graph(builder, NODE_MATH_MULTIPLY, 0.0f);
+ graph.finalize(scene);
}
/*
@@ -1140,14 +1110,14 @@ TEST_F(RenderGraph, constant_fold_part_math_mul_0)
*/
TEST_F(RenderGraph, constant_fold_part_math_div_0)
{
- EXPECT_ANY_MESSAGE(log);
- /* 0 / X == 0 */
- CORRECT_INFO_MESSAGE(log, "Folding Math_Cx::Value to constant (0).");
- INVALID_INFO_MESSAGE(log, "Folding Math_xC::");
- INVALID_INFO_MESSAGE(log, "Folding Out::");
+ EXPECT_ANY_MESSAGE(log);
+ /* 0 / X == 0 */
+ CORRECT_INFO_MESSAGE(log, "Folding Math_Cx::Value to constant (0).");
+ INVALID_INFO_MESSAGE(log, "Folding Math_xC::");
+ INVALID_INFO_MESSAGE(log, "Folding Out::");
- build_math_partial_test_graph(builder, NODE_MATH_DIVIDE, 0.0f);
- graph.finalize(scene);
+ build_math_partial_test_graph(builder, NODE_MATH_DIVIDE, 0.0f);
+ graph.finalize(scene);
}
/*
@@ -1155,14 +1125,14 @@ TEST_F(RenderGraph, constant_fold_part_math_div_0)
*/
TEST_F(RenderGraph, constant_fold_part_math_pow_0)
{
- EXPECT_ANY_MESSAGE(log);
- /* X ^ 0 == 1 */
- INVALID_INFO_MESSAGE(log, "Folding Math_Cx::");
- CORRECT_INFO_MESSAGE(log, "Folding Math_xC::Value to constant (1).");
- INVALID_INFO_MESSAGE(log, "Folding Out::");
+ EXPECT_ANY_MESSAGE(log);
+ /* X ^ 0 == 1 */
+ INVALID_INFO_MESSAGE(log, "Folding Math_Cx::");
+ CORRECT_INFO_MESSAGE(log, "Folding Math_xC::Value to constant (1).");
+ INVALID_INFO_MESSAGE(log, "Folding Out::");
- build_math_partial_test_graph(builder, NODE_MATH_POWER, 0.0f);
- graph.finalize(scene);
+ build_math_partial_test_graph(builder, NODE_MATH_POWER, 0.0f);
+ graph.finalize(scene);
}
/*
@@ -1170,14 +1140,14 @@ TEST_F(RenderGraph, constant_fold_part_math_pow_0)
*/
TEST_F(RenderGraph, constant_fold_part_math_pow_1)
{
- EXPECT_ANY_MESSAGE(log);
- /* 1 ^ X == 1; X ^ 1 == X */
- CORRECT_INFO_MESSAGE(log, "Folding Math_Cx::Value to constant (1)");
- CORRECT_INFO_MESSAGE(log, "Folding Math_xC::Value to socket Attribute::Fac.");
- INVALID_INFO_MESSAGE(log, "Folding Out::");
+ EXPECT_ANY_MESSAGE(log);
+ /* 1 ^ X == 1; X ^ 1 == X */
+ CORRECT_INFO_MESSAGE(log, "Folding Math_Cx::Value to constant (1)");
+ CORRECT_INFO_MESSAGE(log, "Folding Math_xC::Value to socket Attribute::Fac.");
+ INVALID_INFO_MESSAGE(log, "Folding Out::");
- build_math_partial_test_graph(builder, NODE_MATH_POWER, 1.0f);
- graph.finalize(scene);
+ build_math_partial_test_graph(builder, NODE_MATH_POWER, 1.0f);
+ graph.finalize(scene);
}
/*
@@ -1185,51 +1155,52 @@ TEST_F(RenderGraph, constant_fold_part_math_pow_1)
*/
TEST_F(RenderGraph, constant_fold_vector_math)
{
- EXPECT_ANY_MESSAGE(log);
- CORRECT_INFO_MESSAGE(log, "Folding VectorMath::Value to constant (1).");
- CORRECT_INFO_MESSAGE(log, "Folding VectorMath::Vector to constant (3, 0, 0).");
- CORRECT_INFO_MESSAGE(log, "Folding convert_vector_to_float::value_float to constant (1).");
- CORRECT_INFO_MESSAGE(log, "Folding Math::Value to constant (2).");
- CORRECT_INFO_MESSAGE(log, "Folding convert_float_to_color::value_color to constant (2, 2, 2).");
+ EXPECT_ANY_MESSAGE(log);
+ CORRECT_INFO_MESSAGE(log, "Folding VectorMath::Value to constant (1).");
+ CORRECT_INFO_MESSAGE(log, "Folding VectorMath::Vector to constant (3, 0, 0).");
+ CORRECT_INFO_MESSAGE(log, "Folding convert_vector_to_float::value_float to constant (1).");
+ CORRECT_INFO_MESSAGE(log, "Folding Math::Value to constant (2).");
+ CORRECT_INFO_MESSAGE(log, "Folding convert_float_to_color::value_color to constant (2, 2, 2).");
- builder
- .add_node(ShaderNodeBuilder<VectorMathNode>("VectorMath")
- .set(&VectorMathNode::type, NODE_VECTOR_MATH_SUBTRACT)
- .set("Vector1", make_float3(1.3f, 0.5f, 0.7f))
- .set("Vector2", make_float3(-1.7f, 0.5f, 0.7f)))
- .add_node(ShaderNodeBuilder<MathNode>("Math")
- .set(&MathNode::type, NODE_MATH_ADD))
- .add_connection("VectorMath::Vector", "Math::Value1")
- .add_connection("VectorMath::Value", "Math::Value2")
- .output_color("Math::Value");
+ builder
+ .add_node(ShaderNodeBuilder<VectorMathNode>("VectorMath")
+ .set(&VectorMathNode::type, NODE_VECTOR_MATH_SUBTRACT)
+ .set("Vector1", make_float3(1.3f, 0.5f, 0.7f))
+ .set("Vector2", make_float3(-1.7f, 0.5f, 0.7f)))
+ .add_node(ShaderNodeBuilder<MathNode>("Math").set(&MathNode::type, NODE_MATH_ADD))
+ .add_connection("VectorMath::Vector", "Math::Value1")
+ .add_connection("VectorMath::Value", "Math::Value2")
+ .output_color("Math::Value");
- graph.finalize(scene);
+ graph.finalize(scene);
}
/*
* Graph for testing partial folds of Vector Math with one constant argument.
* Includes 2 tests: constant on each side.
*/
-static void build_vecmath_partial_test_graph(ShaderGraphBuilder &builder, NodeVectorMath type, float3 constval)
-{
- builder
- .add_attribute("Attribute")
- /* constant on the left */
- .add_node(ShaderNodeBuilder<VectorMathNode>("Math_Cx")
- .set(&VectorMathNode::type, type)
- .set("Vector1", constval))
- .add_connection("Attribute::Vector", "Math_Cx::Vector2")
- /* constant on the right */
- .add_node(ShaderNodeBuilder<VectorMathNode>("Math_xC")
- .set(&VectorMathNode::type, type)
- .set("Vector2", constval))
- .add_connection("Attribute::Vector", "Math_xC::Vector1")
- /* output sum */
- .add_node(ShaderNodeBuilder<VectorMathNode>("Out")
- .set(&VectorMathNode::type, NODE_VECTOR_MATH_ADD))
- .add_connection("Math_Cx::Vector", "Out::Vector1")
- .add_connection("Math_xC::Vector", "Out::Vector2")
- .output_color("Out::Vector");
+static void build_vecmath_partial_test_graph(ShaderGraphBuilder &builder,
+ NodeVectorMath type,
+ float3 constval)
+{
+ builder
+ .add_attribute("Attribute")
+ /* constant on the left */
+ .add_node(ShaderNodeBuilder<VectorMathNode>("Math_Cx")
+ .set(&VectorMathNode::type, type)
+ .set("Vector1", constval))
+ .add_connection("Attribute::Vector", "Math_Cx::Vector2")
+ /* constant on the right */
+ .add_node(ShaderNodeBuilder<VectorMathNode>("Math_xC")
+ .set(&VectorMathNode::type, type)
+ .set("Vector2", constval))
+ .add_connection("Attribute::Vector", "Math_xC::Vector1")
+ /* output sum */
+ .add_node(ShaderNodeBuilder<VectorMathNode>("Out").set(&VectorMathNode::type,
+ NODE_VECTOR_MATH_ADD))
+ .add_connection("Math_Cx::Vector", "Out::Vector1")
+ .add_connection("Math_xC::Vector", "Out::Vector2")
+ .output_color("Out::Vector");
}
/*
@@ -1237,14 +1208,14 @@ static void build_vecmath_partial_test_graph(ShaderGraphBuilder &builder, NodeVe
*/
TEST_F(RenderGraph, constant_fold_part_vecmath_add_0)
{
- EXPECT_ANY_MESSAGE(log);
- /* X + 0 == 0 + X == X */
- CORRECT_INFO_MESSAGE(log, "Folding Math_Cx::Vector to socket Attribute::Vector.");
- CORRECT_INFO_MESSAGE(log, "Folding Math_xC::Vector to socket Attribute::Vector.");
- INVALID_INFO_MESSAGE(log, "Folding Out::");
+ EXPECT_ANY_MESSAGE(log);
+ /* X + 0 == 0 + X == X */
+ CORRECT_INFO_MESSAGE(log, "Folding Math_Cx::Vector to socket Attribute::Vector.");
+ CORRECT_INFO_MESSAGE(log, "Folding Math_xC::Vector to socket Attribute::Vector.");
+ INVALID_INFO_MESSAGE(log, "Folding Out::");
- build_vecmath_partial_test_graph(builder, NODE_VECTOR_MATH_ADD, make_float3(0,0,0));
- graph.finalize(scene);
+ build_vecmath_partial_test_graph(builder, NODE_VECTOR_MATH_ADD, make_float3(0, 0, 0));
+ graph.finalize(scene);
}
/*
@@ -1252,14 +1223,14 @@ TEST_F(RenderGraph, constant_fold_part_vecmath_add_0)
*/
TEST_F(RenderGraph, constant_fold_part_vecmath_sub_0)
{
- EXPECT_ANY_MESSAGE(log);
- /* X - 0 == X */
- INVALID_INFO_MESSAGE(log, "Folding Math_Cx::");
- CORRECT_INFO_MESSAGE(log, "Folding Math_xC::Vector to socket Attribute::Vector.");
- INVALID_INFO_MESSAGE(log, "Folding Out::");
+ EXPECT_ANY_MESSAGE(log);
+ /* X - 0 == X */
+ INVALID_INFO_MESSAGE(log, "Folding Math_Cx::");
+ CORRECT_INFO_MESSAGE(log, "Folding Math_xC::Vector to socket Attribute::Vector.");
+ INVALID_INFO_MESSAGE(log, "Folding Out::");
- build_vecmath_partial_test_graph(builder, NODE_VECTOR_MATH_SUBTRACT, make_float3(0,0,0));
- graph.finalize(scene);
+ build_vecmath_partial_test_graph(builder, NODE_VECTOR_MATH_SUBTRACT, make_float3(0, 0, 0));
+ graph.finalize(scene);
}
/*
@@ -1267,15 +1238,15 @@ TEST_F(RenderGraph, constant_fold_part_vecmath_sub_0)
*/
TEST_F(RenderGraph, constant_fold_part_vecmath_dot_0)
{
- EXPECT_ANY_MESSAGE(log);
- /* X * 0 == 0 * X == X */
- CORRECT_INFO_MESSAGE(log, "Folding Math_Cx::Vector to constant (0, 0, 0).");
- CORRECT_INFO_MESSAGE(log, "Folding Math_xC::Vector to constant (0, 0, 0).");
- CORRECT_INFO_MESSAGE(log, "Folding Out::Vector to constant (0, 0, 0).");
- CORRECT_INFO_MESSAGE(log, "Discarding closure EmissionNode.");
+ EXPECT_ANY_MESSAGE(log);
+ /* X * 0 == 0 * X == X */
+ CORRECT_INFO_MESSAGE(log, "Folding Math_Cx::Vector to constant (0, 0, 0).");
+ CORRECT_INFO_MESSAGE(log, "Folding Math_xC::Vector to constant (0, 0, 0).");
+ CORRECT_INFO_MESSAGE(log, "Folding Out::Vector to constant (0, 0, 0).");
+ CORRECT_INFO_MESSAGE(log, "Discarding closure EmissionNode.");
- build_vecmath_partial_test_graph(builder, NODE_VECTOR_MATH_DOT_PRODUCT, make_float3(0,0,0));
- graph.finalize(scene);
+ build_vecmath_partial_test_graph(builder, NODE_VECTOR_MATH_DOT_PRODUCT, make_float3(0, 0, 0));
+ graph.finalize(scene);
}
/*
@@ -1283,15 +1254,15 @@ TEST_F(RenderGraph, constant_fold_part_vecmath_dot_0)
*/
TEST_F(RenderGraph, constant_fold_part_vecmath_cross_0)
{
- EXPECT_ANY_MESSAGE(log);
- /* X * 0 == 0 * X == X */
- CORRECT_INFO_MESSAGE(log, "Folding Math_Cx::Vector to constant (0, 0, 0).");
- CORRECT_INFO_MESSAGE(log, "Folding Math_xC::Vector to constant (0, 0, 0).");
- CORRECT_INFO_MESSAGE(log, "Folding Out::Vector to constant (0, 0, 0).");
- CORRECT_INFO_MESSAGE(log, "Discarding closure EmissionNode.");
+ EXPECT_ANY_MESSAGE(log);
+ /* X * 0 == 0 * X == X */
+ CORRECT_INFO_MESSAGE(log, "Folding Math_Cx::Vector to constant (0, 0, 0).");
+ CORRECT_INFO_MESSAGE(log, "Folding Math_xC::Vector to constant (0, 0, 0).");
+ CORRECT_INFO_MESSAGE(log, "Folding Out::Vector to constant (0, 0, 0).");
+ CORRECT_INFO_MESSAGE(log, "Discarding closure EmissionNode.");
- build_vecmath_partial_test_graph(builder, NODE_VECTOR_MATH_CROSS_PRODUCT, make_float3(0,0,0));
- graph.finalize(scene);
+ build_vecmath_partial_test_graph(builder, NODE_VECTOR_MATH_CROSS_PRODUCT, make_float3(0, 0, 0));
+ graph.finalize(scene);
}
/*
@@ -1299,16 +1270,15 @@ TEST_F(RenderGraph, constant_fold_part_vecmath_cross_0)
*/
TEST_F(RenderGraph, constant_fold_bump)
{
- EXPECT_ANY_MESSAGE(log);
- CORRECT_INFO_MESSAGE(log, "Folding Bump::Normal to socket Geometry1::Normal.");
+ EXPECT_ANY_MESSAGE(log);
+ CORRECT_INFO_MESSAGE(log, "Folding Bump::Normal to socket Geometry1::Normal.");
- builder
- .add_node(ShaderNodeBuilder<GeometryNode>("Geometry1"))
- .add_node(ShaderNodeBuilder<BumpNode>("Bump"))
- .add_connection("Geometry1::Normal", "Bump::Normal")
- .output_color("Bump::Normal");
+ builder.add_node(ShaderNodeBuilder<GeometryNode>("Geometry1"))
+ .add_node(ShaderNodeBuilder<BumpNode>("Bump"))
+ .add_connection("Geometry1::Normal", "Bump::Normal")
+ .output_color("Bump::Normal");
- graph.finalize(scene);
+ graph.finalize(scene);
}
/*
@@ -1316,24 +1286,21 @@ TEST_F(RenderGraph, constant_fold_bump)
*/
TEST_F(RenderGraph, constant_fold_bump_no_input)
{
- EXPECT_ANY_MESSAGE(log);
- CORRECT_INFO_MESSAGE(log, "Folding Bump::Normal to socket geometry::Normal.");
+ EXPECT_ANY_MESSAGE(log);
+ CORRECT_INFO_MESSAGE(log, "Folding Bump::Normal to socket geometry::Normal.");
- builder
- .add_node(ShaderNodeBuilder<BumpNode>("Bump"))
- .output_color("Bump::Normal");
+ builder.add_node(ShaderNodeBuilder<BumpNode>("Bump")).output_color("Bump::Normal");
- graph.finalize(scene);
+ graph.finalize(scene);
}
-template<class T>
-void init_test_curve(array<T> &buffer, T start, T end, int steps)
+template<class T> void init_test_curve(array<T> &buffer, T start, T end, int steps)
{
- buffer.resize(steps);
+ buffer.resize(steps);
- for(int i = 0; i < steps; i++) {
- buffer[i] = lerp(start, end, float(i)/(steps-1));
- }
+ for (int i = 0; i < steps; i++) {
+ buffer[i] = lerp(start, end, float(i) / (steps - 1));
+ }
}
/*
@@ -1342,22 +1309,22 @@ void init_test_curve(array<T> &buffer, T start, T end, int steps)
*/
TEST_F(RenderGraph, constant_fold_rgb_curves)
{
- EXPECT_ANY_MESSAGE(log);
- CORRECT_INFO_MESSAGE(log, "Folding Curves::Color to constant (0.275, 0.5, 0.475).");
+ EXPECT_ANY_MESSAGE(log);
+ CORRECT_INFO_MESSAGE(log, "Folding Curves::Color to constant (0.275, 0.5, 0.475).");
- array<float3> curve;
- init_test_curve(curve, make_float3(0.0f, 0.25f, 1.0f), make_float3(1.0f, 0.75f, 0.0f), 257);
+ array<float3> curve;
+ init_test_curve(curve, make_float3(0.0f, 0.25f, 1.0f), make_float3(1.0f, 0.75f, 0.0f), 257);
- builder
- .add_node(ShaderNodeBuilder<RGBCurvesNode>("Curves")
- .set(&CurvesNode::curves, curve)
- .set(&CurvesNode::min_x, 0.1f)
- .set(&CurvesNode::max_x, 0.9f)
- .set("Fac", 0.5f)
- .set("Color", make_float3(0.3f, 0.5f, 0.7f)))
- .output_color("Curves::Color");
+ builder
+ .add_node(ShaderNodeBuilder<RGBCurvesNode>("Curves")
+ .set(&CurvesNode::curves, curve)
+ .set(&CurvesNode::min_x, 0.1f)
+ .set(&CurvesNode::max_x, 0.9f)
+ .set("Fac", 0.5f)
+ .set("Color", make_float3(0.3f, 0.5f, 0.7f)))
+ .output_color("Curves::Color");
- graph.finalize(scene);
+ graph.finalize(scene);
}
/*
@@ -1366,48 +1333,46 @@ TEST_F(RenderGraph, constant_fold_rgb_curves)
*/
TEST_F(RenderGraph, constant_fold_rgb_curves_fac_0)
{
- EXPECT_ANY_MESSAGE(log);
- CORRECT_INFO_MESSAGE(log, "Folding Curves::Color to socket Attribute::Color.");
+ EXPECT_ANY_MESSAGE(log);
+ CORRECT_INFO_MESSAGE(log, "Folding Curves::Color to socket Attribute::Color.");
- array<float3> curve;
- init_test_curve(curve, make_float3(0.0f, 0.25f, 1.0f), make_float3(1.0f, 0.75f, 0.0f), 257);
+ array<float3> curve;
+ init_test_curve(curve, make_float3(0.0f, 0.25f, 1.0f), make_float3(1.0f, 0.75f, 0.0f), 257);
- builder
- .add_attribute("Attribute")
- .add_node(ShaderNodeBuilder<RGBCurvesNode>("Curves")
- .set(&CurvesNode::curves, curve)
- .set(&CurvesNode::min_x, 0.1f)
- .set(&CurvesNode::max_x, 0.9f)
- .set("Fac", 0.0f))
- .add_connection("Attribute::Color", "Curves::Color")
- .output_color("Curves::Color");
+ builder.add_attribute("Attribute")
+ .add_node(ShaderNodeBuilder<RGBCurvesNode>("Curves")
+ .set(&CurvesNode::curves, curve)
+ .set(&CurvesNode::min_x, 0.1f)
+ .set(&CurvesNode::max_x, 0.9f)
+ .set("Fac", 0.0f))
+ .add_connection("Attribute::Color", "Curves::Color")
+ .output_color("Curves::Color");
- graph.finalize(scene);
+ graph.finalize(scene);
}
-
/*
* Tests:
* - Folding of RGB Curves with zero Fac and all constant inputs.
*/
TEST_F(RenderGraph, constant_fold_rgb_curves_fac_0_const)
{
- EXPECT_ANY_MESSAGE(log);
- CORRECT_INFO_MESSAGE(log, "Folding Curves::Color to constant (0.3, 0.5, 0.7).");
+ EXPECT_ANY_MESSAGE(log);
+ CORRECT_INFO_MESSAGE(log, "Folding Curves::Color to constant (0.3, 0.5, 0.7).");
- array<float3> curve;
- init_test_curve(curve, make_float3(0.0f, 0.25f, 1.0f), make_float3(1.0f, 0.75f, 0.0f), 257);
+ array<float3> curve;
+ init_test_curve(curve, make_float3(0.0f, 0.25f, 1.0f), make_float3(1.0f, 0.75f, 0.0f), 257);
- builder
- .add_node(ShaderNodeBuilder<RGBCurvesNode>("Curves")
- .set(&CurvesNode::curves, curve)
- .set(&CurvesNode::min_x, 0.1f)
- .set(&CurvesNode::max_x, 0.9f)
- .set("Fac", 0.0f)
- .set("Color", make_float3(0.3f, 0.5f, 0.7f)))
- .output_color("Curves::Color");
+ builder
+ .add_node(ShaderNodeBuilder<RGBCurvesNode>("Curves")
+ .set(&CurvesNode::curves, curve)
+ .set(&CurvesNode::min_x, 0.1f)
+ .set(&CurvesNode::max_x, 0.9f)
+ .set("Fac", 0.0f)
+ .set("Color", make_float3(0.3f, 0.5f, 0.7f)))
+ .output_color("Curves::Color");
- graph.finalize(scene);
+ graph.finalize(scene);
}
/*
@@ -1416,22 +1381,22 @@ TEST_F(RenderGraph, constant_fold_rgb_curves_fac_0_const)
*/
TEST_F(RenderGraph, constant_fold_vector_curves)
{
- EXPECT_ANY_MESSAGE(log);
- CORRECT_INFO_MESSAGE(log, "Folding Curves::Vector to constant (0.275, 0.5, 0.475).");
+ EXPECT_ANY_MESSAGE(log);
+ CORRECT_INFO_MESSAGE(log, "Folding Curves::Vector to constant (0.275, 0.5, 0.475).");
- array<float3> curve;
- init_test_curve(curve, make_float3(0.0f, 0.25f, 1.0f), make_float3(1.0f, 0.75f, 0.0f), 257);
+ array<float3> curve;
+ init_test_curve(curve, make_float3(0.0f, 0.25f, 1.0f), make_float3(1.0f, 0.75f, 0.0f), 257);
- builder
- .add_node(ShaderNodeBuilder<VectorCurvesNode>("Curves")
- .set(&CurvesNode::curves, curve)
- .set(&CurvesNode::min_x, 0.1f)
- .set(&CurvesNode::max_x, 0.9f)
- .set("Fac", 0.5f)
- .set("Vector", make_float3(0.3f, 0.5f, 0.7f)))
- .output_color("Curves::Vector");
+ builder
+ .add_node(ShaderNodeBuilder<VectorCurvesNode>("Curves")
+ .set(&CurvesNode::curves, curve)
+ .set(&CurvesNode::min_x, 0.1f)
+ .set(&CurvesNode::max_x, 0.9f)
+ .set("Fac", 0.5f)
+ .set("Vector", make_float3(0.3f, 0.5f, 0.7f)))
+ .output_color("Curves::Vector");
- graph.finalize(scene);
+ graph.finalize(scene);
}
/*
@@ -1440,23 +1405,22 @@ TEST_F(RenderGraph, constant_fold_vector_curves)
*/
TEST_F(RenderGraph, constant_fold_vector_curves_fac_0)
{
- EXPECT_ANY_MESSAGE(log);
- CORRECT_INFO_MESSAGE(log, "Folding Curves::Vector to socket Attribute::Vector.");
+ EXPECT_ANY_MESSAGE(log);
+ CORRECT_INFO_MESSAGE(log, "Folding Curves::Vector to socket Attribute::Vector.");
- array<float3> curve;
- init_test_curve(curve, make_float3(0.0f, 0.25f, 1.0f), make_float3(1.0f, 0.75f, 0.0f), 257);
+ array<float3> curve;
+ init_test_curve(curve, make_float3(0.0f, 0.25f, 1.0f), make_float3(1.0f, 0.75f, 0.0f), 257);
- builder
- .add_attribute("Attribute")
- .add_node(ShaderNodeBuilder<VectorCurvesNode>("Curves")
- .set(&CurvesNode::curves, curve)
- .set(&CurvesNode::min_x, 0.1f)
- .set(&CurvesNode::max_x, 0.9f)
- .set("Fac", 0.0f))
- .add_connection("Attribute::Vector", "Curves::Vector")
- .output_color("Curves::Vector");
+ builder.add_attribute("Attribute")
+ .add_node(ShaderNodeBuilder<VectorCurvesNode>("Curves")
+ .set(&CurvesNode::curves, curve)
+ .set(&CurvesNode::min_x, 0.1f)
+ .set(&CurvesNode::max_x, 0.9f)
+ .set("Fac", 0.0f))
+ .add_connection("Attribute::Vector", "Curves::Vector")
+ .output_color("Curves::Vector");
- graph.finalize(scene);
+ graph.finalize(scene);
}
/*
@@ -1465,28 +1429,27 @@ TEST_F(RenderGraph, constant_fold_vector_curves_fac_0)
*/
TEST_F(RenderGraph, constant_fold_rgb_ramp)
{
- EXPECT_ANY_MESSAGE(log);
- CORRECT_INFO_MESSAGE(log, "Folding Ramp::Color to constant (0.14, 0.39, 0.64).");
- CORRECT_INFO_MESSAGE(log, "Folding Ramp::Alpha to constant (0.89).");
+ EXPECT_ANY_MESSAGE(log);
+ CORRECT_INFO_MESSAGE(log, "Folding Ramp::Color to constant (0.14, 0.39, 0.64).");
+ CORRECT_INFO_MESSAGE(log, "Folding Ramp::Alpha to constant (0.89).");
- array<float3> curve;
- array<float> alpha;
- init_test_curve(curve, make_float3(0.0f, 0.25f, 0.5f), make_float3(0.25f, 0.5f, 0.75f), 9);
- init_test_curve(alpha, 0.75f, 1.0f, 9);
+ array<float3> curve;
+ array<float> alpha;
+ init_test_curve(curve, make_float3(0.0f, 0.25f, 0.5f), make_float3(0.25f, 0.5f, 0.75f), 9);
+ init_test_curve(alpha, 0.75f, 1.0f, 9);
- builder
- .add_node(ShaderNodeBuilder<RGBRampNode>("Ramp")
- .set(&RGBRampNode::ramp, curve)
- .set(&RGBRampNode::ramp_alpha, alpha)
- .set(&RGBRampNode::interpolate, true)
- .set("Fac", 0.56f))
- .add_node(ShaderNodeBuilder<MixNode>("Mix")
- .set(&MixNode::type, NODE_MIX_ADD))
- .add_connection("Ramp::Color", "Mix::Color1")
- .add_connection("Ramp::Alpha", "Mix::Color2")
- .output_color("Mix::Color");
+ builder
+ .add_node(ShaderNodeBuilder<RGBRampNode>("Ramp")
+ .set(&RGBRampNode::ramp, curve)
+ .set(&RGBRampNode::ramp_alpha, alpha)
+ .set(&RGBRampNode::interpolate, true)
+ .set("Fac", 0.56f))
+ .add_node(ShaderNodeBuilder<MixNode>("Mix").set(&MixNode::type, NODE_MIX_ADD))
+ .add_connection("Ramp::Color", "Mix::Color1")
+ .add_connection("Ramp::Alpha", "Mix::Color2")
+ .output_color("Mix::Color");
- graph.finalize(scene);
+ graph.finalize(scene);
}
/*
@@ -1495,28 +1458,27 @@ TEST_F(RenderGraph, constant_fold_rgb_ramp)
*/
TEST_F(RenderGraph, constant_fold_rgb_ramp_flat)
{
- EXPECT_ANY_MESSAGE(log);
- CORRECT_INFO_MESSAGE(log, "Folding Ramp::Color to constant (0.125, 0.375, 0.625).");
- CORRECT_INFO_MESSAGE(log, "Folding Ramp::Alpha to constant (0.875).");
+ EXPECT_ANY_MESSAGE(log);
+ CORRECT_INFO_MESSAGE(log, "Folding Ramp::Color to constant (0.125, 0.375, 0.625).");
+ CORRECT_INFO_MESSAGE(log, "Folding Ramp::Alpha to constant (0.875).");
- array<float3> curve;
- array<float> alpha;
- init_test_curve(curve, make_float3(0.0f, 0.25f, 0.5f), make_float3(0.25f, 0.5f, 0.75f), 9);
- init_test_curve(alpha, 0.75f, 1.0f, 9);
+ array<float3> curve;
+ array<float> alpha;
+ init_test_curve(curve, make_float3(0.0f, 0.25f, 0.5f), make_float3(0.25f, 0.5f, 0.75f), 9);
+ init_test_curve(alpha, 0.75f, 1.0f, 9);
- builder
- .add_node(ShaderNodeBuilder<RGBRampNode>("Ramp")
- .set(&RGBRampNode::ramp, curve)
- .set(&RGBRampNode::ramp_alpha, alpha)
- .set(&RGBRampNode::interpolate, false)
- .set("Fac", 0.56f))
- .add_node(ShaderNodeBuilder<MixNode>("Mix")
- .set(&MixNode::type, NODE_MIX_ADD))
- .add_connection("Ramp::Color", "Mix::Color1")
- .add_connection("Ramp::Alpha", "Mix::Color2")
- .output_color("Mix::Color");
+ builder
+ .add_node(ShaderNodeBuilder<RGBRampNode>("Ramp")
+ .set(&RGBRampNode::ramp, curve)
+ .set(&RGBRampNode::ramp_alpha, alpha)
+ .set(&RGBRampNode::interpolate, false)
+ .set("Fac", 0.56f))
+ .add_node(ShaderNodeBuilder<MixNode>("Mix").set(&MixNode::type, NODE_MIX_ADD))
+ .add_connection("Ramp::Color", "Mix::Color1")
+ .add_connection("Ramp::Alpha", "Mix::Color2")
+ .output_color("Mix::Color");
- graph.finalize(scene);
+ graph.finalize(scene);
}
/*
@@ -1525,18 +1487,18 @@ TEST_F(RenderGraph, constant_fold_rgb_ramp_flat)
*/
TEST_F(RenderGraph, constant_fold_convert_float_color_float)
{
- EXPECT_ANY_MESSAGE(log);
- CORRECT_INFO_MESSAGE(log, "Folding Invert::Color to socket convert_float_to_color::value_color.");
- CORRECT_INFO_MESSAGE(log, "Folding convert_color_to_float::value_float to socket Attribute::Fac.");
+ EXPECT_ANY_MESSAGE(log);
+ CORRECT_INFO_MESSAGE(log,
+ "Folding Invert::Color to socket convert_float_to_color::value_color.");
+ CORRECT_INFO_MESSAGE(log,
+ "Folding convert_color_to_float::value_float to socket Attribute::Fac.");
- builder
- .add_attribute("Attribute")
- .add_node(ShaderNodeBuilder<InvertNode>("Invert")
- .set("Fac", 0.0f))
- .add_connection("Attribute::Fac", "Invert::Color")
- .output_value("Invert::Color");
+ builder.add_attribute("Attribute")
+ .add_node(ShaderNodeBuilder<InvertNode>("Invert").set("Fac", 0.0f))
+ .add_connection("Attribute::Fac", "Invert::Color")
+ .output_value("Invert::Color");
- graph.finalize(scene);
+ graph.finalize(scene);
}
/*
@@ -1545,19 +1507,20 @@ TEST_F(RenderGraph, constant_fold_convert_float_color_float)
*/
TEST_F(RenderGraph, constant_fold_convert_color_vector_color)
{
- EXPECT_ANY_MESSAGE(log);
- CORRECT_INFO_MESSAGE(log, "Folding VecAdd::Vector to socket convert_color_to_vector::value_vector.");
- CORRECT_INFO_MESSAGE(log, "Folding convert_vector_to_color::value_color to socket Attribute::Color.");
+ EXPECT_ANY_MESSAGE(log);
+ CORRECT_INFO_MESSAGE(log,
+ "Folding VecAdd::Vector to socket convert_color_to_vector::value_vector.");
+ CORRECT_INFO_MESSAGE(log,
+ "Folding convert_vector_to_color::value_color to socket Attribute::Color.");
- builder
- .add_attribute("Attribute")
- .add_node(ShaderNodeBuilder<VectorMathNode>("VecAdd")
- .set(&VectorMathNode::type, NODE_VECTOR_MATH_ADD)
- .set("Vector2", make_float3(0,0,0)))
- .add_connection("Attribute::Color", "VecAdd::Vector1")
- .output_color("VecAdd::Vector");
+ builder.add_attribute("Attribute")
+ .add_node(ShaderNodeBuilder<VectorMathNode>("VecAdd")
+ .set(&VectorMathNode::type, NODE_VECTOR_MATH_ADD)
+ .set("Vector2", make_float3(0, 0, 0)))
+ .add_connection("Attribute::Color", "VecAdd::Vector1")
+ .output_color("VecAdd::Vector");
- graph.finalize(scene);
+ graph.finalize(scene);
}
/*
@@ -1566,19 +1529,19 @@ TEST_F(RenderGraph, constant_fold_convert_color_vector_color)
*/
TEST_F(RenderGraph, constant_fold_convert_color_float_color)
{
- EXPECT_ANY_MESSAGE(log);
- CORRECT_INFO_MESSAGE(log, "Folding MathAdd::Value to socket convert_color_to_float::value_float.");
- INVALID_INFO_MESSAGE(log, "Folding convert_float_to_color::");
+ EXPECT_ANY_MESSAGE(log);
+ CORRECT_INFO_MESSAGE(log,
+ "Folding MathAdd::Value to socket convert_color_to_float::value_float.");
+ INVALID_INFO_MESSAGE(log, "Folding convert_float_to_color::");
- builder
- .add_attribute("Attribute")
- .add_node(ShaderNodeBuilder<MathNode>("MathAdd")
- .set(&MathNode::type, NODE_MATH_ADD)
- .set("Value2", 0.0f))
- .add_connection("Attribute::Color", "MathAdd::Value1")
- .output_color("MathAdd::Value");
+ builder.add_attribute("Attribute")
+ .add_node(ShaderNodeBuilder<MathNode>("MathAdd")
+ .set(&MathNode::type, NODE_MATH_ADD)
+ .set("Value2", 0.0f))
+ .add_connection("Attribute::Color", "MathAdd::Value1")
+ .output_color("MathAdd::Value");
- graph.finalize(scene);
+ graph.finalize(scene);
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/test/util_aligned_malloc_test.cpp b/intern/cycles/test/util_aligned_malloc_test.cpp
index 9fb3aad0c3f..8829c422a0f 100644
--- a/intern/cycles/test/util_aligned_malloc_test.cpp
+++ b/intern/cycles/test/util_aligned_malloc_test.cpp
@@ -24,19 +24,19 @@ CCL_NAMESPACE_BEGIN
TEST(util_aligned_malloc, aligned_malloc_16)
{
- int *mem = (int*)util_aligned_malloc(sizeof(int), 16);
- CHECK_ALIGNMENT(mem, 16);
- util_aligned_free(mem);
+ int *mem = (int *)util_aligned_malloc(sizeof(int), 16);
+ CHECK_ALIGNMENT(mem, 16);
+ util_aligned_free(mem);
}
/* On Apple we currently only support 16 bytes alignment. */
#ifndef __APPLE__
TEST(util_aligned_malloc, aligned_malloc_32)
{
- int *mem = (int*)util_aligned_malloc(sizeof(int), 32);
- CHECK_ALIGNMENT(mem, 32);
- util_aligned_free(mem);
+ int *mem = (int *)util_aligned_malloc(sizeof(int), 32);
+ CHECK_ALIGNMENT(mem, 32);
+ util_aligned_free(mem);
}
-#endif /* __APPLE__ */
+#endif /* __APPLE__ */
CCL_NAMESPACE_END
diff --git a/intern/cycles/test/util_path_test.cpp b/intern/cycles/test/util_path_test.cpp
index 1df568493d8..76d48dc241d 100644
--- a/intern/cycles/test/util_path_test.cpp
+++ b/intern/cycles/test/util_path_test.cpp
@@ -25,377 +25,377 @@ CCL_NAMESPACE_BEGIN
#ifndef _WIN32
TEST(util_path_filename, simple_unix)
{
- string str = path_filename("/tmp/foo.txt");
- EXPECT_EQ(str, "foo.txt");
+ string str = path_filename("/tmp/foo.txt");
+ EXPECT_EQ(str, "foo.txt");
}
TEST(util_path_filename, root_unix)
{
- string str = path_filename("/");
- EXPECT_EQ(str, "/");
+ string str = path_filename("/");
+ EXPECT_EQ(str, "/");
}
TEST(util_path_filename, last_slash_unix)
{
- string str = path_filename("/tmp/foo.txt/");
- EXPECT_EQ(str, ".");
+ string str = path_filename("/tmp/foo.txt/");
+ EXPECT_EQ(str, ".");
}
TEST(util_path_filename, alternate_slash_unix)
{
- string str = path_filename("/tmp\\foo.txt");
- EXPECT_EQ(str, "tmp\\foo.txt");
+ string str = path_filename("/tmp\\foo.txt");
+ EXPECT_EQ(str, "tmp\\foo.txt");
}
-#endif /* !_WIN32 */
+#endif /* !_WIN32 */
TEST(util_path_filename, file_only)
{
- string str = path_filename("foo.txt");
- EXPECT_EQ(str, "foo.txt");
+ string str = path_filename("foo.txt");
+ EXPECT_EQ(str, "foo.txt");
}
TEST(util_path_filename, empty)
{
- string str = path_filename("");
- EXPECT_EQ(str, "");
+ string str = path_filename("");
+ EXPECT_EQ(str, "");
}
#ifdef _WIN32
TEST(util_path_filename, simple_windows)
{
- string str = path_filename("C:\\tmp\\foo.txt");
- EXPECT_EQ(str, "foo.txt");
+ string str = path_filename("C:\\tmp\\foo.txt");
+ EXPECT_EQ(str, "foo.txt");
}
TEST(util_path_filename, root_windows)
{
- string str = path_filename("C:\\");
- EXPECT_EQ(str, "\\");
+ string str = path_filename("C:\\");
+ EXPECT_EQ(str, "\\");
}
TEST(util_path_filename, last_slash_windows)
{
- string str = path_filename("C:\\tmp\\foo.txt\\");
- EXPECT_EQ(str, ".");
+ string str = path_filename("C:\\tmp\\foo.txt\\");
+ EXPECT_EQ(str, ".");
}
TEST(util_path_filename, alternate_slash_windows)
{
- string str = path_filename("C:\\tmp/foo.txt");
- EXPECT_EQ(str, "foo.txt");
+ string str = path_filename("C:\\tmp/foo.txt");
+ EXPECT_EQ(str, "foo.txt");
}
-#endif /* _WIN32 */
+#endif /* _WIN32 */
/* ******** Tests for path_dirname() ******** */
#ifndef _WIN32
TEST(util_path_dirname, simple_unix)
{
- string str = path_dirname("/tmp/foo.txt");
- EXPECT_EQ(str, "/tmp");
+ string str = path_dirname("/tmp/foo.txt");
+ EXPECT_EQ(str, "/tmp");
}
TEST(util_path_dirname, root_unix)
{
- string str = path_dirname("/");
- EXPECT_EQ(str, "");
+ string str = path_dirname("/");
+ EXPECT_EQ(str, "");
}
TEST(util_path_dirname, last_slash_unix)
{
- string str = path_dirname("/tmp/foo.txt/");
- EXPECT_EQ(str, "/tmp/foo.txt");
+ string str = path_dirname("/tmp/foo.txt/");
+ EXPECT_EQ(str, "/tmp/foo.txt");
}
TEST(util_path_dirname, alternate_slash_unix)
{
- string str = path_dirname("/tmp\\foo.txt");
- EXPECT_EQ(str, "/");
+ string str = path_dirname("/tmp\\foo.txt");
+ EXPECT_EQ(str, "/");
}
-#endif /* !_WIN32 */
+#endif /* !_WIN32 */
TEST(util_path_dirname, file_only)
{
- string str = path_dirname("foo.txt");
- EXPECT_EQ(str, "");
+ string str = path_dirname("foo.txt");
+ EXPECT_EQ(str, "");
}
TEST(util_path_dirname, empty)
{
- string str = path_dirname("");
- EXPECT_EQ(str, "");
+ string str = path_dirname("");
+ EXPECT_EQ(str, "");
}
#ifdef _WIN32
TEST(util_path_dirname, simple_windows)
{
- string str = path_dirname("C:\\tmp\\foo.txt");
- EXPECT_EQ(str, "C:\\tmp");
+ string str = path_dirname("C:\\tmp\\foo.txt");
+ EXPECT_EQ(str, "C:\\tmp");
}
TEST(util_path_dirname, root_windows)
{
- string str = path_dirname("C:\\");
- EXPECT_EQ(str, "C:");
+ string str = path_dirname("C:\\");
+ EXPECT_EQ(str, "C:");
}
TEST(util_path_dirname, last_slash_windows)
{
- string str = path_dirname("C:\\tmp\\foo.txt\\");
- EXPECT_EQ(str, "C:\\tmp\\foo.txt");
+ string str = path_dirname("C:\\tmp\\foo.txt\\");
+ EXPECT_EQ(str, "C:\\tmp\\foo.txt");
}
TEST(util_path_dirname, alternate_slash_windows)
{
- string str = path_dirname("C:\\tmp/foo.txt");
- EXPECT_EQ(str, "C:\\tmp");
+ string str = path_dirname("C:\\tmp/foo.txt");
+ EXPECT_EQ(str, "C:\\tmp");
}
-#endif /* _WIN32 */
+#endif /* _WIN32 */
/* ******** Tests for path_join() ******** */
TEST(util_path_join, empty_both)
{
- string str = path_join("", "");
- EXPECT_EQ(str, "");
+ string str = path_join("", "");
+ EXPECT_EQ(str, "");
}
TEST(util_path_join, empty_directory)
{
- string str = path_join("", "foo.txt");
- EXPECT_EQ(str, "foo.txt");
+ string str = path_join("", "foo.txt");
+ EXPECT_EQ(str, "foo.txt");
}
TEST(util_path_join, empty_filename)
{
- string str = path_join("foo", "");
- EXPECT_EQ(str, "foo");
+ string str = path_join("foo", "");
+ EXPECT_EQ(str, "foo");
}
#ifndef _WIN32
TEST(util_path_join, simple_unix)
{
- string str = path_join("foo", "bar");
- EXPECT_EQ(str, "foo/bar");
+ string str = path_join("foo", "bar");
+ EXPECT_EQ(str, "foo/bar");
}
TEST(util_path_join, directory_slash_unix)
{
- string str = path_join("foo/", "bar");
- EXPECT_EQ(str, "foo/bar");
+ string str = path_join("foo/", "bar");
+ EXPECT_EQ(str, "foo/bar");
}
TEST(util_path_join, filename_slash_unix)
{
- string str = path_join("foo", "/bar");
- EXPECT_EQ(str, "foo/bar");
+ string str = path_join("foo", "/bar");
+ EXPECT_EQ(str, "foo/bar");
}
TEST(util_path_join, both_slash_unix)
{
- string str = path_join("foo/", "/bar");
- EXPECT_EQ(str, "foo//bar");
+ string str = path_join("foo/", "/bar");
+ EXPECT_EQ(str, "foo//bar");
}
TEST(util_path_join, directory_alternate_slash_unix)
{
- string str = path_join("foo\\", "bar");
- EXPECT_EQ(str, "foo\\/bar");
+ string str = path_join("foo\\", "bar");
+ EXPECT_EQ(str, "foo\\/bar");
}
TEST(util_path_join, filename_alternate_slash_unix)
{
- string str = path_join("foo", "\\bar");
- EXPECT_EQ(str, "foo/\\bar");
+ string str = path_join("foo", "\\bar");
+ EXPECT_EQ(str, "foo/\\bar");
}
TEST(util_path_join, both_alternate_slash_unix)
{
- string str = path_join("foo", "\\bar");
- EXPECT_EQ(str, "foo/\\bar");
+ string str = path_join("foo", "\\bar");
+ EXPECT_EQ(str, "foo/\\bar");
}
TEST(util_path_join, empty_dir_filename_slash_unix)
{
- string str = path_join("", "/foo.txt");
- EXPECT_EQ(str, "/foo.txt");
+ string str = path_join("", "/foo.txt");
+ EXPECT_EQ(str, "/foo.txt");
}
TEST(util_path_join, empty_dir_filename_alternate_slash_unix)
{
- string str = path_join("", "\\foo.txt");
- EXPECT_EQ(str, "\\foo.txt");
+ string str = path_join("", "\\foo.txt");
+ EXPECT_EQ(str, "\\foo.txt");
}
TEST(util_path_join, empty_filename_dir_slash_unix)
{
- string str = path_join("foo/", "");
- EXPECT_EQ(str, "foo/");
+ string str = path_join("foo/", "");
+ EXPECT_EQ(str, "foo/");
}
TEST(util_path_join, empty_filename_dir_alternate_slash_unix)
{
- string str = path_join("foo\\", "");
- EXPECT_EQ(str, "foo\\");
+ string str = path_join("foo\\", "");
+ EXPECT_EQ(str, "foo\\");
}
#else /* !_WIN32 */
TEST(util_path_join, simple_windows)
{
- string str = path_join("foo", "bar");
- EXPECT_EQ(str, "foo\\bar");
+ string str = path_join("foo", "bar");
+ EXPECT_EQ(str, "foo\\bar");
}
TEST(util_path_join, directory_slash_windows)
{
- string str = path_join("foo\\", "bar");
- EXPECT_EQ(str, "foo\\bar");
+ string str = path_join("foo\\", "bar");
+ EXPECT_EQ(str, "foo\\bar");
}
TEST(util_path_join, filename_slash_windows)
{
- string str = path_join("foo", "\\bar");
- EXPECT_EQ(str, "foo\\bar");
+ string str = path_join("foo", "\\bar");
+ EXPECT_EQ(str, "foo\\bar");
}
TEST(util_path_join, both_slash_windows)
{
- string str = path_join("foo\\", "\\bar");
- EXPECT_EQ(str, "foo\\\\bar");
+ string str = path_join("foo\\", "\\bar");
+ EXPECT_EQ(str, "foo\\\\bar");
}
TEST(util_path_join, directory_alternate_slash_windows)
{
- string str = path_join("foo/", "bar");
- EXPECT_EQ(str, "foo/bar");
+ string str = path_join("foo/", "bar");
+ EXPECT_EQ(str, "foo/bar");
}
TEST(util_path_join, filename_alternate_slash_windows)
{
- string str = path_join("foo", "/bar");
- EXPECT_EQ(str, "foo/bar");
+ string str = path_join("foo", "/bar");
+ EXPECT_EQ(str, "foo/bar");
}
TEST(util_path_join, both_alternate_slash_windows)
{
- string str = path_join("foo/", "/bar");
- EXPECT_EQ(str, "foo//bar");
+ string str = path_join("foo/", "/bar");
+ EXPECT_EQ(str, "foo//bar");
}
TEST(util_path_join, empty_dir_filename_slash_windows)
{
- string str = path_join("", "\\foo.txt");
- EXPECT_EQ(str, "\\foo.txt");
+ string str = path_join("", "\\foo.txt");
+ EXPECT_EQ(str, "\\foo.txt");
}
TEST(util_path_join, empty_dir_filename_alternate_slash_windows)
{
- string str = path_join("", "/foo.txt");
- EXPECT_EQ(str, "/foo.txt");
+ string str = path_join("", "/foo.txt");
+ EXPECT_EQ(str, "/foo.txt");
}
TEST(util_path_join, empty_filename_dir_slash_windows)
{
- string str = path_join("foo\\", "");
- EXPECT_EQ(str, "foo\\");
+ string str = path_join("foo\\", "");
+ EXPECT_EQ(str, "foo\\");
}
TEST(util_path_join, empty_filename_dir_alternate_slash_windows)
{
- string str = path_join("foo/", "");
- EXPECT_EQ(str, "foo/");
+ string str = path_join("foo/", "");
+ EXPECT_EQ(str, "foo/");
}
-#endif /* !_WIN32 */
+#endif /* !_WIN32 */
/* ******** Tests for path_escape() ******** */
TEST(util_path_escape, no_escape_chars)
{
- string str = path_escape("/tmp/foo/bar");
- EXPECT_EQ(str, "/tmp/foo/bar");
+ string str = path_escape("/tmp/foo/bar");
+ EXPECT_EQ(str, "/tmp/foo/bar");
}
TEST(util_path_escape, simple)
{
- string str = path_escape("/tmp/foo bar");
- EXPECT_EQ(str, "/tmp/foo\\ bar");
+ string str = path_escape("/tmp/foo bar");
+ EXPECT_EQ(str, "/tmp/foo\\ bar");
}
TEST(util_path_escape, simple_end)
{
- string str = path_escape("/tmp/foo/bar ");
- EXPECT_EQ(str, "/tmp/foo/bar\\ ");
+ string str = path_escape("/tmp/foo/bar ");
+ EXPECT_EQ(str, "/tmp/foo/bar\\ ");
}
TEST(util_path_escape, multiple)
{
- string str = path_escape("/tmp/foo bar");
- EXPECT_EQ(str, "/tmp/foo\\ \\ bar");
+ string str = path_escape("/tmp/foo bar");
+ EXPECT_EQ(str, "/tmp/foo\\ \\ bar");
}
TEST(util_path_escape, simple_multiple_end)
{
- string str = path_escape("/tmp/foo/bar ");
- EXPECT_EQ(str, "/tmp/foo/bar\\ \\ ");
+ string str = path_escape("/tmp/foo/bar ");
+ EXPECT_EQ(str, "/tmp/foo/bar\\ \\ ");
}
/* ******** Tests for path_is_relative() ******** */
TEST(util_path_is_relative, filename)
{
- bool is_relative = path_is_relative("foo.txt");
- EXPECT_TRUE(is_relative);
+ bool is_relative = path_is_relative("foo.txt");
+ EXPECT_TRUE(is_relative);
}
#ifndef _WIN32
TEST(util_path_is_relative, absolute_unix)
{
- bool is_relative = path_is_relative("/tmp/foo.txt");
- EXPECT_FALSE(is_relative);
+ bool is_relative = path_is_relative("/tmp/foo.txt");
+ EXPECT_FALSE(is_relative);
}
TEST(util_path_is_relative, relative_dir_unix)
{
- bool is_relative = path_is_relative("tmp/foo.txt");
- EXPECT_TRUE(is_relative);
+ bool is_relative = path_is_relative("tmp/foo.txt");
+ EXPECT_TRUE(is_relative);
}
TEST(util_path_is_relative, absolute_windir_on_unix)
{
- bool is_relative = path_is_relative("C:\\tmp\\foo.txt");
- EXPECT_TRUE(is_relative);
+ bool is_relative = path_is_relative("C:\\tmp\\foo.txt");
+ EXPECT_TRUE(is_relative);
}
TEST(util_path_is_relative, relative_windir_on_unix)
{
- bool is_relative = path_is_relative("tmp\\foo.txt");
- EXPECT_TRUE(is_relative);
+ bool is_relative = path_is_relative("tmp\\foo.txt");
+ EXPECT_TRUE(is_relative);
}
-#endif /* !_WIN32 */
+#endif /* !_WIN32 */
#ifdef _WIN32
TEST(util_path_is_relative, absolute_windows)
{
- bool is_relative = path_is_relative("C:\\tmp\\foo.txt");
- EXPECT_FALSE(is_relative);
+ bool is_relative = path_is_relative("C:\\tmp\\foo.txt");
+ EXPECT_FALSE(is_relative);
}
TEST(util_path_is_relative, relative_dir_windows)
{
- bool is_relative = path_is_relative("tmp\\foo.txt");
- EXPECT_TRUE(is_relative);
+ bool is_relative = path_is_relative("tmp\\foo.txt");
+ EXPECT_TRUE(is_relative);
}
TEST(util_path_is_relative, absolute_unixdir_on_windows)
{
- bool is_relative = path_is_relative("/tmp/foo.txt");
- EXPECT_TRUE(is_relative);
+ bool is_relative = path_is_relative("/tmp/foo.txt");
+ EXPECT_TRUE(is_relative);
}
TEST(util_path_is_relative, relative_unixdir_on_windows)
{
- bool is_relative = path_is_relative("tmp/foo.txt");
- EXPECT_TRUE(is_relative);
+ bool is_relative = path_is_relative("tmp/foo.txt");
+ EXPECT_TRUE(is_relative);
}
-#endif /* _WIN32 */
+#endif /* _WIN32 */
CCL_NAMESPACE_END
diff --git a/intern/cycles/test/util_string_test.cpp b/intern/cycles/test/util_string_test.cpp
index 6c059ba5d12..97f8daa65de 100644
--- a/intern/cycles/test/util_string_test.cpp
+++ b/intern/cycles/test/util_string_test.cpp
@@ -24,262 +24,261 @@ CCL_NAMESPACE_BEGIN
TEST(util_string_printf, no_format)
{
- string str = string_printf("foo bar");
- EXPECT_EQ("foo bar", str);
+ string str = string_printf("foo bar");
+ EXPECT_EQ("foo bar", str);
}
TEST(util_string_printf, int_number)
{
- string str = string_printf("foo %d bar", 314);
- EXPECT_EQ("foo 314 bar", str);
+ string str = string_printf("foo %d bar", 314);
+ EXPECT_EQ("foo 314 bar", str);
}
TEST(util_string_printf, float_number_default_precision)
{
- string str = string_printf("foo %f bar", 3.1415);
- EXPECT_EQ("foo 3.141500 bar", str);
+ string str = string_printf("foo %f bar", 3.1415);
+ EXPECT_EQ("foo 3.141500 bar", str);
}
TEST(util_string_printf, float_number_custom_precision)
{
- string str = string_printf("foo %.1f bar", 3.1415);
- EXPECT_EQ("foo 3.1 bar", str);
+ string str = string_printf("foo %.1f bar", 3.1415);
+ EXPECT_EQ("foo 3.1 bar", str);
}
/* ******** Tests for string_printf() ******** */
TEST(util_string_iequals, empty_a)
{
- bool equals = string_iequals("", "foo");
- EXPECT_FALSE(equals);
+ bool equals = string_iequals("", "foo");
+ EXPECT_FALSE(equals);
}
TEST(util_string_iequals, empty_b)
{
- bool equals = string_iequals("foo", "");
- EXPECT_FALSE(equals);
+ bool equals = string_iequals("foo", "");
+ EXPECT_FALSE(equals);
}
TEST(util_string_iequals, same_register)
{
- bool equals = string_iequals("foo", "foo");
- EXPECT_TRUE(equals);
+ bool equals = string_iequals("foo", "foo");
+ EXPECT_TRUE(equals);
}
TEST(util_string_iequals, different_register)
{
- bool equals = string_iequals("XFoo", "XfoO");
- EXPECT_TRUE(equals);
+ bool equals = string_iequals("XFoo", "XfoO");
+ EXPECT_TRUE(equals);
}
/* ******** Tests for string_split() ******** */
TEST(util_string_split, empty)
{
- vector<string> tokens;
- string_split(tokens, "");
- EXPECT_EQ(tokens.size(), 0);
+ vector<string> tokens;
+ string_split(tokens, "");
+ EXPECT_EQ(tokens.size(), 0);
}
TEST(util_string_split, only_spaces)
{
- vector<string> tokens;
- string_split(tokens, " \t\t \t");
- EXPECT_EQ(tokens.size(), 0);
+ vector<string> tokens;
+ string_split(tokens, " \t\t \t");
+ EXPECT_EQ(tokens.size(), 0);
}
TEST(util_string_split, single)
{
- vector<string> tokens;
- string_split(tokens, "foo");
- EXPECT_EQ(tokens.size(), 1);
- EXPECT_EQ(tokens[0], "foo");
+ vector<string> tokens;
+ string_split(tokens, "foo");
+ EXPECT_EQ(tokens.size(), 1);
+ EXPECT_EQ(tokens[0], "foo");
}
TEST(util_string_split, simple)
{
- vector<string> tokens;
- string_split(tokens, "foo a bar b");
- EXPECT_EQ(tokens.size(), 4);
- EXPECT_EQ(tokens[0], "foo");
- EXPECT_EQ(tokens[1], "a");
- EXPECT_EQ(tokens[2], "bar");
- EXPECT_EQ(tokens[3], "b");
+ vector<string> tokens;
+ string_split(tokens, "foo a bar b");
+ EXPECT_EQ(tokens.size(), 4);
+ EXPECT_EQ(tokens[0], "foo");
+ EXPECT_EQ(tokens[1], "a");
+ EXPECT_EQ(tokens[2], "bar");
+ EXPECT_EQ(tokens[3], "b");
}
TEST(util_string_split, multiple_spaces)
{
- vector<string> tokens;
- string_split(tokens, " \t foo \ta bar b\t ");
- EXPECT_EQ(tokens.size(), 4);
- EXPECT_EQ(tokens[0], "foo");
- EXPECT_EQ(tokens[1], "a");
- EXPECT_EQ(tokens[2], "bar");
- EXPECT_EQ(tokens[3], "b");
+ vector<string> tokens;
+ string_split(tokens, " \t foo \ta bar b\t ");
+ EXPECT_EQ(tokens.size(), 4);
+ EXPECT_EQ(tokens[0], "foo");
+ EXPECT_EQ(tokens[1], "a");
+ EXPECT_EQ(tokens[2], "bar");
+ EXPECT_EQ(tokens[3], "b");
}
/* ******** Tests for string_replace() ******** */
TEST(util_string_replace, empty_haystack_and_other)
{
- string str = "";
- string_replace(str, "x", "");
- EXPECT_EQ(str, "");
+ string str = "";
+ string_replace(str, "x", "");
+ EXPECT_EQ(str, "");
}
TEST(util_string_replace, empty_haystack)
{
- string str = "";
- string_replace(str, "x", "y");
- EXPECT_EQ(str, "");
+ string str = "";
+ string_replace(str, "x", "y");
+ EXPECT_EQ(str, "");
}
TEST(util_string_replace, empty_other)
{
- string str = "x";
- string_replace(str, "x", "");
- EXPECT_EQ(str, "");
+ string str = "x";
+ string_replace(str, "x", "");
+ EXPECT_EQ(str, "");
}
TEST(util_string_replace, long_haystack_empty_other)
{
- string str = "a x b xxc";
- string_replace(str, "x", "");
- EXPECT_EQ(str, "a b c");
+ string str = "a x b xxc";
+ string_replace(str, "x", "");
+ EXPECT_EQ(str, "a b c");
}
TEST(util_string_replace, long_haystack)
{
- string str = "a x b xxc";
- string_replace(str, "x", "FOO");
- EXPECT_EQ(str, "a FOO b FOOFOOc");
+ string str = "a x b xxc";
+ string_replace(str, "x", "FOO");
+ EXPECT_EQ(str, "a FOO b FOOFOOc");
}
/* ******** Tests for string_endswith() ******** */
TEST(util_string_endswith, empty_both)
{
- bool endswith = string_endswith("", "");
- EXPECT_TRUE(endswith);
+ bool endswith = string_endswith("", "");
+ EXPECT_TRUE(endswith);
}
TEST(util_string_endswith, empty_string)
{
- bool endswith = string_endswith("", "foo");
- EXPECT_FALSE(endswith);
+ bool endswith = string_endswith("", "foo");
+ EXPECT_FALSE(endswith);
}
TEST(util_string_endswith, empty_end)
{
- bool endswith = string_endswith("foo", "");
- EXPECT_TRUE(endswith);
+ bool endswith = string_endswith("foo", "");
+ EXPECT_TRUE(endswith);
}
TEST(util_string_endswith, simple_true)
{
- bool endswith = string_endswith("foo bar", "bar");
- EXPECT_TRUE(endswith);
+ bool endswith = string_endswith("foo bar", "bar");
+ EXPECT_TRUE(endswith);
}
TEST(util_string_endswith, simple_false)
{
- bool endswith = string_endswith("foo bar", "foo");
- EXPECT_FALSE(endswith);
+ bool endswith = string_endswith("foo bar", "foo");
+ EXPECT_FALSE(endswith);
}
/* ******** Tests for string_strip() ******** */
TEST(util_string_strip, empty)
{
- string str = string_strip("");
- EXPECT_EQ(str, "");
+ string str = string_strip("");
+ EXPECT_EQ(str, "");
}
TEST(util_string_strip, only_spaces)
{
- string str = string_strip(" ");
- EXPECT_EQ(str, "");
+ string str = string_strip(" ");
+ EXPECT_EQ(str, "");
}
TEST(util_string_strip, no_spaces)
{
- string str = string_strip("foo bar");
- EXPECT_EQ(str, "foo bar");
+ string str = string_strip("foo bar");
+ EXPECT_EQ(str, "foo bar");
}
TEST(util_string_strip, with_spaces)
{
- string str = string_strip(" foo bar ");
- EXPECT_EQ(str, "foo bar");
+ string str = string_strip(" foo bar ");
+ EXPECT_EQ(str, "foo bar");
}
/* ******** Tests for string_remove_trademark() ******** */
TEST(util_string_remove_trademark, empty)
{
- string str = string_remove_trademark("");
- EXPECT_EQ(str, "");
+ string str = string_remove_trademark("");
+ EXPECT_EQ(str, "");
}
TEST(util_string_remove_trademark, no_trademark)
{
- string str = string_remove_trademark("foo bar");
- EXPECT_EQ(str, "foo bar");
+ string str = string_remove_trademark("foo bar");
+ EXPECT_EQ(str, "foo bar");
}
TEST(util_string_remove_trademark, only_tm)
{
- string str = string_remove_trademark("foo bar(TM) zzz");
- EXPECT_EQ(str, "foo bar zzz");
+ string str = string_remove_trademark("foo bar(TM) zzz");
+ EXPECT_EQ(str, "foo bar zzz");
}
TEST(util_string_remove_trademark, only_r)
{
- string str = string_remove_trademark("foo bar(R) zzz");
- EXPECT_EQ(str, "foo bar zzz");
+ string str = string_remove_trademark("foo bar(R) zzz");
+ EXPECT_EQ(str, "foo bar zzz");
}
TEST(util_string_remove_trademark, both)
{
- string str = string_remove_trademark("foo bar(TM)(R) zzz");
- EXPECT_EQ(str, "foo bar zzz");
+ string str = string_remove_trademark("foo bar(TM)(R) zzz");
+ EXPECT_EQ(str, "foo bar zzz");
}
TEST(util_string_remove_trademark, both_space)
{
- string str = string_remove_trademark("foo bar(TM) (R) zzz");
- EXPECT_EQ(str, "foo bar zzz");
+ string str = string_remove_trademark("foo bar(TM) (R) zzz");
+ EXPECT_EQ(str, "foo bar zzz");
}
TEST(util_string_remove_trademark, both_space_around)
{
- string str = string_remove_trademark("foo bar (TM) (R) zzz");
- EXPECT_EQ(str, "foo bar zzz");
+ string str = string_remove_trademark("foo bar (TM) (R) zzz");
+ EXPECT_EQ(str, "foo bar zzz");
}
TEST(util_string_remove_trademark, trademark_space_suffix)
{
- string str = string_remove_trademark("foo bar (TM)");
- EXPECT_EQ(str, "foo bar");
+ string str = string_remove_trademark("foo bar (TM)");
+ EXPECT_EQ(str, "foo bar");
}
TEST(util_string_remove_trademark, trademark_space_middle)
{
- string str = string_remove_trademark("foo bar (TM) baz");
- EXPECT_EQ(str, "foo bar baz");
+ string str = string_remove_trademark("foo bar (TM) baz");
+ EXPECT_EQ(str, "foo bar baz");
}
-
TEST(util_string_remove_trademark, r_space_suffix)
{
- string str = string_remove_trademark("foo bar (R)");
- EXPECT_EQ(str, "foo bar");
+ string str = string_remove_trademark("foo bar (R)");
+ EXPECT_EQ(str, "foo bar");
}
TEST(util_string_remove_trademark, r_space_middle)
{
- string str = string_remove_trademark("foo bar (R) baz");
- EXPECT_EQ(str, "foo bar baz");
+ string str = string_remove_trademark("foo bar (R) baz");
+ EXPECT_EQ(str, "foo bar baz");
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/test/util_task_test.cpp b/intern/cycles/test/util_task_test.cpp
index 2268206b214..a8b4dfc3a37 100644
--- a/intern/cycles/test/util_task_test.cpp
+++ b/intern/cycles/test/util_task_test.cpp
@@ -22,35 +22,38 @@ CCL_NAMESPACE_BEGIN
namespace {
-void task_run() {
+void task_run()
+{
}
} // namespace
-TEST(util_task, basic) {
- TaskScheduler::init(0);
- TaskPool pool;
- for(int i = 0; i < 100; ++i) {
- pool.push(function_bind(task_run));
- }
- TaskPool::Summary summary;
- pool.wait_work(&summary);
- TaskScheduler::exit();
- EXPECT_EQ(summary.num_tasks_handled, 100);
+TEST(util_task, basic)
+{
+ TaskScheduler::init(0);
+ TaskPool pool;
+ for (int i = 0; i < 100; ++i) {
+ pool.push(function_bind(task_run));
+ }
+ TaskPool::Summary summary;
+ pool.wait_work(&summary);
+ TaskScheduler::exit();
+ EXPECT_EQ(summary.num_tasks_handled, 100);
}
-TEST(util_task, multiple_times) {
- for(int N = 0; N < 1000; ++N) {
- TaskScheduler::init(0);
- TaskPool pool;
- for(int i = 0; i < 100; ++i) {
- pool.push(function_bind(task_run));
- }
- TaskPool::Summary summary;
- pool.wait_work(&summary);
- TaskScheduler::exit();
- EXPECT_EQ(summary.num_tasks_handled, 100);
- }
+TEST(util_task, multiple_times)
+{
+ for (int N = 0; N < 1000; ++N) {
+ TaskScheduler::init(0);
+ TaskPool pool;
+ for (int i = 0; i < 100; ++i) {
+ pool.push(function_bind(task_run));
+ }
+ TaskPool::Summary summary;
+ pool.wait_work(&summary);
+ TaskScheduler::exit();
+ EXPECT_EQ(summary.num_tasks_handled, 100);
+ }
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/test/util_time_test.cpp b/intern/cycles/test/util_time_test.cpp
index 74f9f3b2134..ab5ead2c7b1 100644
--- a/intern/cycles/test/util_time_test.cpp
+++ b/intern/cycles/test/util_time_test.cpp
@@ -20,45 +20,50 @@
CCL_NAMESPACE_BEGIN
-TEST(time_human_readable_to_seconds, Empty) {
- EXPECT_EQ(time_human_readable_to_seconds(""), 0.0);
- EXPECT_EQ(time_human_readable_from_seconds(0.0), "00:00.00");
+TEST(time_human_readable_to_seconds, Empty)
+{
+ EXPECT_EQ(time_human_readable_to_seconds(""), 0.0);
+ EXPECT_EQ(time_human_readable_from_seconds(0.0), "00:00.00");
}
-TEST(time_human_readable_to_seconds, Fraction) {
- EXPECT_NEAR(time_human_readable_to_seconds(".1"), 0.1, 1e-8f);
- EXPECT_NEAR(time_human_readable_to_seconds(".10"), 0.1, 1e-8f);
- EXPECT_EQ(time_human_readable_from_seconds(0.1), "00:00.10");
+TEST(time_human_readable_to_seconds, Fraction)
+{
+ EXPECT_NEAR(time_human_readable_to_seconds(".1"), 0.1, 1e-8f);
+ EXPECT_NEAR(time_human_readable_to_seconds(".10"), 0.1, 1e-8f);
+ EXPECT_EQ(time_human_readable_from_seconds(0.1), "00:00.10");
}
-TEST(time_human_readable_to_seconds, Seconds) {
- EXPECT_NEAR(time_human_readable_to_seconds("2.1"), 2.1, 1e-8f);
- EXPECT_NEAR(time_human_readable_to_seconds("02.10"), 2.1, 1e-8f);
- EXPECT_EQ(time_human_readable_from_seconds(2.1), "00:02.10");
+TEST(time_human_readable_to_seconds, Seconds)
+{
+ EXPECT_NEAR(time_human_readable_to_seconds("2.1"), 2.1, 1e-8f);
+ EXPECT_NEAR(time_human_readable_to_seconds("02.10"), 2.1, 1e-8f);
+ EXPECT_EQ(time_human_readable_from_seconds(2.1), "00:02.10");
- EXPECT_NEAR(time_human_readable_to_seconds("12.1"), 12.1, 1e-8f);
- EXPECT_NEAR(time_human_readable_to_seconds("12.10"), 12.1, 1e-8f);
- EXPECT_EQ(time_human_readable_from_seconds(12.1), "00:12.10");
+ EXPECT_NEAR(time_human_readable_to_seconds("12.1"), 12.1, 1e-8f);
+ EXPECT_NEAR(time_human_readable_to_seconds("12.10"), 12.1, 1e-8f);
+ EXPECT_EQ(time_human_readable_from_seconds(12.1), "00:12.10");
}
-TEST(time_human_readable_to_seconds, MinutesSeconds) {
- EXPECT_NEAR(time_human_readable_to_seconds("3:2.1"), 182.1, 1e-8f);
- EXPECT_NEAR(time_human_readable_to_seconds("03:02.10"), 182.1, 1e-8f);
- EXPECT_EQ(time_human_readable_from_seconds(182.1), "03:02.10");
+TEST(time_human_readable_to_seconds, MinutesSeconds)
+{
+ EXPECT_NEAR(time_human_readable_to_seconds("3:2.1"), 182.1, 1e-8f);
+ EXPECT_NEAR(time_human_readable_to_seconds("03:02.10"), 182.1, 1e-8f);
+ EXPECT_EQ(time_human_readable_from_seconds(182.1), "03:02.10");
- EXPECT_NEAR(time_human_readable_to_seconds("34:12.1"), 2052.1, 1e-8f);
- EXPECT_NEAR(time_human_readable_to_seconds("34:12.10"), 2052.1, 1e-8f);
- EXPECT_EQ(time_human_readable_from_seconds(2052.1), "34:12.10");
+ EXPECT_NEAR(time_human_readable_to_seconds("34:12.1"), 2052.1, 1e-8f);
+ EXPECT_NEAR(time_human_readable_to_seconds("34:12.10"), 2052.1, 1e-8f);
+ EXPECT_EQ(time_human_readable_from_seconds(2052.1), "34:12.10");
}
-TEST(time_human_readable_to_seconds, HoursMinutesSeconds) {
- EXPECT_NEAR(time_human_readable_to_seconds("4:3:2.1"), 14582.1, 1e-8f);
- EXPECT_NEAR(time_human_readable_to_seconds("04:03:02.10"), 14582.1, 1e-8f);
- EXPECT_EQ(time_human_readable_from_seconds(14582.1), "04:03:02.10");
+TEST(time_human_readable_to_seconds, HoursMinutesSeconds)
+{
+ EXPECT_NEAR(time_human_readable_to_seconds("4:3:2.1"), 14582.1, 1e-8f);
+ EXPECT_NEAR(time_human_readable_to_seconds("04:03:02.10"), 14582.1, 1e-8f);
+ EXPECT_EQ(time_human_readable_from_seconds(14582.1), "04:03:02.10");
- EXPECT_NEAR(time_human_readable_to_seconds("56:34:12.1"), 203652.1, 1e-8f);
- EXPECT_NEAR(time_human_readable_to_seconds("56:34:12.10"), 203652.1, 1e-8f);
- EXPECT_EQ(time_human_readable_from_seconds(203652.1), "56:34:12.10");
+ EXPECT_NEAR(time_human_readable_to_seconds("56:34:12.1"), 203652.1, 1e-8f);
+ EXPECT_NEAR(time_human_readable_to_seconds("56:34:12.10"), 203652.1, 1e-8f);
+ EXPECT_EQ(time_human_readable_from_seconds(203652.1), "56:34:12.10");
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/util/CMakeLists.txt b/intern/cycles/util/CMakeLists.txt
index b8b38a531ea..1c7a6549253 100644
--- a/intern/cycles/util/CMakeLists.txt
+++ b/intern/cycles/util/CMakeLists.txt
@@ -1,30 +1,30 @@
set(INC
- ..
- ../../glew-mx
+ ..
+ ../../glew-mx
)
set(INC_SYS
- ${GLEW_INCLUDE_DIR}
+ ${GLEW_INCLUDE_DIR}
)
set(SRC
- util_aligned_malloc.cpp
- util_debug.cpp
- util_ies.cpp
- util_logging.cpp
- util_math_cdf.cpp
- util_md5.cpp
- util_murmurhash.cpp
- util_path.cpp
- util_profiling.cpp
- util_string.cpp
- util_simd.cpp
- util_system.cpp
- util_task.cpp
- util_thread.cpp
- util_time.cpp
- util_transform.cpp
+ util_aligned_malloc.cpp
+ util_debug.cpp
+ util_ies.cpp
+ util_logging.cpp
+ util_math_cdf.cpp
+ util_md5.cpp
+ util_murmurhash.cpp
+ util_path.cpp
+ util_profiling.cpp
+ util_string.cpp
+ util_simd.cpp
+ util_system.cpp
+ util_task.cpp
+ util_thread.cpp
+ util_time.cpp
+ util_transform.cpp
)
set(LIB
@@ -32,117 +32,117 @@ set(LIB
)
if(WITH_CYCLES_STANDALONE)
- if (WITH_CYCLES_STANDALONE_GUI)
- list(APPEND SRC
- util_view.cpp
- )
- endif()
+ if (WITH_CYCLES_STANDALONE_GUI)
+ list(APPEND SRC
+ util_view.cpp
+ )
+ endif()
endif()
if(CYCLES_STANDALONE_REPOSITORY)
- list(APPEND INC_SYS ../../third_party/numaapi/include)
+ list(APPEND INC_SYS ../../third_party/numaapi/include)
else()
- list(APPEND INC_SYS ../../numaapi/include)
+ list(APPEND INC_SYS ../../numaapi/include)
endif()
set(SRC_HEADERS
- util_algorithm.h
- util_aligned_malloc.h
- util_args.h
- util_array.h
- util_atomic.h
- util_boundbox.h
- util_debug.h
- util_defines.h
- util_guarded_allocator.cpp
- util_foreach.h
- util_function.h
- util_guarded_allocator.h
- util_half.h
- util_hash.h
- util_ies.h
- util_image.h
- util_image_impl.h
- util_list.h
- util_logging.h
- util_map.h
- util_math.h
- util_math_cdf.h
- util_math_fast.h
- util_math_intersect.h
- util_math_float2.h
- util_math_float3.h
- util_math_float4.h
- util_math_int2.h
- util_math_int3.h
- util_math_int4.h
- util_math_matrix.h
- util_md5.h
- util_murmurhash.h
- util_opengl.h
- util_optimization.h
- util_param.h
- util_path.h
- util_profiling.h
- util_progress.h
- util_projection.h
- util_queue.h
- util_rect.h
- util_set.h
- util_simd.h
- util_sky_model.cpp
- util_sky_model.h
- util_sky_model_data.h
- util_avxf.h
- util_avxb.h
- util_sseb.h
- util_ssef.h
- util_ssei.h
- util_stack_allocator.h
- util_static_assert.h
- util_stats.h
- util_string.h
- util_system.h
- util_task.h
- util_texture.h
- util_thread.h
- util_time.h
- util_transform.h
- util_types.h
- util_types_float2.h
- util_types_float2_impl.h
- util_types_float3.h
- util_types_float3_impl.h
- util_types_float4.h
- util_types_float4_impl.h
- util_types_float8.h
- util_types_float8_impl.h
- util_types_int2.h
- util_types_int2_impl.h
- util_types_int3.h
- util_types_int3_impl.h
- util_types_int4.h
- util_types_int4_impl.h
- util_types_uchar2.h
- util_types_uchar2_impl.h
- util_types_uchar3.h
- util_types_uchar3_impl.h
- util_types_uchar4.h
- util_types_uchar4_impl.h
- util_types_uint2.h
- util_types_uint2_impl.h
- util_types_uint3.h
- util_types_uint3_impl.h
- util_types_uint4.h
- util_types_uint4_impl.h
- util_types_ushort4.h
- util_types_vector3.h
- util_types_vector3_impl.h
- util_vector.h
- util_version.h
- util_view.h
- util_windows.h
- util_xml.h
+ util_algorithm.h
+ util_aligned_malloc.h
+ util_args.h
+ util_array.h
+ util_atomic.h
+ util_boundbox.h
+ util_debug.h
+ util_defines.h
+ util_guarded_allocator.cpp
+ util_foreach.h
+ util_function.h
+ util_guarded_allocator.h
+ util_half.h
+ util_hash.h
+ util_ies.h
+ util_image.h
+ util_image_impl.h
+ util_list.h
+ util_logging.h
+ util_map.h
+ util_math.h
+ util_math_cdf.h
+ util_math_fast.h
+ util_math_intersect.h
+ util_math_float2.h
+ util_math_float3.h
+ util_math_float4.h
+ util_math_int2.h
+ util_math_int3.h
+ util_math_int4.h
+ util_math_matrix.h
+ util_md5.h
+ util_murmurhash.h
+ util_opengl.h
+ util_optimization.h
+ util_param.h
+ util_path.h
+ util_profiling.h
+ util_progress.h
+ util_projection.h
+ util_queue.h
+ util_rect.h
+ util_set.h
+ util_simd.h
+ util_sky_model.cpp
+ util_sky_model.h
+ util_sky_model_data.h
+ util_avxf.h
+ util_avxb.h
+ util_sseb.h
+ util_ssef.h
+ util_ssei.h
+ util_stack_allocator.h
+ util_static_assert.h
+ util_stats.h
+ util_string.h
+ util_system.h
+ util_task.h
+ util_texture.h
+ util_thread.h
+ util_time.h
+ util_transform.h
+ util_types.h
+ util_types_float2.h
+ util_types_float2_impl.h
+ util_types_float3.h
+ util_types_float3_impl.h
+ util_types_float4.h
+ util_types_float4_impl.h
+ util_types_float8.h
+ util_types_float8_impl.h
+ util_types_int2.h
+ util_types_int2_impl.h
+ util_types_int3.h
+ util_types_int3_impl.h
+ util_types_int4.h
+ util_types_int4_impl.h
+ util_types_uchar2.h
+ util_types_uchar2_impl.h
+ util_types_uchar3.h
+ util_types_uchar3_impl.h
+ util_types_uchar4.h
+ util_types_uchar4_impl.h
+ util_types_uint2.h
+ util_types_uint2_impl.h
+ util_types_uint3.h
+ util_types_uint3_impl.h
+ util_types_uint4.h
+ util_types_uint4_impl.h
+ util_types_ushort4.h
+ util_types_vector3.h
+ util_types_vector3_impl.h
+ util_vector.h
+ util_version.h
+ util_view.h
+ util_windows.h
+ util_xml.h
)
include_directories(${INC})
diff --git a/intern/cycles/util/util_algorithm.h b/intern/cycles/util/util_algorithm.h
index f9e6476cc52..62093039625 100644
--- a/intern/cycles/util/util_algorithm.h
+++ b/intern/cycles/util/util_algorithm.h
@@ -21,12 +21,12 @@
CCL_NAMESPACE_BEGIN
-using std::sort;
-using std::swap;
using std::max;
using std::min;
using std::remove;
+using std::sort;
+using std::swap;
CCL_NAMESPACE_END
-#endif /* __UTIL_ALGORITHM_H__ */
+#endif /* __UTIL_ALGORITHM_H__ */
diff --git a/intern/cycles/util/util_aligned_malloc.cpp b/intern/cycles/util/util_aligned_malloc.cpp
index cc7252dcc58..104e6c5e3f4 100644
--- a/intern/cycles/util/util_aligned_malloc.cpp
+++ b/intern/cycles/util/util_aligned_malloc.cpp
@@ -29,7 +29,7 @@
# undef __MSVCRT_VERSION__
# endif
# define __MSVCRT_VERSION__ 0x0700
-# endif /* FREE_WINDOWS */
+# endif /* FREE_WINDOWS */
# include <malloc.h>
#else
/* Apple's malloc is 16-byte aligned, and does not have malloc.h, so include
@@ -43,39 +43,39 @@ CCL_NAMESPACE_BEGIN
void *util_aligned_malloc(size_t size, int alignment)
{
#ifdef WITH_BLENDER_GUARDEDALLOC
- return MEM_mallocN_aligned(size, alignment, "Cycles Aligned Alloc");
+ return MEM_mallocN_aligned(size, alignment, "Cycles Aligned Alloc");
#elif defined(_WIN32)
- return _aligned_malloc(size, alignment);
+ return _aligned_malloc(size, alignment);
#elif defined(__APPLE__)
- /* On Mac OS X, both the heap and the stack are guaranteed 16-byte aligned so
- * they work natively with SSE types with no further work.
- */
- assert(alignment == 16);
- return malloc(size);
+ /* On Mac OS X, both the heap and the stack are guaranteed 16-byte aligned so
+ * they work natively with SSE types with no further work.
+ */
+ assert(alignment == 16);
+ return malloc(size);
#elif defined(__FreeBSD__) || defined(__NetBSD__)
- void *result;
- if(posix_memalign(&result, alignment, size)) {
- /* Non-zero means allocation error
- * either no allocation or bad alignment value.
- */
- return NULL;
- }
- return result;
-#else /* This is for Linux. */
- return memalign(alignment, size);
+ void *result;
+ if (posix_memalign(&result, alignment, size)) {
+ /* Non-zero means allocation error
+ * either no allocation or bad alignment value.
+ */
+ return NULL;
+ }
+ return result;
+#else /* This is for Linux. */
+ return memalign(alignment, size);
#endif
}
void util_aligned_free(void *ptr)
{
#if defined(WITH_BLENDER_GUARDEDALLOC)
- if(ptr != NULL) {
- MEM_freeN(ptr);
- }
+ if (ptr != NULL) {
+ MEM_freeN(ptr);
+ }
#elif defined(_WIN32)
- _aligned_free(ptr);
+ _aligned_free(ptr);
#else
- free(ptr);
+ free(ptr);
#endif
}
diff --git a/intern/cycles/util/util_aligned_malloc.h b/intern/cycles/util/util_aligned_malloc.h
index 66d77c83454..0f006e95f6a 100644
--- a/intern/cycles/util/util_aligned_malloc.h
+++ b/intern/cycles/util/util_aligned_malloc.h
@@ -32,4 +32,4 @@ void util_aligned_free(void *ptr);
CCL_NAMESPACE_END
-#endif /* __UTIL_ALIGNED_MALLOC_H__ */
+#endif /* __UTIL_ALIGNED_MALLOC_H__ */
diff --git a/intern/cycles/util/util_args.h b/intern/cycles/util/util_args.h
index 9fe54b14d77..be6f2c2b9f1 100644
--- a/intern/cycles/util/util_args.h
+++ b/intern/cycles/util/util_args.h
@@ -28,4 +28,4 @@ OIIO_NAMESPACE_USING
CCL_NAMESPACE_END
-#endif /* __UTIL_ARGS_H__ */
+#endif /* __UTIL_ARGS_H__ */
diff --git a/intern/cycles/util/util_array.h b/intern/cycles/util/util_array.h
index 5f18d434c31..1d7e39344f6 100644
--- a/intern/cycles/util/util_array.h
+++ b/intern/cycles/util/util_array.h
@@ -34,256 +34,250 @@ CCL_NAMESPACE_BEGIN
* - if this is used, we are not tempted to use inefficient operations
* - aligned allocation for CPU native data types */
-template<typename T, size_t alignment = MIN_ALIGNMENT_CPU_DATA_TYPES>
-class array
-{
-public:
- array()
- : data_(NULL),
- datasize_(0),
- capacity_(0)
- {}
-
- explicit array(size_t newsize)
- {
- if(newsize == 0) {
- data_ = NULL;
- datasize_ = 0;
- capacity_ = 0;
- }
- else {
- data_ = mem_allocate(newsize);
- datasize_ = newsize;
- capacity_ = datasize_;
- }
- }
-
- array(const array& from)
- {
- if(from.datasize_ == 0) {
- data_ = NULL;
- datasize_ = 0;
- capacity_ = 0;
- }
- else {
- data_ = mem_allocate(from.datasize_);
- memcpy(data_, from.data_, from.datasize_*sizeof(T));
- datasize_ = from.datasize_;
- capacity_ = datasize_;
- }
- }
-
- array& operator=(const array& from)
- {
- if(this != &from) {
- resize(from.size());
- memcpy((void*)data_, from.data_, datasize_*sizeof(T));
- }
-
- return *this;
- }
-
- array& operator=(const vector<T>& from)
- {
- resize(from.size());
-
- if(from.size() > 0) {
- memcpy(data_, &from[0], datasize_*sizeof(T));
- }
-
- return *this;
- }
-
- ~array()
- {
- mem_free(data_, capacity_);
- }
-
- bool operator==(const array<T>& other) const
- {
- if(datasize_ != other.datasize_) {
- return false;
- }
-
- return memcmp(data_, other.data_, datasize_*sizeof(T)) == 0;
- }
-
- bool operator!=(const array<T>& other) const
- {
- return !(*this == other);
- }
-
- void steal_data(array& from)
- {
- if(this != &from) {
- clear();
-
- data_ = from.data_;
- datasize_ = from.datasize_;
- capacity_ = from.capacity_;
-
- from.data_ = NULL;
- from.datasize_ = 0;
- from.capacity_ = 0;
- }
- }
-
- T *steal_pointer()
- {
- T *ptr = data_;
- data_ = NULL;
- clear();
- return ptr;
- }
-
- T* resize(size_t newsize)
- {
- if(newsize == 0) {
- clear();
- }
- else if(newsize != datasize_) {
- if(newsize > capacity_) {
- T *newdata = mem_allocate(newsize);
- if(newdata == NULL) {
- /* Allocation failed, likely out of memory. */
- clear();
- return NULL;
- }
- else if(data_ != NULL) {
- memcpy((void *)newdata,
- data_,
- ((datasize_ < newsize)? datasize_: newsize)*sizeof(T));
- mem_free(data_, capacity_);
- }
- data_ = newdata;
- capacity_ = newsize;
- }
- datasize_ = newsize;
- }
- return data_;
- }
-
- T* resize(size_t newsize, const T& value)
- {
- size_t oldsize = size();
- resize(newsize);
-
- for(size_t i = oldsize; i < size(); i++) {
- data_[i] = value;
- }
-
- return data_;
- }
-
- void clear()
- {
- if(data_ != NULL) {
- mem_free(data_, capacity_);
- data_ = NULL;
- }
- datasize_ = 0;
- capacity_ = 0;
- }
-
- size_t empty() const
- {
- return datasize_ == 0;
- }
-
- size_t size() const
- {
- return datasize_;
- }
-
- T* data()
- {
- return data_;
- }
-
- const T* data() const
- {
- return data_;
- }
-
- T& operator[](size_t i) const
- {
- assert(i < datasize_);
- return data_[i];
- }
-
- void reserve(size_t newcapacity)
- {
- if(newcapacity > capacity_) {
- T *newdata = mem_allocate(newcapacity);
- if(data_ != NULL) {
- memcpy(newdata, data_, ((datasize_ < newcapacity)? datasize_: newcapacity)*sizeof(T));
- mem_free(data_, capacity_);
- }
- data_ = newdata;
- capacity_ = newcapacity;
- }
- }
-
- size_t capacity() const
- {
- return capacity_;
- }
-
- // do not use this method unless you are sure the code is not performance critical
- void push_back_slow(const T& t)
- {
- if(capacity_ == datasize_)
- {
- reserve(datasize_ == 0 ? 1 : (size_t)((datasize_ + 1) * 1.2));
- }
-
- data_[datasize_++] = t;
- }
-
- void push_back_reserved(const T& t)
- {
- assert(datasize_ < capacity_);
- push_back_slow(t);
- }
-
- void append(const array<T>& from)
- {
- if(from.size()) {
- size_t old_size = size();
- resize(old_size + from.size());
- memcpy(data_ + old_size, from.data(), sizeof(T) * from.size());
- }
- }
-
-protected:
- inline T* mem_allocate(size_t N)
- {
- if(N == 0) {
- return NULL;
- }
- T *mem = (T*)util_aligned_malloc(sizeof(T)*N, alignment);
- if(mem != NULL) {
- util_guarded_mem_alloc(sizeof(T)*N);
- }
- else {
- throw std::bad_alloc();
- }
- return mem;
- }
-
- inline void mem_free(T *mem, size_t N)
- {
- if(mem != NULL) {
- util_guarded_mem_free(sizeof(T)*N);
- util_aligned_free(mem);
- }
- }
-
- T *data_;
- size_t datasize_;
- size_t capacity_;
+template<typename T, size_t alignment = MIN_ALIGNMENT_CPU_DATA_TYPES> class array {
+ public:
+ array() : data_(NULL), datasize_(0), capacity_(0)
+ {
+ }
+
+ explicit array(size_t newsize)
+ {
+ if (newsize == 0) {
+ data_ = NULL;
+ datasize_ = 0;
+ capacity_ = 0;
+ }
+ else {
+ data_ = mem_allocate(newsize);
+ datasize_ = newsize;
+ capacity_ = datasize_;
+ }
+ }
+
+ array(const array &from)
+ {
+ if (from.datasize_ == 0) {
+ data_ = NULL;
+ datasize_ = 0;
+ capacity_ = 0;
+ }
+ else {
+ data_ = mem_allocate(from.datasize_);
+ memcpy(data_, from.data_, from.datasize_ * sizeof(T));
+ datasize_ = from.datasize_;
+ capacity_ = datasize_;
+ }
+ }
+
+ array &operator=(const array &from)
+ {
+ if (this != &from) {
+ resize(from.size());
+ memcpy((void *)data_, from.data_, datasize_ * sizeof(T));
+ }
+
+ return *this;
+ }
+
+ array &operator=(const vector<T> &from)
+ {
+ resize(from.size());
+
+ if (from.size() > 0) {
+ memcpy(data_, &from[0], datasize_ * sizeof(T));
+ }
+
+ return *this;
+ }
+
+ ~array()
+ {
+ mem_free(data_, capacity_);
+ }
+
+ bool operator==(const array<T> &other) const
+ {
+ if (datasize_ != other.datasize_) {
+ return false;
+ }
+
+ return memcmp(data_, other.data_, datasize_ * sizeof(T)) == 0;
+ }
+
+ bool operator!=(const array<T> &other) const
+ {
+ return !(*this == other);
+ }
+
+ void steal_data(array &from)
+ {
+ if (this != &from) {
+ clear();
+
+ data_ = from.data_;
+ datasize_ = from.datasize_;
+ capacity_ = from.capacity_;
+
+ from.data_ = NULL;
+ from.datasize_ = 0;
+ from.capacity_ = 0;
+ }
+ }
+
+ T *steal_pointer()
+ {
+ T *ptr = data_;
+ data_ = NULL;
+ clear();
+ return ptr;
+ }
+
+ T *resize(size_t newsize)
+ {
+ if (newsize == 0) {
+ clear();
+ }
+ else if (newsize != datasize_) {
+ if (newsize > capacity_) {
+ T *newdata = mem_allocate(newsize);
+ if (newdata == NULL) {
+ /* Allocation failed, likely out of memory. */
+ clear();
+ return NULL;
+ }
+ else if (data_ != NULL) {
+ memcpy(
+ (void *)newdata, data_, ((datasize_ < newsize) ? datasize_ : newsize) * sizeof(T));
+ mem_free(data_, capacity_);
+ }
+ data_ = newdata;
+ capacity_ = newsize;
+ }
+ datasize_ = newsize;
+ }
+ return data_;
+ }
+
+ T *resize(size_t newsize, const T &value)
+ {
+ size_t oldsize = size();
+ resize(newsize);
+
+ for (size_t i = oldsize; i < size(); i++) {
+ data_[i] = value;
+ }
+
+ return data_;
+ }
+
+ void clear()
+ {
+ if (data_ != NULL) {
+ mem_free(data_, capacity_);
+ data_ = NULL;
+ }
+ datasize_ = 0;
+ capacity_ = 0;
+ }
+
+ size_t empty() const
+ {
+ return datasize_ == 0;
+ }
+
+ size_t size() const
+ {
+ return datasize_;
+ }
+
+ T *data()
+ {
+ return data_;
+ }
+
+ const T *data() const
+ {
+ return data_;
+ }
+
+ T &operator[](size_t i) const
+ {
+ assert(i < datasize_);
+ return data_[i];
+ }
+
+ void reserve(size_t newcapacity)
+ {
+ if (newcapacity > capacity_) {
+ T *newdata = mem_allocate(newcapacity);
+ if (data_ != NULL) {
+ memcpy(newdata, data_, ((datasize_ < newcapacity) ? datasize_ : newcapacity) * sizeof(T));
+ mem_free(data_, capacity_);
+ }
+ data_ = newdata;
+ capacity_ = newcapacity;
+ }
+ }
+
+ size_t capacity() const
+ {
+ return capacity_;
+ }
+
+ // do not use this method unless you are sure the code is not performance critical
+ void push_back_slow(const T &t)
+ {
+ if (capacity_ == datasize_) {
+ reserve(datasize_ == 0 ? 1 : (size_t)((datasize_ + 1) * 1.2));
+ }
+
+ data_[datasize_++] = t;
+ }
+
+ void push_back_reserved(const T &t)
+ {
+ assert(datasize_ < capacity_);
+ push_back_slow(t);
+ }
+
+ void append(const array<T> &from)
+ {
+ if (from.size()) {
+ size_t old_size = size();
+ resize(old_size + from.size());
+ memcpy(data_ + old_size, from.data(), sizeof(T) * from.size());
+ }
+ }
+
+ protected:
+ inline T *mem_allocate(size_t N)
+ {
+ if (N == 0) {
+ return NULL;
+ }
+ T *mem = (T *)util_aligned_malloc(sizeof(T) * N, alignment);
+ if (mem != NULL) {
+ util_guarded_mem_alloc(sizeof(T) * N);
+ }
+ else {
+ throw std::bad_alloc();
+ }
+ return mem;
+ }
+
+ inline void mem_free(T *mem, size_t N)
+ {
+ if (mem != NULL) {
+ util_guarded_mem_free(sizeof(T) * N);
+ util_aligned_free(mem);
+ }
+ }
+
+ T *data_;
+ size_t datasize_;
+ size_t capacity_;
};
CCL_NAMESPACE_END
-#endif /* __UTIL_ARRAY_H__ */
+#endif /* __UTIL_ARRAY_H__ */
diff --git a/intern/cycles/util/util_atomic.h b/intern/cycles/util/util_atomic.h
index 477b667a6fe..a8ea1dc925e 100644
--- a/intern/cycles/util/util_atomic.h
+++ b/intern/cycles/util/util_atomic.h
@@ -20,94 +20,97 @@
#ifndef __KERNEL_GPU__
/* Using atomic ops header from Blender. */
-#include "atomic_ops.h"
+# include "atomic_ops.h"
-#define atomic_add_and_fetch_float(p, x) atomic_add_and_fetch_fl((p), (x))
-#define atomic_compare_and_swap_float(p, old_val, new_val) atomic_cas_float((p), (old_val), (new_val))
+# define atomic_add_and_fetch_float(p, x) atomic_add_and_fetch_fl((p), (x))
+# define atomic_compare_and_swap_float(p, old_val, new_val) \
+ atomic_cas_float((p), (old_val), (new_val))
-#define atomic_fetch_and_inc_uint32(p) atomic_fetch_and_add_uint32((p), 1)
-#define atomic_fetch_and_dec_uint32(p) atomic_fetch_and_add_uint32((p), -1)
+# define atomic_fetch_and_inc_uint32(p) atomic_fetch_and_add_uint32((p), 1)
+# define atomic_fetch_and_dec_uint32(p) atomic_fetch_and_add_uint32((p), -1)
-#define CCL_LOCAL_MEM_FENCE 0
-#define ccl_barrier(flags) ((void) 0)
+# define CCL_LOCAL_MEM_FENCE 0
+# define ccl_barrier(flags) ((void)0)
-#else /* __KERNEL_GPU__ */
+#else /* __KERNEL_GPU__ */
-#ifdef __KERNEL_OPENCL__
+# ifdef __KERNEL_OPENCL__
/* Float atomics implementation credits:
* http://suhorukov.blogspot.in/2011/12/opencl-11-atomic-operations-on-floating.html
*/
ccl_device_inline float atomic_add_and_fetch_float(volatile ccl_global float *source,
- const float operand)
+ const float operand)
{
- union {
- unsigned int int_value;
- float float_value;
- } new_value;
- union {
- unsigned int int_value;
- float float_value;
- } prev_value;
- do {
- prev_value.float_value = *source;
- new_value.float_value = prev_value.float_value + operand;
- } while(atomic_cmpxchg((volatile ccl_global unsigned int *)source,
- prev_value.int_value,
- new_value.int_value) != prev_value.int_value);
- return new_value.float_value;
+ union {
+ unsigned int int_value;
+ float float_value;
+ } new_value;
+ union {
+ unsigned int int_value;
+ float float_value;
+ } prev_value;
+ do {
+ prev_value.float_value = *source;
+ new_value.float_value = prev_value.float_value + operand;
+ } while (atomic_cmpxchg((volatile ccl_global unsigned int *)source,
+ prev_value.int_value,
+ new_value.int_value) != prev_value.int_value);
+ return new_value.float_value;
}
ccl_device_inline float atomic_compare_and_swap_float(volatile ccl_global float *dest,
- const float old_val, const float new_val)
+ const float old_val,
+ const float new_val)
{
- union {
- unsigned int int_value;
- float float_value;
- } new_value, prev_value, result;
- prev_value.float_value = old_val;
- new_value.float_value = new_val;
- result.int_value = atomic_cmpxchg((volatile ccl_global unsigned int *)dest,
- prev_value.int_value, new_value.int_value);
- return result.float_value;
+ union {
+ unsigned int int_value;
+ float float_value;
+ } new_value, prev_value, result;
+ prev_value.float_value = old_val;
+ new_value.float_value = new_val;
+ result.int_value = atomic_cmpxchg(
+ (volatile ccl_global unsigned int *)dest, prev_value.int_value, new_value.int_value);
+ return result.float_value;
}
-#define atomic_fetch_and_add_uint32(p, x) atomic_add((p), (x))
-#define atomic_fetch_and_inc_uint32(p) atomic_inc((p))
-#define atomic_fetch_and_dec_uint32(p) atomic_dec((p))
+# define atomic_fetch_and_add_uint32(p, x) atomic_add((p), (x))
+# define atomic_fetch_and_inc_uint32(p) atomic_inc((p))
+# define atomic_fetch_and_dec_uint32(p) atomic_dec((p))
-#define CCL_LOCAL_MEM_FENCE CLK_LOCAL_MEM_FENCE
-#define ccl_barrier(flags) barrier(flags)
+# define CCL_LOCAL_MEM_FENCE CLK_LOCAL_MEM_FENCE
+# define ccl_barrier(flags) barrier(flags)
-#endif /* __KERNEL_OPENCL__ */
+# endif /* __KERNEL_OPENCL__ */
-#ifdef __KERNEL_CUDA__
+# ifdef __KERNEL_CUDA__
-#define atomic_add_and_fetch_float(p, x) (atomicAdd((float*)(p), (float)(x)) + (float)(x))
+# define atomic_add_and_fetch_float(p, x) (atomicAdd((float *)(p), (float)(x)) + (float)(x))
-#define atomic_fetch_and_add_uint32(p, x) atomicAdd((unsigned int*)(p), (unsigned int)(x))
-#define atomic_fetch_and_sub_uint32(p, x) atomicSub((unsigned int*)(p), (unsigned int)(x))
-#define atomic_fetch_and_inc_uint32(p) atomic_fetch_and_add_uint32((p), 1)
-#define atomic_fetch_and_dec_uint32(p) atomic_fetch_and_sub_uint32((p), 1)
+# define atomic_fetch_and_add_uint32(p, x) atomicAdd((unsigned int *)(p), (unsigned int)(x))
+# define atomic_fetch_and_sub_uint32(p, x) atomicSub((unsigned int *)(p), (unsigned int)(x))
+# define atomic_fetch_and_inc_uint32(p) atomic_fetch_and_add_uint32((p), 1)
+# define atomic_fetch_and_dec_uint32(p) atomic_fetch_and_sub_uint32((p), 1)
ccl_device_inline float atomic_compare_and_swap_float(volatile float *dest,
- const float old_val, const float new_val)
+ const float old_val,
+ const float new_val)
{
- union {
- unsigned int int_value;
- float float_value;
- } new_value, prev_value, result;
- prev_value.float_value = old_val;
- new_value.float_value = new_val;
- result.int_value = atomicCAS((unsigned int *)dest, prev_value.int_value,new_value.int_value);
- return result.float_value;
+ union {
+ unsigned int int_value;
+ float float_value;
+ } new_value, prev_value, result;
+ prev_value.float_value = old_val;
+ new_value.float_value = new_val;
+ result.int_value = atomicCAS((unsigned int *)dest, prev_value.int_value, new_value.int_value);
+ return result.float_value;
}
-#define CCL_LOCAL_MEM_FENCE
-#define ccl_barrier(flags) __syncthreads()
+# define CCL_LOCAL_MEM_FENCE
+# define ccl_barrier(flags) __syncthreads()
-#endif /* __KERNEL_CUDA__ */
+# endif /* __KERNEL_CUDA__ */
-#endif /* __KERNEL_GPU__ */
+#endif /* __KERNEL_GPU__ */
-#endif /* __UTIL_ATOMIC_H__ */
+#endif /* __UTIL_ATOMIC_H__ */
diff --git a/intern/cycles/util/util_avxb.h b/intern/cycles/util/util_avxb.h
index 25ef39d39ae..54dd8068eca 100644
--- a/intern/cycles/util/util_avxb.h
+++ b/intern/cycles/util/util_avxb.h
@@ -16,125 +16,214 @@
*/
#ifndef __UTIL_AVXB_H__
-#define __UTIL_AVXB_H__
+# define __UTIL_AVXB_H__
CCL_NAMESPACE_BEGIN
struct avxf;
/*! 4-wide SSE bool type. */
-struct avxb
-{
- typedef avxb Mask; // mask type
- typedef avxf Float; // float type
-
- enum { size = 8 }; // number of SIMD elements
- union { __m256 m256; int32_t v[8]; }; // data
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Constructors, Assignment & Cast Operators
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline avxb ( ) {}
- __forceinline avxb ( const avxb& other ) { m256 = other.m256; }
- __forceinline avxb& operator=( const avxb& other ) { m256 = other.m256; return *this; }
-
- __forceinline avxb( const __m256 input ) : m256(input) {}
- __forceinline operator const __m256&( void ) const { return m256; }
- __forceinline operator const __m256i( void ) const { return _mm256_castps_si256(m256); }
- __forceinline operator const __m256d( void ) const { return _mm256_castps_pd(m256); }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Constants
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline avxb( FalseTy ) : m256(_mm256_setzero_ps()) {}
- __forceinline avxb( TrueTy ) : m256(_mm256_castsi256_ps(_mm256_set1_epi32(-1))) {}
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Array Access
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline bool operator []( const size_t i ) const { assert(i < 8); return (_mm256_movemask_ps(m256) >> i) & 1; }
- __forceinline int32_t& operator []( const size_t i ) { assert(i < 8); return v[i]; }
+struct avxb {
+ typedef avxb Mask; // mask type
+ typedef avxf Float; // float type
+
+ enum { size = 8 }; // number of SIMD elements
+ union {
+ __m256 m256;
+ int32_t v[8];
+ }; // data
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Constructors, Assignment & Cast Operators
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline avxb()
+ {
+ }
+ __forceinline avxb(const avxb &other)
+ {
+ m256 = other.m256;
+ }
+ __forceinline avxb &operator=(const avxb &other)
+ {
+ m256 = other.m256;
+ return *this;
+ }
+
+ __forceinline avxb(const __m256 input) : m256(input)
+ {
+ }
+ __forceinline operator const __m256 &(void)const
+ {
+ return m256;
+ }
+ __forceinline operator const __m256i(void) const
+ {
+ return _mm256_castps_si256(m256);
+ }
+ __forceinline operator const __m256d(void) const
+ {
+ return _mm256_castps_pd(m256);
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Constants
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline avxb(FalseTy) : m256(_mm256_setzero_ps())
+ {
+ }
+ __forceinline avxb(TrueTy) : m256(_mm256_castsi256_ps(_mm256_set1_epi32(-1)))
+ {
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Array Access
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline bool operator[](const size_t i) const
+ {
+ assert(i < 8);
+ return (_mm256_movemask_ps(m256) >> i) & 1;
+ }
+ __forceinline int32_t &operator[](const size_t i)
+ {
+ assert(i < 8);
+ return v[i];
+ }
};
////////////////////////////////////////////////////////////////////////////////
/// Unary Operators
////////////////////////////////////////////////////////////////////////////////
-__forceinline const avxb operator !( const avxb& a ) { return _mm256_xor_ps(a, avxb(True)); }
+__forceinline const avxb operator!(const avxb &a)
+{
+ return _mm256_xor_ps(a, avxb(True));
+}
////////////////////////////////////////////////////////////////////////////////
/// Binary Operators
////////////////////////////////////////////////////////////////////////////////
-__forceinline const avxb operator &( const avxb& a, const avxb& b ) { return _mm256_and_ps(a, b); }
-__forceinline const avxb operator |( const avxb& a, const avxb& b ) { return _mm256_or_ps (a, b); }
-__forceinline const avxb operator ^( const avxb& a, const avxb& b ) { return _mm256_xor_ps(a, b); }
+__forceinline const avxb operator&(const avxb &a, const avxb &b)
+{
+ return _mm256_and_ps(a, b);
+}
+__forceinline const avxb operator|(const avxb &a, const avxb &b)
+{
+ return _mm256_or_ps(a, b);
+}
+__forceinline const avxb operator^(const avxb &a, const avxb &b)
+{
+ return _mm256_xor_ps(a, b);
+}
////////////////////////////////////////////////////////////////////////////////
/// Assignment Operators
////////////////////////////////////////////////////////////////////////////////
-__forceinline const avxb operator &=( avxb& a, const avxb& b ) { return a = a & b; }
-__forceinline const avxb operator |=( avxb& a, const avxb& b ) { return a = a | b; }
-__forceinline const avxb operator ^=( avxb& a, const avxb& b ) { return a = a ^ b; }
+__forceinline const avxb operator&=(avxb &a, const avxb &b)
+{
+ return a = a & b;
+}
+__forceinline const avxb operator|=(avxb &a, const avxb &b)
+{
+ return a = a | b;
+}
+__forceinline const avxb operator^=(avxb &a, const avxb &b)
+{
+ return a = a ^ b;
+}
////////////////////////////////////////////////////////////////////////////////
/// Comparison Operators + Select
////////////////////////////////////////////////////////////////////////////////
-__forceinline const avxb operator !=( const avxb& a, const avxb& b ) { return _mm256_xor_ps(a, b); }
-__forceinline const avxb operator ==( const avxb& a, const avxb& b )
-{
-#ifdef __KERNEL_AVX2__
- return _mm256_castsi256_ps(_mm256_cmpeq_epi32(a, b));
-#else
- __m128i a_lo = _mm_castps_si128(_mm256_extractf128_ps(a, 0));
- __m128i a_hi = _mm_castps_si128(_mm256_extractf128_ps(a, 1));
- __m128i b_lo = _mm_castps_si128(_mm256_extractf128_ps(b, 0));
- __m128i b_hi = _mm_castps_si128(_mm256_extractf128_ps(b, 1));
- __m128i c_lo = _mm_cmpeq_epi32(a_lo, b_lo);
- __m128i c_hi = _mm_cmpeq_epi32(a_hi, b_hi);
- __m256i result = _mm256_insertf128_si256(_mm256_castsi128_si256(c_lo), c_hi, 1);
- return _mm256_castsi256_ps(result);
-#endif
+__forceinline const avxb operator!=(const avxb &a, const avxb &b)
+{
+ return _mm256_xor_ps(a, b);
+}
+__forceinline const avxb operator==(const avxb &a, const avxb &b)
+{
+# ifdef __KERNEL_AVX2__
+ return _mm256_castsi256_ps(_mm256_cmpeq_epi32(a, b));
+# else
+ __m128i a_lo = _mm_castps_si128(_mm256_extractf128_ps(a, 0));
+ __m128i a_hi = _mm_castps_si128(_mm256_extractf128_ps(a, 1));
+ __m128i b_lo = _mm_castps_si128(_mm256_extractf128_ps(b, 0));
+ __m128i b_hi = _mm_castps_si128(_mm256_extractf128_ps(b, 1));
+ __m128i c_lo = _mm_cmpeq_epi32(a_lo, b_lo);
+ __m128i c_hi = _mm_cmpeq_epi32(a_hi, b_hi);
+ __m256i result = _mm256_insertf128_si256(_mm256_castsi128_si256(c_lo), c_hi, 1);
+ return _mm256_castsi256_ps(result);
+# endif
}
-__forceinline const avxb select( const avxb& m, const avxb& t, const avxb& f ) {
-#if defined(__KERNEL_SSE41__)
- return _mm256_blendv_ps(f, t, m);
-#else
- return _mm256_or_ps(_mm256_and_ps(m, t), _mm256_andnot_ps(m, f));
-#endif
+__forceinline const avxb select(const avxb &m, const avxb &t, const avxb &f)
+{
+# if defined(__KERNEL_SSE41__)
+ return _mm256_blendv_ps(f, t, m);
+# else
+ return _mm256_or_ps(_mm256_and_ps(m, t), _mm256_andnot_ps(m, f));
+# endif
}
////////////////////////////////////////////////////////////////////////////////
/// Movement/Shifting/Shuffling Functions
////////////////////////////////////////////////////////////////////////////////
-__forceinline const avxb unpacklo( const avxb& a, const avxb& b ) { return _mm256_unpacklo_ps(a, b); }
-__forceinline const avxb unpackhi( const avxb& a, const avxb& b ) { return _mm256_unpackhi_ps(a, b); }
+__forceinline const avxb unpacklo(const avxb &a, const avxb &b)
+{
+ return _mm256_unpacklo_ps(a, b);
+}
+__forceinline const avxb unpackhi(const avxb &a, const avxb &b)
+{
+ return _mm256_unpackhi_ps(a, b);
+}
////////////////////////////////////////////////////////////////////////////////
/// Reduction Operations
////////////////////////////////////////////////////////////////////////////////
-#if defined(__KERNEL_SSE41__)
-__forceinline size_t popcnt( const avxb& a ) { return __popcnt(_mm256_movemask_ps(a)); }
-#else
-__forceinline size_t popcnt( const avxb& a ) { return bool(a[0])+bool(a[1])+bool(a[2])+bool(a[3])+bool(a[4])+
- bool(a[5])+bool(a[6])+bool(a[7]); }
-#endif
+# if defined(__KERNEL_SSE41__)
+__forceinline size_t popcnt(const avxb &a)
+{
+ return __popcnt(_mm256_movemask_ps(a));
+}
+# else
+__forceinline size_t popcnt(const avxb &a)
+{
+ return bool(a[0]) + bool(a[1]) + bool(a[2]) + bool(a[3]) + bool(a[4]) + bool(a[5]) + bool(a[6]) +
+ bool(a[7]);
+}
+# endif
-__forceinline bool reduce_and( const avxb& a ) { return _mm256_movemask_ps(a) == 0xf; }
-__forceinline bool reduce_or ( const avxb& a ) { return _mm256_movemask_ps(a) != 0x0; }
-__forceinline bool all ( const avxb& b ) { return _mm256_movemask_ps(b) == 0xf; }
-__forceinline bool any ( const avxb& b ) { return _mm256_movemask_ps(b) != 0x0; }
-__forceinline bool none ( const avxb& b ) { return _mm256_movemask_ps(b) == 0x0; }
+__forceinline bool reduce_and(const avxb &a)
+{
+ return _mm256_movemask_ps(a) == 0xf;
+}
+__forceinline bool reduce_or(const avxb &a)
+{
+ return _mm256_movemask_ps(a) != 0x0;
+}
+__forceinline bool all(const avxb &b)
+{
+ return _mm256_movemask_ps(b) == 0xf;
+}
+__forceinline bool any(const avxb &b)
+{
+ return _mm256_movemask_ps(b) != 0x0;
+}
+__forceinline bool none(const avxb &b)
+{
+ return _mm256_movemask_ps(b) == 0x0;
+}
-__forceinline size_t movemask( const avxb& a ) { return _mm256_movemask_ps(a); }
+__forceinline size_t movemask(const avxb &a)
+{
+ return _mm256_movemask_ps(a);
+}
////////////////////////////////////////////////////////////////////////////////
/// Debug Functions
@@ -142,8 +231,7 @@ __forceinline size_t movemask( const avxb& a ) { return _mm256_movemask_ps(a); }
ccl_device_inline void print_avxb(const char *label, const avxb &a)
{
- printf("%s: %d %d %d %d %d %d %d %d\n",
- label, a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7]);
+ printf("%s: %d %d %d %d %d %d %d %d\n", label, a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7]);
}
#endif
diff --git a/intern/cycles/util/util_avxf.h b/intern/cycles/util/util_avxf.h
index f00c722f25b..156607e65fb 100644
--- a/intern/cycles/util/util_avxf.h
+++ b/intern/cycles/util/util_avxf.h
@@ -15,217 +15,330 @@
*/
#ifndef __UTIL_AVXF_H__
-#define __UTIL_AVXF_H__
+# define __UTIL_AVXF_H__
CCL_NAMESPACE_BEGIN
struct avxb;
-struct avxf
-{
- typedef avxf Float;
-
- enum { size = 8 }; /* Number of SIMD elements. */
-
- union {
- __m256 m256;
- float f[8];
- int i[8];
- };
-
- __forceinline avxf () {}
- __forceinline avxf (const avxf& other) { m256 = other.m256; }
- __forceinline avxf& operator=(const avxf& other) { m256 = other.m256; return *this; }
-
- __forceinline avxf(const __m256 a) : m256(a) {}
- __forceinline avxf(const __m256i a) : m256(_mm256_castsi256_ps (a)) {}
-
- __forceinline operator const __m256&() const { return m256; }
- __forceinline operator __m256&() { return m256; }
-
- __forceinline avxf (float a) : m256(_mm256_set1_ps(a)) {}
-
- __forceinline avxf(float high32x4, float low32x4) :
- m256(_mm256_set_ps(high32x4, high32x4, high32x4, high32x4, low32x4, low32x4, low32x4, low32x4)) {}
-
- __forceinline avxf(float a3, float a2, float a1, float a0) :
- m256(_mm256_set_ps(a3, a2, a1, a0, a3, a2, a1, a0)) {}
-
- __forceinline avxf(float a7, float a6, float a5, float a4, float a3, float a2, float a1, float a0) :
- m256(_mm256_set_ps(a7, a6, a5, a4, a3, a2, a1, a0)) {}
-
- __forceinline avxf(float3 a) :
- m256(_mm256_set_ps(a.w, a.z, a.y, a.x, a.w, a.z, a.y, a.x)) {}
-
-
- __forceinline avxf(int a3, int a2, int a1, int a0)
- {
- const __m256i foo = _mm256_set_epi32(a3, a2, a1, a0, a3, a2, a1, a0);
- m256 = _mm256_castsi256_ps(foo);
- }
-
-
- __forceinline avxf(int a7, int a6, int a5, int a4, int a3, int a2, int a1, int a0)
- {
- const __m256i foo = _mm256_set_epi32(a7, a6, a5, a4, a3, a2, a1, a0);
- m256 = _mm256_castsi256_ps(foo);
- }
-
- __forceinline avxf(__m128 a, __m128 b)
- {
- const __m256 foo = _mm256_castps128_ps256(a);
- m256 = _mm256_insertf128_ps(foo, b, 1);
- }
-
- __forceinline const float& operator [](const size_t i) const { assert(i < 8); return f[i]; }
- __forceinline float& operator [](const size_t i) { assert(i < 8); return f[i]; }
+struct avxf {
+ typedef avxf Float;
+
+ enum { size = 8 }; /* Number of SIMD elements. */
+
+ union {
+ __m256 m256;
+ float f[8];
+ int i[8];
+ };
+
+ __forceinline avxf()
+ {
+ }
+ __forceinline avxf(const avxf &other)
+ {
+ m256 = other.m256;
+ }
+ __forceinline avxf &operator=(const avxf &other)
+ {
+ m256 = other.m256;
+ return *this;
+ }
+
+ __forceinline avxf(const __m256 a) : m256(a)
+ {
+ }
+ __forceinline avxf(const __m256i a) : m256(_mm256_castsi256_ps(a))
+ {
+ }
+
+ __forceinline operator const __m256 &() const
+ {
+ return m256;
+ }
+ __forceinline operator __m256 &()
+ {
+ return m256;
+ }
+
+ __forceinline avxf(float a) : m256(_mm256_set1_ps(a))
+ {
+ }
+
+ __forceinline avxf(float high32x4, float low32x4)
+ : m256(_mm256_set_ps(
+ high32x4, high32x4, high32x4, high32x4, low32x4, low32x4, low32x4, low32x4))
+ {
+ }
+
+ __forceinline avxf(float a3, float a2, float a1, float a0)
+ : m256(_mm256_set_ps(a3, a2, a1, a0, a3, a2, a1, a0))
+ {
+ }
+
+ __forceinline avxf(
+ float a7, float a6, float a5, float a4, float a3, float a2, float a1, float a0)
+ : m256(_mm256_set_ps(a7, a6, a5, a4, a3, a2, a1, a0))
+ {
+ }
+
+ __forceinline avxf(float3 a) : m256(_mm256_set_ps(a.w, a.z, a.y, a.x, a.w, a.z, a.y, a.x))
+ {
+ }
+
+ __forceinline avxf(int a3, int a2, int a1, int a0)
+ {
+ const __m256i foo = _mm256_set_epi32(a3, a2, a1, a0, a3, a2, a1, a0);
+ m256 = _mm256_castsi256_ps(foo);
+ }
+
+ __forceinline avxf(int a7, int a6, int a5, int a4, int a3, int a2, int a1, int a0)
+ {
+ const __m256i foo = _mm256_set_epi32(a7, a6, a5, a4, a3, a2, a1, a0);
+ m256 = _mm256_castsi256_ps(foo);
+ }
+
+ __forceinline avxf(__m128 a, __m128 b)
+ {
+ const __m256 foo = _mm256_castps128_ps256(a);
+ m256 = _mm256_insertf128_ps(foo, b, 1);
+ }
+
+ __forceinline const float &operator[](const size_t i) const
+ {
+ assert(i < 8);
+ return f[i];
+ }
+ __forceinline float &operator[](const size_t i)
+ {
+ assert(i < 8);
+ return f[i];
+ }
};
-__forceinline avxf cross(const avxf& a, const avxf& b)
+__forceinline avxf cross(const avxf &a, const avxf &b)
{
- avxf r(0.0, a[4]*b[5] - a[5]*b[4], a[6]*b[4] - a[4]*b[6], a[5]*b[6] - a[6]*b[5],
- 0.0, a[0]*b[1] - a[1]*b[0], a[2]*b[0] - a[0]*b[2], a[1]*b[2] - a[2]*b[1]);
- return r;
+ avxf r(0.0,
+ a[4] * b[5] - a[5] * b[4],
+ a[6] * b[4] - a[4] * b[6],
+ a[5] * b[6] - a[6] * b[5],
+ 0.0,
+ a[0] * b[1] - a[1] * b[0],
+ a[2] * b[0] - a[0] * b[2],
+ a[1] * b[2] - a[2] * b[1]);
+ return r;
}
-__forceinline void dot3(const avxf& a, const avxf& b, float &den, float &den2)
+__forceinline void dot3(const avxf &a, const avxf &b, float &den, float &den2)
{
- const avxf t = _mm256_mul_ps(a.m256, b.m256);
- den = ((float*)&t)[0] + ((float*)&t)[1] + ((float*)&t)[2];
- den2 = ((float*)&t)[4] + ((float*)&t)[5] + ((float*)&t)[6];
+ const avxf t = _mm256_mul_ps(a.m256, b.m256);
+ den = ((float *)&t)[0] + ((float *)&t)[1] + ((float *)&t)[2];
+ den2 = ((float *)&t)[4] + ((float *)&t)[5] + ((float *)&t)[6];
}
////////////////////////////////////////////////////////////////////////////////
/// Unary Operators
////////////////////////////////////////////////////////////////////////////////
-__forceinline const avxf mm256_sqrt(const avxf& a) { return _mm256_sqrt_ps(a.m256); }
+__forceinline const avxf mm256_sqrt(const avxf &a)
+{
+ return _mm256_sqrt_ps(a.m256);
+}
////////////////////////////////////////////////////////////////////////////////
/// Binary Operators
////////////////////////////////////////////////////////////////////////////////
-__forceinline const avxf operator +(const avxf& a, const avxf& b) { return _mm256_add_ps(a.m256, b.m256); }
-__forceinline const avxf operator +(const avxf& a, const float& b) { return a + avxf(b); }
-__forceinline const avxf operator +(const float& a, const avxf& b) { return avxf(a) + b; }
+__forceinline const avxf operator+(const avxf &a, const avxf &b)
+{
+ return _mm256_add_ps(a.m256, b.m256);
+}
+__forceinline const avxf operator+(const avxf &a, const float &b)
+{
+ return a + avxf(b);
+}
+__forceinline const avxf operator+(const float &a, const avxf &b)
+{
+ return avxf(a) + b;
+}
-__forceinline const avxf operator -(const avxf& a, const avxf& b) { return _mm256_sub_ps(a.m256, b.m256); }
-__forceinline const avxf operator -(const avxf& a, const float& b) { return a - avxf(b); }
-__forceinline const avxf operator -(const float& a, const avxf& b) { return avxf(a) - b; }
+__forceinline const avxf operator-(const avxf &a, const avxf &b)
+{
+ return _mm256_sub_ps(a.m256, b.m256);
+}
+__forceinline const avxf operator-(const avxf &a, const float &b)
+{
+ return a - avxf(b);
+}
+__forceinline const avxf operator-(const float &a, const avxf &b)
+{
+ return avxf(a) - b;
+}
-__forceinline const avxf operator *(const avxf& a, const avxf& b) { return _mm256_mul_ps(a.m256, b.m256); }
-__forceinline const avxf operator *(const avxf& a, const float& b) { return a * avxf(b); }
-__forceinline const avxf operator *(const float& a, const avxf& b) { return avxf(a) * b; }
+__forceinline const avxf operator*(const avxf &a, const avxf &b)
+{
+ return _mm256_mul_ps(a.m256, b.m256);
+}
+__forceinline const avxf operator*(const avxf &a, const float &b)
+{
+ return a * avxf(b);
+}
+__forceinline const avxf operator*(const float &a, const avxf &b)
+{
+ return avxf(a) * b;
+}
-__forceinline const avxf operator /(const avxf& a, const avxf& b) { return _mm256_div_ps(a.m256,b.m256); }
-__forceinline const avxf operator /(const avxf& a, const float& b) { return a/avxf(b); }
-__forceinline const avxf operator /(const float& a, const avxf& b) { return avxf(a)/b; }
+__forceinline const avxf operator/(const avxf &a, const avxf &b)
+{
+ return _mm256_div_ps(a.m256, b.m256);
+}
+__forceinline const avxf operator/(const avxf &a, const float &b)
+{
+ return a / avxf(b);
+}
+__forceinline const avxf operator/(const float &a, const avxf &b)
+{
+ return avxf(a) / b;
+}
-__forceinline const avxf operator|(const avxf& a, const avxf& b) { return _mm256_or_ps(a.m256,b.m256); }
+__forceinline const avxf operator|(const avxf &a, const avxf &b)
+{
+ return _mm256_or_ps(a.m256, b.m256);
+}
-__forceinline const avxf operator^(const avxf& a, const avxf& b) { return _mm256_xor_ps(a.m256,b.m256); }
+__forceinline const avxf operator^(const avxf &a, const avxf &b)
+{
+ return _mm256_xor_ps(a.m256, b.m256);
+}
-__forceinline const avxf operator&(const avxf& a, const avxf& b) { return _mm256_and_ps(a.m256,b.m256); }
+__forceinline const avxf operator&(const avxf &a, const avxf &b)
+{
+ return _mm256_and_ps(a.m256, b.m256);
+}
-__forceinline const avxf max(const avxf& a, const avxf& b) { return _mm256_max_ps(a.m256, b.m256); }
-__forceinline const avxf min(const avxf& a, const avxf& b) { return _mm256_min_ps(a.m256, b.m256); }
+__forceinline const avxf max(const avxf &a, const avxf &b)
+{
+ return _mm256_max_ps(a.m256, b.m256);
+}
+__forceinline const avxf min(const avxf &a, const avxf &b)
+{
+ return _mm256_min_ps(a.m256, b.m256);
+}
////////////////////////////////////////////////////////////////////////////////
/// Movement/Shifting/Shuffling Functions
////////////////////////////////////////////////////////////////////////////////
-__forceinline const avxf shuffle(const avxf& a, const __m256i &shuf) {
- return _mm256_permutevar_ps(a, shuf);
+__forceinline const avxf shuffle(const avxf &a, const __m256i &shuf)
+{
+ return _mm256_permutevar_ps(a, shuf);
}
-template<int i0, int i1, int i2, int i3, int i4, int i5, int i6, int i7> __forceinline const avxf shuffle(const avxf& a) {
- return _mm256_permutevar_ps(a, _mm256_set_epi32( i7,i6,i5,i4 ,i3,i2,i1,i0));
+template<int i0, int i1, int i2, int i3, int i4, int i5, int i6, int i7>
+__forceinline const avxf shuffle(const avxf &a)
+{
+ return _mm256_permutevar_ps(a, _mm256_set_epi32(i7, i6, i5, i4, i3, i2, i1, i0));
}
-template<size_t i0, size_t i1, size_t i2, size_t i3> __forceinline const avxf shuffle(const avxf& a, const avxf& b) {
- return _mm256_shuffle_ps(a, b, _MM_SHUFFLE(i3, i2, i1, i0));
+template<size_t i0, size_t i1, size_t i2, size_t i3>
+__forceinline const avxf shuffle(const avxf &a, const avxf &b)
+{
+ return _mm256_shuffle_ps(a, b, _MM_SHUFFLE(i3, i2, i1, i0));
}
-template<size_t i0, size_t i1, size_t i2, size_t i3> __forceinline const avxf shuffle(const avxf& a) {
- return shuffle<i0,i1,i2,i3>(a,a);
+template<size_t i0, size_t i1, size_t i2, size_t i3>
+__forceinline const avxf shuffle(const avxf &a)
+{
+ return shuffle<i0, i1, i2, i3>(a, a);
}
-template<size_t i0> __forceinline const avxf shuffle(const avxf& a, const avxf& b) {
- return shuffle<i0,i0,i0,i0>(a, b);
+template<size_t i0> __forceinline const avxf shuffle(const avxf &a, const avxf &b)
+{
+ return shuffle<i0, i0, i0, i0>(a, b);
}
-template<size_t i0> __forceinline const avxf shuffle(const avxf& a) {
- return shuffle<i0>(a,a);
+template<size_t i0> __forceinline const avxf shuffle(const avxf &a)
+{
+ return shuffle<i0>(a, a);
}
-template<int i0, int i1, int i2, int i3, int i4, int i5, int i6, int i7> __forceinline const avxf permute(const avxf& a) {
-#ifdef __KERNEL_AVX2__
- return _mm256_permutevar8x32_ps(a,_mm256_set_epi32( i7,i6,i5,i4 ,i3,i2,i1,i0));
-#else
- float temp[8];
- _mm256_storeu_ps((float*)&temp, a);
- return avxf(temp[i7], temp[i6], temp[i5], temp[i4], temp[i3], temp[i2], temp[i1], temp[i0]);
-#endif
+template<int i0, int i1, int i2, int i3, int i4, int i5, int i6, int i7>
+__forceinline const avxf permute(const avxf &a)
+{
+# ifdef __KERNEL_AVX2__
+ return _mm256_permutevar8x32_ps(a, _mm256_set_epi32(i7, i6, i5, i4, i3, i2, i1, i0));
+# else
+ float temp[8];
+ _mm256_storeu_ps((float *)&temp, a);
+ return avxf(temp[i7], temp[i6], temp[i5], temp[i4], temp[i3], temp[i2], temp[i1], temp[i0]);
+# endif
}
-template<int S0, int S1, int S2, int S3,int S4,int S5,int S6, int S7>
+template<int S0, int S1, int S2, int S3, int S4, int S5, int S6, int S7>
ccl_device_inline const avxf set_sign_bit(const avxf &a)
{
- return a ^ avxf(S7 << 31, S6 << 31, S5 << 31, S4 << 31, S3 << 31,S2 << 31,S1 << 31,S0 << 31);
+ return a ^ avxf(S7 << 31, S6 << 31, S5 << 31, S4 << 31, S3 << 31, S2 << 31, S1 << 31, S0 << 31);
}
-template<size_t S0, size_t S1, size_t S2, size_t S3,size_t S4,size_t S5,size_t S6, size_t S7>
+template<size_t S0, size_t S1, size_t S2, size_t S3, size_t S4, size_t S5, size_t S6, size_t S7>
ccl_device_inline const avxf blend(const avxf &a, const avxf &b)
{
- return _mm256_blend_ps(a,b,S7 << 0 | S6 << 1 | S5 << 2 | S4 << 3 | S3 << 4 | S2 << 5 | S1 << 6 | S0 << 7);
+ return _mm256_blend_ps(
+ a, b, S7 << 0 | S6 << 1 | S5 << 2 | S4 << 3 | S3 << 4 | S2 << 5 | S1 << 6 | S0 << 7);
}
-template<size_t S0, size_t S1, size_t S2, size_t S3 >
+template<size_t S0, size_t S1, size_t S2, size_t S3>
ccl_device_inline const avxf blend(const avxf &a, const avxf &b)
{
- return blend<S0,S1,S2,S3,S0,S1,S2,S3>(a,b);
+ return blend<S0, S1, S2, S3, S0, S1, S2, S3>(a, b);
}
//#if defined(__KERNEL_SSE41__)
-__forceinline avxf maxi(const avxf& a, const avxf& b) {
- const avxf ci = _mm256_max_ps(a, b);
- return ci;
+__forceinline avxf maxi(const avxf &a, const avxf &b)
+{
+ const avxf ci = _mm256_max_ps(a, b);
+ return ci;
}
-__forceinline avxf mini(const avxf& a, const avxf& b) {
- const avxf ci = _mm256_min_ps(a, b);
- return ci;
+__forceinline avxf mini(const avxf &a, const avxf &b)
+{
+ const avxf ci = _mm256_min_ps(a, b);
+ return ci;
}
//#endif
////////////////////////////////////////////////////////////////////////////////
/// Ternary Operators
////////////////////////////////////////////////////////////////////////////////
-__forceinline const avxf madd (const avxf& a, const avxf& b, const avxf& c) {
-#ifdef __KERNEL_AVX2__
- return _mm256_fmadd_ps(a,b,c);
-#else
- return c+(a*b);
-#endif
+__forceinline const avxf madd(const avxf &a, const avxf &b, const avxf &c)
+{
+# ifdef __KERNEL_AVX2__
+ return _mm256_fmadd_ps(a, b, c);
+# else
+ return c + (a * b);
+# endif
}
-__forceinline const avxf nmadd(const avxf& a, const avxf& b, const avxf& c) {
-#ifdef __KERNEL_AVX2__
- return _mm256_fnmadd_ps(a, b, c);
-#else
- return c-(a*b);
-#endif
+__forceinline const avxf nmadd(const avxf &a, const avxf &b, const avxf &c)
+{
+# ifdef __KERNEL_AVX2__
+ return _mm256_fnmadd_ps(a, b, c);
+# else
+ return c - (a * b);
+# endif
}
-__forceinline const avxf msub(const avxf& a, const avxf& b, const avxf& c) {
-#ifdef __KERNEL_AVX2__
- return _mm256_fmsub_ps(a, b, c);
-#else
- return (a*b) - c;
-#endif
+__forceinline const avxf msub(const avxf &a, const avxf &b, const avxf &c)
+{
+# ifdef __KERNEL_AVX2__
+ return _mm256_fmsub_ps(a, b, c);
+# else
+ return (a * b) - c;
+# endif
}
////////////////////////////////////////////////////////////////////////////////
/// Comparison Operators
////////////////////////////////////////////////////////////////////////////////
-__forceinline const avxb operator <=(const avxf& a, const avxf& b) {
- return _mm256_cmp_ps(a.m256, b.m256, _CMP_LE_OS);
+__forceinline const avxb operator<=(const avxf &a, const avxf &b)
+{
+ return _mm256_cmp_ps(a.m256, b.m256, _CMP_LE_OS);
}
#endif
@@ -236,6 +349,6 @@ __forceinline const avxb operator <=(const avxf& a, const avxf& b) {
#endif
#define _mm256_loadu2_m128(/* float const* */ hiaddr, /* float const* */ loaddr) \
- _mm256_set_m128(_mm_loadu_ps(hiaddr), _mm_loadu_ps(loaddr))
+ _mm256_set_m128(_mm_loadu_ps(hiaddr), _mm_loadu_ps(loaddr))
CCL_NAMESPACE_END
diff --git a/intern/cycles/util/util_boundbox.h b/intern/cycles/util/util_boundbox.h
index fe89e398840..b5c3f1a8954 100644
--- a/intern/cycles/util/util_boundbox.h
+++ b/intern/cycles/util/util_boundbox.h
@@ -29,257 +29,254 @@ CCL_NAMESPACE_BEGIN
/* 3D BoundBox */
-class BoundBox
-{
-public:
- float3 min, max;
-
- __forceinline BoundBox()
- {
- }
-
- __forceinline BoundBox(const float3& pt)
- : min(pt), max(pt)
- {
- }
-
- __forceinline BoundBox(const float3& min_, const float3& max_)
- : min(min_), max(max_)
- {
- }
-
- enum empty_t { empty = 0};
-
- __forceinline BoundBox(empty_t)
- : min(make_float3(FLT_MAX, FLT_MAX, FLT_MAX)), max(make_float3(-FLT_MAX, -FLT_MAX, -FLT_MAX))
- {
- }
-
- __forceinline void grow(const float3& pt)
- {
- /* the order of arguments to min is such that if pt is nan, it will not
- * influence the resulting bounding box */
- min = ccl::min(pt, min);
- max = ccl::max(pt, max);
- }
-
- __forceinline void grow(const float3& pt, float border)
- {
- float3 shift = make_float3(border, border, border);
- min = ccl::min(pt - shift, min);
- max = ccl::max(pt + shift, max);
- }
-
- __forceinline void grow(const BoundBox& bbox)
- {
- grow(bbox.min);
- grow(bbox.max);
- }
-
- __forceinline void grow_safe(const float3& pt)
- {
- /* the order of arguments to min is such that if pt is nan, it will not
- * influence the resulting bounding box */
- if(isfinite(pt.x) && isfinite(pt.y) && isfinite(pt.z)) {
- min = ccl::min(pt, min);
- max = ccl::max(pt, max);
- }
- }
-
- __forceinline void grow_safe(const float3& pt, float border)
- {
- if(isfinite(pt.x) && isfinite(pt.y) && isfinite(pt.z) && isfinite(border)) {
- float3 shift = make_float3(border, border, border);
- min = ccl::min(pt - shift, min);
- max = ccl::max(pt + shift, max);
- }
- }
-
- __forceinline void grow_safe(const BoundBox& bbox)
- {
- grow_safe(bbox.min);
- grow_safe(bbox.max);
- }
-
- __forceinline void intersect(const BoundBox& bbox)
- {
- min = ccl::max(min, bbox.min);
- max = ccl::min(max, bbox.max);
- }
-
- /* todo: avoid using this */
- __forceinline float safe_area() const
- {
- if(!((min.x <= max.x) && (min.y <= max.y) && (min.z <= max.z)))
- return 0.0f;
-
- return area();
- }
-
- __forceinline float area() const
- {
- return half_area()*2.0f;
- }
-
- __forceinline float half_area() const
- {
- float3 d = max - min;
- return (d.x*d.z + d.y*d.z + d.x*d.y);
- }
-
- __forceinline float3 center() const
- {
- return 0.5f*(min + max);
- }
-
- __forceinline float3 center2() const
- {
- return min + max;
- }
-
- __forceinline float3 size() const
- {
- return max - min;
- }
-
- __forceinline bool valid() const
- {
- return (min.x <= max.x) && (min.y <= max.y) && (min.z <= max.z) &&
- (isfinite(min.x) && isfinite(min.y) && isfinite(min.z)) &&
- (isfinite(max.x) && isfinite(max.y) && isfinite(max.z));
- }
-
- BoundBox transformed(const Transform *tfm) const
- {
- BoundBox result = BoundBox::empty;
-
- for(int i = 0; i < 8; i++) {
- float3 p;
-
- p.x = (i & 1)? min.x: max.x;
- p.y = (i & 2)? min.y: max.y;
- p.z = (i & 4)? min.z: max.z;
-
- result.grow(transform_point(tfm, p));
- }
-
- return result;
- }
-
- __forceinline bool intersects(const BoundBox& other)
- {
- float3 center_diff = center() - other.center(),
- total_size = (size() + other.size()) * 0.5f;
- return fabsf(center_diff.x) <= total_size.x &&
- fabsf(center_diff.y) <= total_size.y &&
- fabsf(center_diff.z) <= total_size.z;
- }
+class BoundBox {
+ public:
+ float3 min, max;
+
+ __forceinline BoundBox()
+ {
+ }
+
+ __forceinline BoundBox(const float3 &pt) : min(pt), max(pt)
+ {
+ }
+
+ __forceinline BoundBox(const float3 &min_, const float3 &max_) : min(min_), max(max_)
+ {
+ }
+
+ enum empty_t { empty = 0 };
+
+ __forceinline BoundBox(empty_t)
+ : min(make_float3(FLT_MAX, FLT_MAX, FLT_MAX)), max(make_float3(-FLT_MAX, -FLT_MAX, -FLT_MAX))
+ {
+ }
+
+ __forceinline void grow(const float3 &pt)
+ {
+ /* the order of arguments to min is such that if pt is nan, it will not
+ * influence the resulting bounding box */
+ min = ccl::min(pt, min);
+ max = ccl::max(pt, max);
+ }
+
+ __forceinline void grow(const float3 &pt, float border)
+ {
+ float3 shift = make_float3(border, border, border);
+ min = ccl::min(pt - shift, min);
+ max = ccl::max(pt + shift, max);
+ }
+
+ __forceinline void grow(const BoundBox &bbox)
+ {
+ grow(bbox.min);
+ grow(bbox.max);
+ }
+
+ __forceinline void grow_safe(const float3 &pt)
+ {
+ /* the order of arguments to min is such that if pt is nan, it will not
+ * influence the resulting bounding box */
+ if (isfinite(pt.x) && isfinite(pt.y) && isfinite(pt.z)) {
+ min = ccl::min(pt, min);
+ max = ccl::max(pt, max);
+ }
+ }
+
+ __forceinline void grow_safe(const float3 &pt, float border)
+ {
+ if (isfinite(pt.x) && isfinite(pt.y) && isfinite(pt.z) && isfinite(border)) {
+ float3 shift = make_float3(border, border, border);
+ min = ccl::min(pt - shift, min);
+ max = ccl::max(pt + shift, max);
+ }
+ }
+
+ __forceinline void grow_safe(const BoundBox &bbox)
+ {
+ grow_safe(bbox.min);
+ grow_safe(bbox.max);
+ }
+
+ __forceinline void intersect(const BoundBox &bbox)
+ {
+ min = ccl::max(min, bbox.min);
+ max = ccl::min(max, bbox.max);
+ }
+
+ /* todo: avoid using this */
+ __forceinline float safe_area() const
+ {
+ if (!((min.x <= max.x) && (min.y <= max.y) && (min.z <= max.z)))
+ return 0.0f;
+
+ return area();
+ }
+
+ __forceinline float area() const
+ {
+ return half_area() * 2.0f;
+ }
+
+ __forceinline float half_area() const
+ {
+ float3 d = max - min;
+ return (d.x * d.z + d.y * d.z + d.x * d.y);
+ }
+
+ __forceinline float3 center() const
+ {
+ return 0.5f * (min + max);
+ }
+
+ __forceinline float3 center2() const
+ {
+ return min + max;
+ }
+
+ __forceinline float3 size() const
+ {
+ return max - min;
+ }
+
+ __forceinline bool valid() const
+ {
+ return (min.x <= max.x) && (min.y <= max.y) && (min.z <= max.z) &&
+ (isfinite(min.x) && isfinite(min.y) && isfinite(min.z)) &&
+ (isfinite(max.x) && isfinite(max.y) && isfinite(max.z));
+ }
+
+ BoundBox transformed(const Transform *tfm) const
+ {
+ BoundBox result = BoundBox::empty;
+
+ for (int i = 0; i < 8; i++) {
+ float3 p;
+
+ p.x = (i & 1) ? min.x : max.x;
+ p.y = (i & 2) ? min.y : max.y;
+ p.z = (i & 4) ? min.z : max.z;
+
+ result.grow(transform_point(tfm, p));
+ }
+
+ return result;
+ }
+
+ __forceinline bool intersects(const BoundBox &other)
+ {
+ float3 center_diff = center() - other.center(), total_size = (size() + other.size()) * 0.5f;
+ return fabsf(center_diff.x) <= total_size.x && fabsf(center_diff.y) <= total_size.y &&
+ fabsf(center_diff.z) <= total_size.z;
+ }
};
-__forceinline BoundBox merge(const BoundBox& bbox, const float3& pt)
+__forceinline BoundBox merge(const BoundBox &bbox, const float3 &pt)
{
- return BoundBox(min(bbox.min, pt), max(bbox.max, pt));
+ return BoundBox(min(bbox.min, pt), max(bbox.max, pt));
}
-__forceinline BoundBox merge(const BoundBox& a, const BoundBox& b)
+__forceinline BoundBox merge(const BoundBox &a, const BoundBox &b)
{
- return BoundBox(min(a.min, b.min), max(a.max, b.max));
+ return BoundBox(min(a.min, b.min), max(a.max, b.max));
}
-__forceinline BoundBox merge(const BoundBox& a, const BoundBox& b, const BoundBox& c, const BoundBox& d)
+__forceinline BoundBox merge(const BoundBox &a,
+ const BoundBox &b,
+ const BoundBox &c,
+ const BoundBox &d)
{
- return merge(merge(a, b), merge(c, d));
+ return merge(merge(a, b), merge(c, d));
}
-__forceinline BoundBox intersect(const BoundBox& a, const BoundBox& b)
+__forceinline BoundBox intersect(const BoundBox &a, const BoundBox &b)
{
- return BoundBox(max(a.min, b.min), min(a.max, b.max));
+ return BoundBox(max(a.min, b.min), min(a.max, b.max));
}
-__forceinline BoundBox intersect(const BoundBox& a, const BoundBox& b, const BoundBox& c)
+__forceinline BoundBox intersect(const BoundBox &a, const BoundBox &b, const BoundBox &c)
{
- return intersect(a, intersect(b, c));
+ return intersect(a, intersect(b, c));
}
/* 2D BoundBox */
class BoundBox2D {
-public:
- float left;
- float right;
- float bottom;
- float top;
-
- BoundBox2D()
- : left(0.0f), right(1.0f), bottom(0.0f), top(1.0f)
- {
- }
-
- bool operator==(const BoundBox2D& other) const
- {
- return (left == other.left && right == other.right &&
- bottom == other.bottom && top == other.top);
- }
-
- float width()
- {
- return right - left;
- }
-
- float height()
- {
- return top - bottom;
- }
-
- BoundBox2D operator*(float f) const
- {
- BoundBox2D result;
-
- result.left = left*f;
- result.right = right*f;
- result.bottom = bottom*f;
- result.top = top*f;
-
- return result;
- }
-
- BoundBox2D subset(const BoundBox2D& other) const
- {
- BoundBox2D subset;
-
- subset.left = left + other.left*(right - left);
- subset.right = left + other.right*(right - left);
- subset.bottom = bottom + other.bottom*(top - bottom);
- subset.top = bottom + other.top*(top - bottom);
-
- return subset;
- }
-
- BoundBox2D make_relative_to(const BoundBox2D& other) const
- {
- BoundBox2D result;
-
- result.left = ((left - other.left) / (other.right - other.left));
- result.right = ((right - other.left) / (other.right - other.left));
- result.bottom = ((bottom - other.bottom) / (other.top - other.bottom));
- result.top = ((top - other.bottom) / (other.top - other.bottom));
-
- return result;
- }
-
- BoundBox2D clamp(float mn = 0.0f, float mx = 1.0f)
- {
- BoundBox2D result;
-
- result.left = ccl::clamp(left, mn, mx);
- result.right = ccl::clamp(right, mn, mx);
- result.bottom = ccl::clamp(bottom, mn, mx);
- result.top = ccl::clamp(top, mn, mx);
-
- return result;
- }
+ public:
+ float left;
+ float right;
+ float bottom;
+ float top;
+
+ BoundBox2D() : left(0.0f), right(1.0f), bottom(0.0f), top(1.0f)
+ {
+ }
+
+ bool operator==(const BoundBox2D &other) const
+ {
+ return (left == other.left && right == other.right && bottom == other.bottom &&
+ top == other.top);
+ }
+
+ float width()
+ {
+ return right - left;
+ }
+
+ float height()
+ {
+ return top - bottom;
+ }
+
+ BoundBox2D operator*(float f) const
+ {
+ BoundBox2D result;
+
+ result.left = left * f;
+ result.right = right * f;
+ result.bottom = bottom * f;
+ result.top = top * f;
+
+ return result;
+ }
+
+ BoundBox2D subset(const BoundBox2D &other) const
+ {
+ BoundBox2D subset;
+
+ subset.left = left + other.left * (right - left);
+ subset.right = left + other.right * (right - left);
+ subset.bottom = bottom + other.bottom * (top - bottom);
+ subset.top = bottom + other.top * (top - bottom);
+
+ return subset;
+ }
+
+ BoundBox2D make_relative_to(const BoundBox2D &other) const
+ {
+ BoundBox2D result;
+
+ result.left = ((left - other.left) / (other.right - other.left));
+ result.right = ((right - other.left) / (other.right - other.left));
+ result.bottom = ((bottom - other.bottom) / (other.top - other.bottom));
+ result.top = ((top - other.bottom) / (other.top - other.bottom));
+
+ return result;
+ }
+
+ BoundBox2D clamp(float mn = 0.0f, float mx = 1.0f)
+ {
+ BoundBox2D result;
+
+ result.left = ccl::clamp(left, mn, mx);
+ result.right = ccl::clamp(right, mn, mx);
+ result.bottom = ccl::clamp(bottom, mn, mx);
+ result.top = ccl::clamp(top, mn, mx);
+
+ return result;
+ }
};
CCL_NAMESPACE_END
-#endif /* __UTIL_BOUNDBOX_H__ */
+#endif /* __UTIL_BOUNDBOX_H__ */
diff --git a/intern/cycles/util/util_color.h b/intern/cycles/util/util_color.h
index e6efc7d73fc..ca4c393f66e 100644
--- a/intern/cycles/util/util_color.h
+++ b/intern/cycles/util/util_color.h
@@ -21,133 +21,147 @@
#include "util/util_types.h"
#ifdef __KERNEL_SSE2__
-#include "util/util_simd.h"
+# include "util/util_simd.h"
#endif
CCL_NAMESPACE_BEGIN
ccl_device uchar float_to_byte(float val)
{
- return ((val <= 0.0f) ? 0 : ((val > (1.0f - 0.5f / 255.0f)) ? 255 : (uchar)((255.0f * val) + 0.5f)));
+ return ((val <= 0.0f) ? 0 :
+ ((val > (1.0f - 0.5f / 255.0f)) ? 255 : (uchar)((255.0f * val) + 0.5f)));
}
ccl_device uchar4 color_float_to_byte(float3 c)
{
- uchar r, g, b;
+ uchar r, g, b;
- r = float_to_byte(c.x);
- g = float_to_byte(c.y);
- b = float_to_byte(c.z);
+ r = float_to_byte(c.x);
+ g = float_to_byte(c.y);
+ b = float_to_byte(c.z);
- return make_uchar4(r, g, b, 0);
+ return make_uchar4(r, g, b, 0);
}
ccl_device_inline float3 color_byte_to_float(uchar4 c)
{
- return make_float3(c.x*(1.0f/255.0f), c.y*(1.0f/255.0f), c.z*(1.0f/255.0f));
+ return make_float3(c.x * (1.0f / 255.0f), c.y * (1.0f / 255.0f), c.z * (1.0f / 255.0f));
}
ccl_device float color_srgb_to_linear(float c)
{
- if(c < 0.04045f)
- return (c < 0.0f)? 0.0f: c * (1.0f/12.92f);
- else
- return powf((c + 0.055f) * (1.0f / 1.055f), 2.4f);
+ if (c < 0.04045f)
+ return (c < 0.0f) ? 0.0f : c * (1.0f / 12.92f);
+ else
+ return powf((c + 0.055f) * (1.0f / 1.055f), 2.4f);
}
ccl_device float color_linear_to_srgb(float c)
{
- if(c < 0.0031308f)
- return (c < 0.0f)? 0.0f: c * 12.92f;
- else
- return 1.055f * powf(c, 1.0f / 2.4f) - 0.055f;
+ if (c < 0.0031308f)
+ return (c < 0.0f) ? 0.0f : c * 12.92f;
+ else
+ return 1.055f * powf(c, 1.0f / 2.4f) - 0.055f;
}
ccl_device float3 rgb_to_hsv(float3 rgb)
{
- float cmax, cmin, h, s, v, cdelta;
- float3 c;
-
- cmax = fmaxf(rgb.x, fmaxf(rgb.y, rgb.z));
- cmin = min(rgb.x, min(rgb.y, rgb.z));
- cdelta = cmax - cmin;
-
- v = cmax;
-
- if(cmax != 0.0f) {
- s = cdelta/cmax;
- }
- else {
- s = 0.0f;
- h = 0.0f;
- }
-
- if(s != 0.0f) {
- float3 cmax3 = make_float3(cmax, cmax, cmax);
- c = (cmax3 - rgb)/cdelta;
-
- if (rgb.x == cmax) h = c.z - c.y;
- else if(rgb.y == cmax) h = 2.0f + c.x - c.z;
- else h = 4.0f + c.y - c.x;
-
- h /= 6.0f;
-
- if(h < 0.0f)
- h += 1.0f;
- }
- else {
- h = 0.0f;
- }
-
- return make_float3(h, s, v);
+ float cmax, cmin, h, s, v, cdelta;
+ float3 c;
+
+ cmax = fmaxf(rgb.x, fmaxf(rgb.y, rgb.z));
+ cmin = min(rgb.x, min(rgb.y, rgb.z));
+ cdelta = cmax - cmin;
+
+ v = cmax;
+
+ if (cmax != 0.0f) {
+ s = cdelta / cmax;
+ }
+ else {
+ s = 0.0f;
+ h = 0.0f;
+ }
+
+ if (s != 0.0f) {
+ float3 cmax3 = make_float3(cmax, cmax, cmax);
+ c = (cmax3 - rgb) / cdelta;
+
+ if (rgb.x == cmax)
+ h = c.z - c.y;
+ else if (rgb.y == cmax)
+ h = 2.0f + c.x - c.z;
+ else
+ h = 4.0f + c.y - c.x;
+
+ h /= 6.0f;
+
+ if (h < 0.0f)
+ h += 1.0f;
+ }
+ else {
+ h = 0.0f;
+ }
+
+ return make_float3(h, s, v);
}
ccl_device float3 hsv_to_rgb(float3 hsv)
{
- float i, f, p, q, t, h, s, v;
- float3 rgb;
-
- h = hsv.x;
- s = hsv.y;
- v = hsv.z;
-
- if(s != 0.0f) {
- if(h == 1.0f)
- h = 0.0f;
-
- h *= 6.0f;
- i = floorf(h);
- f = h - i;
- rgb = make_float3(f, f, f);
- p = v*(1.0f-s);
- q = v*(1.0f-(s*f));
- t = v*(1.0f-(s*(1.0f-f)));
-
- if (i == 0.0f) rgb = make_float3(v, t, p);
- else if(i == 1.0f) rgb = make_float3(q, v, p);
- else if(i == 2.0f) rgb = make_float3(p, v, t);
- else if(i == 3.0f) rgb = make_float3(p, q, v);
- else if(i == 4.0f) rgb = make_float3(t, p, v);
- else rgb = make_float3(v, p, q);
- }
- else {
- rgb = make_float3(v, v, v);
- }
-
- return rgb;
+ float i, f, p, q, t, h, s, v;
+ float3 rgb;
+
+ h = hsv.x;
+ s = hsv.y;
+ v = hsv.z;
+
+ if (s != 0.0f) {
+ if (h == 1.0f)
+ h = 0.0f;
+
+ h *= 6.0f;
+ i = floorf(h);
+ f = h - i;
+ rgb = make_float3(f, f, f);
+ p = v * (1.0f - s);
+ q = v * (1.0f - (s * f));
+ t = v * (1.0f - (s * (1.0f - f)));
+
+ if (i == 0.0f)
+ rgb = make_float3(v, t, p);
+ else if (i == 1.0f)
+ rgb = make_float3(q, v, p);
+ else if (i == 2.0f)
+ rgb = make_float3(p, v, t);
+ else if (i == 3.0f)
+ rgb = make_float3(p, q, v);
+ else if (i == 4.0f)
+ rgb = make_float3(t, p, v);
+ else
+ rgb = make_float3(v, p, q);
+ }
+ else {
+ rgb = make_float3(v, v, v);
+ }
+
+ return rgb;
}
ccl_device float3 xyY_to_xyz(float x, float y, float Y)
{
- float X, Z;
+ float X, Z;
- if(y != 0.0f) X = (x / y) * Y;
- else X = 0.0f;
+ if (y != 0.0f)
+ X = (x / y) * Y;
+ else
+ X = 0.0f;
- if(y != 0.0f && Y != 0.0f) Z = (1.0f - x - y) / y * Y;
- else Z = 0.0f;
+ if (y != 0.0f && Y != 0.0f)
+ Z = (1.0f - x - y) / y * Y;
+ else
+ Z = 0.0f;
- return make_float3(X, Y, Z);
+ return make_float3(X, Y, Z);
}
#ifdef __KERNEL_SSE2__
@@ -158,86 +172,84 @@ ccl_device float3 xyY_to_xyz(float x, float y, float Y)
* exp = exponent, encoded as uint32_t
* e2coeff = 2^(127/exponent - 127) * bias_coeff^(1/exponent), encoded as uint32_t
*/
-template<unsigned exp, unsigned e2coeff>
-ccl_device_inline ssef fastpow(const ssef &arg)
+template<unsigned exp, unsigned e2coeff> ccl_device_inline ssef fastpow(const ssef &arg)
{
- ssef ret;
- ret = arg * cast(ssei(e2coeff));
- ret = ssef(cast(ret));
- ret = ret * cast(ssei(exp));
- ret = cast(ssei(ret));
- return ret;
+ ssef ret;
+ ret = arg * cast(ssei(e2coeff));
+ ret = ssef(cast(ret));
+ ret = ret * cast(ssei(exp));
+ ret = cast(ssei(ret));
+ return ret;
}
/* Improve x ^ 1.0f/5.0f solution with Newton-Raphson method */
ccl_device_inline ssef improve_5throot_solution(const ssef &old_result, const ssef &x)
{
- ssef approx2 = old_result * old_result;
- ssef approx4 = approx2 * approx2;
- ssef t = x / approx4;
- ssef summ = madd(ssef(4.0f), old_result, t);
- return summ * ssef(1.0f/5.0f);
+ ssef approx2 = old_result * old_result;
+ ssef approx4 = approx2 * approx2;
+ ssef t = x / approx4;
+ ssef summ = madd(ssef(4.0f), old_result, t);
+ return summ * ssef(1.0f / 5.0f);
}
/* Calculate powf(x, 2.4). Working domain: 1e-10 < x < 1e+10 */
ccl_device_inline ssef fastpow24(const ssef &arg)
{
- /* max, avg and |avg| errors were calculated in gcc without FMA instructions
- * The final precision should be better than powf in glibc */
-
- /* Calculate x^4/5, coefficient 0.994 was constructed manually to minimize avg error */
- /* 0x3F4CCCCD = 4/5 */
- /* 0x4F55A7FB = 2^(127/(4/5) - 127) * 0.994^(1/(4/5)) */
- ssef x = fastpow<0x3F4CCCCD, 0x4F55A7FB>(arg); // error max = 0.17 avg = 0.0018 |avg| = 0.05
- ssef arg2 = arg * arg;
- ssef arg4 = arg2 * arg2;
- x = improve_5throot_solution(x, arg4); /* error max = 0.018 avg = 0.0031 |avg| = 0.0031 */
- x = improve_5throot_solution(x, arg4); /* error max = 0.00021 avg = 1.6e-05 |avg| = 1.6e-05 */
- x = improve_5throot_solution(x, arg4); /* error max = 6.1e-07 avg = 5.2e-08 |avg| = 1.1e-07 */
- return x * (x * x);
+ /* max, avg and |avg| errors were calculated in gcc without FMA instructions
+ * The final precision should be better than powf in glibc */
+
+ /* Calculate x^4/5, coefficient 0.994 was constructed manually to minimize avg error */
+ /* 0x3F4CCCCD = 4/5 */
+ /* 0x4F55A7FB = 2^(127/(4/5) - 127) * 0.994^(1/(4/5)) */
+ ssef x = fastpow<0x3F4CCCCD, 0x4F55A7FB>(arg); // error max = 0.17 avg = 0.0018 |avg| = 0.05
+ ssef arg2 = arg * arg;
+ ssef arg4 = arg2 * arg2;
+ x = improve_5throot_solution(x,
+ arg4); /* error max = 0.018 avg = 0.0031 |avg| = 0.0031 */
+ x = improve_5throot_solution(x,
+ arg4); /* error max = 0.00021 avg = 1.6e-05 |avg| = 1.6e-05 */
+ x = improve_5throot_solution(x,
+ arg4); /* error max = 6.1e-07 avg = 5.2e-08 |avg| = 1.1e-07 */
+ return x * (x * x);
}
ccl_device ssef color_srgb_to_linear(const ssef &c)
{
- sseb cmp = c < ssef(0.04045f);
- ssef lt = max(c * ssef(1.0f/12.92f), ssef(0.0f));
- ssef gtebase = (c + ssef(0.055f)) * ssef(1.0f/1.055f); /* fma */
- ssef gte = fastpow24(gtebase);
- return select(cmp, lt, gte);
+ sseb cmp = c < ssef(0.04045f);
+ ssef lt = max(c * ssef(1.0f / 12.92f), ssef(0.0f));
+ ssef gtebase = (c + ssef(0.055f)) * ssef(1.0f / 1.055f); /* fma */
+ ssef gte = fastpow24(gtebase);
+ return select(cmp, lt, gte);
}
-#endif /* __KERNEL_SSE2__ */
+#endif /* __KERNEL_SSE2__ */
ccl_device float3 color_srgb_to_linear_v3(float3 c)
{
- return make_float3(color_srgb_to_linear(c.x),
- color_srgb_to_linear(c.y),
- color_srgb_to_linear(c.z));
+ return make_float3(
+ color_srgb_to_linear(c.x), color_srgb_to_linear(c.y), color_srgb_to_linear(c.z));
}
ccl_device float3 color_linear_to_srgb_v3(float3 c)
{
- return make_float3(color_linear_to_srgb(c.x),
- color_linear_to_srgb(c.y),
- color_linear_to_srgb(c.z));
+ return make_float3(
+ color_linear_to_srgb(c.x), color_linear_to_srgb(c.y), color_linear_to_srgb(c.z));
}
ccl_device float4 color_srgb_to_linear_v4(float4 c)
{
#ifdef __KERNEL_SSE2__
- ssef r_ssef;
- float4 &r = (float4 &)r_ssef;
- r = c;
- r_ssef = color_srgb_to_linear(r_ssef);
- r.w = c.w;
- return r;
+ ssef r_ssef;
+ float4 &r = (float4 &)r_ssef;
+ r = c;
+ r_ssef = color_srgb_to_linear(r_ssef);
+ r.w = c.w;
+ return r;
#else
- return make_float4(color_srgb_to_linear(c.x),
- color_srgb_to_linear(c.y),
- color_srgb_to_linear(c.z),
- c.w);
+ return make_float4(
+ color_srgb_to_linear(c.x), color_srgb_to_linear(c.y), color_srgb_to_linear(c.z), c.w);
#endif
}
CCL_NAMESPACE_END
-#endif /* __UTIL_COLOR_H__ */
+#endif /* __UTIL_COLOR_H__ */
diff --git a/intern/cycles/util/util_debug.cpp b/intern/cycles/util/util_debug.cpp
index b4cc69411ed..aabfea7fc49 100644
--- a/intern/cycles/util/util_debug.cpp
+++ b/intern/cycles/util/util_debug.cpp
@@ -26,159 +26,153 @@
CCL_NAMESPACE_BEGIN
DebugFlags::CPU::CPU()
- : avx2(true),
- avx(true),
- sse41(true),
- sse3(true),
- sse2(true),
- bvh_layout(BVH_LAYOUT_DEFAULT),
- split_kernel(false)
+ : avx2(true),
+ avx(true),
+ sse41(true),
+ sse3(true),
+ sse2(true),
+ bvh_layout(BVH_LAYOUT_DEFAULT),
+ split_kernel(false)
{
- reset();
+ reset();
}
void DebugFlags::CPU::reset()
{
#define STRINGIFY(x) #x
#define CHECK_CPU_FLAGS(flag, env) \
- do { \
- flag = (getenv(env) == NULL); \
- if(!flag) { \
- VLOG(1) << "Disabling " << STRINGIFY(flag) << " instruction set."; \
- } \
- } while(0)
-
- CHECK_CPU_FLAGS(avx2, "CYCLES_CPU_NO_AVX2");
- CHECK_CPU_FLAGS(avx, "CYCLES_CPU_NO_AVX");
- CHECK_CPU_FLAGS(sse41, "CYCLES_CPU_NO_SSE41");
- CHECK_CPU_FLAGS(sse3, "CYCLES_CPU_NO_SSE3");
- CHECK_CPU_FLAGS(sse2, "CYCLES_CPU_NO_SSE2");
+ do { \
+ flag = (getenv(env) == NULL); \
+ if (!flag) { \
+ VLOG(1) << "Disabling " << STRINGIFY(flag) << " instruction set."; \
+ } \
+ } while (0)
+
+ CHECK_CPU_FLAGS(avx2, "CYCLES_CPU_NO_AVX2");
+ CHECK_CPU_FLAGS(avx, "CYCLES_CPU_NO_AVX");
+ CHECK_CPU_FLAGS(sse41, "CYCLES_CPU_NO_SSE41");
+ CHECK_CPU_FLAGS(sse3, "CYCLES_CPU_NO_SSE3");
+ CHECK_CPU_FLAGS(sse2, "CYCLES_CPU_NO_SSE2");
#undef STRINGIFY
#undef CHECK_CPU_FLAGS
- if(getenv("CYCLES_BVH2") != NULL) {
- bvh_layout = BVH_LAYOUT_BVH2;
- }
- else if(getenv("CYCLES_BVH4") != NULL) {
- bvh_layout = BVH_LAYOUT_BVH4;
- }
- else if(getenv("CYCLES_BVH8") != NULL) {
- bvh_layout = BVH_LAYOUT_BVH8;
- }
- else {
- bvh_layout = BVH_LAYOUT_DEFAULT;
- }
-
- split_kernel = false;
+ if (getenv("CYCLES_BVH2") != NULL) {
+ bvh_layout = BVH_LAYOUT_BVH2;
+ }
+ else if (getenv("CYCLES_BVH4") != NULL) {
+ bvh_layout = BVH_LAYOUT_BVH4;
+ }
+ else if (getenv("CYCLES_BVH8") != NULL) {
+ bvh_layout = BVH_LAYOUT_BVH8;
+ }
+ else {
+ bvh_layout = BVH_LAYOUT_DEFAULT;
+ }
+
+ split_kernel = false;
}
-DebugFlags::CUDA::CUDA()
- : adaptive_compile(false),
- split_kernel(false)
+DebugFlags::CUDA::CUDA() : adaptive_compile(false), split_kernel(false)
{
- reset();
+ reset();
}
void DebugFlags::CUDA::reset()
{
- if(getenv("CYCLES_CUDA_ADAPTIVE_COMPILE") != NULL)
- adaptive_compile = true;
+ if (getenv("CYCLES_CUDA_ADAPTIVE_COMPILE") != NULL)
+ adaptive_compile = true;
- split_kernel = false;
+ split_kernel = false;
}
-DebugFlags::OpenCL::OpenCL()
- : device_type(DebugFlags::OpenCL::DEVICE_ALL),
- debug(false)
+DebugFlags::OpenCL::OpenCL() : device_type(DebugFlags::OpenCL::DEVICE_ALL), debug(false)
{
- reset();
+ reset();
}
void DebugFlags::OpenCL::reset()
{
- /* Initialize device type from environment variables. */
- device_type = DebugFlags::OpenCL::DEVICE_ALL;
- char *device = getenv("CYCLES_OPENCL_TEST");
- if(device) {
- if(strcmp(device, "NONE") == 0) {
- device_type = DebugFlags::OpenCL::DEVICE_NONE;
- }
- else if(strcmp(device, "ALL") == 0) {
- device_type = DebugFlags::OpenCL::DEVICE_ALL;
- }
- else if(strcmp(device, "DEFAULT") == 0) {
- device_type = DebugFlags::OpenCL::DEVICE_DEFAULT;
- }
- else if(strcmp(device, "CPU") == 0) {
- device_type = DebugFlags::OpenCL::DEVICE_CPU;
- }
- else if(strcmp(device, "GPU") == 0) {
- device_type = DebugFlags::OpenCL::DEVICE_GPU;
- }
- else if(strcmp(device, "ACCELERATOR") == 0) {
- device_type = DebugFlags::OpenCL::DEVICE_ACCELERATOR;
- }
- }
- /* Initialize other flags from environment variables. */
- debug = (getenv("CYCLES_OPENCL_DEBUG") != NULL);
+ /* Initialize device type from environment variables. */
+ device_type = DebugFlags::OpenCL::DEVICE_ALL;
+ char *device = getenv("CYCLES_OPENCL_TEST");
+ if (device) {
+ if (strcmp(device, "NONE") == 0) {
+ device_type = DebugFlags::OpenCL::DEVICE_NONE;
+ }
+ else if (strcmp(device, "ALL") == 0) {
+ device_type = DebugFlags::OpenCL::DEVICE_ALL;
+ }
+ else if (strcmp(device, "DEFAULT") == 0) {
+ device_type = DebugFlags::OpenCL::DEVICE_DEFAULT;
+ }
+ else if (strcmp(device, "CPU") == 0) {
+ device_type = DebugFlags::OpenCL::DEVICE_CPU;
+ }
+ else if (strcmp(device, "GPU") == 0) {
+ device_type = DebugFlags::OpenCL::DEVICE_GPU;
+ }
+ else if (strcmp(device, "ACCELERATOR") == 0) {
+ device_type = DebugFlags::OpenCL::DEVICE_ACCELERATOR;
+ }
+ }
+ /* Initialize other flags from environment variables. */
+ debug = (getenv("CYCLES_OPENCL_DEBUG") != NULL);
}
-DebugFlags::DebugFlags()
-: viewport_static_bvh(false)
+DebugFlags::DebugFlags() : viewport_static_bvh(false)
{
- /* Nothing for now. */
+ /* Nothing for now. */
}
void DebugFlags::reset()
{
- viewport_static_bvh = false;
- cpu.reset();
- cuda.reset();
- opencl.reset();
+ viewport_static_bvh = false;
+ cpu.reset();
+ cuda.reset();
+ opencl.reset();
}
-std::ostream& operator <<(std::ostream &os,
- DebugFlagsConstRef debug_flags)
+std::ostream &operator<<(std::ostream &os, DebugFlagsConstRef debug_flags)
{
- os << "CPU flags:\n"
- << " AVX2 : " << string_from_bool(debug_flags.cpu.avx2) << "\n"
- << " AVX : " << string_from_bool(debug_flags.cpu.avx) << "\n"
- << " SSE4.1 : " << string_from_bool(debug_flags.cpu.sse41) << "\n"
- << " SSE3 : " << string_from_bool(debug_flags.cpu.sse3) << "\n"
- << " SSE2 : " << string_from_bool(debug_flags.cpu.sse2) << "\n"
- << " BVH layout : " << bvh_layout_name(debug_flags.cpu.bvh_layout) << "\n"
- << " Split : " << string_from_bool(debug_flags.cpu.split_kernel) << "\n";
-
- os << "CUDA flags:\n"
- << " Adaptive Compile: " << string_from_bool(debug_flags.cuda.adaptive_compile) << "\n";
-
- const char *opencl_device_type;
- switch(debug_flags.opencl.device_type) {
- case DebugFlags::OpenCL::DEVICE_NONE:
- opencl_device_type = "NONE";
- break;
- case DebugFlags::OpenCL::DEVICE_ALL:
- opencl_device_type = "ALL";
- break;
- case DebugFlags::OpenCL::DEVICE_DEFAULT:
- opencl_device_type = "DEFAULT";
- break;
- case DebugFlags::OpenCL::DEVICE_CPU:
- opencl_device_type = "CPU";
- break;
- case DebugFlags::OpenCL::DEVICE_GPU:
- opencl_device_type = "GPU";
- break;
- case DebugFlags::OpenCL::DEVICE_ACCELERATOR:
- opencl_device_type = "ACCELERATOR";
- break;
- }
- os << "OpenCL flags:\n"
- << " Device type : " << opencl_device_type << "\n"
- << " Debug : " << string_from_bool(debug_flags.opencl.debug) << "\n"
- << " Memory limit : " << string_human_readable_size(debug_flags.opencl.mem_limit) << "\n";
- return os;
+ os << "CPU flags:\n"
+ << " AVX2 : " << string_from_bool(debug_flags.cpu.avx2) << "\n"
+ << " AVX : " << string_from_bool(debug_flags.cpu.avx) << "\n"
+ << " SSE4.1 : " << string_from_bool(debug_flags.cpu.sse41) << "\n"
+ << " SSE3 : " << string_from_bool(debug_flags.cpu.sse3) << "\n"
+ << " SSE2 : " << string_from_bool(debug_flags.cpu.sse2) << "\n"
+ << " BVH layout : " << bvh_layout_name(debug_flags.cpu.bvh_layout) << "\n"
+ << " Split : " << string_from_bool(debug_flags.cpu.split_kernel) << "\n";
+
+ os << "CUDA flags:\n"
+ << " Adaptive Compile: " << string_from_bool(debug_flags.cuda.adaptive_compile) << "\n";
+
+ const char *opencl_device_type;
+ switch (debug_flags.opencl.device_type) {
+ case DebugFlags::OpenCL::DEVICE_NONE:
+ opencl_device_type = "NONE";
+ break;
+ case DebugFlags::OpenCL::DEVICE_ALL:
+ opencl_device_type = "ALL";
+ break;
+ case DebugFlags::OpenCL::DEVICE_DEFAULT:
+ opencl_device_type = "DEFAULT";
+ break;
+ case DebugFlags::OpenCL::DEVICE_CPU:
+ opencl_device_type = "CPU";
+ break;
+ case DebugFlags::OpenCL::DEVICE_GPU:
+ opencl_device_type = "GPU";
+ break;
+ case DebugFlags::OpenCL::DEVICE_ACCELERATOR:
+ opencl_device_type = "ACCELERATOR";
+ break;
+ }
+ os << "OpenCL flags:\n"
+ << " Device type : " << opencl_device_type << "\n"
+ << " Debug : " << string_from_bool(debug_flags.opencl.debug) << "\n"
+ << " Memory limit : " << string_human_readable_size(debug_flags.opencl.mem_limit) << "\n";
+ return os;
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/util/util_debug.h b/intern/cycles/util/util_debug.h
index e8c272cdb80..d668ddc6d6c 100644
--- a/intern/cycles/util/util_debug.h
+++ b/intern/cycles/util/util_debug.h
@@ -29,151 +29,166 @@ CCL_NAMESPACE_BEGIN
* the interface.
*/
class DebugFlags {
-public:
- /* Use static BVH in viewport, to match final render exactly. */
- bool viewport_static_bvh;
-
- /* Descriptor of CPU feature-set to be used. */
- struct CPU {
- CPU();
-
- /* Reset flags to their defaults. */
- void reset();
-
- /* Flags describing which instructions sets are allowed for use. */
- bool avx2;
- bool avx;
- bool sse41;
- bool sse3;
- bool sse2;
-
- /* Check functions to see whether instructions up to the given one
- * are allowed for use.
- */
- bool has_avx2() { return has_avx() && avx2; }
- bool has_avx() { return has_sse41() && avx; }
- bool has_sse41() { return has_sse3() && sse41; }
- bool has_sse3() { return has_sse2() && sse3; }
- bool has_sse2() { return sse2; }
-
- /* Requested BVH size.
- *
- * Rendering will use widest possible BVH which is below or equal
- * this one.
- */
- BVHLayout bvh_layout;
-
- /* Whether split kernel is used */
- bool split_kernel;
- };
-
- /* Descriptor of CUDA feature-set to be used. */
- struct CUDA {
- CUDA();
-
- /* Reset flags to their defaults. */
- void reset();
-
- /* Whether adaptive feature based runtime compile is enabled or not.
- * Requires the CUDA Toolkit and only works on Linux atm. */
- bool adaptive_compile;
-
- /* Whether split kernel is used */
- bool split_kernel;
- };
-
- /* Descriptor of OpenCL feature-set to be used. */
- struct OpenCL {
- OpenCL();
-
- /* Reset flags to their defaults. */
- void reset();
-
- /* Available device types.
- * Only gives a hint which devices to let user to choose from, does not
- * try to use any sort of optimal device or so.
- */
- enum DeviceType {
- /* None of OpenCL devices will be used. */
- DEVICE_NONE,
- /* All OpenCL devices will be used. */
- DEVICE_ALL,
- /* Default system OpenCL device will be used. */
- DEVICE_DEFAULT,
- /* Host processor will be used. */
- DEVICE_CPU,
- /* GPU devices will be used. */
- DEVICE_GPU,
- /* Dedicated OpenCL accelerator device will be used. */
- DEVICE_ACCELERATOR,
- };
-
- /* Available kernel types. */
- enum KernelType {
- /* Do automated guess which kernel to use, based on the officially
- * supported GPUs and such.
- */
- KERNEL_DEFAULT,
- /* Force mega kernel to be used. */
- KERNEL_MEGA,
- /* Force split kernel to be used. */
- KERNEL_SPLIT,
- };
-
- /* Requested device type. */
- DeviceType device_type;
-
- /* Use debug version of the kernel. */
- bool debug;
-
- /* TODO(mai): Currently this is only for OpenCL, but we should have it implemented for all devices. */
- /* Artificial memory limit in bytes (0 if disabled). */
- size_t mem_limit;
- };
-
- /* Get instance of debug flags registry. */
- static DebugFlags& get()
- {
- static DebugFlags instance;
- return instance;
- }
-
- /* Reset flags to their defaults. */
- void reset();
-
- /* Requested CPU flags. */
- CPU cpu;
-
- /* Requested CUDA flags. */
- CUDA cuda;
-
- /* Requested OpenCL flags. */
- OpenCL opencl;
-
-private:
- DebugFlags();
+ public:
+ /* Use static BVH in viewport, to match final render exactly. */
+ bool viewport_static_bvh;
+
+ /* Descriptor of CPU feature-set to be used. */
+ struct CPU {
+ CPU();
+
+ /* Reset flags to their defaults. */
+ void reset();
+
+ /* Flags describing which instructions sets are allowed for use. */
+ bool avx2;
+ bool avx;
+ bool sse41;
+ bool sse3;
+ bool sse2;
+
+ /* Check functions to see whether instructions up to the given one
+ * are allowed for use.
+ */
+ bool has_avx2()
+ {
+ return has_avx() && avx2;
+ }
+ bool has_avx()
+ {
+ return has_sse41() && avx;
+ }
+ bool has_sse41()
+ {
+ return has_sse3() && sse41;
+ }
+ bool has_sse3()
+ {
+ return has_sse2() && sse3;
+ }
+ bool has_sse2()
+ {
+ return sse2;
+ }
+
+ /* Requested BVH size.
+ *
+ * Rendering will use widest possible BVH which is below or equal
+ * this one.
+ */
+ BVHLayout bvh_layout;
+
+ /* Whether split kernel is used */
+ bool split_kernel;
+ };
+
+ /* Descriptor of CUDA feature-set to be used. */
+ struct CUDA {
+ CUDA();
+
+ /* Reset flags to their defaults. */
+ void reset();
+
+ /* Whether adaptive feature based runtime compile is enabled or not.
+ * Requires the CUDA Toolkit and only works on Linux atm. */
+ bool adaptive_compile;
+
+ /* Whether split kernel is used */
+ bool split_kernel;
+ };
+
+ /* Descriptor of OpenCL feature-set to be used. */
+ struct OpenCL {
+ OpenCL();
+
+ /* Reset flags to their defaults. */
+ void reset();
+
+ /* Available device types.
+ * Only gives a hint which devices to let user to choose from, does not
+ * try to use any sort of optimal device or so.
+ */
+ enum DeviceType {
+ /* None of OpenCL devices will be used. */
+ DEVICE_NONE,
+ /* All OpenCL devices will be used. */
+ DEVICE_ALL,
+ /* Default system OpenCL device will be used. */
+ DEVICE_DEFAULT,
+ /* Host processor will be used. */
+ DEVICE_CPU,
+ /* GPU devices will be used. */
+ DEVICE_GPU,
+ /* Dedicated OpenCL accelerator device will be used. */
+ DEVICE_ACCELERATOR,
+ };
+
+ /* Available kernel types. */
+ enum KernelType {
+ /* Do automated guess which kernel to use, based on the officially
+ * supported GPUs and such.
+ */
+ KERNEL_DEFAULT,
+ /* Force mega kernel to be used. */
+ KERNEL_MEGA,
+ /* Force split kernel to be used. */
+ KERNEL_SPLIT,
+ };
+
+ /* Requested device type. */
+ DeviceType device_type;
+
+ /* Use debug version of the kernel. */
+ bool debug;
+
+ /* TODO(mai): Currently this is only for OpenCL, but we should have it implemented for all devices. */
+ /* Artificial memory limit in bytes (0 if disabled). */
+ size_t mem_limit;
+ };
+
+ /* Get instance of debug flags registry. */
+ static DebugFlags &get()
+ {
+ static DebugFlags instance;
+ return instance;
+ }
+
+ /* Reset flags to their defaults. */
+ void reset();
+
+ /* Requested CPU flags. */
+ CPU cpu;
+
+ /* Requested CUDA flags. */
+ CUDA cuda;
+
+ /* Requested OpenCL flags. */
+ OpenCL opencl;
+
+ private:
+ DebugFlags();
#if (__cplusplus > 199711L)
-public:
- explicit DebugFlags(DebugFlags const& /*other*/) = delete;
- void operator=(DebugFlags const& /*other*/) = delete;
+ public:
+ explicit DebugFlags(DebugFlags const & /*other*/) = delete;
+ void operator=(DebugFlags const & /*other*/) = delete;
#else
-private:
- explicit DebugFlags(DebugFlags const& /*other*/);
- void operator=(DebugFlags const& /*other*/);
+ private:
+ explicit DebugFlags(DebugFlags const & /*other*/);
+ void operator=(DebugFlags const & /*other*/);
#endif
};
-typedef DebugFlags& DebugFlagsRef;
-typedef const DebugFlags& DebugFlagsConstRef;
+typedef DebugFlags &DebugFlagsRef;
+typedef const DebugFlags &DebugFlagsConstRef;
-inline DebugFlags& DebugFlags() {
+inline DebugFlags &DebugFlags()
+{
return DebugFlags::get();
}
-std::ostream& operator <<(std::ostream &os,
- DebugFlagsConstRef debug_flags);
+std::ostream &operator<<(std::ostream &os, DebugFlagsConstRef debug_flags);
CCL_NAMESPACE_END
-#endif /* __UTIL_DEBUG_H__ */
+#endif /* __UTIL_DEBUG_H__ */
diff --git a/intern/cycles/util/util_defines.h b/intern/cycles/util/util_defines.h
index 2cb42d9bd56..7f3bead0a18 100644
--- a/intern/cycles/util/util_defines.h
+++ b/intern/cycles/util/util_defines.h
@@ -16,118 +16,125 @@
*/
#ifndef __UTIL_DEFINES_H__
-#define __UTIL_DEFINES_H__
+# define __UTIL_DEFINES_H__
/* Bitness */
-#if defined(__ppc64__) || defined(__PPC64__) || defined(__x86_64__) || defined(__ia64__) || defined(_M_X64)
-# define __KERNEL_64_BIT__
-#endif
+# if defined(__ppc64__) || defined(__PPC64__) || defined(__x86_64__) || defined(__ia64__) || \
+ defined(_M_X64)
+# define __KERNEL_64_BIT__
+# endif
/* Qualifiers for kernel code shared by CPU and GPU */
-#ifndef __KERNEL_GPU__
-# define ccl_device static inline
-# define ccl_device_noinline static
-# define ccl_global
-# define ccl_static_constant static const
-# define ccl_constant const
-# define ccl_local
-# define ccl_local_param
-# define ccl_private
-# define ccl_restrict __restrict
-# define ccl_ref &
-# define __KERNEL_WITH_SSE_ALIGN__
-
-# if defined(_WIN32) && !defined(FREE_WINDOWS)
-# define ccl_device_inline static __forceinline
-# define ccl_device_forceinline static __forceinline
-# define ccl_align(...) __declspec(align(__VA_ARGS__))
-# ifdef __KERNEL_64_BIT__
-# define ccl_try_align(...) __declspec(align(__VA_ARGS__))
-# else /* __KERNEL_64_BIT__ */
-# undef __KERNEL_WITH_SSE_ALIGN__
+# ifndef __KERNEL_GPU__
+# define ccl_device static inline
+# define ccl_device_noinline static
+# define ccl_global
+# define ccl_static_constant static const
+# define ccl_constant const
+# define ccl_local
+# define ccl_local_param
+# define ccl_private
+# define ccl_restrict __restrict
+# define ccl_ref &
+# define __KERNEL_WITH_SSE_ALIGN__
+
+# if defined(_WIN32) && !defined(FREE_WINDOWS)
+# define ccl_device_inline static __forceinline
+# define ccl_device_forceinline static __forceinline
+# define ccl_align(...) __declspec(align(__VA_ARGS__))
+# ifdef __KERNEL_64_BIT__
+# define ccl_try_align(...) __declspec(align(__VA_ARGS__))
+# else /* __KERNEL_64_BIT__ */
+# undef __KERNEL_WITH_SSE_ALIGN__
/* No support for function arguments (error C2719). */
-# define ccl_try_align(...)
-# endif /* __KERNEL_64_BIT__ */
-# define ccl_may_alias
-# define ccl_always_inline __forceinline
-# define ccl_never_inline __declspec(noinline)
-# define ccl_maybe_unused
-# else /* _WIN32 && !FREE_WINDOWS */
-# define ccl_device_inline static inline __attribute__((always_inline))
-# define ccl_device_forceinline static inline __attribute__((always_inline))
-# define ccl_align(...) __attribute__((aligned(__VA_ARGS__)))
-# ifndef FREE_WINDOWS64
-# define __forceinline inline __attribute__((always_inline))
-# endif
-# define ccl_try_align(...) __attribute__((aligned(__VA_ARGS__)))
-# define ccl_may_alias __attribute__((__may_alias__))
-# define ccl_always_inline __attribute__((always_inline))
-# define ccl_never_inline __attribute__((noinline))
-# define ccl_maybe_unused __attribute__((used))
-# endif /* _WIN32 && !FREE_WINDOWS */
+# define ccl_try_align(...)
+# endif /* __KERNEL_64_BIT__ */
+# define ccl_may_alias
+# define ccl_always_inline __forceinline
+# define ccl_never_inline __declspec(noinline)
+# define ccl_maybe_unused
+# else /* _WIN32 && !FREE_WINDOWS */
+# define ccl_device_inline static inline __attribute__((always_inline))
+# define ccl_device_forceinline static inline __attribute__((always_inline))
+# define ccl_align(...) __attribute__((aligned(__VA_ARGS__)))
+# ifndef FREE_WINDOWS64
+# define __forceinline inline __attribute__((always_inline))
+# endif
+# define ccl_try_align(...) __attribute__((aligned(__VA_ARGS__)))
+# define ccl_may_alias __attribute__((__may_alias__))
+# define ccl_always_inline __attribute__((always_inline))
+# define ccl_never_inline __attribute__((noinline))
+# define ccl_maybe_unused __attribute__((used))
+# endif /* _WIN32 && !FREE_WINDOWS */
/* Use to suppress '-Wimplicit-fallthrough' (in place of 'break'). */
-# ifndef ATTR_FALLTHROUGH
-# if defined(__GNUC__) && (__GNUC__ >= 7) /* gcc7.0+ only */
-# define ATTR_FALLTHROUGH __attribute__((fallthrough))
-# else
-# define ATTR_FALLTHROUGH ((void) 0)
+# ifndef ATTR_FALLTHROUGH
+# if defined(__GNUC__) && (__GNUC__ >= 7) /* gcc7.0+ only */
+# define ATTR_FALLTHROUGH __attribute__((fallthrough))
+# else
+# define ATTR_FALLTHROUGH ((void)0)
+# endif
# endif
-# endif
-#endif /* __KERNEL_GPU__ */
+# endif /* __KERNEL_GPU__ */
/* macros */
/* hints for branch prediction, only use in code that runs a _lot_ */
-#if defined(__GNUC__) && defined(__KERNEL_CPU__)
-# define LIKELY(x) __builtin_expect(!!(x), 1)
-# define UNLIKELY(x) __builtin_expect(!!(x), 0)
-#else
-# define LIKELY(x) (x)
-# define UNLIKELY(x) (x)
-#endif
-
-#if defined(__GNUC__) || defined(__clang__)
-# if defined(__cplusplus)
-/* Some magic to be sure we don't have reference in the type. */
-template<typename T> static inline T decltype_helper(T x) { return x; }
-# define TYPEOF(x) decltype(decltype_helper(x))
+# if defined(__GNUC__) && defined(__KERNEL_CPU__)
+# define LIKELY(x) __builtin_expect(!!(x), 1)
+# define UNLIKELY(x) __builtin_expect(!!(x), 0)
# else
-# define TYPEOF(x) typeof(x)
+# define LIKELY(x) (x)
+# define UNLIKELY(x) (x)
+# endif
+
+# if defined(__GNUC__) || defined(__clang__)
+# if defined(__cplusplus)
+/* Some magic to be sure we don't have reference in the type. */
+template<typename T> static inline T decltype_helper(T x)
+{
+ return x;
+}
+# define TYPEOF(x) decltype(decltype_helper(x))
+# else
+# define TYPEOF(x) typeof(x)
+# endif
# endif
-#endif
/* Causes warning:
* incompatible types when assigning to type 'Foo' from type 'Bar'
* ... the compiler optimizes away the temp var */
-#ifdef __GNUC__
-#define CHECK_TYPE(var, type) { \
- TYPEOF(var) *__tmp; \
- __tmp = (type *)NULL; \
- (void) __tmp; \
-} (void) 0
-
-#define CHECK_TYPE_PAIR(var_a, var_b) { \
- TYPEOF(var_a) *__tmp; \
- __tmp = (typeof(var_b) *)NULL; \
- (void) __tmp; \
-} (void) 0
-#else
-# define CHECK_TYPE(var, type)
-# define CHECK_TYPE_PAIR(var_a, var_b)
-#endif
+# ifdef __GNUC__
+# define CHECK_TYPE(var, type) \
+ { \
+ TYPEOF(var) * __tmp; \
+ __tmp = (type *)NULL; \
+ (void)__tmp; \
+ } \
+ (void)0
+
+# define CHECK_TYPE_PAIR(var_a, var_b) \
+ { \
+ TYPEOF(var_a) * __tmp; \
+ __tmp = (typeof(var_b) *)NULL; \
+ (void)__tmp; \
+ } \
+ (void)0
+# else
+# define CHECK_TYPE(var, type)
+# define CHECK_TYPE_PAIR(var_a, var_b)
+# endif
/* can be used in simple macros */
-#define CHECK_TYPE_INLINE(val, type) \
- ((void)(((type)0) != (val)))
+# define CHECK_TYPE_INLINE(val, type) ((void)(((type)0) != (val)))
-#ifndef __KERNEL_GPU__
-# include <cassert>
-# define util_assert(statement) assert(statement)
-#else
-# define util_assert(statement)
-#endif
+# ifndef __KERNEL_GPU__
+# include <cassert>
+# define util_assert(statement) assert(statement)
+# else
+# define util_assert(statement)
+# endif
-#endif /* __UTIL_DEFINES_H__ */
+#endif /* __UTIL_DEFINES_H__ */
diff --git a/intern/cycles/util/util_foreach.h b/intern/cycles/util/util_foreach.h
index fd106d58b43..d907974be91 100644
--- a/intern/cycles/util/util_foreach.h
+++ b/intern/cycles/util/util_foreach.h
@@ -19,6 +19,6 @@
/* Nice foreach() loops for STL data structures. */
-#define foreach(x, y) for(x : y)
+#define foreach(x, y) for (x : y)
-#endif /* __UTIL_FOREACH_H__ */
+#endif /* __UTIL_FOREACH_H__ */
diff --git a/intern/cycles/util/util_function.h b/intern/cycles/util/util_function.h
index 72c7ce43073..f3cc00329ad 100644
--- a/intern/cycles/util/util_function.h
+++ b/intern/cycles/util/util_function.h
@@ -36,4 +36,4 @@ using std::placeholders::_9;
CCL_NAMESPACE_END
-#endif /* __UTIL_FUNCTION_H__ */
+#endif /* __UTIL_FUNCTION_H__ */
diff --git a/intern/cycles/util/util_guarded_allocator.cpp b/intern/cycles/util/util_guarded_allocator.cpp
index ae1d217c54f..1cb466a1ffa 100644
--- a/intern/cycles/util/util_guarded_allocator.cpp
+++ b/intern/cycles/util/util_guarded_allocator.cpp
@@ -25,25 +25,24 @@ static Stats global_stats(Stats::static_init);
void util_guarded_mem_alloc(size_t n)
{
- global_stats.mem_alloc(n);
+ global_stats.mem_alloc(n);
}
void util_guarded_mem_free(size_t n)
{
- global_stats.mem_free(n);
+ global_stats.mem_free(n);
}
/* Public API. */
size_t util_guarded_get_mem_used()
{
- return global_stats.mem_used;
+ return global_stats.mem_used;
}
size_t util_guarded_get_mem_peak()
{
- return global_stats.mem_peak;
+ return global_stats.mem_peak;
}
-
CCL_NAMESPACE_END
diff --git a/intern/cycles/util/util_guarded_allocator.h b/intern/cycles/util/util_guarded_allocator.h
index 99edf77e2c7..2d09326d2ca 100644
--- a/intern/cycles/util/util_guarded_allocator.h
+++ b/intern/cycles/util/util_guarded_allocator.h
@@ -31,117 +31,127 @@ void util_guarded_mem_alloc(size_t n);
void util_guarded_mem_free(size_t n);
/* Guarded allocator for the use with STL. */
-template <typename T>
-class GuardedAllocator {
-public:
- typedef size_t size_type;
- typedef ptrdiff_t difference_type;
- typedef T *pointer;
- typedef const T *const_pointer;
- typedef T& reference;
- typedef const T& const_reference;
- typedef T value_type;
-
- GuardedAllocator() {}
- GuardedAllocator(const GuardedAllocator&) {}
-
- T *allocate(size_t n, const void *hint = 0)
- {
- (void) hint;
- size_t size = n * sizeof(T);
- util_guarded_mem_alloc(size);
- if(n == 0) {
- return NULL;
- }
- T *mem;
+template<typename T> class GuardedAllocator {
+ public:
+ typedef size_t size_type;
+ typedef ptrdiff_t difference_type;
+ typedef T *pointer;
+ typedef const T *const_pointer;
+ typedef T &reference;
+ typedef const T &const_reference;
+ typedef T value_type;
+
+ GuardedAllocator()
+ {
+ }
+ GuardedAllocator(const GuardedAllocator &)
+ {
+ }
+
+ T *allocate(size_t n, const void *hint = 0)
+ {
+ (void)hint;
+ size_t size = n * sizeof(T);
+ util_guarded_mem_alloc(size);
+ if (n == 0) {
+ return NULL;
+ }
+ T *mem;
#ifdef WITH_BLENDER_GUARDEDALLOC
- /* C++ standard requires allocation functions to allocate memory suitably
- * aligned for any standard type. This is 16 bytes for 64 bit platform as
- * far as i concerned. We might over-align on 32bit here, but that should
- * be all safe actually.
- */
- mem = (T*)MEM_mallocN_aligned(size, 16, "Cycles Alloc");
+ /* C++ standard requires allocation functions to allocate memory suitably
+ * aligned for any standard type. This is 16 bytes for 64 bit platform as
+ * far as i concerned. We might over-align on 32bit here, but that should
+ * be all safe actually.
+ */
+ mem = (T *)MEM_mallocN_aligned(size, 16, "Cycles Alloc");
#else
- mem = (T*)malloc(size);
+ mem = (T *)malloc(size);
#endif
- if(mem == NULL) {
- throw std::bad_alloc();
- }
- return mem;
- }
-
- void deallocate(T *p, size_t n)
- {
- util_guarded_mem_free(n * sizeof(T));
- if(p != NULL) {
+ if (mem == NULL) {
+ throw std::bad_alloc();
+ }
+ return mem;
+ }
+
+ void deallocate(T *p, size_t n)
+ {
+ util_guarded_mem_free(n * sizeof(T));
+ if (p != NULL) {
#ifdef WITH_BLENDER_GUARDEDALLOC
- MEM_freeN(p);
+ MEM_freeN(p);
#else
- free(p);
+ free(p);
#endif
- }
- }
-
- T *address(T& x) const
- {
- return &x;
- }
-
- const T *address(const T& x) const
- {
- return &x;
- }
-
- GuardedAllocator<T>& operator=(const GuardedAllocator&)
- {
- return *this;
- }
-
- size_t max_size() const
- {
- return size_t(-1);
- }
-
- template <class U>
- struct rebind {
- typedef GuardedAllocator<U> other;
- };
-
- template <class U>
- GuardedAllocator(const GuardedAllocator<U>&) {}
-
- template <class U>
- GuardedAllocator& operator=(const GuardedAllocator<U>&) { return *this; }
-
- inline bool operator==(GuardedAllocator const& /*other*/) const { return true; }
- inline bool operator!=(GuardedAllocator const& other) const { return !operator==(other); }
+ }
+ }
+
+ T *address(T &x) const
+ {
+ return &x;
+ }
+
+ const T *address(const T &x) const
+ {
+ return &x;
+ }
+
+ GuardedAllocator<T> &operator=(const GuardedAllocator &)
+ {
+ return *this;
+ }
+
+ size_t max_size() const
+ {
+ return size_t(-1);
+ }
+
+ template<class U> struct rebind {
+ typedef GuardedAllocator<U> other;
+ };
+
+ template<class U> GuardedAllocator(const GuardedAllocator<U> &)
+ {
+ }
+
+ template<class U> GuardedAllocator &operator=(const GuardedAllocator<U> &)
+ {
+ return *this;
+ }
+
+ inline bool operator==(GuardedAllocator const & /*other*/) const
+ {
+ return true;
+ }
+ inline bool operator!=(GuardedAllocator const &other) const
+ {
+ return !operator==(other);
+ }
#ifdef _MSC_VER
- /* Welcome to the black magic here.
- *
- * The issue is that MSVC C++ allocates container proxy on any
- * vector initialization, including static vectors which don't
- * have any data yet. This leads to several issues:
- *
- * - Static objects initialization fiasco (global_stats from
- * util_stats.h might not be initialized yet).
- * - If main() function changes allocator type (for example,
- * this might happen with `blender --debug-memory`) nobody
- * will know how to convert already allocated memory to a new
- * guarded allocator.
- *
- * Here we work this around by making it so container proxy does
- * not use guarded allocation. A bit fragile, unfortunately.
- */
- template<>
- struct rebind<std::_Container_proxy> {
- typedef std::allocator<std::_Container_proxy> other;
- };
-
- operator std::allocator<std::_Container_proxy>() const
- {
- return std::allocator<std::_Container_proxy>();
- }
+ /* Welcome to the black magic here.
+ *
+ * The issue is that MSVC C++ allocates container proxy on any
+ * vector initialization, including static vectors which don't
+ * have any data yet. This leads to several issues:
+ *
+ * - Static objects initialization fiasco (global_stats from
+ * util_stats.h might not be initialized yet).
+ * - If main() function changes allocator type (for example,
+ * this might happen with `blender --debug-memory`) nobody
+ * will know how to convert already allocated memory to a new
+ * guarded allocator.
+ *
+ * Here we work this around by making it so container proxy does
+ * not use guarded allocation. A bit fragile, unfortunately.
+ */
+ template<> struct rebind<std::_Container_proxy> {
+ typedef std::allocator<std::_Container_proxy> other;
+ };
+
+ operator std::allocator<std::_Container_proxy>() const
+ {
+ return std::allocator<std::_Container_proxy>();
+ }
#endif
};
@@ -158,17 +168,17 @@ size_t util_guarded_get_mem_peak();
* when running out of memory.
*/
#define MEM_GUARDED_CALL(progress, func, ...) \
- do { \
- try { \
- (func)(__VA_ARGS__); \
- } \
- catch (std::bad_alloc&) { \
- fprintf(stderr, "Error: run out of memory!\n"); \
- fflush(stderr); \
- (progress)->set_error("Out of memory"); \
- } \
- } while(false)
+ do { \
+ try { \
+ (func)(__VA_ARGS__); \
+ } \
+ catch (std::bad_alloc &) { \
+ fprintf(stderr, "Error: run out of memory!\n"); \
+ fflush(stderr); \
+ (progress)->set_error("Out of memory"); \
+ } \
+ } while (false)
CCL_NAMESPACE_END
-#endif /* __UTIL_GUARDED_ALLOCATOR_H__ */
+#endif /* __UTIL_GUARDED_ALLOCATOR_H__ */
diff --git a/intern/cycles/util/util_half.h b/intern/cycles/util/util_half.h
index 3868509c21b..9c40f5310c2 100644
--- a/intern/cycles/util/util_half.h
+++ b/intern/cycles/util/util_half.h
@@ -21,7 +21,7 @@
#include "util/util_math.h"
#ifdef __KERNEL_SSE2__
-#include "util/util_simd.h"
+# include "util/util_simd.h"
#endif
CCL_NAMESPACE_BEGIN
@@ -30,122 +30,139 @@ CCL_NAMESPACE_BEGIN
#ifdef __KERNEL_OPENCL__
-#define float4_store_half(h, f, scale) vstore_half4(f * (scale), 0, h);
+# define float4_store_half(h, f, scale) vstore_half4(f *(scale), 0, h);
#else
/* CUDA has its own half data type, no need to define then */
-#ifndef __KERNEL_CUDA__
+# ifndef __KERNEL_CUDA__
/* Implementing this as a class rather than a typedef so that the compiler can tell it apart from unsigned shorts. */
class half {
-public:
- half() : v(0) {}
- half(const unsigned short& i) : v(i) {}
- operator unsigned short() { return v; }
- half& operator =(const unsigned short& i) { v = i; return *this; }
-private:
- unsigned short v;
+ public:
+ half() : v(0)
+ {
+ }
+ half(const unsigned short &i) : v(i)
+ {
+ }
+ operator unsigned short()
+ {
+ return v;
+ }
+ half &operator=(const unsigned short &i)
+ {
+ v = i;
+ return *this;
+ }
+
+ private:
+ unsigned short v;
};
-#endif
+# endif
-struct half4 { half x, y, z, w; };
+struct half4 {
+ half x, y, z, w;
+};
-#ifdef __KERNEL_CUDA__
+# ifdef __KERNEL_CUDA__
ccl_device_inline void float4_store_half(half *h, float4 f, float scale)
{
- h[0] = __float2half(f.x * scale);
- h[1] = __float2half(f.y * scale);
- h[2] = __float2half(f.z * scale);
- h[3] = __float2half(f.w * scale);
+ h[0] = __float2half(f.x * scale);
+ h[1] = __float2half(f.y * scale);
+ h[2] = __float2half(f.z * scale);
+ h[3] = __float2half(f.w * scale);
}
-#else
+# else
ccl_device_inline void float4_store_half(half *h, float4 f, float scale)
{
-#ifndef __KERNEL_SSE2__
- for(int i = 0; i < 4; i++) {
- /* optimized float to half for pixels:
- * assumes no negative, no nan, no inf, and sets denormal to 0 */
- union { uint i; float f; } in;
- float fscale = f[i] * scale;
- in.f = (fscale > 0.0f)? ((fscale < 65504.0f)? fscale: 65504.0f): 0.0f;
- int x = in.i;
-
- int absolute = x & 0x7FFFFFFF;
- int Z = absolute + 0xC8000000;
- int result = (absolute < 0x38800000)? 0: Z;
- int rshift = (result >> 13);
-
- h[i] = (rshift & 0x7FFF);
- }
-#else
- /* same as above with SSE */
- ssef fscale = load4f(f) * scale;
- ssef x = min(max(fscale, 0.0f), 65504.0f);
-
-#ifdef __KERNEL_AVX2__
- ssei rpack = _mm_cvtps_ph(x, 0);
-#else
- ssei absolute = cast(x) & 0x7FFFFFFF;
- ssei Z = absolute + 0xC8000000;
- ssei result = andnot(absolute < 0x38800000, Z);
- ssei rshift = (result >> 13) & 0x7FFF;
- ssei rpack = _mm_packs_epi32(rshift, rshift);
-#endif
-
- _mm_storel_pi((__m64*)h, _mm_castsi128_ps(rpack));
-#endif
+# ifndef __KERNEL_SSE2__
+ for (int i = 0; i < 4; i++) {
+ /* optimized float to half for pixels:
+ * assumes no negative, no nan, no inf, and sets denormal to 0 */
+ union {
+ uint i;
+ float f;
+ } in;
+ float fscale = f[i] * scale;
+ in.f = (fscale > 0.0f) ? ((fscale < 65504.0f) ? fscale : 65504.0f) : 0.0f;
+ int x = in.i;
+
+ int absolute = x & 0x7FFFFFFF;
+ int Z = absolute + 0xC8000000;
+ int result = (absolute < 0x38800000) ? 0 : Z;
+ int rshift = (result >> 13);
+
+ h[i] = (rshift & 0x7FFF);
+ }
+# else
+ /* same as above with SSE */
+ ssef fscale = load4f(f) * scale;
+ ssef x = min(max(fscale, 0.0f), 65504.0f);
+
+# ifdef __KERNEL_AVX2__
+ ssei rpack = _mm_cvtps_ph(x, 0);
+# else
+ ssei absolute = cast(x) & 0x7FFFFFFF;
+ ssei Z = absolute + 0xC8000000;
+ ssei result = andnot(absolute < 0x38800000, Z);
+ ssei rshift = (result >> 13) & 0x7FFF;
+ ssei rpack = _mm_packs_epi32(rshift, rshift);
+# endif
+
+ _mm_storel_pi((__m64 *)h, _mm_castsi128_ps(rpack));
+# endif
}
ccl_device_inline float half_to_float(half h)
{
- float f;
+ float f;
- *((int*) &f) = ((h & 0x8000) << 16) | (((h & 0x7c00) + 0x1C000) << 13) | ((h & 0x03FF) << 13);
+ *((int *)&f) = ((h & 0x8000) << 16) | (((h & 0x7c00) + 0x1C000) << 13) | ((h & 0x03FF) << 13);
- return f;
+ return f;
}
ccl_device_inline float4 half4_to_float4(half4 h)
{
- float4 f;
+ float4 f;
- f.x = half_to_float(h.x);
- f.y = half_to_float(h.y);
- f.z = half_to_float(h.z);
- f.w = half_to_float(h.w);
+ f.x = half_to_float(h.x);
+ f.y = half_to_float(h.y);
+ f.z = half_to_float(h.z);
+ f.w = half_to_float(h.w);
- return f;
+ return f;
}
ccl_device_inline half float_to_half(float f)
{
- const uint u = __float_as_uint(f);
- /* Sign bit, shifted to it's position. */
- uint sign_bit = u & 0x80000000;
- sign_bit >>= 16;
- /* Exponent. */
- uint exponent_bits = u & 0x7f800000;
- /* Non-sign bits. */
- uint value_bits = u & 0x7fffffff;
- value_bits >>= 13; /* Align mantissa on MSB. */
- value_bits -= 0x1c000; /* Adjust bias. */
- /* Flush-to-zero. */
- value_bits = (exponent_bits < 0x38800000) ? 0 : value_bits;
- /* Clamp-to-max. */
- value_bits = (exponent_bits > 0x47000000) ? 0x7bff : value_bits;
- /* Denormals-as-zero. */
- value_bits = (exponent_bits == 0 ? 0 : value_bits);
- /* Re-insert sign bit and return. */
- return (value_bits | sign_bit);
+ const uint u = __float_as_uint(f);
+ /* Sign bit, shifted to it's position. */
+ uint sign_bit = u & 0x80000000;
+ sign_bit >>= 16;
+ /* Exponent. */
+ uint exponent_bits = u & 0x7f800000;
+ /* Non-sign bits. */
+ uint value_bits = u & 0x7fffffff;
+ value_bits >>= 13; /* Align mantissa on MSB. */
+ value_bits -= 0x1c000; /* Adjust bias. */
+ /* Flush-to-zero. */
+ value_bits = (exponent_bits < 0x38800000) ? 0 : value_bits;
+ /* Clamp-to-max. */
+ value_bits = (exponent_bits > 0x47000000) ? 0x7bff : value_bits;
+ /* Denormals-as-zero. */
+ value_bits = (exponent_bits == 0 ? 0 : value_bits);
+ /* Re-insert sign bit and return. */
+ return (value_bits | sign_bit);
}
-#endif
+# endif
#endif
CCL_NAMESPACE_END
-#endif /* __UTIL_HALF_H__ */
+#endif /* __UTIL_HALF_H__ */
diff --git a/intern/cycles/util/util_hash.h b/intern/cycles/util/util_hash.h
index f343252eaca..785482967db 100644
--- a/intern/cycles/util/util_hash.h
+++ b/intern/cycles/util/util_hash.h
@@ -23,49 +23,56 @@ CCL_NAMESPACE_BEGIN
ccl_device_inline uint hash_int_2d(uint kx, uint ky)
{
-#define rot(x,k) (((x)<<(k)) | ((x)>>(32-(k))))
-
- uint a, b, c;
-
- a = b = c = 0xdeadbeef + (2 << 2) + 13;
- a += kx;
- b += ky;
-
- c ^= b; c -= rot(b,14);
- a ^= c; a -= rot(c,11);
- b ^= a; b -= rot(a,25);
- c ^= b; c -= rot(b,16);
- a ^= c; a -= rot(c,4);
- b ^= a; b -= rot(a,14);
- c ^= b; c -= rot(b,24);
-
- return c;
+#define rot(x, k) (((x) << (k)) | ((x) >> (32 - (k))))
+
+ uint a, b, c;
+
+ a = b = c = 0xdeadbeef + (2 << 2) + 13;
+ a += kx;
+ b += ky;
+
+ c ^= b;
+ c -= rot(b, 14);
+ a ^= c;
+ a -= rot(c, 11);
+ b ^= a;
+ b -= rot(a, 25);
+ c ^= b;
+ c -= rot(b, 16);
+ a ^= c;
+ a -= rot(c, 4);
+ b ^= a;
+ b -= rot(a, 14);
+ c ^= b;
+ c -= rot(b, 24);
+
+ return c;
#undef rot
}
ccl_device_inline uint hash_int(uint k)
{
- return hash_int_2d(k, 0);
+ return hash_int_2d(k, 0);
}
#ifndef __KERNEL_GPU__
static inline uint hash_string(const char *str)
{
- uint i = 0, c;
+ uint i = 0, c;
- while((c = *str++))
- i = i * 37 + c;
+ while ((c = *str++))
+ i = i * 37 + c;
- return i;
+ return i;
}
#endif
ccl_device_inline float hash_int_01(uint k)
{
- return (float)hash_int(k) * (1.0f/(float)0xFFFFFFFF);
+ return (float)hash_int(k) * (1.0f / (float)0xFFFFFFFF);
}
CCL_NAMESPACE_END
-#endif /* __UTIL_HASH_H__ */
+#endif /* __UTIL_HASH_H__ */
diff --git a/intern/cycles/util/util_ies.cpp b/intern/cycles/util/util_ies.cpp
index 277045d9bc4..ff5c709b406 100644
--- a/intern/cycles/util/util_ies.cpp
+++ b/intern/cycles/util/util_ies.cpp
@@ -30,374 +30,376 @@ template class GuardedAllocator<char>;
bool IESFile::load(ustring ies)
{
- clear();
- if(!parse(ies) || !process()) {
- clear();
- return false;
- }
- return true;
+ clear();
+ if (!parse(ies) || !process()) {
+ clear();
+ return false;
+ }
+ return true;
}
void IESFile::clear()
{
- intensity.clear();
- v_angles.clear();
- h_angles.clear();
+ intensity.clear();
+ v_angles.clear();
+ h_angles.clear();
}
int IESFile::packed_size()
{
- if(v_angles.size() && h_angles.size() > 0) {
- return 2 + h_angles.size() + v_angles.size() + h_angles.size()*v_angles.size();
- }
- return 0;
+ if (v_angles.size() && h_angles.size() > 0) {
+ return 2 + h_angles.size() + v_angles.size() + h_angles.size() * v_angles.size();
+ }
+ return 0;
}
void IESFile::pack(float *data)
{
- if(v_angles.size() && h_angles.size()) {
- *(data++) = __int_as_float(h_angles.size());
- *(data++) = __int_as_float(v_angles.size());
-
- memcpy(data, &h_angles[0], h_angles.size()*sizeof(float));
- data += h_angles.size();
- memcpy(data, &v_angles[0], v_angles.size()*sizeof(float));
- data += v_angles.size();
-
- for(int h = 0; h < intensity.size(); h++) {
- memcpy(data, &intensity[h][0], v_angles.size()*sizeof(float));
- data += v_angles.size();
- }
- }
+ if (v_angles.size() && h_angles.size()) {
+ *(data++) = __int_as_float(h_angles.size());
+ *(data++) = __int_as_float(v_angles.size());
+
+ memcpy(data, &h_angles[0], h_angles.size() * sizeof(float));
+ data += h_angles.size();
+ memcpy(data, &v_angles[0], v_angles.size() * sizeof(float));
+ data += v_angles.size();
+
+ for (int h = 0; h < intensity.size(); h++) {
+ memcpy(data, &intensity[h][0], v_angles.size() * sizeof(float));
+ data += v_angles.size();
+ }
+ }
}
class IESTextParser {
-public:
- vector<char> text;
- char *data;
-
- IESTextParser(ustring str)
- : text(str.begin(), str.end())
- {
- std::replace(text.begin(), text.end(), ',', ' ');
- data = strstr(&text[0], "\nTILT=");
- }
-
- bool eof() {
- return (data == NULL) || (data[0] == '\0');
- }
-
- double get_double() {
- if(eof()) {
- return 0.0;
- }
- char *old_data = data;
- double val = strtod(data, &data);
- if(data == old_data) {
- data = NULL;
- return 0.0;
- }
- return val;
- }
-
- long get_long() {
- if(eof()) {
- return 0;
- }
- char *old_data = data;
- long val = strtol(data, &data, 10);
- if(data == old_data) {
- data = NULL;
- return 0;
- }
- return val;
- }
+ public:
+ vector<char> text;
+ char *data;
+
+ IESTextParser(ustring str) : text(str.begin(), str.end())
+ {
+ std::replace(text.begin(), text.end(), ',', ' ');
+ data = strstr(&text[0], "\nTILT=");
+ }
+
+ bool eof()
+ {
+ return (data == NULL) || (data[0] == '\0');
+ }
+
+ double get_double()
+ {
+ if (eof()) {
+ return 0.0;
+ }
+ char *old_data = data;
+ double val = strtod(data, &data);
+ if (data == old_data) {
+ data = NULL;
+ return 0.0;
+ }
+ return val;
+ }
+
+ long get_long()
+ {
+ if (eof()) {
+ return 0;
+ }
+ char *old_data = data;
+ long val = strtol(data, &data, 10);
+ if (data == old_data) {
+ data = NULL;
+ return 0;
+ }
+ return val;
+ }
};
bool IESFile::parse(ustring ies)
{
- if(ies.empty()) {
- return false;
- }
-
- IESTextParser parser(ies);
- if(parser.eof()) {
- return false;
- }
-
- /* Handle the tilt data block. */
- if(strncmp(parser.data, "\nTILT=INCLUDE", 13) == 0) {
- parser.data += 13;
- parser.get_double(); /* Lamp to Luminaire geometry */
- int num_tilt = parser.get_long(); /* Amount of tilt angles and factors */
- /* Skip over angles and factors. */
- for(int i = 0; i < 2*num_tilt; i++) {
- parser.get_double();
- }
- }
- else {
- /* Skip to next line. */
- parser.data = strstr(parser.data+1, "\n");
- }
-
- if(parser.eof()) {
- return false;
- }
- parser.data++;
-
- parser.get_long(); /* Number of lamps */
- parser.get_double(); /* Lumens per lamp */
- double factor = parser.get_double(); /* Candela multiplier */
- int v_angles_num = parser.get_long(); /* Number of vertical angles */
- int h_angles_num = parser.get_long(); /* Number of horizontal angles */
- type = (IESType) parser.get_long(); /* Photometric type */
-
- /* TODO(lukas): Test whether the current type B processing can also deal with type A files.
- * In theory the only difference should be orientation which we ignore anyways, but with IES you never know...
- */
- if(type != TYPE_B && type != TYPE_C) {
- return false;
- }
-
- parser.get_long(); /* Unit of the geometry data */
- parser.get_double(); /* Width */
- parser.get_double(); /* Length */
- parser.get_double(); /* Height */
- factor *= parser.get_double(); /* Ballast factor */
- factor *= parser.get_double(); /* Ballast-Lamp Photometric factor */
- parser.get_double(); /* Input Watts */
-
- /* Intensity values in IES files are specified in candela (lumen/sr), a photometric quantity.
- * Cycles expects radiometric quantities, though, which requires a conversion.
- * However, the Luminous efficacy (ratio of lumens per Watt) depends on the spectral distribution
- * of the light source since lumens take human perception into account.
- * Since this spectral distribution is not known from the IES file, a typical one must be assumed.
- * The D65 standard illuminant has a Luminous efficacy of 177.83, which is used here to convert to Watt/sr.
- * A more advanced approach would be to add a Blackbody Temperature input to the node and numerically
- * integrate the Luminous efficacy from the resulting spectral distribution.
- * Also, the Watt/sr value must be multiplied by 4*pi to get the Watt value that Cycles expects
- * for lamp strength. Therefore, the conversion here uses 4*pi/177.83 as a Candela to Watt factor.
- */
- factor *= 0.0706650768394;
-
- v_angles.reserve(v_angles_num);
- for(int i = 0; i < v_angles_num; i++) {
- v_angles.push_back((float) parser.get_double());
- }
-
- h_angles.reserve(h_angles_num);
- for(int i = 0; i < h_angles_num; i++) {
- h_angles.push_back((float) parser.get_double());
- }
-
- intensity.resize(h_angles_num);
- for(int i = 0; i < h_angles_num; i++) {
- intensity[i].reserve(v_angles_num);
- for(int j = 0; j < v_angles_num; j++) {
- intensity[i].push_back((float) (factor * parser.get_double()));
- }
- }
-
- return !parser.eof();
+ if (ies.empty()) {
+ return false;
+ }
+
+ IESTextParser parser(ies);
+ if (parser.eof()) {
+ return false;
+ }
+
+ /* Handle the tilt data block. */
+ if (strncmp(parser.data, "\nTILT=INCLUDE", 13) == 0) {
+ parser.data += 13;
+ parser.get_double(); /* Lamp to Luminaire geometry */
+ int num_tilt = parser.get_long(); /* Amount of tilt angles and factors */
+ /* Skip over angles and factors. */
+ for (int i = 0; i < 2 * num_tilt; i++) {
+ parser.get_double();
+ }
+ }
+ else {
+ /* Skip to next line. */
+ parser.data = strstr(parser.data + 1, "\n");
+ }
+
+ if (parser.eof()) {
+ return false;
+ }
+ parser.data++;
+
+ parser.get_long(); /* Number of lamps */
+ parser.get_double(); /* Lumens per lamp */
+ double factor = parser.get_double(); /* Candela multiplier */
+ int v_angles_num = parser.get_long(); /* Number of vertical angles */
+ int h_angles_num = parser.get_long(); /* Number of horizontal angles */
+ type = (IESType)parser.get_long(); /* Photometric type */
+
+ /* TODO(lukas): Test whether the current type B processing can also deal with type A files.
+ * In theory the only difference should be orientation which we ignore anyways, but with IES you never know...
+ */
+ if (type != TYPE_B && type != TYPE_C) {
+ return false;
+ }
+
+ parser.get_long(); /* Unit of the geometry data */
+ parser.get_double(); /* Width */
+ parser.get_double(); /* Length */
+ parser.get_double(); /* Height */
+ factor *= parser.get_double(); /* Ballast factor */
+ factor *= parser.get_double(); /* Ballast-Lamp Photometric factor */
+ parser.get_double(); /* Input Watts */
+
+ /* Intensity values in IES files are specified in candela (lumen/sr), a photometric quantity.
+ * Cycles expects radiometric quantities, though, which requires a conversion.
+ * However, the Luminous efficacy (ratio of lumens per Watt) depends on the spectral distribution
+ * of the light source since lumens take human perception into account.
+ * Since this spectral distribution is not known from the IES file, a typical one must be assumed.
+ * The D65 standard illuminant has a Luminous efficacy of 177.83, which is used here to convert to Watt/sr.
+ * A more advanced approach would be to add a Blackbody Temperature input to the node and numerically
+ * integrate the Luminous efficacy from the resulting spectral distribution.
+ * Also, the Watt/sr value must be multiplied by 4*pi to get the Watt value that Cycles expects
+ * for lamp strength. Therefore, the conversion here uses 4*pi/177.83 as a Candela to Watt factor.
+ */
+ factor *= 0.0706650768394;
+
+ v_angles.reserve(v_angles_num);
+ for (int i = 0; i < v_angles_num; i++) {
+ v_angles.push_back((float)parser.get_double());
+ }
+
+ h_angles.reserve(h_angles_num);
+ for (int i = 0; i < h_angles_num; i++) {
+ h_angles.push_back((float)parser.get_double());
+ }
+
+ intensity.resize(h_angles_num);
+ for (int i = 0; i < h_angles_num; i++) {
+ intensity[i].reserve(v_angles_num);
+ for (int j = 0; j < v_angles_num; j++) {
+ intensity[i].push_back((float)(factor * parser.get_double()));
+ }
+ }
+
+ return !parser.eof();
}
bool IESFile::process_type_b()
{
- vector<vector<float> > newintensity;
- newintensity.resize(v_angles.size());
- for(int i = 0; i < v_angles.size(); i++) {
- newintensity[i].reserve(h_angles.size());
- for(int j = 0; j < h_angles.size(); j++) {
- newintensity[i].push_back(intensity[j][i]);
- }
- }
- intensity.swap(newintensity);
- h_angles.swap(v_angles);
-
- float h_first = h_angles[0], h_last = h_angles[h_angles.size()-1];
- if(h_last != 90.0f) {
- return false;
- }
-
- if(h_first == 0.0f) {
- /* The range in the file corresponds to 90°-180°, we need to mirror that to get the
- * full 180° range. */
- vector<float> new_h_angles;
- vector<vector<float> > new_intensity;
- int hnum = h_angles.size();
- new_h_angles.reserve(2*hnum-1);
- new_intensity.reserve(2*hnum-1);
- for(int i = hnum-1; i > 0; i--) {
- new_h_angles.push_back(90.0f - h_angles[i]);
- new_intensity.push_back(intensity[i]);
- }
- for(int i = 0; i < hnum; i++) {
- new_h_angles.push_back(90.0f + h_angles[i]);
- new_intensity.push_back(intensity[i]);
- }
- h_angles.swap(new_h_angles);
- intensity.swap(new_intensity);
- }
- else if(h_first == -90.0f) {
- /* We have full 180° coverage, so just shift to match the angle range convention. */
- for(int i = 0; i < h_angles.size(); i++) {
- h_angles[i] += 90.0f;
- }
- }
- /* To get correct results with the cubic interpolation in the kernel, the horizontal range
- * has to cover all 360°. Therefore, we copy the 0° entry to 360° to ensure full coverage
- * and seamless interpolation. */
- h_angles.push_back(360.0f);
- intensity.push_back(intensity[0]);
-
- float v_first = v_angles[0], v_last = v_angles[v_angles.size()-1];
- if(v_last != 90.0f) {
- return false;
- }
-
- if(v_first == 0.0f) {
- /* The range in the file corresponds to 90°-180°, we need to mirror that to get the
- * full 180° range. */
- vector<float> new_v_angles;
- int hnum = h_angles.size();
- int vnum = v_angles.size();
- new_v_angles.reserve(2*vnum-1);
- for(int i = vnum-1; i > 0; i--) {
- new_v_angles.push_back(90.0f - v_angles[i]);
- }
- for(int i = 0; i < vnum; i++) {
- new_v_angles.push_back(90.0f + v_angles[i]);
- }
- for(int i = 0; i < hnum; i++) {
- vector<float> new_intensity;
- new_intensity.reserve(2*vnum-1);
- for(int j = vnum-2; j >= 0; j--) {
- new_intensity.push_back(intensity[i][j]);
- }
- new_intensity.insert(new_intensity.end(), intensity[i].begin(), intensity[i].end());
- intensity[i].swap(new_intensity);
- }
- v_angles.swap(new_v_angles);
- }
- else if(v_first == -90.0f) {
- /* We have full 180° coverage, so just shift to match the angle range convention. */
- for(int i = 0; i < v_angles.size(); i++) {
- v_angles[i] += 90.0f;
- }
- }
-
- return true;
+ vector<vector<float>> newintensity;
+ newintensity.resize(v_angles.size());
+ for (int i = 0; i < v_angles.size(); i++) {
+ newintensity[i].reserve(h_angles.size());
+ for (int j = 0; j < h_angles.size(); j++) {
+ newintensity[i].push_back(intensity[j][i]);
+ }
+ }
+ intensity.swap(newintensity);
+ h_angles.swap(v_angles);
+
+ float h_first = h_angles[0], h_last = h_angles[h_angles.size() - 1];
+ if (h_last != 90.0f) {
+ return false;
+ }
+
+ if (h_first == 0.0f) {
+ /* The range in the file corresponds to 90°-180°, we need to mirror that to get the
+ * full 180° range. */
+ vector<float> new_h_angles;
+ vector<vector<float>> new_intensity;
+ int hnum = h_angles.size();
+ new_h_angles.reserve(2 * hnum - 1);
+ new_intensity.reserve(2 * hnum - 1);
+ for (int i = hnum - 1; i > 0; i--) {
+ new_h_angles.push_back(90.0f - h_angles[i]);
+ new_intensity.push_back(intensity[i]);
+ }
+ for (int i = 0; i < hnum; i++) {
+ new_h_angles.push_back(90.0f + h_angles[i]);
+ new_intensity.push_back(intensity[i]);
+ }
+ h_angles.swap(new_h_angles);
+ intensity.swap(new_intensity);
+ }
+ else if (h_first == -90.0f) {
+ /* We have full 180° coverage, so just shift to match the angle range convention. */
+ for (int i = 0; i < h_angles.size(); i++) {
+ h_angles[i] += 90.0f;
+ }
+ }
+ /* To get correct results with the cubic interpolation in the kernel, the horizontal range
+ * has to cover all 360°. Therefore, we copy the 0° entry to 360° to ensure full coverage
+ * and seamless interpolation. */
+ h_angles.push_back(360.0f);
+ intensity.push_back(intensity[0]);
+
+ float v_first = v_angles[0], v_last = v_angles[v_angles.size() - 1];
+ if (v_last != 90.0f) {
+ return false;
+ }
+
+ if (v_first == 0.0f) {
+ /* The range in the file corresponds to 90°-180°, we need to mirror that to get the
+ * full 180° range. */
+ vector<float> new_v_angles;
+ int hnum = h_angles.size();
+ int vnum = v_angles.size();
+ new_v_angles.reserve(2 * vnum - 1);
+ for (int i = vnum - 1; i > 0; i--) {
+ new_v_angles.push_back(90.0f - v_angles[i]);
+ }
+ for (int i = 0; i < vnum; i++) {
+ new_v_angles.push_back(90.0f + v_angles[i]);
+ }
+ for (int i = 0; i < hnum; i++) {
+ vector<float> new_intensity;
+ new_intensity.reserve(2 * vnum - 1);
+ for (int j = vnum - 2; j >= 0; j--) {
+ new_intensity.push_back(intensity[i][j]);
+ }
+ new_intensity.insert(new_intensity.end(), intensity[i].begin(), intensity[i].end());
+ intensity[i].swap(new_intensity);
+ }
+ v_angles.swap(new_v_angles);
+ }
+ else if (v_first == -90.0f) {
+ /* We have full 180° coverage, so just shift to match the angle range convention. */
+ for (int i = 0; i < v_angles.size(); i++) {
+ v_angles[i] += 90.0f;
+ }
+ }
+
+ return true;
}
bool IESFile::process_type_c()
{
- if(h_angles[0] == 90.0f) {
- /* Some files are stored from 90° to 270°, so we just rotate them to the regular 0°-180° range here. */
- for(int i = 0; i < h_angles.size(); i++) {
- h_angles[i] -= 90.0f;
- }
- }
-
- if(h_angles[0] != 0.0f) {
- return false;
- }
-
- if(h_angles.size() == 1) {
- h_angles.push_back(360.0f);
- intensity.push_back(intensity[0]);
- }
-
- if(h_angles[h_angles.size()-1] == 90.0f) {
- /* Only one quadrant is defined, so we need to mirror twice (from one to two, then to four).
- * Since the two->four mirroring step might also be required if we get an input of two quadrants,
- * we only do the first mirror here and later do the second mirror in either case. */
- int hnum = h_angles.size();
- for(int i = hnum-2; i >= 0; i--) {
- h_angles.push_back(180.0f - h_angles[i]);
- intensity.push_back(intensity[i]);
- }
- }
-
- if(h_angles[h_angles.size()-1] == 180.0f) {
- /* Mirror half to the full range. */
- int hnum = h_angles.size();
- for(int i = hnum-2; i >= 0; i--) {
- h_angles.push_back(360.0f - h_angles[i]);
- intensity.push_back(intensity[i]);
- }
- }
-
- /* Some files skip the 360° entry (contrary to standard) because it's supposed to be identical to the 0° entry.
- * If the file has a discernible order in its spacing, just fix this. */
- if(h_angles[h_angles.size()-1] != 360.0f) {
- int hnum = h_angles.size();
- float last_step = h_angles[hnum-1]-h_angles[hnum-2];
- float first_step = h_angles[1]-h_angles[0];
- float difference = 360.0f - h_angles[hnum-1];
- if(last_step == difference || first_step == difference) {
- h_angles.push_back(360.0f);
- intensity.push_back(intensity[0]);
- }
- else {
- return false;
- }
- }
-
- float v_first = v_angles[0], v_last = v_angles[v_angles.size()-1];
- if(v_first == 90.0f) {
- if(v_last == 180.0f) {
- /* Flip to ensure that vertical angles always start at 0°. */
- for(int i = 0; i < v_angles.size(); i++) {
- v_angles[i] = 180.0f - v_angles[i];
- }
- }
- else {
- return false;
- }
- }
- else if(v_first != 0.0f) {
- return false;
- }
-
- return true;
+ if (h_angles[0] == 90.0f) {
+ /* Some files are stored from 90° to 270°, so we just rotate them to the regular 0°-180° range here. */
+ for (int i = 0; i < h_angles.size(); i++) {
+ h_angles[i] -= 90.0f;
+ }
+ }
+
+ if (h_angles[0] != 0.0f) {
+ return false;
+ }
+
+ if (h_angles.size() == 1) {
+ h_angles.push_back(360.0f);
+ intensity.push_back(intensity[0]);
+ }
+
+ if (h_angles[h_angles.size() - 1] == 90.0f) {
+ /* Only one quadrant is defined, so we need to mirror twice (from one to two, then to four).
+ * Since the two->four mirroring step might also be required if we get an input of two quadrants,
+ * we only do the first mirror here and later do the second mirror in either case. */
+ int hnum = h_angles.size();
+ for (int i = hnum - 2; i >= 0; i--) {
+ h_angles.push_back(180.0f - h_angles[i]);
+ intensity.push_back(intensity[i]);
+ }
+ }
+
+ if (h_angles[h_angles.size() - 1] == 180.0f) {
+ /* Mirror half to the full range. */
+ int hnum = h_angles.size();
+ for (int i = hnum - 2; i >= 0; i--) {
+ h_angles.push_back(360.0f - h_angles[i]);
+ intensity.push_back(intensity[i]);
+ }
+ }
+
+ /* Some files skip the 360° entry (contrary to standard) because it's supposed to be identical to the 0° entry.
+ * If the file has a discernible order in its spacing, just fix this. */
+ if (h_angles[h_angles.size() - 1] != 360.0f) {
+ int hnum = h_angles.size();
+ float last_step = h_angles[hnum - 1] - h_angles[hnum - 2];
+ float first_step = h_angles[1] - h_angles[0];
+ float difference = 360.0f - h_angles[hnum - 1];
+ if (last_step == difference || first_step == difference) {
+ h_angles.push_back(360.0f);
+ intensity.push_back(intensity[0]);
+ }
+ else {
+ return false;
+ }
+ }
+
+ float v_first = v_angles[0], v_last = v_angles[v_angles.size() - 1];
+ if (v_first == 90.0f) {
+ if (v_last == 180.0f) {
+ /* Flip to ensure that vertical angles always start at 0°. */
+ for (int i = 0; i < v_angles.size(); i++) {
+ v_angles[i] = 180.0f - v_angles[i];
+ }
+ }
+ else {
+ return false;
+ }
+ }
+ else if (v_first != 0.0f) {
+ return false;
+ }
+
+ return true;
}
bool IESFile::process()
{
- if(h_angles.size() == 0 || v_angles.size() == 0) {
- return false;
- }
-
- if(type == TYPE_B) {
- if(!process_type_b()) {
- return false;
- }
- }
- else {
- assert(type == TYPE_C);
- if(!process_type_c()) {
- return false;
- }
- }
-
- assert(v_angles[0] == 0.0f);
- assert(h_angles[0] == 0.0f);
- assert(h_angles[h_angles.size()-1] == 360.0f);
-
- /* Convert from deg to rad. */
- for(int i = 0; i < v_angles.size(); i++) {
- v_angles[i] *= M_PI_F / 180.f;
- }
- for(int i = 0; i < h_angles.size(); i++) {
- h_angles[i] *= M_PI_F / 180.f;
- }
-
- return true;
+ if (h_angles.size() == 0 || v_angles.size() == 0) {
+ return false;
+ }
+
+ if (type == TYPE_B) {
+ if (!process_type_b()) {
+ return false;
+ }
+ }
+ else {
+ assert(type == TYPE_C);
+ if (!process_type_c()) {
+ return false;
+ }
+ }
+
+ assert(v_angles[0] == 0.0f);
+ assert(h_angles[0] == 0.0f);
+ assert(h_angles[h_angles.size() - 1] == 360.0f);
+
+ /* Convert from deg to rad. */
+ for (int i = 0; i < v_angles.size(); i++) {
+ v_angles[i] *= M_PI_F / 180.f;
+ }
+ for (int i = 0; i < h_angles.size(); i++) {
+ h_angles[i] *= M_PI_F / 180.f;
+ }
+
+ return true;
}
IESFile::~IESFile()
{
- clear();
+ clear();
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/util/util_ies.h b/intern/cycles/util/util_ies.h
index 096b1fdf803..ab1b9ea57cf 100644
--- a/intern/cycles/util/util_ies.h
+++ b/intern/cycles/util/util_ies.h
@@ -23,39 +23,37 @@
CCL_NAMESPACE_BEGIN
class IESFile {
-public:
- IESFile() {}
- ~IESFile();
-
- int packed_size();
- void pack(float *data);
-
- bool load(ustring ies);
- void clear();
-
-protected:
- bool parse(ustring ies);
- bool process();
- bool process_type_b();
- bool process_type_c();
-
- /* The brightness distribution is stored in spherical coordinates.
- * The horizontal angles correspond to theta in the regular notation
- * and always span the full range from 0° to 360°.
- * The vertical angles correspond to phi and always start at 0°. */
- vector<float> v_angles, h_angles;
- /* The actual values are stored here, with every entry storing the values
- * of one horizontal segment. */
- vector<vector<float> > intensity;
-
- /* Types of angle representation in IES files. Currently, only B and C are supported. */
- enum IESType {
- TYPE_A = 3,
- TYPE_B = 2,
- TYPE_C = 1
- } type;
+ public:
+ IESFile()
+ {
+ }
+ ~IESFile();
+
+ int packed_size();
+ void pack(float *data);
+
+ bool load(ustring ies);
+ void clear();
+
+ protected:
+ bool parse(ustring ies);
+ bool process();
+ bool process_type_b();
+ bool process_type_c();
+
+ /* The brightness distribution is stored in spherical coordinates.
+ * The horizontal angles correspond to theta in the regular notation
+ * and always span the full range from 0° to 360°.
+ * The vertical angles correspond to phi and always start at 0°. */
+ vector<float> v_angles, h_angles;
+ /* The actual values are stored here, with every entry storing the values
+ * of one horizontal segment. */
+ vector<vector<float>> intensity;
+
+ /* Types of angle representation in IES files. Currently, only B and C are supported. */
+ enum IESType { TYPE_A = 3, TYPE_B = 2, TYPE_C = 1 } type;
};
CCL_NAMESPACE_END
-#endif /* __UTIL_IES_H__ */
+#endif /* __UTIL_IES_H__ */
diff --git a/intern/cycles/util/util_image.h b/intern/cycles/util/util_image.h
index da5f56271c8..8962c09d098 100644
--- a/intern/cycles/util/util_image.h
+++ b/intern/cycles/util/util_image.h
@@ -15,20 +15,20 @@
*/
#ifndef __UTIL_IMAGE_H__
-#define __UTIL_IMAGE_H__
+# define __UTIL_IMAGE_H__
/* OpenImageIO is used for all image file reading and writing. */
-#include <OpenImageIO/imageio.h>
+# include <OpenImageIO/imageio.h>
-#include "util/util_vector.h"
+# include "util/util_vector.h"
CCL_NAMESPACE_BEGIN
OIIO_NAMESPACE_USING
template<typename T>
-void util_image_resize_pixels(const vector<T>& input_pixels,
+void util_image_resize_pixels(const vector<T> &input_pixels,
const size_t input_width,
const size_t input_height,
const size_t input_depth,
@@ -39,69 +39,59 @@ void util_image_resize_pixels(const vector<T>& input_pixels,
size_t *output_depth);
/* Cast input pixel from unknown storage to float. */
-template<typename T>
-inline float util_image_cast_to_float(T value);
+template<typename T> inline float util_image_cast_to_float(T value);
-template<>
-inline float util_image_cast_to_float(float value)
+template<> inline float util_image_cast_to_float(float value)
{
- return value;
+ return value;
}
-template<>
-inline float util_image_cast_to_float(uchar value)
+template<> inline float util_image_cast_to_float(uchar value)
{
- return (float)value / 255.0f;
+ return (float)value / 255.0f;
}
-template<>
-inline float util_image_cast_to_float(uint16_t value)
+template<> inline float util_image_cast_to_float(uint16_t value)
{
- return (float)value / 65535.0f;
+ return (float)value / 65535.0f;
}
-template<>
-inline float util_image_cast_to_float(half value)
+template<> inline float util_image_cast_to_float(half value)
{
- return half_to_float(value);
+ return half_to_float(value);
}
/* Cast float value to output pixel type. */
-template<typename T>
-inline T util_image_cast_from_float(float value);
+template<typename T> inline T util_image_cast_from_float(float value);
-template<>
-inline float util_image_cast_from_float(float value)
+template<> inline float util_image_cast_from_float(float value)
{
- return value;
+ return value;
}
-template<>
-inline uchar util_image_cast_from_float(float value)
+template<> inline uchar util_image_cast_from_float(float value)
{
- if(value < 0.0f) {
- return 0;
- }
- else if(value > (1.0f - 0.5f / 255.0f)) {
- return 255;
- }
- return (uchar)((255.0f * value) + 0.5f);
+ if (value < 0.0f) {
+ return 0;
+ }
+ else if (value > (1.0f - 0.5f / 255.0f)) {
+ return 255;
+ }
+ return (uchar)((255.0f * value) + 0.5f);
}
-template<>
-inline uint16_t util_image_cast_from_float(float value)
+template<> inline uint16_t util_image_cast_from_float(float value)
{
- if(value < 0.0f) {
- return 0;
- }
- else if(value > (1.0f - 0.5f / 65535.0f)) {
- return 65535;
- }
- return (uint16_t)((65535.0f * value) + 0.5f);
+ if (value < 0.0f) {
+ return 0;
+ }
+ else if (value > (1.0f - 0.5f / 65535.0f)) {
+ return 65535;
+ }
+ return (uint16_t)((65535.0f * value) + 0.5f);
}
-template<>
-inline half util_image_cast_from_float(float value)
+template<> inline half util_image_cast_from_float(float value)
{
- return float_to_half(value);
+ return float_to_half(value);
}
CCL_NAMESPACE_END
-#endif /* __UTIL_IMAGE_H__ */
+#endif /* __UTIL_IMAGE_H__ */
#include "util/util_image_impl.h"
diff --git a/intern/cycles/util/util_image_impl.h b/intern/cycles/util/util_image_impl.h
index 5bc1c727595..3eb30d070ea 100644
--- a/intern/cycles/util/util_image_impl.h
+++ b/intern/cycles/util/util_image_impl.h
@@ -26,20 +26,21 @@ CCL_NAMESPACE_BEGIN
namespace {
template<typename T>
-const T *util_image_read(const vector<T>& pixels,
+const T *util_image_read(const vector<T> &pixels,
const size_t width,
const size_t height,
const size_t /*depth*/,
const size_t components,
- const size_t x, const size_t y, const size_t z) {
- const size_t index = ((size_t)z * (width * height) +
- (size_t)y * width +
- (size_t)x) * components;
- return &pixels[index];
+ const size_t x,
+ const size_t y,
+ const size_t z)
+{
+ const size_t index = ((size_t)z * (width * height) + (size_t)y * width + (size_t)x) * components;
+ return &pixels[index];
}
template<typename T>
-void util_image_downscale_sample(const vector<T>& pixels,
+void util_image_downscale_sample(const vector<T> &pixels,
const size_t width,
const size_t height,
const size_t depth,
@@ -50,48 +51,41 @@ void util_image_downscale_sample(const vector<T>& pixels,
const float z,
T *result)
{
- assert(components <= 4);
- const size_t ix = (size_t)x,
- iy = (size_t)y,
- iz = (size_t)z;
- /* TODO(sergey): Support something smarter than box filer. */
- float accum[4] = {0};
- size_t count = 0;
- for(size_t dz = 0; dz < kernel_size; ++dz) {
- for(size_t dy = 0; dy < kernel_size; ++dy) {
- for(size_t dx = 0; dx < kernel_size; ++dx) {
- const size_t nx = ix + dx,
- ny = iy + dy,
- nz = iz + dz;
- if(nx >= width || ny >= height || nz >= depth) {
- continue;
- }
- const T *pixel = util_image_read(pixels,
- width, height, depth,
- components,
- nx, ny, nz);
- for(size_t k = 0; k < components; ++k) {
- accum[k] += util_image_cast_to_float(pixel[k]);
- }
- ++count;
- }
- }
- }
- if(count != 0) {
- const float inv_count = 1.0f / (float)count;
- for(size_t k = 0; k < components; ++k) {
- result[k] = util_image_cast_from_float<T>(accum[k] * inv_count);
- }
- }
- else {
- for(size_t k = 0; k < components; ++k) {
- result[k] = T(0.0f);
- }
- }
+ assert(components <= 4);
+ const size_t ix = (size_t)x, iy = (size_t)y, iz = (size_t)z;
+ /* TODO(sergey): Support something smarter than box filer. */
+ float accum[4] = {0};
+ size_t count = 0;
+ for (size_t dz = 0; dz < kernel_size; ++dz) {
+ for (size_t dy = 0; dy < kernel_size; ++dy) {
+ for (size_t dx = 0; dx < kernel_size; ++dx) {
+ const size_t nx = ix + dx, ny = iy + dy, nz = iz + dz;
+ if (nx >= width || ny >= height || nz >= depth) {
+ continue;
+ }
+ const T *pixel = util_image_read(pixels, width, height, depth, components, nx, ny, nz);
+ for (size_t k = 0; k < components; ++k) {
+ accum[k] += util_image_cast_to_float(pixel[k]);
+ }
+ ++count;
+ }
+ }
+ }
+ if (count != 0) {
+ const float inv_count = 1.0f / (float)count;
+ for (size_t k = 0; k < components; ++k) {
+ result[k] = util_image_cast_from_float<T>(accum[k] * inv_count);
+ }
+ }
+ else {
+ for (size_t k = 0; k < components; ++k) {
+ result[k] = T(0.0f);
+ }
+ }
}
template<typename T>
-void util_image_downscale_pixels(const vector<T>& input_pixels,
+void util_image_downscale_pixels(const vector<T> &input_pixels,
const size_t input_width,
const size_t input_height,
const size_t input_depth,
@@ -102,31 +96,33 @@ void util_image_downscale_pixels(const vector<T>& input_pixels,
const size_t output_depth,
vector<T> *output_pixels)
{
- const size_t kernel_size = (size_t)(inv_scale_factor + 0.5f);
- for(size_t z = 0; z < output_depth; ++z) {
- for(size_t y = 0; y < output_height; ++y) {
- for(size_t x = 0; x < output_width; ++x) {
- const float input_x = (float)x * inv_scale_factor,
- input_y = (float)y * inv_scale_factor,
- input_z = (float)z * inv_scale_factor;
- const size_t output_index =
- (z * output_width * output_height +
- y * output_width + x) * components;
- util_image_downscale_sample(input_pixels,
- input_width, input_height, input_depth,
- components,
- kernel_size,
- input_x, input_y, input_z,
- &output_pixels->at(output_index));
- }
- }
- }
+ const size_t kernel_size = (size_t)(inv_scale_factor + 0.5f);
+ for (size_t z = 0; z < output_depth; ++z) {
+ for (size_t y = 0; y < output_height; ++y) {
+ for (size_t x = 0; x < output_width; ++x) {
+ const float input_x = (float)x * inv_scale_factor, input_y = (float)y * inv_scale_factor,
+ input_z = (float)z * inv_scale_factor;
+ const size_t output_index = (z * output_width * output_height + y * output_width + x) *
+ components;
+ util_image_downscale_sample(input_pixels,
+ input_width,
+ input_height,
+ input_depth,
+ components,
+ kernel_size,
+ input_x,
+ input_y,
+ input_z,
+ &output_pixels->at(output_index));
+ }
+ }
+ }
}
-} /* namespace */
+} /* namespace */
template<typename T>
-void util_image_resize_pixels(const vector<T>& input_pixels,
+void util_image_resize_pixels(const vector<T> &input_pixels,
const size_t input_width,
const size_t input_height,
const size_t input_depth,
@@ -137,39 +133,43 @@ void util_image_resize_pixels(const vector<T>& input_pixels,
size_t *output_height,
size_t *output_depth)
{
- /* Early output for case when no scaling is applied. */
- if(scale_factor == 1.0f) {
- *output_width = input_width;
- *output_height = input_height;
- *output_depth = input_depth;
- *output_pixels = input_pixels;
- return;
- }
- /* First of all, we calculate output image dimensions.
- * We clamp them to be 1 pixel at least so we do not generate degenerate
- * image.
- */
- *output_width = max((size_t)((float)input_width * scale_factor), (size_t)1);
- *output_height = max((size_t)((float)input_height * scale_factor), (size_t)1);
- *output_depth = max((size_t)((float)input_depth * scale_factor), (size_t)1);
- /* Prepare pixel storage for the result. */
- const size_t num_output_pixels = ((*output_width) *
- (*output_height) *
- (*output_depth)) * components;
- output_pixels->resize(num_output_pixels);
- if(scale_factor < 1.0f) {
- const float inv_scale_factor = 1.0f / scale_factor;
- util_image_downscale_pixels(input_pixels,
- input_width, input_height, input_depth,
- components,
- inv_scale_factor,
- *output_width, *output_height, *output_depth,
- output_pixels);
- } else {
- /* TODO(sergey): Needs implementation. */
- }
+ /* Early output for case when no scaling is applied. */
+ if (scale_factor == 1.0f) {
+ *output_width = input_width;
+ *output_height = input_height;
+ *output_depth = input_depth;
+ *output_pixels = input_pixels;
+ return;
+ }
+ /* First of all, we calculate output image dimensions.
+ * We clamp them to be 1 pixel at least so we do not generate degenerate
+ * image.
+ */
+ *output_width = max((size_t)((float)input_width * scale_factor), (size_t)1);
+ *output_height = max((size_t)((float)input_height * scale_factor), (size_t)1);
+ *output_depth = max((size_t)((float)input_depth * scale_factor), (size_t)1);
+ /* Prepare pixel storage for the result. */
+ const size_t num_output_pixels = ((*output_width) * (*output_height) * (*output_depth)) *
+ components;
+ output_pixels->resize(num_output_pixels);
+ if (scale_factor < 1.0f) {
+ const float inv_scale_factor = 1.0f / scale_factor;
+ util_image_downscale_pixels(input_pixels,
+ input_width,
+ input_height,
+ input_depth,
+ components,
+ inv_scale_factor,
+ *output_width,
+ *output_height,
+ *output_depth,
+ output_pixels);
+ }
+ else {
+ /* TODO(sergey): Needs implementation. */
+ }
}
CCL_NAMESPACE_END
-#endif /* __UTIL_IMAGE_IMPL_H__ */
+#endif /* __UTIL_IMAGE_IMPL_H__ */
diff --git a/intern/cycles/util/util_list.h b/intern/cycles/util/util_list.h
index fcf8e4f5c74..f555b001186 100644
--- a/intern/cycles/util/util_list.h
+++ b/intern/cycles/util/util_list.h
@@ -25,4 +25,4 @@ using std::list;
CCL_NAMESPACE_END
-#endif /* __UTIL_LIST_H__ */
+#endif /* __UTIL_LIST_H__ */
diff --git a/intern/cycles/util/util_logging.cpp b/intern/cycles/util/util_logging.cpp
index b0922db32fb..4a5e7e6a9ea 100644
--- a/intern/cycles/util/util_logging.cpp
+++ b/intern/cycles/util/util_logging.cpp
@@ -28,63 +28,55 @@ CCL_NAMESPACE_BEGIN
void util_logging_init(const char *argv0)
{
#ifdef WITH_CYCLES_LOGGING
- using CYCLES_GFLAGS_NAMESPACE::SetCommandLineOption;
+ using CYCLES_GFLAGS_NAMESPACE::SetCommandLineOption;
- /* Make it so ERROR messages are always print into console. */
- char severity_fatal[32];
- snprintf(severity_fatal, sizeof(severity_fatal), "%d",
- google::GLOG_ERROR);
+ /* Make it so ERROR messages are always print into console. */
+ char severity_fatal[32];
+ snprintf(severity_fatal, sizeof(severity_fatal), "%d", google::GLOG_ERROR);
- google::InitGoogleLogging(argv0);
- SetCommandLineOption("logtostderr", "1");
- SetCommandLineOption("v", "0");
- SetCommandLineOption("stderrthreshold", severity_fatal);
- SetCommandLineOption("minloglevel", severity_fatal);
+ google::InitGoogleLogging(argv0);
+ SetCommandLineOption("logtostderr", "1");
+ SetCommandLineOption("v", "0");
+ SetCommandLineOption("stderrthreshold", severity_fatal);
+ SetCommandLineOption("minloglevel", severity_fatal);
#else
- (void) argv0;
+ (void)argv0;
#endif
}
void util_logging_start()
{
#ifdef WITH_CYCLES_LOGGING
- using CYCLES_GFLAGS_NAMESPACE::SetCommandLineOption;
- SetCommandLineOption("logtostderr", "1");
- SetCommandLineOption("v", "2");
- SetCommandLineOption("stderrthreshold", "1");
- SetCommandLineOption("minloglevel", "0");
+ using CYCLES_GFLAGS_NAMESPACE::SetCommandLineOption;
+ SetCommandLineOption("logtostderr", "1");
+ SetCommandLineOption("v", "2");
+ SetCommandLineOption("stderrthreshold", "1");
+ SetCommandLineOption("minloglevel", "0");
#endif
}
void util_logging_verbosity_set(int verbosity)
{
#ifdef WITH_CYCLES_LOGGING
- using CYCLES_GFLAGS_NAMESPACE::SetCommandLineOption;
- char val[10];
- snprintf(val, sizeof(val), "%d", verbosity);
- SetCommandLineOption("v", val);
+ using CYCLES_GFLAGS_NAMESPACE::SetCommandLineOption;
+ char val[10];
+ snprintf(val, sizeof(val), "%d", verbosity);
+ SetCommandLineOption("v", val);
#else
- (void) verbosity;
+ (void)verbosity;
#endif
}
-std::ostream& operator <<(std::ostream &os,
- const int2 &value)
+std::ostream &operator<<(std::ostream &os, const int2 &value)
{
- os << "(" << value.x
- << ", " << value.y
- << ")";
- return os;
+ os << "(" << value.x << ", " << value.y << ")";
+ return os;
}
-std::ostream& operator <<(std::ostream &os,
- const float3 &value)
+std::ostream &operator<<(std::ostream &os, const float3 &value)
{
- os << "(" << value.x
- << ", " << value.y
- << ", " << value.z
- << ")";
- return os;
+ os << "(" << value.x << ", " << value.y << ", " << value.z << ")";
+ return os;
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/util/util_logging.h b/intern/cycles/util/util_logging.h
index f66d7c92dcc..1a5e6666b32 100644
--- a/intern/cycles/util/util_logging.h
+++ b/intern/cycles/util/util_logging.h
@@ -28,25 +28,31 @@ CCL_NAMESPACE_BEGIN
#if !defined(WITH_CYCLES_LOGGING) || defined(__KERNEL_GPU__)
class StubStream {
-public:
- template<class T>
- StubStream& operator<<(const T&) {
- return *this;
- }
+ public:
+ template<class T> StubStream &operator<<(const T &)
+ {
+ return *this;
+ }
};
class LogMessageVoidify {
-public:
- LogMessageVoidify() { }
- void operator&(StubStream&) { }
+ public:
+ LogMessageVoidify()
+ {
+ }
+ void operator&(StubStream &)
+ {
+ }
};
-# define LOG_SUPPRESS() (true) ? ((void) 0) : LogMessageVoidify() & StubStream()
+# define LOG_SUPPRESS() (true) ? ((void)0) : LogMessageVoidify() & StubStream()
# define LOG(severity) LOG_SUPPRESS()
# define VLOG(severity) LOG_SUPPRESS()
#endif
-#define VLOG_ONCE(level, flag) if(!flag) flag = true, VLOG(level)
+#define VLOG_ONCE(level, flag) \
+ if (!flag) \
+ flag = true, VLOG(level)
struct int2;
struct float3;
@@ -55,11 +61,9 @@ void util_logging_init(const char *argv0);
void util_logging_start();
void util_logging_verbosity_set(int verbosity);
-std::ostream& operator <<(std::ostream &os,
- const int2 &value);
-std::ostream& operator <<(std::ostream &os,
- const float3 &value);
+std::ostream &operator<<(std::ostream &os, const int2 &value);
+std::ostream &operator<<(std::ostream &os, const float3 &value);
CCL_NAMESPACE_END
-#endif /* __UTIL_LOGGING_H__ */
+#endif /* __UTIL_LOGGING_H__ */
diff --git a/intern/cycles/util/util_map.h b/intern/cycles/util/util_map.h
index 1952d33ada8..3c9288417cf 100644
--- a/intern/cycles/util/util_map.h
+++ b/intern/cycles/util/util_map.h
@@ -28,4 +28,4 @@ using std::unordered_map;
CCL_NAMESPACE_END
-#endif /* __UTIL_MAP_H__ */
+#endif /* __UTIL_MAP_H__ */
diff --git a/intern/cycles/util/util_math.h b/intern/cycles/util/util_math.h
index 6167119f873..2c7f826db93 100644
--- a/intern/cycles/util/util_math.h
+++ b/intern/cycles/util/util_math.h
@@ -26,12 +26,11 @@
# include <cmath>
#endif
-
#ifndef __KERNEL_OPENCL__
# include <float.h>
# include <math.h>
# include <stdio.h>
-#endif /* __KERNEL_OPENCL__ */
+#endif /* __KERNEL_OPENCL__ */
#include "util/util_types.h"
@@ -41,22 +40,22 @@ CCL_NAMESPACE_BEGIN
/* Division */
#ifndef M_PI_F
-# define M_PI_F (3.1415926535897932f) /* pi */
+# define M_PI_F (3.1415926535897932f) /* pi */
#endif
#ifndef M_PI_2_F
-# define M_PI_2_F (1.5707963267948966f) /* pi/2 */
+# define M_PI_2_F (1.5707963267948966f) /* pi/2 */
#endif
#ifndef M_PI_4_F
-# define M_PI_4_F (0.7853981633974830f) /* pi/4 */
+# define M_PI_4_F (0.7853981633974830f) /* pi/4 */
#endif
#ifndef M_1_PI_F
-# define M_1_PI_F (0.3183098861837067f) /* 1/pi */
+# define M_1_PI_F (0.3183098861837067f) /* 1/pi */
#endif
#ifndef M_2_PI_F
-# define M_2_PI_F (0.6366197723675813f) /* 2/pi */
+# define M_2_PI_F (0.6366197723675813f) /* 2/pi */
#endif
#ifndef M_1_2PI_F
-# define M_1_2PI_F (0.1591549430918953f) /* 1/(2*pi) */
+# define M_1_2PI_F (0.1591549430918953f) /* 1/(2*pi) */
#endif
#ifndef M_SQRT_PI_8_F
# define M_SQRT_PI_8_F (0.6266570686577501f) /* sqrt(pi/8) */
@@ -67,21 +66,21 @@ CCL_NAMESPACE_BEGIN
/* Multiplication */
#ifndef M_2PI_F
-# define M_2PI_F (6.2831853071795864f) /* 2*pi */
+# define M_2PI_F (6.2831853071795864f) /* 2*pi */
#endif
#ifndef M_4PI_F
-# define M_4PI_F (12.566370614359172f) /* 4*pi */
+# define M_4PI_F (12.566370614359172f) /* 4*pi */
#endif
/* Float sqrt variations */
#ifndef M_SQRT2_F
-# define M_SQRT2_F (1.4142135623730950f) /* sqrt(2) */
+# define M_SQRT2_F (1.4142135623730950f) /* sqrt(2) */
#endif
#ifndef M_LN2_F
-# define M_LN2_F (0.6931471805599453f) /* ln(2) */
+# define M_LN2_F (0.6931471805599453f) /* ln(2) */
#endif
#ifndef M_LN10_F
-# define M_LN10_F (2.3025850929940457f) /* ln(10) */
+# define M_LN10_F (2.3025850929940457f) /* ln(10) */
#endif
/* Scalar */
@@ -90,15 +89,15 @@ CCL_NAMESPACE_BEGIN
# ifndef __KERNEL_OPENCL__
ccl_device_inline float fmaxf(float a, float b)
{
- return (a > b)? a: b;
+ return (a > b) ? a : b;
}
ccl_device_inline float fminf(float a, float b)
{
- return (a < b)? a: b;
+ return (a < b) ? a : b;
}
-# endif /* !__KERNEL_OPENCL__ */
-#endif /* _WIN32 */
+# endif /* !__KERNEL_OPENCL__ */
+#endif /* _WIN32 */
#ifndef __KERNEL_GPU__
using std::isfinite;
@@ -107,37 +106,37 @@ using std::sqrt;
ccl_device_inline int abs(int x)
{
- return (x > 0)? x: -x;
+ return (x > 0) ? x : -x;
}
ccl_device_inline int max(int a, int b)
{
- return (a > b)? a: b;
+ return (a > b) ? a : b;
}
ccl_device_inline int min(int a, int b)
{
- return (a < b)? a: b;
+ return (a < b) ? a : b;
}
ccl_device_inline float max(float a, float b)
{
- return (a > b)? a: b;
+ return (a > b) ? a : b;
}
ccl_device_inline float min(float a, float b)
{
- return (a < b)? a: b;
+ return (a < b) ? a : b;
}
ccl_device_inline double max(double a, double b)
{
- return (a > b)? a: b;
+ return (a > b) ? a : b;
}
ccl_device_inline double min(double a, double b)
{
- return (a < b)? a: b;
+ return (a < b) ? a : b;
}
/* These 2 guys are templated for usage with registers data.
@@ -146,27 +145,25 @@ ccl_device_inline double min(double a, double b)
* But for other devices we'll need to be careful about this.
*/
-template<typename T>
-ccl_device_inline T min4(const T& a, const T& b, const T& c, const T& d)
+template<typename T> ccl_device_inline T min4(const T &a, const T &b, const T &c, const T &d)
{
- return min(min(a,b),min(c,d));
+ return min(min(a, b), min(c, d));
}
-template<typename T>
-ccl_device_inline T max4(const T& a, const T& b, const T& c, const T& d)
+template<typename T> ccl_device_inline T max4(const T &a, const T &b, const T &c, const T &d)
{
- return max(max(a,b),max(c,d));
+ return max(max(a, b), max(c, d));
}
-#endif /* __KERNEL_GPU__ */
+#endif /* __KERNEL_GPU__ */
ccl_device_inline float min4(float a, float b, float c, float d)
{
- return min(min(a, b), min(c, d));
+ return min(min(a, b), min(c, d));
}
ccl_device_inline float max4(float a, float b, float c, float d)
{
- return max(max(a, b), max(c, d));
+ return max(max(a, b), max(c, d));
}
#ifndef __KERNEL_OPENCL__
@@ -174,189 +171,210 @@ ccl_device_inline float max4(float a, float b, float c, float d)
ccl_device_inline int as_int(uint i)
{
- union { uint ui; int i; } u;
- u.ui = i;
- return u.i;
+ union {
+ uint ui;
+ int i;
+ } u;
+ u.ui = i;
+ return u.i;
}
ccl_device_inline uint as_uint(int i)
{
- union { uint ui; int i; } u;
- u.i = i;
- return u.ui;
+ union {
+ uint ui;
+ int i;
+ } u;
+ u.i = i;
+ return u.ui;
}
ccl_device_inline uint as_uint(float f)
{
- union { uint i; float f; } u;
- u.f = f;
- return u.i;
+ union {
+ uint i;
+ float f;
+ } u;
+ u.f = f;
+ return u.i;
}
ccl_device_inline int __float_as_int(float f)
{
- union { int i; float f; } u;
- u.f = f;
- return u.i;
+ union {
+ int i;
+ float f;
+ } u;
+ u.f = f;
+ return u.i;
}
ccl_device_inline float __int_as_float(int i)
{
- union { int i; float f; } u;
- u.i = i;
- return u.f;
+ union {
+ int i;
+ float f;
+ } u;
+ u.i = i;
+ return u.f;
}
ccl_device_inline uint __float_as_uint(float f)
{
- union { uint i; float f; } u;
- u.f = f;
- return u.i;
+ union {
+ uint i;
+ float f;
+ } u;
+ u.f = f;
+ return u.i;
}
ccl_device_inline float __uint_as_float(uint i)
{
- union { uint i; float f; } u;
- u.i = i;
- return u.f;
+ union {
+ uint i;
+ float f;
+ } u;
+ u.i = i;
+ return u.f;
}
ccl_device_inline int4 __float4_as_int4(float4 f)
{
-#ifdef __KERNEL_SSE__
- return int4(_mm_castps_si128(f.m128));
- #else
- return make_int4(__float_as_int(f.x),
- __float_as_int(f.y),
- __float_as_int(f.z),
- __float_as_int(f.w));
-#endif
+# ifdef __KERNEL_SSE__
+ return int4(_mm_castps_si128(f.m128));
+# else
+ return make_int4(
+ __float_as_int(f.x), __float_as_int(f.y), __float_as_int(f.z), __float_as_int(f.w));
+# endif
}
ccl_device_inline float4 __int4_as_float4(int4 i)
{
-#ifdef __KERNEL_SSE__
- return float4(_mm_castsi128_ps(i.m128));
-#else
- return make_float4(__int_as_float(i.x),
- __int_as_float(i.y),
- __int_as_float(i.z),
- __int_as_float(i.w));
-#endif
+# ifdef __KERNEL_SSE__
+ return float4(_mm_castsi128_ps(i.m128));
+# else
+ return make_float4(
+ __int_as_float(i.x), __int_as_float(i.y), __int_as_float(i.z), __int_as_float(i.w));
+# endif
}
-#endif /* __KERNEL_OPENCL__ */
+#endif /* __KERNEL_OPENCL__ */
/* Versions of functions which are safe for fast math. */
ccl_device_inline bool isnan_safe(float f)
{
- unsigned int x = __float_as_uint(f);
- return (x << 1) > 0xff000000u;
+ unsigned int x = __float_as_uint(f);
+ return (x << 1) > 0xff000000u;
}
ccl_device_inline bool isfinite_safe(float f)
{
- /* By IEEE 754 rule, 2*Inf equals Inf */
- unsigned int x = __float_as_uint(f);
- return (f == f) && (x == 0 || x == (1u << 31) || (f != 2.0f*f)) && !((x << 1) > 0xff000000u);
+ /* By IEEE 754 rule, 2*Inf equals Inf */
+ unsigned int x = __float_as_uint(f);
+ return (f == f) && (x == 0 || x == (1u << 31) || (f != 2.0f * f)) && !((x << 1) > 0xff000000u);
}
ccl_device_inline float ensure_finite(float v)
{
- return isfinite_safe(v)? v : 0.0f;
+ return isfinite_safe(v) ? v : 0.0f;
}
#ifndef __KERNEL_OPENCL__
ccl_device_inline int clamp(int a, int mn, int mx)
{
- return min(max(a, mn), mx);
+ return min(max(a, mn), mx);
}
ccl_device_inline float clamp(float a, float mn, float mx)
{
- return min(max(a, mn), mx);
+ return min(max(a, mn), mx);
}
ccl_device_inline float mix(float a, float b, float t)
{
- return a + t*(b - a);
+ return a + t * (b - a);
}
-#endif /* __KERNEL_OPENCL__ */
+#endif /* __KERNEL_OPENCL__ */
#ifndef __KERNEL_CUDA__
ccl_device_inline float saturate(float a)
{
- return clamp(a, 0.0f, 1.0f);
+ return clamp(a, 0.0f, 1.0f);
}
-#endif /* __KERNEL_CUDA__ */
+#endif /* __KERNEL_CUDA__ */
ccl_device_inline int float_to_int(float f)
{
- return (int)f;
+ return (int)f;
}
ccl_device_inline int floor_to_int(float f)
{
- return float_to_int(floorf(f));
+ return float_to_int(floorf(f));
}
ccl_device_inline int quick_floor_to_int(float x)
{
- return float_to_int(x) - ((x < 0) ? 1 : 0);
+ return float_to_int(x) - ((x < 0) ? 1 : 0);
}
ccl_device_inline int ceil_to_int(float f)
{
- return float_to_int(ceilf(f));
+ return float_to_int(ceilf(f));
}
ccl_device_inline float signf(float f)
{
- return (f < 0.0f)? -1.0f: 1.0f;
+ return (f < 0.0f) ? -1.0f : 1.0f;
}
ccl_device_inline float nonzerof(float f, float eps)
{
- if(fabsf(f) < eps)
- return signf(f)*eps;
- else
- return f;
+ if (fabsf(f) < eps)
+ return signf(f) * eps;
+ else
+ return f;
}
ccl_device_inline float smoothstepf(float f)
{
- float ff = f*f;
- return (3.0f*ff - 2.0f*ff*f);
+ float ff = f * f;
+ return (3.0f * ff - 2.0f * ff * f);
}
ccl_device_inline int mod(int x, int m)
{
- return (x % m + m) % m;
+ return (x % m + m) % m;
}
ccl_device_inline float3 float2_to_float3(const float2 a)
{
- return make_float3(a.x, a.y, 0.0f);
+ return make_float3(a.x, a.y, 0.0f);
}
ccl_device_inline float3 float4_to_float3(const float4 a)
{
- return make_float3(a.x, a.y, a.z);
+ return make_float3(a.x, a.y, a.z);
}
ccl_device_inline float4 float3_to_float4(const float3 a)
{
- return make_float4(a.x, a.y, a.z, 1.0f);
+ return make_float4(a.x, a.y, a.z, 1.0f);
}
ccl_device_inline float inverse_lerp(float a, float b, float x)
{
- return (x - a) / (b - a);
+ return (x - a) / (b - a);
}
/* Cubic interpolation between b and c, a and d are the previous and next point. */
ccl_device_inline float cubic_interp(float a, float b, float c, float d, float x)
{
- return 0.5f*(((d + 3.0f*(b-c) - a)*x + (2.0f*a - 5.0f*b + 4.0f*c - d))*x + (c - a))*x + b;
+ return 0.5f *
+ (((d + 3.0f * (b - c) - a) * x + (2.0f * a - 5.0f * b + 4.0f * c - d)) * x +
+ (c - a)) *
+ x +
+ b;
}
CCL_NAMESPACE_END
@@ -376,26 +394,22 @@ CCL_NAMESPACE_BEGIN
#ifndef __KERNEL_OPENCL__
/* Interpolation */
-template<class A, class B> A lerp(const A& a, const A& b, const B& t)
+template<class A, class B> A lerp(const A &a, const A &b, const B &t)
{
- return (A)(a * ((B)1 - t) + b * t);
+ return (A)(a * ((B)1 - t) + b * t);
}
-#endif /* __KERNEL_OPENCL__ */
+#endif /* __KERNEL_OPENCL__ */
/* Triangle */
#ifndef __KERNEL_OPENCL__
-ccl_device_inline float triangle_area(const float3& v1,
- const float3& v2,
- const float3& v3)
+ccl_device_inline float triangle_area(const float3 &v1, const float3 &v2, const float3 &v3)
#else
-ccl_device_inline float triangle_area(const float3 v1,
- const float3 v2,
- const float3 v3)
+ccl_device_inline float triangle_area(const float3 v1, const float3 v2, const float3 v3)
#endif
{
- return len(cross(v3 - v2, v1 - v2))*0.5f;
+ return len(cross(v3 - v2, v1 - v2)) * 0.5f;
}
/* Orthonormal vectors */
@@ -403,240 +417,240 @@ ccl_device_inline float triangle_area(const float3 v1,
ccl_device_inline void make_orthonormals(const float3 N, float3 *a, float3 *b)
{
#if 0
- if(fabsf(N.y) >= 0.999f) {
- *a = make_float3(1, 0, 0);
- *b = make_float3(0, 0, 1);
- return;
- }
- if(fabsf(N.z) >= 0.999f) {
- *a = make_float3(1, 0, 0);
- *b = make_float3(0, 1, 0);
- return;
- }
+ if(fabsf(N.y) >= 0.999f) {
+ *a = make_float3(1, 0, 0);
+ *b = make_float3(0, 0, 1);
+ return;
+ }
+ if(fabsf(N.z) >= 0.999f) {
+ *a = make_float3(1, 0, 0);
+ *b = make_float3(0, 1, 0);
+ return;
+ }
#endif
- if(N.x != N.y || N.x != N.z)
- *a = make_float3(N.z-N.y, N.x-N.z, N.y-N.x); //(1,1,1)x N
- else
- *a = make_float3(N.z-N.y, N.x+N.z, -N.y-N.x); //(-1,1,1)x N
+ if (N.x != N.y || N.x != N.z)
+ *a = make_float3(N.z - N.y, N.x - N.z, N.y - N.x); //(1,1,1)x N
+ else
+ *a = make_float3(N.z - N.y, N.x + N.z, -N.y - N.x); //(-1,1,1)x N
- *a = normalize(*a);
- *b = cross(N, *a);
+ *a = normalize(*a);
+ *b = cross(N, *a);
}
/* Color division */
ccl_device_inline float3 safe_invert_color(float3 a)
{
- float x, y, z;
+ float x, y, z;
- x = (a.x != 0.0f)? 1.0f/a.x: 0.0f;
- y = (a.y != 0.0f)? 1.0f/a.y: 0.0f;
- z = (a.z != 0.0f)? 1.0f/a.z: 0.0f;
+ x = (a.x != 0.0f) ? 1.0f / a.x : 0.0f;
+ y = (a.y != 0.0f) ? 1.0f / a.y : 0.0f;
+ z = (a.z != 0.0f) ? 1.0f / a.z : 0.0f;
- return make_float3(x, y, z);
+ return make_float3(x, y, z);
}
ccl_device_inline float3 safe_divide_color(float3 a, float3 b)
{
- float x, y, z;
+ float x, y, z;
- x = (b.x != 0.0f)? a.x/b.x: 0.0f;
- y = (b.y != 0.0f)? a.y/b.y: 0.0f;
- z = (b.z != 0.0f)? a.z/b.z: 0.0f;
+ x = (b.x != 0.0f) ? a.x / b.x : 0.0f;
+ y = (b.y != 0.0f) ? a.y / b.y : 0.0f;
+ z = (b.z != 0.0f) ? a.z / b.z : 0.0f;
- return make_float3(x, y, z);
+ return make_float3(x, y, z);
}
ccl_device_inline float3 safe_divide_even_color(float3 a, float3 b)
{
- float x, y, z;
-
- x = (b.x != 0.0f)? a.x/b.x: 0.0f;
- y = (b.y != 0.0f)? a.y/b.y: 0.0f;
- z = (b.z != 0.0f)? a.z/b.z: 0.0f;
-
- /* try to get gray even if b is zero */
- if(b.x == 0.0f) {
- if(b.y == 0.0f) {
- x = z;
- y = z;
- }
- else if(b.z == 0.0f) {
- x = y;
- z = y;
- }
- else
- x = 0.5f*(y + z);
- }
- else if(b.y == 0.0f) {
- if(b.z == 0.0f) {
- y = x;
- z = x;
- }
- else
- y = 0.5f*(x + z);
- }
- else if(b.z == 0.0f) {
- z = 0.5f*(x + y);
- }
-
- return make_float3(x, y, z);
+ float x, y, z;
+
+ x = (b.x != 0.0f) ? a.x / b.x : 0.0f;
+ y = (b.y != 0.0f) ? a.y / b.y : 0.0f;
+ z = (b.z != 0.0f) ? a.z / b.z : 0.0f;
+
+ /* try to get gray even if b is zero */
+ if (b.x == 0.0f) {
+ if (b.y == 0.0f) {
+ x = z;
+ y = z;
+ }
+ else if (b.z == 0.0f) {
+ x = y;
+ z = y;
+ }
+ else
+ x = 0.5f * (y + z);
+ }
+ else if (b.y == 0.0f) {
+ if (b.z == 0.0f) {
+ y = x;
+ z = x;
+ }
+ else
+ y = 0.5f * (x + z);
+ }
+ else if (b.z == 0.0f) {
+ z = 0.5f * (x + y);
+ }
+
+ return make_float3(x, y, z);
}
/* Rotation of point around axis and angle */
ccl_device_inline float3 rotate_around_axis(float3 p, float3 axis, float angle)
{
- float costheta = cosf(angle);
- float sintheta = sinf(angle);
- float3 r;
+ float costheta = cosf(angle);
+ float sintheta = sinf(angle);
+ float3 r;
- r.x = ((costheta + (1 - costheta) * axis.x * axis.x) * p.x) +
- (((1 - costheta) * axis.x * axis.y - axis.z * sintheta) * p.y) +
- (((1 - costheta) * axis.x * axis.z + axis.y * sintheta) * p.z);
+ r.x = ((costheta + (1 - costheta) * axis.x * axis.x) * p.x) +
+ (((1 - costheta) * axis.x * axis.y - axis.z * sintheta) * p.y) +
+ (((1 - costheta) * axis.x * axis.z + axis.y * sintheta) * p.z);
- r.y = (((1 - costheta) * axis.x * axis.y + axis.z * sintheta) * p.x) +
- ((costheta + (1 - costheta) * axis.y * axis.y) * p.y) +
- (((1 - costheta) * axis.y * axis.z - axis.x * sintheta) * p.z);
+ r.y = (((1 - costheta) * axis.x * axis.y + axis.z * sintheta) * p.x) +
+ ((costheta + (1 - costheta) * axis.y * axis.y) * p.y) +
+ (((1 - costheta) * axis.y * axis.z - axis.x * sintheta) * p.z);
- r.z = (((1 - costheta) * axis.x * axis.z - axis.y * sintheta) * p.x) +
- (((1 - costheta) * axis.y * axis.z + axis.x * sintheta) * p.y) +
- ((costheta + (1 - costheta) * axis.z * axis.z) * p.z);
+ r.z = (((1 - costheta) * axis.x * axis.z - axis.y * sintheta) * p.x) +
+ (((1 - costheta) * axis.y * axis.z + axis.x * sintheta) * p.y) +
+ ((costheta + (1 - costheta) * axis.z * axis.z) * p.z);
- return r;
+ return r;
}
/* NaN-safe math ops */
ccl_device_inline float safe_sqrtf(float f)
{
- return sqrtf(max(f, 0.0f));
+ return sqrtf(max(f, 0.0f));
}
ccl_device float safe_asinf(float a)
{
- return asinf(clamp(a, -1.0f, 1.0f));
+ return asinf(clamp(a, -1.0f, 1.0f));
}
ccl_device float safe_acosf(float a)
{
- return acosf(clamp(a, -1.0f, 1.0f));
+ return acosf(clamp(a, -1.0f, 1.0f));
}
ccl_device float compatible_powf(float x, float y)
{
#ifdef __KERNEL_GPU__
- if(y == 0.0f) /* x^0 -> 1, including 0^0 */
- return 1.0f;
-
- /* GPU pow doesn't accept negative x, do manual checks here */
- if(x < 0.0f) {
- if(fmodf(-y, 2.0f) == 0.0f)
- return powf(-x, y);
- else
- return -powf(-x, y);
- }
- else if(x == 0.0f)
- return 0.0f;
+ if (y == 0.0f) /* x^0 -> 1, including 0^0 */
+ return 1.0f;
+
+ /* GPU pow doesn't accept negative x, do manual checks here */
+ if (x < 0.0f) {
+ if (fmodf(-y, 2.0f) == 0.0f)
+ return powf(-x, y);
+ else
+ return -powf(-x, y);
+ }
+ else if (x == 0.0f)
+ return 0.0f;
#endif
- return powf(x, y);
+ return powf(x, y);
}
ccl_device float safe_powf(float a, float b)
{
- if(UNLIKELY(a < 0.0f && b != float_to_int(b)))
- return 0.0f;
+ if (UNLIKELY(a < 0.0f && b != float_to_int(b)))
+ return 0.0f;
- return compatible_powf(a, b);
+ return compatible_powf(a, b);
}
ccl_device float safe_divide(float a, float b)
{
- return (b != 0.0f)? a/b: 0.0f;
+ return (b != 0.0f) ? a / b : 0.0f;
}
ccl_device float safe_logf(float a, float b)
{
- if(UNLIKELY(a <= 0.0f || b <= 0.0f))
- return 0.0f;
+ if (UNLIKELY(a <= 0.0f || b <= 0.0f))
+ return 0.0f;
- return safe_divide(logf(a),logf(b));
+ return safe_divide(logf(a), logf(b));
}
ccl_device float safe_modulo(float a, float b)
{
- return (b != 0.0f)? fmodf(a, b): 0.0f;
+ return (b != 0.0f) ? fmodf(a, b) : 0.0f;
}
ccl_device_inline float sqr(float a)
{
- return a * a;
+ return a * a;
}
ccl_device_inline float pow20(float a)
{
- return sqr(sqr(sqr(sqr(a))*a));
+ return sqr(sqr(sqr(sqr(a)) * a));
}
ccl_device_inline float pow22(float a)
{
- return sqr(a*sqr(sqr(sqr(a))*a));
+ return sqr(a * sqr(sqr(sqr(a)) * a));
}
ccl_device_inline float beta(float x, float y)
{
#ifndef __KERNEL_OPENCL__
- return expf(lgammaf(x) + lgammaf(y) - lgammaf(x+y));
+ return expf(lgammaf(x) + lgammaf(y) - lgammaf(x + y));
#else
- return expf(lgamma(x) + lgamma(y) - lgamma(x+y));
+ return expf(lgamma(x) + lgamma(y) - lgamma(x + y));
#endif
}
ccl_device_inline float xor_signmask(float x, int y)
{
- return __int_as_float(__float_as_int(x) ^ y);
+ return __int_as_float(__float_as_int(x) ^ y);
}
ccl_device float bits_to_01(uint bits)
{
- return bits * (1.0f/(float)0xFFFFFFFF);
+ return bits * (1.0f / (float)0xFFFFFFFF);
}
/* projections */
ccl_device_inline float2 map_to_tube(const float3 co)
{
- float len, u, v;
- len = sqrtf(co.x * co.x + co.y * co.y);
- if(len > 0.0f) {
- u = (1.0f - (atan2f(co.x / len, co.y / len) / M_PI_F)) * 0.5f;
- v = (co.z + 1.0f) * 0.5f;
- }
- else {
- u = v = 0.0f;
- }
- return make_float2(u, v);
+ float len, u, v;
+ len = sqrtf(co.x * co.x + co.y * co.y);
+ if (len > 0.0f) {
+ u = (1.0f - (atan2f(co.x / len, co.y / len) / M_PI_F)) * 0.5f;
+ v = (co.z + 1.0f) * 0.5f;
+ }
+ else {
+ u = v = 0.0f;
+ }
+ return make_float2(u, v);
}
ccl_device_inline float2 map_to_sphere(const float3 co)
{
- float l = len(co);
- float u, v;
- if(l > 0.0f) {
- if(UNLIKELY(co.x == 0.0f && co.y == 0.0f)) {
- u = 0.0f; /* othwise domain error */
- }
- else {
- u = (1.0f - atan2f(co.x, co.y) / M_PI_F) / 2.0f;
- }
- v = 1.0f - safe_acosf(co.z / l) / M_PI_F;
- }
- else {
- u = v = 0.0f;
- }
- return make_float2(u, v);
+ float l = len(co);
+ float u, v;
+ if (l > 0.0f) {
+ if (UNLIKELY(co.x == 0.0f && co.y == 0.0f)) {
+ u = 0.0f; /* othwise domain error */
+ }
+ else {
+ u = (1.0f - atan2f(co.x, co.y) / M_PI_F) / 2.0f;
+ }
+ v = 1.0f - safe_acosf(co.z / l) / M_PI_F;
+ }
+ else {
+ u = v = 0.0f;
+ }
+ return make_float2(u, v);
}
CCL_NAMESPACE_END
-#endif /* __UTIL_MATH_H__ */
+#endif /* __UTIL_MATH_H__ */
diff --git a/intern/cycles/util/util_math_cdf.cpp b/intern/cycles/util/util_math_cdf.cpp
index c14d4793ea1..a58bab188ef 100644
--- a/intern/cycles/util/util_math_cdf.cpp
+++ b/intern/cycles/util/util_math_cdf.cpp
@@ -27,41 +27,44 @@ void util_cdf_invert(const int resolution,
const float to,
const vector<float> &cdf,
const bool make_symmetric,
- vector<float> &inv_cdf) {
- const float inv_resolution = 1.0f / (float)resolution;
- const float range = to - from;
- inv_cdf.resize(resolution);
- if(make_symmetric) {
- const int half_size = (resolution - 1) / 2;
- for(int i = 0; i <= half_size; i++) {
- float x = i / (float)half_size;
- int index = upper_bound(cdf.begin(), cdf.end(), x) - cdf.begin();
- float t;
- if(index < cdf.size() - 1) {
- t = (x - cdf[index])/(cdf[index+1] - cdf[index]);
- } else {
- t = 0.0f;
- index = cdf.size() - 1;
- }
- float y = ((index + t) / (resolution - 1)) * (2.0f * range);
- inv_cdf[half_size+i] = 0.5f*(1.0f + y);
- inv_cdf[half_size-i] = 0.5f*(1.0f - y);
- }
- }
- else {
- for(int i = 0; i < resolution; i++) {
- float x = from + range * (float)i * inv_resolution;
- int index = upper_bound(cdf.begin(), cdf.end(), x) - cdf.begin();
- float t;
- if(index < cdf.size() - 1) {
- t = (x - cdf[index])/(cdf[index+1] - cdf[index]);
- } else {
- t = 0.0f;
- index = resolution;
- }
- inv_cdf[i] = (index + t) * inv_resolution;
- }
- }
+ vector<float> &inv_cdf)
+{
+ const float inv_resolution = 1.0f / (float)resolution;
+ const float range = to - from;
+ inv_cdf.resize(resolution);
+ if (make_symmetric) {
+ const int half_size = (resolution - 1) / 2;
+ for (int i = 0; i <= half_size; i++) {
+ float x = i / (float)half_size;
+ int index = upper_bound(cdf.begin(), cdf.end(), x) - cdf.begin();
+ float t;
+ if (index < cdf.size() - 1) {
+ t = (x - cdf[index]) / (cdf[index + 1] - cdf[index]);
+ }
+ else {
+ t = 0.0f;
+ index = cdf.size() - 1;
+ }
+ float y = ((index + t) / (resolution - 1)) * (2.0f * range);
+ inv_cdf[half_size + i] = 0.5f * (1.0f + y);
+ inv_cdf[half_size - i] = 0.5f * (1.0f - y);
+ }
+ }
+ else {
+ for (int i = 0; i < resolution; i++) {
+ float x = from + range * (float)i * inv_resolution;
+ int index = upper_bound(cdf.begin(), cdf.end(), x) - cdf.begin();
+ float t;
+ if (index < cdf.size() - 1) {
+ t = (x - cdf[index]) / (cdf[index + 1] - cdf[index]);
+ }
+ else {
+ t = 0.0f;
+ index = resolution;
+ }
+ inv_cdf[i] = (index + t) * inv_resolution;
+ }
+ }
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/util/util_math_cdf.h b/intern/cycles/util/util_math_cdf.h
index 983855e3e9b..43995204263 100644
--- a/intern/cycles/util/util_math_cdf.h
+++ b/intern/cycles/util/util_math_cdf.h
@@ -24,27 +24,24 @@
CCL_NAMESPACE_BEGIN
/* Evaluate CDF of a given functor with given range and resolution. */
-template <typename Functor>
-void util_cdf_evaluate(const int resolution,
- const float from,
- const float to,
- Functor functor,
- vector<float> &cdf)
+template<typename Functor>
+void util_cdf_evaluate(
+ const int resolution, const float from, const float to, Functor functor, vector<float> &cdf)
{
- const int cdf_count = resolution + 1;
- const float range = to - from;
- cdf.resize(cdf_count);
- cdf[0] = 0.0f;
- /* Actual CDF evaluation. */
- for(int i = 0; i < resolution; ++i) {
- float x = from + range * (float)i / (resolution - 1);
- float y = functor(x);
- cdf[i + 1] = cdf[i] + fabsf(y);
- }
- /* Normalize the CDF. */
- for(int i = 0; i <= resolution; i++) {
- cdf[i] /= cdf[resolution];
- }
+ const int cdf_count = resolution + 1;
+ const float range = to - from;
+ cdf.resize(cdf_count);
+ cdf[0] = 0.0f;
+ /* Actual CDF evaluation. */
+ for (int i = 0; i < resolution; ++i) {
+ float x = from + range * (float)i / (resolution - 1);
+ float y = functor(x);
+ cdf[i + 1] = cdf[i] + fabsf(y);
+ }
+ /* Normalize the CDF. */
+ for (int i = 0; i <= resolution; i++) {
+ cdf[i] /= cdf[resolution];
+ }
}
/* Invert pre-calculated CDF function. */
@@ -56,7 +53,7 @@ void util_cdf_invert(const int resolution,
vector<float> &inv_cdf);
/* Evaluate inverted CDF of a given functor with given range and resolution. */
-template <typename Functor>
+template<typename Functor>
void util_cdf_inverted(const int resolution,
const float from,
const float to,
@@ -64,15 +61,15 @@ void util_cdf_inverted(const int resolution,
const bool make_symmetric,
vector<float> &inv_cdf)
{
- vector<float> cdf;
- /* There is no much smartness going around lower resolution for the CDF table,
- * this just to match the old code from pixel filter so it all stays exactly
- * the same and no regression tests are failed.
- */
- util_cdf_evaluate(resolution - 1, from, to, functor, cdf);
- util_cdf_invert(resolution, from, to, cdf, make_symmetric, inv_cdf);
+ vector<float> cdf;
+ /* There is no much smartness going around lower resolution for the CDF table,
+ * this just to match the old code from pixel filter so it all stays exactly
+ * the same and no regression tests are failed.
+ */
+ util_cdf_evaluate(resolution - 1, from, to, functor, cdf);
+ util_cdf_invert(resolution, from, to, cdf, make_symmetric, inv_cdf);
}
CCL_NAMESPACE_END
-#endif /* __UTIL_MATH_H_CDF__ */
+#endif /* __UTIL_MATH_H_CDF__ */
diff --git a/intern/cycles/util/util_math_fast.h b/intern/cycles/util/util_math_fast.h
index fe4e02197a4..872271666aa 100644
--- a/intern/cycles/util/util_math_fast.h
+++ b/intern/cycles/util/util_math_fast.h
@@ -49,18 +49,18 @@ CCL_NAMESPACE_BEGIN
ccl_device_inline float madd(const float a, const float b, const float c)
{
- /* NOTE: In the future we may want to explicitly ask for a fused
- * multiply-add in a specialized version for float.
- *
- * NOTE: GCC/ICC will turn this (for float) into a FMA unless
- * explicitly asked not to, clang seems to leave the code alone.
- */
- return a * b + c;
+ /* NOTE: In the future we may want to explicitly ask for a fused
+ * multiply-add in a specialized version for float.
+ *
+ * NOTE: GCC/ICC will turn this (for float) into a FMA unless
+ * explicitly asked not to, clang seems to leave the code alone.
+ */
+ return a * b + c;
}
ccl_device_inline float4 madd4(const float4 a, const float4 b, const float4 c)
{
- return a * b + c;
+ return a * b + c;
}
/*
@@ -82,116 +82,117 @@ ccl_device_inline float4 madd4(const float4 a, const float4 b, const float4 c)
/* Round to nearest integer, returning as an int. */
ccl_device_inline int fast_rint(float x)
{
- /* used by sin/cos/tan range reduction. */
+ /* used by sin/cos/tan range reduction. */
#ifdef __KERNEL_SSE4__
- /* Single roundps instruction on SSE4.1+ (for gcc/clang at least). */
- return float_to_int(rintf(x));
+ /* Single roundps instruction on SSE4.1+ (for gcc/clang at least). */
+ return float_to_int(rintf(x));
#else
- /* emulate rounding by adding/substracting 0.5. */
- return float_to_int(x + copysignf(0.5f, x));
+ /* emulate rounding by adding/substracting 0.5. */
+ return float_to_int(x + copysignf(0.5f, x));
#endif
}
ccl_device float fast_sinf(float x)
{
- /* Very accurate argument reduction from SLEEF,
- * starts failing around x=262000
- *
- * Results on: [-2pi,2pi].
- *
- * Examined 2173837240 values of sin: 0.00662760244 avg ulp diff, 2 max ulp,
- * 1.19209e-07 max error
- */
- int q = fast_rint(x * M_1_PI_F);
- float qf = q;
- x = madd(qf, -0.78515625f*4, x);
- x = madd(qf, -0.00024187564849853515625f*4, x);
- x = madd(qf, -3.7747668102383613586e-08f*4, x);
- x = madd(qf, -1.2816720341285448015e-12f*4, x);
- x = M_PI_2_F - (M_PI_2_F - x); /* Crush denormals */
- float s = x * x;
- if((q & 1) != 0) x = -x;
- /* This polynomial approximation has very low error on [-pi/2,+pi/2]
- * 1.19209e-07 max error in total over [-2pi,+2pi]. */
- float u = 2.6083159809786593541503e-06f;
- u = madd(u, s, -0.0001981069071916863322258f);
- u = madd(u, s, +0.00833307858556509017944336f);
- u = madd(u, s, -0.166666597127914428710938f);
- u = madd(s, u * x, x);
- /* For large x, the argument reduction can fail and the polynomial can be
- * evaluated with arguments outside the valid internal. Just clamp the bad
- * values away (setting to 0.0f means no branches need to be generated). */
- if(fabsf(u) > 1.0f) {
- u = 0.0f;
- }
- return u;
+ /* Very accurate argument reduction from SLEEF,
+ * starts failing around x=262000
+ *
+ * Results on: [-2pi,2pi].
+ *
+ * Examined 2173837240 values of sin: 0.00662760244 avg ulp diff, 2 max ulp,
+ * 1.19209e-07 max error
+ */
+ int q = fast_rint(x * M_1_PI_F);
+ float qf = q;
+ x = madd(qf, -0.78515625f * 4, x);
+ x = madd(qf, -0.00024187564849853515625f * 4, x);
+ x = madd(qf, -3.7747668102383613586e-08f * 4, x);
+ x = madd(qf, -1.2816720341285448015e-12f * 4, x);
+ x = M_PI_2_F - (M_PI_2_F - x); /* Crush denormals */
+ float s = x * x;
+ if ((q & 1) != 0)
+ x = -x;
+ /* This polynomial approximation has very low error on [-pi/2,+pi/2]
+ * 1.19209e-07 max error in total over [-2pi,+2pi]. */
+ float u = 2.6083159809786593541503e-06f;
+ u = madd(u, s, -0.0001981069071916863322258f);
+ u = madd(u, s, +0.00833307858556509017944336f);
+ u = madd(u, s, -0.166666597127914428710938f);
+ u = madd(s, u * x, x);
+ /* For large x, the argument reduction can fail and the polynomial can be
+ * evaluated with arguments outside the valid internal. Just clamp the bad
+ * values away (setting to 0.0f means no branches need to be generated). */
+ if (fabsf(u) > 1.0f) {
+ u = 0.0f;
+ }
+ return u;
}
ccl_device float fast_cosf(float x)
{
- /* Same argument reduction as fast_sinf(). */
- int q = fast_rint(x * M_1_PI_F);
- float qf = q;
- x = madd(qf, -0.78515625f*4, x);
- x = madd(qf, -0.00024187564849853515625f*4, x);
- x = madd(qf, -3.7747668102383613586e-08f*4, x);
- x = madd(qf, -1.2816720341285448015e-12f*4, x);
- x = M_PI_2_F - (M_PI_2_F - x); /* Crush denormals. */
- float s = x * x;
- /* Polynomial from SLEEF's sincosf, max error is
- * 4.33127e-07 over [-2pi,2pi] (98% of values are "exact"). */
- float u = -2.71811842367242206819355e-07f;
- u = madd(u, s, +2.47990446951007470488548e-05f);
- u = madd(u, s, -0.00138888787478208541870117f);
- u = madd(u, s, +0.0416666641831398010253906f);
- u = madd(u, s, -0.5f);
- u = madd(u, s, +1.0f);
- if((q & 1) != 0) {
- u = -u;
- }
- if(fabsf(u) > 1.0f) {
- u = 0.0f;
- }
- return u;
+ /* Same argument reduction as fast_sinf(). */
+ int q = fast_rint(x * M_1_PI_F);
+ float qf = q;
+ x = madd(qf, -0.78515625f * 4, x);
+ x = madd(qf, -0.00024187564849853515625f * 4, x);
+ x = madd(qf, -3.7747668102383613586e-08f * 4, x);
+ x = madd(qf, -1.2816720341285448015e-12f * 4, x);
+ x = M_PI_2_F - (M_PI_2_F - x); /* Crush denormals. */
+ float s = x * x;
+ /* Polynomial from SLEEF's sincosf, max error is
+ * 4.33127e-07 over [-2pi,2pi] (98% of values are "exact"). */
+ float u = -2.71811842367242206819355e-07f;
+ u = madd(u, s, +2.47990446951007470488548e-05f);
+ u = madd(u, s, -0.00138888787478208541870117f);
+ u = madd(u, s, +0.0416666641831398010253906f);
+ u = madd(u, s, -0.5f);
+ u = madd(u, s, +1.0f);
+ if ((q & 1) != 0) {
+ u = -u;
+ }
+ if (fabsf(u) > 1.0f) {
+ u = 0.0f;
+ }
+ return u;
}
-ccl_device void fast_sincosf(float x, float* sine, float* cosine)
+ccl_device void fast_sincosf(float x, float *sine, float *cosine)
{
- /* Same argument reduction as fast_sin. */
- int q = fast_rint(x * M_1_PI_F);
- float qf = q;
- x = madd(qf, -0.78515625f*4, x);
- x = madd(qf, -0.00024187564849853515625f*4, x);
- x = madd(qf, -3.7747668102383613586e-08f*4, x);
- x = madd(qf, -1.2816720341285448015e-12f*4, x);
- x = M_PI_2_F - (M_PI_2_F - x); // crush denormals
- float s = x * x;
- /* NOTE: same exact polynomials as fast_sinf() and fast_cosf() above. */
- if((q & 1) != 0) {
- x = -x;
- }
- float su = 2.6083159809786593541503e-06f;
- su = madd(su, s, -0.0001981069071916863322258f);
- su = madd(su, s, +0.00833307858556509017944336f);
- su = madd(su, s, -0.166666597127914428710938f);
- su = madd(s, su * x, x);
- float cu = -2.71811842367242206819355e-07f;
- cu = madd(cu, s, +2.47990446951007470488548e-05f);
- cu = madd(cu, s, -0.00138888787478208541870117f);
- cu = madd(cu, s, +0.0416666641831398010253906f);
- cu = madd(cu, s, -0.5f);
- cu = madd(cu, s, +1.0f);
- if((q & 1) != 0) {
- cu = -cu;
- }
- if(fabsf(su) > 1.0f) {
- su = 0.0f;
- }
- if(fabsf(cu) > 1.0f) {
- cu = 0.0f;
- }
- *sine = su;
- *cosine = cu;
+ /* Same argument reduction as fast_sin. */
+ int q = fast_rint(x * M_1_PI_F);
+ float qf = q;
+ x = madd(qf, -0.78515625f * 4, x);
+ x = madd(qf, -0.00024187564849853515625f * 4, x);
+ x = madd(qf, -3.7747668102383613586e-08f * 4, x);
+ x = madd(qf, -1.2816720341285448015e-12f * 4, x);
+ x = M_PI_2_F - (M_PI_2_F - x); // crush denormals
+ float s = x * x;
+ /* NOTE: same exact polynomials as fast_sinf() and fast_cosf() above. */
+ if ((q & 1) != 0) {
+ x = -x;
+ }
+ float su = 2.6083159809786593541503e-06f;
+ su = madd(su, s, -0.0001981069071916863322258f);
+ su = madd(su, s, +0.00833307858556509017944336f);
+ su = madd(su, s, -0.166666597127914428710938f);
+ su = madd(s, su * x, x);
+ float cu = -2.71811842367242206819355e-07f;
+ cu = madd(cu, s, +2.47990446951007470488548e-05f);
+ cu = madd(cu, s, -0.00138888787478208541870117f);
+ cu = madd(cu, s, +0.0416666641831398010253906f);
+ cu = madd(cu, s, -0.5f);
+ cu = madd(cu, s, +1.0f);
+ if ((q & 1) != 0) {
+ cu = -cu;
+ }
+ if (fabsf(su) > 1.0f) {
+ su = 0.0f;
+ }
+ if (fabsf(cu) > 1.0f) {
+ cu = 0.0f;
+ }
+ *sine = su;
+ *cosine = cu;
}
/* NOTE: this approximation is only valid on [-8192.0,+8192.0], it starts
@@ -200,33 +201,33 @@ ccl_device void fast_sincosf(float x, float* sine, float* cosine)
*/
ccl_device float fast_tanf(float x)
{
- /* Derived from SLEEF implementation.
- *
- * Note that we cannot apply the "denormal crush" trick everywhere because
- * we sometimes need to take the reciprocal of the polynomial
- */
- int q = fast_rint(x * 2.0f * M_1_PI_F);
- float qf = q;
- x = madd(qf, -0.78515625f*2, x);
- x = madd(qf, -0.00024187564849853515625f*2, x);
- x = madd(qf, -3.7747668102383613586e-08f*2, x);
- x = madd(qf, -1.2816720341285448015e-12f*2, x);
- if((q & 1) == 0) {
- /* Crush denormals (only if we aren't inverting the result later). */
- x = M_PI_4_F - (M_PI_4_F - x);
- }
- float s = x * x;
- float u = 0.00927245803177356719970703f;
- u = madd(u, s, 0.00331984995864331722259521f);
- u = madd(u, s, 0.0242998078465461730957031f);
- u = madd(u, s, 0.0534495301544666290283203f);
- u = madd(u, s, 0.133383005857467651367188f);
- u = madd(u, s, 0.333331853151321411132812f);
- u = madd(s, u * x, x);
- if((q & 1) != 0) {
- u = -1.0f / u;
- }
- return u;
+ /* Derived from SLEEF implementation.
+ *
+ * Note that we cannot apply the "denormal crush" trick everywhere because
+ * we sometimes need to take the reciprocal of the polynomial
+ */
+ int q = fast_rint(x * 2.0f * M_1_PI_F);
+ float qf = q;
+ x = madd(qf, -0.78515625f * 2, x);
+ x = madd(qf, -0.00024187564849853515625f * 2, x);
+ x = madd(qf, -3.7747668102383613586e-08f * 2, x);
+ x = madd(qf, -1.2816720341285448015e-12f * 2, x);
+ if ((q & 1) == 0) {
+ /* Crush denormals (only if we aren't inverting the result later). */
+ x = M_PI_4_F - (M_PI_4_F - x);
+ }
+ float s = x * x;
+ float u = 0.00927245803177356719970703f;
+ u = madd(u, s, 0.00331984995864331722259521f);
+ u = madd(u, s, 0.0242998078465461730957031f);
+ u = madd(u, s, 0.0534495301544666290283203f);
+ u = madd(u, s, 0.133383005857467651367188f);
+ u = madd(u, s, 0.333331853151321411132812f);
+ u = madd(s, u * x, x);
+ if ((q & 1) != 0) {
+ u = -1.0f / u;
+ }
+ return u;
}
/* Fast, approximate sin(x*M_PI) with maximum absolute error of 0.000918954611.
@@ -235,122 +236,119 @@ ccl_device float fast_tanf(float x)
*/
ccl_device float fast_sinpif(float x)
{
- /* Fast trick to strip the integral part off, so our domain is [-1, 1]. */
- const float z = x - ((x + 25165824.0f) - 25165824.0f);
- const float y = z - z * fabsf(z);
- const float Q = 3.10396624f;
- const float P = 3.584135056f; /* P = 16-4*Q */
- return y * (Q + P * fabsf(y));
-
- /* The original article used used inferior constants for Q and P and
- * so had max error 1.091e-3.
- *
- * The optimal value for Q was determined by exhaustive search, minimizing
- * the absolute numerical error relative to float(std::sin(double(phi*M_PI)))
- * over the interval [0,2] (which is where most of the invocations happen).
- *
- * The basic idea of this approximation starts with the coarse approximation:
- * sin(pi*x) ~= f(x) = 4 * (x - x * abs(x))
- *
- * This approximation always _over_ estimates the target. On the other hand,
- * the curve:
- * sin(pi*x) ~= f(x) * abs(f(x)) / 4
- *
- * always lies _under_ the target. Thus we can simply numerically search for
- * the optimal constant to LERP these curves into a more precise
- * approximation.
- *
- * After folding the constants together and simplifying the resulting math,
- * we end up with the compact implementation above.
- *
- * NOTE: this function actually computes sin(x * pi) which avoids one or two
- * mults in many cases and guarantees exact values at integer periods.
- */
+ /* Fast trick to strip the integral part off, so our domain is [-1, 1]. */
+ const float z = x - ((x + 25165824.0f) - 25165824.0f);
+ const float y = z - z * fabsf(z);
+ const float Q = 3.10396624f;
+ const float P = 3.584135056f; /* P = 16-4*Q */
+ return y * (Q + P * fabsf(y));
+
+ /* The original article used used inferior constants for Q and P and
+ * so had max error 1.091e-3.
+ *
+ * The optimal value for Q was determined by exhaustive search, minimizing
+ * the absolute numerical error relative to float(std::sin(double(phi*M_PI)))
+ * over the interval [0,2] (which is where most of the invocations happen).
+ *
+ * The basic idea of this approximation starts with the coarse approximation:
+ * sin(pi*x) ~= f(x) = 4 * (x - x * abs(x))
+ *
+ * This approximation always _over_ estimates the target. On the other hand,
+ * the curve:
+ * sin(pi*x) ~= f(x) * abs(f(x)) / 4
+ *
+ * always lies _under_ the target. Thus we can simply numerically search for
+ * the optimal constant to LERP these curves into a more precise
+ * approximation.
+ *
+ * After folding the constants together and simplifying the resulting math,
+ * we end up with the compact implementation above.
+ *
+ * NOTE: this function actually computes sin(x * pi) which avoids one or two
+ * mults in many cases and guarantees exact values at integer periods.
+ */
}
/* Fast approximate cos(x*M_PI) with ~0.1% absolute error. */
ccl_device_inline float fast_cospif(float x)
{
- return fast_sinpif(x+0.5f);
+ return fast_sinpif(x + 0.5f);
}
ccl_device float fast_acosf(float x)
{
- const float f = fabsf(x);
- /* clamp and crush denormals. */
- const float m = (f < 1.0f) ? 1.0f - (1.0f - f) : 1.0f;
- /* Based on http://www.pouet.net/topic.php?which=9132&page=2
- * 85% accurate (ulp 0)
- * Examined 2130706434 values of acos: 15.2000597 avg ulp diff, 4492 max ulp, 4.51803e-05 max error // without "denormal crush"
- * Examined 2130706434 values of acos: 15.2007108 avg ulp diff, 4492 max ulp, 4.51803e-05 max error // with "denormal crush"
- */
- const float a = sqrtf(1.0f - m) *
- (1.5707963267f + m * (-0.213300989f + m *
- (0.077980478f + m * -0.02164095f)));
- return x < 0 ? M_PI_F - a : a;
+ const float f = fabsf(x);
+ /* clamp and crush denormals. */
+ const float m = (f < 1.0f) ? 1.0f - (1.0f - f) : 1.0f;
+ /* Based on http://www.pouet.net/topic.php?which=9132&page=2
+ * 85% accurate (ulp 0)
+ * Examined 2130706434 values of acos: 15.2000597 avg ulp diff, 4492 max ulp, 4.51803e-05 max error // without "denormal crush"
+ * Examined 2130706434 values of acos: 15.2007108 avg ulp diff, 4492 max ulp, 4.51803e-05 max error // with "denormal crush"
+ */
+ const float a = sqrtf(1.0f - m) *
+ (1.5707963267f + m * (-0.213300989f + m * (0.077980478f + m * -0.02164095f)));
+ return x < 0 ? M_PI_F - a : a;
}
ccl_device float fast_asinf(float x)
{
- /* Based on acosf approximation above.
- * Max error is 4.51133e-05 (ulps are higher because we are consistently off
- * by a little amount).
- */
- const float f = fabsf(x);
- /* Clamp and crush denormals. */
- const float m = (f < 1.0f) ? 1.0f - (1.0f - f) : 1.0f;
- const float a = M_PI_2_F - sqrtf(1.0f - m) *
- (1.5707963267f + m * (-0.213300989f + m *
- (0.077980478f + m * -0.02164095f)));
- return copysignf(a, x);
+ /* Based on acosf approximation above.
+ * Max error is 4.51133e-05 (ulps are higher because we are consistently off
+ * by a little amount).
+ */
+ const float f = fabsf(x);
+ /* Clamp and crush denormals. */
+ const float m = (f < 1.0f) ? 1.0f - (1.0f - f) : 1.0f;
+ const float a = M_PI_2_F -
+ sqrtf(1.0f - m) * (1.5707963267f +
+ m * (-0.213300989f + m * (0.077980478f + m * -0.02164095f)));
+ return copysignf(a, x);
}
ccl_device float fast_atanf(float x)
{
- const float a = fabsf(x);
- const float k = a > 1.0f ? 1 / a : a;
- const float s = 1.0f - (1.0f - k); /* Crush denormals. */
- const float t = s * s;
- /* http://mathforum.org/library/drmath/view/62672.html
- * Examined 4278190080 values of atan: 2.36864877 avg ulp diff, 302 max ulp, 6.55651e-06 max error // (with denormals)
- * Examined 4278190080 values of atan: 171160502 avg ulp diff, 855638016 max ulp, 6.55651e-06 max error // (crush denormals)
- */
- float r = s * madd(0.43157974f, t, 1.0f) /
- madd(madd(0.05831938f, t, 0.76443945f), t, 1.0f);
- if(a > 1.0f) {
- r = M_PI_2_F - r;
- }
- return copysignf(r, x);
+ const float a = fabsf(x);
+ const float k = a > 1.0f ? 1 / a : a;
+ const float s = 1.0f - (1.0f - k); /* Crush denormals. */
+ const float t = s * s;
+ /* http://mathforum.org/library/drmath/view/62672.html
+ * Examined 4278190080 values of atan: 2.36864877 avg ulp diff, 302 max ulp, 6.55651e-06 max error // (with denormals)
+ * Examined 4278190080 values of atan: 171160502 avg ulp diff, 855638016 max ulp, 6.55651e-06 max error // (crush denormals)
+ */
+ float r = s * madd(0.43157974f, t, 1.0f) / madd(madd(0.05831938f, t, 0.76443945f), t, 1.0f);
+ if (a > 1.0f) {
+ r = M_PI_2_F - r;
+ }
+ return copysignf(r, x);
}
ccl_device float fast_atan2f(float y, float x)
{
- /* Based on atan approximation above.
- *
- * The special cases around 0 and infinity were tested explicitly.
- *
- * The only case not handled correctly is x=NaN,y=0 which returns 0 instead
- * of nan.
- */
- const float a = fabsf(x);
- const float b = fabsf(y);
-
- const float k = (b == 0) ? 0.0f : ((a == b) ? 1.0f : (b > a ? a / b : b / a));
- const float s = 1.0f - (1.0f - k); /* Crush denormals */
- const float t = s * s;
-
- float r = s * madd(0.43157974f, t, 1.0f) /
- madd(madd(0.05831938f, t, 0.76443945f), t, 1.0f);
-
- if(b > a) {
- /* Account for arg reduction. */
- r = M_PI_2_F - r;
- }
- /* Test sign bit of x. */
- if(__float_as_uint(x) & 0x80000000u) {
- r = M_PI_F - r;
- }
- return copysignf(r, y);
+ /* Based on atan approximation above.
+ *
+ * The special cases around 0 and infinity were tested explicitly.
+ *
+ * The only case not handled correctly is x=NaN,y=0 which returns 0 instead
+ * of nan.
+ */
+ const float a = fabsf(x);
+ const float b = fabsf(y);
+
+ const float k = (b == 0) ? 0.0f : ((a == b) ? 1.0f : (b > a ? a / b : b / a));
+ const float s = 1.0f - (1.0f - k); /* Crush denormals */
+ const float t = s * s;
+
+ float r = s * madd(0.43157974f, t, 1.0f) / madd(madd(0.05831938f, t, 0.76443945f), t, 1.0f);
+
+ if (b > a) {
+ /* Account for arg reduction. */
+ r = M_PI_2_F - r;
+ }
+ /* Test sign bit of x. */
+ if (__float_as_uint(x) & 0x80000000u) {
+ r = M_PI_F - r;
+ }
+ return copysignf(r, y);
}
/* Based on:
@@ -359,204 +357,207 @@ ccl_device float fast_atan2f(float y, float x)
*/
ccl_device float fast_log2f(float x)
{
- /* NOTE: clamp to avoid special cases and make result "safe" from large
- * negative values/nans. */
- x = clamp(x, FLT_MIN, FLT_MAX);
- unsigned bits = __float_as_uint(x);
- int exponent = (int)(bits >> 23) - 127;
- float f = __uint_as_float((bits & 0x007FFFFF) | 0x3f800000) - 1.0f;
- /* Examined 2130706432 values of log2 on [1.17549435e-38,3.40282347e+38]:
- * 0.0797524457 avg ulp diff, 3713596 max ulp, 7.62939e-06 max error.
- * ulp histogram:
- * 0 = 97.46%
- * 1 = 2.29%
- * 2 = 0.11%
- */
- float f2 = f * f;
- float f4 = f2 * f2;
- float hi = madd(f, -0.00931049621349f, 0.05206469089414f);
- float lo = madd(f, 0.47868480909345f, -0.72116591947498f);
- hi = madd(f, hi, -0.13753123777116f);
- hi = madd(f, hi, 0.24187369696082f);
- hi = madd(f, hi, -0.34730547155299f);
- lo = madd(f, lo, 1.442689881667200f);
- return ((f4 * hi) + (f * lo)) + exponent;
+ /* NOTE: clamp to avoid special cases and make result "safe" from large
+ * negative values/nans. */
+ x = clamp(x, FLT_MIN, FLT_MAX);
+ unsigned bits = __float_as_uint(x);
+ int exponent = (int)(bits >> 23) - 127;
+ float f = __uint_as_float((bits & 0x007FFFFF) | 0x3f800000) - 1.0f;
+ /* Examined 2130706432 values of log2 on [1.17549435e-38,3.40282347e+38]:
+ * 0.0797524457 avg ulp diff, 3713596 max ulp, 7.62939e-06 max error.
+ * ulp histogram:
+ * 0 = 97.46%
+ * 1 = 2.29%
+ * 2 = 0.11%
+ */
+ float f2 = f * f;
+ float f4 = f2 * f2;
+ float hi = madd(f, -0.00931049621349f, 0.05206469089414f);
+ float lo = madd(f, 0.47868480909345f, -0.72116591947498f);
+ hi = madd(f, hi, -0.13753123777116f);
+ hi = madd(f, hi, 0.24187369696082f);
+ hi = madd(f, hi, -0.34730547155299f);
+ lo = madd(f, lo, 1.442689881667200f);
+ return ((f4 * hi) + (f * lo)) + exponent;
}
ccl_device_inline float fast_logf(float x)
{
- /* Examined 2130706432 values of logf on [1.17549435e-38,3.40282347e+38]:
- * 0.313865375 avg ulp diff, 5148137 max ulp, 7.62939e-06 max error.
- */
- return fast_log2f(x) * M_LN2_F;
+ /* Examined 2130706432 values of logf on [1.17549435e-38,3.40282347e+38]:
+ * 0.313865375 avg ulp diff, 5148137 max ulp, 7.62939e-06 max error.
+ */
+ return fast_log2f(x) * M_LN2_F;
}
ccl_device_inline float fast_log10(float x)
{
- /* Examined 2130706432 values of log10f on [1.17549435e-38,3.40282347e+38]:
- * 0.631237033 avg ulp diff, 4471615 max ulp, 3.8147e-06 max error.
- */
- return fast_log2f(x) * M_LN2_F / M_LN10_F;
+ /* Examined 2130706432 values of log10f on [1.17549435e-38,3.40282347e+38]:
+ * 0.631237033 avg ulp diff, 4471615 max ulp, 3.8147e-06 max error.
+ */
+ return fast_log2f(x) * M_LN2_F / M_LN10_F;
}
ccl_device float fast_logb(float x)
{
- /* Don't bother with denormals. */
- x = fabsf(x);
- x = clamp(x, FLT_MIN, FLT_MAX);
- unsigned bits = __float_as_uint(x);
- return (int)(bits >> 23) - 127;
+ /* Don't bother with denormals. */
+ x = fabsf(x);
+ x = clamp(x, FLT_MIN, FLT_MAX);
+ unsigned bits = __float_as_uint(x);
+ return (int)(bits >> 23) - 127;
}
ccl_device float fast_exp2f(float x)
{
- /* Clamp to safe range for final addition. */
- x = clamp(x, -126.0f, 126.0f);
- /* Range reduction. */
- int m = (int)x; x -= m;
- x = 1.0f - (1.0f - x); /* Crush denormals (does not affect max ulps!). */
- /* 5th degree polynomial generated with sollya
- * Examined 2247622658 values of exp2 on [-126,126]: 2.75764912 avg ulp diff,
- * 232 max ulp.
- *
- * ulp histogram:
- * 0 = 87.81%
- * 1 = 4.18%
- */
- float r = 1.33336498402e-3f;
- r = madd(x, r, 9.810352697968e-3f);
- r = madd(x, r, 5.551834031939e-2f);
- r = madd(x, r, 0.2401793301105f);
- r = madd(x, r, 0.693144857883f);
- r = madd(x, r, 1.0f);
- /* Multiply by 2 ^ m by adding in the exponent. */
- /* NOTE: left-shift of negative number is undefined behavior. */
- return __uint_as_float(__float_as_uint(r) + ((unsigned)m << 23));
+ /* Clamp to safe range for final addition. */
+ x = clamp(x, -126.0f, 126.0f);
+ /* Range reduction. */
+ int m = (int)x;
+ x -= m;
+ x = 1.0f - (1.0f - x); /* Crush denormals (does not affect max ulps!). */
+ /* 5th degree polynomial generated with sollya
+ * Examined 2247622658 values of exp2 on [-126,126]: 2.75764912 avg ulp diff,
+ * 232 max ulp.
+ *
+ * ulp histogram:
+ * 0 = 87.81%
+ * 1 = 4.18%
+ */
+ float r = 1.33336498402e-3f;
+ r = madd(x, r, 9.810352697968e-3f);
+ r = madd(x, r, 5.551834031939e-2f);
+ r = madd(x, r, 0.2401793301105f);
+ r = madd(x, r, 0.693144857883f);
+ r = madd(x, r, 1.0f);
+ /* Multiply by 2 ^ m by adding in the exponent. */
+ /* NOTE: left-shift of negative number is undefined behavior. */
+ return __uint_as_float(__float_as_uint(r) + ((unsigned)m << 23));
}
ccl_device_inline float fast_expf(float x)
{
- /* Examined 2237485550 values of exp on [-87.3300018,87.3300018]:
- * 2.6666452 avg ulp diff, 230 max ulp.
- */
- return fast_exp2f(x / M_LN2_F);
+ /* Examined 2237485550 values of exp on [-87.3300018,87.3300018]:
+ * 2.6666452 avg ulp diff, 230 max ulp.
+ */
+ return fast_exp2f(x / M_LN2_F);
}
#ifndef __KERNEL_GPU__
ccl_device float4 fast_exp2f4(float4 x)
{
- const float4 one = make_float4(1.0f);
- const float4 limit = make_float4(126.0f);
- x = clamp(x, -limit, limit);
- int4 m = make_int4(x);
- x = one - (one - (x - make_float4(m)));
- float4 r = make_float4(1.33336498402e-3f);
- r = madd4(x, r, make_float4(9.810352697968e-3f));
- r = madd4(x, r, make_float4(5.551834031939e-2f));
- r = madd4(x, r, make_float4(0.2401793301105f));
- r = madd4(x, r, make_float4(0.693144857883f));
- r = madd4(x, r, make_float4(1.0f));
- return __int4_as_float4(__float4_as_int4(r) + (m << 23));
+ const float4 one = make_float4(1.0f);
+ const float4 limit = make_float4(126.0f);
+ x = clamp(x, -limit, limit);
+ int4 m = make_int4(x);
+ x = one - (one - (x - make_float4(m)));
+ float4 r = make_float4(1.33336498402e-3f);
+ r = madd4(x, r, make_float4(9.810352697968e-3f));
+ r = madd4(x, r, make_float4(5.551834031939e-2f));
+ r = madd4(x, r, make_float4(0.2401793301105f));
+ r = madd4(x, r, make_float4(0.693144857883f));
+ r = madd4(x, r, make_float4(1.0f));
+ return __int4_as_float4(__float4_as_int4(r) + (m << 23));
}
ccl_device_inline float4 fast_expf4(float4 x)
{
- return fast_exp2f4(x / M_LN2_F);
+ return fast_exp2f4(x / M_LN2_F);
}
#endif
ccl_device_inline float fast_exp10(float x)
{
- /* Examined 2217701018 values of exp10 on [-37.9290009,37.9290009]:
- * 2.71732409 avg ulp diff, 232 max ulp.
- */
- return fast_exp2f(x * M_LN10_F / M_LN2_F);
+ /* Examined 2217701018 values of exp10 on [-37.9290009,37.9290009]:
+ * 2.71732409 avg ulp diff, 232 max ulp.
+ */
+ return fast_exp2f(x * M_LN10_F / M_LN2_F);
}
ccl_device_inline float fast_expm1f(float x)
{
- if(fabsf(x) < 1e-5f) {
- x = 1.0f - (1.0f - x); /* Crush denormals. */
- return madd(0.5f, x * x, x);
- }
- else {
- return fast_expf(x) - 1.0f;
- }
+ if (fabsf(x) < 1e-5f) {
+ x = 1.0f - (1.0f - x); /* Crush denormals. */
+ return madd(0.5f, x * x, x);
+ }
+ else {
+ return fast_expf(x) - 1.0f;
+ }
}
ccl_device float fast_sinhf(float x)
{
- float a = fabsf(x);
- if(a > 1.0f) {
- /* Examined 53389559 values of sinh on [1,87.3300018]:
- * 33.6886442 avg ulp diff, 178 max ulp. */
- float e = fast_expf(a);
- return copysignf(0.5f * e - 0.5f / e, x);
- }
- else {
- a = 1.0f - (1.0f - a); /* Crush denorms. */
- float a2 = a * a;
- /* Degree 7 polynomial generated with sollya. */
- /* Examined 2130706434 values of sinh on [-1,1]: 1.19209e-07 max error. */
- float r = 2.03945513931e-4f;
- r = madd(r, a2, 8.32990277558e-3f);
- r = madd(r, a2, 0.1666673421859f);
- r = madd(r * a, a2, a);
- return copysignf(r, x);
- }
+ float a = fabsf(x);
+ if (a > 1.0f) {
+ /* Examined 53389559 values of sinh on [1,87.3300018]:
+ * 33.6886442 avg ulp diff, 178 max ulp. */
+ float e = fast_expf(a);
+ return copysignf(0.5f * e - 0.5f / e, x);
+ }
+ else {
+ a = 1.0f - (1.0f - a); /* Crush denorms. */
+ float a2 = a * a;
+ /* Degree 7 polynomial generated with sollya. */
+ /* Examined 2130706434 values of sinh on [-1,1]: 1.19209e-07 max error. */
+ float r = 2.03945513931e-4f;
+ r = madd(r, a2, 8.32990277558e-3f);
+ r = madd(r, a2, 0.1666673421859f);
+ r = madd(r * a, a2, a);
+ return copysignf(r, x);
+ }
}
ccl_device_inline float fast_coshf(float x)
{
- /* Examined 2237485550 values of cosh on [-87.3300018,87.3300018]:
- * 1.78256726 avg ulp diff, 178 max ulp.
- */
- float e = fast_expf(fabsf(x));
- return 0.5f * e + 0.5f / e;
+ /* Examined 2237485550 values of cosh on [-87.3300018,87.3300018]:
+ * 1.78256726 avg ulp diff, 178 max ulp.
+ */
+ float e = fast_expf(fabsf(x));
+ return 0.5f * e + 0.5f / e;
}
ccl_device_inline float fast_tanhf(float x)
{
- /* Examined 4278190080 values of tanh on [-3.40282347e+38,3.40282347e+38]:
- * 3.12924e-06 max error.
- */
- /* NOTE: ulp error is high because of sub-optimal handling around the origin. */
- float e = fast_expf(2.0f * fabsf(x));
- return copysignf(1.0f - 2.0f / (1.0f + e), x);
+ /* Examined 4278190080 values of tanh on [-3.40282347e+38,3.40282347e+38]:
+ * 3.12924e-06 max error.
+ */
+ /* NOTE: ulp error is high because of sub-optimal handling around the origin. */
+ float e = fast_expf(2.0f * fabsf(x));
+ return copysignf(1.0f - 2.0f / (1.0f + e), x);
}
ccl_device float fast_safe_powf(float x, float y)
{
- if(y == 0) return 1.0f; /* x^1=1 */
- if(x == 0) return 0.0f; /* 0^y=0 */
- float sign = 1.0f;
- if(x < 0.0f) {
- /* if x is negative, only deal with integer powers
- * powf returns NaN for non-integers, we will return 0 instead.
- */
- int ybits = __float_as_int(y) & 0x7fffffff;
- if(ybits >= 0x4b800000) {
- // always even int, keep positive
- }
- else if(ybits >= 0x3f800000) {
- /* Bigger than 1, check. */
- int k = (ybits >> 23) - 127; /* Get exponent. */
- int j = ybits >> (23 - k); /* Shift out possible fractional bits. */
- if((j << (23 - k)) == ybits) { /* rebuild number and check for a match. */
- /* +1 for even, -1 for odd. */
- sign = __int_as_float(0x3f800000 | (j << 31));
- }
- else {
- /* Not an integer. */
- return 0.0f;
- }
- }
- else {
- /* Not an integer. */
- return 0.0f;
- }
- }
- return sign * fast_exp2f(y * fast_log2f(fabsf(x)));
+ if (y == 0)
+ return 1.0f; /* x^1=1 */
+ if (x == 0)
+ return 0.0f; /* 0^y=0 */
+ float sign = 1.0f;
+ if (x < 0.0f) {
+ /* if x is negative, only deal with integer powers
+ * powf returns NaN for non-integers, we will return 0 instead.
+ */
+ int ybits = __float_as_int(y) & 0x7fffffff;
+ if (ybits >= 0x4b800000) {
+ // always even int, keep positive
+ }
+ else if (ybits >= 0x3f800000) {
+ /* Bigger than 1, check. */
+ int k = (ybits >> 23) - 127; /* Get exponent. */
+ int j = ybits >> (23 - k); /* Shift out possible fractional bits. */
+ if ((j << (23 - k)) == ybits) { /* rebuild number and check for a match. */
+ /* +1 for even, -1 for odd. */
+ sign = __int_as_float(0x3f800000 | (j << 31));
+ }
+ else {
+ /* Not an integer. */
+ return 0.0f;
+ }
+ }
+ else {
+ /* Not an integer. */
+ return 0.0f;
+ }
+ }
+ return sign * fast_exp2f(y * fast_log2f(fabsf(x)));
}
/* TODO(sergey): Check speed with our erf functions implementation from
@@ -565,74 +566,75 @@ ccl_device float fast_safe_powf(float x, float y)
ccl_device_inline float fast_erff(float x)
{
- /* Examined 1082130433 values of erff on [0,4]: 1.93715e-06 max error. */
- /* Abramowitz and Stegun, 7.1.28. */
- const float a1 = 0.0705230784f;
- const float a2 = 0.0422820123f;
- const float a3 = 0.0092705272f;
- const float a4 = 0.0001520143f;
- const float a5 = 0.0002765672f;
- const float a6 = 0.0000430638f;
- const float a = fabsf(x);
- if(a >= 12.3f) {
- return copysignf(1.0f, x);
- }
- const float b = 1.0f - (1.0f - a); /* Crush denormals. */
- const float r = madd(madd(madd(madd(madd(madd(a6, b, a5), b, a4), b, a3), b, a2), b, a1), b, 1.0f);
- const float s = r * r; /* ^2 */
- const float t = s * s; /* ^4 */
- const float u = t * t; /* ^8 */
- const float v = u * u; /* ^16 */
- return copysignf(1.0f - 1.0f / v, x);
+ /* Examined 1082130433 values of erff on [0,4]: 1.93715e-06 max error. */
+ /* Abramowitz and Stegun, 7.1.28. */
+ const float a1 = 0.0705230784f;
+ const float a2 = 0.0422820123f;
+ const float a3 = 0.0092705272f;
+ const float a4 = 0.0001520143f;
+ const float a5 = 0.0002765672f;
+ const float a6 = 0.0000430638f;
+ const float a = fabsf(x);
+ if (a >= 12.3f) {
+ return copysignf(1.0f, x);
+ }
+ const float b = 1.0f - (1.0f - a); /* Crush denormals. */
+ const float r = madd(
+ madd(madd(madd(madd(madd(a6, b, a5), b, a4), b, a3), b, a2), b, a1), b, 1.0f);
+ const float s = r * r; /* ^2 */
+ const float t = s * s; /* ^4 */
+ const float u = t * t; /* ^8 */
+ const float v = u * u; /* ^16 */
+ return copysignf(1.0f - 1.0f / v, x);
}
ccl_device_inline float fast_erfcf(float x)
{
- /* Examined 2164260866 values of erfcf on [-4,4]: 1.90735e-06 max error.
- *
- * ulp histogram:
- *
- * 0 = 80.30%
- */
- return 1.0f - fast_erff(x);
+ /* Examined 2164260866 values of erfcf on [-4,4]: 1.90735e-06 max error.
+ *
+ * ulp histogram:
+ *
+ * 0 = 80.30%
+ */
+ return 1.0f - fast_erff(x);
}
ccl_device_inline float fast_ierff(float x)
{
- /* From: Approximating the erfinv function by Mike Giles. */
- /* To avoid trouble at the limit, clamp input to 1-eps. */
- float a = fabsf(x);
- if(a > 0.99999994f) {
- a = 0.99999994f;
- }
- float w = -fast_logf((1.0f - a) * (1.0f + a)), p;
- if(w < 5.0f) {
- w = w - 2.5f;
- p = 2.81022636e-08f;
- p = madd(p, w, 3.43273939e-07f);
- p = madd(p, w, -3.5233877e-06f);
- p = madd(p, w, -4.39150654e-06f);
- p = madd(p, w, 0.00021858087f);
- p = madd(p, w, -0.00125372503f);
- p = madd(p, w, -0.00417768164f);
- p = madd(p, w, 0.246640727f);
- p = madd(p, w, 1.50140941f);
- }
- else {
- w = sqrtf(w) - 3.0f;
- p = -0.000200214257f;
- p = madd(p, w, 0.000100950558f);
- p = madd(p, w, 0.00134934322f);
- p = madd(p, w, -0.00367342844f);
- p = madd(p, w, 0.00573950773f);
- p = madd(p, w, -0.0076224613f);
- p = madd(p, w, 0.00943887047f);
- p = madd(p, w, 1.00167406f);
- p = madd(p, w, 2.83297682f);
- }
- return p * x;
+ /* From: Approximating the erfinv function by Mike Giles. */
+ /* To avoid trouble at the limit, clamp input to 1-eps. */
+ float a = fabsf(x);
+ if (a > 0.99999994f) {
+ a = 0.99999994f;
+ }
+ float w = -fast_logf((1.0f - a) * (1.0f + a)), p;
+ if (w < 5.0f) {
+ w = w - 2.5f;
+ p = 2.81022636e-08f;
+ p = madd(p, w, 3.43273939e-07f);
+ p = madd(p, w, -3.5233877e-06f);
+ p = madd(p, w, -4.39150654e-06f);
+ p = madd(p, w, 0.00021858087f);
+ p = madd(p, w, -0.00125372503f);
+ p = madd(p, w, -0.00417768164f);
+ p = madd(p, w, 0.246640727f);
+ p = madd(p, w, 1.50140941f);
+ }
+ else {
+ w = sqrtf(w) - 3.0f;
+ p = -0.000200214257f;
+ p = madd(p, w, 0.000100950558f);
+ p = madd(p, w, 0.00134934322f);
+ p = madd(p, w, -0.00367342844f);
+ p = madd(p, w, 0.00573950773f);
+ p = madd(p, w, -0.0076224613f);
+ p = madd(p, w, 0.00943887047f);
+ p = madd(p, w, 1.00167406f);
+ p = madd(p, w, 2.83297682f);
+ }
+ return p * x;
}
CCL_NAMESPACE_END
-#endif /* __UTIL_FAST_MATH__ */
+#endif /* __UTIL_FAST_MATH__ */
diff --git a/intern/cycles/util/util_math_float2.h b/intern/cycles/util/util_math_float2.h
index 6fe8e3b4115..9feaf042d19 100644
--- a/intern/cycles/util/util_math_float2.h
+++ b/intern/cycles/util/util_math_float2.h
@@ -28,206 +28,206 @@ CCL_NAMESPACE_BEGIN
*/
#ifndef __KERNEL_OPENCL__
-ccl_device_inline float2 operator-(const float2& a);
-ccl_device_inline float2 operator*(const float2& a, const float2& b);
-ccl_device_inline float2 operator*(const float2& a, float f);
-ccl_device_inline float2 operator*(float f, const float2& a);
-ccl_device_inline float2 operator/(float f, const float2& a);
-ccl_device_inline float2 operator/(const float2& a, float f);
-ccl_device_inline float2 operator/(const float2& a, const float2& b);
-ccl_device_inline float2 operator+(const float2& a, const float2& b);
-ccl_device_inline float2 operator-(const float2& a, const float2& b);
-ccl_device_inline float2 operator+=(float2& a, const float2& b);
-ccl_device_inline float2 operator*=(float2& a, const float2& b);
-ccl_device_inline float2 operator*=(float2& a, float f);
-ccl_device_inline float2 operator/=(float2& a, const float2& b);
-ccl_device_inline float2 operator/=(float2& a, float f);
-
-ccl_device_inline bool operator==(const float2& a, const float2& b);
-ccl_device_inline bool operator!=(const float2& a, const float2& b);
-
-ccl_device_inline bool is_zero(const float2& a);
-ccl_device_inline float average(const float2& a);
-ccl_device_inline float dot(const float2& a, const float2& b);
-ccl_device_inline float cross(const float2& a, const float2& b);
-ccl_device_inline float len(const float2& a);
-ccl_device_inline float2 normalize(const float2& a);
-ccl_device_inline float2 normalize_len(const float2& a, float *t);
-ccl_device_inline float2 safe_normalize(const float2& a);
-ccl_device_inline float2 min(const float2& a, const float2& b);
-ccl_device_inline float2 max(const float2& a, const float2& b);
-ccl_device_inline float2 clamp(const float2& a, const float2& mn, const float2& mx);
-ccl_device_inline float2 fabs(const float2& a);
-ccl_device_inline float2 as_float2(const float4& a);
-ccl_device_inline float2 interp(const float2& a, const float2& b, float t);
-#endif /* !__KERNEL_OPENCL__ */
+ccl_device_inline float2 operator-(const float2 &a);
+ccl_device_inline float2 operator*(const float2 &a, const float2 &b);
+ccl_device_inline float2 operator*(const float2 &a, float f);
+ccl_device_inline float2 operator*(float f, const float2 &a);
+ccl_device_inline float2 operator/(float f, const float2 &a);
+ccl_device_inline float2 operator/(const float2 &a, float f);
+ccl_device_inline float2 operator/(const float2 &a, const float2 &b);
+ccl_device_inline float2 operator+(const float2 &a, const float2 &b);
+ccl_device_inline float2 operator-(const float2 &a, const float2 &b);
+ccl_device_inline float2 operator+=(float2 &a, const float2 &b);
+ccl_device_inline float2 operator*=(float2 &a, const float2 &b);
+ccl_device_inline float2 operator*=(float2 &a, float f);
+ccl_device_inline float2 operator/=(float2 &a, const float2 &b);
+ccl_device_inline float2 operator/=(float2 &a, float f);
+
+ccl_device_inline bool operator==(const float2 &a, const float2 &b);
+ccl_device_inline bool operator!=(const float2 &a, const float2 &b);
+
+ccl_device_inline bool is_zero(const float2 &a);
+ccl_device_inline float average(const float2 &a);
+ccl_device_inline float dot(const float2 &a, const float2 &b);
+ccl_device_inline float cross(const float2 &a, const float2 &b);
+ccl_device_inline float len(const float2 &a);
+ccl_device_inline float2 normalize(const float2 &a);
+ccl_device_inline float2 normalize_len(const float2 &a, float *t);
+ccl_device_inline float2 safe_normalize(const float2 &a);
+ccl_device_inline float2 min(const float2 &a, const float2 &b);
+ccl_device_inline float2 max(const float2 &a, const float2 &b);
+ccl_device_inline float2 clamp(const float2 &a, const float2 &mn, const float2 &mx);
+ccl_device_inline float2 fabs(const float2 &a);
+ccl_device_inline float2 as_float2(const float4 &a);
+ccl_device_inline float2 interp(const float2 &a, const float2 &b, float t);
+#endif /* !__KERNEL_OPENCL__ */
/*******************************************************************************
* Definition.
*/
#ifndef __KERNEL_OPENCL__
-ccl_device_inline float2 operator-(const float2& a)
+ccl_device_inline float2 operator-(const float2 &a)
{
- return make_float2(-a.x, -a.y);
+ return make_float2(-a.x, -a.y);
}
-ccl_device_inline float2 operator*(const float2& a, const float2& b)
+ccl_device_inline float2 operator*(const float2 &a, const float2 &b)
{
- return make_float2(a.x*b.x, a.y*b.y);
+ return make_float2(a.x * b.x, a.y * b.y);
}
-ccl_device_inline float2 operator*(const float2& a, float f)
+ccl_device_inline float2 operator*(const float2 &a, float f)
{
- return make_float2(a.x*f, a.y*f);
+ return make_float2(a.x * f, a.y * f);
}
-ccl_device_inline float2 operator*(float f, const float2& a)
+ccl_device_inline float2 operator*(float f, const float2 &a)
{
- return make_float2(a.x*f, a.y*f);
+ return make_float2(a.x * f, a.y * f);
}
-ccl_device_inline float2 operator/(float f, const float2& a)
+ccl_device_inline float2 operator/(float f, const float2 &a)
{
- return make_float2(f/a.x, f/a.y);
+ return make_float2(f / a.x, f / a.y);
}
-ccl_device_inline float2 operator/(const float2& a, float f)
+ccl_device_inline float2 operator/(const float2 &a, float f)
{
- float invf = 1.0f/f;
- return make_float2(a.x*invf, a.y*invf);
+ float invf = 1.0f / f;
+ return make_float2(a.x * invf, a.y * invf);
}
-ccl_device_inline float2 operator/(const float2& a, const float2& b)
+ccl_device_inline float2 operator/(const float2 &a, const float2 &b)
{
- return make_float2(a.x/b.x, a.y/b.y);
+ return make_float2(a.x / b.x, a.y / b.y);
}
-ccl_device_inline float2 operator+(const float2& a, const float2& b)
+ccl_device_inline float2 operator+(const float2 &a, const float2 &b)
{
- return make_float2(a.x+b.x, a.y+b.y);
+ return make_float2(a.x + b.x, a.y + b.y);
}
-ccl_device_inline float2 operator-(const float2& a, const float2& b)
+ccl_device_inline float2 operator-(const float2 &a, const float2 &b)
{
- return make_float2(a.x-b.x, a.y-b.y);
+ return make_float2(a.x - b.x, a.y - b.y);
}
-ccl_device_inline float2 operator+=(float2& a, const float2& b)
+ccl_device_inline float2 operator+=(float2 &a, const float2 &b)
{
- return a = a + b;
+ return a = a + b;
}
-ccl_device_inline float2 operator*=(float2& a, const float2& b)
+ccl_device_inline float2 operator*=(float2 &a, const float2 &b)
{
- return a = a * b;
+ return a = a * b;
}
-ccl_device_inline float2 operator*=(float2& a, float f)
+ccl_device_inline float2 operator*=(float2 &a, float f)
{
- return a = a * f;
+ return a = a * f;
}
-ccl_device_inline float2 operator/=(float2& a, const float2& b)
+ccl_device_inline float2 operator/=(float2 &a, const float2 &b)
{
- return a = a / b;
+ return a = a / b;
}
-ccl_device_inline float2 operator/=(float2& a, float f)
+ccl_device_inline float2 operator/=(float2 &a, float f)
{
- float invf = 1.0f/f;
- return a = a * invf;
+ float invf = 1.0f / f;
+ return a = a * invf;
}
-ccl_device_inline bool operator==(const float2& a, const float2& b)
+ccl_device_inline bool operator==(const float2 &a, const float2 &b)
{
- return (a.x == b.x && a.y == b.y);
+ return (a.x == b.x && a.y == b.y);
}
-ccl_device_inline bool operator!=(const float2& a, const float2& b)
+ccl_device_inline bool operator!=(const float2 &a, const float2 &b)
{
- return !(a == b);
+ return !(a == b);
}
-ccl_device_inline bool is_zero(const float2& a)
+ccl_device_inline bool is_zero(const float2 &a)
{
- return (a.x == 0.0f && a.y == 0.0f);
+ return (a.x == 0.0f && a.y == 0.0f);
}
-ccl_device_inline float average(const float2& a)
+ccl_device_inline float average(const float2 &a)
{
- return (a.x + a.y)*(1.0f/2.0f);
+ return (a.x + a.y) * (1.0f / 2.0f);
}
-ccl_device_inline float dot(const float2& a, const float2& b)
+ccl_device_inline float dot(const float2 &a, const float2 &b)
{
- return a.x*b.x + a.y*b.y;
+ return a.x * b.x + a.y * b.y;
}
-ccl_device_inline float cross(const float2& a, const float2& b)
+ccl_device_inline float cross(const float2 &a, const float2 &b)
{
- return (a.x*b.y - a.y*b.x);
+ return (a.x * b.y - a.y * b.x);
}
-ccl_device_inline float len(const float2& a)
+ccl_device_inline float len(const float2 &a)
{
- return sqrtf(dot(a, a));
+ return sqrtf(dot(a, a));
}
-ccl_device_inline float2 normalize(const float2& a)
+ccl_device_inline float2 normalize(const float2 &a)
{
- return a/len(a);
+ return a / len(a);
}
-ccl_device_inline float2 normalize_len(const float2& a, float *t)
+ccl_device_inline float2 normalize_len(const float2 &a, float *t)
{
- *t = len(a);
- return a/(*t);
+ *t = len(a);
+ return a / (*t);
}
-ccl_device_inline float2 safe_normalize(const float2& a)
+ccl_device_inline float2 safe_normalize(const float2 &a)
{
- float t = len(a);
- return (t != 0.0f)? a/t: a;
+ float t = len(a);
+ return (t != 0.0f) ? a / t : a;
}
-ccl_device_inline float2 min(const float2& a, const float2& b)
+ccl_device_inline float2 min(const float2 &a, const float2 &b)
{
- return make_float2(min(a.x, b.x), min(a.y, b.y));
+ return make_float2(min(a.x, b.x), min(a.y, b.y));
}
-ccl_device_inline float2 max(const float2& a, const float2& b)
+ccl_device_inline float2 max(const float2 &a, const float2 &b)
{
- return make_float2(max(a.x, b.x), max(a.y, b.y));
+ return make_float2(max(a.x, b.x), max(a.y, b.y));
}
-ccl_device_inline float2 clamp(const float2& a, const float2& mn, const float2& mx)
+ccl_device_inline float2 clamp(const float2 &a, const float2 &mn, const float2 &mx)
{
- return min(max(a, mn), mx);
+ return min(max(a, mn), mx);
}
-ccl_device_inline float2 fabs(const float2& a)
+ccl_device_inline float2 fabs(const float2 &a)
{
- return make_float2(fabsf(a.x), fabsf(a.y));
+ return make_float2(fabsf(a.x), fabsf(a.y));
}
-ccl_device_inline float2 as_float2(const float4& a)
+ccl_device_inline float2 as_float2(const float4 &a)
{
- return make_float2(a.x, a.y);
+ return make_float2(a.x, a.y);
}
-ccl_device_inline float2 interp(const float2& a, const float2& b, float t)
+ccl_device_inline float2 interp(const float2 &a, const float2 &b, float t)
{
- return a + t*(b - a);
+ return a + t * (b - a);
}
-ccl_device_inline float2 mix(const float2& a, const float2& b, float t)
+ccl_device_inline float2 mix(const float2 &a, const float2 &b, float t)
{
- return a + t*(b - a);
+ return a + t * (b - a);
}
-#endif /* !__KERNEL_OPENCL__ */
+#endif /* !__KERNEL_OPENCL__ */
CCL_NAMESPACE_END
-#endif /* __UTIL_MATH_FLOAT2_H__ */
+#endif /* __UTIL_MATH_FLOAT2_H__ */
diff --git a/intern/cycles/util/util_math_float3.h b/intern/cycles/util/util_math_float3.h
index a54a3f3087c..85e9b8114ff 100644
--- a/intern/cycles/util/util_math_float3.h
+++ b/intern/cycles/util/util_math_float3.h
@@ -28,37 +28,37 @@ CCL_NAMESPACE_BEGIN
*/
#ifndef __KERNEL_OPENCL__
-ccl_device_inline float3 operator-(const float3& a);
-ccl_device_inline float3 operator*(const float3& a, const float3& b);
-ccl_device_inline float3 operator*(const float3& a, const float f);
-ccl_device_inline float3 operator*(const float f, const float3& a);
-ccl_device_inline float3 operator/(const float f, const float3& a);
-ccl_device_inline float3 operator/(const float3& a, const float f);
-ccl_device_inline float3 operator/(const float3& a, const float3& b);
-ccl_device_inline float3 operator+(const float3& a, const float3& b);
-ccl_device_inline float3 operator-(const float3& a, const float3& b);
-ccl_device_inline float3 operator+=(float3& a, const float3& b);
-ccl_device_inline float3 operator-=(float3& a, const float3& b);
-ccl_device_inline float3 operator*=(float3& a, const float3& b);
-ccl_device_inline float3 operator*=(float3& a, float f);
-ccl_device_inline float3 operator/=(float3& a, const float3& b);
-ccl_device_inline float3 operator/=(float3& a, float f);
-
-ccl_device_inline bool operator==(const float3& a, const float3& b);
-ccl_device_inline bool operator!=(const float3& a, const float3& b);
-
-ccl_device_inline float dot(const float3& a, const float3& b);
-ccl_device_inline float dot_xy(const float3& a, const float3& b);
-ccl_device_inline float3 cross(const float3& a, const float3& b);
-ccl_device_inline float3 normalize(const float3& a);
-ccl_device_inline float3 min(const float3& a, const float3& b);
-ccl_device_inline float3 max(const float3& a, const float3& b);
-ccl_device_inline float3 clamp(const float3& a, const float3& mn, const float3& mx);
-ccl_device_inline float3 fabs(const float3& a);
-ccl_device_inline float3 mix(const float3& a, const float3& b, float t);
-ccl_device_inline float3 rcp(const float3& a);
-ccl_device_inline float3 sqrt(const float3& a);
-#endif /* !__KERNEL_OPENCL__ */
+ccl_device_inline float3 operator-(const float3 &a);
+ccl_device_inline float3 operator*(const float3 &a, const float3 &b);
+ccl_device_inline float3 operator*(const float3 &a, const float f);
+ccl_device_inline float3 operator*(const float f, const float3 &a);
+ccl_device_inline float3 operator/(const float f, const float3 &a);
+ccl_device_inline float3 operator/(const float3 &a, const float f);
+ccl_device_inline float3 operator/(const float3 &a, const float3 &b);
+ccl_device_inline float3 operator+(const float3 &a, const float3 &b);
+ccl_device_inline float3 operator-(const float3 &a, const float3 &b);
+ccl_device_inline float3 operator+=(float3 &a, const float3 &b);
+ccl_device_inline float3 operator-=(float3 &a, const float3 &b);
+ccl_device_inline float3 operator*=(float3 &a, const float3 &b);
+ccl_device_inline float3 operator*=(float3 &a, float f);
+ccl_device_inline float3 operator/=(float3 &a, const float3 &b);
+ccl_device_inline float3 operator/=(float3 &a, float f);
+
+ccl_device_inline bool operator==(const float3 &a, const float3 &b);
+ccl_device_inline bool operator!=(const float3 &a, const float3 &b);
+
+ccl_device_inline float dot(const float3 &a, const float3 &b);
+ccl_device_inline float dot_xy(const float3 &a, const float3 &b);
+ccl_device_inline float3 cross(const float3 &a, const float3 &b);
+ccl_device_inline float3 normalize(const float3 &a);
+ccl_device_inline float3 min(const float3 &a, const float3 &b);
+ccl_device_inline float3 max(const float3 &a, const float3 &b);
+ccl_device_inline float3 clamp(const float3 &a, const float3 &mn, const float3 &mx);
+ccl_device_inline float3 fabs(const float3 &a);
+ccl_device_inline float3 mix(const float3 &a, const float3 &b, float t);
+ccl_device_inline float3 rcp(const float3 &a);
+ccl_device_inline float3 sqrt(const float3 &a);
+#endif /* !__KERNEL_OPENCL__ */
ccl_device_inline float min3(float3 a);
ccl_device_inline float max3(float3 a);
@@ -81,342 +81,345 @@ ccl_device_inline bool isequal_float3(const float3 a, const float3 b);
*/
#ifndef __KERNEL_OPENCL__
-ccl_device_inline float3 operator-(const float3& a)
+ccl_device_inline float3 operator-(const float3 &a)
{
-#ifdef __KERNEL_SSE__
- return float3(_mm_xor_ps(a.m128, _mm_castsi128_ps(_mm_set1_epi32(0x80000000))));
-#else
- return make_float3(-a.x, -a.y, -a.z);
-#endif
+# ifdef __KERNEL_SSE__
+ return float3(_mm_xor_ps(a.m128, _mm_castsi128_ps(_mm_set1_epi32(0x80000000))));
+# else
+ return make_float3(-a.x, -a.y, -a.z);
+# endif
}
-ccl_device_inline float3 operator*(const float3& a, const float3& b)
+ccl_device_inline float3 operator*(const float3 &a, const float3 &b)
{
-#ifdef __KERNEL_SSE__
- return float3(_mm_mul_ps(a.m128,b.m128));
-#else
- return make_float3(a.x*b.x, a.y*b.y, a.z*b.z);
-#endif
+# ifdef __KERNEL_SSE__
+ return float3(_mm_mul_ps(a.m128, b.m128));
+# else
+ return make_float3(a.x * b.x, a.y * b.y, a.z * b.z);
+# endif
}
-ccl_device_inline float3 operator*(const float3& a, const float f)
+ccl_device_inline float3 operator*(const float3 &a, const float f)
{
-#ifdef __KERNEL_SSE__
- return float3(_mm_mul_ps(a.m128,_mm_set1_ps(f)));
-#else
- return make_float3(a.x*f, a.y*f, a.z*f);
-#endif
+# ifdef __KERNEL_SSE__
+ return float3(_mm_mul_ps(a.m128, _mm_set1_ps(f)));
+# else
+ return make_float3(a.x * f, a.y * f, a.z * f);
+# endif
}
-ccl_device_inline float3 operator*(const float f, const float3& a)
+ccl_device_inline float3 operator*(const float f, const float3 &a)
{
-#if defined(__KERNEL_SSE__)
- return float3(_mm_mul_ps(_mm_set1_ps(f), a.m128));
-#else
- return make_float3(a.x*f, a.y*f, a.z*f);
-#endif
+# if defined(__KERNEL_SSE__)
+ return float3(_mm_mul_ps(_mm_set1_ps(f), a.m128));
+# else
+ return make_float3(a.x * f, a.y * f, a.z * f);
+# endif
}
-ccl_device_inline float3 operator/(const float f, const float3& a)
+ccl_device_inline float3 operator/(const float f, const float3 &a)
{
-#if defined(__KERNEL_SSE__)
- return float3(_mm_div_ps(_mm_set1_ps(f), a.m128));
-#else
- return make_float3(f / a.x, f / a.y, f / a.z);
-#endif
+# if defined(__KERNEL_SSE__)
+ return float3(_mm_div_ps(_mm_set1_ps(f), a.m128));
+# else
+ return make_float3(f / a.x, f / a.y, f / a.z);
+# endif
}
-ccl_device_inline float3 operator/(const float3& a, const float f)
+ccl_device_inline float3 operator/(const float3 &a, const float f)
{
- float invf = 1.0f/f;
- return a * invf;
+ float invf = 1.0f / f;
+ return a * invf;
}
-ccl_device_inline float3 operator/(const float3& a, const float3& b)
+ccl_device_inline float3 operator/(const float3 &a, const float3 &b)
{
-#if defined(__KERNEL_SSE__)
- return float3(_mm_div_ps(a.m128, b.m128));
-#else
- return make_float3(a.x / b.x, a.y / b.y, a.z / b.z);
-#endif
+# if defined(__KERNEL_SSE__)
+ return float3(_mm_div_ps(a.m128, b.m128));
+# else
+ return make_float3(a.x / b.x, a.y / b.y, a.z / b.z);
+# endif
}
-ccl_device_inline float3 operator+(const float3& a, const float3& b)
+ccl_device_inline float3 operator+(const float3 &a, const float3 &b)
{
-#ifdef __KERNEL_SSE__
- return float3(_mm_add_ps(a.m128, b.m128));
-#else
- return make_float3(a.x + b.x, a.y + b.y, a.z + b.z);
-#endif
+# ifdef __KERNEL_SSE__
+ return float3(_mm_add_ps(a.m128, b.m128));
+# else
+ return make_float3(a.x + b.x, a.y + b.y, a.z + b.z);
+# endif
}
-ccl_device_inline float3 operator-(const float3& a, const float3& b)
+ccl_device_inline float3 operator-(const float3 &a, const float3 &b)
{
-#ifdef __KERNEL_SSE__
- return float3(_mm_sub_ps(a.m128, b.m128));
-#else
- return make_float3(a.x - b.x, a.y - b.y, a.z - b.z);
-#endif
+# ifdef __KERNEL_SSE__
+ return float3(_mm_sub_ps(a.m128, b.m128));
+# else
+ return make_float3(a.x - b.x, a.y - b.y, a.z - b.z);
+# endif
}
-ccl_device_inline float3 operator+=(float3& a, const float3& b)
+ccl_device_inline float3 operator+=(float3 &a, const float3 &b)
{
- return a = a + b;
+ return a = a + b;
}
-ccl_device_inline float3 operator-=(float3& a, const float3& b)
+ccl_device_inline float3 operator-=(float3 &a, const float3 &b)
{
- return a = a - b;
+ return a = a - b;
}
-ccl_device_inline float3 operator*=(float3& a, const float3& b)
+ccl_device_inline float3 operator*=(float3 &a, const float3 &b)
{
- return a = a * b;
+ return a = a * b;
}
-ccl_device_inline float3 operator*=(float3& a, float f)
+ccl_device_inline float3 operator*=(float3 &a, float f)
{
- return a = a * f;
+ return a = a * f;
}
-ccl_device_inline float3 operator/=(float3& a, const float3& b)
+ccl_device_inline float3 operator/=(float3 &a, const float3 &b)
{
- return a = a / b;
+ return a = a / b;
}
-ccl_device_inline float3 operator/=(float3& a, float f)
+ccl_device_inline float3 operator/=(float3 &a, float f)
{
- float invf = 1.0f/f;
- return a = a * invf;
+ float invf = 1.0f / f;
+ return a = a * invf;
}
-ccl_device_inline bool operator==(const float3& a, const float3& b)
+ccl_device_inline bool operator==(const float3 &a, const float3 &b)
{
-#ifdef __KERNEL_SSE__
- return (_mm_movemask_ps(_mm_cmpeq_ps(a.m128, b.m128)) & 7) == 7;
-#else
- return (a.x == b.x && a.y == b.y && a.z == b.z);
-#endif
+# ifdef __KERNEL_SSE__
+ return (_mm_movemask_ps(_mm_cmpeq_ps(a.m128, b.m128)) & 7) == 7;
+# else
+ return (a.x == b.x && a.y == b.y && a.z == b.z);
+# endif
}
-ccl_device_inline bool operator!=(const float3& a, const float3& b)
+ccl_device_inline bool operator!=(const float3 &a, const float3 &b)
{
- return !(a == b);
+ return !(a == b);
}
-ccl_device_inline float dot(const float3& a, const float3& b)
+ccl_device_inline float dot(const float3 &a, const float3 &b)
{
-#if defined(__KERNEL_SSE41__) && defined(__KERNEL_SSE__)
- return _mm_cvtss_f32(_mm_dp_ps(a, b, 0x7F));
-#else
- return a.x*b.x + a.y*b.y + a.z*b.z;
-#endif
+# if defined(__KERNEL_SSE41__) && defined(__KERNEL_SSE__)
+ return _mm_cvtss_f32(_mm_dp_ps(a, b, 0x7F));
+# else
+ return a.x * b.x + a.y * b.y + a.z * b.z;
+# endif
}
-ccl_device_inline float dot_xy(const float3& a, const float3& b)
+ccl_device_inline float dot_xy(const float3 &a, const float3 &b)
{
-#if defined(__KERNEL_SSE41__) && defined(__KERNEL_SSE__)
- return _mm_cvtss_f32(_mm_hadd_ps(_mm_mul_ps(a,b),b));
-#else
- return a.x*b.x + a.y*b.y;
-#endif
+# if defined(__KERNEL_SSE41__) && defined(__KERNEL_SSE__)
+ return _mm_cvtss_f32(_mm_hadd_ps(_mm_mul_ps(a, b), b));
+# else
+ return a.x * b.x + a.y * b.y;
+# endif
}
-ccl_device_inline float3 cross(const float3& a, const float3& b)
+ccl_device_inline float3 cross(const float3 &a, const float3 &b)
{
- float3 r = make_float3(a.y*b.z - a.z*b.y, a.z*b.x - a.x*b.z, a.x*b.y - a.y*b.x);
- return r;
+ float3 r = make_float3(a.y * b.z - a.z * b.y, a.z * b.x - a.x * b.z, a.x * b.y - a.y * b.x);
+ return r;
}
-ccl_device_inline float3 normalize(const float3& a)
+ccl_device_inline float3 normalize(const float3 &a)
{
-#if defined(__KERNEL_SSE41__) && defined(__KERNEL_SSE__)
- __m128 norm = _mm_sqrt_ps(_mm_dp_ps(a.m128, a.m128, 0x7F));
- return float3(_mm_div_ps(a.m128, norm));
-#else
- return a/len(a);
-#endif
+# if defined(__KERNEL_SSE41__) && defined(__KERNEL_SSE__)
+ __m128 norm = _mm_sqrt_ps(_mm_dp_ps(a.m128, a.m128, 0x7F));
+ return float3(_mm_div_ps(a.m128, norm));
+# else
+ return a / len(a);
+# endif
}
-ccl_device_inline float3 min(const float3& a, const float3& b)
+ccl_device_inline float3 min(const float3 &a, const float3 &b)
{
-#ifdef __KERNEL_SSE__
- return float3(_mm_min_ps(a.m128, b.m128));
-#else
- return make_float3(min(a.x, b.x), min(a.y, b.y), min(a.z, b.z));
-#endif
+# ifdef __KERNEL_SSE__
+ return float3(_mm_min_ps(a.m128, b.m128));
+# else
+ return make_float3(min(a.x, b.x), min(a.y, b.y), min(a.z, b.z));
+# endif
}
-ccl_device_inline float3 max(const float3& a, const float3& b)
+ccl_device_inline float3 max(const float3 &a, const float3 &b)
{
-#ifdef __KERNEL_SSE__
- return float3(_mm_max_ps(a.m128, b.m128));
-#else
- return make_float3(max(a.x, b.x), max(a.y, b.y), max(a.z, b.z));
-#endif
+# ifdef __KERNEL_SSE__
+ return float3(_mm_max_ps(a.m128, b.m128));
+# else
+ return make_float3(max(a.x, b.x), max(a.y, b.y), max(a.z, b.z));
+# endif
}
-ccl_device_inline float3 clamp(const float3& a, const float3& mn, const float3& mx)
+ccl_device_inline float3 clamp(const float3 &a, const float3 &mn, const float3 &mx)
{
- return min(max(a, mn), mx);
+ return min(max(a, mn), mx);
}
-ccl_device_inline float3 fabs(const float3& a)
+ccl_device_inline float3 fabs(const float3 &a)
{
-#ifdef __KERNEL_SSE__
- __m128 mask = _mm_castsi128_ps(_mm_set1_epi32(0x7fffffff));
- return float3(_mm_and_ps(a.m128, mask));
-#else
- return make_float3(fabsf(a.x), fabsf(a.y), fabsf(a.z));
-#endif
+# ifdef __KERNEL_SSE__
+ __m128 mask = _mm_castsi128_ps(_mm_set1_epi32(0x7fffffff));
+ return float3(_mm_and_ps(a.m128, mask));
+# else
+ return make_float3(fabsf(a.x), fabsf(a.y), fabsf(a.z));
+# endif
}
-ccl_device_inline float3 sqrt(const float3& a)
+ccl_device_inline float3 sqrt(const float3 &a)
{
-#ifdef __KERNEL_SSE__
- return float3(_mm_sqrt_ps(a));
-#else
- return make_float3(sqrtf(a.x), sqrtf(a.y), sqrtf(a.z));
-#endif
+# ifdef __KERNEL_SSE__
+ return float3(_mm_sqrt_ps(a));
+# else
+ return make_float3(sqrtf(a.x), sqrtf(a.y), sqrtf(a.z));
+# endif
}
-ccl_device_inline float3 mix(const float3& a, const float3& b, float t)
+ccl_device_inline float3 mix(const float3 &a, const float3 &b, float t)
{
- return a + t*(b - a);
+ return a + t * (b - a);
}
-ccl_device_inline float3 rcp(const float3& a)
+ccl_device_inline float3 rcp(const float3 &a)
{
-#ifdef __KERNEL_SSE__
- /* Don't use _mm_rcp_ps due to poor precision. */
- return float3(_mm_div_ps(_mm_set_ps1(1.0f), a.m128));
-#else
- return make_float3(1.0f/a.x, 1.0f/a.y, 1.0f/a.z);
-#endif
+# ifdef __KERNEL_SSE__
+ /* Don't use _mm_rcp_ps due to poor precision. */
+ return float3(_mm_div_ps(_mm_set_ps1(1.0f), a.m128));
+# else
+ return make_float3(1.0f / a.x, 1.0f / a.y, 1.0f / a.z);
+# endif
}
-#endif /* !__KERNEL_OPENCL__ */
+#endif /* !__KERNEL_OPENCL__ */
ccl_device_inline float min3(float3 a)
{
- return min(min(a.x, a.y), a.z);
+ return min(min(a.x, a.y), a.z);
}
ccl_device_inline float max3(float3 a)
{
- return max(max(a.x, a.y), a.z);
+ return max(max(a.x, a.y), a.z);
}
ccl_device_inline float len(const float3 a)
{
#if defined(__KERNEL_SSE41__) && defined(__KERNEL_SSE__)
- return _mm_cvtss_f32(_mm_sqrt_ss(_mm_dp_ps(a.m128, a.m128, 0x7F)));
+ return _mm_cvtss_f32(_mm_sqrt_ss(_mm_dp_ps(a.m128, a.m128, 0x7F)));
#else
- return sqrtf(dot(a, a));
+ return sqrtf(dot(a, a));
#endif
}
ccl_device_inline float len_squared(const float3 a)
{
- return dot(a, a);
+ return dot(a, a);
}
ccl_device_inline float3 saturate3(float3 a)
{
- return make_float3(saturate(a.x), saturate(a.y), saturate(a.z));
+ return make_float3(saturate(a.x), saturate(a.y), saturate(a.z));
}
ccl_device_inline float3 normalize_len(const float3 a, float *t)
{
- *t = len(a);
- float x = 1.0f / *t;
- return a*x;
+ *t = len(a);
+ float x = 1.0f / *t;
+ return a * x;
}
ccl_device_inline float3 safe_normalize(const float3 a)
{
- float t = len(a);
- return (t != 0.0f)? a * (1.0f/t) : a;
+ float t = len(a);
+ return (t != 0.0f) ? a * (1.0f / t) : a;
}
ccl_device_inline float3 safe_normalize_len(const float3 a, float *t)
{
- *t = len(a);
- return (*t != 0.0f)? a/(*t): a;
+ *t = len(a);
+ return (*t != 0.0f) ? a / (*t) : a;
}
ccl_device_inline float3 interp(float3 a, float3 b, float t)
{
- return a + t*(b - a);
+ return a + t * (b - a);
}
ccl_device_inline bool is_zero(const float3 a)
{
#ifdef __KERNEL_SSE__
- return a == make_float3(0.0f);
+ return a == make_float3(0.0f);
#else
- return (a.x == 0.0f && a.y == 0.0f && a.z == 0.0f);
+ return (a.x == 0.0f && a.y == 0.0f && a.z == 0.0f);
#endif
}
ccl_device_inline float reduce_add(const float3 a)
{
- return (a.x + a.y + a.z);
+ return (a.x + a.y + a.z);
}
ccl_device_inline float average(const float3 a)
{
- return reduce_add(a)*(1.0f/3.0f);
+ return reduce_add(a) * (1.0f / 3.0f);
}
ccl_device_inline bool isequal_float3(const float3 a, const float3 b)
{
#ifdef __KERNEL_OPENCL__
- return all(a == b);
+ return all(a == b);
#else
- return a == b;
+ return a == b;
#endif
}
ccl_device_inline float3 pow3(float3 v, float e)
{
- return make_float3(powf(v.x, e), powf(v.y, e), powf(v.z, e));
+ return make_float3(powf(v.x, e), powf(v.y, e), powf(v.z, e));
}
ccl_device_inline float3 exp3(float3 v)
{
- return make_float3(expf(v.x), expf(v.y), expf(v.z));
+ return make_float3(expf(v.x), expf(v.y), expf(v.z));
}
ccl_device_inline float3 log3(float3 v)
{
- return make_float3(logf(v.x), logf(v.y), logf(v.z));
+ return make_float3(logf(v.x), logf(v.y), logf(v.z));
}
ccl_device_inline int3 quick_floor_to_int3(const float3 a)
{
#ifdef __KERNEL_SSE__
- int3 b = int3(_mm_cvttps_epi32(a.m128));
- int3 isneg = int3(_mm_castps_si128(_mm_cmplt_ps(a.m128, _mm_set_ps1(0.0f))));
- /* Unsaturated add 0xffffffff is the same as subtract -1. */
- return b + isneg;
+ int3 b = int3(_mm_cvttps_epi32(a.m128));
+ int3 isneg = int3(_mm_castps_si128(_mm_cmplt_ps(a.m128, _mm_set_ps1(0.0f))));
+ /* Unsaturated add 0xffffffff is the same as subtract -1. */
+ return b + isneg;
#else
- return make_int3(quick_floor_to_int(a.x), quick_floor_to_int(a.y), quick_floor_to_int(a.z));
+ return make_int3(quick_floor_to_int(a.x), quick_floor_to_int(a.y), quick_floor_to_int(a.z));
#endif
}
ccl_device_inline bool isfinite3_safe(float3 v)
{
- return isfinite_safe(v.x) && isfinite_safe(v.y) && isfinite_safe(v.z);
+ return isfinite_safe(v.x) && isfinite_safe(v.y) && isfinite_safe(v.z);
}
ccl_device_inline float3 ensure_finite3(float3 v)
{
- if(!isfinite_safe(v.x)) v.x = 0.0f;
- if(!isfinite_safe(v.y)) v.y = 0.0f;
- if(!isfinite_safe(v.z)) v.z = 0.0f;
- return v;
+ if (!isfinite_safe(v.x))
+ v.x = 0.0f;
+ if (!isfinite_safe(v.y))
+ v.y = 0.0f;
+ if (!isfinite_safe(v.z))
+ v.z = 0.0f;
+ return v;
}
CCL_NAMESPACE_END
-#endif /* __UTIL_MATH_FLOAT3_H__ */
+#endif /* __UTIL_MATH_FLOAT3_H__ */
diff --git a/intern/cycles/util/util_math_float4.h b/intern/cycles/util/util_math_float4.h
index 479ccf202ba..1fb886572e3 100644
--- a/intern/cycles/util/util_math_float4.h
+++ b/intern/cycles/util/util_math_float4.h
@@ -28,433 +28,408 @@ CCL_NAMESPACE_BEGIN
*/
#ifndef __KERNEL_OPENCL__
-ccl_device_inline float4 operator-(const float4& a);
-ccl_device_inline float4 operator*(const float4& a, const float4& b);
-ccl_device_inline float4 operator*(const float4& a, float f);
-ccl_device_inline float4 operator*(float f, const float4& a);
-ccl_device_inline float4 operator/(const float4& a, float f);
-ccl_device_inline float4 operator/(const float4& a, const float4& b);
-ccl_device_inline float4 operator+(const float4& a, const float4& b);
-ccl_device_inline float4 operator-(const float4& a, const float4& b);
-ccl_device_inline float4 operator+=(float4& a, const float4& b);
-ccl_device_inline float4 operator*=(float4& a, const float4& b);
-ccl_device_inline float4 operator*=(float4& a, float f);
-ccl_device_inline float4 operator/=(float4& a, float f);
-
-ccl_device_inline int4 operator<(const float4& a, const float4& b);
-ccl_device_inline int4 operator>=(const float4& a, const float4& b);
-ccl_device_inline int4 operator<=(const float4& a, const float4& b);
-ccl_device_inline bool operator==(const float4& a, const float4& b);
-
-ccl_device_inline float dot(const float4& a, const float4& b);
-ccl_device_inline float len_squared(const float4& a);
-ccl_device_inline float4 rcp(const float4& a);
-ccl_device_inline float4 sqrt(const float4& a);
-ccl_device_inline float4 sqr(const float4& a);
-ccl_device_inline float4 cross(const float4& a, const float4& b);
-ccl_device_inline bool is_zero(const float4& a);
-ccl_device_inline float average(const float4& a);
-ccl_device_inline float len(const float4& a);
-ccl_device_inline float4 normalize(const float4& a);
-ccl_device_inline float4 safe_normalize(const float4& a);
-ccl_device_inline float4 min(const float4& a, const float4& b);
-ccl_device_inline float4 max(const float4& a, const float4& b);
-ccl_device_inline float4 clamp(const float4& a, const float4& mn, const float4& mx);
-ccl_device_inline float4 fabs(const float4& a);
-#endif /* !__KERNEL_OPENCL__*/
+ccl_device_inline float4 operator-(const float4 &a);
+ccl_device_inline float4 operator*(const float4 &a, const float4 &b);
+ccl_device_inline float4 operator*(const float4 &a, float f);
+ccl_device_inline float4 operator*(float f, const float4 &a);
+ccl_device_inline float4 operator/(const float4 &a, float f);
+ccl_device_inline float4 operator/(const float4 &a, const float4 &b);
+ccl_device_inline float4 operator+(const float4 &a, const float4 &b);
+ccl_device_inline float4 operator-(const float4 &a, const float4 &b);
+ccl_device_inline float4 operator+=(float4 &a, const float4 &b);
+ccl_device_inline float4 operator*=(float4 &a, const float4 &b);
+ccl_device_inline float4 operator*=(float4 &a, float f);
+ccl_device_inline float4 operator/=(float4 &a, float f);
+
+ccl_device_inline int4 operator<(const float4 &a, const float4 &b);
+ccl_device_inline int4 operator>=(const float4 &a, const float4 &b);
+ccl_device_inline int4 operator<=(const float4 &a, const float4 &b);
+ccl_device_inline bool operator==(const float4 &a, const float4 &b);
+
+ccl_device_inline float dot(const float4 &a, const float4 &b);
+ccl_device_inline float len_squared(const float4 &a);
+ccl_device_inline float4 rcp(const float4 &a);
+ccl_device_inline float4 sqrt(const float4 &a);
+ccl_device_inline float4 sqr(const float4 &a);
+ccl_device_inline float4 cross(const float4 &a, const float4 &b);
+ccl_device_inline bool is_zero(const float4 &a);
+ccl_device_inline float average(const float4 &a);
+ccl_device_inline float len(const float4 &a);
+ccl_device_inline float4 normalize(const float4 &a);
+ccl_device_inline float4 safe_normalize(const float4 &a);
+ccl_device_inline float4 min(const float4 &a, const float4 &b);
+ccl_device_inline float4 max(const float4 &a, const float4 &b);
+ccl_device_inline float4 clamp(const float4 &a, const float4 &mn, const float4 &mx);
+ccl_device_inline float4 fabs(const float4 &a);
+#endif /* !__KERNEL_OPENCL__*/
#ifdef __KERNEL_SSE__
template<size_t index_0, size_t index_1, size_t index_2, size_t index_3>
-__forceinline const float4 shuffle(const float4& b);
+__forceinline const float4 shuffle(const float4 &b);
template<size_t index_0, size_t index_1, size_t index_2, size_t index_3>
-__forceinline const float4 shuffle(const float4& a, const float4& b);
+__forceinline const float4 shuffle(const float4 &a, const float4 &b);
-template<> __forceinline const float4 shuffle<0, 1, 0, 1>(const float4& b);
+template<> __forceinline const float4 shuffle<0, 1, 0, 1>(const float4 &b);
-template<> __forceinline const float4 shuffle<0, 1, 0, 1>(const float4& a, const float4& b);
-template<> __forceinline const float4 shuffle<2, 3, 2, 3>(const float4& a, const float4& b);
+template<> __forceinline const float4 shuffle<0, 1, 0, 1>(const float4 &a, const float4 &b);
+template<> __forceinline const float4 shuffle<2, 3, 2, 3>(const float4 &a, const float4 &b);
# ifdef __KERNEL_SSE3__
-template<> __forceinline const float4 shuffle<0, 0, 2, 2>(const float4& b);
-template<> __forceinline const float4 shuffle<1, 1, 3, 3>(const float4& b);
+template<> __forceinline const float4 shuffle<0, 0, 2, 2>(const float4 &b);
+template<> __forceinline const float4 shuffle<1, 1, 3, 3>(const float4 &b);
# endif
-#endif /* __KERNEL_SSE__ */
+#endif /* __KERNEL_SSE__ */
#ifndef __KERNEL_GPU__
-ccl_device_inline float4 select(const int4& mask,
- const float4& a,
- const float4& b);
-ccl_device_inline float4 reduce_min(const float4& a);
-ccl_device_inline float4 reduce_max(const float4& a);
-ccl_device_inline float4 reduce_add(const float4& a);
-#endif /* !__KERNEL_GPU__ */
+ccl_device_inline float4 select(const int4 &mask, const float4 &a, const float4 &b);
+ccl_device_inline float4 reduce_min(const float4 &a);
+ccl_device_inline float4 reduce_max(const float4 &a);
+ccl_device_inline float4 reduce_add(const float4 &a);
+#endif /* !__KERNEL_GPU__ */
/*******************************************************************************
* Definition.
*/
#ifndef __KERNEL_OPENCL__
-ccl_device_inline float4 operator-(const float4& a)
+ccl_device_inline float4 operator-(const float4 &a)
{
-#ifdef __KERNEL_SSE__
- __m128 mask = _mm_castsi128_ps(_mm_set1_epi32(0x80000000));
- return float4(_mm_xor_ps(a.m128, mask));
-#else
- return make_float4(-a.x, -a.y, -a.z, -a.w);
-#endif
+# ifdef __KERNEL_SSE__
+ __m128 mask = _mm_castsi128_ps(_mm_set1_epi32(0x80000000));
+ return float4(_mm_xor_ps(a.m128, mask));
+# else
+ return make_float4(-a.x, -a.y, -a.z, -a.w);
+# endif
}
-ccl_device_inline float4 operator*(const float4& a, const float4& b)
+ccl_device_inline float4 operator*(const float4 &a, const float4 &b)
{
-#ifdef __KERNEL_SSE__
- return float4(_mm_mul_ps(a.m128, b.m128));
-#else
- return make_float4(a.x*b.x, a.y*b.y, a.z*b.z, a.w*b.w);
-#endif
+# ifdef __KERNEL_SSE__
+ return float4(_mm_mul_ps(a.m128, b.m128));
+# else
+ return make_float4(a.x * b.x, a.y * b.y, a.z * b.z, a.w * b.w);
+# endif
}
-ccl_device_inline float4 operator*(const float4& a, float f)
+ccl_device_inline float4 operator*(const float4 &a, float f)
{
-#if defined(__KERNEL_SSE__)
- return a * make_float4(f);
-#else
- return make_float4(a.x*f, a.y*f, a.z*f, a.w*f);
-#endif
+# if defined(__KERNEL_SSE__)
+ return a * make_float4(f);
+# else
+ return make_float4(a.x * f, a.y * f, a.z * f, a.w * f);
+# endif
}
-ccl_device_inline float4 operator*(float f, const float4& a)
+ccl_device_inline float4 operator*(float f, const float4 &a)
{
- return a * f;
+ return a * f;
}
-ccl_device_inline float4 operator/(const float4& a, float f)
+ccl_device_inline float4 operator/(const float4 &a, float f)
{
- return a * (1.0f/f);
+ return a * (1.0f / f);
}
-ccl_device_inline float4 operator/(const float4& a, const float4& b)
+ccl_device_inline float4 operator/(const float4 &a, const float4 &b)
{
-#ifdef __KERNEL_SSE__
- return float4(_mm_div_ps(a.m128, b.m128));
-#else
- return make_float4(a.x/b.x, a.y/b.y, a.z/b.z, a.w/b.w);
-#endif
-
+# ifdef __KERNEL_SSE__
+ return float4(_mm_div_ps(a.m128, b.m128));
+# else
+ return make_float4(a.x / b.x, a.y / b.y, a.z / b.z, a.w / b.w);
+# endif
}
-ccl_device_inline float4 operator+(const float4& a, const float4& b)
+ccl_device_inline float4 operator+(const float4 &a, const float4 &b)
{
-#ifdef __KERNEL_SSE__
- return float4(_mm_add_ps(a.m128, b.m128));
-#else
- return make_float4(a.x+b.x, a.y+b.y, a.z+b.z, a.w+b.w);
-#endif
+# ifdef __KERNEL_SSE__
+ return float4(_mm_add_ps(a.m128, b.m128));
+# else
+ return make_float4(a.x + b.x, a.y + b.y, a.z + b.z, a.w + b.w);
+# endif
}
-ccl_device_inline float4 operator-(const float4& a, const float4& b)
+ccl_device_inline float4 operator-(const float4 &a, const float4 &b)
{
-#ifdef __KERNEL_SSE__
- return float4(_mm_sub_ps(a.m128, b.m128));
-#else
- return make_float4(a.x-b.x, a.y-b.y, a.z-b.z, a.w-b.w);
-#endif
+# ifdef __KERNEL_SSE__
+ return float4(_mm_sub_ps(a.m128, b.m128));
+# else
+ return make_float4(a.x - b.x, a.y - b.y, a.z - b.z, a.w - b.w);
+# endif
}
-ccl_device_inline float4 operator+=(float4& a, const float4& b)
+ccl_device_inline float4 operator+=(float4 &a, const float4 &b)
{
- return a = a + b;
+ return a = a + b;
}
-ccl_device_inline float4 operator*=(float4& a, const float4& b)
+ccl_device_inline float4 operator*=(float4 &a, const float4 &b)
{
- return a = a * b;
+ return a = a * b;
}
-ccl_device_inline float4 operator*=(float4& a, float f)
+ccl_device_inline float4 operator*=(float4 &a, float f)
{
- return a = a * f;
+ return a = a * f;
}
-ccl_device_inline float4 operator/=(float4& a, float f)
+ccl_device_inline float4 operator/=(float4 &a, float f)
{
- return a = a / f;
+ return a = a / f;
}
-ccl_device_inline int4 operator<(const float4& a, const float4& b)
+ccl_device_inline int4 operator<(const float4 &a, const float4 &b)
{
-#ifdef __KERNEL_SSE__
- return int4(_mm_castps_si128(_mm_cmplt_ps(a.m128, b.m128)));
-#else
- return make_int4(a.x < b.x, a.y < b.y, a.z < b.z, a.w < b.w);
-#endif
+# ifdef __KERNEL_SSE__
+ return int4(_mm_castps_si128(_mm_cmplt_ps(a.m128, b.m128)));
+# else
+ return make_int4(a.x < b.x, a.y < b.y, a.z < b.z, a.w < b.w);
+# endif
}
-ccl_device_inline int4 operator>=(const float4& a, const float4& b)
+ccl_device_inline int4 operator>=(const float4 &a, const float4 &b)
{
-#ifdef __KERNEL_SSE__
- return int4(_mm_castps_si128(_mm_cmpge_ps(a.m128, b.m128)));
-#else
- return make_int4(a.x >= b.x, a.y >= b.y, a.z >= b.z, a.w >= b.w);
-#endif
+# ifdef __KERNEL_SSE__
+ return int4(_mm_castps_si128(_mm_cmpge_ps(a.m128, b.m128)));
+# else
+ return make_int4(a.x >= b.x, a.y >= b.y, a.z >= b.z, a.w >= b.w);
+# endif
}
-ccl_device_inline int4 operator<=(const float4& a, const float4& b)
+ccl_device_inline int4 operator<=(const float4 &a, const float4 &b)
{
-#ifdef __KERNEL_SSE__
- return int4(_mm_castps_si128(_mm_cmple_ps(a.m128, b.m128)));
-#else
- return make_int4(a.x <= b.x, a.y <= b.y, a.z <= b.z, a.w <= b.w);
-#endif
+# ifdef __KERNEL_SSE__
+ return int4(_mm_castps_si128(_mm_cmple_ps(a.m128, b.m128)));
+# else
+ return make_int4(a.x <= b.x, a.y <= b.y, a.z <= b.z, a.w <= b.w);
+# endif
}
-ccl_device_inline bool operator==(const float4& a, const float4& b)
+ccl_device_inline bool operator==(const float4 &a, const float4 &b)
{
-#ifdef __KERNEL_SSE__
- return (_mm_movemask_ps(_mm_cmpeq_ps(a.m128, b.m128)) & 15) == 15;
-#else
- return (a.x == b.x && a.y == b.y && a.z == b.z && a.w == b.w);
-#endif
+# ifdef __KERNEL_SSE__
+ return (_mm_movemask_ps(_mm_cmpeq_ps(a.m128, b.m128)) & 15) == 15;
+# else
+ return (a.x == b.x && a.y == b.y && a.z == b.z && a.w == b.w);
+# endif
}
-ccl_device_inline float dot(const float4& a, const float4& b)
+ccl_device_inline float dot(const float4 &a, const float4 &b)
{
-#if defined(__KERNEL_SSE41__) && defined(__KERNEL_SSE__)
- return _mm_cvtss_f32(_mm_dp_ps(a, b, 0xFF));
-#else
- return (a.x*b.x + a.y*b.y) + (a.z*b.z + a.w*b.w);
-#endif
+# if defined(__KERNEL_SSE41__) && defined(__KERNEL_SSE__)
+ return _mm_cvtss_f32(_mm_dp_ps(a, b, 0xFF));
+# else
+ return (a.x * b.x + a.y * b.y) + (a.z * b.z + a.w * b.w);
+# endif
}
-ccl_device_inline float len_squared(const float4& a)
+ccl_device_inline float len_squared(const float4 &a)
{
- return dot(a, a);
+ return dot(a, a);
}
-ccl_device_inline float4 rcp(const float4& a)
+ccl_device_inline float4 rcp(const float4 &a)
{
-#ifdef __KERNEL_SSE__
- /* Don't use _mm_rcp_ps due to poor precision. */
- return float4(_mm_div_ps(_mm_set_ps1(1.0f), a.m128));
-#else
- return make_float4(1.0f/a.x, 1.0f/a.y, 1.0f/a.z, 1.0f/a.w);
-#endif
+# ifdef __KERNEL_SSE__
+ /* Don't use _mm_rcp_ps due to poor precision. */
+ return float4(_mm_div_ps(_mm_set_ps1(1.0f), a.m128));
+# else
+ return make_float4(1.0f / a.x, 1.0f / a.y, 1.0f / a.z, 1.0f / a.w);
+# endif
}
-ccl_device_inline float4 sqrt(const float4& a)
+ccl_device_inline float4 sqrt(const float4 &a)
{
-#ifdef __KERNEL_SSE__
- return float4(_mm_sqrt_ps(a.m128));
-#else
- return make_float4(sqrtf(a.x),
- sqrtf(a.y),
- sqrtf(a.z),
- sqrtf(a.w));
-#endif
+# ifdef __KERNEL_SSE__
+ return float4(_mm_sqrt_ps(a.m128));
+# else
+ return make_float4(sqrtf(a.x), sqrtf(a.y), sqrtf(a.z), sqrtf(a.w));
+# endif
}
-ccl_device_inline float4 sqr(const float4& a)
+ccl_device_inline float4 sqr(const float4 &a)
{
- return a * a;
+ return a * a;
}
-ccl_device_inline float4 cross(const float4& a, const float4& b)
+ccl_device_inline float4 cross(const float4 &a, const float4 &b)
{
-#ifdef __KERNEL_SSE__
- return (shuffle<1,2,0,0>(a)*shuffle<2,0,1,0>(b)) -
- (shuffle<2,0,1,0>(a)*shuffle<1,2,0,0>(b));
-#else
- return make_float4(a.y*b.z - a.z*b.y,
- a.z*b.x - a.x*b.z,
- a.x*b.y - a.y*b.x,
- 0.0f);
-#endif
+# ifdef __KERNEL_SSE__
+ return (shuffle<1, 2, 0, 0>(a) * shuffle<2, 0, 1, 0>(b)) -
+ (shuffle<2, 0, 1, 0>(a) * shuffle<1, 2, 0, 0>(b));
+# else
+ return make_float4(a.y * b.z - a.z * b.y, a.z * b.x - a.x * b.z, a.x * b.y - a.y * b.x, 0.0f);
+# endif
}
-ccl_device_inline bool is_zero(const float4& a)
+ccl_device_inline bool is_zero(const float4 &a)
{
-#ifdef __KERNEL_SSE__
- return a == make_float4(0.0f);
-#else
- return (a.x == 0.0f && a.y == 0.0f && a.z == 0.0f && a.w == 0.0f);
-#endif
+# ifdef __KERNEL_SSE__
+ return a == make_float4(0.0f);
+# else
+ return (a.x == 0.0f && a.y == 0.0f && a.z == 0.0f && a.w == 0.0f);
+# endif
}
-ccl_device_inline float4 reduce_add(const float4& a)
+ccl_device_inline float4 reduce_add(const float4 &a)
{
-#ifdef __KERNEL_SSE__
-# ifdef __KERNEL_SSE3__
- float4 h(_mm_hadd_ps(a.m128, a.m128));
- return float4( _mm_hadd_ps(h.m128, h.m128));
+# ifdef __KERNEL_SSE__
+# ifdef __KERNEL_SSE3__
+ float4 h(_mm_hadd_ps(a.m128, a.m128));
+ return float4(_mm_hadd_ps(h.m128, h.m128));
+# else
+ float4 h(shuffle<1, 0, 3, 2>(a) + a);
+ return shuffle<2, 3, 0, 1>(h) + h;
+# endif
# else
- float4 h(shuffle<1,0,3,2>(a) + a);
- return shuffle<2,3,0,1>(h) + h;
+ float sum = (a.x + a.y) + (a.z + a.w);
+ return make_float4(sum, sum, sum, sum);
# endif
-#else
- float sum = (a.x + a.y) + (a.z + a.w);
- return make_float4(sum, sum, sum, sum);
-#endif
}
-ccl_device_inline float average(const float4& a)
+ccl_device_inline float average(const float4 &a)
{
- return reduce_add(a).x * 0.25f;
+ return reduce_add(a).x * 0.25f;
}
-ccl_device_inline float len(const float4& a)
+ccl_device_inline float len(const float4 &a)
{
- return sqrtf(dot(a, a));
+ return sqrtf(dot(a, a));
}
-ccl_device_inline float4 normalize(const float4& a)
+ccl_device_inline float4 normalize(const float4 &a)
{
- return a/len(a);
+ return a / len(a);
}
-ccl_device_inline float4 safe_normalize(const float4& a)
+ccl_device_inline float4 safe_normalize(const float4 &a)
{
- float t = len(a);
- return (t != 0.0f)? a/t: a;
+ float t = len(a);
+ return (t != 0.0f) ? a / t : a;
}
-ccl_device_inline float4 min(const float4& a, const float4& b)
+ccl_device_inline float4 min(const float4 &a, const float4 &b)
{
-#ifdef __KERNEL_SSE__
- return float4(_mm_min_ps(a.m128, b.m128));
-#else
- return make_float4(min(a.x, b.x),
- min(a.y, b.y),
- min(a.z, b.z),
- min(a.w, b.w));
-#endif
+# ifdef __KERNEL_SSE__
+ return float4(_mm_min_ps(a.m128, b.m128));
+# else
+ return make_float4(min(a.x, b.x), min(a.y, b.y), min(a.z, b.z), min(a.w, b.w));
+# endif
}
-ccl_device_inline float4 max(const float4& a, const float4& b)
+ccl_device_inline float4 max(const float4 &a, const float4 &b)
{
-#ifdef __KERNEL_SSE__
- return float4(_mm_max_ps(a.m128, b.m128));
-#else
- return make_float4(max(a.x, b.x),
- max(a.y, b.y),
- max(a.z, b.z),
- max(a.w, b.w));
-#endif
+# ifdef __KERNEL_SSE__
+ return float4(_mm_max_ps(a.m128, b.m128));
+# else
+ return make_float4(max(a.x, b.x), max(a.y, b.y), max(a.z, b.z), max(a.w, b.w));
+# endif
}
-ccl_device_inline float4 clamp(const float4& a, const float4& mn, const float4& mx)
+ccl_device_inline float4 clamp(const float4 &a, const float4 &mn, const float4 &mx)
{
- return min(max(a, mn), mx);
+ return min(max(a, mn), mx);
}
-ccl_device_inline float4 fabs(const float4& a)
+ccl_device_inline float4 fabs(const float4 &a)
{
-#ifdef __KERNEL_SSE__
- return float4(_mm_and_ps(a.m128, _mm_castsi128_ps(_mm_set1_epi32(0x7fffffff))));
-#else
- return make_float4(fabsf(a.x),
- fabsf(a.y),
- fabsf(a.z),
- fabsf(a.w));
-#endif
+# ifdef __KERNEL_SSE__
+ return float4(_mm_and_ps(a.m128, _mm_castsi128_ps(_mm_set1_epi32(0x7fffffff))));
+# else
+ return make_float4(fabsf(a.x), fabsf(a.y), fabsf(a.z), fabsf(a.w));
+# endif
}
-#endif /* !__KERNEL_OPENCL__*/
+#endif /* !__KERNEL_OPENCL__*/
#ifdef __KERNEL_SSE__
template<size_t index_0, size_t index_1, size_t index_2, size_t index_3>
-__forceinline const float4 shuffle(const float4& b)
+__forceinline const float4 shuffle(const float4 &b)
{
- return float4(_mm_castsi128_ps(
- _mm_shuffle_epi32(_mm_castps_si128(b),
- _MM_SHUFFLE(index_3, index_2, index_1, index_0))));
+ return float4(_mm_castsi128_ps(
+ _mm_shuffle_epi32(_mm_castps_si128(b), _MM_SHUFFLE(index_3, index_2, index_1, index_0))));
}
template<size_t index_0, size_t index_1, size_t index_2, size_t index_3>
-__forceinline const float4 shuffle(const float4& a, const float4& b)
+__forceinline const float4 shuffle(const float4 &a, const float4 &b)
{
- return float4(_mm_shuffle_ps(a.m128, b.m128,
- _MM_SHUFFLE(index_3, index_2, index_1, index_0)));
+ return float4(_mm_shuffle_ps(a.m128, b.m128, _MM_SHUFFLE(index_3, index_2, index_1, index_0)));
}
-template<> __forceinline const float4 shuffle<0, 1, 0, 1>(const float4& b)
+template<> __forceinline const float4 shuffle<0, 1, 0, 1>(const float4 &b)
{
- return float4(_mm_castpd_ps(_mm_movedup_pd(_mm_castps_pd(b))));
+ return float4(_mm_castpd_ps(_mm_movedup_pd(_mm_castps_pd(b))));
}
-template<> __forceinline const float4 shuffle<0, 1, 0, 1>(const float4& a, const float4& b)
+template<> __forceinline const float4 shuffle<0, 1, 0, 1>(const float4 &a, const float4 &b)
{
- return float4(_mm_movelh_ps(a.m128, b.m128));
+ return float4(_mm_movelh_ps(a.m128, b.m128));
}
-template<> __forceinline const float4 shuffle<2, 3, 2, 3>(const float4& a, const float4& b)
+template<> __forceinline const float4 shuffle<2, 3, 2, 3>(const float4 &a, const float4 &b)
{
- return float4(_mm_movehl_ps(b.m128, a.m128));
+ return float4(_mm_movehl_ps(b.m128, a.m128));
}
# ifdef __KERNEL_SSE3__
-template<> __forceinline const float4 shuffle<0, 0, 2, 2>(const float4& b)
+template<> __forceinline const float4 shuffle<0, 0, 2, 2>(const float4 &b)
{
- return float4(_mm_moveldup_ps(b));
+ return float4(_mm_moveldup_ps(b));
}
-template<> __forceinline const float4 shuffle<1, 1, 3, 3>(const float4& b)
+template<> __forceinline const float4 shuffle<1, 1, 3, 3>(const float4 &b)
{
- return float4(_mm_movehdup_ps(b));
+ return float4(_mm_movehdup_ps(b));
}
-# endif /* __KERNEL_SSE3__ */
-#endif /* __KERNEL_SSE__ */
+# endif /* __KERNEL_SSE3__ */
+#endif /* __KERNEL_SSE__ */
#ifndef __KERNEL_GPU__
-ccl_device_inline float4 select(const int4& mask,
- const float4& a,
- const float4& b)
+ccl_device_inline float4 select(const int4 &mask, const float4 &a, const float4 &b)
{
-#ifdef __KERNEL_SSE__
- return float4(_mm_blendv_ps(b.m128, a.m128, _mm_castsi128_ps(mask.m128)));
-#else
- return make_float4((mask.x)? a.x: b.x,
- (mask.y)? a.y: b.y,
- (mask.z)? a.z: b.z,
- (mask.w)? a.w: b.w);
-#endif
+# ifdef __KERNEL_SSE__
+ return float4(_mm_blendv_ps(b.m128, a.m128, _mm_castsi128_ps(mask.m128)));
+# else
+ return make_float4(
+ (mask.x) ? a.x : b.x, (mask.y) ? a.y : b.y, (mask.z) ? a.z : b.z, (mask.w) ? a.w : b.w);
+# endif
}
-ccl_device_inline float4 mask(const int4& mask,
- const float4& a)
+ccl_device_inline float4 mask(const int4 &mask, const float4 &a)
{
- /* Replace elements of x with zero where mask isn't set. */
- return select(mask, a, make_float4(0.0f));
+ /* Replace elements of x with zero where mask isn't set. */
+ return select(mask, a, make_float4(0.0f));
}
-ccl_device_inline float4 reduce_min(const float4& a)
+ccl_device_inline float4 reduce_min(const float4 &a)
{
-#ifdef __KERNEL_SSE__
- float4 h = min(shuffle<1,0,3,2>(a), a);
- return min(shuffle<2,3,0,1>(h), h);
-#else
- return make_float4(min(min(a.x, a.y), min(a.z, a.w)));
-#endif
+# ifdef __KERNEL_SSE__
+ float4 h = min(shuffle<1, 0, 3, 2>(a), a);
+ return min(shuffle<2, 3, 0, 1>(h), h);
+# else
+ return make_float4(min(min(a.x, a.y), min(a.z, a.w)));
+# endif
}
-ccl_device_inline float4 reduce_max(const float4& a)
+ccl_device_inline float4 reduce_max(const float4 &a)
{
-#ifdef __KERNEL_SSE__
- float4 h = max(shuffle<1,0,3,2>(a), a);
- return max(shuffle<2,3,0,1>(h), h);
-#else
- return make_float4(max(max(a.x, a.y), max(a.z, a.w)));
-#endif
+# ifdef __KERNEL_SSE__
+ float4 h = max(shuffle<1, 0, 3, 2>(a), a);
+ return max(shuffle<2, 3, 0, 1>(h), h);
+# else
+ return make_float4(max(max(a.x, a.y), max(a.z, a.w)));
+# endif
}
ccl_device_inline float4 load_float4(const float *v)
{
-#ifdef __KERNEL_SSE__
- return float4(_mm_loadu_ps(v));
-#else
- return make_float4(v[0], v[1], v[2], v[3]);
-#endif
+# ifdef __KERNEL_SSE__
+ return float4(_mm_loadu_ps(v));
+# else
+ return make_float4(v[0], v[1], v[2], v[3]);
+# endif
}
-#endif /* !__KERNEL_GPU__ */
+#endif /* !__KERNEL_GPU__ */
CCL_NAMESPACE_END
-#endif /* __UTIL_MATH_FLOAT4_H__ */
+#endif /* __UTIL_MATH_FLOAT4_H__ */
diff --git a/intern/cycles/util/util_math_int2.h b/intern/cycles/util/util_math_int2.h
index dd401d9a091..0295cd51f7e 100644
--- a/intern/cycles/util/util_math_int2.h
+++ b/intern/cycles/util/util_math_int2.h
@@ -34,7 +34,7 @@ ccl_device_inline int2 operator+=(int2 &a, const int2 &b);
ccl_device_inline int2 operator-(const int2 &a, const int2 &b);
ccl_device_inline int2 operator*(const int2 &a, const int2 &b);
ccl_device_inline int2 operator/(const int2 &a, const int2 &b);
-#endif /* !__KERNEL_OPENCL__ */
+#endif /* !__KERNEL_OPENCL__ */
/*******************************************************************************
* Definition.
@@ -43,35 +43,35 @@ ccl_device_inline int2 operator/(const int2 &a, const int2 &b);
#ifndef __KERNEL_OPENCL__
ccl_device_inline bool operator==(const int2 a, const int2 b)
{
- return (a.x == b.x && a.y == b.y);
+ return (a.x == b.x && a.y == b.y);
}
ccl_device_inline int2 operator+(const int2 &a, const int2 &b)
{
- return make_int2(a.x + b.x, a.y + b.y);
+ return make_int2(a.x + b.x, a.y + b.y);
}
ccl_device_inline int2 operator+=(int2 &a, const int2 &b)
{
- return a = a + b;
+ return a = a + b;
}
ccl_device_inline int2 operator-(const int2 &a, const int2 &b)
{
- return make_int2(a.x - b.x, a.y - b.y);
+ return make_int2(a.x - b.x, a.y - b.y);
}
ccl_device_inline int2 operator*(const int2 &a, const int2 &b)
{
- return make_int2(a.x * b.x, a.y * b.y);
+ return make_int2(a.x * b.x, a.y * b.y);
}
ccl_device_inline int2 operator/(const int2 &a, const int2 &b)
{
- return make_int2(a.x / b.x, a.y / b.y);
+ return make_int2(a.x / b.x, a.y / b.y);
}
-#endif /* !__KERNEL_OPENCL__ */
+#endif /* !__KERNEL_OPENCL__ */
CCL_NAMESPACE_END
-#endif /* __UTIL_MATH_INT2_H__ */
+#endif /* __UTIL_MATH_INT2_H__ */
diff --git a/intern/cycles/util/util_math_int3.h b/intern/cycles/util/util_math_int3.h
index 2f4752f90f1..d92ed895dc2 100644
--- a/intern/cycles/util/util_math_int3.h
+++ b/intern/cycles/util/util_math_int3.h
@@ -30,9 +30,9 @@ CCL_NAMESPACE_BEGIN
#ifndef __KERNEL_OPENCL__
ccl_device_inline int3 min(int3 a, int3 b);
ccl_device_inline int3 max(int3 a, int3 b);
-ccl_device_inline int3 clamp(const int3& a, int mn, int mx);
-ccl_device_inline int3 clamp(const int3& a, int3& mn, int mx);
-#endif /* !__KERNEL_OPENCL__ */
+ccl_device_inline int3 clamp(const int3 &a, int mn, int mx);
+ccl_device_inline int3 clamp(const int3 &a, int3 &mn, int mx);
+#endif /* !__KERNEL_OPENCL__ */
/*******************************************************************************
* Definition.
@@ -41,76 +41,74 @@ ccl_device_inline int3 clamp(const int3& a, int3& mn, int mx);
#ifndef __KERNEL_OPENCL__
ccl_device_inline int3 min(int3 a, int3 b)
{
-#if defined(__KERNEL_SSE__) && defined(__KERNEL_SSE41__)
- return int3(_mm_min_epi32(a.m128, b.m128));
-#else
- return make_int3(min(a.x, b.x), min(a.y, b.y), min(a.z, b.z));
-#endif
+# if defined(__KERNEL_SSE__) && defined(__KERNEL_SSE41__)
+ return int3(_mm_min_epi32(a.m128, b.m128));
+# else
+ return make_int3(min(a.x, b.x), min(a.y, b.y), min(a.z, b.z));
+# endif
}
ccl_device_inline int3 max(int3 a, int3 b)
{
-#if defined(__KERNEL_SSE__) && defined(__KERNEL_SSE41__)
- return int3(_mm_max_epi32(a.m128, b.m128));
-#else
- return make_int3(max(a.x, b.x), max(a.y, b.y), max(a.z, b.z));
-#endif
+# if defined(__KERNEL_SSE__) && defined(__KERNEL_SSE41__)
+ return int3(_mm_max_epi32(a.m128, b.m128));
+# else
+ return make_int3(max(a.x, b.x), max(a.y, b.y), max(a.z, b.z));
+# endif
}
-ccl_device_inline int3 clamp(const int3& a, int mn, int mx)
+ccl_device_inline int3 clamp(const int3 &a, int mn, int mx)
{
-#ifdef __KERNEL_SSE__
- return min(max(a, make_int3(mn)), make_int3(mx));
-#else
- return make_int3(clamp(a.x, mn, mx), clamp(a.y, mn, mx), clamp(a.z, mn, mx));
-#endif
+# ifdef __KERNEL_SSE__
+ return min(max(a, make_int3(mn)), make_int3(mx));
+# else
+ return make_int3(clamp(a.x, mn, mx), clamp(a.y, mn, mx), clamp(a.z, mn, mx));
+# endif
}
-ccl_device_inline int3 clamp(const int3& a, int3& mn, int mx)
+ccl_device_inline int3 clamp(const int3 &a, int3 &mn, int mx)
{
-#ifdef __KERNEL_SSE__
- return min(max(a, mn), make_int3(mx));
-#else
- return make_int3(clamp(a.x, mn.x, mx),
- clamp(a.y, mn.y, mx),
- clamp(a.z, mn.z, mx));
-#endif
+# ifdef __KERNEL_SSE__
+ return min(max(a, mn), make_int3(mx));
+# else
+ return make_int3(clamp(a.x, mn.x, mx), clamp(a.y, mn.y, mx), clamp(a.z, mn.z, mx));
+# endif
}
ccl_device_inline bool operator==(const int3 &a, const int3 &b)
{
- return a.x == b.x && a.y == b.y && a.z == b.z;
+ return a.x == b.x && a.y == b.y && a.z == b.z;
}
ccl_device_inline bool operator!=(const int3 &a, const int3 &b)
{
- return !(a == b);
+ return !(a == b);
}
ccl_device_inline bool operator<(const int3 &a, const int3 &b)
{
- return a.x < b.x && a.y < b.y && a.z < b.z;
+ return a.x < b.x && a.y < b.y && a.z < b.z;
}
ccl_device_inline int3 operator+(const int3 &a, const int3 &b)
{
-#ifdef __KERNEL_SSE__
- return int3(_mm_add_epi32(a.m128, b.m128));
-#else
- return make_int3(a.x + b.x, a.y + b.y, a.z + b.z);
-#endif
+# ifdef __KERNEL_SSE__
+ return int3(_mm_add_epi32(a.m128, b.m128));
+# else
+ return make_int3(a.x + b.x, a.y + b.y, a.z + b.z);
+# endif
}
ccl_device_inline int3 operator-(const int3 &a, const int3 &b)
{
-#ifdef __KERNEL_SSE__
- return int3(_mm_sub_epi32(a.m128, b.m128));
-#else
- return make_int3(a.x - b.x, a.y - b.y, a.z - b.z);
-#endif
+# ifdef __KERNEL_SSE__
+ return int3(_mm_sub_epi32(a.m128, b.m128));
+# else
+ return make_int3(a.x - b.x, a.y - b.y, a.z - b.z);
+# endif
}
-#endif /* !__KERNEL_OPENCL__ */
+#endif /* !__KERNEL_OPENCL__ */
CCL_NAMESPACE_END
-#endif /* __UTIL_MATH_INT3_H__ */
+#endif /* __UTIL_MATH_INT3_H__ */
diff --git a/intern/cycles/util/util_math_int4.h b/intern/cycles/util/util_math_int4.h
index 763c42318d5..186cc58489b 100644
--- a/intern/cycles/util/util_math_int4.h
+++ b/intern/cycles/util/util_math_int4.h
@@ -28,132 +28,129 @@ CCL_NAMESPACE_BEGIN
*/
#ifndef __KERNEL_GPU__
-ccl_device_inline int4 operator+(const int4& a, const int4& b);
-ccl_device_inline int4 operator+=(int4& a, const int4& b);
-ccl_device_inline int4 operator>>(const int4& a, int i);
-ccl_device_inline int4 operator<<(const int4& a, int i);
-ccl_device_inline int4 operator<(const int4& a, const int4& b);
-ccl_device_inline int4 operator>=(const int4& a, const int4& b);
-ccl_device_inline int4 operator&(const int4& a, const int4& b);
+ccl_device_inline int4 operator+(const int4 &a, const int4 &b);
+ccl_device_inline int4 operator+=(int4 &a, const int4 &b);
+ccl_device_inline int4 operator>>(const int4 &a, int i);
+ccl_device_inline int4 operator<<(const int4 &a, int i);
+ccl_device_inline int4 operator<(const int4 &a, const int4 &b);
+ccl_device_inline int4 operator>=(const int4 &a, const int4 &b);
+ccl_device_inline int4 operator&(const int4 &a, const int4 &b);
ccl_device_inline int4 min(int4 a, int4 b);
ccl_device_inline int4 max(int4 a, int4 b);
-ccl_device_inline int4 clamp(const int4& a, const int4& mn, const int4& mx);
-ccl_device_inline int4 select(const int4& mask, const int4& a, const int4& b);
-#endif /* __KERNEL_GPU__ */
+ccl_device_inline int4 clamp(const int4 &a, const int4 &mn, const int4 &mx);
+ccl_device_inline int4 select(const int4 &mask, const int4 &a, const int4 &b);
+#endif /* __KERNEL_GPU__ */
/*******************************************************************************
* Definition.
*/
#ifndef __KERNEL_GPU__
-ccl_device_inline int4 operator+(const int4& a, const int4& b)
+ccl_device_inline int4 operator+(const int4 &a, const int4 &b)
{
-#ifdef __KERNEL_SSE__
- return int4(_mm_add_epi32(a.m128, b.m128));
-#else
- return make_int4(a.x+b.x, a.y+b.y, a.z+b.z, a.w+b.w);
-#endif
+# ifdef __KERNEL_SSE__
+ return int4(_mm_add_epi32(a.m128, b.m128));
+# else
+ return make_int4(a.x + b.x, a.y + b.y, a.z + b.z, a.w + b.w);
+# endif
}
-ccl_device_inline int4 operator+=(int4& a, const int4& b)
+ccl_device_inline int4 operator+=(int4 &a, const int4 &b)
{
- return a = a + b;
+ return a = a + b;
}
-ccl_device_inline int4 operator>>(const int4& a, int i)
+ccl_device_inline int4 operator>>(const int4 &a, int i)
{
-#ifdef __KERNEL_SSE__
- return int4(_mm_srai_epi32(a.m128, i));
-#else
- return make_int4(a.x >> i, a.y >> i, a.z >> i, a.w >> i);
-#endif
+# ifdef __KERNEL_SSE__
+ return int4(_mm_srai_epi32(a.m128, i));
+# else
+ return make_int4(a.x >> i, a.y >> i, a.z >> i, a.w >> i);
+# endif
}
-ccl_device_inline int4 operator<<(const int4& a, int i)
+ccl_device_inline int4 operator<<(const int4 &a, int i)
{
-#ifdef __KERNEL_SSE__
- return int4(_mm_slli_epi32(a.m128, i));
-#else
- return make_int4(a.x << i, a.y << i, a.z << i, a.w << i);
-#endif
+# ifdef __KERNEL_SSE__
+ return int4(_mm_slli_epi32(a.m128, i));
+# else
+ return make_int4(a.x << i, a.y << i, a.z << i, a.w << i);
+# endif
}
-ccl_device_inline int4 operator<(const int4& a, const int4& b)
+ccl_device_inline int4 operator<(const int4 &a, const int4 &b)
{
-#ifdef __KERNEL_SSE__
- return int4(_mm_cmplt_epi32(a.m128, b.m128));
-#else
- return make_int4(a.x < b.x, a.y < b.y, a.z < b.z, a.w < b.w);
-#endif
+# ifdef __KERNEL_SSE__
+ return int4(_mm_cmplt_epi32(a.m128, b.m128));
+# else
+ return make_int4(a.x < b.x, a.y < b.y, a.z < b.z, a.w < b.w);
+# endif
}
-ccl_device_inline int4 operator>=(const int4& a, const int4& b)
+ccl_device_inline int4 operator>=(const int4 &a, const int4 &b)
{
-#ifdef __KERNEL_SSE__
- return int4(_mm_xor_si128(_mm_set1_epi32(0xffffffff), _mm_cmplt_epi32(a.m128, b.m128)));
-#else
- return make_int4(a.x >= b.x, a.y >= b.y, a.z >= b.z, a.w >= b.w);
-#endif
+# ifdef __KERNEL_SSE__
+ return int4(_mm_xor_si128(_mm_set1_epi32(0xffffffff), _mm_cmplt_epi32(a.m128, b.m128)));
+# else
+ return make_int4(a.x >= b.x, a.y >= b.y, a.z >= b.z, a.w >= b.w);
+# endif
}
-ccl_device_inline int4 operator&(const int4& a, const int4& b)
+ccl_device_inline int4 operator&(const int4 &a, const int4 &b)
{
-#ifdef __KERNEL_SSE__
- return int4(_mm_and_si128(a.m128, b.m128));
-#else
- return make_int4(a.x & b.x, a.y & b.y, a.z & b.z, a.w & b.w);
-#endif
+# ifdef __KERNEL_SSE__
+ return int4(_mm_and_si128(a.m128, b.m128));
+# else
+ return make_int4(a.x & b.x, a.y & b.y, a.z & b.z, a.w & b.w);
+# endif
}
ccl_device_inline int4 min(int4 a, int4 b)
{
-#if defined(__KERNEL_SSE__) && defined(__KERNEL_SSE41__)
- return int4(_mm_min_epi32(a.m128, b.m128));
-#else
- return make_int4(min(a.x, b.x), min(a.y, b.y), min(a.z, b.z), min(a.w, b.w));
-#endif
+# if defined(__KERNEL_SSE__) && defined(__KERNEL_SSE41__)
+ return int4(_mm_min_epi32(a.m128, b.m128));
+# else
+ return make_int4(min(a.x, b.x), min(a.y, b.y), min(a.z, b.z), min(a.w, b.w));
+# endif
}
ccl_device_inline int4 max(int4 a, int4 b)
{
-#if defined(__KERNEL_SSE__) && defined(__KERNEL_SSE41__)
- return int4(_mm_max_epi32(a.m128, b.m128));
-#else
- return make_int4(max(a.x, b.x), max(a.y, b.y), max(a.z, b.z), max(a.w, b.w));
-#endif
+# if defined(__KERNEL_SSE__) && defined(__KERNEL_SSE41__)
+ return int4(_mm_max_epi32(a.m128, b.m128));
+# else
+ return make_int4(max(a.x, b.x), max(a.y, b.y), max(a.z, b.z), max(a.w, b.w));
+# endif
}
-ccl_device_inline int4 clamp(const int4& a, const int4& mn, const int4& mx)
+ccl_device_inline int4 clamp(const int4 &a, const int4 &mn, const int4 &mx)
{
- return min(max(a, mn), mx);
+ return min(max(a, mn), mx);
}
-ccl_device_inline int4 select(const int4& mask, const int4& a, const int4& b)
+ccl_device_inline int4 select(const int4 &mask, const int4 &a, const int4 &b)
{
-#ifdef __KERNEL_SSE__
- const __m128 m = _mm_cvtepi32_ps(mask);
- /* TODO(sergey): avoid cvt. */
- return int4(_mm_castps_si128(
- _mm_or_ps(_mm_and_ps(m, _mm_castsi128_ps(a)),
- _mm_andnot_ps(m, _mm_castsi128_ps(b)))));
-#else
- return make_int4((mask.x)? a.x: b.x,
- (mask.y)? a.y: b.y,
- (mask.z)? a.z: b.z,
- (mask.w)? a.w: b.w);
-#endif
+# ifdef __KERNEL_SSE__
+ const __m128 m = _mm_cvtepi32_ps(mask);
+ /* TODO(sergey): avoid cvt. */
+ return int4(_mm_castps_si128(
+ _mm_or_ps(_mm_and_ps(m, _mm_castsi128_ps(a)), _mm_andnot_ps(m, _mm_castsi128_ps(b)))));
+# else
+ return make_int4(
+ (mask.x) ? a.x : b.x, (mask.y) ? a.y : b.y, (mask.z) ? a.z : b.z, (mask.w) ? a.w : b.w);
+# endif
}
ccl_device_inline int4 load_int4(const int *v)
{
-#ifdef __KERNEL_SSE__
- return int4(_mm_loadu_si128((__m128i*)v));
-#else
- return make_int4(v[0], v[1], v[2], v[3]);
-#endif
+# ifdef __KERNEL_SSE__
+ return int4(_mm_loadu_si128((__m128i *)v));
+# else
+ return make_int4(v[0], v[1], v[2], v[3]);
+# endif
}
-#endif /* __KERNEL_GPU__ */
+#endif /* __KERNEL_GPU__ */
CCL_NAMESPACE_END
-#endif /* __UTIL_MATH_INT4_H__ */
+#endif /* __UTIL_MATH_INT4_H__ */
diff --git a/intern/cycles/util/util_math_intersect.h b/intern/cycles/util/util_math_intersect.h
index aa75783d378..95ac231c611 100644
--- a/intern/cycles/util/util_math_intersect.h
+++ b/intern/cycles/util/util_math_intersect.h
@@ -21,167 +21,175 @@ CCL_NAMESPACE_BEGIN
/* Ray Intersection */
-ccl_device bool ray_sphere_intersect(
- float3 ray_P, float3 ray_D, float ray_t,
- float3 sphere_P, float sphere_radius,
- float3 *isect_P, float *isect_t)
+ccl_device bool ray_sphere_intersect(float3 ray_P,
+ float3 ray_D,
+ float ray_t,
+ float3 sphere_P,
+ float sphere_radius,
+ float3 *isect_P,
+ float *isect_t)
{
- const float3 d = sphere_P - ray_P;
- const float radiussq = sphere_radius*sphere_radius;
- const float tsq = dot(d, d);
-
- if(tsq > radiussq) {
- /* Ray origin outside sphere. */
- const float tp = dot(d, ray_D);
- if(tp < 0.0f) {
- /* Ray points away from sphere. */
- return false;
- }
- const float dsq = tsq - tp*tp; /* pythagoras */
- if(dsq > radiussq) {
- /* Closest point on ray outside sphere. */
- return false;
- }
- const float t = tp - sqrtf(radiussq - dsq); /* pythagoras */
- if(t < ray_t) {
- *isect_t = t;
- *isect_P = ray_P + ray_D*t;
- return true;
- }
- }
- return false;
+ const float3 d = sphere_P - ray_P;
+ const float radiussq = sphere_radius * sphere_radius;
+ const float tsq = dot(d, d);
+
+ if (tsq > radiussq) {
+ /* Ray origin outside sphere. */
+ const float tp = dot(d, ray_D);
+ if (tp < 0.0f) {
+ /* Ray points away from sphere. */
+ return false;
+ }
+ const float dsq = tsq - tp * tp; /* pythagoras */
+ if (dsq > radiussq) {
+ /* Closest point on ray outside sphere. */
+ return false;
+ }
+ const float t = tp - sqrtf(radiussq - dsq); /* pythagoras */
+ if (t < ray_t) {
+ *isect_t = t;
+ *isect_P = ray_P + ray_D * t;
+ return true;
+ }
+ }
+ return false;
}
-ccl_device bool ray_aligned_disk_intersect(
- float3 ray_P, float3 ray_D, float ray_t,
- float3 disk_P, float disk_radius,
- float3 *isect_P, float *isect_t)
+ccl_device bool ray_aligned_disk_intersect(float3 ray_P,
+ float3 ray_D,
+ float ray_t,
+ float3 disk_P,
+ float disk_radius,
+ float3 *isect_P,
+ float *isect_t)
{
- /* Aligned disk normal. */
- float disk_t;
- const float3 disk_N = normalize_len(ray_P - disk_P, &disk_t);
- const float div = dot(ray_D, disk_N);
- if(UNLIKELY(div == 0.0f)) {
- return false;
- }
- /* Compute t to intersection point. */
- const float t = -disk_t/div;
- if(t < 0.0f || t > ray_t) {
- return false;
- }
- /* Test if within radius. */
- float3 P = ray_P + ray_D*t;
- if(len_squared(P - disk_P) > disk_radius*disk_radius) {
- return false;
- }
- *isect_P = P;
- *isect_t = t;
- return true;
+ /* Aligned disk normal. */
+ float disk_t;
+ const float3 disk_N = normalize_len(ray_P - disk_P, &disk_t);
+ const float div = dot(ray_D, disk_N);
+ if (UNLIKELY(div == 0.0f)) {
+ return false;
+ }
+ /* Compute t to intersection point. */
+ const float t = -disk_t / div;
+ if (t < 0.0f || t > ray_t) {
+ return false;
+ }
+ /* Test if within radius. */
+ float3 P = ray_P + ray_D * t;
+ if (len_squared(P - disk_P) > disk_radius * disk_radius) {
+ return false;
+ }
+ *isect_P = P;
+ *isect_t = t;
+ return true;
}
-ccl_device_forceinline bool ray_triangle_intersect(
- float3 ray_P, float3 ray_dir, float ray_t,
+ccl_device_forceinline bool ray_triangle_intersect(float3 ray_P,
+ float3 ray_dir,
+ float ray_t,
#if defined(__KERNEL_SSE2__) && defined(__KERNEL_SSE__)
- const ssef *ssef_verts,
+ const ssef *ssef_verts,
#else
- const float3 tri_a, const float3 tri_b, const float3 tri_c,
+ const float3 tri_a,
+ const float3 tri_b,
+ const float3 tri_c,
#endif
- float *isect_u, float *isect_v, float *isect_t)
+ float *isect_u,
+ float *isect_v,
+ float *isect_t)
{
#if defined(__KERNEL_SSE2__) && defined(__KERNEL_SSE__)
- typedef ssef float3;
- const float3 tri_a(ssef_verts[0]);
- const float3 tri_b(ssef_verts[1]);
- const float3 tri_c(ssef_verts[2]);
- const float3 P(ray_P);
- const float3 dir(ray_dir);
+ typedef ssef float3;
+ const float3 tri_a(ssef_verts[0]);
+ const float3 tri_b(ssef_verts[1]);
+ const float3 tri_c(ssef_verts[2]);
+ const float3 P(ray_P);
+ const float3 dir(ray_dir);
#else
# define dot3(a, b) dot(a, b)
- const float3 P = ray_P;
- const float3 dir = ray_dir;
+ const float3 P = ray_P;
+ const float3 dir = ray_dir;
#endif
- /* Calculate vertices relative to ray origin. */
- const float3 v0 = tri_c - P;
- const float3 v1 = tri_a - P;
- const float3 v2 = tri_b - P;
-
- /* Calculate triangle edges. */
- const float3 e0 = v2 - v0;
- const float3 e1 = v0 - v1;
- const float3 e2 = v1 - v2;
-
- /* Perform edge tests. */
-#if defined(__KERNEL_SSE2__) && defined (__KERNEL_SSE__)
- const float3 crossU = cross(v2 + v0, e0);
- const float3 crossV = cross(v0 + v1, e1);
- const float3 crossW = cross(v1 + v2, e2);
-
- ssef crossX(crossU);
- ssef crossY(crossV);
- ssef crossZ(crossW);
- ssef zero = _mm_setzero_ps();
- _MM_TRANSPOSE4_PS(crossX, crossY, crossZ, zero);
-
- const ssef dirX(ray_dir.x);
- const ssef dirY(ray_dir.y);
- const ssef dirZ(ray_dir.z);
-
- ssef UVWW = madd(crossX, dirX, madd(crossY, dirY, crossZ * dirZ));
+ /* Calculate vertices relative to ray origin. */
+ const float3 v0 = tri_c - P;
+ const float3 v1 = tri_a - P;
+ const float3 v2 = tri_b - P;
+
+ /* Calculate triangle edges. */
+ const float3 e0 = v2 - v0;
+ const float3 e1 = v0 - v1;
+ const float3 e2 = v1 - v2;
+
+ /* Perform edge tests. */
+#if defined(__KERNEL_SSE2__) && defined(__KERNEL_SSE__)
+ const float3 crossU = cross(v2 + v0, e0);
+ const float3 crossV = cross(v0 + v1, e1);
+ const float3 crossW = cross(v1 + v2, e2);
+
+ ssef crossX(crossU);
+ ssef crossY(crossV);
+ ssef crossZ(crossW);
+ ssef zero = _mm_setzero_ps();
+ _MM_TRANSPOSE4_PS(crossX, crossY, crossZ, zero);
+
+ const ssef dirX(ray_dir.x);
+ const ssef dirY(ray_dir.y);
+ const ssef dirZ(ray_dir.z);
+
+ ssef UVWW = madd(crossX, dirX, madd(crossY, dirY, crossZ * dirZ));
#else /* __KERNEL_SSE2__ */
- const float U = dot(cross(v2 + v0, e0), ray_dir);
- const float V = dot(cross(v0 + v1, e1), ray_dir);
- const float W = dot(cross(v1 + v2, e2), ray_dir);
-#endif /* __KERNEL_SSE2__ */
-
-#if defined(__KERNEL_SSE2__) && defined (__KERNEL_SSE__)
- int uvw_sign = movemask(UVWW) & 0x7;
- if(uvw_sign != 0) {
- if(uvw_sign != 0x7) {
- return false;
- }
- }
+ const float U = dot(cross(v2 + v0, e0), ray_dir);
+ const float V = dot(cross(v0 + v1, e1), ray_dir);
+ const float W = dot(cross(v1 + v2, e2), ray_dir);
+#endif /* __KERNEL_SSE2__ */
+
+#if defined(__KERNEL_SSE2__) && defined(__KERNEL_SSE__)
+ int uvw_sign = movemask(UVWW) & 0x7;
+ if (uvw_sign != 0) {
+ if (uvw_sign != 0x7) {
+ return false;
+ }
+ }
#else
- const float minUVW = min(U, min(V, W));
- const float maxUVW = max(U, max(V, W));
+ const float minUVW = min(U, min(V, W));
+ const float maxUVW = max(U, max(V, W));
- if(minUVW < 0.0f && maxUVW > 0.0f) {
- return false;
- }
+ if (minUVW < 0.0f && maxUVW > 0.0f) {
+ return false;
+ }
#endif
-
- /* Calculate geometry normal and denominator. */
- const float3 Ng1 = cross(e1, e0);
- //const Vec3vfM Ng1 = stable_triangle_normal(e2,e1,e0);
- const float3 Ng = Ng1 + Ng1;
- const float den = dot3(Ng, dir);
- /* Avoid division by 0. */
- if(UNLIKELY(den == 0.0f)) {
- return false;
- }
-
- /* Perform depth test. */
- const float T = dot3(v0, Ng);
- const int sign_den = (__float_as_int(den) & 0x80000000);
- const float sign_T = xor_signmask(T, sign_den);
- if((sign_T < 0.0f) ||
- (sign_T > ray_t * xor_signmask(den, sign_den)))
- {
- return false;
- }
-
- const float inv_den = 1.0f / den;
-#if defined(__KERNEL_SSE2__) && defined (__KERNEL_SSE__)
- UVWW *= inv_den;
- _mm_store_ss(isect_u, UVWW);
- _mm_store_ss(isect_v, shuffle<1,1,3,3>(UVWW));
+ /* Calculate geometry normal and denominator. */
+ const float3 Ng1 = cross(e1, e0);
+ //const Vec3vfM Ng1 = stable_triangle_normal(e2,e1,e0);
+ const float3 Ng = Ng1 + Ng1;
+ const float den = dot3(Ng, dir);
+ /* Avoid division by 0. */
+ if (UNLIKELY(den == 0.0f)) {
+ return false;
+ }
+
+ /* Perform depth test. */
+ const float T = dot3(v0, Ng);
+ const int sign_den = (__float_as_int(den) & 0x80000000);
+ const float sign_T = xor_signmask(T, sign_den);
+ if ((sign_T < 0.0f) || (sign_T > ray_t * xor_signmask(den, sign_den))) {
+ return false;
+ }
+
+ const float inv_den = 1.0f / den;
+#if defined(__KERNEL_SSE2__) && defined(__KERNEL_SSE__)
+ UVWW *= inv_den;
+ _mm_store_ss(isect_u, UVWW);
+ _mm_store_ss(isect_v, shuffle<1, 1, 3, 3>(UVWW));
#else
- *isect_u = U * inv_den;
- *isect_v = V * inv_den;
+ *isect_u = U * inv_den;
+ *isect_v = V * inv_den;
#endif
- *isect_t = T * inv_den;
- return true;
+ *isect_t = T * inv_den;
+ return true;
#undef dot3
}
@@ -191,40 +199,51 @@ ccl_device_forceinline bool ray_triangle_intersect(
* If ellipse is true, hits outside the ellipse that's enclosed by the
* quad are rejected.
*/
-ccl_device bool ray_quad_intersect(float3 ray_P, float3 ray_D,
- float ray_mint, float ray_maxt,
+ccl_device bool ray_quad_intersect(float3 ray_P,
+ float3 ray_D,
+ float ray_mint,
+ float ray_maxt,
float3 quad_P,
- float3 quad_u, float3 quad_v, float3 quad_n,
- float3 *isect_P, float *isect_t,
- float *isect_u, float *isect_v, bool ellipse)
+ float3 quad_u,
+ float3 quad_v,
+ float3 quad_n,
+ float3 *isect_P,
+ float *isect_t,
+ float *isect_u,
+ float *isect_v,
+ bool ellipse)
{
- /* Perform intersection test. */
- float t = -(dot(ray_P, quad_n) - dot(quad_P, quad_n)) / dot(ray_D, quad_n);
- if(t < ray_mint || t > ray_maxt) {
- return false;
- }
- const float3 hit = ray_P + t*ray_D;
- const float3 inplane = hit - quad_P;
- const float u = dot(inplane, quad_u) / dot(quad_u, quad_u);
- if(u < -0.5f || u > 0.5f) {
- return false;
- }
- const float v = dot(inplane, quad_v) / dot(quad_v, quad_v);
- if(v < -0.5f || v > 0.5f) {
- return false;
- }
- if(ellipse && (u*u + v*v > 0.25f)) {
- return false;
- }
- /* Store the result. */
- /* TODO(sergey): Check whether we can avoid some checks here. */
- if(isect_P != NULL) *isect_P = hit;
- if(isect_t != NULL) *isect_t = t;
- if(isect_u != NULL) *isect_u = u + 0.5f;
- if(isect_v != NULL) *isect_v = v + 0.5f;
- return true;
+ /* Perform intersection test. */
+ float t = -(dot(ray_P, quad_n) - dot(quad_P, quad_n)) / dot(ray_D, quad_n);
+ if (t < ray_mint || t > ray_maxt) {
+ return false;
+ }
+ const float3 hit = ray_P + t * ray_D;
+ const float3 inplane = hit - quad_P;
+ const float u = dot(inplane, quad_u) / dot(quad_u, quad_u);
+ if (u < -0.5f || u > 0.5f) {
+ return false;
+ }
+ const float v = dot(inplane, quad_v) / dot(quad_v, quad_v);
+ if (v < -0.5f || v > 0.5f) {
+ return false;
+ }
+ if (ellipse && (u * u + v * v > 0.25f)) {
+ return false;
+ }
+ /* Store the result. */
+ /* TODO(sergey): Check whether we can avoid some checks here. */
+ if (isect_P != NULL)
+ *isect_P = hit;
+ if (isect_t != NULL)
+ *isect_t = t;
+ if (isect_u != NULL)
+ *isect_u = u + 0.5f;
+ if (isect_v != NULL)
+ *isect_v = v + 0.5f;
+ return true;
}
CCL_NAMESPACE_END
-#endif /* __UTIL_MATH_INTERSECT_H__ */
+#endif /* __UTIL_MATH_INTERSECT_H__ */
diff --git a/intern/cycles/util/util_math_matrix.h b/intern/cycles/util/util_math_matrix.h
index 9ffcb9659b2..fe80fab6ebd 100644
--- a/intern/cycles/util/util_math_matrix.h
+++ b/intern/cycles/util/util_math_matrix.h
@@ -19,17 +19,17 @@
CCL_NAMESPACE_BEGIN
-#define MAT(A, size, row, col) A[(row)*(size)+(col)]
+#define MAT(A, size, row, col) A[(row) * (size) + (col)]
/* Variants that use a constant stride on GPUS. */
#ifdef __KERNEL_GPU__
-# define MATS(A, n, r, c, s) A[((r)*(n)+(c))*(s)]
+# define MATS(A, n, r, c, s) A[((r) * (n) + (c)) * (s)]
/* Element access when only the lower-triangular elements are stored. */
-# define MATHS(A, r, c, s) A[((r)*((r)+1)/2+(c))*(s)]
-# define VECS(V, i, s) V[(i)*(s)]
+# define MATHS(A, r, c, s) A[((r) * ((r) + 1) / 2 + (c)) * (s)]
+# define VECS(V, i, s) V[(i) * (s)]
#else
# define MATS(A, n, r, c, s) MAT(A, n, r, c)
-# define MATHS(A, r, c, s) A[(r)*((r)+1)/2+(c)]
+# define MATHS(A, r, c, s) A[(r) * ((r) + 1) / 2 + (c)]
# define VECS(V, i, s) V[i]
#endif
@@ -37,111 +37,115 @@ CCL_NAMESPACE_BEGIN
ccl_device_inline void math_vector_zero(float *v, int n)
{
- for(int i = 0; i < n; i++) {
- v[i] = 0.0f;
- }
+ for (int i = 0; i < n; i++) {
+ v[i] = 0.0f;
+ }
}
ccl_device_inline void math_matrix_zero(float *A, int n)
{
- for(int row = 0; row < n; row++) {
- for(int col = 0; col <= row; col++) {
- MAT(A, n, row, col) = 0.0f;
- }
- }
+ for (int row = 0; row < n; row++) {
+ for (int col = 0; col <= row; col++) {
+ MAT(A, n, row, col) = 0.0f;
+ }
+ }
}
/* Elementary vector operations. */
ccl_device_inline void math_vector_add(float *a, const float *ccl_restrict b, int n)
{
- for(int i = 0; i < n; i++) {
- a[i] += b[i];
- }
+ for (int i = 0; i < n; i++) {
+ a[i] += b[i];
+ }
}
ccl_device_inline void math_vector_mul(float *a, const float *ccl_restrict b, int n)
{
- for(int i = 0; i < n; i++) {
- a[i] *= b[i];
- }
+ for (int i = 0; i < n; i++) {
+ a[i] *= b[i];
+ }
}
-ccl_device_inline void math_vector_mul_strided(ccl_global float *a, const float *ccl_restrict b, int astride, int n)
+ccl_device_inline void math_vector_mul_strided(ccl_global float *a,
+ const float *ccl_restrict b,
+ int astride,
+ int n)
{
- for(int i = 0; i < n; i++) {
- a[i*astride] *= b[i];
- }
+ for (int i = 0; i < n; i++) {
+ a[i * astride] *= b[i];
+ }
}
ccl_device_inline void math_vector_scale(float *a, float b, int n)
{
- for(int i = 0; i < n; i++) {
- a[i] *= b;
- }
+ for (int i = 0; i < n; i++) {
+ a[i] *= b;
+ }
}
ccl_device_inline void math_vector_max(float *a, const float *ccl_restrict b, int n)
{
- for(int i = 0; i < n; i++) {
- a[i] = max(a[i], b[i]);
- }
+ for (int i = 0; i < n; i++) {
+ a[i] = max(a[i], b[i]);
+ }
}
ccl_device_inline void math_vec3_add(float3 *v, int n, float *x, float3 w)
{
- for(int i = 0; i < n; i++) {
- v[i] += w*x[i];
- }
+ for (int i = 0; i < n; i++) {
+ v[i] += w * x[i];
+ }
}
-ccl_device_inline void math_vec3_add_strided(ccl_global float3 *v, int n, float *x, float3 w, int stride)
+ccl_device_inline void math_vec3_add_strided(
+ ccl_global float3 *v, int n, float *x, float3 w, int stride)
{
- for(int i = 0; i < n; i++) {
- ccl_global float *elem = (ccl_global float*) (v + i*stride);
- atomic_add_and_fetch_float(elem+0, w.x*x[i]);
- atomic_add_and_fetch_float(elem+1, w.y*x[i]);
- atomic_add_and_fetch_float(elem+2, w.z*x[i]);
- }
+ for (int i = 0; i < n; i++) {
+ ccl_global float *elem = (ccl_global float *)(v + i * stride);
+ atomic_add_and_fetch_float(elem + 0, w.x * x[i]);
+ atomic_add_and_fetch_float(elem + 1, w.y * x[i]);
+ atomic_add_and_fetch_float(elem + 2, w.z * x[i]);
+ }
}
/* Elementary matrix operations.
* Note: TriMatrix refers to a square matrix that is symmetric, and therefore its upper-triangular part isn't stored. */
-ccl_device_inline void math_trimatrix_add_diagonal(ccl_global float *A, int n, float val, int stride)
+ccl_device_inline void math_trimatrix_add_diagonal(ccl_global float *A,
+ int n,
+ float val,
+ int stride)
{
- for(int row = 0; row < n; row++) {
- MATHS(A, row, row, stride) += val;
- }
+ for (int row = 0; row < n; row++) {
+ MATHS(A, row, row, stride) += val;
+ }
}
/* Add Gramian matrix of v to A.
* The Gramian matrix of v is vt*v, so element (i,j) is v[i]*v[j]. */
ccl_device_inline void math_matrix_add_gramian(float *A,
- int n,
- const float *ccl_restrict v,
- float weight)
+ int n,
+ const float *ccl_restrict v,
+ float weight)
{
- for(int row = 0; row < n; row++) {
- for(int col = 0; col <= row; col++) {
- MAT(A, n, row, col) += v[row]*v[col]*weight;
- }
- }
+ for (int row = 0; row < n; row++) {
+ for (int col = 0; col <= row; col++) {
+ MAT(A, n, row, col) += v[row] * v[col] * weight;
+ }
+ }
}
/* Add Gramian matrix of v to A.
* The Gramian matrix of v is vt*v, so element (i,j) is v[i]*v[j]. */
-ccl_device_inline void math_trimatrix_add_gramian_strided(ccl_global float *A,
- int n,
- const float *ccl_restrict v,
- float weight,
- int stride)
+ccl_device_inline void math_trimatrix_add_gramian_strided(
+ ccl_global float *A, int n, const float *ccl_restrict v, float weight, int stride)
{
- for(int row = 0; row < n; row++) {
- for(int col = 0; col <= row; col++) {
- atomic_add_and_fetch_float(&MATHS(A, row, col, stride), v[row]*v[col]*weight);
- }
- }
+ for (int row = 0; row < n; row++) {
+ for (int col = 0; col <= row; col++) {
+ atomic_add_and_fetch_float(&MATHS(A, row, col, stride), v[row] * v[col] * weight);
+ }
+ }
}
ccl_device_inline void math_trimatrix_add_gramian(ccl_global float *A,
@@ -149,23 +153,23 @@ ccl_device_inline void math_trimatrix_add_gramian(ccl_global float *A,
const float *ccl_restrict v,
float weight)
{
- for(int row = 0; row < n; row++) {
- for(int col = 0; col <= row; col++) {
- MATHS(A, row, col, 1) += v[row]*v[col]*weight;
- }
- }
+ for (int row = 0; row < n; row++) {
+ for (int col = 0; col <= row; col++) {
+ MATHS(A, row, col, 1) += v[row] * v[col] * weight;
+ }
+ }
}
/* Transpose matrix A inplace. */
ccl_device_inline void math_matrix_transpose(ccl_global float *A, int n, int stride)
{
- for(int i = 0; i < n; i++) {
- for(int j = 0; j < i; j++) {
- float temp = MATS(A, n, i, j, stride);
- MATS(A, n, i, j, stride) = MATS(A, n, j, i, stride);
- MATS(A, n, j, i, stride) = temp;
- }
- }
+ for (int i = 0; i < n; i++) {
+ for (int j = 0; j < i; j++) {
+ float temp = MATS(A, n, i, j, stride);
+ MATS(A, n, i, j, stride) = MATS(A, n, j, i, stride);
+ MATS(A, n, j, i, stride) = temp;
+ }
+ }
}
/* Solvers for matrix problems */
@@ -175,21 +179,21 @@ ccl_device_inline void math_matrix_transpose(ccl_global float *A, int n, int str
* Also, only the lower triangular part of A is ever accessed. */
ccl_device void math_trimatrix_cholesky(ccl_global float *A, int n, int stride)
{
- for(int row = 0; row < n; row++) {
- for(int col = 0; col <= row; col++) {
- float sum_col = MATHS(A, row, col, stride);
- for(int k = 0; k < col; k++) {
- sum_col -= MATHS(A, row, k, stride) * MATHS(A, col, k, stride);
- }
- if(row == col) {
- sum_col = sqrtf(max(sum_col, 0.0f));
- }
- else {
- sum_col /= MATHS(A, col, col, stride);
- }
- MATHS(A, row, col, stride) = sum_col;
- }
- }
+ for (int row = 0; row < n; row++) {
+ for (int col = 0; col <= row; col++) {
+ float sum_col = MATHS(A, row, col, stride);
+ for (int k = 0; k < col; k++) {
+ sum_col -= MATHS(A, row, k, stride) * MATHS(A, col, k, stride);
+ }
+ if (row == col) {
+ sum_col = sqrtf(max(sum_col, 0.0f));
+ }
+ else {
+ sum_col /= MATHS(A, col, col, stride);
+ }
+ MATHS(A, row, col, stride) = sum_col;
+ }
+ }
}
/* Solve A*S=y for S given A and y, where A is symmetrical positive-semidefinite and both inputs are destroyed in the process.
@@ -201,29 +205,32 @@ ccl_device void math_trimatrix_cholesky(ccl_global float *A, int n, int stride)
*
* This is useful for solving the normal equation S=inv(Xt*W*X)*Xt*W*y, since Xt*W*X is
* symmetrical positive-semidefinite by construction, so we can just use this function with A=Xt*W*X and y=Xt*W*y. */
-ccl_device_inline void math_trimatrix_vec3_solve(ccl_global float *A, ccl_global float3 *y, int n, int stride)
+ccl_device_inline void math_trimatrix_vec3_solve(ccl_global float *A,
+ ccl_global float3 *y,
+ int n,
+ int stride)
{
- /* Since the first entry of the design row is always 1, the upper-left element of XtWX is a good
- * heuristic for the amount of pixels considered (with weighting), therefore the amount of correction
- * is scaled based on it. */
- math_trimatrix_add_diagonal(A, n, 3e-7f*A[0], stride); /* Improve the numerical stability. */
- math_trimatrix_cholesky(A, n, stride); /* Replace A with L so that L*Lt = A. */
-
- /* Use forward substitution to solve L*b = y, replacing y by b. */
- for(int row = 0; row < n; row++) {
- float3 sum = VECS(y, row, stride);
- for(int col = 0; col < row; col++)
- sum -= MATHS(A, row, col, stride) * VECS(y, col, stride);
- VECS(y, row, stride) = sum / MATHS(A, row, row, stride);
- }
-
- /* Use backward substitution to solve Lt*S = b, replacing b by S. */
- for(int row = n-1; row >= 0; row--) {
- float3 sum = VECS(y, row, stride);
- for(int col = row+1; col < n; col++)
- sum -= MATHS(A, col, row, stride) * VECS(y, col, stride);
- VECS(y, row, stride) = sum / MATHS(A, row, row, stride);
- }
+ /* Since the first entry of the design row is always 1, the upper-left element of XtWX is a good
+ * heuristic for the amount of pixels considered (with weighting), therefore the amount of correction
+ * is scaled based on it. */
+ math_trimatrix_add_diagonal(A, n, 3e-7f * A[0], stride); /* Improve the numerical stability. */
+ math_trimatrix_cholesky(A, n, stride); /* Replace A with L so that L*Lt = A. */
+
+ /* Use forward substitution to solve L*b = y, replacing y by b. */
+ for (int row = 0; row < n; row++) {
+ float3 sum = VECS(y, row, stride);
+ for (int col = 0; col < row; col++)
+ sum -= MATHS(A, row, col, stride) * VECS(y, col, stride);
+ VECS(y, row, stride) = sum / MATHS(A, row, row, stride);
+ }
+
+ /* Use backward substitution to solve Lt*S = b, replacing b by S. */
+ for (int row = n - 1; row >= 0; row--) {
+ float3 sum = VECS(y, row, stride);
+ for (int col = row + 1; col < n; col++)
+ sum -= MATHS(A, col, row, stride) * VECS(y, col, stride);
+ VECS(y, row, stride) = sum / MATHS(A, row, row, stride);
+ }
}
/* Perform the Jacobi Eigenvalue Methon on matrix A.
@@ -234,181 +241,193 @@ ccl_device_inline void math_trimatrix_vec3_solve(ccl_global float *A, ccl_global
* and V will contain the eigenvectors of the original A in its rows (!),
* so that A = V^T*D*V. Therefore, the diagonal elements of D are the (sorted) eigenvalues of A.
*/
-ccl_device void math_matrix_jacobi_eigendecomposition(float *A, ccl_global float *V, int n, int v_stride)
+ccl_device void math_matrix_jacobi_eigendecomposition(float *A,
+ ccl_global float *V,
+ int n,
+ int v_stride)
{
- const float singular_epsilon = 1e-9f;
-
- for(int row = 0; row < n; row++) {
- for(int col = 0; col < n; col++) {
- MATS(V, n, row, col, v_stride) = (col == row) ? 1.0f : 0.0f;
- }
- }
-
- for(int sweep = 0; sweep < 8; sweep++) {
- float off_diagonal = 0.0f;
- for(int row = 1; row < n; row++) {
- for(int col = 0; col < row; col++) {
- off_diagonal += fabsf(MAT(A, n, row, col));
- }
- }
- if(off_diagonal < 1e-7f) {
- /* The matrix has nearly reached diagonal form.
- * Since the eigenvalues are only used to determine truncation, their exact values aren't required - a relative error of a few ULPs won't matter at all. */
- break;
- }
-
- /* Set the threshold for the small element rotation skip in the first sweep:
- * Skip all elements that are less than a tenth of the average off-diagonal element. */
- float threshold = 0.2f*off_diagonal / (n*n);
-
- for(int row = 1; row < n; row++) {
- for(int col = 0; col < row; col++) {
- /* Perform a Jacobi rotation on this element that reduces it to zero. */
- float element = MAT(A, n, row, col);
- float abs_element = fabsf(element);
-
- /* If we're in a later sweep and the element already is very small, just set it to zero and skip the rotation. */
- if(sweep > 3 && abs_element <= singular_epsilon*fabsf(MAT(A, n, row, row)) && abs_element <= singular_epsilon*fabsf(MAT(A, n, col, col))) {
- MAT(A, n, row, col) = 0.0f;
- continue;
- }
-
- if(element == 0.0f) {
- continue;
- }
-
- /* If we're in one of the first sweeps and the element is smaller than the threshold, skip it. */
- if(sweep < 3 && (abs_element < threshold)) {
- continue;
- }
-
- /* Determine rotation: The rotation is characterized by its angle phi - or, in the actual implementation, sin(phi) and cos(phi).
- * To find those, we first compute their ratio - that might be unstable if the angle approaches 90°, so there's a fallback for that case.
- * Then, we compute sin(phi) and cos(phi) themselves. */
- float singular_diff = MAT(A, n, row, row) - MAT(A, n, col, col);
- float ratio;
- if(abs_element > singular_epsilon*fabsf(singular_diff)) {
- float cot_2phi = 0.5f*singular_diff / element;
- ratio = 1.0f / (fabsf(cot_2phi) + sqrtf(1.0f + cot_2phi*cot_2phi));
- if(cot_2phi < 0.0f) ratio = -ratio; /* Copy sign. */
- }
- else {
- ratio = element / singular_diff;
- }
-
- float c = 1.0f / sqrtf(1.0f + ratio*ratio);
- float s = ratio*c;
- /* To improve numerical stability by avoiding cancellation, the update equations are reformulized to use sin(phi) and tan(phi/2) instead. */
- float tan_phi_2 = s / (1.0f + c);
-
- /* Update the singular values in the diagonal. */
- float singular_delta = ratio*element;
- MAT(A, n, row, row) += singular_delta;
- MAT(A, n, col, col) -= singular_delta;
-
- /* Set the element itself to zero. */
- MAT(A, n, row, col) = 0.0f;
-
- /* Perform the actual rotations on the matrices. */
-#define ROT(M, r1, c1, r2, c2, stride) \
- { \
- float M1 = MATS(M, n, r1, c1, stride); \
- float M2 = MATS(M, n, r2, c2, stride); \
- MATS(M, n, r1, c1, stride) -= s*(M2 + tan_phi_2*M1); \
- MATS(M, n, r2, c2, stride) += s*(M1 - tan_phi_2*M2); \
- }
-
- /* Split into three parts to ensure correct accesses since we only store the lower-triangular part of A. */
- for(int i = 0 ; i < col; i++) ROT(A, col, i, row, i, 1);
- for(int i = col+1; i < row; i++) ROT(A, i, col, row, i, 1);
- for(int i = row+1; i < n ; i++) ROT(A, i, col, i, row, 1);
-
- for(int i = 0 ; i < n ; i++) ROT(V, col, i, row, i, v_stride);
+ const float singular_epsilon = 1e-9f;
+
+ for (int row = 0; row < n; row++) {
+ for (int col = 0; col < n; col++) {
+ MATS(V, n, row, col, v_stride) = (col == row) ? 1.0f : 0.0f;
+ }
+ }
+
+ for (int sweep = 0; sweep < 8; sweep++) {
+ float off_diagonal = 0.0f;
+ for (int row = 1; row < n; row++) {
+ for (int col = 0; col < row; col++) {
+ off_diagonal += fabsf(MAT(A, n, row, col));
+ }
+ }
+ if (off_diagonal < 1e-7f) {
+ /* The matrix has nearly reached diagonal form.
+ * Since the eigenvalues are only used to determine truncation, their exact values aren't required - a relative error of a few ULPs won't matter at all. */
+ break;
+ }
+
+ /* Set the threshold for the small element rotation skip in the first sweep:
+ * Skip all elements that are less than a tenth of the average off-diagonal element. */
+ float threshold = 0.2f * off_diagonal / (n * n);
+
+ for (int row = 1; row < n; row++) {
+ for (int col = 0; col < row; col++) {
+ /* Perform a Jacobi rotation on this element that reduces it to zero. */
+ float element = MAT(A, n, row, col);
+ float abs_element = fabsf(element);
+
+ /* If we're in a later sweep and the element already is very small, just set it to zero and skip the rotation. */
+ if (sweep > 3 && abs_element <= singular_epsilon * fabsf(MAT(A, n, row, row)) &&
+ abs_element <= singular_epsilon * fabsf(MAT(A, n, col, col))) {
+ MAT(A, n, row, col) = 0.0f;
+ continue;
+ }
+
+ if (element == 0.0f) {
+ continue;
+ }
+
+ /* If we're in one of the first sweeps and the element is smaller than the threshold, skip it. */
+ if (sweep < 3 && (abs_element < threshold)) {
+ continue;
+ }
+
+ /* Determine rotation: The rotation is characterized by its angle phi - or, in the actual implementation, sin(phi) and cos(phi).
+ * To find those, we first compute their ratio - that might be unstable if the angle approaches 90°, so there's a fallback for that case.
+ * Then, we compute sin(phi) and cos(phi) themselves. */
+ float singular_diff = MAT(A, n, row, row) - MAT(A, n, col, col);
+ float ratio;
+ if (abs_element > singular_epsilon * fabsf(singular_diff)) {
+ float cot_2phi = 0.5f * singular_diff / element;
+ ratio = 1.0f / (fabsf(cot_2phi) + sqrtf(1.0f + cot_2phi * cot_2phi));
+ if (cot_2phi < 0.0f)
+ ratio = -ratio; /* Copy sign. */
+ }
+ else {
+ ratio = element / singular_diff;
+ }
+
+ float c = 1.0f / sqrtf(1.0f + ratio * ratio);
+ float s = ratio * c;
+ /* To improve numerical stability by avoiding cancellation, the update equations are reformulized to use sin(phi) and tan(phi/2) instead. */
+ float tan_phi_2 = s / (1.0f + c);
+
+ /* Update the singular values in the diagonal. */
+ float singular_delta = ratio * element;
+ MAT(A, n, row, row) += singular_delta;
+ MAT(A, n, col, col) -= singular_delta;
+
+ /* Set the element itself to zero. */
+ MAT(A, n, row, col) = 0.0f;
+
+ /* Perform the actual rotations on the matrices. */
+#define ROT(M, r1, c1, r2, c2, stride) \
+ { \
+ float M1 = MATS(M, n, r1, c1, stride); \
+ float M2 = MATS(M, n, r2, c2, stride); \
+ MATS(M, n, r1, c1, stride) -= s * (M2 + tan_phi_2 * M1); \
+ MATS(M, n, r2, c2, stride) += s * (M1 - tan_phi_2 * M2); \
+ }
+
+ /* Split into three parts to ensure correct accesses since we only store the lower-triangular part of A. */
+ for (int i = 0; i < col; i++)
+ ROT(A, col, i, row, i, 1);
+ for (int i = col + 1; i < row; i++)
+ ROT(A, i, col, row, i, 1);
+ for (int i = row + 1; i < n; i++)
+ ROT(A, i, col, i, row, 1);
+
+ for (int i = 0; i < n; i++)
+ ROT(V, col, i, row, i, v_stride);
#undef ROT
- }
- }
- }
-
- /* Sort eigenvalues and the associated eigenvectors. */
- for(int i = 0; i < n - 1; i++) {
- float v = MAT(A, n, i, i);
- int k = i;
- for(int j = i; j < n; j++) {
- if(MAT(A, n, j, j) >= v) {
- v = MAT(A, n, j, j);
- k = j;
- }
- }
- if(k != i) {
- /* Swap eigenvalues. */
- MAT(A, n, k, k) = MAT(A, n, i, i);
- MAT(A, n, i, i) = v;
- /* Swap eigenvectors. */
- for(int j = 0; j < n; j++) {
- float v = MATS(V, n, i, j, v_stride);
- MATS(V, n, i, j, v_stride) = MATS(V, n, k, j, v_stride);
- MATS(V, n, k, j, v_stride) = v;
- }
- }
- }
+ }
+ }
+ }
+
+ /* Sort eigenvalues and the associated eigenvectors. */
+ for (int i = 0; i < n - 1; i++) {
+ float v = MAT(A, n, i, i);
+ int k = i;
+ for (int j = i; j < n; j++) {
+ if (MAT(A, n, j, j) >= v) {
+ v = MAT(A, n, j, j);
+ k = j;
+ }
+ }
+ if (k != i) {
+ /* Swap eigenvalues. */
+ MAT(A, n, k, k) = MAT(A, n, i, i);
+ MAT(A, n, i, i) = v;
+ /* Swap eigenvectors. */
+ for (int j = 0; j < n; j++) {
+ float v = MATS(V, n, i, j, v_stride);
+ MATS(V, n, i, j, v_stride) = MATS(V, n, k, j, v_stride);
+ MATS(V, n, k, j, v_stride) = v;
+ }
+ }
+ }
}
#ifdef __KERNEL_SSE3__
ccl_device_inline void math_vector_zero_sse(float4 *A, int n)
{
- for(int i = 0; i < n; i++) {
- A[i] = make_float4(0.0f);
- }
+ for (int i = 0; i < n; i++) {
+ A[i] = make_float4(0.0f);
+ }
}
ccl_device_inline void math_matrix_zero_sse(float4 *A, int n)
{
- for(int row = 0; row < n; row++) {
- for(int col = 0; col <= row; col++) {
- MAT(A, n, row, col) = make_float4(0.0f);
- }
- }
+ for (int row = 0; row < n; row++) {
+ for (int col = 0; col <= row; col++) {
+ MAT(A, n, row, col) = make_float4(0.0f);
+ }
+ }
}
/* Add Gramian matrix of v to A.
* The Gramian matrix of v is v^T*v, so element (i,j) is v[i]*v[j]. */
-ccl_device_inline void math_matrix_add_gramian_sse(float4 *A, int n, const float4 *ccl_restrict v, float4 weight)
+ccl_device_inline void math_matrix_add_gramian_sse(float4 *A,
+ int n,
+ const float4 *ccl_restrict v,
+ float4 weight)
{
- for(int row = 0; row < n; row++) {
- for(int col = 0; col <= row; col++) {
- MAT(A, n, row, col) = MAT(A, n, row, col) + v[row] * v[col] * weight;
- }
- }
+ for (int row = 0; row < n; row++) {
+ for (int col = 0; col <= row; col++) {
+ MAT(A, n, row, col) = MAT(A, n, row, col) + v[row] * v[col] * weight;
+ }
+ }
}
ccl_device_inline void math_vector_add_sse(float4 *V, int n, const float4 *ccl_restrict a)
{
- for(int i = 0; i < n; i++) {
- V[i] += a[i];
- }
+ for (int i = 0; i < n; i++) {
+ V[i] += a[i];
+ }
}
ccl_device_inline void math_vector_mul_sse(float4 *V, int n, const float4 *ccl_restrict a)
{
- for(int i = 0; i < n; i++) {
- V[i] *= a[i];
- }
+ for (int i = 0; i < n; i++) {
+ V[i] *= a[i];
+ }
}
ccl_device_inline void math_vector_max_sse(float4 *a, const float4 *ccl_restrict b, int n)
{
- for(int i = 0; i < n; i++) {
- a[i] = max(a[i], b[i]);
- }
+ for (int i = 0; i < n; i++) {
+ a[i] = max(a[i], b[i]);
+ }
}
ccl_device_inline void math_matrix_hsum(float *A, int n, const float4 *ccl_restrict B)
{
- for(int row = 0; row < n; row++) {
- for(int col = 0; col <= row; col++) {
- MAT(A, n, row, col) = reduce_add(MAT(B, n, row, col))[0];
- }
- }
+ for (int row = 0; row < n; row++) {
+ for (int col = 0; col <= row; col++) {
+ MAT(A, n, row, col) = reduce_add(MAT(B, n, row, col))[0];
+ }
+ }
}
#endif
@@ -416,4 +435,4 @@ ccl_device_inline void math_matrix_hsum(float *A, int n, const float4 *ccl_restr
CCL_NAMESPACE_END
-#endif /* __UTIL_MATH_MATRIX_H__ */
+#endif /* __UTIL_MATH_MATRIX_H__ */
diff --git a/intern/cycles/util/util_md5.cpp b/intern/cycles/util/util_md5.cpp
index 7cdd28a4793..c11f495f785 100644
--- a/intern/cycles/util/util_md5.cpp
+++ b/intern/cycles/util/util_md5.cpp
@@ -10,11 +10,11 @@
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
- * claim that you wrote the original software. If you use this software
- * in a product, an acknowledgment in the product documentation would be
- * appreciated but is not required.
+ * claim that you wrote the original software. If you use this software
+ * in a product, an acknowledgment in the product documentation would be
+ * appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
- * misrepresented as being the original software.
+ * misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
*
* L. Peter Deutsch
@@ -34,239 +34,237 @@ CCL_NAMESPACE_BEGIN
#define T_MASK ((uint32_t)~0)
#define T1 /* 0xd76aa478 */ (T_MASK ^ 0x28955b87)
#define T2 /* 0xe8c7b756 */ (T_MASK ^ 0x173848a9)
-#define T3 0x242070db
+#define T3 0x242070db
#define T4 /* 0xc1bdceee */ (T_MASK ^ 0x3e423111)
#define T5 /* 0xf57c0faf */ (T_MASK ^ 0x0a83f050)
-#define T6 0x4787c62a
+#define T6 0x4787c62a
#define T7 /* 0xa8304613 */ (T_MASK ^ 0x57cfb9ec)
#define T8 /* 0xfd469501 */ (T_MASK ^ 0x02b96afe)
-#define T9 0x698098d8
+#define T9 0x698098d8
#define T10 /* 0x8b44f7af */ (T_MASK ^ 0x74bb0850)
#define T11 /* 0xffff5bb1 */ (T_MASK ^ 0x0000a44e)
#define T12 /* 0x895cd7be */ (T_MASK ^ 0x76a32841)
-#define T13 0x6b901122
+#define T13 0x6b901122
#define T14 /* 0xfd987193 */ (T_MASK ^ 0x02678e6c)
#define T15 /* 0xa679438e */ (T_MASK ^ 0x5986bc71)
-#define T16 0x49b40821
+#define T16 0x49b40821
#define T17 /* 0xf61e2562 */ (T_MASK ^ 0x09e1da9d)
#define T18 /* 0xc040b340 */ (T_MASK ^ 0x3fbf4cbf)
-#define T19 0x265e5a51
+#define T19 0x265e5a51
#define T20 /* 0xe9b6c7aa */ (T_MASK ^ 0x16493855)
#define T21 /* 0xd62f105d */ (T_MASK ^ 0x29d0efa2)
-#define T22 0x02441453
+#define T22 0x02441453
#define T23 /* 0xd8a1e681 */ (T_MASK ^ 0x275e197e)
#define T24 /* 0xe7d3fbc8 */ (T_MASK ^ 0x182c0437)
-#define T25 0x21e1cde6
+#define T25 0x21e1cde6
#define T26 /* 0xc33707d6 */ (T_MASK ^ 0x3cc8f829)
#define T27 /* 0xf4d50d87 */ (T_MASK ^ 0x0b2af278)
-#define T28 0x455a14ed
+#define T28 0x455a14ed
#define T29 /* 0xa9e3e905 */ (T_MASK ^ 0x561c16fa)
#define T30 /* 0xfcefa3f8 */ (T_MASK ^ 0x03105c07)
-#define T31 0x676f02d9
+#define T31 0x676f02d9
#define T32 /* 0x8d2a4c8a */ (T_MASK ^ 0x72d5b375)
#define T33 /* 0xfffa3942 */ (T_MASK ^ 0x0005c6bd)
#define T34 /* 0x8771f681 */ (T_MASK ^ 0x788e097e)
-#define T35 0x6d9d6122
+#define T35 0x6d9d6122
#define T36 /* 0xfde5380c */ (T_MASK ^ 0x021ac7f3)
#define T37 /* 0xa4beea44 */ (T_MASK ^ 0x5b4115bb)
-#define T38 0x4bdecfa9
+#define T38 0x4bdecfa9
#define T39 /* 0xf6bb4b60 */ (T_MASK ^ 0x0944b49f)
#define T40 /* 0xbebfbc70 */ (T_MASK ^ 0x4140438f)
-#define T41 0x289b7ec6
+#define T41 0x289b7ec6
#define T42 /* 0xeaa127fa */ (T_MASK ^ 0x155ed805)
#define T43 /* 0xd4ef3085 */ (T_MASK ^ 0x2b10cf7a)
-#define T44 0x04881d05
+#define T44 0x04881d05
#define T45 /* 0xd9d4d039 */ (T_MASK ^ 0x262b2fc6)
#define T46 /* 0xe6db99e5 */ (T_MASK ^ 0x1924661a)
-#define T47 0x1fa27cf8
+#define T47 0x1fa27cf8
#define T48 /* 0xc4ac5665 */ (T_MASK ^ 0x3b53a99a)
#define T49 /* 0xf4292244 */ (T_MASK ^ 0x0bd6ddbb)
-#define T50 0x432aff97
+#define T50 0x432aff97
#define T51 /* 0xab9423a7 */ (T_MASK ^ 0x546bdc58)
#define T52 /* 0xfc93a039 */ (T_MASK ^ 0x036c5fc6)
-#define T53 0x655b59c3
+#define T53 0x655b59c3
#define T54 /* 0x8f0ccc92 */ (T_MASK ^ 0x70f3336d)
#define T55 /* 0xffeff47d */ (T_MASK ^ 0x00100b82)
#define T56 /* 0x85845dd1 */ (T_MASK ^ 0x7a7ba22e)
-#define T57 0x6fa87e4f
+#define T57 0x6fa87e4f
#define T58 /* 0xfe2ce6e0 */ (T_MASK ^ 0x01d3191f)
#define T59 /* 0xa3014314 */ (T_MASK ^ 0x5cfebceb)
-#define T60 0x4e0811a1
+#define T60 0x4e0811a1
#define T61 /* 0xf7537e82 */ (T_MASK ^ 0x08ac817d)
#define T62 /* 0xbd3af235 */ (T_MASK ^ 0x42c50dca)
-#define T63 0x2ad7d2bb
+#define T63 0x2ad7d2bb
#define T64 /* 0xeb86d391 */ (T_MASK ^ 0x14792c6e)
void MD5Hash::process(const uint8_t *data /*[64]*/)
{
- uint32_t
- a = abcd[0], b = abcd[1],
- c = abcd[2], d = abcd[3];
- uint32_t t;
- /* Define storage for little-endian or both types of CPUs. */
- uint32_t xbuf[16];
- const uint32_t *X;
-
- {
- /*
- * Determine dynamically whether this is a big-endian or
- * little-endian machine, since we can use a more efficient
- * algorithm on the latter.
- */
- static const int w = 1;
-
- if(*((const uint8_t *)&w)) /* dynamic little-endian */
- {
- /*
- * On little-endian machines, we can process properly aligned
- * data without copying it.
- */
- if(!((data - (const uint8_t *)0) & 3)) {
- /* data are properly aligned */
- X = (const uint32_t *)data;
- }
- else {
- /* not aligned */
- memcpy(xbuf, data, 64);
- X = xbuf;
- }
- }
- else { /* dynamic big-endian */
- /*
- * On big-endian machines, we must arrange the bytes in the
- * right order.
- */
- const uint8_t *xp = data;
- int i;
-
- X = xbuf; /* (dynamic only) */
- for(i = 0; i < 16; ++i, xp += 4)
- xbuf[i] = xp[0] + (xp[1] << 8) + (xp[2] << 16) + (xp[3] << 24);
- }
- }
+ uint32_t a = abcd[0], b = abcd[1], c = abcd[2], d = abcd[3];
+ uint32_t t;
+ /* Define storage for little-endian or both types of CPUs. */
+ uint32_t xbuf[16];
+ const uint32_t *X;
+
+ {
+ /*
+ * Determine dynamically whether this is a big-endian or
+ * little-endian machine, since we can use a more efficient
+ * algorithm on the latter.
+ */
+ static const int w = 1;
+
+ if (*((const uint8_t *)&w)) /* dynamic little-endian */
+ {
+ /*
+ * On little-endian machines, we can process properly aligned
+ * data without copying it.
+ */
+ if (!((data - (const uint8_t *)0) & 3)) {
+ /* data are properly aligned */
+ X = (const uint32_t *)data;
+ }
+ else {
+ /* not aligned */
+ memcpy(xbuf, data, 64);
+ X = xbuf;
+ }
+ }
+ else { /* dynamic big-endian */
+ /*
+ * On big-endian machines, we must arrange the bytes in the
+ * right order.
+ */
+ const uint8_t *xp = data;
+ int i;
+
+ X = xbuf; /* (dynamic only) */
+ for (i = 0; i < 16; ++i, xp += 4)
+ xbuf[i] = xp[0] + (xp[1] << 8) + (xp[2] << 16) + (xp[3] << 24);
+ }
+ }
#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32 - (n))))
- /* Round 1. */
- /* Let [abcd k s i] denote the operation
- * a = b + ((a + F(b,c,d) + X[k] + T[i]) <<< s). */
+ /* Round 1. */
+ /* Let [abcd k s i] denote the operation
+ * a = b + ((a + F(b,c,d) + X[k] + T[i]) <<< s). */
#define F(x, y, z) (((x) & (y)) | (~(x) & (z)))
-#define SET(a, b, c, d, k, s, Ti)\
- t = a + F(b,c,d) + X[k] + Ti;\
- a = ROTATE_LEFT(t, s) + b
- /* Do the following 16 operations. */
- SET(a, b, c, d, 0, 7, T1);
- SET(d, a, b, c, 1, 12, T2);
- SET(c, d, a, b, 2, 17, T3);
- SET(b, c, d, a, 3, 22, T4);
- SET(a, b, c, d, 4, 7, T5);
- SET(d, a, b, c, 5, 12, T6);
- SET(c, d, a, b, 6, 17, T7);
- SET(b, c, d, a, 7, 22, T8);
- SET(a, b, c, d, 8, 7, T9);
- SET(d, a, b, c, 9, 12, T10);
- SET(c, d, a, b, 10, 17, T11);
- SET(b, c, d, a, 11, 22, T12);
- SET(a, b, c, d, 12, 7, T13);
- SET(d, a, b, c, 13, 12, T14);
- SET(c, d, a, b, 14, 17, T15);
- SET(b, c, d, a, 15, 22, T16);
+#define SET(a, b, c, d, k, s, Ti) \
+ t = a + F(b, c, d) + X[k] + Ti; \
+ a = ROTATE_LEFT(t, s) + b
+ /* Do the following 16 operations. */
+ SET(a, b, c, d, 0, 7, T1);
+ SET(d, a, b, c, 1, 12, T2);
+ SET(c, d, a, b, 2, 17, T3);
+ SET(b, c, d, a, 3, 22, T4);
+ SET(a, b, c, d, 4, 7, T5);
+ SET(d, a, b, c, 5, 12, T6);
+ SET(c, d, a, b, 6, 17, T7);
+ SET(b, c, d, a, 7, 22, T8);
+ SET(a, b, c, d, 8, 7, T9);
+ SET(d, a, b, c, 9, 12, T10);
+ SET(c, d, a, b, 10, 17, T11);
+ SET(b, c, d, a, 11, 22, T12);
+ SET(a, b, c, d, 12, 7, T13);
+ SET(d, a, b, c, 13, 12, T14);
+ SET(c, d, a, b, 14, 17, T15);
+ SET(b, c, d, a, 15, 22, T16);
#undef SET
- /* Round 2. */
- /* Let [abcd k s i] denote the operation
- * a = b + ((a + G(b,c,d) + X[k] + T[i]) <<< s). */
+ /* Round 2. */
+ /* Let [abcd k s i] denote the operation
+ * a = b + ((a + G(b,c,d) + X[k] + T[i]) <<< s). */
#define G(x, y, z) (((x) & (z)) | ((y) & ~(z)))
-#define SET(a, b, c, d, k, s, Ti)\
- t = a + G(b,c,d) + X[k] + Ti;\
- a = ROTATE_LEFT(t, s) + b
- /* Do the following 16 operations. */
- SET(a, b, c, d, 1, 5, T17);
- SET(d, a, b, c, 6, 9, T18);
- SET(c, d, a, b, 11, 14, T19);
- SET(b, c, d, a, 0, 20, T20);
- SET(a, b, c, d, 5, 5, T21);
- SET(d, a, b, c, 10, 9, T22);
- SET(c, d, a, b, 15, 14, T23);
- SET(b, c, d, a, 4, 20, T24);
- SET(a, b, c, d, 9, 5, T25);
- SET(d, a, b, c, 14, 9, T26);
- SET(c, d, a, b, 3, 14, T27);
- SET(b, c, d, a, 8, 20, T28);
- SET(a, b, c, d, 13, 5, T29);
- SET(d, a, b, c, 2, 9, T30);
- SET(c, d, a, b, 7, 14, T31);
- SET(b, c, d, a, 12, 20, T32);
+#define SET(a, b, c, d, k, s, Ti) \
+ t = a + G(b, c, d) + X[k] + Ti; \
+ a = ROTATE_LEFT(t, s) + b
+ /* Do the following 16 operations. */
+ SET(a, b, c, d, 1, 5, T17);
+ SET(d, a, b, c, 6, 9, T18);
+ SET(c, d, a, b, 11, 14, T19);
+ SET(b, c, d, a, 0, 20, T20);
+ SET(a, b, c, d, 5, 5, T21);
+ SET(d, a, b, c, 10, 9, T22);
+ SET(c, d, a, b, 15, 14, T23);
+ SET(b, c, d, a, 4, 20, T24);
+ SET(a, b, c, d, 9, 5, T25);
+ SET(d, a, b, c, 14, 9, T26);
+ SET(c, d, a, b, 3, 14, T27);
+ SET(b, c, d, a, 8, 20, T28);
+ SET(a, b, c, d, 13, 5, T29);
+ SET(d, a, b, c, 2, 9, T30);
+ SET(c, d, a, b, 7, 14, T31);
+ SET(b, c, d, a, 12, 20, T32);
#undef SET
- /* Round 3. */
- /* Let [abcd k s t] denote the operation
- * a = b + ((a + H(b,c,d) + X[k] + T[i]) <<< s). */
+ /* Round 3. */
+ /* Let [abcd k s t] denote the operation
+ * a = b + ((a + H(b,c,d) + X[k] + T[i]) <<< s). */
#define H(x, y, z) ((x) ^ (y) ^ (z))
-#define SET(a, b, c, d, k, s, Ti)\
- t = a + H(b,c,d) + X[k] + Ti;\
+#define SET(a, b, c, d, k, s, Ti) \
+ t = a + H(b, c, d) + X[k] + Ti; \
a = ROTATE_LEFT(t, s) + b
- /* Do the following 16 operations. */
- SET(a, b, c, d, 5, 4, T33);
- SET(d, a, b, c, 8, 11, T34);
- SET(c, d, a, b, 11, 16, T35);
- SET(b, c, d, a, 14, 23, T36);
- SET(a, b, c, d, 1, 4, T37);
- SET(d, a, b, c, 4, 11, T38);
- SET(c, d, a, b, 7, 16, T39);
- SET(b, c, d, a, 10, 23, T40);
- SET(a, b, c, d, 13, 4, T41);
- SET(d, a, b, c, 0, 11, T42);
- SET(c, d, a, b, 3, 16, T43);
- SET(b, c, d, a, 6, 23, T44);
- SET(a, b, c, d, 9, 4, T45);
- SET(d, a, b, c, 12, 11, T46);
- SET(c, d, a, b, 15, 16, T47);
- SET(b, c, d, a, 2, 23, T48);
+ /* Do the following 16 operations. */
+ SET(a, b, c, d, 5, 4, T33);
+ SET(d, a, b, c, 8, 11, T34);
+ SET(c, d, a, b, 11, 16, T35);
+ SET(b, c, d, a, 14, 23, T36);
+ SET(a, b, c, d, 1, 4, T37);
+ SET(d, a, b, c, 4, 11, T38);
+ SET(c, d, a, b, 7, 16, T39);
+ SET(b, c, d, a, 10, 23, T40);
+ SET(a, b, c, d, 13, 4, T41);
+ SET(d, a, b, c, 0, 11, T42);
+ SET(c, d, a, b, 3, 16, T43);
+ SET(b, c, d, a, 6, 23, T44);
+ SET(a, b, c, d, 9, 4, T45);
+ SET(d, a, b, c, 12, 11, T46);
+ SET(c, d, a, b, 15, 16, T47);
+ SET(b, c, d, a, 2, 23, T48);
#undef SET
- /* Round 4. */
- /* Let [abcd k s t] denote the operation
- * a = b + ((a + I(b,c,d) + X[k] + T[i]) <<< s). */
+ /* Round 4. */
+ /* Let [abcd k s t] denote the operation
+ * a = b + ((a + I(b,c,d) + X[k] + T[i]) <<< s). */
#define I(x, y, z) ((y) ^ ((x) | ~(z)))
-#define SET(a, b, c, d, k, s, Ti)\
- t = a + I(b,c,d) + X[k] + Ti;\
- a = ROTATE_LEFT(t, s) + b
- /* Do the following 16 operations. */
- SET(a, b, c, d, 0, 6, T49);
- SET(d, a, b, c, 7, 10, T50);
- SET(c, d, a, b, 14, 15, T51);
- SET(b, c, d, a, 5, 21, T52);
- SET(a, b, c, d, 12, 6, T53);
- SET(d, a, b, c, 3, 10, T54);
- SET(c, d, a, b, 10, 15, T55);
- SET(b, c, d, a, 1, 21, T56);
- SET(a, b, c, d, 8, 6, T57);
- SET(d, a, b, c, 15, 10, T58);
- SET(c, d, a, b, 6, 15, T59);
- SET(b, c, d, a, 13, 21, T60);
- SET(a, b, c, d, 4, 6, T61);
- SET(d, a, b, c, 11, 10, T62);
- SET(c, d, a, b, 2, 15, T63);
- SET(b, c, d, a, 9, 21, T64);
+#define SET(a, b, c, d, k, s, Ti) \
+ t = a + I(b, c, d) + X[k] + Ti; \
+ a = ROTATE_LEFT(t, s) + b
+ /* Do the following 16 operations. */
+ SET(a, b, c, d, 0, 6, T49);
+ SET(d, a, b, c, 7, 10, T50);
+ SET(c, d, a, b, 14, 15, T51);
+ SET(b, c, d, a, 5, 21, T52);
+ SET(a, b, c, d, 12, 6, T53);
+ SET(d, a, b, c, 3, 10, T54);
+ SET(c, d, a, b, 10, 15, T55);
+ SET(b, c, d, a, 1, 21, T56);
+ SET(a, b, c, d, 8, 6, T57);
+ SET(d, a, b, c, 15, 10, T58);
+ SET(c, d, a, b, 6, 15, T59);
+ SET(b, c, d, a, 13, 21, T60);
+ SET(a, b, c, d, 4, 6, T61);
+ SET(d, a, b, c, 11, 10, T62);
+ SET(c, d, a, b, 2, 15, T63);
+ SET(b, c, d, a, 9, 21, T64);
#undef SET
- /* Then perform the following additions. (That is increment each
- * of the four registers by the value it had before this block
- * was started.) */
- abcd[0] += a;
- abcd[1] += b;
- abcd[2] += c;
- abcd[3] += d;
+ /* Then perform the following additions. (That is increment each
+ * of the four registers by the value it had before this block
+ * was started.) */
+ abcd[0] += a;
+ abcd[1] += b;
+ abcd[2] += c;
+ abcd[3] += d;
}
MD5Hash::MD5Hash()
{
- count[0] = count[1] = 0;
- abcd[0] = 0x67452301;
- abcd[1] = /*0xefcdab89*/ T_MASK ^ 0x10325476;
- abcd[2] = /*0x98badcfe*/ T_MASK ^ 0x67452301;
- abcd[3] = 0x10325476;
+ count[0] = count[1] = 0;
+ abcd[0] = 0x67452301;
+ abcd[1] = /*0xefcdab89*/ T_MASK ^ 0x10325476;
+ abcd[2] = /*0x98badcfe*/ T_MASK ^ 0x67452301;
+ abcd[3] = 0x10325476;
}
MD5Hash::~MD5Hash()
@@ -275,116 +273,115 @@ MD5Hash::~MD5Hash()
void MD5Hash::append(const uint8_t *data, int nbytes)
{
- const uint8_t *p = data;
- int left = nbytes;
- int offset = (count[0] >> 3) & 63;
- uint32_t nbits = (uint32_t)(nbytes << 3);
-
- if(nbytes <= 0)
- return;
-
- /* Update the message length. */
- count[1] += nbytes >> 29;
- count[0] += nbits;
- if(count[0] < nbits)
- count[1]++;
-
- /* Process an initial partial block. */
- if(offset) {
- int copy = (offset + nbytes > 64 ? 64 - offset : nbytes);
-
- memcpy(buf + offset, p, copy);
- if(offset + copy < 64)
- return;
- p += copy;
- left -= copy;
- process(buf);
- }
-
- /* Process full blocks. */
- for(; left >= 64; p += 64, left -= 64)
- process(p);
-
- /* Process a final partial block. */
- if(left)
- memcpy(buf, p, left);
+ const uint8_t *p = data;
+ int left = nbytes;
+ int offset = (count[0] >> 3) & 63;
+ uint32_t nbits = (uint32_t)(nbytes << 3);
+
+ if (nbytes <= 0)
+ return;
+
+ /* Update the message length. */
+ count[1] += nbytes >> 29;
+ count[0] += nbits;
+ if (count[0] < nbits)
+ count[1]++;
+
+ /* Process an initial partial block. */
+ if (offset) {
+ int copy = (offset + nbytes > 64 ? 64 - offset : nbytes);
+
+ memcpy(buf + offset, p, copy);
+ if (offset + copy < 64)
+ return;
+ p += copy;
+ left -= copy;
+ process(buf);
+ }
+
+ /* Process full blocks. */
+ for (; left >= 64; p += 64, left -= 64)
+ process(p);
+
+ /* Process a final partial block. */
+ if (left)
+ memcpy(buf, p, left);
}
-void MD5Hash::append(const string& str)
+void MD5Hash::append(const string &str)
{
- if(str.size()) {
- append((const uint8_t*)str.c_str(), str.size());
- }
+ if (str.size()) {
+ append((const uint8_t *)str.c_str(), str.size());
+ }
}
-bool MD5Hash::append_file(const string& filepath)
+bool MD5Hash::append_file(const string &filepath)
{
- FILE *f = path_fopen(filepath, "rb");
+ FILE *f = path_fopen(filepath, "rb");
- if(!f) {
- fprintf(stderr, "MD5: failed to open file %s\n", filepath.c_str());
- return false;
- }
+ if (!f) {
+ fprintf(stderr, "MD5: failed to open file %s\n", filepath.c_str());
+ return false;
+ }
- const size_t buffer_size = 1024;
- uint8_t buffer[buffer_size];
- size_t n;
+ const size_t buffer_size = 1024;
+ uint8_t buffer[buffer_size];
+ size_t n;
- do {
- n = fread(buffer, 1, buffer_size, f);
- append(buffer, n);
- } while(n == buffer_size);
+ do {
+ n = fread(buffer, 1, buffer_size, f);
+ append(buffer, n);
+ } while (n == buffer_size);
- bool success = (ferror(f) == 0);
+ bool success = (ferror(f) == 0);
- fclose(f);
+ fclose(f);
- return success;
+ return success;
}
void MD5Hash::finish(uint8_t digest[16])
{
- static const uint8_t pad[64] = {
- 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
-
- uint8_t data[8];
- int i;
-
- /* Save the length before padding. */
- for(i = 0; i < 8; ++i)
- data[i] = (uint8_t)(count[i >> 2] >> ((i & 3) << 3));
-
- /* Pad to 56 bytes mod 64. */
- append(pad, ((55 - (count[0] >> 3)) & 63) + 1);
- /* Append the length. */
- append(data, 8);
-
- for(i = 0; i < 16; ++i)
- digest[i] = (uint8_t)(abcd[i >> 2] >> ((i & 3) << 3));
+ static const uint8_t pad[64] = {0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+
+ uint8_t data[8];
+ int i;
+
+ /* Save the length before padding. */
+ for (i = 0; i < 8; ++i)
+ data[i] = (uint8_t)(count[i >> 2] >> ((i & 3) << 3));
+
+ /* Pad to 56 bytes mod 64. */
+ append(pad, ((55 - (count[0] >> 3)) & 63) + 1);
+ /* Append the length. */
+ append(data, 8);
+
+ for (i = 0; i < 16; ++i)
+ digest[i] = (uint8_t)(abcd[i >> 2] >> ((i & 3) << 3));
}
string MD5Hash::get_hex()
{
- uint8_t digest[16];
- char buf[16*2+1];
+ uint8_t digest[16];
+ char buf[16 * 2 + 1];
- finish(digest);
+ finish(digest);
- for(int i = 0; i < 16; i++)
- sprintf(buf + i*2, "%02X", (unsigned int)digest[i]);
- buf[sizeof(buf)-1] = '\0';
+ for (int i = 0; i < 16; i++)
+ sprintf(buf + i * 2, "%02X", (unsigned int)digest[i]);
+ buf[sizeof(buf) - 1] = '\0';
- return string(buf);
+ return string(buf);
}
-string util_md5_string(const string& str)
+string util_md5_string(const string &str)
{
- MD5Hash md5;
- md5.append((uint8_t*)str.c_str(), str.size());
- return md5.get_hex();
+ MD5Hash md5;
+ md5.append((uint8_t *)str.c_str(), str.size());
+ return md5.get_hex();
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/util/util_md5.h b/intern/cycles/util/util_md5.h
index f8c0115d8ce..4622945f9d2 100644
--- a/intern/cycles/util/util_md5.h
+++ b/intern/cycles/util/util_md5.h
@@ -36,26 +36,26 @@
CCL_NAMESPACE_BEGIN
class MD5Hash {
-public:
- MD5Hash();
- ~MD5Hash();
-
- void append(const uint8_t *data, int size);
- void append(const string& str);
- bool append_file(const string& filepath);
- string get_hex();
-
-protected:
- void process(const uint8_t *data);
- void finish(uint8_t digest[16]);
-
- uint32_t count[2]; /* message length in bits, lsw first */
- uint32_t abcd[4]; /* digest buffer */
- uint8_t buf[64]; /* accumulate block */
+ public:
+ MD5Hash();
+ ~MD5Hash();
+
+ void append(const uint8_t *data, int size);
+ void append(const string &str);
+ bool append_file(const string &filepath);
+ string get_hex();
+
+ protected:
+ void process(const uint8_t *data);
+ void finish(uint8_t digest[16]);
+
+ uint32_t count[2]; /* message length in bits, lsw first */
+ uint32_t abcd[4]; /* digest buffer */
+ uint8_t buf[64]; /* accumulate block */
};
-string util_md5_string(const string& str);
+string util_md5_string(const string &str);
CCL_NAMESPACE_END
-#endif /* __UTIL_MD5_H__ */
+#endif /* __UTIL_MD5_H__ */
diff --git a/intern/cycles/util/util_murmurhash.cpp b/intern/cycles/util/util_murmurhash.cpp
index 68df8fa1a84..5d728769fe9 100644
--- a/intern/cycles/util/util_murmurhash.cpp
+++ b/intern/cycles/util/util_murmurhash.cpp
@@ -27,15 +27,15 @@
#include "util/util_murmurhash.h"
#if defined(_MSC_VER)
-# define ROTL32(x,y) _rotl(x,y)
-# define ROTL64(x,y) _rotl64(x,y)
+# define ROTL32(x, y) _rotl(x, y)
+# define ROTL64(x, y) _rotl64(x, y)
# define BIG_CONSTANT(x) (x)
#else
ccl_device_inline uint32_t rotl32(uint32_t x, int8_t r)
{
- return (x << r) | (x >> (32 - r));
+ return (x << r) | (x >> (32 - r));
}
-# define ROTL32(x,y) rotl32(x,y)
+# define ROTL32(x, y) rotl32(x, y)
# define BIG_CONSTANT(x) (x##LLU)
#endif
@@ -45,82 +45,82 @@ CCL_NAMESPACE_BEGIN
* handle aligned reads, do the conversion here. */
ccl_device_inline uint32_t mm_hash_getblock32(const uint32_t *p, int i)
{
- return p[i];
+ return p[i];
}
/* Finalization mix - force all bits of a hash block to avalanche */
-ccl_device_inline uint32_t mm_hash_fmix32 ( uint32_t h )
+ccl_device_inline uint32_t mm_hash_fmix32(uint32_t h)
{
- h ^= h >> 16;
- h *= 0x85ebca6b;
- h ^= h >> 13;
- h *= 0xc2b2ae35;
- h ^= h >> 16;
- return h;
+ h ^= h >> 16;
+ h *= 0x85ebca6b;
+ h ^= h >> 13;
+ h *= 0xc2b2ae35;
+ h ^= h >> 16;
+ return h;
}
uint32_t util_murmur_hash3(const void *key, int len, uint32_t seed)
{
- const uint8_t * data = (const uint8_t*)key;
- const int nblocks = len / 4;
-
- uint32_t h1 = seed;
-
- const uint32_t c1 = 0xcc9e2d51;
- const uint32_t c2 = 0x1b873593;
-
- const uint32_t * blocks = (const uint32_t *)(data + nblocks*4);
-
- for(int i = -nblocks; i; i++) {
- uint32_t k1 = mm_hash_getblock32(blocks,i);
-
- k1 *= c1;
- k1 = ROTL32(k1,15);
- k1 *= c2;
-
- h1 ^= k1;
- h1 = ROTL32(h1,13);
- h1 = h1 * 5 + 0xe6546b64;
- }
-
- const uint8_t *tail = (const uint8_t*)(data + nblocks*4);
-
- uint32_t k1 = 0;
-
- switch(len & 3) {
- case 3:
- k1 ^= tail[2] << 16;
- ATTR_FALLTHROUGH;
- case 2:
- k1 ^= tail[1] << 8;
- ATTR_FALLTHROUGH;
- case 1:
- k1 ^= tail[0];
- k1 *= c1;
- k1 = ROTL32(k1,15);
- k1 *= c2;
- h1 ^= k1;
- }
-
- h1 ^= len;
- h1 = mm_hash_fmix32(h1);
- return h1;
+ const uint8_t *data = (const uint8_t *)key;
+ const int nblocks = len / 4;
+
+ uint32_t h1 = seed;
+
+ const uint32_t c1 = 0xcc9e2d51;
+ const uint32_t c2 = 0x1b873593;
+
+ const uint32_t *blocks = (const uint32_t *)(data + nblocks * 4);
+
+ for (int i = -nblocks; i; i++) {
+ uint32_t k1 = mm_hash_getblock32(blocks, i);
+
+ k1 *= c1;
+ k1 = ROTL32(k1, 15);
+ k1 *= c2;
+
+ h1 ^= k1;
+ h1 = ROTL32(h1, 13);
+ h1 = h1 * 5 + 0xe6546b64;
+ }
+
+ const uint8_t *tail = (const uint8_t *)(data + nblocks * 4);
+
+ uint32_t k1 = 0;
+
+ switch (len & 3) {
+ case 3:
+ k1 ^= tail[2] << 16;
+ ATTR_FALLTHROUGH;
+ case 2:
+ k1 ^= tail[1] << 8;
+ ATTR_FALLTHROUGH;
+ case 1:
+ k1 ^= tail[0];
+ k1 *= c1;
+ k1 = ROTL32(k1, 15);
+ k1 *= c2;
+ h1 ^= k1;
+ }
+
+ h1 ^= len;
+ h1 = mm_hash_fmix32(h1);
+ return h1;
}
/* This is taken from the cryptomatte specification 1.0 */
float util_hash_to_float(uint32_t hash)
{
- uint32_t mantissa = hash & (( 1 << 23) - 1);
- uint32_t exponent = (hash >> 23) & ((1 << 8) - 1);
- exponent = max(exponent, (uint32_t) 1);
- exponent = min(exponent, (uint32_t) 254);
- exponent = exponent << 23;
- uint32_t sign = (hash >> 31);
- sign = sign << 31;
- uint32_t float_bits = sign | exponent | mantissa;
- float f;
- memcpy(&f, &float_bits, sizeof(uint32_t));
- return f;
+ uint32_t mantissa = hash & ((1 << 23) - 1);
+ uint32_t exponent = (hash >> 23) & ((1 << 8) - 1);
+ exponent = max(exponent, (uint32_t)1);
+ exponent = min(exponent, (uint32_t)254);
+ exponent = exponent << 23;
+ uint32_t sign = (hash >> 31);
+ sign = sign << 31;
+ uint32_t float_bits = sign | exponent | mantissa;
+ float f;
+ memcpy(&f, &float_bits, sizeof(uint32_t));
+ return f;
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/util/util_murmurhash.h b/intern/cycles/util/util_murmurhash.h
index 3e7897d3ae6..2ec87efd87a 100644
--- a/intern/cycles/util/util_murmurhash.h
+++ b/intern/cycles/util/util_murmurhash.h
@@ -14,7 +14,6 @@
* limitations under the License.
*/
-
#ifndef __UTIL_MURMURHASH_H__
#define __UTIL_MURMURHASH_H__
@@ -27,4 +26,4 @@ float util_hash_to_float(uint32_t hash);
CCL_NAMESPACE_END
-#endif /* __UTIL_MURMURHASH_H__ */
+#endif /* __UTIL_MURMURHASH_H__ */
diff --git a/intern/cycles/util/util_opengl.h b/intern/cycles/util/util_opengl.h
index 04f0fbaf288..7a8d5eec1f9 100644
--- a/intern/cycles/util/util_opengl.h
+++ b/intern/cycles/util/util_opengl.h
@@ -22,4 +22,4 @@
#include <GL/glew.h>
-#endif /* __UTIL_OPENGL_H__ */
+#endif /* __UTIL_OPENGL_H__ */
diff --git a/intern/cycles/util/util_optimization.h b/intern/cycles/util/util_optimization.h
index 5267bd9a97a..46dd883282a 100644
--- a/intern/cycles/util/util_optimization.h
+++ b/intern/cycles/util/util_optimization.h
@@ -23,49 +23,49 @@
*
* Compile a regular, SSE2 and SSE3 kernel. */
-#if defined(i386) || defined(_M_IX86)
+# if defined(i386) || defined(_M_IX86)
/* We require minimum SSE2 support on x86, so auto enable. */
-# define __KERNEL_SSE2__
+# define __KERNEL_SSE2__
-# ifdef WITH_KERNEL_SSE2
-# define WITH_CYCLES_OPTIMIZED_KERNEL_SSE2
-# endif
+# ifdef WITH_KERNEL_SSE2
+# define WITH_CYCLES_OPTIMIZED_KERNEL_SSE2
+# endif
-# ifdef WITH_KERNEL_SSE3
-# define WITH_CYCLES_OPTIMIZED_KERNEL_SSE3
-# endif
+# ifdef WITH_KERNEL_SSE3
+# define WITH_CYCLES_OPTIMIZED_KERNEL_SSE3
+# endif
-#endif /* defined(i386) || defined(_M_IX86) */
+# endif /* defined(i386) || defined(_M_IX86) */
/* x86-64
*
* Compile a regular (includes SSE2), SSE3, SSE 4.1, AVX and AVX2 kernel. */
-#if defined(__x86_64__) || defined(_M_X64)
+# if defined(__x86_64__) || defined(_M_X64)
/* SSE2 is always available on x86-64 CPUs, so auto enable */
-# define __KERNEL_SSE2__
+# define __KERNEL_SSE2__
/* no SSE2 kernel on x86-64, part of regular kernel */
-# ifdef WITH_KERNEL_SSE3
-# define WITH_CYCLES_OPTIMIZED_KERNEL_SSE3
-# endif
+# ifdef WITH_KERNEL_SSE3
+# define WITH_CYCLES_OPTIMIZED_KERNEL_SSE3
+# endif
-# ifdef WITH_KERNEL_SSE41
-# define WITH_CYCLES_OPTIMIZED_KERNEL_SSE41
-# endif
+# ifdef WITH_KERNEL_SSE41
+# define WITH_CYCLES_OPTIMIZED_KERNEL_SSE41
+# endif
-# ifdef WITH_KERNEL_AVX
-# define WITH_CYCLES_OPTIMIZED_KERNEL_AVX
-# endif
+# ifdef WITH_KERNEL_AVX
+# define WITH_CYCLES_OPTIMIZED_KERNEL_AVX
+# endif
-# ifdef WITH_KERNEL_AVX2
-# define WITH_CYCLES_OPTIMIZED_KERNEL_AVX2
-# endif
+# ifdef WITH_KERNEL_AVX2
+# define WITH_CYCLES_OPTIMIZED_KERNEL_AVX2
+# endif
-#endif /* defined(__x86_64__) || defined(_M_X64) */
+# endif /* defined(__x86_64__) || defined(_M_X64) */
#endif
-#endif /* __UTIL_OPTIMIZATION_H__ */
+#endif /* __UTIL_OPTIMIZATION_H__ */
diff --git a/intern/cycles/util/util_param.h b/intern/cycles/util/util_param.h
index 03815486429..cfbe416aba1 100644
--- a/intern/cycles/util/util_param.h
+++ b/intern/cycles/util/util_param.h
@@ -32,4 +32,4 @@ static constexpr TypeDesc TypeFloat2(TypeDesc::FLOAT, TypeDesc::VEC2);
CCL_NAMESPACE_END
-#endif /* __UTIL_PARAM_H__ */
+#endif /* __UTIL_PARAM_H__ */
diff --git a/intern/cycles/util/util_path.cpp b/intern/cycles/util/util_path.cpp
index 93080a6c80c..77293c45f6b 100644
--- a/intern/cycles/util/util_path.cpp
+++ b/intern/cycles/util/util_path.cpp
@@ -58,7 +58,7 @@ typedef struct _stati64 path_stat_t;
typedef struct _stat path_stat_t;
# endif
# ifndef S_ISDIR
-# define S_ISDIR(x) (((x) & _S_IFDIR) == _S_IFDIR)
+# define S_ISDIR(x) (((x)&_S_IFDIR) == _S_IFDIR)
# endif
#else
typedef struct stat path_stat_t;
@@ -72,918 +72,870 @@ namespace {
#ifdef _WIN32
class directory_iterator {
-public:
- class path_info {
- public:
- path_info(const string& path,
- const WIN32_FIND_DATAW& find_data)
- : path_(path),
- find_data_(find_data)
- {
- }
-
- string path() {
- return path_join(path_, string_from_wstring(find_data_.cFileName));
- }
- protected:
- const string& path_;
- const WIN32_FIND_DATAW& find_data_;
- };
-
- directory_iterator()
- : path_info_("", find_data_),
- h_find_(INVALID_HANDLE_VALUE)
- {
- }
-
- explicit directory_iterator(const string& path)
- : path_(path),
- path_info_(path, find_data_)
- {
- string wildcard = path;
- if(wildcard[wildcard.size() - 1] != DIR_SEP) {
- wildcard += DIR_SEP;
- }
- wildcard += "*";
- h_find_ = FindFirstFileW(string_to_wstring(wildcard).c_str(),
- &find_data_);
- if(h_find_ != INVALID_HANDLE_VALUE) {
- skip_dots();
- }
- }
-
- ~directory_iterator()
- {
- if(h_find_ != INVALID_HANDLE_VALUE) {
- FindClose(h_find_);
- }
- }
-
- directory_iterator& operator++()
- {
- step();
- return *this;
- }
-
- path_info* operator-> ()
- {
- return &path_info_;
- }
-
- bool operator!=(const directory_iterator& other)
- {
- return h_find_ != other.h_find_;
- }
-
-protected:
- bool step()
- {
- if(do_step()) {
- return skip_dots();
- }
- return false;
- }
-
- bool do_step()
- {
- if(h_find_ != INVALID_HANDLE_VALUE) {
- bool result = FindNextFileW(h_find_, &find_data_) == TRUE;
- if(!result) {
- FindClose(h_find_);
- h_find_ = INVALID_HANDLE_VALUE;
- }
- return result;
- }
- return false;
- }
-
- bool skip_dots()
- {
- while(wcscmp(find_data_.cFileName, L".") == 0 ||
- wcscmp(find_data_.cFileName, L"..") == 0)
- {
- if(!do_step()) {
- return false;
- }
- }
- return true;
- }
-
- string path_;
- path_info path_info_;
- WIN32_FIND_DATAW find_data_;
- HANDLE h_find_;
+ public:
+ class path_info {
+ public:
+ path_info(const string &path, const WIN32_FIND_DATAW &find_data)
+ : path_(path), find_data_(find_data)
+ {
+ }
+
+ string path()
+ {
+ return path_join(path_, string_from_wstring(find_data_.cFileName));
+ }
+
+ protected:
+ const string &path_;
+ const WIN32_FIND_DATAW &find_data_;
+ };
+
+ directory_iterator() : path_info_("", find_data_), h_find_(INVALID_HANDLE_VALUE)
+ {
+ }
+
+ explicit directory_iterator(const string &path) : path_(path), path_info_(path, find_data_)
+ {
+ string wildcard = path;
+ if (wildcard[wildcard.size() - 1] != DIR_SEP) {
+ wildcard += DIR_SEP;
+ }
+ wildcard += "*";
+ h_find_ = FindFirstFileW(string_to_wstring(wildcard).c_str(), &find_data_);
+ if (h_find_ != INVALID_HANDLE_VALUE) {
+ skip_dots();
+ }
+ }
+
+ ~directory_iterator()
+ {
+ if (h_find_ != INVALID_HANDLE_VALUE) {
+ FindClose(h_find_);
+ }
+ }
+
+ directory_iterator &operator++()
+ {
+ step();
+ return *this;
+ }
+
+ path_info *operator->()
+ {
+ return &path_info_;
+ }
+
+ bool operator!=(const directory_iterator &other)
+ {
+ return h_find_ != other.h_find_;
+ }
+
+ protected:
+ bool step()
+ {
+ if (do_step()) {
+ return skip_dots();
+ }
+ return false;
+ }
+
+ bool do_step()
+ {
+ if (h_find_ != INVALID_HANDLE_VALUE) {
+ bool result = FindNextFileW(h_find_, &find_data_) == TRUE;
+ if (!result) {
+ FindClose(h_find_);
+ h_find_ = INVALID_HANDLE_VALUE;
+ }
+ return result;
+ }
+ return false;
+ }
+
+ bool skip_dots()
+ {
+ while (wcscmp(find_data_.cFileName, L".") == 0 || wcscmp(find_data_.cFileName, L"..") == 0) {
+ if (!do_step()) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ string path_;
+ path_info path_info_;
+ WIN32_FIND_DATAW find_data_;
+ HANDLE h_find_;
};
-#else /* _WIN32 */
+#else /* _WIN32 */
class directory_iterator {
-public:
- class path_info {
- public:
- explicit path_info(const string& path)
- : path_(path),
- entry_(NULL)
- {
- }
-
- string path() {
- return path_join(path_, entry_->d_name);
- }
-
- void current_entry_set(const struct dirent *entry)
- {
- entry_ = entry;
- }
- protected:
- const string& path_;
- const struct dirent *entry_;
- };
-
- directory_iterator()
- : path_info_(""),
- name_list_(NULL),
- num_entries_(-1),
- cur_entry_(-1)
- {
- }
-
- explicit directory_iterator(const string& path)
- : path_(path),
- path_info_(path_),
- cur_entry_(0)
- {
- num_entries_ = scandir(path.c_str(),
- &name_list_,
- NULL,
- alphasort);
- if(num_entries_ < 0) {
- perror("scandir");
- }
- else {
- skip_dots();
- }
- }
-
- ~directory_iterator()
- {
- destroy_name_list();
- }
-
- directory_iterator& operator++()
- {
- step();
- return *this;
- }
-
- path_info* operator-> ()
- {
- path_info_.current_entry_set(name_list_[cur_entry_]);
- return &path_info_;
- }
-
- bool operator!=(const directory_iterator& other)
- {
- return name_list_ != other.name_list_;
- }
-
-protected:
- bool step()
- {
- if(do_step()) {
- return skip_dots();
- }
- return false;
- }
-
- bool do_step()
- {
- ++cur_entry_;
- if(cur_entry_ >= num_entries_) {
- destroy_name_list();
- return false;
- }
- return true;
- }
-
- /* Skip . and .. folders. */
- bool skip_dots()
- {
- while(strcmp(name_list_[cur_entry_]->d_name, ".") == 0 ||
- strcmp(name_list_[cur_entry_]->d_name, "..") == 0)
- {
- if(!step()) {
- return false;
- }
- }
- return true;
- }
-
- void destroy_name_list()
- {
- if(name_list_ == NULL) {
- return;
- }
- for(int i = 0; i < num_entries_; ++i) {
- free(name_list_[i]);
- }
- free(name_list_);
- name_list_ = NULL;
- }
-
- string path_;
- path_info path_info_;
- struct dirent **name_list_;
- int num_entries_, cur_entry_;
+ public:
+ class path_info {
+ public:
+ explicit path_info(const string &path) : path_(path), entry_(NULL)
+ {
+ }
+
+ string path()
+ {
+ return path_join(path_, entry_->d_name);
+ }
+
+ void current_entry_set(const struct dirent *entry)
+ {
+ entry_ = entry;
+ }
+
+ protected:
+ const string &path_;
+ const struct dirent *entry_;
+ };
+
+ directory_iterator() : path_info_(""), name_list_(NULL), num_entries_(-1), cur_entry_(-1)
+ {
+ }
+
+ explicit directory_iterator(const string &path) : path_(path), path_info_(path_), cur_entry_(0)
+ {
+ num_entries_ = scandir(path.c_str(), &name_list_, NULL, alphasort);
+ if (num_entries_ < 0) {
+ perror("scandir");
+ }
+ else {
+ skip_dots();
+ }
+ }
+
+ ~directory_iterator()
+ {
+ destroy_name_list();
+ }
+
+ directory_iterator &operator++()
+ {
+ step();
+ return *this;
+ }
+
+ path_info *operator->()
+ {
+ path_info_.current_entry_set(name_list_[cur_entry_]);
+ return &path_info_;
+ }
+
+ bool operator!=(const directory_iterator &other)
+ {
+ return name_list_ != other.name_list_;
+ }
+
+ protected:
+ bool step()
+ {
+ if (do_step()) {
+ return skip_dots();
+ }
+ return false;
+ }
+
+ bool do_step()
+ {
+ ++cur_entry_;
+ if (cur_entry_ >= num_entries_) {
+ destroy_name_list();
+ return false;
+ }
+ return true;
+ }
+
+ /* Skip . and .. folders. */
+ bool skip_dots()
+ {
+ while (strcmp(name_list_[cur_entry_]->d_name, ".") == 0 ||
+ strcmp(name_list_[cur_entry_]->d_name, "..") == 0) {
+ if (!step()) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ void destroy_name_list()
+ {
+ if (name_list_ == NULL) {
+ return;
+ }
+ for (int i = 0; i < num_entries_; ++i) {
+ free(name_list_[i]);
+ }
+ free(name_list_);
+ name_list_ = NULL;
+ }
+
+ string path_;
+ path_info path_info_;
+ struct dirent **name_list_;
+ int num_entries_, cur_entry_;
};
-#endif /* _WIN32 */
+#endif /* _WIN32 */
-size_t find_last_slash(const string& path)
+size_t find_last_slash(const string &path)
{
- for(size_t i = 0; i < path.size(); ++i) {
- size_t index = path.size() - 1 - i;
+ for (size_t i = 0; i < path.size(); ++i) {
+ size_t index = path.size() - 1 - i;
#ifdef _WIN32
- if(path[index] == DIR_SEP || path[index] == DIR_SEP_ALT)
+ if (path[index] == DIR_SEP || path[index] == DIR_SEP_ALT)
#else
- if(path[index] == DIR_SEP)
+ if (path[index] == DIR_SEP)
#endif
- {
- return index;
- }
- }
- return string::npos;
-}
-
-} /* namespace */
-
-static char *path_specials(const string& sub)
-{
- static bool env_init = false;
- static char *env_shader_path;
- static char *env_source_path;
- if(!env_init) {
- env_shader_path = getenv("CYCLES_SHADER_PATH");
- /* NOTE: It is KERNEL in env variable for compatibility reasons. */
- env_source_path = getenv("CYCLES_KERNEL_PATH");
- env_init = true;
- }
- if(env_shader_path != NULL && sub == "shader") {
- return env_shader_path;
- }
- else if(env_shader_path != NULL && sub == "source") {
- return env_source_path;
- }
- return NULL;
+ {
+ return index;
+ }
+ }
+ return string::npos;
+}
+
+} /* namespace */
+
+static char *path_specials(const string &sub)
+{
+ static bool env_init = false;
+ static char *env_shader_path;
+ static char *env_source_path;
+ if (!env_init) {
+ env_shader_path = getenv("CYCLES_SHADER_PATH");
+ /* NOTE: It is KERNEL in env variable for compatibility reasons. */
+ env_source_path = getenv("CYCLES_KERNEL_PATH");
+ env_init = true;
+ }
+ if (env_shader_path != NULL && sub == "shader") {
+ return env_shader_path;
+ }
+ else if (env_shader_path != NULL && sub == "source") {
+ return env_source_path;
+ }
+ return NULL;
}
#if defined(__linux__) || defined(__APPLE__)
static string path_xdg_cache_get()
{
- const char *home = getenv("XDG_CACHE_HOME");
- if(home) {
- return string(home);
- }
- else {
- home = getenv("HOME");
- if(home == NULL) {
- home = getpwuid(getuid())->pw_dir;
- }
- return path_join(string(home), ".cache");
- }
+ const char *home = getenv("XDG_CACHE_HOME");
+ if (home) {
+ return string(home);
+ }
+ else {
+ home = getenv("HOME");
+ if (home == NULL) {
+ home = getpwuid(getuid())->pw_dir;
+ }
+ return path_join(string(home), ".cache");
+ }
}
#endif
-void path_init(const string& path, const string& user_path)
+void path_init(const string &path, const string &user_path)
{
- cached_path = path;
- cached_user_path = user_path;
+ cached_path = path;
+ cached_user_path = user_path;
#ifdef _MSC_VER
- // workaround for https://svn.boost.org/trac/boost/ticket/6320
- // indirectly init boost codec here since it's not thread safe, and can
- // cause crashes when it happens in multithreaded image load
- OIIO::Filesystem::exists(path);
+ // workaround for https://svn.boost.org/trac/boost/ticket/6320
+ // indirectly init boost codec here since it's not thread safe, and can
+ // cause crashes when it happens in multithreaded image load
+ OIIO::Filesystem::exists(path);
#endif
}
-string path_get(const string& sub)
+string path_get(const string &sub)
{
- char *special = path_specials(sub);
- if(special != NULL)
- return special;
+ char *special = path_specials(sub);
+ if (special != NULL)
+ return special;
- if(cached_path == "")
- cached_path = path_dirname(Sysutil::this_program_path());
+ if (cached_path == "")
+ cached_path = path_dirname(Sysutil::this_program_path());
- return path_join(cached_path, sub);
+ return path_join(cached_path, sub);
}
-string path_user_get(const string& sub)
+string path_user_get(const string &sub)
{
- if(cached_user_path == "")
- cached_user_path = path_dirname(Sysutil::this_program_path());
+ if (cached_user_path == "")
+ cached_user_path = path_dirname(Sysutil::this_program_path());
- return path_join(cached_user_path, sub);
+ return path_join(cached_user_path, sub);
}
-string path_cache_get(const string& sub)
+string path_cache_get(const string &sub)
{
#if defined(__linux__) || defined(__APPLE__)
- if(cached_xdg_cache_path == "") {
- cached_xdg_cache_path = path_xdg_cache_get();
- }
- string result = path_join(cached_xdg_cache_path, "cycles");
- return path_join(result, sub);
+ if (cached_xdg_cache_path == "") {
+ cached_xdg_cache_path = path_xdg_cache_get();
+ }
+ string result = path_join(cached_xdg_cache_path, "cycles");
+ return path_join(result, sub);
#else
- /* TODO(sergey): What that should be on Windows? */
- return path_user_get(path_join("cache", sub));
+ /* TODO(sergey): What that should be on Windows? */
+ return path_user_get(path_join("cache", sub));
#endif
}
#if defined(__linux__) || defined(__APPLE__)
-string path_xdg_home_get(const string& sub = "");
+string path_xdg_home_get(const string &sub = "");
#endif
-string path_filename(const string& path)
+string path_filename(const string &path)
{
- size_t index = find_last_slash(path);
- if(index != string::npos) {
- /* Corner cases to match boost behavior. */
+ size_t index = find_last_slash(path);
+ if (index != string::npos) {
+ /* Corner cases to match boost behavior. */
#ifndef _WIN32
- if(index == 0 && path.size() == 1) {
- return path;
- }
+ if (index == 0 && path.size() == 1) {
+ return path;
+ }
#endif
- if(index == path.size() - 1) {
+ if (index == path.size() - 1) {
#ifdef _WIN32
- if(index == 2) {
- return string(1, DIR_SEP);
- }
+ if (index == 2) {
+ return string(1, DIR_SEP);
+ }
#endif
- return ".";
- }
- return path.substr(index + 1, path.size() - index - 1);
- }
- return path;
+ return ".";
+ }
+ return path.substr(index + 1, path.size() - index - 1);
+ }
+ return path;
}
-string path_dirname(const string& path)
+string path_dirname(const string &path)
{
- size_t index = find_last_slash(path);
- if(index != string::npos) {
+ size_t index = find_last_slash(path);
+ if (index != string::npos) {
#ifndef _WIN32
- if(index == 0 && path.size() > 1) {
- return string(1, DIR_SEP);
- }
+ if (index == 0 && path.size() > 1) {
+ return string(1, DIR_SEP);
+ }
#endif
- return path.substr(0, index);
- }
- return "";
+ return path.substr(0, index);
+ }
+ return "";
}
-string path_join(const string& dir, const string& file)
+string path_join(const string &dir, const string &file)
{
- if(dir.size() == 0) {
- return file;
- }
- if(file.size() == 0) {
- return dir;
- }
- string result = dir;
+ if (dir.size() == 0) {
+ return file;
+ }
+ if (file.size() == 0) {
+ return dir;
+ }
+ string result = dir;
#ifndef _WIN32
- if(result[result.size() - 1] != DIR_SEP &&
- file[0] != DIR_SEP)
+ if (result[result.size() - 1] != DIR_SEP && file[0] != DIR_SEP)
#else
- if(result[result.size() - 1] != DIR_SEP &&
- result[result.size() - 1] != DIR_SEP_ALT &&
- file[0] != DIR_SEP &&
- file[0] != DIR_SEP_ALT)
+ if (result[result.size() - 1] != DIR_SEP && result[result.size() - 1] != DIR_SEP_ALT &&
+ file[0] != DIR_SEP && file[0] != DIR_SEP_ALT)
#endif
- {
- result += DIR_SEP;
- }
- result += file;
- return result;
+ {
+ result += DIR_SEP;
+ }
+ result += file;
+ return result;
}
-string path_escape(const string& path)
+string path_escape(const string &path)
{
- string result = path;
- string_replace(result, " ", "\\ ");
- return result;
+ string result = path;
+ string_replace(result, " ", "\\ ");
+ return result;
}
-bool path_is_relative(const string& path)
+bool path_is_relative(const string &path)
{
#ifdef _WIN32
# ifdef HAVE_SHLWAPI_H
- return PathIsRelative(path.c_str());
+ return PathIsRelative(path.c_str());
# else /* HAVE_SHLWAPI_H */
- if(path.size() >= 3) {
- return !(((path[0] >= 'a' && path[0] <= 'z') ||
- (path[0] >= 'A' && path[0] <= 'Z')) &&
- path[1] == ':' && path[2] == DIR_SEP);
- }
- return true;
-# endif /* HAVE_SHLWAPI_H */
-#else /* _WIN32 */
- if(path.size() == 0) {
- return 1;
- }
- return path[0] != DIR_SEP;
-#endif /* _WIN32 */
+ if (path.size() >= 3) {
+ return !(((path[0] >= 'a' && path[0] <= 'z') || (path[0] >= 'A' && path[0] <= 'Z')) &&
+ path[1] == ':' && path[2] == DIR_SEP);
+ }
+ return true;
+# endif /* HAVE_SHLWAPI_H */
+#else /* _WIN32 */
+ if (path.size() == 0) {
+ return 1;
+ }
+ return path[0] != DIR_SEP;
+#endif /* _WIN32 */
}
#ifdef _WIN32
/* Add a slash if the UNC path points to a share. */
-static string path_unc_add_slash_to_share(const string& path)
+static string path_unc_add_slash_to_share(const string &path)
{
- size_t slash_after_server = path.find(DIR_SEP, 2);
- if(slash_after_server != string::npos) {
- size_t slash_after_share = path.find(DIR_SEP,
- slash_after_server + 1);
- if(slash_after_share == string::npos) {
- return path + DIR_SEP;
- }
- }
- return path;
+ size_t slash_after_server = path.find(DIR_SEP, 2);
+ if (slash_after_server != string::npos) {
+ size_t slash_after_share = path.find(DIR_SEP, slash_after_server + 1);
+ if (slash_after_share == string::npos) {
+ return path + DIR_SEP;
+ }
+ }
+ return path;
}
/* Convert:
* \\?\UNC\server\share\folder\... to \\server\share\folder\...
* \\?\C:\ to C:\ and \\?\C:\folder\... to C:\folder\...
*/
-static string path_unc_to_short(const string& path)
-{
- size_t len = path.size();
- if((len > 3) &&
- (path[0] == DIR_SEP) &&
- (path[1] == DIR_SEP) &&
- (path[2] == '?') &&
- ((path[3] == DIR_SEP) || (path[3] == DIR_SEP_ALT)))
- {
- if((len > 5) && (path[5] == ':')) {
- return path.substr(4, len - 4);
- }
- else if((len > 7) &&
- (path.substr(4, 3) == "UNC") &&
- ((path[7] == DIR_SEP) || (path[7] == DIR_SEP_ALT)))
- {
- return "\\\\" + path.substr(8, len - 8);
- }
- }
- return path;
-}
-
-static string path_cleanup_unc(const string& path)
-{
- string result = path_unc_to_short(path);
- if(path.size() > 2) {
- /* It's possible path is now a non-UNC. */
- if(result[0] == DIR_SEP && result[1] == DIR_SEP) {
- return path_unc_add_slash_to_share(result);
- }
- }
- return result;
+static string path_unc_to_short(const string &path)
+{
+ size_t len = path.size();
+ if ((len > 3) && (path[0] == DIR_SEP) && (path[1] == DIR_SEP) && (path[2] == '?') &&
+ ((path[3] == DIR_SEP) || (path[3] == DIR_SEP_ALT))) {
+ if ((len > 5) && (path[5] == ':')) {
+ return path.substr(4, len - 4);
+ }
+ else if ((len > 7) && (path.substr(4, 3) == "UNC") &&
+ ((path[7] == DIR_SEP) || (path[7] == DIR_SEP_ALT))) {
+ return "\\\\" + path.substr(8, len - 8);
+ }
+ }
+ return path;
+}
+
+static string path_cleanup_unc(const string &path)
+{
+ string result = path_unc_to_short(path);
+ if (path.size() > 2) {
+ /* It's possible path is now a non-UNC. */
+ if (result[0] == DIR_SEP && result[1] == DIR_SEP) {
+ return path_unc_add_slash_to_share(result);
+ }
+ }
+ return result;
}
/* Make path compatible for stat() functions. */
-static string path_make_compatible(const string& path)
-{
- string result = path;
- /* In Windows stat() doesn't recognize dir ending on a slash. */
- if(result.size() > 3 && result[result.size() - 1] == DIR_SEP) {
- result.resize(result.size() - 1);
- }
- /* Clean up UNC path. */
- if((path.size() >= 3) && (path[0] == DIR_SEP) && (path[1] == DIR_SEP)) {
- result = path_cleanup_unc(result);
- }
- /* Make sure volume-only path ends up wit ha directory separator. */
- if(result.size() == 2 && result[1] == ':') {
- result += DIR_SEP;
- }
- return result;
-}
-
-static int path_wstat(const wstring& path_wc, path_stat_t *st)
-{
-#if defined(_MSC_VER) || defined(__MINGW64__)
- return _wstat64(path_wc.c_str(), st);
-#elif defined(__MINGW32__)
- return _wstati64(path_wc.c_str(), st);
-#else
- return _wstat(path_wc.c_str(), st);
-#endif
+static string path_make_compatible(const string &path)
+{
+ string result = path;
+ /* In Windows stat() doesn't recognize dir ending on a slash. */
+ if (result.size() > 3 && result[result.size() - 1] == DIR_SEP) {
+ result.resize(result.size() - 1);
+ }
+ /* Clean up UNC path. */
+ if ((path.size() >= 3) && (path[0] == DIR_SEP) && (path[1] == DIR_SEP)) {
+ result = path_cleanup_unc(result);
+ }
+ /* Make sure volume-only path ends up wit ha directory separator. */
+ if (result.size() == 2 && result[1] == ':') {
+ result += DIR_SEP;
+ }
+ return result;
+}
+
+static int path_wstat(const wstring &path_wc, path_stat_t *st)
+{
+# if defined(_MSC_VER) || defined(__MINGW64__)
+ return _wstat64(path_wc.c_str(), st);
+# elif defined(__MINGW32__)
+ return _wstati64(path_wc.c_str(), st);
+# else
+ return _wstat(path_wc.c_str(), st);
+# endif
}
-static int path_stat(const string& path, path_stat_t *st)
+static int path_stat(const string &path, path_stat_t *st)
{
- wstring path_wc = string_to_wstring(path);
- return path_wstat(path_wc, st);
+ wstring path_wc = string_to_wstring(path);
+ return path_wstat(path_wc, st);
}
#else /* _WIN32 */
-static int path_stat(const string& path, path_stat_t *st)
+static int path_stat(const string &path, path_stat_t *st)
{
- return stat(path.c_str(), st);
+ return stat(path.c_str(), st);
}
-#endif /* _WIN32 */
+#endif /* _WIN32 */
-size_t path_file_size(const string& path)
+size_t path_file_size(const string &path)
{
- path_stat_t st;
- if(path_stat(path, &st) != 0) {
- return -1;
- }
- return st.st_size;
+ path_stat_t st;
+ if (path_stat(path, &st) != 0) {
+ return -1;
+ }
+ return st.st_size;
}
-bool path_exists(const string& path)
+bool path_exists(const string &path)
{
#ifdef _WIN32
- string fixed_path = path_make_compatible(path);
- wstring path_wc = string_to_wstring(fixed_path);
- path_stat_t st;
- if(path_wstat(path_wc, &st) != 0) {
- return false;
- }
- return st.st_mode != 0;
+ string fixed_path = path_make_compatible(path);
+ wstring path_wc = string_to_wstring(fixed_path);
+ path_stat_t st;
+ if (path_wstat(path_wc, &st) != 0) {
+ return false;
+ }
+ return st.st_mode != 0;
#else /* _WIN32 */
- struct stat st;
- if(stat(path.c_str(), &st) != 0) {
- return 0;
- }
- return st.st_mode != 0;
-#endif /* _WIN32 */
+ struct stat st;
+ if (stat(path.c_str(), &st) != 0) {
+ return 0;
+ }
+ return st.st_mode != 0;
+#endif /* _WIN32 */
}
-bool path_is_directory(const string& path)
+bool path_is_directory(const string &path)
{
- path_stat_t st;
- if(path_stat(path, &st) != 0) {
- return false;
- }
- return S_ISDIR(st.st_mode);
+ path_stat_t st;
+ if (path_stat(path, &st) != 0) {
+ return false;
+ }
+ return S_ISDIR(st.st_mode);
}
-static void path_files_md5_hash_recursive(MD5Hash& hash, const string& dir)
+static void path_files_md5_hash_recursive(MD5Hash &hash, const string &dir)
{
- if(path_exists(dir)) {
- directory_iterator it(dir), it_end;
+ if (path_exists(dir)) {
+ directory_iterator it(dir), it_end;
- for(; it != it_end; ++it) {
- if(path_is_directory(it->path())) {
- path_files_md5_hash_recursive(hash, it->path());
- }
- else {
- string filepath = it->path();
+ for (; it != it_end; ++it) {
+ if (path_is_directory(it->path())) {
+ path_files_md5_hash_recursive(hash, it->path());
+ }
+ else {
+ string filepath = it->path();
- hash.append((const uint8_t*)filepath.c_str(), filepath.size());
- hash.append_file(filepath);
- }
- }
- }
+ hash.append((const uint8_t *)filepath.c_str(), filepath.size());
+ hash.append_file(filepath);
+ }
+ }
+ }
}
-string path_files_md5_hash(const string& dir)
+string path_files_md5_hash(const string &dir)
{
- /* computes md5 hash of all files in the directory */
- MD5Hash hash;
+ /* computes md5 hash of all files in the directory */
+ MD5Hash hash;
- path_files_md5_hash_recursive(hash, dir);
+ path_files_md5_hash_recursive(hash, dir);
- return hash.get_hex();
+ return hash.get_hex();
}
-static bool create_directories_recursivey(const string& path)
+static bool create_directories_recursivey(const string &path)
{
- if(path_is_directory(path)) {
- /* Directory already exists, nothing to do. */
- return true;
- }
- if(path_exists(path)) {
- /* File exists and it's not a directory. */
- return false;
- }
+ if (path_is_directory(path)) {
+ /* Directory already exists, nothing to do. */
+ return true;
+ }
+ if (path_exists(path)) {
+ /* File exists and it's not a directory. */
+ return false;
+ }
- string parent = path_dirname(path);
- if(parent.size() > 0 && parent != path) {
- if(!create_directories_recursivey(parent)) {
- return false;
- }
- }
+ string parent = path_dirname(path);
+ if (parent.size() > 0 && parent != path) {
+ if (!create_directories_recursivey(parent)) {
+ return false;
+ }
+ }
#ifdef _WIN32
- wstring path_wc = string_to_wstring(path);
- return _wmkdir(path_wc.c_str()) == 0;
+ wstring path_wc = string_to_wstring(path);
+ return _wmkdir(path_wc.c_str()) == 0;
#else
- return mkdir(path.c_str(), 0777) == 0;
+ return mkdir(path.c_str(), 0777) == 0;
#endif
}
-void path_create_directories(const string& filepath)
+void path_create_directories(const string &filepath)
{
- string path = path_dirname(filepath);
- create_directories_recursivey(path);
+ string path = path_dirname(filepath);
+ create_directories_recursivey(path);
}
-bool path_write_binary(const string& path, const vector<uint8_t>& binary)
+bool path_write_binary(const string &path, const vector<uint8_t> &binary)
{
- path_create_directories(path);
+ path_create_directories(path);
- /* write binary file from memory */
- FILE *f = path_fopen(path, "wb");
+ /* write binary file from memory */
+ FILE *f = path_fopen(path, "wb");
- if(!f)
- return false;
+ if (!f)
+ return false;
- if(binary.size() > 0)
- fwrite(&binary[0], sizeof(uint8_t), binary.size(), f);
+ if (binary.size() > 0)
+ fwrite(&binary[0], sizeof(uint8_t), binary.size(), f);
- fclose(f);
+ fclose(f);
- return true;
+ return true;
}
-bool path_write_text(const string& path, string& text)
+bool path_write_text(const string &path, string &text)
{
- vector<uint8_t> binary(text.length(), 0);
- std::copy(text.begin(), text.end(), binary.begin());
+ vector<uint8_t> binary(text.length(), 0);
+ std::copy(text.begin(), text.end(), binary.begin());
- return path_write_binary(path, binary);
+ return path_write_binary(path, binary);
}
-bool path_read_binary(const string& path, vector<uint8_t>& binary)
+bool path_read_binary(const string &path, vector<uint8_t> &binary)
{
- /* read binary file into memory */
- FILE *f = path_fopen(path, "rb");
+ /* read binary file into memory */
+ FILE *f = path_fopen(path, "rb");
- if(!f) {
- binary.resize(0);
- return false;
- }
+ if (!f) {
+ binary.resize(0);
+ return false;
+ }
- binary.resize(path_file_size(path));
+ binary.resize(path_file_size(path));
- if(binary.size() == 0) {
- fclose(f);
- return false;
- }
+ if (binary.size() == 0) {
+ fclose(f);
+ return false;
+ }
- if(fread(&binary[0], sizeof(uint8_t), binary.size(), f) != binary.size()) {
- fclose(f);
- return false;
- }
+ if (fread(&binary[0], sizeof(uint8_t), binary.size(), f) != binary.size()) {
+ fclose(f);
+ return false;
+ }
- fclose(f);
+ fclose(f);
- return true;
+ return true;
}
-bool path_read_text(const string& path, string& text)
+bool path_read_text(const string &path, string &text)
{
- vector<uint8_t> binary;
+ vector<uint8_t> binary;
- if(!path_exists(path) || !path_read_binary(path, binary))
- return false;
+ if (!path_exists(path) || !path_read_binary(path, binary))
+ return false;
- const char *str = (const char*)&binary[0];
- size_t size = binary.size();
- text = string(str, size);
+ const char *str = (const char *)&binary[0];
+ size_t size = binary.size();
+ text = string(str, size);
- return true;
+ return true;
}
-uint64_t path_modified_time(const string& path)
+uint64_t path_modified_time(const string &path)
{
- path_stat_t st;
- if(path_stat(path, &st) != 0) {
- return 0;
- }
- return st.st_mtime;
+ path_stat_t st;
+ if (path_stat(path, &st) != 0) {
+ return 0;
+ }
+ return st.st_mtime;
}
-bool path_remove(const string& path)
+bool path_remove(const string &path)
{
- return remove(path.c_str()) == 0;
+ return remove(path.c_str()) == 0;
}
struct SourceReplaceState {
- typedef map<string, string> ProcessedMapping;
- /* Base director for all relative include headers. */
- string base;
- /* Result of processed files. */
- ProcessedMapping processed_files;
- /* Set of files which are considered "precompiled" and which are replaced
- * with and empty string on a subsequent occurrence in include statement.
- */
- set<string> precompiled_headers;
+ typedef map<string, string> ProcessedMapping;
+ /* Base director for all relative include headers. */
+ string base;
+ /* Result of processed files. */
+ ProcessedMapping processed_files;
+ /* Set of files which are considered "precompiled" and which are replaced
+ * with and empty string on a subsequent occurrence in include statement.
+ */
+ set<string> precompiled_headers;
};
-static string path_source_replace_includes_recursive(
- const string& source,
- const string& source_filepath,
- SourceReplaceState *state);
-
-static string line_directive(const SourceReplaceState& state,
- const string& path,
- const int line)
-{
- string unescaped_path = path;
- /* First we make path relative. */
- if(string_startswith(unescaped_path, state.base.c_str())) {
- const string base_file = path_filename(state.base);
- const size_t base_len = state.base.length();
- unescaped_path = base_file +
- unescaped_path.substr(base_len,
- unescaped_path.length() - base_len);
- }
- /* Second, we replace all unsafe characters. */
- const size_t length = unescaped_path.length();
- string escaped_path = "";
- for(size_t i = 0; i < length; ++i) {
- const char ch = unescaped_path[i];
- if(strchr("\"\'\?\\", ch) != NULL) {
- escaped_path += "\\";
- }
- escaped_path += ch;
- }
- /* TODO(sergey): Check whether using std::to_string combined with several
- * concatenation operations is any faster.
- */
- return string_printf("#line %d \"%s\"", line, escaped_path.c_str());
-}
-
-static string path_source_handle_preprocessor(
- const string& preprocessor_line,
- const string& source_filepath,
- const size_t line_number,
- SourceReplaceState *state)
-{
- string result = preprocessor_line;
- string token = string_strip(
- preprocessor_line.substr(1, preprocessor_line.size() - 1));
- if(string_startswith(token, "include")) {
- token = string_strip(token.substr(7, token.size() - 7));
- if(token[0] == '"') {
- const size_t n_start = 1;
- const size_t n_end = token.find("\"", n_start);
- const string filename = token.substr(n_start, n_end - n_start);
- const bool is_precompiled = string_endswith(token, "// PRECOMPILED");
- string filepath = path_join(state->base, filename);
- if(!path_exists(filepath)) {
- filepath = path_join(path_dirname(source_filepath),
- filename);
- }
- if(is_precompiled) {
- state->precompiled_headers.insert(filepath);
- }
- string text;
- if(path_read_text(filepath, text)) {
- text = path_source_replace_includes_recursive(
- text, filepath, state);
- /* Use line directives for better error messages. */
- result = line_directive(*state, filepath, 1) + "\n"
- + text + "\n"
- + line_directive(*state, source_filepath, line_number + 1);
- }
- }
- }
- return result;
+static string path_source_replace_includes_recursive(const string &source,
+ const string &source_filepath,
+ SourceReplaceState *state);
+
+static string line_directive(const SourceReplaceState &state, const string &path, const int line)
+{
+ string unescaped_path = path;
+ /* First we make path relative. */
+ if (string_startswith(unescaped_path, state.base.c_str())) {
+ const string base_file = path_filename(state.base);
+ const size_t base_len = state.base.length();
+ unescaped_path = base_file +
+ unescaped_path.substr(base_len, unescaped_path.length() - base_len);
+ }
+ /* Second, we replace all unsafe characters. */
+ const size_t length = unescaped_path.length();
+ string escaped_path = "";
+ for (size_t i = 0; i < length; ++i) {
+ const char ch = unescaped_path[i];
+ if (strchr("\"\'\?\\", ch) != NULL) {
+ escaped_path += "\\";
+ }
+ escaped_path += ch;
+ }
+ /* TODO(sergey): Check whether using std::to_string combined with several
+ * concatenation operations is any faster.
+ */
+ return string_printf("#line %d \"%s\"", line, escaped_path.c_str());
+}
+
+static string path_source_handle_preprocessor(const string &preprocessor_line,
+ const string &source_filepath,
+ const size_t line_number,
+ SourceReplaceState *state)
+{
+ string result = preprocessor_line;
+ string token = string_strip(preprocessor_line.substr(1, preprocessor_line.size() - 1));
+ if (string_startswith(token, "include")) {
+ token = string_strip(token.substr(7, token.size() - 7));
+ if (token[0] == '"') {
+ const size_t n_start = 1;
+ const size_t n_end = token.find("\"", n_start);
+ const string filename = token.substr(n_start, n_end - n_start);
+ const bool is_precompiled = string_endswith(token, "// PRECOMPILED");
+ string filepath = path_join(state->base, filename);
+ if (!path_exists(filepath)) {
+ filepath = path_join(path_dirname(source_filepath), filename);
+ }
+ if (is_precompiled) {
+ state->precompiled_headers.insert(filepath);
+ }
+ string text;
+ if (path_read_text(filepath, text)) {
+ text = path_source_replace_includes_recursive(text, filepath, state);
+ /* Use line directives for better error messages. */
+ result = line_directive(*state, filepath, 1) + "\n" + text + "\n" +
+ line_directive(*state, source_filepath, line_number + 1);
+ }
+ }
+ }
+ return result;
}
/* Our own little c preprocessor that replaces #includes with the file
* contents, to work around issue of OpenCL drivers not supporting
* include paths with spaces in them.
*/
-static string path_source_replace_includes_recursive(
- const string& source,
- const string& source_filepath,
- SourceReplaceState *state)
-{
- /* Try to re-use processed file without spending time on replacing all
- * include directives again.
- */
- SourceReplaceState::ProcessedMapping::iterator replaced_file =
- state->processed_files.find(source_filepath);
- if(replaced_file != state->processed_files.end()) {
- if(state->precompiled_headers.find(source_filepath) !=
- state->precompiled_headers.end()) {
- return "";
- }
- return replaced_file->second;
- }
- /* Perform full file processing. */
- string result = "";
- const size_t source_length = source.length();
- size_t index = 0;
- /* Information about where we are in the source. */
- size_t line_number = 0, column_number = 1;
- /* Currently gathered non-preprocessor token.
- * Store as start/length rather than token itself to avoid overhead of
- * memory re-allocations on each character concatenation.
- */
- size_t token_start = 0, token_length = 0;
- /* Denotes whether we're inside of preprocessor line, together with
- * preprocessor line itself.
- *
- * TODO(sergey): Investigate whether using token start/end position
- * gives measurable speedup.
- */
- bool inside_preprocessor = false;
- string preprocessor_line = "";
- /* Actual loop over the whole source. */
- while(index < source_length) {
- const char ch = source[index];
- if(ch == '\n') {
- if(inside_preprocessor) {
- result += path_source_handle_preprocessor(preprocessor_line,
- source_filepath,
- line_number,
- state);
- /* Start gathering net part of the token. */
- token_start = index;
- token_length = 0;
- }
- inside_preprocessor = false;
- preprocessor_line = "";
- column_number = 0;
- ++line_number;
- }
- else if(ch == '#' && column_number == 1 && !inside_preprocessor) {
- /* Append all possible non-preprocessor token to the result. */
- if(token_length != 0) {
- result.append(source, token_start, token_length);
- token_start = index;
- token_length = 0;
- }
- inside_preprocessor = true;
- }
- if(inside_preprocessor) {
- preprocessor_line += ch;
- }
- else {
- ++token_length;
- }
- ++index;
- ++column_number;
- }
- /* Append possible tokens which happened before special events handled
- * above.
- */
- if(token_length != 0) {
- result.append(source, token_start, token_length);
- }
- if(inside_preprocessor) {
- result += path_source_handle_preprocessor(preprocessor_line,
- source_filepath,
- line_number,
- state);
- }
- /* Store result for further reuse. */
- state->processed_files[source_filepath] = result;
- return result;
-}
-
-string path_source_replace_includes(const string& source,
- const string& path,
- const string& source_filename)
-{
- SourceReplaceState state;
- state.base = path;
- return path_source_replace_includes_recursive(
- source,
- path_join(path, source_filename),
- &state);
-}
-
-FILE *path_fopen(const string& path, const string& mode)
+static string path_source_replace_includes_recursive(const string &source,
+ const string &source_filepath,
+ SourceReplaceState *state)
+{
+ /* Try to re-use processed file without spending time on replacing all
+ * include directives again.
+ */
+ SourceReplaceState::ProcessedMapping::iterator replaced_file = state->processed_files.find(
+ source_filepath);
+ if (replaced_file != state->processed_files.end()) {
+ if (state->precompiled_headers.find(source_filepath) != state->precompiled_headers.end()) {
+ return "";
+ }
+ return replaced_file->second;
+ }
+ /* Perform full file processing. */
+ string result = "";
+ const size_t source_length = source.length();
+ size_t index = 0;
+ /* Information about where we are in the source. */
+ size_t line_number = 0, column_number = 1;
+ /* Currently gathered non-preprocessor token.
+ * Store as start/length rather than token itself to avoid overhead of
+ * memory re-allocations on each character concatenation.
+ */
+ size_t token_start = 0, token_length = 0;
+ /* Denotes whether we're inside of preprocessor line, together with
+ * preprocessor line itself.
+ *
+ * TODO(sergey): Investigate whether using token start/end position
+ * gives measurable speedup.
+ */
+ bool inside_preprocessor = false;
+ string preprocessor_line = "";
+ /* Actual loop over the whole source. */
+ while (index < source_length) {
+ const char ch = source[index];
+ if (ch == '\n') {
+ if (inside_preprocessor) {
+ result += path_source_handle_preprocessor(
+ preprocessor_line, source_filepath, line_number, state);
+ /* Start gathering net part of the token. */
+ token_start = index;
+ token_length = 0;
+ }
+ inside_preprocessor = false;
+ preprocessor_line = "";
+ column_number = 0;
+ ++line_number;
+ }
+ else if (ch == '#' && column_number == 1 && !inside_preprocessor) {
+ /* Append all possible non-preprocessor token to the result. */
+ if (token_length != 0) {
+ result.append(source, token_start, token_length);
+ token_start = index;
+ token_length = 0;
+ }
+ inside_preprocessor = true;
+ }
+ if (inside_preprocessor) {
+ preprocessor_line += ch;
+ }
+ else {
+ ++token_length;
+ }
+ ++index;
+ ++column_number;
+ }
+ /* Append possible tokens which happened before special events handled
+ * above.
+ */
+ if (token_length != 0) {
+ result.append(source, token_start, token_length);
+ }
+ if (inside_preprocessor) {
+ result += path_source_handle_preprocessor(
+ preprocessor_line, source_filepath, line_number, state);
+ }
+ /* Store result for further reuse. */
+ state->processed_files[source_filepath] = result;
+ return result;
+}
+
+string path_source_replace_includes(const string &source,
+ const string &path,
+ const string &source_filename)
+{
+ SourceReplaceState state;
+ state.base = path;
+ return path_source_replace_includes_recursive(source, path_join(path, source_filename), &state);
+}
+
+FILE *path_fopen(const string &path, const string &mode)
{
#ifdef _WIN32
- wstring path_wc = string_to_wstring(path);
- wstring mode_wc = string_to_wstring(mode);
- return _wfopen(path_wc.c_str(), mode_wc.c_str());
+ wstring path_wc = string_to_wstring(path);
+ wstring mode_wc = string_to_wstring(mode);
+ return _wfopen(path_wc.c_str(), mode_wc.c_str());
#else
- return fopen(path.c_str(), mode.c_str());
+ return fopen(path.c_str(), mode.c_str());
#endif
}
-void path_cache_clear_except(const string& name, const set<string>& except)
+void path_cache_clear_except(const string &name, const set<string> &except)
{
- string dir = path_user_get("cache");
-
- if(path_exists(dir)) {
- directory_iterator it(dir), it_end;
+ string dir = path_user_get("cache");
- for(; it != it_end; ++it) {
- string filename = path_filename(it->path());
+ if (path_exists(dir)) {
+ directory_iterator it(dir), it_end;
- if(string_startswith(filename, name.c_str()))
- if(except.find(filename) == except.end())
- path_remove(it->path());
- }
- }
+ for (; it != it_end; ++it) {
+ string filename = path_filename(it->path());
+ if (string_startswith(filename, name.c_str()))
+ if (except.find(filename) == except.end())
+ path_remove(it->path());
+ }
+ }
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/util/util_path.h b/intern/cycles/util/util_path.h
index 738dba94647..7a83c2135a4 100644
--- a/intern/cycles/util/util_path.h
+++ b/intern/cycles/util/util_path.h
@@ -32,46 +32,46 @@
CCL_NAMESPACE_BEGIN
/* program paths */
-void path_init(const string& path = "", const string& user_path = "");
-string path_get(const string& sub = "");
-string path_user_get(const string& sub = "");
-string path_cache_get(const string& sub = "");
+void path_init(const string &path = "", const string &user_path = "");
+string path_get(const string &sub = "");
+string path_user_get(const string &sub = "");
+string path_cache_get(const string &sub = "");
/* path string manipulation */
-string path_filename(const string& path);
-string path_dirname(const string& path);
-string path_join(const string& dir, const string& file);
-string path_escape(const string& path);
-bool path_is_relative(const string& path);
+string path_filename(const string &path);
+string path_dirname(const string &path);
+string path_join(const string &dir, const string &file);
+string path_escape(const string &path);
+bool path_is_relative(const string &path);
/* file info */
-size_t path_file_size(const string& path);
-bool path_exists(const string& path);
-bool path_is_directory(const string& path);
-string path_files_md5_hash(const string& dir);
-uint64_t path_modified_time(const string& path);
+size_t path_file_size(const string &path);
+bool path_exists(const string &path);
+bool path_is_directory(const string &path);
+string path_files_md5_hash(const string &dir);
+uint64_t path_modified_time(const string &path);
/* directory utility */
-void path_create_directories(const string& path);
+void path_create_directories(const string &path);
/* file read/write utilities */
-FILE *path_fopen(const string& path, const string& mode);
+FILE *path_fopen(const string &path, const string &mode);
-bool path_write_binary(const string& path, const vector<uint8_t>& binary);
-bool path_write_text(const string& path, string& text);
-bool path_read_binary(const string& path, vector<uint8_t>& binary);
-bool path_read_text(const string& path, string& text);
+bool path_write_binary(const string &path, const vector<uint8_t> &binary);
+bool path_write_text(const string &path, string &text);
+bool path_read_binary(const string &path, vector<uint8_t> &binary);
+bool path_read_text(const string &path, string &text);
/* File manipulation. */
-bool path_remove(const string& path);
+bool path_remove(const string &path);
/* source code utility */
-string path_source_replace_includes(const string& source,
- const string& path,
- const string& source_filename="");
+string path_source_replace_includes(const string &source,
+ const string &path,
+ const string &source_filename = "");
/* cache utility */
-void path_cache_clear_except(const string& name, const set<string>& except);
+void path_cache_clear_except(const string &name, const set<string> &except);
CCL_NAMESPACE_END
diff --git a/intern/cycles/util/util_profiling.cpp b/intern/cycles/util/util_profiling.cpp
index 30aaef69310..e3edf219435 100644
--- a/intern/cycles/util/util_profiling.cpp
+++ b/intern/cycles/util/util_profiling.cpp
@@ -20,159 +20,159 @@
CCL_NAMESPACE_BEGIN
-Profiler::Profiler()
- : do_stop_worker(true), worker(NULL)
+Profiler::Profiler() : do_stop_worker(true), worker(NULL)
{
}
Profiler::~Profiler()
{
- assert(worker == NULL);
+ assert(worker == NULL);
}
void Profiler::run()
{
- uint64_t updates = 0;
- auto start_time = std::chrono::system_clock::now();
- while(!do_stop_worker) {
- thread_scoped_lock lock(mutex);
- foreach(ProfilingState *state, states) {
- uint32_t cur_event = state->event;
- int32_t cur_shader = state->shader;
- int32_t cur_object = state->object;
-
- /* The state reads/writes should be atomic, but just to be sure
- * check the values for validity anyways. */
- if(cur_event < PROFILING_NUM_EVENTS) {
- event_samples[cur_event]++;
- }
-
- if(cur_shader >= 0 && cur_shader < shader_samples.size()) {
- /* Only consider the active shader during events whose runtime significantly depends on it. */
- if(((cur_event >= PROFILING_SHADER_EVAL ) && (cur_event <= PROFILING_SUBSURFACE)) ||
- ((cur_event >= PROFILING_CLOSURE_EVAL) && (cur_event <= PROFILING_CLOSURE_VOLUME_SAMPLE))) {
- shader_samples[cur_shader]++;
- }
- }
-
- if(cur_object >= 0 && cur_object < object_samples.size()) {
- object_samples[cur_object]++;
- }
- }
- lock.unlock();
-
- /* Relative waits always overshoot a bit, so just waiting 1ms every
- * time would cause the sampling to drift over time.
- * By keeping track of the absolute time, the wait times correct themselves -
- * if one wait overshoots a lot, the next one will be shorter to compensate. */
- updates++;
- std::this_thread::sleep_until(start_time + updates*std::chrono::milliseconds(1));
- }
+ uint64_t updates = 0;
+ auto start_time = std::chrono::system_clock::now();
+ while (!do_stop_worker) {
+ thread_scoped_lock lock(mutex);
+ foreach (ProfilingState *state, states) {
+ uint32_t cur_event = state->event;
+ int32_t cur_shader = state->shader;
+ int32_t cur_object = state->object;
+
+ /* The state reads/writes should be atomic, but just to be sure
+ * check the values for validity anyways. */
+ if (cur_event < PROFILING_NUM_EVENTS) {
+ event_samples[cur_event]++;
+ }
+
+ if (cur_shader >= 0 && cur_shader < shader_samples.size()) {
+ /* Only consider the active shader during events whose runtime significantly depends on it. */
+ if (((cur_event >= PROFILING_SHADER_EVAL) && (cur_event <= PROFILING_SUBSURFACE)) ||
+ ((cur_event >= PROFILING_CLOSURE_EVAL) &&
+ (cur_event <= PROFILING_CLOSURE_VOLUME_SAMPLE))) {
+ shader_samples[cur_shader]++;
+ }
+ }
+
+ if (cur_object >= 0 && cur_object < object_samples.size()) {
+ object_samples[cur_object]++;
+ }
+ }
+ lock.unlock();
+
+ /* Relative waits always overshoot a bit, so just waiting 1ms every
+ * time would cause the sampling to drift over time.
+ * By keeping track of the absolute time, the wait times correct themselves -
+ * if one wait overshoots a lot, the next one will be shorter to compensate. */
+ updates++;
+ std::this_thread::sleep_until(start_time + updates * std::chrono::milliseconds(1));
+ }
}
void Profiler::reset(int num_shaders, int num_objects)
{
- bool running = (worker != NULL);
- if(running) {
- stop();
- }
-
- /* Resize and clear the accumulation vectors. */
- shader_hits.assign(num_shaders, 0);
- object_hits.assign(num_objects, 0);
-
- event_samples.assign(PROFILING_NUM_EVENTS, 0);
- shader_samples.assign(num_shaders, 0);
- object_samples.assign(num_objects, 0);
-
- if(running) {
- start();
- }
+ bool running = (worker != NULL);
+ if (running) {
+ stop();
+ }
+
+ /* Resize and clear the accumulation vectors. */
+ shader_hits.assign(num_shaders, 0);
+ object_hits.assign(num_objects, 0);
+
+ event_samples.assign(PROFILING_NUM_EVENTS, 0);
+ shader_samples.assign(num_shaders, 0);
+ object_samples.assign(num_objects, 0);
+
+ if (running) {
+ start();
+ }
}
void Profiler::start()
{
- assert(worker == NULL);
- do_stop_worker = false;
- worker = new thread(function_bind(&Profiler::run, this));
+ assert(worker == NULL);
+ do_stop_worker = false;
+ worker = new thread(function_bind(&Profiler::run, this));
}
void Profiler::stop()
{
- if(worker != NULL) {
- do_stop_worker = true;
+ if (worker != NULL) {
+ do_stop_worker = true;
- worker->join();
- delete worker;
- worker = NULL;
- }
+ worker->join();
+ delete worker;
+ worker = NULL;
+ }
}
void Profiler::add_state(ProfilingState *state)
{
- thread_scoped_lock lock(mutex);
+ thread_scoped_lock lock(mutex);
- /* Add the ProfilingState from the list of sampled states. */
- assert(std::find(states.begin(), states.end(), state) == states.end());
- states.push_back(state);
+ /* Add the ProfilingState from the list of sampled states. */
+ assert(std::find(states.begin(), states.end(), state) == states.end());
+ states.push_back(state);
- /* Resize thread-local hit counters. */
- state->shader_hits.assign(shader_hits.size(), 0);
- state->object_hits.assign(object_hits.size(), 0);
+ /* Resize thread-local hit counters. */
+ state->shader_hits.assign(shader_hits.size(), 0);
+ state->object_hits.assign(object_hits.size(), 0);
- /* Initialize the state. */
- state->event = PROFILING_UNKNOWN;
- state->shader = -1;
- state->object = -1;
- state->active = true;
+ /* Initialize the state. */
+ state->event = PROFILING_UNKNOWN;
+ state->shader = -1;
+ state->object = -1;
+ state->active = true;
}
void Profiler::remove_state(ProfilingState *state)
{
- thread_scoped_lock lock(mutex);
-
- /* Remove the ProfilingState from the list of sampled states. */
- states.erase(std::remove(states.begin(), states.end(), state), states.end());
- state->active = false;
-
- /* Merge thread-local hit counters. */
- assert(shader_hits.size() == state->shader_hits.size());
- for(int i = 0; i < shader_hits.size(); i++) {
- shader_hits[i] += state->shader_hits[i];
- }
-
- assert(object_hits.size() == state->object_hits.size());
- for(int i = 0; i < object_hits.size(); i++) {
- object_hits[i] += state->object_hits[i];
- }
+ thread_scoped_lock lock(mutex);
+
+ /* Remove the ProfilingState from the list of sampled states. */
+ states.erase(std::remove(states.begin(), states.end(), state), states.end());
+ state->active = false;
+
+ /* Merge thread-local hit counters. */
+ assert(shader_hits.size() == state->shader_hits.size());
+ for (int i = 0; i < shader_hits.size(); i++) {
+ shader_hits[i] += state->shader_hits[i];
+ }
+
+ assert(object_hits.size() == state->object_hits.size());
+ for (int i = 0; i < object_hits.size(); i++) {
+ object_hits[i] += state->object_hits[i];
+ }
}
uint64_t Profiler::get_event(ProfilingEvent event)
{
- assert(worker == NULL);
- return event_samples[event];
+ assert(worker == NULL);
+ return event_samples[event];
}
bool Profiler::get_shader(int shader, uint64_t &samples, uint64_t &hits)
{
- assert(worker == NULL);
- if(shader_samples[shader] == 0) {
- return false;
- }
- samples = shader_samples[shader];
- hits = shader_hits[shader];
- return true;
+ assert(worker == NULL);
+ if (shader_samples[shader] == 0) {
+ return false;
+ }
+ samples = shader_samples[shader];
+ hits = shader_hits[shader];
+ return true;
}
bool Profiler::get_object(int object, uint64_t &samples, uint64_t &hits)
{
- assert(worker == NULL);
- if(object_samples[object] == 0) {
- return false;
- }
- samples = object_samples[object];
- hits = object_hits[object];
- return true;
+ assert(worker == NULL);
+ if (object_samples[object] == 0) {
+ return false;
+ }
+ samples = object_samples[object];
+ hits = object_hits[object];
+ return true;
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/util/util_profiling.h b/intern/cycles/util/util_profiling.h
index 77cdbb0b325..f5f500239f2 100644
--- a/intern/cycles/util/util_profiling.h
+++ b/intern/cycles/util/util_profiling.h
@@ -27,42 +27,42 @@
CCL_NAMESPACE_BEGIN
enum ProfilingEvent : uint32_t {
- PROFILING_UNKNOWN,
- PROFILING_RAY_SETUP,
- PROFILING_PATH_INTEGRATE,
- PROFILING_SCENE_INTERSECT,
- PROFILING_INDIRECT_EMISSION,
- PROFILING_VOLUME,
- PROFILING_SHADER_SETUP,
- PROFILING_SHADER_EVAL,
- PROFILING_SHADER_APPLY,
- PROFILING_AO,
- PROFILING_SUBSURFACE,
- PROFILING_CONNECT_LIGHT,
- PROFILING_SURFACE_BOUNCE,
- PROFILING_WRITE_RESULT,
-
- PROFILING_INTERSECT,
- PROFILING_INTERSECT_LOCAL,
- PROFILING_INTERSECT_SHADOW_ALL,
- PROFILING_INTERSECT_VOLUME,
- PROFILING_INTERSECT_VOLUME_ALL,
-
- PROFILING_CLOSURE_EVAL,
- PROFILING_CLOSURE_SAMPLE,
- PROFILING_CLOSURE_VOLUME_EVAL,
- PROFILING_CLOSURE_VOLUME_SAMPLE,
-
- PROFILING_DENOISING,
- PROFILING_DENOISING_CONSTRUCT_TRANSFORM,
- PROFILING_DENOISING_RECONSTRUCT,
- PROFILING_DENOISING_DIVIDE_SHADOW,
- PROFILING_DENOISING_NON_LOCAL_MEANS,
- PROFILING_DENOISING_COMBINE_HALVES,
- PROFILING_DENOISING_GET_FEATURE,
- PROFILING_DENOISING_DETECT_OUTLIERS,
-
- PROFILING_NUM_EVENTS,
+ PROFILING_UNKNOWN,
+ PROFILING_RAY_SETUP,
+ PROFILING_PATH_INTEGRATE,
+ PROFILING_SCENE_INTERSECT,
+ PROFILING_INDIRECT_EMISSION,
+ PROFILING_VOLUME,
+ PROFILING_SHADER_SETUP,
+ PROFILING_SHADER_EVAL,
+ PROFILING_SHADER_APPLY,
+ PROFILING_AO,
+ PROFILING_SUBSURFACE,
+ PROFILING_CONNECT_LIGHT,
+ PROFILING_SURFACE_BOUNCE,
+ PROFILING_WRITE_RESULT,
+
+ PROFILING_INTERSECT,
+ PROFILING_INTERSECT_LOCAL,
+ PROFILING_INTERSECT_SHADOW_ALL,
+ PROFILING_INTERSECT_VOLUME,
+ PROFILING_INTERSECT_VOLUME_ALL,
+
+ PROFILING_CLOSURE_EVAL,
+ PROFILING_CLOSURE_SAMPLE,
+ PROFILING_CLOSURE_VOLUME_EVAL,
+ PROFILING_CLOSURE_VOLUME_SAMPLE,
+
+ PROFILING_DENOISING,
+ PROFILING_DENOISING_CONSTRUCT_TRANSFORM,
+ PROFILING_DENOISING_RECONSTRUCT,
+ PROFILING_DENOISING_DIVIDE_SHADOW,
+ PROFILING_DENOISING_NON_LOCAL_MEANS,
+ PROFILING_DENOISING_COMBINE_HALVES,
+ PROFILING_DENOISING_GET_FEATURE,
+ PROFILING_DENOISING_DETECT_OUTLIERS,
+
+ PROFILING_NUM_EVENTS,
};
/* Contains the current execution state of a worker thread.
@@ -79,97 +79,97 @@ enum ProfilingEvent : uint32_t {
* case of reading an intermediate state could at worst result
* in a single incorrect sample. */
struct ProfilingState {
- volatile uint32_t event = PROFILING_UNKNOWN;
- volatile int32_t shader = -1;
- volatile int32_t object = -1;
- volatile bool active = false;
+ volatile uint32_t event = PROFILING_UNKNOWN;
+ volatile int32_t shader = -1;
+ volatile int32_t object = -1;
+ volatile bool active = false;
- vector<uint64_t> shader_hits;
- vector<uint64_t> object_hits;
+ vector<uint64_t> shader_hits;
+ vector<uint64_t> object_hits;
};
class Profiler {
-public:
- Profiler();
- ~Profiler();
+ public:
+ Profiler();
+ ~Profiler();
- void reset(int num_shaders, int num_objects);
+ void reset(int num_shaders, int num_objects);
- void start();
- void stop();
+ void start();
+ void stop();
- void add_state(ProfilingState *state);
- void remove_state(ProfilingState *state);
+ void add_state(ProfilingState *state);
+ void remove_state(ProfilingState *state);
- uint64_t get_event(ProfilingEvent event);
- bool get_shader(int shader, uint64_t &samples, uint64_t &hits);
- bool get_object(int object, uint64_t &samples, uint64_t &hits);
+ uint64_t get_event(ProfilingEvent event);
+ bool get_shader(int shader, uint64_t &samples, uint64_t &hits);
+ bool get_object(int object, uint64_t &samples, uint64_t &hits);
-protected:
- void run();
+ protected:
+ void run();
- /* Tracks how often the worker was in each ProfilingEvent while sampling,
- * so multiplying the values by the sample frequency (currently 1ms)
- * gives the approximate time spent in each state. */
- vector<uint64_t> event_samples;
- vector<uint64_t> shader_samples;
- vector<uint64_t> object_samples;
+ /* Tracks how often the worker was in each ProfilingEvent while sampling,
+ * so multiplying the values by the sample frequency (currently 1ms)
+ * gives the approximate time spent in each state. */
+ vector<uint64_t> event_samples;
+ vector<uint64_t> shader_samples;
+ vector<uint64_t> object_samples;
- /* Tracks the total amounts every object/shader was hit.
- * Used to evaluate relative cost, written by the render thread.
- * Indexed by the shader and object IDs that the kernel also uses
- * to index __object_flag and __shaders. */
- vector<uint64_t> shader_hits;
- vector<uint64_t> object_hits;
+ /* Tracks the total amounts every object/shader was hit.
+ * Used to evaluate relative cost, written by the render thread.
+ * Indexed by the shader and object IDs that the kernel also uses
+ * to index __object_flag and __shaders. */
+ vector<uint64_t> shader_hits;
+ vector<uint64_t> object_hits;
- volatile bool do_stop_worker;
- thread *worker;
+ volatile bool do_stop_worker;
+ thread *worker;
- thread_mutex mutex;
- vector<ProfilingState*> states;
+ thread_mutex mutex;
+ vector<ProfilingState *> states;
};
class ProfilingHelper {
-public:
- ProfilingHelper(ProfilingState *state, ProfilingEvent event)
- : state(state)
- {
- previous_event = state->event;
- state->event = event;
- }
-
- inline void set_event(ProfilingEvent event)
- {
- state->event = event;
- }
-
- inline void set_shader(int shader)
- {
- state->shader = shader;
- if(state->active) {
- assert(shader < state->shader_hits.size());
- state->shader_hits[shader]++;
- }
- }
-
- inline void set_object(int object)
- {
- state->object = object;
- if(state->active) {
- assert(object < state->object_hits.size());
- state->object_hits[object]++;
- }
- }
-
- ~ProfilingHelper()
- {
- state->event = previous_event;
- }
-private:
- ProfilingState *state;
- uint32_t previous_event;
+ public:
+ ProfilingHelper(ProfilingState *state, ProfilingEvent event) : state(state)
+ {
+ previous_event = state->event;
+ state->event = event;
+ }
+
+ inline void set_event(ProfilingEvent event)
+ {
+ state->event = event;
+ }
+
+ inline void set_shader(int shader)
+ {
+ state->shader = shader;
+ if (state->active) {
+ assert(shader < state->shader_hits.size());
+ state->shader_hits[shader]++;
+ }
+ }
+
+ inline void set_object(int object)
+ {
+ state->object = object;
+ if (state->active) {
+ assert(object < state->object_hits.size());
+ state->object_hits[object]++;
+ }
+ }
+
+ ~ProfilingHelper()
+ {
+ state->event = previous_event;
+ }
+
+ private:
+ ProfilingState *state;
+ uint32_t previous_event;
};
CCL_NAMESPACE_END
-#endif /* __UTIL_PROFILING_H__ */
+#endif /* __UTIL_PROFILING_H__ */
diff --git a/intern/cycles/util/util_progress.h b/intern/cycles/util/util_progress.h
index 06900d14cdc..f05e5b918f3 100644
--- a/intern/cycles/util/util_progress.h
+++ b/intern/cycles/util/util_progress.h
@@ -31,361 +31,359 @@
CCL_NAMESPACE_BEGIN
class Progress {
-public:
- Progress()
- {
- pixel_samples = 0;
- total_pixel_samples = 0;
- current_tile_sample = 0;
- rendered_tiles = 0;
- denoised_tiles = 0;
- start_time = time_dt();
- render_start_time = time_dt();
- end_time = 0.0;
- status = "Initializing";
- substatus = "";
- sync_status = "";
- sync_substatus = "";
- kernel_status = "";
- update_cb = function_null;
- cancel = false;
- cancel_message = "";
- error = false;
- error_message = "";
- cancel_cb = function_null;
- }
-
- Progress(Progress& progress)
- {
- *this = progress;
- }
-
- Progress& operator=(Progress& progress)
- {
- thread_scoped_lock lock(progress.progress_mutex);
-
- progress.get_status(status, substatus);
-
- pixel_samples = progress.pixel_samples;
- total_pixel_samples = progress.total_pixel_samples;
- current_tile_sample = progress.get_current_sample();
-
- return *this;
- }
-
- void reset()
- {
- pixel_samples = 0;
- total_pixel_samples = 0;
- current_tile_sample = 0;
- rendered_tiles = 0;
- denoised_tiles = 0;
- start_time = time_dt();
- render_start_time = time_dt();
- end_time = 0.0;
- status = "Initializing";
- substatus = "";
- sync_status = "";
- sync_substatus = "";
- kernel_status = "";
- cancel = false;
- cancel_message = "";
- error = false;
- error_message = "";
- }
-
- /* cancel */
- void set_cancel(const string& cancel_message_)
- {
- thread_scoped_lock lock(progress_mutex);
- cancel_message = cancel_message_;
- cancel = true;
- }
-
- bool get_cancel()
- {
- if(!cancel && cancel_cb)
- cancel_cb();
-
- return cancel;
- }
-
- string get_cancel_message()
- {
- thread_scoped_lock lock(progress_mutex);
- return cancel_message;
- }
-
- void set_cancel_callback(function<void()> function)
- {
- cancel_cb = function;
- }
-
- /* error */
- void set_error(const string& error_message_)
- {
- thread_scoped_lock lock(progress_mutex);
- error_message = error_message_;
- error = true;
- /* If error happens we also stop rendering. */
- cancel_message = error_message_;
- cancel = true;
- }
-
- bool get_error()
- {
- return error;
- }
-
- string get_error_message()
- {
- thread_scoped_lock lock(progress_mutex);
- return error_message;
- }
-
- /* tile and timing information */
-
- void set_start_time()
- {
- thread_scoped_lock lock(progress_mutex);
-
- start_time = time_dt();
- end_time = 0.0;
- }
-
- void set_render_start_time()
- {
- thread_scoped_lock lock(progress_mutex);
-
- render_start_time = time_dt();
- }
-
- void add_skip_time(const scoped_timer &start_timer, bool only_render)
- {
- double skip_time = time_dt() - start_timer.get_start();
-
- render_start_time += skip_time;
- if(!only_render) {
- start_time += skip_time;
- }
- }
-
- void get_time(double& total_time_, double& render_time_)
- {
- thread_scoped_lock lock(progress_mutex);
-
- double time = (end_time > 0) ? end_time : time_dt();
-
- total_time_ = time - start_time;
- render_time_ = time - render_start_time;
- }
-
- void set_end_time()
- {
- end_time = time_dt();
- }
-
- void reset_sample()
- {
- thread_scoped_lock lock(progress_mutex);
-
- pixel_samples = 0;
- current_tile_sample = 0;
- rendered_tiles = 0;
- denoised_tiles = 0;
- }
-
- void set_total_pixel_samples(uint64_t total_pixel_samples_)
- {
- thread_scoped_lock lock(progress_mutex);
-
- total_pixel_samples = total_pixel_samples_;
- }
-
- float get_progress()
- {
- if(total_pixel_samples > 0) {
- return ((float) pixel_samples) / total_pixel_samples;
- }
- return 0.0f;
- }
-
- void add_samples(uint64_t pixel_samples_, int tile_sample)
- {
- thread_scoped_lock lock(progress_mutex);
-
- pixel_samples += pixel_samples_;
- current_tile_sample = tile_sample;
- }
-
- void add_samples_update(uint64_t pixel_samples_, int tile_sample)
- {
- add_samples(pixel_samples_, tile_sample);
- set_update();
- }
-
- void add_finished_tile(bool denoised)
- {
- thread_scoped_lock lock(progress_mutex);
-
- if(denoised) {
- denoised_tiles++;
- }
- else {
- rendered_tiles++;
- }
- }
-
- int get_current_sample()
- {
- thread_scoped_lock lock(progress_mutex);
- /* Note that the value here always belongs to the last tile that updated,
- * so it's only useful if there is only one active tile. */
- return current_tile_sample;
- }
-
- int get_rendered_tiles()
- {
- thread_scoped_lock lock(progress_mutex);
- return rendered_tiles;
- }
-
- int get_denoised_tiles()
- {
- thread_scoped_lock lock(progress_mutex);
- return denoised_tiles;
- }
-
- /* status messages */
-
- void set_status(const string& status_, const string& substatus_ = "")
- {
- {
- thread_scoped_lock lock(progress_mutex);
- status = status_;
- substatus = substatus_;
- }
-
- set_update();
- }
-
- void set_substatus(const string& substatus_)
- {
- {
- thread_scoped_lock lock(progress_mutex);
- substatus = substatus_;
- }
-
- set_update();
- }
-
- void set_sync_status(const string& status_, const string& substatus_ = "")
- {
- {
- thread_scoped_lock lock(progress_mutex);
- sync_status = status_;
- sync_substatus = substatus_;
- }
-
- set_update();
-
- }
-
- void set_sync_substatus(const string& substatus_)
- {
- {
- thread_scoped_lock lock(progress_mutex);
- sync_substatus = substatus_;
- }
-
- set_update();
- }
-
- void get_status(string& status_, string& substatus_)
- {
- thread_scoped_lock lock(progress_mutex);
-
- if(sync_status != "") {
- status_ = sync_status;
- substatus_ = sync_substatus;
- }
- else {
- status_ = status;
- substatus_ = substatus;
- }
- }
-
-
- /* kernel status */
-
- void set_kernel_status(const string &kernel_status_)
- {
- {
- thread_scoped_lock lock(progress_mutex);
- kernel_status = kernel_status_;
- }
-
- set_update();
- }
-
- void get_kernel_status(string &kernel_status_)
- {
- thread_scoped_lock lock(progress_mutex);
- kernel_status_ = kernel_status;
- }
-
- /* callback */
-
- void set_update()
- {
- if(update_cb) {
- thread_scoped_lock lock(update_mutex);
- update_cb();
- }
- }
-
- void set_update_callback(function<void()> function)
- {
- update_cb = function;
- }
-
-protected:
- thread_mutex progress_mutex;
- thread_mutex update_mutex;
- function<void()> update_cb;
- function<void()> cancel_cb;
-
- /* pixel_samples counts how many samples have been rendered over all pixel, not just per pixel.
- * This makes the progress estimate more accurate when tiles with different sizes are used.
- *
- * total_pixel_samples is the total amount of pixel samples that will be rendered. */
- uint64_t pixel_samples, total_pixel_samples;
- /* Stores the current sample count of the last tile that called the update function.
- * It's used to display the sample count if only one tile is active. */
- int current_tile_sample;
- /* Stores the number of tiles that's already finished.
- * Used to determine whether all but the last tile are finished rendering, in which case the current_tile_sample is displayed. */
- int rendered_tiles, denoised_tiles;
-
- double start_time, render_start_time;
- /* End time written when render is done, so it doesn't keep increasing on redraws. */
- double end_time;
-
- string status;
- string substatus;
-
- string sync_status;
- string sync_substatus;
-
- string kernel_status;
-
- volatile bool cancel;
- string cancel_message;
-
- volatile bool error;
- string error_message;
+ public:
+ Progress()
+ {
+ pixel_samples = 0;
+ total_pixel_samples = 0;
+ current_tile_sample = 0;
+ rendered_tiles = 0;
+ denoised_tiles = 0;
+ start_time = time_dt();
+ render_start_time = time_dt();
+ end_time = 0.0;
+ status = "Initializing";
+ substatus = "";
+ sync_status = "";
+ sync_substatus = "";
+ kernel_status = "";
+ update_cb = function_null;
+ cancel = false;
+ cancel_message = "";
+ error = false;
+ error_message = "";
+ cancel_cb = function_null;
+ }
+
+ Progress(Progress &progress)
+ {
+ *this = progress;
+ }
+
+ Progress &operator=(Progress &progress)
+ {
+ thread_scoped_lock lock(progress.progress_mutex);
+
+ progress.get_status(status, substatus);
+
+ pixel_samples = progress.pixel_samples;
+ total_pixel_samples = progress.total_pixel_samples;
+ current_tile_sample = progress.get_current_sample();
+
+ return *this;
+ }
+
+ void reset()
+ {
+ pixel_samples = 0;
+ total_pixel_samples = 0;
+ current_tile_sample = 0;
+ rendered_tiles = 0;
+ denoised_tiles = 0;
+ start_time = time_dt();
+ render_start_time = time_dt();
+ end_time = 0.0;
+ status = "Initializing";
+ substatus = "";
+ sync_status = "";
+ sync_substatus = "";
+ kernel_status = "";
+ cancel = false;
+ cancel_message = "";
+ error = false;
+ error_message = "";
+ }
+
+ /* cancel */
+ void set_cancel(const string &cancel_message_)
+ {
+ thread_scoped_lock lock(progress_mutex);
+ cancel_message = cancel_message_;
+ cancel = true;
+ }
+
+ bool get_cancel()
+ {
+ if (!cancel && cancel_cb)
+ cancel_cb();
+
+ return cancel;
+ }
+
+ string get_cancel_message()
+ {
+ thread_scoped_lock lock(progress_mutex);
+ return cancel_message;
+ }
+
+ void set_cancel_callback(function<void()> function)
+ {
+ cancel_cb = function;
+ }
+
+ /* error */
+ void set_error(const string &error_message_)
+ {
+ thread_scoped_lock lock(progress_mutex);
+ error_message = error_message_;
+ error = true;
+ /* If error happens we also stop rendering. */
+ cancel_message = error_message_;
+ cancel = true;
+ }
+
+ bool get_error()
+ {
+ return error;
+ }
+
+ string get_error_message()
+ {
+ thread_scoped_lock lock(progress_mutex);
+ return error_message;
+ }
+
+ /* tile and timing information */
+
+ void set_start_time()
+ {
+ thread_scoped_lock lock(progress_mutex);
+
+ start_time = time_dt();
+ end_time = 0.0;
+ }
+
+ void set_render_start_time()
+ {
+ thread_scoped_lock lock(progress_mutex);
+
+ render_start_time = time_dt();
+ }
+
+ void add_skip_time(const scoped_timer &start_timer, bool only_render)
+ {
+ double skip_time = time_dt() - start_timer.get_start();
+
+ render_start_time += skip_time;
+ if (!only_render) {
+ start_time += skip_time;
+ }
+ }
+
+ void get_time(double &total_time_, double &render_time_)
+ {
+ thread_scoped_lock lock(progress_mutex);
+
+ double time = (end_time > 0) ? end_time : time_dt();
+
+ total_time_ = time - start_time;
+ render_time_ = time - render_start_time;
+ }
+
+ void set_end_time()
+ {
+ end_time = time_dt();
+ }
+
+ void reset_sample()
+ {
+ thread_scoped_lock lock(progress_mutex);
+
+ pixel_samples = 0;
+ current_tile_sample = 0;
+ rendered_tiles = 0;
+ denoised_tiles = 0;
+ }
+
+ void set_total_pixel_samples(uint64_t total_pixel_samples_)
+ {
+ thread_scoped_lock lock(progress_mutex);
+
+ total_pixel_samples = total_pixel_samples_;
+ }
+
+ float get_progress()
+ {
+ if (total_pixel_samples > 0) {
+ return ((float)pixel_samples) / total_pixel_samples;
+ }
+ return 0.0f;
+ }
+
+ void add_samples(uint64_t pixel_samples_, int tile_sample)
+ {
+ thread_scoped_lock lock(progress_mutex);
+
+ pixel_samples += pixel_samples_;
+ current_tile_sample = tile_sample;
+ }
+
+ void add_samples_update(uint64_t pixel_samples_, int tile_sample)
+ {
+ add_samples(pixel_samples_, tile_sample);
+ set_update();
+ }
+
+ void add_finished_tile(bool denoised)
+ {
+ thread_scoped_lock lock(progress_mutex);
+
+ if (denoised) {
+ denoised_tiles++;
+ }
+ else {
+ rendered_tiles++;
+ }
+ }
+
+ int get_current_sample()
+ {
+ thread_scoped_lock lock(progress_mutex);
+ /* Note that the value here always belongs to the last tile that updated,
+ * so it's only useful if there is only one active tile. */
+ return current_tile_sample;
+ }
+
+ int get_rendered_tiles()
+ {
+ thread_scoped_lock lock(progress_mutex);
+ return rendered_tiles;
+ }
+
+ int get_denoised_tiles()
+ {
+ thread_scoped_lock lock(progress_mutex);
+ return denoised_tiles;
+ }
+
+ /* status messages */
+
+ void set_status(const string &status_, const string &substatus_ = "")
+ {
+ {
+ thread_scoped_lock lock(progress_mutex);
+ status = status_;
+ substatus = substatus_;
+ }
+
+ set_update();
+ }
+
+ void set_substatus(const string &substatus_)
+ {
+ {
+ thread_scoped_lock lock(progress_mutex);
+ substatus = substatus_;
+ }
+
+ set_update();
+ }
+
+ void set_sync_status(const string &status_, const string &substatus_ = "")
+ {
+ {
+ thread_scoped_lock lock(progress_mutex);
+ sync_status = status_;
+ sync_substatus = substatus_;
+ }
+
+ set_update();
+ }
+
+ void set_sync_substatus(const string &substatus_)
+ {
+ {
+ thread_scoped_lock lock(progress_mutex);
+ sync_substatus = substatus_;
+ }
+
+ set_update();
+ }
+
+ void get_status(string &status_, string &substatus_)
+ {
+ thread_scoped_lock lock(progress_mutex);
+
+ if (sync_status != "") {
+ status_ = sync_status;
+ substatus_ = sync_substatus;
+ }
+ else {
+ status_ = status;
+ substatus_ = substatus;
+ }
+ }
+
+ /* kernel status */
+
+ void set_kernel_status(const string &kernel_status_)
+ {
+ {
+ thread_scoped_lock lock(progress_mutex);
+ kernel_status = kernel_status_;
+ }
+
+ set_update();
+ }
+
+ void get_kernel_status(string &kernel_status_)
+ {
+ thread_scoped_lock lock(progress_mutex);
+ kernel_status_ = kernel_status;
+ }
+
+ /* callback */
+
+ void set_update()
+ {
+ if (update_cb) {
+ thread_scoped_lock lock(update_mutex);
+ update_cb();
+ }
+ }
+
+ void set_update_callback(function<void()> function)
+ {
+ update_cb = function;
+ }
+
+ protected:
+ thread_mutex progress_mutex;
+ thread_mutex update_mutex;
+ function<void()> update_cb;
+ function<void()> cancel_cb;
+
+ /* pixel_samples counts how many samples have been rendered over all pixel, not just per pixel.
+ * This makes the progress estimate more accurate when tiles with different sizes are used.
+ *
+ * total_pixel_samples is the total amount of pixel samples that will be rendered. */
+ uint64_t pixel_samples, total_pixel_samples;
+ /* Stores the current sample count of the last tile that called the update function.
+ * It's used to display the sample count if only one tile is active. */
+ int current_tile_sample;
+ /* Stores the number of tiles that's already finished.
+ * Used to determine whether all but the last tile are finished rendering, in which case the current_tile_sample is displayed. */
+ int rendered_tiles, denoised_tiles;
+
+ double start_time, render_start_time;
+ /* End time written when render is done, so it doesn't keep increasing on redraws. */
+ double end_time;
+
+ string status;
+ string substatus;
+
+ string sync_status;
+ string sync_substatus;
+
+ string kernel_status;
+
+ volatile bool cancel;
+ string cancel_message;
+
+ volatile bool error;
+ string error_message;
};
CCL_NAMESPACE_END
-#endif /* __UTIL_PROGRESS_H__ */
+#endif /* __UTIL_PROGRESS_H__ */
diff --git a/intern/cycles/util/util_projection.h b/intern/cycles/util/util_projection.h
index d1af013ae3a..416af18b53e 100644
--- a/intern/cycles/util/util_projection.h
+++ b/intern/cycles/util/util_projection.h
@@ -24,153 +24,193 @@ CCL_NAMESPACE_BEGIN
/* 4x4 projection matrix, perspective or orthographic. */
typedef struct ProjectionTransform {
- float4 x, y, z, w; /* rows */
+ float4 x, y, z, w; /* rows */
#ifndef __KERNEL_GPU__
- ProjectionTransform()
- {
- }
-
- explicit ProjectionTransform(const Transform& tfm)
- : x(tfm.x),
- y(tfm.y),
- z(tfm.z),
- w(make_float4(0.0f, 0.0f, 0.0f, 1.0f))
- {
- }
+ ProjectionTransform()
+ {
+ }
+
+ explicit ProjectionTransform(const Transform &tfm)
+ : x(tfm.x), y(tfm.y), z(tfm.z), w(make_float4(0.0f, 0.0f, 0.0f, 1.0f))
+ {
+ }
#endif
} ProjectionTransform;
typedef struct PerspectiveMotionTransform {
- ProjectionTransform pre;
- ProjectionTransform post;
+ ProjectionTransform pre;
+ ProjectionTransform post;
} PerspectiveMotionTransform;
/* Functions */
ccl_device_inline float3 transform_perspective(const ProjectionTransform *t, const float3 a)
{
- float4 b = make_float4(a.x, a.y, a.z, 1.0f);
- float3 c = make_float3(dot(t->x, b), dot(t->y, b), dot(t->z, b));
- float w = dot(t->w, b);
+ float4 b = make_float4(a.x, a.y, a.z, 1.0f);
+ float3 c = make_float3(dot(t->x, b), dot(t->y, b), dot(t->z, b));
+ float w = dot(t->w, b);
- return (w != 0.0f)? c/w: make_float3(0.0f, 0.0f, 0.0f);
+ return (w != 0.0f) ? c / w : make_float3(0.0f, 0.0f, 0.0f);
}
-ccl_device_inline float3 transform_perspective_direction(const ProjectionTransform *t, const float3 a)
+ccl_device_inline float3 transform_perspective_direction(const ProjectionTransform *t,
+ const float3 a)
{
- float3 c = make_float3(
- a.x*t->x.x + a.y*t->x.y + a.z*t->x.z,
- a.x*t->y.x + a.y*t->y.y + a.z*t->y.z,
- a.x*t->z.x + a.y*t->z.y + a.z*t->z.z);
+ float3 c = make_float3(a.x * t->x.x + a.y * t->x.y + a.z * t->x.z,
+ a.x * t->y.x + a.y * t->y.y + a.z * t->y.z,
+ a.x * t->z.x + a.y * t->z.y + a.z * t->z.z);
- return c;
+ return c;
}
#ifndef __KERNEL_GPU__
-ccl_device_inline Transform projection_to_transform(const ProjectionTransform& a)
+ccl_device_inline Transform projection_to_transform(const ProjectionTransform &a)
{
- Transform tfm = {a.x, a.y, a.z};
- return tfm;
+ Transform tfm = {a.x, a.y, a.z};
+ return tfm;
}
-ccl_device_inline ProjectionTransform projection_transpose(const ProjectionTransform& a)
+ccl_device_inline ProjectionTransform projection_transpose(const ProjectionTransform &a)
{
- ProjectionTransform t;
-
- t.x.x = a.x.x; t.x.y = a.y.x; t.x.z = a.z.x; t.x.w = a.w.x;
- t.y.x = a.x.y; t.y.y = a.y.y; t.y.z = a.z.y; t.y.w = a.w.y;
- t.z.x = a.x.z; t.z.y = a.y.z; t.z.z = a.z.z; t.z.w = a.w.z;
- t.w.x = a.x.w; t.w.y = a.y.w; t.w.z = a.z.w; t.w.w = a.w.w;
-
- return t;
+ ProjectionTransform t;
+
+ t.x.x = a.x.x;
+ t.x.y = a.y.x;
+ t.x.z = a.z.x;
+ t.x.w = a.w.x;
+ t.y.x = a.x.y;
+ t.y.y = a.y.y;
+ t.y.z = a.z.y;
+ t.y.w = a.w.y;
+ t.z.x = a.x.z;
+ t.z.y = a.y.z;
+ t.z.z = a.z.z;
+ t.z.w = a.w.z;
+ t.w.x = a.x.w;
+ t.w.y = a.y.w;
+ t.w.z = a.z.w;
+ t.w.w = a.w.w;
+
+ return t;
}
-ProjectionTransform projection_inverse(const ProjectionTransform& a);
-
-ccl_device_inline ProjectionTransform make_projection(
- float a, float b, float c, float d,
- float e, float f, float g, float h,
- float i, float j, float k, float l,
- float m, float n, float o, float p)
+ProjectionTransform projection_inverse(const ProjectionTransform &a);
+
+ccl_device_inline ProjectionTransform make_projection(float a,
+ float b,
+ float c,
+ float d,
+ float e,
+ float f,
+ float g,
+ float h,
+ float i,
+ float j,
+ float k,
+ float l,
+ float m,
+ float n,
+ float o,
+ float p)
{
- ProjectionTransform t;
-
- t.x.x = a; t.x.y = b; t.x.z = c; t.x.w = d;
- t.y.x = e; t.y.y = f; t.y.z = g; t.y.w = h;
- t.z.x = i; t.z.y = j; t.z.z = k; t.z.w = l;
- t.w.x = m; t.w.y = n; t.w.z = o; t.w.w = p;
-
- return t;
+ ProjectionTransform t;
+
+ t.x.x = a;
+ t.x.y = b;
+ t.x.z = c;
+ t.x.w = d;
+ t.y.x = e;
+ t.y.y = f;
+ t.y.z = g;
+ t.y.w = h;
+ t.z.x = i;
+ t.z.y = j;
+ t.z.z = k;
+ t.z.w = l;
+ t.w.x = m;
+ t.w.y = n;
+ t.w.z = o;
+ t.w.w = p;
+
+ return t;
}
ccl_device_inline ProjectionTransform projection_identity()
{
- return make_projection(
- 1.0f, 0.0f, 0.0f, 0.0f,
- 0.0f, 1.0f, 0.0f, 0.0f,
- 0.0f, 0.0f, 1.0f, 0.0f,
- 0.0f, 0.0f, 0.0f, 1.0f);
+ return make_projection(1.0f,
+ 0.0f,
+ 0.0f,
+ 0.0f,
+ 0.0f,
+ 1.0f,
+ 0.0f,
+ 0.0f,
+ 0.0f,
+ 0.0f,
+ 1.0f,
+ 0.0f,
+ 0.0f,
+ 0.0f,
+ 0.0f,
+ 1.0f);
}
-ccl_device_inline ProjectionTransform operator*(const ProjectionTransform& a, const ProjectionTransform& b)
+ccl_device_inline ProjectionTransform operator*(const ProjectionTransform &a,
+ const ProjectionTransform &b)
{
- ProjectionTransform c = projection_transpose(b);
- ProjectionTransform t;
+ ProjectionTransform c = projection_transpose(b);
+ ProjectionTransform t;
- t.x = make_float4(dot(a.x, c.x), dot(a.x, c.y), dot(a.x, c.z), dot(a.x, c.w));
- t.y = make_float4(dot(a.y, c.x), dot(a.y, c.y), dot(a.y, c.z), dot(a.y, c.w));
- t.z = make_float4(dot(a.z, c.x), dot(a.z, c.y), dot(a.z, c.z), dot(a.z, c.w));
- t.w = make_float4(dot(a.w, c.x), dot(a.w, c.y), dot(a.w, c.z), dot(a.w, c.w));
+ t.x = make_float4(dot(a.x, c.x), dot(a.x, c.y), dot(a.x, c.z), dot(a.x, c.w));
+ t.y = make_float4(dot(a.y, c.x), dot(a.y, c.y), dot(a.y, c.z), dot(a.y, c.w));
+ t.z = make_float4(dot(a.z, c.x), dot(a.z, c.y), dot(a.z, c.z), dot(a.z, c.w));
+ t.w = make_float4(dot(a.w, c.x), dot(a.w, c.y), dot(a.w, c.z), dot(a.w, c.w));
- return t;
+ return t;
}
-ccl_device_inline ProjectionTransform operator*(const ProjectionTransform& a, const Transform& b)
+ccl_device_inline ProjectionTransform operator*(const ProjectionTransform &a, const Transform &b)
{
- return a * ProjectionTransform(b);
+ return a * ProjectionTransform(b);
}
-ccl_device_inline ProjectionTransform operator*(const Transform& a, const ProjectionTransform& b)
+ccl_device_inline ProjectionTransform operator*(const Transform &a, const ProjectionTransform &b)
{
- return ProjectionTransform(a) * b;
+ return ProjectionTransform(a) * b;
}
-ccl_device_inline void print_projection(const char *label, const ProjectionTransform& t)
+ccl_device_inline void print_projection(const char *label, const ProjectionTransform &t)
{
- print_float4(label, t.x);
- print_float4(label, t.y);
- print_float4(label, t.z);
- print_float4(label, t.w);
- printf("\n");
+ print_float4(label, t.x);
+ print_float4(label, t.y);
+ print_float4(label, t.z);
+ print_float4(label, t.w);
+ printf("\n");
}
ccl_device_inline ProjectionTransform projection_perspective(float fov, float n, float f)
{
- ProjectionTransform persp = make_projection(
- 1, 0, 0, 0,
- 0, 1, 0, 0,
- 0, 0, f / (f - n), -f*n / (f - n),
- 0, 0, 1, 0);
+ ProjectionTransform persp = make_projection(
+ 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, f / (f - n), -f * n / (f - n), 0, 0, 1, 0);
- float inv_angle = 1.0f/tanf(0.5f*fov);
+ float inv_angle = 1.0f / tanf(0.5f * fov);
- Transform scale = transform_scale(inv_angle, inv_angle, 1);
+ Transform scale = transform_scale(inv_angle, inv_angle, 1);
- return scale * persp;
+ return scale * persp;
}
ccl_device_inline ProjectionTransform projection_orthographic(float znear, float zfar)
{
- Transform t =
- transform_scale(1.0f, 1.0f, 1.0f / (zfar-znear)) *
- transform_translate(0.0f, 0.0f, -znear);
+ Transform t = transform_scale(1.0f, 1.0f, 1.0f / (zfar - znear)) *
+ transform_translate(0.0f, 0.0f, -znear);
- return ProjectionTransform(t);
+ return ProjectionTransform(t);
}
-#endif /* __KERNEL_GPU__ */
+#endif /* __KERNEL_GPU__ */
CCL_NAMESPACE_END
-#endif /* __UTIL_PROJECTION_H__ */
+#endif /* __UTIL_PROJECTION_H__ */
diff --git a/intern/cycles/util/util_queue.h b/intern/cycles/util/util_queue.h
index 0a2b7718f57..622f4fe3e47 100644
--- a/intern/cycles/util/util_queue.h
+++ b/intern/cycles/util/util_queue.h
@@ -25,4 +25,4 @@ using std::queue;
CCL_NAMESPACE_END
-#endif /* __UTIL_LIST_H__ */
+#endif /* __UTIL_LIST_H__ */
diff --git a/intern/cycles/util/util_rect.h b/intern/cycles/util/util_rect.h
index 389669acf2e..36f02a01f7b 100644
--- a/intern/cycles/util/util_rect.h
+++ b/intern/cycles/util/util_rect.h
@@ -26,47 +26,47 @@ CCL_NAMESPACE_BEGIN
ccl_device_inline int4 rect_from_shape(int x0, int y0, int w, int h)
{
- return make_int4(x0, y0, x0 + w, y0 + h);
+ return make_int4(x0, y0, x0 + w, y0 + h);
}
ccl_device_inline int4 rect_expand(int4 rect, int d)
{
- return make_int4(rect.x - d, rect.y - d, rect.z + d, rect.w + d);
+ return make_int4(rect.x - d, rect.y - d, rect.z + d, rect.w + d);
}
/* Returns the intersection of two rects. */
ccl_device_inline int4 rect_clip(int4 a, int4 b)
{
- return make_int4(max(a.x, b.x), max(a.y, b.y), min(a.z, b.z), min(a.w, b.w));
+ return make_int4(max(a.x, b.x), max(a.y, b.y), min(a.z, b.z), min(a.w, b.w));
}
ccl_device_inline bool rect_is_valid(int4 rect)
{
- return (rect.z > rect.x) && (rect.w > rect.y);
+ return (rect.z > rect.x) && (rect.w > rect.y);
}
/* Returns the local row-major index of the pixel inside the rect. */
ccl_device_inline int coord_to_local_index(int4 rect, int x, int y)
{
- int w = rect.z - rect.x;
- return (y - rect.y) * w + (x - rect.x);
+ int w = rect.z - rect.x;
+ return (y - rect.y) * w + (x - rect.x);
}
/* Finds the coordinates of a pixel given by its row-major index in the rect,
* and returns whether the pixel is inside it. */
ccl_device_inline bool local_index_to_coord(int4 rect, int idx, int *x, int *y)
{
- int w = rect.z - rect.x;
- *x = (idx % w) + rect.x;
- *y = (idx / w) + rect.y;
- return (*y < rect.w);
+ int w = rect.z - rect.x;
+ *x = (idx % w) + rect.x;
+ *y = (idx / w) + rect.y;
+ return (*y < rect.w);
}
ccl_device_inline int rect_size(int4 rect)
{
- return (rect.z - rect.x) * (rect.w - rect.y);
+ return (rect.z - rect.x) * (rect.w - rect.y);
}
CCL_NAMESPACE_END
-#endif /* __UTIL_RECT_H__ */
+#endif /* __UTIL_RECT_H__ */
diff --git a/intern/cycles/util/util_set.h b/intern/cycles/util/util_set.h
index a9c56bb4919..298e1f7729a 100644
--- a/intern/cycles/util/util_set.h
+++ b/intern/cycles/util/util_set.h
@@ -31,4 +31,4 @@ using std::unordered_set;
CCL_NAMESPACE_END
-#endif /* __UTIL_SET_H__ */
+#endif /* __UTIL_SET_H__ */
diff --git a/intern/cycles/util/util_simd.cpp b/intern/cycles/util/util_simd.cpp
index f90439c188b..861dcf1fe36 100644
--- a/intern/cycles/util/util_simd.cpp
+++ b/intern/cycles/util/util_simd.cpp
@@ -15,33 +15,29 @@
* limitations under the License.
*/
-#if (defined(WITH_KERNEL_SSE2)) || \
- (defined(WITH_KERNEL_NATIVE) && defined(__SSE2__))
+#if (defined(WITH_KERNEL_SSE2)) || (defined(WITH_KERNEL_NATIVE) && defined(__SSE2__))
-#define __KERNEL_SSE2__
-#include "util/util_simd.h"
+# define __KERNEL_SSE2__
+# include "util/util_simd.h"
CCL_NAMESPACE_BEGIN
-const __m128 _mm_lookupmask_ps[16] = {
- _mm_castsi128_ps(_mm_set_epi32( 0, 0, 0, 0)),
- _mm_castsi128_ps(_mm_set_epi32( 0, 0, 0,-1)),
- _mm_castsi128_ps(_mm_set_epi32( 0, 0,-1, 0)),
- _mm_castsi128_ps(_mm_set_epi32( 0, 0,-1,-1)),
- _mm_castsi128_ps(_mm_set_epi32( 0,-1, 0, 0)),
- _mm_castsi128_ps(_mm_set_epi32( 0,-1, 0,-1)),
- _mm_castsi128_ps(_mm_set_epi32( 0,-1,-1, 0)),
- _mm_castsi128_ps(_mm_set_epi32( 0,-1,-1,-1)),
- _mm_castsi128_ps(_mm_set_epi32(-1, 0, 0, 0)),
- _mm_castsi128_ps(_mm_set_epi32(-1, 0, 0,-1)),
- _mm_castsi128_ps(_mm_set_epi32(-1, 0,-1, 0)),
- _mm_castsi128_ps(_mm_set_epi32(-1, 0,-1,-1)),
- _mm_castsi128_ps(_mm_set_epi32(-1,-1, 0, 0)),
- _mm_castsi128_ps(_mm_set_epi32(-1,-1, 0,-1)),
- _mm_castsi128_ps(_mm_set_epi32(-1,-1,-1, 0)),
- _mm_castsi128_ps(_mm_set_epi32(-1,-1,-1,-1))
-};
-
+const __m128 _mm_lookupmask_ps[16] = {_mm_castsi128_ps(_mm_set_epi32(0, 0, 0, 0)),
+ _mm_castsi128_ps(_mm_set_epi32(0, 0, 0, -1)),
+ _mm_castsi128_ps(_mm_set_epi32(0, 0, -1, 0)),
+ _mm_castsi128_ps(_mm_set_epi32(0, 0, -1, -1)),
+ _mm_castsi128_ps(_mm_set_epi32(0, -1, 0, 0)),
+ _mm_castsi128_ps(_mm_set_epi32(0, -1, 0, -1)),
+ _mm_castsi128_ps(_mm_set_epi32(0, -1, -1, 0)),
+ _mm_castsi128_ps(_mm_set_epi32(0, -1, -1, -1)),
+ _mm_castsi128_ps(_mm_set_epi32(-1, 0, 0, 0)),
+ _mm_castsi128_ps(_mm_set_epi32(-1, 0, 0, -1)),
+ _mm_castsi128_ps(_mm_set_epi32(-1, 0, -1, 0)),
+ _mm_castsi128_ps(_mm_set_epi32(-1, 0, -1, -1)),
+ _mm_castsi128_ps(_mm_set_epi32(-1, -1, 0, 0)),
+ _mm_castsi128_ps(_mm_set_epi32(-1, -1, 0, -1)),
+ _mm_castsi128_ps(_mm_set_epi32(-1, -1, -1, 0)),
+ _mm_castsi128_ps(_mm_set_epi32(-1, -1, -1, -1))};
CCL_NAMESPACE_END
diff --git a/intern/cycles/util/util_simd.h b/intern/cycles/util/util_simd.h
index c92fc1ae391..8fcaadc5f53 100644
--- a/intern/cycles/util/util_simd.h
+++ b/intern/cycles/util/util_simd.h
@@ -20,439 +20,550 @@
#ifndef __KERNEL_GPU__
-#include <limits>
+# include <limits>
-#include "util/util_defines.h"
+# include "util/util_defines.h"
/* SSE Intrinsics includes
*
* We assume __KERNEL_SSEX__ flags to have been defined at this point */
/* SSE intrinsics headers */
-#ifndef FREE_WINDOWS64
+# ifndef FREE_WINDOWS64
-#ifdef _MSC_VER
-# include <intrin.h>
-#elif (defined(__x86_64__) || defined(__i386__))
-# include <x86intrin.h>
-#endif
+# ifdef _MSC_VER
+# include <intrin.h>
+# elif (defined(__x86_64__) || defined(__i386__))
+# include <x86intrin.h>
+# endif
-#else
+# else
/* MinGW64 has conflicting declarations for these SSE headers in <windows.h>.
* Since we can't avoid including <windows.h>, better only include that */
-#include "util/util_windows.h"
+# include "util/util_windows.h"
-#endif
+# endif
-#if defined(__x86_64__) || defined(__i386__) || defined(_M_X64) || defined(_M_IX86)
- #define SIMD_SET_FLUSH_TO_ZERO \
- _MM_SET_FLUSH_ZERO_MODE(_MM_FLUSH_ZERO_ON); \
- _MM_SET_DENORMALS_ZERO_MODE(_MM_DENORMALS_ZERO_ON);
-#else
- #define SIMD_SET_FLUSH_TO_ZERO
-#endif
+# if defined(__x86_64__) || defined(__i386__) || defined(_M_X64) || defined(_M_IX86)
+# define SIMD_SET_FLUSH_TO_ZERO \
+ _MM_SET_FLUSH_ZERO_MODE(_MM_FLUSH_ZERO_ON); \
+ _MM_SET_DENORMALS_ZERO_MODE(_MM_DENORMALS_ZERO_ON);
+# else
+# define SIMD_SET_FLUSH_TO_ZERO
+# endif
CCL_NAMESPACE_BEGIN
-#ifdef __KERNEL_SSE2__
+# ifdef __KERNEL_SSE2__
extern const __m128 _mm_lookupmask_ps[16];
/* Special Types */
static struct TrueTy {
-__forceinline operator bool( ) const { return true; }
+ __forceinline operator bool() const
+ {
+ return true;
+ }
} True ccl_maybe_unused;
static struct FalseTy {
-__forceinline operator bool( ) const { return false; }
+ __forceinline operator bool() const
+ {
+ return false;
+ }
} False ccl_maybe_unused;
-static struct NegInfTy
-{
-__forceinline operator float ( ) const { return -std::numeric_limits<float>::infinity(); }
-__forceinline operator int ( ) const { return std::numeric_limits<int>::min(); }
+static struct NegInfTy {
+ __forceinline operator float() const
+ {
+ return -std::numeric_limits<float>::infinity();
+ }
+ __forceinline operator int() const
+ {
+ return std::numeric_limits<int>::min();
+ }
} neg_inf ccl_maybe_unused;
-static struct PosInfTy
-{
-__forceinline operator float ( ) const { return std::numeric_limits<float>::infinity(); }
-__forceinline operator int ( ) const { return std::numeric_limits<int>::max(); }
+static struct PosInfTy {
+ __forceinline operator float() const
+ {
+ return std::numeric_limits<float>::infinity();
+ }
+ __forceinline operator int() const
+ {
+ return std::numeric_limits<int>::max();
+ }
} inf ccl_maybe_unused, pos_inf ccl_maybe_unused;
/* Intrinsics Functions */
-#if defined(__BMI__) && defined(__GNUC__)
-# ifndef _tzcnt_u32
-# define _tzcnt_u32 __tzcnt_u32
-# endif
-# ifndef _tzcnt_u64
-# define _tzcnt_u64 __tzcnt_u64
-# endif
-#endif
+# if defined(__BMI__) && defined(__GNUC__)
+# ifndef _tzcnt_u32
+# define _tzcnt_u32 __tzcnt_u32
+# endif
+# ifndef _tzcnt_u64
+# define _tzcnt_u64 __tzcnt_u64
+# endif
+# endif
-#if defined(__LZCNT__)
-#define _lzcnt_u32 __lzcnt32
-#define _lzcnt_u64 __lzcnt64
-#endif
+# if defined(__LZCNT__)
+# define _lzcnt_u32 __lzcnt32
+# define _lzcnt_u64 __lzcnt64
+# endif
-#if defined(_WIN32) && !defined(__MINGW32__) && !defined(__clang__)
+# if defined(_WIN32) && !defined(__MINGW32__) && !defined(__clang__)
-__forceinline int __popcnt(int in) {
+__forceinline int __popcnt(int in)
+{
return _mm_popcnt_u32(in);
}
-#if !defined(_MSC_VER)
-__forceinline unsigned int __popcnt(unsigned int in) {
+# if !defined(_MSC_VER)
+__forceinline unsigned int __popcnt(unsigned int in)
+{
return _mm_popcnt_u32(in);
}
-#endif
+# endif
-#if defined(__KERNEL_64_BIT__)
-__forceinline long long __popcnt(long long in) {
+# if defined(__KERNEL_64_BIT__)
+__forceinline long long __popcnt(long long in)
+{
return _mm_popcnt_u64(in);
}
-__forceinline size_t __popcnt(size_t in) {
+__forceinline size_t __popcnt(size_t in)
+{
return _mm_popcnt_u64(in);
}
-#endif
+# endif
-__forceinline int __bsf(int v) {
-#if defined(__KERNEL_AVX2__)
+__forceinline int __bsf(int v)
+{
+# if defined(__KERNEL_AVX2__)
return _tzcnt_u32(v);
-#else
- unsigned long r = 0; _BitScanForward(&r,v); return r;
-#endif
+# else
+ unsigned long r = 0;
+ _BitScanForward(&r, v);
+ return r;
+# endif
}
-__forceinline unsigned int __bsf(unsigned int v) {
-#if defined(__KERNEL_AVX2__)
+__forceinline unsigned int __bsf(unsigned int v)
+{
+# if defined(__KERNEL_AVX2__)
return _tzcnt_u32(v);
-#else
- unsigned long r = 0; _BitScanForward(&r,v); return r;
-#endif
+# else
+ unsigned long r = 0;
+ _BitScanForward(&r, v);
+ return r;
+# endif
}
-__forceinline int __bsr(int v) {
- unsigned long r = 0; _BitScanReverse(&r,v); return r;
+__forceinline int __bsr(int v)
+{
+ unsigned long r = 0;
+ _BitScanReverse(&r, v);
+ return r;
}
-__forceinline int __btc(int v, int i) {
- long r = v; _bittestandcomplement(&r,i); return r;
+__forceinline int __btc(int v, int i)
+{
+ long r = v;
+ _bittestandcomplement(&r, i);
+ return r;
}
-__forceinline int __bts(int v, int i) {
- long r = v; _bittestandset(&r,i); return r;
+__forceinline int __bts(int v, int i)
+{
+ long r = v;
+ _bittestandset(&r, i);
+ return r;
}
-__forceinline int __btr(int v, int i) {
- long r = v; _bittestandreset(&r,i); return r;
+__forceinline int __btr(int v, int i)
+{
+ long r = v;
+ _bittestandreset(&r, i);
+ return r;
}
-__forceinline int bitscan(int v) {
-#if defined(__KERNEL_AVX2__)
+__forceinline int bitscan(int v)
+{
+# if defined(__KERNEL_AVX2__)
return _tzcnt_u32(v);
-#else
+# else
return __bsf(v);
-#endif
+# endif
}
__forceinline int clz(const int x)
{
-#if defined(__KERNEL_AVX2__)
+# if defined(__KERNEL_AVX2__)
return _lzcnt_u32(x);
-#else
- if(UNLIKELY(x == 0)) return 32;
+# else
+ if (UNLIKELY(x == 0))
+ return 32;
return 31 - __bsr(x);
-#endif
+# endif
}
-__forceinline int __bscf(int& v)
+__forceinline int __bscf(int &v)
{
int i = __bsf(v);
- v &= v-1;
+ v &= v - 1;
return i;
}
-__forceinline unsigned int __bscf(unsigned int& v)
+__forceinline unsigned int __bscf(unsigned int &v)
{
unsigned int i = __bsf(v);
- v &= v-1;
+ v &= v - 1;
return i;
}
-#if defined(__KERNEL_64_BIT__)
+# if defined(__KERNEL_64_BIT__)
-__forceinline size_t __bsf(size_t v) {
-#if defined(__KERNEL_AVX2__)
+__forceinline size_t __bsf(size_t v)
+{
+# if defined(__KERNEL_AVX2__)
return _tzcnt_u64(v);
-#else
- unsigned long r = 0; _BitScanForward64(&r,v); return r;
-#endif
+# else
+ unsigned long r = 0;
+ _BitScanForward64(&r, v);
+ return r;
+# endif
}
-__forceinline size_t __bsr(size_t v) {
- unsigned long r = 0; _BitScanReverse64(&r,v); return r;
+__forceinline size_t __bsr(size_t v)
+{
+ unsigned long r = 0;
+ _BitScanReverse64(&r, v);
+ return r;
}
-__forceinline size_t __btc(size_t v, size_t i) {
- size_t r = v; _bittestandcomplement64((__int64*)&r,i); return r;
+__forceinline size_t __btc(size_t v, size_t i)
+{
+ size_t r = v;
+ _bittestandcomplement64((__int64 *)&r, i);
+ return r;
}
-__forceinline size_t __bts(size_t v, size_t i) {
- __int64 r = v; _bittestandset64(&r,i); return r;
+__forceinline size_t __bts(size_t v, size_t i)
+{
+ __int64 r = v;
+ _bittestandset64(&r, i);
+ return r;
}
-__forceinline size_t __btr(size_t v, size_t i) {
- __int64 r = v; _bittestandreset64(&r,i); return r;
+__forceinline size_t __btr(size_t v, size_t i)
+{
+ __int64 r = v;
+ _bittestandreset64(&r, i);
+ return r;
}
-__forceinline size_t bitscan(size_t v) {
-#if defined(__KERNEL_AVX2__)
-#if defined(__KERNEL_64_BIT__)
+__forceinline size_t bitscan(size_t v)
+{
+# if defined(__KERNEL_AVX2__)
+# if defined(__KERNEL_64_BIT__)
return _tzcnt_u64(v);
-#else
+# else
return _tzcnt_u32(v);
-#endif
-#else
+# endif
+# else
return __bsf(v);
-#endif
+# endif
}
-__forceinline size_t __bscf(size_t& v)
+__forceinline size_t __bscf(size_t &v)
{
size_t i = __bsf(v);
- v &= v-1;
+ v &= v - 1;
return i;
}
-#endif /* __KERNEL_64_BIT__ */
+# endif /* __KERNEL_64_BIT__ */
-#else /* _WIN32 */
+# else /* _WIN32 */
-__forceinline unsigned int __popcnt(unsigned int in) {
- int r = 0; asm ("popcnt %1,%0" : "=r"(r) : "r"(in)); return r;
+__forceinline unsigned int __popcnt(unsigned int in)
+{
+ int r = 0;
+ asm("popcnt %1,%0" : "=r"(r) : "r"(in));
+ return r;
}
-__forceinline int __bsf(int v) {
- int r = 0; asm ("bsf %1,%0" : "=r"(r) : "r"(v)); return r;
+__forceinline int __bsf(int v)
+{
+ int r = 0;
+ asm("bsf %1,%0" : "=r"(r) : "r"(v));
+ return r;
}
-__forceinline int __bsr(int v) {
- int r = 0; asm ("bsr %1,%0" : "=r"(r) : "r"(v)); return r;
+__forceinline int __bsr(int v)
+{
+ int r = 0;
+ asm("bsr %1,%0" : "=r"(r) : "r"(v));
+ return r;
}
-__forceinline int __btc(int v, int i) {
- int r = 0; asm ("btc %1,%0" : "=r"(r) : "r"(i), "0"(v) : "flags" ); return r;
+__forceinline int __btc(int v, int i)
+{
+ int r = 0;
+ asm("btc %1,%0" : "=r"(r) : "r"(i), "0"(v) : "flags");
+ return r;
}
-__forceinline int __bts(int v, int i) {
- int r = 0; asm ("bts %1,%0" : "=r"(r) : "r"(i), "0"(v) : "flags"); return r;
+__forceinline int __bts(int v, int i)
+{
+ int r = 0;
+ asm("bts %1,%0" : "=r"(r) : "r"(i), "0"(v) : "flags");
+ return r;
}
-__forceinline int __btr(int v, int i) {
- int r = 0; asm ("btr %1,%0" : "=r"(r) : "r"(i), "0"(v) : "flags"); return r;
+__forceinline int __btr(int v, int i)
+{
+ int r = 0;
+ asm("btr %1,%0" : "=r"(r) : "r"(i), "0"(v) : "flags");
+ return r;
}
-#if (defined(__KERNEL_64_BIT__) || defined(__APPLE__)) && !(defined(__ILP32__) && defined(__x86_64__))
-__forceinline size_t __bsf(size_t v) {
- size_t r = 0; asm ("bsf %1,%0" : "=r"(r) : "r"(v)); return r;
+# if (defined(__KERNEL_64_BIT__) || defined(__APPLE__)) && \
+ !(defined(__ILP32__) && defined(__x86_64__))
+__forceinline size_t __bsf(size_t v)
+{
+ size_t r = 0;
+ asm("bsf %1,%0" : "=r"(r) : "r"(v));
+ return r;
}
-#endif
+# endif
-__forceinline unsigned int __bsf(unsigned int v) {
- unsigned int r = 0; asm ("bsf %1,%0" : "=r"(r) : "r"(v)); return r;
+__forceinline unsigned int __bsf(unsigned int v)
+{
+ unsigned int r = 0;
+ asm("bsf %1,%0" : "=r"(r) : "r"(v));
+ return r;
}
-__forceinline size_t __bsr(size_t v) {
- size_t r = 0; asm ("bsr %1,%0" : "=r"(r) : "r"(v)); return r;
+__forceinline size_t __bsr(size_t v)
+{
+ size_t r = 0;
+ asm("bsr %1,%0" : "=r"(r) : "r"(v));
+ return r;
}
-__forceinline size_t __btc(size_t v, size_t i) {
- size_t r = 0; asm ("btc %1,%0" : "=r"(r) : "r"(i), "0"(v) : "flags" ); return r;
+__forceinline size_t __btc(size_t v, size_t i)
+{
+ size_t r = 0;
+ asm("btc %1,%0" : "=r"(r) : "r"(i), "0"(v) : "flags");
+ return r;
}
-__forceinline size_t __bts(size_t v, size_t i) {
- size_t r = 0; asm ("bts %1,%0" : "=r"(r) : "r"(i), "0"(v) : "flags"); return r;
+__forceinline size_t __bts(size_t v, size_t i)
+{
+ size_t r = 0;
+ asm("bts %1,%0" : "=r"(r) : "r"(i), "0"(v) : "flags");
+ return r;
}
-__forceinline size_t __btr(size_t v, size_t i) {
- size_t r = 0; asm ("btr %1,%0" : "=r"(r) : "r"(i), "0"(v) : "flags"); return r;
+__forceinline size_t __btr(size_t v, size_t i)
+{
+ size_t r = 0;
+ asm("btr %1,%0" : "=r"(r) : "r"(i), "0"(v) : "flags");
+ return r;
}
-__forceinline int bitscan(int v) {
-#if defined(__KERNEL_AVX2__)
+__forceinline int bitscan(int v)
+{
+# if defined(__KERNEL_AVX2__)
return _tzcnt_u32(v);
-#else
+# else
return __bsf(v);
-#endif
+# endif
}
-__forceinline unsigned int bitscan(unsigned int v) {
-#if defined(__KERNEL_AVX2__)
+__forceinline unsigned int bitscan(unsigned int v)
+{
+# if defined(__KERNEL_AVX2__)
return _tzcnt_u32(v);
-#else
+# else
return __bsf(v);
-#endif
+# endif
}
-#if (defined(__KERNEL_64_BIT__) || defined(__APPLE__)) && !(defined(__ILP32__) && defined(__x86_64__))
-__forceinline size_t bitscan(size_t v) {
-#if defined(__KERNEL_AVX2__)
-#if defined(__KERNEL_64_BIT__)
+# if (defined(__KERNEL_64_BIT__) || defined(__APPLE__)) && \
+ !(defined(__ILP32__) && defined(__x86_64__))
+__forceinline size_t bitscan(size_t v)
+{
+# if defined(__KERNEL_AVX2__)
+# if defined(__KERNEL_64_BIT__)
return _tzcnt_u64(v);
-#else
+# else
return _tzcnt_u32(v);
-#endif
-#else
+# endif
+# else
return __bsf(v);
-#endif
+# endif
}
-#endif
+# endif
__forceinline int clz(const int x)
{
-#if defined(__KERNEL_AVX2__)
+# if defined(__KERNEL_AVX2__)
return _lzcnt_u32(x);
-#else
- if(UNLIKELY(x == 0)) return 32;
+# else
+ if (UNLIKELY(x == 0))
+ return 32;
return 31 - __bsr(x);
-#endif
+# endif
}
-__forceinline int __bscf(int& v)
+__forceinline int __bscf(int &v)
{
int i = bitscan(v);
-#if defined(__KERNEL_AVX2__)
- v &= v-1;
-#else
- v = __btc(v,i);
-#endif
+# if defined(__KERNEL_AVX2__)
+ v &= v - 1;
+# else
+ v = __btc(v, i);
+# endif
return i;
}
-__forceinline unsigned int __bscf(unsigned int& v)
+__forceinline unsigned int __bscf(unsigned int &v)
{
unsigned int i = bitscan(v);
- v &= v-1;
+ v &= v - 1;
return i;
}
-#if (defined(__KERNEL_64_BIT__) || defined(__APPLE__)) && !(defined(__ILP32__) && defined(__x86_64__))
-__forceinline size_t __bscf(size_t& v)
+# if (defined(__KERNEL_64_BIT__) || defined(__APPLE__)) && \
+ !(defined(__ILP32__) && defined(__x86_64__))
+__forceinline size_t __bscf(size_t &v)
{
size_t i = bitscan(v);
-#if defined(__KERNEL_AVX2__)
- v &= v-1;
-#else
- v = __btc(v,i);
-#endif
+# if defined(__KERNEL_AVX2__)
+ v &= v - 1;
+# else
+ v = __btc(v, i);
+# endif
return i;
}
-#endif
+# endif
-#endif /* _WIN32 */
+# endif /* _WIN32 */
/* Test __KERNEL_SSE41__ for MSVC which does not define __SSE4_1__, and test
* __SSE4_1__ to avoid OpenImageIO conflicts with our emulation macros on other
* platforms when compiling code outside the kernel. */
-#if !(defined(__KERNEL_SSE41__) || defined(__SSE4_1__) || defined(__SSE4_2__))
+# if !(defined(__KERNEL_SSE41__) || defined(__SSE4_1__) || defined(__SSE4_2__))
/* Emulation of SSE4 functions with SSE2 */
-#define _MM_FROUND_TO_NEAREST_INT 0x00
-#define _MM_FROUND_TO_NEG_INF 0x01
-#define _MM_FROUND_TO_POS_INF 0x02
-#define _MM_FROUND_TO_ZERO 0x03
-#define _MM_FROUND_CUR_DIRECTION 0x04
+# define _MM_FROUND_TO_NEAREST_INT 0x00
+# define _MM_FROUND_TO_NEG_INF 0x01
+# define _MM_FROUND_TO_POS_INF 0x02
+# define _MM_FROUND_TO_ZERO 0x03
+# define _MM_FROUND_CUR_DIRECTION 0x04
-#undef _mm_blendv_ps
-#define _mm_blendv_ps _mm_blendv_ps_emu
-__forceinline __m128 _mm_blendv_ps_emu( __m128 value, __m128 input, __m128 mask)
+# undef _mm_blendv_ps
+# define _mm_blendv_ps _mm_blendv_ps_emu
+__forceinline __m128 _mm_blendv_ps_emu(__m128 value, __m128 input, __m128 mask)
{
- __m128i isignmask = _mm_set1_epi32(0x80000000);
- __m128 signmask = _mm_castsi128_ps(isignmask);
- __m128i iandsign = _mm_castps_si128(_mm_and_ps(mask, signmask));
- __m128i icmpmask = _mm_cmpeq_epi32(iandsign, isignmask);
- __m128 cmpmask = _mm_castsi128_ps(icmpmask);
- return _mm_or_ps(_mm_and_ps(cmpmask, input), _mm_andnot_ps(cmpmask, value));
+ __m128i isignmask = _mm_set1_epi32(0x80000000);
+ __m128 signmask = _mm_castsi128_ps(isignmask);
+ __m128i iandsign = _mm_castps_si128(_mm_and_ps(mask, signmask));
+ __m128i icmpmask = _mm_cmpeq_epi32(iandsign, isignmask);
+ __m128 cmpmask = _mm_castsi128_ps(icmpmask);
+ return _mm_or_ps(_mm_and_ps(cmpmask, input), _mm_andnot_ps(cmpmask, value));
}
-#undef _mm_blend_ps
-#define _mm_blend_ps _mm_blend_ps_emu
-__forceinline __m128 _mm_blend_ps_emu( __m128 value, __m128 input, const int mask)
+# undef _mm_blend_ps
+# define _mm_blend_ps _mm_blend_ps_emu
+__forceinline __m128 _mm_blend_ps_emu(__m128 value, __m128 input, const int mask)
{
- assert(mask < 0x10); return _mm_blendv_ps(value, input, _mm_lookupmask_ps[mask]);
+ assert(mask < 0x10);
+ return _mm_blendv_ps(value, input, _mm_lookupmask_ps[mask]);
}
-#undef _mm_blendv_epi8
-#define _mm_blendv_epi8 _mm_blendv_epi8_emu
-__forceinline __m128i _mm_blendv_epi8_emu( __m128i value, __m128i input, __m128i mask)
+# undef _mm_blendv_epi8
+# define _mm_blendv_epi8 _mm_blendv_epi8_emu
+__forceinline __m128i _mm_blendv_epi8_emu(__m128i value, __m128i input, __m128i mask)
{
- return _mm_or_si128(_mm_and_si128(mask, input), _mm_andnot_si128(mask, value));
+ return _mm_or_si128(_mm_and_si128(mask, input), _mm_andnot_si128(mask, value));
}
-#undef _mm_min_epi32
-#define _mm_min_epi32 _mm_min_epi32_emu
-__forceinline __m128i _mm_min_epi32_emu( __m128i value, __m128i input)
+# undef _mm_min_epi32
+# define _mm_min_epi32 _mm_min_epi32_emu
+__forceinline __m128i _mm_min_epi32_emu(__m128i value, __m128i input)
{
- return _mm_blendv_epi8(input, value, _mm_cmplt_epi32(value, input));
+ return _mm_blendv_epi8(input, value, _mm_cmplt_epi32(value, input));
}
-#undef _mm_max_epi32
-#define _mm_max_epi32 _mm_max_epi32_emu
-__forceinline __m128i _mm_max_epi32_emu( __m128i value, __m128i input)
+# undef _mm_max_epi32
+# define _mm_max_epi32 _mm_max_epi32_emu
+__forceinline __m128i _mm_max_epi32_emu(__m128i value, __m128i input)
{
- return _mm_blendv_epi8(value, input, _mm_cmplt_epi32(value, input));
+ return _mm_blendv_epi8(value, input, _mm_cmplt_epi32(value, input));
}
-#undef _mm_extract_epi32
-#define _mm_extract_epi32 _mm_extract_epi32_emu
-__forceinline int _mm_extract_epi32_emu( __m128i input, const int index)
+# undef _mm_extract_epi32
+# define _mm_extract_epi32 _mm_extract_epi32_emu
+__forceinline int _mm_extract_epi32_emu(__m128i input, const int index)
{
- switch(index) {
- case 0: return _mm_cvtsi128_si32(input);
- case 1: return _mm_cvtsi128_si32(_mm_shuffle_epi32(input, _MM_SHUFFLE(1, 1, 1, 1)));
- case 2: return _mm_cvtsi128_si32(_mm_shuffle_epi32(input, _MM_SHUFFLE(2, 2, 2, 2)));
- case 3: return _mm_cvtsi128_si32(_mm_shuffle_epi32(input, _MM_SHUFFLE(3, 3, 3, 3)));
- default: assert(false); return 0;
+ switch (index) {
+ case 0:
+ return _mm_cvtsi128_si32(input);
+ case 1:
+ return _mm_cvtsi128_si32(_mm_shuffle_epi32(input, _MM_SHUFFLE(1, 1, 1, 1)));
+ case 2:
+ return _mm_cvtsi128_si32(_mm_shuffle_epi32(input, _MM_SHUFFLE(2, 2, 2, 2)));
+ case 3:
+ return _mm_cvtsi128_si32(_mm_shuffle_epi32(input, _MM_SHUFFLE(3, 3, 3, 3)));
+ default:
+ assert(false);
+ return 0;
}
}
-#undef _mm_insert_epi32
-#define _mm_insert_epi32 _mm_insert_epi32_emu
-__forceinline __m128i _mm_insert_epi32_emu( __m128i value, int input, const int index)
+# undef _mm_insert_epi32
+# define _mm_insert_epi32 _mm_insert_epi32_emu
+__forceinline __m128i _mm_insert_epi32_emu(__m128i value, int input, const int index)
{
- assert(index >= 0 && index < 4); ((int*)&value)[index] = input; return value;
+ assert(index >= 0 && index < 4);
+ ((int *)&value)[index] = input;
+ return value;
}
-#undef _mm_insert_ps
-#define _mm_insert_ps _mm_insert_ps_emu
-__forceinline __m128 _mm_insert_ps_emu( __m128 value, __m128 input, const int index)
+# undef _mm_insert_ps
+# define _mm_insert_ps _mm_insert_ps_emu
+__forceinline __m128 _mm_insert_ps_emu(__m128 value, __m128 input, const int index)
{
- assert(index < 0x100);
- ((float*)&value)[(index >> 4)&0x3] = ((float*)&input)[index >> 6];
- return _mm_andnot_ps(_mm_lookupmask_ps[index&0xf], value);
+ assert(index < 0x100);
+ ((float *)&value)[(index >> 4) & 0x3] = ((float *)&input)[index >> 6];
+ return _mm_andnot_ps(_mm_lookupmask_ps[index & 0xf], value);
}
-#undef _mm_round_ps
-#define _mm_round_ps _mm_round_ps_emu
-__forceinline __m128 _mm_round_ps_emu( __m128 value, const int flags)
+# undef _mm_round_ps
+# define _mm_round_ps _mm_round_ps_emu
+__forceinline __m128 _mm_round_ps_emu(__m128 value, const int flags)
{
- switch(flags)
- {
- case _MM_FROUND_TO_NEAREST_INT: return _mm_cvtepi32_ps(_mm_cvtps_epi32(value));
- case _MM_FROUND_TO_NEG_INF : return _mm_cvtepi32_ps(_mm_cvtps_epi32(_mm_add_ps(value, _mm_set1_ps(-0.5f))));
- case _MM_FROUND_TO_POS_INF : return _mm_cvtepi32_ps(_mm_cvtps_epi32(_mm_add_ps(value, _mm_set1_ps( 0.5f))));
- case _MM_FROUND_TO_ZERO : return _mm_cvtepi32_ps(_mm_cvttps_epi32(value));
+ switch (flags) {
+ case _MM_FROUND_TO_NEAREST_INT:
+ return _mm_cvtepi32_ps(_mm_cvtps_epi32(value));
+ case _MM_FROUND_TO_NEG_INF:
+ return _mm_cvtepi32_ps(_mm_cvtps_epi32(_mm_add_ps(value, _mm_set1_ps(-0.5f))));
+ case _MM_FROUND_TO_POS_INF:
+ return _mm_cvtepi32_ps(_mm_cvtps_epi32(_mm_add_ps(value, _mm_set1_ps(0.5f))));
+ case _MM_FROUND_TO_ZERO:
+ return _mm_cvtepi32_ps(_mm_cvttps_epi32(value));
}
return value;
}
-#endif /* !(defined(__KERNEL_SSE41__) || defined(__SSE4_1__) || defined(__SSE4_2__)) */
+# endif /* !(defined(__KERNEL_SSE41__) || defined(__SSE4_1__) || defined(__SSE4_2__)) */
-#else /* __KERNEL_SSE2__ */
+# else /* __KERNEL_SSE2__ */
/* This section is for utility functions which operates on non-register data
* which might be used from a non-vectorized code.
@@ -460,38 +571,34 @@ __forceinline __m128 _mm_round_ps_emu( __m128 value, const int flags)
ccl_device_inline int bitscan(int value)
{
- assert(value != 0);
- int bit = 0;
- while((value & (1 << bit)) == 0) {
- ++bit;
- }
- return bit;
+ assert(value != 0);
+ int bit = 0;
+ while ((value & (1 << bit)) == 0) {
+ ++bit;
+ }
+ return bit;
}
ccl_device_inline int __bsr(int value)
{
- assert(value != 0);
- int bit = 0;
- while(value >>= 1) {
- ++bit;
- }
- return bit;
+ assert(value != 0);
+ int bit = 0;
+ while (value >>= 1) {
+ ++bit;
+ }
+ return bit;
}
-#endif /* __KERNEL_SSE2__ */
+# endif /* __KERNEL_SSE2__ */
/* quiet unused define warnings */
-#if defined(__KERNEL_SSE2__) || \
- defined(__KERNEL_SSE3__) || \
- defined(__KERNEL_SSSE3__) || \
- defined(__KERNEL_SSE41__) || \
- defined(__KERNEL_AVX__) || \
- defined(__KERNEL_AVX2__)
- /* do nothing */
-#endif
+# if defined(__KERNEL_SSE2__) || defined(__KERNEL_SSE3__) || defined(__KERNEL_SSSE3__) || \
+ defined(__KERNEL_SSE41__) || defined(__KERNEL_AVX__) || defined(__KERNEL_AVX2__)
+/* do nothing */
+# endif
CCL_NAMESPACE_END
-#endif /* __KERNEL_GPU__ */
+#endif /* __KERNEL_GPU__ */
-#endif /* __UTIL_SIMD_TYPES_H__ */
+#endif /* __UTIL_SIMD_TYPES_H__ */
diff --git a/intern/cycles/util/util_sky_model.cpp b/intern/cycles/util/util_sky_model.cpp
index 526bce4ff88..4a6a9f32607 100644
--- a/intern/cycles/util/util_sky_model.cpp
+++ b/intern/cycles/util/util_sky_model.cpp
@@ -111,23 +111,23 @@ CCL_NAMESPACE_BEGIN
// replicated to make this a stand-alone module.
#ifndef MATH_PI
-#define MATH_PI 3.141592653589793
+# define MATH_PI 3.141592653589793
#endif
#ifndef MATH_DEG_TO_RAD
-#define MATH_DEG_TO_RAD ( MATH_PI / 180.0 )
+# define MATH_DEG_TO_RAD (MATH_PI / 180.0)
#endif
#ifndef DEGREES
-#define DEGREES * MATH_DEG_TO_RAD
+# define DEGREES *MATH_DEG_TO_RAD
#endif
#ifndef TERRESTRIAL_SOLAR_RADIUS
-#define TERRESTRIAL_SOLAR_RADIUS ( ( 0.51 DEGREES ) / 2.0 )
+# define TERRESTRIAL_SOLAR_RADIUS ((0.51 DEGREES) / 2.0)
#endif
#ifndef ALLOC
-#define ALLOC(_struct) ((_struct *)malloc(sizeof(_struct)))
+# define ALLOC(_struct) ((_struct *)malloc(sizeof(_struct)))
#endif
// internal definitions
@@ -137,233 +137,213 @@ typedef const double *ArHosekSkyModel_Radiance_Dataset;
// internal functions
-static void ArHosekSkyModel_CookConfiguration(
- ArHosekSkyModel_Dataset dataset,
- ArHosekSkyModelConfiguration config,
- double turbidity,
- double albedo,
- double solar_elevation)
+static void ArHosekSkyModel_CookConfiguration(ArHosekSkyModel_Dataset dataset,
+ ArHosekSkyModelConfiguration config,
+ double turbidity,
+ double albedo,
+ double solar_elevation)
{
- const double * elev_matrix;
-
- int int_turbidity = (int)turbidity;
- double turbidity_rem = turbidity - (double)int_turbidity;
-
- solar_elevation = pow(solar_elevation / (MATH_PI / 2.0), (1.0 / 3.0));
-
- // alb 0 low turb
-
- elev_matrix = dataset + ( 9 * 6 * (int_turbidity-1));
-
- for(unsigned int i = 0; i < 9; ++i) {
- //(1-t).^3* A1 + 3*(1-t).^2.*t * A2 + 3*(1-t) .* t .^ 2 * A3 + t.^3 * A4;
- config[i] =
- (1.0-albedo) * (1.0 - turbidity_rem)
- * ( pow(1.0-solar_elevation, 5.0) * elev_matrix[i] +
- 5.0 * pow(1.0-solar_elevation, 4.0) * solar_elevation * elev_matrix[i+9] +
- 10.0*pow(1.0-solar_elevation, 3.0)*pow(solar_elevation, 2.0) * elev_matrix[i+18] +
- 10.0*pow(1.0-solar_elevation, 2.0)*pow(solar_elevation, 3.0) * elev_matrix[i+27] +
- 5.0*(1.0-solar_elevation)*pow(solar_elevation, 4.0) * elev_matrix[i+36] +
- pow(solar_elevation, 5.0) * elev_matrix[i+45]);
- }
-
- // alb 1 low turb
- elev_matrix = dataset + (9*6*10 + 9*6*(int_turbidity-1));
- for(unsigned int i = 0; i < 9; ++i) {
- //(1-t).^3* A1 + 3*(1-t).^2.*t * A2 + 3*(1-t) .* t .^ 2 * A3 + t.^3 * A4;
- config[i] +=
- (albedo) * (1.0 - turbidity_rem)
- * ( pow(1.0-solar_elevation, 5.0) * elev_matrix[i] +
- 5.0 * pow(1.0-solar_elevation, 4.0) * solar_elevation * elev_matrix[i+9] +
- 10.0*pow(1.0-solar_elevation, 3.0)*pow(solar_elevation, 2.0) * elev_matrix[i+18] +
- 10.0*pow(1.0-solar_elevation, 2.0)*pow(solar_elevation, 3.0) * elev_matrix[i+27] +
- 5.0*(1.0-solar_elevation)*pow(solar_elevation, 4.0) * elev_matrix[i+36] +
- pow(solar_elevation, 5.0) * elev_matrix[i+45]);
- }
-
- if(int_turbidity == 10)
- return;
-
- // alb 0 high turb
- elev_matrix = dataset + (9*6*(int_turbidity));
- for(unsigned int i = 0; i < 9; ++i) {
- //(1-t).^3* A1 + 3*(1-t).^2.*t * A2 + 3*(1-t) .* t .^ 2 * A3 + t.^3 * A4;
- config[i] +=
- (1.0-albedo) * (turbidity_rem)
- * ( pow(1.0-solar_elevation, 5.0) * elev_matrix[i] +
- 5.0 * pow(1.0-solar_elevation, 4.0) * solar_elevation * elev_matrix[i+9] +
- 10.0*pow(1.0-solar_elevation, 3.0)*pow(solar_elevation, 2.0) * elev_matrix[i+18] +
- 10.0*pow(1.0-solar_elevation, 2.0)*pow(solar_elevation, 3.0) * elev_matrix[i+27] +
- 5.0*(1.0-solar_elevation)*pow(solar_elevation, 4.0) * elev_matrix[i+36] +
- pow(solar_elevation, 5.0) * elev_matrix[i+45]);
- }
-
- // alb 1 high turb
- elev_matrix = dataset + (9*6*10 + 9*6*(int_turbidity));
- for(unsigned int i = 0; i < 9; ++i) {
- //(1-t).^3* A1 + 3*(1-t).^2.*t * A2 + 3*(1-t) .* t .^ 2 * A3 + t.^3 * A4;
- config[i] +=
- (albedo) * (turbidity_rem)
- * ( pow(1.0-solar_elevation, 5.0) * elev_matrix[i] +
- 5.0 * pow(1.0-solar_elevation, 4.0) * solar_elevation * elev_matrix[i+9] +
- 10.0*pow(1.0-solar_elevation, 3.0)*pow(solar_elevation, 2.0) * elev_matrix[i+18] +
- 10.0*pow(1.0-solar_elevation, 2.0)*pow(solar_elevation, 3.0) * elev_matrix[i+27] +
- 5.0*(1.0-solar_elevation)*pow(solar_elevation, 4.0) * elev_matrix[i+36] +
- pow(solar_elevation, 5.0) * elev_matrix[i+45]);
- }
+ const double *elev_matrix;
+
+ int int_turbidity = (int)turbidity;
+ double turbidity_rem = turbidity - (double)int_turbidity;
+
+ solar_elevation = pow(solar_elevation / (MATH_PI / 2.0), (1.0 / 3.0));
+
+ // alb 0 low turb
+
+ elev_matrix = dataset + (9 * 6 * (int_turbidity - 1));
+
+ for (unsigned int i = 0; i < 9; ++i) {
+ //(1-t).^3* A1 + 3*(1-t).^2.*t * A2 + 3*(1-t) .* t .^ 2 * A3 + t.^3 * A4;
+ config[i] =
+ (1.0 - albedo) * (1.0 - turbidity_rem) *
+ (pow(1.0 - solar_elevation, 5.0) * elev_matrix[i] +
+ 5.0 * pow(1.0 - solar_elevation, 4.0) * solar_elevation * elev_matrix[i + 9] +
+ 10.0 * pow(1.0 - solar_elevation, 3.0) * pow(solar_elevation, 2.0) * elev_matrix[i + 18] +
+ 10.0 * pow(1.0 - solar_elevation, 2.0) * pow(solar_elevation, 3.0) * elev_matrix[i + 27] +
+ 5.0 * (1.0 - solar_elevation) * pow(solar_elevation, 4.0) * elev_matrix[i + 36] +
+ pow(solar_elevation, 5.0) * elev_matrix[i + 45]);
+ }
+
+ // alb 1 low turb
+ elev_matrix = dataset + (9 * 6 * 10 + 9 * 6 * (int_turbidity - 1));
+ for (unsigned int i = 0; i < 9; ++i) {
+ //(1-t).^3* A1 + 3*(1-t).^2.*t * A2 + 3*(1-t) .* t .^ 2 * A3 + t.^3 * A4;
+ config[i] +=
+ (albedo) * (1.0 - turbidity_rem) *
+ (pow(1.0 - solar_elevation, 5.0) * elev_matrix[i] +
+ 5.0 * pow(1.0 - solar_elevation, 4.0) * solar_elevation * elev_matrix[i + 9] +
+ 10.0 * pow(1.0 - solar_elevation, 3.0) * pow(solar_elevation, 2.0) * elev_matrix[i + 18] +
+ 10.0 * pow(1.0 - solar_elevation, 2.0) * pow(solar_elevation, 3.0) * elev_matrix[i + 27] +
+ 5.0 * (1.0 - solar_elevation) * pow(solar_elevation, 4.0) * elev_matrix[i + 36] +
+ pow(solar_elevation, 5.0) * elev_matrix[i + 45]);
+ }
+
+ if (int_turbidity == 10)
+ return;
+
+ // alb 0 high turb
+ elev_matrix = dataset + (9 * 6 * (int_turbidity));
+ for (unsigned int i = 0; i < 9; ++i) {
+ //(1-t).^3* A1 + 3*(1-t).^2.*t * A2 + 3*(1-t) .* t .^ 2 * A3 + t.^3 * A4;
+ config[i] +=
+ (1.0 - albedo) * (turbidity_rem) *
+ (pow(1.0 - solar_elevation, 5.0) * elev_matrix[i] +
+ 5.0 * pow(1.0 - solar_elevation, 4.0) * solar_elevation * elev_matrix[i + 9] +
+ 10.0 * pow(1.0 - solar_elevation, 3.0) * pow(solar_elevation, 2.0) * elev_matrix[i + 18] +
+ 10.0 * pow(1.0 - solar_elevation, 2.0) * pow(solar_elevation, 3.0) * elev_matrix[i + 27] +
+ 5.0 * (1.0 - solar_elevation) * pow(solar_elevation, 4.0) * elev_matrix[i + 36] +
+ pow(solar_elevation, 5.0) * elev_matrix[i + 45]);
+ }
+
+ // alb 1 high turb
+ elev_matrix = dataset + (9 * 6 * 10 + 9 * 6 * (int_turbidity));
+ for (unsigned int i = 0; i < 9; ++i) {
+ //(1-t).^3* A1 + 3*(1-t).^2.*t * A2 + 3*(1-t) .* t .^ 2 * A3 + t.^3 * A4;
+ config[i] +=
+ (albedo) * (turbidity_rem) *
+ (pow(1.0 - solar_elevation, 5.0) * elev_matrix[i] +
+ 5.0 * pow(1.0 - solar_elevation, 4.0) * solar_elevation * elev_matrix[i + 9] +
+ 10.0 * pow(1.0 - solar_elevation, 3.0) * pow(solar_elevation, 2.0) * elev_matrix[i + 18] +
+ 10.0 * pow(1.0 - solar_elevation, 2.0) * pow(solar_elevation, 3.0) * elev_matrix[i + 27] +
+ 5.0 * (1.0 - solar_elevation) * pow(solar_elevation, 4.0) * elev_matrix[i + 36] +
+ pow(solar_elevation, 5.0) * elev_matrix[i + 45]);
+ }
}
-static double ArHosekSkyModel_CookRadianceConfiguration(
- ArHosekSkyModel_Radiance_Dataset dataset,
- double turbidity,
- double albedo,
- double solar_elevation)
+static double ArHosekSkyModel_CookRadianceConfiguration(ArHosekSkyModel_Radiance_Dataset dataset,
+ double turbidity,
+ double albedo,
+ double solar_elevation)
{
- const double* elev_matrix;
-
- int int_turbidity = (int)turbidity;
- double turbidity_rem = turbidity - (double)int_turbidity;
- double res;
- solar_elevation = pow(solar_elevation / (MATH_PI / 2.0), (1.0 / 3.0));
-
- // alb 0 low turb
- elev_matrix = dataset + (6*(int_turbidity-1));
- //(1-t).^3* A1 + 3*(1-t).^2.*t * A2 + 3*(1-t) .* t .^ 2 * A3 + t.^3 * A4;
- res = (1.0-albedo) * (1.0 - turbidity_rem) *
- ( pow(1.0-solar_elevation, 5.0) * elev_matrix[0] +
- 5.0*pow(1.0-solar_elevation, 4.0)*solar_elevation * elev_matrix[1] +
- 10.0*pow(1.0-solar_elevation, 3.0)*pow(solar_elevation, 2.0) * elev_matrix[2] +
- 10.0*pow(1.0-solar_elevation, 2.0)*pow(solar_elevation, 3.0) * elev_matrix[3] +
- 5.0*(1.0-solar_elevation)*pow(solar_elevation, 4.0) * elev_matrix[4] +
- pow(solar_elevation, 5.0) * elev_matrix[5]);
-
- // alb 1 low turb
- elev_matrix = dataset + (6*10 + 6*(int_turbidity-1));
- //(1-t).^3* A1 + 3*(1-t).^2.*t * A2 + 3*(1-t) .* t .^ 2 * A3 + t.^3 * A4;
- res += (albedo) * (1.0 - turbidity_rem) *
- ( pow(1.0-solar_elevation, 5.0) * elev_matrix[0] +
- 5.0*pow(1.0-solar_elevation, 4.0)*solar_elevation * elev_matrix[1] +
- 10.0*pow(1.0-solar_elevation, 3.0)*pow(solar_elevation, 2.0) * elev_matrix[2] +
- 10.0*pow(1.0-solar_elevation, 2.0)*pow(solar_elevation, 3.0) * elev_matrix[3] +
- 5.0*(1.0-solar_elevation)*pow(solar_elevation, 4.0) * elev_matrix[4] +
- pow(solar_elevation, 5.0) * elev_matrix[5]);
- if(int_turbidity == 10)
- return res;
-
- // alb 0 high turb
- elev_matrix = dataset + (6*(int_turbidity));
- //(1-t).^3* A1 + 3*(1-t).^2.*t * A2 + 3*(1-t) .* t .^ 2 * A3 + t.^3 * A4;
- res += (1.0-albedo) * (turbidity_rem) *
- ( pow(1.0-solar_elevation, 5.0) * elev_matrix[0] +
- 5.0*pow(1.0-solar_elevation, 4.0)*solar_elevation * elev_matrix[1] +
- 10.0*pow(1.0-solar_elevation, 3.0)*pow(solar_elevation, 2.0) * elev_matrix[2] +
- 10.0*pow(1.0-solar_elevation, 2.0)*pow(solar_elevation, 3.0) * elev_matrix[3] +
- 5.0*(1.0-solar_elevation)*pow(solar_elevation, 4.0) * elev_matrix[4] +
- pow(solar_elevation, 5.0) * elev_matrix[5]);
-
- // alb 1 high turb
- elev_matrix = dataset + (6*10 + 6*(int_turbidity));
- //(1-t).^3* A1 + 3*(1-t).^2.*t * A2 + 3*(1-t) .* t .^ 2 * A3 + t.^3 * A4;
- res += (albedo) * (turbidity_rem) *
- ( pow(1.0-solar_elevation, 5.0) * elev_matrix[0] +
- 5.0*pow(1.0-solar_elevation, 4.0)*solar_elevation * elev_matrix[1] +
- 10.0*pow(1.0-solar_elevation, 3.0)*pow(solar_elevation, 2.0) * elev_matrix[2] +
- 10.0*pow(1.0-solar_elevation, 2.0)*pow(solar_elevation, 3.0) * elev_matrix[3] +
- 5.0*(1.0-solar_elevation)*pow(solar_elevation, 4.0) * elev_matrix[4] +
- pow(solar_elevation, 5.0) * elev_matrix[5]);
- return res;
+ const double *elev_matrix;
+
+ int int_turbidity = (int)turbidity;
+ double turbidity_rem = turbidity - (double)int_turbidity;
+ double res;
+ solar_elevation = pow(solar_elevation / (MATH_PI / 2.0), (1.0 / 3.0));
+
+ // alb 0 low turb
+ elev_matrix = dataset + (6 * (int_turbidity - 1));
+ //(1-t).^3* A1 + 3*(1-t).^2.*t * A2 + 3*(1-t) .* t .^ 2 * A3 + t.^3 * A4;
+ res = (1.0 - albedo) * (1.0 - turbidity_rem) *
+ (pow(1.0 - solar_elevation, 5.0) * elev_matrix[0] +
+ 5.0 * pow(1.0 - solar_elevation, 4.0) * solar_elevation * elev_matrix[1] +
+ 10.0 * pow(1.0 - solar_elevation, 3.0) * pow(solar_elevation, 2.0) * elev_matrix[2] +
+ 10.0 * pow(1.0 - solar_elevation, 2.0) * pow(solar_elevation, 3.0) * elev_matrix[3] +
+ 5.0 * (1.0 - solar_elevation) * pow(solar_elevation, 4.0) * elev_matrix[4] +
+ pow(solar_elevation, 5.0) * elev_matrix[5]);
+
+ // alb 1 low turb
+ elev_matrix = dataset + (6 * 10 + 6 * (int_turbidity - 1));
+ //(1-t).^3* A1 + 3*(1-t).^2.*t * A2 + 3*(1-t) .* t .^ 2 * A3 + t.^3 * A4;
+ res += (albedo) * (1.0 - turbidity_rem) *
+ (pow(1.0 - solar_elevation, 5.0) * elev_matrix[0] +
+ 5.0 * pow(1.0 - solar_elevation, 4.0) * solar_elevation * elev_matrix[1] +
+ 10.0 * pow(1.0 - solar_elevation, 3.0) * pow(solar_elevation, 2.0) * elev_matrix[2] +
+ 10.0 * pow(1.0 - solar_elevation, 2.0) * pow(solar_elevation, 3.0) * elev_matrix[3] +
+ 5.0 * (1.0 - solar_elevation) * pow(solar_elevation, 4.0) * elev_matrix[4] +
+ pow(solar_elevation, 5.0) * elev_matrix[5]);
+ if (int_turbidity == 10)
+ return res;
+
+ // alb 0 high turb
+ elev_matrix = dataset + (6 * (int_turbidity));
+ //(1-t).^3* A1 + 3*(1-t).^2.*t * A2 + 3*(1-t) .* t .^ 2 * A3 + t.^3 * A4;
+ res += (1.0 - albedo) * (turbidity_rem) *
+ (pow(1.0 - solar_elevation, 5.0) * elev_matrix[0] +
+ 5.0 * pow(1.0 - solar_elevation, 4.0) * solar_elevation * elev_matrix[1] +
+ 10.0 * pow(1.0 - solar_elevation, 3.0) * pow(solar_elevation, 2.0) * elev_matrix[2] +
+ 10.0 * pow(1.0 - solar_elevation, 2.0) * pow(solar_elevation, 3.0) * elev_matrix[3] +
+ 5.0 * (1.0 - solar_elevation) * pow(solar_elevation, 4.0) * elev_matrix[4] +
+ pow(solar_elevation, 5.0) * elev_matrix[5]);
+
+ // alb 1 high turb
+ elev_matrix = dataset + (6 * 10 + 6 * (int_turbidity));
+ //(1-t).^3* A1 + 3*(1-t).^2.*t * A2 + 3*(1-t) .* t .^ 2 * A3 + t.^3 * A4;
+ res += (albedo) * (turbidity_rem) *
+ (pow(1.0 - solar_elevation, 5.0) * elev_matrix[0] +
+ 5.0 * pow(1.0 - solar_elevation, 4.0) * solar_elevation * elev_matrix[1] +
+ 10.0 * pow(1.0 - solar_elevation, 3.0) * pow(solar_elevation, 2.0) * elev_matrix[2] +
+ 10.0 * pow(1.0 - solar_elevation, 2.0) * pow(solar_elevation, 3.0) * elev_matrix[3] +
+ 5.0 * (1.0 - solar_elevation) * pow(solar_elevation, 4.0) * elev_matrix[4] +
+ pow(solar_elevation, 5.0) * elev_matrix[5]);
+ return res;
}
-static double ArHosekSkyModel_GetRadianceInternal(
- ArHosekSkyModelConfiguration configuration,
- double theta,
- double gamma)
+static double ArHosekSkyModel_GetRadianceInternal(ArHosekSkyModelConfiguration configuration,
+ double theta,
+ double gamma)
{
- const double expM = exp(configuration[4] * gamma);
- const double rayM = cos(gamma)*cos(gamma);
- const double mieM = (1.0 + cos(gamma)*cos(gamma)) / pow((1.0 + configuration[8]*configuration[8] - 2.0*configuration[8]*cos(gamma)), 1.5);
- const double zenith = sqrt(cos(theta));
-
- return (1.0 + configuration[0] * exp(configuration[1] / (cos(theta) + 0.01))) *
- (configuration[2] + configuration[3] * expM + configuration[5] * rayM + configuration[6] * mieM + configuration[7] * zenith);
+ const double expM = exp(configuration[4] * gamma);
+ const double rayM = cos(gamma) * cos(gamma);
+ const double mieM =
+ (1.0 + cos(gamma) * cos(gamma)) /
+ pow((1.0 + configuration[8] * configuration[8] - 2.0 * configuration[8] * cos(gamma)), 1.5);
+ const double zenith = sqrt(cos(theta));
+
+ return (1.0 + configuration[0] * exp(configuration[1] / (cos(theta) + 0.01))) *
+ (configuration[2] + configuration[3] * expM + configuration[5] * rayM +
+ configuration[6] * mieM + configuration[7] * zenith);
}
-void arhosekskymodelstate_free(ArHosekSkyModelState * state)
+void arhosekskymodelstate_free(ArHosekSkyModelState *state)
{
- free(state);
+ free(state);
}
-double arhosekskymodel_radiance(ArHosekSkyModelState *state,
+double arhosekskymodel_radiance(ArHosekSkyModelState *state,
double theta,
double gamma,
double wavelength)
{
- int low_wl = (int)((wavelength - 320.0) / 40.0);
-
- if(low_wl < 0 || low_wl >= 11)
- return 0.0;
-
- double interp = fmod((wavelength - 320.0 ) / 40.0, 1.0);
-
- double val_low =
- ArHosekSkyModel_GetRadianceInternal(
- state->configs[low_wl],
- theta,
- gamma)
- * state->radiances[low_wl]
- * state->emission_correction_factor_sky[low_wl];
-
- if(interp < 1e-6)
- return val_low;
-
- double result = ( 1.0 - interp ) * val_low;
-
- if(low_wl+1 < 11) {
- result +=
- interp
- * ArHosekSkyModel_GetRadianceInternal(
- state->configs[low_wl+1],
- theta,
- gamma)
- * state->radiances[low_wl+1]
- * state->emission_correction_factor_sky[low_wl+1];
- }
-
- return result;
-}
+ int low_wl = (int)((wavelength - 320.0) / 40.0);
+
+ if (low_wl < 0 || low_wl >= 11)
+ return 0.0;
+
+ double interp = fmod((wavelength - 320.0) / 40.0, 1.0);
+
+ double val_low = ArHosekSkyModel_GetRadianceInternal(state->configs[low_wl], theta, gamma) *
+ state->radiances[low_wl] * state->emission_correction_factor_sky[low_wl];
+
+ if (interp < 1e-6)
+ return val_low;
+
+ double result = (1.0 - interp) * val_low;
+ if (low_wl + 1 < 11) {
+ result += interp *
+ ArHosekSkyModel_GetRadianceInternal(state->configs[low_wl + 1], theta, gamma) *
+ state->radiances[low_wl + 1] * state->emission_correction_factor_sky[low_wl + 1];
+ }
+
+ return result;
+}
// xyz and rgb versions
-ArHosekSkyModelState * arhosek_xyz_skymodelstate_alloc_init(
- const double turbidity,
- const double albedo,
- const double elevation)
+ArHosekSkyModelState *arhosek_xyz_skymodelstate_alloc_init(const double turbidity,
+ const double albedo,
+ const double elevation)
{
- ArHosekSkyModelState * state = ALLOC(ArHosekSkyModelState);
-
- state->solar_radius = TERRESTRIAL_SOLAR_RADIUS;
- state->turbidity = turbidity;
- state->albedo = albedo;
- state->elevation = elevation;
-
- for(unsigned int channel = 0; channel < 3; ++channel) {
- ArHosekSkyModel_CookConfiguration(
- datasetsXYZ[channel],
- state->configs[channel],
- turbidity,
- albedo,
- elevation);
-
- state->radiances[channel] =
- ArHosekSkyModel_CookRadianceConfiguration(
- datasetsXYZRad[channel],
- turbidity,
- albedo,
- elevation);
- }
-
- return state;
+ ArHosekSkyModelState *state = ALLOC(ArHosekSkyModelState);
+
+ state->solar_radius = TERRESTRIAL_SOLAR_RADIUS;
+ state->turbidity = turbidity;
+ state->albedo = albedo;
+ state->elevation = elevation;
+
+ for (unsigned int channel = 0; channel < 3; ++channel) {
+ ArHosekSkyModel_CookConfiguration(
+ datasetsXYZ[channel], state->configs[channel], turbidity, albedo, elevation);
+
+ state->radiances[channel] = ArHosekSkyModel_CookRadianceConfiguration(
+ datasetsXYZRad[channel], turbidity, albedo, elevation);
+ }
+
+ return state;
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/util/util_sky_model.h b/intern/cycles/util/util_sky_model.h
index 2e593f58c39..84340614b2c 100644
--- a/intern/cycles/util/util_sky_model.h
+++ b/intern/cycles/util/util_sky_model.h
@@ -28,7 +28,6 @@ ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-
/* ============================================================================
This file is part of a sample implementation of the analytical skylight and
@@ -92,7 +91,6 @@ an updated version of this code has been published!
============================================================================ */
-
/*
This code is taken from ART, a rendering research system written in a
@@ -303,11 +301,10 @@ HINT #1: if you want to model the sky of an earth-like planet that orbits
CCL_NAMESPACE_BEGIN
#ifndef _SKY_MODEL_H_
-#define _SKY_MODEL_H_
+# define _SKY_MODEL_H_
typedef double ArHosekSkyModelConfiguration[9];
-
// Spectral version of the model
/* ----------------------------------------------------------------------------
@@ -336,18 +333,16 @@ typedef double ArHosekSkyModelConfiguration[9];
---------------------------------------------------------------------------- */
-typedef struct ArHosekSkyModelState
-{
- ArHosekSkyModelConfiguration configs[11];
- double radiances[11];
- double turbidity;
- double solar_radius;
- double emission_correction_factor_sky[11];
- double emission_correction_factor_sun[11];
- double albedo;
- double elevation;
-}
-ArHosekSkyModelState;
+typedef struct ArHosekSkyModelState {
+ ArHosekSkyModelConfiguration configs[11];
+ double radiances[11];
+ double turbidity;
+ double solar_radius;
+ double emission_correction_factor_sky[11];
+ double emission_correction_factor_sun[11];
+ double albedo;
+ double elevation;
+} ArHosekSkyModelState;
/* ----------------------------------------------------------------------------
@@ -358,11 +353,9 @@ ArHosekSkyModelState;
---------------------------------------------------------------------------- */
-ArHosekSkyModelState *arhosekskymodelstate_alloc_init(
- const double solar_elevation,
- const double atmospheric_turbidity,
- const double ground_albedo);
-
+ArHosekSkyModelState *arhosekskymodelstate_alloc_init(const double solar_elevation,
+ const double atmospheric_turbidity,
+ const double ground_albedo);
/* ----------------------------------------------------------------------------
@@ -393,14 +386,14 @@ ArHosekSkyModelState *arhosekskymodelstate_alloc_init(
---------------------------------------------------------------------------- */
-ArHosekSkyModelState* arhosekskymodelstate_alienworld_alloc_init(
- const double solar_elevation,
- const double solar_intensity,
- const double solar_surface_temperature_kelvin,
- const double atmospheric_turbidity,
- const double ground_albedo);
+ArHosekSkyModelState *arhosekskymodelstate_alienworld_alloc_init(
+ const double solar_elevation,
+ const double solar_intensity,
+ const double solar_surface_temperature_kelvin,
+ const double atmospheric_turbidity,
+ const double ground_albedo);
-void arhosekskymodelstate_free(ArHosekSkyModelState *state);
+void arhosekskymodelstate_free(ArHosekSkyModelState *state);
double arhosekskymodel_radiance(ArHosekSkyModelState *state,
double theta,
@@ -409,20 +402,15 @@ double arhosekskymodel_radiance(ArHosekSkyModelState *state,
// CIE XYZ and RGB versions
+ArHosekSkyModelState *arhosek_xyz_skymodelstate_alloc_init(const double turbidity,
+ const double albedo,
+ const double elevation);
-ArHosekSkyModelState * arhosek_xyz_skymodelstate_alloc_init(
- const double turbidity,
- const double albedo,
- const double elevation);
+ArHosekSkyModelState *arhosek_rgb_skymodelstate_alloc_init(const double turbidity,
+ const double albedo,
+ const double elevation);
-
-ArHosekSkyModelState * arhosek_rgb_skymodelstate_alloc_init(
- const double turbidity,
- const double albedo,
- const double elevation);
-
-
-double arhosek_tristim_skymodel_radiance(ArHosekSkyModelState* state,
+double arhosek_tristim_skymodel_radiance(ArHosekSkyModelState *state,
double theta,
double gamma,
int channel);
@@ -431,12 +419,11 @@ double arhosek_tristim_skymodel_radiance(ArHosekSkyModelState* state,
// Please read the above description before using this - there are several
// caveats!
-double arhosekskymodel_solar_radiance(ArHosekSkyModelState* state,
+double arhosekskymodel_solar_radiance(ArHosekSkyModelState *state,
double theta,
double gamma,
double wavelength);
-
#endif // _SKY_MODEL_H_
CCL_NAMESPACE_END
diff --git a/intern/cycles/util/util_sky_model_data.h b/intern/cycles/util/util_sky_model_data.h
index e6f3f761532..a2a3935eb84 100644
--- a/intern/cycles/util/util_sky_model_data.h
+++ b/intern/cycles/util/util_sky_model_data.h
@@ -28,7 +28,6 @@ ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-
/* ============================================================================
This file is part of a sample implementation of the analytical skylight and
@@ -104,3760 +103,3745 @@ the model.
// Uses Sep 9 pattern / Aug 23 mean dataset
static const double datasetXYZ1[] = {
- // albedo 0, turbidity 1
- -1.117001e+000,
- -1.867262e-001,
- -1.113505e+001,
- 1.259865e+001,
- -3.937339e-002,
- 1.167571e+000,
- 7.100686e-003,
- 3.592678e+000,
- 6.083296e-001,
- -1.152006e+000,
- -1.926669e-001,
- 6.152049e+000,
- -4.770802e+000,
- -8.704701e-002,
- 7.483626e-001,
- 3.372718e-002,
- 4.464592e+000,
- 4.036546e-001,
- -1.072371e+000,
- -2.696632e-001,
- 2.816168e-001,
- 1.820571e+000,
- -3.742666e-001,
- 2.080607e+000,
- -7.675295e-002,
- -2.835366e+000,
- 1.129329e+000,
- -1.109935e+000,
- -1.532764e-001,
- 1.198787e+000,
- -9.015183e-001,
- 5.173015e-003,
- 5.749178e-001,
- 1.075633e-001,
- 4.387949e+000,
- 2.650413e-001,
- -1.052297e+000,
- -2.229452e-001,
- 1.952347e+000,
- 5.727205e-001,
- -4.885070e+000,
- 1.984016e+000,
- -1.106197e-001,
- -4.898361e-001,
- 8.907873e-001,
- -1.070108e+000,
- -1.600465e-001,
- 1.593886e+000,
- -4.479251e-005,
- -3.306541e+000,
- 9.390193e-001,
- 9.513168e-002,
- 2.343583e+000,
- 5.335404e-001,
- // albedo 0, turbidity 2
- -1.113253e+000,
- -1.699600e-001,
- -1.038822e+001,
- 1.137513e+001,
- -4.040911e-002,
- 1.037455e+000,
- 4.991792e-002,
- 4.801919e+000,
- 6.302710e-001,
- -1.135747e+000,
- -1.678594e-001,
- 4.970755e+000,
- -4.430230e+000,
- -6.657408e-002,
- 3.636161e-001,
- 1.558009e-001,
- 6.013370e+000,
- 3.959601e-001,
- -1.095892e+000,
- -2.732595e-001,
- 7.666496e-001,
- 1.350731e+000,
- -4.401401e-001,
- 2.470135e+000,
- -1.707929e-001,
- -3.260793e+000,
- 1.170337e+000,
- -1.073668e+000,
- -2.603929e-002,
- -1.944589e-001,
- 4.575207e-001,
- 6.878164e-001,
- -1.390770e-001,
- 3.690299e-001,
- 7.885781e+000,
- 1.877694e-001,
- -1.070091e+000,
- -2.798957e-001,
- 2.338478e+000,
- -2.647221e+000,
- -7.387808e+000,
- 2.329210e+000,
- -1.644639e-001,
- -2.003710e+000,
- 9.874527e-001,
- -1.067120e+000,
- -1.418866e-001,
- 1.254090e+000,
- 6.053048e+000,
- -2.918892e+000,
- 5.322812e-001,
- 1.613053e-001,
- 3.018161e+000,
- 5.274090e-001,
- // albedo 0, turbidity 3
- -1.129483e+000,
- -1.890619e-001,
- -9.065101e+000,
- 9.659923e+000,
- -3.607819e-002,
- 8.314359e-001,
- 8.181661e-002,
- 4.768868e+000,
- 6.339777e-001,
- -1.146420e+000,
- -1.883579e-001,
- 3.309173e+000,
- -3.127882e+000,
- -6.938176e-002,
- 3.987113e-001,
- 1.400581e-001,
- 6.283042e+000,
- 5.267076e-001,
- -1.128348e+000,
- -2.641305e-001,
- 1.223176e+000,
- 5.514952e-002,
- -3.490649e-001,
- 1.997784e+000,
- -4.123709e-002,
- -2.251251e+000,
- 9.483466e-001,
- -1.025820e+000,
- 1.404690e-002,
- -1.187406e+000,
- 2.729900e+000,
- 5.877588e-001,
- -2.761140e-001,
- 4.602633e-001,
- 8.305125e+000,
- 3.945001e-001,
- -1.083957e+000,
- -2.606679e-001,
- 2.207108e+000,
- -7.202803e+000,
- -5.968103e+000,
- 2.129455e+000,
- -7.789512e-002,
- -1.137688e+000,
- 8.871769e-001,
- -1.062465e+000,
- -1.512189e-001,
- 1.042881e+000,
- 1.427839e+001,
- -4.242214e+000,
- 4.038100e-001,
- 1.997780e-001,
- 2.814449e+000,
- 5.803196e-001,
- // albedo 0, turbidity 4
- -1.175099e+000,
- -2.410789e-001,
- -1.108587e+001,
- 1.133404e+001,
- -1.819300e-002,
- 6.772942e-001,
- 9.605043e-002,
- 4.231166e+000,
- 6.239972e-001,
- -1.224207e+000,
- -2.883527e-001,
- 3.002206e+000,
- -2.649612e+000,
- -4.795418e-002,
- 4.984398e-001,
- 3.251434e-002,
- 4.851611e+000,
- 6.551019e-001,
- -1.136955e+000,
- -2.423048e-001,
- 1.058823e+000,
- -2.489236e-001,
- -2.462179e-001,
- 1.933140e+000,
- 9.106828e-002,
- -1.905869e-001,
- 8.171065e-001,
- -1.014535e+000,
- -8.262500e-003,
- -1.448017e+000,
- 2.295788e+000,
- 3.510334e-001,
- -1.477418e+000,
- 5.432449e-001,
- 5.762796e+000,
- 4.908751e-001,
- -1.070666e+000,
- -2.379780e-001,
- 1.844589e+000,
- -5.442448e+000,
- -4.012768e+000,
- 2.945275e+000,
- 9.854725e-003,
- 8.455959e-002,
- 8.145030e-001,
- -1.071525e+000,
- -1.777132e-001,
- 8.076590e-001,
- 9.925865e+000,
- -3.324623e+000,
- -6.367437e-001,
- 2.844581e-001,
- 2.248384e+000,
- 6.544022e-001,
- // albedo 0, turbidity 5
- -1.218818e+000,
- -2.952382e-001,
- -1.345975e+001,
- 1.347153e+001,
- -6.814585e-003,
- 5.079068e-001,
- 1.197230e-001,
- 3.776949e+000,
- 5.836961e-001,
- -1.409868e+000,
- -5.114330e-001,
- 2.776539e+000,
- -2.039001e+000,
- -2.673769e-002,
- 4.145288e-001,
- 7.829342e-004,
- 2.275883e+000,
- 6.629691e-001,
- -1.069151e+000,
- -9.434247e-002,
- 7.293972e-001,
- -1.222473e+000,
- -1.533461e-001,
- 2.160357e+000,
- 4.626837e-002,
- 3.852415e+000,
- 8.593570e-001,
- -1.021306e+000,
- -1.149551e-001,
- -1.108414e+000,
- 4.178343e+000,
- 4.013665e-001,
- -2.222814e+000,
- 6.929462e-001,
- 1.392652e+000,
- 4.401662e-001,
- -1.074251e+000,
- -2.224002e-001,
- 1.372356e+000,
- -8.858704e+000,
- -3.922660e+000,
- 3.020018e+000,
- -1.458724e-002,
- 1.511186e+000,
- 8.288064e-001,
- -1.062048e+000,
- -1.526582e-001,
- 4.921067e-001,
- 1.485522e+001,
- -3.229936e+000,
- -8.426604e-001,
- 3.916243e-001,
- 2.678994e+000,
- 6.689264e-001,
- // albedo 0, turbidity 6
- -1.257023e+000,
- -3.364700e-001,
- -1.527795e+001,
- 1.504223e+001,
- 2.717715e-003,
- 3.029910e-001,
- 1.636851e-001,
- 3.561663e+000,
- 5.283161e-001,
- -1.635124e+000,
- -7.329993e-001,
- 3.523939e+000,
- -2.566337e+000,
- -1.902543e-002,
- 5.505483e-001,
- -6.242176e-002,
- 1.065992e+000,
- 6.654236e-001,
- -9.295823e-001,
- 4.845834e-002,
- -2.992990e-001,
- -2.001327e-001,
- -8.019339e-002,
- 1.807806e+000,
- 9.020277e-002,
- 5.095372e+000,
- 8.639936e-001,
- -1.093740e+000,
- -2.148608e-001,
- -5.216240e-001,
- 2.119777e+000,
- 9.506454e-002,
- -1.831439e+000,
- 6.961204e-001,
- 1.102084e-001,
- 4.384319e-001,
- -1.044181e+000,
- -1.849257e-001,
- 9.071246e-001,
- -4.648901e+000,
- -2.279385e+000,
- 2.356502e+000,
- -4.169147e-002,
- 1.932557e+000,
- 8.296550e-001,
- -1.061451e+000,
- -1.458745e-001,
- 2.952267e-001,
- 8.967214e+000,
- -3.726228e+000,
- -5.022316e-001,
- 5.684877e-001,
- 3.102347e+000,
- 6.658443e-001,
- // albedo 0, turbidity 7
- -1.332391e+000,
- -4.127769e-001,
- -9.328643e+000,
- 9.046194e+000,
- 3.457775e-003,
- 3.377425e-001,
- 1.530909e-001,
- 3.301209e+000,
- 4.997917e-001,
- -1.932002e+000,
- -9.947777e-001,
- -2.042329e+000,
- 3.586940e+000,
- -5.642182e-002,
- 8.130478e-001,
- -8.195988e-002,
- 1.118294e-001,
- 5.617231e-001,
- -8.707374e-001,
- 1.286999e-001,
- 1.820054e+000,
- -4.674706e+000,
- 3.317471e-003,
- 5.919018e-001,
- 1.975278e-001,
- 6.686519e+000,
- 9.631727e-001,
- -1.070378e+000,
- -3.030579e-001,
- -9.041938e-001,
- 6.200201e+000,
- 1.232207e-001,
- -3.650628e-001,
- 5.029403e-001,
- -2.903162e+000,
- 3.811408e-001,
- -1.063035e+000,
- -1.637545e-001,
- 5.853072e-001,
- -7.889906e+000,
- -1.200641e+000,
- 1.035018e+000,
- 1.192093e-001,
- 3.267054e+000,
- 8.416151e-001,
- -1.053655e+000,
- -1.562286e-001,
- 2.423683e-001,
- 1.128575e+001,
- -4.363262e+000,
- -7.314160e-002,
- 5.642088e-001,
- 2.514023e+000,
- 6.670457e-001,
- // albedo 0, turbidity 8
- -1.366112e+000,
- -4.718287e-001,
- -7.876222e+000,
- 7.746900e+000,
- -9.182309e-003,
- 4.716076e-001,
- 8.320252e-002,
- 3.165603e+000,
- 5.392334e-001,
- -2.468204e+000,
- -1.336340e+000,
- -5.386723e+000,
- 7.072672e+000,
- -8.329266e-002,
- 8.636876e-001,
- -1.978177e-002,
- -1.326218e-001,
- 2.979222e-001,
- -9.653522e-001,
- -2.373416e-002,
- 1.810250e+000,
- -6.467262e+000,
- 1.410706e-001,
- -4.753717e-001,
- 3.003095e-001,
- 6.551163e+000,
- 1.151083e+000,
- -8.943186e-001,
- -2.487152e-001,
- -2.308960e-001,
- 8.512648e+000,
- 1.298402e-001,
- 1.034705e+000,
- 2.303509e-001,
- -3.924095e+000,
- 2.982717e-001,
- -1.146999e+000,
- -2.318784e-001,
- 8.992419e-002,
- -9.933614e+000,
- -8.860920e-001,
- -3.071656e-002,
- 2.852012e-001,
- 3.046199e+000,
- 8.599001e-001,
- -1.032399e+000,
- -1.645145e-001,
- 2.683599e-001,
- 1.327701e+001,
- -4.407670e+000,
- 7.709869e-002,
- 4.951727e-001,
- 1.957277e+000,
- 6.630943e-001,
- // albedo 0, turbidity 9
- -1.469070e+000,
- -6.135092e-001,
- -6.506263e+000,
- 6.661315e+000,
- -3.835383e-002,
- 7.150413e-001,
- 7.784318e-003,
- 2.820577e+000,
- 6.756784e-001,
- -2.501583e+000,
- -1.247404e+000,
- -1.523462e+001,
- 1.633191e+001,
- -1.204803e-002,
- 5.896471e-001,
- -2.002023e-002,
- 1.144647e+000,
- 6.177874e-002,
- -2.438672e+000,
- -1.127291e+000,
- 5.731172e+000,
- -1.021350e+001,
- 6.165610e-002,
- -7.752641e-001,
- 4.708254e-001,
- 4.176847e+000,
- 1.200881e+000,
- -1.513427e-001,
- 9.792731e-002,
- -1.612349e+000,
- 9.814289e+000,
- 5.188921e-002,
- 1.716403e+000,
- -7.039255e-002,
- -2.815115e+000,
- 3.291874e-001,
- -1.318511e+000,
- -3.650554e-001,
- 4.221268e-001,
- -9.294529e+000,
- -4.397520e-002,
- -8.100625e-001,
- 3.742719e-001,
- 1.834166e+000,
- 8.223450e-001,
- -1.016009e+000,
- -1.820264e-001,
- 1.278426e-001,
- 1.182696e+001,
- -4.801528e+000,
- 4.947899e-001,
- 4.660378e-001,
- 1.601254e+000,
- 6.702359e-001,
- // albedo 0, turbidity 10
- -1.841310e+000,
- -9.781779e-001,
- -4.610903e+000,
- 4.824662e+000,
- -5.100806e-002,
- 6.463776e-001,
- -6.377724e-006,
- 2.216875e+000,
- 8.618530e-001,
- -2.376373e+000,
- -1.108657e+000,
- -1.489799e+001,
- 1.546458e+001,
- 4.091025e-002,
- 9.761780e-002,
- -1.048958e-002,
- 2.165834e+000,
- -1.609171e-001,
- -4.710318e+000,
- -2.261963e+000,
- 6.947327e+000,
- -1.034828e+001,
- -1.325542e-001,
- 7.508674e-001,
- 2.247553e-001,
- 2.873142e+000,
- 1.297100e+000,
- 2.163750e-001,
- -1.944345e-001,
- -2.437860e+000,
- 1.011314e+001,
- 4.450500e-001,
- 3.111492e-001,
- 2.751323e-001,
- -1.627906e+000,
- 2.531213e-001,
- -1.258794e+000,
- -3.524641e-001,
- 8.425444e-001,
- -1.085313e+001,
- -1.154381e+000,
- -4.638014e-001,
- -2.781115e-003,
- 4.344498e-001,
- 8.507091e-001,
- -1.018938e+000,
- -1.804153e-001,
- -6.354054e-002,
- 1.573150e+001,
- -4.386999e+000,
- 6.211115e-001,
- 5.294648e-001,
- 1.580749e+000,
- 6.586655e-001,
- // albedo 1, turbidity 1
- -1.116416e+000,
- -1.917524e-001,
- -1.068233e+001,
- 1.222221e+001,
- -3.668978e-002,
- 1.054022e+000,
- 1.592132e-002,
- 3.180583e+000,
- 5.627370e-001,
- -1.132341e+000,
- -1.671286e-001,
- 5.976499e+000,
- -4.227366e+000,
- -9.542489e-002,
- 8.664938e-001,
- 8.351793e-003,
- 4.876068e+000,
- 4.492779e-001,
- -1.087635e+000,
- -3.173679e-001,
- 4.314407e-001,
- 1.100555e+000,
- -4.410057e-001,
- 1.677253e+000,
- -3.005925e-002,
- -4.201249e+000,
- 1.070902e+000,
- -1.083031e+000,
- -8.847705e-002,
- 1.291773e+000,
- 4.546776e-001,
- 3.091894e-001,
- 7.261760e-001,
- 4.203659e-002,
- 5.990615e+000,
- 3.704756e-001,
- -1.057899e+000,
- -2.246706e-001,
- 2.329563e+000,
- -1.219656e+000,
- -5.335260e+000,
- 8.545378e-001,
- -3.906209e-002,
- -9.025499e-001,
- 7.797348e-001,
- -1.073305e+000,
- -1.522553e-001,
- 1.767063e+000,
- 1.904280e+000,
- -3.101673e+000,
- 3.995856e-001,
- 2.905192e-002,
- 2.563977e+000,
- 5.753067e-001,
- // albedo 1, turbidity 2
- -1.113674e+000,
- -1.759694e-001,
- -9.754125e+000,
- 1.087391e+001,
- -3.841093e-002,
- 9.524272e-001,
- 5.680219e-002,
- 4.227034e+000,
- 6.029571e-001,
- -1.126496e+000,
- -1.680281e-001,
- 5.332352e+000,
- -4.575579e+000,
- -6.761755e-002,
- 3.295335e-001,
- 1.194896e-001,
- 5.570901e+000,
- 4.536185e-001,
- -1.103074e+000,
- -2.681801e-001,
- 6.571479e-002,
- 2.396522e+000,
- -4.551280e-001,
- 2.466331e+000,
- -1.232022e-001,
- -3.023201e+000,
- 1.086379e+000,
- -1.053299e+000,
- -2.697173e-002,
- 8.379121e-001,
- -9.681458e-001,
- 5.890692e-001,
- -4.872027e-001,
- 2.936929e-001,
- 7.510139e+000,
- 3.079122e-001,
- -1.079553e+000,
- -2.710448e-001,
- 2.462379e+000,
- -3.713554e-001,
- -8.534512e+000,
- 1.828242e+000,
- -1.686398e-001,
- -1.961340e+000,
- 8.941077e-001,
- -1.069741e+000,
- -1.396394e-001,
- 1.657868e+000,
- 3.236313e+000,
- -2.706344e+000,
- -2.948122e-001,
- 1.314816e-001,
- 2.868457e+000,
- 5.413403e-001,
- // albedo 1, turbidity 3
- -1.131649e+000,
- -1.954455e-001,
- -7.751595e+000,
- 8.685861e+000,
- -4.910871e-002,
- 8.992952e-001,
- 4.710143e-002,
- 4.254818e+000,
- 6.821116e-001,
- -1.156689e+000,
- -1.884324e-001,
- 3.163519e+000,
- -3.091522e+000,
- -6.613927e-002,
- -2.575883e-002,
- 1.640065e-001,
- 6.073643e+000,
- 4.453468e-001,
- -1.079224e+000,
- -2.621389e-001,
- 9.446437e-001,
- 1.448479e+000,
- -3.969384e-001,
- 2.626638e+000,
- -8.101186e-002,
- -3.016355e+000,
- 1.076295e+000,
- -1.080832e+000,
- 1.033057e-002,
- -3.500156e-001,
- -3.281419e-002,
- 5.655512e-001,
- -1.156742e+000,
- 4.534710e-001,
- 8.774122e+000,
- 2.772869e-001,
- -1.051202e+000,
- -2.679975e-001,
- 2.719109e+000,
- -2.190316e+000,
- -6.878798e+000,
- 2.250481e+000,
- -2.030252e-001,
- -2.026527e+000,
- 9.701096e-001,
- -1.089849e+000,
- -1.598589e-001,
- 1.564748e+000,
- 6.869187e+000,
- -3.053670e+000,
- -6.110435e-001,
- 1.644472e-001,
- 2.370452e+000,
- 5.511770e-001,
- // albedo 1, turbidity 4
- -1.171419e+000,
- -2.429746e-001,
- -8.991334e+000,
- 9.571216e+000,
- -2.772861e-002,
- 6.688262e-001,
- 7.683478e-002,
- 3.785611e+000,
- 6.347635e-001,
- -1.228554e+000,
- -2.917562e-001,
- 2.753986e+000,
- -2.491780e+000,
- -4.663434e-002,
- 3.118303e-001,
- 7.546506e-002,
- 4.463096e+000,
- 5.955071e-001,
- -1.093124e+000,
- -2.447767e-001,
- 9.097406e-001,
- 5.448296e-001,
- -2.957824e-001,
- 2.024167e+000,
- -5.152333e-004,
- -1.069081e+000,
- 9.369565e-001,
- -1.056994e+000,
- 1.569507e-002,
- -8.217491e-001,
- 1.870818e+000,
- 7.061930e-001,
- -1.483928e+000,
- 5.978206e-001,
- 6.864902e+000,
- 3.673332e-001,
- -1.054871e+000,
- -2.758129e-001,
- 2.712807e+000,
- -5.950110e+000,
- -6.554039e+000,
- 2.447523e+000,
- -1.895171e-001,
- -1.454292e+000,
- 9.131738e-001,
- -1.100218e+000,
- -1.746241e-001,
- 1.438505e+000,
- 1.115481e+001,
- -3.266076e+000,
- -8.837357e-001,
- 1.970100e-001,
- 1.991595e+000,
- 5.907821e-001,
- // albedo 1, turbidity 5
- -1.207267e+000,
- -2.913610e-001,
- -1.103767e+001,
- 1.140724e+001,
- -1.416800e-002,
- 5.564047e-001,
- 8.476262e-002,
- 3.371255e+000,
- 6.221335e-001,
- -1.429698e+000,
- -5.374218e-001,
- 2.837524e+000,
- -2.221936e+000,
- -2.422337e-002,
- 9.313758e-002,
- 7.190250e-002,
- 1.869022e+000,
- 5.609035e-001,
- -1.002274e+000,
- -6.972810e-002,
- 4.031308e-001,
- -3.932997e-001,
- -1.521923e-001,
- 2.390646e+000,
- -6.893990e-002,
- 2.999661e+000,
- 1.017843e+000,
- -1.081168e+000,
- -1.178666e-001,
- -4.968080e-001,
- 3.919299e+000,
- 6.046866e-001,
- -2.440615e+000,
- 7.891538e-001,
- 2.140835e+000,
- 2.740470e-001,
- -1.050727e+000,
- -2.307688e-001,
- 2.276396e+000,
- -9.454407e+000,
- -5.505176e+000,
- 2.992620e+000,
- -2.450942e-001,
- 6.078372e-001,
- 9.606765e-001,
- -1.103752e+000,
- -1.810202e-001,
- 1.375044e+000,
- 1.589095e+001,
- -3.438954e+000,
- -1.265669e+000,
- 2.475172e-001,
- 1.680768e+000,
- 5.978056e-001,
- // albedo 1, turbidity 6
- -1.244324e+000,
- -3.378542e-001,
- -1.111001e+001,
- 1.137784e+001,
- -7.896794e-003,
- 4.808023e-001,
- 9.249904e-002,
- 3.025816e+000,
- 5.880239e-001,
- -1.593165e+000,
- -7.027621e-001,
- 2.220896e+000,
- -1.437709e+000,
- -1.534738e-002,
- 6.286958e-002,
- 6.644555e-002,
- 1.091727e+000,
- 5.470080e-001,
- -9.136506e-001,
- 1.344874e-002,
- 7.772636e-001,
- -1.209396e+000,
- -1.408978e-001,
- 2.433718e+000,
- -1.041938e-001,
- 3.791244e+000,
- 1.037916e+000,
- -1.134968e+000,
- -1.803315e-001,
- -9.267335e-001,
- 4.576670e+000,
- 6.851928e-001,
- -2.805000e+000,
- 8.687208e-001,
- 1.161483e+000,
- 2.571688e-001,
- -1.017037e+000,
- -2.053943e-001,
- 2.361640e+000,
- -9.887818e+000,
- -5.122889e+000,
- 3.287088e+000,
- -2.594102e-001,
- 8.578927e-001,
- 9.592340e-001,
- -1.118723e+000,
- -1.934942e-001,
- 1.226023e+000,
- 1.674140e+001,
- -3.277335e+000,
- -1.629809e+000,
- 2.765232e-001,
- 1.637713e+000,
- 6.113963e-001,
- // albedo 1, turbidity 7
- -1.314779e+000,
- -4.119915e-001,
- -1.241150e+001,
- 1.241578e+001,
- 2.344284e-003,
- 2.980837e-001,
- 1.414613e-001,
- 2.781731e+000,
- 4.998556e-001,
- -1.926199e+000,
- -1.020038e+000,
- 2.569200e+000,
- -1.081159e+000,
- -2.266833e-002,
- 3.588668e-001,
- 8.750078e-003,
- -2.452171e-001,
- 4.796758e-001,
- -7.780002e-001,
- 1.850647e-001,
- 4.445456e-002,
- -2.409297e+000,
- -7.816346e-002,
- 1.546790e+000,
- -2.807227e-002,
- 5.998176e+000,
- 1.132396e+000,
- -1.179326e+000,
- -3.578330e-001,
- -2.392933e-001,
- 6.467883e+000,
- 5.904596e-001,
- -1.869975e+000,
- 8.045839e-001,
- -2.498121e+000,
- 1.610633e-001,
- -1.009956e+000,
- -1.311896e-001,
- 1.726577e+000,
- -1.219356e+001,
- -3.466239e+000,
- 2.343602e+000,
- -2.252205e-001,
- 2.573681e+000,
- 1.027109e+000,
- -1.112460e+000,
- -2.063093e-001,
- 1.233051e+000,
- 2.058946e+001,
- -4.578074e+000,
- -1.145643e+000,
- 3.160192e-001,
- 1.420159e+000,
- 5.860212e-001,
- // albedo 1, turbidity 8
- -1.371689e+000,
- -4.914196e-001,
- -1.076610e+001,
- 1.107405e+001,
- -1.485077e-002,
- 5.936218e-001,
- 3.685482e-002,
- 2.599968e+000,
- 6.002204e-001,
- -2.436997e+000,
- -1.377939e+000,
- 2.130141e-002,
- 1.079593e+000,
- -1.796232e-002,
- -3.933248e-002,
- 1.610711e-001,
- -6.901181e-001,
- 1.206416e-001,
- -8.743368e-001,
- 7.331370e-002,
- 8.734259e-001,
- -3.743126e+000,
- -3.151167e-002,
- 1.297596e+000,
- -7.634926e-002,
- 6.532873e+000,
- 1.435737e+000,
- -9.810197e-001,
- -3.521634e-001,
- -2.855205e-001,
- 7.134674e+000,
- 6.839748e-001,
- -1.394841e+000,
- 6.952036e-001,
- -4.633104e+000,
- -2.173401e-002,
- -1.122958e+000,
- -1.691536e-001,
- 1.382360e+000,
- -1.102913e+001,
- -2.608171e+000,
- 1.865111e+000,
- -1.345154e-001,
- 3.112342e+000,
- 1.094134e+000,
- -1.075586e+000,
- -2.077415e-001,
- 1.171477e+000,
- 1.793270e+001,
- -4.656858e+000,
- -1.036839e+000,
- 3.338295e-001,
- 1.042793e+000,
- 5.739374e-001,
- // albedo 1, turbidity 9
- -1.465871e+000,
- -6.364486e-001,
- -8.833718e+000,
- 9.343650e+000,
- -3.223600e-002,
- 7.552848e-001,
- -3.121341e-006,
- 2.249164e+000,
- 8.094662e-001,
- -2.448924e+000,
- -1.270878e+000,
- -4.823703e+000,
- 5.853058e+000,
- -2.149127e-002,
- 3.581132e-002,
- -1.230276e-003,
- 4.892553e-001,
- -1.597657e-001,
- -2.419809e+000,
- -1.071337e+000,
- 1.575648e+000,
- -4.983580e+000,
- 9.545185e-003,
- 5.032615e-001,
- 4.186266e-001,
- 4.634147e+000,
- 1.433517e+000,
- -1.383278e-001,
- -2.797095e-002,
- -1.943067e-001,
- 6.679623e+000,
- 4.118280e-001,
- -2.744289e-001,
- -2.118722e-002,
- -4.337025e+000,
- 1.505072e-001,
- -1.341872e+000,
- -2.518572e-001,
- 1.027009e+000,
- -6.527103e+000,
- -1.081271e+000,
- 1.015465e+000,
- 2.845789e-001,
- 2.470371e+000,
- 9.278120e-001,
- -1.040640e+000,
- -2.367454e-001,
- 1.100744e+000,
- 8.827253e+000,
- -4.560794e+000,
- -7.287017e-001,
- 2.842503e-001,
- 6.336593e-001,
- 6.327335e-001,
- // albedo 1, turbidity 10
- -1.877993e+000,
- -1.025135e+000,
- -4.311037e+000,
- 4.715016e+000,
- -4.711631e-002,
- 6.335844e-001,
- -7.665398e-006,
- 1.788017e+000,
- 9.001409e-001,
- -2.281540e+000,
- -1.137668e+000,
- -1.036869e+001,
- 1.136254e+001,
- 1.961739e-002,
- -9.836174e-002,
- -6.734567e-003,
- 1.320918e+000,
- -2.400807e-001,
- -4.904054e+000,
- -2.315781e+000,
- 5.735999e+000,
- -8.626257e+000,
- -1.255643e-001,
- 1.545446e+000,
- 1.396860e-001,
- 2.972897e+000,
- 1.429934e+000,
- 4.077067e-001,
- -1.833688e-001,
- -2.450939e+000,
- 9.119433e+000,
- 4.505361e-001,
- -1.340828e+000,
- 3.973690e-001,
- -1.785370e+000,
- 9.628711e-002,
- -1.296052e+000,
- -3.250526e-001,
- 1.813294e+000,
- -1.031485e+001,
- -1.388690e+000,
- 1.239733e+000,
- -8.989196e-002,
- -3.389637e-001,
- 9.639560e-001,
- -1.062181e+000,
- -2.423444e-001,
- 7.577592e-001,
- 1.566938e+001,
- -4.462264e+000,
- -5.742810e-001,
- 3.262259e-001,
- 9.461672e-001,
- 6.232887e-001,
+ // albedo 0, turbidity 1
+ -1.117001e+000,
+ -1.867262e-001,
+ -1.113505e+001,
+ 1.259865e+001,
+ -3.937339e-002,
+ 1.167571e+000,
+ 7.100686e-003,
+ 3.592678e+000,
+ 6.083296e-001,
+ -1.152006e+000,
+ -1.926669e-001,
+ 6.152049e+000,
+ -4.770802e+000,
+ -8.704701e-002,
+ 7.483626e-001,
+ 3.372718e-002,
+ 4.464592e+000,
+ 4.036546e-001,
+ -1.072371e+000,
+ -2.696632e-001,
+ 2.816168e-001,
+ 1.820571e+000,
+ -3.742666e-001,
+ 2.080607e+000,
+ -7.675295e-002,
+ -2.835366e+000,
+ 1.129329e+000,
+ -1.109935e+000,
+ -1.532764e-001,
+ 1.198787e+000,
+ -9.015183e-001,
+ 5.173015e-003,
+ 5.749178e-001,
+ 1.075633e-001,
+ 4.387949e+000,
+ 2.650413e-001,
+ -1.052297e+000,
+ -2.229452e-001,
+ 1.952347e+000,
+ 5.727205e-001,
+ -4.885070e+000,
+ 1.984016e+000,
+ -1.106197e-001,
+ -4.898361e-001,
+ 8.907873e-001,
+ -1.070108e+000,
+ -1.600465e-001,
+ 1.593886e+000,
+ -4.479251e-005,
+ -3.306541e+000,
+ 9.390193e-001,
+ 9.513168e-002,
+ 2.343583e+000,
+ 5.335404e-001,
+ // albedo 0, turbidity 2
+ -1.113253e+000,
+ -1.699600e-001,
+ -1.038822e+001,
+ 1.137513e+001,
+ -4.040911e-002,
+ 1.037455e+000,
+ 4.991792e-002,
+ 4.801919e+000,
+ 6.302710e-001,
+ -1.135747e+000,
+ -1.678594e-001,
+ 4.970755e+000,
+ -4.430230e+000,
+ -6.657408e-002,
+ 3.636161e-001,
+ 1.558009e-001,
+ 6.013370e+000,
+ 3.959601e-001,
+ -1.095892e+000,
+ -2.732595e-001,
+ 7.666496e-001,
+ 1.350731e+000,
+ -4.401401e-001,
+ 2.470135e+000,
+ -1.707929e-001,
+ -3.260793e+000,
+ 1.170337e+000,
+ -1.073668e+000,
+ -2.603929e-002,
+ -1.944589e-001,
+ 4.575207e-001,
+ 6.878164e-001,
+ -1.390770e-001,
+ 3.690299e-001,
+ 7.885781e+000,
+ 1.877694e-001,
+ -1.070091e+000,
+ -2.798957e-001,
+ 2.338478e+000,
+ -2.647221e+000,
+ -7.387808e+000,
+ 2.329210e+000,
+ -1.644639e-001,
+ -2.003710e+000,
+ 9.874527e-001,
+ -1.067120e+000,
+ -1.418866e-001,
+ 1.254090e+000,
+ 6.053048e+000,
+ -2.918892e+000,
+ 5.322812e-001,
+ 1.613053e-001,
+ 3.018161e+000,
+ 5.274090e-001,
+ // albedo 0, turbidity 3
+ -1.129483e+000,
+ -1.890619e-001,
+ -9.065101e+000,
+ 9.659923e+000,
+ -3.607819e-002,
+ 8.314359e-001,
+ 8.181661e-002,
+ 4.768868e+000,
+ 6.339777e-001,
+ -1.146420e+000,
+ -1.883579e-001,
+ 3.309173e+000,
+ -3.127882e+000,
+ -6.938176e-002,
+ 3.987113e-001,
+ 1.400581e-001,
+ 6.283042e+000,
+ 5.267076e-001,
+ -1.128348e+000,
+ -2.641305e-001,
+ 1.223176e+000,
+ 5.514952e-002,
+ -3.490649e-001,
+ 1.997784e+000,
+ -4.123709e-002,
+ -2.251251e+000,
+ 9.483466e-001,
+ -1.025820e+000,
+ 1.404690e-002,
+ -1.187406e+000,
+ 2.729900e+000,
+ 5.877588e-001,
+ -2.761140e-001,
+ 4.602633e-001,
+ 8.305125e+000,
+ 3.945001e-001,
+ -1.083957e+000,
+ -2.606679e-001,
+ 2.207108e+000,
+ -7.202803e+000,
+ -5.968103e+000,
+ 2.129455e+000,
+ -7.789512e-002,
+ -1.137688e+000,
+ 8.871769e-001,
+ -1.062465e+000,
+ -1.512189e-001,
+ 1.042881e+000,
+ 1.427839e+001,
+ -4.242214e+000,
+ 4.038100e-001,
+ 1.997780e-001,
+ 2.814449e+000,
+ 5.803196e-001,
+ // albedo 0, turbidity 4
+ -1.175099e+000,
+ -2.410789e-001,
+ -1.108587e+001,
+ 1.133404e+001,
+ -1.819300e-002,
+ 6.772942e-001,
+ 9.605043e-002,
+ 4.231166e+000,
+ 6.239972e-001,
+ -1.224207e+000,
+ -2.883527e-001,
+ 3.002206e+000,
+ -2.649612e+000,
+ -4.795418e-002,
+ 4.984398e-001,
+ 3.251434e-002,
+ 4.851611e+000,
+ 6.551019e-001,
+ -1.136955e+000,
+ -2.423048e-001,
+ 1.058823e+000,
+ -2.489236e-001,
+ -2.462179e-001,
+ 1.933140e+000,
+ 9.106828e-002,
+ -1.905869e-001,
+ 8.171065e-001,
+ -1.014535e+000,
+ -8.262500e-003,
+ -1.448017e+000,
+ 2.295788e+000,
+ 3.510334e-001,
+ -1.477418e+000,
+ 5.432449e-001,
+ 5.762796e+000,
+ 4.908751e-001,
+ -1.070666e+000,
+ -2.379780e-001,
+ 1.844589e+000,
+ -5.442448e+000,
+ -4.012768e+000,
+ 2.945275e+000,
+ 9.854725e-003,
+ 8.455959e-002,
+ 8.145030e-001,
+ -1.071525e+000,
+ -1.777132e-001,
+ 8.076590e-001,
+ 9.925865e+000,
+ -3.324623e+000,
+ -6.367437e-001,
+ 2.844581e-001,
+ 2.248384e+000,
+ 6.544022e-001,
+ // albedo 0, turbidity 5
+ -1.218818e+000,
+ -2.952382e-001,
+ -1.345975e+001,
+ 1.347153e+001,
+ -6.814585e-003,
+ 5.079068e-001,
+ 1.197230e-001,
+ 3.776949e+000,
+ 5.836961e-001,
+ -1.409868e+000,
+ -5.114330e-001,
+ 2.776539e+000,
+ -2.039001e+000,
+ -2.673769e-002,
+ 4.145288e-001,
+ 7.829342e-004,
+ 2.275883e+000,
+ 6.629691e-001,
+ -1.069151e+000,
+ -9.434247e-002,
+ 7.293972e-001,
+ -1.222473e+000,
+ -1.533461e-001,
+ 2.160357e+000,
+ 4.626837e-002,
+ 3.852415e+000,
+ 8.593570e-001,
+ -1.021306e+000,
+ -1.149551e-001,
+ -1.108414e+000,
+ 4.178343e+000,
+ 4.013665e-001,
+ -2.222814e+000,
+ 6.929462e-001,
+ 1.392652e+000,
+ 4.401662e-001,
+ -1.074251e+000,
+ -2.224002e-001,
+ 1.372356e+000,
+ -8.858704e+000,
+ -3.922660e+000,
+ 3.020018e+000,
+ -1.458724e-002,
+ 1.511186e+000,
+ 8.288064e-001,
+ -1.062048e+000,
+ -1.526582e-001,
+ 4.921067e-001,
+ 1.485522e+001,
+ -3.229936e+000,
+ -8.426604e-001,
+ 3.916243e-001,
+ 2.678994e+000,
+ 6.689264e-001,
+ // albedo 0, turbidity 6
+ -1.257023e+000,
+ -3.364700e-001,
+ -1.527795e+001,
+ 1.504223e+001,
+ 2.717715e-003,
+ 3.029910e-001,
+ 1.636851e-001,
+ 3.561663e+000,
+ 5.283161e-001,
+ -1.635124e+000,
+ -7.329993e-001,
+ 3.523939e+000,
+ -2.566337e+000,
+ -1.902543e-002,
+ 5.505483e-001,
+ -6.242176e-002,
+ 1.065992e+000,
+ 6.654236e-001,
+ -9.295823e-001,
+ 4.845834e-002,
+ -2.992990e-001,
+ -2.001327e-001,
+ -8.019339e-002,
+ 1.807806e+000,
+ 9.020277e-002,
+ 5.095372e+000,
+ 8.639936e-001,
+ -1.093740e+000,
+ -2.148608e-001,
+ -5.216240e-001,
+ 2.119777e+000,
+ 9.506454e-002,
+ -1.831439e+000,
+ 6.961204e-001,
+ 1.102084e-001,
+ 4.384319e-001,
+ -1.044181e+000,
+ -1.849257e-001,
+ 9.071246e-001,
+ -4.648901e+000,
+ -2.279385e+000,
+ 2.356502e+000,
+ -4.169147e-002,
+ 1.932557e+000,
+ 8.296550e-001,
+ -1.061451e+000,
+ -1.458745e-001,
+ 2.952267e-001,
+ 8.967214e+000,
+ -3.726228e+000,
+ -5.022316e-001,
+ 5.684877e-001,
+ 3.102347e+000,
+ 6.658443e-001,
+ // albedo 0, turbidity 7
+ -1.332391e+000,
+ -4.127769e-001,
+ -9.328643e+000,
+ 9.046194e+000,
+ 3.457775e-003,
+ 3.377425e-001,
+ 1.530909e-001,
+ 3.301209e+000,
+ 4.997917e-001,
+ -1.932002e+000,
+ -9.947777e-001,
+ -2.042329e+000,
+ 3.586940e+000,
+ -5.642182e-002,
+ 8.130478e-001,
+ -8.195988e-002,
+ 1.118294e-001,
+ 5.617231e-001,
+ -8.707374e-001,
+ 1.286999e-001,
+ 1.820054e+000,
+ -4.674706e+000,
+ 3.317471e-003,
+ 5.919018e-001,
+ 1.975278e-001,
+ 6.686519e+000,
+ 9.631727e-001,
+ -1.070378e+000,
+ -3.030579e-001,
+ -9.041938e-001,
+ 6.200201e+000,
+ 1.232207e-001,
+ -3.650628e-001,
+ 5.029403e-001,
+ -2.903162e+000,
+ 3.811408e-001,
+ -1.063035e+000,
+ -1.637545e-001,
+ 5.853072e-001,
+ -7.889906e+000,
+ -1.200641e+000,
+ 1.035018e+000,
+ 1.192093e-001,
+ 3.267054e+000,
+ 8.416151e-001,
+ -1.053655e+000,
+ -1.562286e-001,
+ 2.423683e-001,
+ 1.128575e+001,
+ -4.363262e+000,
+ -7.314160e-002,
+ 5.642088e-001,
+ 2.514023e+000,
+ 6.670457e-001,
+ // albedo 0, turbidity 8
+ -1.366112e+000,
+ -4.718287e-001,
+ -7.876222e+000,
+ 7.746900e+000,
+ -9.182309e-003,
+ 4.716076e-001,
+ 8.320252e-002,
+ 3.165603e+000,
+ 5.392334e-001,
+ -2.468204e+000,
+ -1.336340e+000,
+ -5.386723e+000,
+ 7.072672e+000,
+ -8.329266e-002,
+ 8.636876e-001,
+ -1.978177e-002,
+ -1.326218e-001,
+ 2.979222e-001,
+ -9.653522e-001,
+ -2.373416e-002,
+ 1.810250e+000,
+ -6.467262e+000,
+ 1.410706e-001,
+ -4.753717e-001,
+ 3.003095e-001,
+ 6.551163e+000,
+ 1.151083e+000,
+ -8.943186e-001,
+ -2.487152e-001,
+ -2.308960e-001,
+ 8.512648e+000,
+ 1.298402e-001,
+ 1.034705e+000,
+ 2.303509e-001,
+ -3.924095e+000,
+ 2.982717e-001,
+ -1.146999e+000,
+ -2.318784e-001,
+ 8.992419e-002,
+ -9.933614e+000,
+ -8.860920e-001,
+ -3.071656e-002,
+ 2.852012e-001,
+ 3.046199e+000,
+ 8.599001e-001,
+ -1.032399e+000,
+ -1.645145e-001,
+ 2.683599e-001,
+ 1.327701e+001,
+ -4.407670e+000,
+ 7.709869e-002,
+ 4.951727e-001,
+ 1.957277e+000,
+ 6.630943e-001,
+ // albedo 0, turbidity 9
+ -1.469070e+000,
+ -6.135092e-001,
+ -6.506263e+000,
+ 6.661315e+000,
+ -3.835383e-002,
+ 7.150413e-001,
+ 7.784318e-003,
+ 2.820577e+000,
+ 6.756784e-001,
+ -2.501583e+000,
+ -1.247404e+000,
+ -1.523462e+001,
+ 1.633191e+001,
+ -1.204803e-002,
+ 5.896471e-001,
+ -2.002023e-002,
+ 1.144647e+000,
+ 6.177874e-002,
+ -2.438672e+000,
+ -1.127291e+000,
+ 5.731172e+000,
+ -1.021350e+001,
+ 6.165610e-002,
+ -7.752641e-001,
+ 4.708254e-001,
+ 4.176847e+000,
+ 1.200881e+000,
+ -1.513427e-001,
+ 9.792731e-002,
+ -1.612349e+000,
+ 9.814289e+000,
+ 5.188921e-002,
+ 1.716403e+000,
+ -7.039255e-002,
+ -2.815115e+000,
+ 3.291874e-001,
+ -1.318511e+000,
+ -3.650554e-001,
+ 4.221268e-001,
+ -9.294529e+000,
+ -4.397520e-002,
+ -8.100625e-001,
+ 3.742719e-001,
+ 1.834166e+000,
+ 8.223450e-001,
+ -1.016009e+000,
+ -1.820264e-001,
+ 1.278426e-001,
+ 1.182696e+001,
+ -4.801528e+000,
+ 4.947899e-001,
+ 4.660378e-001,
+ 1.601254e+000,
+ 6.702359e-001,
+ // albedo 0, turbidity 10
+ -1.841310e+000,
+ -9.781779e-001,
+ -4.610903e+000,
+ 4.824662e+000,
+ -5.100806e-002,
+ 6.463776e-001,
+ -6.377724e-006,
+ 2.216875e+000,
+ 8.618530e-001,
+ -2.376373e+000,
+ -1.108657e+000,
+ -1.489799e+001,
+ 1.546458e+001,
+ 4.091025e-002,
+ 9.761780e-002,
+ -1.048958e-002,
+ 2.165834e+000,
+ -1.609171e-001,
+ -4.710318e+000,
+ -2.261963e+000,
+ 6.947327e+000,
+ -1.034828e+001,
+ -1.325542e-001,
+ 7.508674e-001,
+ 2.247553e-001,
+ 2.873142e+000,
+ 1.297100e+000,
+ 2.163750e-001,
+ -1.944345e-001,
+ -2.437860e+000,
+ 1.011314e+001,
+ 4.450500e-001,
+ 3.111492e-001,
+ 2.751323e-001,
+ -1.627906e+000,
+ 2.531213e-001,
+ -1.258794e+000,
+ -3.524641e-001,
+ 8.425444e-001,
+ -1.085313e+001,
+ -1.154381e+000,
+ -4.638014e-001,
+ -2.781115e-003,
+ 4.344498e-001,
+ 8.507091e-001,
+ -1.018938e+000,
+ -1.804153e-001,
+ -6.354054e-002,
+ 1.573150e+001,
+ -4.386999e+000,
+ 6.211115e-001,
+ 5.294648e-001,
+ 1.580749e+000,
+ 6.586655e-001,
+ // albedo 1, turbidity 1
+ -1.116416e+000,
+ -1.917524e-001,
+ -1.068233e+001,
+ 1.222221e+001,
+ -3.668978e-002,
+ 1.054022e+000,
+ 1.592132e-002,
+ 3.180583e+000,
+ 5.627370e-001,
+ -1.132341e+000,
+ -1.671286e-001,
+ 5.976499e+000,
+ -4.227366e+000,
+ -9.542489e-002,
+ 8.664938e-001,
+ 8.351793e-003,
+ 4.876068e+000,
+ 4.492779e-001,
+ -1.087635e+000,
+ -3.173679e-001,
+ 4.314407e-001,
+ 1.100555e+000,
+ -4.410057e-001,
+ 1.677253e+000,
+ -3.005925e-002,
+ -4.201249e+000,
+ 1.070902e+000,
+ -1.083031e+000,
+ -8.847705e-002,
+ 1.291773e+000,
+ 4.546776e-001,
+ 3.091894e-001,
+ 7.261760e-001,
+ 4.203659e-002,
+ 5.990615e+000,
+ 3.704756e-001,
+ -1.057899e+000,
+ -2.246706e-001,
+ 2.329563e+000,
+ -1.219656e+000,
+ -5.335260e+000,
+ 8.545378e-001,
+ -3.906209e-002,
+ -9.025499e-001,
+ 7.797348e-001,
+ -1.073305e+000,
+ -1.522553e-001,
+ 1.767063e+000,
+ 1.904280e+000,
+ -3.101673e+000,
+ 3.995856e-001,
+ 2.905192e-002,
+ 2.563977e+000,
+ 5.753067e-001,
+ // albedo 1, turbidity 2
+ -1.113674e+000,
+ -1.759694e-001,
+ -9.754125e+000,
+ 1.087391e+001,
+ -3.841093e-002,
+ 9.524272e-001,
+ 5.680219e-002,
+ 4.227034e+000,
+ 6.029571e-001,
+ -1.126496e+000,
+ -1.680281e-001,
+ 5.332352e+000,
+ -4.575579e+000,
+ -6.761755e-002,
+ 3.295335e-001,
+ 1.194896e-001,
+ 5.570901e+000,
+ 4.536185e-001,
+ -1.103074e+000,
+ -2.681801e-001,
+ 6.571479e-002,
+ 2.396522e+000,
+ -4.551280e-001,
+ 2.466331e+000,
+ -1.232022e-001,
+ -3.023201e+000,
+ 1.086379e+000,
+ -1.053299e+000,
+ -2.697173e-002,
+ 8.379121e-001,
+ -9.681458e-001,
+ 5.890692e-001,
+ -4.872027e-001,
+ 2.936929e-001,
+ 7.510139e+000,
+ 3.079122e-001,
+ -1.079553e+000,
+ -2.710448e-001,
+ 2.462379e+000,
+ -3.713554e-001,
+ -8.534512e+000,
+ 1.828242e+000,
+ -1.686398e-001,
+ -1.961340e+000,
+ 8.941077e-001,
+ -1.069741e+000,
+ -1.396394e-001,
+ 1.657868e+000,
+ 3.236313e+000,
+ -2.706344e+000,
+ -2.948122e-001,
+ 1.314816e-001,
+ 2.868457e+000,
+ 5.413403e-001,
+ // albedo 1, turbidity 3
+ -1.131649e+000,
+ -1.954455e-001,
+ -7.751595e+000,
+ 8.685861e+000,
+ -4.910871e-002,
+ 8.992952e-001,
+ 4.710143e-002,
+ 4.254818e+000,
+ 6.821116e-001,
+ -1.156689e+000,
+ -1.884324e-001,
+ 3.163519e+000,
+ -3.091522e+000,
+ -6.613927e-002,
+ -2.575883e-002,
+ 1.640065e-001,
+ 6.073643e+000,
+ 4.453468e-001,
+ -1.079224e+000,
+ -2.621389e-001,
+ 9.446437e-001,
+ 1.448479e+000,
+ -3.969384e-001,
+ 2.626638e+000,
+ -8.101186e-002,
+ -3.016355e+000,
+ 1.076295e+000,
+ -1.080832e+000,
+ 1.033057e-002,
+ -3.500156e-001,
+ -3.281419e-002,
+ 5.655512e-001,
+ -1.156742e+000,
+ 4.534710e-001,
+ 8.774122e+000,
+ 2.772869e-001,
+ -1.051202e+000,
+ -2.679975e-001,
+ 2.719109e+000,
+ -2.190316e+000,
+ -6.878798e+000,
+ 2.250481e+000,
+ -2.030252e-001,
+ -2.026527e+000,
+ 9.701096e-001,
+ -1.089849e+000,
+ -1.598589e-001,
+ 1.564748e+000,
+ 6.869187e+000,
+ -3.053670e+000,
+ -6.110435e-001,
+ 1.644472e-001,
+ 2.370452e+000,
+ 5.511770e-001,
+ // albedo 1, turbidity 4
+ -1.171419e+000,
+ -2.429746e-001,
+ -8.991334e+000,
+ 9.571216e+000,
+ -2.772861e-002,
+ 6.688262e-001,
+ 7.683478e-002,
+ 3.785611e+000,
+ 6.347635e-001,
+ -1.228554e+000,
+ -2.917562e-001,
+ 2.753986e+000,
+ -2.491780e+000,
+ -4.663434e-002,
+ 3.118303e-001,
+ 7.546506e-002,
+ 4.463096e+000,
+ 5.955071e-001,
+ -1.093124e+000,
+ -2.447767e-001,
+ 9.097406e-001,
+ 5.448296e-001,
+ -2.957824e-001,
+ 2.024167e+000,
+ -5.152333e-004,
+ -1.069081e+000,
+ 9.369565e-001,
+ -1.056994e+000,
+ 1.569507e-002,
+ -8.217491e-001,
+ 1.870818e+000,
+ 7.061930e-001,
+ -1.483928e+000,
+ 5.978206e-001,
+ 6.864902e+000,
+ 3.673332e-001,
+ -1.054871e+000,
+ -2.758129e-001,
+ 2.712807e+000,
+ -5.950110e+000,
+ -6.554039e+000,
+ 2.447523e+000,
+ -1.895171e-001,
+ -1.454292e+000,
+ 9.131738e-001,
+ -1.100218e+000,
+ -1.746241e-001,
+ 1.438505e+000,
+ 1.115481e+001,
+ -3.266076e+000,
+ -8.837357e-001,
+ 1.970100e-001,
+ 1.991595e+000,
+ 5.907821e-001,
+ // albedo 1, turbidity 5
+ -1.207267e+000,
+ -2.913610e-001,
+ -1.103767e+001,
+ 1.140724e+001,
+ -1.416800e-002,
+ 5.564047e-001,
+ 8.476262e-002,
+ 3.371255e+000,
+ 6.221335e-001,
+ -1.429698e+000,
+ -5.374218e-001,
+ 2.837524e+000,
+ -2.221936e+000,
+ -2.422337e-002,
+ 9.313758e-002,
+ 7.190250e-002,
+ 1.869022e+000,
+ 5.609035e-001,
+ -1.002274e+000,
+ -6.972810e-002,
+ 4.031308e-001,
+ -3.932997e-001,
+ -1.521923e-001,
+ 2.390646e+000,
+ -6.893990e-002,
+ 2.999661e+000,
+ 1.017843e+000,
+ -1.081168e+000,
+ -1.178666e-001,
+ -4.968080e-001,
+ 3.919299e+000,
+ 6.046866e-001,
+ -2.440615e+000,
+ 7.891538e-001,
+ 2.140835e+000,
+ 2.740470e-001,
+ -1.050727e+000,
+ -2.307688e-001,
+ 2.276396e+000,
+ -9.454407e+000,
+ -5.505176e+000,
+ 2.992620e+000,
+ -2.450942e-001,
+ 6.078372e-001,
+ 9.606765e-001,
+ -1.103752e+000,
+ -1.810202e-001,
+ 1.375044e+000,
+ 1.589095e+001,
+ -3.438954e+000,
+ -1.265669e+000,
+ 2.475172e-001,
+ 1.680768e+000,
+ 5.978056e-001,
+ // albedo 1, turbidity 6
+ -1.244324e+000,
+ -3.378542e-001,
+ -1.111001e+001,
+ 1.137784e+001,
+ -7.896794e-003,
+ 4.808023e-001,
+ 9.249904e-002,
+ 3.025816e+000,
+ 5.880239e-001,
+ -1.593165e+000,
+ -7.027621e-001,
+ 2.220896e+000,
+ -1.437709e+000,
+ -1.534738e-002,
+ 6.286958e-002,
+ 6.644555e-002,
+ 1.091727e+000,
+ 5.470080e-001,
+ -9.136506e-001,
+ 1.344874e-002,
+ 7.772636e-001,
+ -1.209396e+000,
+ -1.408978e-001,
+ 2.433718e+000,
+ -1.041938e-001,
+ 3.791244e+000,
+ 1.037916e+000,
+ -1.134968e+000,
+ -1.803315e-001,
+ -9.267335e-001,
+ 4.576670e+000,
+ 6.851928e-001,
+ -2.805000e+000,
+ 8.687208e-001,
+ 1.161483e+000,
+ 2.571688e-001,
+ -1.017037e+000,
+ -2.053943e-001,
+ 2.361640e+000,
+ -9.887818e+000,
+ -5.122889e+000,
+ 3.287088e+000,
+ -2.594102e-001,
+ 8.578927e-001,
+ 9.592340e-001,
+ -1.118723e+000,
+ -1.934942e-001,
+ 1.226023e+000,
+ 1.674140e+001,
+ -3.277335e+000,
+ -1.629809e+000,
+ 2.765232e-001,
+ 1.637713e+000,
+ 6.113963e-001,
+ // albedo 1, turbidity 7
+ -1.314779e+000,
+ -4.119915e-001,
+ -1.241150e+001,
+ 1.241578e+001,
+ 2.344284e-003,
+ 2.980837e-001,
+ 1.414613e-001,
+ 2.781731e+000,
+ 4.998556e-001,
+ -1.926199e+000,
+ -1.020038e+000,
+ 2.569200e+000,
+ -1.081159e+000,
+ -2.266833e-002,
+ 3.588668e-001,
+ 8.750078e-003,
+ -2.452171e-001,
+ 4.796758e-001,
+ -7.780002e-001,
+ 1.850647e-001,
+ 4.445456e-002,
+ -2.409297e+000,
+ -7.816346e-002,
+ 1.546790e+000,
+ -2.807227e-002,
+ 5.998176e+000,
+ 1.132396e+000,
+ -1.179326e+000,
+ -3.578330e-001,
+ -2.392933e-001,
+ 6.467883e+000,
+ 5.904596e-001,
+ -1.869975e+000,
+ 8.045839e-001,
+ -2.498121e+000,
+ 1.610633e-001,
+ -1.009956e+000,
+ -1.311896e-001,
+ 1.726577e+000,
+ -1.219356e+001,
+ -3.466239e+000,
+ 2.343602e+000,
+ -2.252205e-001,
+ 2.573681e+000,
+ 1.027109e+000,
+ -1.112460e+000,
+ -2.063093e-001,
+ 1.233051e+000,
+ 2.058946e+001,
+ -4.578074e+000,
+ -1.145643e+000,
+ 3.160192e-001,
+ 1.420159e+000,
+ 5.860212e-001,
+ // albedo 1, turbidity 8
+ -1.371689e+000,
+ -4.914196e-001,
+ -1.076610e+001,
+ 1.107405e+001,
+ -1.485077e-002,
+ 5.936218e-001,
+ 3.685482e-002,
+ 2.599968e+000,
+ 6.002204e-001,
+ -2.436997e+000,
+ -1.377939e+000,
+ 2.130141e-002,
+ 1.079593e+000,
+ -1.796232e-002,
+ -3.933248e-002,
+ 1.610711e-001,
+ -6.901181e-001,
+ 1.206416e-001,
+ -8.743368e-001,
+ 7.331370e-002,
+ 8.734259e-001,
+ -3.743126e+000,
+ -3.151167e-002,
+ 1.297596e+000,
+ -7.634926e-002,
+ 6.532873e+000,
+ 1.435737e+000,
+ -9.810197e-001,
+ -3.521634e-001,
+ -2.855205e-001,
+ 7.134674e+000,
+ 6.839748e-001,
+ -1.394841e+000,
+ 6.952036e-001,
+ -4.633104e+000,
+ -2.173401e-002,
+ -1.122958e+000,
+ -1.691536e-001,
+ 1.382360e+000,
+ -1.102913e+001,
+ -2.608171e+000,
+ 1.865111e+000,
+ -1.345154e-001,
+ 3.112342e+000,
+ 1.094134e+000,
+ -1.075586e+000,
+ -2.077415e-001,
+ 1.171477e+000,
+ 1.793270e+001,
+ -4.656858e+000,
+ -1.036839e+000,
+ 3.338295e-001,
+ 1.042793e+000,
+ 5.739374e-001,
+ // albedo 1, turbidity 9
+ -1.465871e+000,
+ -6.364486e-001,
+ -8.833718e+000,
+ 9.343650e+000,
+ -3.223600e-002,
+ 7.552848e-001,
+ -3.121341e-006,
+ 2.249164e+000,
+ 8.094662e-001,
+ -2.448924e+000,
+ -1.270878e+000,
+ -4.823703e+000,
+ 5.853058e+000,
+ -2.149127e-002,
+ 3.581132e-002,
+ -1.230276e-003,
+ 4.892553e-001,
+ -1.597657e-001,
+ -2.419809e+000,
+ -1.071337e+000,
+ 1.575648e+000,
+ -4.983580e+000,
+ 9.545185e-003,
+ 5.032615e-001,
+ 4.186266e-001,
+ 4.634147e+000,
+ 1.433517e+000,
+ -1.383278e-001,
+ -2.797095e-002,
+ -1.943067e-001,
+ 6.679623e+000,
+ 4.118280e-001,
+ -2.744289e-001,
+ -2.118722e-002,
+ -4.337025e+000,
+ 1.505072e-001,
+ -1.341872e+000,
+ -2.518572e-001,
+ 1.027009e+000,
+ -6.527103e+000,
+ -1.081271e+000,
+ 1.015465e+000,
+ 2.845789e-001,
+ 2.470371e+000,
+ 9.278120e-001,
+ -1.040640e+000,
+ -2.367454e-001,
+ 1.100744e+000,
+ 8.827253e+000,
+ -4.560794e+000,
+ -7.287017e-001,
+ 2.842503e-001,
+ 6.336593e-001,
+ 6.327335e-001,
+ // albedo 1, turbidity 10
+ -1.877993e+000,
+ -1.025135e+000,
+ -4.311037e+000,
+ 4.715016e+000,
+ -4.711631e-002,
+ 6.335844e-001,
+ -7.665398e-006,
+ 1.788017e+000,
+ 9.001409e-001,
+ -2.281540e+000,
+ -1.137668e+000,
+ -1.036869e+001,
+ 1.136254e+001,
+ 1.961739e-002,
+ -9.836174e-002,
+ -6.734567e-003,
+ 1.320918e+000,
+ -2.400807e-001,
+ -4.904054e+000,
+ -2.315781e+000,
+ 5.735999e+000,
+ -8.626257e+000,
+ -1.255643e-001,
+ 1.545446e+000,
+ 1.396860e-001,
+ 2.972897e+000,
+ 1.429934e+000,
+ 4.077067e-001,
+ -1.833688e-001,
+ -2.450939e+000,
+ 9.119433e+000,
+ 4.505361e-001,
+ -1.340828e+000,
+ 3.973690e-001,
+ -1.785370e+000,
+ 9.628711e-002,
+ -1.296052e+000,
+ -3.250526e-001,
+ 1.813294e+000,
+ -1.031485e+001,
+ -1.388690e+000,
+ 1.239733e+000,
+ -8.989196e-002,
+ -3.389637e-001,
+ 9.639560e-001,
+ -1.062181e+000,
+ -2.423444e-001,
+ 7.577592e-001,
+ 1.566938e+001,
+ -4.462264e+000,
+ -5.742810e-001,
+ 3.262259e-001,
+ 9.461672e-001,
+ 6.232887e-001,
};
-static const double datasetXYZRad1[] =
-{
- // albedo 0, turbidity 1
- 1.560219e+000,
- 1.417388e+000,
- 1.206927e+000,
- 1.091949e+001,
- 5.931416e+000,
- 7.304788e+000,
- // albedo 0, turbidity 2
- 1.533049e+000,
- 1.560532e+000,
- 3.685059e-001,
- 1.355040e+001,
- 5.543711e+000,
- 7.792189e+000,
- // albedo 0, turbidity 3
- 1.471043e+000,
- 1.746088e+000,
- -9.299697e-001,
- 1.720362e+001,
- 5.473384e+000,
- 8.336416e+000,
- // albedo 0, turbidity 4
- 1.355991e+000,
- 2.109348e+000,
- -3.295855e+000,
- 2.264843e+001,
- 5.454607e+000,
- 9.304656e+000,
- // albedo 0, turbidity 5
- 1.244963e+000,
- 2.547533e+000,
- -5.841485e+000,
- 2.756879e+001,
- 5.576104e+000,
- 1.043287e+001,
- // albedo 0, turbidity 6
- 1.175532e+000,
- 2.784634e+000,
- -7.212225e+000,
- 2.975347e+001,
- 6.472980e+000,
- 1.092331e+001,
- // albedo 0, turbidity 7
- 1.082973e+000,
- 3.118094e+000,
- -8.934293e+000,
- 3.186879e+001,
- 8.473885e+000,
- 1.174019e+001,
- // albedo 0, turbidity 8
- 9.692500e-001,
- 3.349574e+000,
- -1.003810e+001,
- 3.147654e+001,
- 1.338931e+001,
- 1.272547e+001,
- // albedo 0, turbidity 9
- 8.547044e-001,
- 3.151538e+000,
- -9.095567e+000,
- 2.554995e+001,
- 2.273219e+001,
- 1.410398e+001,
- // albedo 0, turbidity 10
- 7.580340e-001,
- 2.311153e+000,
- -5.170814e+000,
- 1.229669e+001,
- 3.686529e+001,
- 1.598882e+001,
- // albedo 1, turbidity 1
- 1.664273e+000,
- 1.574468e+000,
- 1.422078e+000,
- 9.768247e+000,
- 1.447338e+001,
- 1.644988e+001,
- // albedo 1, turbidity 2
- 1.638295e+000,
- 1.719586e+000,
- 5.786675e-001,
- 1.239846e+001,
- 1.415419e+001,
- 1.728605e+001,
- // albedo 1, turbidity 3
- 1.572623e+000,
- 1.921559e+000,
- -7.714802e-001,
- 1.609246e+001,
- 1.420954e+001,
- 1.825908e+001,
- // albedo 1, turbidity 4
- 1.468395e+000,
- 2.211970e+000,
- -2.845869e+000,
- 2.075027e+001,
- 1.524822e+001,
- 1.937622e+001,
- // albedo 1, turbidity 5
- 1.355047e+000,
- 2.556469e+000,
- -4.960920e+000,
- 2.460237e+001,
- 1.648360e+001,
- 2.065648e+001,
- // albedo 1, turbidity 6
- 1.291642e+000,
- 2.742036e+000,
- -6.061967e+000,
- 2.602002e+001,
- 1.819144e+001,
- 2.116712e+001,
- // albedo 1, turbidity 7
- 1.194565e+000,
- 2.972120e+000,
- -7.295779e+000,
- 2.691805e+001,
- 2.124880e+001,
- 2.201819e+001,
- // albedo 1, turbidity 8
- 1.083631e+000,
- 3.047021e+000,
- -7.766096e+000,
- 2.496261e+001,
- 2.744264e+001,
- 2.291875e+001,
- // albedo 1, turbidity 9
- 9.707994e-001,
- 2.736459e+000,
- -6.308284e+000,
- 1.760860e+001,
- 3.776291e+001,
- 2.392150e+001,
- // albedo 1, turbidity 10
- 8.574294e-001,
- 1.865155e+000,
- -2.364707e+000,
- 4.337793e+000,
- 5.092831e+001,
- 2.523432e+001,
+static const double datasetXYZRad1[] = {
+ // albedo 0, turbidity 1
+ 1.560219e+000,
+ 1.417388e+000,
+ 1.206927e+000,
+ 1.091949e+001,
+ 5.931416e+000,
+ 7.304788e+000,
+ // albedo 0, turbidity 2
+ 1.533049e+000,
+ 1.560532e+000,
+ 3.685059e-001,
+ 1.355040e+001,
+ 5.543711e+000,
+ 7.792189e+000,
+ // albedo 0, turbidity 3
+ 1.471043e+000,
+ 1.746088e+000,
+ -9.299697e-001,
+ 1.720362e+001,
+ 5.473384e+000,
+ 8.336416e+000,
+ // albedo 0, turbidity 4
+ 1.355991e+000,
+ 2.109348e+000,
+ -3.295855e+000,
+ 2.264843e+001,
+ 5.454607e+000,
+ 9.304656e+000,
+ // albedo 0, turbidity 5
+ 1.244963e+000,
+ 2.547533e+000,
+ -5.841485e+000,
+ 2.756879e+001,
+ 5.576104e+000,
+ 1.043287e+001,
+ // albedo 0, turbidity 6
+ 1.175532e+000,
+ 2.784634e+000,
+ -7.212225e+000,
+ 2.975347e+001,
+ 6.472980e+000,
+ 1.092331e+001,
+ // albedo 0, turbidity 7
+ 1.082973e+000,
+ 3.118094e+000,
+ -8.934293e+000,
+ 3.186879e+001,
+ 8.473885e+000,
+ 1.174019e+001,
+ // albedo 0, turbidity 8
+ 9.692500e-001,
+ 3.349574e+000,
+ -1.003810e+001,
+ 3.147654e+001,
+ 1.338931e+001,
+ 1.272547e+001,
+ // albedo 0, turbidity 9
+ 8.547044e-001,
+ 3.151538e+000,
+ -9.095567e+000,
+ 2.554995e+001,
+ 2.273219e+001,
+ 1.410398e+001,
+ // albedo 0, turbidity 10
+ 7.580340e-001,
+ 2.311153e+000,
+ -5.170814e+000,
+ 1.229669e+001,
+ 3.686529e+001,
+ 1.598882e+001,
+ // albedo 1, turbidity 1
+ 1.664273e+000,
+ 1.574468e+000,
+ 1.422078e+000,
+ 9.768247e+000,
+ 1.447338e+001,
+ 1.644988e+001,
+ // albedo 1, turbidity 2
+ 1.638295e+000,
+ 1.719586e+000,
+ 5.786675e-001,
+ 1.239846e+001,
+ 1.415419e+001,
+ 1.728605e+001,
+ // albedo 1, turbidity 3
+ 1.572623e+000,
+ 1.921559e+000,
+ -7.714802e-001,
+ 1.609246e+001,
+ 1.420954e+001,
+ 1.825908e+001,
+ // albedo 1, turbidity 4
+ 1.468395e+000,
+ 2.211970e+000,
+ -2.845869e+000,
+ 2.075027e+001,
+ 1.524822e+001,
+ 1.937622e+001,
+ // albedo 1, turbidity 5
+ 1.355047e+000,
+ 2.556469e+000,
+ -4.960920e+000,
+ 2.460237e+001,
+ 1.648360e+001,
+ 2.065648e+001,
+ // albedo 1, turbidity 6
+ 1.291642e+000,
+ 2.742036e+000,
+ -6.061967e+000,
+ 2.602002e+001,
+ 1.819144e+001,
+ 2.116712e+001,
+ // albedo 1, turbidity 7
+ 1.194565e+000,
+ 2.972120e+000,
+ -7.295779e+000,
+ 2.691805e+001,
+ 2.124880e+001,
+ 2.201819e+001,
+ // albedo 1, turbidity 8
+ 1.083631e+000,
+ 3.047021e+000,
+ -7.766096e+000,
+ 2.496261e+001,
+ 2.744264e+001,
+ 2.291875e+001,
+ // albedo 1, turbidity 9
+ 9.707994e-001,
+ 2.736459e+000,
+ -6.308284e+000,
+ 1.760860e+001,
+ 3.776291e+001,
+ 2.392150e+001,
+ // albedo 1, turbidity 10
+ 8.574294e-001,
+ 1.865155e+000,
+ -2.364707e+000,
+ 4.337793e+000,
+ 5.092831e+001,
+ 2.523432e+001,
};
-static const double datasetXYZ2[] =
-{
- // albedo 0, turbidity 1
- -1.127942e+000,
- -1.905548e-001,
- -1.252356e+001,
- 1.375799e+001,
- -3.624732e-002,
- 1.055453e+000,
- 1.385036e-002,
- 4.176970e+000,
- 5.928345e-001,
- -1.155260e+000,
- -1.778135e-001,
- 6.216056e+000,
- -5.254116e+000,
- -8.787445e-002,
- 8.434621e-001,
- 4.025734e-002,
- 6.195322e+000,
- 3.111856e-001,
- -1.125624e+000,
- -3.217593e-001,
- 5.043919e-001,
- 1.686284e+000,
- -3.536071e-001,
- 1.476321e+000,
- -7.899019e-002,
- -4.522531e+000,
- 1.271691e+000,
- -1.081801e+000,
- -1.033234e-001,
- 9.995550e-001,
- 7.482946e-003,
- -6.776018e-002,
- 1.463141e+000,
- 9.492021e-002,
- 5.612723e+000,
- 1.298846e-001,
- -1.075320e+000,
- -2.402711e-001,
- 2.141284e+000,
- -1.203359e+000,
- -4.945188e+000,
- 1.437221e+000,
- -8.096750e-002,
- -1.028378e+000,
- 1.004164e+000,
- -1.073337e+000,
- -1.516517e-001,
- 1.639379e+000,
- 2.304669e+000,
- -3.214244e+000,
- 1.286245e+000,
- 5.613957e-002,
- 2.480902e+000,
- 4.999363e-001,
- // albedo 0, turbidity 2
- -1.128399e+000,
- -1.857793e-001,
- -1.089863e+001,
- 1.172984e+001,
- -3.768099e-002,
- 9.439285e-001,
- 4.869335e-002,
- 4.845114e+000,
- 6.119211e-001,
- -1.114002e+000,
- -1.399280e-001,
- 4.963800e+000,
- -4.685500e+000,
- -7.780879e-002,
- 4.049736e-001,
- 1.586297e-001,
- 7.770264e+000,
- 3.449006e-001,
- -1.185472e+000,
- -3.403543e-001,
- 6.588322e-001,
- 1.133713e+000,
- -4.118674e-001,
- 2.061191e+000,
- -1.882768e-001,
- -4.372586e+000,
- 1.223530e+000,
- -1.002272e+000,
- 2.000703e-002,
- 7.073269e-002,
- 1.485075e+000,
- 5.005589e-001,
- 4.301494e-001,
- 3.626541e-001,
- 7.921098e+000,
- 1.574766e-001,
- -1.121006e+000,
- -3.007777e-001,
- 2.242051e+000,
- -4.571561e+000,
- -7.761071e+000,
- 2.053404e+000,
- -1.524018e-001,
- -1.886162e+000,
- 1.018208e+000,
- -1.058864e+000,
- -1.358673e-001,
- 1.389667e+000,
- 8.633409e+000,
- -3.437249e+000,
- 7.295429e-001,
- 1.514700e-001,
- 2.842513e+000,
- 5.014325e-001,
- // albedo 0, turbidity 3
- -1.144464e+000,
- -2.043799e-001,
- -1.020188e+001,
- 1.071247e+001,
- -3.256693e-002,
- 7.860205e-001,
- 6.872719e-002,
- 4.824771e+000,
- 6.259836e-001,
- -1.170104e+000,
- -2.118626e-001,
- 4.391405e+000,
- -4.198900e+000,
- -7.111559e-002,
- 3.890442e-001,
- 1.024831e-001,
- 6.282535e+000,
- 5.365688e-001,
- -1.129171e+000,
- -2.552880e-001,
- 2.238298e-001,
- 7.314295e-001,
- -3.562730e-001,
- 1.881931e+000,
- -3.078716e-002,
- -1.039120e+000,
- 9.096301e-001,
- -1.042294e+000,
- 4.450203e-003,
- -5.116033e-001,
- 2.627589e+000,
- 6.098996e-001,
- -1.264638e-001,
- 4.325281e-001,
- 7.080503e+000,
- 4.583646e-001,
- -1.082293e+000,
- -2.723056e-001,
- 2.065076e+000,
- -8.143133e+000,
- -7.892212e+000,
- 2.142231e+000,
- -7.106240e-002,
- -1.122398e+000,
- 8.338505e-001,
- -1.071715e+000,
- -1.426568e-001,
- 1.095351e+000,
- 1.729783e+001,
- -3.851931e+000,
- 4.360514e-001,
- 2.114440e-001,
- 2.970832e+000,
- 5.944389e-001,
- // albedo 0, turbidity 4
- -1.195909e+000,
- -2.590449e-001,
- -1.191037e+001,
- 1.207947e+001,
- -1.589842e-002,
- 6.297846e-001,
- 9.054772e-002,
- 4.285959e+000,
- 5.933752e-001,
- -1.245763e+000,
- -3.316637e-001,
- 4.293660e+000,
- -3.694011e+000,
- -4.699947e-002,
- 4.843684e-001,
- 2.130425e-002,
- 4.097549e+000,
- 6.530809e-001,
- -1.148742e+000,
- -1.902509e-001,
- -2.393233e-001,
- -2.441254e-001,
- -2.610918e-001,
- 1.846988e+000,
- 3.532866e-002,
- 2.660106e+000,
- 8.358294e-001,
- -1.016080e+000,
- -7.444960e-002,
- -5.053436e-001,
- 4.388855e+000,
- 6.054987e-001,
- -1.208300e+000,
- 5.817215e-001,
- 2.543570e+000,
- 4.726568e-001,
- -1.072027e+000,
- -2.101440e-001,
- 1.518378e+000,
- -1.060119e+001,
- -6.016546e+000,
- 2.649475e+000,
- -5.166992e-002,
- 1.571269e+000,
- 8.344622e-001,
- -1.072365e+000,
- -1.511201e-001,
- 7.478010e-001,
- 1.900732e+001,
- -3.950387e+000,
- -3.473907e-001,
- 3.797211e-001,
- 2.782949e+000,
- 6.296808e-001,
- // albedo 0, turbidity 5
- -1.239423e+000,
- -3.136289e-001,
- -1.351100e+001,
- 1.349468e+001,
- -7.070423e-003,
- 5.012315e-001,
- 1.106008e-001,
- 3.803619e+000,
- 5.577948e-001,
- -1.452524e+000,
- -5.676944e-001,
- 2.993153e+000,
- -2.277288e+000,
- -2.168954e-002,
- 3.056720e-001,
- 1.152338e-002,
- 1.852697e+000,
- 6.427228e-001,
- -1.061421e+000,
- -4.590521e-002,
- 6.057022e-001,
- -1.096835e+000,
- -1.504952e-001,
- 2.344921e+000,
- -5.491832e-002,
- 5.268322e+000,
- 9.082253e-001,
- -1.042373e+000,
- -1.769498e-001,
- -1.075388e+000,
- 3.831712e+000,
- 3.154140e-001,
- -2.416458e+000,
- 7.909032e-001,
- -1.492892e-002,
- 3.854049e-001,
- -1.064159e+000,
- -1.892684e-001,
- 1.438685e+000,
- -8.166362e+000,
- -3.616364e+000,
- 3.275206e+000,
- -1.203825e-001,
- 2.039491e+000,
- 8.688057e-001,
- -1.070120e+000,
- -1.569508e-001,
- 4.124760e-001,
- 1.399683e+001,
- -3.547085e+000,
- -1.046326e+000,
- 4.973825e-001,
- 2.791231e+000,
- 6.503286e-001,
- // albedo 0, turbidity 6
- -1.283579e+000,
- -3.609518e-001,
- -1.335397e+001,
- 1.315248e+001,
- -4.431938e-004,
- 3.769526e-001,
- 1.429824e-001,
- 3.573613e+000,
- 4.998696e-001,
- -1.657952e+000,
- -7.627948e-001,
- 1.958222e+000,
- -7.949816e-001,
- -2.882837e-002,
- 5.356149e-001,
- -5.191946e-002,
- 8.869955e-001,
- 6.263320e-001,
- -9.527600e-001,
- 6.494189e-002,
- 5.361303e-001,
- -2.129590e+000,
- -9.258630e-002,
- 1.604776e+000,
- 5.067770e-002,
- 6.376055e+000,
- 9.138052e-001,
- -1.080827e+000,
- -2.523120e-001,
- -7.154262e-001,
- 4.120085e+000,
- 1.878228e-001,
- -1.492158e+000,
- 6.881655e-001,
- -1.446611e+000,
- 4.040631e-001,
- -1.054075e+000,
- -1.665498e-001,
- 9.191052e-001,
- -6.636943e+000,
- -1.894826e+000,
- 2.107810e+000,
- -3.680499e-002,
- 2.655452e+000,
- 8.413840e-001,
- -1.061127e+000,
- -1.448849e-001,
- 2.667493e-001,
- 1.034103e+001,
- -4.285769e+000,
- -3.874504e-001,
- 5.998752e-001,
- 3.132426e+000,
- 6.652753e-001,
- // albedo 0, turbidity 7
- -1.347345e+000,
- -4.287832e-001,
- -9.305553e+000,
- 9.133813e+000,
- -3.173527e-003,
- 3.977564e-001,
- 1.151420e-001,
- 3.320564e+000,
- 4.998134e-001,
- -1.927296e+000,
- -9.901372e-001,
- -2.593499e+000,
- 4.087421e+000,
- -5.833993e-002,
- 8.158929e-001,
- -4.681279e-002,
- 2.423716e-001,
- 4.938052e-001,
- -9.470092e-001,
- 7.325237e-002,
- 2.064735e+000,
- -5.167540e+000,
- -1.313751e-002,
- 4.832169e-001,
- 1.126295e-001,
- 6.970522e+000,
- 1.035022e+000,
- -1.022557e+000,
- -2.762616e-001,
- -9.375748e-001,
- 6.696739e+000,
- 2.200765e-001,
- -1.133253e-001,
- 5.492505e-001,
- -3.109391e+000,
- 3.321914e-001,
- -1.087444e+000,
- -1.836263e-001,
- 6.225024e-001,
- -8.576765e+000,
- -1.107637e+000,
- 7.859427e-001,
- 9.910909e-002,
- 3.112938e+000,
- 8.596261e-001,
- -1.051544e+000,
- -1.546262e-001,
- 2.371731e-001,
- 1.200502e+001,
- -4.527291e+000,
- 7.268862e-002,
- 5.571478e-001,
- 2.532873e+000,
- 6.662000e-001,
- // albedo 0, turbidity 8
- -1.375576e+000,
- -4.840019e-001,
- -8.121290e+000,
- 8.058140e+000,
- -1.445661e-002,
- 5.123314e-001,
- 5.813321e-002,
- 3.203219e+000,
- 5.442318e-001,
- -2.325221e+000,
- -1.241463e+000,
- -7.063430e+000,
- 8.741369e+000,
- -7.829950e-002,
- 8.844273e-001,
- -3.471106e-002,
- 1.740583e-001,
- 2.814079e-001,
- -1.228700e+000,
- -2.013412e-001,
- 2.949042e+000,
- -7.371945e+000,
- 1.071753e-001,
- -2.491970e-001,
- 2.265223e-001,
- 6.391504e+000,
- 1.172389e+000,
- -7.601786e-001,
- -1.680631e-001,
- -7.584444e-001,
- 8.541356e+000,
- 8.222291e-002,
- 6.729633e-001,
- 3.206615e-001,
- -3.700940e+000,
- 2.710054e-001,
- -1.191166e+000,
- -2.672347e-001,
- 2.927498e-001,
- -9.713613e+000,
- -4.783721e-001,
- 2.352803e-001,
- 2.161949e-001,
- 2.691481e+000,
- 8.745447e-001,
- -1.030135e+000,
- -1.653301e-001,
- 2.263443e-001,
- 1.296157e+001,
- -4.650644e+000,
- 7.055709e-003,
- 5.091975e-001,
- 2.000370e+000,
- 6.603839e-001,
- // albedo 0, turbidity 9
- -1.508018e+000,
- -6.460933e-001,
- -6.402745e+000,
- 6.545995e+000,
- -3.750320e-002,
- 6.921803e-001,
- 3.309819e-003,
- 2.797527e+000,
- 6.978446e-001,
- -2.333308e+000,
- -1.167837e+000,
- -1.746787e+001,
- 1.868630e+001,
- -8.948229e-003,
- 5.621946e-001,
- -3.402626e-002,
- 1.217943e+000,
- 1.149865e-002,
- -2.665953e+000,
- -1.226307e+000,
- 7.169725e+000,
- -1.159434e+001,
- 3.583420e-002,
- -3.074378e-001,
- 3.412248e-001,
- 4.422122e+000,
- 1.283791e+000,
- -9.705116e-002,
- 8.312991e-002,
- -2.160462e+000,
- 1.028235e+001,
- 3.543357e-002,
- 1.032049e+000,
- 1.058310e-001,
- -2.972898e+000,
- 2.418628e-001,
- -1.329617e+000,
- -3.699557e-001,
- 5.560117e-001,
- -9.730113e+000,
- 9.938865e-002,
- -3.071488e-001,
- 2.510691e-001,
- 1.777111e+000,
- 8.705142e-001,
- -1.019387e+000,
- -1.893247e-001,
- 1.194079e-001,
- 1.239436e+001,
- -4.799224e+000,
- 2.940213e-001,
- 4.841268e-001,
- 1.529724e+000,
- 6.582615e-001,
- // albedo 0, turbidity 10
- -1.896737e+000,
- -1.005442e+000,
- -6.411032e+000,
- 6.548220e+000,
- -3.227596e-002,
- 5.717262e-001,
- -8.115192e-006,
- 2.296704e+000,
- 9.000749e-001,
- -2.411116e+000,
- -1.225587e+000,
- -1.753629e+001,
- 1.829393e+001,
- 1.247555e-002,
- 2.364616e-001,
- -5.114637e-003,
- 1.603778e+000,
- -2.224156e-001,
- -4.707121e+000,
- -2.074977e+000,
- 7.942300e+000,
- -1.132407e+001,
- -5.415654e-002,
- 5.446811e-001,
- 1.032493e-001,
- 4.010235e+000,
- 1.369802e+000,
- 1.010482e-001,
- -4.013305e-001,
- -2.674579e+000,
- 9.779409e+000,
- 1.782506e-001,
- 7.053045e-001,
- 4.200002e-001,
- -2.400671e+000,
- 1.953165e-001,
- -1.243526e+000,
- -3.391255e-001,
- 8.848882e-001,
- -9.789025e+000,
- -3.997324e-001,
- -9.546227e-001,
- -1.044017e-001,
- 6.010593e-001,
- 8.714462e-001,
- -1.014633e+000,
- -1.730009e-001,
- -7.738934e-002,
- 1.390903e+001,
- -4.847307e+000,
- 1.076059e+000,
- 5.685743e-001,
- 1.572992e+000,
- 6.561432e-001,
- // albedo 1, turbidity 1
- -1.122998e+000,
- -1.881183e-001,
- -1.030709e+001,
- 1.158932e+001,
- -4.079495e-002,
- 9.603774e-001,
- 3.079436e-002,
- 4.009235e+000,
- 5.060745e-001,
- -1.134790e+000,
- -1.539688e-001,
- 5.478405e+000,
- -4.217270e+000,
- -1.043858e-001,
- 7.165008e-001,
- 1.524765e-002,
- 6.473623e+000,
- 4.207882e-001,
- -1.134957e+000,
- -3.513318e-001,
- 7.393837e-001,
- 1.354415e+000,
- -4.764078e-001,
- 1.690441e+000,
- -5.492640e-002,
- -5.563523e+000,
- 1.145743e+000,
- -1.058344e+000,
- -5.758503e-002,
- 1.168230e+000,
- 3.269824e-001,
- 1.795193e-001,
- 7.849011e-001,
- 7.441853e-002,
- 6.904804e+000,
- 2.818790e-001,
- -1.075194e+000,
- -2.355813e-001,
- 2.463685e+000,
- -1.536505e+000,
- -7.505771e+000,
- 9.619712e-001,
- -6.465851e-002,
- -1.355492e+000,
- 8.489847e-001,
- -1.079030e+000,
- -1.465328e-001,
- 1.773838e+000,
- 2.310131e+000,
- -3.136065e+000,
- 3.507952e-001,
- 4.435014e-002,
- 2.819225e+000,
- 5.689008e-001,
- // albedo 1, turbidity 2
- -1.125833e+000,
- -1.870849e-001,
- -9.555833e+000,
- 1.059713e+001,
- -4.225402e-002,
- 9.164663e-001,
- 4.338796e-002,
- 4.400980e+000,
- 6.056119e-001,
- -1.127440e+000,
- -1.551891e-001,
- 4.755621e+000,
- -4.408806e+000,
- -7.851763e-002,
- 2.268284e-001,
- 1.460070e-001,
- 7.048003e+000,
- 3.525997e-001,
- -1.143788e+000,
- -3.170178e-001,
- 5.480669e-001,
- 2.041830e+000,
- -4.532139e-001,
- 2.302233e+000,
- -1.887419e-001,
- -4.489221e+000,
- 1.250967e+000,
- -1.032849e+000,
- 7.376031e-003,
- 5.666073e-001,
- -2.312203e-001,
- 4.862894e-001,
- -1.748294e-001,
- 3.572870e-001,
- 8.380522e+000,
- 1.302333e-001,
- -1.093728e+000,
- -2.786977e-001,
- 2.641272e+000,
- -1.507494e+000,
- -8.731243e+000,
- 1.684055e+000,
- -2.023377e-001,
- -2.176398e+000,
- 1.013249e+000,
- -1.076578e+000,
- -1.456205e-001,
- 1.693935e+000,
- 2.945003e+000,
- -2.822673e+000,
- -2.520033e-001,
- 1.517034e-001,
- 2.649109e+000,
- 5.179094e-001,
- // albedo 1, turbidity 3
- -1.146417e+000,
- -2.119353e-001,
- -7.187525e+000,
- 8.058599e+000,
- -5.256438e-002,
- 8.375733e-001,
- 3.887093e-002,
- 4.222111e+000,
- 6.695347e-001,
- -1.173674e+000,
- -2.067025e-001,
- 2.899359e+000,
- -2.804918e+000,
- -8.473899e-002,
- 3.944225e-003,
- 1.340641e-001,
- 6.160887e+000,
- 4.527141e-001,
- -1.090098e+000,
- -2.599633e-001,
- 9.180856e-001,
- 1.092710e+000,
- -4.215019e-001,
- 2.427660e+000,
- -9.277667e-002,
- -2.123523e+000,
- 1.058159e+000,
- -1.084460e+000,
- 8.056181e-003,
- -2.453510e-001,
- 6.619567e-001,
- 4.668118e-001,
- -9.526719e-001,
- 4.648454e-001,
- 8.001572e+000,
- 3.054194e-001,
- -1.053728e+000,
- -2.765784e-001,
- 2.792388e+000,
- -3.489517e+000,
- -8.150535e+000,
- 2.195757e+000,
- -2.017234e-001,
- -2.128017e+000,
- 9.326589e-001,
- -1.099348e+000,
- -1.593939e-001,
- 1.568292e+000,
- 7.247853e+000,
- -2.933000e+000,
- -5.890481e-001,
- 1.724440e-001,
- 2.433484e+000,
- 5.736558e-001,
- // albedo 1, turbidity 4
- -1.185983e+000,
- -2.581184e-001,
- -7.761056e+000,
- 8.317053e+000,
- -3.351773e-002,
- 6.676667e-001,
- 5.941733e-002,
- 3.820727e+000,
- 6.324032e-001,
- -1.268591e+000,
- -3.398067e-001,
- 2.348503e+000,
- -2.023779e+000,
- -5.368458e-002,
- 1.083282e-001,
- 8.402858e-002,
- 3.910254e+000,
- 5.577481e-001,
- -1.071353e+000,
- -1.992459e-001,
- 7.878387e-001,
- 1.974702e-001,
- -3.033058e-001,
- 2.335298e+000,
- -8.205259e-002,
- 7.954454e-001,
- 9.972312e-001,
- -1.089513e+000,
- -3.104364e-002,
- -5.995746e-001,
- 2.330281e+000,
- 6.581939e-001,
- -1.821467e+000,
- 6.679973e-001,
- 5.090195e+000,
- 3.125161e-001,
- -1.040214e+000,
- -2.570934e-001,
- 2.660489e+000,
- -6.506045e+000,
- -7.053586e+000,
- 2.763153e+000,
- -2.433632e-001,
- -7.648176e-001,
- 9.452937e-001,
- -1.116052e+000,
- -1.831993e-001,
- 1.457694e+000,
- 1.163608e+001,
- -3.216426e+000,
- -1.045594e+000,
- 2.285002e-001,
- 1.817407e+000,
- 5.810396e-001,
- // albedo 1, turbidity 5
- -1.230134e+000,
- -3.136264e-001,
- -8.909301e+000,
- 9.145006e+000,
- -1.055387e-002,
- 4.467317e-001,
- 1.016826e-001,
- 3.342964e+000,
- 5.633840e-001,
- -1.442907e+000,
- -5.593147e-001,
- 2.156447e+000,
- -1.241657e+000,
- -3.512130e-002,
- 3.050274e-001,
- 1.797175e-002,
- 1.742358e+000,
- 5.977153e-001,
- -1.027627e+000,
- -6.481539e-002,
- 4.351975e-001,
- -1.051677e+000,
- -2.030672e-001,
- 1.942684e+000,
- -3.615993e-002,
- 4.050266e+000,
- 9.801624e-001,
- -1.082110e+000,
- -1.578209e-001,
- -3.397511e-001,
- 4.163851e+000,
- 6.650368e-001,
- -1.841730e+000,
- 7.062544e-001,
- 6.789881e-001,
- 3.172623e-001,
- -1.047447e+000,
- -1.977560e-001,
- 2.183364e+000,
- -8.805249e+000,
- -5.483962e+000,
- 2.551309e+000,
- -1.779640e-001,
- 1.519501e+000,
- 9.212536e-001,
- -1.111853e+000,
- -1.935736e-001,
- 1.394408e+000,
- 1.392405e+001,
- -3.465430e+000,
- -1.068432e+000,
- 2.388671e-001,
- 1.455336e+000,
- 6.233425e-001,
- // albedo 1, turbidity 6
- -1.262238e+000,
- -3.546341e-001,
- -1.008703e+001,
- 1.020084e+001,
- -1.852187e-003,
- 3.537580e-001,
- 1.239199e-001,
- 3.056093e+000,
- 5.132052e-001,
- -1.613810e+000,
- -7.355585e-001,
- 2.760123e+000,
- -1.685253e+000,
- -2.517552e-002,
- 2.914258e-001,
- 4.743448e-003,
- 8.689596e-001,
- 5.674192e-001,
- -9.462336e-001,
- 2.950767e-002,
- -2.613816e-001,
- -7.398653e-001,
- -1.315558e-001,
- 1.901042e+000,
- -6.447844e-002,
- 4.969341e+000,
- 1.027342e+000,
- -1.111481e+000,
- -2.194054e-001,
- -9.004538e-002,
- 3.983442e+000,
- 4.871278e-001,
- -1.965315e+000,
- 7.956121e-001,
- -2.363225e-001,
- 2.718037e-001,
- -1.036397e+000,
- -1.827106e-001,
- 1.964747e+000,
- -8.870759e+000,
- -4.208011e+000,
- 2.461215e+000,
- -2.158905e-001,
- 1.561676e+000,
- 9.436866e-001,
- -1.113769e+000,
- -1.947819e-001,
- 1.300720e+000,
- 1.516476e+001,
- -4.088732e+000,
- -1.069384e+000,
- 2.836434e-001,
- 1.671451e+000,
- 6.229612e-001,
- // albedo 1, turbidity 7
- -1.328069e+000,
- -4.244047e-001,
- -8.417040e+000,
- 8.552244e+000,
- -6.813504e-003,
- 4.127422e-001,
- 9.619897e-002,
- 2.854227e+000,
- 5.059880e-001,
- -1.927552e+000,
- -1.025290e+000,
- 9.529576e-001,
- 4.255950e-001,
- -3.738779e-002,
- 2.584586e-001,
- 4.911004e-002,
- -2.640913e-001,
- 4.138626e-001,
- -8.488094e-001,
- 1.435988e-001,
- 6.356807e-001,
- -2.895732e+000,
- -8.473961e-002,
- 1.701305e+000,
- -1.323908e-001,
- 6.499338e+000,
- 1.210928e+000,
- -1.128313e+000,
- -3.397048e-001,
- -4.043140e-001,
- 6.265097e+000,
- 5.482395e-001,
- -2.057614e+000,
- 8.884087e-001,
- -2.943879e+000,
- 9.760301e-002,
- -1.039764e+000,
- -1.494772e-001,
- 1.781915e+000,
- -1.153012e+001,
- -3.379232e+000,
- 2.517231e+000,
- -2.764393e-001,
- 2.588849e+000,
- 1.052120e+000,
- -1.108447e+000,
- -2.012251e-001,
- 1.198640e+000,
- 1.925331e+001,
- -4.423892e+000,
- -1.257122e+000,
- 3.395690e-001,
- 1.481220e+000,
- 5.880175e-001,
- // albedo 1, turbidity 8
- -1.374185e+000,
- -4.967434e-001,
- -7.401318e+000,
- 7.724021e+000,
- -2.345723e-002,
- 5.979653e-001,
- 2.436346e-002,
- 2.658970e+000,
- 6.014891e-001,
- -2.310933e+000,
- -1.290290e+000,
- -1.301909e+000,
- 2.557806e+000,
- -3.744449e-002,
- 8.982861e-002,
- 1.090613e-001,
- -4.398363e-001,
- 1.184329e-001,
- -1.124730e+000,
- -9.921830e-002,
- 1.366902e+000,
- -4.172489e+000,
- -5.078016e-002,
- 1.393597e+000,
- -9.323843e-002,
- 6.452721e+000,
- 1.435913e+000,
- -8.468477e-001,
- -2.744819e-001,
- -4.347200e-001,
- 6.713362e+000,
- 6.127133e-001,
- -1.685634e+000,
- 7.360941e-001,
- -4.535502e+000,
- -2.920866e-002,
- -1.165242e+000,
- -2.008697e-001,
- 1.438778e+000,
- -1.008936e+001,
- -2.214771e+000,
- 2.102909e+000,
- -1.763085e-001,
- 2.859075e+000,
- 1.093470e+000,
- -1.074614e+000,
- -2.066374e-001,
- 1.131891e+000,
- 1.630063e+001,
- -4.801441e+000,
- -1.112590e+000,
- 3.595785e-001,
- 1.122227e+000,
- 5.794610e-001,
- // albedo 1, turbidity 9
- -1.521515e+000,
- -6.835604e-001,
- -5.571044e+000,
- 6.028774e+000,
- -4.253715e-002,
- 6.875746e-001,
- -5.279456e-006,
- 2.180150e+000,
- 8.487705e-001,
- -2.240415e+000,
- -1.171166e+000,
- -7.182771e+000,
- 8.417068e+000,
- -1.932866e-002,
- 1.101887e-001,
- -1.098862e-002,
- 6.242195e-001,
- -2.393875e-001,
- -2.712354e+000,
- -1.198830e+000,
- 3.180200e+000,
- -6.768130e+000,
- -2.563386e-003,
- 7.984607e-001,
- 2.764376e-001,
- 4.695358e+000,
- 1.557045e+000,
- -3.655172e-002,
- -2.142321e-002,
- -9.138120e-001,
- 7.932786e+000,
- 3.516542e-001,
- -7.994343e-001,
- 1.786761e-001,
- -4.208399e+000,
- 1.820576e-002,
- -1.368610e+000,
- -2.656212e-001,
- 1.249397e+000,
- -8.317818e+000,
- -8.962772e-001,
- 1.423249e+000,
- 1.478381e-001,
- 2.191660e+000,
- 1.007748e+000,
- -1.041753e+000,
- -2.453366e-001,
- 1.061102e+000,
- 1.130172e+001,
- -4.739312e+000,
- -9.223334e-001,
- 2.982776e-001,
- 6.162931e-001,
- 6.080302e-001,
- // albedo 1, turbidity 10
- -1.989159e+000,
- -1.095160e+000,
- -2.915550e+000,
- 3.275339e+000,
- -5.735765e-002,
- 5.742174e-001,
- -7.683288e-006,
- 1.763400e+000,
- 9.001342e-001,
- -2.070020e+000,
- -1.086338e+000,
- -1.095898e+001,
- 1.206960e+001,
- 3.780123e-002,
- -1.774699e-002,
- -5.881348e-004,
- 1.333819e+000,
- -2.605423e-001,
- -5.249653e+000,
- -2.383040e+000,
- 6.160406e+000,
- -9.097138e+000,
- -1.955319e-001,
- 1.651785e+000,
- 6.016463e-004,
- 3.021824e+000,
- 1.493574e+000,
- 4.685432e-001,
- -2.358662e-001,
- -2.666433e+000,
- 9.685763e+000,
- 5.804928e-001,
- -1.521875e+000,
- 5.668989e-001,
- -1.548136e+000,
- 1.688642e-002,
- -1.296891e+000,
- -3.449031e-001,
- 1.928548e+000,
- -1.167560e+001,
- -1.627615e+000,
- 1.355603e+000,
- -1.929074e-001,
- -6.568952e-001,
- 1.009774e+000,
- -1.067288e+000,
- -2.410392e-001,
- 7.147961e-001,
- 1.783840e+001,
- -4.374399e+000,
- -6.588777e-001,
- 3.329831e-001,
- 1.012066e+000,
- 6.118645e-001,
+static const double datasetXYZ2[] = {
+ // albedo 0, turbidity 1
+ -1.127942e+000,
+ -1.905548e-001,
+ -1.252356e+001,
+ 1.375799e+001,
+ -3.624732e-002,
+ 1.055453e+000,
+ 1.385036e-002,
+ 4.176970e+000,
+ 5.928345e-001,
+ -1.155260e+000,
+ -1.778135e-001,
+ 6.216056e+000,
+ -5.254116e+000,
+ -8.787445e-002,
+ 8.434621e-001,
+ 4.025734e-002,
+ 6.195322e+000,
+ 3.111856e-001,
+ -1.125624e+000,
+ -3.217593e-001,
+ 5.043919e-001,
+ 1.686284e+000,
+ -3.536071e-001,
+ 1.476321e+000,
+ -7.899019e-002,
+ -4.522531e+000,
+ 1.271691e+000,
+ -1.081801e+000,
+ -1.033234e-001,
+ 9.995550e-001,
+ 7.482946e-003,
+ -6.776018e-002,
+ 1.463141e+000,
+ 9.492021e-002,
+ 5.612723e+000,
+ 1.298846e-001,
+ -1.075320e+000,
+ -2.402711e-001,
+ 2.141284e+000,
+ -1.203359e+000,
+ -4.945188e+000,
+ 1.437221e+000,
+ -8.096750e-002,
+ -1.028378e+000,
+ 1.004164e+000,
+ -1.073337e+000,
+ -1.516517e-001,
+ 1.639379e+000,
+ 2.304669e+000,
+ -3.214244e+000,
+ 1.286245e+000,
+ 5.613957e-002,
+ 2.480902e+000,
+ 4.999363e-001,
+ // albedo 0, turbidity 2
+ -1.128399e+000,
+ -1.857793e-001,
+ -1.089863e+001,
+ 1.172984e+001,
+ -3.768099e-002,
+ 9.439285e-001,
+ 4.869335e-002,
+ 4.845114e+000,
+ 6.119211e-001,
+ -1.114002e+000,
+ -1.399280e-001,
+ 4.963800e+000,
+ -4.685500e+000,
+ -7.780879e-002,
+ 4.049736e-001,
+ 1.586297e-001,
+ 7.770264e+000,
+ 3.449006e-001,
+ -1.185472e+000,
+ -3.403543e-001,
+ 6.588322e-001,
+ 1.133713e+000,
+ -4.118674e-001,
+ 2.061191e+000,
+ -1.882768e-001,
+ -4.372586e+000,
+ 1.223530e+000,
+ -1.002272e+000,
+ 2.000703e-002,
+ 7.073269e-002,
+ 1.485075e+000,
+ 5.005589e-001,
+ 4.301494e-001,
+ 3.626541e-001,
+ 7.921098e+000,
+ 1.574766e-001,
+ -1.121006e+000,
+ -3.007777e-001,
+ 2.242051e+000,
+ -4.571561e+000,
+ -7.761071e+000,
+ 2.053404e+000,
+ -1.524018e-001,
+ -1.886162e+000,
+ 1.018208e+000,
+ -1.058864e+000,
+ -1.358673e-001,
+ 1.389667e+000,
+ 8.633409e+000,
+ -3.437249e+000,
+ 7.295429e-001,
+ 1.514700e-001,
+ 2.842513e+000,
+ 5.014325e-001,
+ // albedo 0, turbidity 3
+ -1.144464e+000,
+ -2.043799e-001,
+ -1.020188e+001,
+ 1.071247e+001,
+ -3.256693e-002,
+ 7.860205e-001,
+ 6.872719e-002,
+ 4.824771e+000,
+ 6.259836e-001,
+ -1.170104e+000,
+ -2.118626e-001,
+ 4.391405e+000,
+ -4.198900e+000,
+ -7.111559e-002,
+ 3.890442e-001,
+ 1.024831e-001,
+ 6.282535e+000,
+ 5.365688e-001,
+ -1.129171e+000,
+ -2.552880e-001,
+ 2.238298e-001,
+ 7.314295e-001,
+ -3.562730e-001,
+ 1.881931e+000,
+ -3.078716e-002,
+ -1.039120e+000,
+ 9.096301e-001,
+ -1.042294e+000,
+ 4.450203e-003,
+ -5.116033e-001,
+ 2.627589e+000,
+ 6.098996e-001,
+ -1.264638e-001,
+ 4.325281e-001,
+ 7.080503e+000,
+ 4.583646e-001,
+ -1.082293e+000,
+ -2.723056e-001,
+ 2.065076e+000,
+ -8.143133e+000,
+ -7.892212e+000,
+ 2.142231e+000,
+ -7.106240e-002,
+ -1.122398e+000,
+ 8.338505e-001,
+ -1.071715e+000,
+ -1.426568e-001,
+ 1.095351e+000,
+ 1.729783e+001,
+ -3.851931e+000,
+ 4.360514e-001,
+ 2.114440e-001,
+ 2.970832e+000,
+ 5.944389e-001,
+ // albedo 0, turbidity 4
+ -1.195909e+000,
+ -2.590449e-001,
+ -1.191037e+001,
+ 1.207947e+001,
+ -1.589842e-002,
+ 6.297846e-001,
+ 9.054772e-002,
+ 4.285959e+000,
+ 5.933752e-001,
+ -1.245763e+000,
+ -3.316637e-001,
+ 4.293660e+000,
+ -3.694011e+000,
+ -4.699947e-002,
+ 4.843684e-001,
+ 2.130425e-002,
+ 4.097549e+000,
+ 6.530809e-001,
+ -1.148742e+000,
+ -1.902509e-001,
+ -2.393233e-001,
+ -2.441254e-001,
+ -2.610918e-001,
+ 1.846988e+000,
+ 3.532866e-002,
+ 2.660106e+000,
+ 8.358294e-001,
+ -1.016080e+000,
+ -7.444960e-002,
+ -5.053436e-001,
+ 4.388855e+000,
+ 6.054987e-001,
+ -1.208300e+000,
+ 5.817215e-001,
+ 2.543570e+000,
+ 4.726568e-001,
+ -1.072027e+000,
+ -2.101440e-001,
+ 1.518378e+000,
+ -1.060119e+001,
+ -6.016546e+000,
+ 2.649475e+000,
+ -5.166992e-002,
+ 1.571269e+000,
+ 8.344622e-001,
+ -1.072365e+000,
+ -1.511201e-001,
+ 7.478010e-001,
+ 1.900732e+001,
+ -3.950387e+000,
+ -3.473907e-001,
+ 3.797211e-001,
+ 2.782949e+000,
+ 6.296808e-001,
+ // albedo 0, turbidity 5
+ -1.239423e+000,
+ -3.136289e-001,
+ -1.351100e+001,
+ 1.349468e+001,
+ -7.070423e-003,
+ 5.012315e-001,
+ 1.106008e-001,
+ 3.803619e+000,
+ 5.577948e-001,
+ -1.452524e+000,
+ -5.676944e-001,
+ 2.993153e+000,
+ -2.277288e+000,
+ -2.168954e-002,
+ 3.056720e-001,
+ 1.152338e-002,
+ 1.852697e+000,
+ 6.427228e-001,
+ -1.061421e+000,
+ -4.590521e-002,
+ 6.057022e-001,
+ -1.096835e+000,
+ -1.504952e-001,
+ 2.344921e+000,
+ -5.491832e-002,
+ 5.268322e+000,
+ 9.082253e-001,
+ -1.042373e+000,
+ -1.769498e-001,
+ -1.075388e+000,
+ 3.831712e+000,
+ 3.154140e-001,
+ -2.416458e+000,
+ 7.909032e-001,
+ -1.492892e-002,
+ 3.854049e-001,
+ -1.064159e+000,
+ -1.892684e-001,
+ 1.438685e+000,
+ -8.166362e+000,
+ -3.616364e+000,
+ 3.275206e+000,
+ -1.203825e-001,
+ 2.039491e+000,
+ 8.688057e-001,
+ -1.070120e+000,
+ -1.569508e-001,
+ 4.124760e-001,
+ 1.399683e+001,
+ -3.547085e+000,
+ -1.046326e+000,
+ 4.973825e-001,
+ 2.791231e+000,
+ 6.503286e-001,
+ // albedo 0, turbidity 6
+ -1.283579e+000,
+ -3.609518e-001,
+ -1.335397e+001,
+ 1.315248e+001,
+ -4.431938e-004,
+ 3.769526e-001,
+ 1.429824e-001,
+ 3.573613e+000,
+ 4.998696e-001,
+ -1.657952e+000,
+ -7.627948e-001,
+ 1.958222e+000,
+ -7.949816e-001,
+ -2.882837e-002,
+ 5.356149e-001,
+ -5.191946e-002,
+ 8.869955e-001,
+ 6.263320e-001,
+ -9.527600e-001,
+ 6.494189e-002,
+ 5.361303e-001,
+ -2.129590e+000,
+ -9.258630e-002,
+ 1.604776e+000,
+ 5.067770e-002,
+ 6.376055e+000,
+ 9.138052e-001,
+ -1.080827e+000,
+ -2.523120e-001,
+ -7.154262e-001,
+ 4.120085e+000,
+ 1.878228e-001,
+ -1.492158e+000,
+ 6.881655e-001,
+ -1.446611e+000,
+ 4.040631e-001,
+ -1.054075e+000,
+ -1.665498e-001,
+ 9.191052e-001,
+ -6.636943e+000,
+ -1.894826e+000,
+ 2.107810e+000,
+ -3.680499e-002,
+ 2.655452e+000,
+ 8.413840e-001,
+ -1.061127e+000,
+ -1.448849e-001,
+ 2.667493e-001,
+ 1.034103e+001,
+ -4.285769e+000,
+ -3.874504e-001,
+ 5.998752e-001,
+ 3.132426e+000,
+ 6.652753e-001,
+ // albedo 0, turbidity 7
+ -1.347345e+000,
+ -4.287832e-001,
+ -9.305553e+000,
+ 9.133813e+000,
+ -3.173527e-003,
+ 3.977564e-001,
+ 1.151420e-001,
+ 3.320564e+000,
+ 4.998134e-001,
+ -1.927296e+000,
+ -9.901372e-001,
+ -2.593499e+000,
+ 4.087421e+000,
+ -5.833993e-002,
+ 8.158929e-001,
+ -4.681279e-002,
+ 2.423716e-001,
+ 4.938052e-001,
+ -9.470092e-001,
+ 7.325237e-002,
+ 2.064735e+000,
+ -5.167540e+000,
+ -1.313751e-002,
+ 4.832169e-001,
+ 1.126295e-001,
+ 6.970522e+000,
+ 1.035022e+000,
+ -1.022557e+000,
+ -2.762616e-001,
+ -9.375748e-001,
+ 6.696739e+000,
+ 2.200765e-001,
+ -1.133253e-001,
+ 5.492505e-001,
+ -3.109391e+000,
+ 3.321914e-001,
+ -1.087444e+000,
+ -1.836263e-001,
+ 6.225024e-001,
+ -8.576765e+000,
+ -1.107637e+000,
+ 7.859427e-001,
+ 9.910909e-002,
+ 3.112938e+000,
+ 8.596261e-001,
+ -1.051544e+000,
+ -1.546262e-001,
+ 2.371731e-001,
+ 1.200502e+001,
+ -4.527291e+000,
+ 7.268862e-002,
+ 5.571478e-001,
+ 2.532873e+000,
+ 6.662000e-001,
+ // albedo 0, turbidity 8
+ -1.375576e+000,
+ -4.840019e-001,
+ -8.121290e+000,
+ 8.058140e+000,
+ -1.445661e-002,
+ 5.123314e-001,
+ 5.813321e-002,
+ 3.203219e+000,
+ 5.442318e-001,
+ -2.325221e+000,
+ -1.241463e+000,
+ -7.063430e+000,
+ 8.741369e+000,
+ -7.829950e-002,
+ 8.844273e-001,
+ -3.471106e-002,
+ 1.740583e-001,
+ 2.814079e-001,
+ -1.228700e+000,
+ -2.013412e-001,
+ 2.949042e+000,
+ -7.371945e+000,
+ 1.071753e-001,
+ -2.491970e-001,
+ 2.265223e-001,
+ 6.391504e+000,
+ 1.172389e+000,
+ -7.601786e-001,
+ -1.680631e-001,
+ -7.584444e-001,
+ 8.541356e+000,
+ 8.222291e-002,
+ 6.729633e-001,
+ 3.206615e-001,
+ -3.700940e+000,
+ 2.710054e-001,
+ -1.191166e+000,
+ -2.672347e-001,
+ 2.927498e-001,
+ -9.713613e+000,
+ -4.783721e-001,
+ 2.352803e-001,
+ 2.161949e-001,
+ 2.691481e+000,
+ 8.745447e-001,
+ -1.030135e+000,
+ -1.653301e-001,
+ 2.263443e-001,
+ 1.296157e+001,
+ -4.650644e+000,
+ 7.055709e-003,
+ 5.091975e-001,
+ 2.000370e+000,
+ 6.603839e-001,
+ // albedo 0, turbidity 9
+ -1.508018e+000,
+ -6.460933e-001,
+ -6.402745e+000,
+ 6.545995e+000,
+ -3.750320e-002,
+ 6.921803e-001,
+ 3.309819e-003,
+ 2.797527e+000,
+ 6.978446e-001,
+ -2.333308e+000,
+ -1.167837e+000,
+ -1.746787e+001,
+ 1.868630e+001,
+ -8.948229e-003,
+ 5.621946e-001,
+ -3.402626e-002,
+ 1.217943e+000,
+ 1.149865e-002,
+ -2.665953e+000,
+ -1.226307e+000,
+ 7.169725e+000,
+ -1.159434e+001,
+ 3.583420e-002,
+ -3.074378e-001,
+ 3.412248e-001,
+ 4.422122e+000,
+ 1.283791e+000,
+ -9.705116e-002,
+ 8.312991e-002,
+ -2.160462e+000,
+ 1.028235e+001,
+ 3.543357e-002,
+ 1.032049e+000,
+ 1.058310e-001,
+ -2.972898e+000,
+ 2.418628e-001,
+ -1.329617e+000,
+ -3.699557e-001,
+ 5.560117e-001,
+ -9.730113e+000,
+ 9.938865e-002,
+ -3.071488e-001,
+ 2.510691e-001,
+ 1.777111e+000,
+ 8.705142e-001,
+ -1.019387e+000,
+ -1.893247e-001,
+ 1.194079e-001,
+ 1.239436e+001,
+ -4.799224e+000,
+ 2.940213e-001,
+ 4.841268e-001,
+ 1.529724e+000,
+ 6.582615e-001,
+ // albedo 0, turbidity 10
+ -1.896737e+000,
+ -1.005442e+000,
+ -6.411032e+000,
+ 6.548220e+000,
+ -3.227596e-002,
+ 5.717262e-001,
+ -8.115192e-006,
+ 2.296704e+000,
+ 9.000749e-001,
+ -2.411116e+000,
+ -1.225587e+000,
+ -1.753629e+001,
+ 1.829393e+001,
+ 1.247555e-002,
+ 2.364616e-001,
+ -5.114637e-003,
+ 1.603778e+000,
+ -2.224156e-001,
+ -4.707121e+000,
+ -2.074977e+000,
+ 7.942300e+000,
+ -1.132407e+001,
+ -5.415654e-002,
+ 5.446811e-001,
+ 1.032493e-001,
+ 4.010235e+000,
+ 1.369802e+000,
+ 1.010482e-001,
+ -4.013305e-001,
+ -2.674579e+000,
+ 9.779409e+000,
+ 1.782506e-001,
+ 7.053045e-001,
+ 4.200002e-001,
+ -2.400671e+000,
+ 1.953165e-001,
+ -1.243526e+000,
+ -3.391255e-001,
+ 8.848882e-001,
+ -9.789025e+000,
+ -3.997324e-001,
+ -9.546227e-001,
+ -1.044017e-001,
+ 6.010593e-001,
+ 8.714462e-001,
+ -1.014633e+000,
+ -1.730009e-001,
+ -7.738934e-002,
+ 1.390903e+001,
+ -4.847307e+000,
+ 1.076059e+000,
+ 5.685743e-001,
+ 1.572992e+000,
+ 6.561432e-001,
+ // albedo 1, turbidity 1
+ -1.122998e+000,
+ -1.881183e-001,
+ -1.030709e+001,
+ 1.158932e+001,
+ -4.079495e-002,
+ 9.603774e-001,
+ 3.079436e-002,
+ 4.009235e+000,
+ 5.060745e-001,
+ -1.134790e+000,
+ -1.539688e-001,
+ 5.478405e+000,
+ -4.217270e+000,
+ -1.043858e-001,
+ 7.165008e-001,
+ 1.524765e-002,
+ 6.473623e+000,
+ 4.207882e-001,
+ -1.134957e+000,
+ -3.513318e-001,
+ 7.393837e-001,
+ 1.354415e+000,
+ -4.764078e-001,
+ 1.690441e+000,
+ -5.492640e-002,
+ -5.563523e+000,
+ 1.145743e+000,
+ -1.058344e+000,
+ -5.758503e-002,
+ 1.168230e+000,
+ 3.269824e-001,
+ 1.795193e-001,
+ 7.849011e-001,
+ 7.441853e-002,
+ 6.904804e+000,
+ 2.818790e-001,
+ -1.075194e+000,
+ -2.355813e-001,
+ 2.463685e+000,
+ -1.536505e+000,
+ -7.505771e+000,
+ 9.619712e-001,
+ -6.465851e-002,
+ -1.355492e+000,
+ 8.489847e-001,
+ -1.079030e+000,
+ -1.465328e-001,
+ 1.773838e+000,
+ 2.310131e+000,
+ -3.136065e+000,
+ 3.507952e-001,
+ 4.435014e-002,
+ 2.819225e+000,
+ 5.689008e-001,
+ // albedo 1, turbidity 2
+ -1.125833e+000,
+ -1.870849e-001,
+ -9.555833e+000,
+ 1.059713e+001,
+ -4.225402e-002,
+ 9.164663e-001,
+ 4.338796e-002,
+ 4.400980e+000,
+ 6.056119e-001,
+ -1.127440e+000,
+ -1.551891e-001,
+ 4.755621e+000,
+ -4.408806e+000,
+ -7.851763e-002,
+ 2.268284e-001,
+ 1.460070e-001,
+ 7.048003e+000,
+ 3.525997e-001,
+ -1.143788e+000,
+ -3.170178e-001,
+ 5.480669e-001,
+ 2.041830e+000,
+ -4.532139e-001,
+ 2.302233e+000,
+ -1.887419e-001,
+ -4.489221e+000,
+ 1.250967e+000,
+ -1.032849e+000,
+ 7.376031e-003,
+ 5.666073e-001,
+ -2.312203e-001,
+ 4.862894e-001,
+ -1.748294e-001,
+ 3.572870e-001,
+ 8.380522e+000,
+ 1.302333e-001,
+ -1.093728e+000,
+ -2.786977e-001,
+ 2.641272e+000,
+ -1.507494e+000,
+ -8.731243e+000,
+ 1.684055e+000,
+ -2.023377e-001,
+ -2.176398e+000,
+ 1.013249e+000,
+ -1.076578e+000,
+ -1.456205e-001,
+ 1.693935e+000,
+ 2.945003e+000,
+ -2.822673e+000,
+ -2.520033e-001,
+ 1.517034e-001,
+ 2.649109e+000,
+ 5.179094e-001,
+ // albedo 1, turbidity 3
+ -1.146417e+000,
+ -2.119353e-001,
+ -7.187525e+000,
+ 8.058599e+000,
+ -5.256438e-002,
+ 8.375733e-001,
+ 3.887093e-002,
+ 4.222111e+000,
+ 6.695347e-001,
+ -1.173674e+000,
+ -2.067025e-001,
+ 2.899359e+000,
+ -2.804918e+000,
+ -8.473899e-002,
+ 3.944225e-003,
+ 1.340641e-001,
+ 6.160887e+000,
+ 4.527141e-001,
+ -1.090098e+000,
+ -2.599633e-001,
+ 9.180856e-001,
+ 1.092710e+000,
+ -4.215019e-001,
+ 2.427660e+000,
+ -9.277667e-002,
+ -2.123523e+000,
+ 1.058159e+000,
+ -1.084460e+000,
+ 8.056181e-003,
+ -2.453510e-001,
+ 6.619567e-001,
+ 4.668118e-001,
+ -9.526719e-001,
+ 4.648454e-001,
+ 8.001572e+000,
+ 3.054194e-001,
+ -1.053728e+000,
+ -2.765784e-001,
+ 2.792388e+000,
+ -3.489517e+000,
+ -8.150535e+000,
+ 2.195757e+000,
+ -2.017234e-001,
+ -2.128017e+000,
+ 9.326589e-001,
+ -1.099348e+000,
+ -1.593939e-001,
+ 1.568292e+000,
+ 7.247853e+000,
+ -2.933000e+000,
+ -5.890481e-001,
+ 1.724440e-001,
+ 2.433484e+000,
+ 5.736558e-001,
+ // albedo 1, turbidity 4
+ -1.185983e+000,
+ -2.581184e-001,
+ -7.761056e+000,
+ 8.317053e+000,
+ -3.351773e-002,
+ 6.676667e-001,
+ 5.941733e-002,
+ 3.820727e+000,
+ 6.324032e-001,
+ -1.268591e+000,
+ -3.398067e-001,
+ 2.348503e+000,
+ -2.023779e+000,
+ -5.368458e-002,
+ 1.083282e-001,
+ 8.402858e-002,
+ 3.910254e+000,
+ 5.577481e-001,
+ -1.071353e+000,
+ -1.992459e-001,
+ 7.878387e-001,
+ 1.974702e-001,
+ -3.033058e-001,
+ 2.335298e+000,
+ -8.205259e-002,
+ 7.954454e-001,
+ 9.972312e-001,
+ -1.089513e+000,
+ -3.104364e-002,
+ -5.995746e-001,
+ 2.330281e+000,
+ 6.581939e-001,
+ -1.821467e+000,
+ 6.679973e-001,
+ 5.090195e+000,
+ 3.125161e-001,
+ -1.040214e+000,
+ -2.570934e-001,
+ 2.660489e+000,
+ -6.506045e+000,
+ -7.053586e+000,
+ 2.763153e+000,
+ -2.433632e-001,
+ -7.648176e-001,
+ 9.452937e-001,
+ -1.116052e+000,
+ -1.831993e-001,
+ 1.457694e+000,
+ 1.163608e+001,
+ -3.216426e+000,
+ -1.045594e+000,
+ 2.285002e-001,
+ 1.817407e+000,
+ 5.810396e-001,
+ // albedo 1, turbidity 5
+ -1.230134e+000,
+ -3.136264e-001,
+ -8.909301e+000,
+ 9.145006e+000,
+ -1.055387e-002,
+ 4.467317e-001,
+ 1.016826e-001,
+ 3.342964e+000,
+ 5.633840e-001,
+ -1.442907e+000,
+ -5.593147e-001,
+ 2.156447e+000,
+ -1.241657e+000,
+ -3.512130e-002,
+ 3.050274e-001,
+ 1.797175e-002,
+ 1.742358e+000,
+ 5.977153e-001,
+ -1.027627e+000,
+ -6.481539e-002,
+ 4.351975e-001,
+ -1.051677e+000,
+ -2.030672e-001,
+ 1.942684e+000,
+ -3.615993e-002,
+ 4.050266e+000,
+ 9.801624e-001,
+ -1.082110e+000,
+ -1.578209e-001,
+ -3.397511e-001,
+ 4.163851e+000,
+ 6.650368e-001,
+ -1.841730e+000,
+ 7.062544e-001,
+ 6.789881e-001,
+ 3.172623e-001,
+ -1.047447e+000,
+ -1.977560e-001,
+ 2.183364e+000,
+ -8.805249e+000,
+ -5.483962e+000,
+ 2.551309e+000,
+ -1.779640e-001,
+ 1.519501e+000,
+ 9.212536e-001,
+ -1.111853e+000,
+ -1.935736e-001,
+ 1.394408e+000,
+ 1.392405e+001,
+ -3.465430e+000,
+ -1.068432e+000,
+ 2.388671e-001,
+ 1.455336e+000,
+ 6.233425e-001,
+ // albedo 1, turbidity 6
+ -1.262238e+000,
+ -3.546341e-001,
+ -1.008703e+001,
+ 1.020084e+001,
+ -1.852187e-003,
+ 3.537580e-001,
+ 1.239199e-001,
+ 3.056093e+000,
+ 5.132052e-001,
+ -1.613810e+000,
+ -7.355585e-001,
+ 2.760123e+000,
+ -1.685253e+000,
+ -2.517552e-002,
+ 2.914258e-001,
+ 4.743448e-003,
+ 8.689596e-001,
+ 5.674192e-001,
+ -9.462336e-001,
+ 2.950767e-002,
+ -2.613816e-001,
+ -7.398653e-001,
+ -1.315558e-001,
+ 1.901042e+000,
+ -6.447844e-002,
+ 4.969341e+000,
+ 1.027342e+000,
+ -1.111481e+000,
+ -2.194054e-001,
+ -9.004538e-002,
+ 3.983442e+000,
+ 4.871278e-001,
+ -1.965315e+000,
+ 7.956121e-001,
+ -2.363225e-001,
+ 2.718037e-001,
+ -1.036397e+000,
+ -1.827106e-001,
+ 1.964747e+000,
+ -8.870759e+000,
+ -4.208011e+000,
+ 2.461215e+000,
+ -2.158905e-001,
+ 1.561676e+000,
+ 9.436866e-001,
+ -1.113769e+000,
+ -1.947819e-001,
+ 1.300720e+000,
+ 1.516476e+001,
+ -4.088732e+000,
+ -1.069384e+000,
+ 2.836434e-001,
+ 1.671451e+000,
+ 6.229612e-001,
+ // albedo 1, turbidity 7
+ -1.328069e+000,
+ -4.244047e-001,
+ -8.417040e+000,
+ 8.552244e+000,
+ -6.813504e-003,
+ 4.127422e-001,
+ 9.619897e-002,
+ 2.854227e+000,
+ 5.059880e-001,
+ -1.927552e+000,
+ -1.025290e+000,
+ 9.529576e-001,
+ 4.255950e-001,
+ -3.738779e-002,
+ 2.584586e-001,
+ 4.911004e-002,
+ -2.640913e-001,
+ 4.138626e-001,
+ -8.488094e-001,
+ 1.435988e-001,
+ 6.356807e-001,
+ -2.895732e+000,
+ -8.473961e-002,
+ 1.701305e+000,
+ -1.323908e-001,
+ 6.499338e+000,
+ 1.210928e+000,
+ -1.128313e+000,
+ -3.397048e-001,
+ -4.043140e-001,
+ 6.265097e+000,
+ 5.482395e-001,
+ -2.057614e+000,
+ 8.884087e-001,
+ -2.943879e+000,
+ 9.760301e-002,
+ -1.039764e+000,
+ -1.494772e-001,
+ 1.781915e+000,
+ -1.153012e+001,
+ -3.379232e+000,
+ 2.517231e+000,
+ -2.764393e-001,
+ 2.588849e+000,
+ 1.052120e+000,
+ -1.108447e+000,
+ -2.012251e-001,
+ 1.198640e+000,
+ 1.925331e+001,
+ -4.423892e+000,
+ -1.257122e+000,
+ 3.395690e-001,
+ 1.481220e+000,
+ 5.880175e-001,
+ // albedo 1, turbidity 8
+ -1.374185e+000,
+ -4.967434e-001,
+ -7.401318e+000,
+ 7.724021e+000,
+ -2.345723e-002,
+ 5.979653e-001,
+ 2.436346e-002,
+ 2.658970e+000,
+ 6.014891e-001,
+ -2.310933e+000,
+ -1.290290e+000,
+ -1.301909e+000,
+ 2.557806e+000,
+ -3.744449e-002,
+ 8.982861e-002,
+ 1.090613e-001,
+ -4.398363e-001,
+ 1.184329e-001,
+ -1.124730e+000,
+ -9.921830e-002,
+ 1.366902e+000,
+ -4.172489e+000,
+ -5.078016e-002,
+ 1.393597e+000,
+ -9.323843e-002,
+ 6.452721e+000,
+ 1.435913e+000,
+ -8.468477e-001,
+ -2.744819e-001,
+ -4.347200e-001,
+ 6.713362e+000,
+ 6.127133e-001,
+ -1.685634e+000,
+ 7.360941e-001,
+ -4.535502e+000,
+ -2.920866e-002,
+ -1.165242e+000,
+ -2.008697e-001,
+ 1.438778e+000,
+ -1.008936e+001,
+ -2.214771e+000,
+ 2.102909e+000,
+ -1.763085e-001,
+ 2.859075e+000,
+ 1.093470e+000,
+ -1.074614e+000,
+ -2.066374e-001,
+ 1.131891e+000,
+ 1.630063e+001,
+ -4.801441e+000,
+ -1.112590e+000,
+ 3.595785e-001,
+ 1.122227e+000,
+ 5.794610e-001,
+ // albedo 1, turbidity 9
+ -1.521515e+000,
+ -6.835604e-001,
+ -5.571044e+000,
+ 6.028774e+000,
+ -4.253715e-002,
+ 6.875746e-001,
+ -5.279456e-006,
+ 2.180150e+000,
+ 8.487705e-001,
+ -2.240415e+000,
+ -1.171166e+000,
+ -7.182771e+000,
+ 8.417068e+000,
+ -1.932866e-002,
+ 1.101887e-001,
+ -1.098862e-002,
+ 6.242195e-001,
+ -2.393875e-001,
+ -2.712354e+000,
+ -1.198830e+000,
+ 3.180200e+000,
+ -6.768130e+000,
+ -2.563386e-003,
+ 7.984607e-001,
+ 2.764376e-001,
+ 4.695358e+000,
+ 1.557045e+000,
+ -3.655172e-002,
+ -2.142321e-002,
+ -9.138120e-001,
+ 7.932786e+000,
+ 3.516542e-001,
+ -7.994343e-001,
+ 1.786761e-001,
+ -4.208399e+000,
+ 1.820576e-002,
+ -1.368610e+000,
+ -2.656212e-001,
+ 1.249397e+000,
+ -8.317818e+000,
+ -8.962772e-001,
+ 1.423249e+000,
+ 1.478381e-001,
+ 2.191660e+000,
+ 1.007748e+000,
+ -1.041753e+000,
+ -2.453366e-001,
+ 1.061102e+000,
+ 1.130172e+001,
+ -4.739312e+000,
+ -9.223334e-001,
+ 2.982776e-001,
+ 6.162931e-001,
+ 6.080302e-001,
+ // albedo 1, turbidity 10
+ -1.989159e+000,
+ -1.095160e+000,
+ -2.915550e+000,
+ 3.275339e+000,
+ -5.735765e-002,
+ 5.742174e-001,
+ -7.683288e-006,
+ 1.763400e+000,
+ 9.001342e-001,
+ -2.070020e+000,
+ -1.086338e+000,
+ -1.095898e+001,
+ 1.206960e+001,
+ 3.780123e-002,
+ -1.774699e-002,
+ -5.881348e-004,
+ 1.333819e+000,
+ -2.605423e-001,
+ -5.249653e+000,
+ -2.383040e+000,
+ 6.160406e+000,
+ -9.097138e+000,
+ -1.955319e-001,
+ 1.651785e+000,
+ 6.016463e-004,
+ 3.021824e+000,
+ 1.493574e+000,
+ 4.685432e-001,
+ -2.358662e-001,
+ -2.666433e+000,
+ 9.685763e+000,
+ 5.804928e-001,
+ -1.521875e+000,
+ 5.668989e-001,
+ -1.548136e+000,
+ 1.688642e-002,
+ -1.296891e+000,
+ -3.449031e-001,
+ 1.928548e+000,
+ -1.167560e+001,
+ -1.627615e+000,
+ 1.355603e+000,
+ -1.929074e-001,
+ -6.568952e-001,
+ 1.009774e+000,
+ -1.067288e+000,
+ -2.410392e-001,
+ 7.147961e-001,
+ 1.783840e+001,
+ -4.374399e+000,
+ -6.588777e-001,
+ 3.329831e-001,
+ 1.012066e+000,
+ 6.118645e-001,
};
-static const double datasetXYZRad2[] =
-{
- // albedo 0, turbidity 1
- 1.632341e+000,
- 1.395230e+000,
- 1.375634e+000,
- 1.238193e+001,
- 5.921102e+000,
- 7.766508e+000,
- // albedo 0, turbidity 2
- 1.597115e+000,
- 1.554617e+000,
- 3.932382e-001,
- 1.505284e+001,
- 5.725234e+000,
- 8.158155e+000,
- // albedo 0, turbidity 3
- 1.522034e+000,
- 1.844545e+000,
- -1.322862e+000,
- 1.918382e+001,
- 5.440769e+000,
- 8.837119e+000,
- // albedo 0, turbidity 4
- 1.403048e+000,
- 2.290852e+000,
- -4.013792e+000,
- 2.485100e+001,
- 5.521888e+000,
- 9.845547e+000,
- // albedo 0, turbidity 5
- 1.286364e+000,
- 2.774498e+000,
- -6.648221e+000,
- 2.964151e+001,
- 5.923777e+000,
- 1.097075e+001,
- // albedo 0, turbidity 6
- 1.213544e+000,
- 3.040195e+000,
- -8.092676e+000,
- 3.186082e+001,
- 6.789782e+000,
- 1.158899e+001,
- // albedo 0, turbidity 7
- 1.122622e+000,
- 3.347465e+000,
- -9.649016e+000,
- 3.343824e+001,
- 9.347715e+000,
- 1.231374e+001,
- // albedo 0, turbidity 8
- 1.007356e+000,
- 3.543858e+000,
- -1.053520e+001,
- 3.239842e+001,
- 1.483962e+001,
- 1.331718e+001,
- // albedo 0, turbidity 9
- 8.956642e-001,
- 3.278700e+000,
- -9.254933e+000,
- 2.557923e+001,
- 2.489677e+001,
- 1.476166e+001,
- // albedo 0, turbidity 10
- 7.985143e-001,
- 2.340404e+000,
- -4.928274e+000,
- 1.141787e+001,
- 3.961501e+001,
- 1.682448e+001,
- // albedo 1, turbidity 1
- 1.745162e+000,
- 1.639467e+000,
- 1.342721e+000,
- 1.166033e+001,
- 1.490124e+001,
- 1.774031e+001,
- // albedo 1, turbidity 2
- 1.708439e+000,
- 1.819144e+000,
- 2.834399e-001,
- 1.448066e+001,
- 1.459214e+001,
- 1.858679e+001,
- // albedo 1, turbidity 3
- 1.631720e+000,
- 2.094799e+000,
- -1.378825e+000,
- 1.843198e+001,
- 1.463173e+001,
- 1.962881e+001,
- // albedo 1, turbidity 4
- 1.516536e+000,
- 2.438729e+000,
- -3.624121e+000,
- 2.298621e+001,
- 1.599782e+001,
- 2.070027e+001,
- // albedo 1, turbidity 5
- 1.405863e+000,
- 2.785191e+000,
- -5.705236e+000,
- 2.645121e+001,
- 1.768330e+001,
- 2.191903e+001,
- // albedo 1, turbidity 6
- 1.344052e+000,
- 2.951807e+000,
- -6.683851e+000,
- 2.744271e+001,
- 1.985706e+001,
- 2.229452e+001,
- // albedo 1, turbidity 7
- 1.245827e+000,
- 3.182923e+000,
- -7.822960e+000,
- 2.791395e+001,
- 2.327254e+001,
- 2.315910e+001,
- // albedo 1, turbidity 8
- 1.132305e+000,
- 3.202593e+000,
- -8.008429e+000,
- 2.521093e+001,
- 3.000014e+001,
- 2.405306e+001,
- // albedo 1, turbidity 9
- 1.020330e+000,
- 2.820556e+000,
- -6.238704e+000,
- 1.709276e+001,
- 4.077916e+001,
- 2.509949e+001,
- // albedo 1, turbidity 10
- 9.031570e-001,
- 1.863917e+000,
- -1.955738e+000,
- 3.032665e+000,
- 5.434290e+001,
- 2.641780e+001,
+static const double datasetXYZRad2[] = {
+ // albedo 0, turbidity 1
+ 1.632341e+000,
+ 1.395230e+000,
+ 1.375634e+000,
+ 1.238193e+001,
+ 5.921102e+000,
+ 7.766508e+000,
+ // albedo 0, turbidity 2
+ 1.597115e+000,
+ 1.554617e+000,
+ 3.932382e-001,
+ 1.505284e+001,
+ 5.725234e+000,
+ 8.158155e+000,
+ // albedo 0, turbidity 3
+ 1.522034e+000,
+ 1.844545e+000,
+ -1.322862e+000,
+ 1.918382e+001,
+ 5.440769e+000,
+ 8.837119e+000,
+ // albedo 0, turbidity 4
+ 1.403048e+000,
+ 2.290852e+000,
+ -4.013792e+000,
+ 2.485100e+001,
+ 5.521888e+000,
+ 9.845547e+000,
+ // albedo 0, turbidity 5
+ 1.286364e+000,
+ 2.774498e+000,
+ -6.648221e+000,
+ 2.964151e+001,
+ 5.923777e+000,
+ 1.097075e+001,
+ // albedo 0, turbidity 6
+ 1.213544e+000,
+ 3.040195e+000,
+ -8.092676e+000,
+ 3.186082e+001,
+ 6.789782e+000,
+ 1.158899e+001,
+ // albedo 0, turbidity 7
+ 1.122622e+000,
+ 3.347465e+000,
+ -9.649016e+000,
+ 3.343824e+001,
+ 9.347715e+000,
+ 1.231374e+001,
+ // albedo 0, turbidity 8
+ 1.007356e+000,
+ 3.543858e+000,
+ -1.053520e+001,
+ 3.239842e+001,
+ 1.483962e+001,
+ 1.331718e+001,
+ // albedo 0, turbidity 9
+ 8.956642e-001,
+ 3.278700e+000,
+ -9.254933e+000,
+ 2.557923e+001,
+ 2.489677e+001,
+ 1.476166e+001,
+ // albedo 0, turbidity 10
+ 7.985143e-001,
+ 2.340404e+000,
+ -4.928274e+000,
+ 1.141787e+001,
+ 3.961501e+001,
+ 1.682448e+001,
+ // albedo 1, turbidity 1
+ 1.745162e+000,
+ 1.639467e+000,
+ 1.342721e+000,
+ 1.166033e+001,
+ 1.490124e+001,
+ 1.774031e+001,
+ // albedo 1, turbidity 2
+ 1.708439e+000,
+ 1.819144e+000,
+ 2.834399e-001,
+ 1.448066e+001,
+ 1.459214e+001,
+ 1.858679e+001,
+ // albedo 1, turbidity 3
+ 1.631720e+000,
+ 2.094799e+000,
+ -1.378825e+000,
+ 1.843198e+001,
+ 1.463173e+001,
+ 1.962881e+001,
+ // albedo 1, turbidity 4
+ 1.516536e+000,
+ 2.438729e+000,
+ -3.624121e+000,
+ 2.298621e+001,
+ 1.599782e+001,
+ 2.070027e+001,
+ // albedo 1, turbidity 5
+ 1.405863e+000,
+ 2.785191e+000,
+ -5.705236e+000,
+ 2.645121e+001,
+ 1.768330e+001,
+ 2.191903e+001,
+ // albedo 1, turbidity 6
+ 1.344052e+000,
+ 2.951807e+000,
+ -6.683851e+000,
+ 2.744271e+001,
+ 1.985706e+001,
+ 2.229452e+001,
+ // albedo 1, turbidity 7
+ 1.245827e+000,
+ 3.182923e+000,
+ -7.822960e+000,
+ 2.791395e+001,
+ 2.327254e+001,
+ 2.315910e+001,
+ // albedo 1, turbidity 8
+ 1.132305e+000,
+ 3.202593e+000,
+ -8.008429e+000,
+ 2.521093e+001,
+ 3.000014e+001,
+ 2.405306e+001,
+ // albedo 1, turbidity 9
+ 1.020330e+000,
+ 2.820556e+000,
+ -6.238704e+000,
+ 1.709276e+001,
+ 4.077916e+001,
+ 2.509949e+001,
+ // albedo 1, turbidity 10
+ 9.031570e-001,
+ 1.863917e+000,
+ -1.955738e+000,
+ 3.032665e+000,
+ 5.434290e+001,
+ 2.641780e+001,
};
-static const double datasetXYZ3[] =
-{
- // albedo 0, turbidity 1
- -1.310023e+000,
- -4.407658e-001,
- -3.640340e+001,
- 3.683292e+001,
- -8.124762e-003,
- 5.297961e-001,
- 1.188633e-002,
- 3.138320e+000,
- 5.134778e-001,
- -1.424100e+000,
- -5.501606e-001,
- -1.753510e+001,
- 1.822769e+001,
- -1.539272e-002,
- 6.366826e-001,
- 2.661996e-003,
- 2.659915e+000,
- 4.071138e-001,
- -1.103436e+000,
- -1.884105e-001,
- 6.425322e+000,
- -6.910579e+000,
- -2.019861e-002,
- 3.553271e-001,
- -1.589061e-002,
- 5.345985e+000,
- 8.790218e-001,
- -1.186200e+000,
- -4.307514e-001,
- -3.957947e+000,
- 5.979352e+000,
- -5.348869e-002,
- 1.736117e+000,
- 3.491346e-002,
- -2.692261e+000,
- 5.610506e-001,
- -1.006038e+000,
- -1.305995e-001,
- 4.473513e+000,
- -3.806719e+000,
- 1.419407e-001,
- -2.148238e-002,
- -5.081185e-002,
- 3.735362e+000,
- 5.358280e-001,
- -1.078507e+000,
- -1.633754e-001,
- -3.812368e+000,
- 4.381700e+000,
- 2.988122e-002,
- 1.754224e+000,
- 1.472376e-001,
- 3.722798e+000,
- 4.999157e-001,
- // albedo 0, turbidity 2
- -1.333582e+000,
- -4.649908e-001,
- -3.359528e+001,
- 3.404375e+001,
- -9.384242e-003,
- 5.587511e-001,
- 5.726310e-003,
- 3.073145e+000,
- 5.425529e-001,
- -1.562624e+000,
- -7.107068e-001,
- -1.478170e+001,
- 1.559839e+001,
- -1.462375e-002,
- 5.050133e-001,
- 2.516017e-002,
- 1.604696e+000,
- 2.902403e-001,
- -8.930158e-001,
- 4.068077e-002,
- 1.373481e+000,
- -2.342752e+000,
- -2.098058e-002,
- 6.248686e-001,
- -5.258363e-002,
- 7.058214e+000,
- 1.150373e+000,
- -1.262823e+000,
- -4.818353e-001,
- 8.892610e-004,
- 1.923120e+000,
- -4.979718e-002,
- 1.040693e+000,
- 1.558103e-001,
- -2.852480e+000,
- 2.420691e-001,
- -9.968383e-001,
- -1.200648e-001,
- 1.324342e+000,
- -9.430889e-001,
- 1.931098e-001,
- 4.436916e-001,
- -7.320456e-002,
- 4.215931e+000,
- 7.898019e-001,
- -1.078185e+000,
- -1.718192e-001,
- -1.720191e+000,
- 2.358918e+000,
- 2.765637e-002,
- 1.260245e+000,
- 2.021941e-001,
- 3.395483e+000,
- 5.173628e-001,
- // albedo 0, turbidity 3
- -1.353023e+000,
- -4.813523e-001,
- -3.104920e+001,
- 3.140156e+001,
- -9.510741e-003,
- 5.542030e-001,
- 8.135471e-003,
- 3.136646e+000,
- 5.215989e-001,
- -1.624704e+000,
- -7.990201e-001,
- -2.167125e+001,
- 2.246341e+001,
- -1.163533e-002,
- 5.415746e-001,
- 2.618378e-002,
- 1.139214e+000,
- 3.444357e-001,
- -7.983610e-001,
- 1.417476e-001,
- 9.914841e+000,
- -1.081503e+001,
- -1.218845e-002,
- 3.411392e-001,
- -6.137698e-002,
- 7.445848e+000,
- 1.180080e+000,
- -1.266679e+000,
- -4.288977e-001,
- -5.818701e+000,
- 6.986437e+000,
- -8.180711e-002,
- 1.397403e+000,
- 2.016916e-001,
- -1.275731e+000,
- 2.592773e-001,
- -1.009707e+000,
- -1.537754e-001,
- 3.496378e+000,
- -3.013726e+000,
- 2.421150e-001,
- -2.831925e-001,
- 3.003395e-002,
- 3.702862e+000,
- 7.746320e-001,
- -1.075646e+000,
- -1.768747e-001,
- -1.347762e+000,
- 1.989004e+000,
- 1.375836e-002,
- 1.764810e+000,
- 1.330018e-001,
- 3.230864e+000,
- 6.626210e-001,
- // albedo 0, turbidity 4
- -1.375269e+000,
- -5.103569e-001,
- -3.442661e+001,
- 3.478703e+001,
- -8.460009e-003,
- 5.408643e-001,
- 4.813323e-003,
- 3.016078e+000,
- 5.062069e-001,
- -1.821679e+000,
- -9.766461e-001,
- -1.926488e+001,
- 1.997912e+001,
- -9.822567e-003,
- 3.649556e-001,
- 4.316092e-002,
- 8.930190e-001,
- 4.166527e-001,
- -6.633542e-001,
- 1.997841e-001,
- 2.395592e+000,
- -3.117175e+000,
- -1.080884e-002,
- 8.983814e-001,
- -1.375825e-001,
- 6.673463e+000,
- 1.115663e+000,
- -1.303240e+000,
- -3.612712e-001,
- 8.292959e-002,
- 3.381364e-001,
- -6.078648e-002,
- 3.229247e-001,
- 3.680987e-001,
- 7.046755e-001,
- 3.144924e-001,
- -9.952598e-001,
- -2.039076e-001,
- 4.026851e-001,
- 2.686684e-001,
- 1.640712e-001,
- 5.186341e-001,
- -1.205520e-002,
- 2.659613e+000,
- 8.030394e-001,
- -1.098579e+000,
- -2.151992e-001,
- 6.558198e-001,
- -7.436900e-004,
- -1.421817e-003,
- 1.073701e+000,
- 1.886875e-001,
- 2.536857e+000,
- 6.673923e-001,
- // albedo 0, turbidity 5
- -1.457986e+000,
- -5.906842e-001,
- -3.812464e+001,
- 3.838539e+001,
- -6.024357e-003,
- 4.741484e-001,
- 1.209223e-002,
- 2.818432e+000,
- 5.012433e-001,
- -1.835728e+000,
- -1.003405e+000,
- -6.848129e+000,
- 7.601943e+000,
- -1.277375e-002,
- 4.785598e-001,
- 3.366853e-002,
- 1.097701e+000,
- 4.636635e-001,
- -8.491348e-001,
- 9.466365e-003,
- -2.685226e+000,
- 2.004060e+000,
- -1.168708e-002,
- 6.752316e-001,
- -1.543371e-001,
- 5.674759e+000,
- 1.039534e+000,
- -1.083379e+000,
- -1.506790e-001,
- 7.328236e-001,
- -5.095568e-001,
- -8.609153e-002,
- 4.448820e-001,
- 4.174662e-001,
- 1.481556e+000,
- 3.942551e-001,
- -1.117089e+000,
- -3.337605e-001,
- 2.502281e-001,
- 4.036323e-001,
- 2.673899e-001,
- 2.829817e-001,
- 2.242450e-002,
- 2.043207e+000,
- 7.706902e-001,
- -1.071648e+000,
- -2.126200e-001,
- 6.069466e-001,
- -1.456290e-003,
- -5.515960e-001,
- 1.046755e+000,
- 1.985021e-001,
- 2.290245e+000,
- 6.876058e-001,
- // albedo 0, turbidity 6
- -1.483903e+000,
- -6.309647e-001,
- -4.380213e+001,
- 4.410537e+001,
- -5.712161e-003,
- 5.195992e-001,
- 2.028428e-003,
- 2.687114e+000,
- 5.098321e-001,
- -2.053976e+000,
- -1.141473e+000,
- 5.109183e-001,
- 8.060391e-002,
- -1.033983e-002,
- 4.066532e-001,
- 4.869627e-002,
- 1.161722e+000,
- 4.039525e-001,
- -6.348185e-001,
- 7.651292e-002,
- -1.031327e+001,
- 1.007598e+001,
- -2.083688e-002,
- 7.359516e-001,
- -2.029459e-001,
- 5.013257e+000,
- 1.077649e+000,
- -1.228630e+000,
- -1.650496e-001,
- 4.077157e-002,
- -7.189167e-001,
- -5.092220e-002,
- 2.959814e-001,
- 5.111496e-001,
- 2.540433e+000,
- 3.615330e-001,
- -1.041883e+000,
- -3.278413e-001,
- -6.691911e-002,
- 1.307364e+000,
- 2.166663e-001,
- 3.000595e-001,
- -3.157136e-003,
- 1.389208e+000,
- 7.999026e-001,
- -1.103556e+000,
- -2.443602e-001,
- 4.705347e-001,
- -9.296482e-004,
- -5.309920e-001,
- 9.654511e-001,
- 2.142587e-001,
- 2.244723e+000,
- 6.839976e-001,
- // albedo 0, turbidity 7
- -1.555684e+000,
- -6.962113e-001,
- -4.647983e+001,
- 4.674270e+001,
- -5.034895e-003,
- 4.755090e-001,
- -9.502561e-007,
- 2.626569e+000,
- 5.056194e-001,
- -1.998288e+000,
- -1.124720e+000,
- -1.629586e+000,
- 2.187993e+000,
- -8.284384e-003,
- 3.845258e-001,
- 5.726240e-002,
- 1.185644e+000,
- 4.255812e-001,
- -1.032570e+000,
- -2.513850e-001,
- -3.721112e+000,
- 3.506967e+000,
- -2.186561e-002,
- 9.436049e-001,
- -2.451412e-001,
- 4.725724e+000,
- 1.039256e+000,
- -8.597532e-001,
- 9.073332e-002,
- -2.553741e+000,
- 1.993237e+000,
- -4.390891e-002,
- -2.046928e-001,
- 5.515623e-001,
- 1.909127e+000,
- 3.948212e-001,
- -1.210482e+000,
- -4.477622e-001,
- -2.267805e-001,
- 1.219488e+000,
- 1.336186e-001,
- 6.866897e-001,
- 2.808997e-002,
- 1.600403e+000,
- 7.816409e-001,
- -1.078168e+000,
- -2.699261e-001,
- 2.537282e-001,
- 3.820684e-001,
- -4.425103e-001,
- 5.298235e-001,
- 2.185217e-001,
- 1.728679e+000,
- 6.882743e-001,
- // albedo 0, turbidity 8
- -1.697968e+000,
- -8.391488e-001,
- -5.790105e+001,
- 5.814120e+001,
- -3.404760e-003,
- 4.265140e-001,
- -1.796301e-006,
- 2.368442e+000,
- 5.324429e-001,
- -2.141552e+000,
- -1.172230e+000,
- 1.677872e+001,
- -1.641470e+001,
- -5.732425e-003,
- 2.002199e-001,
- 6.841834e-002,
- 1.485338e+000,
- 3.215763e-001,
- -1.442946e+000,
- -7.264245e-001,
- -9.503706e+000,
- 9.650462e+000,
- -2.120995e-002,
- 1.419263e+000,
- -2.893098e-001,
- 3.860731e+000,
- 1.120857e+000,
- -5.696752e-001,
- 3.411279e-001,
- -2.931035e-001,
- -6.512552e-001,
- -1.068437e-001,
- -1.085661e+000,
- 6.107549e-001,
- 1.459503e+000,
- 3.210336e-001,
- -1.313839e+000,
- -5.921371e-001,
- -2.332222e-001,
- 1.648196e+000,
- 2.492787e-001,
- 1.381033e+000,
- -1.993392e-002,
- 9.812560e-001,
- 8.316329e-001,
- -1.087464e+000,
- -3.195534e-001,
- 2.902095e-001,
- 3.383709e-001,
- -8.798482e-001,
- 1.494668e-002,
- 2.529703e-001,
- 1.452644e+000,
- 6.693870e-001,
- // albedo 0, turbidity 9
- -2.068582e+000,
- -1.118605e+000,
- -5.081598e+001,
- 5.097486e+001,
- -3.280669e-003,
- 4.067371e-001,
- -2.544951e-006,
- 2.179497e+000,
- 5.778017e-001,
- -1.744693e+000,
- -8.537207e-001,
- 2.234361e+001,
- -2.208318e+001,
- -5.932616e-003,
- 1.035049e-001,
- 5.742772e-002,
- 1.977880e+000,
- 2.124846e-001,
- -3.287515e+000,
- -2.140268e+000,
- -1.249566e+001,
- 1.240091e+001,
- -2.409349e-002,
- 1.397821e+000,
- -2.371627e-001,
- 2.771192e+000,
- 1.170496e+000,
- 5.502311e-001,
- 1.046630e+000,
- 2.193517e+000,
- -2.220400e+000,
- -1.064394e-001,
- -1.017926e+000,
- 4.795457e-001,
- 1.030644e+000,
- 3.177516e-001,
- -1.719734e+000,
- -9.536198e-001,
- -6.586821e-001,
- 1.386361e+000,
- -2.513065e-002,
- 1.187011e+000,
- 6.542539e-002,
- 5.296055e-001,
- 8.082660e-001,
- -1.005700e+000,
- -3.028096e-001,
- 4.470957e-002,
- 1.007760e+000,
- -8.119016e-001,
- 3.153338e-002,
- 2.311321e-001,
- 1.182208e+000,
- 6.824758e-001,
- // albedo 0, turbidity 10
- -2.728867e+000,
- -1.580388e+000,
- -3.079627e+001,
- 3.092586e+001,
- -4.197673e-003,
- 3.154759e-001,
- -3.897675e-006,
- 1.920567e+000,
- 6.664791e-001,
- -1.322495e+000,
- -7.249275e-001,
- 1.477660e+001,
- -1.468154e+001,
- -9.044857e-003,
- 5.624314e-002,
- 6.498392e-002,
- 2.047389e+000,
- 6.367540e-002,
- -6.102376e+000,
- -3.473018e+000,
- -9.926071e+000,
- 9.637797e+000,
- -1.097909e-002,
- 1.103498e+000,
- -2.424521e-001,
- 2.520748e+000,
- 1.240260e+000,
- 1.351796e+000,
- 1.018588e+000,
- 2.009081e+000,
- -1.333394e+000,
- -1.979125e-001,
- -3.318292e-001,
- 4.476624e-001,
- 9.095235e-001,
- 2.955611e-001,
- -1.774467e+000,
- -1.079880e+000,
- -8.084680e-002,
- 2.577697e-001,
- -1.149295e-001,
- 4.975303e-001,
- 2.931611e-003,
- -3.803171e-001,
- 8.002794e-001,
- -9.898401e-001,
- -2.542513e-001,
- -7.530911e-002,
- 1.870355e+000,
- -1.521918e+000,
- 2.405164e-001,
- 2.964615e-001,
- 1.334800e+000,
- 6.789053e-001,
- // albedo 1, turbidity 1
- -1.279730e+000,
- -4.290674e-001,
- -4.277972e+001,
- 4.343305e+001,
- -6.541826e-003,
- 4.945086e-001,
- 1.425338e-002,
- 2.685244e+000,
- 5.011313e-001,
- -1.449506e+000,
- -5.766374e-001,
- -1.688496e+001,
- 1.781118e+001,
- -1.121649e-002,
- 3.545020e-001,
- 2.287338e-002,
- 1.904281e+000,
- 4.936998e-001,
- -1.021980e+000,
- -1.897574e-001,
- 2.482462e+000,
- -2.941725e+000,
- -1.570448e-002,
- 7.532578e-001,
- -4.256800e-002,
- 5.239660e+000,
- 4.983116e-001,
- -1.162608e+000,
- -3.428049e-001,
- 3.974358e+000,
- -1.527935e+000,
- -3.919201e-002,
- 8.758593e-001,
- 7.291363e-002,
- -3.455257e+000,
- 8.007426e-001,
- -9.929985e-001,
- -8.712006e-002,
- -7.397313e-001,
- 1.348372e+000,
- 9.511685e-002,
- 3.233584e-001,
- -7.549148e-002,
- 5.806452e+000,
- 4.990042e-001,
- -1.084996e+000,
- -1.739767e-001,
- 1.580475e-001,
- 9.088180e-001,
- 6.871433e-002,
- 5.933079e-001,
- 1.188921e-001,
- 3.074079e+000,
- 4.999327e-001,
- // albedo 1, turbidity 2
- -1.317009e+000,
- -4.661946e-001,
- -4.255347e+001,
- 4.312782e+001,
- -5.727235e-003,
- 4.285447e-001,
- 2.189854e-002,
- 2.608310e+000,
- 5.190700e-001,
- -1.469236e+000,
- -6.282139e-001,
- -1.241404e+001,
- 1.348765e+001,
- -1.204770e-002,
- 5.070285e-001,
- -7.280216e-004,
- 1.491533e+000,
- 3.635064e-001,
- -9.713808e-001,
- -8.138038e-002,
- 3.709854e-001,
- -1.041174e+000,
- -1.814075e-002,
- 5.060860e-001,
- -2.053756e-002,
- 6.161431e+000,
- 1.093736e+000,
- -1.159057e+000,
- -3.698074e-001,
- 2.711209e+000,
- -6.006479e-001,
- -4.896926e-002,
- 9.273957e-001,
- 1.137712e-001,
- -3.496828e+000,
- 2.867109e-001,
- -1.011601e+000,
- -8.201890e-002,
- 2.105725e-001,
- 4.597520e-001,
- 1.478925e-001,
- 2.138940e-001,
- -5.660670e-002,
- 6.057755e+000,
- 7.859121e-001,
- -1.078020e+000,
- -1.811580e-001,
- 1.646622e-001,
- 8.348426e-001,
- 1.149064e-001,
- 4.985738e-001,
- 1.376605e-001,
- 2.746607e+000,
- 4.999626e-001,
- // albedo 1, turbidity 3
- -1.325672e+000,
- -4.769313e-001,
- -4.111215e+001,
- 4.168293e+001,
- -6.274997e-003,
- 4.649469e-001,
- 1.119411e-002,
- 2.631267e+000,
- 5.234546e-001,
- -1.619391e+000,
- -8.000253e-001,
- -1.534098e+001,
- 1.632706e+001,
- -1.012023e-002,
- 4.242255e-001,
- 2.931597e-002,
- 8.925807e-001,
- 3.314765e-001,
- -7.356979e-001,
- 1.368406e-001,
- 2.972579e+000,
- -3.535359e+000,
- -1.318948e-002,
- 4.607620e-001,
- -7.182778e-002,
- 6.254100e+000,
- 1.236299e+000,
- -1.316217e+000,
- -4.194427e-001,
- 3.489902e-002,
- 1.289849e+000,
- -4.755960e-002,
- 1.138222e+000,
- 1.975992e-001,
- -8.991542e-001,
- 2.290572e-001,
- -9.502188e-001,
- -1.172703e-001,
- 1.405202e+000,
- -3.061919e-001,
- 1.058772e-001,
- -3.760592e-001,
- -1.983179e-002,
- 3.562353e+000,
- 7.895959e-001,
- -1.100117e+000,
- -1.900567e-001,
- 4.925030e-001,
- 5.250225e-001,
- 1.576804e-001,
- 1.042701e+000,
- 7.330743e-002,
- 2.796064e+000,
- 6.749783e-001,
- // albedo 1, turbidity 4
- -1.354183e+000,
- -5.130625e-001,
- -4.219268e+001,
- 4.271772e+001,
- -5.365373e-003,
- 4.136743e-001,
- 1.235172e-002,
- 2.520122e+000,
- 5.187269e-001,
- -1.741434e+000,
- -9.589761e-001,
- -8.230339e+000,
- 9.296799e+000,
- -9.600162e-003,
- 4.994969e-001,
- 2.955452e-002,
- 3.667099e-001,
- 3.526999e-001,
- -6.917347e-001,
- 2.154887e-001,
- -8.760264e-001,
- 2.334121e-001,
- -1.909621e-002,
- 4.748033e-001,
- -1.138514e-001,
- 6.515360e+000,
- 1.225097e+000,
- -1.293189e+000,
- -4.218700e-001,
- 1.620952e+000,
- -7.858597e-001,
- -3.769410e-002,
- 6.636786e-001,
- 3.364945e-001,
- -5.341017e-001,
- 2.128347e-001,
- -9.735521e-001,
- -1.325495e-001,
- 1.007517e+000,
- 2.598258e-001,
- 6.762169e-002,
- 1.421018e-003,
- -6.915987e-002,
- 3.185897e+000,
- 8.641956e-001,
- -1.094800e+000,
- -1.962062e-001,
- 5.755591e-001,
- 2.906259e-001,
- 2.625748e-001,
- 7.644049e-001,
- 1.347492e-001,
- 2.677126e+000,
- 6.465460e-001,
- // albedo 1, turbidity 5
- -1.393063e+000,
- -5.578338e-001,
- -4.185249e+001,
- 4.233504e+001,
- -5.435640e-003,
- 4.743765e-001,
- 7.422477e-003,
- 2.442801e+000,
- 5.211707e-001,
- -1.939487e+000,
- -1.128509e+000,
- -8.974257e+000,
- 9.978383e+000,
- -7.965597e-003,
- 2.948830e-001,
- 4.436763e-002,
- 2.839868e-001,
- 3.440424e-001,
- -6.011562e-001,
- 2.354877e-001,
- -3.079820e+000,
- 2.585094e+000,
- -2.002701e-002,
- 7.793909e-001,
- -1.598414e-001,
- 5.834678e+000,
- 1.202856e+000,
- -1.315676e+000,
- -3.903446e-001,
- 1.701900e+000,
- -1.304609e+000,
- -1.045121e-002,
- 2.747707e-001,
- 4.143967e-001,
- 3.197102e-001,
- 2.637580e-001,
- -9.618628e-001,
- -1.625841e-001,
- 1.187138e+000,
- 1.497802e-001,
- -5.590954e-006,
- 3.178475e-002,
- -4.153145e-002,
- 2.496096e+000,
- 8.195082e-001,
- -1.111554e+000,
- -2.365546e-001,
- 7.831875e-001,
- 2.018684e-001,
- 2.074369e-001,
- 7.395978e-001,
- 1.225730e-001,
- 1.876478e+000,
- 6.821167e-001,
- // albedo 1, turbidity 6
- -1.427879e+000,
- -5.994879e-001,
- -3.531016e+001,
- 3.581581e+001,
- -6.431497e-003,
- 4.554192e-001,
- 7.348731e-004,
- 2.334619e+000,
- 5.233377e-001,
- -1.998177e+000,
- -1.206633e+000,
- -2.146510e+001,
- 2.242237e+001,
- -5.857596e-003,
- 2.755663e-001,
- 6.384795e-002,
- 1.358244e-001,
- 3.328437e-001,
- -6.440630e-001,
- 2.058571e-001,
- 2.155499e+000,
- -2.587968e+000,
- -1.840023e-002,
- 8.826555e-001,
- -2.222452e-001,
- 5.847073e+000,
- 1.228387e+000,
- -1.229071e+000,
- -3.360441e-001,
- -3.429599e-001,
- 6.179469e-001,
- 2.029610e-003,
- 8.899319e-002,
- 5.041624e-001,
- 1.882964e-001,
- 2.252040e-001,
- -1.022905e+000,
- -2.101621e-001,
- 1.915689e+000,
- -6.498794e-001,
- -3.463651e-002,
- 8.954605e-002,
- -6.797854e-002,
- 2.417705e+000,
- 8.568618e-001,
- -1.082538e+000,
- -2.007723e-001,
- 4.731009e-001,
- 4.077267e-001,
- 1.324289e-001,
- 6.514880e-001,
- 1.702912e-001,
- 2.309383e+000,
- 6.600895e-001,
- // albedo 1, turbidity 7
- -1.472139e+000,
- -6.499815e-001,
- -3.428465e+001,
- 3.469659e+001,
- -5.747023e-003,
- 4.174167e-001,
- 1.688597e-003,
- 2.323046e+000,
- 5.395191e-001,
- -2.161176e+000,
- -1.353089e+000,
- -2.226827e+001,
- 2.329138e+001,
- -5.583808e-003,
- 2.364793e-001,
- 6.096656e-002,
- 1.944666e-003,
- 2.861624e-001,
- -6.593044e-001,
- 1.393558e-001,
- 4.698373e+000,
- -5.193883e+000,
- -1.998390e-002,
- 1.095635e+000,
- -2.391254e-001,
- 5.598103e+000,
- 1.236193e+000,
- -1.195717e+000,
- -2.972715e-001,
- 4.648953e-002,
- 3.024588e-001,
- 5.003313e-003,
- -3.754741e-001,
- 5.247265e-001,
- -1.381312e-001,
- 2.493896e-001,
- -1.020139e+000,
- -2.253524e-001,
- 3.548437e-001,
- 7.030485e-001,
- -2.107076e-002,
- 4.581395e-001,
- -3.243757e-002,
- 2.453259e+000,
- 8.323623e-001,
- -1.098770e+000,
- -2.435780e-001,
- 8.761614e-001,
- 1.941613e-001,
- -1.990692e-001,
- 3.761139e-001,
- 1.657412e-001,
- 1.590503e+000,
- 6.741417e-001,
- // albedo 1, turbidity 8
- -1.648007e+000,
- -8.205121e-001,
- -4.435106e+001,
- 4.479801e+001,
- -4.181353e-003,
- 3.854830e-001,
- -1.842385e-006,
- 2.000281e+000,
- 5.518363e-001,
- -2.140986e+000,
- -1.282239e+000,
- -3.979213e+000,
- 4.672459e+000,
- -5.008582e-003,
- 2.421920e-001,
- 6.253602e-002,
- 6.612713e-001,
- 2.555851e-001,
- -1.300502e+000,
- -5.137898e-001,
- 5.179821e-001,
- -4.032341e-001,
- -2.066785e-002,
- 1.087929e+000,
- -2.615309e-001,
- 4.225887e+000,
- 1.229237e+000,
- -6.963340e-001,
- 9.241060e-002,
- 6.936356e-002,
- -3.588571e-001,
- -5.461843e-002,
- -5.616643e-001,
- 5.484166e-001,
- -4.776267e-002,
- 2.414935e-001,
- -1.233179e+000,
- -4.325498e-001,
- 6.479813e-001,
- 8.368356e-001,
- 2.458875e-001,
- 6.464752e-001,
- -2.897097e-002,
- 1.561773e+000,
- 8.518598e-001,
- -1.051023e+000,
- -2.533690e-001,
- 1.004294e+000,
- 3.028083e-001,
- -1.520108e+000,
- 1.607013e-001,
- 1.619975e-001,
- 1.131094e+000,
- 6.706655e-001,
- // albedo 1, turbidity 9
- -1.948249e+000,
- -1.097383e+000,
- -4.453697e+001,
- 4.494902e+001,
- -3.579939e-003,
- 3.491605e-001,
- -2.500253e-006,
- 1.740442e+000,
- 6.188022e-001,
- -2.154253e+000,
- -1.209559e+000,
- 4.144894e+000,
- -3.562411e+000,
- -5.638843e-003,
- 1.067169e-001,
- 7.594858e-002,
- 1.005280e+000,
- 1.072543e-001,
- -2.513259e+000,
- -1.507208e+000,
- -1.602979e+000,
- 1.404154e+000,
- -5.560750e-003,
- 1.240490e+000,
- -2.852117e-001,
- 3.485252e+000,
- 1.349321e+000,
- -7.832214e-002,
- 3.655626e-001,
- 3.856288e-001,
- 6.867894e-001,
- -1.609523e-001,
- -6.704306e-001,
- 5.357301e-001,
- -6.457935e-001,
- 1.479503e-001,
- -1.354784e+000,
- -5.454375e-001,
- 8.797469e-001,
- -1.466514e+000,
- 7.134420e-001,
- 5.934903e-001,
- -2.911178e-002,
- 8.643737e-001,
- 9.030724e-001,
- -1.048324e+000,
- -2.738736e-001,
- 8.783074e-001,
- 3.246188e+000,
- -4.435369e+000,
- 1.251791e-001,
- 1.783486e-001,
- 1.064657e+000,
- 6.522878e-001,
- // albedo 1, turbidity 10
- -2.770408e+000,
- -1.618911e+000,
- -2.504031e+001,
- 2.531674e+001,
- -4.239279e-003,
- 3.241013e-001,
- -3.764484e-006,
- 1.586843e+000,
- 7.035906e-001,
- -1.913500e+000,
- -1.144014e+000,
- -1.080587e+001,
- 1.153677e+001,
- -1.003197e-002,
- 1.577515e-001,
- 5.217789e-002,
- 1.225278e+000,
- 5.172771e-003,
- -5.293208e+000,
- -2.876463e+000,
- 2.087053e+000,
- -3.201552e+000,
- 3.892964e-003,
- 5.323930e-001,
- -2.034512e-001,
- 2.617760e+000,
- 1.273597e+000,
- 9.060340e-001,
- 3.773409e-001,
- -6.399945e-001,
- 3.213979e+000,
- -9.112172e-002,
- 6.494055e-001,
- 3.953280e-001,
- 5.047796e-001,
- 2.998695e-001,
- -1.482179e+000,
- -6.778310e-001,
- 1.161775e+000,
- -3.004872e+000,
- 4.774797e-001,
- -4.969248e-001,
- -3.512074e-003,
- -1.307190e+000,
- 7.927378e-001,
- -9.863181e-001,
- -1.803364e-001,
- 5.810824e-001,
- 4.580570e+000,
- -3.863454e+000,
- 5.328174e-001,
- 2.272821e-001,
- 1.771114e+000,
- 6.791814e-001,
+static const double datasetXYZ3[] = {
+ // albedo 0, turbidity 1
+ -1.310023e+000,
+ -4.407658e-001,
+ -3.640340e+001,
+ 3.683292e+001,
+ -8.124762e-003,
+ 5.297961e-001,
+ 1.188633e-002,
+ 3.138320e+000,
+ 5.134778e-001,
+ -1.424100e+000,
+ -5.501606e-001,
+ -1.753510e+001,
+ 1.822769e+001,
+ -1.539272e-002,
+ 6.366826e-001,
+ 2.661996e-003,
+ 2.659915e+000,
+ 4.071138e-001,
+ -1.103436e+000,
+ -1.884105e-001,
+ 6.425322e+000,
+ -6.910579e+000,
+ -2.019861e-002,
+ 3.553271e-001,
+ -1.589061e-002,
+ 5.345985e+000,
+ 8.790218e-001,
+ -1.186200e+000,
+ -4.307514e-001,
+ -3.957947e+000,
+ 5.979352e+000,
+ -5.348869e-002,
+ 1.736117e+000,
+ 3.491346e-002,
+ -2.692261e+000,
+ 5.610506e-001,
+ -1.006038e+000,
+ -1.305995e-001,
+ 4.473513e+000,
+ -3.806719e+000,
+ 1.419407e-001,
+ -2.148238e-002,
+ -5.081185e-002,
+ 3.735362e+000,
+ 5.358280e-001,
+ -1.078507e+000,
+ -1.633754e-001,
+ -3.812368e+000,
+ 4.381700e+000,
+ 2.988122e-002,
+ 1.754224e+000,
+ 1.472376e-001,
+ 3.722798e+000,
+ 4.999157e-001,
+ // albedo 0, turbidity 2
+ -1.333582e+000,
+ -4.649908e-001,
+ -3.359528e+001,
+ 3.404375e+001,
+ -9.384242e-003,
+ 5.587511e-001,
+ 5.726310e-003,
+ 3.073145e+000,
+ 5.425529e-001,
+ -1.562624e+000,
+ -7.107068e-001,
+ -1.478170e+001,
+ 1.559839e+001,
+ -1.462375e-002,
+ 5.050133e-001,
+ 2.516017e-002,
+ 1.604696e+000,
+ 2.902403e-001,
+ -8.930158e-001,
+ 4.068077e-002,
+ 1.373481e+000,
+ -2.342752e+000,
+ -2.098058e-002,
+ 6.248686e-001,
+ -5.258363e-002,
+ 7.058214e+000,
+ 1.150373e+000,
+ -1.262823e+000,
+ -4.818353e-001,
+ 8.892610e-004,
+ 1.923120e+000,
+ -4.979718e-002,
+ 1.040693e+000,
+ 1.558103e-001,
+ -2.852480e+000,
+ 2.420691e-001,
+ -9.968383e-001,
+ -1.200648e-001,
+ 1.324342e+000,
+ -9.430889e-001,
+ 1.931098e-001,
+ 4.436916e-001,
+ -7.320456e-002,
+ 4.215931e+000,
+ 7.898019e-001,
+ -1.078185e+000,
+ -1.718192e-001,
+ -1.720191e+000,
+ 2.358918e+000,
+ 2.765637e-002,
+ 1.260245e+000,
+ 2.021941e-001,
+ 3.395483e+000,
+ 5.173628e-001,
+ // albedo 0, turbidity 3
+ -1.353023e+000,
+ -4.813523e-001,
+ -3.104920e+001,
+ 3.140156e+001,
+ -9.510741e-003,
+ 5.542030e-001,
+ 8.135471e-003,
+ 3.136646e+000,
+ 5.215989e-001,
+ -1.624704e+000,
+ -7.990201e-001,
+ -2.167125e+001,
+ 2.246341e+001,
+ -1.163533e-002,
+ 5.415746e-001,
+ 2.618378e-002,
+ 1.139214e+000,
+ 3.444357e-001,
+ -7.983610e-001,
+ 1.417476e-001,
+ 9.914841e+000,
+ -1.081503e+001,
+ -1.218845e-002,
+ 3.411392e-001,
+ -6.137698e-002,
+ 7.445848e+000,
+ 1.180080e+000,
+ -1.266679e+000,
+ -4.288977e-001,
+ -5.818701e+000,
+ 6.986437e+000,
+ -8.180711e-002,
+ 1.397403e+000,
+ 2.016916e-001,
+ -1.275731e+000,
+ 2.592773e-001,
+ -1.009707e+000,
+ -1.537754e-001,
+ 3.496378e+000,
+ -3.013726e+000,
+ 2.421150e-001,
+ -2.831925e-001,
+ 3.003395e-002,
+ 3.702862e+000,
+ 7.746320e-001,
+ -1.075646e+000,
+ -1.768747e-001,
+ -1.347762e+000,
+ 1.989004e+000,
+ 1.375836e-002,
+ 1.764810e+000,
+ 1.330018e-001,
+ 3.230864e+000,
+ 6.626210e-001,
+ // albedo 0, turbidity 4
+ -1.375269e+000,
+ -5.103569e-001,
+ -3.442661e+001,
+ 3.478703e+001,
+ -8.460009e-003,
+ 5.408643e-001,
+ 4.813323e-003,
+ 3.016078e+000,
+ 5.062069e-001,
+ -1.821679e+000,
+ -9.766461e-001,
+ -1.926488e+001,
+ 1.997912e+001,
+ -9.822567e-003,
+ 3.649556e-001,
+ 4.316092e-002,
+ 8.930190e-001,
+ 4.166527e-001,
+ -6.633542e-001,
+ 1.997841e-001,
+ 2.395592e+000,
+ -3.117175e+000,
+ -1.080884e-002,
+ 8.983814e-001,
+ -1.375825e-001,
+ 6.673463e+000,
+ 1.115663e+000,
+ -1.303240e+000,
+ -3.612712e-001,
+ 8.292959e-002,
+ 3.381364e-001,
+ -6.078648e-002,
+ 3.229247e-001,
+ 3.680987e-001,
+ 7.046755e-001,
+ 3.144924e-001,
+ -9.952598e-001,
+ -2.039076e-001,
+ 4.026851e-001,
+ 2.686684e-001,
+ 1.640712e-001,
+ 5.186341e-001,
+ -1.205520e-002,
+ 2.659613e+000,
+ 8.030394e-001,
+ -1.098579e+000,
+ -2.151992e-001,
+ 6.558198e-001,
+ -7.436900e-004,
+ -1.421817e-003,
+ 1.073701e+000,
+ 1.886875e-001,
+ 2.536857e+000,
+ 6.673923e-001,
+ // albedo 0, turbidity 5
+ -1.457986e+000,
+ -5.906842e-001,
+ -3.812464e+001,
+ 3.838539e+001,
+ -6.024357e-003,
+ 4.741484e-001,
+ 1.209223e-002,
+ 2.818432e+000,
+ 5.012433e-001,
+ -1.835728e+000,
+ -1.003405e+000,
+ -6.848129e+000,
+ 7.601943e+000,
+ -1.277375e-002,
+ 4.785598e-001,
+ 3.366853e-002,
+ 1.097701e+000,
+ 4.636635e-001,
+ -8.491348e-001,
+ 9.466365e-003,
+ -2.685226e+000,
+ 2.004060e+000,
+ -1.168708e-002,
+ 6.752316e-001,
+ -1.543371e-001,
+ 5.674759e+000,
+ 1.039534e+000,
+ -1.083379e+000,
+ -1.506790e-001,
+ 7.328236e-001,
+ -5.095568e-001,
+ -8.609153e-002,
+ 4.448820e-001,
+ 4.174662e-001,
+ 1.481556e+000,
+ 3.942551e-001,
+ -1.117089e+000,
+ -3.337605e-001,
+ 2.502281e-001,
+ 4.036323e-001,
+ 2.673899e-001,
+ 2.829817e-001,
+ 2.242450e-002,
+ 2.043207e+000,
+ 7.706902e-001,
+ -1.071648e+000,
+ -2.126200e-001,
+ 6.069466e-001,
+ -1.456290e-003,
+ -5.515960e-001,
+ 1.046755e+000,
+ 1.985021e-001,
+ 2.290245e+000,
+ 6.876058e-001,
+ // albedo 0, turbidity 6
+ -1.483903e+000,
+ -6.309647e-001,
+ -4.380213e+001,
+ 4.410537e+001,
+ -5.712161e-003,
+ 5.195992e-001,
+ 2.028428e-003,
+ 2.687114e+000,
+ 5.098321e-001,
+ -2.053976e+000,
+ -1.141473e+000,
+ 5.109183e-001,
+ 8.060391e-002,
+ -1.033983e-002,
+ 4.066532e-001,
+ 4.869627e-002,
+ 1.161722e+000,
+ 4.039525e-001,
+ -6.348185e-001,
+ 7.651292e-002,
+ -1.031327e+001,
+ 1.007598e+001,
+ -2.083688e-002,
+ 7.359516e-001,
+ -2.029459e-001,
+ 5.013257e+000,
+ 1.077649e+000,
+ -1.228630e+000,
+ -1.650496e-001,
+ 4.077157e-002,
+ -7.189167e-001,
+ -5.092220e-002,
+ 2.959814e-001,
+ 5.111496e-001,
+ 2.540433e+000,
+ 3.615330e-001,
+ -1.041883e+000,
+ -3.278413e-001,
+ -6.691911e-002,
+ 1.307364e+000,
+ 2.166663e-001,
+ 3.000595e-001,
+ -3.157136e-003,
+ 1.389208e+000,
+ 7.999026e-001,
+ -1.103556e+000,
+ -2.443602e-001,
+ 4.705347e-001,
+ -9.296482e-004,
+ -5.309920e-001,
+ 9.654511e-001,
+ 2.142587e-001,
+ 2.244723e+000,
+ 6.839976e-001,
+ // albedo 0, turbidity 7
+ -1.555684e+000,
+ -6.962113e-001,
+ -4.647983e+001,
+ 4.674270e+001,
+ -5.034895e-003,
+ 4.755090e-001,
+ -9.502561e-007,
+ 2.626569e+000,
+ 5.056194e-001,
+ -1.998288e+000,
+ -1.124720e+000,
+ -1.629586e+000,
+ 2.187993e+000,
+ -8.284384e-003,
+ 3.845258e-001,
+ 5.726240e-002,
+ 1.185644e+000,
+ 4.255812e-001,
+ -1.032570e+000,
+ -2.513850e-001,
+ -3.721112e+000,
+ 3.506967e+000,
+ -2.186561e-002,
+ 9.436049e-001,
+ -2.451412e-001,
+ 4.725724e+000,
+ 1.039256e+000,
+ -8.597532e-001,
+ 9.073332e-002,
+ -2.553741e+000,
+ 1.993237e+000,
+ -4.390891e-002,
+ -2.046928e-001,
+ 5.515623e-001,
+ 1.909127e+000,
+ 3.948212e-001,
+ -1.210482e+000,
+ -4.477622e-001,
+ -2.267805e-001,
+ 1.219488e+000,
+ 1.336186e-001,
+ 6.866897e-001,
+ 2.808997e-002,
+ 1.600403e+000,
+ 7.816409e-001,
+ -1.078168e+000,
+ -2.699261e-001,
+ 2.537282e-001,
+ 3.820684e-001,
+ -4.425103e-001,
+ 5.298235e-001,
+ 2.185217e-001,
+ 1.728679e+000,
+ 6.882743e-001,
+ // albedo 0, turbidity 8
+ -1.697968e+000,
+ -8.391488e-001,
+ -5.790105e+001,
+ 5.814120e+001,
+ -3.404760e-003,
+ 4.265140e-001,
+ -1.796301e-006,
+ 2.368442e+000,
+ 5.324429e-001,
+ -2.141552e+000,
+ -1.172230e+000,
+ 1.677872e+001,
+ -1.641470e+001,
+ -5.732425e-003,
+ 2.002199e-001,
+ 6.841834e-002,
+ 1.485338e+000,
+ 3.215763e-001,
+ -1.442946e+000,
+ -7.264245e-001,
+ -9.503706e+000,
+ 9.650462e+000,
+ -2.120995e-002,
+ 1.419263e+000,
+ -2.893098e-001,
+ 3.860731e+000,
+ 1.120857e+000,
+ -5.696752e-001,
+ 3.411279e-001,
+ -2.931035e-001,
+ -6.512552e-001,
+ -1.068437e-001,
+ -1.085661e+000,
+ 6.107549e-001,
+ 1.459503e+000,
+ 3.210336e-001,
+ -1.313839e+000,
+ -5.921371e-001,
+ -2.332222e-001,
+ 1.648196e+000,
+ 2.492787e-001,
+ 1.381033e+000,
+ -1.993392e-002,
+ 9.812560e-001,
+ 8.316329e-001,
+ -1.087464e+000,
+ -3.195534e-001,
+ 2.902095e-001,
+ 3.383709e-001,
+ -8.798482e-001,
+ 1.494668e-002,
+ 2.529703e-001,
+ 1.452644e+000,
+ 6.693870e-001,
+ // albedo 0, turbidity 9
+ -2.068582e+000,
+ -1.118605e+000,
+ -5.081598e+001,
+ 5.097486e+001,
+ -3.280669e-003,
+ 4.067371e-001,
+ -2.544951e-006,
+ 2.179497e+000,
+ 5.778017e-001,
+ -1.744693e+000,
+ -8.537207e-001,
+ 2.234361e+001,
+ -2.208318e+001,
+ -5.932616e-003,
+ 1.035049e-001,
+ 5.742772e-002,
+ 1.977880e+000,
+ 2.124846e-001,
+ -3.287515e+000,
+ -2.140268e+000,
+ -1.249566e+001,
+ 1.240091e+001,
+ -2.409349e-002,
+ 1.397821e+000,
+ -2.371627e-001,
+ 2.771192e+000,
+ 1.170496e+000,
+ 5.502311e-001,
+ 1.046630e+000,
+ 2.193517e+000,
+ -2.220400e+000,
+ -1.064394e-001,
+ -1.017926e+000,
+ 4.795457e-001,
+ 1.030644e+000,
+ 3.177516e-001,
+ -1.719734e+000,
+ -9.536198e-001,
+ -6.586821e-001,
+ 1.386361e+000,
+ -2.513065e-002,
+ 1.187011e+000,
+ 6.542539e-002,
+ 5.296055e-001,
+ 8.082660e-001,
+ -1.005700e+000,
+ -3.028096e-001,
+ 4.470957e-002,
+ 1.007760e+000,
+ -8.119016e-001,
+ 3.153338e-002,
+ 2.311321e-001,
+ 1.182208e+000,
+ 6.824758e-001,
+ // albedo 0, turbidity 10
+ -2.728867e+000,
+ -1.580388e+000,
+ -3.079627e+001,
+ 3.092586e+001,
+ -4.197673e-003,
+ 3.154759e-001,
+ -3.897675e-006,
+ 1.920567e+000,
+ 6.664791e-001,
+ -1.322495e+000,
+ -7.249275e-001,
+ 1.477660e+001,
+ -1.468154e+001,
+ -9.044857e-003,
+ 5.624314e-002,
+ 6.498392e-002,
+ 2.047389e+000,
+ 6.367540e-002,
+ -6.102376e+000,
+ -3.473018e+000,
+ -9.926071e+000,
+ 9.637797e+000,
+ -1.097909e-002,
+ 1.103498e+000,
+ -2.424521e-001,
+ 2.520748e+000,
+ 1.240260e+000,
+ 1.351796e+000,
+ 1.018588e+000,
+ 2.009081e+000,
+ -1.333394e+000,
+ -1.979125e-001,
+ -3.318292e-001,
+ 4.476624e-001,
+ 9.095235e-001,
+ 2.955611e-001,
+ -1.774467e+000,
+ -1.079880e+000,
+ -8.084680e-002,
+ 2.577697e-001,
+ -1.149295e-001,
+ 4.975303e-001,
+ 2.931611e-003,
+ -3.803171e-001,
+ 8.002794e-001,
+ -9.898401e-001,
+ -2.542513e-001,
+ -7.530911e-002,
+ 1.870355e+000,
+ -1.521918e+000,
+ 2.405164e-001,
+ 2.964615e-001,
+ 1.334800e+000,
+ 6.789053e-001,
+ // albedo 1, turbidity 1
+ -1.279730e+000,
+ -4.290674e-001,
+ -4.277972e+001,
+ 4.343305e+001,
+ -6.541826e-003,
+ 4.945086e-001,
+ 1.425338e-002,
+ 2.685244e+000,
+ 5.011313e-001,
+ -1.449506e+000,
+ -5.766374e-001,
+ -1.688496e+001,
+ 1.781118e+001,
+ -1.121649e-002,
+ 3.545020e-001,
+ 2.287338e-002,
+ 1.904281e+000,
+ 4.936998e-001,
+ -1.021980e+000,
+ -1.897574e-001,
+ 2.482462e+000,
+ -2.941725e+000,
+ -1.570448e-002,
+ 7.532578e-001,
+ -4.256800e-002,
+ 5.239660e+000,
+ 4.983116e-001,
+ -1.162608e+000,
+ -3.428049e-001,
+ 3.974358e+000,
+ -1.527935e+000,
+ -3.919201e-002,
+ 8.758593e-001,
+ 7.291363e-002,
+ -3.455257e+000,
+ 8.007426e-001,
+ -9.929985e-001,
+ -8.712006e-002,
+ -7.397313e-001,
+ 1.348372e+000,
+ 9.511685e-002,
+ 3.233584e-001,
+ -7.549148e-002,
+ 5.806452e+000,
+ 4.990042e-001,
+ -1.084996e+000,
+ -1.739767e-001,
+ 1.580475e-001,
+ 9.088180e-001,
+ 6.871433e-002,
+ 5.933079e-001,
+ 1.188921e-001,
+ 3.074079e+000,
+ 4.999327e-001,
+ // albedo 1, turbidity 2
+ -1.317009e+000,
+ -4.661946e-001,
+ -4.255347e+001,
+ 4.312782e+001,
+ -5.727235e-003,
+ 4.285447e-001,
+ 2.189854e-002,
+ 2.608310e+000,
+ 5.190700e-001,
+ -1.469236e+000,
+ -6.282139e-001,
+ -1.241404e+001,
+ 1.348765e+001,
+ -1.204770e-002,
+ 5.070285e-001,
+ -7.280216e-004,
+ 1.491533e+000,
+ 3.635064e-001,
+ -9.713808e-001,
+ -8.138038e-002,
+ 3.709854e-001,
+ -1.041174e+000,
+ -1.814075e-002,
+ 5.060860e-001,
+ -2.053756e-002,
+ 6.161431e+000,
+ 1.093736e+000,
+ -1.159057e+000,
+ -3.698074e-001,
+ 2.711209e+000,
+ -6.006479e-001,
+ -4.896926e-002,
+ 9.273957e-001,
+ 1.137712e-001,
+ -3.496828e+000,
+ 2.867109e-001,
+ -1.011601e+000,
+ -8.201890e-002,
+ 2.105725e-001,
+ 4.597520e-001,
+ 1.478925e-001,
+ 2.138940e-001,
+ -5.660670e-002,
+ 6.057755e+000,
+ 7.859121e-001,
+ -1.078020e+000,
+ -1.811580e-001,
+ 1.646622e-001,
+ 8.348426e-001,
+ 1.149064e-001,
+ 4.985738e-001,
+ 1.376605e-001,
+ 2.746607e+000,
+ 4.999626e-001,
+ // albedo 1, turbidity 3
+ -1.325672e+000,
+ -4.769313e-001,
+ -4.111215e+001,
+ 4.168293e+001,
+ -6.274997e-003,
+ 4.649469e-001,
+ 1.119411e-002,
+ 2.631267e+000,
+ 5.234546e-001,
+ -1.619391e+000,
+ -8.000253e-001,
+ -1.534098e+001,
+ 1.632706e+001,
+ -1.012023e-002,
+ 4.242255e-001,
+ 2.931597e-002,
+ 8.925807e-001,
+ 3.314765e-001,
+ -7.356979e-001,
+ 1.368406e-001,
+ 2.972579e+000,
+ -3.535359e+000,
+ -1.318948e-002,
+ 4.607620e-001,
+ -7.182778e-002,
+ 6.254100e+000,
+ 1.236299e+000,
+ -1.316217e+000,
+ -4.194427e-001,
+ 3.489902e-002,
+ 1.289849e+000,
+ -4.755960e-002,
+ 1.138222e+000,
+ 1.975992e-001,
+ -8.991542e-001,
+ 2.290572e-001,
+ -9.502188e-001,
+ -1.172703e-001,
+ 1.405202e+000,
+ -3.061919e-001,
+ 1.058772e-001,
+ -3.760592e-001,
+ -1.983179e-002,
+ 3.562353e+000,
+ 7.895959e-001,
+ -1.100117e+000,
+ -1.900567e-001,
+ 4.925030e-001,
+ 5.250225e-001,
+ 1.576804e-001,
+ 1.042701e+000,
+ 7.330743e-002,
+ 2.796064e+000,
+ 6.749783e-001,
+ // albedo 1, turbidity 4
+ -1.354183e+000,
+ -5.130625e-001,
+ -4.219268e+001,
+ 4.271772e+001,
+ -5.365373e-003,
+ 4.136743e-001,
+ 1.235172e-002,
+ 2.520122e+000,
+ 5.187269e-001,
+ -1.741434e+000,
+ -9.589761e-001,
+ -8.230339e+000,
+ 9.296799e+000,
+ -9.600162e-003,
+ 4.994969e-001,
+ 2.955452e-002,
+ 3.667099e-001,
+ 3.526999e-001,
+ -6.917347e-001,
+ 2.154887e-001,
+ -8.760264e-001,
+ 2.334121e-001,
+ -1.909621e-002,
+ 4.748033e-001,
+ -1.138514e-001,
+ 6.515360e+000,
+ 1.225097e+000,
+ -1.293189e+000,
+ -4.218700e-001,
+ 1.620952e+000,
+ -7.858597e-001,
+ -3.769410e-002,
+ 6.636786e-001,
+ 3.364945e-001,
+ -5.341017e-001,
+ 2.128347e-001,
+ -9.735521e-001,
+ -1.325495e-001,
+ 1.007517e+000,
+ 2.598258e-001,
+ 6.762169e-002,
+ 1.421018e-003,
+ -6.915987e-002,
+ 3.185897e+000,
+ 8.641956e-001,
+ -1.094800e+000,
+ -1.962062e-001,
+ 5.755591e-001,
+ 2.906259e-001,
+ 2.625748e-001,
+ 7.644049e-001,
+ 1.347492e-001,
+ 2.677126e+000,
+ 6.465460e-001,
+ // albedo 1, turbidity 5
+ -1.393063e+000,
+ -5.578338e-001,
+ -4.185249e+001,
+ 4.233504e+001,
+ -5.435640e-003,
+ 4.743765e-001,
+ 7.422477e-003,
+ 2.442801e+000,
+ 5.211707e-001,
+ -1.939487e+000,
+ -1.128509e+000,
+ -8.974257e+000,
+ 9.978383e+000,
+ -7.965597e-003,
+ 2.948830e-001,
+ 4.436763e-002,
+ 2.839868e-001,
+ 3.440424e-001,
+ -6.011562e-001,
+ 2.354877e-001,
+ -3.079820e+000,
+ 2.585094e+000,
+ -2.002701e-002,
+ 7.793909e-001,
+ -1.598414e-001,
+ 5.834678e+000,
+ 1.202856e+000,
+ -1.315676e+000,
+ -3.903446e-001,
+ 1.701900e+000,
+ -1.304609e+000,
+ -1.045121e-002,
+ 2.747707e-001,
+ 4.143967e-001,
+ 3.197102e-001,
+ 2.637580e-001,
+ -9.618628e-001,
+ -1.625841e-001,
+ 1.187138e+000,
+ 1.497802e-001,
+ -5.590954e-006,
+ 3.178475e-002,
+ -4.153145e-002,
+ 2.496096e+000,
+ 8.195082e-001,
+ -1.111554e+000,
+ -2.365546e-001,
+ 7.831875e-001,
+ 2.018684e-001,
+ 2.074369e-001,
+ 7.395978e-001,
+ 1.225730e-001,
+ 1.876478e+000,
+ 6.821167e-001,
+ // albedo 1, turbidity 6
+ -1.427879e+000,
+ -5.994879e-001,
+ -3.531016e+001,
+ 3.581581e+001,
+ -6.431497e-003,
+ 4.554192e-001,
+ 7.348731e-004,
+ 2.334619e+000,
+ 5.233377e-001,
+ -1.998177e+000,
+ -1.206633e+000,
+ -2.146510e+001,
+ 2.242237e+001,
+ -5.857596e-003,
+ 2.755663e-001,
+ 6.384795e-002,
+ 1.358244e-001,
+ 3.328437e-001,
+ -6.440630e-001,
+ 2.058571e-001,
+ 2.155499e+000,
+ -2.587968e+000,
+ -1.840023e-002,
+ 8.826555e-001,
+ -2.222452e-001,
+ 5.847073e+000,
+ 1.228387e+000,
+ -1.229071e+000,
+ -3.360441e-001,
+ -3.429599e-001,
+ 6.179469e-001,
+ 2.029610e-003,
+ 8.899319e-002,
+ 5.041624e-001,
+ 1.882964e-001,
+ 2.252040e-001,
+ -1.022905e+000,
+ -2.101621e-001,
+ 1.915689e+000,
+ -6.498794e-001,
+ -3.463651e-002,
+ 8.954605e-002,
+ -6.797854e-002,
+ 2.417705e+000,
+ 8.568618e-001,
+ -1.082538e+000,
+ -2.007723e-001,
+ 4.731009e-001,
+ 4.077267e-001,
+ 1.324289e-001,
+ 6.514880e-001,
+ 1.702912e-001,
+ 2.309383e+000,
+ 6.600895e-001,
+ // albedo 1, turbidity 7
+ -1.472139e+000,
+ -6.499815e-001,
+ -3.428465e+001,
+ 3.469659e+001,
+ -5.747023e-003,
+ 4.174167e-001,
+ 1.688597e-003,
+ 2.323046e+000,
+ 5.395191e-001,
+ -2.161176e+000,
+ -1.353089e+000,
+ -2.226827e+001,
+ 2.329138e+001,
+ -5.583808e-003,
+ 2.364793e-001,
+ 6.096656e-002,
+ 1.944666e-003,
+ 2.861624e-001,
+ -6.593044e-001,
+ 1.393558e-001,
+ 4.698373e+000,
+ -5.193883e+000,
+ -1.998390e-002,
+ 1.095635e+000,
+ -2.391254e-001,
+ 5.598103e+000,
+ 1.236193e+000,
+ -1.195717e+000,
+ -2.972715e-001,
+ 4.648953e-002,
+ 3.024588e-001,
+ 5.003313e-003,
+ -3.754741e-001,
+ 5.247265e-001,
+ -1.381312e-001,
+ 2.493896e-001,
+ -1.020139e+000,
+ -2.253524e-001,
+ 3.548437e-001,
+ 7.030485e-001,
+ -2.107076e-002,
+ 4.581395e-001,
+ -3.243757e-002,
+ 2.453259e+000,
+ 8.323623e-001,
+ -1.098770e+000,
+ -2.435780e-001,
+ 8.761614e-001,
+ 1.941613e-001,
+ -1.990692e-001,
+ 3.761139e-001,
+ 1.657412e-001,
+ 1.590503e+000,
+ 6.741417e-001,
+ // albedo 1, turbidity 8
+ -1.648007e+000,
+ -8.205121e-001,
+ -4.435106e+001,
+ 4.479801e+001,
+ -4.181353e-003,
+ 3.854830e-001,
+ -1.842385e-006,
+ 2.000281e+000,
+ 5.518363e-001,
+ -2.140986e+000,
+ -1.282239e+000,
+ -3.979213e+000,
+ 4.672459e+000,
+ -5.008582e-003,
+ 2.421920e-001,
+ 6.253602e-002,
+ 6.612713e-001,
+ 2.555851e-001,
+ -1.300502e+000,
+ -5.137898e-001,
+ 5.179821e-001,
+ -4.032341e-001,
+ -2.066785e-002,
+ 1.087929e+000,
+ -2.615309e-001,
+ 4.225887e+000,
+ 1.229237e+000,
+ -6.963340e-001,
+ 9.241060e-002,
+ 6.936356e-002,
+ -3.588571e-001,
+ -5.461843e-002,
+ -5.616643e-001,
+ 5.484166e-001,
+ -4.776267e-002,
+ 2.414935e-001,
+ -1.233179e+000,
+ -4.325498e-001,
+ 6.479813e-001,
+ 8.368356e-001,
+ 2.458875e-001,
+ 6.464752e-001,
+ -2.897097e-002,
+ 1.561773e+000,
+ 8.518598e-001,
+ -1.051023e+000,
+ -2.533690e-001,
+ 1.004294e+000,
+ 3.028083e-001,
+ -1.520108e+000,
+ 1.607013e-001,
+ 1.619975e-001,
+ 1.131094e+000,
+ 6.706655e-001,
+ // albedo 1, turbidity 9
+ -1.948249e+000,
+ -1.097383e+000,
+ -4.453697e+001,
+ 4.494902e+001,
+ -3.579939e-003,
+ 3.491605e-001,
+ -2.500253e-006,
+ 1.740442e+000,
+ 6.188022e-001,
+ -2.154253e+000,
+ -1.209559e+000,
+ 4.144894e+000,
+ -3.562411e+000,
+ -5.638843e-003,
+ 1.067169e-001,
+ 7.594858e-002,
+ 1.005280e+000,
+ 1.072543e-001,
+ -2.513259e+000,
+ -1.507208e+000,
+ -1.602979e+000,
+ 1.404154e+000,
+ -5.560750e-003,
+ 1.240490e+000,
+ -2.852117e-001,
+ 3.485252e+000,
+ 1.349321e+000,
+ -7.832214e-002,
+ 3.655626e-001,
+ 3.856288e-001,
+ 6.867894e-001,
+ -1.609523e-001,
+ -6.704306e-001,
+ 5.357301e-001,
+ -6.457935e-001,
+ 1.479503e-001,
+ -1.354784e+000,
+ -5.454375e-001,
+ 8.797469e-001,
+ -1.466514e+000,
+ 7.134420e-001,
+ 5.934903e-001,
+ -2.911178e-002,
+ 8.643737e-001,
+ 9.030724e-001,
+ -1.048324e+000,
+ -2.738736e-001,
+ 8.783074e-001,
+ 3.246188e+000,
+ -4.435369e+000,
+ 1.251791e-001,
+ 1.783486e-001,
+ 1.064657e+000,
+ 6.522878e-001,
+ // albedo 1, turbidity 10
+ -2.770408e+000,
+ -1.618911e+000,
+ -2.504031e+001,
+ 2.531674e+001,
+ -4.239279e-003,
+ 3.241013e-001,
+ -3.764484e-006,
+ 1.586843e+000,
+ 7.035906e-001,
+ -1.913500e+000,
+ -1.144014e+000,
+ -1.080587e+001,
+ 1.153677e+001,
+ -1.003197e-002,
+ 1.577515e-001,
+ 5.217789e-002,
+ 1.225278e+000,
+ 5.172771e-003,
+ -5.293208e+000,
+ -2.876463e+000,
+ 2.087053e+000,
+ -3.201552e+000,
+ 3.892964e-003,
+ 5.323930e-001,
+ -2.034512e-001,
+ 2.617760e+000,
+ 1.273597e+000,
+ 9.060340e-001,
+ 3.773409e-001,
+ -6.399945e-001,
+ 3.213979e+000,
+ -9.112172e-002,
+ 6.494055e-001,
+ 3.953280e-001,
+ 5.047796e-001,
+ 2.998695e-001,
+ -1.482179e+000,
+ -6.778310e-001,
+ 1.161775e+000,
+ -3.004872e+000,
+ 4.774797e-001,
+ -4.969248e-001,
+ -3.512074e-003,
+ -1.307190e+000,
+ 7.927378e-001,
+ -9.863181e-001,
+ -1.803364e-001,
+ 5.810824e-001,
+ 4.580570e+000,
+ -3.863454e+000,
+ 5.328174e-001,
+ 2.272821e-001,
+ 1.771114e+000,
+ 6.791814e-001,
};
-static const double datasetXYZRad3[] =
-{
- // albedo 0, turbidity 1
- 1.168084e+000,
- 2.156455e+000,
- -3.980314e+000,
- 1.989302e+001,
- 1.328335e+001,
- 1.435621e+001,
- // albedo 0, turbidity 2
- 1.135488e+000,
- 2.294701e+000,
- -4.585886e+000,
- 2.090208e+001,
- 1.347840e+001,
- 1.467658e+001,
- // albedo 0, turbidity 3
- 1.107408e+000,
- 2.382765e+000,
- -5.112357e+000,
- 2.147823e+001,
- 1.493128e+001,
- 1.460882e+001,
- // albedo 0, turbidity 4
- 1.054193e+000,
- 2.592891e+000,
- -6.115000e+000,
- 2.268967e+001,
- 1.635672e+001,
- 1.518999e+001,
- // albedo 0, turbidity 5
- 1.006946e+000,
- 2.705420e+000,
- -6.698930e+000,
- 2.291830e+001,
- 1.834324e+001,
- 1.570651e+001,
- // albedo 0, turbidity 6
- 9.794044e-001,
- 2.742440e+000,
- -6.805283e+000,
- 2.225271e+001,
- 2.050797e+001,
- 1.563130e+001,
- // albedo 0, turbidity 7
- 9.413577e-001,
- 2.722009e+000,
- -6.760707e+000,
- 2.098242e+001,
- 2.342588e+001,
- 1.605011e+001,
- // albedo 0, turbidity 8
- 8.917923e-001,
- 2.592780e+000,
- -6.152635e+000,
- 1.774141e+001,
- 2.858324e+001,
- 1.657910e+001,
- // albedo 0, turbidity 9
- 8.288391e-001,
- 2.153434e+000,
- -4.118327e+000,
- 1.078118e+001,
- 3.681710e+001,
- 1.738139e+001,
- // albedo 0, turbidity 10
- 7.623528e-001,
- 1.418187e+000,
- -8.845235e-001,
- 7.590129e-001,
- 4.629859e+001,
- 1.921657e+001,
- // albedo 1, turbidity 1
- 1.352858e+000,
- 2.048862e+000,
- -2.053393e+000,
- 1.405874e+001,
- 3.045344e+001,
- 3.044430e+001,
- // albedo 1, turbidity 2
- 1.330497e+000,
- 2.126497e+000,
- -2.466296e+000,
- 1.467559e+001,
- 3.090738e+001,
- 3.069707e+001,
- // albedo 1, turbidity 3
- 1.286344e+000,
- 2.200436e+000,
- -2.877228e+000,
- 1.492701e+001,
- 3.236288e+001,
- 3.077223e+001,
- // albedo 1, turbidity 4
- 1.234428e+000,
- 2.289628e+000,
- -3.404699e+000,
- 1.499436e+001,
- 3.468390e+001,
- 3.084842e+001,
- // albedo 1, turbidity 5
- 1.178660e+000,
- 2.306071e+000,
- -3.549159e+000,
- 1.411006e+001,
- 3.754188e+001,
- 3.079730e+001,
- // albedo 1, turbidity 6
- 1.151366e+000,
- 2.333005e+000,
- -3.728627e+000,
- 1.363374e+001,
- 3.905894e+001,
- 3.092599e+001,
- // albedo 1, turbidity 7
- 1.101593e+000,
- 2.299422e+000,
- -3.565787e+000,
- 1.196745e+001,
- 4.188472e+001,
- 3.102755e+001,
- // albedo 1, turbidity 8
- 1.038322e+000,
- 2.083539e+000,
- -2.649585e+000,
- 8.037389e+000,
- 4.700869e+001,
- 3.065948e+001,
- // albedo 1, turbidity 9
- 9.596146e-001,
- 1.671470e+000,
- -8.751538e-001,
- 1.679772e+000,
- 5.345784e+001,
- 3.054520e+001,
- // albedo 1, turbidity 10
- 8.640731e-001,
- 9.858301e-001,
- 1.854956e+000,
- -6.798097e+000,
- 5.936468e+001,
- 3.110255e+001,
+static const double datasetXYZRad3[] = {
+ // albedo 0, turbidity 1
+ 1.168084e+000,
+ 2.156455e+000,
+ -3.980314e+000,
+ 1.989302e+001,
+ 1.328335e+001,
+ 1.435621e+001,
+ // albedo 0, turbidity 2
+ 1.135488e+000,
+ 2.294701e+000,
+ -4.585886e+000,
+ 2.090208e+001,
+ 1.347840e+001,
+ 1.467658e+001,
+ // albedo 0, turbidity 3
+ 1.107408e+000,
+ 2.382765e+000,
+ -5.112357e+000,
+ 2.147823e+001,
+ 1.493128e+001,
+ 1.460882e+001,
+ // albedo 0, turbidity 4
+ 1.054193e+000,
+ 2.592891e+000,
+ -6.115000e+000,
+ 2.268967e+001,
+ 1.635672e+001,
+ 1.518999e+001,
+ // albedo 0, turbidity 5
+ 1.006946e+000,
+ 2.705420e+000,
+ -6.698930e+000,
+ 2.291830e+001,
+ 1.834324e+001,
+ 1.570651e+001,
+ // albedo 0, turbidity 6
+ 9.794044e-001,
+ 2.742440e+000,
+ -6.805283e+000,
+ 2.225271e+001,
+ 2.050797e+001,
+ 1.563130e+001,
+ // albedo 0, turbidity 7
+ 9.413577e-001,
+ 2.722009e+000,
+ -6.760707e+000,
+ 2.098242e+001,
+ 2.342588e+001,
+ 1.605011e+001,
+ // albedo 0, turbidity 8
+ 8.917923e-001,
+ 2.592780e+000,
+ -6.152635e+000,
+ 1.774141e+001,
+ 2.858324e+001,
+ 1.657910e+001,
+ // albedo 0, turbidity 9
+ 8.288391e-001,
+ 2.153434e+000,
+ -4.118327e+000,
+ 1.078118e+001,
+ 3.681710e+001,
+ 1.738139e+001,
+ // albedo 0, turbidity 10
+ 7.623528e-001,
+ 1.418187e+000,
+ -8.845235e-001,
+ 7.590129e-001,
+ 4.629859e+001,
+ 1.921657e+001,
+ // albedo 1, turbidity 1
+ 1.352858e+000,
+ 2.048862e+000,
+ -2.053393e+000,
+ 1.405874e+001,
+ 3.045344e+001,
+ 3.044430e+001,
+ // albedo 1, turbidity 2
+ 1.330497e+000,
+ 2.126497e+000,
+ -2.466296e+000,
+ 1.467559e+001,
+ 3.090738e+001,
+ 3.069707e+001,
+ // albedo 1, turbidity 3
+ 1.286344e+000,
+ 2.200436e+000,
+ -2.877228e+000,
+ 1.492701e+001,
+ 3.236288e+001,
+ 3.077223e+001,
+ // albedo 1, turbidity 4
+ 1.234428e+000,
+ 2.289628e+000,
+ -3.404699e+000,
+ 1.499436e+001,
+ 3.468390e+001,
+ 3.084842e+001,
+ // albedo 1, turbidity 5
+ 1.178660e+000,
+ 2.306071e+000,
+ -3.549159e+000,
+ 1.411006e+001,
+ 3.754188e+001,
+ 3.079730e+001,
+ // albedo 1, turbidity 6
+ 1.151366e+000,
+ 2.333005e+000,
+ -3.728627e+000,
+ 1.363374e+001,
+ 3.905894e+001,
+ 3.092599e+001,
+ // albedo 1, turbidity 7
+ 1.101593e+000,
+ 2.299422e+000,
+ -3.565787e+000,
+ 1.196745e+001,
+ 4.188472e+001,
+ 3.102755e+001,
+ // albedo 1, turbidity 8
+ 1.038322e+000,
+ 2.083539e+000,
+ -2.649585e+000,
+ 8.037389e+000,
+ 4.700869e+001,
+ 3.065948e+001,
+ // albedo 1, turbidity 9
+ 9.596146e-001,
+ 1.671470e+000,
+ -8.751538e-001,
+ 1.679772e+000,
+ 5.345784e+001,
+ 3.054520e+001,
+ // albedo 1, turbidity 10
+ 8.640731e-001,
+ 9.858301e-001,
+ 1.854956e+000,
+ -6.798097e+000,
+ 5.936468e+001,
+ 3.110255e+001,
};
+static const double *datasetsXYZ[] = {datasetXYZ1, datasetXYZ2, datasetXYZ3};
-
-static const double* datasetsXYZ[] = {
- datasetXYZ1,
- datasetXYZ2,
- datasetXYZ3
-};
-
-static const double* datasetsXYZRad[] = {
- datasetXYZRad1,
- datasetXYZRad2,
- datasetXYZRad3
-};
+static const double *datasetsXYZRad[] = {datasetXYZRad1, datasetXYZRad2, datasetXYZRad3};
CCL_NAMESPACE_END
diff --git a/intern/cycles/util/util_sseb.h b/intern/cycles/util/util_sseb.h
index f6810505126..56f8f676ba1 100644
--- a/intern/cycles/util/util_sseb.h
+++ b/intern/cycles/util/util_sseb.h
@@ -26,150 +26,274 @@ struct ssei;
struct ssef;
/*! 4-wide SSE bool type. */
-struct sseb
-{
- typedef sseb Mask; // mask type
- typedef ssei Int; // int type
- typedef ssef Float; // float type
-
- enum { size = 4 }; // number of SIMD elements
- union { __m128 m128; int32_t v[4]; }; // data
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Constructors, Assignment & Cast Operators
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline sseb ( ) {}
- __forceinline sseb ( const sseb& other ) { m128 = other.m128; }
- __forceinline sseb& operator=( const sseb& other ) { m128 = other.m128; return *this; }
-
- __forceinline sseb( const __m128 input ) : m128(input) {}
- __forceinline operator const __m128&( void ) const { return m128; }
- __forceinline operator const __m128i( void ) const { return _mm_castps_si128(m128); }
- __forceinline operator const __m128d( void ) const { return _mm_castps_pd(m128); }
-
- __forceinline sseb ( bool a )
- : m128(_mm_lookupmask_ps[(size_t(a) << 3) | (size_t(a) << 2) | (size_t(a) << 1) | size_t(a)]) {}
- __forceinline sseb ( bool a, bool b)
- : m128(_mm_lookupmask_ps[(size_t(b) << 3) | (size_t(a) << 2) | (size_t(b) << 1) | size_t(a)]) {}
- __forceinline sseb ( bool a, bool b, bool c, bool d)
- : m128(_mm_lookupmask_ps[(size_t(d) << 3) | (size_t(c) << 2) | (size_t(b) << 1) | size_t(a)]) {}
- __forceinline sseb(int mask) {
- assert(mask >= 0 && mask < 16);
- m128 = _mm_lookupmask_ps[mask];
- }
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Constants
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline sseb( FalseTy ) : m128(_mm_setzero_ps()) {}
- __forceinline sseb( TrueTy ) : m128(_mm_castsi128_ps(_mm_cmpeq_epi32(_mm_setzero_si128(), _mm_setzero_si128()))) {}
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Array Access
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline bool operator []( const size_t i ) const { assert(i < 4); return (_mm_movemask_ps(m128) >> i) & 1; }
- __forceinline int32_t& operator []( const size_t i ) { assert(i < 4); return v[i]; }
+struct sseb {
+ typedef sseb Mask; // mask type
+ typedef ssei Int; // int type
+ typedef ssef Float; // float type
+
+ enum { size = 4 }; // number of SIMD elements
+ union {
+ __m128 m128;
+ int32_t v[4];
+ }; // data
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Constructors, Assignment & Cast Operators
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline sseb()
+ {
+ }
+ __forceinline sseb(const sseb &other)
+ {
+ m128 = other.m128;
+ }
+ __forceinline sseb &operator=(const sseb &other)
+ {
+ m128 = other.m128;
+ return *this;
+ }
+
+ __forceinline sseb(const __m128 input) : m128(input)
+ {
+ }
+ __forceinline operator const __m128 &(void)const
+ {
+ return m128;
+ }
+ __forceinline operator const __m128i(void) const
+ {
+ return _mm_castps_si128(m128);
+ }
+ __forceinline operator const __m128d(void) const
+ {
+ return _mm_castps_pd(m128);
+ }
+
+ __forceinline sseb(bool a)
+ : m128(_mm_lookupmask_ps[(size_t(a) << 3) | (size_t(a) << 2) | (size_t(a) << 1) | size_t(a)])
+ {
+ }
+ __forceinline sseb(bool a, bool b)
+ : m128(_mm_lookupmask_ps[(size_t(b) << 3) | (size_t(a) << 2) | (size_t(b) << 1) | size_t(a)])
+ {
+ }
+ __forceinline sseb(bool a, bool b, bool c, bool d)
+ : m128(_mm_lookupmask_ps[(size_t(d) << 3) | (size_t(c) << 2) | (size_t(b) << 1) | size_t(a)])
+ {
+ }
+ __forceinline sseb(int mask)
+ {
+ assert(mask >= 0 && mask < 16);
+ m128 = _mm_lookupmask_ps[mask];
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Constants
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline sseb(FalseTy) : m128(_mm_setzero_ps())
+ {
+ }
+ __forceinline sseb(TrueTy)
+ : m128(_mm_castsi128_ps(_mm_cmpeq_epi32(_mm_setzero_si128(), _mm_setzero_si128())))
+ {
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Array Access
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline bool operator[](const size_t i) const
+ {
+ assert(i < 4);
+ return (_mm_movemask_ps(m128) >> i) & 1;
+ }
+ __forceinline int32_t &operator[](const size_t i)
+ {
+ assert(i < 4);
+ return v[i];
+ }
};
////////////////////////////////////////////////////////////////////////////////
/// Unary Operators
////////////////////////////////////////////////////////////////////////////////
-__forceinline const sseb operator !( const sseb& a ) { return _mm_xor_ps(a, sseb(True)); }
+__forceinline const sseb operator!(const sseb &a)
+{
+ return _mm_xor_ps(a, sseb(True));
+}
////////////////////////////////////////////////////////////////////////////////
/// Binary Operators
////////////////////////////////////////////////////////////////////////////////
-__forceinline const sseb operator &( const sseb& a, const sseb& b ) { return _mm_and_ps(a, b); }
-__forceinline const sseb operator |( const sseb& a, const sseb& b ) { return _mm_or_ps (a, b); }
-__forceinline const sseb operator ^( const sseb& a, const sseb& b ) { return _mm_xor_ps(a, b); }
+__forceinline const sseb operator&(const sseb &a, const sseb &b)
+{
+ return _mm_and_ps(a, b);
+}
+__forceinline const sseb operator|(const sseb &a, const sseb &b)
+{
+ return _mm_or_ps(a, b);
+}
+__forceinline const sseb operator^(const sseb &a, const sseb &b)
+{
+ return _mm_xor_ps(a, b);
+}
////////////////////////////////////////////////////////////////////////////////
/// Assignment Operators
////////////////////////////////////////////////////////////////////////////////
-__forceinline const sseb operator &=( sseb& a, const sseb& b ) { return a = a & b; }
-__forceinline const sseb operator |=( sseb& a, const sseb& b ) { return a = a | b; }
-__forceinline const sseb operator ^=( sseb& a, const sseb& b ) { return a = a ^ b; }
+__forceinline const sseb operator&=(sseb &a, const sseb &b)
+{
+ return a = a & b;
+}
+__forceinline const sseb operator|=(sseb &a, const sseb &b)
+{
+ return a = a | b;
+}
+__forceinline const sseb operator^=(sseb &a, const sseb &b)
+{
+ return a = a ^ b;
+}
////////////////////////////////////////////////////////////////////////////////
/// Comparison Operators + Select
////////////////////////////////////////////////////////////////////////////////
-__forceinline const sseb operator !=( const sseb& a, const sseb& b ) { return _mm_xor_ps(a, b); }
-__forceinline const sseb operator ==( const sseb& a, const sseb& b ) { return _mm_castsi128_ps(_mm_cmpeq_epi32(a, b)); }
+__forceinline const sseb operator!=(const sseb &a, const sseb &b)
+{
+ return _mm_xor_ps(a, b);
+}
+__forceinline const sseb operator==(const sseb &a, const sseb &b)
+{
+ return _mm_castsi128_ps(_mm_cmpeq_epi32(a, b));
+}
-__forceinline const sseb select( const sseb& m, const sseb& t, const sseb& f ) {
-#if defined(__KERNEL_SSE41__)
- return _mm_blendv_ps(f, t, m);
-#else
- return _mm_or_ps(_mm_and_ps(m, t), _mm_andnot_ps(m, f));
-#endif
+__forceinline const sseb select(const sseb &m, const sseb &t, const sseb &f)
+{
+# if defined(__KERNEL_SSE41__)
+ return _mm_blendv_ps(f, t, m);
+# else
+ return _mm_or_ps(_mm_and_ps(m, t), _mm_andnot_ps(m, f));
+# endif
}
////////////////////////////////////////////////////////////////////////////////
/// Movement/Shifting/Shuffling Functions
////////////////////////////////////////////////////////////////////////////////
-__forceinline const sseb unpacklo( const sseb& a, const sseb& b ) { return _mm_unpacklo_ps(a, b); }
-__forceinline const sseb unpackhi( const sseb& a, const sseb& b ) { return _mm_unpackhi_ps(a, b); }
+__forceinline const sseb unpacklo(const sseb &a, const sseb &b)
+{
+ return _mm_unpacklo_ps(a, b);
+}
+__forceinline const sseb unpackhi(const sseb &a, const sseb &b)
+{
+ return _mm_unpackhi_ps(a, b);
+}
-template<size_t i0, size_t i1, size_t i2, size_t i3> __forceinline const sseb shuffle( const sseb& a ) {
- return _mm_castsi128_ps(_mm_shuffle_epi32(a, _MM_SHUFFLE(i3, i2, i1, i0)));
+template<size_t i0, size_t i1, size_t i2, size_t i3>
+__forceinline const sseb shuffle(const sseb &a)
+{
+ return _mm_castsi128_ps(_mm_shuffle_epi32(a, _MM_SHUFFLE(i3, i2, i1, i0)));
}
-template<> __forceinline const sseb shuffle<0, 1, 0, 1>( const sseb& a ) {
- return _mm_movelh_ps(a, a);
+template<> __forceinline const sseb shuffle<0, 1, 0, 1>(const sseb &a)
+{
+ return _mm_movelh_ps(a, a);
}
-template<> __forceinline const sseb shuffle<2, 3, 2, 3>( const sseb& a ) {
- return _mm_movehl_ps(a, a);
+template<> __forceinline const sseb shuffle<2, 3, 2, 3>(const sseb &a)
+{
+ return _mm_movehl_ps(a, a);
}
-template<size_t i0, size_t i1, size_t i2, size_t i3> __forceinline const sseb shuffle( const sseb& a, const sseb& b ) {
- return _mm_shuffle_ps(a, b, _MM_SHUFFLE(i3, i2, i1, i0));
+template<size_t i0, size_t i1, size_t i2, size_t i3>
+__forceinline const sseb shuffle(const sseb &a, const sseb &b)
+{
+ return _mm_shuffle_ps(a, b, _MM_SHUFFLE(i3, i2, i1, i0));
}
-template<> __forceinline const sseb shuffle<0, 1, 0, 1>( const sseb& a, const sseb& b ) {
- return _mm_movelh_ps(a, b);
+template<> __forceinline const sseb shuffle<0, 1, 0, 1>(const sseb &a, const sseb &b)
+{
+ return _mm_movelh_ps(a, b);
}
-template<> __forceinline const sseb shuffle<2, 3, 2, 3>( const sseb& a, const sseb& b ) {
- return _mm_movehl_ps(b, a);
+template<> __forceinline const sseb shuffle<2, 3, 2, 3>(const sseb &a, const sseb &b)
+{
+ return _mm_movehl_ps(b, a);
}
-#if defined(__KERNEL_SSE3__)
-template<> __forceinline const sseb shuffle<0, 0, 2, 2>( const sseb& a ) { return _mm_moveldup_ps(a); }
-template<> __forceinline const sseb shuffle<1, 1, 3, 3>( const sseb& a ) { return _mm_movehdup_ps(a); }
-#endif
+# if defined(__KERNEL_SSE3__)
+template<> __forceinline const sseb shuffle<0, 0, 2, 2>(const sseb &a)
+{
+ return _mm_moveldup_ps(a);
+}
+template<> __forceinline const sseb shuffle<1, 1, 3, 3>(const sseb &a)
+{
+ return _mm_movehdup_ps(a);
+}
+# endif
-#if defined(__KERNEL_SSE41__)
-template<size_t dst, size_t src, size_t clr> __forceinline const sseb insert( const sseb& a, const sseb& b ) { return _mm_insert_ps(a, b, (dst << 4) | (src << 6) | clr); }
-template<size_t dst, size_t src> __forceinline const sseb insert( const sseb& a, const sseb& b ) { return insert<dst, src, 0>(a, b); }
-template<size_t dst> __forceinline const sseb insert( const sseb& a, const bool b ) { return insert<dst,0>(a, sseb(b)); }
-#endif
+# if defined(__KERNEL_SSE41__)
+template<size_t dst, size_t src, size_t clr>
+__forceinline const sseb insert(const sseb &a, const sseb &b)
+{
+ return _mm_insert_ps(a, b, (dst << 4) | (src << 6) | clr);
+}
+template<size_t dst, size_t src> __forceinline const sseb insert(const sseb &a, const sseb &b)
+{
+ return insert<dst, src, 0>(a, b);
+}
+template<size_t dst> __forceinline const sseb insert(const sseb &a, const bool b)
+{
+ return insert<dst, 0>(a, sseb(b));
+}
+# endif
////////////////////////////////////////////////////////////////////////////////
/// Reduction Operations
////////////////////////////////////////////////////////////////////////////////
-#if defined(__KERNEL_SSE41__)
-__forceinline size_t popcnt( const sseb& a ) { return __popcnt(_mm_movemask_ps(a)); }
-#else
-__forceinline size_t popcnt( const sseb& a ) { return bool(a[0])+bool(a[1])+bool(a[2])+bool(a[3]); }
-#endif
+# if defined(__KERNEL_SSE41__)
+__forceinline size_t popcnt(const sseb &a)
+{
+ return __popcnt(_mm_movemask_ps(a));
+}
+# else
+__forceinline size_t popcnt(const sseb &a)
+{
+ return bool(a[0]) + bool(a[1]) + bool(a[2]) + bool(a[3]);
+}
+# endif
-__forceinline bool reduce_and( const sseb& a ) { return _mm_movemask_ps(a) == 0xf; }
-__forceinline bool reduce_or ( const sseb& a ) { return _mm_movemask_ps(a) != 0x0; }
-__forceinline bool all ( const sseb& b ) { return _mm_movemask_ps(b) == 0xf; }
-__forceinline bool any ( const sseb& b ) { return _mm_movemask_ps(b) != 0x0; }
-__forceinline bool none ( const sseb& b ) { return _mm_movemask_ps(b) == 0x0; }
+__forceinline bool reduce_and(const sseb &a)
+{
+ return _mm_movemask_ps(a) == 0xf;
+}
+__forceinline bool reduce_or(const sseb &a)
+{
+ return _mm_movemask_ps(a) != 0x0;
+}
+__forceinline bool all(const sseb &b)
+{
+ return _mm_movemask_ps(b) == 0xf;
+}
+__forceinline bool any(const sseb &b)
+{
+ return _mm_movemask_ps(b) != 0x0;
+}
+__forceinline bool none(const sseb &b)
+{
+ return _mm_movemask_ps(b) == 0x0;
+}
-__forceinline size_t movemask( const sseb& a ) { return _mm_movemask_ps(a); }
+__forceinline size_t movemask(const sseb &a)
+{
+ return _mm_movemask_ps(a);
+}
////////////////////////////////////////////////////////////////////////////////
/// Debug Functions
@@ -177,8 +301,7 @@ __forceinline size_t movemask( const sseb& a ) { return _mm_movemask_ps(a); }
ccl_device_inline void print_sseb(const char *label, const sseb &a)
{
- printf("%s: %d %d %d %d\n",
- label, a[0], a[1], a[2], a[3]);
+ printf("%s: %d %d %d %d\n", label, a[0], a[1], a[2], a[3]);
}
#endif
diff --git a/intern/cycles/util/util_ssef.h b/intern/cycles/util/util_ssef.h
index 66670c9a779..e6610dbb197 100644
--- a/intern/cycles/util/util_ssef.h
+++ b/intern/cycles/util/util_ssef.h
@@ -26,587 +26,971 @@ struct sseb;
struct ssef;
/*! 4-wide SSE float type. */
-struct ssef
-{
- typedef sseb Mask; // mask type
- typedef ssei Int; // int type
- typedef ssef Float; // float type
-
- enum { size = 4 }; // number of SIMD elements
- union { __m128 m128; float f[4]; int i[4]; }; // data
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Constructors, Assignment & Cast Operators
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline ssef () {}
- __forceinline ssef (const ssef& other) { m128 = other.m128; }
- __forceinline ssef& operator=(const ssef& other) { m128 = other.m128; return *this; }
-
- __forceinline ssef(const __m128 a) : m128(a) {}
- __forceinline operator const __m128&() const { return m128; }
- __forceinline operator __m128&() { return m128; }
-
- __forceinline ssef (float a) : m128(_mm_set1_ps(a)) {}
- __forceinline ssef (float a, float b, float c, float d) : m128(_mm_setr_ps(a, b, c, d)) {}
-
- __forceinline explicit ssef(const __m128i a) : m128(_mm_cvtepi32_ps(a)) {}
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Loads and Stores
- ////////////////////////////////////////////////////////////////////////////////
-
-#if defined(__KERNEL_AVX__)
- static __forceinline ssef broadcast(const void* const a) { return _mm_broadcast_ss((float*)a); }
-#else
- static __forceinline ssef broadcast(const void* const a) { return _mm_set1_ps(*(float*)a); }
-#endif
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Array Access
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline const float& operator [](const size_t i) const { assert(i < 4); return f[i]; }
- __forceinline float& operator [](const size_t i) { assert(i < 4); return f[i]; }
+struct ssef {
+ typedef sseb Mask; // mask type
+ typedef ssei Int; // int type
+ typedef ssef Float; // float type
+
+ enum { size = 4 }; // number of SIMD elements
+ union {
+ __m128 m128;
+ float f[4];
+ int i[4];
+ }; // data
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Constructors, Assignment & Cast Operators
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline ssef()
+ {
+ }
+ __forceinline ssef(const ssef &other)
+ {
+ m128 = other.m128;
+ }
+ __forceinline ssef &operator=(const ssef &other)
+ {
+ m128 = other.m128;
+ return *this;
+ }
+
+ __forceinline ssef(const __m128 a) : m128(a)
+ {
+ }
+ __forceinline operator const __m128 &() const
+ {
+ return m128;
+ }
+ __forceinline operator __m128 &()
+ {
+ return m128;
+ }
+
+ __forceinline ssef(float a) : m128(_mm_set1_ps(a))
+ {
+ }
+ __forceinline ssef(float a, float b, float c, float d) : m128(_mm_setr_ps(a, b, c, d))
+ {
+ }
+
+ __forceinline explicit ssef(const __m128i a) : m128(_mm_cvtepi32_ps(a))
+ {
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Loads and Stores
+ ////////////////////////////////////////////////////////////////////////////////
+
+# if defined(__KERNEL_AVX__)
+ static __forceinline ssef broadcast(const void *const a)
+ {
+ return _mm_broadcast_ss((float *)a);
+ }
+# else
+ static __forceinline ssef broadcast(const void *const a)
+ {
+ return _mm_set1_ps(*(float *)a);
+ }
+# endif
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Array Access
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline const float &operator[](const size_t i) const
+ {
+ assert(i < 4);
+ return f[i];
+ }
+ __forceinline float &operator[](const size_t i)
+ {
+ assert(i < 4);
+ return f[i];
+ }
};
-
////////////////////////////////////////////////////////////////////////////////
/// Unary Operators
////////////////////////////////////////////////////////////////////////////////
-__forceinline const ssef cast (const __m128i& a) { return _mm_castsi128_ps(a); }
-__forceinline const ssef operator +(const ssef& a) { return a; }
-__forceinline const ssef operator -(const ssef& a) { return _mm_xor_ps(a.m128, _mm_castsi128_ps(_mm_set1_epi32(0x80000000))); }
-__forceinline const ssef abs (const ssef& a) { return _mm_and_ps(a.m128, _mm_castsi128_ps(_mm_set1_epi32(0x7fffffff))); }
-#if defined(__KERNEL_SSE41__)
-__forceinline const ssef sign (const ssef& a) { return _mm_blendv_ps(ssef(1.0f), -ssef(1.0f), _mm_cmplt_ps(a,ssef(0.0f))); }
-#endif
-__forceinline const ssef signmsk (const ssef& a) { return _mm_and_ps(a.m128,_mm_castsi128_ps(_mm_set1_epi32(0x80000000))); }
+__forceinline const ssef cast(const __m128i &a)
+{
+ return _mm_castsi128_ps(a);
+}
+__forceinline const ssef operator+(const ssef &a)
+{
+ return a;
+}
+__forceinline const ssef operator-(const ssef &a)
+{
+ return _mm_xor_ps(a.m128, _mm_castsi128_ps(_mm_set1_epi32(0x80000000)));
+}
+__forceinline const ssef abs(const ssef &a)
+{
+ return _mm_and_ps(a.m128, _mm_castsi128_ps(_mm_set1_epi32(0x7fffffff)));
+}
+# if defined(__KERNEL_SSE41__)
+__forceinline const ssef sign(const ssef &a)
+{
+ return _mm_blendv_ps(ssef(1.0f), -ssef(1.0f), _mm_cmplt_ps(a, ssef(0.0f)));
+}
+# endif
+__forceinline const ssef signmsk(const ssef &a)
+{
+ return _mm_and_ps(a.m128, _mm_castsi128_ps(_mm_set1_epi32(0x80000000)));
+}
-__forceinline const ssef rcp (const ssef& a) {
- const ssef r = _mm_rcp_ps(a.m128);
- return _mm_sub_ps(_mm_add_ps(r, r), _mm_mul_ps(_mm_mul_ps(r, r), a));
+__forceinline const ssef rcp(const ssef &a)
+{
+ const ssef r = _mm_rcp_ps(a.m128);
+ return _mm_sub_ps(_mm_add_ps(r, r), _mm_mul_ps(_mm_mul_ps(r, r), a));
+}
+__forceinline const ssef sqr(const ssef &a)
+{
+ return _mm_mul_ps(a, a);
}
-__forceinline const ssef sqr (const ssef& a) { return _mm_mul_ps(a,a); }
-__forceinline const ssef mm_sqrt(const ssef& a) { return _mm_sqrt_ps(a.m128); }
-__forceinline const ssef rsqrt(const ssef& a) {
- const ssef r = _mm_rsqrt_ps(a.m128);
- return _mm_add_ps(_mm_mul_ps(_mm_set_ps(1.5f, 1.5f, 1.5f, 1.5f), r),
- _mm_mul_ps(_mm_mul_ps(_mm_mul_ps(a, _mm_set_ps(-0.5f, -0.5f, -0.5f, -0.5f)), r), _mm_mul_ps(r, r)));
+__forceinline const ssef mm_sqrt(const ssef &a)
+{
+ return _mm_sqrt_ps(a.m128);
+}
+__forceinline const ssef rsqrt(const ssef &a)
+{
+ const ssef r = _mm_rsqrt_ps(a.m128);
+ return _mm_add_ps(
+ _mm_mul_ps(_mm_set_ps(1.5f, 1.5f, 1.5f, 1.5f), r),
+ _mm_mul_ps(_mm_mul_ps(_mm_mul_ps(a, _mm_set_ps(-0.5f, -0.5f, -0.5f, -0.5f)), r),
+ _mm_mul_ps(r, r)));
}
////////////////////////////////////////////////////////////////////////////////
/// Binary Operators
////////////////////////////////////////////////////////////////////////////////
-__forceinline const ssef operator +(const ssef& a, const ssef& b) { return _mm_add_ps(a.m128, b.m128); }
-__forceinline const ssef operator +(const ssef& a, const float& b) { return a + ssef(b); }
-__forceinline const ssef operator +(const float& a, const ssef& b) { return ssef(a) + b; }
+__forceinline const ssef operator+(const ssef &a, const ssef &b)
+{
+ return _mm_add_ps(a.m128, b.m128);
+}
+__forceinline const ssef operator+(const ssef &a, const float &b)
+{
+ return a + ssef(b);
+}
+__forceinline const ssef operator+(const float &a, const ssef &b)
+{
+ return ssef(a) + b;
+}
-__forceinline const ssef operator -(const ssef& a, const ssef& b) { return _mm_sub_ps(a.m128, b.m128); }
-__forceinline const ssef operator -(const ssef& a, const float& b) { return a - ssef(b); }
-__forceinline const ssef operator -(const float& a, const ssef& b) { return ssef(a) - b; }
+__forceinline const ssef operator-(const ssef &a, const ssef &b)
+{
+ return _mm_sub_ps(a.m128, b.m128);
+}
+__forceinline const ssef operator-(const ssef &a, const float &b)
+{
+ return a - ssef(b);
+}
+__forceinline const ssef operator-(const float &a, const ssef &b)
+{
+ return ssef(a) - b;
+}
-__forceinline const ssef operator *(const ssef& a, const ssef& b) { return _mm_mul_ps(a.m128, b.m128); }
-__forceinline const ssef operator *(const ssef& a, const float& b) { return a * ssef(b); }
-__forceinline const ssef operator *(const float& a, const ssef& b) { return ssef(a) * b; }
+__forceinline const ssef operator*(const ssef &a, const ssef &b)
+{
+ return _mm_mul_ps(a.m128, b.m128);
+}
+__forceinline const ssef operator*(const ssef &a, const float &b)
+{
+ return a * ssef(b);
+}
+__forceinline const ssef operator*(const float &a, const ssef &b)
+{
+ return ssef(a) * b;
+}
-__forceinline const ssef operator /(const ssef& a, const ssef& b) { return _mm_div_ps(a.m128,b.m128); }
-__forceinline const ssef operator /(const ssef& a, const float& b) { return a/ssef(b); }
-__forceinline const ssef operator /(const float& a, const ssef& b) { return ssef(a)/b; }
+__forceinline const ssef operator/(const ssef &a, const ssef &b)
+{
+ return _mm_div_ps(a.m128, b.m128);
+}
+__forceinline const ssef operator/(const ssef &a, const float &b)
+{
+ return a / ssef(b);
+}
+__forceinline const ssef operator/(const float &a, const ssef &b)
+{
+ return ssef(a) / b;
+}
-__forceinline const ssef operator^(const ssef& a, const ssef& b) { return _mm_xor_ps(a.m128,b.m128); }
-__forceinline const ssef operator^(const ssef& a, const ssei& b) { return _mm_xor_ps(a.m128,_mm_castsi128_ps(b.m128)); }
+__forceinline const ssef operator^(const ssef &a, const ssef &b)
+{
+ return _mm_xor_ps(a.m128, b.m128);
+}
+__forceinline const ssef operator^(const ssef &a, const ssei &b)
+{
+ return _mm_xor_ps(a.m128, _mm_castsi128_ps(b.m128));
+}
-__forceinline const ssef operator&(const ssef& a, const ssef& b) { return _mm_and_ps(a.m128,b.m128); }
-__forceinline const ssef operator&(const ssef& a, const ssei& b) { return _mm_and_ps(a.m128,_mm_castsi128_ps(b.m128)); }
+__forceinline const ssef operator&(const ssef &a, const ssef &b)
+{
+ return _mm_and_ps(a.m128, b.m128);
+}
+__forceinline const ssef operator&(const ssef &a, const ssei &b)
+{
+ return _mm_and_ps(a.m128, _mm_castsi128_ps(b.m128));
+}
-__forceinline const ssef operator|(const ssef& a, const ssef& b) { return _mm_or_ps(a.m128,b.m128); }
-__forceinline const ssef operator|(const ssef& a, const ssei& b) { return _mm_or_ps(a.m128,_mm_castsi128_ps(b.m128)); }
+__forceinline const ssef operator|(const ssef &a, const ssef &b)
+{
+ return _mm_or_ps(a.m128, b.m128);
+}
+__forceinline const ssef operator|(const ssef &a, const ssei &b)
+{
+ return _mm_or_ps(a.m128, _mm_castsi128_ps(b.m128));
+}
-__forceinline const ssef andnot(const ssef& a, const ssef& b) { return _mm_andnot_ps(a.m128,b.m128); }
+__forceinline const ssef andnot(const ssef &a, const ssef &b)
+{
+ return _mm_andnot_ps(a.m128, b.m128);
+}
-__forceinline const ssef min(const ssef& a, const ssef& b) { return _mm_min_ps(a.m128,b.m128); }
-__forceinline const ssef min(const ssef& a, const float& b) { return _mm_min_ps(a.m128,ssef(b)); }
-__forceinline const ssef min(const float& a, const ssef& b) { return _mm_min_ps(ssef(a),b.m128); }
+__forceinline const ssef min(const ssef &a, const ssef &b)
+{
+ return _mm_min_ps(a.m128, b.m128);
+}
+__forceinline const ssef min(const ssef &a, const float &b)
+{
+ return _mm_min_ps(a.m128, ssef(b));
+}
+__forceinline const ssef min(const float &a, const ssef &b)
+{
+ return _mm_min_ps(ssef(a), b.m128);
+}
-__forceinline const ssef max(const ssef& a, const ssef& b) { return _mm_max_ps(a.m128,b.m128); }
-__forceinline const ssef max(const ssef& a, const float& b) { return _mm_max_ps(a.m128,ssef(b)); }
-__forceinline const ssef max(const float& a, const ssef& b) { return _mm_max_ps(ssef(a),b.m128); }
+__forceinline const ssef max(const ssef &a, const ssef &b)
+{
+ return _mm_max_ps(a.m128, b.m128);
+}
+__forceinline const ssef max(const ssef &a, const float &b)
+{
+ return _mm_max_ps(a.m128, ssef(b));
+}
+__forceinline const ssef max(const float &a, const ssef &b)
+{
+ return _mm_max_ps(ssef(a), b.m128);
+}
-#if defined(__KERNEL_SSE41__)
-__forceinline ssef mini(const ssef& a, const ssef& b) {
- const ssei ai = _mm_castps_si128(a);
- const ssei bi = _mm_castps_si128(b);
- const ssei ci = _mm_min_epi32(ai,bi);
- return _mm_castsi128_ps(ci);
+# if defined(__KERNEL_SSE41__)
+__forceinline ssef mini(const ssef &a, const ssef &b)
+{
+ const ssei ai = _mm_castps_si128(a);
+ const ssei bi = _mm_castps_si128(b);
+ const ssei ci = _mm_min_epi32(ai, bi);
+ return _mm_castsi128_ps(ci);
}
-#endif
+# endif
-#if defined(__KERNEL_SSE41__)
-__forceinline ssef maxi(const ssef& a, const ssef& b) {
- const ssei ai = _mm_castps_si128(a);
- const ssei bi = _mm_castps_si128(b);
- const ssei ci = _mm_max_epi32(ai,bi);
- return _mm_castsi128_ps(ci);
+# if defined(__KERNEL_SSE41__)
+__forceinline ssef maxi(const ssef &a, const ssef &b)
+{
+ const ssei ai = _mm_castps_si128(a);
+ const ssei bi = _mm_castps_si128(b);
+ const ssei ci = _mm_max_epi32(ai, bi);
+ return _mm_castsi128_ps(ci);
}
-#endif
+# endif
////////////////////////////////////////////////////////////////////////////////
/// Ternary Operators
////////////////////////////////////////////////////////////////////////////////
-#if defined(__KERNEL_AVX2__)
-__forceinline const ssef madd (const ssef& a, const ssef& b, const ssef& c) { return _mm_fmadd_ps(a,b,c); }
-__forceinline const ssef msub (const ssef& a, const ssef& b, const ssef& c) { return _mm_fmsub_ps(a,b,c); }
-__forceinline const ssef nmadd(const ssef& a, const ssef& b, const ssef& c) { return _mm_fnmadd_ps(a,b,c); }
-__forceinline const ssef nmsub(const ssef& a, const ssef& b, const ssef& c) { return _mm_fnmsub_ps(a,b,c); }
-#else
-__forceinline const ssef madd (const ssef& a, const ssef& b, const ssef& c) { return a*b+c; }
-__forceinline const ssef msub (const ssef& a, const ssef& b, const ssef& c) { return a*b-c; }
-__forceinline const ssef nmadd(const ssef& a, const ssef& b, const ssef& c) { return c-a*b;}
-__forceinline const ssef nmsub(const ssef& a, const ssef& b, const ssef& c) { return -a*b-c; }
-#endif
+# if defined(__KERNEL_AVX2__)
+__forceinline const ssef madd(const ssef &a, const ssef &b, const ssef &c)
+{
+ return _mm_fmadd_ps(a, b, c);
+}
+__forceinline const ssef msub(const ssef &a, const ssef &b, const ssef &c)
+{
+ return _mm_fmsub_ps(a, b, c);
+}
+__forceinline const ssef nmadd(const ssef &a, const ssef &b, const ssef &c)
+{
+ return _mm_fnmadd_ps(a, b, c);
+}
+__forceinline const ssef nmsub(const ssef &a, const ssef &b, const ssef &c)
+{
+ return _mm_fnmsub_ps(a, b, c);
+}
+# else
+__forceinline const ssef madd(const ssef &a, const ssef &b, const ssef &c)
+{
+ return a * b + c;
+}
+__forceinline const ssef msub(const ssef &a, const ssef &b, const ssef &c)
+{
+ return a * b - c;
+}
+__forceinline const ssef nmadd(const ssef &a, const ssef &b, const ssef &c)
+{
+ return c - a * b;
+}
+__forceinline const ssef nmsub(const ssef &a, const ssef &b, const ssef &c)
+{
+ return -a * b - c;
+}
+# endif
////////////////////////////////////////////////////////////////////////////////
/// Assignment Operators
////////////////////////////////////////////////////////////////////////////////
-__forceinline ssef& operator +=(ssef& a, const ssef& b) { return a = a + b; }
-__forceinline ssef& operator +=(ssef& a, const float& b) { return a = a + b; }
+__forceinline ssef &operator+=(ssef &a, const ssef &b)
+{
+ return a = a + b;
+}
+__forceinline ssef &operator+=(ssef &a, const float &b)
+{
+ return a = a + b;
+}
-__forceinline ssef& operator -=(ssef& a, const ssef& b) { return a = a - b; }
-__forceinline ssef& operator -=(ssef& a, const float& b) { return a = a - b; }
+__forceinline ssef &operator-=(ssef &a, const ssef &b)
+{
+ return a = a - b;
+}
+__forceinline ssef &operator-=(ssef &a, const float &b)
+{
+ return a = a - b;
+}
-__forceinline ssef& operator *=(ssef& a, const ssef& b) { return a = a * b; }
-__forceinline ssef& operator *=(ssef& a, const float& b) { return a = a * b; }
+__forceinline ssef &operator*=(ssef &a, const ssef &b)
+{
+ return a = a * b;
+}
+__forceinline ssef &operator*=(ssef &a, const float &b)
+{
+ return a = a * b;
+}
-__forceinline ssef& operator /=(ssef& a, const ssef& b) { return a = a / b; }
-__forceinline ssef& operator /=(ssef& a, const float& b) { return a = a / b; }
+__forceinline ssef &operator/=(ssef &a, const ssef &b)
+{
+ return a = a / b;
+}
+__forceinline ssef &operator/=(ssef &a, const float &b)
+{
+ return a = a / b;
+}
////////////////////////////////////////////////////////////////////////////////
/// Comparison Operators + Select
////////////////////////////////////////////////////////////////////////////////
-__forceinline const sseb operator ==(const ssef& a, const ssef& b) { return _mm_cmpeq_ps(a.m128, b.m128); }
-__forceinline const sseb operator ==(const ssef& a, const float& b) { return a == ssef(b); }
-__forceinline const sseb operator ==(const float& a, const ssef& b) { return ssef(a) == b; }
+__forceinline const sseb operator==(const ssef &a, const ssef &b)
+{
+ return _mm_cmpeq_ps(a.m128, b.m128);
+}
+__forceinline const sseb operator==(const ssef &a, const float &b)
+{
+ return a == ssef(b);
+}
+__forceinline const sseb operator==(const float &a, const ssef &b)
+{
+ return ssef(a) == b;
+}
-__forceinline const sseb operator !=(const ssef& a, const ssef& b) { return _mm_cmpneq_ps(a.m128, b.m128); }
-__forceinline const sseb operator !=(const ssef& a, const float& b) { return a != ssef(b); }
-__forceinline const sseb operator !=(const float& a, const ssef& b) { return ssef(a) != b; }
+__forceinline const sseb operator!=(const ssef &a, const ssef &b)
+{
+ return _mm_cmpneq_ps(a.m128, b.m128);
+}
+__forceinline const sseb operator!=(const ssef &a, const float &b)
+{
+ return a != ssef(b);
+}
+__forceinline const sseb operator!=(const float &a, const ssef &b)
+{
+ return ssef(a) != b;
+}
-__forceinline const sseb operator <(const ssef& a, const ssef& b) { return _mm_cmplt_ps(a.m128, b.m128); }
-__forceinline const sseb operator <(const ssef& a, const float& b) { return a < ssef(b); }
-__forceinline const sseb operator <(const float& a, const ssef& b) { return ssef(a) < b; }
+__forceinline const sseb operator<(const ssef &a, const ssef &b)
+{
+ return _mm_cmplt_ps(a.m128, b.m128);
+}
+__forceinline const sseb operator<(const ssef &a, const float &b)
+{
+ return a < ssef(b);
+}
+__forceinline const sseb operator<(const float &a, const ssef &b)
+{
+ return ssef(a) < b;
+}
-__forceinline const sseb operator >=(const ssef& a, const ssef& b) { return _mm_cmpnlt_ps(a.m128, b.m128); }
-__forceinline const sseb operator >=(const ssef& a, const float& b) { return a >= ssef(b); }
-__forceinline const sseb operator >=(const float& a, const ssef& b) { return ssef(a) >= b; }
+__forceinline const sseb operator>=(const ssef &a, const ssef &b)
+{
+ return _mm_cmpnlt_ps(a.m128, b.m128);
+}
+__forceinline const sseb operator>=(const ssef &a, const float &b)
+{
+ return a >= ssef(b);
+}
+__forceinline const sseb operator>=(const float &a, const ssef &b)
+{
+ return ssef(a) >= b;
+}
-__forceinline const sseb operator >(const ssef& a, const ssef& b) { return _mm_cmpnle_ps(a.m128, b.m128); }
-__forceinline const sseb operator >(const ssef& a, const float& b) { return a > ssef(b); }
-__forceinline const sseb operator >(const float& a, const ssef& b) { return ssef(a) > b; }
+__forceinline const sseb operator>(const ssef &a, const ssef &b)
+{
+ return _mm_cmpnle_ps(a.m128, b.m128);
+}
+__forceinline const sseb operator>(const ssef &a, const float &b)
+{
+ return a > ssef(b);
+}
+__forceinline const sseb operator>(const float &a, const ssef &b)
+{
+ return ssef(a) > b;
+}
-__forceinline const sseb operator <=(const ssef& a, const ssef& b) { return _mm_cmple_ps(a.m128, b.m128); }
-__forceinline const sseb operator <=(const ssef& a, const float& b) { return a <= ssef(b); }
-__forceinline const sseb operator <=(const float& a, const ssef& b) { return ssef(a) <= b; }
+__forceinline const sseb operator<=(const ssef &a, const ssef &b)
+{
+ return _mm_cmple_ps(a.m128, b.m128);
+}
+__forceinline const sseb operator<=(const ssef &a, const float &b)
+{
+ return a <= ssef(b);
+}
+__forceinline const sseb operator<=(const float &a, const ssef &b)
+{
+ return ssef(a) <= b;
+}
-__forceinline const ssef select(const sseb& m, const ssef& t, const ssef& f) {
-#ifdef __KERNEL_SSE41__
- return _mm_blendv_ps(f, t, m);
-#else
- return _mm_or_ps(_mm_and_ps(m, t), _mm_andnot_ps(m, f));
-#endif
+__forceinline const ssef select(const sseb &m, const ssef &t, const ssef &f)
+{
+# ifdef __KERNEL_SSE41__
+ return _mm_blendv_ps(f, t, m);
+# else
+ return _mm_or_ps(_mm_and_ps(m, t), _mm_andnot_ps(m, f));
+# endif
}
-__forceinline const ssef select(const ssef& m, const ssef& t, const ssef& f) {
-#ifdef __KERNEL_SSE41__
- return _mm_blendv_ps(f, t, m);
-#else
- return _mm_or_ps(_mm_and_ps(m, t), _mm_andnot_ps(m, f));
-#endif
+__forceinline const ssef select(const ssef &m, const ssef &t, const ssef &f)
+{
+# ifdef __KERNEL_SSE41__
+ return _mm_blendv_ps(f, t, m);
+# else
+ return _mm_or_ps(_mm_and_ps(m, t), _mm_andnot_ps(m, f));
+# endif
}
-__forceinline const ssef select(const int mask, const ssef& t, const ssef& f) {
-#if defined(__KERNEL_SSE41__) && ((!defined(__clang__) && !defined(_MSC_VER)) || defined(__INTEL_COMPILER))
- return _mm_blend_ps(f, t, mask);
-#else
- return select(sseb(mask),t,f);
-#endif
+__forceinline const ssef select(const int mask, const ssef &t, const ssef &f)
+{
+# if defined(__KERNEL_SSE41__) && \
+ ((!defined(__clang__) && !defined(_MSC_VER)) || defined(__INTEL_COMPILER))
+ return _mm_blend_ps(f, t, mask);
+# else
+ return select(sseb(mask), t, f);
+# endif
}
////////////////////////////////////////////////////////////////////////////////
/// Rounding Functions
////////////////////////////////////////////////////////////////////////////////
-#if defined(__KERNEL_SSE41__)
-__forceinline const ssef round_even(const ssef& a) { return _mm_round_ps(a, _MM_FROUND_TO_NEAREST_INT); }
-__forceinline const ssef round_down(const ssef& a) { return _mm_round_ps(a, _MM_FROUND_TO_NEG_INF ); }
-__forceinline const ssef round_up (const ssef& a) { return _mm_round_ps(a, _MM_FROUND_TO_POS_INF ); }
-__forceinline const ssef round_zero(const ssef& a) { return _mm_round_ps(a, _MM_FROUND_TO_ZERO ); }
-__forceinline const ssef floor (const ssef& a) { return _mm_round_ps(a, _MM_FROUND_TO_NEG_INF ); }
-__forceinline const ssef ceil (const ssef& a) { return _mm_round_ps(a, _MM_FROUND_TO_POS_INF ); }
-#endif
+# if defined(__KERNEL_SSE41__)
+__forceinline const ssef round_even(const ssef &a)
+{
+ return _mm_round_ps(a, _MM_FROUND_TO_NEAREST_INT);
+}
+__forceinline const ssef round_down(const ssef &a)
+{
+ return _mm_round_ps(a, _MM_FROUND_TO_NEG_INF);
+}
+__forceinline const ssef round_up(const ssef &a)
+{
+ return _mm_round_ps(a, _MM_FROUND_TO_POS_INF);
+}
+__forceinline const ssef round_zero(const ssef &a)
+{
+ return _mm_round_ps(a, _MM_FROUND_TO_ZERO);
+}
+__forceinline const ssef floor(const ssef &a)
+{
+ return _mm_round_ps(a, _MM_FROUND_TO_NEG_INF);
+}
+__forceinline const ssef ceil(const ssef &a)
+{
+ return _mm_round_ps(a, _MM_FROUND_TO_POS_INF);
+}
+# endif
-__forceinline ssei truncatei(const ssef& a) {
- return _mm_cvttps_epi32(a.m128);
+__forceinline ssei truncatei(const ssef &a)
+{
+ return _mm_cvttps_epi32(a.m128);
}
-__forceinline ssei floori(const ssef& a) {
-#if defined(__KERNEL_SSE41__)
- return ssei(floor(a));
-#else
- return ssei(a-ssef(0.5f));
-#endif
+__forceinline ssei floori(const ssef &a)
+{
+# if defined(__KERNEL_SSE41__)
+ return ssei(floor(a));
+# else
+ return ssei(a - ssef(0.5f));
+# endif
}
////////////////////////////////////////////////////////////////////////////////
/// Movement/Shifting/Shuffling Functions
////////////////////////////////////////////////////////////////////////////////
-__forceinline ssef unpacklo(const ssef& a, const ssef& b) { return _mm_unpacklo_ps(a.m128, b.m128); }
-__forceinline ssef unpackhi(const ssef& a, const ssef& b) { return _mm_unpackhi_ps(a.m128, b.m128); }
+__forceinline ssef unpacklo(const ssef &a, const ssef &b)
+{
+ return _mm_unpacklo_ps(a.m128, b.m128);
+}
+__forceinline ssef unpackhi(const ssef &a, const ssef &b)
+{
+ return _mm_unpackhi_ps(a.m128, b.m128);
+}
-template<size_t i0, size_t i1, size_t i2, size_t i3> __forceinline const ssef shuffle(const ssef& b) {
- return _mm_castsi128_ps(_mm_shuffle_epi32(_mm_castps_si128(b), _MM_SHUFFLE(i3, i2, i1, i0)));
+template<size_t i0, size_t i1, size_t i2, size_t i3>
+__forceinline const ssef shuffle(const ssef &b)
+{
+ return _mm_castsi128_ps(_mm_shuffle_epi32(_mm_castps_si128(b), _MM_SHUFFLE(i3, i2, i1, i0)));
}
-template<> __forceinline const ssef shuffle<0, 1, 0, 1>(const ssef& a) {
- return _mm_movelh_ps(a, a);
+template<> __forceinline const ssef shuffle<0, 1, 0, 1>(const ssef &a)
+{
+ return _mm_movelh_ps(a, a);
}
-template<> __forceinline const ssef shuffle<2, 3, 2, 3>(const ssef& a) {
- return _mm_movehl_ps(a, a);
+template<> __forceinline const ssef shuffle<2, 3, 2, 3>(const ssef &a)
+{
+ return _mm_movehl_ps(a, a);
}
-template<size_t i0, size_t i1, size_t i2, size_t i3> __forceinline const ssef shuffle(const ssef& a, const ssef& b) {
- return _mm_shuffle_ps(a, b, _MM_SHUFFLE(i3, i2, i1, i0));
+template<size_t i0, size_t i1, size_t i2, size_t i3>
+__forceinline const ssef shuffle(const ssef &a, const ssef &b)
+{
+ return _mm_shuffle_ps(a, b, _MM_SHUFFLE(i3, i2, i1, i0));
}
-template<size_t i0> __forceinline const ssef shuffle(const ssef& a, const ssef& b) {
- return _mm_shuffle_ps(a, b, _MM_SHUFFLE(i0, i0, i0, i0));
+template<size_t i0> __forceinline const ssef shuffle(const ssef &a, const ssef &b)
+{
+ return _mm_shuffle_ps(a, b, _MM_SHUFFLE(i0, i0, i0, i0));
}
-template<> __forceinline const ssef shuffle<0, 1, 0, 1>(const ssef& a, const ssef& b) {
- return _mm_movelh_ps(a, b);
+template<> __forceinline const ssef shuffle<0, 1, 0, 1>(const ssef &a, const ssef &b)
+{
+ return _mm_movelh_ps(a, b);
}
-template<> __forceinline const ssef shuffle<2, 3, 2, 3>(const ssef& a, const ssef& b) {
- return _mm_movehl_ps(b, a);
+template<> __forceinline const ssef shuffle<2, 3, 2, 3>(const ssef &a, const ssef &b)
+{
+ return _mm_movehl_ps(b, a);
}
-#if defined(__KERNEL_SSSE3__)
-__forceinline const ssef shuffle8(const ssef& a, const ssei& shuf) {
- return _mm_castsi128_ps(_mm_shuffle_epi8(_mm_castps_si128(a), shuf));
+# if defined(__KERNEL_SSSE3__)
+__forceinline const ssef shuffle8(const ssef &a, const ssei &shuf)
+{
+ return _mm_castsi128_ps(_mm_shuffle_epi8(_mm_castps_si128(a), shuf));
}
-#endif
+# endif
-#if defined(__KERNEL_SSE3__)
-template<> __forceinline const ssef shuffle<0, 0, 2, 2>(const ssef& b) { return _mm_moveldup_ps(b); }
-template<> __forceinline const ssef shuffle<1, 1, 3, 3>(const ssef& b) { return _mm_movehdup_ps(b); }
-#endif
+# if defined(__KERNEL_SSE3__)
+template<> __forceinline const ssef shuffle<0, 0, 2, 2>(const ssef &b)
+{
+ return _mm_moveldup_ps(b);
+}
+template<> __forceinline const ssef shuffle<1, 1, 3, 3>(const ssef &b)
+{
+ return _mm_movehdup_ps(b);
+}
+# endif
-template<size_t i0> __forceinline const ssef shuffle(const ssef& b) {
- return shuffle<i0,i0,i0,i0>(b);
+template<size_t i0> __forceinline const ssef shuffle(const ssef &b)
+{
+ return shuffle<i0, i0, i0, i0>(b);
}
-#if defined(__KERNEL_AVX__)
-__forceinline const ssef shuffle(const ssef& a, const ssei& shuf) {
- return _mm_permutevar_ps(a, shuf);
+# if defined(__KERNEL_AVX__)
+__forceinline const ssef shuffle(const ssef &a, const ssei &shuf)
+{
+ return _mm_permutevar_ps(a, shuf);
}
-#endif
+# endif
-template<size_t i> __forceinline float extract (const ssef& a) { return _mm_cvtss_f32(shuffle<i,i,i,i>(a)); }
-template<> __forceinline float extract<0>(const ssef& a) { return _mm_cvtss_f32(a); }
+template<size_t i> __forceinline float extract(const ssef &a)
+{
+ return _mm_cvtss_f32(shuffle<i, i, i, i>(a));
+}
+template<> __forceinline float extract<0>(const ssef &a)
+{
+ return _mm_cvtss_f32(a);
+}
-#if defined(__KERNEL_SSE41__)
-template<size_t dst, size_t src, size_t clr> __forceinline const ssef insert(const ssef& a, const ssef& b) { return _mm_insert_ps(a, b,(dst << 4) |(src << 6) | clr); }
-template<size_t dst, size_t src> __forceinline const ssef insert(const ssef& a, const ssef& b) { return insert<dst, src, 0>(a, b); }
-template<size_t dst> __forceinline const ssef insert(const ssef& a, const float b) { return insert<dst, 0>(a, _mm_set_ss(b)); }
-#else
-template<size_t dst> __forceinline const ssef insert(const ssef& a, const float b) { ssef c = a; c[dst] = b; return c; }
-#endif
+# if defined(__KERNEL_SSE41__)
+template<size_t dst, size_t src, size_t clr>
+__forceinline const ssef insert(const ssef &a, const ssef &b)
+{
+ return _mm_insert_ps(a, b, (dst << 4) | (src << 6) | clr);
+}
+template<size_t dst, size_t src> __forceinline const ssef insert(const ssef &a, const ssef &b)
+{
+ return insert<dst, src, 0>(a, b);
+}
+template<size_t dst> __forceinline const ssef insert(const ssef &a, const float b)
+{
+ return insert<dst, 0>(a, _mm_set_ss(b));
+}
+# else
+template<size_t dst> __forceinline const ssef insert(const ssef &a, const float b)
+{
+ ssef c = a;
+ c[dst] = b;
+ return c;
+}
+# endif
////////////////////////////////////////////////////////////////////////////////
/// Transpose
////////////////////////////////////////////////////////////////////////////////
-__forceinline void transpose(const ssef& r0, const ssef& r1, const ssef& r2, const ssef& r3, ssef& c0, ssef& c1, ssef& c2, ssef& c3)
+__forceinline void transpose(const ssef &r0,
+ const ssef &r1,
+ const ssef &r2,
+ const ssef &r3,
+ ssef &c0,
+ ssef &c1,
+ ssef &c2,
+ ssef &c3)
{
- ssef l02 = unpacklo(r0,r2);
- ssef h02 = unpackhi(r0,r2);
- ssef l13 = unpacklo(r1,r3);
- ssef h13 = unpackhi(r1,r3);
- c0 = unpacklo(l02,l13);
- c1 = unpackhi(l02,l13);
- c2 = unpacklo(h02,h13);
- c3 = unpackhi(h02,h13);
-}
-
-__forceinline void transpose(const ssef& r0, const ssef& r1, const ssef& r2, const ssef& r3, ssef& c0, ssef& c1, ssef& c2)
+ ssef l02 = unpacklo(r0, r2);
+ ssef h02 = unpackhi(r0, r2);
+ ssef l13 = unpacklo(r1, r3);
+ ssef h13 = unpackhi(r1, r3);
+ c0 = unpacklo(l02, l13);
+ c1 = unpackhi(l02, l13);
+ c2 = unpacklo(h02, h13);
+ c3 = unpackhi(h02, h13);
+}
+
+__forceinline void transpose(
+ const ssef &r0, const ssef &r1, const ssef &r2, const ssef &r3, ssef &c0, ssef &c1, ssef &c2)
{
- ssef l02 = unpacklo(r0,r2);
- ssef h02 = unpackhi(r0,r2);
- ssef l13 = unpacklo(r1,r3);
- ssef h13 = unpackhi(r1,r3);
- c0 = unpacklo(l02,l13);
- c1 = unpackhi(l02,l13);
- c2 = unpacklo(h02,h13);
+ ssef l02 = unpacklo(r0, r2);
+ ssef h02 = unpackhi(r0, r2);
+ ssef l13 = unpacklo(r1, r3);
+ ssef h13 = unpackhi(r1, r3);
+ c0 = unpacklo(l02, l13);
+ c1 = unpackhi(l02, l13);
+ c2 = unpacklo(h02, h13);
}
////////////////////////////////////////////////////////////////////////////////
/// Reductions
////////////////////////////////////////////////////////////////////////////////
-__forceinline const ssef vreduce_min(const ssef& v) { ssef h = min(shuffle<1,0,3,2>(v),v); return min(shuffle<2,3,0,1>(h),h); }
-__forceinline const ssef vreduce_max(const ssef& v) { ssef h = max(shuffle<1,0,3,2>(v),v); return max(shuffle<2,3,0,1>(h),h); }
-__forceinline const ssef vreduce_add(const ssef& v) { ssef h = shuffle<1,0,3,2>(v) + v ; return shuffle<2,3,0,1>(h) + h ; }
+__forceinline const ssef vreduce_min(const ssef &v)
+{
+ ssef h = min(shuffle<1, 0, 3, 2>(v), v);
+ return min(shuffle<2, 3, 0, 1>(h), h);
+}
+__forceinline const ssef vreduce_max(const ssef &v)
+{
+ ssef h = max(shuffle<1, 0, 3, 2>(v), v);
+ return max(shuffle<2, 3, 0, 1>(h), h);
+}
+__forceinline const ssef vreduce_add(const ssef &v)
+{
+ ssef h = shuffle<1, 0, 3, 2>(v) + v;
+ return shuffle<2, 3, 0, 1>(h) + h;
+}
-__forceinline float reduce_min(const ssef& v) { return _mm_cvtss_f32(vreduce_min(v)); }
-__forceinline float reduce_max(const ssef& v) { return _mm_cvtss_f32(vreduce_max(v)); }
-__forceinline float reduce_add(const ssef& v) { return _mm_cvtss_f32(vreduce_add(v)); }
+__forceinline float reduce_min(const ssef &v)
+{
+ return _mm_cvtss_f32(vreduce_min(v));
+}
+__forceinline float reduce_max(const ssef &v)
+{
+ return _mm_cvtss_f32(vreduce_max(v));
+}
+__forceinline float reduce_add(const ssef &v)
+{
+ return _mm_cvtss_f32(vreduce_add(v));
+}
-__forceinline size_t select_min(const ssef& v) { return __bsf(movemask(v == vreduce_min(v))); }
-__forceinline size_t select_max(const ssef& v) { return __bsf(movemask(v == vreduce_max(v))); }
+__forceinline size_t select_min(const ssef &v)
+{
+ return __bsf(movemask(v == vreduce_min(v)));
+}
+__forceinline size_t select_max(const ssef &v)
+{
+ return __bsf(movemask(v == vreduce_max(v)));
+}
-__forceinline size_t select_min(const sseb& valid, const ssef& v) { const ssef a = select(valid,v,ssef(pos_inf)); return __bsf(movemask(valid &(a == vreduce_min(a)))); }
-__forceinline size_t select_max(const sseb& valid, const ssef& v) { const ssef a = select(valid,v,ssef(neg_inf)); return __bsf(movemask(valid &(a == vreduce_max(a)))); }
+__forceinline size_t select_min(const sseb &valid, const ssef &v)
+{
+ const ssef a = select(valid, v, ssef(pos_inf));
+ return __bsf(movemask(valid & (a == vreduce_min(a))));
+}
+__forceinline size_t select_max(const sseb &valid, const ssef &v)
+{
+ const ssef a = select(valid, v, ssef(neg_inf));
+ return __bsf(movemask(valid & (a == vreduce_max(a))));
+}
-__forceinline size_t movemask( const ssef& a ) { return _mm_movemask_ps(a); }
+__forceinline size_t movemask(const ssef &a)
+{
+ return _mm_movemask_ps(a);
+}
////////////////////////////////////////////////////////////////////////////////
/// Memory load and store operations
////////////////////////////////////////////////////////////////////////////////
-__forceinline ssef load4f(const float4& a) {
-#ifdef __KERNEL_WITH_SSE_ALIGN__
- return _mm_load_ps(&a.x);
-#else
- return _mm_loadu_ps(&a.x);
-#endif
+__forceinline ssef load4f(const float4 &a)
+{
+# ifdef __KERNEL_WITH_SSE_ALIGN__
+ return _mm_load_ps(&a.x);
+# else
+ return _mm_loadu_ps(&a.x);
+# endif
}
-__forceinline ssef load4f(const float3& a) {
-#ifdef __KERNEL_WITH_SSE_ALIGN__
- return _mm_load_ps(&a.x);
-#else
- return _mm_loadu_ps(&a.x);
-#endif
+__forceinline ssef load4f(const float3 &a)
+{
+# ifdef __KERNEL_WITH_SSE_ALIGN__
+ return _mm_load_ps(&a.x);
+# else
+ return _mm_loadu_ps(&a.x);
+# endif
}
-__forceinline ssef load4f(const void* const a) {
- return _mm_load_ps((float*)a);
+__forceinline ssef load4f(const void *const a)
+{
+ return _mm_load_ps((float *)a);
}
-__forceinline ssef load1f_first(const float a) {
- return _mm_set_ss(a);
+__forceinline ssef load1f_first(const float a)
+{
+ return _mm_set_ss(a);
}
-__forceinline void store4f(void* ptr, const ssef& v) {
- _mm_store_ps((float*)ptr,v);
+__forceinline void store4f(void *ptr, const ssef &v)
+{
+ _mm_store_ps((float *)ptr, v);
}
-__forceinline ssef loadu4f(const void* const a) {
- return _mm_loadu_ps((float*)a);
+__forceinline ssef loadu4f(const void *const a)
+{
+ return _mm_loadu_ps((float *)a);
}
-__forceinline void storeu4f(void* ptr, const ssef& v) {
- _mm_storeu_ps((float*)ptr,v);
+__forceinline void storeu4f(void *ptr, const ssef &v)
+{
+ _mm_storeu_ps((float *)ptr, v);
}
-__forceinline void store4f(const sseb& mask, void* ptr, const ssef& f) {
-#if defined(__KERNEL_AVX__)
- _mm_maskstore_ps((float*)ptr,(__m128i)mask,f);
-#else
- *(ssef*)ptr = select(mask,f,*(ssef*)ptr);
-#endif
+__forceinline void store4f(const sseb &mask, void *ptr, const ssef &f)
+{
+# if defined(__KERNEL_AVX__)
+ _mm_maskstore_ps((float *)ptr, (__m128i)mask, f);
+# else
+ *(ssef *)ptr = select(mask, f, *(ssef *)ptr);
+# endif
}
-__forceinline ssef load4f_nt(void* ptr) {
-#if defined(__KERNEL_SSE41__)
- return _mm_castsi128_ps(_mm_stream_load_si128((__m128i*)ptr));
-#else
- return _mm_load_ps((float*)ptr);
-#endif
+__forceinline ssef load4f_nt(void *ptr)
+{
+# if defined(__KERNEL_SSE41__)
+ return _mm_castsi128_ps(_mm_stream_load_si128((__m128i *)ptr));
+# else
+ return _mm_load_ps((float *)ptr);
+# endif
}
-__forceinline void store4f_nt(void* ptr, const ssef& v) {
-#if defined(__KERNEL_SSE41__)
- _mm_stream_ps((float*)ptr,v);
-#else
- _mm_store_ps((float*)ptr,v);
-#endif
+__forceinline void store4f_nt(void *ptr, const ssef &v)
+{
+# if defined(__KERNEL_SSE41__)
+ _mm_stream_ps((float *)ptr, v);
+# else
+ _mm_store_ps((float *)ptr, v);
+# endif
}
////////////////////////////////////////////////////////////////////////////////
/// Euclidian Space Operators
////////////////////////////////////////////////////////////////////////////////
-__forceinline float dot(const ssef& a, const ssef& b) {
- return reduce_add(a*b);
+__forceinline float dot(const ssef &a, const ssef &b)
+{
+ return reduce_add(a * b);
}
/* calculate shuffled cross product, useful when order of components does not matter */
-__forceinline ssef cross_zxy(const ssef& a, const ssef& b)
+__forceinline ssef cross_zxy(const ssef &a, const ssef &b)
{
- const ssef a0 = a;
- const ssef b0 = shuffle<1,2,0,3>(b);
- const ssef a1 = shuffle<1,2,0,3>(a);
- const ssef b1 = b;
- return msub(a0,b0,a1*b1);
+ const ssef a0 = a;
+ const ssef b0 = shuffle<1, 2, 0, 3>(b);
+ const ssef a1 = shuffle<1, 2, 0, 3>(a);
+ const ssef b1 = b;
+ return msub(a0, b0, a1 * b1);
}
-__forceinline ssef cross(const ssef& a, const ssef& b)
+__forceinline ssef cross(const ssef &a, const ssef &b)
{
- return shuffle<1,2,0,3>(cross_zxy(a, b));
+ return shuffle<1, 2, 0, 3>(cross_zxy(a, b));
}
-ccl_device_inline const ssef dot3_splat(const ssef& a, const ssef& b)
+ccl_device_inline const ssef dot3_splat(const ssef &a, const ssef &b)
{
-#ifdef __KERNEL_SSE41__
- return _mm_dp_ps(a.m128, b.m128, 0x7f);
-#else
- ssef t = a * b;
- return ssef(((float*)&t)[0] + ((float*)&t)[1] + ((float*)&t)[2]);
-#endif
+# ifdef __KERNEL_SSE41__
+ return _mm_dp_ps(a.m128, b.m128, 0x7f);
+# else
+ ssef t = a * b;
+ return ssef(((float *)&t)[0] + ((float *)&t)[1] + ((float *)&t)[2]);
+# endif
}
/* squared length taking only specified axes into account */
-template<size_t X, size_t Y, size_t Z, size_t W>
-ccl_device_inline float len_squared(const ssef& a)
-{
-#ifndef __KERNEL_SSE41__
- float4& t = (float4 &)a;
- return (X ? t.x * t.x : 0.0f) + (Y ? t.y * t.y : 0.0f) + (Z ? t.z * t.z : 0.0f) + (W ? t.w * t.w : 0.0f);
-#else
- return extract<0>(ssef(_mm_dp_ps(a.m128, a.m128, (X << 4) | (Y << 5) | (Z << 6) | (W << 7) | 0xf)));
-#endif
+template<size_t X, size_t Y, size_t Z, size_t W> ccl_device_inline float len_squared(const ssef &a)
+{
+# ifndef __KERNEL_SSE41__
+ float4 &t = (float4 &)a;
+ return (X ? t.x * t.x : 0.0f) + (Y ? t.y * t.y : 0.0f) + (Z ? t.z * t.z : 0.0f) +
+ (W ? t.w * t.w : 0.0f);
+# else
+ return extract<0>(
+ ssef(_mm_dp_ps(a.m128, a.m128, (X << 4) | (Y << 5) | (Z << 6) | (W << 7) | 0xf)));
+# endif
}
-ccl_device_inline float dot3(const ssef& a, const ssef& b)
+ccl_device_inline float dot3(const ssef &a, const ssef &b)
{
-#ifdef __KERNEL_SSE41__
- return extract<0>(ssef(_mm_dp_ps(a.m128, b.m128, 0x7f)));
-#else
- ssef t = a * b;
- return ((float*)&t)[0] + ((float*)&t)[1] + ((float*)&t)[2];
-#endif
+# ifdef __KERNEL_SSE41__
+ return extract<0>(ssef(_mm_dp_ps(a.m128, b.m128, 0x7f)));
+# else
+ ssef t = a * b;
+ return ((float *)&t)[0] + ((float *)&t)[1] + ((float *)&t)[2];
+# endif
}
-ccl_device_inline const ssef len3_squared_splat(const ssef& a)
+ccl_device_inline const ssef len3_squared_splat(const ssef &a)
{
- return dot3_splat(a, a);
+ return dot3_splat(a, a);
}
-ccl_device_inline float len3_squared(const ssef& a)
+ccl_device_inline float len3_squared(const ssef &a)
{
- return dot3(a, a);
+ return dot3(a, a);
}
-ccl_device_inline float len3(const ssef& a)
+ccl_device_inline float len3(const ssef &a)
{
- return extract<0>(mm_sqrt(dot3_splat(a, a)));
+ return extract<0>(mm_sqrt(dot3_splat(a, a)));
}
/* SSE shuffle utility functions */
-#ifdef __KERNEL_SSSE3__
+# ifdef __KERNEL_SSSE3__
/* faster version for SSSE3 */
typedef ssei shuffle_swap_t;
ccl_device_inline shuffle_swap_t shuffle_swap_identity()
{
- return _mm_set_epi8(15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0);
+ return _mm_set_epi8(15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0);
}
ccl_device_inline shuffle_swap_t shuffle_swap_swap()
{
- return _mm_set_epi8(7, 6, 5, 4, 3, 2, 1, 0, 15, 14, 13, 12, 11, 10, 9, 8);
+ return _mm_set_epi8(7, 6, 5, 4, 3, 2, 1, 0, 15, 14, 13, 12, 11, 10, 9, 8);
}
-ccl_device_inline const ssef shuffle_swap(const ssef& a, const shuffle_swap_t& shuf)
+ccl_device_inline const ssef shuffle_swap(const ssef &a, const shuffle_swap_t &shuf)
{
- return cast(_mm_shuffle_epi8(cast(a), shuf));
+ return cast(_mm_shuffle_epi8(cast(a), shuf));
}
-#else
+# else
/* somewhat slower version for SSE2 */
typedef int shuffle_swap_t;
ccl_device_inline shuffle_swap_t shuffle_swap_identity()
{
- return 0;
+ return 0;
}
ccl_device_inline shuffle_swap_t shuffle_swap_swap()
{
- return 1;
+ return 1;
}
-ccl_device_inline const ssef shuffle_swap(const ssef& a, shuffle_swap_t shuf)
+ccl_device_inline const ssef shuffle_swap(const ssef &a, shuffle_swap_t shuf)
{
- /* shuffle value must be a constant, so we need to branch */
- if(shuf)
- return ssef(_mm_shuffle_ps(a.m128, a.m128, _MM_SHUFFLE(1, 0, 3, 2)));
- else
- return ssef(_mm_shuffle_ps(a.m128, a.m128, _MM_SHUFFLE(3, 2, 1, 0)));
+ /* shuffle value must be a constant, so we need to branch */
+ if (shuf)
+ return ssef(_mm_shuffle_ps(a.m128, a.m128, _MM_SHUFFLE(1, 0, 3, 2)));
+ else
+ return ssef(_mm_shuffle_ps(a.m128, a.m128, _MM_SHUFFLE(3, 2, 1, 0)));
}
-#endif
+# endif
-#ifdef __KERNEL_SSE41__
+# ifdef __KERNEL_SSE41__
-ccl_device_inline void gen_idirsplat_swap(const ssef &pn, const shuffle_swap_t &shuf_identity, const shuffle_swap_t &shuf_swap,
- const float3& idir, ssef idirsplat[3], shuffle_swap_t shufflexyz[3])
+ccl_device_inline void gen_idirsplat_swap(const ssef &pn,
+ const shuffle_swap_t &shuf_identity,
+ const shuffle_swap_t &shuf_swap,
+ const float3 &idir,
+ ssef idirsplat[3],
+ shuffle_swap_t shufflexyz[3])
{
- const __m128 idirsplat_raw[] = { _mm_set_ps1(idir.x), _mm_set_ps1(idir.y), _mm_set_ps1(idir.z) };
- idirsplat[0] = _mm_xor_ps(idirsplat_raw[0], pn);
- idirsplat[1] = _mm_xor_ps(idirsplat_raw[1], pn);
- idirsplat[2] = _mm_xor_ps(idirsplat_raw[2], pn);
-
- const ssef signmask = cast(ssei(0x80000000));
- const ssef shuf_identity_f = cast(shuf_identity);
- const ssef shuf_swap_f = cast(shuf_swap);
-
- shufflexyz[0] = _mm_castps_si128(_mm_blendv_ps(shuf_identity_f, shuf_swap_f, _mm_and_ps(idirsplat_raw[0], signmask)));
- shufflexyz[1] = _mm_castps_si128(_mm_blendv_ps(shuf_identity_f, shuf_swap_f, _mm_and_ps(idirsplat_raw[1], signmask)));
- shufflexyz[2] = _mm_castps_si128(_mm_blendv_ps(shuf_identity_f, shuf_swap_f, _mm_and_ps(idirsplat_raw[2], signmask)));
-}
-
-#else
-
-ccl_device_inline void gen_idirsplat_swap(const ssef &pn, const shuffle_swap_t &shuf_identity, const shuffle_swap_t &shuf_swap,
- const float3& idir, ssef idirsplat[3], shuffle_swap_t shufflexyz[3])
+ const __m128 idirsplat_raw[] = {_mm_set_ps1(idir.x), _mm_set_ps1(idir.y), _mm_set_ps1(idir.z)};
+ idirsplat[0] = _mm_xor_ps(idirsplat_raw[0], pn);
+ idirsplat[1] = _mm_xor_ps(idirsplat_raw[1], pn);
+ idirsplat[2] = _mm_xor_ps(idirsplat_raw[2], pn);
+
+ const ssef signmask = cast(ssei(0x80000000));
+ const ssef shuf_identity_f = cast(shuf_identity);
+ const ssef shuf_swap_f = cast(shuf_swap);
+
+ shufflexyz[0] = _mm_castps_si128(
+ _mm_blendv_ps(shuf_identity_f, shuf_swap_f, _mm_and_ps(idirsplat_raw[0], signmask)));
+ shufflexyz[1] = _mm_castps_si128(
+ _mm_blendv_ps(shuf_identity_f, shuf_swap_f, _mm_and_ps(idirsplat_raw[1], signmask)));
+ shufflexyz[2] = _mm_castps_si128(
+ _mm_blendv_ps(shuf_identity_f, shuf_swap_f, _mm_and_ps(idirsplat_raw[2], signmask)));
+}
+
+# else
+
+ccl_device_inline void gen_idirsplat_swap(const ssef &pn,
+ const shuffle_swap_t &shuf_identity,
+ const shuffle_swap_t &shuf_swap,
+ const float3 &idir,
+ ssef idirsplat[3],
+ shuffle_swap_t shufflexyz[3])
{
- idirsplat[0] = ssef(idir.x) ^ pn;
- idirsplat[1] = ssef(idir.y) ^ pn;
- idirsplat[2] = ssef(idir.z) ^ pn;
+ idirsplat[0] = ssef(idir.x) ^ pn;
+ idirsplat[1] = ssef(idir.y) ^ pn;
+ idirsplat[2] = ssef(idir.z) ^ pn;
- shufflexyz[0] = (idir.x >= 0)? shuf_identity: shuf_swap;
- shufflexyz[1] = (idir.y >= 0)? shuf_identity: shuf_swap;
- shufflexyz[2] = (idir.z >= 0)? shuf_identity: shuf_swap;
+ shufflexyz[0] = (idir.x >= 0) ? shuf_identity : shuf_swap;
+ shufflexyz[1] = (idir.y >= 0) ? shuf_identity : shuf_swap;
+ shufflexyz[2] = (idir.z >= 0) ? shuf_identity : shuf_swap;
}
-#endif
+# endif
ccl_device_inline const ssef uint32_to_float(const ssei &in)
{
- ssei a = _mm_srli_epi32(in, 16);
- ssei b = _mm_and_si128(in, _mm_set1_epi32(0x0000ffff));
- ssei c = _mm_or_si128(a, _mm_set1_epi32(0x53000000));
- ssef d = _mm_cvtepi32_ps(b);
- ssef e = _mm_sub_ps(_mm_castsi128_ps(c), _mm_castsi128_ps(_mm_set1_epi32(0x53000000)));
- return _mm_add_ps(e, d);
+ ssei a = _mm_srli_epi32(in, 16);
+ ssei b = _mm_and_si128(in, _mm_set1_epi32(0x0000ffff));
+ ssei c = _mm_or_si128(a, _mm_set1_epi32(0x53000000));
+ ssef d = _mm_cvtepi32_ps(b);
+ ssef e = _mm_sub_ps(_mm_castsi128_ps(c), _mm_castsi128_ps(_mm_set1_epi32(0x53000000)));
+ return _mm_add_ps(e, d);
}
template<size_t S1, size_t S2, size_t S3, size_t S4>
ccl_device_inline const ssef set_sign_bit(const ssef &a)
{
- return cast(cast(a) ^ ssei(S1 << 31, S2 << 31, S3 << 31, S4 << 31));
+ return cast(cast(a) ^ ssei(S1 << 31, S2 << 31, S3 << 31, S4 << 31));
}
////////////////////////////////////////////////////////////////////////////////
@@ -615,12 +999,8 @@ ccl_device_inline const ssef set_sign_bit(const ssef &a)
ccl_device_inline void print_ssef(const char *label, const ssef &a)
{
- printf("%s: %.8f %.8f %.8f %.8f\n",
- label,
- (double)a[0],
- (double)a[1],
- (double)a[2],
- (double)a[3]);
+ printf(
+ "%s: %.8f %.8f %.8f %.8f\n", label, (double)a[0], (double)a[1], (double)a[2], (double)a[3]);
}
#endif
diff --git a/intern/cycles/util/util_ssei.h b/intern/cycles/util/util_ssei.h
index ba0389cd114..86429260a0e 100644
--- a/intern/cycles/util/util_ssei.h
+++ b/intern/cycles/util/util_ssei.h
@@ -26,263 +26,576 @@ struct sseb;
struct ssef;
/*! 4-wide SSE integer type. */
-struct ssei
-{
- typedef sseb Mask; // mask type
- typedef ssei Int; // int type
- typedef ssef Float; // float type
-
- enum { size = 4 }; // number of SIMD elements
- union { __m128i m128; int32_t i[4]; }; // data
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Constructors, Assignment & Cast Operators
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline ssei ( ) {}
- __forceinline ssei ( const ssei& a ) { m128 = a.m128; }
- __forceinline ssei& operator=( const ssei& a ) { m128 = a.m128; return *this; }
-
- __forceinline ssei( const __m128i a ) : m128(a) {}
- __forceinline operator const __m128i&( void ) const { return m128; }
- __forceinline operator __m128i&( void ) { return m128; }
-
- __forceinline ssei ( const int a ) : m128(_mm_set1_epi32(a)) {}
- __forceinline ssei ( int a, int b, int c, int d ) : m128(_mm_setr_epi32(a, b, c, d)) {}
-
- __forceinline explicit ssei( const __m128 a ) : m128(_mm_cvtps_epi32(a)) {}
-
- ////////////////////////////////////////////////////////////////////////////////
- /// Array Access
- ////////////////////////////////////////////////////////////////////////////////
-
- __forceinline const int32_t& operator []( const size_t index ) const { assert(index < 4); return i[index]; }
- __forceinline int32_t& operator []( const size_t index ) { assert(index < 4); return i[index]; }
+struct ssei {
+ typedef sseb Mask; // mask type
+ typedef ssei Int; // int type
+ typedef ssef Float; // float type
+
+ enum { size = 4 }; // number of SIMD elements
+ union {
+ __m128i m128;
+ int32_t i[4];
+ }; // data
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Constructors, Assignment & Cast Operators
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline ssei()
+ {
+ }
+ __forceinline ssei(const ssei &a)
+ {
+ m128 = a.m128;
+ }
+ __forceinline ssei &operator=(const ssei &a)
+ {
+ m128 = a.m128;
+ return *this;
+ }
+
+ __forceinline ssei(const __m128i a) : m128(a)
+ {
+ }
+ __forceinline operator const __m128i &(void)const
+ {
+ return m128;
+ }
+ __forceinline operator __m128i &(void)
+ {
+ return m128;
+ }
+
+ __forceinline ssei(const int a) : m128(_mm_set1_epi32(a))
+ {
+ }
+ __forceinline ssei(int a, int b, int c, int d) : m128(_mm_setr_epi32(a, b, c, d))
+ {
+ }
+
+ __forceinline explicit ssei(const __m128 a) : m128(_mm_cvtps_epi32(a))
+ {
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// Array Access
+ ////////////////////////////////////////////////////////////////////////////////
+
+ __forceinline const int32_t &operator[](const size_t index) const
+ {
+ assert(index < 4);
+ return i[index];
+ }
+ __forceinline int32_t &operator[](const size_t index)
+ {
+ assert(index < 4);
+ return i[index];
+ }
};
////////////////////////////////////////////////////////////////////////////////
/// Unary Operators
////////////////////////////////////////////////////////////////////////////////
-__forceinline const ssei cast ( const __m128& a ) { return _mm_castps_si128(a); }
-__forceinline const ssei operator +( const ssei& a ) { return a; }
-__forceinline const ssei operator -( const ssei& a ) { return _mm_sub_epi32(_mm_setzero_si128(), a.m128); }
-#if defined(__KERNEL_SSSE3__)
-__forceinline const ssei abs ( const ssei& a ) { return _mm_abs_epi32(a.m128); }
-#endif
+__forceinline const ssei cast(const __m128 &a)
+{
+ return _mm_castps_si128(a);
+}
+__forceinline const ssei operator+(const ssei &a)
+{
+ return a;
+}
+__forceinline const ssei operator-(const ssei &a)
+{
+ return _mm_sub_epi32(_mm_setzero_si128(), a.m128);
+}
+# if defined(__KERNEL_SSSE3__)
+__forceinline const ssei abs(const ssei &a)
+{
+ return _mm_abs_epi32(a.m128);
+}
+# endif
////////////////////////////////////////////////////////////////////////////////
/// Binary Operators
////////////////////////////////////////////////////////////////////////////////
-__forceinline const ssei operator +( const ssei& a, const ssei& b ) { return _mm_add_epi32(a.m128, b.m128); }
-__forceinline const ssei operator +( const ssei& a, const int32_t& b ) { return a + ssei(b); }
-__forceinline const ssei operator +( const int32_t& a, const ssei& b ) { return ssei(a) + b; }
+__forceinline const ssei operator+(const ssei &a, const ssei &b)
+{
+ return _mm_add_epi32(a.m128, b.m128);
+}
+__forceinline const ssei operator+(const ssei &a, const int32_t &b)
+{
+ return a + ssei(b);
+}
+__forceinline const ssei operator+(const int32_t &a, const ssei &b)
+{
+ return ssei(a) + b;
+}
-__forceinline const ssei operator -( const ssei& a, const ssei& b ) { return _mm_sub_epi32(a.m128, b.m128); }
-__forceinline const ssei operator -( const ssei& a, const int32_t& b ) { return a - ssei(b); }
-__forceinline const ssei operator -( const int32_t& a, const ssei& b ) { return ssei(a) - b; }
+__forceinline const ssei operator-(const ssei &a, const ssei &b)
+{
+ return _mm_sub_epi32(a.m128, b.m128);
+}
+__forceinline const ssei operator-(const ssei &a, const int32_t &b)
+{
+ return a - ssei(b);
+}
+__forceinline const ssei operator-(const int32_t &a, const ssei &b)
+{
+ return ssei(a) - b;
+}
-#if defined(__KERNEL_SSE41__)
-__forceinline const ssei operator *( const ssei& a, const ssei& b ) { return _mm_mullo_epi32(a.m128, b.m128); }
-__forceinline const ssei operator *( const ssei& a, const int32_t& b ) { return a * ssei(b); }
-__forceinline const ssei operator *( const int32_t& a, const ssei& b ) { return ssei(a) * b; }
-#endif
+# if defined(__KERNEL_SSE41__)
+__forceinline const ssei operator*(const ssei &a, const ssei &b)
+{
+ return _mm_mullo_epi32(a.m128, b.m128);
+}
+__forceinline const ssei operator*(const ssei &a, const int32_t &b)
+{
+ return a * ssei(b);
+}
+__forceinline const ssei operator*(const int32_t &a, const ssei &b)
+{
+ return ssei(a) * b;
+}
+# endif
-__forceinline const ssei operator &( const ssei& a, const ssei& b ) { return _mm_and_si128(a.m128, b.m128); }
-__forceinline const ssei operator &( const ssei& a, const int32_t& b ) { return a & ssei(b); }
-__forceinline const ssei operator &( const int32_t& a, const ssei& b ) { return ssei(a) & b; }
+__forceinline const ssei operator&(const ssei &a, const ssei &b)
+{
+ return _mm_and_si128(a.m128, b.m128);
+}
+__forceinline const ssei operator&(const ssei &a, const int32_t &b)
+{
+ return a & ssei(b);
+}
+__forceinline const ssei operator&(const int32_t &a, const ssei &b)
+{
+ return ssei(a) & b;
+}
-__forceinline const ssei operator |( const ssei& a, const ssei& b ) { return _mm_or_si128(a.m128, b.m128); }
-__forceinline const ssei operator |( const ssei& a, const int32_t& b ) { return a | ssei(b); }
-__forceinline const ssei operator |( const int32_t& a, const ssei& b ) { return ssei(a) | b; }
+__forceinline const ssei operator|(const ssei &a, const ssei &b)
+{
+ return _mm_or_si128(a.m128, b.m128);
+}
+__forceinline const ssei operator|(const ssei &a, const int32_t &b)
+{
+ return a | ssei(b);
+}
+__forceinline const ssei operator|(const int32_t &a, const ssei &b)
+{
+ return ssei(a) | b;
+}
-__forceinline const ssei operator ^( const ssei& a, const ssei& b ) { return _mm_xor_si128(a.m128, b.m128); }
-__forceinline const ssei operator ^( const ssei& a, const int32_t& b ) { return a ^ ssei(b); }
-__forceinline const ssei operator ^( const int32_t& a, const ssei& b ) { return ssei(a) ^ b; }
+__forceinline const ssei operator^(const ssei &a, const ssei &b)
+{
+ return _mm_xor_si128(a.m128, b.m128);
+}
+__forceinline const ssei operator^(const ssei &a, const int32_t &b)
+{
+ return a ^ ssei(b);
+}
+__forceinline const ssei operator^(const int32_t &a, const ssei &b)
+{
+ return ssei(a) ^ b;
+}
-__forceinline const ssei operator <<( const ssei& a, const int32_t& n ) { return _mm_slli_epi32(a.m128, n); }
-__forceinline const ssei operator >>( const ssei& a, const int32_t& n ) { return _mm_srai_epi32(a.m128, n); }
+__forceinline const ssei operator<<(const ssei &a, const int32_t &n)
+{
+ return _mm_slli_epi32(a.m128, n);
+}
+__forceinline const ssei operator>>(const ssei &a, const int32_t &n)
+{
+ return _mm_srai_epi32(a.m128, n);
+}
-__forceinline const ssei andnot(const ssei& a, const ssei& b) { return _mm_andnot_si128(a.m128,b.m128); }
-__forceinline const ssei andnot(const sseb& a, const ssei& b) { return _mm_andnot_si128(cast(a.m128),b.m128); }
-__forceinline const ssei andnot(const ssei& a, const sseb& b) { return _mm_andnot_si128(a.m128,cast(b.m128)); }
+__forceinline const ssei andnot(const ssei &a, const ssei &b)
+{
+ return _mm_andnot_si128(a.m128, b.m128);
+}
+__forceinline const ssei andnot(const sseb &a, const ssei &b)
+{
+ return _mm_andnot_si128(cast(a.m128), b.m128);
+}
+__forceinline const ssei andnot(const ssei &a, const sseb &b)
+{
+ return _mm_andnot_si128(a.m128, cast(b.m128));
+}
-__forceinline const ssei sra ( const ssei& a, const int32_t& b ) { return _mm_srai_epi32(a.m128, b); }
-__forceinline const ssei srl ( const ssei& a, const int32_t& b ) { return _mm_srli_epi32(a.m128, b); }
+__forceinline const ssei sra(const ssei &a, const int32_t &b)
+{
+ return _mm_srai_epi32(a.m128, b);
+}
+__forceinline const ssei srl(const ssei &a, const int32_t &b)
+{
+ return _mm_srli_epi32(a.m128, b);
+}
-#if defined(__KERNEL_SSE41__)
-__forceinline const ssei min( const ssei& a, const ssei& b ) { return _mm_min_epi32(a.m128, b.m128); }
-__forceinline const ssei min( const ssei& a, const int32_t& b ) { return min(a,ssei(b)); }
-__forceinline const ssei min( const int32_t& a, const ssei& b ) { return min(ssei(a),b); }
+# if defined(__KERNEL_SSE41__)
+__forceinline const ssei min(const ssei &a, const ssei &b)
+{
+ return _mm_min_epi32(a.m128, b.m128);
+}
+__forceinline const ssei min(const ssei &a, const int32_t &b)
+{
+ return min(a, ssei(b));
+}
+__forceinline const ssei min(const int32_t &a, const ssei &b)
+{
+ return min(ssei(a), b);
+}
-__forceinline const ssei max( const ssei& a, const ssei& b ) { return _mm_max_epi32(a.m128, b.m128); }
-__forceinline const ssei max( const ssei& a, const int32_t& b ) { return max(a,ssei(b)); }
-__forceinline const ssei max( const int32_t& a, const ssei& b ) { return max(ssei(a),b); }
-#endif
+__forceinline const ssei max(const ssei &a, const ssei &b)
+{
+ return _mm_max_epi32(a.m128, b.m128);
+}
+__forceinline const ssei max(const ssei &a, const int32_t &b)
+{
+ return max(a, ssei(b));
+}
+__forceinline const ssei max(const int32_t &a, const ssei &b)
+{
+ return max(ssei(a), b);
+}
+# endif
////////////////////////////////////////////////////////////////////////////////
/// Assignment Operators
////////////////////////////////////////////////////////////////////////////////
-__forceinline ssei& operator +=( ssei& a, const ssei& b ) { return a = a + b; }
-__forceinline ssei& operator +=( ssei& a, const int32_t& b ) { return a = a + b; }
+__forceinline ssei &operator+=(ssei &a, const ssei &b)
+{
+ return a = a + b;
+}
+__forceinline ssei &operator+=(ssei &a, const int32_t &b)
+{
+ return a = a + b;
+}
-__forceinline ssei& operator -=( ssei& a, const ssei& b ) { return a = a - b; }
-__forceinline ssei& operator -=( ssei& a, const int32_t& b ) { return a = a - b; }
+__forceinline ssei &operator-=(ssei &a, const ssei &b)
+{
+ return a = a - b;
+}
+__forceinline ssei &operator-=(ssei &a, const int32_t &b)
+{
+ return a = a - b;
+}
-#if defined(__KERNEL_SSE41__)
-__forceinline ssei& operator *=( ssei& a, const ssei& b ) { return a = a * b; }
-__forceinline ssei& operator *=( ssei& a, const int32_t& b ) { return a = a * b; }
-#endif
+# if defined(__KERNEL_SSE41__)
+__forceinline ssei &operator*=(ssei &a, const ssei &b)
+{
+ return a = a * b;
+}
+__forceinline ssei &operator*=(ssei &a, const int32_t &b)
+{
+ return a = a * b;
+}
+# endif
-__forceinline ssei& operator &=( ssei& a, const ssei& b ) { return a = a & b; }
-__forceinline ssei& operator &=( ssei& a, const int32_t& b ) { return a = a & b; }
+__forceinline ssei &operator&=(ssei &a, const ssei &b)
+{
+ return a = a & b;
+}
+__forceinline ssei &operator&=(ssei &a, const int32_t &b)
+{
+ return a = a & b;
+}
-__forceinline ssei& operator |=( ssei& a, const ssei& b ) { return a = a | b; }
-__forceinline ssei& operator |=( ssei& a, const int32_t& b ) { return a = a | b; }
+__forceinline ssei &operator|=(ssei &a, const ssei &b)
+{
+ return a = a | b;
+}
+__forceinline ssei &operator|=(ssei &a, const int32_t &b)
+{
+ return a = a | b;
+}
-__forceinline ssei& operator <<=( ssei& a, const int32_t& b ) { return a = a << b; }
-__forceinline ssei& operator >>=( ssei& a, const int32_t& b ) { return a = a >> b; }
+__forceinline ssei &operator<<=(ssei &a, const int32_t &b)
+{
+ return a = a << b;
+}
+__forceinline ssei &operator>>=(ssei &a, const int32_t &b)
+{
+ return a = a >> b;
+}
////////////////////////////////////////////////////////////////////////////////
/// Comparison Operators + Select
////////////////////////////////////////////////////////////////////////////////
-__forceinline const sseb operator ==( const ssei& a, const ssei& b ) { return _mm_castsi128_ps(_mm_cmpeq_epi32 (a.m128, b.m128)); }
-__forceinline const sseb operator ==( const ssei& a, const int32_t& b ) { return a == ssei(b); }
-__forceinline const sseb operator ==( const int32_t& a, const ssei& b ) { return ssei(a) == b; }
+__forceinline const sseb operator==(const ssei &a, const ssei &b)
+{
+ return _mm_castsi128_ps(_mm_cmpeq_epi32(a.m128, b.m128));
+}
+__forceinline const sseb operator==(const ssei &a, const int32_t &b)
+{
+ return a == ssei(b);
+}
+__forceinline const sseb operator==(const int32_t &a, const ssei &b)
+{
+ return ssei(a) == b;
+}
-__forceinline const sseb operator !=( const ssei& a, const ssei& b ) { return !(a == b); }
-__forceinline const sseb operator !=( const ssei& a, const int32_t& b ) { return a != ssei(b); }
-__forceinline const sseb operator !=( const int32_t& a, const ssei& b ) { return ssei(a) != b; }
+__forceinline const sseb operator!=(const ssei &a, const ssei &b)
+{
+ return !(a == b);
+}
+__forceinline const sseb operator!=(const ssei &a, const int32_t &b)
+{
+ return a != ssei(b);
+}
+__forceinline const sseb operator!=(const int32_t &a, const ssei &b)
+{
+ return ssei(a) != b;
+}
-__forceinline const sseb operator < ( const ssei& a, const ssei& b ) { return _mm_castsi128_ps(_mm_cmplt_epi32 (a.m128, b.m128)); }
-__forceinline const sseb operator < ( const ssei& a, const int32_t& b ) { return a < ssei(b); }
-__forceinline const sseb operator < ( const int32_t& a, const ssei& b ) { return ssei(a) < b; }
+__forceinline const sseb operator<(const ssei &a, const ssei &b)
+{
+ return _mm_castsi128_ps(_mm_cmplt_epi32(a.m128, b.m128));
+}
+__forceinline const sseb operator<(const ssei &a, const int32_t &b)
+{
+ return a < ssei(b);
+}
+__forceinline const sseb operator<(const int32_t &a, const ssei &b)
+{
+ return ssei(a) < b;
+}
-__forceinline const sseb operator >=( const ssei& a, const ssei& b ) { return !(a < b); }
-__forceinline const sseb operator >=( const ssei& a, const int32_t& b ) { return a >= ssei(b); }
-__forceinline const sseb operator >=( const int32_t& a, const ssei& b ) { return ssei(a) >= b; }
+__forceinline const sseb operator>=(const ssei &a, const ssei &b)
+{
+ return !(a < b);
+}
+__forceinline const sseb operator>=(const ssei &a, const int32_t &b)
+{
+ return a >= ssei(b);
+}
+__forceinline const sseb operator>=(const int32_t &a, const ssei &b)
+{
+ return ssei(a) >= b;
+}
-__forceinline const sseb operator > ( const ssei& a, const ssei& b ) { return _mm_castsi128_ps(_mm_cmpgt_epi32 (a.m128, b.m128)); }
-__forceinline const sseb operator > ( const ssei& a, const int32_t& b ) { return a > ssei(b); }
-__forceinline const sseb operator > ( const int32_t& a, const ssei& b ) { return ssei(a) > b; }
+__forceinline const sseb operator>(const ssei &a, const ssei &b)
+{
+ return _mm_castsi128_ps(_mm_cmpgt_epi32(a.m128, b.m128));
+}
+__forceinline const sseb operator>(const ssei &a, const int32_t &b)
+{
+ return a > ssei(b);
+}
+__forceinline const sseb operator>(const int32_t &a, const ssei &b)
+{
+ return ssei(a) > b;
+}
-__forceinline const sseb operator <=( const ssei& a, const ssei& b ) { return !(a > b); }
-__forceinline const sseb operator <=( const ssei& a, const int32_t& b ) { return a <= ssei(b); }
-__forceinline const sseb operator <=( const int32_t& a, const ssei& b ) { return ssei(a) <= b; }
+__forceinline const sseb operator<=(const ssei &a, const ssei &b)
+{
+ return !(a > b);
+}
+__forceinline const sseb operator<=(const ssei &a, const int32_t &b)
+{
+ return a <= ssei(b);
+}
+__forceinline const sseb operator<=(const int32_t &a, const ssei &b)
+{
+ return ssei(a) <= b;
+}
-__forceinline const ssei select( const sseb& m, const ssei& t, const ssei& f ) {
-#ifdef __KERNEL_SSE41__
- return _mm_castps_si128(_mm_blendv_ps(_mm_castsi128_ps(f), _mm_castsi128_ps(t), m));
-#else
- return _mm_or_si128(_mm_and_si128(m, t), _mm_andnot_si128(m, f));
-#endif
+__forceinline const ssei select(const sseb &m, const ssei &t, const ssei &f)
+{
+# ifdef __KERNEL_SSE41__
+ return _mm_castps_si128(_mm_blendv_ps(_mm_castsi128_ps(f), _mm_castsi128_ps(t), m));
+# else
+ return _mm_or_si128(_mm_and_si128(m, t), _mm_andnot_si128(m, f));
+# endif
}
-__forceinline const ssei select( const int mask, const ssei& t, const ssei& f ) {
-#if defined(__KERNEL_SSE41__) && ((!defined(__clang__) && !defined(_MSC_VER)) || defined(__INTEL_COMPILER))
- return _mm_castps_si128(_mm_blend_ps(_mm_castsi128_ps(f), _mm_castsi128_ps(t), mask));
-#else
- return select(sseb(mask),t,f);
-#endif
+__forceinline const ssei select(const int mask, const ssei &t, const ssei &f)
+{
+# if defined(__KERNEL_SSE41__) && \
+ ((!defined(__clang__) && !defined(_MSC_VER)) || defined(__INTEL_COMPILER))
+ return _mm_castps_si128(_mm_blend_ps(_mm_castsi128_ps(f), _mm_castsi128_ps(t), mask));
+# else
+ return select(sseb(mask), t, f);
+# endif
}
////////////////////////////////////////////////////////////////////////////////
// Movement/Shifting/Shuffling Functions
////////////////////////////////////////////////////////////////////////////////
-__forceinline ssei unpacklo( const ssei& a, const ssei& b ) { return _mm_unpacklo_epi32(a, b); }
-__forceinline ssei unpackhi( const ssei& a, const ssei& b ) { return _mm_unpackhi_epi32(a, b); }
+__forceinline ssei unpacklo(const ssei &a, const ssei &b)
+{
+ return _mm_unpacklo_epi32(a, b);
+}
+__forceinline ssei unpackhi(const ssei &a, const ssei &b)
+{
+ return _mm_unpackhi_epi32(a, b);
+}
-template<size_t i0, size_t i1, size_t i2, size_t i3> __forceinline const ssei shuffle( const ssei& a ) {
- return _mm_shuffle_epi32(a, _MM_SHUFFLE(i3, i2, i1, i0));
+template<size_t i0, size_t i1, size_t i2, size_t i3>
+__forceinline const ssei shuffle(const ssei &a)
+{
+ return _mm_shuffle_epi32(a, _MM_SHUFFLE(i3, i2, i1, i0));
}
-template<size_t i0, size_t i1, size_t i2, size_t i3> __forceinline const ssei shuffle( const ssei& a, const ssei& b ) {
- return _mm_castps_si128(_mm_shuffle_ps(_mm_castsi128_ps(a), _mm_castsi128_ps(b), _MM_SHUFFLE(i3, i2, i1, i0)));
+template<size_t i0, size_t i1, size_t i2, size_t i3>
+__forceinline const ssei shuffle(const ssei &a, const ssei &b)
+{
+ return _mm_castps_si128(
+ _mm_shuffle_ps(_mm_castsi128_ps(a), _mm_castsi128_ps(b), _MM_SHUFFLE(i3, i2, i1, i0)));
}
-template<size_t i0> __forceinline const ssei shuffle( const ssei& b ) {
- return shuffle<i0,i0,i0,i0>(b);
+template<size_t i0> __forceinline const ssei shuffle(const ssei &b)
+{
+ return shuffle<i0, i0, i0, i0>(b);
}
-#if defined(__KERNEL_SSE41__)
-template<size_t src> __forceinline int extract( const ssei& b ) { return _mm_extract_epi32(b, src); }
-template<size_t dst> __forceinline const ssei insert( const ssei& a, const int32_t b ) { return _mm_insert_epi32(a, b, dst); }
-#else
-template<size_t src> __forceinline int extract( const ssei& b ) { return b[src]; }
-template<size_t dst> __forceinline const ssei insert( const ssei& a, const int32_t b ) { ssei c = a; c[dst] = b; return c; }
-#endif
+# if defined(__KERNEL_SSE41__)
+template<size_t src> __forceinline int extract(const ssei &b)
+{
+ return _mm_extract_epi32(b, src);
+}
+template<size_t dst> __forceinline const ssei insert(const ssei &a, const int32_t b)
+{
+ return _mm_insert_epi32(a, b, dst);
+}
+# else
+template<size_t src> __forceinline int extract(const ssei &b)
+{
+ return b[src];
+}
+template<size_t dst> __forceinline const ssei insert(const ssei &a, const int32_t b)
+{
+ ssei c = a;
+ c[dst] = b;
+ return c;
+}
+# endif
////////////////////////////////////////////////////////////////////////////////
/// Reductions
////////////////////////////////////////////////////////////////////////////////
-#if defined(__KERNEL_SSE41__)
-__forceinline const ssei vreduce_min(const ssei& v) { ssei h = min(shuffle<1,0,3,2>(v),v); return min(shuffle<2,3,0,1>(h),h); }
-__forceinline const ssei vreduce_max(const ssei& v) { ssei h = max(shuffle<1,0,3,2>(v),v); return max(shuffle<2,3,0,1>(h),h); }
-__forceinline const ssei vreduce_add(const ssei& v) { ssei h = shuffle<1,0,3,2>(v) + v ; return shuffle<2,3,0,1>(h) + h ; }
+# if defined(__KERNEL_SSE41__)
+__forceinline const ssei vreduce_min(const ssei &v)
+{
+ ssei h = min(shuffle<1, 0, 3, 2>(v), v);
+ return min(shuffle<2, 3, 0, 1>(h), h);
+}
+__forceinline const ssei vreduce_max(const ssei &v)
+{
+ ssei h = max(shuffle<1, 0, 3, 2>(v), v);
+ return max(shuffle<2, 3, 0, 1>(h), h);
+}
+__forceinline const ssei vreduce_add(const ssei &v)
+{
+ ssei h = shuffle<1, 0, 3, 2>(v) + v;
+ return shuffle<2, 3, 0, 1>(h) + h;
+}
-__forceinline int reduce_min(const ssei& v) { return extract<0>(vreduce_min(v)); }
-__forceinline int reduce_max(const ssei& v) { return extract<0>(vreduce_max(v)); }
-__forceinline int reduce_add(const ssei& v) { return extract<0>(vreduce_add(v)); }
+__forceinline int reduce_min(const ssei &v)
+{
+ return extract<0>(vreduce_min(v));
+}
+__forceinline int reduce_max(const ssei &v)
+{
+ return extract<0>(vreduce_max(v));
+}
+__forceinline int reduce_add(const ssei &v)
+{
+ return extract<0>(vreduce_add(v));
+}
-__forceinline size_t select_min(const ssei& v) { return __bsf(movemask(v == vreduce_min(v))); }
-__forceinline size_t select_max(const ssei& v) { return __bsf(movemask(v == vreduce_max(v))); }
+__forceinline size_t select_min(const ssei &v)
+{
+ return __bsf(movemask(v == vreduce_min(v)));
+}
+__forceinline size_t select_max(const ssei &v)
+{
+ return __bsf(movemask(v == vreduce_max(v)));
+}
-__forceinline size_t select_min(const sseb& valid, const ssei& v) { const ssei a = select(valid,v,ssei((int)pos_inf)); return __bsf(movemask(valid & (a == vreduce_min(a)))); }
-__forceinline size_t select_max(const sseb& valid, const ssei& v) { const ssei a = select(valid,v,ssei((int)neg_inf)); return __bsf(movemask(valid & (a == vreduce_max(a)))); }
+__forceinline size_t select_min(const sseb &valid, const ssei &v)
+{
+ const ssei a = select(valid, v, ssei((int)pos_inf));
+ return __bsf(movemask(valid & (a == vreduce_min(a))));
+}
+__forceinline size_t select_max(const sseb &valid, const ssei &v)
+{
+ const ssei a = select(valid, v, ssei((int)neg_inf));
+ return __bsf(movemask(valid & (a == vreduce_max(a))));
+}
-#else
+# else
-__forceinline int ssei_min(int a, int b) { return (a < b)? a: b; }
-__forceinline int ssei_max(int a, int b) { return (a > b)? a: b; }
-__forceinline int reduce_min(const ssei& v) { return ssei_min(ssei_min(v[0],v[1]),ssei_min(v[2],v[3])); }
-__forceinline int reduce_max(const ssei& v) { return ssei_max(ssei_max(v[0],v[1]),ssei_max(v[2],v[3])); }
-__forceinline int reduce_add(const ssei& v) { return v[0]+v[1]+v[2]+v[3]; }
+__forceinline int ssei_min(int a, int b)
+{
+ return (a < b) ? a : b;
+}
+__forceinline int ssei_max(int a, int b)
+{
+ return (a > b) ? a : b;
+}
+__forceinline int reduce_min(const ssei &v)
+{
+ return ssei_min(ssei_min(v[0], v[1]), ssei_min(v[2], v[3]));
+}
+__forceinline int reduce_max(const ssei &v)
+{
+ return ssei_max(ssei_max(v[0], v[1]), ssei_max(v[2], v[3]));
+}
+__forceinline int reduce_add(const ssei &v)
+{
+ return v[0] + v[1] + v[2] + v[3];
+}
-#endif
+# endif
////////////////////////////////////////////////////////////////////////////////
/// Memory load and store operations
////////////////////////////////////////////////////////////////////////////////
-__forceinline ssei load4i( const void* const a ) {
- return _mm_load_si128((__m128i*)a);
+__forceinline ssei load4i(const void *const a)
+{
+ return _mm_load_si128((__m128i *)a);
}
-__forceinline void store4i(void* ptr, const ssei& v) {
- _mm_store_si128((__m128i*)ptr,v);
+__forceinline void store4i(void *ptr, const ssei &v)
+{
+ _mm_store_si128((__m128i *)ptr, v);
}
-__forceinline void storeu4i(void* ptr, const ssei& v) {
- _mm_storeu_si128((__m128i*)ptr,v);
+__forceinline void storeu4i(void *ptr, const ssei &v)
+{
+ _mm_storeu_si128((__m128i *)ptr, v);
}
-__forceinline void store4i( const sseb& mask, void* ptr, const ssei& i ) {
-#if defined (__KERNEL_AVX__)
- _mm_maskstore_ps((float*)ptr,(__m128i)mask,_mm_castsi128_ps(i));
-#else
- *(ssei*)ptr = select(mask,i,*(ssei*)ptr);
-#endif
+__forceinline void store4i(const sseb &mask, void *ptr, const ssei &i)
+{
+# if defined(__KERNEL_AVX__)
+ _mm_maskstore_ps((float *)ptr, (__m128i)mask, _mm_castsi128_ps(i));
+# else
+ *(ssei *)ptr = select(mask, i, *(ssei *)ptr);
+# endif
}
-__forceinline ssei load4i_nt (void* ptr) {
-#if defined(__KERNEL_SSE41__)
- return _mm_stream_load_si128((__m128i*)ptr);
-#else
- return _mm_load_si128((__m128i*)ptr);
-#endif
+__forceinline ssei load4i_nt(void *ptr)
+{
+# if defined(__KERNEL_SSE41__)
+ return _mm_stream_load_si128((__m128i *)ptr);
+# else
+ return _mm_load_si128((__m128i *)ptr);
+# endif
}
-__forceinline void store4i_nt(void* ptr, const ssei& v) {
-#if defined(__KERNEL_SSE41__)
- _mm_stream_ps((float*)ptr,_mm_castsi128_ps(v));
-#else
- _mm_store_si128((__m128i*)ptr,v);
-#endif
+__forceinline void store4i_nt(void *ptr, const ssei &v)
+{
+# if defined(__KERNEL_SSE41__)
+ _mm_stream_ps((float *)ptr, _mm_castsi128_ps(v));
+# else
+ _mm_store_si128((__m128i *)ptr, v);
+# endif
}
////////////////////////////////////////////////////////////////////////////////
@@ -291,8 +604,7 @@ __forceinline void store4i_nt(void* ptr, const ssei& v) {
ccl_device_inline void print_ssei(const char *label, const ssei &a)
{
- printf("%s: %df %df %df %d\n",
- label, a[0], a[1], a[2], a[3]);
+ printf("%s: %df %df %df %d\n", label, a[0], a[1], a[2], a[3]);
}
#endif
diff --git a/intern/cycles/util/util_stack_allocator.h b/intern/cycles/util/util_stack_allocator.h
index 4e978e18bee..36db655e5eb 100644
--- a/intern/cycles/util/util_stack_allocator.h
+++ b/intern/cycles/util/util_stack_allocator.h
@@ -23,145 +23,143 @@
CCL_NAMESPACE_BEGIN
/* Stack allocator for the use with STL. */
-template <int SIZE, typename T>
-class ccl_try_align(16) StackAllocator {
-public:
- typedef size_t size_type;
- typedef ptrdiff_t difference_type;
- typedef T *pointer;
- typedef const T *const_pointer;
- typedef T& reference;
- typedef const T& const_reference;
- typedef T value_type;
-
- /* Allocator construction/destruction. */
-
- StackAllocator()
- : pointer_(0),
- use_stack_(true) {}
-
- StackAllocator(const StackAllocator&)
- : pointer_(0),
- use_stack_(true) {}
-
- template <class U>
- StackAllocator(const StackAllocator<SIZE, U>&)
- : pointer_(0),
- use_stack_(false) {}
-
- /* Memory allocation/deallocation. */
-
- T *allocate(size_t n, const void *hint = 0)
- {
- (void) hint;
- if(n == 0) {
- return NULL;
- }
- if(pointer_ + n >= SIZE || use_stack_ == false) {
- size_t size = n * sizeof(T);
- util_guarded_mem_alloc(size);
- T *mem;
+template<int SIZE, typename T> class ccl_try_align(16) StackAllocator
+{
+ public:
+ typedef size_t size_type;
+ typedef ptrdiff_t difference_type;
+ typedef T *pointer;
+ typedef const T *const_pointer;
+ typedef T &reference;
+ typedef const T &const_reference;
+ typedef T value_type;
+
+ /* Allocator construction/destruction. */
+
+ StackAllocator() : pointer_(0), use_stack_(true)
+ {
+ }
+
+ StackAllocator(const StackAllocator &) : pointer_(0), use_stack_(true)
+ {
+ }
+
+ template<class U>
+ StackAllocator(const StackAllocator<SIZE, U> &) : pointer_(0), use_stack_(false)
+ {
+ }
+
+ /* Memory allocation/deallocation. */
+
+ T *allocate(size_t n, const void *hint = 0)
+ {
+ (void)hint;
+ if (n == 0) {
+ return NULL;
+ }
+ if (pointer_ + n >= SIZE || use_stack_ == false) {
+ size_t size = n * sizeof(T);
+ util_guarded_mem_alloc(size);
+ T *mem;
#ifdef WITH_BLENDER_GUARDEDALLOC
- mem = (T*)MEM_mallocN_aligned(size, 16, "Cycles Alloc");
+ mem = (T *)MEM_mallocN_aligned(size, 16, "Cycles Alloc");
#else
- mem = (T*)malloc(size);
+ mem = (T *)malloc(size);
#endif
- if(mem == NULL) {
- throw std::bad_alloc();
- }
- return mem;
- }
- T *mem = &data_[pointer_];
- pointer_ += n;
- return mem;
- }
-
- void deallocate(T *p, size_t n)
- {
- if(p == NULL) {
- return;
- }
- if(p < data_ || p >= data_ + SIZE) {
- util_guarded_mem_free(n * sizeof(T));
+ if (mem == NULL) {
+ throw std::bad_alloc();
+ }
+ return mem;
+ }
+ T *mem = &data_[pointer_];
+ pointer_ += n;
+ return mem;
+ }
+
+ void deallocate(T * p, size_t n)
+ {
+ if (p == NULL) {
+ return;
+ }
+ if (p < data_ || p >= data_ + SIZE) {
+ util_guarded_mem_free(n * sizeof(T));
#ifdef WITH_BLENDER_GUARDEDALLOC
- MEM_freeN(p);
+ MEM_freeN(p);
#else
- free(p);
+ free(p);
#endif
- return;
- }
- /* We don't support memory free for the stack allocator. */
- }
-
- /* Address of an reference. */
-
- T *address(T& x) const
- {
- return &x;
- }
-
- const T *address(const T& x) const
- {
- return &x;
- }
-
- /* Object construction/destruction. */
-
- void construct(T *p, const T& val)
- {
- if(p != NULL) {
- new ((T *)p) T(val);
- }
- }
-
- void destroy(T *p)
- {
- p->~T();
- }
-
- /* Maximum allocation size. */
-
- size_t max_size() const
- {
- return size_t(-1);
- }
-
- /* Rebind to other ype of allocator. */
-
- template <class U>
- struct rebind {
- typedef StackAllocator<SIZE, U> other;
- };
-
- /* Operators */
-
- template <class U>
- inline StackAllocator& operator=(const StackAllocator<SIZE, U>&)
- {
- return *this;
- }
-
- StackAllocator<SIZE, T>& operator=(const StackAllocator&)
- {
- return *this;
- }
-
- inline bool operator==(StackAllocator const& /*other*/) const
- {
- return true;
- }
-
- inline bool operator!=(StackAllocator const& other) const
- {
- return !operator==(other);
- }
-
-private:
- int pointer_;
- bool use_stack_;
- T data_[SIZE];
+ return;
+ }
+ /* We don't support memory free for the stack allocator. */
+ }
+
+ /* Address of an reference. */
+
+ T *address(T & x) const
+ {
+ return &x;
+ }
+
+ const T *address(const T &x) const
+ {
+ return &x;
+ }
+
+ /* Object construction/destruction. */
+
+ void construct(T * p, const T &val)
+ {
+ if (p != NULL) {
+ new ((T *)p) T(val);
+ }
+ }
+
+ void destroy(T * p)
+ {
+ p->~T();
+ }
+
+ /* Maximum allocation size. */
+
+ size_t max_size() const
+ {
+ return size_t(-1);
+ }
+
+ /* Rebind to other ype of allocator. */
+
+ template<class U> struct rebind {
+ typedef StackAllocator<SIZE, U> other;
+ };
+
+ /* Operators */
+
+ template<class U> inline StackAllocator &operator=(const StackAllocator<SIZE, U> &)
+ {
+ return *this;
+ }
+
+ StackAllocator<SIZE, T> &operator=(const StackAllocator &)
+ {
+ return *this;
+ }
+
+ inline bool operator==(StackAllocator const & /*other*/) const
+ {
+ return true;
+ }
+
+ inline bool operator!=(StackAllocator const &other) const
+ {
+ return !operator==(other);
+ }
+
+ private:
+ int pointer_;
+ bool use_stack_;
+ T data_[SIZE];
};
CCL_NAMESPACE_END
-#endif /* __UTIL_STACK_ALLOCATOR_H__ */
+#endif /* __UTIL_STACK_ALLOCATOR_H__ */
diff --git a/intern/cycles/util/util_static_assert.h b/intern/cycles/util/util_static_assert.h
index b1c6c374693..b4b972a4036 100644
--- a/intern/cycles/util/util_static_assert.h
+++ b/intern/cycles/util/util_static_assert.h
@@ -15,18 +15,18 @@
*/
#ifndef __UTIL_STATIC_ASSERT_H__
-#define __UTIL_STATIC_ASSERT_H__
+# define __UTIL_STATIC_ASSERT_H__
CCL_NAMESPACE_BEGIN
/* TODO(sergey): In theory CUDA might work with own static assert
* implementation since it's just pure C++.
*/
-#ifdef __KERNEL_GPU__
-# ifndef static_assert
-# define static_assert(statement, message)
-# endif
-#endif /* __KERNEL_GPU__ */
+# ifdef __KERNEL_GPU__
+# ifndef static_assert
+# define static_assert(statement, message)
+# endif
+# endif /* __KERNEL_GPU__ */
/* TODO(sergey): For until C++11 is a bare minimum for us,
* we do a bit of a trickery to show meaningful message so
@@ -43,8 +43,8 @@ CCL_NAMESPACE_BEGIN
* name to the error message,
*/
# define static_assert_align(st, align) \
- static_assert((sizeof(st) % (align) == 0), "Structure must be strictly aligned") // NOLINT
+ static_assert((sizeof(st) % (align) == 0), "Structure must be strictly aligned") // NOLINT
CCL_NAMESPACE_END
-#endif /* __UTIL_STATIC_ASSERT_H__ */
+#endif /* __UTIL_STATIC_ASSERT_H__ */
diff --git a/intern/cycles/util/util_stats.h b/intern/cycles/util/util_stats.h
index f1f2df94e33..15cf836de3c 100644
--- a/intern/cycles/util/util_stats.h
+++ b/intern/cycles/util/util_stats.h
@@ -23,26 +23,32 @@
CCL_NAMESPACE_BEGIN
class Stats {
-public:
- enum static_init_t { static_init = 0 };
-
- Stats() : mem_used(0), mem_peak(0) {}
- explicit Stats(static_init_t) {}
-
- void mem_alloc(size_t size) {
- atomic_add_and_fetch_z(&mem_used, size);
- atomic_fetch_and_update_max_z(&mem_peak, mem_used);
- }
-
- void mem_free(size_t size) {
- assert(mem_used >= size);
- atomic_sub_and_fetch_z(&mem_used, size);
- }
-
- size_t mem_used;
- size_t mem_peak;
+ public:
+ enum static_init_t { static_init = 0 };
+
+ Stats() : mem_used(0), mem_peak(0)
+ {
+ }
+ explicit Stats(static_init_t)
+ {
+ }
+
+ void mem_alloc(size_t size)
+ {
+ atomic_add_and_fetch_z(&mem_used, size);
+ atomic_fetch_and_update_max_z(&mem_peak, mem_used);
+ }
+
+ void mem_free(size_t size)
+ {
+ assert(mem_used >= size);
+ atomic_sub_and_fetch_z(&mem_used, size);
+ }
+
+ size_t mem_used;
+ size_t mem_peak;
};
CCL_NAMESPACE_END
-#endif /* __UTIL_STATS_H__ */
+#endif /* __UTIL_STATS_H__ */
diff --git a/intern/cycles/util/util_string.cpp b/intern/cycles/util/util_string.cpp
index 47119e90a45..afcca7e0411 100644
--- a/intern/cycles/util/util_string.cpp
+++ b/intern/cycles/util/util_string.cpp
@@ -25,276 +25,232 @@
# ifndef vsnprintf
# define vsnprintf _vsnprintf
# endif
-#endif /* _WIN32 */
+#endif /* _WIN32 */
CCL_NAMESPACE_BEGIN
string string_printf(const char *format, ...)
{
- vector<char> str(128, 0);
-
- while(1) {
- va_list args;
- int result;
-
- va_start(args, format);
- result = vsnprintf(&str[0], str.size(), format, args);
- va_end(args);
-
- if(result == -1) {
- /* not enough space or formatting error */
- if(str.size() > 65536) {
- assert(0);
- return string("");
- }
-
- str.resize(str.size()*2, 0);
- continue;
- }
- else if(result >= (int)str.size()) {
- /* not enough space */
- str.resize(result + 1, 0);
- continue;
- }
-
- return string(&str[0]);
- }
+ vector<char> str(128, 0);
+
+ while (1) {
+ va_list args;
+ int result;
+
+ va_start(args, format);
+ result = vsnprintf(&str[0], str.size(), format, args);
+ va_end(args);
+
+ if (result == -1) {
+ /* not enough space or formatting error */
+ if (str.size() > 65536) {
+ assert(0);
+ return string("");
+ }
+
+ str.resize(str.size() * 2, 0);
+ continue;
+ }
+ else if (result >= (int)str.size()) {
+ /* not enough space */
+ str.resize(result + 1, 0);
+ continue;
+ }
+
+ return string(&str[0]);
+ }
}
-bool string_iequals(const string& a, const string& b)
+bool string_iequals(const string &a, const string &b)
{
- if(a.size() == b.size()) {
- for(size_t i = 0; i < a.size(); i++)
- if(toupper(a[i]) != toupper(b[i]))
- return false;
+ if (a.size() == b.size()) {
+ for (size_t i = 0; i < a.size(); i++)
+ if (toupper(a[i]) != toupper(b[i]))
+ return false;
- return true;
- }
+ return true;
+ }
- return false;
+ return false;
}
-void string_split(vector<string>& tokens,
- const string& str,
- const string& separators,
+void string_split(vector<string> &tokens,
+ const string &str,
+ const string &separators,
bool skip_empty_tokens)
{
- size_t token_start = 0, token_length = 0;
- for(size_t i = 0; i < str.size(); ++i) {
- const char ch = str[i];
- if(separators.find(ch) == string::npos) {
- /* Current character is not a separator,
- * append it to token by increasing token length.
- */
- ++token_length;
- }
- else {
- /* Current character is a separator,
- * append current token to the list.
- */
- if(!skip_empty_tokens || token_length > 0) {
- string token = str.substr(token_start, token_length);
- tokens.push_back(token);
- }
- token_start = i + 1;
- token_length = 0;
- }
- }
- /* Append token from the tail of the string if exists. */
- if(token_length) {
- string token = str.substr(token_start, token_length);
- tokens.push_back(token);
- }
+ size_t token_start = 0, token_length = 0;
+ for (size_t i = 0; i < str.size(); ++i) {
+ const char ch = str[i];
+ if (separators.find(ch) == string::npos) {
+ /* Current character is not a separator,
+ * append it to token by increasing token length.
+ */
+ ++token_length;
+ }
+ else {
+ /* Current character is a separator,
+ * append current token to the list.
+ */
+ if (!skip_empty_tokens || token_length > 0) {
+ string token = str.substr(token_start, token_length);
+ tokens.push_back(token);
+ }
+ token_start = i + 1;
+ token_length = 0;
+ }
+ }
+ /* Append token from the tail of the string if exists. */
+ if (token_length) {
+ string token = str.substr(token_start, token_length);
+ tokens.push_back(token);
+ }
}
-bool string_startswith(const string& s, const char *start)
+bool string_startswith(const string &s, const char *start)
{
- size_t len = strlen(start);
+ size_t len = strlen(start);
- if(len > s.size())
- return 0;
- else
- return strncmp(s.c_str(), start, len) == 0;
+ if (len > s.size())
+ return 0;
+ else
+ return strncmp(s.c_str(), start, len) == 0;
}
-bool string_endswith(const string& s, const char *end)
+bool string_endswith(const string &s, const char *end)
{
- size_t len = strlen(end);
+ size_t len = strlen(end);
- if(len > s.size())
- return 0;
- else
- return strncmp(s.c_str() + s.size() - len, end, len) == 0;
+ if (len > s.size())
+ return 0;
+ else
+ return strncmp(s.c_str() + s.size() - len, end, len) == 0;
}
-string string_strip(const string& s)
+string string_strip(const string &s)
{
- string result = s;
- result.erase(0, result.find_first_not_of(' '));
- result.erase(result.find_last_not_of(' ') + 1);
- return result;
-
+ string result = s;
+ result.erase(0, result.find_first_not_of(' '));
+ result.erase(result.find_last_not_of(' ') + 1);
+ return result;
}
-void string_replace(string& haystack, const string& needle, const string& other)
+void string_replace(string &haystack, const string &needle, const string &other)
{
- size_t i = 0, index;
- while((index = haystack.find(needle, i)) != string::npos) {
- haystack.replace(index, needle.size(), other);
- i = index + other.size();
- }
+ size_t i = 0, index;
+ while ((index = haystack.find(needle, i)) != string::npos) {
+ haystack.replace(index, needle.size(), other);
+ i = index + other.size();
+ }
}
string string_remove_trademark(const string &s)
{
- string result = s;
+ string result = s;
- /* Special case, so we don;t leave sequential spaces behind. */
- /* TODO(sergey): Consider using regex perhaps? */
- string_replace(result, " (TM)", "");
- string_replace(result, " (R)", "");
+ /* Special case, so we don;t leave sequential spaces behind. */
+ /* TODO(sergey): Consider using regex perhaps? */
+ string_replace(result, " (TM)", "");
+ string_replace(result, " (R)", "");
- string_replace(result, "(TM)", "");
- string_replace(result, "(R)", "");
+ string_replace(result, "(TM)", "");
+ string_replace(result, "(R)", "");
- return string_strip(result);
+ return string_strip(result);
}
string string_from_bool(bool var)
{
- if(var)
- return "True";
- else
- return "False";
+ if (var)
+ return "True";
+ else
+ return "False";
}
string to_string(const char *str)
{
- return string(str);
+ return string(str);
}
/* Wide char strings helpers for Windows. */
#ifdef _WIN32
-wstring string_to_wstring(const string& str)
+wstring string_to_wstring(const string &str)
{
- const int length_wc = MultiByteToWideChar(CP_UTF8,
- 0,
- str.c_str(),
- str.length(),
- NULL,
- 0);
- wstring str_wc(length_wc, 0);
- MultiByteToWideChar(CP_UTF8,
- 0,
- str.c_str(),
- str.length(),
- &str_wc[0],
- length_wc);
- return str_wc;
+ const int length_wc = MultiByteToWideChar(CP_UTF8, 0, str.c_str(), str.length(), NULL, 0);
+ wstring str_wc(length_wc, 0);
+ MultiByteToWideChar(CP_UTF8, 0, str.c_str(), str.length(), &str_wc[0], length_wc);
+ return str_wc;
}
-string string_from_wstring(const wstring& str)
+string string_from_wstring(const wstring &str)
{
- int length_mb = WideCharToMultiByte(CP_UTF8,
- 0,
- str.c_str(),
- str.size(),
- NULL,
- 0,
- NULL, NULL);
- string str_mb(length_mb, 0);
- WideCharToMultiByte(CP_UTF8,
- 0,
- str.c_str(),
- str.size(),
- &str_mb[0],
- length_mb,
- NULL, NULL);
- return str_mb;
+ int length_mb = WideCharToMultiByte(CP_UTF8, 0, str.c_str(), str.size(), NULL, 0, NULL, NULL);
+ string str_mb(length_mb, 0);
+ WideCharToMultiByte(CP_UTF8, 0, str.c_str(), str.size(), &str_mb[0], length_mb, NULL, NULL);
+ return str_mb;
}
-string string_to_ansi(const string& str)
+string string_to_ansi(const string &str)
{
- const int length_wc = MultiByteToWideChar(CP_UTF8,
- 0,
- str.c_str(),
- str.length(),
- NULL,
- 0);
- wstring str_wc(length_wc, 0);
- MultiByteToWideChar(CP_UTF8,
- 0,
- str.c_str(),
- str.length(),
- &str_wc[0],
- length_wc);
-
- int length_mb = WideCharToMultiByte(CP_ACP,
- 0,
- str_wc.c_str(),
- str_wc.size(),
- NULL,
- 0,
- NULL, NULL);
-
- string str_mb(length_mb, 0);
- WideCharToMultiByte(CP_ACP,
- 0,
- str_wc.c_str(),
- str_wc.size(),
- &str_mb[0],
- length_mb,
- NULL, NULL);
-
- return str_mb;
+ const int length_wc = MultiByteToWideChar(CP_UTF8, 0, str.c_str(), str.length(), NULL, 0);
+ wstring str_wc(length_wc, 0);
+ MultiByteToWideChar(CP_UTF8, 0, str.c_str(), str.length(), &str_wc[0], length_wc);
+
+ int length_mb = WideCharToMultiByte(
+ CP_ACP, 0, str_wc.c_str(), str_wc.size(), NULL, 0, NULL, NULL);
+
+ string str_mb(length_mb, 0);
+ WideCharToMultiByte(CP_ACP, 0, str_wc.c_str(), str_wc.size(), &str_mb[0], length_mb, NULL, NULL);
+
+ return str_mb;
}
-#endif /* _WIN32 */
+#endif /* _WIN32 */
string string_human_readable_size(size_t size)
{
- static const char suffixes[] = "BKMGTPEZY";
+ static const char suffixes[] = "BKMGTPEZY";
- const char* suffix = suffixes;
- size_t r = 0;
+ const char *suffix = suffixes;
+ size_t r = 0;
- while(size >= 1024) {
- r = size % 1024;
- size /= 1024;
- suffix++;
- }
+ while (size >= 1024) {
+ r = size % 1024;
+ size /= 1024;
+ suffix++;
+ }
- if(*suffix != 'B')
- return string_printf("%.2f%c", double(size*1024+r)/1024.0, *suffix);
- else
- return string_printf("%zu", size);
+ if (*suffix != 'B')
+ return string_printf("%.2f%c", double(size * 1024 + r) / 1024.0, *suffix);
+ else
+ return string_printf("%zu", size);
}
string string_human_readable_number(size_t num)
{
- if(num == 0) {
- return "0";
- }
+ if (num == 0) {
+ return "0";
+ }
- /* Add thousands separators. */
- char buf[32];
+ /* Add thousands separators. */
+ char buf[32];
- char* p = buf+31;
- *p = '\0';
+ char *p = buf + 31;
+ *p = '\0';
- int i = -1;
- while(num) {
- if(++i && i % 3 == 0)
- *(--p) = ',';
+ int i = -1;
+ while (num) {
+ if (++i && i % 3 == 0)
+ *(--p) = ',';
- *(--p) = '0' + (num % 10);
+ *(--p) = '0' + (num % 10);
- num /= 10;
- }
+ num /= 10;
+ }
- return p;
+ return p;
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/util/util_string.h b/intern/cycles/util/util_string.h
index 02584fe5113..f71145741c9 100644
--- a/intern/cycles/util/util_string.h
+++ b/intern/cycles/util/util_string.h
@@ -25,30 +25,30 @@
CCL_NAMESPACE_BEGIN
+using std::istringstream;
+using std::ostringstream;
using std::string;
using std::stringstream;
-using std::ostringstream;
-using std::istringstream;
using std::to_string;
#ifdef __GNUC__
-#define PRINTF_ATTRIBUTE __attribute__((format(printf, 1, 2)))
+# define PRINTF_ATTRIBUTE __attribute__((format(printf, 1, 2)))
#else
-#define PRINTF_ATTRIBUTE
+# define PRINTF_ATTRIBUTE
#endif
string string_printf(const char *format, ...) PRINTF_ATTRIBUTE;
-bool string_iequals(const string& a, const string& b);
-void string_split(vector<string>& tokens,
- const string& str,
- const string& separators = "\t ",
+bool string_iequals(const string &a, const string &b);
+void string_split(vector<string> &tokens,
+ const string &str,
+ const string &separators = "\t ",
bool skip_empty_tokens = true);
-void string_replace(string& haystack, const string& needle, const string& other);
-bool string_startswith(const string& s, const char *start);
-bool string_endswith(const string& s, const char *end);
-string string_strip(const string& s);
-string string_remove_trademark(const string& s);
+void string_replace(string &haystack, const string &needle, const string &other);
+bool string_startswith(const string &s, const char *start);
+bool string_endswith(const string &s, const char *end);
+string string_strip(const string &s);
+string string_remove_trademark(const string &s);
string string_from_bool(const bool var);
string to_string(const char *str);
@@ -61,9 +61,9 @@ string to_string(const char *str);
*/
#ifdef _WIN32
using std::wstring;
-wstring string_to_wstring(const string& path);
-string string_from_wstring(const wstring& path);
-string string_to_ansi(const string& str);
+wstring string_to_wstring(const string &path);
+string string_from_wstring(const wstring &path);
+string string_to_ansi(const string &str);
#endif
/* Make a string from a size in bytes in human readable form */
@@ -73,4 +73,4 @@ string string_human_readable_number(size_t num);
CCL_NAMESPACE_END
-#endif /* __UTIL_STRING_H__ */
+#endif /* __UTIL_STRING_H__ */
diff --git a/intern/cycles/util/util_system.cpp b/intern/cycles/util/util_system.cpp
index 2a5c4a8f012..0cd991c6231 100644
--- a/intern/cycles/util/util_system.cpp
+++ b/intern/cycles/util/util_system.cpp
@@ -26,7 +26,7 @@
OIIO_NAMESPACE_USING
#ifdef _WIN32
-# if(!defined(FREE_WINDOWS))
+# if (!defined(FREE_WINDOWS))
# include <intrin.h>
# endif
# include "util_windows.h"
@@ -43,333 +43,332 @@ CCL_NAMESPACE_BEGIN
bool system_cpu_ensure_initialized()
{
- static bool is_initialized = false;
- static bool result = false;
- if(is_initialized) {
- return result;
- }
- is_initialized = true;
- const NUMAAPI_Result numa_result = numaAPI_Initialize();
- result = (numa_result == NUMAAPI_SUCCESS);
- return result;
+ static bool is_initialized = false;
+ static bool result = false;
+ if (is_initialized) {
+ return result;
+ }
+ is_initialized = true;
+ const NUMAAPI_Result numa_result = numaAPI_Initialize();
+ result = (numa_result == NUMAAPI_SUCCESS);
+ return result;
}
/* Fallback solution, which doesn't use NUMA/CPU groups. */
static int system_cpu_thread_count_fallback()
{
#ifdef _WIN32
- SYSTEM_INFO info;
- GetSystemInfo(&info);
- return info.dwNumberOfProcessors;
+ SYSTEM_INFO info;
+ GetSystemInfo(&info);
+ return info.dwNumberOfProcessors;
#elif defined(__APPLE__)
- int count;
- size_t len = sizeof(count);
- int mib[2] = { CTL_HW, HW_NCPU };
- sysctl(mib, 2, &count, &len, NULL, 0);
- return count;
+ int count;
+ size_t len = sizeof(count);
+ int mib[2] = {CTL_HW, HW_NCPU};
+ sysctl(mib, 2, &count, &len, NULL, 0);
+ return count;
#else
- return sysconf(_SC_NPROCESSORS_ONLN);
+ return sysconf(_SC_NPROCESSORS_ONLN);
#endif
}
int system_cpu_thread_count()
{
- const int num_nodes = system_cpu_num_numa_nodes();
- int num_threads = 0;
- for(int node = 0; node < num_nodes; ++node) {
- if(!system_cpu_is_numa_node_available(node)) {
- continue;
- }
- num_threads += system_cpu_num_numa_node_processors(node);
- }
- return num_threads;
+ const int num_nodes = system_cpu_num_numa_nodes();
+ int num_threads = 0;
+ for (int node = 0; node < num_nodes; ++node) {
+ if (!system_cpu_is_numa_node_available(node)) {
+ continue;
+ }
+ num_threads += system_cpu_num_numa_node_processors(node);
+ }
+ return num_threads;
}
int system_cpu_num_numa_nodes()
{
- if(!system_cpu_ensure_initialized()) {
- /* Fallback to a single node with all the threads. */
- return 1;
- }
- return numaAPI_GetNumNodes();
+ if (!system_cpu_ensure_initialized()) {
+ /* Fallback to a single node with all the threads. */
+ return 1;
+ }
+ return numaAPI_GetNumNodes();
}
bool system_cpu_is_numa_node_available(int node)
{
- if(!system_cpu_ensure_initialized()) {
- return true;
- }
- return numaAPI_IsNodeAvailable(node);
+ if (!system_cpu_ensure_initialized()) {
+ return true;
+ }
+ return numaAPI_IsNodeAvailable(node);
}
int system_cpu_num_numa_node_processors(int node)
{
- if(!system_cpu_ensure_initialized()) {
- return system_cpu_thread_count_fallback();
- }
- return numaAPI_GetNumNodeProcessors(node);
+ if (!system_cpu_ensure_initialized()) {
+ return system_cpu_thread_count_fallback();
+ }
+ return numaAPI_GetNumNodeProcessors(node);
}
bool system_cpu_run_thread_on_node(int node)
{
- if(!system_cpu_ensure_initialized()) {
- return true;
- }
- return numaAPI_RunThreadOnNode(node);
+ if (!system_cpu_ensure_initialized()) {
+ return true;
+ }
+ return numaAPI_RunThreadOnNode(node);
}
int system_console_width()
{
- int columns = 0;
+ int columns = 0;
#ifdef _WIN32
- CONSOLE_SCREEN_BUFFER_INFO csbi;
- if(GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &csbi)) {
- columns = csbi.dwSize.X;
- }
+ CONSOLE_SCREEN_BUFFER_INFO csbi;
+ if (GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &csbi)) {
+ columns = csbi.dwSize.X;
+ }
#else
- struct winsize w;
- if(ioctl(STDOUT_FILENO, TIOCGWINSZ, &w) == 0) {
- columns = w.ws_col;
- }
+ struct winsize w;
+ if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &w) == 0) {
+ columns = w.ws_col;
+ }
#endif
- return (columns > 0) ? columns : 80;
+ return (columns > 0) ? columns : 80;
}
int system_cpu_num_active_group_processors()
{
- if(!system_cpu_ensure_initialized()) {
- return system_cpu_thread_count_fallback();
- }
- return numaAPI_GetNumCurrentNodesProcessors();
+ if (!system_cpu_ensure_initialized()) {
+ return system_cpu_thread_count_fallback();
+ }
+ return numaAPI_GetNumCurrentNodesProcessors();
}
#if !defined(_WIN32) || defined(FREE_WINDOWS)
static void __cpuid(int data[4], int selector)
{
-#if defined(__x86_64__)
- asm("cpuid" : "=a" (data[0]), "=b" (data[1]), "=c" (data[2]), "=d" (data[3]) : "a"(selector));
-#elif defined(__i386__)
- asm("pushl %%ebx \n\t"
- "cpuid \n\t"
- "movl %%ebx, %1 \n\t"
- "popl %%ebx \n\t"
- : "=a" (data[0]), "=r" (data[1]), "=c" (data[2]), "=d" (data[3])
- : "a"(selector)
- : "ebx");
-#else
- data[0] = data[1] = data[2] = data[3] = 0;
-#endif
+# if defined(__x86_64__)
+ asm("cpuid" : "=a"(data[0]), "=b"(data[1]), "=c"(data[2]), "=d"(data[3]) : "a"(selector));
+# elif defined(__i386__)
+ asm("pushl %%ebx \n\t"
+ "cpuid \n\t"
+ "movl %%ebx, %1 \n\t"
+ "popl %%ebx \n\t"
+ : "=a"(data[0]), "=r"(data[1]), "=c"(data[2]), "=d"(data[3])
+ : "a"(selector)
+ : "ebx");
+# else
+ data[0] = data[1] = data[2] = data[3] = 0;
+# endif
}
#endif
string system_cpu_brand_string()
{
- char buf[48] = {0};
- int result[4] = {0};
+ char buf[48] = {0};
+ int result[4] = {0};
- __cpuid(result, 0x80000000);
+ __cpuid(result, 0x80000000);
- if(result[0] >= (int)0x80000004) {
- __cpuid((int*)(buf+0), 0x80000002);
- __cpuid((int*)(buf+16), 0x80000003);
- __cpuid((int*)(buf+32), 0x80000004);
+ if (result[0] >= (int)0x80000004) {
+ __cpuid((int *)(buf + 0), 0x80000002);
+ __cpuid((int *)(buf + 16), 0x80000003);
+ __cpuid((int *)(buf + 32), 0x80000004);
- string brand = buf;
+ string brand = buf;
- /* make it a bit more presentable */
- brand = string_remove_trademark(brand);
+ /* make it a bit more presentable */
+ brand = string_remove_trademark(brand);
- return brand;
- }
+ return brand;
+ }
- return "Unknown CPU";
+ return "Unknown CPU";
}
int system_cpu_bits()
{
- return (sizeof(void*)*8);
+ return (sizeof(void *) * 8);
}
#if defined(__x86_64__) || defined(_M_X64) || defined(i386) || defined(_M_IX86)
struct CPUCapabilities {
- bool x64;
- bool mmx;
- bool sse;
- bool sse2;
- bool sse3;
- bool ssse3;
- bool sse41;
- bool sse42;
- bool sse4a;
- bool avx;
- bool f16c;
- bool avx2;
- bool xop;
- bool fma3;
- bool fma4;
- bool bmi1;
- bool bmi2;
+ bool x64;
+ bool mmx;
+ bool sse;
+ bool sse2;
+ bool sse3;
+ bool ssse3;
+ bool sse41;
+ bool sse42;
+ bool sse4a;
+ bool avx;
+ bool f16c;
+ bool avx2;
+ bool xop;
+ bool fma3;
+ bool fma4;
+ bool bmi1;
+ bool bmi2;
};
-static CPUCapabilities& system_cpu_capabilities()
+static CPUCapabilities &system_cpu_capabilities()
{
- static CPUCapabilities caps;
- static bool caps_init = false;
-
- if(!caps_init) {
- int result[4], num;
-
- memset(&caps, 0, sizeof(caps));
-
- __cpuid(result, 0);
- num = result[0];
-
- if(num >= 1) {
- __cpuid(result, 0x00000001);
- caps.mmx = (result[3] & ((int)1 << 23)) != 0;
- caps.sse = (result[3] & ((int)1 << 25)) != 0;
- caps.sse2 = (result[3] & ((int)1 << 26)) != 0;
- caps.sse3 = (result[2] & ((int)1 << 0)) != 0;
-
- caps.ssse3 = (result[2] & ((int)1 << 9)) != 0;
- caps.sse41 = (result[2] & ((int)1 << 19)) != 0;
- caps.sse42 = (result[2] & ((int)1 << 20)) != 0;
-
- caps.fma3 = (result[2] & ((int)1 << 12)) != 0;
- caps.avx = false;
- bool os_uses_xsave_xrestore = (result[2] & ((int)1 << 27)) != 0;
- bool cpu_avx_support = (result[2] & ((int)1 << 28)) != 0;
-
- if( os_uses_xsave_xrestore && cpu_avx_support) {
- // Check if the OS will save the YMM registers
- uint32_t xcr_feature_mask;
-#if defined(__GNUC__)
- int edx; /* not used */
- /* actual opcode for xgetbv */
- __asm__ (".byte 0x0f, 0x01, 0xd0" : "=a" (xcr_feature_mask) , "=d" (edx) : "c" (0) );
-#elif defined(_MSC_VER) && defined(_XCR_XFEATURE_ENABLED_MASK)
- xcr_feature_mask = (uint32_t)_xgetbv(_XCR_XFEATURE_ENABLED_MASK); /* min VS2010 SP1 compiler is required */
-#else
- xcr_feature_mask = 0;
-#endif
- caps.avx = (xcr_feature_mask & 0x6) == 0x6;
- }
+ static CPUCapabilities caps;
+ static bool caps_init = false;
+
+ if (!caps_init) {
+ int result[4], num;
+
+ memset(&caps, 0, sizeof(caps));
+
+ __cpuid(result, 0);
+ num = result[0];
+
+ if (num >= 1) {
+ __cpuid(result, 0x00000001);
+ caps.mmx = (result[3] & ((int)1 << 23)) != 0;
+ caps.sse = (result[3] & ((int)1 << 25)) != 0;
+ caps.sse2 = (result[3] & ((int)1 << 26)) != 0;
+ caps.sse3 = (result[2] & ((int)1 << 0)) != 0;
+
+ caps.ssse3 = (result[2] & ((int)1 << 9)) != 0;
+ caps.sse41 = (result[2] & ((int)1 << 19)) != 0;
+ caps.sse42 = (result[2] & ((int)1 << 20)) != 0;
+
+ caps.fma3 = (result[2] & ((int)1 << 12)) != 0;
+ caps.avx = false;
+ bool os_uses_xsave_xrestore = (result[2] & ((int)1 << 27)) != 0;
+ bool cpu_avx_support = (result[2] & ((int)1 << 28)) != 0;
+
+ if (os_uses_xsave_xrestore && cpu_avx_support) {
+ // Check if the OS will save the YMM registers
+ uint32_t xcr_feature_mask;
+# if defined(__GNUC__)
+ int edx; /* not used */
+ /* actual opcode for xgetbv */
+ __asm__(".byte 0x0f, 0x01, 0xd0" : "=a"(xcr_feature_mask), "=d"(edx) : "c"(0));
+# elif defined(_MSC_VER) && defined(_XCR_XFEATURE_ENABLED_MASK)
+ xcr_feature_mask = (uint32_t)_xgetbv(
+ _XCR_XFEATURE_ENABLED_MASK); /* min VS2010 SP1 compiler is required */
+# else
+ xcr_feature_mask = 0;
+# endif
+ caps.avx = (xcr_feature_mask & 0x6) == 0x6;
+ }
- caps.f16c = (result[2] & ((int)1 << 29)) != 0;
+ caps.f16c = (result[2] & ((int)1 << 29)) != 0;
- __cpuid(result, 0x00000007);
- caps.bmi1 = (result[1] & ((int)1 << 3)) != 0;
- caps.bmi2 = (result[1] & ((int)1 << 8)) != 0;
- caps.avx2 = (result[1] & ((int)1 << 5)) != 0;
- }
+ __cpuid(result, 0x00000007);
+ caps.bmi1 = (result[1] & ((int)1 << 3)) != 0;
+ caps.bmi2 = (result[1] & ((int)1 << 8)) != 0;
+ caps.avx2 = (result[1] & ((int)1 << 5)) != 0;
+ }
- caps_init = true;
- }
+ caps_init = true;
+ }
- return caps;
+ return caps;
}
bool system_cpu_support_sse2()
{
- CPUCapabilities& caps = system_cpu_capabilities();
- return caps.sse && caps.sse2;
+ CPUCapabilities &caps = system_cpu_capabilities();
+ return caps.sse && caps.sse2;
}
bool system_cpu_support_sse3()
{
- CPUCapabilities& caps = system_cpu_capabilities();
- return caps.sse && caps.sse2 && caps.sse3 && caps.ssse3;
+ CPUCapabilities &caps = system_cpu_capabilities();
+ return caps.sse && caps.sse2 && caps.sse3 && caps.ssse3;
}
bool system_cpu_support_sse41()
{
- CPUCapabilities& caps = system_cpu_capabilities();
- return caps.sse && caps.sse2 && caps.sse3 && caps.ssse3 && caps.sse41;
+ CPUCapabilities &caps = system_cpu_capabilities();
+ return caps.sse && caps.sse2 && caps.sse3 && caps.ssse3 && caps.sse41;
}
bool system_cpu_support_avx()
{
- CPUCapabilities& caps = system_cpu_capabilities();
- return caps.sse && caps.sse2 && caps.sse3 && caps.ssse3 &&
- caps.sse41 && caps.avx;
+ CPUCapabilities &caps = system_cpu_capabilities();
+ return caps.sse && caps.sse2 && caps.sse3 && caps.ssse3 && caps.sse41 && caps.avx;
}
bool system_cpu_support_avx2()
{
- CPUCapabilities& caps = system_cpu_capabilities();
- return caps.sse && caps.sse2 && caps.sse3 && caps.ssse3 && caps.sse41 &&
- caps.avx && caps.f16c && caps.avx2 && caps.fma3 && caps.bmi1 &&
- caps.bmi2;
+ CPUCapabilities &caps = system_cpu_capabilities();
+ return caps.sse && caps.sse2 && caps.sse3 && caps.ssse3 && caps.sse41 && caps.avx && caps.f16c &&
+ caps.avx2 && caps.fma3 && caps.bmi1 && caps.bmi2;
}
#else
bool system_cpu_support_sse2()
{
- return false;
+ return false;
}
bool system_cpu_support_sse3()
{
- return false;
+ return false;
}
bool system_cpu_support_sse41()
{
- return false;
+ return false;
}
bool system_cpu_support_avx()
{
- return false;
+ return false;
}
bool system_cpu_support_avx2()
{
- return false;
+ return false;
}
#endif
-bool system_call_self(const vector<string>& args)
+bool system_call_self(const vector<string> &args)
{
- /* Escape program and arguments in case they contain spaces. */
- string cmd = "\"" + Sysutil::this_program_path() + "\"";
+ /* Escape program and arguments in case they contain spaces. */
+ string cmd = "\"" + Sysutil::this_program_path() + "\"";
- for(int i = 0; i < args.size(); i++) {
- cmd += " \"" + args[i] + "\"";
- }
+ for (int i = 0; i < args.size(); i++) {
+ cmd += " \"" + args[i] + "\"";
+ }
#ifdef _WIN32
- /* Use cmd /S to avoid issues with spaces in arguments. */
- cmd = "cmd /S /C \"" + cmd + " > nul \"";
+ /* Use cmd /S to avoid issues with spaces in arguments. */
+ cmd = "cmd /S /C \"" + cmd + " > nul \"";
#else
- /* Quiet output. */
- cmd += " > /dev/null";
+ /* Quiet output. */
+ cmd += " > /dev/null";
#endif
- return (system(cmd.c_str()) == 0);
+ return (system(cmd.c_str()) == 0);
}
size_t system_physical_ram()
{
#ifdef _WIN32
- MEMORYSTATUSEX ram;
- ram.dwLength = sizeof (ram);
- GlobalMemoryStatusEx(&ram);
- return ram.ullTotalPhys * 1024;
+ MEMORYSTATUSEX ram;
+ ram.dwLength = sizeof(ram);
+ GlobalMemoryStatusEx(&ram);
+ return ram.ullTotalPhys * 1024;
#elif defined(__APPLE__)
- uint64_t ram = 0;
- size_t len = sizeof(ram);
- if(sysctlbyname("hw.memsize", &ram, &len, NULL, 0) == 0) {
- return ram;
- }
- return 0;
+ uint64_t ram = 0;
+ size_t len = sizeof(ram);
+ if (sysctlbyname("hw.memsize", &ram, &len, NULL, 0) == 0) {
+ return ram;
+ }
+ return 0;
#else
- size_t ps = sysconf(_SC_PAGESIZE);
- size_t pn = sysconf(_SC_PHYS_PAGES);
- return ps * pn;
+ size_t ps = sysconf(_SC_PAGESIZE);
+ size_t pn = sysconf(_SC_PHYS_PAGES);
+ return ps * pn;
#endif
}
diff --git a/intern/cycles/util/util_system.h b/intern/cycles/util/util_system.h
index 2590b31a59d..c4db8b74339 100644
--- a/intern/cycles/util/util_system.h
+++ b/intern/cycles/util/util_system.h
@@ -63,8 +63,8 @@ bool system_cpu_support_avx2();
size_t system_physical_ram();
/* Start a new process of the current application with the given arguments. */
-bool system_call_self(const vector<string>& args);
+bool system_call_self(const vector<string> &args);
CCL_NAMESPACE_END
-#endif /* __UTIL_SYSTEM_H__ */
+#endif /* __UTIL_SYSTEM_H__ */
diff --git a/intern/cycles/util/util_task.cpp b/intern/cycles/util/util_task.cpp
index ce166af206a..4b11ce73ea9 100644
--- a/intern/cycles/util/util_task.cpp
+++ b/intern/cycles/util/util_task.cpp
@@ -23,10 +23,14 @@
//#define THREADING_DEBUG_ENABLED
#ifdef THREADING_DEBUG_ENABLED
-#include <stdio.h>
-#define THREADING_DEBUG(...) do { printf(__VA_ARGS__); fflush(stdout); } while(0)
+# include <stdio.h>
+# define THREADING_DEBUG(...) \
+ do { \
+ printf(__VA_ARGS__); \
+ fflush(stdout); \
+ } while (0)
#else
-#define THREADING_DEBUG(...)
+# define THREADING_DEBUG(...)
#endif
CCL_NAMESPACE_BEGIN
@@ -35,156 +39,156 @@ CCL_NAMESPACE_BEGIN
TaskPool::TaskPool()
{
- num_tasks_handled = 0;
- num = 0;
- do_cancel = false;
+ num_tasks_handled = 0;
+ num = 0;
+ do_cancel = false;
}
TaskPool::~TaskPool()
{
- stop();
+ stop();
}
void TaskPool::push(Task *task, bool front)
{
- TaskScheduler::Entry entry;
+ TaskScheduler::Entry entry;
- entry.task = task;
- entry.pool = this;
+ entry.task = task;
+ entry.pool = this;
- TaskScheduler::push(entry, front);
+ TaskScheduler::push(entry, front);
}
-void TaskPool::push(const TaskRunFunction& run, bool front)
+void TaskPool::push(const TaskRunFunction &run, bool front)
{
- push(new Task(run), front);
+ push(new Task(run), front);
}
void TaskPool::wait_work(Summary *stats)
{
- thread_scoped_lock num_lock(num_mutex);
+ thread_scoped_lock num_lock(num_mutex);
- while(num != 0) {
- num_lock.unlock();
+ while (num != 0) {
+ num_lock.unlock();
- thread_scoped_lock queue_lock(TaskScheduler::queue_mutex);
+ thread_scoped_lock queue_lock(TaskScheduler::queue_mutex);
- /* find task from this pool. if we get a task from another pool,
- * we can get into deadlock */
- TaskScheduler::Entry work_entry;
- bool found_entry = false;
- list<TaskScheduler::Entry>::iterator it;
+ /* find task from this pool. if we get a task from another pool,
+ * we can get into deadlock */
+ TaskScheduler::Entry work_entry;
+ bool found_entry = false;
+ list<TaskScheduler::Entry>::iterator it;
- for(it = TaskScheduler::queue.begin(); it != TaskScheduler::queue.end(); it++) {
- TaskScheduler::Entry& entry = *it;
+ for (it = TaskScheduler::queue.begin(); it != TaskScheduler::queue.end(); it++) {
+ TaskScheduler::Entry &entry = *it;
- if(entry.pool == this) {
- work_entry = entry;
- found_entry = true;
- TaskScheduler::queue.erase(it);
- break;
- }
- }
+ if (entry.pool == this) {
+ work_entry = entry;
+ found_entry = true;
+ TaskScheduler::queue.erase(it);
+ break;
+ }
+ }
- queue_lock.unlock();
+ queue_lock.unlock();
- /* if found task, do it, otherwise wait until other tasks are done */
- if(found_entry) {
- /* run task */
- work_entry.task->run(0);
+ /* if found task, do it, otherwise wait until other tasks are done */
+ if (found_entry) {
+ /* run task */
+ work_entry.task->run(0);
- /* delete task */
- delete work_entry.task;
+ /* delete task */
+ delete work_entry.task;
- /* notify pool task was done */
- num_decrease(1);
- }
+ /* notify pool task was done */
+ num_decrease(1);
+ }
- num_lock.lock();
- if(num == 0)
- break;
+ num_lock.lock();
+ if (num == 0)
+ break;
- if(!found_entry) {
- THREADING_DEBUG("num==%d, Waiting for condition in TaskPool::wait_work !found_entry\n", num);
- num_cond.wait(num_lock);
- THREADING_DEBUG("num==%d, condition wait done in TaskPool::wait_work !found_entry\n", num);
- }
- }
+ if (!found_entry) {
+ THREADING_DEBUG("num==%d, Waiting for condition in TaskPool::wait_work !found_entry\n", num);
+ num_cond.wait(num_lock);
+ THREADING_DEBUG("num==%d, condition wait done in TaskPool::wait_work !found_entry\n", num);
+ }
+ }
- if(stats != NULL) {
- stats->time_total = time_dt() - start_time;
- stats->num_tasks_handled = num_tasks_handled;
- }
+ if (stats != NULL) {
+ stats->time_total = time_dt() - start_time;
+ stats->num_tasks_handled = num_tasks_handled;
+ }
}
void TaskPool::cancel()
{
- do_cancel = true;
+ do_cancel = true;
- TaskScheduler::clear(this);
+ TaskScheduler::clear(this);
- {
- thread_scoped_lock num_lock(num_mutex);
+ {
+ thread_scoped_lock num_lock(num_mutex);
- while(num) {
- THREADING_DEBUG("num==%d, Waiting for condition in TaskPool::cancel\n", num);
- num_cond.wait(num_lock);
- THREADING_DEBUG("num==%d condition wait done in TaskPool::cancel\n", num);
- }
- }
+ while (num) {
+ THREADING_DEBUG("num==%d, Waiting for condition in TaskPool::cancel\n", num);
+ num_cond.wait(num_lock);
+ THREADING_DEBUG("num==%d condition wait done in TaskPool::cancel\n", num);
+ }
+ }
- do_cancel = false;
+ do_cancel = false;
}
void TaskPool::stop()
{
- TaskScheduler::clear(this);
+ TaskScheduler::clear(this);
- assert(num == 0);
+ assert(num == 0);
}
bool TaskPool::canceled()
{
- return do_cancel;
+ return do_cancel;
}
bool TaskPool::finished()
{
- thread_scoped_lock num_lock(num_mutex);
- return num == 0;
+ thread_scoped_lock num_lock(num_mutex);
+ return num == 0;
}
void TaskPool::num_decrease(int done)
{
- num_mutex.lock();
- num -= done;
+ num_mutex.lock();
+ num -= done;
- assert(num >= 0);
- if(num == 0) {
- THREADING_DEBUG("num==%d, notifying all in TaskPool::num_decrease\n", num);
- num_cond.notify_all();
- }
+ assert(num >= 0);
+ if (num == 0) {
+ THREADING_DEBUG("num==%d, notifying all in TaskPool::num_decrease\n", num);
+ num_cond.notify_all();
+ }
- num_mutex.unlock();
+ num_mutex.unlock();
}
void TaskPool::num_increase()
{
- thread_scoped_lock num_lock(num_mutex);
- if(num_tasks_handled == 0) {
- start_time = time_dt();
- }
- num++;
- num_tasks_handled++;
- THREADING_DEBUG("num==%d, notifying all in TaskPool::num_increase\n", num);
- num_cond.notify_all();
+ thread_scoped_lock num_lock(num_mutex);
+ if (num_tasks_handled == 0) {
+ start_time = time_dt();
+ }
+ num++;
+ num_tasks_handled++;
+ THREADING_DEBUG("num==%d, notifying all in TaskPool::num_increase\n", num);
+ num_cond.notify_all();
}
/* Task Scheduler */
thread_mutex TaskScheduler::mutex;
int TaskScheduler::users = 0;
-vector<thread*> TaskScheduler::threads;
+vector<thread *> TaskScheduler::threads;
bool TaskScheduler::do_exit = false;
list<TaskScheduler::Entry> TaskScheduler::queue;
@@ -198,412 +202,401 @@ namespace {
* that node.
* If node is not available, then the corresponding number of processors is
* zero. */
-void get_per_node_num_processors(vector<int>* num_per_node_processors)
-{
- const int num_nodes = system_cpu_num_numa_nodes();
- if(num_nodes == 0) {
- LOG(ERROR) << "Zero available NUMA nodes, is not supposed to happen.";
- return;
- }
- num_per_node_processors->resize(num_nodes);
- for(int node = 0; node < num_nodes; ++node) {
- if(!system_cpu_is_numa_node_available(node)) {
- (*num_per_node_processors)[node] = 0;
- continue;
- }
- (*num_per_node_processors)[node] =
- system_cpu_num_numa_node_processors(node);
- }
+void get_per_node_num_processors(vector<int> *num_per_node_processors)
+{
+ const int num_nodes = system_cpu_num_numa_nodes();
+ if (num_nodes == 0) {
+ LOG(ERROR) << "Zero available NUMA nodes, is not supposed to happen.";
+ return;
+ }
+ num_per_node_processors->resize(num_nodes);
+ for (int node = 0; node < num_nodes; ++node) {
+ if (!system_cpu_is_numa_node_available(node)) {
+ (*num_per_node_processors)[node] = 0;
+ continue;
+ }
+ (*num_per_node_processors)[node] = system_cpu_num_numa_node_processors(node);
+ }
}
/* Calculate total number of processors on all available nodes.
* This is similar to system_cpu_thread_count(), but uses pre-calculated number
* of processors on each of the node, avoiding extra system calls and checks for
* the node availability. */
-int get_num_total_processors(const vector<int>& num_per_node_processors)
+int get_num_total_processors(const vector<int> &num_per_node_processors)
{
- int num_total_processors = 0;
- foreach(int num_node_processors, num_per_node_processors) {
- num_total_processors += num_node_processors;
- }
- return num_total_processors;
+ int num_total_processors = 0;
+ foreach (int num_node_processors, num_per_node_processors) {
+ num_total_processors += num_node_processors;
+ }
+ return num_total_processors;
}
/* Compute NUMA node for every thread to run on, for the best performance. */
vector<int> distribute_threads_on_nodes(const int num_threads)
{
- /* Start with all threads unassigned to any specific NUMA node. */
- vector<int> thread_nodes(num_threads, -1);
- const int num_active_group_processors =
- system_cpu_num_active_group_processors();
- VLOG(1) << "Detected " << num_active_group_processors << " processors "
- << "in active group.";
- if(num_active_group_processors >= num_threads) {
- /* If the current thread is set up in a way that its affinity allows to
- * use at least requested number of threads we do not explicitly set
- * affinity to the worker therads.
- * This way we allow users to manually edit affinity of the parent
- * thread, and here we follow that affinity. This way it's possible to
- * have two Cycles/Blender instances running manually set to a different
- * dies on a CPU. */
- VLOG(1) << "Not setting thread group affinity.";
- return thread_nodes;
- }
- vector<int> num_per_node_processors;
- get_per_node_num_processors(&num_per_node_processors);
- if(num_per_node_processors.size() == 0) {
- /* Error was already repported, here we can't do anything, so we simply
- * leave default affinity to all the worker threads. */
- return thread_nodes;
- }
- const int num_nodes = num_per_node_processors.size();
- int thread_index = 0;
- /* First pass: fill in all the nodes to their maximum.
- *
- * If there is less threads than the overall nodes capacity, some of the
- * nodes or parts of them will idle.
- *
- * TODO(sergey): Consider picking up fastest nodes if number of threads
- * fits on them. For example, on Threadripper2 we might consider using nodes
- * 0 and 2 if user requested 32 render threads. */
- const int num_total_node_processors =
- get_num_total_processors(num_per_node_processors);
- int current_node_index = 0;
- while(thread_index < num_total_node_processors &&
- thread_index < num_threads) {
- const int num_node_processors =
- num_per_node_processors[current_node_index];
- for(int processor_index = 0;
- processor_index < num_node_processors;
- ++processor_index)
- {
- VLOG(1) << "Scheduling thread " << thread_index << " to node "
- << current_node_index << ".";
- thread_nodes[thread_index] = current_node_index;
- ++thread_index;
- if(thread_index == num_threads) {
- /* All threads are scheduled on their nodes. */
- return thread_nodes;
- }
- }
- ++current_node_index;
- }
- /* Second pass: keep scheduling threads to each node one by one, uniformly
- * fillign them in.
- * This is where things becomes tricky to predict for the maximum
- * performance: on the one hand this avoids too much threading overhead on
- * few nodes, but for the final performance having all the overhead on one
- * node might be better idea (since other nodes will have better chance of
- * rendering faster).
- * But more tricky is that nodes might have difference capacity, so we might
- * want to do some weighted scheduling. For example, if node 0 has 16
- * processors and node 1 has 32 processors, we'd better schedule 1 extra
- * thread on node 0 and 2 extra threads on node 1. */
- current_node_index = 0;
- while(thread_index < num_threads) {
- /* Skip unavailable nodes. */
- /* TODO(sergey): Add sanity check against deadlock. */
- while(num_per_node_processors[current_node_index] == 0) {
- current_node_index = (current_node_index + 1) % num_nodes;
- }
- VLOG(1) << "Scheduling thread " << thread_index << " to node "
- << current_node_index << ".";
- ++thread_index;
- current_node_index = (current_node_index + 1) % num_nodes;
- }
-
- return thread_nodes;
+ /* Start with all threads unassigned to any specific NUMA node. */
+ vector<int> thread_nodes(num_threads, -1);
+ const int num_active_group_processors = system_cpu_num_active_group_processors();
+ VLOG(1) << "Detected " << num_active_group_processors << " processors "
+ << "in active group.";
+ if (num_active_group_processors >= num_threads) {
+ /* If the current thread is set up in a way that its affinity allows to
+ * use at least requested number of threads we do not explicitly set
+ * affinity to the worker therads.
+ * This way we allow users to manually edit affinity of the parent
+ * thread, and here we follow that affinity. This way it's possible to
+ * have two Cycles/Blender instances running manually set to a different
+ * dies on a CPU. */
+ VLOG(1) << "Not setting thread group affinity.";
+ return thread_nodes;
+ }
+ vector<int> num_per_node_processors;
+ get_per_node_num_processors(&num_per_node_processors);
+ if (num_per_node_processors.size() == 0) {
+ /* Error was already repported, here we can't do anything, so we simply
+ * leave default affinity to all the worker threads. */
+ return thread_nodes;
+ }
+ const int num_nodes = num_per_node_processors.size();
+ int thread_index = 0;
+ /* First pass: fill in all the nodes to their maximum.
+ *
+ * If there is less threads than the overall nodes capacity, some of the
+ * nodes or parts of them will idle.
+ *
+ * TODO(sergey): Consider picking up fastest nodes if number of threads
+ * fits on them. For example, on Threadripper2 we might consider using nodes
+ * 0 and 2 if user requested 32 render threads. */
+ const int num_total_node_processors = get_num_total_processors(num_per_node_processors);
+ int current_node_index = 0;
+ while (thread_index < num_total_node_processors && thread_index < num_threads) {
+ const int num_node_processors = num_per_node_processors[current_node_index];
+ for (int processor_index = 0; processor_index < num_node_processors; ++processor_index) {
+ VLOG(1) << "Scheduling thread " << thread_index << " to node " << current_node_index << ".";
+ thread_nodes[thread_index] = current_node_index;
+ ++thread_index;
+ if (thread_index == num_threads) {
+ /* All threads are scheduled on their nodes. */
+ return thread_nodes;
+ }
+ }
+ ++current_node_index;
+ }
+ /* Second pass: keep scheduling threads to each node one by one, uniformly
+ * fillign them in.
+ * This is where things becomes tricky to predict for the maximum
+ * performance: on the one hand this avoids too much threading overhead on
+ * few nodes, but for the final performance having all the overhead on one
+ * node might be better idea (since other nodes will have better chance of
+ * rendering faster).
+ * But more tricky is that nodes might have difference capacity, so we might
+ * want to do some weighted scheduling. For example, if node 0 has 16
+ * processors and node 1 has 32 processors, we'd better schedule 1 extra
+ * thread on node 0 and 2 extra threads on node 1. */
+ current_node_index = 0;
+ while (thread_index < num_threads) {
+ /* Skip unavailable nodes. */
+ /* TODO(sergey): Add sanity check against deadlock. */
+ while (num_per_node_processors[current_node_index] == 0) {
+ current_node_index = (current_node_index + 1) % num_nodes;
+ }
+ VLOG(1) << "Scheduling thread " << thread_index << " to node " << current_node_index << ".";
+ ++thread_index;
+ current_node_index = (current_node_index + 1) % num_nodes;
+ }
+
+ return thread_nodes;
}
} // namespace
void TaskScheduler::init(int num_threads)
{
- thread_scoped_lock lock(mutex);
- /* Multiple cycles instances can use this task scheduler, sharing the same
- * threads, so we keep track of the number of users. */
- ++users;
- if(users != 1) {
- return;
- }
- do_exit = false;
- const bool use_auto_threads = (num_threads == 0);
- if(use_auto_threads) {
- /* Automatic number of threads. */
- num_threads = system_cpu_thread_count();
- }
- VLOG(1) << "Creating pool of " << num_threads << " threads.";
-
- /* Compute distribution on NUMA nodes. */
- vector<int> thread_nodes = distribute_threads_on_nodes(num_threads);
-
- /* Launch threads that will be waiting for work. */
- threads.resize(num_threads);
- for(int thread_index = 0; thread_index < num_threads; ++thread_index) {
- threads[thread_index] = new thread(
- function_bind(&TaskScheduler::thread_run, thread_index + 1),
- thread_nodes[thread_index]);
- }
+ thread_scoped_lock lock(mutex);
+ /* Multiple cycles instances can use this task scheduler, sharing the same
+ * threads, so we keep track of the number of users. */
+ ++users;
+ if (users != 1) {
+ return;
+ }
+ do_exit = false;
+ const bool use_auto_threads = (num_threads == 0);
+ if (use_auto_threads) {
+ /* Automatic number of threads. */
+ num_threads = system_cpu_thread_count();
+ }
+ VLOG(1) << "Creating pool of " << num_threads << " threads.";
+
+ /* Compute distribution on NUMA nodes. */
+ vector<int> thread_nodes = distribute_threads_on_nodes(num_threads);
+
+ /* Launch threads that will be waiting for work. */
+ threads.resize(num_threads);
+ for (int thread_index = 0; thread_index < num_threads; ++thread_index) {
+ threads[thread_index] = new thread(function_bind(&TaskScheduler::thread_run, thread_index + 1),
+ thread_nodes[thread_index]);
+ }
}
void TaskScheduler::exit()
{
- thread_scoped_lock lock(mutex);
- users--;
- if(users == 0) {
- VLOG(1) << "De-initializing thread pool of task scheduler.";
- /* stop all waiting threads */
- TaskScheduler::queue_mutex.lock();
- do_exit = true;
- TaskScheduler::queue_cond.notify_all();
- TaskScheduler::queue_mutex.unlock();
-
- /* delete threads */
- foreach(thread *t, threads) {
- t->join();
- delete t;
- }
- threads.clear();
- }
+ thread_scoped_lock lock(mutex);
+ users--;
+ if (users == 0) {
+ VLOG(1) << "De-initializing thread pool of task scheduler.";
+ /* stop all waiting threads */
+ TaskScheduler::queue_mutex.lock();
+ do_exit = true;
+ TaskScheduler::queue_cond.notify_all();
+ TaskScheduler::queue_mutex.unlock();
+
+ /* delete threads */
+ foreach (thread *t, threads) {
+ t->join();
+ delete t;
+ }
+ threads.clear();
+ }
}
void TaskScheduler::free_memory()
{
- assert(users == 0);
- threads.free_memory();
+ assert(users == 0);
+ threads.free_memory();
}
-bool TaskScheduler::thread_wait_pop(Entry& entry)
+bool TaskScheduler::thread_wait_pop(Entry &entry)
{
- thread_scoped_lock queue_lock(queue_mutex);
+ thread_scoped_lock queue_lock(queue_mutex);
- while(queue.empty() && !do_exit)
- queue_cond.wait(queue_lock);
+ while (queue.empty() && !do_exit)
+ queue_cond.wait(queue_lock);
- if(queue.empty()) {
- assert(do_exit);
- return false;
- }
+ if (queue.empty()) {
+ assert(do_exit);
+ return false;
+ }
- entry = queue.front();
- queue.pop_front();
+ entry = queue.front();
+ queue.pop_front();
- return true;
+ return true;
}
void TaskScheduler::thread_run(int thread_id)
{
- Entry entry;
+ Entry entry;
- /* todo: test affinity/denormal mask */
+ /* todo: test affinity/denormal mask */
- /* keep popping off tasks */
- while(thread_wait_pop(entry)) {
- /* run task */
- entry.task->run(thread_id);
+ /* keep popping off tasks */
+ while (thread_wait_pop(entry)) {
+ /* run task */
+ entry.task->run(thread_id);
- /* delete task */
- delete entry.task;
+ /* delete task */
+ delete entry.task;
- /* notify pool task was done */
- entry.pool->num_decrease(1);
- }
+ /* notify pool task was done */
+ entry.pool->num_decrease(1);
+ }
}
-void TaskScheduler::push(Entry& entry, bool front)
+void TaskScheduler::push(Entry &entry, bool front)
{
- entry.pool->num_increase();
+ entry.pool->num_increase();
- /* add entry to queue */
- TaskScheduler::queue_mutex.lock();
- if(front)
- TaskScheduler::queue.push_front(entry);
- else
- TaskScheduler::queue.push_back(entry);
+ /* add entry to queue */
+ TaskScheduler::queue_mutex.lock();
+ if (front)
+ TaskScheduler::queue.push_front(entry);
+ else
+ TaskScheduler::queue.push_back(entry);
- TaskScheduler::queue_cond.notify_one();
- TaskScheduler::queue_mutex.unlock();
+ TaskScheduler::queue_cond.notify_one();
+ TaskScheduler::queue_mutex.unlock();
}
void TaskScheduler::clear(TaskPool *pool)
{
- thread_scoped_lock queue_lock(TaskScheduler::queue_mutex);
+ thread_scoped_lock queue_lock(TaskScheduler::queue_mutex);
- /* erase all tasks from this pool from the queue */
- list<Entry>::iterator it = queue.begin();
- int done = 0;
+ /* erase all tasks from this pool from the queue */
+ list<Entry>::iterator it = queue.begin();
+ int done = 0;
- while(it != queue.end()) {
- Entry& entry = *it;
+ while (it != queue.end()) {
+ Entry &entry = *it;
- if(entry.pool == pool) {
- done++;
- delete entry.task;
+ if (entry.pool == pool) {
+ done++;
+ delete entry.task;
- it = queue.erase(it);
- }
- else
- it++;
- }
+ it = queue.erase(it);
+ }
+ else
+ it++;
+ }
- queue_lock.unlock();
+ queue_lock.unlock();
- /* notify done */
- pool->num_decrease(done);
+ /* notify done */
+ pool->num_decrease(done);
}
/* Dedicated Task Pool */
DedicatedTaskPool::DedicatedTaskPool()
{
- do_cancel = false;
- do_exit = false;
- num = 0;
+ do_cancel = false;
+ do_exit = false;
+ num = 0;
- worker_thread = new thread(function_bind(&DedicatedTaskPool::thread_run, this));
+ worker_thread = new thread(function_bind(&DedicatedTaskPool::thread_run, this));
}
DedicatedTaskPool::~DedicatedTaskPool()
{
- stop();
- worker_thread->join();
- delete worker_thread;
+ stop();
+ worker_thread->join();
+ delete worker_thread;
}
void DedicatedTaskPool::push(Task *task, bool front)
{
- num_increase();
+ num_increase();
- /* add task to queue */
- queue_mutex.lock();
- if(front)
- queue.push_front(task);
- else
- queue.push_back(task);
+ /* add task to queue */
+ queue_mutex.lock();
+ if (front)
+ queue.push_front(task);
+ else
+ queue.push_back(task);
- queue_cond.notify_one();
- queue_mutex.unlock();
+ queue_cond.notify_one();
+ queue_mutex.unlock();
}
-void DedicatedTaskPool::push(const TaskRunFunction& run, bool front)
+void DedicatedTaskPool::push(const TaskRunFunction &run, bool front)
{
- push(new Task(run), front);
+ push(new Task(run), front);
}
void DedicatedTaskPool::wait()
{
- thread_scoped_lock num_lock(num_mutex);
+ thread_scoped_lock num_lock(num_mutex);
- while(num)
- num_cond.wait(num_lock);
+ while (num)
+ num_cond.wait(num_lock);
}
void DedicatedTaskPool::cancel()
{
- do_cancel = true;
+ do_cancel = true;
- clear();
- wait();
+ clear();
+ wait();
- do_cancel = false;
+ do_cancel = false;
}
void DedicatedTaskPool::stop()
{
- clear();
+ clear();
- do_exit = true;
- queue_cond.notify_all();
+ do_exit = true;
+ queue_cond.notify_all();
- wait();
+ wait();
- assert(num == 0);
+ assert(num == 0);
}
bool DedicatedTaskPool::canceled()
{
- return do_cancel;
+ return do_cancel;
}
void DedicatedTaskPool::num_decrease(int done)
{
- thread_scoped_lock num_lock(num_mutex);
- num -= done;
+ thread_scoped_lock num_lock(num_mutex);
+ num -= done;
- assert(num >= 0);
- if(num == 0)
- num_cond.notify_all();
+ assert(num >= 0);
+ if (num == 0)
+ num_cond.notify_all();
}
void DedicatedTaskPool::num_increase()
{
- thread_scoped_lock num_lock(num_mutex);
- num++;
- num_cond.notify_all();
+ thread_scoped_lock num_lock(num_mutex);
+ num++;
+ num_cond.notify_all();
}
-bool DedicatedTaskPool::thread_wait_pop(Task*& task)
+bool DedicatedTaskPool::thread_wait_pop(Task *&task)
{
- thread_scoped_lock queue_lock(queue_mutex);
+ thread_scoped_lock queue_lock(queue_mutex);
- while(queue.empty() && !do_exit)
- queue_cond.wait(queue_lock);
+ while (queue.empty() && !do_exit)
+ queue_cond.wait(queue_lock);
- if(queue.empty()) {
- assert(do_exit);
- return false;
- }
+ if (queue.empty()) {
+ assert(do_exit);
+ return false;
+ }
- task = queue.front();
- queue.pop_front();
+ task = queue.front();
+ queue.pop_front();
- return true;
+ return true;
}
void DedicatedTaskPool::thread_run()
{
- Task *task;
+ Task *task;
- /* keep popping off tasks */
- while(thread_wait_pop(task)) {
- /* run task */
- task->run(0);
+ /* keep popping off tasks */
+ while (thread_wait_pop(task)) {
+ /* run task */
+ task->run(0);
- /* delete task */
- delete task;
+ /* delete task */
+ delete task;
- /* notify task was done */
- num_decrease(1);
- }
+ /* notify task was done */
+ num_decrease(1);
+ }
}
void DedicatedTaskPool::clear()
{
- thread_scoped_lock queue_lock(queue_mutex);
+ thread_scoped_lock queue_lock(queue_mutex);
- /* erase all tasks from the queue */
- list<Task*>::iterator it = queue.begin();
- int done = 0;
+ /* erase all tasks from the queue */
+ list<Task *>::iterator it = queue.begin();
+ int done = 0;
- while(it != queue.end()) {
- done++;
- delete *it;
+ while (it != queue.end()) {
+ done++;
+ delete *it;
- it = queue.erase(it);
- }
+ it = queue.erase(it);
+ }
- queue_lock.unlock();
+ queue_lock.unlock();
- /* notify done */
- num_decrease(done);
+ /* notify done */
+ num_decrease(done);
}
string TaskPool::Summary::full_report() const
{
- string report = "";
- report += string_printf("Total time: %f\n", time_total);
- report += string_printf("Tasks handled: %d\n", num_tasks_handled);
- return report;
+ string report = "";
+ report += string_printf("Total time: %f\n", time_total);
+ report += string_printf("Tasks handled: %d\n", num_tasks_handled);
+ return report;
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/util/util_task.h b/intern/cycles/util/util_task.h
index a7e19d1ab75..fd30a33d8ef 100644
--- a/intern/cycles/util/util_task.h
+++ b/intern/cycles/util/util_task.h
@@ -48,15 +48,18 @@ typedef function<void(int thread_id)> TaskRunFunction;
*
* Base class for tasks to be executed in threads. */
-class Task
-{
-public:
- Task() {};
- explicit Task(const TaskRunFunction& run_) : run(run_) {}
-
- virtual ~Task() {}
-
- TaskRunFunction run;
+class Task {
+ public:
+ Task(){};
+ explicit Task(const TaskRunFunction &run_) : run(run_)
+ {
+ }
+
+ virtual ~Task()
+ {
+ }
+
+ TaskRunFunction run;
};
/* Task Pool
@@ -68,54 +71,53 @@ public:
* The run callback that actually executes the task may be created like this:
* function_bind(&MyClass::task_execute, this, _1, _2) */
-class TaskPool
-{
-public:
- struct Summary {
- /* Time spent to handle all tasks. */
- double time_total;
+class TaskPool {
+ public:
+ struct Summary {
+ /* Time spent to handle all tasks. */
+ double time_total;
- /* Number of all tasks handled by this pool. */
- int num_tasks_handled;
+ /* Number of all tasks handled by this pool. */
+ int num_tasks_handled;
- /* A full multiline description of the state of the pool after
- * all work is done.
- */
- string full_report() const;
- };
+ /* A full multiline description of the state of the pool after
+ * all work is done.
+ */
+ string full_report() const;
+ };
- TaskPool();
- ~TaskPool();
+ TaskPool();
+ ~TaskPool();
- void push(Task *task, bool front = false);
- void push(const TaskRunFunction& run, bool front = false);
+ void push(Task *task, bool front = false);
+ void push(const TaskRunFunction &run, bool front = false);
- void wait_work(Summary *stats = NULL); /* work and wait until all tasks are done */
- void cancel(); /* cancel all tasks, keep worker threads running */
- void stop(); /* stop all worker threads */
- bool finished(); /* check if all work has been completed */
+ void wait_work(Summary *stats = NULL); /* work and wait until all tasks are done */
+ void cancel(); /* cancel all tasks, keep worker threads running */
+ void stop(); /* stop all worker threads */
+ bool finished(); /* check if all work has been completed */
- bool canceled(); /* for worker threads, test if canceled */
+ bool canceled(); /* for worker threads, test if canceled */
-protected:
- friend class TaskScheduler;
+ protected:
+ friend class TaskScheduler;
- void num_decrease(int done);
- void num_increase();
+ void num_decrease(int done);
+ void num_increase();
- thread_mutex num_mutex;
- thread_condition_variable num_cond;
+ thread_mutex num_mutex;
+ thread_condition_variable num_cond;
- int num;
- bool do_cancel;
+ int num;
+ bool do_cancel;
- /* ** Statistics ** */
+ /* ** Statistics ** */
- /* Time time stamp of first task pushed. */
- double start_time;
+ /* Time time stamp of first task pushed. */
+ double start_time;
- /* Number of all tasks handled by this pool. */
- int num_tasks_handled;
+ /* Number of all tasks handled by this pool. */
+ int num_tasks_handled;
};
/* Task Scheduler
@@ -123,41 +125,46 @@ protected:
* Central scheduler that holds running threads ready to execute tasks. A singe
* queue holds the task from all pools. */
-class TaskScheduler
-{
-public:
- static void init(int num_threads = 0);
- static void exit();
- static void free_memory();
-
- /* number of threads that can work on task */
- static int num_threads() { return threads.size(); }
-
- /* test if any session is using the scheduler */
- static bool active() { return users != 0; }
-
-protected:
- friend class TaskPool;
-
- struct Entry {
- Task *task;
- TaskPool *pool;
- };
-
- static thread_mutex mutex;
- static int users;
- static vector<thread*> threads;
- static bool do_exit;
-
- static list<Entry> queue;
- static thread_mutex queue_mutex;
- static thread_condition_variable queue_cond;
-
- static void thread_run(int thread_id);
- static bool thread_wait_pop(Entry& entry);
-
- static void push(Entry& entry, bool front);
- static void clear(TaskPool *pool);
+class TaskScheduler {
+ public:
+ static void init(int num_threads = 0);
+ static void exit();
+ static void free_memory();
+
+ /* number of threads that can work on task */
+ static int num_threads()
+ {
+ return threads.size();
+ }
+
+ /* test if any session is using the scheduler */
+ static bool active()
+ {
+ return users != 0;
+ }
+
+ protected:
+ friend class TaskPool;
+
+ struct Entry {
+ Task *task;
+ TaskPool *pool;
+ };
+
+ static thread_mutex mutex;
+ static int users;
+ static vector<thread *> threads;
+ static bool do_exit;
+
+ static list<Entry> queue;
+ static thread_mutex queue_mutex;
+ static thread_condition_variable queue_cond;
+
+ static void thread_run(int thread_id);
+ static bool thread_wait_pop(Entry &entry);
+
+ static void push(Entry &entry, bool front);
+ static void clear(TaskPool *pool);
};
/* Dedicated Task Pool
@@ -167,42 +174,41 @@ protected:
* The run callback that actually executes the task may be created like this:
* function_bind(&MyClass::task_execute, this, _1, _2) */
-class DedicatedTaskPool
-{
-public:
- DedicatedTaskPool();
- ~DedicatedTaskPool();
+class DedicatedTaskPool {
+ public:
+ DedicatedTaskPool();
+ ~DedicatedTaskPool();
- void push(Task *task, bool front = false);
- void push(const TaskRunFunction& run, bool front = false);
+ void push(Task *task, bool front = false);
+ void push(const TaskRunFunction &run, bool front = false);
- void wait(); /* wait until all tasks are done */
- void cancel(); /* cancel all tasks, keep worker thread running */
- void stop(); /* stop worker thread */
+ void wait(); /* wait until all tasks are done */
+ void cancel(); /* cancel all tasks, keep worker thread running */
+ void stop(); /* stop worker thread */
- bool canceled(); /* for worker thread, test if canceled */
+ bool canceled(); /* for worker thread, test if canceled */
-protected:
- void num_decrease(int done);
- void num_increase();
+ protected:
+ void num_decrease(int done);
+ void num_increase();
- void thread_run();
- bool thread_wait_pop(Task*& entry);
+ void thread_run();
+ bool thread_wait_pop(Task *&entry);
- void clear();
+ void clear();
- thread_mutex num_mutex;
- thread_condition_variable num_cond;
+ thread_mutex num_mutex;
+ thread_condition_variable num_cond;
- list<Task*> queue;
- thread_mutex queue_mutex;
- thread_condition_variable queue_cond;
+ list<Task *> queue;
+ thread_mutex queue_mutex;
+ thread_condition_variable queue_cond;
- int num;
- bool do_cancel;
- bool do_exit;
+ int num;
+ bool do_cancel;
+ bool do_exit;
- thread *worker_thread;
+ thread *worker_thread;
};
CCL_NAMESPACE_END
diff --git a/intern/cycles/util/util_texture.h b/intern/cycles/util/util_texture.h
index 233cfe33305..5ce16e0095a 100644
--- a/intern/cycles/util/util_texture.h
+++ b/intern/cycles/util/util_texture.h
@@ -34,29 +34,29 @@ CCL_NAMESPACE_BEGIN
/* Interpolation types for textures
* cuda also use texture space to store other objects */
typedef enum InterpolationType {
- INTERPOLATION_NONE = -1,
- INTERPOLATION_LINEAR = 0,
- INTERPOLATION_CLOSEST = 1,
- INTERPOLATION_CUBIC = 2,
- INTERPOLATION_SMART = 3,
+ INTERPOLATION_NONE = -1,
+ INTERPOLATION_LINEAR = 0,
+ INTERPOLATION_CLOSEST = 1,
+ INTERPOLATION_CUBIC = 2,
+ INTERPOLATION_SMART = 3,
- INTERPOLATION_NUM_TYPES,
+ INTERPOLATION_NUM_TYPES,
} InterpolationType;
/* Texture types
* Since we store the type in the lower bits of a flat index,
* the shift and bit mask constant below need to be kept in sync. */
typedef enum ImageDataType {
- IMAGE_DATA_TYPE_FLOAT4 = 0,
- IMAGE_DATA_TYPE_BYTE4 = 1,
- IMAGE_DATA_TYPE_HALF4 = 2,
- IMAGE_DATA_TYPE_FLOAT = 3,
- IMAGE_DATA_TYPE_BYTE = 4,
- IMAGE_DATA_TYPE_HALF = 5,
- IMAGE_DATA_TYPE_USHORT4 = 6,
- IMAGE_DATA_TYPE_USHORT = 7,
+ IMAGE_DATA_TYPE_FLOAT4 = 0,
+ IMAGE_DATA_TYPE_BYTE4 = 1,
+ IMAGE_DATA_TYPE_HALF4 = 2,
+ IMAGE_DATA_TYPE_FLOAT = 3,
+ IMAGE_DATA_TYPE_BYTE = 4,
+ IMAGE_DATA_TYPE_HALF = 5,
+ IMAGE_DATA_TYPE_USHORT4 = 6,
+ IMAGE_DATA_TYPE_USHORT = 7,
- IMAGE_DATA_NUM_TYPES
+ IMAGE_DATA_NUM_TYPES
} ImageDataType;
#define IMAGE_DATA_TYPE_SHIFT 3
@@ -66,27 +66,27 @@ typedef enum ImageDataType {
*
* Defines how the image is extrapolated past its original bounds. */
typedef enum ExtensionType {
- /* Cause the image to repeat horizontally and vertically. */
- EXTENSION_REPEAT = 0,
- /* Extend by repeating edge pixels of the image. */
- EXTENSION_EXTEND = 1,
- /* Clip to image size and set exterior pixels as transparent. */
- EXTENSION_CLIP = 2,
+ /* Cause the image to repeat horizontally and vertically. */
+ EXTENSION_REPEAT = 0,
+ /* Extend by repeating edge pixels of the image. */
+ EXTENSION_EXTEND = 1,
+ /* Clip to image size and set exterior pixels as transparent. */
+ EXTENSION_CLIP = 2,
- EXTENSION_NUM_TYPES,
+ EXTENSION_NUM_TYPES,
} ExtensionType;
typedef struct TextureInfo {
- /* Pointer, offset or texture depending on device. */
- uint64_t data;
- /* Buffer number for OpenCL. */
- uint cl_buffer;
- /* Interpolation and extension type. */
- uint interpolation, extension;
- /* Dimensions. */
- uint width, height, depth;
+ /* Pointer, offset or texture depending on device. */
+ uint64_t data;
+ /* Buffer number for OpenCL. */
+ uint cl_buffer;
+ /* Interpolation and extension type. */
+ uint interpolation, extension;
+ /* Dimensions. */
+ uint width, height, depth;
} TextureInfo;
CCL_NAMESPACE_END
-#endif /* __UTIL_TEXTURE_H__ */
+#endif /* __UTIL_TEXTURE_H__ */
diff --git a/intern/cycles/util/util_thread.cpp b/intern/cycles/util/util_thread.cpp
index f3c6077f6b7..cccde5ae7d5 100644
--- a/intern/cycles/util/util_thread.cpp
+++ b/intern/cycles/util/util_thread.cpp
@@ -21,54 +21,51 @@
CCL_NAMESPACE_BEGIN
-thread::thread(function<void()> run_cb, int node)
- : run_cb_(run_cb),
- joined_(false),
- node_(node)
+thread::thread(function<void()> run_cb, int node) : run_cb_(run_cb), joined_(false), node_(node)
{
#ifdef __APPLE__
- /* Set the stack size to 2MB to match Linux. The default 512KB on macOS is
- * too small for Embree, and consistent stack size also makes things more
- * predictable in general. */
- pthread_attr_t attribute;
- pthread_attr_init(&attribute);
- pthread_attr_setstacksize(&attribute, 1024*1024*2);
- pthread_create(&pthread_id, &attribute, run, (void*)this);
+ /* Set the stack size to 2MB to match Linux. The default 512KB on macOS is
+ * too small for Embree, and consistent stack size also makes things more
+ * predictable in general. */
+ pthread_attr_t attribute;
+ pthread_attr_init(&attribute);
+ pthread_attr_setstacksize(&attribute, 1024 * 1024 * 2);
+ pthread_create(&pthread_id, &attribute, run, (void *)this);
#else
- std_thread = std::thread(&thread::run, this);
+ std_thread = std::thread(&thread::run, this);
#endif
}
thread::~thread()
{
- if(!joined_) {
- join();
- }
+ if (!joined_) {
+ join();
+ }
}
void *thread::run(void *arg)
{
- thread *self = (thread*)(arg);
- if (self->node_ != -1) {
- system_cpu_run_thread_on_node(self->node_);
- }
- self->run_cb_();
- return NULL;
+ thread *self = (thread *)(arg);
+ if (self->node_ != -1) {
+ system_cpu_run_thread_on_node(self->node_);
+ }
+ self->run_cb_();
+ return NULL;
}
bool thread::join()
{
- joined_ = true;
+ joined_ = true;
#ifdef __APPLE__
- return pthread_join(pthread_id, NULL) == 0;
+ return pthread_join(pthread_id, NULL) == 0;
#else
- try {
- std_thread.join();
- return true;
- }
- catch (const std::system_error&) {
- return false;
- }
+ try {
+ std_thread.join();
+ return true;
+ }
+ catch (const std::system_error &) {
+ return false;
+ }
#endif
}
diff --git a/intern/cycles/util/util_thread.h b/intern/cycles/util/util_thread.h
index 793d44130b6..18ec5b32144 100644
--- a/intern/cycles/util/util_thread.h
+++ b/intern/cycles/util/util_thread.h
@@ -45,103 +45,115 @@ typedef std::condition_variable thread_condition_variable;
* custom stack size on macOS. */
class thread {
-public:
- /* NOTE: Node index of -1 means that affinity will be inherited from the
- * parent thread and no override on top of that will happen. */
- thread(function<void()> run_cb, int node = -1);
- ~thread();
+ public:
+ /* NOTE: Node index of -1 means that affinity will be inherited from the
+ * parent thread and no override on top of that will happen. */
+ thread(function<void()> run_cb, int node = -1);
+ ~thread();
- static void *run(void *arg);
- bool join();
+ static void *run(void *arg);
+ bool join();
-protected:
- function<void()> run_cb_;
+ protected:
+ function<void()> run_cb_;
#ifdef __APPLE__
- pthread_t pthread_id;
+ pthread_t pthread_id;
#else
- std::thread std_thread;
+ std::thread std_thread;
#endif
- bool joined_;
- int node_;
+ bool joined_;
+ int node_;
};
/* Own wrapper around pthread's spin lock to make it's use easier. */
class thread_spin_lock {
-public:
+ public:
#ifdef __APPLE__
- inline thread_spin_lock() {
- spin_ = OS_SPINLOCK_INIT;
- }
-
- inline void lock() {
- OSSpinLockLock(&spin_);
- }
-
- inline void unlock() {
- OSSpinLockUnlock(&spin_);
- }
+ inline thread_spin_lock()
+ {
+ spin_ = OS_SPINLOCK_INIT;
+ }
+
+ inline void lock()
+ {
+ OSSpinLockLock(&spin_);
+ }
+
+ inline void unlock()
+ {
+ OSSpinLockUnlock(&spin_);
+ }
#elif defined(_WIN32)
- inline thread_spin_lock() {
- const DWORD SPIN_COUNT = 50000;
- InitializeCriticalSectionAndSpinCount(&cs_, SPIN_COUNT);
- }
-
- inline ~thread_spin_lock() {
- DeleteCriticalSection(&cs_);
- }
-
- inline void lock() {
- EnterCriticalSection(&cs_);
- }
-
- inline void unlock() {
- LeaveCriticalSection(&cs_);
- }
+ inline thread_spin_lock()
+ {
+ const DWORD SPIN_COUNT = 50000;
+ InitializeCriticalSectionAndSpinCount(&cs_, SPIN_COUNT);
+ }
+
+ inline ~thread_spin_lock()
+ {
+ DeleteCriticalSection(&cs_);
+ }
+
+ inline void lock()
+ {
+ EnterCriticalSection(&cs_);
+ }
+
+ inline void unlock()
+ {
+ LeaveCriticalSection(&cs_);
+ }
#else
- inline thread_spin_lock() {
- pthread_spin_init(&spin_, 0);
- }
-
- inline ~thread_spin_lock() {
- pthread_spin_destroy(&spin_);
- }
-
- inline void lock() {
- pthread_spin_lock(&spin_);
- }
-
- inline void unlock() {
- pthread_spin_unlock(&spin_);
- }
+ inline thread_spin_lock()
+ {
+ pthread_spin_init(&spin_, 0);
+ }
+
+ inline ~thread_spin_lock()
+ {
+ pthread_spin_destroy(&spin_);
+ }
+
+ inline void lock()
+ {
+ pthread_spin_lock(&spin_);
+ }
+
+ inline void unlock()
+ {
+ pthread_spin_unlock(&spin_);
+ }
#endif
-protected:
+ protected:
#ifdef __APPLE__
- OSSpinLock spin_;
+ OSSpinLock spin_;
#elif defined(_WIN32)
- CRITICAL_SECTION cs_;
+ CRITICAL_SECTION cs_;
#else
- pthread_spinlock_t spin_;
+ pthread_spinlock_t spin_;
#endif
};
class thread_scoped_spin_lock {
-public:
- explicit thread_scoped_spin_lock(thread_spin_lock& lock)
- : lock_(lock) {
- lock_.lock();
- }
+ public:
+ explicit thread_scoped_spin_lock(thread_spin_lock &lock) : lock_(lock)
+ {
+ lock_.lock();
+ }
- ~thread_scoped_spin_lock() {
- lock_.unlock();
- }
+ ~thread_scoped_spin_lock()
+ {
+ lock_.unlock();
+ }
- /* TODO(sergey): Implement manual control over lock/unlock. */
+ /* TODO(sergey): Implement manual control over lock/unlock. */
-protected:
- thread_spin_lock& lock_;
+ protected:
+ thread_spin_lock &lock_;
};
CCL_NAMESPACE_END
-#endif /* __UTIL_THREAD_H__ */
+#endif /* __UTIL_THREAD_H__ */
diff --git a/intern/cycles/util/util_time.cpp b/intern/cycles/util/util_time.cpp
index 9983fdd1df3..1641395d07e 100644
--- a/intern/cycles/util/util_time.cpp
+++ b/intern/cycles/util/util_time.cpp
@@ -32,44 +32,44 @@ CCL_NAMESPACE_BEGIN
#ifdef _WIN32
double time_dt()
{
- __int64 frequency, counter;
+ __int64 frequency, counter;
- QueryPerformanceFrequency((LARGE_INTEGER*)&frequency);
- QueryPerformanceCounter((LARGE_INTEGER*)&counter);
+ QueryPerformanceFrequency((LARGE_INTEGER *)&frequency);
+ QueryPerformanceCounter((LARGE_INTEGER *)&counter);
- return (double)counter/(double)frequency;
+ return (double)counter / (double)frequency;
}
void time_sleep(double t)
{
- Sleep((int)(t*1000));
+ Sleep((int)(t * 1000));
}
#else
double time_dt()
{
- struct timeval now;
- gettimeofday(&now, NULL);
+ struct timeval now;
+ gettimeofday(&now, NULL);
- return now.tv_sec + now.tv_usec*1e-6;
+ return now.tv_sec + now.tv_usec * 1e-6;
}
/* sleep t seconds */
void time_sleep(double t)
{
- /* get whole seconds */
- int s = (int)t;
+ /* get whole seconds */
+ int s = (int)t;
- if(s >= 1) {
- sleep(s);
+ if (s >= 1) {
+ sleep(s);
- /* adjust parameter to remove whole seconds */
- t -= s;
- }
+ /* adjust parameter to remove whole seconds */
+ t -= s;
+ }
- /* get microseconds */
- int us = (int)(t * 1e6);
- if(us > 0)
- usleep(us);
+ /* get microseconds */
+ int us = (int)(t * 1e6);
+ if (us > 0)
+ usleep(us);
}
#endif
@@ -77,63 +77,63 @@ void time_sleep(double t)
string time_human_readable_from_seconds(const double seconds)
{
- const int h = (((int)seconds) / (60 * 60));
- const int m = (((int)seconds) / 60) % 60;
- const int s = (((int)seconds) % 60);
- const int r = (((int)(seconds * 100)) % 100);
-
- if(h > 0) {
- return string_printf("%.2d:%.2d:%.2d.%.2d", h, m, s, r);
- }
- else {
- return string_printf("%.2d:%.2d.%.2d", m, s, r);
- }
+ const int h = (((int)seconds) / (60 * 60));
+ const int m = (((int)seconds) / 60) % 60;
+ const int s = (((int)seconds) % 60);
+ const int r = (((int)(seconds * 100)) % 100);
+
+ if (h > 0) {
+ return string_printf("%.2d:%.2d:%.2d.%.2d", h, m, s, r);
+ }
+ else {
+ return string_printf("%.2d:%.2d.%.2d", m, s, r);
+ }
}
-double time_human_readable_to_seconds(const string& time_string)
+double time_human_readable_to_seconds(const string &time_string)
{
- /* Those are multiplies of a corresponding token surrounded by : in the
- * time string, which denotes how to convert value to seconds.
- * Effectively: seconds, minutes, hours, days in seconds. */
- const int multipliers[] = {1, 60, 60*60, 24*60*60};
- const int num_multiplies = sizeof(multipliers) / sizeof(*multipliers);
- if(time_string.empty()) {
- return 0.0;
- }
- double result = 0.0;
- /* Split fractions of a second from the encoded time. */
- vector<string> fraction_tokens;
- string_split(fraction_tokens, time_string, ".", false);
- const int num_fraction_tokens = fraction_tokens.size();
- if(num_fraction_tokens == 0) {
- /* Time string is malformed. */
- return 0.0;
- }
- else if(fraction_tokens.size() == 1) {
- /* There is no fraction of a second specified, the rest of the code
- * handles this normally. */
- }
- else if(fraction_tokens.size() == 2) {
- result = atof(fraction_tokens[1].c_str());
- result *= pow(0.1, fraction_tokens[1].length());
- }
- else {
- /* This is not a valid string, the result can not be reliable. */
- return 0.0;
- }
- /* Split hours, minutes and seconds.
- * Hours part is optional. */
- vector<string> tokens;
- string_split(tokens, fraction_tokens[0], ":", false);
- const int num_tokens = tokens.size();
- if(num_tokens > num_multiplies) {
- /* Can not reliably represent the value. */
- return 0.0;
- }
- for(int i = 0; i < num_tokens; ++i) {
- result += atoi(tokens[num_tokens - i - 1].c_str()) * multipliers[i];
- }
- return result;
+ /* Those are multiplies of a corresponding token surrounded by : in the
+ * time string, which denotes how to convert value to seconds.
+ * Effectively: seconds, minutes, hours, days in seconds. */
+ const int multipliers[] = {1, 60, 60 * 60, 24 * 60 * 60};
+ const int num_multiplies = sizeof(multipliers) / sizeof(*multipliers);
+ if (time_string.empty()) {
+ return 0.0;
+ }
+ double result = 0.0;
+ /* Split fractions of a second from the encoded time. */
+ vector<string> fraction_tokens;
+ string_split(fraction_tokens, time_string, ".", false);
+ const int num_fraction_tokens = fraction_tokens.size();
+ if (num_fraction_tokens == 0) {
+ /* Time string is malformed. */
+ return 0.0;
+ }
+ else if (fraction_tokens.size() == 1) {
+ /* There is no fraction of a second specified, the rest of the code
+ * handles this normally. */
+ }
+ else if (fraction_tokens.size() == 2) {
+ result = atof(fraction_tokens[1].c_str());
+ result *= pow(0.1, fraction_tokens[1].length());
+ }
+ else {
+ /* This is not a valid string, the result can not be reliable. */
+ return 0.0;
+ }
+ /* Split hours, minutes and seconds.
+ * Hours part is optional. */
+ vector<string> tokens;
+ string_split(tokens, fraction_tokens[0], ":", false);
+ const int num_tokens = tokens.size();
+ if (num_tokens > num_multiplies) {
+ /* Can not reliably represent the value. */
+ return 0.0;
+ }
+ for (int i = 0; i < num_tokens; ++i) {
+ result += atoi(tokens[num_tokens - i - 1].c_str()) * multipliers[i];
+ }
+ return result;
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/util/util_time.h b/intern/cycles/util/util_time.h
index ed4dd5154d7..bc9a7414312 100644
--- a/intern/cycles/util/util_time.h
+++ b/intern/cycles/util/util_time.h
@@ -32,38 +32,38 @@ void time_sleep(double t);
/* Scoped timer. */
class scoped_timer {
-public:
- explicit scoped_timer(double *value = NULL) : value_(value)
- {
- time_start_ = time_dt();
- }
-
- ~scoped_timer()
- {
- if(value_ != NULL) {
- *value_ = get_time();
- }
- }
-
- double get_start() const
- {
- return time_start_;
- }
-
- double get_time() const
- {
- return time_dt() - time_start_;
- }
-
-protected:
- double *value_;
- double time_start_;
+ public:
+ explicit scoped_timer(double *value = NULL) : value_(value)
+ {
+ time_start_ = time_dt();
+ }
+
+ ~scoped_timer()
+ {
+ if (value_ != NULL) {
+ *value_ = get_time();
+ }
+ }
+
+ double get_start() const
+ {
+ return time_start_;
+ }
+
+ double get_time() const
+ {
+ return time_dt() - time_start_;
+ }
+
+ protected:
+ double *value_;
+ double time_start_;
};
/* Make human readable string from time, compatible with Blender metadata. */
string time_human_readable_from_seconds(const double seconds);
-double time_human_readable_to_seconds(const string& str);
+double time_human_readable_to_seconds(const string &str);
CCL_NAMESPACE_END
diff --git a/intern/cycles/util/util_transform.cpp b/intern/cycles/util/util_transform.cpp
index c72e729a2e5..6a9bfbea4ca 100644
--- a/intern/cycles/util/util_transform.cpp
+++ b/intern/cycles/util/util_transform.cpp
@@ -58,232 +58,230 @@ CCL_NAMESPACE_BEGIN
static bool transform_matrix4_gj_inverse(float R[][4], float M[][4])
{
- /* forward elimination */
- for(int i = 0; i < 4; i++) {
- int pivot = i;
- float pivotsize = M[i][i];
-
- if(pivotsize < 0)
- pivotsize = -pivotsize;
-
- for(int j = i + 1; j < 4; j++) {
- float tmp = M[j][i];
-
- if(tmp < 0)
- tmp = -tmp;
-
- if(tmp > pivotsize) {
- pivot = j;
- pivotsize = tmp;
- }
- }
-
- if(UNLIKELY(pivotsize == 0.0f))
- return false;
-
- if(pivot != i) {
- for(int j = 0; j < 4; j++) {
- float tmp;
-
- tmp = M[i][j];
- M[i][j] = M[pivot][j];
- M[pivot][j] = tmp;
-
- tmp = R[i][j];
- R[i][j] = R[pivot][j];
- R[pivot][j] = tmp;
- }
- }
-
- for(int j = i + 1; j < 4; j++) {
- float f = M[j][i] / M[i][i];
-
- for(int k = 0; k < 4; k++) {
- M[j][k] -= f*M[i][k];
- R[j][k] -= f*R[i][k];
- }
- }
- }
-
- /* backward substitution */
- for(int i = 3; i >= 0; --i) {
- float f;
-
- if(UNLIKELY((f = M[i][i]) == 0.0f))
- return false;
-
- for(int j = 0; j < 4; j++) {
- M[i][j] /= f;
- R[i][j] /= f;
- }
-
- for(int j = 0; j < i; j++) {
- f = M[j][i];
-
- for(int k = 0; k < 4; k++) {
- M[j][k] -= f*M[i][k];
- R[j][k] -= f*R[i][k];
- }
- }
- }
-
- return true;
+ /* forward elimination */
+ for (int i = 0; i < 4; i++) {
+ int pivot = i;
+ float pivotsize = M[i][i];
+
+ if (pivotsize < 0)
+ pivotsize = -pivotsize;
+
+ for (int j = i + 1; j < 4; j++) {
+ float tmp = M[j][i];
+
+ if (tmp < 0)
+ tmp = -tmp;
+
+ if (tmp > pivotsize) {
+ pivot = j;
+ pivotsize = tmp;
+ }
+ }
+
+ if (UNLIKELY(pivotsize == 0.0f))
+ return false;
+
+ if (pivot != i) {
+ for (int j = 0; j < 4; j++) {
+ float tmp;
+
+ tmp = M[i][j];
+ M[i][j] = M[pivot][j];
+ M[pivot][j] = tmp;
+
+ tmp = R[i][j];
+ R[i][j] = R[pivot][j];
+ R[pivot][j] = tmp;
+ }
+ }
+
+ for (int j = i + 1; j < 4; j++) {
+ float f = M[j][i] / M[i][i];
+
+ for (int k = 0; k < 4; k++) {
+ M[j][k] -= f * M[i][k];
+ R[j][k] -= f * R[i][k];
+ }
+ }
+ }
+
+ /* backward substitution */
+ for (int i = 3; i >= 0; --i) {
+ float f;
+
+ if (UNLIKELY((f = M[i][i]) == 0.0f))
+ return false;
+
+ for (int j = 0; j < 4; j++) {
+ M[i][j] /= f;
+ R[i][j] /= f;
+ }
+
+ for (int j = 0; j < i; j++) {
+ f = M[j][i];
+
+ for (int k = 0; k < 4; k++) {
+ M[j][k] -= f * M[i][k];
+ R[j][k] -= f * R[i][k];
+ }
+ }
+ }
+
+ return true;
}
-ProjectionTransform projection_inverse(const ProjectionTransform& tfm)
+ProjectionTransform projection_inverse(const ProjectionTransform &tfm)
{
- ProjectionTransform tfmR = projection_identity();
- float M[4][4], R[4][4];
+ ProjectionTransform tfmR = projection_identity();
+ float M[4][4], R[4][4];
- memcpy(R, &tfmR, sizeof(R));
- memcpy(M, &tfm, sizeof(M));
+ memcpy(R, &tfmR, sizeof(R));
+ memcpy(M, &tfm, sizeof(M));
- if(UNLIKELY(!transform_matrix4_gj_inverse(R, M))) {
- /* matrix is degenerate (e.g. 0 scale on some axis), ideally we should
- * never be in this situation, but try to invert it anyway with tweak */
- M[0][0] += 1e-8f;
- M[1][1] += 1e-8f;
- M[2][2] += 1e-8f;
+ if (UNLIKELY(!transform_matrix4_gj_inverse(R, M))) {
+ /* matrix is degenerate (e.g. 0 scale on some axis), ideally we should
+ * never be in this situation, but try to invert it anyway with tweak */
+ M[0][0] += 1e-8f;
+ M[1][1] += 1e-8f;
+ M[2][2] += 1e-8f;
- if(UNLIKELY(!transform_matrix4_gj_inverse(R, M))) {
- return projection_identity();
- }
- }
+ if (UNLIKELY(!transform_matrix4_gj_inverse(R, M))) {
+ return projection_identity();
+ }
+ }
- memcpy(&tfmR, R, sizeof(R));
+ memcpy(&tfmR, R, sizeof(R));
- return tfmR;
+ return tfmR;
}
-Transform transform_inverse(const Transform& tfm)
+Transform transform_inverse(const Transform &tfm)
{
- ProjectionTransform projection(tfm);
- return projection_to_transform(projection_inverse(projection));
+ ProjectionTransform projection(tfm);
+ return projection_to_transform(projection_inverse(projection));
}
-Transform transform_transposed_inverse(const Transform& tfm)
+Transform transform_transposed_inverse(const Transform &tfm)
{
- ProjectionTransform projection(tfm);
- ProjectionTransform iprojection = projection_inverse(projection);
- return projection_to_transform(projection_transpose(iprojection));
+ ProjectionTransform projection(tfm);
+ ProjectionTransform iprojection = projection_inverse(projection);
+ return projection_to_transform(projection_transpose(iprojection));
}
/* Motion Transform */
-float4 transform_to_quat(const Transform& tfm)
+float4 transform_to_quat(const Transform &tfm)
{
- double trace = (double)(tfm[0][0] + tfm[1][1] + tfm[2][2]);
- float4 qt;
+ double trace = (double)(tfm[0][0] + tfm[1][1] + tfm[2][2]);
+ float4 qt;
- if(trace > 0.0) {
- double s = sqrt(trace + 1.0);
+ if (trace > 0.0) {
+ double s = sqrt(trace + 1.0);
- qt.w = (float)(s/2.0);
- s = 0.5/s;
+ qt.w = (float)(s / 2.0);
+ s = 0.5 / s;
- qt.x = (float)((double)(tfm[2][1] - tfm[1][2]) * s);
- qt.y = (float)((double)(tfm[0][2] - tfm[2][0]) * s);
- qt.z = (float)((double)(tfm[1][0] - tfm[0][1]) * s);
- }
- else {
- int i = 0;
+ qt.x = (float)((double)(tfm[2][1] - tfm[1][2]) * s);
+ qt.y = (float)((double)(tfm[0][2] - tfm[2][0]) * s);
+ qt.z = (float)((double)(tfm[1][0] - tfm[0][1]) * s);
+ }
+ else {
+ int i = 0;
- if(tfm[1][1] > tfm[i][i])
- i = 1;
- if(tfm[2][2] > tfm[i][i])
- i = 2;
+ if (tfm[1][1] > tfm[i][i])
+ i = 1;
+ if (tfm[2][2] > tfm[i][i])
+ i = 2;
- int j = (i + 1)%3;
- int k = (j + 1)%3;
+ int j = (i + 1) % 3;
+ int k = (j + 1) % 3;
- double s = sqrt((double)(tfm[i][i] - (tfm[j][j] + tfm[k][k])) + 1.0);
+ double s = sqrt((double)(tfm[i][i] - (tfm[j][j] + tfm[k][k])) + 1.0);
- double q[3];
- q[i] = s * 0.5;
- if(s != 0.0)
- s = 0.5/s;
+ double q[3];
+ q[i] = s * 0.5;
+ if (s != 0.0)
+ s = 0.5 / s;
- double w = (double)(tfm[k][j] - tfm[j][k]) * s;
- q[j] = (double)(tfm[j][i] + tfm[i][j]) * s;
- q[k] = (double)(tfm[k][i] + tfm[i][k]) * s;
+ double w = (double)(tfm[k][j] - tfm[j][k]) * s;
+ q[j] = (double)(tfm[j][i] + tfm[i][j]) * s;
+ q[k] = (double)(tfm[k][i] + tfm[i][k]) * s;
- qt.x = (float)q[0];
- qt.y = (float)q[1];
- qt.z = (float)q[2];
- qt.w = (float)w;
- }
+ qt.x = (float)q[0];
+ qt.y = (float)q[1];
+ qt.z = (float)q[2];
+ qt.w = (float)w;
+ }
- return qt;
+ return qt;
}
static void transform_decompose(DecomposedTransform *decomp, const Transform *tfm)
{
- /* extract translation */
- decomp->y = make_float4(tfm->x.w, tfm->y.w, tfm->z.w, 0.0f);
-
- /* extract rotation */
- Transform M = *tfm;
- M.x.w = 0.0f; M.y.w = 0.0f; M.z.w = 0.0f;
-
- Transform R = M;
- float norm;
- int iteration = 0;
-
- do {
- Transform Rnext;
- Transform Rit = transform_transposed_inverse(R);
-
- for(int i = 0; i < 3; i++)
- for(int j = 0; j < 4; j++)
- Rnext[i][j] = 0.5f * (R[i][j] + Rit[i][j]);
-
- norm = 0.0f;
- for(int i = 0; i < 3; i++) {
- norm = max(norm,
- fabsf(R[i][0] - Rnext[i][0]) +
- fabsf(R[i][1] - Rnext[i][1]) +
- fabsf(R[i][2] - Rnext[i][2]));
- }
-
- R = Rnext;
- iteration++;
- } while(iteration < 100 && norm > 1e-4f);
-
- if(transform_negative_scale(R))
- R = R * transform_scale(-1.0f, -1.0f, -1.0f);
-
- decomp->x = transform_to_quat(R);
-
- /* extract scale and pack it */
- Transform scale = transform_inverse(R) * M;
- decomp->y.w = scale.x.x;
- decomp->z = make_float4(scale.x.y, scale.x.z, scale.y.x, scale.y.y);
- decomp->w = make_float4(scale.y.z, scale.z.x, scale.z.y, scale.z.z);
+ /* extract translation */
+ decomp->y = make_float4(tfm->x.w, tfm->y.w, tfm->z.w, 0.0f);
+
+ /* extract rotation */
+ Transform M = *tfm;
+ M.x.w = 0.0f;
+ M.y.w = 0.0f;
+ M.z.w = 0.0f;
+
+ Transform R = M;
+ float norm;
+ int iteration = 0;
+
+ do {
+ Transform Rnext;
+ Transform Rit = transform_transposed_inverse(R);
+
+ for (int i = 0; i < 3; i++)
+ for (int j = 0; j < 4; j++)
+ Rnext[i][j] = 0.5f * (R[i][j] + Rit[i][j]);
+
+ norm = 0.0f;
+ for (int i = 0; i < 3; i++) {
+ norm = max(norm,
+ fabsf(R[i][0] - Rnext[i][0]) + fabsf(R[i][1] - Rnext[i][1]) +
+ fabsf(R[i][2] - Rnext[i][2]));
+ }
+
+ R = Rnext;
+ iteration++;
+ } while (iteration < 100 && norm > 1e-4f);
+
+ if (transform_negative_scale(R))
+ R = R * transform_scale(-1.0f, -1.0f, -1.0f);
+
+ decomp->x = transform_to_quat(R);
+
+ /* extract scale and pack it */
+ Transform scale = transform_inverse(R) * M;
+ decomp->y.w = scale.x.x;
+ decomp->z = make_float4(scale.x.y, scale.x.z, scale.y.x, scale.y.y);
+ decomp->w = make_float4(scale.y.z, scale.z.x, scale.z.y, scale.z.z);
}
void transform_motion_decompose(DecomposedTransform *decomp, const Transform *motion, size_t size)
{
- for(size_t i = 0; i < size; i++) {
- transform_decompose(decomp + i, motion + i);
-
- if(i > 0) {
- /* Ensure rotation around shortest angle, negated quaternions are the same
- * but this means we don't have to do the check in quat_interpolate */
- if(dot(decomp[i-1].x, decomp[i].x) < 0.0f)
- decomp[i-1].x = -decomp[i-1].x;
- }
- }
+ for (size_t i = 0; i < size; i++) {
+ transform_decompose(decomp + i, motion + i);
+
+ if (i > 0) {
+ /* Ensure rotation around shortest angle, negated quaternions are the same
+ * but this means we don't have to do the check in quat_interpolate */
+ if (dot(decomp[i - 1].x, decomp[i].x) < 0.0f)
+ decomp[i - 1].x = -decomp[i - 1].x;
+ }
+ }
}
-Transform transform_from_viewplane(BoundBox2D& viewplane)
+Transform transform_from_viewplane(BoundBox2D &viewplane)
{
- return
- transform_scale(1.0f / (viewplane.right - viewplane.left),
- 1.0f / (viewplane.top - viewplane.bottom),
- 1.0f) *
- transform_translate(-viewplane.left,
- -viewplane.bottom,
- 0.0f);
+ return transform_scale(1.0f / (viewplane.right - viewplane.left),
+ 1.0f / (viewplane.top - viewplane.bottom),
+ 1.0f) *
+ transform_translate(-viewplane.left, -viewplane.bottom, 0.0f);
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/util/util_transform.h b/intern/cycles/util/util_transform.h
index e4cadd3e81a..13ca27c2fed 100644
--- a/intern/cycles/util/util_transform.h
+++ b/intern/cycles/util/util_transform.h
@@ -18,7 +18,7 @@
#define __UTIL_TRANSFORM_H__
#ifndef __KERNEL_GPU__
-#include <string.h>
+# include <string.h>
#endif
#include "util/util_math.h"
@@ -29,11 +29,17 @@ CCL_NAMESPACE_BEGIN
/* Affine transformation, stored as 4x3 matrix. */
typedef struct Transform {
- float4 x, y, z;
+ float4 x, y, z;
#ifndef __KERNEL_GPU__
- float4 operator[](int i) const { return *(&x + i); }
- float4& operator[](int i) { return *(&x + i); }
+ float4 operator[](int i) const
+ {
+ return *(&x + i);
+ }
+ float4 &operator[](int i)
+ {
+ return *(&x + i);
+ }
#endif
} Transform;
@@ -42,267 +48,268 @@ typedef struct Transform {
* rotation (4), then translation (3), then 3x3 scale matrix (9). */
typedef struct DecomposedTransform {
- float4 x, y, z, w;
+ float4 x, y, z, w;
} DecomposedTransform;
/* Functions */
ccl_device_inline float3 transform_point(const Transform *t, const float3 a)
{
- /* TODO(sergey): Disabled for now, causes crashes in certain cases. */
+ /* TODO(sergey): Disabled for now, causes crashes in certain cases. */
#if defined(__KERNEL_SSE__) && defined(__KERNEL_SSE2__)
- ssef x, y, z, w, aa;
- aa = a.m128;
+ ssef x, y, z, w, aa;
+ aa = a.m128;
- x = _mm_loadu_ps(&t->x.x);
- y = _mm_loadu_ps(&t->y.x);
- z = _mm_loadu_ps(&t->z.x);
- w = _mm_set_ps(1.0f, 0.0f, 0.0f, 0.0f);
+ x = _mm_loadu_ps(&t->x.x);
+ y = _mm_loadu_ps(&t->y.x);
+ z = _mm_loadu_ps(&t->z.x);
+ w = _mm_set_ps(1.0f, 0.0f, 0.0f, 0.0f);
- _MM_TRANSPOSE4_PS(x, y, z, w);
+ _MM_TRANSPOSE4_PS(x, y, z, w);
- ssef tmp = shuffle<0>(aa) * x;
- tmp = madd(shuffle<1>(aa), y, tmp);
- tmp = madd(shuffle<2>(aa), z, tmp);
- tmp += w;
+ ssef tmp = shuffle<0>(aa) * x;
+ tmp = madd(shuffle<1>(aa), y, tmp);
+ tmp = madd(shuffle<2>(aa), z, tmp);
+ tmp += w;
- return float3(tmp.m128);
+ return float3(tmp.m128);
#else
- float3 c = make_float3(
- a.x*t->x.x + a.y*t->x.y + a.z*t->x.z + t->x.w,
- a.x*t->y.x + a.y*t->y.y + a.z*t->y.z + t->y.w,
- a.x*t->z.x + a.y*t->z.y + a.z*t->z.z + t->z.w);
+ float3 c = make_float3(a.x * t->x.x + a.y * t->x.y + a.z * t->x.z + t->x.w,
+ a.x * t->y.x + a.y * t->y.y + a.z * t->y.z + t->y.w,
+ a.x * t->z.x + a.y * t->z.y + a.z * t->z.z + t->z.w);
- return c;
+ return c;
#endif
}
ccl_device_inline float3 transform_direction(const Transform *t, const float3 a)
{
#if defined(__KERNEL_SSE__) && defined(__KERNEL_SSE2__)
- ssef x, y, z, w, aa;
- aa = a.m128;
- x = _mm_loadu_ps(&t->x.x);
- y = _mm_loadu_ps(&t->y.x);
- z = _mm_loadu_ps(&t->z.x);
- w = _mm_setzero_ps();
+ ssef x, y, z, w, aa;
+ aa = a.m128;
+ x = _mm_loadu_ps(&t->x.x);
+ y = _mm_loadu_ps(&t->y.x);
+ z = _mm_loadu_ps(&t->z.x);
+ w = _mm_setzero_ps();
- _MM_TRANSPOSE4_PS(x, y, z, w);
+ _MM_TRANSPOSE4_PS(x, y, z, w);
- ssef tmp = shuffle<0>(aa) * x;
- tmp = madd(shuffle<1>(aa), y, tmp);
- tmp = madd(shuffle<2>(aa), z, tmp);
+ ssef tmp = shuffle<0>(aa) * x;
+ tmp = madd(shuffle<1>(aa), y, tmp);
+ tmp = madd(shuffle<2>(aa), z, tmp);
- return float3(tmp.m128);
+ return float3(tmp.m128);
#else
- float3 c = make_float3(
- a.x*t->x.x + a.y*t->x.y + a.z*t->x.z,
- a.x*t->y.x + a.y*t->y.y + a.z*t->y.z,
- a.x*t->z.x + a.y*t->z.y + a.z*t->z.z);
+ float3 c = make_float3(a.x * t->x.x + a.y * t->x.y + a.z * t->x.z,
+ a.x * t->y.x + a.y * t->y.y + a.z * t->y.z,
+ a.x * t->z.x + a.y * t->z.y + a.z * t->z.z);
- return c;
+ return c;
#endif
}
ccl_device_inline float3 transform_direction_transposed(const Transform *t, const float3 a)
{
- float3 x = make_float3(t->x.x, t->y.x, t->z.x);
- float3 y = make_float3(t->x.y, t->y.y, t->z.y);
- float3 z = make_float3(t->x.z, t->y.z, t->z.z);
+ float3 x = make_float3(t->x.x, t->y.x, t->z.x);
+ float3 y = make_float3(t->x.y, t->y.y, t->z.y);
+ float3 z = make_float3(t->x.z, t->y.z, t->z.z);
- return make_float3(dot(x, a), dot(y, a), dot(z, a));
+ return make_float3(dot(x, a), dot(y, a), dot(z, a));
}
-ccl_device_inline Transform make_transform(float a, float b, float c, float d,
- float e, float f, float g, float h,
- float i, float j, float k, float l)
+ccl_device_inline Transform make_transform(float a,
+ float b,
+ float c,
+ float d,
+ float e,
+ float f,
+ float g,
+ float h,
+ float i,
+ float j,
+ float k,
+ float l)
{
- Transform t;
-
- t.x.x = a; t.x.y = b; t.x.z = c; t.x.w = d;
- t.y.x = e; t.y.y = f; t.y.z = g; t.y.w = h;
- t.z.x = i; t.z.y = j; t.z.z = k; t.z.w = l;
-
- return t;
+ Transform t;
+
+ t.x.x = a;
+ t.x.y = b;
+ t.x.z = c;
+ t.x.w = d;
+ t.y.x = e;
+ t.y.y = f;
+ t.y.z = g;
+ t.y.w = h;
+ t.z.x = i;
+ t.z.y = j;
+ t.z.z = k;
+ t.z.w = l;
+
+ return t;
}
/* Constructs a coordinate frame from a normalized normal. */
ccl_device_inline Transform make_transform_frame(float3 N)
{
- const float3 dx0 = cross(make_float3(1.0f, 0.0f, 0.0f), N);
- const float3 dx1 = cross(make_float3(0.0f, 1.0f, 0.0f), N);
- const float3 dx = normalize((dot(dx0,dx0) > dot(dx1,dx1))? dx0: dx1);
- const float3 dy = normalize(cross(N, dx));
- return make_transform(dx.x, dx.y, dx.z, 0.0f,
- dy.x, dy.y, dy.z, 0.0f,
- N.x , N.y, N.z, 0.0f);
+ const float3 dx0 = cross(make_float3(1.0f, 0.0f, 0.0f), N);
+ const float3 dx1 = cross(make_float3(0.0f, 1.0f, 0.0f), N);
+ const float3 dx = normalize((dot(dx0, dx0) > dot(dx1, dx1)) ? dx0 : dx1);
+ const float3 dy = normalize(cross(N, dx));
+ return make_transform(dx.x, dx.y, dx.z, 0.0f, dy.x, dy.y, dy.z, 0.0f, N.x, N.y, N.z, 0.0f);
}
#ifndef __KERNEL_GPU__
ccl_device_inline Transform operator*(const Transform a, const Transform b)
{
- float4 c_x = make_float4(b.x.x, b.y.x, b.z.x, 0.0f);
- float4 c_y = make_float4(b.x.y, b.y.y, b.z.y, 0.0f);
- float4 c_z = make_float4(b.x.z, b.y.z, b.z.z, 0.0f);
- float4 c_w = make_float4(b.x.w, b.y.w, b.z.w, 1.0f);
+ float4 c_x = make_float4(b.x.x, b.y.x, b.z.x, 0.0f);
+ float4 c_y = make_float4(b.x.y, b.y.y, b.z.y, 0.0f);
+ float4 c_z = make_float4(b.x.z, b.y.z, b.z.z, 0.0f);
+ float4 c_w = make_float4(b.x.w, b.y.w, b.z.w, 1.0f);
- Transform t;
- t.x = make_float4(dot(a.x, c_x), dot(a.x, c_y), dot(a.x, c_z), dot(a.x, c_w));
- t.y = make_float4(dot(a.y, c_x), dot(a.y, c_y), dot(a.y, c_z), dot(a.y, c_w));
- t.z = make_float4(dot(a.z, c_x), dot(a.z, c_y), dot(a.z, c_z), dot(a.z, c_w));
+ Transform t;
+ t.x = make_float4(dot(a.x, c_x), dot(a.x, c_y), dot(a.x, c_z), dot(a.x, c_w));
+ t.y = make_float4(dot(a.y, c_x), dot(a.y, c_y), dot(a.y, c_z), dot(a.y, c_w));
+ t.z = make_float4(dot(a.z, c_x), dot(a.z, c_y), dot(a.z, c_z), dot(a.z, c_w));
- return t;
+ return t;
}
-ccl_device_inline void print_transform(const char *label, const Transform& t)
+ccl_device_inline void print_transform(const char *label, const Transform &t)
{
- print_float4(label, t.x);
- print_float4(label, t.y);
- print_float4(label, t.z);
- printf("\n");
+ print_float4(label, t.x);
+ print_float4(label, t.y);
+ print_float4(label, t.z);
+ printf("\n");
}
ccl_device_inline Transform transform_translate(float3 t)
{
- return make_transform(
- 1, 0, 0, t.x,
- 0, 1, 0, t.y,
- 0, 0, 1, t.z);
+ return make_transform(1, 0, 0, t.x, 0, 1, 0, t.y, 0, 0, 1, t.z);
}
ccl_device_inline Transform transform_translate(float x, float y, float z)
{
- return transform_translate(make_float3(x, y, z));
+ return transform_translate(make_float3(x, y, z));
}
ccl_device_inline Transform transform_scale(float3 s)
{
- return make_transform(
- s.x, 0, 0, 0,
- 0, s.y, 0, 0,
- 0, 0, s.z, 0);
+ return make_transform(s.x, 0, 0, 0, 0, s.y, 0, 0, 0, 0, s.z, 0);
}
ccl_device_inline Transform transform_scale(float x, float y, float z)
{
- return transform_scale(make_float3(x, y, z));
+ return transform_scale(make_float3(x, y, z));
}
ccl_device_inline Transform transform_rotate(float angle, float3 axis)
{
- float s = sinf(angle);
- float c = cosf(angle);
- float t = 1.0f - c;
-
- axis = normalize(axis);
-
- return make_transform(
- axis.x*axis.x*t + c,
- axis.x*axis.y*t - s*axis.z,
- axis.x*axis.z*t + s*axis.y,
- 0.0f,
-
- axis.y*axis.x*t + s*axis.z,
- axis.y*axis.y*t + c,
- axis.y*axis.z*t - s*axis.x,
- 0.0f,
-
- axis.z*axis.x*t - s*axis.y,
- axis.z*axis.y*t + s*axis.x,
- axis.z*axis.z*t + c,
- 0.0f);
+ float s = sinf(angle);
+ float c = cosf(angle);
+ float t = 1.0f - c;
+
+ axis = normalize(axis);
+
+ return make_transform(axis.x * axis.x * t + c,
+ axis.x * axis.y * t - s * axis.z,
+ axis.x * axis.z * t + s * axis.y,
+ 0.0f,
+
+ axis.y * axis.x * t + s * axis.z,
+ axis.y * axis.y * t + c,
+ axis.y * axis.z * t - s * axis.x,
+ 0.0f,
+
+ axis.z * axis.x * t - s * axis.y,
+ axis.z * axis.y * t + s * axis.x,
+ axis.z * axis.z * t + c,
+ 0.0f);
}
/* Euler is assumed to be in XYZ order. */
ccl_device_inline Transform transform_euler(float3 euler)
{
- return
- transform_rotate(euler.z, make_float3(0.0f, 0.0f, 1.0f)) *
- transform_rotate(euler.y, make_float3(0.0f, 1.0f, 0.0f)) *
- transform_rotate(euler.x, make_float3(1.0f, 0.0f, 0.0f));
+ return transform_rotate(euler.z, make_float3(0.0f, 0.0f, 1.0f)) *
+ transform_rotate(euler.y, make_float3(0.0f, 1.0f, 0.0f)) *
+ transform_rotate(euler.x, make_float3(1.0f, 0.0f, 0.0f));
}
ccl_device_inline Transform transform_identity()
{
- return transform_scale(1.0f, 1.0f, 1.0f);
+ return transform_scale(1.0f, 1.0f, 1.0f);
}
-ccl_device_inline bool operator==(const Transform& A, const Transform& B)
+ccl_device_inline bool operator==(const Transform &A, const Transform &B)
{
- return memcmp(&A, &B, sizeof(Transform)) == 0;
+ return memcmp(&A, &B, sizeof(Transform)) == 0;
}
-ccl_device_inline bool operator!=(const Transform& A, const Transform& B)
+ccl_device_inline bool operator!=(const Transform &A, const Transform &B)
{
- return !(A == B);
+ return !(A == B);
}
ccl_device_inline float3 transform_get_column(const Transform *t, int column)
{
- return make_float3(t->x[column], t->y[column], t->z[column]);
+ return make_float3(t->x[column], t->y[column], t->z[column]);
}
ccl_device_inline void transform_set_column(Transform *t, int column, float3 value)
{
- t->x[column] = value.x;
- t->y[column] = value.y;
- t->z[column] = value.z;
+ t->x[column] = value.x;
+ t->y[column] = value.y;
+ t->z[column] = value.z;
}
-Transform transform_inverse(const Transform& a);
-Transform transform_transposed_inverse(const Transform& a);
+Transform transform_inverse(const Transform &a);
+Transform transform_transposed_inverse(const Transform &a);
-ccl_device_inline bool transform_uniform_scale(const Transform& tfm, float& scale)
+ccl_device_inline bool transform_uniform_scale(const Transform &tfm, float &scale)
{
- /* the epsilon here is quite arbitrary, but this function is only used for
- * surface area and bump, where we expect it to not be so sensitive */
- float eps = 1e-6f;
-
- float sx = len_squared(float4_to_float3(tfm.x));
- float sy = len_squared(float4_to_float3(tfm.y));
- float sz = len_squared(float4_to_float3(tfm.z));
- float stx = len_squared(transform_get_column(&tfm, 0));
- float sty = len_squared(transform_get_column(&tfm, 1));
- float stz = len_squared(transform_get_column(&tfm, 2));
-
- if(fabsf(sx - sy) < eps && fabsf(sx - sz) < eps &&
- fabsf(sx - stx) < eps && fabsf(sx - sty) < eps &&
- fabsf(sx - stz) < eps)
- {
- scale = sx;
- return true;
- }
-
- return false;
+ /* the epsilon here is quite arbitrary, but this function is only used for
+ * surface area and bump, where we expect it to not be so sensitive */
+ float eps = 1e-6f;
+
+ float sx = len_squared(float4_to_float3(tfm.x));
+ float sy = len_squared(float4_to_float3(tfm.y));
+ float sz = len_squared(float4_to_float3(tfm.z));
+ float stx = len_squared(transform_get_column(&tfm, 0));
+ float sty = len_squared(transform_get_column(&tfm, 1));
+ float stz = len_squared(transform_get_column(&tfm, 2));
+
+ if (fabsf(sx - sy) < eps && fabsf(sx - sz) < eps && fabsf(sx - stx) < eps &&
+ fabsf(sx - sty) < eps && fabsf(sx - stz) < eps) {
+ scale = sx;
+ return true;
+ }
+
+ return false;
}
-ccl_device_inline bool transform_negative_scale(const Transform& tfm)
+ccl_device_inline bool transform_negative_scale(const Transform &tfm)
{
- float3 c0 = transform_get_column(&tfm, 0);
- float3 c1 = transform_get_column(&tfm, 1);
- float3 c2 = transform_get_column(&tfm, 2);
+ float3 c0 = transform_get_column(&tfm, 0);
+ float3 c1 = transform_get_column(&tfm, 1);
+ float3 c2 = transform_get_column(&tfm, 2);
- return (dot(cross(c0, c1), c2) < 0.0f);
+ return (dot(cross(c0, c1), c2) < 0.0f);
}
-ccl_device_inline Transform transform_clear_scale(const Transform& tfm)
+ccl_device_inline Transform transform_clear_scale(const Transform &tfm)
{
- Transform ntfm = tfm;
+ Transform ntfm = tfm;
- transform_set_column(&ntfm, 0, normalize(transform_get_column(&ntfm, 0)));
- transform_set_column(&ntfm, 1, normalize(transform_get_column(&ntfm, 1)));
- transform_set_column(&ntfm, 2, normalize(transform_get_column(&ntfm, 2)));
+ transform_set_column(&ntfm, 0, normalize(transform_get_column(&ntfm, 0)));
+ transform_set_column(&ntfm, 1, normalize(transform_get_column(&ntfm, 1)));
+ transform_set_column(&ntfm, 2, normalize(transform_get_column(&ntfm, 2)));
- return ntfm;
+ return ntfm;
}
ccl_device_inline Transform transform_empty()
{
- return make_transform(
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0);
+ return make_transform(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
}
#endif
@@ -311,90 +318,101 @@ ccl_device_inline Transform transform_empty()
ccl_device_inline float4 quat_interpolate(float4 q1, float4 q2, float t)
{
- /* use simpe nlerp instead of slerp. it's faster and almost the same */
- return normalize((1.0f - t)*q1 + t*q2);
+ /* use simpe nlerp instead of slerp. it's faster and almost the same */
+ return normalize((1.0f - t) * q1 + t * q2);
#if 0
- /* note: this does not ensure rotation around shortest angle, q1 and q2
- * are assumed to be matched already in transform_motion_decompose */
- float costheta = dot(q1, q2);
-
- /* possible optimization: it might be possible to precompute theta/qperp */
-
- if(costheta > 0.9995f) {
- /* linear interpolation in degenerate case */
- return normalize((1.0f - t)*q1 + t*q2);
- }
- else {
- /* slerp */
- float theta = acosf(clamp(costheta, -1.0f, 1.0f));
- float4 qperp = normalize(q2 - q1 * costheta);
- float thetap = theta * t;
- return q1 * cosf(thetap) + qperp * sinf(thetap);
- }
+ /* note: this does not ensure rotation around shortest angle, q1 and q2
+ * are assumed to be matched already in transform_motion_decompose */
+ float costheta = dot(q1, q2);
+
+ /* possible optimization: it might be possible to precompute theta/qperp */
+
+ if(costheta > 0.9995f) {
+ /* linear interpolation in degenerate case */
+ return normalize((1.0f - t)*q1 + t*q2);
+ }
+ else {
+ /* slerp */
+ float theta = acosf(clamp(costheta, -1.0f, 1.0f));
+ float4 qperp = normalize(q2 - q1 * costheta);
+ float thetap = theta * t;
+ return q1 * cosf(thetap) + qperp * sinf(thetap);
+ }
#endif
}
ccl_device_inline Transform transform_quick_inverse(Transform M)
{
- /* possible optimization: can we avoid doing this altogether and construct
- * the inverse matrix directly from negated translation, transposed rotation,
- * scale can be inverted but what about shearing? */
- Transform R;
- float det = M.x.x*(M.z.z*M.y.y - M.z.y*M.y.z) - M.y.x*(M.z.z*M.x.y - M.z.y*M.x.z) + M.z.x*(M.y.z*M.x.y - M.y.y*M.x.z);
- if(det == 0.0f) {
- M.x.x += 1e-8f;
- M.y.y += 1e-8f;
- M.z.z += 1e-8f;
- det = M.x.x*(M.z.z*M.y.y - M.z.y*M.y.z) - M.y.x*(M.z.z*M.x.y - M.z.y*M.x.z) + M.z.x*(M.y.z*M.x.y - M.y.y*M.x.z);
- }
- det = (det != 0.0f)? 1.0f/det: 0.0f;
-
- float3 Rx = det*make_float3(M.z.z*M.y.y - M.z.y*M.y.z, M.z.y*M.x.z - M.z.z*M.x.y, M.y.z*M.x.y - M.y.y*M.x.z);
- float3 Ry = det*make_float3(M.z.x*M.y.z - M.z.z*M.y.x, M.z.z*M.x.x - M.z.x*M.x.z, M.y.x*M.x.z - M.y.z*M.x.x);
- float3 Rz = det*make_float3(M.z.y*M.y.x - M.z.x*M.y.y, M.z.x*M.x.y - M.z.y*M.x.x, M.y.y*M.x.x - M.y.x*M.x.y);
- float3 T = -make_float3(M.x.w, M.y.w, M.z.w);
-
- R.x = make_float4(Rx.x, Rx.y, Rx.z, dot(Rx, T));
- R.y = make_float4(Ry.x, Ry.y, Ry.z, dot(Ry, T));
- R.z = make_float4(Rz.x, Rz.y, Rz.z, dot(Rz, T));
-
- return R;
+ /* possible optimization: can we avoid doing this altogether and construct
+ * the inverse matrix directly from negated translation, transposed rotation,
+ * scale can be inverted but what about shearing? */
+ Transform R;
+ float det = M.x.x * (M.z.z * M.y.y - M.z.y * M.y.z) - M.y.x * (M.z.z * M.x.y - M.z.y * M.x.z) +
+ M.z.x * (M.y.z * M.x.y - M.y.y * M.x.z);
+ if (det == 0.0f) {
+ M.x.x += 1e-8f;
+ M.y.y += 1e-8f;
+ M.z.z += 1e-8f;
+ det = M.x.x * (M.z.z * M.y.y - M.z.y * M.y.z) - M.y.x * (M.z.z * M.x.y - M.z.y * M.x.z) +
+ M.z.x * (M.y.z * M.x.y - M.y.y * M.x.z);
+ }
+ det = (det != 0.0f) ? 1.0f / det : 0.0f;
+
+ float3 Rx = det * make_float3(M.z.z * M.y.y - M.z.y * M.y.z,
+ M.z.y * M.x.z - M.z.z * M.x.y,
+ M.y.z * M.x.y - M.y.y * M.x.z);
+ float3 Ry = det * make_float3(M.z.x * M.y.z - M.z.z * M.y.x,
+ M.z.z * M.x.x - M.z.x * M.x.z,
+ M.y.x * M.x.z - M.y.z * M.x.x);
+ float3 Rz = det * make_float3(M.z.y * M.y.x - M.z.x * M.y.y,
+ M.z.x * M.x.y - M.z.y * M.x.x,
+ M.y.y * M.x.x - M.y.x * M.x.y);
+ float3 T = -make_float3(M.x.w, M.y.w, M.z.w);
+
+ R.x = make_float4(Rx.x, Rx.y, Rx.z, dot(Rx, T));
+ R.y = make_float4(Ry.x, Ry.y, Ry.z, dot(Ry, T));
+ R.z = make_float4(Rz.x, Rz.y, Rz.z, dot(Rz, T));
+
+ return R;
}
ccl_device_inline void transform_compose(Transform *tfm, const DecomposedTransform *decomp)
{
- /* rotation */
- float q0, q1, q2, q3, qda, qdb, qdc, qaa, qab, qac, qbb, qbc, qcc;
-
- q0 = M_SQRT2_F * decomp->x.w;
- q1 = M_SQRT2_F * decomp->x.x;
- q2 = M_SQRT2_F * decomp->x.y;
- q3 = M_SQRT2_F * decomp->x.z;
-
- qda = q0*q1;
- qdb = q0*q2;
- qdc = q0*q3;
- qaa = q1*q1;
- qab = q1*q2;
- qac = q1*q3;
- qbb = q2*q2;
- qbc = q2*q3;
- qcc = q3*q3;
-
- float3 rotation_x = make_float3(1.0f-qbb-qcc, -qdc+qab, qdb+qac);
- float3 rotation_y = make_float3(qdc+qab, 1.0f-qaa-qcc, -qda+qbc);
- float3 rotation_z = make_float3(-qdb+qac, qda+qbc, 1.0f-qaa-qbb);
-
- /* scale */
- float3 scale_x = make_float3(decomp->y.w, decomp->z.z, decomp->w.y);
- float3 scale_y = make_float3(decomp->z.x, decomp->z.w, decomp->w.z);
- float3 scale_z = make_float3(decomp->z.y, decomp->w.x, decomp->w.w);
-
- /* compose with translation */
- tfm->x = make_float4(dot(rotation_x, scale_x), dot(rotation_x, scale_y), dot(rotation_x, scale_z), decomp->y.x);
- tfm->y = make_float4(dot(rotation_y, scale_x), dot(rotation_y, scale_y), dot(rotation_y, scale_z), decomp->y.y);
- tfm->z = make_float4(dot(rotation_z, scale_x), dot(rotation_z, scale_y), dot(rotation_z, scale_z), decomp->y.z);
+ /* rotation */
+ float q0, q1, q2, q3, qda, qdb, qdc, qaa, qab, qac, qbb, qbc, qcc;
+
+ q0 = M_SQRT2_F * decomp->x.w;
+ q1 = M_SQRT2_F * decomp->x.x;
+ q2 = M_SQRT2_F * decomp->x.y;
+ q3 = M_SQRT2_F * decomp->x.z;
+
+ qda = q0 * q1;
+ qdb = q0 * q2;
+ qdc = q0 * q3;
+ qaa = q1 * q1;
+ qab = q1 * q2;
+ qac = q1 * q3;
+ qbb = q2 * q2;
+ qbc = q2 * q3;
+ qcc = q3 * q3;
+
+ float3 rotation_x = make_float3(1.0f - qbb - qcc, -qdc + qab, qdb + qac);
+ float3 rotation_y = make_float3(qdc + qab, 1.0f - qaa - qcc, -qda + qbc);
+ float3 rotation_z = make_float3(-qdb + qac, qda + qbc, 1.0f - qaa - qbb);
+
+ /* scale */
+ float3 scale_x = make_float3(decomp->y.w, decomp->z.z, decomp->w.y);
+ float3 scale_y = make_float3(decomp->z.x, decomp->z.w, decomp->w.z);
+ float3 scale_z = make_float3(decomp->z.y, decomp->w.x, decomp->w.w);
+
+ /* compose with translation */
+ tfm->x = make_float4(
+ dot(rotation_x, scale_x), dot(rotation_x, scale_y), dot(rotation_x, scale_z), decomp->y.x);
+ tfm->y = make_float4(
+ dot(rotation_y, scale_x), dot(rotation_y, scale_y), dot(rotation_y, scale_z), decomp->y.y);
+ tfm->z = make_float4(
+ dot(rotation_z, scale_x), dot(rotation_z, scale_y), dot(rotation_z, scale_z), decomp->y.z);
}
/* Interpolate from array of decomposed transforms. */
@@ -403,62 +421,60 @@ ccl_device void transform_motion_array_interpolate(Transform *tfm,
uint numsteps,
float time)
{
- /* Figure out which steps we need to interpolate. */
- int maxstep = numsteps-1;
- int step = min((int)(time*maxstep), maxstep-1);
- float t = time*maxstep - step;
-
- const ccl_global DecomposedTransform *a = motion + step;
- const ccl_global DecomposedTransform *b = motion + step + 1;
-
- /* Interpolate rotation, translation and scale. */
- DecomposedTransform decomp;
- decomp.x = quat_interpolate(a->x, b->x, t);
- decomp.y = (1.0f - t)*a->y + t*b->y;
- decomp.z = (1.0f - t)*a->z + t*b->z;
- decomp.w = (1.0f - t)*a->w + t*b->w;
-
- /* Compose rotation, translation, scale into matrix. */
- transform_compose(tfm, &decomp);
+ /* Figure out which steps we need to interpolate. */
+ int maxstep = numsteps - 1;
+ int step = min((int)(time * maxstep), maxstep - 1);
+ float t = time * maxstep - step;
+
+ const ccl_global DecomposedTransform *a = motion + step;
+ const ccl_global DecomposedTransform *b = motion + step + 1;
+
+ /* Interpolate rotation, translation and scale. */
+ DecomposedTransform decomp;
+ decomp.x = quat_interpolate(a->x, b->x, t);
+ decomp.y = (1.0f - t) * a->y + t * b->y;
+ decomp.z = (1.0f - t) * a->z + t * b->z;
+ decomp.w = (1.0f - t) * a->w + t * b->w;
+
+ /* Compose rotation, translation, scale into matrix. */
+ transform_compose(tfm, &decomp);
}
#ifndef __KERNEL_GPU__
-#ifdef WITH_EMBREE
-ccl_device void transform_motion_array_interpolate_straight(Transform *tfm,
- const ccl_global DecomposedTransform *motion,
- uint numsteps,
- float time)
+# ifdef WITH_EMBREE
+ccl_device void transform_motion_array_interpolate_straight(
+ Transform *tfm, const ccl_global DecomposedTransform *motion, uint numsteps, float time)
{
- /* Figure out which steps we need to interpolate. */
- int maxstep = numsteps - 1;
- int step = min((int)(time*maxstep), maxstep - 1);
- float t = time * maxstep - step;
-
- const ccl_global DecomposedTransform *a = motion + step;
- const ccl_global DecomposedTransform *b = motion + step + 1;
- Transform step1, step2;
-
- transform_compose(&step1, a);
- transform_compose(&step2, b);
-
- /* matrix lerp */
- tfm->x = (1.0f - t) * step1.x + t * step2.x;
- tfm->y = (1.0f - t) * step1.y + t * step2.y;
- tfm->z = (1.0f - t) * step1.z + t * step2.z;
+ /* Figure out which steps we need to interpolate. */
+ int maxstep = numsteps - 1;
+ int step = min((int)(time * maxstep), maxstep - 1);
+ float t = time * maxstep - step;
+
+ const ccl_global DecomposedTransform *a = motion + step;
+ const ccl_global DecomposedTransform *b = motion + step + 1;
+ Transform step1, step2;
+
+ transform_compose(&step1, a);
+ transform_compose(&step2, b);
+
+ /* matrix lerp */
+ tfm->x = (1.0f - t) * step1.x + t * step2.x;
+ tfm->y = (1.0f - t) * step1.y + t * step2.y;
+ tfm->z = (1.0f - t) * step1.z + t * step2.z;
}
-#endif
+# endif
class BoundBox2D;
-ccl_device_inline bool operator==(const DecomposedTransform& A, const DecomposedTransform& B)
+ccl_device_inline bool operator==(const DecomposedTransform &A, const DecomposedTransform &B)
{
- return memcmp(&A, &B, sizeof(DecomposedTransform)) == 0;
+ return memcmp(&A, &B, sizeof(DecomposedTransform)) == 0;
}
-float4 transform_to_quat(const Transform& tfm);
+float4 transform_to_quat(const Transform &tfm);
void transform_motion_decompose(DecomposedTransform *decomp, const Transform *motion, size_t size);
-Transform transform_from_viewplane(BoundBox2D& viewplane);
+Transform transform_from_viewplane(BoundBox2D &viewplane);
#endif
@@ -469,14 +485,14 @@ Transform transform_from_viewplane(BoundBox2D& viewplane);
#ifdef __KERNEL_OPENCL__
-#define OPENCL_TRANSFORM_ADDRSPACE_GLUE(a, b) a ## b
-#define OPENCL_TRANSFORM_ADDRSPACE_DECLARE(function) \
-ccl_device_inline float3 OPENCL_TRANSFORM_ADDRSPACE_GLUE(function, _addrspace)( \
- ccl_addr_space const Transform *t, const float3 a) \
-{ \
- Transform private_tfm = *t; \
- return function(&private_tfm, a); \
-}
+# define OPENCL_TRANSFORM_ADDRSPACE_GLUE(a, b) a##b
+# define OPENCL_TRANSFORM_ADDRSPACE_DECLARE(function) \
+ ccl_device_inline float3 OPENCL_TRANSFORM_ADDRSPACE_GLUE(function, _addrspace)( \
+ ccl_addr_space const Transform *t, const float3 a) \
+ { \
+ Transform private_tfm = *t; \
+ return function(&private_tfm, a); \
+ }
OPENCL_TRANSFORM_ADDRSPACE_DECLARE(transform_point)
OPENCL_TRANSFORM_ADDRSPACE_DECLARE(transform_direction)
@@ -495,4 +511,4 @@ OPENCL_TRANSFORM_ADDRSPACE_DECLARE(transform_direction_transposed)
CCL_NAMESPACE_END
-#endif /* __UTIL_TRANSFORM_H__ */
+#endif /* __UTIL_TRANSFORM_H__ */
diff --git a/intern/cycles/util/util_types.h b/intern/cycles/util/util_types.h
index 535048d8f8c..48e9983ac8f 100644
--- a/intern/cycles/util/util_types.h
+++ b/intern/cycles/util/util_types.h
@@ -74,31 +74,31 @@ typedef int64_t ssize_t;
# else
typedef int32_t ssize_t;
# endif
-# endif /* _WIN32 */
+# endif /* _WIN32 */
/* Generic Memory Pointer */
typedef uint64_t device_ptr;
-#endif /* __KERNEL_GPU__ */
+#endif /* __KERNEL_GPU__ */
ccl_device_inline size_t align_up(size_t offset, size_t alignment)
{
- return (offset + alignment - 1) & ~(alignment - 1);
+ return (offset + alignment - 1) & ~(alignment - 1);
}
ccl_device_inline size_t divide_up(size_t x, size_t y)
{
- return (x + y - 1) / y;
+ return (x + y - 1) / y;
}
ccl_device_inline size_t round_up(size_t x, size_t multiple)
{
- return ((x + multiple - 1) / multiple) * multiple;
+ return ((x + multiple - 1) / multiple) * multiple;
}
ccl_device_inline size_t round_down(size_t x, size_t multiple)
{
- return (x / multiple) * multiple;
+ return (x / multiple) * multiple;
}
CCL_NAMESPACE_END
@@ -150,10 +150,10 @@ CCL_NAMESPACE_END
# include "util/util_sseb.h"
# include "util/util_ssei.h"
# include "util/util_ssef.h"
-#if defined(__KERNEL_AVX__) || defined(__KERNEL_AVX2__)
-# include "util/util_avxb.h"
-# include "util/util_avxf.h"
-#endif
+# if defined(__KERNEL_AVX__) || defined(__KERNEL_AVX2__)
+# include "util/util_avxb.h"
+# include "util/util_avxf.h"
+# endif
#endif
-#endif /* __UTIL_TYPES_H__ */
+#endif /* __UTIL_TYPES_H__ */
diff --git a/intern/cycles/util/util_types_float2.h b/intern/cycles/util/util_types_float2.h
index ec7a1f717a1..3760bf579b6 100644
--- a/intern/cycles/util/util_types_float2.h
+++ b/intern/cycles/util/util_types_float2.h
@@ -25,16 +25,16 @@ CCL_NAMESPACE_BEGIN
#ifndef __KERNEL_GPU__
struct float2 {
- float x, y;
+ float x, y;
- __forceinline float operator[](int i) const;
- __forceinline float& operator[](int i);
+ __forceinline float operator[](int i) const;
+ __forceinline float &operator[](int i);
};
ccl_device_inline float2 make_float2(float x, float y);
-ccl_device_inline void print_float2(const char *label, const float2& a);
-#endif /* __KERNEL_GPU__ */
+ccl_device_inline void print_float2(const char *label, const float2 &a);
+#endif /* __KERNEL_GPU__ */
CCL_NAMESPACE_END
-#endif /* __UTIL_TYPES_FLOAT2_H__ */
+#endif /* __UTIL_TYPES_FLOAT2_H__ */
diff --git a/intern/cycles/util/util_types_float2_impl.h b/intern/cycles/util/util_types_float2_impl.h
index 782dda195eb..7810d2a8781 100644
--- a/intern/cycles/util/util_types_float2_impl.h
+++ b/intern/cycles/util/util_types_float2_impl.h
@@ -30,30 +30,30 @@ CCL_NAMESPACE_BEGIN
#ifndef __KERNEL_GPU__
__forceinline float float2::operator[](int i) const
{
- util_assert(i >= 0);
- util_assert(i < 2);
- return *(&x + i);
+ util_assert(i >= 0);
+ util_assert(i < 2);
+ return *(&x + i);
}
-__forceinline float& float2::operator[](int i)
+__forceinline float &float2::operator[](int i)
{
- util_assert(i >= 0);
- util_assert(i < 2);
- return *(&x + i);
+ util_assert(i >= 0);
+ util_assert(i < 2);
+ return *(&x + i);
}
ccl_device_inline float2 make_float2(float x, float y)
{
- float2 a = {x, y};
- return a;
+ float2 a = {x, y};
+ return a;
}
-ccl_device_inline void print_float2(const char *label, const float2& a)
+ccl_device_inline void print_float2(const char *label, const float2 &a)
{
- printf("%s: %.8f %.8f\n", label, (double)a.x, (double)a.y);
+ printf("%s: %.8f %.8f\n", label, (double)a.x, (double)a.y);
}
-#endif /* __KERNEL_GPU__ */
+#endif /* __KERNEL_GPU__ */
CCL_NAMESPACE_END
-#endif /* __UTIL_TYPES_FLOAT2_IMPL_H__ */
+#endif /* __UTIL_TYPES_FLOAT2_IMPL_H__ */
diff --git a/intern/cycles/util/util_types_float3.h b/intern/cycles/util/util_types_float3.h
index ed2300e7996..694a600bf5c 100644
--- a/intern/cycles/util/util_types_float3.h
+++ b/intern/cycles/util/util_types_float3.h
@@ -24,34 +24,37 @@
CCL_NAMESPACE_BEGIN
#ifndef __KERNEL_GPU__
-struct ccl_try_align(16) float3 {
-#ifdef __KERNEL_SSE__
- union {
- __m128 m128;
- struct { float x, y, z, w; };
- };
-
- __forceinline float3();
- __forceinline float3(const float3& a);
- __forceinline explicit float3(const __m128& a);
-
- __forceinline operator const __m128&() const;
- __forceinline operator __m128&();
-
- __forceinline float3& operator =(const float3& a);
-#else /* __KERNEL_SSE__ */
- float x, y, z, w;
-#endif /* __KERNEL_SSE__ */
-
- __forceinline float operator[](int i) const;
- __forceinline float& operator[](int i);
+struct ccl_try_align(16) float3
+{
+# ifdef __KERNEL_SSE__
+ union {
+ __m128 m128;
+ struct {
+ float x, y, z, w;
+ };
+ };
+
+ __forceinline float3();
+ __forceinline float3(const float3 &a);
+ __forceinline explicit float3(const __m128 &a);
+
+ __forceinline operator const __m128 &() const;
+ __forceinline operator __m128 &();
+
+ __forceinline float3 &operator=(const float3 &a);
+# else /* __KERNEL_SSE__ */
+ float x, y, z, w;
+# endif /* __KERNEL_SSE__ */
+
+ __forceinline float operator[](int i) const;
+ __forceinline float &operator[](int i);
};
ccl_device_inline float3 make_float3(float f);
ccl_device_inline float3 make_float3(float x, float y, float z);
-ccl_device_inline void print_float3(const char *label, const float3& a);
-#endif /* __KERNEL_GPU__ */
+ccl_device_inline void print_float3(const char *label, const float3 &a);
+#endif /* __KERNEL_GPU__ */
CCL_NAMESPACE_END
-#endif /* __UTIL_TYPES_FLOAT3_H__ */
+#endif /* __UTIL_TYPES_FLOAT3_H__ */
diff --git a/intern/cycles/util/util_types_float3_impl.h b/intern/cycles/util/util_types_float3_impl.h
index 2e840a5c399..ab25fb4c975 100644
--- a/intern/cycles/util/util_types_float3_impl.h
+++ b/intern/cycles/util/util_types_float3_impl.h
@@ -28,78 +28,76 @@
CCL_NAMESPACE_BEGIN
#ifndef __KERNEL_GPU__
-#ifdef __KERNEL_SSE__
+# ifdef __KERNEL_SSE__
__forceinline float3::float3()
{
}
-__forceinline float3::float3(const float3& a)
- : m128(a.m128)
+__forceinline float3::float3(const float3 &a) : m128(a.m128)
{
}
-__forceinline float3::float3(const __m128& a)
- : m128(a)
+__forceinline float3::float3(const __m128 &a) : m128(a)
{
}
-__forceinline float3::operator const __m128&() const
+__forceinline float3::operator const __m128 &() const
{
- return m128;
+ return m128;
}
-__forceinline float3::operator __m128&()
+__forceinline float3::operator __m128 &()
{
- return m128;
+ return m128;
}
-__forceinline float3& float3::operator =(const float3& a)
+__forceinline float3 &float3::operator=(const float3 &a)
{
- m128 = a.m128;
- return *this;
+ m128 = a.m128;
+ return *this;
}
-#endif /* __KERNEL_SSE__ */
+# endif /* __KERNEL_SSE__ */
__forceinline float float3::operator[](int i) const
{
- util_assert(i >= 0);
- util_assert(i < 3);
- return *(&x + i);
+ util_assert(i >= 0);
+ util_assert(i < 3);
+ return *(&x + i);
}
-__forceinline float& float3::operator[](int i)
+__forceinline float &float3::operator[](int i)
{
- util_assert(i >= 0);
- util_assert(i < 3);
- return *(&x + i);
+ util_assert(i >= 0);
+ util_assert(i < 3);
+ return *(&x + i);
}
ccl_device_inline float3 make_float3(float f)
{
-#ifdef __KERNEL_SSE__
- float3 a(_mm_set1_ps(f));
-#else
- float3 a = {f, f, f, f};
-#endif
- return a;
+# ifdef __KERNEL_SSE__
+ float3 a(_mm_set1_ps(f));
+# else
+ float3 a = {f, f, f, f};
+# endif
+ return a;
}
ccl_device_inline float3 make_float3(float x, float y, float z)
{
-#ifdef __KERNEL_SSE__
- float3 a(_mm_set_ps(0.0f, z, y, x));
-#else
- float3 a = {x, y, z, 0.0f};
-#endif
- return a;
+# ifdef __KERNEL_SSE__
+ float3 a(_mm_set_ps(0.0f, z, y, x));
+# else
+ float3 a = {x, y, z, 0.0f};
+# endif
+ return a;
}
-ccl_device_inline void print_float3(const char *label, const float3& a)
+ccl_device_inline void print_float3(const char *label, const float3 &a)
{
- printf("%s: %.8f %.8f %.8f\n", label, (double)a.x, (double)a.y, (double)a.z);
+ printf("%s: %.8f %.8f %.8f\n", label, (double)a.x, (double)a.y, (double)a.z);
}
-#endif /* __KERNEL_GPU__ */
+#endif /* __KERNEL_GPU__ */
CCL_NAMESPACE_END
-#endif /* __UTIL_TYPES_FLOAT3_IMPL_H__ */
+#endif /* __UTIL_TYPES_FLOAT3_IMPL_H__ */
diff --git a/intern/cycles/util/util_types_float4.h b/intern/cycles/util/util_types_float4.h
index 5c10d483c2e..c29e6e15bc3 100644
--- a/intern/cycles/util/util_types_float4.h
+++ b/intern/cycles/util/util_types_float4.h
@@ -26,35 +26,38 @@ CCL_NAMESPACE_BEGIN
#ifndef __KERNEL_GPU__
struct int4;
-struct ccl_try_align(16) float4 {
-#ifdef __KERNEL_SSE__
- union {
- __m128 m128;
- struct { float x, y, z, w; };
- };
-
- __forceinline float4();
- __forceinline explicit float4(const __m128& a);
-
- __forceinline operator const __m128&() const;
- __forceinline operator __m128&();
-
- __forceinline float4& operator =(const float4& a);
-
-#else /* __KERNEL_SSE__ */
- float x, y, z, w;
-#endif /* __KERNEL_SSE__ */
-
- __forceinline float operator[](int i) const;
- __forceinline float& operator[](int i);
+struct ccl_try_align(16) float4
+{
+# ifdef __KERNEL_SSE__
+ union {
+ __m128 m128;
+ struct {
+ float x, y, z, w;
+ };
+ };
+
+ __forceinline float4();
+ __forceinline explicit float4(const __m128 &a);
+
+ __forceinline operator const __m128 &() const;
+ __forceinline operator __m128 &();
+
+ __forceinline float4 &operator=(const float4 &a);
+
+# else /* __KERNEL_SSE__ */
+ float x, y, z, w;
+# endif /* __KERNEL_SSE__ */
+
+ __forceinline float operator[](int i) const;
+ __forceinline float &operator[](int i);
};
ccl_device_inline float4 make_float4(float f);
ccl_device_inline float4 make_float4(float x, float y, float z, float w);
-ccl_device_inline float4 make_float4(const int4& i);
-ccl_device_inline void print_float4(const char *label, const float4& a);
-#endif /* __KERNEL_GPU__ */
+ccl_device_inline float4 make_float4(const int4 &i);
+ccl_device_inline void print_float4(const char *label, const float4 &a);
+#endif /* __KERNEL_GPU__ */
CCL_NAMESPACE_END
-#endif /* __UTIL_TYPES_FLOAT4_H__ */
+#endif /* __UTIL_TYPES_FLOAT4_H__ */
diff --git a/intern/cycles/util/util_types_float4_impl.h b/intern/cycles/util/util_types_float4_impl.h
index a83148031f1..05a1feee5b2 100644
--- a/intern/cycles/util/util_types_float4_impl.h
+++ b/intern/cycles/util/util_types_float4_impl.h
@@ -28,85 +28,82 @@
CCL_NAMESPACE_BEGIN
#ifndef __KERNEL_GPU__
-#ifdef __KERNEL_SSE__
+# ifdef __KERNEL_SSE__
__forceinline float4::float4()
{
}
-__forceinline float4::float4(const __m128& a)
- : m128(a)
+__forceinline float4::float4(const __m128 &a) : m128(a)
{
}
-__forceinline float4::operator const __m128&() const
+__forceinline float4::operator const __m128 &() const
{
- return m128;
+ return m128;
}
-__forceinline float4::operator __m128&()
+__forceinline float4::operator __m128 &()
{
- return m128;
+ return m128;
}
-__forceinline float4& float4::operator =(const float4& a)
+__forceinline float4 &float4::operator=(const float4 &a)
{
- m128 = a.m128;
- return *this;
+ m128 = a.m128;
+ return *this;
}
-#endif /* __KERNEL_SSE__ */
+# endif /* __KERNEL_SSE__ */
__forceinline float float4::operator[](int i) const
{
- util_assert(i >= 0);
- util_assert(i < 4);
- return *(&x + i);
+ util_assert(i >= 0);
+ util_assert(i < 4);
+ return *(&x + i);
}
-__forceinline float& float4::operator[](int i)
+__forceinline float &float4::operator[](int i)
{
- util_assert(i >= 0);
- util_assert(i < 4);
- return *(&x + i);
+ util_assert(i >= 0);
+ util_assert(i < 4);
+ return *(&x + i);
}
ccl_device_inline float4 make_float4(float f)
{
-#ifdef __KERNEL_SSE__
- float4 a(_mm_set1_ps(f));
-#else
- float4 a = {f, f, f, f};
-#endif
- return a;
+# ifdef __KERNEL_SSE__
+ float4 a(_mm_set1_ps(f));
+# else
+ float4 a = {f, f, f, f};
+# endif
+ return a;
}
ccl_device_inline float4 make_float4(float x, float y, float z, float w)
{
-#ifdef __KERNEL_SSE__
- float4 a(_mm_set_ps(w, z, y, x));
-#else
- float4 a = {x, y, z, w};
-#endif
- return a;
+# ifdef __KERNEL_SSE__
+ float4 a(_mm_set_ps(w, z, y, x));
+# else
+ float4 a = {x, y, z, w};
+# endif
+ return a;
}
-ccl_device_inline float4 make_float4(const int4& i)
+ccl_device_inline float4 make_float4(const int4 &i)
{
-#ifdef __KERNEL_SSE__
- float4 a(_mm_cvtepi32_ps(i.m128));
-#else
- float4 a = {(float)i.x, (float)i.y, (float)i.z, (float)i.w};
-#endif
- return a;
+# ifdef __KERNEL_SSE__
+ float4 a(_mm_cvtepi32_ps(i.m128));
+# else
+ float4 a = {(float)i.x, (float)i.y, (float)i.z, (float)i.w};
+# endif
+ return a;
}
-ccl_device_inline void print_float4(const char *label, const float4& a)
+ccl_device_inline void print_float4(const char *label, const float4 &a)
{
- printf("%s: %.8f %.8f %.8f %.8f\n",
- label,
- (double)a.x, (double)a.y, (double)a.z, (double)a.w);
+ printf("%s: %.8f %.8f %.8f %.8f\n", label, (double)a.x, (double)a.y, (double)a.z, (double)a.w);
}
-#endif /* __KERNEL_GPU__ */
+#endif /* __KERNEL_GPU__ */
CCL_NAMESPACE_END
-#endif /* __UTIL_TYPES_FLOAT4_IMPL_H__ */
+#endif /* __UTIL_TYPES_FLOAT4_IMPL_H__ */
diff --git a/intern/cycles/util/util_types_float8.h b/intern/cycles/util/util_types_float8.h
index 08720b8ff48..7289e3298c3 100644
--- a/intern/cycles/util/util_types_float8.h
+++ b/intern/cycles/util/util_types_float8.h
@@ -37,35 +37,38 @@ CCL_NAMESPACE_BEGIN
#ifndef __KERNEL_GPU__
-struct ccl_try_align(32) float8 {
-#ifdef __KERNEL_AVX2__
- union {
- __m256 m256;
- struct { float a, b, c, d, e, f, g, h; };
- };
+struct ccl_try_align(32) float8
+{
+# ifdef __KERNEL_AVX2__
+ union {
+ __m256 m256;
+ struct {
+ float a, b, c, d, e, f, g, h;
+ };
+ };
- __forceinline float8();
- __forceinline float8(const float8& a);
- __forceinline explicit float8(const __m256& a);
+ __forceinline float8();
+ __forceinline float8(const float8 &a);
+ __forceinline explicit float8(const __m256 &a);
- __forceinline operator const __m256&() const;
- __forceinline operator __m256&();
+ __forceinline operator const __m256 &() const;
+ __forceinline operator __m256 &();
- __forceinline float8& operator =(const float8& a);
+ __forceinline float8 &operator=(const float8 &a);
-#else /* __KERNEL_AVX2__ */
- float a, b, c, d, e, f, g, h;
-#endif /* __KERNEL_AVX2__ */
+# else /* __KERNEL_AVX2__ */
+ float a, b, c, d, e, f, g, h;
+# endif /* __KERNEL_AVX2__ */
- __forceinline float operator[](int i) const;
- __forceinline float& operator[](int i);
+ __forceinline float operator[](int i) const;
+ __forceinline float &operator[](int i);
};
ccl_device_inline float8 make_float8(float f);
-ccl_device_inline float8 make_float8(float a, float b, float c, float d,
- float e, float f, float g, float h);
-#endif /* __KERNEL_GPU__ */
+ccl_device_inline float8
+make_float8(float a, float b, float c, float d, float e, float f, float g, float h);
+#endif /* __KERNEL_GPU__ */
CCL_NAMESPACE_END
-#endif /* __UTIL_TYPES_FLOAT8_H__ */
+#endif /* __UTIL_TYPES_FLOAT8_H__ */
diff --git a/intern/cycles/util/util_types_float8_impl.h b/intern/cycles/util/util_types_float8_impl.h
index 84fe233c334..8ce3d81b1bb 100644
--- a/intern/cycles/util/util_types_float8_impl.h
+++ b/intern/cycles/util/util_types_float8_impl.h
@@ -40,75 +40,73 @@
CCL_NAMESPACE_BEGIN
#ifndef __KERNEL_GPU__
-#ifdef __KERNEL_AVX2__
+# ifdef __KERNEL_AVX2__
__forceinline float8::float8()
{
}
-__forceinline float8::float8(const float8& f)
- : m256(f.m256)
+__forceinline float8::float8(const float8 &f) : m256(f.m256)
{
}
-__forceinline float8::float8(const __m256& f)
- : m256(f)
+__forceinline float8::float8(const __m256 &f) : m256(f)
{
}
-__forceinline float8::operator const __m256&() const
+__forceinline float8::operator const __m256 &() const
{
- return m256;
+ return m256;
}
-__forceinline float8::operator __m256&()
+__forceinline float8::operator __m256 &()
{
- return m256;
+ return m256;
}
-__forceinline float8& float8::operator =(const float8& f)
+__forceinline float8 &float8::operator=(const float8 &f)
{
- m256 = f.m256;
- return *this;
+ m256 = f.m256;
+ return *this;
}
-#endif /* __KERNEL_AVX2__ */
+# endif /* __KERNEL_AVX2__ */
__forceinline float float8::operator[](int i) const
{
- util_assert(i >= 0);
- util_assert(i < 8);
- return *(&a + i);
+ util_assert(i >= 0);
+ util_assert(i < 8);
+ return *(&a + i);
}
-__forceinline float& float8::operator[](int i)
+__forceinline float &float8::operator[](int i)
{
- util_assert(i >= 0);
- util_assert(i < 8);
- return *(&a + i);
+ util_assert(i >= 0);
+ util_assert(i < 8);
+ return *(&a + i);
}
ccl_device_inline float8 make_float8(float f)
{
-#ifdef __KERNEL_AVX2__
- float8 r(_mm256_set1_ps(f));
-#else
- float8 r = {f, f, f, f, f, f, f, f};
-#endif
- return r;
+# ifdef __KERNEL_AVX2__
+ float8 r(_mm256_set1_ps(f));
+# else
+ float8 r = {f, f, f, f, f, f, f, f};
+# endif
+ return r;
}
-ccl_device_inline float8 make_float8(float a, float b, float c, float d,
- float e, float f, float g, float h)
+ccl_device_inline float8
+make_float8(float a, float b, float c, float d, float e, float f, float g, float h)
{
-#ifdef __KERNEL_AVX2__
- float8 r(_mm256_set_ps(a, b, c, d, e, f, g, h));
-#else
- float8 r = {a, b, c, d, e, f, g, h};
-#endif
- return r;
+# ifdef __KERNEL_AVX2__
+ float8 r(_mm256_set_ps(a, b, c, d, e, f, g, h));
+# else
+ float8 r = {a, b, c, d, e, f, g, h};
+# endif
+ return r;
}
-#endif /* __KERNEL_GPU__ */
+#endif /* __KERNEL_GPU__ */
CCL_NAMESPACE_END
-#endif /* __UTIL_TYPES_FLOAT8_IMPL_H__ */
+#endif /* __UTIL_TYPES_FLOAT8_IMPL_H__ */
diff --git a/intern/cycles/util/util_types_int2.h b/intern/cycles/util/util_types_int2.h
index 82e860f89eb..8811e5ec7c2 100644
--- a/intern/cycles/util/util_types_int2.h
+++ b/intern/cycles/util/util_types_int2.h
@@ -25,15 +25,15 @@ CCL_NAMESPACE_BEGIN
#ifndef __KERNEL_GPU__
struct int2 {
- int x, y;
+ int x, y;
- __forceinline int operator[](int i) const;
- __forceinline int& operator[](int i);
+ __forceinline int operator[](int i) const;
+ __forceinline int &operator[](int i);
};
ccl_device_inline int2 make_int2(int x, int y);
-#endif /* __KERNEL_GPU__ */
+#endif /* __KERNEL_GPU__ */
CCL_NAMESPACE_END
-#endif /* __UTIL_TYPES_INT2_H__ */
+#endif /* __UTIL_TYPES_INT2_H__ */
diff --git a/intern/cycles/util/util_types_int2_impl.h b/intern/cycles/util/util_types_int2_impl.h
index c7d3942e723..ce95d4f14e5 100644
--- a/intern/cycles/util/util_types_int2_impl.h
+++ b/intern/cycles/util/util_types_int2_impl.h
@@ -26,25 +26,25 @@ CCL_NAMESPACE_BEGIN
#ifndef __KERNEL_GPU__
int int2::operator[](int i) const
{
- util_assert(i >= 0);
- util_assert(i < 2);
- return *(&x + i);
+ util_assert(i >= 0);
+ util_assert(i < 2);
+ return *(&x + i);
}
-int& int2::operator[](int i)
+int &int2::operator[](int i)
{
- util_assert(i >= 0);
- util_assert(i < 2);
- return *(&x + i);
+ util_assert(i >= 0);
+ util_assert(i < 2);
+ return *(&x + i);
}
ccl_device_inline int2 make_int2(int x, int y)
{
- int2 a = {x, y};
- return a;
+ int2 a = {x, y};
+ return a;
}
-#endif /* __KERNEL_GPU__ */
+#endif /* __KERNEL_GPU__ */
CCL_NAMESPACE_END
-#endif /* __UTIL_TYPES_INT2_IMPL_H__ */
+#endif /* __UTIL_TYPES_INT2_IMPL_H__ */
diff --git a/intern/cycles/util/util_types_int3.h b/intern/cycles/util/util_types_int3.h
index f68074b982b..09edc09dff3 100644
--- a/intern/cycles/util/util_types_int3.h
+++ b/intern/cycles/util/util_types_int3.h
@@ -24,34 +24,37 @@
CCL_NAMESPACE_BEGIN
#ifndef __KERNEL_GPU__
-struct ccl_try_align(16) int3 {
-#ifdef __KERNEL_SSE__
- union {
- __m128i m128;
- struct { int x, y, z, w; };
- };
-
- __forceinline int3();
- __forceinline int3(const int3& a);
- __forceinline explicit int3(const __m128i& a);
-
- __forceinline operator const __m128i&() const;
- __forceinline operator __m128i&();
-
- __forceinline int3& operator =(const int3& a);
-#else /* __KERNEL_SSE__ */
- int x, y, z, w;
-#endif /* __KERNEL_SSE__ */
-
- __forceinline int operator[](int i) const;
- __forceinline int& operator[](int i);
+struct ccl_try_align(16) int3
+{
+# ifdef __KERNEL_SSE__
+ union {
+ __m128i m128;
+ struct {
+ int x, y, z, w;
+ };
+ };
+
+ __forceinline int3();
+ __forceinline int3(const int3 &a);
+ __forceinline explicit int3(const __m128i &a);
+
+ __forceinline operator const __m128i &() const;
+ __forceinline operator __m128i &();
+
+ __forceinline int3 &operator=(const int3 &a);
+# else /* __KERNEL_SSE__ */
+ int x, y, z, w;
+# endif /* __KERNEL_SSE__ */
+
+ __forceinline int operator[](int i) const;
+ __forceinline int &operator[](int i);
};
ccl_device_inline int3 make_int3(int i);
ccl_device_inline int3 make_int3(int x, int y, int z);
-ccl_device_inline void print_int3(const char *label, const int3& a);
-#endif /* __KERNEL_GPU__ */
+ccl_device_inline void print_int3(const char *label, const int3 &a);
+#endif /* __KERNEL_GPU__ */
CCL_NAMESPACE_END
-#endif /* __UTIL_TYPES_INT3_H__ */
+#endif /* __UTIL_TYPES_INT3_H__ */
diff --git a/intern/cycles/util/util_types_int3_impl.h b/intern/cycles/util/util_types_int3_impl.h
index 1b195ca753f..080c892640b 100644
--- a/intern/cycles/util/util_types_int3_impl.h
+++ b/intern/cycles/util/util_types_int3_impl.h
@@ -28,79 +28,77 @@
CCL_NAMESPACE_BEGIN
#ifndef __KERNEL_GPU__
-#ifdef __KERNEL_SSE__
+# ifdef __KERNEL_SSE__
__forceinline int3::int3()
{
}
-__forceinline int3::int3(const __m128i& a)
- : m128(a)
+__forceinline int3::int3(const __m128i &a) : m128(a)
{
}
-__forceinline int3::int3(const int3& a)
- : m128(a.m128)
+__forceinline int3::int3(const int3 &a) : m128(a.m128)
{
}
-__forceinline int3::operator const __m128i&() const
+__forceinline int3::operator const __m128i &() const
{
- return m128;
+ return m128;
}
-__forceinline int3::operator __m128i&()
+__forceinline int3::operator __m128i &()
{
- return m128;
+ return m128;
}
-__forceinline int3& int3::operator =(const int3& a)
+__forceinline int3 &int3::operator=(const int3 &a)
{
- m128 = a.m128;
- return *this;
+ m128 = a.m128;
+ return *this;
}
-#endif /* __KERNEL_SSE__ */
+# endif /* __KERNEL_SSE__ */
__forceinline int int3::operator[](int i) const
{
- util_assert(i >= 0);
- util_assert(i < 3);
- return *(&x + i);
+ util_assert(i >= 0);
+ util_assert(i < 3);
+ return *(&x + i);
}
-__forceinline int& int3::operator[](int i)
+__forceinline int &int3::operator[](int i)
{
- util_assert(i >= 0);
- util_assert(i < 3);
- return *(&x + i);
+ util_assert(i >= 0);
+ util_assert(i < 3);
+ return *(&x + i);
}
ccl_device_inline int3 make_int3(int i)
{
-#ifdef __KERNEL_SSE__
- int3 a(_mm_set1_epi32(i));
-#else
- int3 a = {i, i, i, i};
-#endif
- return a;
+# ifdef __KERNEL_SSE__
+ int3 a(_mm_set1_epi32(i));
+# else
+ int3 a = {i, i, i, i};
+# endif
+ return a;
}
ccl_device_inline int3 make_int3(int x, int y, int z)
{
-#ifdef __KERNEL_SSE__
- int3 a(_mm_set_epi32(0, z, y, x));
-#else
- int3 a = {x, y, z, 0};
-#endif
+# ifdef __KERNEL_SSE__
+ int3 a(_mm_set_epi32(0, z, y, x));
+# else
+ int3 a = {x, y, z, 0};
+# endif
- return a;
+ return a;
}
-ccl_device_inline void print_int3(const char *label, const int3& a)
+ccl_device_inline void print_int3(const char *label, const int3 &a)
{
- printf("%s: %d %d %d\n", label, a.x, a.y, a.z);
+ printf("%s: %d %d %d\n", label, a.x, a.y, a.z);
}
-#endif /* __KERNEL_GPU__ */
+#endif /* __KERNEL_GPU__ */
CCL_NAMESPACE_END
-#endif /* __UTIL_TYPES_INT3_IMPL_H__ */
+#endif /* __UTIL_TYPES_INT3_IMPL_H__ */
diff --git a/intern/cycles/util/util_types_int4.h b/intern/cycles/util/util_types_int4.h
index 52e6fed8c14..5c7917cf5d6 100644
--- a/intern/cycles/util/util_types_int4.h
+++ b/intern/cycles/util/util_types_int4.h
@@ -28,36 +28,39 @@ CCL_NAMESPACE_BEGIN
struct float3;
struct float4;
-struct ccl_try_align(16) int4 {
-#ifdef __KERNEL_SSE__
- union {
- __m128i m128;
- struct { int x, y, z, w; };
- };
-
- __forceinline int4();
- __forceinline int4(const int4& a);
- __forceinline explicit int4(const __m128i& a);
-
- __forceinline operator const __m128i&() const;
- __forceinline operator __m128i&();
-
- __forceinline int4& operator=(const int4& a);
-#else /* __KERNEL_SSE__ */
- int x, y, z, w;
-#endif /* __KERNEL_SSE__ */
-
- __forceinline int operator[](int i) const;
- __forceinline int& operator[](int i);
+struct ccl_try_align(16) int4
+{
+# ifdef __KERNEL_SSE__
+ union {
+ __m128i m128;
+ struct {
+ int x, y, z, w;
+ };
+ };
+
+ __forceinline int4();
+ __forceinline int4(const int4 &a);
+ __forceinline explicit int4(const __m128i &a);
+
+ __forceinline operator const __m128i &() const;
+ __forceinline operator __m128i &();
+
+ __forceinline int4 &operator=(const int4 &a);
+# else /* __KERNEL_SSE__ */
+ int x, y, z, w;
+# endif /* __KERNEL_SSE__ */
+
+ __forceinline int operator[](int i) const;
+ __forceinline int &operator[](int i);
};
ccl_device_inline int4 make_int4(int i);
ccl_device_inline int4 make_int4(int x, int y, int z, int w);
-ccl_device_inline int4 make_int4(const float3& f);
-ccl_device_inline int4 make_int4(const float4& f);
-ccl_device_inline void print_int4(const char *label, const int4& a);
-#endif /* __KERNEL_GPU__ */
+ccl_device_inline int4 make_int4(const float3 &f);
+ccl_device_inline int4 make_int4(const float4 &f);
+ccl_device_inline void print_int4(const char *label, const int4 &a);
+#endif /* __KERNEL_GPU__ */
CCL_NAMESPACE_END
-#endif /* __UTIL_TYPES_INT4_H__ */
+#endif /* __UTIL_TYPES_INT4_H__ */
diff --git a/intern/cycles/util/util_types_int4_impl.h b/intern/cycles/util/util_types_int4_impl.h
index c058f86c400..c6f6ff23a17 100644
--- a/intern/cycles/util/util_types_int4_impl.h
+++ b/intern/cycles/util/util_types_int4_impl.h
@@ -28,98 +28,96 @@
CCL_NAMESPACE_BEGIN
#ifndef __KERNEL_GPU__
-#ifdef __KERNEL_SSE__
+# ifdef __KERNEL_SSE__
__forceinline int4::int4()
{
}
-__forceinline int4::int4(const int4& a)
- : m128(a.m128)
+__forceinline int4::int4(const int4 &a) : m128(a.m128)
{
}
-__forceinline int4::int4(const __m128i& a)
- : m128(a)
+__forceinline int4::int4(const __m128i &a) : m128(a)
{
}
-__forceinline int4::operator const __m128i&() const
+__forceinline int4::operator const __m128i &() const
{
- return m128;
+ return m128;
}
-__forceinline int4::operator __m128i&()
+__forceinline int4::operator __m128i &()
{
- return m128;
+ return m128;
}
-__forceinline int4& int4::operator=(const int4& a)
+__forceinline int4 &int4::operator=(const int4 &a)
{
- m128 = a.m128;
- return *this;
+ m128 = a.m128;
+ return *this;
}
-#endif /* __KERNEL_SSE__ */
+# endif /* __KERNEL_SSE__ */
__forceinline int int4::operator[](int i) const
{
- util_assert(i >= 0);
- util_assert(i < 4);
- return *(&x + i);
+ util_assert(i >= 0);
+ util_assert(i < 4);
+ return *(&x + i);
}
-__forceinline int& int4::operator[](int i)
+__forceinline int &int4::operator[](int i)
{
- util_assert(i >= 0);
- util_assert(i < 4);
- return *(&x + i);
+ util_assert(i >= 0);
+ util_assert(i < 4);
+ return *(&x + i);
}
ccl_device_inline int4 make_int4(int i)
{
-#ifdef __KERNEL_SSE__
- int4 a(_mm_set1_epi32(i));
-#else
- int4 a = {i, i, i, i};
-#endif
- return a;
+# ifdef __KERNEL_SSE__
+ int4 a(_mm_set1_epi32(i));
+# else
+ int4 a = {i, i, i, i};
+# endif
+ return a;
}
ccl_device_inline int4 make_int4(int x, int y, int z, int w)
{
-#ifdef __KERNEL_SSE__
- int4 a(_mm_set_epi32(w, z, y, x));
-#else
- int4 a = {x, y, z, w};
-#endif
- return a;
+# ifdef __KERNEL_SSE__
+ int4 a(_mm_set_epi32(w, z, y, x));
+# else
+ int4 a = {x, y, z, w};
+# endif
+ return a;
}
-ccl_device_inline int4 make_int4(const float3& f)
+ccl_device_inline int4 make_int4(const float3 &f)
{
-#ifdef __KERNEL_SSE__
- int4 a(_mm_cvtps_epi32(f.m128));
-#else
- int4 a = {(int)f.x, (int)f.y, (int)f.z, (int)f.w};
-#endif
- return a;
+# ifdef __KERNEL_SSE__
+ int4 a(_mm_cvtps_epi32(f.m128));
+# else
+ int4 a = {(int)f.x, (int)f.y, (int)f.z, (int)f.w};
+# endif
+ return a;
}
-ccl_device_inline int4 make_int4(const float4& f)
+ccl_device_inline int4 make_int4(const float4 &f)
{
-#ifdef __KERNEL_SSE__
- int4 a(_mm_cvtps_epi32(f.m128));
-#else
- int4 a = {(int)f.x, (int)f.y, (int)f.z, (int)f.w};
-#endif
- return a;
+# ifdef __KERNEL_SSE__
+ int4 a(_mm_cvtps_epi32(f.m128));
+# else
+ int4 a = {(int)f.x, (int)f.y, (int)f.z, (int)f.w};
+# endif
+ return a;
}
-ccl_device_inline void print_int4(const char *label, const int4& a)
+ccl_device_inline void print_int4(const char *label, const int4 &a)
{
- printf("%s: %d %d %d %d\n", label, a.x, a.y, a.z, a.w);
+ printf("%s: %d %d %d %d\n", label, a.x, a.y, a.z, a.w);
}
-#endif /* __KERNEL_GPU__ */
+#endif /* __KERNEL_GPU__ */
CCL_NAMESPACE_END
-#endif /* __UTIL_TYPES_INT4_IMPL_H__ */
+#endif /* __UTIL_TYPES_INT4_IMPL_H__ */
diff --git a/intern/cycles/util/util_types_uchar2.h b/intern/cycles/util/util_types_uchar2.h
index f618a2234ca..8cc486e3e48 100644
--- a/intern/cycles/util/util_types_uchar2.h
+++ b/intern/cycles/util/util_types_uchar2.h
@@ -25,15 +25,15 @@ CCL_NAMESPACE_BEGIN
#ifndef __KERNEL_GPU__
struct uchar2 {
- uchar x, y;
+ uchar x, y;
- __forceinline uchar operator[](int i) const;
- __forceinline uchar& operator[](int i);
+ __forceinline uchar operator[](int i) const;
+ __forceinline uchar &operator[](int i);
};
ccl_device_inline uchar2 make_uchar2(uchar x, uchar y);
-#endif /* __KERNEL_GPU__ */
+#endif /* __KERNEL_GPU__ */
CCL_NAMESPACE_END
-#endif /* __UTIL_TYPES_UCHAR2_H__ */
+#endif /* __UTIL_TYPES_UCHAR2_H__ */
diff --git a/intern/cycles/util/util_types_uchar2_impl.h b/intern/cycles/util/util_types_uchar2_impl.h
index d5f196d0ce0..16968c32dd9 100644
--- a/intern/cycles/util/util_types_uchar2_impl.h
+++ b/intern/cycles/util/util_types_uchar2_impl.h
@@ -26,25 +26,25 @@ CCL_NAMESPACE_BEGIN
#ifndef __KERNEL_GPU__
uchar uchar2::operator[](int i) const
{
- util_assert(i >= 0);
- util_assert(i < 2);
- return *(&x + i);
+ util_assert(i >= 0);
+ util_assert(i < 2);
+ return *(&x + i);
}
-uchar& uchar2::operator[](int i)
+uchar &uchar2::operator[](int i)
{
- util_assert(i >= 0);
- util_assert(i < 2);
- return *(&x + i);
+ util_assert(i >= 0);
+ util_assert(i < 2);
+ return *(&x + i);
}
ccl_device_inline uchar2 make_uchar2(uchar x, uchar y)
{
- uchar2 a = {x, y};
- return a;
+ uchar2 a = {x, y};
+ return a;
}
-#endif /* __KERNEL_GPU__ */
+#endif /* __KERNEL_GPU__ */
CCL_NAMESPACE_END
-#endif /* __UTIL_TYPES_UCHAR2_IMPL_H__ */
+#endif /* __UTIL_TYPES_UCHAR2_IMPL_H__ */
diff --git a/intern/cycles/util/util_types_uchar3.h b/intern/cycles/util/util_types_uchar3.h
index 1e3644e6fd6..5838c437c70 100644
--- a/intern/cycles/util/util_types_uchar3.h
+++ b/intern/cycles/util/util_types_uchar3.h
@@ -25,15 +25,15 @@ CCL_NAMESPACE_BEGIN
#ifndef __KERNEL_GPU__
struct uchar3 {
- uchar x, y, z;
+ uchar x, y, z;
- __forceinline uchar operator[](int i) const;
- __forceinline uchar& operator[](int i);
+ __forceinline uchar operator[](int i) const;
+ __forceinline uchar &operator[](int i);
};
ccl_device_inline uchar3 make_uchar3(uchar x, uchar y, uchar z);
-#endif /* __KERNEL_GPU__ */
+#endif /* __KERNEL_GPU__ */
CCL_NAMESPACE_END
-#endif /* __UTIL_TYPES_UCHAR3_H__ */
+#endif /* __UTIL_TYPES_UCHAR3_H__ */
diff --git a/intern/cycles/util/util_types_uchar3_impl.h b/intern/cycles/util/util_types_uchar3_impl.h
index 611021efb7f..aa31b725731 100644
--- a/intern/cycles/util/util_types_uchar3_impl.h
+++ b/intern/cycles/util/util_types_uchar3_impl.h
@@ -26,25 +26,25 @@ CCL_NAMESPACE_BEGIN
#ifndef __KERNEL_GPU__
uchar uchar3::operator[](int i) const
{
- util_assert(i >= 0);
- util_assert(i < 3);
- return *(&x + i);
+ util_assert(i >= 0);
+ util_assert(i < 3);
+ return *(&x + i);
}
-uchar& uchar3::operator[](int i)
+uchar &uchar3::operator[](int i)
{
- util_assert(i >= 0);
- util_assert(i < 3);
- return *(&x + i);
+ util_assert(i >= 0);
+ util_assert(i < 3);
+ return *(&x + i);
}
ccl_device_inline uchar3 make_uchar3(uchar x, uchar y, uchar z)
{
- uchar3 a = {x, y, z};
- return a;
+ uchar3 a = {x, y, z};
+ return a;
}
-#endif /* __KERNEL_GPU__ */
+#endif /* __KERNEL_GPU__ */
CCL_NAMESPACE_END
-#endif /* __UTIL_TYPES_UCHAR3_IMPL_H__ */
+#endif /* __UTIL_TYPES_UCHAR3_IMPL_H__ */
diff --git a/intern/cycles/util/util_types_uchar4.h b/intern/cycles/util/util_types_uchar4.h
index 3802cebbfb9..22b6a1ac705 100644
--- a/intern/cycles/util/util_types_uchar4.h
+++ b/intern/cycles/util/util_types_uchar4.h
@@ -25,15 +25,15 @@ CCL_NAMESPACE_BEGIN
#ifndef __KERNEL_GPU__
struct uchar4 {
- uchar x, y, z, w;
+ uchar x, y, z, w;
- __forceinline uchar operator[](int i) const;
- __forceinline uchar& operator[](int i);
+ __forceinline uchar operator[](int i) const;
+ __forceinline uchar &operator[](int i);
};
ccl_device_inline uchar4 make_uchar4(uchar x, uchar y, uchar z, uchar w);
-#endif /* __KERNEL_GPU__ */
+#endif /* __KERNEL_GPU__ */
CCL_NAMESPACE_END
-#endif /* __UTIL_TYPES_UCHAR4_H__ */
+#endif /* __UTIL_TYPES_UCHAR4_H__ */
diff --git a/intern/cycles/util/util_types_uchar4_impl.h b/intern/cycles/util/util_types_uchar4_impl.h
index 03039f60c54..79879f176a6 100644
--- a/intern/cycles/util/util_types_uchar4_impl.h
+++ b/intern/cycles/util/util_types_uchar4_impl.h
@@ -26,25 +26,25 @@ CCL_NAMESPACE_BEGIN
#ifndef __KERNEL_GPU__
uchar uchar4::operator[](int i) const
{
- util_assert(i >= 0);
- util_assert(i < 4);
- return *(&x + i);
+ util_assert(i >= 0);
+ util_assert(i < 4);
+ return *(&x + i);
}
-uchar& uchar4::operator[](int i)
+uchar &uchar4::operator[](int i)
{
- util_assert(i >= 0);
- util_assert(i < 4);
- return *(&x + i);
+ util_assert(i >= 0);
+ util_assert(i < 4);
+ return *(&x + i);
}
ccl_device_inline uchar4 make_uchar4(uchar x, uchar y, uchar z, uchar w)
{
- uchar4 a = {x, y, z, w};
- return a;
+ uchar4 a = {x, y, z, w};
+ return a;
}
-#endif /* __KERNEL_GPU__ */
+#endif /* __KERNEL_GPU__ */
CCL_NAMESPACE_END
-#endif /* __UTIL_TYPES_UCHAR4_IMPL_H__ */
+#endif /* __UTIL_TYPES_UCHAR4_IMPL_H__ */
diff --git a/intern/cycles/util/util_types_uint2.h b/intern/cycles/util/util_types_uint2.h
index c4a31899614..abcb8ee5346 100644
--- a/intern/cycles/util/util_types_uint2.h
+++ b/intern/cycles/util/util_types_uint2.h
@@ -25,15 +25,15 @@ CCL_NAMESPACE_BEGIN
#ifndef __KERNEL_GPU__
struct uint2 {
- uint x, y;
+ uint x, y;
- __forceinline uint operator[](uint i) const;
- __forceinline uint& operator[](uint i);
+ __forceinline uint operator[](uint i) const;
+ __forceinline uint &operator[](uint i);
};
ccl_device_inline uint2 make_uint2(uint x, uint y);
-#endif /* __KERNEL_GPU__ */
+#endif /* __KERNEL_GPU__ */
CCL_NAMESPACE_END
-#endif /* __UTIL_TYPES_UINT2_H__ */
+#endif /* __UTIL_TYPES_UINT2_H__ */
diff --git a/intern/cycles/util/util_types_uint2_impl.h b/intern/cycles/util/util_types_uint2_impl.h
index b50ffa2667f..db62bd99b89 100644
--- a/intern/cycles/util/util_types_uint2_impl.h
+++ b/intern/cycles/util/util_types_uint2_impl.h
@@ -26,23 +26,23 @@ CCL_NAMESPACE_BEGIN
#ifndef __KERNEL_GPU__
__forceinline uint uint2::operator[](uint i) const
{
- util_assert(i < 2);
- return *(&x + i);
+ util_assert(i < 2);
+ return *(&x + i);
}
-__forceinline uint& uint2::operator[](uint i)
+__forceinline uint &uint2::operator[](uint i)
{
- util_assert(i < 2);
- return *(&x + i);
+ util_assert(i < 2);
+ return *(&x + i);
}
ccl_device_inline uint2 make_uint2(uint x, uint y)
{
- uint2 a = {x, y};
- return a;
+ uint2 a = {x, y};
+ return a;
}
-#endif /* __KERNEL_GPU__ */
+#endif /* __KERNEL_GPU__ */
CCL_NAMESPACE_END
-#endif /* __UTIL_TYPES_UINT2_IMPL_H__ */
+#endif /* __UTIL_TYPES_UINT2_IMPL_H__ */
diff --git a/intern/cycles/util/util_types_uint3.h b/intern/cycles/util/util_types_uint3.h
index aeeecd2df06..436d870b621 100644
--- a/intern/cycles/util/util_types_uint3.h
+++ b/intern/cycles/util/util_types_uint3.h
@@ -25,15 +25,15 @@ CCL_NAMESPACE_BEGIN
#ifndef __KERNEL_GPU__
struct uint3 {
- uint x, y, z;
+ uint x, y, z;
- __forceinline uint operator[](uint i) const;
- __forceinline uint& operator[](uint i);
+ __forceinline uint operator[](uint i) const;
+ __forceinline uint &operator[](uint i);
};
ccl_device_inline uint3 make_uint3(uint x, uint y, uint z);
-#endif /* __KERNEL_GPU__ */
+#endif /* __KERNEL_GPU__ */
CCL_NAMESPACE_END
-#endif /* __UTIL_TYPES_UINT3_H__ */
+#endif /* __UTIL_TYPES_UINT3_H__ */
diff --git a/intern/cycles/util/util_types_uint3_impl.h b/intern/cycles/util/util_types_uint3_impl.h
index 26005d5baff..d188fa06e2a 100644
--- a/intern/cycles/util/util_types_uint3_impl.h
+++ b/intern/cycles/util/util_types_uint3_impl.h
@@ -26,23 +26,23 @@ CCL_NAMESPACE_BEGIN
#ifndef __KERNEL_GPU__
__forceinline uint uint3::operator[](uint i) const
{
- util_assert(i < 3);
- return *(&x + i);
+ util_assert(i < 3);
+ return *(&x + i);
}
-__forceinline uint& uint3::operator[](uint i)
+__forceinline uint &uint3::operator[](uint i)
{
- util_assert(i < 3);
- return *(&x + i);
+ util_assert(i < 3);
+ return *(&x + i);
}
ccl_device_inline uint3 make_uint3(uint x, uint y, uint z)
{
- uint3 a = {x, y, z};
- return a;
+ uint3 a = {x, y, z};
+ return a;
}
-#endif /* __KERNEL_GPU__ */
+#endif /* __KERNEL_GPU__ */
CCL_NAMESPACE_END
-#endif /* __UTIL_TYPES_UINT3_IMPL_H__ */
+#endif /* __UTIL_TYPES_UINT3_IMPL_H__ */
diff --git a/intern/cycles/util/util_types_uint4.h b/intern/cycles/util/util_types_uint4.h
index 2d3a7bb85e4..57f2859fedf 100644
--- a/intern/cycles/util/util_types_uint4.h
+++ b/intern/cycles/util/util_types_uint4.h
@@ -25,15 +25,15 @@ CCL_NAMESPACE_BEGIN
#ifndef __KERNEL_GPU__
struct uint4 {
- uint x, y, z, w;
+ uint x, y, z, w;
- __forceinline uint operator[](uint i) const;
- __forceinline uint& operator[](uint i);
+ __forceinline uint operator[](uint i) const;
+ __forceinline uint &operator[](uint i);
};
ccl_device_inline uint4 make_uint4(uint x, uint y, uint z, uint w);
-#endif /* __KERNEL_GPU__ */
+#endif /* __KERNEL_GPU__ */
CCL_NAMESPACE_END
-#endif /* __UTIL_TYPES_UINT4_H__ */
+#endif /* __UTIL_TYPES_UINT4_H__ */
diff --git a/intern/cycles/util/util_types_uint4_impl.h b/intern/cycles/util/util_types_uint4_impl.h
index 6d48131a446..bac8d23030d 100644
--- a/intern/cycles/util/util_types_uint4_impl.h
+++ b/intern/cycles/util/util_types_uint4_impl.h
@@ -26,23 +26,23 @@ CCL_NAMESPACE_BEGIN
#ifndef __KERNEL_GPU__
__forceinline uint uint4::operator[](uint i) const
{
- util_assert(i < 3);
- return *(&x + i);
+ util_assert(i < 3);
+ return *(&x + i);
}
-__forceinline uint& uint4::operator[](uint i)
+__forceinline uint &uint4::operator[](uint i)
{
- util_assert(i < 3);
- return *(&x + i);
+ util_assert(i < 3);
+ return *(&x + i);
}
ccl_device_inline uint4 make_uint4(uint x, uint y, uint z, uint w)
{
- uint4 a = {x, y, z, w};
- return a;
+ uint4 a = {x, y, z, w};
+ return a;
}
-#endif /* __KERNEL_GPU__ */
+#endif /* __KERNEL_GPU__ */
CCL_NAMESPACE_END
-#endif /* __UTIL_TYPES_UINT4_IMPL_H__ */
+#endif /* __UTIL_TYPES_UINT4_IMPL_H__ */
diff --git a/intern/cycles/util/util_types_ushort4.h b/intern/cycles/util/util_types_ushort4.h
index fc234b8abe8..476ceec622c 100644
--- a/intern/cycles/util/util_types_ushort4.h
+++ b/intern/cycles/util/util_types_ushort4.h
@@ -26,11 +26,11 @@ CCL_NAMESPACE_BEGIN
#ifndef __KERNEL_GPU__
struct ushort4 {
- uint16_t x, y, z, w;
+ uint16_t x, y, z, w;
};
#endif
CCL_NAMESPACE_END
-#endif /* __UTIL_TYPES_USHORT4_H__ */
+#endif /* __UTIL_TYPES_USHORT4_H__ */
diff --git a/intern/cycles/util/util_types_vector3.h b/intern/cycles/util/util_types_vector3.h
index 12acf9dc959..728c7ca62a1 100644
--- a/intern/cycles/util/util_types_vector3.h
+++ b/intern/cycles/util/util_types_vector3.h
@@ -24,18 +24,16 @@
CCL_NAMESPACE_BEGIN
#ifndef __KERNEL_GPU__
-template<typename T>
-class vector3
-{
-public:
- T x, y, z;
+template<typename T> class vector3 {
+ public:
+ T x, y, z;
- __forceinline vector3();
- __forceinline vector3(const T& a);
- __forceinline vector3(const T& x, const T& y, const T& z);
+ __forceinline vector3();
+ __forceinline vector3(const T &a);
+ __forceinline vector3(const T &x, const T &y, const T &z);
};
-#endif /* __KERNEL_GPU__ */
+#endif /* __KERNEL_GPU__ */
CCL_NAMESPACE_END
-#endif /* __UTIL_TYPES_VECTOR3_H__ */
+#endif /* __UTIL_TYPES_VECTOR3_H__ */
diff --git a/intern/cycles/util/util_types_vector3_impl.h b/intern/cycles/util/util_types_vector3_impl.h
index 2f6b8368540..33ba53e20b2 100644
--- a/intern/cycles/util/util_types_vector3_impl.h
+++ b/intern/cycles/util/util_types_vector3_impl.h
@@ -24,24 +24,20 @@
CCL_NAMESPACE_BEGIN
#ifndef __KERNEL_GPU__
-template<typename T>
-ccl_always_inline vector3<T>::vector3()
+template<typename T> ccl_always_inline vector3<T>::vector3()
{
}
-template<typename T>
-ccl_always_inline vector3<T>::vector3(const T& a)
- : x(a), y(a), z(a)
+template<typename T> ccl_always_inline vector3<T>::vector3(const T &a) : x(a), y(a), z(a)
{
}
template<typename T>
-ccl_always_inline vector3<T>::vector3(const T& x, const T& y, const T& z)
- : x(x), y(y), z(z)
+ccl_always_inline vector3<T>::vector3(const T &x, const T &y, const T &z) : x(x), y(y), z(z)
{
}
-#endif /* __KERNEL_GPU__ */
+#endif /* __KERNEL_GPU__ */
CCL_NAMESPACE_END
-#endif /* __UTIL_TYPES_VECTOR3_IMPL_H__ */
+#endif /* __UTIL_TYPES_VECTOR3_IMPL_H__ */
diff --git a/intern/cycles/util/util_unique_ptr.h b/intern/cycles/util/util_unique_ptr.h
index 1ceae73172e..3aaaf083eff 100644
--- a/intern/cycles/util/util_unique_ptr.h
+++ b/intern/cycles/util/util_unique_ptr.h
@@ -25,4 +25,4 @@ using std::unique_ptr;
CCL_NAMESPACE_END
-#endif /* __UTIL_UNIQUE_PTR_H__ */
+#endif /* __UTIL_UNIQUE_PTR_H__ */
diff --git a/intern/cycles/util/util_vector.h b/intern/cycles/util/util_vector.h
index 18fa231d6e7..437478d64d3 100644
--- a/intern/cycles/util/util_vector.h
+++ b/intern/cycles/util/util_vector.h
@@ -32,30 +32,28 @@ CCL_NAMESPACE_BEGIN
* - Use own allocator which keeps track of used/peak memory.
* - Have method to ensure capacity is re-set to 0.
*/
-template<typename value_type,
- typename allocator_type = GuardedAllocator<value_type> >
-class vector : public std::vector<value_type, allocator_type>
-{
-public:
- typedef std::vector<value_type, allocator_type> BaseClass;
-
- /* Inherit all constructors from base class. */
- using BaseClass::vector;
-
- /* Try as hard as possible to use zero memory. */
- void free_memory()
- {
- BaseClass::resize(0);
- BaseClass::shrink_to_fit();
- }
-
- /* Some external API might demand working with std::vector. */
- operator std::vector<value_type>()
- {
- return std::vector<value_type>(this->begin(), this->end());
- }
+template<typename value_type, typename allocator_type = GuardedAllocator<value_type>>
+class vector : public std::vector<value_type, allocator_type> {
+ public:
+ typedef std::vector<value_type, allocator_type> BaseClass;
+
+ /* Inherit all constructors from base class. */
+ using BaseClass::vector;
+
+ /* Try as hard as possible to use zero memory. */
+ void free_memory()
+ {
+ BaseClass::resize(0);
+ BaseClass::shrink_to_fit();
+ }
+
+ /* Some external API might demand working with std::vector. */
+ operator std::vector<value_type>()
+ {
+ return std::vector<value_type>(this->begin(), this->end());
+ }
};
CCL_NAMESPACE_END
-#endif /* __UTIL_VECTOR_H__ */
+#endif /* __UTIL_VECTOR_H__ */
diff --git a/intern/cycles/util/util_version.h b/intern/cycles/util/util_version.h
index 980c5a269e6..38829d3a29c 100644
--- a/intern/cycles/util/util_version.h
+++ b/intern/cycles/util/util_version.h
@@ -21,17 +21,15 @@
CCL_NAMESPACE_BEGIN
-#define CYCLES_VERSION_MAJOR 1
-#define CYCLES_VERSION_MINOR 9
-#define CYCLES_VERSION_PATCH 0
+#define CYCLES_VERSION_MAJOR 1
+#define CYCLES_VERSION_MINOR 9
+#define CYCLES_VERSION_PATCH 0
-#define CYCLES_MAKE_VERSION_STRING2(a,b,c) #a "." #b "." #c
-#define CYCLES_MAKE_VERSION_STRING(a,b,c) CYCLES_MAKE_VERSION_STRING2(a,b,c)
+#define CYCLES_MAKE_VERSION_STRING2(a, b, c) #a "." #b "." #c
+#define CYCLES_MAKE_VERSION_STRING(a, b, c) CYCLES_MAKE_VERSION_STRING2(a, b, c)
#define CYCLES_VERSION_STRING \
- CYCLES_MAKE_VERSION_STRING(CYCLES_VERSION_MAJOR, \
- CYCLES_VERSION_MINOR, \
- CYCLES_VERSION_PATCH)
+ CYCLES_MAKE_VERSION_STRING(CYCLES_VERSION_MAJOR, CYCLES_VERSION_MINOR, CYCLES_VERSION_PATCH)
CCL_NAMESPACE_END
-#endif /* __UTIL_VERSION_H__ */
+#endif /* __UTIL_VERSION_H__ */
diff --git a/intern/cycles/util/util_view.cpp b/intern/cycles/util/util_view.cpp
index c0ddc2a88bf..f23174fd6dc 100644
--- a/intern/cycles/util/util_view.cpp
+++ b/intern/cycles/util/util_view.cpp
@@ -24,9 +24,9 @@
#include "util/util_view.h"
#ifdef __APPLE__
-#include <GLUT/glut.h>
+# include <GLUT/glut.h>
#else
-#include <GL/glut.h>
+# include <GL/glut.h>
#endif
CCL_NAMESPACE_BEGIN
@@ -34,241 +34,249 @@ CCL_NAMESPACE_BEGIN
/* structs */
struct View {
- ViewInitFunc initf;
- ViewExitFunc exitf;
- ViewResizeFunc resize;
- ViewDisplayFunc display;
- ViewKeyboardFunc keyboard;
- ViewMotionFunc motion;
+ ViewInitFunc initf;
+ ViewExitFunc exitf;
+ ViewResizeFunc resize;
+ ViewDisplayFunc display;
+ ViewKeyboardFunc keyboard;
+ ViewMotionFunc motion;
- bool first_display;
- bool redraw;
+ bool first_display;
+ bool redraw;
- int mouseX, mouseY;
- int mouseBut0, mouseBut2;
+ int mouseX, mouseY;
+ int mouseBut0, mouseBut2;
- int width, height;
+ int width, height;
} V;
/* public */
static void view_display_text(int x, int y, const char *text)
{
- const char *c;
+ const char *c;
- glRasterPos3f(x, y, 0);
+ glRasterPos3f(x, y, 0);
- for(c = text; *c != '\0'; c++)
- glutBitmapCharacter(GLUT_BITMAP_HELVETICA_10, *c);
+ for (c = text; *c != '\0'; c++)
+ glutBitmapCharacter(GLUT_BITMAP_HELVETICA_10, *c);
}
void view_display_info(const char *info)
{
- const int height = 20;
+ const int height = 20;
- glEnable(GL_BLEND);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- glColor4f(0.1f, 0.1f, 0.1f, 0.8f);
- glRectf(0.0f, V.height - height, V.width, V.height);
- glDisable(GL_BLEND);
+ glEnable(GL_BLEND);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ glColor4f(0.1f, 0.1f, 0.1f, 0.8f);
+ glRectf(0.0f, V.height - height, V.width, V.height);
+ glDisable(GL_BLEND);
- glColor3f(0.5f, 0.5f, 0.5f);
+ glColor3f(0.5f, 0.5f, 0.5f);
- view_display_text(10, 7 + V.height - height, info);
+ view_display_text(10, 7 + V.height - height, info);
- glColor3f(1.0f, 1.0f, 1.0f);
+ glColor3f(1.0f, 1.0f, 1.0f);
}
void view_display_help()
{
- const int w = (int)((float)V.width / 1.15f);
- const int h = (int)((float)V.height / 1.15f);
+ const int w = (int)((float)V.width / 1.15f);
+ const int h = (int)((float)V.height / 1.15f);
- const int x1 = (V.width - w) / 2;
- const int x2 = x1 + w;
+ const int x1 = (V.width - w) / 2;
+ const int x2 = x1 + w;
- const int y1 = (V.height - h) / 2;
- const int y2 = y1 + h;
+ const int y1 = (V.height - h) / 2;
+ const int y2 = y1 + h;
- glEnable(GL_BLEND);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- glColor4f(0.5f, 0.5f, 0.5f, 0.8f);
- glRectf(x1, y1, x2, y2);
- glDisable(GL_BLEND);
+ glEnable(GL_BLEND);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ glColor4f(0.5f, 0.5f, 0.5f, 0.8f);
+ glRectf(x1, y1, x2, y2);
+ glDisable(GL_BLEND);
- glColor3f(0.8f, 0.8f, 0.8f);
+ glColor3f(0.8f, 0.8f, 0.8f);
- string info = string("Cycles Renderer ") + CYCLES_VERSION_STRING;
+ string info = string("Cycles Renderer ") + CYCLES_VERSION_STRING;
- view_display_text(x1+20, y2-20, info.c_str());
- view_display_text(x1+20, y2-40, "(C) 2011-2016 Blender Foundation");
- view_display_text(x1+20, y2-80, "Controls:");
- view_display_text(x1+20, y2-100, "h: Info/Help");
- view_display_text(x1+20, y2-120, "r: Reset");
- view_display_text(x1+20, y2-140, "p: Pause");
- view_display_text(x1+20, y2-160, "esc: Cancel");
- view_display_text(x1+20, y2-180, "q: Quit program");
+ view_display_text(x1 + 20, y2 - 20, info.c_str());
+ view_display_text(x1 + 20, y2 - 40, "(C) 2011-2016 Blender Foundation");
+ view_display_text(x1 + 20, y2 - 80, "Controls:");
+ view_display_text(x1 + 20, y2 - 100, "h: Info/Help");
+ view_display_text(x1 + 20, y2 - 120, "r: Reset");
+ view_display_text(x1 + 20, y2 - 140, "p: Pause");
+ view_display_text(x1 + 20, y2 - 160, "esc: Cancel");
+ view_display_text(x1 + 20, y2 - 180, "q: Quit program");
- view_display_text(x1+20, y2-210, "i: Interactive mode");
- view_display_text(x1+20, y2-230, "Left mouse: Move camera");
- view_display_text(x1+20, y2-250, "Right mouse: Rotate camera");
- view_display_text(x1+20, y2-270, "W/A/S/D: Move camera");
- view_display_text(x1+20, y2-290, "0/1/2/3: Set max bounces");
+ view_display_text(x1 + 20, y2 - 210, "i: Interactive mode");
+ view_display_text(x1 + 20, y2 - 230, "Left mouse: Move camera");
+ view_display_text(x1 + 20, y2 - 250, "Right mouse: Rotate camera");
+ view_display_text(x1 + 20, y2 - 270, "W/A/S/D: Move camera");
+ view_display_text(x1 + 20, y2 - 290, "0/1/2/3: Set max bounces");
- glColor3f(1.0f, 1.0f, 1.0f);
+ glColor3f(1.0f, 1.0f, 1.0f);
}
static void view_display()
{
- if(V.first_display) {
- if(V.initf) V.initf();
- if(V.exitf) atexit(V.exitf);
+ if (V.first_display) {
+ if (V.initf)
+ V.initf();
+ if (V.exitf)
+ atexit(V.exitf);
- V.first_display = false;
- }
+ V.first_display = false;
+ }
- glClearColor(0.05f, 0.05f, 0.05f, 0.0f);
- glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+ glClearColor(0.05f, 0.05f, 0.05f, 0.0f);
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
- glMatrixMode(GL_PROJECTION);
- glLoadIdentity();
- gluOrtho2D(0, V.width, 0, V.height);
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
+ gluOrtho2D(0, V.width, 0, V.height);
- glMatrixMode(GL_MODELVIEW);
- glLoadIdentity();
+ glMatrixMode(GL_MODELVIEW);
+ glLoadIdentity();
- glRasterPos3f(0, 0, 0);
+ glRasterPos3f(0, 0, 0);
- if(V.display)
- V.display();
+ if (V.display)
+ V.display();
- glutSwapBuffers();
+ glutSwapBuffers();
}
static void view_reshape(int width, int height)
{
- if(width <= 0 || height <= 0)
- return;
+ if (width <= 0 || height <= 0)
+ return;
- V.width = width;
- V.height = height;
+ V.width = width;
+ V.height = height;
- glViewport(0, 0, width, height);
+ glViewport(0, 0, width, height);
- glMatrixMode(GL_PROJECTION);
- glLoadIdentity();
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
- glMatrixMode(GL_MODELVIEW);
- glLoadIdentity();
+ glMatrixMode(GL_MODELVIEW);
+ glLoadIdentity();
- if(V.resize)
- V.resize(width, height);
+ if (V.resize)
+ V.resize(width, height);
}
static void view_keyboard(unsigned char key, int x, int y)
{
- if(V.keyboard)
- V.keyboard(key);
-
- if(key == 'm')
- printf("mouse %d %d\n", x, y);
- if(key == 'q') {
- if(V.exitf) V.exitf();
- exit(0);
- }
+ if (V.keyboard)
+ V.keyboard(key);
+
+ if (key == 'm')
+ printf("mouse %d %d\n", x, y);
+ if (key == 'q') {
+ if (V.exitf)
+ V.exitf();
+ exit(0);
+ }
}
static void view_mouse(int button, int state, int x, int y)
{
- if(button == 0) {
- if(state == GLUT_DOWN) {
- V.mouseX = x;
- V.mouseY = y;
- V.mouseBut0 = 1;
- }
- else if(state == GLUT_UP) {
- V.mouseBut0 = 0;
- }
- }
- else if(button == 2) {
- if(state == GLUT_DOWN) {
- V.mouseX = x;
- V.mouseY = y;
- V.mouseBut2 = 1;
- }
- else if(state == GLUT_UP) {
- V.mouseBut2 = 0;
- }
- }
+ if (button == 0) {
+ if (state == GLUT_DOWN) {
+ V.mouseX = x;
+ V.mouseY = y;
+ V.mouseBut0 = 1;
+ }
+ else if (state == GLUT_UP) {
+ V.mouseBut0 = 0;
+ }
+ }
+ else if (button == 2) {
+ if (state == GLUT_DOWN) {
+ V.mouseX = x;
+ V.mouseY = y;
+ V.mouseBut2 = 1;
+ }
+ else if (state == GLUT_UP) {
+ V.mouseBut2 = 0;
+ }
+ }
}
static void view_motion(int x, int y)
{
- const int but = V.mouseBut0? 0:2;
- const int distX = x - V.mouseX;
- const int distY = y - V.mouseY;
+ const int but = V.mouseBut0 ? 0 : 2;
+ const int distX = x - V.mouseX;
+ const int distY = y - V.mouseY;
- if(V.motion)
- V.motion(distX, distY, but);
+ if (V.motion)
+ V.motion(distX, distY, but);
- V.mouseX = x;
- V.mouseY = y;
+ V.mouseX = x;
+ V.mouseY = y;
}
static void view_idle()
{
- if(V.redraw) {
- V.redraw = false;
- glutPostRedisplay();
- }
+ if (V.redraw) {
+ V.redraw = false;
+ glutPostRedisplay();
+ }
- time_sleep(0.1);
+ time_sleep(0.1);
}
-void view_main_loop(const char *title, int width, int height,
- ViewInitFunc initf, ViewExitFunc exitf,
- ViewResizeFunc resize, ViewDisplayFunc display,
- ViewKeyboardFunc keyboard, ViewMotionFunc motion)
+void view_main_loop(const char *title,
+ int width,
+ int height,
+ ViewInitFunc initf,
+ ViewExitFunc exitf,
+ ViewResizeFunc resize,
+ ViewDisplayFunc display,
+ ViewKeyboardFunc keyboard,
+ ViewMotionFunc motion)
{
- const char *name = "app";
- char *argv = (char*)name;
- int argc = 1;
-
- memset(&V, 0, sizeof(V));
- V.width = width;
- V.height = height;
- V.first_display = true;
- V.redraw = false;
- V.initf = initf;
- V.exitf = exitf;
- V.resize = resize;
- V.display = display;
- V.keyboard = keyboard;
- V.motion = motion;
-
- glutInit(&argc, &argv);
- glutInitWindowSize(width, height);
- glutInitWindowPosition(0, 0);
- glutInitDisplayMode(GLUT_RGB|GLUT_DOUBLE|GLUT_DEPTH);
- glutCreateWindow(title);
-
- glewInit();
-
- view_reshape(width, height);
-
- glutDisplayFunc(view_display);
- glutIdleFunc(view_idle);
- glutReshapeFunc(view_reshape);
- glutKeyboardFunc(view_keyboard);
- glutMouseFunc(view_mouse);
- glutMotionFunc(view_motion);
-
- glutMainLoop();
+ const char *name = "app";
+ char *argv = (char *)name;
+ int argc = 1;
+
+ memset(&V, 0, sizeof(V));
+ V.width = width;
+ V.height = height;
+ V.first_display = true;
+ V.redraw = false;
+ V.initf = initf;
+ V.exitf = exitf;
+ V.resize = resize;
+ V.display = display;
+ V.keyboard = keyboard;
+ V.motion = motion;
+
+ glutInit(&argc, &argv);
+ glutInitWindowSize(width, height);
+ glutInitWindowPosition(0, 0);
+ glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH);
+ glutCreateWindow(title);
+
+ glewInit();
+
+ view_reshape(width, height);
+
+ glutDisplayFunc(view_display);
+ glutIdleFunc(view_idle);
+ glutReshapeFunc(view_reshape);
+ glutKeyboardFunc(view_keyboard);
+ glutMouseFunc(view_mouse);
+ glutMotionFunc(view_motion);
+
+ glutMainLoop();
}
void view_redraw()
{
- V.redraw = true;
+ V.redraw = true;
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/util/util_view.h b/intern/cycles/util/util_view.h
index ae50b098b39..ad5c53ee5d5 100644
--- a/intern/cycles/util/util_view.h
+++ b/intern/cycles/util/util_view.h
@@ -29,10 +29,15 @@ typedef void (*ViewDisplayFunc)();
typedef void (*ViewKeyboardFunc)(unsigned char key);
typedef void (*ViewMotionFunc)(int x, int y, int button);
-void view_main_loop(const char *title, int width, int height,
- ViewInitFunc initf, ViewExitFunc exitf,
- ViewResizeFunc resize, ViewDisplayFunc display,
- ViewKeyboardFunc keyboard, ViewMotionFunc motion);
+void view_main_loop(const char *title,
+ int width,
+ int height,
+ ViewInitFunc initf,
+ ViewExitFunc exitf,
+ ViewResizeFunc resize,
+ ViewDisplayFunc display,
+ ViewKeyboardFunc keyboard,
+ ViewMotionFunc motion);
void view_display_info(const char *info);
void view_display_help();
@@ -40,4 +45,4 @@ void view_redraw();
CCL_NAMESPACE_END
-#endif /*__UTIL_VIEW_H__*/
+#endif /*__UTIL_VIEW_H__*/
diff --git a/intern/cycles/util/util_windows.h b/intern/cycles/util/util_windows.h
index bd1bc85adff..0d85c5437f6 100644
--- a/intern/cycles/util/util_windows.h
+++ b/intern/cycles/util/util_windows.h
@@ -19,18 +19,18 @@
#ifdef _WIN32
-#ifndef NOGDI
-# define NOGDI
-#endif
-#ifndef NOMINMAX
-# define NOMINMAX
-#endif
-#ifndef WIN32_LEAN_AND_MEAN
-# define WIN32_LEAN_AND_MEAN
-#endif
+# ifndef NOGDI
+# define NOGDI
+# endif
+# ifndef NOMINMAX
+# define NOMINMAX
+# endif
+# ifndef WIN32_LEAN_AND_MEAN
+# define WIN32_LEAN_AND_MEAN
+# endif
-#include <windows.h>
+# include <windows.h>
-#endif /* _WIN32 */
+#endif /* _WIN32 */
-#endif /* __UTIL_WINDOWS_H__ */
+#endif /* __UTIL_WINDOWS_H__ */
diff --git a/intern/cycles/util/util_xml.h b/intern/cycles/util/util_xml.h
index c8a3a495f30..6f06f17937b 100644
--- a/intern/cycles/util/util_xml.h
+++ b/intern/cycles/util/util_xml.h
@@ -38,4 +38,4 @@ using PUGIXML_NAMESPACE::xml_parse_result;
CCL_NAMESPACE_END
-#endif /* __UTIL_XML_H__ */
+#endif /* __UTIL_XML_H__ */